Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNick Doiron <ndoiron@mapmeld.com>2011-05-10 20:07:11 (GMT)
committer Nick Doiron <ndoiron@mapmeld.com>2011-05-10 20:07:11 (GMT)
commit6f64fe14ea678edba5b7ed3ea1a97aac3ffe20b1 (patch)
tree1260de00b8633c35483013d06a30d2354235bb4b
Uploaded Map Activity code to GitoriousHEADmaster
-rw-r--r--Makefile35
-rw-r--r--_camera.c276
-rw-r--r--_camera.obin0 -> 35172 bytes
-rw-r--r--_camera.sobin0 -> 31804 bytes
-rw-r--r--activity/activity-map.svg20
-rw-r--r--activity/activity.info9
-rw-r--r--button.py79
-rw-r--r--color.py75
-rw-r--r--constants.py131
-rw-r--r--filepicker.py46
-rw-r--r--gplay.py154
-rw-r--r--html/MediaMarker.js21
-rw-r--r--html/staticMapCanvas.js148
-rw-r--r--html/staticmap2.html734
-rw-r--r--html/zMinus.pngbin0 -> 379 bytes
-rw-r--r--html/zPlus.pngbin0 -> 485 bytes
-rw-r--r--icons/add-icon.svg26
-rw-r--r--icons/corner-info.svg15
-rw-r--r--icons/delete-icon.svg25
-rw-r--r--icons/info-marker.svg74
-rw-r--r--icons/localwiki.svg327
-rw-r--r--icons/map-icon-croseE.svg13
-rw-r--r--icons/map-icon-croseN.svg12
-rw-r--r--icons/map-icon-croseS.svg13
-rw-r--r--icons/map-icon-croseW.svg12
-rw-r--r--icons/map-icon-zoomIn.svg95
-rw-r--r--icons/map-icon-zoomOut.svg12
-rw-r--r--icons/measure-icon.svg12
-rw-r--r--icons/panoramio.svg25
-rw-r--r--icons/save-search.svg63
-rw-r--r--icons/static-icon.svg16
-rw-r--r--icons/tool-polygon.svg59
-rw-r--r--icons/tool-shape-line.svg11
-rw-r--r--icons/topo-icon.svg21
-rw-r--r--icons/web-icon.svg14
-rw-r--r--icons/wikimapia.svg100
-rw-r--r--idlethread.py175
-rw-r--r--instance.py45
-rw-r--r--locale/es/LC_MESSAGES/org.laptop.map.mobin0 -> 1087 bytes
-rw-r--r--locale/es/activity.linfo2
-rw-r--r--locale/mn/LC_MESSAGES/org.laptop.map.mobin0 -> 1200 bytes
-rw-r--r--locale/mn/activity.linfo2
-rw-r--r--logic.py359
-rw-r--r--manifest43
-rw-r--r--map-activity.iml12
-rw-r--r--map-activity.ipr286
-rw-r--r--map-activity.iws694
-rw-r--r--map.py1799
-rw-r--r--model.py147
-rw-r--r--news5
-rw-r--r--p5.py86
-rw-r--r--photocanvas.py65
-rw-r--r--po/es.po99
-rw-r--r--po/map.pot113
-rw-r--r--po/mn.po99
-rw-r--r--recorded.py82
-rw-r--r--result.py25
-rw-r--r--savedmap.py41
-rw-r--r--serialize.py203
-rw-r--r--server.py69
-rw-r--r--setup.py25
-rw-r--r--tray.py207
-rw-r--r--utils.py110
-rw-r--r--webviewer.py148
64 files changed, 7614 insertions, 0 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..3cd0564
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,35 @@
+PYVER=`python -c "import sys; print '%s.%s' % (sys.version_info[0], sys.version_info[1])"`
+PYTHON=python$(PYVER)
+
+GLIB_INCLUDES=`pkg-config --cflags glib-2.0`
+GLIB_LIBS=`pkg-config --libs glib-2.0`
+
+GTK_INCLUDES=`pkg-config --cflags gtk+-2.0`
+GTK_LIBS=`pkg-config --libs gtk+-2.0`
+
+PYGTK_INCLUDES=`pkg-config --cflags pygtk-2.0`
+PYGTK_LIBS=`pkg-config --libs pygtk-2.0`
+
+CAIRO_INCLUDES=`pkg-config --cflags cairo`
+CAIRO_LIBS=`pkg-config --libs cairo`
+
+PYCAIRO_INCLUDES=`pkg-config --cflags pycairo`
+PYCAIRO_LIBS=`pkg-config --libs pycairo`
+
+INCLUDES=-I. -I/usr/include/${PYTHON} ${GLIB_INCLUDES} ${PYGTK_INCLUDES} ${CAIRO_INCLUDES} ${PYCAIRO_INCLUDES} ${GTK_INCLUDES}
+ARCHFLAGS=-m32 -march=i386 -mtune=generic
+OPTFLAGS=-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -fasynchronous-unwind-tables
+CFLAGS=-g -fPIC -DPIC
+LDFLAGS=-shared -nostdlib -Wl,--export-dynamic -pthread
+
+all: build link
+
+build:
+ gcc ${INCLUDES} ${ARCHFLAGS} ${OPTFLAGS} ${CFLAGS} -c _camera.c -o _camera.o
+
+link:
+ g++ ${LDFLAGS} _camera.o ${GLIB_LIBS} ${PYGTK_LIBS} ${CAIRO_LIBS} ${PYCAIRO_LIBS} ${GTK_LIBS} -Wl,-soname -Wl,_camera.so -o _camera.so
+
+clean:
+ @find -name "*.o" -exec rm {} \;
+ @find -name "*.so" -exec rm {} \;
diff --git a/_camera.c b/_camera.c
new file mode 100644
index 0000000..694f0a4
--- /dev/null
+++ b/_camera.c
@@ -0,0 +1,276 @@
+#include <Python.h>
+
+#include "pycairo.h"
+#include <glib.h>
+
+#include <pygobject.h>
+
+static PyTypeObject *_PyGObject_Type;
+#define PyGObject_Type (*_PyGObject_Type)
+Pycairo_CAPI_t *Pycairo_CAPI;
+static PyTypeObject *_PyGdkPixbuf_Type;
+#define PyGdkPixbuf_Type (*_PyGdkPixbuf_Type)
+
+#include <cairo.h>
+#include <gdk/gdkpixbuf.h>
+#include <gdk/gdkpixmap.h>
+#include <cairo-xlib.h>
+#include <gdk/gdkcairo.h>
+
+static cairo_surface_t *
+_cairo_surface_from_pixbuf (GdkPixbuf *pixbuf)
+{
+/* Ripped from GooCanvas */
+ gint width = gdk_pixbuf_get_width (pixbuf);
+ gint height = gdk_pixbuf_get_height (pixbuf);
+ guchar *gdk_pixels = gdk_pixbuf_get_pixels (pixbuf);
+ int gdk_rowstride = gdk_pixbuf_get_rowstride (pixbuf);
+ int n_channels = gdk_pixbuf_get_n_channels (pixbuf);
+ guchar *cairo_pixels;
+ cairo_format_t format;
+ cairo_surface_t *surface;
+ static const cairo_user_data_key_t key;
+ int j;
+
+ if (n_channels == 3)
+ format = CAIRO_FORMAT_RGB24;
+ else
+ format = CAIRO_FORMAT_ARGB32;
+
+ cairo_pixels = g_malloc (4 * width * height);
+ surface = cairo_image_surface_create_for_data ((unsigned char *)cairo_pixels,
+ format,
+ width, height, 4 * width);
+ cairo_surface_set_user_data (surface, &key,
+ cairo_pixels, (cairo_destroy_func_t)g_free);
+
+ for (j = height; j; j--)
+ {
+ guchar *p = gdk_pixels;
+ guchar *q = cairo_pixels;
+
+ if (n_channels == 3)
+ {
+ guchar *end = p + 3 * width;
+
+ while (p < end)
+ {
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+ q[0] = p[2];
+ q[1] = p[1];
+ q[2] = p[0];
+#else
+ q[1] = p[0];
+ q[2] = p[1];
+ q[3] = p[2];
+#endif
+ p += 3;
+ q += 4;
+ }
+ }
+ else
+ {
+ guchar *end = p + 4 * width;
+ guint t1,t2,t3;
+
+#define MULT(d,c,a,t) G_STMT_START { t = c * a; d = ((t >> 8) + t) >> 8; } G_STMT_END
+
+ while (p < end)
+ {
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+ MULT(q[0], p[2], p[3], t1);
+ MULT(q[1], p[1], p[3], t2);
+ MULT(q[2], p[0], p[3], t3);
+ q[3] = p[3];
+#else
+ q[0] = p[3];
+ MULT(q[1], p[0], p[3], t1);
+ MULT(q[2], p[1], p[3], t2);
+ MULT(q[3], p[2], p[3], t3);
+#endif
+
+ p += 4;
+ q += 4;
+ }
+
+#undef MULT
+ }
+
+ gdk_pixels += gdk_rowstride;
+ cairo_pixels += 4 * width;
+ }
+
+ return surface;
+}
+
+static PyObject*
+_wrap_camera_cairo_surface_from_gdk_pixbuf(PyGObject *self, PyObject *args, PyObject *kwargs)
+{
+ static char *kwlist[] = { "pixbuf", NULL };
+ PyGObject *child;
+ cairo_surface_t *surface;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs,"O!:camera.cairo_surface_from_gdk_pixbuf", kwlist, &PyGdkPixbuf_Type, &child))
+ return NULL;
+
+ surface = _cairo_surface_from_pixbuf(GDK_PIXBUF (child->obj));
+ if (surface == NULL) {
+ PyErr_SetString(PyExc_RuntimeError, "surface could not be converted");
+ return NULL;
+ }
+
+ return PycairoSurface_FromSurface(surface, NULL);
+}
+
+static GdkPixbuf *
+_pixbuf_from_cairo_surface (cairo_surface_t * sf)
+{
+ GdkPixmap * pixmap;
+ GdkPixbuf * pixbuf = NULL;
+ cairo_surface_type_t type;
+ gint width = 0, height = 0, depth = 0;
+ int format;
+ cairo_t * cr;
+ GdkColormap * cm;
+
+ type = cairo_surface_get_type (sf);
+ switch (type) {
+ case CAIRO_SURFACE_TYPE_IMAGE:
+ width = cairo_image_surface_get_width (sf);
+ height = cairo_image_surface_get_height (sf);
+ format = cairo_image_surface_get_format (sf);
+ if (format == CAIRO_FORMAT_ARGB32)
+ depth = 32;
+ else if (format == CAIRO_FORMAT_RGB24)
+ depth = 24;
+ else if (format == CAIRO_FORMAT_A8)
+ depth = 8;
+ else if (format == CAIRO_FORMAT_A1)
+ depth = 1;
+ else if (format == CAIRO_FORMAT_RGB16_565)
+ depth = 16;
+ break;
+ case CAIRO_SURFACE_TYPE_XLIB:
+ width = cairo_xlib_surface_get_width (sf);
+ height = cairo_xlib_surface_get_height (sf);
+ depth = cairo_xlib_surface_get_depth (sf);
+ break;
+ default:
+ break;
+ }
+ if (!depth)
+ return NULL;
+
+ pixmap = gdk_pixmap_new (NULL, width, height, depth);
+ if (!pixmap)
+ return NULL;
+
+ cr = gdk_cairo_create (pixmap);
+ if (!cr)
+ goto release_pixmap;
+
+ cairo_set_source_surface (cr, sf, 0, 0);
+ cairo_paint (cr);
+ cairo_destroy (cr);
+
+ cm = gdk_colormap_get_system ();
+ pixbuf = gdk_pixbuf_get_from_drawable (NULL, pixmap, cm, 0, 0, 0, 0, -1, -1);
+
+release_pixmap:
+ gdk_pixmap_unref (pixmap);
+
+ return pixbuf;
+}
+
+
+static PyObject*
+_wrap_camera_gdk_pixbuf_from_cairo_surface(PyGObject *self, PyObject *args, PyObject *kwargs)
+{
+ static char *kwlist[] = { "surface", NULL };
+ PyGObject *child;
+ GdkPixbuf * pixbuf;
+ PyTypeObject *type = &PycairoSurface_Type;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs,"O!:camera.gdk_pixbuf_from_cairo_surface", kwlist, type, &child))
+ return NULL;
+
+ pixbuf = _pixbuf_from_cairo_surface((cairo_surface_t *)(child->obj));
+ if (pixbuf == NULL) {
+ PyErr_SetString(PyExc_RuntimeError, "pixbuf could not be converted");
+ return NULL;
+ }
+
+ return pygobject_new ((GObject *) pixbuf);
+}
+
+const PyMethodDef py_camera_functions[] = {
+ { "cairo_surface_from_gdk_pixbuf", (PyCFunction)_wrap_camera_cairo_surface_from_gdk_pixbuf,
+ METH_VARARGS|METH_KEYWORDS, NULL },
+ { "gdk_pixbuf_from_cairo_surface", (PyCFunction)_wrap_camera_gdk_pixbuf_from_cairo_surface,
+ METH_VARARGS|METH_KEYWORDS, NULL },
+ { NULL, NULL, 0, NULL }
+};
+
+
+/* ----------- enums and flags ----------- */
+
+void
+py_sugar_add_constants(PyObject *module, const gchar *strip_prefix)
+{
+}
+
+/* initialise stuff extension classes */
+void
+py_camera_register_classes(PyObject *d)
+{
+ PyObject *module;
+
+ if ((module = PyImport_ImportModule("gobject")) != NULL) {
+ _PyGObject_Type = (PyTypeObject *)PyObject_GetAttrString(module, "GObject");
+ if (_PyGObject_Type == NULL) {
+ PyErr_SetString(PyExc_ImportError,
+ "cannot import name GObject from gobject");
+ return ;
+ }
+ _PyGObject_Type = (PyTypeObject *)PyObject_GetAttrString(module, "GObject");
+ if (_PyGObject_Type == NULL) {
+ PyErr_SetString(PyExc_ImportError,
+ "cannot import name GObject from gobject");
+ return ;
+ }
+ } else {
+ PyErr_SetString(PyExc_ImportError,
+ "could not import gobject");
+ return ;
+ }
+ if ((module = PyImport_ImportModule("gtk.gdk")) != NULL) {
+ _PyGdkPixbuf_Type = (PyTypeObject *)PyObject_GetAttrString(module, "Pixbuf");
+ if (_PyGdkPixbuf_Type == NULL) {
+ PyErr_SetString(PyExc_ImportError,
+ "cannot import name Pixbuf from gtk.gdk");
+ return ;
+ }
+ } else {
+ PyErr_SetString(PyExc_ImportError,
+ "could not import gtk.gdk");
+ return ;
+ }
+
+ Pycairo_IMPORT;
+}
+
+DL_EXPORT(void)
+init_camera(void)
+{
+ PyObject *m, *d;
+
+ Pycairo_IMPORT;
+
+ m = Py_InitModule ("_camera", py_camera_functions);
+ d = PyModule_GetDict (m);
+
+ py_camera_register_classes (d);
+ if (PyErr_Occurred ()) {
+ Py_FatalError ("can't initialise module _camera");
+ }
+}
diff --git a/_camera.o b/_camera.o
new file mode 100644
index 0000000..e126c76
--- /dev/null
+++ b/_camera.o
Binary files differ
diff --git a/_camera.so b/_camera.so
new file mode 100644
index 0000000..c57a12b
--- /dev/null
+++ b/_camera.so
Binary files differ
diff --git a/activity/activity-map.svg b/activity/activity-map.svg
new file mode 100644
index 0000000..a768956
--- /dev/null
+++ b/activity/activity-map.svg
@@ -0,0 +1,20 @@
+<?xml version="1.0"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"[
+ <!ENTITY stroke_color "#010101">
+ <!ENTITY fill_color "#FFFFFF">
+]>
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="74.5px" height="74px" viewBox="0 0 74.5 74" enable-background="new 0 0 74.5 74" xml:space="preserve">
+<g>
+ <path fill="&fill_color;" d="M74.563,55.001c0,10.692-8.748,19.44-19.44,19.44H18.67c-10.692,0-19.44-8.748-19.44-19.44V18.882
+ c0-10.692,8.748-19.44,19.44-19.44h36.454c10.692,0,19.44,8.748,19.44,19.44V55.001z"/>
+</g>
+<g>
+ <line fill="none" stroke="&stroke_color;" stroke-width="3.5" x1="37.124" y1="13.641" x2="37.124" y2="23.035"/>
+ <path fill="none" stroke="&stroke_color;" stroke-width="3.5" d="M43.213,29.176c0,3.406-2.762,6.168-6.166,6.168
+ c-3.406,0-6.167-2.762-6.167-6.168c0-3.404,2.761-6.141,6.167-6.141C40.451,23.035,43.213,25.771,43.213,29.176z M21.735,59.275
+ L34.298,34.5"/>
+ <line fill="none" stroke="&stroke_color;" stroke-width="3.5" x1="27.88" y1="47.344" x2="54.881" y2="47.344"/>
+ <line fill="none" stroke="&stroke_color;" stroke-width="3.5" x1="39.949" y1="34.434" x2="52.546" y2="59.275"/>
+</g>
+</svg>
diff --git a/activity/activity.info b/activity/activity.info
new file mode 100644
index 0000000..127473f
--- /dev/null
+++ b/activity/activity.info
@@ -0,0 +1,9 @@
+[Activity]
+name = Map
+activity_version = 12
+host_version = 1
+license = MIT
+icon = activity-map
+service_name = org.laptop.map
+class = map.Map
+show_launcher = 1 \ No newline at end of file
diff --git a/button.py b/button.py
new file mode 100644
index 0000000..d09791d
--- /dev/null
+++ b/button.py
@@ -0,0 +1,79 @@
+import gtk
+import os
+import gobject
+import rsvg
+import gc
+
+from sugar.graphics.palette import Palette
+from sugar.graphics.tray import TrayButton
+from sugar.graphics.icon import Icon
+from sugar.graphics import style
+from constants import Constants
+import utils
+
+class SavedButton(TrayButton, gobject.GObject):
+ def __init__(self, ui, savedmapData):
+ TrayButton.__init__(self)
+ self.ui = ui
+ self.data = savedmapData
+
+ img = self.getImg()
+ self.set_icon_widget( img )
+
+ self.setup_rollover_options()
+
+
+ def getImg( self ):
+ pb = gtk.gdk.pixbuf_new_from_file(self.data.thumbPath)
+
+ img = gtk.Image()
+ img.set_from_pixbuf(pb)
+ img.show()
+
+ return img
+
+
+ def setButtClickedId( self, id ):
+ self.BUTT_CLICKED_ID = id
+
+
+ def getButtClickedId( self ):
+ return self.BUTT_CLICKED_ID
+
+
+ def setup_rollover_options( self ):
+ palette = Palette( Constants.istrSavedMap )
+ self.set_palette(palette)
+
+ self.tag_menu_item = gtk.MenuItem( Constants.istrTagMap )
+ self.ACTIVATE_TAG_ID = self.tag_menu_item.connect('activate', self._tagCb)
+ palette.menu.append(self.tag_menu_item)
+ self.tag_menu_item.show()
+
+ self.rem_menu_item = gtk.MenuItem( Constants.istrRemove )
+ self.ACTIVATE_REMOVE_ID = self.rem_menu_item.connect('activate', self._itemRemoveCb)
+ palette.menu.append(self.rem_menu_item)
+ self.rem_menu_item.show()
+
+ self.copy_menu_item = gtk.MenuItem( Constants.istrCopyToClipboard )
+ self.ACTIVATE_COPY_ID = self.copy_menu_item.connect('activate', self._itemCopyToClipboardCb)
+ self.get_palette().menu.append(self.copy_menu_item)
+ self.copy_menu_item.show()
+
+
+ def cleanUp( self ):
+ self.rem_menu_item.disconnect( self.ACTIVATE_REMOVE_ID )
+ self.copy_menu_item.disconnect( self.ACTIVATE_COPY_ID )
+ self.tag_menu_item.disconnect( self.ACTIVATE_TAG_ID)
+
+
+ def _tagCb(self, widget):
+ self.ui.showSearchResultTags( self.data )
+
+
+ def _itemRemoveCb(self, widget):
+ self.ui.removeThumb( self.data )
+
+
+ def _itemCopyToClipboardCb(self, widget):
+ self.ui.copyToClipboard( self.data )
diff --git a/color.py b/color.py
new file mode 100644
index 0000000..8c8903e
--- /dev/null
+++ b/color.py
@@ -0,0 +1,75 @@
+# Copyright (c) 2008, Media Modifications Ltd.
+
+#Permission is hereby granted, free of charge, to any person obtaining a copy
+#of this software and associated documentation files (the "Software"), to deal
+#in the Software without restriction, including without limitation the rights
+#to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+#copies of the Software, and to permit persons to whom the Software is
+#furnished to do so, subject to the following conditions:
+
+#The above copyright notice and this permission notice shall be included in
+#all copies or substantial portions of the Software.
+
+#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+#THE SOFTWARE.
+
+import gtk
+
+class Color:
+
+ def __init__(self):
+ pass
+
+
+ def init_rgba(self, r, g, b, a):
+ self._ro = r
+ self._go = g
+ self._bo = b
+ self._ao = a;
+ self._r = self._ro / 255.0
+ self._g = self._go / 255.0
+ self._b = self._bo / 255.0
+ self._a = self._ao / 255.0
+
+ self._opaque = False
+ if (self._a == 1):
+ self.opaque = True
+
+ rgb_tup = ( self._ro, self._go, self._bo )
+ self.hex = self.rgb_to_hex( rgb_tup )
+ self.gColor = gtk.gdk.color_parse( self.hex )
+
+
+ def init_gdk(self, col):
+ self.init_hex( col.get_html() )
+
+
+ def init_hex(self, hex):
+ cTup = self.hex_to_rgb( hex )
+ self.init_rgba( cTup[0], cTup[1], cTup[2], 255 )
+
+
+ def get_int(self):
+ return int(self._a * 255) + (int(self._b * 255) << 8) + (int(self._g * 255) << 16) + (int(self._r * 255) << 24)
+
+
+ def rgb_to_hex(self, rgb_tup):
+ hexcolor = '#%02x%02x%02x' % rgb_tup
+ return hexcolor
+
+
+ def hex_to_rgb(self, h):
+ c = eval('0x' + h[1:])
+ r = (c >> 16) & 0xFF
+ g = (c >> 8) & 0xFF
+ b = c & 0xFF
+ return (int(r), int(g), int(b))
+
+
+ def getCanvasColor(self):
+ return str(self._ro) + "," + str(self._go) + "," + str(self._bo) \ No newline at end of file
diff --git a/constants.py b/constants.py
new file mode 100644
index 0000000..9ae1ecf
--- /dev/null
+++ b/constants.py
@@ -0,0 +1,131 @@
+import os
+import gtk
+from gettext import gettext as _
+
+import sugar.graphics.style
+from sugar.activity import activity
+from sugar import profile
+
+from instance import Instance
+from color import Color
+import utils
+
+class Constants:
+
+ VERSION = 8
+
+ SERVICE = "org.laptop.Map"
+ IFACE = SERVICE
+ PATH = "/org/laptop/Map"
+ activityId = None
+
+ gfxPath = os.path.join(activity.get_bundle_path(), "gfx")
+ htmlPath = os.path.join(activity.get_bundle_path(), "html")
+ iconsPath = os.path.join(activity.get_bundle_path(), "icons")
+
+ istrAnnotate = _("Edit")
+ istrSearch = _("Search")
+ istrSearchAddress = _('Find:')
+ istrSearchMedia = _("Tags:")
+ istrSaveSearch = _("Save Search")
+ istrConnecting = _("Connecting to Map Server")
+ istrZoomIn = _("Zoom In")
+ istrZoomOut = _("Zoom Out")
+ istrSaveSearch = _("Save")
+ istrDensity = _("Density")
+ istrSavedMap = _("Saved Map")
+ istrTagMap = _("Describe Map")
+ istrRemove = _("Remove Map")
+ istrCopyToClipboard = _("Copy to Clipboard")
+ istrAddMedia = _("Add Media")
+ istrAddInfo = _("Add Info")
+ istrDeleteMedia = _("Delete")
+ istrWebMedia = _("Library")
+ istrMeasure = _("Measure")
+ istrStaticMaps = _("olpcMAP.net")
+ istrPanoramio = _("Panoramio")
+ istrLocalWiki = _("LocationWiki")
+ istrWikiMapia = _("WikiMapia")
+ istrLatitude = _("Latitude:")
+ istrLongitude = _("Longitude:")
+ istrTags = _("Description:")
+ istrLang = _("lang=en")
+ LineButton = _("Add Line")
+ PolyButton = _("Add Shape")
+
+ TYPE_PHOTO = 0
+ TYPE_VIDEO = 1
+
+ ui_dim_INSET = 4
+
+ recdAlbum = "map"
+ recdLat = "lat"
+ recdLng = "lng"
+ recdDatastoreId = "datastore"
+ recdInfo = "info"
+ recdMapItem = "mapItem"
+ recdSavedMapItem = "savedMap"
+ recdInfoMarker = "infoMarker"
+ recdIcon = "icon"
+ recdZoom = "zoom"
+ recdNotes = "notes"
+ recdMapImg = "mapImg"
+ recdTags = "tags"
+ recdMapThumbImg = "mapThumbImg"
+ recdRecdId = "recdId"
+ recdRecdLat = "recdLat"
+ recdRecdLng = "recdLng"
+ recdDensity = "density"
+ recdLine = "line"
+ lineID = "lid"
+ lineColor = "lcolor"
+ lineThick = "lthickness"
+ linePts = "lpts"
+ mapLat="lat"
+ mapLng="lng"
+ mapZoom="zoom"
+
+ colorBlack = Color()
+ colorBlack.init_rgba( 0, 0, 0, 255 )
+ colorWhite = Color()
+ colorWhite.init_rgba( 255, 255, 255, 255 )
+ colorRed = Color()
+ colorRed.init_rgba( 255, 0, 0, 255)
+ colorGreen = Color()
+ colorGreen.init_rgba( 0, 255, 0, 255)
+ colorBlue = Color()
+ colorBlue.init_rgba( 0, 0, 255, 255)
+ colorGrey = Color()
+ colorGrey.init_gdk( sugar.graphics.style.COLOR_BUTTON_GREY )
+ colorBg = colorBlack
+
+ def __init__( self, ca ):
+ self.__class__.activityId = ca._activity_id
+ self.__class__.northImgClr, self.__class__.northImgBw = self.loadSvgImg('map-icon-croseN.svg')
+ self.__class__.southImgClr, self.__class__.southImgBw = self.loadSvgImg('map-icon-croseS.svg')
+ self.__class__.eastImgClr, self.__class__.eastImgBw = self.loadSvgImg('map-icon-croseE.svg')
+ self.__class__.westImgClr, self.__class__.westImgBw = self.loadSvgImg('map-icon-croseW.svg')
+
+ infoOnSvgPath = os.path.join(self.__class__.iconsPath, 'corner-info.svg')
+ infoOnSvgFile = open(infoOnSvgPath, 'r')
+ infoOnSvgData = infoOnSvgFile.read()
+ self.__class__.infoOnSvg = utils.loadSvg(infoOnSvgData, None, None )
+ infoOnSvgFile.close()
+
+ def loadSvgImg(self, fileName):
+ SvgPath = os.path.join(self.__class__.iconsPath, fileName)
+ SvgFile = open(SvgPath, 'r')
+ SvgData = SvgFile.read()
+ SvgFile.close()
+
+ ColorSvg = utils.loadSvg(SvgData, Instance.colorStroke.hex, Instance.colorFill.hex)
+ ColorPixBuf = ColorSvg.get_pixbuf()
+ ColorImg = gtk.Image()
+ ColorImg.set_from_pixbuf(ColorPixBuf)
+
+ MonoSvg = utils.loadSvg(SvgData, self.__class__.colorGrey.hex, self.__class__.colorWhite.hex)
+ MonoPixBuf = MonoSvg.get_pixbuf()
+ MonoImg = gtk.Image()
+ MonoImg.set_from_pixbuf(MonoPixBuf)
+
+ return [ColorImg, MonoImg]
diff --git a/filepicker.py b/filepicker.py
new file mode 100644
index 0000000..cabc295
--- /dev/null
+++ b/filepicker.py
@@ -0,0 +1,46 @@
+# Copyright (C) 2007, One Laptop Per Child
+# Copyright (c) 2008, Media Modifications Ltd.
+#
+# 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+
+import gtk
+
+from sugar.graphics.objectchooser import ObjectChooser
+
+class FilePicker:
+
+ def __init__(self):
+ pass
+
+
+ def show(self):
+ title = None
+ parent = None
+ file = None
+ job = None
+ chooser = ObjectChooser()
+
+ try:
+ result = chooser.run()
+ if result == gtk.RESPONSE_ACCEPT:
+ jobject = chooser.get_selected_object()
+ if (jobject and jobject.file_path):
+ job = jobject
+
+ finally:
+ chooser.destroy()
+ del chooser
+
+ return job
diff --git a/gplay.py b/gplay.py
new file mode 100644
index 0000000..3ceb353
--- /dev/null
+++ b/gplay.py
@@ -0,0 +1,154 @@
+# Copyright (c) 2008, Media Modifications Ltd.
+
+#Permission is hereby granted, free of charge, to any person obtaining a copy
+#of this software and associated documentation files (the "Software"), to deal
+#in the Software without restriction, including without limitation the rights
+#to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+#copies of the Software, and to permit persons to whom the Software is
+#furnished to do so, subject to the following conditions:
+
+#The above copyright notice and this permission notice shall be included in
+#all copies or substantial portions of the Software.
+
+#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+#THE SOFTWARE.
+
+#look at jukeboxactivity.py
+
+import gtk
+import pygtk
+pygtk.require('2.0')
+import sys
+import pygst
+pygst.require('0.10')
+import gst
+import gst.interfaces
+import gobject
+import time
+gobject.threads_init()
+
+class Gplay:
+
+ def __init__(self):
+ self.window = None
+ self.players = []
+ self.playing = False
+ self.nextMovie()
+
+ def nextMovie(self):
+ if ( len(self.players) > 0 ):
+ self.playing = False
+ self.getPlayer().set_property("video-sink", None)
+ self.getPlayer().get_bus().disconnect(self.SYNC_ID)
+ self.getPlayer().get_bus().remove_signal_watch()
+ self.getPlayer().get_bus().disable_sync_message_emission()
+
+ player = gst.element_factory_make("playbin", "playbin")
+ xis = gst.element_factory_make("xvimagesink", "xvimagesink")
+ player.set_property("video-sink", xis)
+ bus = player.get_bus()
+ bus.enable_sync_message_emission()
+ bus.add_signal_watch()
+ self.SYNC_ID = bus.connect('sync-message::element', self.onSyncMessage)
+ self.players.append(player)
+
+
+ def getPlayer(self):
+ return self.players[len(self.players)-1]
+
+
+ def onSyncMessage(self, bus, message):
+ if message.structure is None:
+ return True
+ if message.structure.get_name() == 'prepare-xwindow-id':
+ self.window.set_sink(message.src)
+ message.src.set_property('force-aspect-ratio', True)
+ return True
+
+
+ def setLocation(self, location):
+ print("setLocation: ", location )
+ if (self.getPlayer().get_property('uri') == location):
+ self.seek(gst.SECOND*0)
+ return
+
+ self.getPlayer().set_state(gst.STATE_READY)
+ self.getPlayer().set_property('uri', location)
+ ext = location[len(location)-3:]
+ if (ext == "jpg"):
+ self.pause()
+ print("all played?")
+
+
+ def queryPosition(self):
+ "Returns a (position, duration) tuple"
+ try:
+ position, format = self.getPlayer().query_position(gst.FORMAT_TIME)
+ except:
+ position = gst.CLOCK_TIME_NONE
+
+ try:
+ duration, format = self.getPlayer().query_duration(gst.FORMAT_TIME)
+ except:
+ duration = gst.CLOCK_TIME_NONE
+
+ return (position, duration)
+
+
+ def seek(self, location):
+ event = gst.event_new_seek(1.0, gst.FORMAT_TIME, gst.SEEK_FLAG_FLUSH | gst.SEEK_FLAG_ACCURATE, gst.SEEK_TYPE_SET, location, gst.SEEK_TYPE_NONE, 0)
+ res = self.getPlayer().send_event(event)
+ if res:
+ self.getPlayer().set_new_stream_time(0L)
+
+
+ def pause(self):
+ self.playing = False
+ self.getPlayer().set_state(gst.STATE_PAUSED)
+
+
+ def play(self):
+ self.playing = True
+ self.getPlayer().set_state(gst.STATE_PLAYING)
+
+
+ def stop(self):
+ self.playing = False
+ self.getPlayer().set_state(gst.STATE_NULL)
+ self.nextMovie()
+
+
+ def get_state(self, timeout=1):
+ return self.getPlayer().get_state(timeout=timeout)
+
+
+ def is_playing(self):
+ return self.playing
+
+
+
+class PlayVideoWindow(gtk.EventBox):
+ def __init__(self, bgd):
+ gtk.EventBox.__init__(self)
+
+ self.imagesink = None
+
+ self.modify_bg( gtk.STATE_NORMAL, bgd )
+ self.modify_bg( gtk.STATE_INSENSITIVE, bgd )
+ self.unset_flags(gtk.DOUBLE_BUFFERED)
+ self.set_flags(gtk.APP_PAINTABLE)
+
+
+ def set_sink(self, sink):
+ if (self.imagesink != None):
+ assert self.window.xid
+ self.imagesink = None
+ del self.imagesink
+
+ self.imagesink = sink
+ self.imagesink.set_xwindow_id(self.window.xid) \ No newline at end of file
diff --git a/html/MediaMarker.js b/html/MediaMarker.js
new file mode 100644
index 0000000..a47b00b
--- /dev/null
+++ b/html/MediaMarker.js
@@ -0,0 +1,21 @@
+function MediaMarker(){
+return{
+ initialize:function(pt, markerServer, markerId, tags, info, icon)
+ {this.markerServer=markerServer;
+ this.markerId=markerId;
+ this.pt=pt;
+ this.tags=tags;
+ this.info=info;
+ if(icon==null){icon="null";}
+ this.icon=icon;
+ this.iconDiv=null;
+ if((this.tags == undefined)||(this.tags==null))
+ {this.tags = "";}
+ },
+ getLatLng:function(){return this.pt;},
+ get_position:function(){return this.pt;},
+ get_info:function(){return this.info;},
+ getMarkerServer:function(){return this.markerServer;},
+ getMarkerId:function(){return this.markerId;}
+};
+} \ No newline at end of file
diff --git a/html/staticMapCanvas.js b/html/staticMapCanvas.js
new file mode 100644
index 0000000..422c373
--- /dev/null
+++ b/html/staticMapCanvas.js
@@ -0,0 +1,148 @@
+var GMapCanvas2={
+ initialize: function(prefLat, prefLng, prefZoom, prefType)
+ { this.map = document.getElementById("map");
+ this.center = [prefLat*1,prefLng*1];
+ this.zoom=prefZoom;
+ this.resolution="480x303";
+ this.factor=0.75;
+ this.yfactor=0.75;
+ switch(prefType){
+ case "terrain":
+ this.mapType = "terrain";break;
+ case "sat":
+ this.mapType = "satellite";break;
+ case "terr":
+ this.mapType = "hybrid";break;
+ case "hyb":
+ this.mapType = "hybrid";break;
+ case "osm":
+ this.mapType = "osm";break;
+ default:
+ this.mapType = "roadmap";break;
+ }
+ document.getElementById(this.mapType).className="selectmaptype";
+ this.markerList=[];
+ this.lineColor="ff0000";
+ this.updateImg();
+ return this;
+ },
+ get_center:function(){return this.center;},
+ get_zoom:function(){return this.zoom;},
+ get_type:function(){return this.mapType;},
+ get_bounds:function(){
+ var sw=[1*this.center[0]-0.55618*this.factor*Math.pow(2,(9-1*this.zoom)),this.center[1]*1 - 0.98877*this.factor*Math.pow(2,(9-1*this.zoom))];
+ var ne=[1*this.center[0]+0.55618*this.factor*Math.pow(2,(9-1*this.zoom)),this.center[1]*1 + 0.98877*this.factor*Math.pow(2,(9-1*this.zoom))];
+ return [sw,ne];
+ },
+ set_center:function(latlng){
+ if(latlng[0]>85){latlng=[85,latlng[1]]}
+ if(latlng[0]<-85){latlng=[-85,latlng[1]]}
+ this.center = latlng;
+ this.updateImg();
+ updateLoc()
+ },
+ set_zoom:function(z){this.zoom = z;this.updateImg();},
+ set_type:function(type){
+ if(type==this.mapType){return;}
+ try{document.getElementById(this.mapType).className = "maptype";document.getElementById(type).className = "selectmaptype";}
+ catch(e){}
+ this.mapType=type;
+ this.updateImg();
+ },
+ fitBounds:function(bounds){
+ this.bounds=bounds;
+ this.center=[(bounds[0][0]*1.0+1.0*bounds[1][0])/2.0,(bounds[0][1]*1.0+1.0*bounds[1][1])/2.0];
+ var latDiff=Math.abs(bounds[0][0]-bounds[1][0]);
+ var lngDiff=Math.abs(bounds[0][1]-bounds[1][1]);
+ if(latDiff/lngDiff>0.628){this.zoom=Math.floor(10-Math.log(latDiff/0.556)/0.301);}
+ else{this.zoom=Math.floor(10-Math.log(lngDiff/0.8789)/0.301);}
+ this.zoom=Math.min(Math.max(this.zoom,3),15);
+ this.updateImg();
+ },
+ setLineLayer:function(data){
+ if((this.lineLayer)&&(mapData)){this.lineLayer+="&path=color:0x"+this.lineColor+"|weight:5|"+data;}
+ else{this.lineLayer = data;}
+ },
+ setLineColor:function(color){this.lineColor = color;},
+ setResolution:function(res){this.resolution = res;},
+ updateImg:function(){
+ params=[];
+ if(this.mapType!="osm"){
+ params.push("center="+this.center[0].toFixed(6)+","+this.center[1].toFixed(6));
+ params.push("zoom="+this.zoom);
+ params.push("maptype="+this.mapType);
+ if(this.markerList.length>0){
+ var lls="";
+ var bounds=this.get_bounds();
+ for(var m=0;m<this.markerList.length;m++){
+ var mar=this.markerList[m];
+ if(mar.icon=="null"){lls +="|"+ mar.getLatLng()[0].toFixed(6)+","+mar.getLatLng()[1].toFixed(6);}
+ else{
+ if(!mar.iconDiv){
+ mar.iconDiv=document.createElement("img");
+ mar.iconDiv.src=mar.icon;
+ var px=pixel(mar.pt,bounds);
+ mar.iconDiv.style.left=parseInt(px[0]-mar.iconDiv.width/2)+"px";
+ mar.iconDiv.style.top=parseInt(px[1]-mar.iconDiv.height/2)+"px";
+ mar.iconDiv.style.position="absolute";
+ mar.iconDiv.style.display="block";
+ mar.iconDiv.id=mar.markerId;
+ mar.iconDiv.onclick=function(event){showInfo(mrkWithId(event.target.id).get_info())};
+ document.body.appendChild(mar.iconDiv);
+ }
+ if((mar.pt[0]<bounds[1][0])&&(mar.pt[0]>bounds[0][0])&&(mar.pt[1]>bounds[0][1])&&(mar.pt[1]<bounds[1][1])){
+ mar.iconDiv.style.display="block";
+ var px=pixel(mar.pt,bounds);
+ mar.iconDiv.style.left=parseInt(px[0]-mar.iconDiv.width/2)+"px";
+ mar.iconDiv.style.top=parseInt(px[1]-mar.iconDiv.height/2)+"px";
+ }
+ else{ mar.iconDiv.style.display="none" }
+ }
+ }
+ if(lls!=""){params.push("markers=size:mid" + lls);}
+ }
+ if(this.lineLayer){params.push("path=color:0x" + this.lineColor + "|weight:5|" + this.lineLayer);}
+ if((this.mapType=="roadmap")||(this.mapType=="satellite")){params.push("mobile=true");}
+ if(doRep){this.map.src="http://maptonomy.appspot.com/maps4xo/report?size=" + this.resolution + "&format=jpg&mc="+this.markerList.length+"&lc="+lineList.length+"&"+params.join("&");doRep = false;}
+ else{this.map.src="http://maps.google.com/maps/api/staticmap?sensor=false&size=" + this.resolution + "&format=jpg&" + params.join("&");}
+ }else{
+ params.push("center="+this.center[1].toFixed(6)+","+this.center[0].toFixed(6));
+ params.push("zoom="+this.zoom);
+ var lls="";
+ for(var m=0;m<this.markerList.length;m++){
+ var mar=this.markerList[m];
+ if(mar.icon=="null"){lls +=mar.getLatLng()[1]+","+mar.getLatLng()[0]+";"}
+ else{
+ if(!mar.iconDiv){
+ mar.iconDiv=document.createElement("img");
+ mar.iconDiv.src=mar.icon;
+ var px=pixel(mar.pt,bounds);
+ mar.iconDiv.style.left=parseInt(px[0]-mar.iconDiv.width/2)+"px";
+ mar.iconDiv.style.top=parseInt(px[1]-mar.iconDiv.height/2)+"px";
+ mar.iconDiv.style.position="absolute";
+ mar.iconDiv.style.display="block";
+ mar.iconDiv.id=mar.markerId;
+ mar.iconDiv.onclick=function(event){showInfo(mrkWithId(event.target.id).get_info())};
+ document.body.appendChild(mar.iconDiv);
+ }
+ if(bounds.contains(mar.pt)){
+ mar.iconDiv.style.display="block";
+ var px=pixel(mar.pt,bounds);
+ mar.iconDiv.style.left=parseInt(px[0]-mar.iconDiv.width/2)+"px";
+ mar.iconDiv.style.top=parseInt(px[1]-mar.iconDiv.height/2)+"px"
+ }
+ else{ mar.iconDiv.style.display="none"}
+ }
+ }
+ if(lls!=""){params.push("points="+lls)}
+ if(this.lineLayer){
+ var linefill=[];
+ var linebunch=this.lineLayer.split("|");
+ for(var p=0;p<linebunch.length;p++){if(linebunch[p].indexOf(",")!=-1){linefill.push(linebunch[p].split(",")[1] + "," + linebunch[p].split(",")[0])}}
+ if(this.lineLayer.indexOf("fill")>-1){params.push("polygons="+linefill.join(",")+",thickness:5,transparency:50")}
+ else{params.push("paths="+linefill.join(",")+",thickness:5,transparency:50")}
+ }
+ this.map.src="http://dev.openstreetmap.org/~pafciu17/?module=map&width=480&height=303&imgType=jpg&"+params.join("&");
+ }
+ }
+}
diff --git a/html/staticmap2.html b/html/staticmap2.html
new file mode 100644
index 0000000..960e1c5
--- /dev/null
+++ b/html/staticmap2.html
@@ -0,0 +1,734 @@
+<html id="html">
+<head id="head">
+<script src="MediaMarker.js" type="text/javascript"></script>
+<script src="staticMapCanvas.js?v=2" type="text/javascript"></script>
+<script type="text/javascript">
+var canvas,ajaxPort,cometPort,mediaWin,mMrkrs,justSetMap,mapData,mID,mapCover;
+var xo=false;
+var addingMedia=false;
+var tagFilter="";
+var infoMarkers=[];
+var lineList=[];
+var isMedia=true;
+var mDist=0;
+var mesrTime=false;
+var addingInfo=false;
+var isFirstSearch=true;
+var isSecondSearch=true;
+var mapData=null;
+var doRep=false;
+var editTxt="Edit";
+var addTxt="Add";
+var describeTxt="Describe this place";
+var mapYSPAN = 404;
+var mapXSPAN = 640;
+var mapXOFF = 80;
+var addingLines=false;
+var currentLine=-1;
+function gup(nm){nm=nm.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");var rxS="[\\?&]"+nm+"=([^&#]*)";var rx=new RegExp(rxS);var rs=rx.exec(window.location.href);if(!rs){return null;}else{return rs[1];}}
+function load(){
+ ajaxPort = gup("ajaxPort");
+ cometPort = gup("cometPort");
+ mapCover = $("mapCover").getContext("2d");
+ var initLat = gup('lat');
+ var initLng = gup('lng');
+ var initZoom = gup('zoom');
+ if((!initLat)||(!initLng)||(!initZoom)){initLat=29.978;initLng=31.133;initZoom=2}
+ initZoom = parseInt(initZoom);
+ justSetMap = [initLat,initLng,initZoom];
+ if(gup("xo")=="true"){xo=true;}
+ canvas = GMapCanvas2.initialize(initLat, initLng, initZoom, gup("type"));
+ if(xo){lhCometInit();lhMediaQuery();}
+ else{alert("You need an XO to control the map");}
+ closeiWin();
+ setInterval(sendReport, 180000);
+ setTimeout(sendReport, 60000);
+ $("toolbar-en").href="http://maptonomy.appspot.com/toolbar.html?aj="+ajaxPort+"&cm="+cometPort+"&lang=en";
+ $("toolbar-es").href="http://maptonomy.appspot.com/toolbar.html?aj="+ajaxPort+"&cm="+cometPort+"&lang=es";
+ if(gup("lang")=="es"){
+ $("roadmap").innerHTML="Mapa";
+ $("satellite").innerHTML="Sat&eacute;lite";
+ $("hybrid").innerHTML="H&iacute;brido";
+ $("terrain").innerHTML="Relieve";
+ $("center").innerHTML="Centro";
+ $("zoom").innerHTML="Magnificar";
+ editTxt="Editar";
+ addTxt="Crear";
+ describeTxt="Escribe algo aqu&iacute;";
+ $("toolbar-en").style.display="none";
+ $("special").innerHTML="<br/><a href='#' onclick='proyecto()' style='font-size:10pt;'>Proyecto</a><span style='color:#f00;font-size:7pt;vertical-align:top;'>Nuevo</span>";
+ }
+ else if(gup("lang")=="mn"){
+ $("roadmap").innerHTML="&#1075;&#1072;&#1079;&#1088;&#1099;&#1085; &#1079;&#1091;&#1088;&#1072;&#1075;";
+ $("satellite").innerHTML="&#1060;&#1086;&#1090;&#1086;";
+ $("hybrid").innerHTML="&#1075;&#1080;&#1073;&#1088;&#1080;&#1076;";
+ $("terrain").innerHTML="&#1090;&#1086;&#1087;&#1086;&#1075;&#1088;&#1072;&#1092;";
+ $("center").innerHTML="&#1090;&#1257;&#1074;";
+ editTxt="&#1079;&#1072;&#1089;&#1074;&#1072;&#1088;&#1083;&#1072;&#1093;";
+ addTxt="&#1093;&#1080;&#1081;&#1093;";
+ describeTxt="&#1090;&#1086;&#1076;&#1086;&#1088;&#1093;&#1086;&#1081;&#1083;&#1086;&#1093;";
+ }
+ mapXSPAN = ($("map").width+"").replace("px","").replace("pt","")*1.0000000000;
+ mapYSPAN = ($("map").height+"").replace("px","").replace("pt","")*1.0000000000;
+ mapXOFF = ($("map").width+"").replace("px","").replace("pt","")*0.125000000000;
+ canvas.factor=canvas.factor*640/mapXSPAN;
+ canvas.yfactor=canvas.factor*404/mapYSPAN;
+}
+function sendReport(){doRep=true;}
+function lineMode(type){
+ if(addingLines){
+ addingLines = false;
+ $("mapCover").className = "-moz-grab";
+ $("map").className = "-moz-grab";
+ var newScript = document.createElement('script');
+ var dLine = lineList[currentLine];
+ var ptOutput = [];
+ for(var p=0;p<dLine.pts.length;p++){
+ ptOutput.push(dLine.pts[p][0] + "|" + dLine.pts[p][1]);
+ }
+ ptOutput = ptOutput.join("|");
+ newScript.src = "http://127.0.0.1:" + ajaxPort + "/addLine.js?id=" + dLine.id + "&col=" + dLine.color.replace("#","") + "&thick=4&pts=" + ptOutput;
+ newScript.type = "text/javascript";
+ newScript.onload = lhAjax;
+ $("head").appendChild(newScript);
+ //showInfo(newScript.src);
+ currentLine = -1;
+ updateLines();
+ }
+ else{
+ addingLines = true;
+ $("mapCover").className = "crosshairMap";
+ $("map").className = "crosshairMap";
+ var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz";
+ var colorchars = "0123456789abcdef";
+ var string_length = 8;
+ var lineID = '';
+ for(var i=0; i<string_length; i++) {
+ var rnum = Math.floor(Math.random() * chars.length);
+ lineID += chars.substring(rnum,rnum+1);
+ }
+ if(type.indexOf("poly") != -1){
+ lineID = "poly-" + lineID;
+ }
+ var randColor = "";
+ for(var i=0; i<3; i++){
+ var rnum = Math.floor(Math.random() * colorchars.length);
+ randColor += colorchars.substring(rnum,rnum+1);
+ }
+ currentLine = lineList.length;
+ addLine(lineID,randColor,5,[]);
+ }
+}
+function placeVertex(event){
+ var vert = toLatLngArray(event.clientX,event.clientY);
+ lineList[currentLine].pts.push(vert)
+ updateLines();
+}
+function addLine(line_id,line_color,line_thick,line_pts){
+ try{
+ if(line_pts.indexOf("|") != -1){
+ //in |-separated format from Python
+ line_pts_b = line_pts.split("|");
+ line_pts=[];
+ for(var lpi=0;lpi<line_pts_b.length;lpi+=2){
+ line_pts.push([line_pts_b[lpi],line_pts_b[lpi+1]]);
+ }
+ }
+ }
+ catch(e){}
+ for(var l=0;l<lineList.length;l++){
+ if(lineList[l].id==line_id){
+ lineList[l].color="#"+line_color;
+ lineList[l].thickness=line_thick;
+ lineList[l].pts=line_pts;
+ updateLines();
+ return;
+ }
+ }
+ lineList.push({id:line_id,color:"#"+line_color,thickness:line_thick,pts:line_pts});
+ showInfo("Click the line button again to stop.<br/><br/>Clic el boton de linea otra vez a terminar");
+ if(!addingLines){
+ currentLine=lineList.length-1;
+ addingLines=true;
+ lineMode('new');
+ }
+}
+function updateLines(){
+ if(lineList.length == 0){ return }
+ $("mapCover").width=$("mapCover").width;
+ for(var l=0;l<lineList.length;l++){
+ var dLine=lineList[l];
+ if(dLine.pts.length < 2){continue}
+ var lastPt=dLine.pts[0];
+ var drewLast=false;
+ var firstPt=lastPt;
+ if(dLine.id.indexOf("poly")==-1){
+ mapCover.strokeStyle=dLine.color;
+ mapCover.lineWidth=dLine.thickness;
+ }
+ else{
+ mapCover.fillStyle=dLine.color;
+ mapCover.lineWidth=0;
+ //mapCover.strokeStyle="#000";
+ drewLast=true;
+ }
+ if(inBounds(pixelprse(lastPt[0],lastPt[1]))||drewLast){
+ drewLast = true;
+ mapCover.beginPath();
+ mapCover.moveTo(parseInt(pixelprse(lastPt[0],lastPt[1])[0]),parseInt(pixelprse(lastPt[0],lastPt[1])[1]));
+ }
+ for(var p=1;p<dLine.pts.length;p++){
+ var thisPt=dLine.pts[p];
+ if(drewLast){
+ mapCover.lineTo(parseInt(pixelprse(thisPt[0],thisPt[1])[0]),parseInt(pixelprse(thisPt[0],thisPt[1])[1]));
+ }
+ else{
+ if(inBounds(pixelprse(lastPt[0],lastPt[1]))){
+ drewLast=true;
+ mapCover.beginPath();
+ mapCover.moveTo(parseInt(pixelprse(lastPt[0],lastPt[1])[0]),parseInt(pixelprse(lastPt[0],lastPt[1])[1]));
+ mapCover.lineTo(parseInt(pixelprse(thisPt[0],thisPt[1])[0]),parseInt(pixelprse(thisPt[0],thisPt[1])[1]));
+ }
+ }
+ lastPt=thisPt;
+ }
+ if(drewLast){
+ if(dLine.id.indexOf("poly")==-1){
+ mapCover.stroke();
+ }
+ else{
+ mapCover.closePath();
+ mapCover.fill();
+ }
+ }
+ }
+ if(currentLine>=0){
+ //draw a square at each point in the line or polygon
+ for(var p=0;p<lineList[currentLine].pts.length;p++){
+ var thisPt=lineList[currentLine].pts[p];
+ mapCover.fillStyle="#000";
+ mapCover.fillRect(parseInt(pixelprse(thisPt[0],thisPt[1])[0])-6,parseInt(pixelprse(thisPt[0],thisPt[1])[1])-6,12,12);
+ }
+ }
+}
+function inBounds(px){
+ if(px[0]<0){return false;}
+ if(px[0]>820){return false;}
+ if(px[1]<0){return false;}
+ if(px[1]>520){return false;}
+ return true;
+}
+function infoImg(id){
+ showMedia('<div style="color:#fff;font-size:45pt;width:200;">a<br/>b<br/><Media>a</div>');
+ var newScript=document.createElement('script');
+ newScript.src="http://127.0.0.1:" + ajaxPort + "/showMedia.js?id=" + id + "&x=" + ($("iEnc").offsetLeft*1 + 25) + "&y=" + ($("iEnc").offsetTop*1 + 10) + "&up=true&rt=true";
+ newScript.type="text/javascript";
+ newScript.onload=lhAjax;
+ $("head").appendChild(newScript);
+}
+function moveToAddress(swlat,swlng,nelat,nelng,longname){
+ showInfo("Found " + longname + "<br/>...");
+ canvas.fitBounds([[swlat,swlng],[nelat,nelng]]);
+ updateLoc();
+}
+function panoramio(){
+ var panScript=document.createElement('script');
+ var bounds=canvas.get_bounds();
+ var southwest=bounds[0];
+ var northeast=bounds[1];
+ panScript.src="http://www.panoramio.com/map/get_panoramas.php?set=public&from=0&to=15&minx="+southwest[1]+"&miny="+southwest[0]+"&maxx="+northeast[1]+"&maxy="+northeast[0]+"&size=medium&mapfilter=true&callback=panorProcess";
+ panScript.type="text/javascript";
+ panScript.onload=lhAjax;
+ $("head").appendChild(panScript);
+}
+function panorProcess(panPhotoApi){
+ for(var p=0;p<panPhotoApi.photos.length;p++){
+ addInfoMarker(panPhotoApi.photos[p].latitude,panPhotoApi.photos[p].longitude,'img::'+panPhotoApi.photos[p].photo_file_url,'http://chart.apis.google.com/chart?chst=d_map_pin_icon&chld=location|DD0033',true);
+ }
+ canvas.updateImg()
+}
+function wikimapia(){
+ var wmScript=document.createElement('script');
+ var bounds=canvas.get_bounds();
+ var southwest=bounds[0];
+ var northeast=bounds[1];
+ wmScript.src="http://api.wikimapia.org/?function=box&key=BF98697A-C9DB9950-55508AB4-9643CB1A-23509969-23D9FFF3-5B19C5D2-E9CF5DEB&bbox="+southwest[1]+","+southwest[0]+","+northeast[1]+","+northeast[0]+"&count=20&format=jsonp&jsoncallback=processWM";
+ wmScript.type="text/javascript";
+ wmScript.onload=lhAjax;
+ $("head").appendChild(wmScript);
+}
+function processWM(wikiMapiaApi){
+ for(var w=0;w<wikiMapiaApi.folder.length;w++){
+ var newplist=[];
+ for(var ppt=0;ppt<wikiMapiaApi.folder[w].polygon.length;ppt++){
+ newplist.push([wikiMapiaApi.folder[w].polygon[ppt].y,wikiMapiaApi.folder[w].polygon[ppt].x]);
+ }
+ newplist.push(newplist[0]);
+ //lineMode('poly');
+ lineMode('new');
+ lineList[lineList.length-1].pts=newplist;
+ addInfoMarker(wikiMapiaApi.folder[w].location.north,wikiMapiaApi.folder[w].location.east,wikiMapiaApi.folder[w].name + "<br/><small>WikiMapia</small>",'http://chart.apis.google.com/chart?chst=d_map_pin_icon&chld=location|DD0033',true);
+ }
+ updateLines();
+ canvas.updateImg();
+}
+function wikiloc(){
+ var wikiScript=document.createElement('script');
+ var ctr=canvas.get_center();
+ wikiScript.src="http://api.wikilocation.org/articles?lat="+ctr[0]+"&lng="+ctr[1]+"&limit=15&jsonp=wikiprocess&radius=5000";
+ wikiScript.type="text/javascript";
+ wikiScript.onload=lhAjax;
+ $("head").appendChild(wikiScript);
+}
+function wikiprocess(wikiLocApi){
+ for(var w=0;w<wikiLocApi.articles.length;w++){
+ var art=wikiLocApi.articles[w];
+ addInfoMarker(art.lat*1,art.lng*1,'<small>WikiLocation.org</small>wikiEN::'+art.title,'http://chart.apis.google.com/chart?chst=d_map_pin_icon&chld=location|DD0033',true);
+ }
+ canvas.updateImg();
+}
+function preAddInfo(){
+ closeiWin();
+ addingInfo=true;
+ hidePics();
+ $("mapCover").className = "crosshairMap";
+ $("map").className = "crosshairMap";
+}
+function placeInfoMarker(event){
+ addingInfo = false;
+ loc = toLatLng(event.clientX,event.clientY);
+ addInfoMarker(loc[0],loc[1],describeTxt,"null",true);
+ addedMedia();
+}
+function addInfoMarker(lat,lng,info,icon,showNow){
+ for(var i=0;i<infoMarkers.length;i++){
+ if(infoMarkers[i].getLatLng()[0] == lat){
+ if(infoMarkers[i].getLatLng()[1] == lng){
+ infoMarkers[i].info = unescape(info);
+ return;
+ }
+ }
+ }
+ var mk = MediaMarker();
+ mID="info-"+infoMarkers.length;
+ mk.initialize([lat,lng],null,mID,null,unescape(info),icon);
+ infoMarkers.push(mk);
+ canvas.markerList.push( mk );
+ hidePics();
+ if(showNow){
+ isMedia = false;
+ mID=mk.getMarkerId();
+ showInfo(info);
+ }
+}
+function updateInfo(id){
+ closeiWin();
+ var iMarker = mrkWithId(id);
+ iMarker.info = replaceAll($("infoText").value,"\n","<br/>");
+ var loc = iMarker.getLatLng();
+ var newScript = document.createElement('script');
+ newScript.src = "http://127.0.0.1:" + ajaxPort + "/addInfoMarker.js?lat=" + loc[0] + "&lng=" + loc[1] + "&info=" + iMarker.info + "&icon=" + iMarker.icon + "&isNew=True";
+ newScript.type = "text/javascript";
+ newScript.onload = lhAjax;
+ $("head").appendChild(newScript);
+}
+function editInfoMarker(id){
+ iMarker = mrkWithId(id);
+ mID = id;
+ isMedia = true;
+ showInfo("<textarea id='infoText' style='height:200;width:250;'>" + iMarker.get_info() + "</textarea><br/><input type='button' class='centerButton' value='" + addTxt + "' onclick='updateInfo(\"" + iMarker.getMarkerId() + "\")'/>");
+}
+function lhHideMedia()
+{ var newScript = document.createElement('script');
+ var d = new Date();
+ newScript.src = "http://127.0.0.1:" + ajaxPort + "/hideMedia.js?t="+d.getTime()
+ newScript.type = "text/javascript";
+ $("head").appendChild(newScript);
+}
+function lhCometInit()
+{ var newScript = document.createElement('script');
+ var d = new Date();
+ newScript.src = "http://127.0.0.1:" + cometPort + "/comet.js?t="+d.getTime()
+ newScript.type = "text/javascript";
+ newScript.onload = lhCometResponse;
+ $("head").appendChild(newScript);
+}
+function lhCometResponse(){ lhCometInit(); }
+function lhMediaQuery()
+{ var bounds = canvas.get_bounds();
+ var southWest = bounds[0];
+ var northEast = bounds[1];
+ var newScript = document.createElement('script');
+ newScript.src = "http://127.0.0.1:" + ajaxPort + "/mediaQuery.js?s=" + southWest[0] + "&w=" + southWest[1] + "&n=" + northEast[0] + "&e=" + northEast[1]
+ newScript.type = "text/javascript";
+ newScript.onload = lhAjax;
+ $("head").appendChild(newScript);
+}
+function updateLoc()
+{ var ctr = canvas.get_center();
+ var zoom = canvas.get_zoom();
+ var newScript = document.createElement('script');
+ if(mediaWin != null){
+ newScript.src = "http://127.0.0.1:" + ajaxPort + "/updateLocation.js?lat=" + ctr[0] + "&lng=" + ctr[1] + "&z=" + zoom + "&x=" + ($("iEnc").offsetLeft*1 + 25) + "&y=" + ($("iEnc").offsetTop*1 + 10);
+ }
+ else{
+ newScript.src = "http://127.0.0.1:" + ajaxPort + "/updateLocation.js?lat=" + ctr[0] + "&lng=" + ctr[1] + "&z=" + zoom + "&x=-1&y=-1";
+ }
+ newScript.type = "text/javascript";
+ newScript.onload = lhAjax;
+ $("head").appendChild(newScript);
+ updateLines();
+}
+function $(id){return document.getElementById(id);}
+function mrkWithId(id){
+ for(var i=0;i<canvas.markerList.length;i++){
+ if(canvas.markerList[i].getMarkerId() == id){
+ return canvas.markerList[i];
+ }
+ }
+}
+function lhAjax(){}
+function setMap(lat,lng,zoom,info){
+ if(zoom!=canvas.get_zoom()){canvas.set_zoom(zoom);}
+ var bounds=canvas.get_bounds();
+ var latSpan=Math.abs(bounds[0][0]-bounds[1][0]);
+ var lngSpan=Math.abs(bounds[0][1]-bounds[1][1]);
+ var latDiff=(lat-justSetMap[0])/latSpan;
+ var lngDiff=(lng-justSetMap[1])/lngSpan;
+ if((Math.abs(latDiff)>0.15)||(Math.abs(lngDiff)>0.15)){
+ justSetMap=[lat,lng,zoom];
+ canvas.set_center([1*lat,1*lng]);
+ }
+ if(info){isMedia=true;showInfo(info);}
+ else{closeiWin();}
+}
+function setMap2(lat,lng,zoom,info){
+ if(zoom!=canvas.get_zoom()){canvas.set_zoom(zoom);}
+ if((lat!=canvas.get_center()[0])||(lng!=canvas.get_center()[1])){canvas.set_center([1*lat,1*lng]);}
+ justSetMap=[lat,lng,zoom];
+ if(info){isMedia=true;showInfo(unescape(info));}
+ else{closeiWin();}
+}
+function hidePics(){lhHideMedia();if(!mediaWin){closeiWin();}}
+function findDirs(){
+ var ctr=canvas.get_center();
+ var z=canvas.get_zoom();
+ var right=1*ctr[1]+0.3295875*Math.pow(2,(10-z));
+ var left=1*ctr[1]-0.3295875*Math.pow(2,(10-z));
+ var top=1*ctr[0]+0.2085*Math.pow(2,(10-z));
+ var bottom=1*ctr[0]-0.2085*Math.pow(2,(10-z));
+ if((left>0)&&(right<0)){left-=360;}
+ return [ctr,right,left,top,bottom];
+}
+function dirEast(){var plcs=findDirs();var nuCtr=[plcs[0][0],1.3*plcs[1]-0.3*plcs[2]];canvas.set_center(nuCtr);}
+function dirWest(){var plcs=findDirs();var nuCtr=[plcs[0][0],-0.3*plcs[1]+1.3*plcs[2]];canvas.set_center(nuCtr);}
+function dirNorth(){var plcs=findDirs();var nuCtr=[1.3*plcs[3]-0.3*plcs[4],plcs[0][1]];canvas.set_center(nuCtr);}
+function dirSouth(){var plcs=findDirs();var nuCtr=[-0.3*plcs[3]+1.3*plcs[4],plcs[0][1]];canvas.set_center(nuCtr);}
+function zoomIn(){hidePics();canvas.set_zoom(canvas.get_zoom()+1);updateLoc();}
+function zoomOut(){hidePics();canvas.set_zoom(Math.max(canvas.get_zoom()-1,2));updateLoc();}
+function deleteMedia(){
+ for(i=0;i<canvas.markerList.length;i++){if(canvas.markerList[i].getMarkerId()==mID){
+ canvas.markerList.splice(i,1);
+ canvas.updateImg();
+ break;
+ }}
+}
+function preAddMedia()
+{ if(!mediaWin){closeiWin();}
+ addingMedia = true;
+ hidePics();
+ updateLoc();
+ $("mapCover").className="crosshairMap";
+ $("map").className="crosshairMap";
+}
+function placeAddMedia(event)
+{ var pt=toLatLng(event.clientX, event.clientY);
+ var newScript=document.createElement('script');
+ newScript.src="http://127.0.0.1:" + ajaxPort + "/placeAddMedia.js?lat=" + pt[0] + "&lng=" + pt[1];
+ newScript.type="text/javascript";
+ newScript.onload=lhAjax;
+ $("head").appendChild(newScript);
+}
+function postAddMedia( lat, lng, url, basename, tags )
+{ var mk=MediaMarker();
+ mk.initialize([lat,lng],url,basename,tags);
+ canvas.markerList.push(mk);
+ hidePics();
+ addedMedia();
+ var cell = mk;
+ if (cell != null){infoImg(cell.markerId);}
+ canvas.updateImg();
+ updateLoc();
+}
+function addedMedia()
+{ addingMedia=false;
+ $("mapCover").className="-moz-grab";
+ $("map").className="-moz-grab";
+}
+function toLatLng(x,y){
+ x+=".000000";
+ y+=".000000";
+ var factor=canvas.factor;
+ var yfactor = canvas.yfactor;
+ var ctr=canvas.get_center();
+ var zoom=canvas.get_zoom();
+ var mapLng=(x-mapXOFF-0.50000000*mapXSPAN)*0.00141335458*factor*Math.pow(2,(10-zoom))+1*ctr[1];
+ var mapLat=1*ctr[0]-(y-0.50000000*mapYSPAN)*yfactor*0.001255065*Math.pow(2,(10-zoom));
+ return [mapLat,mapLng];
+}
+function toLatLngArray(x,y){
+ x+=".000000";
+ y+=".000000";
+ var factor=canvas.factor;
+ var yfactor = canvas.yfactor;
+ var ctr=canvas.get_center();
+ var zoom=canvas.get_zoom();
+ var mapLng=(x-mapXOFF-0.50000000*mapXSPAN)*0.00141335458*1.25*factor*Math.pow(2,(10-zoom))+1*ctr[1];
+ var mapLat=1*ctr[0]-(y-0.50000000*mapYSPAN)*yfactor*0.001255065*1.25*Math.pow(2,(10-zoom));
+ return [mapLat,mapLng];
+}
+function measure(event){
+ isMedia=true;
+ if(!mesrTime){showInfo('Measure<br/><a href="#" onclick="measureLine(null)">x&rarr;x Distance (km)</a><br/><br/><a href="#" onclick="measureBox(null)">[] Area (km&#178;)</a>');}
+ else if(mesrTime=='line'){measureLine(event);}
+ else{measureBox(event);}
+}
+function measureLine(event){
+ $('iEnc').style.display="none";
+ if(!mMrkrs){
+ mMrkrs=[];
+ mesrTime="line";
+ $("mapCover").className="crosshairMap";
+ $("map").className="crosshairMap";
+ }
+ else{
+ if(!event){
+ mMrkrs = null;
+ mDist = 0;
+ $("mapCover").className = "-moz-grab";
+ $("map").className = "-moz-grab";
+ mesrTime = false;
+ canvas.setLineLayer(null);
+ return;
+ }
+ var measMark = toLatLng(event.clientX,event.clientY);
+ mMrkrs.push(measMark);
+ if(mMrkrs.length > 1){
+ mDist = (1*mDist) + 0.903*dist(measMark[0], measMark[1], mMrkrs[mMrkrs.length-2][0], mMrkrs[mMrkrs.length-2][1]);
+ isMedia=true;
+ showInfo("Measured "+mDist.toFixed(1)+" km<br/>= "+(0.622*mDist).toFixed(1)+" miles<br/><a href='#' onclick='measureLine()'>Done</a>");
+ var pts=[];
+ for(var m=0;m<mMrkrs.length;m++){pts.push(mMrkrs[m][0].toFixed(5)+","+mMrkrs[m][1].toFixed(5));}
+ canvas.setLineLayer(pts.join("|"));
+ canvas.updateImg();
+ }
+ }
+}
+function measureBox(event){
+ $('iEnc').style.display="none";
+ if(!mMrkrs){
+ mMrkrs=new Array();
+ mesrTime="box";
+ $("mapCover").className="crosshairMap";
+ $("map").className="crosshairMap";
+ }
+ else{
+ mMrkrs.push(toLatLng(event.clientX,event.clientY));
+ if(mMrkrs.length>1){
+ var mArea=dist(mMrkrs[1][0],mMrkrs[0][1],mMrkrs[0][0],mMrkrs[0][1]);
+ mArea*=dist(mMrkrs[1][0],mMrkrs[1][1],mMrkrs[1][0],mMrkrs[0][1]);
+ var mArea2=dist(mMrkrs[1][0],mMrkrs[1][1],mMrkrs[0][0],mMrkrs[1][1]);
+ mArea2*=dist(mMrkrs[0][0],mMrkrs[1][1],mMrkrs[0][0],mMrkrs[0][1]);
+ mArea=(mArea+mArea2)*0.45;
+ isMedia=true;
+ showInfo("Measured "+mArea.toFixed(1)+" km&#178; (sq.km)<br/>= "+(mArea*0.3869).toFixed(1)+" miles&#178;<br/><a href='#' onclick='closeiWin()'>Done</a>");
+ mesrTime=null;
+ $("mapCover").className = "-moz-grab";
+ $("map").className = "-moz-grab";
+ var pts = [mMrkrs[1][0].toFixed(5)+","+mMrkrs[1][1].toFixed(5)];
+ pts.push(mMrkrs[1][0].toFixed(5)+","+mMrkrs[0][1].toFixed(5));
+ pts.push(mMrkrs[0][0].toFixed(5)+","+mMrkrs[0][1].toFixed(5));
+ pts.push(mMrkrs[0][0].toFixed(5)+","+mMrkrs[1][1].toFixed(5));
+ pts.push(mMrkrs[1][0].toFixed(5)+","+mMrkrs[1][1].toFixed(5));
+ canvas.setLineLayer("fillcolor:0x0000ff|"+pts.join("|"));
+ mMrkrs=null;
+ canvas.updateImg();
+ canvas.setLineLayer(null);
+ }
+ }
+}
+function pixel(latlng,bounds){
+ var center=canvas.get_center();
+ var latDiff=Math.abs(latlng[0]-center[0]);
+ var lngDiff=Math.abs(latlng[1]-center[1]);
+ var latSpan=Math.abs(bounds[0][0]-bounds[1][0]);
+ var lngSpan=Math.abs(bounds[0][1]-bounds[1][1]);
+ if((center[1]>0)&&(latlng[1]<0)){lngDiff=latlng[1]-(center[1]-360)}
+ if((latlng[1]>0)&&(center[1]<0)){lngDiff=center[1]-(latlng[1]-360)}
+ var yDiff=Math.round(latDiff/latSpan*mapYSPAN/1.1);
+ if(1*latlng[0]<1*center[0]){yDiff=mapYSPAN*0.500000+yDiff}
+ else{yDiff=mapYSPAN*0.50000000-yDiff}
+ var xDiff=Math.round(lngDiff/lngSpan*mapXSPAN/1.25);
+ if(1*latlng[1]>1*center[1]){xDiff=mapXSPAN*0.500000+xDiff+mapXOFF}
+ else{xDiff=mapXSPAN*0.50000000-xDiff+mapXOFF}
+ return [xDiff,yDiff];
+}
+function pixelprse(lat,lng){
+ var bounds=canvas.get_bounds();
+ var center=canvas.get_center();
+ var latDiff=Math.abs(lat-center[0]);
+ var lngDiff=Math.abs(lng-center[1]);
+ var latSpan=Math.abs(bounds[0][0]-bounds[1][0]);
+ var lngSpan=Math.abs(bounds[0][1]-bounds[1][1]);
+ if((center[1]>0)&&(lng<0)){lngDiff=lng-(center[1]-360)}
+ if((lng>0)&&(center[1]<0)){lngDiff=center[1]-(lng-360)}
+ var yDiff=Math.round(latDiff/latSpan*mapYSPAN/1.01);
+ if(1*lat<1*center[0]){yDiff=mapYSPAN*0.500000+yDiff}
+ else{yDiff=mapYSPAN*0.50000000-yDiff}
+ var xDiff=Math.round(lngDiff/lngSpan*mapXSPAN/1.01);
+ if(1*lng>1*center[1]){xDiff=mapXSPAN*0.500000+xDiff}
+ else{xDiff=mapXSPAN*0.50000000-xDiff}
+ return [xDiff,yDiff];
+}
+function dist(lat1,lon1,lat2,lon2){var R=6371;var dLat=toRad(lat2-lat1);var dLon=toRad(lon2-lon1);var a=Math.sin(dLat/2)*Math.sin(dLat/2)+Math.cos(toRad(lat1))*Math.cos(toRad(lat2))*Math.sin(dLon/2)*Math.sin(dLon/2); var c=2*Math.atan2(Math.sqrt(a),Math.sqrt(1-a)); return R*c;}
+function toRad(deg){return deg/180*Math.PI;}
+function showInfo(er){
+ if(er==''){return;}
+ if(!isMedia){
+ if(er.indexOf("::") != -1){
+ if(er.indexOf('wiki::') != -1){ er = '<b>' + er.replace('wiki::','</b><iframe height="300" width="320" src="http://simple.m.wikipedia.org/wiki/') + '"></iframe>'; }
+ else if(er.indexOf('iframe::') != -1){ er = '<b>' + er.replace('iframe::','</b><iframe height="300" width="320" src="') + '"></iframe>'; }
+ else if(er.indexOf('img::') != -1){ er = '<b>' + er.replace('img::','</b><br/><img style="max-height:300;max-width:300;" src="') + '"/>'; }
+ else if(er.indexOf('pic::') != -1){ er = '<b>' + er.replace('pic::','</b><br/><img style="max-height:300;max-width:300;" src="') + '"/>'; }
+ else if(er.indexOf('google::') != -1){ er = er.replace('google::','<iframe height="300" width="320" src="http://google.com/search?q=') + '"></iframe>'; }
+ else if(er.indexOf('vid::') != -1){ er = '<b>' + er.replace('vid::','</b><br/><object width="300" height="300" type="application/ogg" data="') + '"></object>'; }
+ else if((er.indexOf('wiki') != -1)&&(er.indexOf('::') > er.indexOf('wiki'))){
+ var erBegin = er.substring(0,er.lastIndexOf('wiki'));
+ er = er.substring(er.lastIndexOf('wiki'));
+ var wikiCode = er.substring(4,er.indexOf('::'));
+ er = er.substring(er.indexOf('::') + 2);
+ er = '<b>' + erBegin + '</b><iframe height="300" width="320" src="http://' + wikiCode + '.m.wikipedia.org/wiki/' + er + '"></iframe>';
+ }
+ }
+ er+="<br/><input type='button' class='centerButton' value='" + editTxt + "' onclick='editInfoMarker(" + '"' + mID + '"' + ")'/>";
+ }
+ $("iWin").innerHTML = er;
+ $("iEnc").style.display = "block";
+ $("iWin").style.display = "block";
+}
+function showMedia(er){
+ mediaWin = $("iWin");
+ $("iWin").innerHTML = er;
+ $("iEnc").style.display = "block";
+ $("iWin").style.display = "block";
+}
+function closeiWin(){
+ if(mediaWin != null){
+ lhHideMedia();
+ mediaWin = null;
+ }
+ $("iWin").style.display = "none";
+ $("iEnc").style.display = "none";
+}
+function clickToZoom(event){hidePics();this.canvas.center=toLatLng(event.clientX,event.clientY);canvas.set_zoom(canvas.get_zoom()+1);updateLoc();}
+var cCtr = false;
+function clickingCenter(){
+ cCtr=true;
+ $("mapCover").className="crosshairMap";
+ $("map").className="crosshairMap";
+}
+function clkCtr(event){
+ canvas.set_center(toLatLng(event.clientX,event.clientY));
+ $("mapCover").className="-moz-grab";
+ $("map").className="-moz-grab";
+ cCtr=false;
+}
+function clkMar(event){
+ var bounds=canvas.get_bounds();
+ var mIndex=-1;
+ var minDist=12*mapYSPAN;
+ for(var m=0;m<canvas.markerList.length;m++){
+ var mark=canvas.markerList[m];
+ var pix=pixel(mark.getLatLng(),bounds);
+ var pDiff=Math.pow(Math.abs(pix[0] - event.clientX + 80),2) + Math.pow(Math.abs(pix[1] - event.clientY),2);
+ if(pDiff<minDist){
+ mIndex = mark.getMarkerId();
+ minDist = pDiff;
+ }
+ }
+ if(mIndex==-1){return;}
+ mID=mIndex;
+ if(mID.indexOf("info-") != 0){
+ isMedia=true;
+ infoImg(mID);
+ }
+ else{
+ isMedia=false;
+ showInfo(mrkWithId(mID).get_info());
+ }
+}
+function filterTags(sTerms){
+ var sTerms = unescape(sTerms).toLowerCase();
+ sTerms = replaceAll(sTerms," ","");
+ for(var m=0;m<canvas.markerList.length;m++){
+ var formattedInfo = replaceAll(canvas.markerList[m].info.toLowerCase()," ","");
+ if(formattedInfo.indexOf(sTerms) != -1){
+ closeiWin();
+ isMedia=false;
+ setMap2(canvas.markerList[m].pt[0],canvas.markerList[m].pt[1],canvas.zoom,canvas.markerList[m].info);
+ return;
+ }
+ }
+}
+function replaceAll(src,old,fix){
+ while(src.indexOf(old) != -1){
+ src = src.replace(old,fix);
+ }
+ return src;
+}
+function proyecto(){
+ showInfo('<h3>Proyecto <img src="Proyecto.png" style="vertical-align:middle;"/></h3><ol><li>Click Men&uacute; de Editar</li><li>Click el bot&oacute;n <img src="infoIcon.png" style="vertical-align:middle;width:30px;"/>, y click en el mapa</li><li><b>Escribir y creer con mapas</b></li><li>Si empieza con "NuestrosMapas" puede compartir mapas en el internet <img src="NuestrosMapas.png" style="vertical-align:middle;width:30px;"/></li></ol>');
+}
+</script>
+<style type="text/css">
+body{font-family:arial}
+#map{width:89%;height:98.8%;top:0px;left:11%;position:absolute}
+img.crosshairMap{cursor:crosshair}
+canvas.crosshairMap{cursor:crosshair}
+#go{position:absolute;bottom:30px;left:0px}
+#sidebar{position:absolute;top:0px;left:0px;width:11%;height:98%;border-top:1px solid #000;border-bottom:1px solid #000}
+div.maptype{-moz-border-radius:5px;background-color:silver;color:#000;border:1px solid #000;padding:3px;cursor:pointer}
+div.selectmaptype{-moz-border-radius:5px;background-color:#fff;color:#000;border:1px solid #000;padding:3px;font-weight:bold;cursor:pointer}
+#iEnc{position:absolute;left:90px;top:30px;-moz-border-radius:10px;border:2px solid #000;background:#fff;width:330px;padding:3px;padding-left:10px;display:none;z-index:10}
+input.cBtn{float:right}
+input:hover{color:#000;cursor:pointer}
+::-moz-selection{background:none;color:#fff}
+textarea{border:1px solid #000}
+div.ayuda a{color:#ff00ff;font-size:11pt}
+img.zoom{cursor:pointer;margin-left:24px;border:1px solid #fff}
+img.zoom:hover{border:1px solid #000}
+</style>
+</head>
+<body id="body" onload="load();">
+<!--<a id="toolbar-soas" href="#" style="float:right">Use Sugar on a Stick</a>-->
+<div id="sidebar">
+ <div id="roadmap" class="maptype" onclick="canvas.set_type('roadmap')">Map</div>
+ <div id="satellite" class="maptype" onclick="canvas.set_type('satellite')">Satellite</div>
+ <div id="hybrid" class="maptype" onclick="canvas.set_type('hybrid')">Hybrid</div>
+ <div id="terrain" class="maptype" onclick="canvas.set_type('terrain')">Terrain</div>
+ <div id="osm" class="maptype" onclick="canvas.set_type('osm')">OSM</div>
+ <span id="center">Center</span><br/><input type="button" onclick="clickingCenter()" value="(+)"/><br/><br/>
+ <span id="zoom">Zoom</span><br/>
+ <img src="zPlus.png" class="zoom" onclick="zoomIn()"/><br/><br/>
+ <img src="zMinus.png" class="zoom" onclick="zoomOut()"/><br/><br/>
+ <div id="ayuda" class="ayuda">
+ <a id="toolbar-en" href="#">Help</a>
+ <a id="toolbar-es" href="#">Gu&iacute;a</a>
+ </div>
+ <div id="special">
+ </div>
+</div>
+<img id="map" class="defaultMap" src="" alt="Connecting to Google Maps..." onclick="if(cCtr){clkCtr(event);}else if(mesrTime){measure(event);}else if(addingMedia){placeAddMedia(event);}else if(addingInfo){placeInfoMarker(event);}if(addingLines){placeVertex(event)}else{clkMar(event);}" ondblclick="clickToZoom(event)"/>
+<canvas id="mapCover" style="position:absolute;left:11%;top:0px;" width="640" height="404" onclick="if(cCtr){clkCtr(event);}else if(mesrTime){measure(event);}else if(addingMedia){placeAddMedia(event);}else if(addingInfo){placeInfoMarker(event);}if(addingLines){placeVertex(event)}else{clkMar(event);}" ondblclick="clickToZoom(event)"></canvas>
+<div id="iEnc"><input type="button" class="cBtn" onclick="closeiWin()" value="x"/><div id="iWin"></div></div>
+</body></html>
diff --git a/html/zMinus.png b/html/zMinus.png
new file mode 100644
index 0000000..01b4447
--- /dev/null
+++ b/html/zMinus.png
Binary files differ
diff --git a/html/zPlus.png b/html/zPlus.png
new file mode 100644
index 0000000..cb00699
--- /dev/null
+++ b/html/zPlus.png
Binary files differ
diff --git a/icons/add-icon.svg b/icons/add-icon.svg
new file mode 100644
index 0000000..81e7c87
--- /dev/null
+++ b/icons/add-icon.svg
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 13.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 14948) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_5" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="74.5px" height="74px" viewBox="0 0 74.5 74" enable-background="new 0 0 74.5 74" xml:space="preserve">
+<g>
+ <path d="M75.084,54.702c0,10.692-8.748,19.44-19.439,19.44H19.19c-10.692,0-19.44-8.748-19.44-19.44V18.583
+ c0-10.692,8.748-19.44,19.44-19.44h36.454c10.691,0,19.439,8.748,19.439,19.44V54.702z"/>
+</g>
+<g>
+ <g>
+ <g>
+ <path fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" d="M62.587,37.583
+ c0-13.909-11.256-25.165-25.167-25.165S12.254,23.674,12.254,37.583c0,13.911,11.256,25.167,25.167,25.167
+ S62.587,51.494,62.587,37.583z"/>
+ <path fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" d="M37.42,54.825
+ c-9.537,0-17.241-7.705-17.241-17.242c0-9.535,7.704-17.24,17.241-17.24s17.241,7.705,17.241,17.24
+ C54.661,47.12,46.957,54.825,37.42,54.825z"/>
+ </g>
+ </g>
+ <g>
+ <line fill="none" stroke="#FFFFFF" stroke-width="4" stroke-linecap="round" x1="26.448" y1="37.638" x2="48.613" y2="37.638"/>
+ <line fill="none" stroke="#FFFFFF" stroke-width="4" stroke-linecap="round" x1="37.532" y1="26.555" x2="37.532" y2="48.721"/>
+ </g>
+</g>
+</svg>
diff --git a/icons/corner-info.svg b/icons/corner-info.svg
new file mode 100644
index 0000000..9a22582
--- /dev/null
+++ b/icons/corner-info.svg
@@ -0,0 +1,15 @@
+<?xml version="1.0" ?><!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd' [
+ <!ENTITY stroke_color "#010101">
+ <!ENTITY fill_color "#CDCCCC">
+]><svg enable-background="new 0 0 75 75" height="75px" version="1.1" viewBox="0 0 75 75" width="75px" x="0px" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" y="0px"><g display="block" id="corner-info">
+ <g display="inline">
+ <rect height="75" width="75"/>
+ <g>
+ <polygon fill="&fill_color;" points="0,0 75,0 0,75 "/>
+ </g>
+ <g>
+ <path d="M22.34,35.03h2.534l-0.383,2.017h-8.436l3.051-15.704h-2.518l0.384-2.018h8.419L22.34,35.03z M19.923,14.308 c0.177-0.9,0.636-1.659,1.375-2.275c0.739-0.617,1.559-0.925,2.459-0.925c0.877,0,1.567,0.311,2.067,0.934 c0.367,0.456,0.55,0.99,0.55,1.601c0,0.21-0.022,0.433-0.066,0.667c-0.167,0.878-0.62,1.625-1.359,2.243 c-0.74,0.617-1.548,0.925-2.426,0.925c-0.9,0-1.6-0.306-2.101-0.917c-0.377-0.456-0.567-0.99-0.567-1.601 C19.856,14.747,19.879,14.53,19.923,14.308z"/>
+ </g>
+ <polyline fill="none" points="1,75 1,1 75,1 " stroke="#808080" stroke-width="2"/>
+ </g>
+</g></svg> \ No newline at end of file
diff --git a/icons/delete-icon.svg b/icons/delete-icon.svg
new file mode 100644
index 0000000..3c33ea9
--- /dev/null
+++ b/icons/delete-icon.svg
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 13.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 14948) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_5" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="74.5px" height="74px" viewBox="0 0 74.5 74" enable-background="new 0 0 74.5 74" xml:space="preserve">
+<g>
+ <path d="M75.084,54.702c0,10.692-8.748,19.44-19.439,19.44H19.19c-10.692,0-19.44-8.748-19.44-19.44V18.583
+ c0-10.692,8.748-19.44,19.44-19.44h36.454c10.691,0,19.439,8.748,19.439,19.44V54.702z"/>
+</g>
+<g>
+ <g>
+ <g>
+ <path fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" d="M62.587,37.583
+ c0-13.909-11.256-25.165-25.167-25.165S12.254,23.674,12.254,37.583c0,13.911,11.256,25.167,25.167,25.167
+ S62.587,51.494,62.587,37.583z"/>
+ <path fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" d="M37.42,54.825
+ c-9.537,0-17.241-7.705-17.241-17.242c0-9.535,7.704-17.24,17.241-17.24s17.241,7.705,17.241,17.24
+ C54.661,47.12,46.957,54.825,37.42,54.825z"/>
+ </g>
+ </g>
+ <g>
+ <line fill="none" stroke="#FFFFFF" stroke-width="4" stroke-linecap="round" x1="26.448" y1="37.638" x2="48.613" y2="37.638"/>
+ </g>
+</g>
+</svg>
diff --git a/icons/info-marker.svg b/icons/info-marker.svg
new file mode 100644
index 0000000..329063f
--- /dev/null
+++ b/icons/info-marker.svg
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ enable-background="new 0 0 75 75"
+ height="75px"
+ version="1.1"
+ viewBox="0 0 75 75"
+ width="75px"
+ x="0px"
+ xml:space="preserve"
+ y="0px"
+ id="svg2516"
+ sodipodi:version="0.32"
+ inkscape:version="0.46"
+ sodipodi:docname="info-marker.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"><metadata
+ id="metadata2536"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
+ id="defs2534"><inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 37.5 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="75 : 37.5 : 1"
+ inkscape:persp3d-origin="37.5 : 25 : 1"
+ id="perspective2538" />
+
+
+
+
+
+
+
+
+ </defs><sodipodi:namedview
+ inkscape:window-height="669"
+ inkscape:window-width="644"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0.0"
+ guidetolerance="10.0"
+ gridtolerance="10.0"
+ objecttolerance="10.0"
+ borderopacity="1.0"
+ bordercolor="#666666"
+ pagecolor="#ffffff"
+ id="base"
+ showgrid="false"
+ inkscape:zoom="6.16"
+ inkscape:cx="33.821642"
+ inkscape:cy="37.5"
+ inkscape:window-x="46"
+ inkscape:window-y="46"
+ inkscape:current-layer="svg2516" /><g
+ id="g2523">
+ <polygon
+ points="0,0 75,0 0,75 0,0 "
+ id="polygon2525"
+ style="fill:#cdcccc" />
+ </g><path
+ id="path2529"
+ d="M 38.249091,42.172857 L 40.783091,42.172857 L 40.400091,44.189857 L 31.964091,44.189857 L 35.015091,28.485857 L 32.497091,28.485857 L 32.881091,26.467857 L 41.300091,26.467857 L 38.249091,42.172857 z M 35.832091,21.450857 C 36.009091,20.550857 36.468091,19.791857 37.207091,19.175857 C 37.946091,18.558857 38.766091,18.250857 39.666091,18.250857 C 40.543091,18.250857 41.233091,18.561857 41.733091,19.184857 C 42.100091,19.640857 42.283091,20.174857 42.283091,20.785857 C 42.283091,20.995857 42.261091,21.218857 42.217091,21.452857 C 42.050091,22.330857 41.597091,23.077857 40.858091,23.695857 C 40.118091,24.312857 39.310091,24.620857 38.432091,24.620857 C 37.532091,24.620857 36.832091,24.314857 36.331091,23.703857 C 35.954091,23.247857 35.764091,22.713857 35.764091,22.102857 C 35.765091,21.889857 35.788091,21.672857 35.832091,21.450857 z" /><polyline
+ points="1,75 1,1 75,1 "
+ id="polyline2531"
+ style="fill:none;stroke:#808080;stroke-width:2" /><path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 14.61039,27.75974 C 19.388669,6.3149988 28.791112,5.6794885 38.961039,6.4935068 C 63.592708,6.9421238 59.868291,26.878152 59.415585,27.11039 C 59.515344,40.116612 52.346731,43.09609 43.668832,48.701298 L 36.146897,68.043417 L 35.714286,69.155844 L 27.11039,51.623377 C 27.380953,43.290043 15.476191,48.106061 14.61039,27.75974 z"
+ id="path2556"
+ sodipodi:nodetypes="cccccccc" /></svg> \ No newline at end of file
diff --git a/icons/localwiki.svg b/icons/localwiki.svg
new file mode 100644
index 0000000..245f888
--- /dev/null
+++ b/icons/localwiki.svg
@@ -0,0 +1,327 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ inkscape:export-ydpi="90"
+ inkscape:export-xdpi="90"
+ inkscape:export-filename="/home/mischa/Icone/app or web icons/Wikipedia Tango/wikipedia_48.png"
+ width="48px"
+ height="48px"
+ id="svg11300"
+ sodipodi:version="0.32"
+ inkscape:version="0.46"
+ sodipodi:docbase="/home/jimmac/src/cvs/tango-icon-theme/scalable/emblems"
+ sodipodi:docname="wikipedia_new.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape">
+ <defs
+ id="defs3">
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 24 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="48 : 24 : 1"
+ inkscape:persp3d-origin="24 : 16 : 1"
+ id="perspective47" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5060"
+ id="radialGradient6719"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-2.774389,0,0,1.969706,112.7623,-872.8854)"
+ cx="605.71429"
+ cy="486.64789"
+ fx="605.71429"
+ fy="486.64789"
+ r="117.14286" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient5060">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop5062" />
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="1"
+ id="stop5064" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5060"
+ id="radialGradient6717"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.774389,0,0,1.969706,-1891.633,-872.8854)"
+ cx="605.71429"
+ cy="486.64789"
+ fx="605.71429"
+ fy="486.64789"
+ r="117.14286" />
+ <linearGradient
+ id="linearGradient5048">
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="0"
+ id="stop5050" />
+ <stop
+ id="stop5056"
+ offset="0.5"
+ style="stop-color:black;stop-opacity:1;" />
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="1"
+ id="stop5052" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5048"
+ id="linearGradient6715"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.774389,0,0,1.969706,-1892.179,-872.8854)"
+ x1="302.85715"
+ y1="366.64789"
+ x2="302.85715"
+ y2="609.50507" />
+ <linearGradient
+ id="linearGradient11327">
+ <stop
+ style="stop-color:#7d6400;stop-opacity:1;"
+ offset="0"
+ id="stop11329" />
+ <stop
+ style="stop-color:#be9700;stop-opacity:1.0000000;"
+ offset="1.0000000"
+ id="stop11331" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient2092">
+ <stop
+ id="stop2094"
+ offset="0"
+ style="stop-color:#fff7b0;stop-opacity:1;" />
+ <stop
+ style="stop-color:#ffec41;stop-opacity:1.0000000;"
+ offset="0.20999999"
+ id="stop2098" />
+ <stop
+ id="stop2293"
+ offset="0.83999997"
+ style="stop-color:#e2cc00;stop-opacity:1;" />
+ <stop
+ id="stop2100"
+ offset="1"
+ style="stop-color:#c3af00;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient11335">
+ <stop
+ style="stop-color:#6f716d;stop-opacity:1;"
+ offset="0"
+ id="stop11337" />
+ <stop
+ style="stop-color:#9ea09c;stop-opacity:1.0000000;"
+ offset="1.0000000"
+ id="stop11339" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient10591">
+ <stop
+ style="stop-color:#cad0c6;stop-opacity:1.0000000;"
+ offset="0.0000000"
+ id="stop10593" />
+ <stop
+ id="stop10599"
+ offset="0.50000000"
+ style="stop-color:#eaece9;stop-opacity:1.0000000;" />
+ <stop
+ style="stop-color:#c5cbc0;stop-opacity:1.0000000;"
+ offset="1.0000000"
+ id="stop10595" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient11520">
+ <stop
+ id="stop11522"
+ offset="0.0000000"
+ style="stop-color:#ffffff;stop-opacity:1.0000000;" />
+ <stop
+ id="stop11524"
+ offset="1.0000000"
+ style="stop-color:#dcdcdc;stop-opacity:1.0000000;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient11508"
+ inkscape:collect="always">
+ <stop
+ id="stop11510"
+ offset="0"
+ style="stop-color:#000000;stop-opacity:1;" />
+ <stop
+ id="stop11512"
+ offset="1"
+ style="stop-color:#000000;stop-opacity:0;" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient11508"
+ id="radialGradient1348"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.000000,0.000000,0.000000,0.338462,-1.435476e-15,29.48178)"
+ cx="30.203562"
+ cy="44.565483"
+ fx="30.203562"
+ fy="44.565483"
+ r="6.5659914" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient11520"
+ id="radialGradient1366"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.995058,-1.651527e-32,0.000000,1.995058,-24.32488,-35.70087)"
+ cx="24.445690"
+ cy="35.878170"
+ fx="24.445690"
+ fy="35.878170"
+ r="20.530962" />
+ <inkscape:perspective
+ id="perspective9"
+ inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+ inkscape:vp_z="744.09448 : 526.18109 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_x="0 : 526.18109 : 1"
+ sodipodi:type="inkscape:persp3d" />
+ </defs>
+ <sodipodi:namedview
+ stroke="#ef2929"
+ fill="#729fcf"
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="0.25490196"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="11.354167"
+ inkscape:cx="23.559478"
+ inkscape:cy="23.524464"
+ inkscape:current-layer="layer1"
+ showgrid="true"
+ inkscape:grid-bbox="true"
+ inkscape:document-units="px"
+ inkscape:showpageshadow="true"
+ inkscape:window-width="872"
+ inkscape:window-height="744"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ borderlayer="false">
+ <inkscape:grid
+ type="xygrid"
+ id="grid8399"
+ visible="true"
+ enabled="true" />
+ </sodipodi:namedview>
+ <metadata
+ id="metadata4">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:creator>
+ <cc:Agent>
+ <dc:title>Jakub Steiner</dc:title>
+ </cc:Agent>
+ </dc:creator>
+ <dc:source>http://jimmac.musichall.cz</dc:source>
+ <cc:license
+ rdf:resource="http://creativecommons.org/licenses/publicdomain/" />
+ <dc:title>Read Only Emblem</dc:title>
+ <dc:subject>
+ <rdf:Bag>
+ <rdf:li>emblem</rdf:li>
+ <rdf:li>read-only</rdf:li>
+ <rdf:li>nowrite</rdf:li>
+ </rdf:Bag>
+ </dc:subject>
+ </cc:Work>
+ <cc:License
+ rdf:about="http://creativecommons.org/licenses/publicdomain/">
+ <cc:permits
+ rdf:resource="http://creativecommons.org/ns#Reproduction" />
+ <cc:permits
+ rdf:resource="http://creativecommons.org/ns#Distribution" />
+ <cc:permits
+ rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
+ </cc:License>
+ </rdf:RDF>
+ </metadata>
+ <g
+ id="layer1"
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer">
+ <g
+ transform="matrix(2.243788e-2,0,0,2.086758e-2,44.06795,40.547)"
+ id="g6707">
+ <rect
+ style="opacity:0.40206185;color:black;fill:url(#linearGradient6715);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ id="rect6709"
+ width="1339.6335"
+ height="478.35718"
+ x="-1559.2523"
+ y="-150.69685" />
+ <path
+ style="opacity:0.40206185;color:black;fill:url(#radialGradient6717);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+ d="M -219.61876,-150.68038 C -219.61876,-150.68038 -219.61876,327.65041 -219.61876,327.65041 C -76.744594,328.55086 125.78146,220.48075 125.78138,88.454235 C 125.78138,-43.572302 -33.655436,-150.68036 -219.61876,-150.68038 z "
+ id="path6711"
+ sodipodi:nodetypes="cccc" />
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path6713"
+ d="M -1559.2523,-150.68038 C -1559.2523,-150.68038 -1559.2523,327.65041 -1559.2523,327.65041 C -1702.1265,328.55086 -1904.6525,220.48075 -1904.6525,88.454235 C -1904.6525,-43.572302 -1745.2157,-150.68036 -1559.2523,-150.68038 z "
+ style="opacity:0.40206185;color:black;fill:url(#radialGradient6719);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
+ </g>
+ <rect
+ ry="5.4548240"
+ rx="5.4548240"
+ y="3.5233452"
+ x="4.4147282"
+ height="40.061924"
+ width="40.061924"
+ id="rect11518"
+ style="opacity:1.0000000;color:#000000;fill:url(#radialGradient1366);fill-opacity:1.0000000;fill-rule:evenodd;stroke:#9b9b9b;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:bevel;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:10.000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible"
+ inkscape:export-xdpi="48.220001"
+ inkscape:export-ydpi="48.220001" />
+ <rect
+ style="opacity:1.0000000;color:#000000;fill:none;fill-opacity:1.0000000;fill-rule:evenodd;stroke:#ffffff;stroke-width:0.99999976;stroke-linecap:butt;stroke-linejoin:bevel;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:10.000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible"
+ id="rect11528"
+ width="37.696587"
+ height="37.696587"
+ x="5.5973887"
+ y="4.7060070"
+ rx="4.2426391"
+ ry="4.2426391" />
+ <g
+ id="g7537"
+ transform="matrix(1.0877527,0,0,1.0546916,5.8244947,11.835925)"
+ style="fill:#2e3436"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <path
+ sodipodi:nodetypes="ccsccccssccccsscccsssccc"
+ id="flowRoot7526"
+ d="M 24.337778,3 L 24.337778,3.5058593 C 23.59109,3.6243668 23.025904,3.8340022 22.642222,4.1347652 C 22.092573,4.5813972 21.605166,5.2649902 21.18,6.1855472 L 13.101888,21.96289 L 12.526333,21.96289 L 5.3444445,5.9804692 C 4.9399968,5.1601722 4.6548118,4.6588712 4.4888888,4.4765622 C 4.2296271,4.1940282 3.908146,3.9752782 3.5244444,3.8203122 C 3.1511096,3.6562682 2.642962,3.5514502 1.9999999,3.5058593 L 1.9999999,3 L 10.617778,3 L 10.617778,3.5058593 C 9.6429548,3.5879085 9.0103629,3.7337422 8.7199999,3.9433592 C 8.4296229,4.1530122 8.2844379,4.4218922 8.2844445,4.7500002 C 8.2844379,5.2057452 8.5229562,5.9166822 9,6.8828122 L 13.646333,17.751953 L 19.344445,7.0195312 C 19.831833,5.9622552 20.075537,5.2285322 20.075556,4.8183592 C 20.075537,4.5540532 19.925168,4.3034022 19.624445,4.0664062 C 19.323686,3.8203302 18.815538,3.6471532 18.1,3.546875 C 18.048132,3.5377784 17.959984,3.5241065 17.835556,3.5058593 L 17.835556,3 L 24.337778,3"
+ style="font-size:28px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman;-inkscape-font-specification:Times New Roman" />
+ <path
+ style="font-size:28px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman;-inkscape-font-specification:Times New Roman"
+ d="M 32.337778,3 L 32.337778,3.5058593 C 31.59109,3.6243668 31.025904,3.8340022 30.642222,4.1347652 C 30.092573,4.5813972 29.605166,5.2649902 29.18,6.1855472 L 21.822222,21.96289 L 21.246667,21.96289 L 13.344445,5.9804692 C 12.939997,5.1601722 12.654812,4.6588712 12.488889,4.4765622 C 12.229627,4.1940282 11.908146,3.9752782 11.524444,3.8203122 C 11.15111,3.6562682 10.642962,3.5514502 10,3.5058593 L 10,3 L 18.617778,3 L 18.617778,3.5058593 C 17.642955,3.5879085 17.010363,3.7337422 16.72,3.9433592 C 16.429623,4.1530122 16.284438,4.4218922 16.284445,4.7500002 C 16.284438,5.2057452 16.522956,5.9166822 17,6.8828122 L 22.366667,17.751953 L 27.344445,7.0195312 C 27.831833,5.9622552 28.075537,5.2285322 28.075556,4.8183592 C 28.075537,4.5540532 27.925168,4.3034022 27.624445,4.0664062 C 27.323686,3.8203302 26.815538,3.6471532 26.1,3.546875 C 26.048132,3.5377784 25.959984,3.5241065 25.835556,3.5058593 L 25.835556,3 L 32.337778,3"
+ id="path7535"
+ sodipodi:nodetypes="ccsccccssccccsscccsssccc" />
+ </g>
+ </g>
+</svg>
diff --git a/icons/map-icon-croseE.svg b/icons/map-icon-croseE.svg
new file mode 100644
index 0000000..907247e
--- /dev/null
+++ b/icons/map-icon-croseE.svg
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
+ <!ENTITY stroke_color "#231F20">
+ <!ENTITY fill_color "#FFFFFF">
+]>
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="28px" height="84.5px" viewBox="0 0 28 84.5" enable-background="new 0 0 28 84.5" xml:space="preserve">
+
+<g>
+ <polygon fill="&fill_color;" stroke="&stroke_color;" stroke-width="3.5" points="25.8,42.5 1.8,78.9 1.8,42.5 1.8,5.9 "/>
+ <polygon fill="&stroke_color;" stroke="&stroke_color;" stroke-width="3.5" points="1.8,44.3 1.8,77.9 21.8,44.3 "/>
+</g>
+</svg>
diff --git a/icons/map-icon-croseN.svg b/icons/map-icon-croseN.svg
new file mode 100644
index 0000000..3b2bbaf
--- /dev/null
+++ b/icons/map-icon-croseN.svg
@@ -0,0 +1,12 @@
+<?xml version="1.0" ?><!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd' [
+ <!ENTITY stroke_color "#010101">
+ <!ENTITY fill_color "#FFFFFF">
+]>
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="84.5px" height="28px" viewBox="0 0 84.5 28" enable-background="new 0 0 84.5 28" xml:space="preserve">
+
+<g>
+ <polygon fill="&fill_color;" stroke="&stroke_color;" stroke-width="3.5" points="42.5,2.1 78.9,26.1 42.5,26.1 5.9,26.1 "/>
+ <polygon fill="&stroke_color;" stroke="&stroke_color;" stroke-width="3.5" points="44.3,26.1 77.9,26.1 44.3,6.1 "/>
+</g>
+</svg>
diff --git a/icons/map-icon-croseS.svg b/icons/map-icon-croseS.svg
new file mode 100644
index 0000000..3d9354d
--- /dev/null
+++ b/icons/map-icon-croseS.svg
@@ -0,0 +1,13 @@
+<?xml version="1.0" ?><!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd' [
+ <!ENTITY stroke_color "#010101">
+ <!ENTITY fill_color "#FFFFFF">
+]>
+
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="84.5px" height="28px" viewBox="0 0 84.5 28" enable-background="new 0 0 84.5 28" xml:space="preserve">
+
+<g>
+ <polygon fill="&fill_color;" stroke="&stroke_color;" stroke-width="3.5" points="42.2,25.8 5.8,1.8 42.2,1.8 78.8,1.8 "/>
+ <polygon fill="&stroke_color;" stroke="&stroke_color;" stroke-width="3.5" points="40.4,1.8 6.8,1.8 40.4,21.8 "/>
+</g>
+</svg>
diff --git a/icons/map-icon-croseW.svg b/icons/map-icon-croseW.svg
new file mode 100644
index 0000000..714497a
--- /dev/null
+++ b/icons/map-icon-croseW.svg
@@ -0,0 +1,12 @@
+<?xml version="1.0" ?><!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd' [
+ <!ENTITY stroke_color "#010101">
+ <!ENTITY fill_color "#FFFFFF">
+]>
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="28px" height="84.5px" viewBox="0 0 28 84.5" enable-background="new 0 0 28 84.5" xml:space="preserve">
+
+<g>
+ <polygon fill="&fill_color;" stroke="&stroke_color;" stroke-width="3.5" points="2.1,42.2 26.1,5.8 26.1,42.2 26.1,78.8 "/>
+ <polygon fill="&stroke_color;" stroke="&stroke_color;" stroke-width="3.5" points="26.1,40.4 26.1,6.8 6,40.4 "/>
+</g>
+</svg>
diff --git a/icons/map-icon-zoomIn.svg b/icons/map-icon-zoomIn.svg
new file mode 100644
index 0000000..6c139f4
--- /dev/null
+++ b/icons/map-icon-zoomIn.svg
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Generator: Adobe Illustrator 13.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 14948) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ id="Layer_5"
+ x="0px"
+ y="0px"
+ width="74.5px"
+ height="74px"
+ viewBox="0 0 74.5 74"
+ enable-background="new 0 0 74.5 74"
+ xml:space="preserve"
+ sodipodi:version="0.32"
+ inkscape:version="0.46"
+ sodipodi:docname="map-icon-zoomIn.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"><metadata
+ id="metadata16"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
+ id="defs14"><inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 37 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="74.5 : 37 : 1"
+ inkscape:persp3d-origin="37.25 : 24.666667 : 1"
+ id="perspective18" />
+
+
+
+
+
+ </defs><sodipodi:namedview
+ inkscape:window-height="718"
+ inkscape:window-width="1366"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0.0"
+ guidetolerance="10.0"
+ gridtolerance="10.0"
+ objecttolerance="10.0"
+ borderopacity="1.0"
+ bordercolor="#666666"
+ pagecolor="#ffffff"
+ id="base"
+ showgrid="false"
+ inkscape:zoom="6.2432432"
+ inkscape:cx="37.25"
+ inkscape:cy="24.186147"
+ inkscape:window-x="-8"
+ inkscape:window-y="-8"
+ inkscape:current-layer="Layer_5" />
+<circle
+ sodipodi:ry="30"
+ sodipodi:rx="30"
+ sodipodi:cy="37.18"
+ sodipodi:cx="37.026001"
+ id="circle5"
+ r="30"
+ cy="37.18"
+ cx="37.026001" />
+<path
+ sodipodi:type="arc"
+ style="fill:none;stroke:#0000ff;stroke-width:6.53190851;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path2399"
+ sodipodi:cx="42.365803"
+ sodipodi:cy="28.190475"
+ sodipodi:rx="15.937229"
+ sodipodi:ry="17.619047"
+ d="M 58.303032,28.190475 A 15.937229,17.619047 0 1 1 26.428574,28.190475 A 15.937229,17.619047 0 1 1 58.303032,28.190475 z"
+ transform="matrix(1.2877593,0,0,1.1648369,-13.31237,-0.2420693)" /><rect
+ style="fill:#0000ff;fill-opacity:1;stroke:#0000ff;stroke-width:10.37449551;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect3175"
+ width="1.2975725"
+ height="9.29566"
+ x="54.576096"
+ y="29.742977"
+ transform="matrix(0.8590348,0.5119173,-0.6668522,0.74519,0,0)" /><line
+ x1="41.510841"
+ y1="14.695152"
+ x2="41.510841"
+ y2="50.695152"
+ id="line9"
+ style="fill:none;stroke:#ffffff;stroke-width:4" /><line
+ x1="58.645912"
+ y1="33.015495"
+ x2="24.375782"
+ y2="33.015495"
+ id="line11"
+ style="fill:none;stroke:#ffffff;stroke-width:3.90271306" /></svg> \ No newline at end of file
diff --git a/icons/map-icon-zoomOut.svg b/icons/map-icon-zoomOut.svg
new file mode 100644
index 0000000..712f350
--- /dev/null
+++ b/icons/map-icon-zoomOut.svg
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 13.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 14948) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_5" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="74.5px" height="74px" viewBox="0 0 74.5 74" enable-background="new 0 0 74.5 74" xml:space="preserve">
+<g>
+ <circle cx="37.026" cy="37.18" r="30"/>
+ <g>
+ <line fill="none" stroke="#FFFFFF" stroke-width="4" x1="55.026" y1="37.18" x2="19.026" y2="37.18"/>
+ </g>
+</g>
+</svg>
diff --git a/icons/measure-icon.svg b/icons/measure-icon.svg
new file mode 100644
index 0000000..cd21013
--- /dev/null
+++ b/icons/measure-icon.svg
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
+ <!ENTITY fill_color "#AAAAAA">
+ <!ENTITY stroke_color "#000000">
+]>
+<svg xmlns="http://www.w3.org/2000/svg" width="45" height="45">
+ <rect x="13" y="3" width="20" height="40" style="fill:&fill_color;;stroke:&stroke_color;;stroke-width:3.0"/>
+ <line y1="13" y2="13" x1="25" x2="33" style="fill:&fill_color;;stroke:&stroke_color;;stroke-width:3.0"/>
+ <line y1="23" y2="23" x1="25" x2="33" style="fill:&fill_color;;stroke:&stroke_color;;stroke-width:3.0"/>
+ <line y1="33" y2="33" x1="25" x2="33" style="fill:&fill_color;;stroke:&stroke_color;;stroke-width:3.0"/>
+</svg>
diff --git a/icons/panoramio.svg b/icons/panoramio.svg
new file mode 100644
index 0000000..3d46175
--- /dev/null
+++ b/icons/panoramio.svg
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!-- Generator: Adobe Illustrator 12.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 51448) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
+ <!ENTITY ns_svg "http://www.w3.org/2000/svg">
+ <!ENTITY ns_xlink "http://www.w3.org/1999/xlink">
+]>
+<svg version="1.1" id="Layer_1" xmlns="&ns_svg;" xmlns:xlink="&ns_xlink;" width="32" height="27.2" viewBox="0 0 32 27.2"
+ style="overflow:visible;enable-background:new 0 0 32 27.2;" xml:space="preserve">
+<rect y="1.6" width="32" height="25.6"/>
+<rect x="1.6" width="1.6" height="2.6"/>
+<rect x="8" width="1.6" height="2.9"/>
+<rect x="1.6" y="3.2" style="fill:#FFFFFF;" width="8" height="4.8"/>
+<rect x="20.8" y="3.2" style="fill:#FFFFFF;" width="8" height="4.8"/>
+<rect x="9.4" y="4.8" style="fill:#FFFFFF;" width="12.1" height="1.6"/>
+<path style="fill:none;stroke:#FFFFFF;stroke-width:1.6;" d="M8,15.2c0,4,3.2,7.2,7.2,7.2c4,0,7.2-3.2,7.2-7.2c0-4-3.2-7.2-7.2-7.2
+ C11.2,8,8,11.2,8,15.2z"/>
+<g>
+ <path style="fill:#FFFFFF;" d="M10.4,15.2c0,2.6,2.2,4.8,4.8,4.8c2.6,0,4.8-2.2,4.8-4.8s-2.2-4.8-4.8-4.8
+ C12.6,10.4,10.4,12.6,10.4,15.2z"/>
+ <path d="M15.2,9.6c-3.1,0-5.6,2.5-5.6,5.6c0,3.1,2.5,5.6,5.6,5.6c3.1,0,5.6-2.5,5.6-5.6C20.8,12.1,18.3,9.6,15.2,9.6L15.2,9.6z
+ M11.2,15.2c0-2.2,1.8-4,4-4c2.2,0,4,1.8,4,4l0,0l0,0c0,2.2-1.8,4-4,4C13,19.2,11.2,17.4,11.2,15.2L11.2,15.2L11.2,15.2z"/>
+ <path d="M15.2,9.6c-3.1,0-5.6,2.5-5.6,5.6c0,3.1,2.5,5.6,5.6,5.6c3.1,0,5.6-2.5,5.6-5.6C20.8,12.1,18.3,9.6,15.2,9.6L15.2,9.6z
+ M11.2,15.2c0-2.2,1.8-4,4-4c2.2,0,4,1.8,4,4l0,0l0,0c0,2.2-1.8,4-4,4C13,19.2,11.2,17.4,11.2,15.2L11.2,15.2L11.2,15.2z"/>
+</g>
+</svg>
diff --git a/icons/save-search.svg b/icons/save-search.svg
new file mode 100644
index 0000000..22b18bf
--- /dev/null
+++ b/icons/save-search.svg
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Generator: Adobe Illustrator 13.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 14948) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ id="Layer_1"
+ x="0px"
+ y="0px"
+ width="76px"
+ height="76px"
+ viewBox="0 0 76 76"
+ enable-background="new 0 0 76 76"
+ xml:space="preserve"
+ sodipodi:version="0.32"
+ inkscape:version="0.45.1"
+ sodipodi:docname="save-search.svg"
+ sodipodi:docbase="/root/Desktop"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"><metadata
+ id="metadata2230"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
+ id="defs2228" /><sodipodi:namedview
+ inkscape:window-height="622"
+ inkscape:window-width="872"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0.0"
+ guidetolerance="10.0"
+ gridtolerance="10.0"
+ objecttolerance="10.0"
+ borderopacity="1.0"
+ bordercolor="#666666"
+ pagecolor="#ffffff"
+ id="base"
+ inkscape:zoom="5.3552632"
+ inkscape:cx="38"
+ inkscape:cy="38"
+ inkscape:window-x="127"
+ inkscape:window-y="103"
+ inkscape:current-layer="Layer_1" />
+<g
+ id="g2221">
+ <path
+ d="M75.946,56.313c0,10.692-8.748,19.44-19.44,19.44H20.053c-10.692,0-19.44-8.748-19.44-19.44v-36.12 c0-10.692,8.748-19.44,19.44-19.44h36.453c10.692,0,19.44,8.748,19.44,19.44V56.313z"
+ id="path2223" />
+</g>
+
+<g
+ display="block"
+ id="share-link"
+ transform="matrix(1.2,0,0,1.2,5.6048,4.5697942)"
+ style="display:block">
+ <polygon
+ display="inline"
+ points="27.5,7.266 34.074,20.588 48.774,22.723 38.138,33.092 40.647,47.734 27.5,40.82 14.353,47.734 16.862,33.092 6.226,22.723 20.926,20.588 27.5,7.266 "
+ id="polygon5"
+ style="fill:#ffffff;stroke:#010101;stroke-width:3.5;display:inline" />
+</g></svg> \ No newline at end of file
diff --git a/icons/static-icon.svg b/icons/static-icon.svg
new file mode 100644
index 0000000..2bf143b
--- /dev/null
+++ b/icons/static-icon.svg
@@ -0,0 +1,16 @@
+<?xml version="1.0"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"[
+ <!ENTITY stroke_color "#FFFFFF">
+ <!ENTITY fill_color "#010101">
+]>
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="74.5px" height="74px" viewBox="0 0 74.5 74" enable-background="new 0 0 74.5 74" xml:space="preserve">
+<g>
+ <line fill="none" stroke="&stroke_color;" stroke-width="3.5" x1="37.124" y1="13.641" x2="37.124" y2="23.035"/>
+ <path fill="none" stroke="&stroke_color;" stroke-width="3.5" d="M43.213,29.176c0,3.406-2.762,6.168-6.166,6.168
+ c-3.406,0-6.167-2.762-6.167-6.168c0-3.404,2.761-6.141,6.167-6.141C40.451,23.035,43.213,25.771,43.213,29.176z M21.735,59.275
+ L34.298,34.5"/>
+ <line fill="none" stroke="&stroke_color;" stroke-width="3.5" x1="27.88" y1="47.344" x2="54.881" y2="47.344"/>
+ <line fill="none" stroke="&stroke_color;" stroke-width="3.5" x1="39.949" y1="34.434" x2="52.546" y2="59.275"/>
+</g>
+</svg>
diff --git a/icons/tool-polygon.svg b/icons/tool-polygon.svg
new file mode 100644
index 0000000..0c8fee6
--- /dev/null
+++ b/icons/tool-polygon.svg
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Generator: Adobe Illustrator 13.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 14948) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ x="0px"
+ y="0px"
+ width="55px"
+ height="55px"
+ viewBox="0 0 55 55"
+ enable-background="new 0 0 55 55"
+ xml:space="preserve"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.45"
+ sodipodi:docname="tool-shape-polygon.svg"
+ sodipodi:docbase="/home/joy/oficina_sugar/oficina/icons"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ sodipodi:modified="true"><metadata
+ id="metadata10"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
+ id="defs8" /><sodipodi:namedview
+ inkscape:window-height="941"
+ inkscape:window-width="1269"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0.0"
+ guidetolerance="10.0"
+ gridtolerance="10.0"
+ objecttolerance="10.0"
+ borderopacity="1.0"
+ bordercolor="#666666"
+ pagecolor="#ffffff"
+ id="base"
+ inkscape:zoom="6.8909091"
+ inkscape:cx="27.5"
+ inkscape:cy="27.5"
+ inkscape:window-x="0"
+ inkscape:window-y="27"
+ inkscape:current-layer="svg2" />
+
+<g
+ id="Polygon"
+ style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-opacity:1">
+ <polygon
+ display="inline"
+ fill="#FFFFFF"
+ points="16.834,46.58 5.83,27.522 16.834,8.464 38.841,8.464 49.844,27.522 38.841,46.58 "
+ id="polygon5"
+ style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-opacity:1" />
+</g>
+
+</svg> \ No newline at end of file
diff --git a/icons/tool-shape-line.svg b/icons/tool-shape-line.svg
new file mode 100644
index 0000000..0bf4d8e
--- /dev/null
+++ b/icons/tool-shape-line.svg
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 13.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 14948) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="55px"
+ height="55px" viewBox="0 0 55 55" enable-background="new 0 0 55 55" xml:space="preserve">
+
+<g id="Line" >
+ <line display="inline" fill="none" stroke="#FFFFFF" stroke-width="2.25" x1="8.708" y1="47.167" x2="48.042" y2="7.833"/>
+</g>
+
+</svg>
diff --git a/icons/topo-icon.svg b/icons/topo-icon.svg
new file mode 100644
index 0000000..18a25d6
--- /dev/null
+++ b/icons/topo-icon.svg
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 13.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 14948) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="75.667px" height="75.333px" viewBox="0 0 75.667 75.333" enable-background="new 0 0 75.667 75.333" xml:space="preserve">
+<g>
+ <path d="M75.828,55.925c0,10.692-8.748,19.44-19.439,19.44H19.935c-10.692,0-19.44-8.748-19.44-19.44V19.806
+ c0-10.692,8.748-19.44,19.44-19.44h36.454c10.691,0,19.439,8.748,19.439,19.44V55.925z"/>
+</g>
+<g>
+ <path fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" d="M44.936,43.372
+ c-2.121,4.811-6.641,7.477-10.094,5.953c-3.454-1.522,1.952-3.797,4.073-8.608c2.121-4.811,0.156-10.337,3.609-8.813
+ C45.979,33.427,47.058,38.562,44.936,43.372z"/>
+ <path fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" d="M50.594,45.6
+ c-3.481,7.896-13.633,11.064-22.676,7.077c-9.041-3.987,3.43-6.133,6.911-14.028c3.481-7.896-3.344-18.551,5.696-14.563
+ C49.568,28.072,54.075,37.705,50.594,45.6z"/>
+ <path fill="none" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" d="M58.834,49.5
+ c-4.625,10.486-21.741,13.091-38.235,5.818c-16.491-7.272,4.856-8.013,9.479-18.498s-9.226-26.746,7.265-19.474
+ C53.837,24.619,63.457,39.015,58.834,49.5z"/>
+</g>
+</svg>
diff --git a/icons/web-icon.svg b/icons/web-icon.svg
new file mode 100644
index 0000000..d5e7e59
--- /dev/null
+++ b/icons/web-icon.svg
@@ -0,0 +1,14 @@
+<?xml version="1.0" ?><!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd' [
+ <!ENTITY stroke_color "#010101">
+ <!ENTITY fill_color "#FFFFFF">
+]><svg enable-background="new 0 0 55 55" height="55px" version="1.1" viewBox="0 0 55 55" width="55px" x="0px" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" y="0px"><g display="block" id="activity-browse">
+ <circle cx="27.375" cy="27.5" display="inline" fill="&fill_color;" r="19.903" stroke="&stroke_color;" stroke-width="3.5"/>
+ <g display="inline">
+ <path d="M27.376,7.598c0,0-11.205,8.394-11.205,19.976 c0,11.583,11.205,19.829,11.205,19.829" fill="&fill_color;" stroke="&stroke_color;" stroke-width="3.5"/>
+ <path d="M27.376,7.598c0,0,11.066,9.141,11.066,19.976 c0,10.839-11.066,19.829-11.066,19.829" fill="&fill_color;" stroke="&stroke_color;" stroke-width="3.5"/>
+ <line fill="&fill_color;" stroke="&stroke_color;" stroke-width="3.5" x1="27.376" x2="27.376" y1="7.598" y2="47.402"/>
+ <line fill="&fill_color;" stroke="&stroke_color;" stroke-width="3.5" x1="27.376" x2="27.376" y1="7.598" y2="47.402"/>
+ <line fill="&fill_color;" stroke="&stroke_color;" stroke-width="3.5" x1="27.376" x2="27.376" y1="7.598" y2="47.402"/>
+ <line fill="&fill_color;" stroke="&stroke_color;" stroke-width="3.5" x1="7.472" x2="47.278" y1="27.5" y2="27.5"/>
+ </g>
+</g></svg> \ No newline at end of file
diff --git a/icons/wikimapia.svg b/icons/wikimapia.svg
new file mode 100644
index 0000000..0101988
--- /dev/null
+++ b/icons/wikimapia.svg
@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Generator: Adobe Illustrator 12.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 51448) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.0"
+ id="Layer_1"
+ width="48"
+ height="48.119"
+ viewBox="0 0 48 48.119"
+ overflow="visible"
+ enable-background="new 0 0 48 48.119"
+ xml:space="preserve"
+ sodipodi:version="0.32"
+ inkscape:version="0.46"
+ sodipodi:docname="activity-maptech.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"><metadata
+ id="metadata2471"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
+ id="defs2469"><inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 24.0595 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="48 : 24.0595 : 1"
+ inkscape:persp3d-origin="24 : 16.039666 : 1"
+ id="perspective2473" /></defs><sodipodi:namedview
+ inkscape:window-height="669"
+ inkscape:window-width="779"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0.0"
+ guidetolerance="10.0"
+ gridtolerance="10.0"
+ objecttolerance="10.0"
+ borderopacity="1.0"
+ bordercolor="#666666"
+ pagecolor="#ffffff"
+ id="base"
+ showgrid="false"
+ inkscape:zoom="11.333333"
+ inkscape:cx="24"
+ inkscape:cy="23.70819"
+ inkscape:window-x="23"
+ inkscape:window-y="23"
+ inkscape:current-layer="Layer_1" />
+
+
+
+
+
+<path
+ sodipodi:type="arc"
+ style="fill:#ffffff;fill-rule:evenodd;stroke:#808080;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ id="path2475"
+ sodipodi:cx="36.037174"
+ sodipodi:cy="16.300051"
+ sodipodi:rx="8.748909"
+ sodipodi:ry="8.592679"
+ d="M 44.786083,16.300051 A 8.748909,8.592679 0 1 1 27.288265,16.300051 A 8.748909,8.592679 0 1 1 44.786083,16.300051 z" /><path
+ sodipodi:type="arc"
+ style="fill:#666666;fill-rule:evenodd;stroke:#4d4d4d;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ id="path2483"
+ sodipodi:cx="23.122116"
+ sodipodi:cy="37.703632"
+ sodipodi:rx="12.915056"
+ sodipodi:ry="2.9163029"
+ d="M 36.037172,37.703632 A 12.915056,2.9163029 0 1 1 10.20706,37.703632 A 12.915056,2.9163029 0 1 1 36.037172,37.703632 z"
+ transform="translate(6.6817539,5.8394479)" /><rect
+ style="fill:#f9f9f9;stroke:#999999;stroke-width:1.05382084999999990"
+ id="rect2485"
+ width="9.4241638"
+ height="34.898167"
+ x="3.1515205"
+ y="1.9016767" /><rect
+ style="fill:#f9f9f9;stroke:#999999;stroke-width:1.07296026000000010"
+ id="rect2487"
+ width="7.5302582"
+ height="26.634966"
+ x="12.951536"
+ y="10.243541" /><rect
+ style="fill:#f9f9f9;stroke:#b3b3b3;stroke-width:1.40962899000000010"
+ id="rect2489"
+ width="5.9437451"
+ height="15.942498"
+ x="21.139704"
+ y="20.855909" /><path
+ style="fill:none;fill-rule:evenodd;stroke:#999999;stroke-width:1.19097257000000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="M 30.800071,23.217604 L 29.338108,42.372851 L 36.310546,25.817245 L 30.800071,23.217604 z"
+ id="path2495" /><rect
+ style="fill:#ffffff;stroke:#ffffff"
+ id="rect2533"
+ width="3.2647059"
+ height="4.2352943"
+ x="31.941177"
+ y="21.295471" /></svg> \ No newline at end of file
diff --git a/idlethread.py b/idlethread.py
new file mode 100644
index 0000000..7dc424e
--- /dev/null
+++ b/idlethread.py
@@ -0,0 +1,175 @@
+from __future__ import generators
+
+import gobject
+import time
+import traceback
+
+class GIdleThread(object):
+ """This is a pseudo-"thread" for use with the GTK+ main loop.
+
+ This class does act a bit like a thread, all code is executed in
+ the callers thread though. The provided function should be a generator
+ (or iterator).
+
+ It can be started with start(). While the "thread" is running is_alive()
+ can be called to see if it's alive. wait([timeout]) will wait till the
+ generator is finished, or timeout seconds.
+
+ If an exception is raised from within the generator, it is stored in
+ the error property. Execution of the generator is finished.
+
+ Note that this routine runs in the current thread, so there is no need
+ for nasty locking schemes.
+
+ Example (runs a counter through the GLib main loop routine):
+ >>> def counter(max): for x in xrange(max): yield x
+ >>> t = GIdleThread(counter(123))
+ >>> t.start()
+ >>> while gen.is_alive():
+ ... main.iteration(False)
+ """
+
+ def __init__(self, generator, queue=None):
+ assert hasattr(generator, 'next'), 'The generator should be an iterator'
+ self._generator = generator
+ self._queue = queue
+ self._idle_id = 0
+ self._error = None
+
+ def start(self, priority=gobject.PRIORITY_LOW):
+ """Start the generator. Default priority is low, so screen updates
+ will be allowed to happen.
+ """
+ idle_id = gobject.idle_add(self.__generator_executer,
+ priority=priority)
+ self._idle_id = idle_id
+ return idle_id
+
+ def wait(self, timeout=0):
+ """Wait until the corouine is finished or return after timeout seconds.
+ This is achieved by running the GTK+ main loop.
+ """
+ clock = time.clock
+ start_time = clock()
+ main = gobject.main_context_default()
+ while self.is_alive():
+ main.iteration(False)
+ if timeout and (clock() - start_time >= timeout):
+ return
+
+ def interrupt(self):
+ """Force the generator to stop running.
+ """
+ if self.is_alive():
+ gobject.source_remove(self._idle_id)
+ self._idle_id = 0
+
+ def is_alive(self):
+ """Returns True if the generator is still running.
+ """
+ return self._idle_id != 0
+
+ error = property(lambda self: self._error,
+ doc="Return a possible exception that had occured "\
+ "during execution of the generator")
+
+ def __generator_executer(self):
+ try:
+ result = self._generator.next()
+ if self._queue:
+ try:
+ self._queue.put(result)
+ except QueueFull:
+ self.wait(0.5)
+ # If this doesn't work...
+ self._queue.put(result)
+ return True
+ except StopIteration:
+ self._idle_id = 0
+ return False
+ except Exception, e:
+ self._error = e
+ traceback.print_exc()
+ self._idle_id = 0
+ return False
+
+
+class QueueEmpty(Exception):
+ """Exception raised whenever the queue is empty and someone tries to fetch
+ a value.
+ """
+ pass
+
+
+class QueueFull(Exception):
+ """Exception raised when the queue is full and the oldest item may not be
+ disposed.
+ """
+ pass
+
+
+class Queue(object):
+ """A FIFO queue. If the queue has a max size, the oldest item on the
+ queue is dropped if that size id exceeded.
+ """
+
+ def __init__(self, size=0, dispose_oldest=True):
+ self._queue = []
+ self._size = size
+ self._dispose_oldest = dispose_oldest
+
+ def put(self, item):
+ """Put item on the queue. If the queue size is limited ...
+ """
+ if self._size > 0 and len(self._queue) >= self._size:
+ if self._dispose_oldest:
+ self.get()
+ else:
+ raise QueueFull
+
+ self._queue.insert(0, item)
+
+ def get(self):
+ """Get the oldest item off the queue.
+ QueueEmpty is raised if no items are left on the queue.
+ """
+ try:
+ return self._queue.pop()
+ except IndexError:
+ raise QueueEmpty
+
+
+if __name__ == '__main__':
+ def counter(max):
+ for i in range(max):
+ yield i
+
+ def shower(queue):
+ # Never stop reading the queue:
+ while True:
+ try:
+ cnt = queue.get()
+ print 'cnt =', cnt
+ except QueueEmpty:
+ pass
+ yield None
+
+ print 'Test 1: (should print range 0..22)'
+ queue = Queue()
+ c = GIdleThread(counter(23), queue)
+ s = GIdleThread(shower(queue))
+
+ main = gobject.main_context_default()
+ c.start()
+ s.start()
+ s.wait(2)
+
+ print 'Test 2: (should only print 22)'
+ queue = Queue(size=1)
+ c = GIdleThread(counter(23), queue)
+ s = GIdleThread(shower(queue))
+
+ main = gobject.main_context_default()
+ c.start(priority=gobject.PRIORITY_DEFAULT)
+ s.start()
+ s.wait(3)
diff --git a/instance.py b/instance.py
new file mode 100644
index 0000000..95fb932
--- /dev/null
+++ b/instance.py
@@ -0,0 +1,45 @@
+import os
+
+from sugar import profile
+from sugar import util
+from sugar.activity import activity
+import shutil
+
+from color import Color
+
+class Instance:
+ key = profile.get_pubkey()
+ #joyride ...
+ #keyHash = util.sha_data(key)
+ #8.2...
+ #keyHash = util._sha_data(key)
+ #keyHashPrintable = util.printable_hash(keyHash)
+ nickName = profile.get_nick_name()
+
+ colorFill = Color()
+ colorFill.init_hex( profile.get_color().get_fill_color() )
+ colorStroke = Color()
+ colorStroke.init_hex( profile.get_color().get_stroke_color() )
+
+ instanceId = None
+ instancePath = None
+ dataPath = None
+
+ def __init__(self, ca):
+ self.__class__.instanceId = ca._activity_id
+
+ self.__class__.instancePath = os.path.join(ca.get_activity_root(), "instance")
+ recreateTmp()
+
+ self.__class__.dataPath = os.path.join(ca.get_activity_root(), "data")
+ recreateData()
+
+
+def recreateTmp():
+ if (not os.path.exists(Instance.instancePath)):
+ os.makedirs(Instance.instancePath)
+
+
+def recreateData():
+ if (not os.path.exists(Instance.dataPath)):
+ os.makedirs(Instance.dataPath) \ No newline at end of file
diff --git a/locale/es/LC_MESSAGES/org.laptop.map.mo b/locale/es/LC_MESSAGES/org.laptop.map.mo
new file mode 100644
index 0000000..ea90e33
--- /dev/null
+++ b/locale/es/LC_MESSAGES/org.laptop.map.mo
Binary files differ
diff --git a/locale/es/activity.linfo b/locale/es/activity.linfo
new file mode 100644
index 0000000..b8f1dd2
--- /dev/null
+++ b/locale/es/activity.linfo
@@ -0,0 +1,2 @@
+[Activity]
+name = Mapa
diff --git a/locale/mn/LC_MESSAGES/org.laptop.map.mo b/locale/mn/LC_MESSAGES/org.laptop.map.mo
new file mode 100644
index 0000000..2ef674c
--- /dev/null
+++ b/locale/mn/LC_MESSAGES/org.laptop.map.mo
Binary files differ
diff --git a/locale/mn/activity.linfo b/locale/mn/activity.linfo
new file mode 100644
index 0000000..eadffb2
--- /dev/null
+++ b/locale/mn/activity.linfo
@@ -0,0 +1,2 @@
+[Activity]
+name = Map
diff --git a/logic.py b/logic.py
new file mode 100644
index 0000000..820e306
--- /dev/null
+++ b/logic.py
@@ -0,0 +1,359 @@
+# Copyright (c) 2008, Media Modifications Ltd.
+
+#Permission is hereby granted, free of charge, to any person obtaining a copy
+#of this software and associated documentation files (the "Software"), to deal
+#in the Software without restriction, including without limitation the rights
+#to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+#copies of the Software, and to permit persons to whom the Software is
+#furnished to do so, subject to the following conditions:
+
+#The above copyright notice and this permission notice shall be included in
+#all copies or substantial portions of the Software.
+
+#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+#THE SOFTWARE.
+
+
+from result import ServerResult
+from constants import Constants
+from instance import Instance
+
+from threading import Thread
+import threading
+import os
+import gobject
+import time
+import gtk
+import urllib
+
+class ServerLogic:
+ def __init__(self, ca):
+ self.ca = ca
+ self.proceedTxt = ""
+ self.proceedHeaders = []
+ self.cond = ca.cond
+ self.addKMLSet=0
+
+ def doServerLogic(self, url, path, params):
+ self.ca.remoteServerActive( True )
+ r = ServerResult()
+ fileName = path[len(path)-1]
+
+ if (fileName == "comet.js"):
+
+ #clear...
+ self.proceedHeaders = []
+ self.proceedTxt = ""
+
+ #wait...
+ self.cond.acquire()
+ self.cond.wait()
+ self.cond.release()
+
+ #prep response...
+ for h in range( len(self.proceedHeaders) ):
+ r.headers.append( self.proceedHeaders[h] )
+ #r.txt = ""+self.proceedTxt
+ #self.ca.browser.load_uri("javascript:"+r.txt+"void(0);")
+
+ else:
+ kickThroughComet = True
+
+ if (fileName =="mediaQuery.js"):
+ self.proceedHeaders.append( ("Content-type", "text/javascript") )
+ self.proceedTxt = self.ca.m.getMediaResponse( params[0][1], params[1][1], params[2][1], params[3][1] )
+
+ elif (fileName == "showMedia.js"):
+ id = params[0][1]
+ locX = params[1][1]
+ locY = params[2][1]
+ up = params[3][1]
+ rt = params[4][1]
+ gobject.idle_add(self.ca.showMedia, id, locX, locY, up=='true', rt=='true')
+ self.proceedHeaders.append( ("Content-type", "text/javascript") )
+
+ elif (fileName == "placeAddMedia.js"):
+ lat = params[0][1]
+ lng = params[1][1]
+ gobject.idle_add(self.ca.placeAddMedia, lat, lng)
+ self.proceedHeaders.append( ("Content-type", "text/javascript") )
+ kickThroughComet = False
+
+ elif (fileName == "hideMedia.js"):
+ gobject.idle_add(self.ca.hideMedia)
+
+ elif (fileName == "getImage.js"):
+ localfile = open(os.path.join(Instance.instancePath, params[0][1]), 'r')
+ localdata = localfile.read()
+ localfile.close()
+
+ #one day we might need to kick you through comet as a base64'd image.
+ r.txt = localdata
+ r.headers.append( ("Content-type", "image/jpeg") )
+ kickThroughComet = False
+
+ elif (fileName == "updateLocation.js"):
+ lat = params[0][1]
+ lng = params[1][1]
+ zoom = params[2][1]
+ x = params[3][1]
+ y = params[4][1]
+ gobject.idle_add(self.ca.updateMapMetaData,lat,lng,zoom,x,y)
+
+ elif (fileName == "addSavedMap.js"):
+ # allow internet to send an array of SavedMaps back to map.py
+ latitudes = params[0][1]
+ longitudes = params[1][1]
+ zooms = params[2][1]
+ notes = params[3][1]
+ gobject.idle_add(self.ca.addSavedMap,latitudes,longitudes,zooms,urllib.unquote(notes),True)
+
+ elif (fileName == "addInfoMarker.js"):
+ lat = params[0][1]
+ lng = params[1][1]
+ info = params[2][1]
+ icon = params[3][1]
+ if(params[4][1] == "True"):
+ isNew = True
+ gobject.idle_add(self.ca.cometLogic.forceupdate)
+ else:
+ isNew = False
+ gobject.idle_add(self.ca.addInfoMarker,lat,lng,info,icon,isNew)
+
+ elif (fileName == "addLine.js"):
+ id = params[0][1]
+ color = params[1][1]
+ thickness = params[2][1]
+ pts = params[3][1] # send pts separated with | instead of ,
+ gobject.idle_add(self.ca.addLine,id,color,thickness,pts,1)
+
+ elif (fileName == "promptSearch.js"):
+ address = params[0][1]
+ time.sleep(0.5)
+ self.ca.preComet()
+ self.handleAddressUpdate(address+"+")
+ self.ca.postComet()
+
+ #elif (fileName == "gotoMapV3.js"):
+ # button on static maps links to mapv3
+ #self.ca.loadMapV3()
+
+ if (kickThroughComet):
+ #not sure how & why this goes out, but it does.
+ self.cond.acquire()
+ self.cond.notifyAll()
+ self.cond.release()
+ time.sleep(.1)
+
+ return r
+
+ def handleAddressUpdate( self, address ):
+ findsrc="http://maps.googleapis.com/maps/api/geocode/json?sensor=false&address=" + urllib.quote(address)
+ findAddress = urllib.urlopen(findsrc).read()
+
+ longname=findAddress[findAddress.find('long_name')+13:len(findAddress)]
+ longname=longname[0:longname.find('"')]
+
+ findSW=findAddress[findAddress.find('southwest'):findAddress.find('northeast')].replace(" ","").replace('\n','')
+ swlat=findSW[findSW.find('lat')+5:findSW.find(',')]
+ swlng=findSW[findSW.find('lng')+5:findSW.find('}')]
+
+ findNE=findAddress[findAddress.find('northeast'):len(findAddress)].replace(" ","").replace('\n','')
+ nelat=findNE[findNE.find('lat')+5:findNE.find(',')]
+ nelng=findNE[findNE.find('lng')+5:findNE.find('}')]
+
+ self.proceedHeaders.append( ("Content-type", "text/javascript") )
+ #self.proceedTxt = "showInfo('" + swlat + "," + swlng + "," + nelat + "," + nelng + "');"
+ self.proceedTxt = "moveToAddress(" + swlat + "," + swlng + "," + nelat + "," + nelng + ",'" + longname + "');"
+ self.ca.ajaxServer.stop()
+ self.ca.cometServer.stop()
+ self.ca.browser.load_uri("javascript:"+self.proceedTxt+";void(0);")
+
+ def forceupdate(self):
+ #self.ca.preComet()
+
+ self.proceedHeaders.append( ("Content-type", "text/javascript") )
+ self.proceedTxt = "canvas.updateImg();"
+ self.ca.ajaxServer.stop()
+ self.ca.cometServer.stop()
+ self.ca.browser.load_uri("javascript:"+self.proceedTxt+";void(0);")
+ #self.ca.postComet()
+
+ def handleCompassUpdate( self, dir ):
+ self.proceedHeaders.append( ("Content-type", "text/javascript") )
+
+ if (dir == "e"):
+ self.proceedTxt = "dirEast();"
+ elif (dir == "w"):
+ self.proceedTxt = "dirWest();"
+ elif (dir == "n"):
+ self.proceedTxt = "dirNorth();"
+ elif (dir == "s"):
+ self.proceedTxt = "dirSouth();"
+ else:
+ # use this as a print warning window
+ self.proceedTxt = 'showInfo("' + dir + '");'
+ self.ca.ajaxServer.stop()
+ self.ca.cometServer.stop()
+ self.ca.browser.load_uri("javascript:"+self.proceedTxt+";void(0);")
+
+ def handlePanoramio(self):
+ self.proceedHeaders.append( ("Content-type", "text/javascript") )
+ self.proceedTxt = 'panoramio();'
+ self.ca.ajaxServer.stop()
+ self.ca.cometServer.stop()
+ self.ca.browser.load_uri("javascript:"+self.proceedTxt+";void(0);")
+
+ def handleLocalWiki(self):
+ self.proceedHeaders.append( ("Content-type", "text/javascript") )
+ self.proceedTxt = 'wikiloc();'
+ self.ca.ajaxServer.stop()
+ self.ca.cometServer.stop()
+ self.ca.browser.load_uri("javascript:"+self.proceedTxt+";void(0);")
+
+ def handleWikiMapia(self):
+ self.proceedHeaders.append( ("Content-type", "text/javascript") )
+ self.proceedTxt = 'wikimapia();'
+ self.ca.ajaxServer.stop()
+ self.ca.cometServer.stop()
+ self.ca.browser.load_uri("javascript:"+self.proceedTxt+";void(0);")
+
+ def handleOlpcMAP(self):
+ self.proceedHeaders.append( ("Content-type", "text/javascript") )
+ llc=[float(self.ca.NOW_MAP_CENTER_LAT),float(self.ca.NOW_MAP_CENTER_LNG)]
+ llz=float(self.ca.NOW_MAP_ZOOM)
+ lln=llc[0]+0.55618*0.75*(2**(9-llz))
+ lle=llc[1]+0.98877*0.75*(2**(9-llz))
+ lls=llc[0]-0.55618*0.75*(2**(9-llz))
+ llw=llc[1]-0.98877*0.75*(2**(9-llz))
+ findsrc="http://mapmeld.appspot.com/olpcMAP/kml?llregion="+str(lln)+","+str(lle)+","+str(lls)+","+str(llw)
+ self.ca.readKML(urllib.urlopen(findsrc))
+
+ def handleZoomUpdate( self, dir ):
+ self.proceedHeaders.append( ("Content-type", "text/javascript") )
+ if (dir == "+"):
+ self.proceedTxt = "zoomIn();"
+ elif (dir == "-"):
+ self.proceedTxt = "zoomOut();"
+ self.ca.ajaxServer.stop()
+ self.ca.cometServer.stop()
+ self.ca.browser.load_uri("javascript:"+self.proceedTxt+";void(0);")
+
+ def handleClear( self ):
+ self.proceedHeaders.append( ("Content-type", "text/javascript") )
+ self.proceedTxt = "clear();"
+ self.ca.ajaxServer.stop()
+ self.ca.cometServer.stop()
+ self.ca.browser.load_uri("javascript:"+self.proceedTxt+";void(0);")
+
+ def handlePreAdd( self ):
+ self.proceedHeaders.append( ("Content-type", "text/javascript") )
+ self.proceedTxt = "preAddMedia();"
+ self.ca.ajaxServer.stop()
+ self.ca.cometServer.stop()
+ self.ca.browser.load_uri("javascript:"+self.proceedTxt+";void(0);")
+
+ def handlePreAddInfo( self ):
+ self.proceedHeaders.append( ("Content-type", "text/javascript") )
+ self.proceedTxt = "preAddInfo();"
+ self.ca.ajaxServer.stop()
+ self.ca.cometServer.stop()
+ self.ca.browser.load_uri("javascript:"+self.proceedTxt+";void(0);")
+
+ def handlePostAdd( self, rec ):
+ self.proceedHeaders.append( ("Content-type", "text/javascript") )
+ self.proceedTxt = "postAddMedia(" + rec.latitude + ", " + rec.longitude + ", '" + rec.getThumbUrl() + "', '" + rec.getThumbBasename() + "', '" + rec.tags + "');"
+ self.ca.ajaxServer.stop()
+ self.ca.cometServer.stop()
+ self.ca.browser.load_uri("javascript:"+self.proceedTxt+";void(0);")
+
+ def handleDelete( self ):
+ self.proceedHeaders.append( ("Content-type", "text/javascript") )
+ self.proceedTxt = "deleteMedia();"
+ self.ca.ajaxServer.stop()
+ self.ca.cometServer.stop()
+ self.ca.browser.load_uri("javascript:"+self.proceedTxt+";void(0);")
+
+ # handle a map that was sent to us
+ def handleReceivedMap( self, lat, lng, zoom):
+ self.proceedHeaders.append( ("Content-type", "text/javascript") )
+ self.proceedTxt = "setMap(" + lat + "," + lng + "," + zoom + ");"
+ self.ca.ajaxServer.stop()
+ self.ca.cometServer.stop()
+ self.ca.browser.load_uri("javascript:"+self.proceedTxt+";void(0);")
+
+ def handleSavedMap( self, lat, lng, zoom, info ):
+ self.proceedHeaders.append( ("Content-type", "text/javascript") )
+ if(info.find("Describe the map") != 0):
+ self.proceedTxt = "setMap2(" + lat + "," + lng + "," + zoom + ",'" + urllib.quote(info) + "');"
+ else:
+ self.proceedTxt = "setMap2(" + lat + "," + lng + "," + zoom + ",'');"
+ self.ca.ajaxServer.stop()
+ self.ca.cometServer.stop()
+ self.ca.browser.load_uri("javascript:"+self.proceedTxt+";void(0);")
+
+ # handle a marker that was sent to us
+ def handleAddMarker( self, lat, lng, pixString, icon ):
+ if(self.addKMLSet < 1):
+ self.proceedHeaders.append( ("Content-type", "text/javascript") )
+ self.proceedTxt = ""
+ if(self.addKMLSet == -1):
+ self.addKMLSet = 1
+ self.proceedTxt = self.proceedTxt + "addInfoMarker(" + lat + ", " + lng + ", '" + pixString.replace("'",'"') + "', '" + icon + "',false);"
+ #self.proceedTxt = self.proceedTxt + "addInfoMarker(" + lat + ", " + lng + ", '"+pixString.replace("'",'"')+"', 'http://mapmeld.appspot.com/xo-red.png',false);"
+ self.ca.ajaxServer.stop()
+ self.ca.cometServer.stop()
+ self.ca.browser.load_uri("javascript:"+self.proceedTxt+";void(0);")
+
+ def startKML( self, tellOthers ):
+ self.addKMLSet = -1
+ if((self.ca.maptube is not None) and (tellOthers == 1)):
+ self.ca.sendStartKML()
+
+ def handleEndKML( self, tellOthers ):
+ self.proceedHeaders.append( ("Content-type", "text/javascript") )
+ self.proceedTxt = self.proceedTxt + "canvas.updateImg();"
+ self.addKMLSet = 0
+ if((self.ca.maptube is not None) and (tellOthers == 1)):
+ self.ca.sendEndKML()
+ self.ca.ajaxServer.stop()
+ self.ca.cometServer.stop()
+ self.ca.browser.load_uri("javascript:"+self.proceedTxt+";void(0);")
+
+ def lineMode(self, type):
+ self.proceedHeaders.append( ("Content-type", "text/javascript") )
+ self.proceedTxt = "lineMode('" + type + "');"
+ self.ca.ajaxServer.stop()
+ self.ca.cometServer.stop()
+ self.ca.browser.load_uri("javascript:"+self.proceedTxt+";void(0);")
+
+ def handleLine(self,id,color,thickness,pts):
+ if(self.addKMLSet < 1):
+ self.proceedHeaders.append( ("Content-type", "text/javascript") )
+ self.proceedTxt = ""
+ if(self.addKMLSet == -1):
+ self.addKMLSet = 1
+ self.proceedTxt = self.proceedTxt + "addLine('" + id + "','" + color + "','" + thickness + "','" + pts + "');"
+ self.ca.ajaxServer.stop()
+ self.ca.cometServer.stop()
+ self.ca.browser.load_uri("javascript:"+self.proceedTxt+";void(0);")
+
+ # handle start of measure tool
+ def handleMeasure(self):
+ self.proceedHeaders.append( ("Content-type", "text/javascript") )
+ self.proceedTxt = "measure();"
+ self.ca.ajaxServer.stop()
+ self.ca.cometServer.stop()
+ self.ca.browser.load_uri("javascript:"+self.proceedTxt+";void(0);")
+
+ def handleTagSearch( self, tags ):
+ self.proceedHeaders.append( ("Content-type", "text/javascript") )
+ self.proceedTxt = "filterTags('" + tags + "');"
+ self.ca.ajaxServer.stop()
+ self.ca.cometServer.stop()
+ self.ca.browser.load_uri("javascript:"+self.proceedTxt+";void(0);")
diff --git a/manifest b/manifest
new file mode 100644
index 0000000..82cff9f
--- /dev/null
+++ b/manifest
@@ -0,0 +1,43 @@
+_camera.c
+logic.py
+server.py
+setup.py
+idlethread.py
+webviewer.py
+NEWS
+instance.py
+constants.py
+tray.py
+_camera.so
+recorded.py
+model.py
+gplay.py
+savedmap.py
+button.py
+utils.py
+p5.py
+filepicker.py
+result.py
+color.py
+serialize.py
+map.py
+_camera.o
+photocanvas.py
+activity/activity.info
+activity/activity-map.svg
+icons/map-icon-zoomIn.svg
+icons/map-icon-croseS.svg
+icons/map-icon-croseE.svg
+icons/map-icon-croseW.svg
+icons/add-icon.svg
+icons/delete-icon.svg
+icons/corner-info.svg
+icons/map-icon-croseN.svg
+icons/topo-icon.svg
+icons/map-icon-zoomOut.svg
+icons/save-search.svg
+icons/web-icon.svg
+icons/measure-icon.svg
+icons/static-icon.svg
+po/map.pot
+Makefile
diff --git a/map-activity.iml b/map-activity.iml
new file mode 100644
index 0000000..4e07241
--- /dev/null
+++ b/map-activity.iml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module version="4" relativePaths="true" type="JAVA_MODULE">
+ <component name="ModuleRootManager" />
+ <component name="NewModuleRootManager" inherit-compiler-output="true">
+ <exclude-output />
+ <content url="file://$MODULE_DIR$" />
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ <orderEntryProperties />
+ </component>
+</module>
+
diff --git a/map-activity.ipr b/map-activity.ipr
new file mode 100644
index 0000000..3e24b75
--- /dev/null
+++ b/map-activity.ipr
@@ -0,0 +1,286 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4" relativePaths="false">
+ <component name="AntConfiguration">
+ <defaultAnt bundledAnt="true" />
+ </component>
+ <component name="BuildJarProjectSettings">
+ <option name="BUILD_JARS_ON_MAKE" value="false" />
+ </component>
+ <component name="CodeStyleProjectProfileManger">
+ <option name="PROJECT_PROFILE" />
+ <option name="USE_PROJECT_LEVEL_SETTINGS" value="false" />
+ </component>
+ <component name="CodeStyleSettingsManager">
+ <option name="PER_PROJECT_SETTINGS" />
+ <option name="USE_PER_PROJECT_SETTINGS" value="false" />
+ </component>
+ <component name="CompilerConfiguration">
+ <option name="DEFAULT_COMPILER" value="Javac" />
+ <option name="DEPLOY_AFTER_MAKE" value="0" />
+ <resourceExtensions>
+ <entry name=".+\.(properties|xml|html|dtd|tld)" />
+ <entry name=".+\.(gif|png|jpeg|jpg)" />
+ </resourceExtensions>
+ <wildcardResourcePatterns>
+ <entry name="?*.properties" />
+ <entry name="?*.xml" />
+ <entry name="?*.gif" />
+ <entry name="?*.png" />
+ <entry name="?*.jpeg" />
+ <entry name="?*.jpg" />
+ <entry name="?*.html" />
+ <entry name="?*.dtd" />
+ <entry name="?*.tld" />
+ </wildcardResourcePatterns>
+ </component>
+ <component name="DataSourceManagerImpl" />
+ <component name="DependenciesAnalyzeManager">
+ <option name="myForwardDirection" value="false" />
+ </component>
+ <component name="DependencyValidationManager" />
+ <component name="EclipseCompilerSettings">
+ <option name="DEBUGGING_INFO" value="true" />
+ <option name="GENERATE_NO_WARNINGS" value="true" />
+ <option name="DEPRECATION" value="false" />
+ <option name="ADDITIONAL_OPTIONS_STRING" value="" />
+ <option name="MAXIMUM_HEAP_SIZE" value="128" />
+ </component>
+ <component name="EclipseEmbeddedCompilerSettings">
+ <option name="DEBUGGING_INFO" value="true" />
+ <option name="GENERATE_NO_WARNINGS" value="true" />
+ <option name="DEPRECATION" value="false" />
+ <option name="ADDITIONAL_OPTIONS_STRING" value="" />
+ <option name="MAXIMUM_HEAP_SIZE" value="128" />
+ </component>
+ <component name="EntryPointsManager">
+ <entry_points />
+ </component>
+ <component name="ExportToHTMLSettings">
+ <option name="PRINT_LINE_NUMBERS" value="false" />
+ <option name="OPEN_IN_BROWSER" value="false" />
+ <option name="OUTPUT_DIRECTORY" />
+ </component>
+ <component name="GUI Designer component loader factory" />
+ <component name="IdProvider" IDEtalkID="473E4E27819B3CDE0F546064F2F319B7" />
+ <component name="InspectionProjectProfileManager">
+ <option name="PROJECT_PROFILE" value="Project Default" />
+ <option name="USE_PROJECT_LEVEL_SETTINGS" value="false" />
+ <scopes />
+ <profiles>
+ <profile version="1.0" is_locked="false">
+ <option name="myName" value="Project Default" />
+ <option name="myLocal" value="false" />
+ <used_levels>
+ <error>
+ <option name="myName" value="ERROR" />
+ <option name="myVal" value="400" />
+ </error>
+ <warning>
+ <option name="myName" value="WARNING" />
+ <option name="myVal" value="300" />
+ </warning>
+ <information>
+ <option name="myName" value="INFO" />
+ <option name="myVal" value="200" />
+ </information>
+ <server>
+ <option name="myName" value="SERVER PROBLEM" />
+ <option name="myVal" value="100" />
+ </server>
+ </used_levels>
+ </profile>
+ </profiles>
+ </component>
+ <component name="JavacSettings">
+ <option name="DEBUGGING_INFO" value="true" />
+ <option name="GENERATE_NO_WARNINGS" value="false" />
+ <option name="DEPRECATION" value="true" />
+ <option name="ADDITIONAL_OPTIONS_STRING" value="" />
+ <option name="MAXIMUM_HEAP_SIZE" value="128" />
+ </component>
+ <component name="JavadocGenerationManager">
+ <option name="OUTPUT_DIRECTORY" />
+ <option name="OPTION_SCOPE" value="protected" />
+ <option name="OPTION_HIERARCHY" value="true" />
+ <option name="OPTION_NAVIGATOR" value="true" />
+ <option name="OPTION_INDEX" value="true" />
+ <option name="OPTION_SEPARATE_INDEX" value="true" />
+ <option name="OPTION_DOCUMENT_TAG_USE" value="false" />
+ <option name="OPTION_DOCUMENT_TAG_AUTHOR" value="false" />
+ <option name="OPTION_DOCUMENT_TAG_VERSION" value="false" />
+ <option name="OPTION_DOCUMENT_TAG_DEPRECATED" value="true" />
+ <option name="OPTION_DEPRECATED_LIST" value="true" />
+ <option name="OTHER_OPTIONS" value="" />
+ <option name="HEAP_SIZE" />
+ <option name="LOCALE" />
+ <option name="OPEN_IN_BROWSER" value="true" />
+ </component>
+ <component name="JikesSettings">
+ <option name="JIKES_PATH" value="" />
+ <option name="DEBUGGING_INFO" value="true" />
+ <option name="DEPRECATION" value="true" />
+ <option name="GENERATE_NO_WARNINGS" value="false" />
+ <option name="IS_EMACS_ERRORS_MODE" value="true" />
+ <option name="ADDITIONAL_OPTIONS_STRING" value="" />
+ </component>
+ <component name="LogConsolePreferences">
+ <option name="FILTER_ERRORS" value="false" />
+ <option name="FILTER_WARNINGS" value="false" />
+ <option name="FILTER_INFO" value="true" />
+ <option name="CUSTOM_FILTER" />
+ </component>
+ <component name="Palette2">
+ <group name="Swing">
+ <item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
+ <default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
+ </item>
+ <item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
+ <default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
+ </item>
+ <item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.png" removable="false" auto-create-binding="false" can-attach-label="false">
+ <default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
+ </item>
+ <item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.png" removable="false" auto-create-binding="false" can-attach-label="true">
+ <default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
+ </item>
+ <item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.png" removable="false" auto-create-binding="true" can-attach-label="false">
+ <default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
+ <initial-values>
+ <property name="text" value="Button" />
+ </initial-values>
+ </item>
+ <item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.png" removable="false" auto-create-binding="true" can-attach-label="false">
+ <default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
+ <initial-values>
+ <property name="text" value="RadioButton" />
+ </initial-values>
+ </item>
+ <item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.png" removable="false" auto-create-binding="true" can-attach-label="false">
+ <default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
+ <initial-values>
+ <property name="text" value="CheckBox" />
+ </initial-values>
+ </item>
+ <item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.png" removable="false" auto-create-binding="false" can-attach-label="false">
+ <default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
+ <initial-values>
+ <property name="text" value="Label" />
+ </initial-values>
+ </item>
+ <item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.png" removable="false" auto-create-binding="true" can-attach-label="true">
+ <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
+ <preferred-size width="150" height="-1" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.png" removable="false" auto-create-binding="true" can-attach-label="true">
+ <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
+ <preferred-size width="150" height="-1" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.png" removable="false" auto-create-binding="true" can-attach-label="true">
+ <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
+ <preferred-size width="150" height="-1" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.png" removable="false" auto-create-binding="true" can-attach-label="true">
+ <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+ <preferred-size width="150" height="50" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
+ <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+ <preferred-size width="150" height="50" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
+ <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+ <preferred-size width="150" height="50" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.png" removable="false" auto-create-binding="true" can-attach-label="true">
+ <default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
+ </item>
+ <item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.png" removable="false" auto-create-binding="true" can-attach-label="false">
+ <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+ <preferred-size width="150" height="50" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.png" removable="false" auto-create-binding="true" can-attach-label="false">
+ <default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
+ <preferred-size width="150" height="50" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.png" removable="false" auto-create-binding="true" can-attach-label="false">
+ <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+ <preferred-size width="150" height="50" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.png" removable="false" auto-create-binding="true" can-attach-label="false">
+ <default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
+ <preferred-size width="200" height="200" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.png" removable="false" auto-create-binding="false" can-attach-label="false">
+ <default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
+ <preferred-size width="200" height="200" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.png" removable="false" auto-create-binding="true" can-attach-label="true">
+ <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
+ </item>
+ <item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.png" removable="false" auto-create-binding="true" can-attach-label="false">
+ <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
+ </item>
+ <item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.png" removable="false" auto-create-binding="false" can-attach-label="false">
+ <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
+ </item>
+ <item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
+ <default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
+ </item>
+ <item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.png" removable="false" auto-create-binding="false" can-attach-label="false">
+ <default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
+ <preferred-size width="-1" height="20" />
+ </default-constraints>
+ </item>
+ <item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.png" removable="false" auto-create-binding="false" can-attach-label="false">
+ <default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
+ </item>
+ <item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
+ <default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
+ </item>
+ </group>
+ </component>
+ <component name="ProjectModuleManager">
+ <modules>
+ <module fileurl="file://$PROJECT_DIR$/map-activity.iml" filepath="$PROJECT_DIR$/map-activity.iml" />
+ </modules>
+ </component>
+ <component name="ProjectRootManager" version="2" assert-keyword="true" jdk-15="true" project-jdk-name="1.5" project-jdk-type="JavaSDK">
+ <output url="file://$PROJECT_DIR$/classes" />
+ </component>
+ <component name="ProjectRunConfigurationManager" />
+ <component name="RmicSettings">
+ <option name="IS_EANABLED" value="false" />
+ <option name="DEBUGGING_INFO" value="true" />
+ <option name="GENERATE_NO_WARNINGS" value="false" />
+ <option name="GENERATE_IIOP_STUBS" value="false" />
+ <option name="ADDITIONAL_OPTIONS_STRING" value="" />
+ </component>
+ <component name="StarteamVcsAdapter" />
+ <component name="VssVcs" />
+ <component name="com.intellij.jsf.UserDefinedFacesConfigs">
+ <option name="USER_DEFINED_CONFIGS">
+ <value>
+ <list size="0" />
+ </value>
+ </option>
+ </component>
+ <component name="libraryTable" />
+ <component name="uidesigner-configuration">
+ <option name="INSTRUMENT_CLASSES" value="true" />
+ <option name="COPY_FORMS_RUNTIME_TO_OUTPUT" value="true" />
+ <option name="DEFAULT_LAYOUT_MANAGER" value="GridLayoutManager" />
+ </component>
+ <UsedPathMacros />
+</project>
+
diff --git a/map-activity.iws b/map-activity.iws
new file mode 100644
index 0000000..76651af
--- /dev/null
+++ b/map-activity.iws
@@ -0,0 +1,694 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4" relativePaths="false">
+ <component name="BookmarkManager" />
+ <component name="ChangeBrowserSettings">
+ <option name="MAIN_SPLITTER_PROPORTION" value="0.3" />
+ <option name="MESSAGES_SPLITTER_PROPORTION" value="0.8" />
+ <option name="USE_DATE_BEFORE_FILTER" value="false" />
+ <option name="USE_DATE_AFTER_FILTER" value="false" />
+ <option name="USE_CHANGE_BEFORE_FILTER" value="false" />
+ <option name="USE_CHANGE_AFTER_FILTER" value="false" />
+ <option name="DATE_BEFORE" value="" />
+ <option name="DATE_AFTER" value="" />
+ <option name="CHANGE_BEFORE" value="" />
+ <option name="CHANGE_AFTER" value="" />
+ <option name="USE_USER_FILTER" value="false" />
+ <option name="USER" value="" />
+ </component>
+ <component name="ChangeListManager">
+ <list default="true" name="Default" comment="" />
+ </component>
+ <component name="ChangeListSynchronizer" />
+ <component name="ChangesViewManager" flattened_view="true" />
+ <component name="CheckinPanelState" />
+ <component name="Commander">
+ <leftPanel />
+ <rightPanel />
+ <splitter proportion="0.5" />
+ </component>
+ <component name="CompilerWorkspaceConfiguration">
+ <option name="COMPILE_IN_BACKGROUND" value="false" />
+ <option name="AUTO_SHOW_ERRORS_IN_EDITOR" value="true" />
+ <option name="CLOSE_MESSAGE_VIEW_IF_SUCCESS" value="true" />
+ <option name="COMPILE_DEPENDENT_FILES" value="false" />
+ <option name="CLEAR_OUTPUT_DIRECTORY" value="false" />
+ <option name="ASSERT_NOT_NULL" value="true" />
+ </component>
+ <component name="CoverageDataManager" />
+ <component name="Cvs2Configuration">
+ <option name="PRUNE_EMPTY_DIRECTORIES" value="true" />
+ <option name="MERGING_MODE" value="0" />
+ <option name="MERGE_WITH_BRANCH1_NAME" value="HEAD" />
+ <option name="MERGE_WITH_BRANCH2_NAME" value="HEAD" />
+ <option name="RESET_STICKY" value="false" />
+ <option name="CREATE_NEW_DIRECTORIES" value="true" />
+ <option name="DEFAULT_TEXT_FILE_SUBSTITUTION" value="kv" />
+ <option name="PROCESS_UNKNOWN_FILES" value="false" />
+ <option name="PROCESS_DELETED_FILES" value="false" />
+ <option name="PROCESS_IGNORED_FILES" value="false" />
+ <option name="RESERVED_EDIT" value="false" />
+ <option name="CHECKOUT_DATE_OR_REVISION_SETTINGS">
+ <value>
+ <option name="BRANCH" value="" />
+ <option name="DATE" value="" />
+ <option name="USE_BRANCH" value="false" />
+ <option name="USE_DATE" value="false" />
+ </value>
+ </option>
+ <option name="UPDATE_DATE_OR_REVISION_SETTINGS">
+ <value>
+ <option name="BRANCH" value="" />
+ <option name="DATE" value="" />
+ <option name="USE_BRANCH" value="false" />
+ <option name="USE_DATE" value="false" />
+ </value>
+ </option>
+ <option name="SHOW_CHANGES_REVISION_SETTINGS">
+ <value>
+ <option name="BRANCH" value="" />
+ <option name="DATE" value="" />
+ <option name="USE_BRANCH" value="false" />
+ <option name="USE_DATE" value="false" />
+ </value>
+ </option>
+ <option name="SHOW_OUTPUT" value="false" />
+ <option name="ADD_WATCH_INDEX" value="0" />
+ <option name="REMOVE_WATCH_INDEX" value="0" />
+ <option name="UPDATE_KEYWORD_SUBSTITUTION" />
+ <option name="MAKE_NEW_FILES_READONLY" value="false" />
+ <option name="SHOW_CORRUPTED_PROJECT_FILES" value="0" />
+ <option name="TAG_AFTER_PROJECT_COMMIT" value="false" />
+ <option name="OVERRIDE_EXISTING_TAG_FOR_PROJECT" value="true" />
+ <option name="TAG_AFTER_PROJECT_COMMIT_NAME" value="" />
+ <option name="CLEAN_COPY" value="false" />
+ </component>
+ <component name="DaemonCodeAnalyzer">
+ <disable_hints />
+ </component>
+ <component name="DebuggerManager">
+ <breakpoint_any>
+ <breakpoint>
+ <option name="NOTIFY_CAUGHT" value="true" />
+ <option name="NOTIFY_UNCAUGHT" value="true" />
+ <option name="ENABLED" value="false" />
+ <option name="SUSPEND_POLICY" value="SuspendAll" />
+ <option name="LOG_ENABLED" value="false" />
+ <option name="LOG_EXPRESSION_ENABLED" value="false" />
+ <option name="COUNT_FILTER_ENABLED" value="false" />
+ <option name="COUNT_FILTER" value="0" />
+ <option name="CONDITION_ENABLED" value="false" />
+ <option name="CLASS_FILTERS_ENABLED" value="false" />
+ <option name="INSTANCE_FILTERS_ENABLED" value="false" />
+ <option name="CONDITION" value="" />
+ <option name="LOG_MESSAGE" value="" />
+ </breakpoint>
+ <breakpoint>
+ <option name="NOTIFY_CAUGHT" value="true" />
+ <option name="NOTIFY_UNCAUGHT" value="true" />
+ <option name="ENABLED" value="false" />
+ <option name="SUSPEND_POLICY" value="SuspendAll" />
+ <option name="LOG_ENABLED" value="false" />
+ <option name="LOG_EXPRESSION_ENABLED" value="false" />
+ <option name="COUNT_FILTER_ENABLED" value="false" />
+ <option name="COUNT_FILTER" value="0" />
+ <option name="CONDITION_ENABLED" value="false" />
+ <option name="CLASS_FILTERS_ENABLED" value="false" />
+ <option name="INSTANCE_FILTERS_ENABLED" value="false" />
+ <option name="CONDITION" value="" />
+ <option name="LOG_MESSAGE" value="" />
+ </breakpoint>
+ </breakpoint_any>
+ <breakpoint_rules />
+ <ui_properties />
+ </component>
+ <component name="ErrorTreeViewConfiguration">
+ <option name="IS_AUTOSCROLL_TO_SOURCE" value="false" />
+ <option name="HIDE_WARNINGS" value="false" />
+ </component>
+ <component name="FavoritesManager">
+ <favorites_list name="map-activity" />
+ </component>
+ <component name="FavoritesProjectViewPane">
+ <subPane subId="map-activity">
+ <PATH>
+ <PATH_ELEMENT>
+ <option name="myItemId" />
+ <option name="myItemType" value="com.intellij.ide.favoritesTreeView.FavoritesTreeNodeDescriptor" />
+ </PATH_ELEMENT>
+ </PATH>
+ </subPane>
+ </component>
+ <component name="FileEditorManager">
+ <leaf>
+ <file leaf-file-name="1.jpg" pinned="false" current="false" current-in-tab="false">
+ <entry file="file://$PROJECT_DIR$/html/1.jpg">
+ <provider selected="true" editor-type-id="images">
+ <state />
+ </provider>
+ </entry>
+ </file>
+ <file leaf-file-name="model.py" pinned="false" current="false" current-in-tab="false">
+ <entry file="file://$PROJECT_DIR$/model.py">
+ <provider selected="true" editor-type-id="text-editor">
+ <state line="107" column="57" selection-start="3153" selection-end="3153" vertical-scroll-proportion="0.6363636">
+ <folding />
+ </state>
+ </provider>
+ </entry>
+ </file>
+ <file leaf-file-name="activity.info" pinned="false" current="false" current-in-tab="false">
+ <entry file="file://$PROJECT_DIR$/activity/activity.info">
+ <provider selected="true" editor-type-id="text-editor">
+ <state line="7" column="0" selection-start="126" selection-end="126" vertical-scroll-proportion="0.125">
+ <folding />
+ </state>
+ </provider>
+ </entry>
+ </file>
+ <file leaf-file-name="NEWS" pinned="false" current="false" current-in-tab="false">
+ <entry file="file://$PROJECT_DIR$/NEWS">
+ <provider selected="true" editor-type-id="text-editor">
+ <state line="1" column="18" selection-start="20" selection-end="20" vertical-scroll-proportion="0.017857144">
+ <folding />
+ </state>
+ </provider>
+ </entry>
+ </file>
+ <file leaf-file-name="setup.py" pinned="false" current="true" current-in-tab="true">
+ <entry file="file://$PROJECT_DIR$/setup.py">
+ <provider selected="true" editor-type-id="text-editor">
+ <state line="23" column="0" selection-start="830" selection-end="830" vertical-scroll-proportion="0.4107143">
+ <folding />
+ </state>
+ </provider>
+ </entry>
+ </file>
+ </leaf>
+ </component>
+ <component name="FindManager">
+ <FindUsagesManager>
+ <setting name="OPEN_NEW_TAB" value="false" />
+ </FindUsagesManager>
+ </component>
+ <component name="HierarchyBrowserManager">
+ <option name="IS_AUTOSCROLL_TO_SOURCE" value="false" />
+ <option name="SORT_ALPHABETICALLY" value="false" />
+ <option name="HIDE_CLASSES_WHERE_METHOD_NOT_IMPLEMENTED" value="false" />
+ </component>
+ <component name="InspectionManager">
+ <option name="AUTOSCROLL_TO_SOURCE" value="false" />
+ <option name="SPLITTER_PROPORTION" value="0.5" />
+ <option name="GROUP_BY_SEVERITY" value="false" />
+ <option name="FILTER_RESOLVED_ITEMS" value="true" />
+ <option name="ANALYZE_TEST_SOURCES" value="true" />
+ <option name="SHOW_DIFF_WITH_PREVIOUS_RUN" value="false" />
+ <option name="SCOPE_TYPE" value="1" />
+ <option name="CUSTOM_SCOPE_NAME" value="" />
+ <option name="SHOW_ONLY_DIFF" value="false" />
+ <option name="myCurrentProfileName" value="Default" />
+ </component>
+ <component name="J2EEProjectPane" />
+ <component name="JspContextManager" />
+ <component name="ModuleEditorState">
+ <option name="LAST_EDITED_MODULE_NAME" />
+ <option name="LAST_EDITED_TAB_NAME" />
+ </component>
+ <component name="NamedScopeManager" />
+ <component name="PackagesPane">
+ <subPane />
+ </component>
+ <component name="PerforceChangeBrowserSettings">
+ <option name="USE_CLIENT_FILTER" value="true" />
+ <option name="CLIENT" value="" />
+ </component>
+ <component name="PerforceDirect.Settings">
+ <option name="useP4CONFIG" value="true" />
+ <option name="port" value="&lt;perforce_server&gt;:1666" />
+ <option name="client" value="" />
+ <option name="user" value="" />
+ <option name="passwd" value="" />
+ <option name="showCmds" value="false" />
+ <option name="useNativeApi" value="false" />
+ <option name="pathToExec" value="p4" />
+ <option name="useCustomPathToExec" value="false" />
+ <option name="SYNC_FORCE" value="false" />
+ <option name="SYNC_RUN_RESOLVE" value="true" />
+ <option name="REVERT_UNCHANGED_FILES" value="true" />
+ <option name="CHARSET" value="none" />
+ <option name="SHOW_BRANCHES_HISTORY" value="true" />
+ <option name="ENABLED" value="true" />
+ <option name="USE_LOGIN" value="false" />
+ <option name="LOGIN_SILENTLY" value="false" />
+ <option name="INTEGRATE_RUN_RESOLVE" value="true" />
+ <option name="INTEGRATE_REVERT_UNCHANGED" value="true" />
+ <option name="SERVER_TIMEOUT" value="20000" />
+ </component>
+ <component name="ProjectLevelVcsManager">
+ <OptionsSetting value="true" id="Add" />
+ <OptionsSetting value="true" id="Remove" />
+ <OptionsSetting value="true" id="Checkin" />
+ <OptionsSetting value="true" id="Checkout" />
+ <OptionsSetting value="true" id="Update" />
+ <OptionsSetting value="true" id="Status" />
+ <OptionsSetting value="true" id="Edit" />
+ <OptionsSetting value="true" id="Undo Check Out" />
+ <OptionsSetting value="true" id="Compare with SourceSafe Version" />
+ <OptionsSetting value="true" id="Get Latest Version" />
+ <ConfirmationsSetting value="0" id="Add" />
+ <ConfirmationsSetting value="0" id="Remove" />
+ </component>
+ <component name="ProjectPane">
+ <subPane>
+ <PATH>
+ <PATH_ELEMENT>
+ <option name="myItemId" value="map-activity.ipr" />
+ <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
+ </PATH_ELEMENT>
+ <PATH_ELEMENT>
+ <option name="myItemId" value="map-activity" />
+ <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewModuleNode" />
+ </PATH_ELEMENT>
+ </PATH>
+ <PATH>
+ <PATH_ELEMENT>
+ <option name="myItemId" value="map-activity.ipr" />
+ <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
+ </PATH_ELEMENT>
+ <PATH_ELEMENT>
+ <option name="myItemId" value="map-activity" />
+ <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewModuleNode" />
+ </PATH_ELEMENT>
+ <PATH_ELEMENT>
+ <option name="myItemId" value="PsiDirectory:$PROJECT_DIR$" />
+ <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
+ </PATH_ELEMENT>
+ </PATH>
+ <PATH>
+ <PATH_ELEMENT>
+ <option name="myItemId" value="map-activity.ipr" />
+ <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
+ </PATH_ELEMENT>
+ <PATH_ELEMENT>
+ <option name="myItemId" value="map-activity" />
+ <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewModuleNode" />
+ </PATH_ELEMENT>
+ <PATH_ELEMENT>
+ <option name="myItemId" value="PsiDirectory:$PROJECT_DIR$" />
+ <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
+ </PATH_ELEMENT>
+ <PATH_ELEMENT>
+ <option name="myItemId" value="PsiDirectory:$PROJECT_DIR$/po" />
+ <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
+ </PATH_ELEMENT>
+ </PATH>
+ <PATH>
+ <PATH_ELEMENT>
+ <option name="myItemId" value="map-activity.ipr" />
+ <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
+ </PATH_ELEMENT>
+ <PATH_ELEMENT>
+ <option name="myItemId" value="map-activity" />
+ <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewModuleNode" />
+ </PATH_ELEMENT>
+ <PATH_ELEMENT>
+ <option name="myItemId" value="PsiDirectory:$PROJECT_DIR$" />
+ <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
+ </PATH_ELEMENT>
+ <PATH_ELEMENT>
+ <option name="myItemId" value="PsiDirectory:$PROJECT_DIR$/icons" />
+ <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
+ </PATH_ELEMENT>
+ </PATH>
+ <PATH>
+ <PATH_ELEMENT>
+ <option name="myItemId" value="map-activity.ipr" />
+ <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
+ </PATH_ELEMENT>
+ <PATH_ELEMENT>
+ <option name="myItemId" value="map-activity" />
+ <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewModuleNode" />
+ </PATH_ELEMENT>
+ <PATH_ELEMENT>
+ <option name="myItemId" value="PsiDirectory:$PROJECT_DIR$" />
+ <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
+ </PATH_ELEMENT>
+ <PATH_ELEMENT>
+ <option name="myItemId" value="PsiDirectory:$PROJECT_DIR$/html" />
+ <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
+ </PATH_ELEMENT>
+ </PATH>
+ <PATH>
+ <PATH_ELEMENT>
+ <option name="myItemId" value="map-activity.ipr" />
+ <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
+ </PATH_ELEMENT>
+ <PATH_ELEMENT>
+ <option name="myItemId" value="map-activity" />
+ <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewModuleNode" />
+ </PATH_ELEMENT>
+ <PATH_ELEMENT>
+ <option name="myItemId" value="PsiDirectory:$PROJECT_DIR$" />
+ <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
+ </PATH_ELEMENT>
+ <PATH_ELEMENT>
+ <option name="myItemId" value="PsiDirectory:$PROJECT_DIR$/gfx" />
+ <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
+ </PATH_ELEMENT>
+ </PATH>
+ <PATH>
+ <PATH_ELEMENT>
+ <option name="myItemId" value="map-activity.ipr" />
+ <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
+ </PATH_ELEMENT>
+ <PATH_ELEMENT>
+ <option name="myItemId" value="map-activity" />
+ <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewModuleNode" />
+ </PATH_ELEMENT>
+ <PATH_ELEMENT>
+ <option name="myItemId" value="PsiDirectory:$PROJECT_DIR$" />
+ <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
+ </PATH_ELEMENT>
+ <PATH_ELEMENT>
+ <option name="myItemId" value="PsiDirectory:$PROJECT_DIR$/activity" />
+ <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
+ </PATH_ELEMENT>
+ </PATH>
+ </subPane>
+ </component>
+ <component name="ProjectReloadState">
+ <option name="STATE" value="0" />
+ </component>
+ <component name="ProjectView">
+ <navigator currentView="ProjectPane" proportions="0.11111111" version="1" splitterProportion="0.5">
+ <flattenPackages />
+ <showMembers />
+ <showModules />
+ <showLibraryContents />
+ <hideEmptyPackages />
+ <abbreviatePackageNames />
+ <showStructure Favorites="false" PackagesPane="false" Scope="false" ProjectPane="false" />
+ <autoscrollToSource />
+ <autoscrollFromSource />
+ <sortByType />
+ </navigator>
+ </component>
+ <component name="PropertiesComponent">
+ <property name="GoToFile.includeJavaFiles" value="false" />
+ <property name="GoToClass.toSaveIncludeLibraries" value="false" />
+ <property name="MemberChooser.sorted" value="false" />
+ <property name="MemberChooser.showClasses" value="true" />
+ <property name="GoToClass.includeLibraries" value="false" />
+ <property name="MemberChooser.copyJavadoc" value="false" />
+ </component>
+ <component name="ReadonlyStatusHandler">
+ <option name="SHOW_DIALOG" value="true" />
+ </component>
+ <component name="RecentsManager" />
+ <component name="RestoreUpdateTree" />
+ <component name="RunManager">
+ <configuration default="true" type="JUnit" factoryName="JUnit" enabled="false" merge="false">
+ <module name="" />
+ <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
+ <option name="ALTERNATIVE_JRE_PATH" />
+ <option name="PACKAGE_NAME" />
+ <option name="MAIN_CLASS_NAME" />
+ <option name="METHOD_NAME" />
+ <option name="TEST_OBJECT" value="class" />
+ <option name="VM_PARAMETERS" />
+ <option name="PARAMETERS" />
+ <option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
+ <option name="ADDITIONAL_CLASS_PATH" />
+ <option name="TEST_SEARCH_SCOPE">
+ <value defaultName="wholeProject" />
+ </option>
+ </configuration>
+ <configuration default="true" type="Application" factoryName="Application" enabled="false" merge="false">
+ <option name="MAIN_CLASS_NAME" />
+ <option name="VM_PARAMETERS" />
+ <option name="PROGRAM_PARAMETERS" />
+ <option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
+ <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
+ <option name="ALTERNATIVE_JRE_PATH" />
+ <option name="ENABLE_SWING_INSPECTOR" value="false" />
+ <module name="" />
+ </configuration>
+ <configuration default="true" type="Remote" factoryName="Remote">
+ <option name="USE_SOCKET_TRANSPORT" value="true" />
+ <option name="SERVER_MODE" value="false" />
+ <option name="SHMEM_ADDRESS" value="javadebug" />
+ <option name="HOST" value="localhost" />
+ <option name="PORT" value="5005" />
+ </configuration>
+ <configuration default="true" type="Applet" factoryName="Applet">
+ <module name="" />
+ <option name="MAIN_CLASS_NAME" />
+ <option name="HTML_FILE_NAME" />
+ <option name="HTML_USED" value="false" />
+ <option name="WIDTH" value="400" />
+ <option name="HEIGHT" value="300" />
+ <option name="POLICY_FILE" value="/Applications/IntelliJ IDEA 6.0.4.app/bin/appletviewer.policy" />
+ <option name="VM_PARAMETERS" />
+ <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
+ <option name="ALTERNATIVE_JRE_PATH" />
+ </configuration>
+ <configuration name="&lt;template&gt;" type="WebApp" default="true" selected="false">
+ <Host>localhost</Host>
+ <Port>5050</Port>
+ </configuration>
+ </component>
+ <component name="ScopeViewComponent">
+ <subPane subId="Project">
+ <PATH>
+ <PATH_ELEMENT USER_OBJECT="Root">
+ <option name="myItemId" value="" />
+ <option name="myItemType" value="" />
+ </PATH_ELEMENT>
+ </PATH>
+ </subPane>
+ </component>
+ <component name="SelectInManager" />
+ <component name="StarteamConfiguration">
+ <option name="SERVER" value="" />
+ <option name="PORT" value="49201" />
+ <option name="USER" value="" />
+ <option name="PASSWORD" value="" />
+ <option name="PROJECT" value="" />
+ <option name="VIEW" value="" />
+ <option name="ALTERNATIVE_WORKING_PATH" value="" />
+ <option name="LOCK_ON_CHECKOUT" value="false" />
+ <option name="UNLOCK_ON_CHECKIN" value="false" />
+ </component>
+ <component name="StructuralSearchPlugin" />
+ <component name="StructureViewFactory">
+ <option name="AUTOSCROLL_MODE" value="true" />
+ <option name="AUTOSCROLL_FROM_SOURCE" value="false" />
+ <option name="ACTIVE_ACTIONS" value="" />
+ </component>
+ <component name="Struts Assistant">
+ <option name="showInputs" value="true" />
+ <option name="resources">
+ <value>
+ <option name="strutsPath" />
+ <option name="strutsHelp" />
+ </value>
+ </option>
+ <option name="selectedTaglibs" />
+ <option name="selectedTaglibs" />
+ <option name="myStrutsValidationEnabled" value="true" />
+ <option name="myTilesValidationEnabled" value="true" />
+ <option name="myValidatorValidationEnabled" value="true" />
+ <option name="myReportErrorsAsWarnings" value="true" />
+ </component>
+ <component name="SvnChangesBrowserSettings">
+ <option name="USE_AUTHOR_FIELD" value="true" />
+ <option name="AUTHOR" value="" />
+ <option name="LOCATION" value="" />
+ <option name="USE_PROJECT_SETTINGS" value="true" />
+ <option name="USE_ALTERNATE_LOCATION" value="false" />
+ </component>
+ <component name="SvnConfiguration">
+ <option name="USER" value="" />
+ <option name="PASSWORD" value="" />
+ <option name="PROCESS_UNRESOLVED" value="false" />
+ <option name="LAST_MERGED_REVISION" />
+ <option name="UPDATE_RUN_STATUS" value="false" />
+ <option name="UPDATE_RECURSIVELY" value="true" />
+ <option name="MERGE_DRY_RUN" value="false" />
+ <configuration useDefault="false">/Users/erikb/.subversion</configuration>
+ <checkoutURL>http://mediamods.com/public-svn</checkoutURL>
+ <checkoutURL>http://mediamods.com/private-svn/</checkoutURL>
+ <checkoutURL>https://svn.gforge.i-a-i.com/svn/storytiles-sim</checkoutURL>
+ <upgradeMode>auto</upgradeMode>
+ </component>
+ <component name="TodoView" selected-index="0">
+ <todo-panel id="selected-file">
+ <are-packages-shown value="false" />
+ <are-modules-shown value="false" />
+ <flatten-packages value="false" />
+ <is-autoscroll-to-source value="true" />
+ </todo-panel>
+ <todo-panel id="all">
+ <are-packages-shown value="true" />
+ <are-modules-shown value="false" />
+ <flatten-packages value="false" />
+ <is-autoscroll-to-source value="true" />
+ </todo-panel>
+ </component>
+ <component name="ToolWindowManager">
+ <frame x="0" y="25" width="1400" height="1000" extended-state="0" />
+ <editor active="false" />
+ <layout>
+ <window_info id="UI Designer" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" order="3" />
+ <window_info id="Changes" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" order="8" />
+ <window_info id="Palette" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" order="3" />
+ <window_info id="Ant Build" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.24981357" order="1" />
+ <window_info id="Find" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.32760596" order="1" />
+ <window_info id="Debug" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.4" order="4" />
+ <window_info id="IDEtalk Messages" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" order="8" />
+ <window_info id="IDEtalk" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" order="3" />
+ <window_info id="Version Control" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" order="8" />
+ <window_info id="Messages" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.32875144" order="8" />
+ <window_info id="TODO" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" order="7" />
+ <window_info id="Structure" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.24981357" order="1" />
+ <window_info id="Commander" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.4" order="0" />
+ <window_info id="CVS" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" order="8" />
+ <window_info id="Module Dependencies" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" order="3" />
+ <window_info id="Dependency Viewer" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" order="8" />
+ <window_info id="File View" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" order="3" />
+ <window_info id="Project" active="true" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" weight="0.17971663" order="0" />
+ <window_info id="Hierarchy" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.25" order="2" />
+ <window_info id="Inspection" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.4" order="6" />
+ <window_info id="Run" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" order="2" />
+ <window_info id="SVN Repositories" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" weight="0.3298969" order="8" />
+ <window_info id="Cvs" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.25" order="5" />
+ <window_info id="Message" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" order="0" />
+ <window_info id="Web" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.25" order="2" />
+ <window_info id="EJB" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.25" order="3" />
+ </layout>
+ </component>
+ <component name="VCS.FileViewConfiguration">
+ <option name="SELECTED_STATUSES" value="DEFAULT" />
+ <option name="SELECTED_COLUMNS" value="DEFAULT" />
+ <option name="SHOW_FILTERS" value="true" />
+ <option name="CUSTOMIZE_VIEW" value="true" />
+ <option name="SHOW_FILE_HISTORY_AS_TREE" value="true" />
+ </component>
+ <component name="VcsManagerConfiguration">
+ <option name="OFFER_MOVE_TO_ANOTHER_CHANGELIST_ON_PARTIAL_COMMIT" value="true" />
+ <option name="CHECK_CODE_SMELLS_BEFORE_PROJECT_COMMIT" value="true" />
+ <option name="PERFORM_UPDATE_IN_BACKGROUND" value="false" />
+ <option name="PERFORM_COMMIT_IN_BACKGROUND" value="false" />
+ <option name="PUT_FOCUS_INTO_COMMENT" value="false" />
+ <option name="FORCE_NON_EMPTY_COMMENT" value="false" />
+ <option name="LAST_COMMIT_MESSAGE" value="po" />
+ <option name="SAVE_LAST_COMMIT_MESSAGE" value="true" />
+ <option name="CHECKIN_DIALOG_SPLITTER_PROPORTION" value="0.8" />
+ <option name="OPTIMIZE_IMPORTS_BEFORE_PROJECT_COMMIT" value="false" />
+ <option name="REFORMAT_BEFORE_PROJECT_COMMIT" value="false" />
+ <option name="REFORMAT_BEFORE_FILE_COMMIT" value="false" />
+ <option name="FILE_HISTORY_DIALOG_COMMENTS_SPLITTER_PROPORTION" value="0.8" />
+ <option name="FILE_HISTORY_DIALOG_SPLITTER_PROPORTION" value="0.5" />
+ <option name="ERROR_OCCURED" value="false" />
+ <option name="ACTIVE_VCS_NAME" value="svn" />
+ <option name="UPDATE_GROUP_BY_PACKAGES" value="false" />
+ <option name="SHOW_FILE_HISTORY_AS_TREE" value="false" />
+ <option name="FILE_HISTORY_SPLITTER_PROPORTION" value="0.6" />
+ <MESSAGE value="after a movie... not sure where the code is at." />
+ <MESSAGE value="adding tags to map locations works like a charm now" />
+ <MESSAGE value="load in image files that do not have thumbnails in their ds metadata works" />
+ <MESSAGE value="serialize search results with popup and density tags" />
+ <MESSAGE value="added tags when we add media" />
+ <MESSAGE value="make file changes" />
+ <MESSAGE value="prep for launch" />
+ <MESSAGE value="more prep for launch" />
+ <MESSAGE value="NEWS" />
+ <MESSAGE value="po" />
+ </component>
+ <component name="VssConfiguration">
+ <option name="CLIENT_PATH" value="" />
+ <option name="SRCSAFEINI_PATH" value="" />
+ <option name="USER_NAME" value="" />
+ <option name="PWD" value="" />
+ <option name="VSS_IS_INITIALIZED" value="true" />
+ <CheckoutOptions>
+ <option name="COMMENT" value="" />
+ <option name="DO_NOT_GET_LATEST_VERSION" value="false" />
+ <option name="REPLACE_WRITABLE" value="false" />
+ <option name="RECURSIVE" value="false" />
+ </CheckoutOptions>
+ <CheckinOptions>
+ <option name="COMMENT" value="" />
+ <option name="KEEP_CHECKED_OUT" value="false" />
+ <option name="RECURSIVE" value="false" />
+ </CheckinOptions>
+ <AddOptions>
+ <option name="STORE_ONLY_LATEST_VERSION" value="false" />
+ <option name="CHECK_OUT_IMMEDIATELY" value="false" />
+ <option name="FILE_TYPE" value="0" />
+ </AddOptions>
+ <UndocheckoutOptions>
+ <option name="MAKE_WRITABLE" value="false" />
+ <option name="REPLACE_LOCAL_COPY" value="0" />
+ <option name="RECURSIVE" value="false" />
+ </UndocheckoutOptions>
+ <GetOptions>
+ <option name="REPLACE_WRITABLE" value="0" />
+ <option name="MAKE_WRITABLE" value="false" />
+ <option name="ANSWER_NEGATIVELY" value="false" />
+ <option name="ANSWER_POSITIVELY" value="false" />
+ <option name="RECURSIVE" value="false" />
+ <option name="VERSION" />
+ </GetOptions>
+ <VssConfigurableExcludedFilesTag />
+ </component>
+ <component name="antWorkspaceConfiguration">
+ <option name="IS_AUTOSCROLL_TO_SOURCE" value="false" />
+ <option name="FILTER_TARGETS" value="false" />
+ </component>
+ <component name="com.intellij.ide.util.scopeChooser.ScopeChooserConfigurable" proportions="" version="1">
+ <option name="myLastEditedConfigurable" />
+ </component>
+ <component name="com.intellij.openapi.roots.ui.configuration.projectRoot.ProjectRootMasterDetailsConfigurable" proportions="" version="1">
+ <option name="myPlainMode" value="false" />
+ <option name="myLastEditedConfigurable" />
+ </component>
+ <component name="com.intellij.profile.ui.ErrorOptionsConfigurable" proportions="0.16666667" version="1">
+ <option name="myLastEditedConfigurable" value="IDE Profiles" />
+ </component>
+ <component name="editorHistoryManager">
+ <entry file="file://$PROJECT_DIR$/html/1.jpg">
+ <provider selected="true" editor-type-id="images">
+ <state />
+ </provider>
+ </entry>
+ <entry file="file://$PROJECT_DIR$/model.py">
+ <provider selected="true" editor-type-id="text-editor">
+ <state line="107" column="57" selection-start="3153" selection-end="3153" vertical-scroll-proportion="0.6363636">
+ <folding />
+ </state>
+ </provider>
+ </entry>
+ <entry file="file://$PROJECT_DIR$/activity/activity.info">
+ <provider selected="true" editor-type-id="text-editor">
+ <state line="7" column="0" selection-start="126" selection-end="126" vertical-scroll-proportion="0.125">
+ <folding />
+ </state>
+ </provider>
+ </entry>
+ <entry file="file://$PROJECT_DIR$/NEWS">
+ <provider selected="true" editor-type-id="text-editor">
+ <state line="1" column="18" selection-start="20" selection-end="20" vertical-scroll-proportion="0.017857144">
+ <folding />
+ </state>
+ </provider>
+ </entry>
+ <entry file="file://$PROJECT_DIR$/setup.py">
+ <provider selected="true" editor-type-id="text-editor">
+ <state line="23" column="0" selection-start="830" selection-end="830" vertical-scroll-proportion="0.4107143">
+ <folding />
+ </state>
+ </provider>
+ </entry>
+ </component>
+</project>
+
diff --git a/map.py b/map.py
new file mode 100644
index 0000000..82a8216
--- /dev/null
+++ b/map.py
@@ -0,0 +1,1799 @@
+#!/usr/bin/env python
+# Copyright (c) 2008, Media Modifications Ltd.
+
+#Permission is hereby granted, free of charge, to any person obtaining a copy
+#of this software and associated documentation files (the "Software"), to deal
+#in the Software without restriction, including without limitation the rights
+#to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+#copies of the Software, and to permit persons to whom the Software is
+#furnished to do so, subject to the following conditions:
+
+#The above copyright notice and this permission notice shall be included in
+#all copies or substantial portions of the Software.
+
+#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+#THE SOFTWARE.
+
+import gtk
+import gobject
+import os
+import threading
+from threading import *
+import time
+import hippo
+import shutil
+import urllib
+import random
+
+from sugar.graphics.toggletoolbutton import ToggleToolButton
+from sugar.graphics.toolbutton import ToolButton
+from sugar.activity import activity
+from sugar.graphics import style
+
+from filepicker import FilePicker
+
+from constants import Constants
+from webviewer import WebViewer
+from server import Server
+from logic import ServerLogic
+from result import ServerResult
+from instance import Instance
+from constants import Constants
+from model import Model
+from tray import HTray
+from photocanvas import PhotoCanvas
+from p5 import P5
+from gplay import Gplay
+from gplay import PlayVideoWindow
+import serialize
+import utils
+from button import SavedButton
+from savedmap import SavedMap
+import _camera
+
+# sharing
+import telepathy
+from dbus.service import method, signal
+from dbus.gobject_service import ExportedGObject
+from sugar.graphics.alert import NotifyAlert
+from sugar.presence import presenceservice
+from sugar.presence.tubeconn import TubeConnection
+
+SERVICE = "org.laptop.map"
+IFACE = SERVICE
+PATH = "/org/laptop/map"
+
+imgWidth = 180
+imgHeight = 135
+webWidth = imgWidth*4
+webHeight = imgHeight*3
+
+class Map(activity.Activity):
+
+ #temp values until they get assigned
+ cometPort = 8889
+ ajaxPort = 8890
+
+ initLat = '48.224'
+ initLng = '-11.07'
+ initZoom = '3'
+ initType = 'terr'
+
+ popW = 320
+ popH = 240
+ popB = 10
+
+ def __init__(self, handle):
+ activity.Activity.__init__(self, handle)
+ Instance(self)
+ Constants(self)
+ self.modify_bg( gtk.STATE_NORMAL, Constants.colorBg.gColor )
+ gobject.idle_add(self._initme, None)
+
+ def _initme( self, userdata=None ):
+ self.basePath = activity.get_bundle_path()
+ self.htmlPath = os.path.join(self.basePath, "html")
+ self.libPath = "/home/olpc/Library/MapPack/"
+ self.m = Model(self)
+ self.cond = Condition()
+
+ self.SAVING_SEARCH = False
+ self.shownSave = None
+ self.shownRecd = None
+ #these get updated whenever we hear back from the server
+ self.NOW_MAP_CENTER_LAT = self.__class__.initLat
+ self.NOW_MAP_CENTER_LNG = self.__class__.initLng
+ self.NOW_MAP_ZOOM = self.__class__.initZoom
+ self.NOW_MAP_TAGS = ""
+
+ #calc unique ports
+ h = hash(Instance.instanceId)
+ self.__class__.cometPort = 1024 + (h%32255) * 2
+ self.__class__.ajaxPort = self.__class__.cometPort + 1
+
+ #ui
+ self.windowStack = []
+
+ self.toolbox = activity.ActivityToolbox(self)
+ self.set_toolbox(self.toolbox)
+ self.searchToolbar = SearchToolbar(self)
+ self.searchToolbar.connect("address-update", self._addressUpdateCb)
+ self.searchToolbar.connect("zoom-in", self._zoomInCb)
+ self.searchToolbar.connect("zoom-out", self._zoomOutCb)
+ self.searchToolbar.connect("save-search", self._saveSearchCb)
+ self.searchToolbar.connect("search-update", self._searchUpdateCb)
+ self.searchToolbar.set_sensitive(False)
+ self.toolbox.add_toolbar( Constants.istrSearch, self.searchToolbar )
+ self.addToolbar = AddToolbar(self)
+ self.toolbox.add_toolbar( Constants.istrAnnotate, self.addToolbar )
+ self.addToolbar.connect("add-media", self._addMediaCb)
+ self.addToolbar.connect("add-kml", self._addKMLCb)
+ self.addToolbar.connect("add-info", self._addInfoCb)
+ self.addToolbar.connect("delete-media", self._deleteMediaCb)
+ self.addToolbar.connect("measure", self._measureCb)
+ self.addToolbar.connect("olpcmap", self._olpcmapCb)
+ self.addToolbar.connect("panoramio", self._panoramioCb)
+ self.addToolbar.connect("local-wiki", self._localwikiCb)
+ self.addToolbar.connect("wikimapia",self._wikimapiaCb)
+ self.addToolbar.set_sensitive(False)
+ self.firstSearch = True
+ self.toolbox.set_current_toolbar(1)
+
+ self.toolbox.remove(self.toolbox._separator)
+ #taken directly from toolbox.py b/c I don't know how to mod the hongry hippo
+ separator = hippo.Canvas()
+ box = hippo.CanvasBox(
+ border_color=Constants.colorBg.get_int(),
+ background_color=Constants.colorBg.get_int(),
+ box_height=style.TOOLBOX_SEPARATOR_HEIGHT,
+ border_bottom=style.LINE_WIDTH)
+ separator.set_root(box)
+ self.toolbox.separator = separator
+ self.toolbox._notebook.set_property("can-focus", False)
+ self.toolbox.show()
+
+ #add components
+ vbox = gtk.VBox()
+
+ vboxNorth = gtk.VBox()
+ vbox.pack_start(vboxNorth)
+ buttNorthFiller = gtk.EventBox()
+ buttNorthFiller.modify_bg( gtk.STATE_NORMAL, Constants.colorBg.gColor )
+ buttNorthFiller.modify_bg( gtk.STATE_ACTIVE, Constants.colorBg.gColor )
+ buttNorthFiller.modify_bg( gtk.STATE_INSENSITIVE, Constants.colorBg.gColor )
+ vboxNorth.pack_start(buttNorthFiller, expand=True)
+ buttNorthEventBox = gtk.EventBox()
+ buttNorthEventBox.modify_bg( gtk.STATE_NORMAL, Constants.colorBg.gColor )
+ buttNorthEventBox.modify_bg( gtk.STATE_ACTIVE, Constants.colorBg.gColor )
+ buttNorthEventBox.modify_bg( gtk.STATE_INSENSITIVE, Constants.colorBg.gColor )
+ self.buttNorth = gtk.Button()
+ self.buttNorth.set_property("can-focus", False)
+ self.buttNorth.modify_bg( gtk.STATE_NORMAL, Constants.colorBg.gColor )
+ self.buttNorth.modify_bg( gtk.STATE_ACTIVE, Constants.colorBg.gColor )
+ self.buttNorth.modify_bg( gtk.STATE_INSENSITIVE, Constants.colorBg.gColor )
+ buttNorthEventBox.add(self.buttNorth)
+ self.buttNorth.set_image( Constants.northImgClr )
+ self.buttNorth.connect('clicked', self._buttNorthCb)
+ vboxNorth.pack_start(buttNorthEventBox, expand=False)
+ self.buttNorth.set_relief(gtk.RELIEF_NONE)
+
+ hbox = gtk.HBox()
+ self.htmlScale = 1.43
+ hbox.set_size_request(-1, int(webHeight*self.htmlScale))
+ vbox.pack_start(hbox, expand=False)
+
+ vboxSouth = gtk.VBox()
+ vbox.pack_start(vboxSouth)
+ buttSouthEventBox = gtk.EventBox()
+ buttSouthEventBox.modify_bg( gtk.STATE_ACTIVE, Constants.colorBg.gColor )
+ buttSouthEventBox.modify_bg( gtk.STATE_NORMAL, Constants.colorBg.gColor )
+ buttSouthEventBox.modify_bg( gtk.STATE_INSENSITIVE, Constants.colorBg.gColor )
+ vboxSouth.pack_start(buttSouthEventBox, expand=False)
+ self.buttSouth = gtk.Button()
+ self.buttSouth.set_property("can-focus", False)
+ self.buttSouth.modify_bg( gtk.STATE_NORMAL, Constants.colorBg.gColor )
+ self.buttSouth.modify_bg( gtk.STATE_ACTIVE, Constants.colorBg.gColor )
+ self.buttSouth.modify_bg( gtk.STATE_INSENSITIVE, Constants.colorBg.gColor )
+ buttSouthEventBox.add(self.buttSouth)
+ self.buttSouth.set_image(Constants.southImgClr)
+ self.buttSouth.connect('clicked', self._buttSouthCb)
+ buttSouthFiller = gtk.EventBox()
+ buttSouthFiller.modify_bg( gtk.STATE_NORMAL, Constants.colorBg.gColor )
+ buttSouthFiller.modify_bg( gtk.STATE_ACTIVE, Constants.colorBg.gColor )
+ buttSouthFiller.modify_bg( gtk.STATE_INSENSITIVE, Constants.colorBg.gColor )
+ vboxSouth.pack_start(buttSouthFiller, expand=True)
+ self.buttSouth.set_relief(gtk.RELIEF_NONE)
+
+ self.tray = HTray()
+ self.tray.set_size_request(-1, 130)
+ self.tray.connect("enter-notify-event", self._trayMouseCb)
+ self.tray.viewport.connect("enter-notify-event", self._trayMouseCb)
+ self.tray.viewport.traybar.connect("enter-notify-event", self._trayMouseCb)
+ self.tray.scroll_left.connect("enter-notify-event", self._trayMouseCb)
+ self.tray.scroll_right.connect("enter-notify-event", self._trayMouseCb)
+ self.tray.scroll_left_event.connect("enter-notify-event", self._trayMouseCb)
+ self.tray.scroll_right_event.connect("enter-notify-event", self._trayMouseCb)
+ fakeTray = gtk.VBox()
+ fakeTray.set_size_request(-1, 130)
+ fakeTray.modify_bg( gtk.STATE_NORMAL, Constants.colorBg.gColor )
+ fakeTrayEvent = gtk.EventBox()
+ fakeTrayEvent.modify_bg( gtk.STATE_NORMAL, Constants.colorBg.gColor )
+ fakeTrayEvent.set_size_request(-1, 130)
+ fakeTrayEvent.add( fakeTray )
+ self.trayBox = gtk.Notebook()
+ self.trayBox.set_size_request(-1, 130)
+ self.trayBox.set_show_tabs(False)
+ vbox.pack_start(self.trayBox, expand=False)
+ self.trayBox.append_page(self.tray)
+ self.trayBox.append_page(fakeTrayEvent)
+ self.realTrayIndex = self.trayBox.page_num(self.tray)
+ self.fakeTrayIndex = self.trayBox.page_num(fakeTrayEvent)
+ self.trayBox.set_current_page(self.realTrayIndex)
+ fakeTrayEvent.add_events(gtk.gdk.VISIBILITY_NOTIFY_MASK)
+ fakeTrayEvent.connect_after("visibility-notify-event", self._fakeTrayVisibleNotifyCb)
+
+ hboxWest = gtk.HBox()
+ hbox.pack_start(hboxWest)
+ buttWestFiller = gtk.EventBox()
+ buttWestFiller.modify_bg( gtk.STATE_ACTIVE, Constants.colorBg.gColor )
+ buttWestFiller.modify_bg( gtk.STATE_NORMAL, Constants.colorBg.gColor )
+ buttWestFiller.modify_bg( gtk.STATE_INSENSITIVE, Constants.colorBg.gColor )
+ hboxWest.pack_start(buttWestFiller, expand=True)
+ buttWestEventBox = gtk.EventBox()
+ hboxWest.pack_start(buttWestEventBox, expand=False)
+ buttWestEventBox.modify_bg( gtk.STATE_NORMAL, Constants.colorBg.gColor )
+ buttWestEventBox.modify_bg( gtk.STATE_ACTIVE, Constants.colorBg.gColor )
+ buttWestEventBox.modify_bg( gtk.STATE_INSENSITIVE, Constants.colorBg.gColor )
+ self.buttWest = gtk.Button()
+ self.buttWest.set_property("can-focus", False)
+ buttWestEventBox.add(self.buttWest)
+ self.buttWest.modify_bg( gtk.STATE_NORMAL, Constants.colorBg.gColor )
+ self.buttWest.modify_bg( gtk.STATE_ACTIVE, Constants.colorBg.gColor )
+ self.buttWest.modify_bg( gtk.STATE_INSENSITIVE, Constants.colorBg.gColor )
+ self.buttWest.set_image( Constants.westImgClr )
+ self.buttWest.connect('clicked', self._buttWestCb)
+ self.buttWest.set_relief(gtk.RELIEF_NONE)
+
+ self.browseBox = gtk.VBox()
+ self.browser = WebViewer()
+ self.browser.set_size_request(int(webWidth*self.htmlScale), int(webHeight*self.htmlScale))
+ self.browseBox.pack_start(self.browser)
+ self.browseBox.set_size_request(int(webWidth*self.htmlScale), int(webHeight*self.htmlScale))
+ hbox.pack_start(self.browseBox, expand=False)
+
+ hboxEast = gtk.HBox()
+ hbox.pack_start(hboxEast)
+ buttEastEventBox = gtk.EventBox()
+ hboxEast.pack_start(buttEastEventBox, expand=False)
+ buttEastEventBox.modify_bg( gtk.STATE_ACTIVE, Constants.colorBg.gColor )
+ buttEastEventBox.modify_bg( gtk.STATE_NORMAL, Constants.colorBg.gColor )
+ buttEastEventBox.modify_bg( gtk.STATE_INSENSITIVE, Constants.colorBg.gColor )
+ self.buttEast = gtk.Button()
+ self.buttEast.set_property("can-focus", False)
+ self.buttEast.modify_bg( gtk.STATE_ACTIVE, Constants.colorBg.gColor )
+ self.buttEast.modify_bg( gtk.STATE_NORMAL, Constants.colorBg.gColor )
+ self.buttEast.modify_bg( gtk.STATE_INSENSITIVE, Constants.colorBg.gColor )
+ buttEastEventBox.add(self.buttEast)
+ self.buttEast.set_image(Constants.eastImgClr)
+ buttEastFiller = gtk.EventBox()
+ hboxEast.pack_start(buttEastFiller, expand=True)
+ buttEastFiller.modify_bg( gtk.STATE_ACTIVE, Constants.colorBg.gColor )
+ buttEastFiller.modify_bg( gtk.STATE_NORMAL, Constants.colorBg.gColor )
+ buttEastFiller.modify_bg( gtk.STATE_INSENSITIVE, Constants.colorBg.gColor )
+ self.buttEast.connect('clicked', self._buttEastCb)
+ self.buttEast.set_relief(gtk.RELIEF_NONE)
+
+ #important to call these in this order to ensure they show up
+ self.set_canvas(vbox)
+ self.browser.show()
+
+ #fire up the web engine, spiderman!
+ self.cometLogic = ServerLogic(self)
+
+ self.ajaxServer = ServerThread(self.__class__.ajaxPort, self.cometLogic)
+ self.ajaxServer.start()
+
+ self.cometServer = ServerThread(self.__class__.cometPort, self.cometLogic)
+ self.cometServer.start()
+
+ self.browser.load_uri("file://" + self.htmlPath + "/staticmap2.html?ajaxPort=" + str(self.__class__.ajaxPort) + "&cometPort=" + str(self.__class__.cometPort) + "&xo=true" + "&lat=" + str(self.NOW_MAP_CENTER_LAT) + "&lng=" + str(self.NOW_MAP_CENTER_LNG) + "&zoom=" + str(self.NOW_MAP_ZOOM) + "&type=" + self.__class__.initType + "&" + Constants.istrLang)
+
+ self.loaded = True
+ self.loadingWindow = gtk.Window()
+ self.addToWindowStack( self.loadingWindow, self )
+ self.loadingWindow.modify_bg( gtk.STATE_NORMAL, Constants.colorBlack.gColor )
+ loadingVBox = gtk.VBox()
+ self.loadingWindow.add(loadingVBox)
+
+ loadingTopEventBox = gtk.EventBox()
+ loadingTopEventBox.modify_bg( gtk.STATE_NORMAL, Constants.colorBlack.gColor )
+ loadingVBox.pack_start(loadingTopEventBox, expand=True)
+
+ self.loadingCanvas = PhotoCanvas()
+ self.loadingCanvas.modify_bg( gtk.STATE_NORMAL, Constants.colorBlack.gColor )
+ self.loadingCanvas.set_size_request( 1200, 600 )
+ loadingVBox.pack_start(self.loadingCanvas, expand=True)
+
+ loadingInfo = gtk.Label()
+ loadingInfo.set_alignment( .5, 0 )
+ loadingInfo.set_text( "<b><span foreground='white' size='xx-large'>" + Constants.istrConnecting + "</span></b>")
+ loadingInfo.set_use_markup( True )
+ loadingVBox.pack_start(loadingInfo, expand=False)
+
+ loadingBotEventBox = gtk.EventBox()
+ loadingBotEventBox.modify_bg( gtk.STATE_NORMAL, Constants.colorBlack.gColor )
+ loadingVBox.pack_start(loadingBotEventBox, expand=True)
+ self.loadingWindow.resize( gtk.gdk.screen_width(), gtk.gdk.screen_height()-(self.toolbox.allocation.height) )
+ self.moveWinOffscreen(self.loadingWindow)
+
+ self.popWindow = gtk.Window()
+ self.addToWindowStack( self.popWindow, self.loadingWindow )
+ self.popWindow.modify_bg( gtk.STATE_NORMAL, Constants.colorBlack.gColor )
+ self.popWindow.resize( self.popW+(2*self.popB), self.popH+(2*self.popB) )
+ self.popUpBg = PopUpP5()
+ self.popWindow.add( self.popUpBg )
+ self.moveWinOffscreen(self.popWindow)
+ self.popWindow.show_all()
+
+ self.mediaWindow = gtk.Window()
+ self.addToWindowStack(self.mediaWindow, self.popWindow)
+ self.moveWinOffscreen(self.mediaWindow)
+ self.mediaWindow.show_all()
+
+ self.infoWindow = gtk.Window()
+ self._fillInInfoWindow()
+ self.addToWindowStack(self.infoWindow, self.mediaWindow)
+ self.moveWinOffscreen(self.infoWindow)
+ self.infoWindow.show_all()
+
+ self.selectWindow = gtk.Window()
+ self.selectWindow.modify_bg( gtk.STATE_NORMAL, Constants.colorBlack.gColor )
+ self.addToWindowStack(self.selectWindow, self.infoWindow)
+ self.moveWinOffscreen(self.selectWindow)
+ self.selectWindow.show_all()
+
+ self.photoCanvas = PhotoCanvas()
+
+ self.gplayWin = PlayVideoWindow( Constants.colorBlack.gColor )
+ self.gplay = Gplay()
+ self.gplay.window = self.gplayWin
+
+ self.connect("destroy", self.destroy)
+ self.TOOLBOX_SIZE_ALLOCATE_ID = self.toolbox.connect_after("size-allocate", self._sizeAllocateCb)
+ self.show_all()
+
+ # break loading screen
+ self.loaded = True
+ self.enableNavigation()
+
+ # add sharing
+ self.maptube = None # Shared session
+ self.initiating = False
+ self.pservice = presenceservice.get_instance()
+ owner = self.pservice.get_owner()
+ self.owner = owner
+ self.connect('shared', self._shared_cb)
+ self.connect('joined', self._joined_cb)
+ self.mediaType = "photo"
+
+ return False
+
+ def _received_cb(self, text):
+ if(text.find(",") != -1):
+ params = text.split(",")
+ if(params[0] == "loc"):
+ # other XO's map location has moved [lat,lng,zoom]
+ self.preComet()
+ self.cometLogic.handleReceivedMap(params[1],params[2],params[3])
+ self.postComet()
+ elif(params[0] == "mar"):
+ # other XO has added or modded info marker [lat,lng,infoText,iconImg]
+ if(self.cometLogic.addKMLSet == 0):
+ self.preComet()
+ self.cometLogic.handleAddMarker(params[1], params[2], params[3], params[4])
+ self.m.setInfo(params[1],params[2],params[3],params[4])
+ #self.cometLogic.handleEndKML()
+ if(self.cometLogic.addKMLSet == 0):
+ self.postComet()
+ elif(params[0] == "del"):
+ # delete a marker (not working)
+ self.preComet()
+ self.cometLogic.handleDelete()
+ self.postComet()
+ elif(params[0] == "smap"):
+ # add SavedMap [lat,lng,zoom,info] + not-new reminder
+ self.addSavedMap(params[1],params[2],params[3],params[4],False)
+ elif(params[0] == "line"):
+ # add a line
+ if(self.cometLogic.addKMLSet == 0):
+ self.preComet()
+ self.cometLogic.handleLine(params[1],params[2],params[3],params[4])
+ self.addLine(params[1],params[2],params[3],params[4],0)
+ #self.cometLogic.handleEndKML()
+ if(self.cometLogic.addKMLSet == 0):
+ self.postComet()
+ elif(params[0] == "endkml"):
+ self.cometLogic.handleEndKML(0)
+ self.postComet()
+ elif(params[0] == "startkml"):
+ self.preComet()
+ self.cometLogic.startKML(0)
+
+ def updateMapMetaData( self, ctrlat, ctrlng, zoom, showx, showy ):
+ self.NOW_MAP_CENTER_LAT = ctrlat
+ self.NOW_MAP_CENTER_LNG = ctrlng
+ self.NOW_MAP_ZOOM = zoom
+ # calculate where to put media overlay
+ showx = int(showx) + 60
+ showy = int(showy) + 125
+ if(showx > 60) and (showx < 700) and (showy > 125) and (showy < 400):
+ # open media overlay
+ if(self.mediaType == "photo"):
+ # mediaWindow contains a photo
+ self.mediaWindow.show()
+ self.smartMove(self.mediaWindow, self.htmlScale * showx, self.htmlScale * showy )
+ else:
+ # popWindow contains a video player
+ self.popWindow.show()
+ self.smartMove(self.popWindow, self.htmlScale * showx, self.htmlScale * showy )
+ self.popWindow.hide()
+ self.mediaWindow.show_all()
+ else:
+ self.mediaWindow.hide()
+ self.popWindow.hide()
+ if(self.maptube is not None):
+ # update XO group location
+ self.maptube.SendText("loc," + ctrlat + "," + ctrlng + "," + zoom)
+
+ def _trayMouseCb( self, events, args):
+ if (self.shownRecd != None):
+ self.hideMedia()
+ self.preComet()
+ self.cometLogic.handleClear( )
+ self.postComet()
+
+ return True
+
+ #def loadMapV3( self ):
+ # self.browser.load_uri("file://" + self.htmlPath + "/map3.html?ajaxPort=" + str(self.__class__.ajaxPort) + "&cometPort=" + str(self.__class__.cometPort) + "&xo=true" + "&lat=" + str(self.NOW_MAP_CENTER_LAT) + "&lng=" + str(self.NOW_MAP_CENTER_LNG) + "&zoom=" + str(self.NOW_MAP_ZOOM) + "&type=" + self.__class__.initType)
+
+ def _tagsBufferEditedCb(self, widget):
+ if (self.shownSave != None):
+ txt = self.tagsBuffer.get_text( self.tagsBuffer.get_start_iter(), self.tagsBuffer.get_end_iter() )
+ if (txt != self.shownSave.notes):
+ self.shownSave.notes = txt
+
+ def _hideInfoCb( self, butt ):
+ self.hideSearchResult()
+
+ def hideSearchResult(self):
+ #self.shownSave = None
+ self.infoWindow.set_property("accept-focus", False)
+ self.moveWinOffscreen( self.infoWindow )
+ self.enableNavigation()
+
+ def showFileLoadBlocker( self, show ):
+ if (show):
+ self.smartMove( self.selectWindow, 0, 0 )
+ self.smartResize( self.selectWindow, gtk.gdk.screen_width(), gtk.gdk.screen_height() )
+ else:
+ self.moveWinOffscreen( self.selectWindow )
+
+
+ def _sizeAllocateCb( self, widget, event ):
+ self.toolbox.disconnect( self.TOOLBOX_SIZE_ALLOCATE_ID)
+
+ self.smartMove(self.loadingWindow, 0, self.toolbox.allocation.height)
+ self.loadingWindow.resize( gtk.gdk.screen_width(), gtk.gdk.screen_height()-(self.toolbox.allocation.height) )
+ return False
+
+
+ def remoteServerActive(self, loaded):
+ if (self.loaded):
+ return
+ else:
+ self.loaded = loaded
+ #add search results from load_file
+ for i in range(0, len(self.m.savedMaps)):
+ smap = self.m.savedMaps[i]
+ self.addThumb( smap, False )
+ self.searchToolbar.set_sensitive(True)
+ self.addToolbar.set_sensitive(True)
+ browserW = self.browseBox.allocation.width
+ browserH = self.browseBox.allocation.height
+ self.smartResize( self.infoWindow, browserW, browserH )
+ self.moveWinOffscreen(self.loadingWindow)
+
+
+ def addToWindowStack( self, win, parent ):
+ self.windowStack.append( win )
+ win.set_transient_for( parent )
+ win.set_type_hint( gtk.gdk.WINDOW_TYPE_HINT_DIALOG )
+ win.set_decorated( False )
+ win.set_focus_on_map( False )
+ win.set_property("accept-focus", False)
+
+
+ def moveWinOffscreen( self, win ):
+ #we move offscreen to resize or else we get flashes on screen, and setting hide() doesn't allow resize & moves
+ offW = (gtk.gdk.screen_width() + 100)
+ offH = (gtk.gdk.screen_height() + 100)
+ self.smartMove(win, offW, offH)
+
+
+ def smartMove( self, win, x, y ):
+ winLoc = win.get_position()
+ if ( (winLoc[0] != x) or (winLoc[1] != y) ):
+ win.move( int(x), int(y) )
+ return True
+ else:
+ return False
+
+
+ def smartResize( self, win, w, h ):
+ winSize = win.get_size()
+ if ( (winSize[0] != w) or (winSize[1] != h) ):
+ win.resize( w, h )
+ return True
+ else:
+ return False
+
+
+ def preComet(self):
+ self.cond.acquire()
+
+
+ def postComet(self):
+ self.cond.notifyAll()
+ self.cond.release()
+ time.sleep(.1)
+
+
+ def read_file(self, file):
+ serialize.fillMediaHash(file, self.m)
+
+
+ def close( self ):
+ self.hide()
+ activity.Activity.close( self )
+
+
+ def write_file(self, file):
+ dom = serialize.saveMediaHash(self.m)
+ xmlFile = open( file, "w" )
+ dom.writexml(xmlFile)
+ xmlFile.close()
+
+ def _addressUpdateCb( self, otets, address ):
+ if(address.find(',') != -1):
+ if(len(address.split(',')) == 3):
+ addSplit = address.split(',')
+ if(addSplit[2] == 'm'):
+ # add a marker at this lat,lng
+ self.preComet()
+ self.cometLogic.handleAddMarker(addSplit[0],addSplit[1],addSplit[0]+","+addSplit[1],"magenta")
+ self.cometLogic.handleEndKML()
+ self.postComet()
+ self.addInfoMarker(addSplit[0],addSplit[1],addSplit[0]+","+addSplit[1],"magenta",True)
+ return
+ elif(os.path.exists(self.libPath)):
+ mp_address = address.lower().replace(' ','').replace('-','')
+ zoom="13"
+ lat="-190"
+ lng="-190"
+ places = open(self.libPath + "Places.csv", 'r')
+ for place in places:
+ pData = place.split(',')
+ pData[0] = pData[0].lower().replace(' ','').replace('-','')
+ if(pData[0] == mp_address):
+ lat = pData[1]
+ lng = pData[2]
+ if(pData[3] != "-1"):
+ zoom = pData[3]
+ self.preComet()
+ self.cometLogic.handleReceivedMap(lat,lng,zoom)
+ self.postComet()
+ return
+ self.preComet()
+ self.cometLogic.handleAddressUpdate(address)
+ self.postComet()
+
+ def _searchUpdateCb( self, otets, tags ):
+ self.NOW_MAP_TAGS = tags
+ self.preComet()
+ self.cometLogic.handleTagSearch(tags)
+ self.postComet()
+
+ def _buttEastCb( self, butt ):
+ self.hideMedia()
+ self.preComet()
+ self.cometLogic.handleCompassUpdate("e")
+ self.postComet()
+
+
+ def _buttWestCb( self, butt ):
+ self.hideMedia()
+ self.preComet()
+ self.cometLogic.handleCompassUpdate("w")
+ self.postComet()
+
+ def _buttNorthCb( self, butt ):
+ self.hideMedia()
+ self.preComet()
+ self.cometLogic.handleCompassUpdate("n")
+ self.postComet()
+
+ def _buttSouthCb( self, butt ):
+ self.hideMedia()
+ self.preComet()
+ self.cometLogic.handleCompassUpdate("s")
+ self.postComet()
+
+ def _zoomInCb( self, butt ):
+ self.hideMedia()
+ self.preComet()
+ self.cometLogic.handleZoomUpdate("+")
+ self.postComet()
+
+ def _zoomOutCb( self, butt ):
+ self.hideMedia()
+ self.preComet()
+ self.cometLogic.handleZoomUpdate("-")
+ self.postComet()
+
+ def _saveSearchCb( self, otets ):
+ self._saveSearch()
+
+ def _saveSearch( self ):
+ #1st: cover up the tray when grabbing a screenshot
+ #this will take a moment, so disable all buttons while we wait
+ self.SAVING_SEARCH = True
+ self.disableNavigation()
+ self.savingSearchMediaLoc = self.mediaWindow.get_position()
+ self.moveWinOffscreen( self.mediaWindow )
+ self.hideTray(True)
+
+
+ def hideTray( self, hide ):
+ if (hide):
+ self.trayBox.set_current_page(self.fakeTrayIndex)
+ else:
+ self.trayBox.set_current_page(self.realTrayIndex)
+
+
+ def _fakeTrayVisibleNotifyCb( self, widget, event ):
+ #if (event.state == gtk.gdk.VISIBILITY_UNOBSCURED): #this is not used, bc a popup might be over it
+ if (self.SAVING_SEARCH):
+ gobject.idle_add( self._saveSearch2 )
+
+ def _saveSearch2( self ):
+ # add SavedMap
+ window = self.canvas.window
+ width, height = window.get_size()
+ screenshot = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, has_alpha=False, bits_per_sample=8, width=width, height=height)
+ screenshot.get_from_drawable(window, window.get_colormap(), 0, 0, 0, 0, width, height)
+
+ popW, popH = [self.popW+(2*self.popB), self.popH+(2*self.popB) ]
+ popScreenshot = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, has_alpha=False, bits_per_sample=8, width=width, height=height)
+ popScreenshot.get_from_drawable(self.popWindow.window, self.popWindow.window.get_colormap(), 0, 0, 0, 0, popW, popH)
+
+ popLoc = self.popWindow.get_position()
+ popLocX = popLoc[0]
+ popLocY = popLoc[1] - self.toolbox.allocation.height
+ popScreenshot.composite(screenshot,
+ popLocX, popLocY, #move the actual mini-canvas (but not its internals (?))
+ popW, popH, #actual size of the mini-canvas
+ popLocX, popLocY, #offx, y of the painting (irrespective of the mini-canvas)
+ 1, 1, #scalex,y
+ gtk.gdk.INTERP_BILINEAR, 255)
+
+ screenshotPath = os.path.join(Instance.instancePath, "savedMap.jpg")
+ screenshotPath = utils.getUniqueFilepath(screenshotPath, 0)
+ screenshot.save( screenshotPath, "jpeg", {} )
+
+ smallHeight = 120
+ smallWidth = (width*smallHeight) / height
+ screenshotSmall = screenshot.scale_simple(smallWidth, smallHeight, gtk.gdk.INTERP_NEAREST)
+ screenshotSmallPath = os.path.join(Instance.instancePath, "savedMapThumb.jpg")
+ screenshotSmallPath = utils.getUniqueFilepath(screenshotSmallPath, 0)
+ screenshotSmall.save( screenshotSmallPath, "jpeg", {} )
+
+ sm = SavedMap( self.NOW_MAP_CENTER_LAT, self.NOW_MAP_CENTER_LNG, self.NOW_MAP_ZOOM, screenshotPath, screenshotSmallPath, "Describe the map", self.NOW_MAP_TAGS )
+ if (self.shownRecd != None):
+ sm.addViewedRecd(self.shownRecd.datastoreId, self.shownRecd.latitude, self.shownRecd.longitude)
+
+ self.m.addSavedMap( sm )
+ self.addThumb( sm, True )
+
+ self.hideTray(False)
+ self.enableNavigation()
+ self.smartMove( self.mediaWindow, self.savingSearchMediaLoc[0], self.savingSearchMediaLoc[1] )
+
+ if(self.maptube is not None):
+ self.maptube.SendText("smap," + str(self.NOW_MAP_CENTER_LAT) + "," + str(self.NOW_MAP_CENTER_LNG) + "," + str(self.NOW_MAP_ZOOM) + ",Describe this map")
+
+ def addLine(self,id,color,thickness,pts,isNew):
+ self.m.setLine(id,color,thickness,pts)
+ if((self.maptube is not None) and (isNew == 1)):
+ self.maptube.SendText("line," + id + "," + color + "," + thickness + "," + pts)
+
+ def lineMode(self,type):
+ self.preComet()
+ self.cometLogic.lineMode(type)
+ self.postComet()
+
+ def addSavedMap(self,lat,lng,zoom,info,isNew):
+ # add SavedMap received from internet or other XO, use Google Static Maps
+ window = self.canvas.window
+ width, height = window.get_size()
+ screenshotPath = os.path.join(Instance.instancePath, "savedMap.jpg")
+ urllib.urlretrieve("http://maps.google.com/staticmap?key=ABQIAAAAxkKtrWN5q-vPTLRVmO_r6RRFDCLHCbUG3VrjXnZmMRXvQdFL3RS-b-ld9hTrkIgQlYsxPQ1kYq6y9A&size=200x120&format=jpg&center=" + str(lat) + "," + str(lng) + "&zoom=" + str(int(zoom)-1), screenshotPath)
+ smallHeight = 120
+ smallWidth = 200
+ sm = SavedMap( lat, lng, zoom, screenshotPath, screenshotPath, info, "" )
+ self.m.addSavedMap( sm )
+ self.addThumb( sm, True )
+ if(isNew == True):
+ if(self.maptube is not None):
+ # user created SaveMap, send to others
+ self.maptube.SendText("smap," + lat + "," + lng + "," + zoom + "," + info)
+
+ def addInfoMarker(self,lat,lng,info,icon,sendUpdate):
+ # add/update InfoMarker in model
+ self.m.setInfo(lat, lng, info, icon)
+ if(sendUpdate == True):
+ if(self.maptube is not None):
+ # send added/updated info marker
+ self.maptube.SendText("mar," + lat + "," + lng + "," + info + "," + icon)
+ else:
+ # put InfoMarker on own map
+ self.preComet()
+ self.cometLogic.handleAddMarker(lat,lng,info,icon)
+ self.postComet()
+
+ def removeThumb( self, sm ):
+ kids = self.tray.get_children()
+ for i in range (0, len(kids)):
+ if (kids[i].data == sm):
+ self.tray.remove_item(kids[i])
+ kids[i].cleanUp()
+ kids[i].disconnect( kids[i].getButtClickedId() )
+ kids[i].setButtClickedId(0)
+ if (sm == self.shownSave):
+ self.hideSearchResult()
+ self.m.savedMaps.remove(sm)
+
+ def addThumb( self, sm, forceScroll ):
+ butt = SavedButton( self, sm )
+ BUTT_CLICKED_ID = butt.connect( "clicked", self._thumbClickedCb, sm )
+ butt.setButtClickedId(BUTT_CLICKED_ID)
+ self.tray.add_item( butt, len(self.tray.get_children()) )
+ butt.show()
+ if (forceScroll):
+ self.tray.scroll_to_end()
+
+ #1 way to see a sr
+ def _thumbClickedCb( self, button, smap ):
+ self.showSearchResult(smap)
+ self.preComet()
+ self.cometLogic.handleSavedMap(smap.lat,smap.lng,smap.zoom,smap.notes)
+ self.postComet()
+
+ def showSearchResult( self, smap ):
+ self.shownSave = smap
+ self.updateSearchResultTags(smap)
+ self.searchToolbar._setTagsString( smap.tags )
+
+ def updateSearchResultTags( self, smap ):
+ self.shownSave = smap
+ self.lngValueLabel.set_text( str(smap.lng) )
+ self.latValueLabel.set_text( str(smap.lat) )
+ self.tagsBuffer.set_text( smap.notes )
+
+ def _fillInInfoWindow( self ):
+ hbox = gtk.HBox()
+ self.infoWindow.add(hbox)
+ clr = Constants.colorGrey
+ inset = 10
+ self.infoWindow.modify_bg( gtk.STATE_NORMAL, clr.gColor )
+ ltBox = gtk.VBox()
+ ltBox.set_border_width(inset)
+ rtBox = gtk.VBox()
+ hbox.pack_start(ltBox)
+ hbox.pack_start(rtBox, expand=False)
+ latHBox = gtk.HBox()
+ ltBox.pack_start(latHBox, expand=False)
+ latLabel = gtk.Label("<b>" + Constants.istrLatitude + "</b> ")
+ latLabel.set_use_markup(True)
+ latLabel.set_alignment(0, .5)
+ latHBox.pack_start(latLabel, expand=False)
+ self.latValueLabel = gtk.Label()
+ self.latValueLabel.set_alignment(0, .5)
+ latHBox.pack_start(self.latValueLabel)
+ fillb1 = gtk.HBox()
+ fillb1.set_size_request(inset,inset)
+ ltBox.pack_start(fillb1, expand=False)
+ lngHBox = gtk.HBox()
+ ltBox.pack_start(lngHBox, expand=False)
+ lngLabel = gtk.Label("<b>" + Constants.istrLongitude + "</b> ")
+ lngLabel.set_use_markup(True)
+ lngLabel.set_alignment(0, .5)
+ lngHBox.pack_start(lngLabel, expand=False)
+ self.lngValueLabel = gtk.Label()
+ self.lngValueLabel.set_alignment(0, .5)
+ lngHBox.pack_start(self.lngValueLabel)
+ fillb2 = gtk.HBox()
+ fillb2.set_size_request(inset,inset)
+ ltBox.pack_start(fillb2, expand=False)
+ tagLabelBox = gtk.HBox()
+ ltBox.pack_start(tagLabelBox, expand=False)
+ tagsLabel = gtk.Label("<b>" + Constants.istrTags + "</b>")
+ tagsLabel.set_use_markup(True)
+ tagsLabel.set_alignment(0, .5)
+ tagLabelBox.pack_start(tagsLabel, expand=False)
+ tagBox = gtk.HBox()
+ self.tagsBuffer = gtk.TextBuffer()
+ self.tagsBuffer.set_text("please edit me!")
+ self.tagsBuffer.connect('changed', self._tagsBufferEditedCb)
+ self.tagsField = gtk.TextView(self.tagsBuffer)
+ ltBox.pack_start(self.tagsField, expand=True)
+ rtFill = gtk.VBox()
+ rtFill.set_spacing( 0 )
+ rtFill.set_border_width( 0 )
+ rtBox.pack_start(rtFill, expand=True)
+ buttImg = gtk.Image()
+ buttPixb = Constants.infoOnSvg.get_pixbuf()
+ buttImg.set_from_pixbuf( buttPixb )
+ buttImg.show()
+ rtButt = gtk.Button()
+ rtButt.set_image(buttImg)
+ rtButt.modify_bg( gtk.STATE_NORMAL, Constants.colorBlack.gColor )
+ rtButt.modify_bg( gtk.STATE_ACTIVE, Constants.colorBlack.gColor )
+ rtButt.modify_bg( gtk.STATE_INSENSITIVE, Constants.colorBlack.gColor )
+ rtButt.set_relief(gtk.RELIEF_NONE)
+ rtButt.set_property('can-default', True)
+ rtButt.set_property('can-focus', False)
+ rtButt.set_property('yalign', 1)
+ rtButt.set_size_request( 75, 75 )
+ rtButt.connect("clicked", self._hideInfoCb)
+ grr = gtk.EventBox()
+ grr.modify_bg( gtk.STATE_NORMAL, Constants.colorBlack.gColor )
+ grr.add(rtButt)
+ rtBox.pack_start(grr, expand=False)
+ hbox.show_all()
+
+ def showSearchResultTags( self, smap ):
+ self.updateSearchResultTags( smap )
+
+ #avoid popups lingering
+ self.hideMedia()
+ self.preComet()
+ self.cometLogic.handleClear()
+ self.postComet()
+ self.disableNavigation()
+ browserLoc = self.browseBox.translate_coordinates(self, 0, 0)
+ self.infoWindow.show_all()
+ self.smartMove(self.infoWindow, browserLoc[0], browserLoc[1])
+ browserW = self.browseBox.allocation.width
+ browserH = self.browseBox.allocation.height
+ self.smartResize(self.infoWindow, browserW, browserH)
+ self.infoWindow.set_property("accept-focus", True)
+
+ def copyToClipboard( self, smap ):
+ tmpImgPath = self.doClipboardCopyStart( smap )
+ gtk.Clipboard().set_with_data( [('text/uri-list', 0, 0)], self._clipboardGetFuncCb, self._clipboardClearFuncCb, tmpImgPath )
+ return True
+
+ def doClipboardCopyStart( self, smap ):
+ tmpImgPath = utils.getUniqueFilepath(smap.imgPath, 0)
+ shutil.copyfile( smap.imgPath, tmpImgPath )
+ return tmpImgPath
+
+ def doClipboardCopyCopy( self, tmpImgPath, selection_data ):
+ tmpImgUri = "file://" + tmpImgPath
+ selection_data.set( "text/uri-list", 8, tmpImgUri )
+
+ def doClipboardCopyFinish( self, tmpImgPath ):
+ if (tmpImgPath != None):
+ if (os.path.exists(tmpImgPath)):
+ os.remove( tmpImgPath )
+ tmpImgPath = None
+
+ def _clipboardGetFuncCb( self, clipboard, selection_data, info, data):
+ self.doClipboardCopyCopy( data, selection_data )
+
+ def _clipboardClearFuncCb( self, clipboard, data):
+ self.doClipboardCopyFinish( data )
+
+ def _addMediaCb( self, ot, datastoreOb ):
+ self.addMeToMapObj = datastoreOb
+ self.hideMedia()
+ self.preComet()
+ self.cometLogic.handlePreAdd()
+ self.postComet()
+
+ def _addKMLCb( self, ot, datastoreOb ):
+ self.readKML(open(datastoreOb.file_path, 'r'))
+
+ def readKML(self, kml):
+ firstLine = kml.readline()
+ if(firstLine.find('<?xml version="1.0" ?><map')==0):
+ # Offline Map or regular Map file without meta-data
+ self.preComet()
+ self.cometLogic.startKML(1)
+ xmlarray = firstLine.split('>')
+ for node in xmlarray:
+ #if(node.find('<mapItem') == 0):
+ # picture marker
+ if(node.find('<infoMarker') == 0):
+ # info marker
+ lat = node[node.find('lat="')+5:len(node)]
+ lat = lat[0:lat.find('"')]
+ lng = node[node.find('lng="')+5:len(node)]
+ lng = lng[0:lng.find('"')]
+ description = node[node.find('info="')+6:len(node)]
+ description = description[0:description.find('"')]
+ icon = node[node.find('icon="')+6:len(node)]
+ icon = icon[0:icon.find('"')]
+ self.cometLogic.handleAddMarker(lat,lng,description,icon)
+ self.addInfoMarker(lat,lng,description,icon,True)
+ elif(node.find('<line') == 0):
+ # line
+ lineColor = node[node.find('lcolor="')+8:len(node)]
+ lineColor = lineColor[0:lineColor.find('"')]
+ lineID = node[node.find('lid="')+5:len(node)]
+ lineID = lineID[0:lineID.find('"')]
+ ptStr = node[node.find('lpts="')+6:len(node)]
+ ptStr = ptStr[0:ptStr.find('"')]
+ lineThick = node[node.find('lthickness="')+12:len(node)]
+ lineThick = lineThick[0:lineThick.find('"')]
+ self.cometLogic.handleLine(lineID,lineColor,lineThick,ptStr)
+ self.addLine(lineID,lineColor,lineThick,ptStr,1)
+ elif(node.find('<savedMap') == 0):
+ # saved map
+ lat = node[node.find('lat="')+5:len(node)]
+ lat = lat[0:lat.find('"')]
+ lng = node[node.find('lng="')+5:len(node)]
+ lng = lng[0:lng.find('"')]
+ notes = node[node.find('notes="')+7:len(node)]
+ notes = notes[0:notes.find('"')]
+ zoom = node[node.find('zoom="')+6:len(node)]
+ zoom = zoom[0:zoom.find('"')]
+ self.addSavedMap(lat,lng,zoom,notes,True)
+ self.cometLogic.handleEndKML(1)
+ self.postComet()
+ return
+ placename = None
+ description = None
+ kmlIcon = None
+ lat = None
+ lng = None
+ coordList = None
+ placemarkType = None
+ lineType = None
+ stillDescribing = False
+ morePts = False
+ dataTable = None
+ isOSM = False
+ isGeoRSS = False
+ self.preComet()
+ self.cometLogic.startKML(1)
+ for kmlline in kml:
+ if((kmlline.find('<osm') != -1) and (lat == None) and (lng == None) and (coordList == None)):
+ # jump to osm
+ isOSM = True
+ break
+ elif((kmlline.find('georss') != -1) and (lat == None) and (lng == None) and (coordList == None)):
+ # jump to GeoRSS
+ isGeoRSS = True
+ break
+ if(kmlline.find('<Point') != -1):
+ placemarkType = 'info'
+ elif(kmlline.find('<LineString') != -1):
+ placemarkType = 'line'
+ lineType = 'line'
+ elif(kmlline.find('<Polygon') != -1):
+ placemarkType = 'poly'
+ lineType = 'poly'
+ #elif(kmlline.find('<GroundOverlay') != -1):
+ # placemarkType = 'overlay'
+ if(kmlline.find('<ExtendedData') != -1):
+ dataTable = '<table>'
+ elif(kmlline.find('</ExtendedData>') != -1):
+ dataTable = dataTable + '</table>'
+ if(dataTable is not None):
+ if(kmlline.find('<Data') != -1):
+ dataTable = dataTable + '<tr>'
+ if(kmlline.find('<Data name="') != -1):
+ dataTable = dataTable + "<td><b>" + kmlline[kmlline.find('<Data name="')+12:kmlline.rfind('"')] + "</b></td>"
+ if(kmlline.find('<value>') != -1):
+ dataTable = dataTable + "<td>" + kmlline[kmlline.find('<value>')+7:kmlline.find('</value>')] + "</td>"
+ elif(kmlline.find('</Data>') != -1):
+ dataTable = dataTable + '</tr>'
+
+ if(kmlline.find('<coordinates>') != -1):
+ if(placemarkType == 'info'):
+ lng = kmlline[kmlline.find('<coordinates>')+13:kmlline.find(',')]
+ lat = kmlline[kmlline.find(',')+1:kmlline.rfind(',')]
+ else:
+ if(kmlline.find('</coordinates>') == -1):
+ morePts = True
+ kmlline = kmlline.replace('<coordinates>','').replace('</coordinates>','')
+ coordList = kmlline.split(' ')
+ elif(morePts == True):
+ if(kmlline.find('</coordinates>') != -1):
+ morePts = False
+ kmlline = kmlline.replace('</coordinates>','')
+ coordList.extend(kmlline.split(' '))
+
+ if(kmlline.find('<name>') != -1):
+ placename = kmlline[kmlline.find('<name>')+6:kmlline.find('</name>')]
+ if(kmlline.find('<description>') != -1):
+ description = kmlline[kmlline.find('<description>')+13:len(kmlline)]
+ if(kmlline.find('</description>') == -1):
+ # need to read in more lines
+ stillDescribing = True
+ else:
+ description = description[0:description.find('</description')]
+ if(description.find('<![CDATA[') != -1):
+ description = description.replace('<![CDATA[','').replace(']]>','')
+ elif(stillDescribing == True):
+ description = description + kmlline
+ if(kmlline.find('</description>') != -1):
+ stillDescribing = False
+ description = description[0:description.find('</description')]
+ if(description.find('<![CDATA[') != -1):
+ description = description.replace('<![CDATA[','').replace(']]>','')
+ if(kmlline.find('<Icon><href>')!=-1):
+ icon = kmlline[kmlline.find('<Icon><href>')+12:kmlline.find('</href>')]
+ if((kmlline.find('</Placemark>') != -1) or (kmlline.find('<Placemark>') != -1)):
+ # finish this placemark
+ if(lat is not None):
+ if(description is None):
+ description = ""
+ else:
+ description=description.replace("width:300","width:60").replace("max-height:400","max-height:80")
+ if(dataTable is not None):
+ description = dataTable + description
+ if(placename is not None):
+ description = '<h3>' + placename + '</h3>' + description
+ if(icon is None):
+ icon="null"
+ self.cometLogic.handleAddMarker(lat,lng,description,icon)
+ self.addInfoMarker(lat,lng,description,icon,True)
+ if(coordList is not None):
+ ptList = []
+ maxInterval = 1
+ if(len(coordList) > 50):
+ maxInterval = int(len(coordList) / 50)
+ interval = 1
+ for pt in coordList:
+ ptloc = pt.split(',')
+ interval = interval - 1
+ if((len(ptloc) > 1) and (interval < 2)):
+ ptList.append(ptloc[1]+"|"+ptloc[0])
+ interval = maxInterval
+ if(lineType == 'line'):
+ lineID = str(random.getrandbits(128))
+ self.cometLogic.handleLine(lineID,"B22222","5",'|'.join(ptList))
+ self.addLine(lineID,"B22222","5",'|'.join(ptList),1)
+ elif(lineType == 'poly'):
+ lineID = "poly-" + str(random.getrandbits(128))
+ self.cometLogic.handleLine(lineID,"7CFC00","5",'|'.join(ptList))
+ self.addLine(lineID,"7CFC00","5",'|'.join(ptList),1)
+ #elif(placemarkType == 'overlay'):
+ lat = None
+ lng = None
+ description = None
+ placename = None
+ placemarkType = None
+ coordList = None
+ dataTable = None
+ if(isOSM == True):
+ # read in an OSM style file
+ osmNodes = {}
+ readingInNodeID = None
+ readingInWayID = None
+ for osm in kml:
+ if(osm.find('<node') != -1):
+ # point, which may be part of a line
+ nodeID = osm[osm.find('id=')+4:len(osm)]
+ nodeID = nodeID[0:nodeID.find('"')]
+ nodeID = nodeID[0:nodeID.find("'")]
+ lat = osm[osm.find('lat=')+5:len(osm)]
+ lat = lat[0:lat.find("'")]
+ lat = lat[0:lat.find('"')]
+ lng = osm[osm.find('lon=')+5:len(osm)]
+ lng = lng[0:lng.find("'")]
+ lng = lng[0:lng.find('"')]
+ osmNodes[nodeID] = {"latitude":lat,"longitude":lng,"inWay":False,"isWay":False}
+ if(osm.find('/>') == -1):
+ readingInNodeID = nodeID
+ elif(readingInNodeID is not None):
+ # reading in tag-values for the point
+ if(osm.find('</node>') != -1):
+ readingInNodeID = None
+ else:
+ if(osm.find('<tag') != -1):
+ tName = osm[osm.find('k=')+3:len(osm)]
+ tName = tName[0:tName.find('"')]
+ tName = tName[0:tName.find("'")]
+ vName = osm[osm.find('v=')+3:len(osm)]
+ vName = vName[0:vName.find('"')]
+ vName = vName[0:vName.find("'")]
+ osmNodes[readingInNodeID][tName] = vName
+ elif(osm.find('<way') != -1):
+ # line, composed of multiple points
+ readingInWayID = osm[osm.find('id=')+4:len(osm)]
+ readingInWayID = readingInWayID[0:readingInWayID.find('"')]
+ readingInWayID = readingInWayID[0:readingInWayID.find("'")]
+ osmNodes[readingInWayID] = {"isWay":True,"pts":[]}
+ elif(readingInWayID is not None):
+ # reading in node ids composing the line
+ if(osm.find('</way>') != -1):
+ readingInWayID = None
+ else:
+ if(osm.find('<nd') != -1):
+ nodeRef = osm[osm.find('ref=')+5:len(osm)]
+ if(nodeRef.find('"') != -1):
+ nodeRef = nodeRef[0:nodeRef.find('"')]
+ else:
+ nodeRef = nodeRef[0:nodeRef.find("'")]
+ osmNodes[readingInWayID]["pts"].append(nodeRef)
+ osmNodes[nodeRef]["inWay"] = True
+ # decide how to publish nodes
+ for node in osmNodes:
+ if(osmNodes[node]["isWay"] == True):
+ # line composed of points
+ ptList=[]
+ for pID in osmNodes[node]["pts"]:
+ ptList.append(osmNodes[pID]["latitude"]+"|"+osmNodes[pID]["longitude"])
+ lineID = str(random.getrandbits(128))
+ self.cometLogic.handleLine(lineID,"B22222","5",'|'.join(ptList))
+ self.addLine(lineID,"B22222","5",'|'.join(ptList),1)
+ elif(osmNodes[node]["inWay"] == False):
+ # independent point
+ description="<table>"
+ for tag in osmNodes[node]:
+ if(tag=="latitude"):
+ continue
+ elif(tag=="longitude"):
+ continue
+ elif(tag=="inWay"):
+ continue
+ elif(tag=="isWay"):
+ continue
+ else:
+ value = osmNodes[node][tag]
+ description=description+"<tr><td>"+tag+"</td><td>"+str(value)+"</td></tr>"
+ description=description+"</table>"
+ self.cometLogic.handleAddMarker(osmNodes[node]["latitude"],osmNodes[node]["longitude"],description,"null")
+ self.addInfoMarker(osmNodes[node]["latitude"],osmNodes[node]["longitude"],description,"null",True)
+ elif(isGeoRSS == True):
+ # scan in GeoRSS
+ placeLink = None
+ lat = None
+ lng = None
+ description = None
+ placename = None
+ stillDescribing = False
+ #self.preComet()
+ for rss in kml:
+ if(rss.find('<title') != -1):
+ placename = rss[rss.find('>')+1:rss.find('</title>')]
+ if(rss.find('<link') != -1):
+ placeLink = rss[rss.find('>')+1:rss.find('</link>')]
+ if(rss.find('<georss:point') != -1):
+ latlng = rss[rss.find('>')+1:rss.find('</georss:point>')].split(' ')
+ lat = latlng[0]
+ lng = latlng[1]
+ if(rss.find('<description>') != -1):
+ description = rss[rss.find('<description>')+13:len(rss)]
+ if(rss.find('</description>') == -1):
+ # need to read in more lines
+ stillDescribing = True
+ else:
+ description = description[0:description.find('</description')]
+ elif(stillDescribing == True):
+ description = description + rss
+ if(rss.find('</description>') != -1):
+ stillDescribing = False
+ description = description[0:description.find('</description')]
+ if(rss.find('</item>') != -1):
+ # publish the point
+ if(lat is not None):
+ if(description == None):
+ description = ""
+ if(placeLink is not None):
+ description = placeLink + "<br/>" + description
+ if(placename is not None):
+ description = '<h3>' + placename + '</h3>' + description
+ description=description.replace("'","\\'").replace('"','\\"')
+ description=description.replace("\n","<br/>").replace("\r","<br/>")
+ description=description.replace("<![CDATA[","").replace("]]>","")
+ self.cometLogic.handleAddMarker(lat,lng,description,"null")
+ self.addInfoMarker(lat,lng,description,"null",True)
+ placeLink = None
+ lat = None
+ lng = None
+ placename = None
+ description = None
+ stillDescribing = False
+ self.cometLogic.handleEndKML(1)
+ self.postComet()
+
+ def _addInfoCb(self,ot):
+ self.preComet()
+ self.cometLogic.handlePreAddInfo()
+ self.postComet()
+
+ def _measureCb(self,ot):
+ self.preComet()
+ self.cometLogic.handleMeasure()
+ self.postComet()
+
+ def _olpcmapCb(self,ot):
+ self.preComet()
+ self.cometLogic.handleOlpcMAP()
+ self.postComet()
+
+ def _panoramioCb(self,ot):
+ self.preComet()
+ self.cometLogic.handlePanoramio()
+ self.postComet()
+
+ def _localwikiCb(self,ot):
+ self.preComet()
+ self.cometLogic.handleLocalWiki()
+ self.postComet()
+
+ def _wikimapiaCb(self,ot):
+ self.preComet()
+ self.cometLogic.handleWikiMapia()
+ self.postComet()
+
+ def disableNavigation( self ):
+ #disable the nav buttons
+ self.buttEast.set_image(Constants.eastImgBw)
+ self.buttEast.set_sensitive(False)
+ self.buttWest.set_image(Constants.westImgBw)
+ self.buttWest.set_sensitive(False)
+ self.buttNorth.set_image(Constants.northImgBw)
+ self.buttNorth.set_sensitive(False)
+ self.buttSouth.set_image(Constants.southImgBw)
+ self.buttSouth.set_sensitive(False)
+ #disable the toolbar buttons
+ self.addToolbar.set_sensitive( False )
+ self.searchToolbar.set_sensitive( False )
+
+ def enableNavigation( self ):
+ #enable the nav buttons
+ self.buttEast.set_image(Constants.eastImgClr)
+ self.buttEast.set_sensitive(True)
+ self.buttWest.set_image(Constants.westImgClr)
+ self.buttWest.set_sensitive(True)
+ self.buttNorth.set_image(Constants.northImgClr)
+ self.buttNorth.set_sensitive(True)
+ self.buttSouth.set_image(Constants.southImgClr)
+ self.buttSouth.set_sensitive(True)
+ #enable the toolbar buttons
+ self.addToolbar.set_sensitive( True )
+ self.searchToolbar.set_sensitive( True )
+
+ def placeAddMedia( self, lat, lng ):
+ self.enableNavigation()
+ #append to the map
+ recd = self.m.addMedia( lat, lng, self.addMeToMapObj )
+ #now show the new addition to the map
+ self.preComet()
+ self.cometLogic.handlePostAdd( recd )
+ self.postComet()
+ # send image to others
+ #if(self.maptube is not None):
+ # self.maptube.SendText("mar," + lat + "," + lng + "," + utils.getStringFromPixbuf(recd.getPixBuf()) )
+
+ def sendEndKML(self):
+ self.maptube.SendText("endkml,now")
+
+ def sendStartKML(self):
+ self.maptube.SendText("startkml,now")
+
+ def _deleteMediaCb( self, ot ):
+ self.preComet()
+ self.cometLogic.handleDelete()
+ self.postComet()
+
+ def showMedia(self, id, x, y, up, rt):
+ recd = self.m.getMediaByThumbFilename(id)
+ if (recd == None):
+ return
+ self.shownRecd = recd
+ thumbPath = recd.getThumbPath()
+ thumbPixbuf = gtk.gdk.pixbuf_new_from_file(thumbPath)
+ px, py = [self.popW, self.popH]
+ scl = (self.popW+0.0) / (thumbPixbuf.get_width()+0.0)
+ thumbCairo = utils.generateThumbnail( thumbPixbuf, scl, px, py )
+ self.popUpBg.updatePopInfo( recd.colorStroke, recd.colorFill, thumbCairo, up, rt, self.popB, self.popB, self.htmlScale )
+ browserLoc = self.browseBox.translate_coordinates( self, 0, 0 )
+ x = int(x) * self.htmlScale
+ y = int(y) * self.htmlScale
+ x = browserLoc[0]+x
+ y = browserLoc[1]+y
+ if (not rt):
+ x = x - (self.popW + (2*self.popB))
+ if (not up):
+ y = y - (self.popH + (2*self.popB))
+ self.smartMove( self.popWindow, x, y )
+ kid = self.mediaWindow.get_child()
+ if (kid != None):
+ self.gplay.stop()
+ self.mediaWindow.remove( kid )
+ self.mediaWindow.modify_bg(gtk.STATE_NORMAL, recd.colorFill.gColor)
+ if (recd.type == Constants.TYPE_PHOTO):
+ self.mediaType = 'photo'
+ self.popWindow.hide()
+ self.mediaWindow.show()
+ self.smartResize( self.mediaWindow, self.popW, self.popH )
+ self.smartMove( self.mediaWindow, x+self.popB, y+self.popB)
+ pbuf = recd.getPixBuf()
+ img = _camera.cairo_surface_from_gdk_pixbuf(pbuf)
+ self.photoCanvas.modify_bg(gtk.STATE_NORMAL, recd.colorFill.gColor)
+ self.photoCanvas.set_size_request(self.popW, self.popH)
+ self.photoCanvas.setImage(img)
+ self.mediaWindow.add(self.photoCanvas)
+ self.photoCanvas.show_all()
+
+ elif (recd.type == Constants.TYPE_VIDEO):
+ self.mediaType = 'video'
+ self.popWindow.show()
+ self.mediaWindow.show()
+ self.smartResize( self.mediaWindow, self.popW, self.popH )
+ self.smartMove( self.mediaWindow, x+self.popB, y+self.popB)
+ self.smartMove( self.popWindow, x+self.popB, y+self.popB)
+ self.mediaWindow.add(self.gplayWin)
+ self.gplayWin.modify_bg(gtk.STATE_NORMAL, recd.colorFill.gColor)
+ self.popWindow.hide()
+ self.mediaWindow.show()
+ self.gplayWin.show_all()
+ videoUrl = "file://" + str( recd.getFilepath() )
+ self.gplay.setLocation( videoUrl )
+ self.gplay.play()
+
+ def hideMedia( self ):
+ self.shownRecd = None
+ self.moveWinOffscreen( self.popWindow )
+ self.moveWinOffscreen( self.mediaWindow )
+ self.gplay.pause()
+
+ def destroy(self, *args):
+ self.hide_all()
+ os._exit(0) #needed to kill all threads
+ gtk.main_quit()
+
+ def _shared_cb(self, activity):
+ self.initiating = True
+ self._sharing_setup()
+ id = self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].OfferDBusTube(SERVICE, {})
+
+ def _sharing_setup(self):
+ if self._shared_activity is None:
+ return
+ self.conn = self._shared_activity.telepathy_conn
+ self.tubes_chan = self._shared_activity.telepathy_tubes_chan
+ self.text_chan = self._shared_activity.telepathy_text_chan
+ self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].connect_to_signal('NewTube', self._new_tube_cb)
+
+ def _list_tubes_reply_cb(self, tubes):
+ for tube_info in tubes:
+ self._new_tube_cb(*tube_info)
+
+ # joining a pre-existing activity
+ def _joined_cb(self, activity):
+ if not self._shared_activity:
+ return
+ self.initiating = False
+ self._sharing_setup()
+ self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].ListTubes(reply_handler=self._list_tubes_reply_cb,error_handler=self.tubes_error)
+
+ # display error raised by XO-XO connection on map
+ def tubes_error(self,e):
+ self.preComet()
+ self.cometLogic.handleCompassUpdate("Error: %s",e)
+ self.postComet()
+
+ def _new_tube_cb(self, id, initiator, type, service, params, state):
+ if (type == telepathy.TUBE_TYPE_DBUS and service == SERVICE):
+ if state == telepathy.TUBE_STATE_LOCAL_PENDING:
+ self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].AcceptDBusTube(id)
+ tube_conn = TubeConnection(self.conn, self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES], id, group_iface=self.text_chan[telepathy.CHANNEL_INTERFACE_GROUP])
+ self.maptube = TextSync(tube_conn, self.initiating, self._received_cb, self.tubes_error, self._get_buddy)
+
+ # _get_buddy may not be necessary. Borrowed from HelloMesh
+ def _get_buddy(self, cs_handle):
+ group = self.text_chan[telepathy.CHANNEL_INTERFACE_GROUP]
+ my_csh = group.GetSelfHandle()
+ if my_csh == cs_handle:
+ handle = self.conn.GetSelfHandle()
+ elif group.GetGroupFlags() & telepathy.CHANNEL_GROUP_FLAG_CHANNEL_SPECIFIC_HANDLES:
+ handle = group.GetHandleOwners([cs_handle])[0]
+ else:
+ handle = cs_handle
+ return self.pservice.get_buddy_by_telepathy_handle(self.conn.service_name, self.conn.object_path, handle)
+
+class TextSync(ExportedGObject):
+ def __init__(self, tube, is_initiator, text_received_cb, alert, get_buddy):
+ super(TextSync, self).__init__(tube, PATH)
+ self.tube = tube
+ self.is_initiator = is_initiator
+ self.text_received_cb = text_received_cb
+ self._alert = alert
+ self.entered = False # Have we set up the tube?
+ self.text = '' # State that gets sent or received
+ self._get_buddy = get_buddy # Converts handle to Buddy object
+ self.tube.watch_participants(self.participant_change_cb)
+
+ def participant_change_cb(self, added, removed):
+ for handle, bus_name in added:
+ buddy = self._get_buddy(handle)
+ for handle in removed:
+ buddy = self._get_buddy(handle)
+ if not self.entered:
+ if self.is_initiator:
+ self.add_hello_handler()
+ else:
+ self.Hello()
+ self.entered = True
+
+ @signal(dbus_interface=IFACE, signature='')
+ def Hello(self):
+ self.bogus = 1
+
+ @method(dbus_interface=IFACE, in_signature='s', out_signature='')
+ def World(self, text):
+ if not self.text:
+ self.text = text
+ self.text_received_cb(text)
+ self.add_hello_handler()
+
+ def add_hello_handler(self):
+ self.tube.add_signal_receiver(self.hello_cb, 'Hello', IFACE,
+ path=PATH, sender_keyword='sender')
+ self.tube.add_signal_receiver(self.sendtext_cb, 'SendText', IFACE,
+ path=PATH, sender_keyword='sender')
+
+ def hello_cb(self, sender=None):
+ if sender == self.tube.get_unique_name():
+ return
+ self.tube.get_object(sender, PATH).World(self.text,
+ dbus_interface=IFACE)
+
+ def sendtext_cb(self, text, sender=None):
+ if sender == self.tube.get_unique_name():
+ return
+ self.text = text
+ self.text_received_cb(text)
+
+ @signal(dbus_interface=IFACE, signature='s')
+ def SendText(self, text):
+ self.text = text
+
+class SearchToolbar(gtk.Toolbar):
+
+ __gsignals__ = {
+ 'address-update': (gobject.SIGNAL_RUN_FIRST, None, [object]),
+ 'search': (gobject.SIGNAL_RUN_FIRST, None, [object]),
+ 'zoom-in': (gobject.SIGNAL_RUN_FIRST, None, []),
+ 'zoom-out': (gobject.SIGNAL_RUN_FIRST, None, []),
+ 'save-search': (gobject.SIGNAL_RUN_FIRST, None, []),
+ 'search-update': (gobject.SIGNAL_RUN_FIRST, None, [object])
+ }
+
+ def __init__(self, pc):
+ gtk.Toolbar.__init__(self)
+ self.ca = pc
+
+ addressLabel = gtk.Label( Constants.istrSearchAddress )
+ addressLabel.show()
+ toolAddressLabel = gtk.ToolItem()
+ toolAddressLabel.add(addressLabel)
+ self.insert(toolAddressLabel, -1)
+ toolAddressLabel.show()
+
+ self._insertSep()
+
+ self.addressField = gtk.Entry()
+ self.addressField.connect('activate', self._addressActivateCb)
+ addressItem = gtk.ToolItem()
+ addressItem.set_expand(True)
+ addressItem.add(self.addressField)
+ self.addressField.show()
+ self.insert( addressItem, -1 )
+ addressItem.show()
+
+ self._insertSep()
+ self._insertSep()
+ self._insertSep()
+ self._insertSep()
+
+ searchLabel = gtk.Label( Constants.istrSearchMedia )
+ searchLabel.show()
+ toolSearchLabel = gtk.ToolItem()
+ toolSearchLabel.add(searchLabel)
+ self.insert(toolSearchLabel, -1)
+ toolSearchLabel.show()
+
+ self._insertSep()
+
+ self.searchField = gtk.Entry()
+ self.searchField.connect('activate', self._searchActivateCb)
+ searchItem = gtk.ToolItem()
+ searchItem.set_expand(True)
+ searchItem.add(self.searchField)
+ self.searchField.show()
+ self.insert( searchItem, -1 )
+ searchItem.show()
+
+ self._insertSep()
+
+ saveButt = ToolButton("save-search")
+ saveButt.set_tooltip(Constants.istrSaveSearch)
+ saveButt.connect('clicked', self._saveCb)
+ self.insert(saveButt, -1)
+ saveButt.show()
+
+ self._insertSep()
+
+ zout = ToolButton('map-icon-zoomOut')
+ zout.set_tooltip(Constants.istrZoomOut)
+ self.insert( zout, -1 )
+ zout.connect('clicked', self._zoomOutCb)
+
+ zin = ToolButton('map-icon-zoomIn')
+ zin.set_tooltip(Constants.istrZoomIn)
+ self.insert( zin, -1 )
+ zin.connect('clicked', self._zoomInCb)
+
+ def _setTagsString( self, tags ):
+ self.searchField.set_text(tags)
+
+ def _insertSep( self ):
+ separator = gtk.SeparatorToolItem()
+ separator.set_draw(False)
+ separator.set_expand(False)
+ separator.set_size_request(Constants.ui_dim_INSET, -1)
+ self.insert( separator, -1 )
+
+
+ def _addressActivateCb(self, widget):
+ address = widget.props.text
+ self.emit('address-update', address)
+
+
+ def _saveCb(self, widget):
+ self.emit('save-search')
+
+
+ def _searchActivateCb(self, widget):
+ search = widget.props.text
+ self.emit('search-update', search)
+
+
+ def _zoomInCb(self, button):
+ self.emit('zoom-in')
+
+ def _zoomOutCb(self, button):
+ self.emit('zoom-out')
+
+class PopUpP5(P5):
+ def __init__(self):
+ P5.__init__(self)
+ self.fill = None
+ self.stroke = None
+ self.previewCairoImg = None
+ self.up = None
+ self.rt = None
+ self.scale = None
+ self.insetX = 0
+ self.insetY = 0
+
+ def updatePopInfo(self, stroke, fill, cairoThumb, up, rt, insetX, insetY, scale):
+ self.fill = fill
+ self.stroke = stroke
+ self.previewCairoImg = cairoThumb
+ self.up = up
+ self.rt = rt
+ self.scale = scale
+ self.insetX = insetX
+ self.insetY = insetY
+ self.queue_draw()
+
+
+ def draw(self, ctx, w, h):
+ #for stroking
+ self.fillRect( ctx, self.fill, w, h )
+
+ lw = 5
+ hlw = lw/2
+ ctx.set_line_width( lw*self.scale )
+ ctx.rectangle(0, 0, w, h)
+ self.setColor(ctx, self.stroke)
+ ctx.stroke()
+
+ #for the popup bubble's handle
+ if (not self.up):
+ ctx.translate(0, h-(3*self.scale))
+ if (not self.rt):
+ ctx.translate(w-((hlw+21)*self.scale), 0)
+ else:
+ ctx.translate(hlw*self.scale, 0)
+
+ ctx.rectangle(0, 0, 21*self.scale, 3*self.scale)
+ self.setColor(ctx, self.fill)
+ ctx.fill()
+
+ ctx.identity_matrix()
+ ctx.set_source_surface(self.previewCairoImg, self.insetX, self.insetY)
+ ctx.paint()
+
+
+class AddToolbar(gtk.Toolbar):
+ __gsignals__ = {
+ 'add-media': (gobject.SIGNAL_RUN_FIRST, None, [object]),
+ 'add-kml': (gobject.SIGNAL_RUN_FIRST, None, [object]),
+ 'web-media': (gobject.SIGNAL_RUN_FIRST, None, []),
+ 'delete-media': (gobject.SIGNAL_RUN_FIRST, None, []),
+ 'measure': (gobject.SIGNAL_RUN_FIRST, None, []),
+ 'olpcmap': (gobject.SIGNAL_RUN_FIRST, None, []),
+ 'panoramio':(gobject.SIGNAL_RUN_FIRST, None, []),
+ 'local-wiki':(gobject.SIGNAL_RUN_FIRST, None, []),
+ 'wikimapia':(gobject.SIGNAL_RUN_FIRST, None, []),
+ 'add-info': (gobject.SIGNAL_RUN_FIRST, None, [])
+ }
+
+ def __init__(self, pc):
+ gtk.Toolbar.__init__(self)
+ self.ca = pc
+
+ self.addButt = ToolButton('add-icon')
+ self.addButt.set_tooltip(Constants.istrAddMedia)
+ self.insert(self.addButt, -1)
+ self.addButt.connect('clicked', self._addCb)
+
+ infoButt = ToolButton('info-marker')
+ infoButt.set_tooltip(Constants.istrAddInfo)
+ self.insert(infoButt, -1)
+ infoButt.connect('clicked', self._addInfoCb)
+
+ delButt = ToolButton('delete-icon')
+ delButt.set_tooltip(Constants.istrDeleteMedia)
+ self.insert(delButt, -1)
+ delButt.connect('clicked', self._delCb)
+
+ self._insertSep()
+
+ # add line tools
+ lineButt = ToolButton('tool-shape-line')
+ lineButt.set_tooltip(Constants.LineButton)
+ self.insert(lineButt, -1)
+ lineButt.connect('clicked', self._lineCb)
+ polyButt = ToolButton('tool-polygon')
+ polyButt.set_tooltip(Constants.PolyButton)
+ self.insert(polyButt,-1)
+ polyButt.connect('clicked', self._polyCb)
+
+ self._insertSep()
+
+ measButt = ToolButton('measure-icon')
+ measButt.set_tooltip(Constants.istrMeasure)
+ self.insert(measButt, -1)
+ measButt.connect('clicked', self._measCb)
+
+ self._insertSep()
+
+ # Maps4xo library
+ webButt = ToolButton('web-icon')
+ webButt.set_tooltip(Constants.istrWebMedia)
+ self.insert(webButt, -1)
+ webButt.connect('clicked', self._webCb)
+
+ # OurMaps Wiki
+ staticButt = ToolButton('static-icon')
+ staticButt.set_tooltip(Constants.istrStaticMaps)
+ self.insert(staticButt, -1)
+ staticButt.connect('clicked', self._toStaticCb)
+
+ panorButt = ToolButton('panoramio')
+ panorButt.set_tooltip(Constants.istrPanoramio)
+ self.insert(panorButt,-1)
+ panorButt.connect('clicked', self._toPanoramioCb)
+
+ lwButt = ToolButton('localwiki')
+ lwButt.set_tooltip(Constants.istrLocalWiki)
+ self.insert(lwButt,-1)
+ lwButt.connect('clicked', self._toLocalWikiCb)
+
+ mapiaButt = ToolButton('wikimapia')
+ mapiaButt.set_tooltip(Constants.istrWikiMapia)
+ self.insert(mapiaButt,-1)
+ mapiaButt.connect('clicked', self._toWikiMapiaCb)
+
+ def _insertSep( self ):
+ separator = gtk.SeparatorToolItem()
+ separator.set_draw(False)
+ separator.set_expand(False)
+ separator.set_size_request(25 + Constants.ui_dim_INSET, -1)
+ self.insert( separator, -1 )
+
+ def _addCb(self, button):
+ self.ca.showFileLoadBlocker(True)
+
+ fp = FilePicker()
+ dOb = fp.show()
+ if (dOb != None):
+ if (dOb.file_path != None):
+ if(dOb.metadata['mime_type']=="video/ogg") or (dOb.metadata['mime_type']=="image/jpeg"):
+ self.emit("add-media", dOb)
+ elif(dOb.metadata['mime_type']=="audio/ogg"):
+ self.emit("add-media", dOb)
+ else:
+ self.emit("add-kml", dOb)
+ #else:
+ # self.emit("add-info")
+
+ self.ca.showFileLoadBlocker(False)
+
+ def _addInfoCb(self, button):
+ self.emit("add-info")
+
+ def _delCb(self, button):
+ self.emit("delete-media")
+
+ def _webCb(self, button):
+ self.ca.browser.load_uri("http://maptonomy.appspot.com/maps4xo?ajaxPort=" + str(self.ca.__class__.ajaxPort) + "&cometPort=" + str(self.ca.__class__.cometPort) + "&xo=true&lat=" + str(self.ca.NOW_MAP_CENTER_LAT) + "&lng=" + str(self.ca.NOW_MAP_CENTER_LNG) + "&z=" + str(self.ca.NOW_MAP_ZOOM) + "&" + Constants.istrLang )
+
+ def _measCb(self, button):
+ # start a measure tool (rect area or polyline) - calculation handled in HTML/JavaScript
+ self.emit("measure")
+
+ def _toStaticCb(self, button):
+ # Map wiki through maptonomy.appspot.com/ourmap.html
+ #self.ca.browser.load_uri("http://maptonomy.appspot.com/ourmap.html?ajaxPort=" + str(self.ca.__class__.ajaxPort) + "&cometPort=" + str(self.ca.__class__.cometPort) + "&xo=true&lat=" + str(self.ca.NOW_MAP_CENTER_LAT) + "&lng=" + str(self.ca.NOW_MAP_CENTER_LNG) + "&zoom=" + str(self.ca.NOW_MAP_ZOOM) + "&" + Constants.istrLang )
+ self.emit("olpcmap")
+ #self.ca.preComet()
+ #self.ca.cometLogic.handleOlpcMAP()
+ #self.ca.postComet()
+
+ def _toPanoramioCb(self, button):
+ self.emit("panoramio")
+
+ def _toLocalWikiCb(self, button):
+ self.emit("local-wiki")
+
+ def _toWikiMapiaCb(self, button):
+ self.emit("wikimapia")
+
+ def _lineCb(self, button):
+ self.ca.lineMode('line')
+
+ def _polyCb(self, button):
+ self.ca.lineMode('polygon')
+
+class ServerThread(threading.Thread):
+ def __init__(self, port, logic):
+ threading.Thread.__init__(self)
+ self.server = Server( ("127.0.0.1", port), logic)
+
+ def run(self):
+ try:
+ self.server.serve_forever()
+ except:
+ self.run()
+
+ def stop(self):
+ #self.server.shutdown()
+ r = 2
diff --git a/model.py b/model.py
new file mode 100644
index 0000000..c97f3fe
--- /dev/null
+++ b/model.py
@@ -0,0 +1,147 @@
+# Copyright (c) 2008, Media Modifications Ltd.
+
+#Permission is hereby granted, free of charge, to any person obtaining a copy
+#of this software and associated documentation files (the "Software"), to deal
+#in the Software without restriction, including without limitation the rights
+#to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+#copies of the Software, and to permit persons to whom the Software is
+#furnished to do so, subject to the following conditions:
+
+#The above copyright notice and this permission notice shall be included in
+#all copies or substantial portions of the Software.
+
+#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+#THE SOFTWARE.
+
+from constants import Constants
+from recorded import Recorded
+from color import Color
+from instance import Instance
+import utils
+from recorded import Recorded
+
+import gtk
+import os
+import shutil
+import StringIO
+
+class Model:
+ def __init__(self, ca):
+ self.ca = ca
+
+ self.recs = []
+ self.savedMaps = []
+ self.infoMarkers = {}
+ self.lineData = {}
+
+ def getMediaByThumbFilename(self, id):
+ for i in range(len(self.recs)):
+ if (self.recs[i].thumbFilename == id):
+ return self.recs[i]
+
+ return None
+
+
+ def getMediaByDatastoreId(self, id):
+ for i in range(len(self.recs)):
+ if (self.recs[i].datastoreId == id):
+ return self.recs[i]
+
+ return None
+
+
+ def addMedia(self, lat, lon, datastoreOb):
+ rec = Recorded()
+
+ #default photo
+ rec.type = Constants.TYPE_PHOTO
+ if((datastoreOb.metadata['mime_type'] == "video/ogg") or (datastoreOb.metadata['mime_type'] == "audio/ogg")):
+ rec.type = Constants.TYPE_VIDEO
+
+ rec.source = Recorded.SOURCE_DATASTORE
+ rec.datastoreOb = datastoreOb
+ rec.datastoreId = datastoreOb.object_id
+
+ rec.tags = ""
+ if (datastoreOb.metadata.has_key("tags")):
+ rec.tags = datastoreOb.metadata['tags']
+
+ rec.latitude = lat
+ rec.longitude = lon
+
+
+ colors = datastoreOb.metadata['icon-color']
+ colorStroke, colorFill = colors.split(",")
+ rec.colorStroke = Color()
+ rec.colorStroke.init_hex(colorStroke)
+ rec.colorFill = Color()
+ rec.colorFill.init_hex(colorFill)
+
+ thumbPixbuf = None
+ if (datastoreOb.metadata.has_key("preview")):
+ try:
+ thumb = datastoreOb.metadata['preview']
+ if thumb[1:4] == 'PNG':
+ pbl = gtk.gdk.PixbufLoader()
+ pbl.write(thumb)
+ pbl.close()
+ thumbPixbuf = pbl.get_pixbuf()
+ else:
+ thumbPixbuf = utils.getPixbufFromString(thumb)
+ except:
+ pass
+
+ if (thumbPixbuf == None):
+ #try to create the thumbnail yourself...
+ if (rec.type == Constants.TYPE_PHOTO):
+ try:
+ #load in the image, make a thumbnail
+ thumbPixbuf = gtk.gdk.pixbuf_new_from_file_at_size(rec.getFilepath(), 320, 240)
+ except:
+ pass
+
+ if (thumbPixbuf == None):
+ #i give up. load in a blank image from the activity itself.
+ thumbPath = os.path.join(self.ca.htmlPath, "1.jpg")
+ thumbPixbuf = gtk.gdk.pixbuf_new_from_file(thumbPath)
+
+
+ thumbFilepath = os.path.join(Instance.instancePath, "thumb.png")
+ thumbFilepath = utils.getUniqueFilepath(thumbFilepath, 0)
+ thumbPixbuf.save( thumbFilepath, "png", {} )
+ rec.thumbFilename = os.path.basename(thumbFilepath)
+
+ self.recs.append(rec)
+
+ return rec
+
+ def setInfo( self, lat, lng, info, icon ):
+ self.infoMarkers[lat+','+lng] = lat + ";~" + lng + ";~" + info + ";~" + icon
+
+ def setLine( self, id, color, thickness, pts ):
+ self.lineData[id] = id + ";~" + color + ";~" + thickness + ";~" + pts
+
+ def addSavedMap( self, smap ):
+ self.savedMaps.append(smap)
+
+ def getMediaResponse(self, s, w, n, e):
+ r = ""
+
+ for i in range( len(self.recs) ):
+ rec = self.recs[i]
+ r = r + "var m" + str(i) + " = new MediaMarker( new google.maps.LatLng(" + str(rec.latitude) + "," + str(rec.longitude) + "), '" + rec.getThumbUrl() + "', '" + rec.getThumbBasename() + "', null, null, 'null');"
+ r = r + "canvas.markerList.addMarker(m" + str(i) + ");"
+
+ for k, i in self.infoMarkers.iteritems():
+ iMarker = i.split(";~")
+ r = r + "addInfoMarker(" + iMarker[0] + "," + iMarker[1] + ",'" + iMarker[2] + "','" + iMarker[3] + "');"
+
+ for k, i in self.lineData.iteritems():
+ iLine = i.split(";~")
+ r = r + "addLine('" + iLine[0] + "','" + iLine[1] + "','" + iLine[2] + "','" + iLine[3] + "');"
+ return r
diff --git a/news b/news
new file mode 100644
index 0000000..8ebe0c3
--- /dev/null
+++ b/news
@@ -0,0 +1,5 @@
+1
+* init (jedierikb)
+
+2
+* 8.2 re-release( jedierikb) \ No newline at end of file
diff --git a/p5.py b/p5.py
new file mode 100644
index 0000000..8a92c15
--- /dev/null
+++ b/p5.py
@@ -0,0 +1,86 @@
+# Copyright (c) 2008, Media Modifications Ltd.
+
+#Permission is hereby granted, free of charge, to any person obtaining a copy
+#of this software and associated documentation files (the "Software"), to deal
+#in the Software without restriction, including without limitation the rights
+#to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+#copies of the Software, and to permit persons to whom the Software is
+#furnished to do so, subject to the following conditions:
+
+#The above copyright notice and this permission notice shall be included in
+#all copies or substantial portions of the Software.
+
+#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+#THE SOFTWARE.
+
+import gtk
+from gtk import gdk
+import gobject
+import cairo
+import math
+
+
+class P5(gtk.DrawingArea):
+ def __init__(self, button=False):
+ super(P5, self).__init__()
+ self.connect("expose_event", self.expose)
+ if (button):
+ self.add_events(gdk.BUTTON_PRESS_MASK | gdk.BUTTON_RELEASE_MASK | gdk.POINTER_MOTION_MASK)
+ self.connect("button_press_event", self._buttonPress)
+
+
+ def expose(self, widget, event):
+ ctx = widget.window.cairo_create()
+
+ # set a clip region for the expose event
+ ctx.rectangle(event.area.x, event.area.y, event.area.width, event.area.height)
+ ctx.clip()
+
+ rect = widget.allocation
+ self.draw( ctx, rect.width, rect.height )
+
+
+ def redraw_canvas(self):
+ #called from update
+ if self.window:
+ alloc = self.get_allocation()
+ self.queue_draw_area(0, 0, alloc.width, alloc.height)
+ self.window.process_updates(True)
+
+
+ def update(self):
+ #paint thread -- call redraw_canvas, which calls expose
+ self.redraw_canvas()
+
+
+ def fillRect( self, ctx, col, w, h ):
+ self.setColor( ctx, col )
+
+ ctx.line_to(0, 0)
+ ctx.line_to(w, 0)
+ ctx.line_to(w, h)
+ ctx.line_to(0, h)
+ ctx.close_path()
+
+ ctx.fill()
+
+
+ def setColor( self, ctx, col ):
+ if (not col._opaque):
+ ctx.set_source_rgba( col._r, col._g, col._b, col._a )
+ else:
+ ctx.set_source_rgb( col._r, col._g, col._b )
+
+
+ def _buttonPress(self, widget, event):
+ self.fireButton()
+
+
+ def fireButton( self ):
+ #for extending
+ pass \ No newline at end of file
diff --git a/photocanvas.py b/photocanvas.py
new file mode 100644
index 0000000..9346066
--- /dev/null
+++ b/photocanvas.py
@@ -0,0 +1,65 @@
+import cairo
+import gtk
+import gobject
+from gtk import gdk
+
+from p5 import P5
+from constants import Constants
+
+class PhotoCanvas(P5):
+
+ def __init__(self):
+ P5.__init__(self)
+ self.img = None
+ self.drawImg = None
+ self.SCALING_IMG_ID = 0
+ self.cacheWid = -1
+ self.modify_bg( gtk.STATE_NORMAL, Constants.colorBlack.gColor )
+ self.modify_bg( gtk.STATE_INSENSITIVE, Constants.colorBlack.gColor )
+
+
+ def draw(self, ctx, w, h):
+ self.fillRect( ctx, Constants.colorBlack, w, h )
+
+ if (self.img != None):
+
+ if (w == self.img.get_width()):
+ self.cacheWid == w
+ self.drawImg = self.img
+
+ #only scale images when you need to, otherwise you're wasting cycles, fool!
+ if (self.cacheWid != w):
+ if (self.SCALING_IMG_ID == 0):
+ self.drawImg = None
+ self.SCALING_IMG_ID = gobject.idle_add( self.resizeImage, w, h )
+
+ if (self.drawImg != None):
+ #center the image based on the image size, and w & h
+ ctx.set_source_surface(self.drawImg, (w/2)-(self.drawImg.get_width()/2), (h/2)-(self.drawImg.get_height()/2))
+ ctx.paint()
+
+ self.cacheWid = w
+
+
+ def setImage(self, img):
+ self.cacheWid = -1
+ self.img = img
+ self.drawImg = None
+ self.queue_draw()
+
+
+ def resizeImage(self, w, h):
+ self.SCALING_IMG_ID = 0
+ if (self.img == None):
+ return
+
+ #use image size in case 640 no more
+ scaleImg = cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h)
+ sCtx = cairo.Context(scaleImg)
+ sScl = (w+0.0)/(self.img.get_width()+0.0)
+ sCtx.scale( sScl, sScl )
+ sCtx.set_source_surface( self.img, 0, 0 )
+ sCtx.paint()
+ self.drawImg = scaleImg
+ self.cacheWid = w
+ self.queue_draw()
diff --git a/po/es.po b/po/es.po
new file mode 100644
index 0000000..f01d56c
--- /dev/null
+++ b/po/es.po
@@ -0,0 +1,99 @@
+#: activity/activity.info:2
+msgid "Map"
+msgstr "Mapa"
+
+#: constants.py:26
+msgid "Edit"
+msgstr "Editar"
+
+#: constants.py:27
+msgid "Search"
+msgstr "Buscar"
+
+#: constants.py:28
+msgid "Find:"
+msgstr "Busca:"
+
+#: constants.py:29
+msgid "Tags:"
+msgstr "Palabras:"
+
+#: constants.py:30
+msgid "Save Search"
+msgstr "Recordar Mapa"
+
+#: constants.py:31
+msgid "Connecting to Map Server"
+msgstr "Está Connectando"
+
+#: constants.py:32
+msgid "Zoom In"
+msgstr "Magnificar"
+
+#: constants.py:33
+msgid "Zoom Out"
+msgstr "Magnificar Menos"
+
+#: constants.py:34
+msgid "Save"
+msgstr "Recordar"
+
+#: constants.py:35
+msgid "Density"
+msgstr "Density"
+
+#: constants.py:36
+msgid "Saved Map"
+msgstr "Mapa recordado"
+
+#: constants.py:37
+msgid "Describe Map"
+msgstr "Escribe sobre esto"
+
+#: constants.py:38
+msgid "Remove Map"
+msgstr "Cancelación"
+
+#: constants.py:39
+msgid "Copy to Clipboard"
+msgstr "Copiar"
+
+#: constants.py:40
+msgid "Add Media"
+msgstr "Foto nuevo"
+
+#: constants.py:41
+msgid "Add Info"
+msgstr "Escribir"
+
+#: constants.py:42
+msgid "Delete"
+msgstr "Cancelar"
+
+#: constants.py:43
+msgid "Library"
+msgstr "Biblioteca"
+
+#: constants.py:44
+msgid "Measure"
+msgstr "Medición"
+
+#: constants.py:45
+msgid "OurMaps"
+msgstr "NuestrosMapas"
+
+#: constants.py:46
+msgid "Latitude:"
+msgstr "Latitud:"
+
+#: constants.py:47
+msgid "Longitude:"
+msgstr "Longitud:"
+
+#: constants.py:48
+msgid "Description:"
+msgstr "Descripción:"
+
+#: constants.py:49
+msgid "lang=en"
+msgstr "lang=es"
diff --git a/po/map.pot b/po/map.pot
new file mode 100644
index 0000000..8b191ef
--- /dev/null
+++ b/po/map.pot
@@ -0,0 +1,113 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2008-03-10 11:08-0400\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: activity/activity.info:2
+msgid "Map"
+msgstr ""
+
+#: constants.py:26
+msgid "Edit"
+msgstr ""
+
+#: constants.py:27
+msgid "Search"
+msgstr ""
+
+#: constants.py:28
+msgid "Find:"
+msgstr ""
+
+#: constants.py:29
+msgid "Tags:"
+msgstr ""
+
+#: constants.py:30
+msgid "Save Search"
+msgstr ""
+
+#: constants.py:31
+msgid "Connecting to Map Server"
+msgstr ""
+
+#: constants.py:32
+msgid "Zoom In"
+msgstr ""
+
+#: constants.py:33
+msgid "Zoom Out"
+msgstr ""
+
+#: constants.py:34
+msgid "Save"
+msgstr ""
+
+#: constants.py:35
+msgid "Density"
+msgstr ""
+
+#: constants.py:36
+msgid "Saved Map"
+msgstr ""
+
+#: constants.py:37
+msgid "Describe Map"
+msgstr ""
+
+#: constants.py:38
+msgid "Remove Map"
+msgstr ""
+
+#: constants.py:39
+msgid "Copy to Clipboard"
+msgstr ""
+
+#: constants.py:40
+msgid "Add Media"
+msgstr ""
+
+#: constants.py:41
+msgid "Add Info"
+msgstr ""
+
+#: constants.py:42
+msgid "Delete"
+msgstr ""
+
+#: constants.py:43
+msgid "Library"
+msgstr ""
+
+#: constants.py:44
+msgid "Measure"
+msgstr ""
+
+#: constants.py:45
+msgid "OurMaps"
+msgstr ""
+
+#: constants.py:46
+msgid "Latitude:"
+msgstr ""
+
+#: constants.py:47
+msgid "Longitude:"
+msgstr ""
+
+#: constants.py:48
+msgid "Description:"
+msgstr "" \ No newline at end of file
diff --git a/po/mn.po b/po/mn.po
new file mode 100644
index 0000000..433bdce
--- /dev/null
+++ b/po/mn.po
@@ -0,0 +1,99 @@
+#: activity/activity.info:2
+msgid "Map"
+msgstr "Газрын зураг"
+
+#: constants.py:26
+msgid "Edit"
+msgstr "хийх"
+
+#: constants.py:27
+msgid "Search"
+msgstr "хайлт"
+
+#: constants.py:28
+msgid "Find:"
+msgstr "олох:"
+
+#: constants.py:29
+msgid "Tags:"
+msgstr "--"
+
+#: constants.py:30
+msgid "Save Search"
+msgstr "хадгалах"
+
+#: constants.py:31
+msgid "Connecting to Map Server"
+msgstr "Connecting"
+
+#: constants.py:32
+msgid "Zoom In"
+msgstr "ойрхон"
+
+#: constants.py:33
+msgid "Zoom Out"
+msgstr "алс"
+
+#: constants.py:34
+msgid "Save"
+msgstr "хадгалах"
+
+#: constants.py:35
+msgid "Density"
+msgstr "Density"
+
+#: constants.py:36
+msgid "Saved Map"
+msgstr "газрын зураг"
+
+#: constants.py:37
+msgid "Describe Map"
+msgstr "тодорхойлох"
+
+#: constants.py:38
+msgid "Remove Map"
+msgstr "арилгах"
+
+#: constants.py:39
+msgid "Copy to Clipboard"
+msgstr "хувъ"
+
+#: constants.py:40
+msgid "Add Media"
+msgstr "фото нэмэх"
+
+#: constants.py:41
+msgid "Add Info"
+msgstr "бичих"
+
+#: constants.py:42
+msgid "Delete"
+msgstr "хадгалах"
+
+#: constants.py:43
+msgid "Library"
+msgstr "номын сан"
+
+#: constants.py:44
+msgid "Measure"
+msgstr "зай | орон зай"
+
+#: constants.py:45
+msgid "OurMaps"
+msgstr "хат газрын зураг"
+
+#: constants.py:46
+msgid "Latitude:"
+msgstr "широта:"
+
+#: constants.py:47
+msgid "Longitude:"
+msgstr "долгота:"
+
+#: constants.py:48
+msgid "Description:"
+msgstr "тодорхойлох:"
+
+#: constants.py:49
+msgid "lang=en"
+msgstr "lang=mn"
diff --git a/recorded.py b/recorded.py
new file mode 100644
index 0000000..2378f1d
--- /dev/null
+++ b/recorded.py
@@ -0,0 +1,82 @@
+# Copyright (c) 2008, Media Modifications Ltd.
+
+#Permission is hereby granted, free of charge, to any person obtaining a copy
+#of this software and associated documentation files (the "Software"), to deal
+#in the Software without restriction, including without limitation the rights
+#to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+#copies of the Software, and to permit persons to whom the Software is
+#furnished to do so, subject to the following conditions:
+
+#The above copyright notice and this permission notice shall be included in
+#all copies or substantial portions of the Software.
+
+#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+#THE SOFTWARE.
+
+import os
+import map
+import gtk
+
+from constants import Constants
+from instance import Instance
+
+class Recorded:
+ SOURCE_DATASTORE = 0
+ SOURCE_LOCAL = 1
+ SOURCE_BUNDLE = 2
+
+ def __init__(self):
+ self.name = None
+ self.recorded = None
+ self.colorStroke = None
+ self.colorFill = None
+ self.type = None
+
+ self.latitude = None
+ self.longitude = None
+
+ self.thumbFilename = None
+ self.fileName = None
+ self.datastoreOb = None
+ self.datastoreId = None
+ self.tags = ""
+
+ self.source = 0
+
+
+ def getFilepath(self):
+ if (self.source == self.__class__.SOURCE_BUNDLE):
+ path = os.path.join( Constants.htmlPath, self.fileName )
+ return path
+ elif (self.source == self.__class__.SOURCE_DATASTORE):
+ return self.datastoreOb.file_path
+ else:
+ return None
+
+
+ def getPixBuf(self):
+ pb = None
+
+ fp = self.getFilepath()
+ if (fp != None):
+ pb = gtk.gdk.pixbuf_new_from_file(fp)
+
+ return pb
+
+
+ def getThumbUrl(self):
+ return "http://127.0.0.1:" + str(map.Map.ajaxPort) + "/getImage.js?id="
+
+
+ def getThumbBasename(self):
+ return str(self.thumbFilename)
+
+
+ def getThumbPath(self):
+ thumbPath = os.path.join( Instance.instancePath, self.getThumbBasename() )
+ return thumbPath \ No newline at end of file
diff --git a/result.py b/result.py
new file mode 100644
index 0000000..a43b67a
--- /dev/null
+++ b/result.py
@@ -0,0 +1,25 @@
+# Copyright (c) 2008, Media Modifications Ltd.
+
+#Permission is hereby granted, free of charge, to any person obtaining a copy
+#of this software and associated documentation files (the "Software"), to deal
+#in the Software without restriction, including without limitation the rights
+#to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+#copies of the Software, and to permit persons to whom the Software is
+#furnished to do so, subject to the following conditions:
+
+#The above copyright notice and this permission notice shall be included in
+#all copies or substantial portions of the Software.
+
+#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+#THE SOFTWARE.
+
+
+class ServerResult:
+ def __init__(self):
+ self.txt = ""
+ self.headers = [] \ No newline at end of file
diff --git a/savedmap.py b/savedmap.py
new file mode 100644
index 0000000..ca890c0
--- /dev/null
+++ b/savedmap.py
@@ -0,0 +1,41 @@
+# Copyright (c) 2008, Media Modifications Ltd.
+
+#Permission is hereby granted, free of charge, to any person obtaining a copy
+#of this software and associated documentation files (the "Software"), to deal
+#in the Software without restriction, including without limitation the rights
+#to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+#copies of the Software, and to permit persons to whom the Software is
+#furnished to do so, subject to the following conditions:
+
+#The above copyright notice and this permission notice shall be included in
+#all copies or substantial portions of the Software.
+
+#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+#THE SOFTWARE.
+
+class SavedMap:
+
+ def __init__(self, lat, lng, zoom, imgFile, thumbFile, notes, tags):
+ self.lat = lat
+ self.lng = lng
+ self.zoom = zoom
+ self.imgPath = imgFile
+ self.thumbPath = thumbFile
+ self.notes = notes
+ self.tags = tags
+ self.density = " "
+
+ self.recdDatastoreId = None
+ self.recdLat = None
+ self.recdLng = None
+
+
+ def addViewedRecd(self, id, lat, lng):
+ self.recdDatastoreId = id
+ self.recdLat = lat
+ self.recdLng = lng
diff --git a/serialize.py b/serialize.py
new file mode 100644
index 0000000..4415f3a
--- /dev/null
+++ b/serialize.py
@@ -0,0 +1,203 @@
+import xml.dom.minidom
+from xml.dom.minidom import getDOMImplementation
+from xml.dom.minidom import parse
+import cStringIO
+import os
+import gtk
+
+from sugar.datastore import datastore
+
+from constants import Constants
+from instance import Instance
+import utils
+from recorded import Recorded
+import recorded
+from savedmap import SavedMap
+
+def fillMediaHash( index, m ):
+ doc = None
+ if (os.path.exists(index)):
+ try:
+ doc = parse( os.path.abspath(index) )
+ except:
+ doc = None
+ if (doc == None):
+ return
+
+ try:
+ lastLat = doc.documentElement.getAttributeNode(Constants.mapLat).nodeValue
+ lastLng = doc.documentElement.getAttributeNode(Constants.mapLng).nodeValue
+ lastZoom = doc.documentElement.getAttributeNode(Constants.mapZoom).nodeValue
+ m.ca.preComet()
+ m.ca.cometLogic.handleReceivedMap(lastLat,lastLng,lastZoom)
+ m.ca.postComet()
+ except:
+ # likely an old saved map
+ lastLat = 0
+
+ recdElements = doc.documentElement.getElementsByTagName(Constants.recdMapItem)
+ for el in recdElements:
+ _loadMediaIntoHash( el, m )
+
+ saveElements = doc.documentElement.getElementsByTagName(Constants.recdSavedMapItem)
+ for el in saveElements:
+ _loadSavedMap( el, m )
+
+ saveElements = doc.documentElement.getElementsByTagName(Constants.recdInfoMarker)
+ for el in saveElements:
+ _loadInfoMarker( el, m )
+
+ saveElements = doc.documentElement.getElementsByTagName(Constants.recdLine)
+ for el in saveElements:
+ _loadLine( el, m )
+
+def _loadSavedMap( el, m ):
+ latNode = el.getAttributeNode(Constants.recdLat)
+ lat = latNode.nodeValue
+ lngNode = el.getAttributeNode(Constants.recdLng)
+ lng = lngNode.nodeValue
+
+ zoomNode = el.getAttributeNode(Constants.recdZoom)
+ zoom = zoomNode.nodeValue
+ notesNode = el.getAttributeNode(Constants.recdNotes)
+ notes = notesNode.nodeValue
+ tagsNode = el.getAttributeNode(Constants.recdTags)
+ tags = tagsNode.nodeValue
+
+ m.ca.addSavedMap(lat,lng,zoom,notes,False)
+
+def _loadInfoMarker( el, m ):
+ latNode = el.getAttributeNode(Constants.recdLat)
+ lat = latNode.nodeValue
+ lngNode = el.getAttributeNode(Constants.recdLng)
+ lng = lngNode.nodeValue
+ infoNode = el.getAttributeNode(Constants.recdInfo)
+ info = infoNode.nodeValue
+ iconNode = el.getAttributeNode(Constants.recdIcon)
+ icon = iconNode.nodeValue
+ m.setInfo(lat,lng,info,icon)
+
+def _loadLine( el, m ):
+ idNode = el.getAttributeNode(Constants.lineID)
+ id = idNode.nodeValue
+ colorNode = el.getAttributeNode(Constants.lineColor)
+ color = colorNode.nodeValue
+ thickNode = el.getAttributeNode(Constants.lineThick)
+ thick = thickNode.nodeValue
+ ptsNode = el.getAttributeNode(Constants.linePts)
+ pts = ptsNode.nodeValue
+ m.setLine(id,color,thick,pts)
+
+def _loadMediaIntoHash( el, m ):
+ if (el.getAttributeNode(Constants.recdDatastoreId) == None):
+ return
+
+ datastoreNode = el.getAttributeNode(Constants.recdDatastoreId)
+ if (datastoreNode != None):
+ datastoreId = datastoreNode.nodeValue
+ if (datastoreId != None):
+ #quickly check: if you have a datastoreId that the file hasn't been deleted,
+ #cause if you do, we need to flag your removal
+ #2904 trac
+ datastoreOb = getMediaFromDatastore(datastoreId)
+ if (datastoreOb != None):
+
+ lat = 0
+ lng = 0
+
+ if (el.getAttributeNode(Constants.recdLat) != None):
+ latNode = el.getAttributeNode(Constants.recdLat)
+ lat = latNode.nodeValue
+ else:
+ return
+
+ if (el.getAttributeNode(Constants.recdLng) != None):
+ lngNode = el.getAttributeNode(Constants.recdLng)
+ lng = lngNode.nodeValue
+ else:
+ return
+
+ m.addMedia( lat, lng, datastoreOb )
+
+
+def getMediaFromDatastore( id ):
+ mediaObject = None
+ try:
+ mediaObject = datastore.get( id )
+ finally:
+ if (mediaObject == None):
+ return None
+
+ return mediaObject
+
+
+def fillRecdFromNode( recd, el ):
+ latNode = el.getAttributeNode(Constants.recdLat)
+ if (latNode != None):
+ recd.latitude = latNode.nodeValue
+ lngNode = el.getAttributeNode(Constants.recdLng)
+ if (lngNode != None):
+ recd.longitude = lngNode.nodeValue
+
+ return recd
+
+
+def _addRecdXmlAttrs( el, recd ):
+ el.setAttribute(Constants.recdDatastoreId, str(recd.datastoreId))
+ el.setAttribute(Constants.recdLat, str(recd.latitude))
+ el.setAttribute(Constants.recdLng, str(recd.longitude))
+
+def _addInfoXmlAttrs( el, recd ):
+ el.setAttribute(Constants.recdInfo, recd[2])
+ el.setAttribute(Constants.recdIcon, recd[3])
+ el.setAttribute(Constants.recdLat, str(recd[0]))
+ el.setAttribute(Constants.recdLng, str(recd[1]))
+
+def _addLineXmlAttrs( el, recd ):
+ el.setAttribute(Constants.lineID, recd[0])
+ el.setAttribute(Constants.lineColor, recd[1])
+ el.setAttribute(Constants.lineThick, recd[2])
+ el.setAttribute(Constants.linePts, recd[3])
+
+def _addSaveXmlAttrs( el, smap ):
+ el.setAttribute(Constants.recdLat, str(smap.lat))
+ el.setAttribute(Constants.recdLng, str(smap.lng))
+ el.setAttribute(Constants.recdZoom, str(smap.zoom))
+ el.setAttribute(Constants.recdNotes, str(smap.notes))
+ el.setAttribute(Constants.recdTags, smap.tags)
+ #el.setAttribute(Constants.recdDensity, str(smap.density))
+
+ if (smap.recdDatastoreId != None):
+ el.setAttribute(Constants.recdRecdId, smap.recdDatastoreId)
+ el.setAttribute(Constants.recdRecdLat, smap.recdLat)
+ el.setAttribute(Constants.recdRecdLng, smap.recdLng)
+
+
+def saveMediaHash( m ):
+ impl = getDOMImplementation()
+ album = impl.createDocument(None, Constants.recdAlbum, None)
+ root = album.documentElement
+
+ for i in range (0, len(m.recs)):
+ recd = m.recs[i]
+ mediaEl = album.createElement(Constants.recdMapItem)
+ root.appendChild( mediaEl )
+ _addRecdXmlAttrs( mediaEl, recd )
+
+ for k, iMarker in m.infoMarkers.iteritems():
+ mediaEl = album.createElement(Constants.recdInfoMarker)
+ root.appendChild( mediaEl )
+ _addInfoXmlAttrs( mediaEl, iMarker.split(";~") )
+
+ for k, iMarker in m.lineData.iteritems():
+ mediaEl = album.createElement(Constants.recdLine)
+ root.appendChild( mediaEl )
+ _addLineXmlAttrs( mediaEl, iMarker.split(";~") )
+
+ for i in range (0, len(m.savedMaps)):
+ smap = m.savedMaps[i]
+ saveEl = album.createElement(Constants.recdSavedMapItem)
+ root.appendChild( saveEl )
+ _addSaveXmlAttrs( saveEl, smap )
+
+ return album
diff --git a/server.py b/server.py
new file mode 100644
index 0000000..9a91ad4
--- /dev/null
+++ b/server.py
@@ -0,0 +1,69 @@
+# Copyright (c) 2008, Media Modifications Ltd.
+
+#Permission is hereby granted, free of charge, to any person obtaining a copy
+#of this software and associated documentation files (the "Software"), to deal
+#in the Software without restriction, including without limitation the rights
+#to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+#copies of the Software, and to permit persons to whom the Software is
+#furnished to do so, subject to the following conditions:
+
+#The above copyright notice and this permission notice shall be included in
+#all copies or substantial portions of the Software.
+
+#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+#THE SOFTWARE.
+
+
+import urlparse
+import urllib
+import posixpath
+import SimpleHTTPServer
+import BaseHTTPServer
+
+
+class Server(BaseHTTPServer.HTTPServer):
+ def __init__(self, server_address, logic):
+ BaseHTTPServer.HTTPServer.__init__(self, server_address, RegHandler)
+ self.logic = logic
+
+
+#RegHandler extends SimpleHTTPServer.py (in python 2.4)
+class RegHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
+ def do_POST( self ):
+ self.translate_path()
+
+
+ def do_GET( self ):
+ self.translate_path()
+
+
+ def do_HEAD( self ):
+ self.translate_path()
+
+
+ def translate_path(self):
+ #todo: compare with send_head in parent
+ urlp = urlparse.urlparse(self.path)
+
+ urls = urlp[2]
+ urls = posixpath.normpath(urllib.unquote(urls))
+ urlPath = urls.split('/')
+ urlPath = filter(None, urlPath)
+
+ params = urlp[4]
+ parama = []
+ allParams = params.split('&')
+ for i in range (0, len(allParams)):
+ parama.append(allParams[i].split('='))
+
+ result = self.server.logic.doServerLogic(self.path, urlPath, parama)
+ self.send_response(200)
+ for i in range (0, len(result.headers)):
+ self.send_header( result.headers[i][0], result.headers[i][1] )
+ self.end_headers()
+ self.wfile.write( result.txt ) \ No newline at end of file
diff --git a/setup.py b/setup.py
new file mode 100644
index 0000000..235a560
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,25 @@
+#!/bin/env python
+
+# Copyright (C) 2006, Red Hat, Inc.
+#
+# 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+
+from sugar.activity import bundlebuilder
+
+import os
+
+os.system("make")
+
+bundlebuilder.start("map") \ No newline at end of file
diff --git a/tray.py b/tray.py
new file mode 100644
index 0000000..d82e442
--- /dev/null
+++ b/tray.py
@@ -0,0 +1,207 @@
+# Copyright (C) 2007, One Laptop Per Child
+# Copyright (c) 2008, Media Modifications Ltd.
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+import gobject
+import gtk
+import hippo
+
+import sugar
+from sugar.graphics import style
+from sugar.graphics.palette import Palette, ToolInvoker
+from sugar.graphics.toolbutton import ToolButton
+from sugar.graphics.icon import Icon
+
+from constants import Constants
+
+_PREVIOUS_PAGE = 0
+_NEXT_PAGE = 1
+
+class _TrayViewport(gtk.Viewport):
+ __gproperties__ = {
+ 'can-scroll' : (bool, None, None, False,
+ gobject.PARAM_READABLE),
+ }
+
+ def __init__(self, orientation):
+ self.orientation = orientation
+ self._can_scroll = False
+
+ gobject.GObject.__init__(self)
+
+ self.set_shadow_type(gtk.SHADOW_NONE)
+
+ self.traybar = gtk.Toolbar()
+ self.traybar.set_orientation(orientation)
+ self.traybar.set_show_arrow(False)
+ self.add(self.traybar)
+ self.traybar.show()
+
+ self.connect('size_allocate', self._size_allocate_cb)
+
+ def scroll(self, direction):
+ if direction == _PREVIOUS_PAGE:
+ self._scroll_previous()
+ elif direction == _NEXT_PAGE:
+ self._scroll_next()
+
+ def _scroll_next(self):
+ if self.orientation == gtk.ORIENTATION_HORIZONTAL:
+ adj = self.get_hadjustment()
+ new_value = adj.value + self.allocation.width
+ adj.value = min(new_value, adj.upper - self.allocation.width)
+ else:
+ adj = self.get_vadjustment()
+ new_value = adj.value + self.allocation.height
+ adj.value = min(new_value, adj.upper - self.allocation.height)
+
+ def _scroll_to_end(self):
+ if self.orientation == gtk.ORIENTATION_HORIZONTAL:
+ adj = self.get_hadjustment()
+ adj.value = adj.upper# - self.allocation.width
+ else:
+ adj = self.get_vadjustment()
+ adj.value = adj.upper - self.allocation.height
+
+ def _scroll_previous(self):
+ if self.orientation == gtk.ORIENTATION_HORIZONTAL:
+ adj = self.get_hadjustment()
+ new_value = adj.value - self.allocation.width
+ adj.value = max(adj.lower, new_value)
+ else:
+ adj = self.get_vadjustment()
+ new_value = adj.value - self.allocation.height
+ adj.value = max(adj.lower, new_value)
+
+ def do_size_request(self, requisition):
+ child_requisition = self.child.size_request()
+ if self.orientation == gtk.ORIENTATION_HORIZONTAL:
+ requisition[0] = 0
+ requisition[1] = child_requisition[1]
+ else:
+ requisition[0] = child_requisition[0]
+ requisition[1] = 0
+
+ def do_get_property(self, pspec):
+ if pspec.name == 'can-scroll':
+ return self._can_scroll
+
+ def _size_allocate_cb(self, viewport, allocation):
+ bar_requisition = self.traybar.get_child_requisition()
+ if self.orientation == gtk.ORIENTATION_HORIZONTAL:
+ can_scroll = bar_requisition[0] > allocation.width
+ else:
+ can_scroll = bar_requisition[1] > allocation.height
+
+ if can_scroll != self._can_scroll:
+ self._can_scroll = can_scroll
+ self.notify('can-scroll')
+
+class _TrayScrollButton(gtk.Button):
+ def __init__(self, icon_name, scroll_direction):
+ gobject.GObject.__init__(self)
+
+ self._viewport = None
+
+ self._scroll_direction = scroll_direction
+
+ self.set_relief(gtk.RELIEF_NONE)
+ self.set_size_request(style.GRID_CELL_SIZE, style.GRID_CELL_SIZE)
+
+ icon = Icon(icon_name = icon_name,
+ icon_size=gtk.ICON_SIZE_SMALL_TOOLBAR)
+ self.set_image(icon)
+ icon.show()
+
+ self.connect('clicked', self._clicked_cb)
+
+ def set_viewport(self, viewport):
+ self._viewport = viewport
+ self._viewport.connect('notify::can-scroll',
+ self._viewport_can_scroll_changed_cb)
+
+ def _viewport_can_scroll_changed_cb(self, viewport, pspec):
+ #self.props.visible = self._viewport.props.can_scroll
+ self.set_sensitive(self._viewport.props.can_scroll)
+
+ def _clicked_cb(self, button):
+ self._viewport.scroll(self._scroll_direction)
+
+ viewport = property(fset=set_viewport)
+
+class HTray(gtk.VBox):
+ def __init__(self, **kwargs):
+ gobject.GObject.__init__(self, **kwargs)
+
+ separator = hippo.Canvas()
+ box = hippo.CanvasBox(
+ border_color=Constants.colorWhite.get_int(),
+ background_color=Constants.colorWhite.get_int(),
+ box_height=1,
+ border_bottom=1)
+ separator.set_root(box)
+ self.pack_start(separator, False)
+
+ hbox = gtk.HBox()
+ self.pack_start(hbox)
+
+ self.scroll_left = _TrayScrollButton('go-left', _PREVIOUS_PAGE)
+ self.scroll_left_event = gtk.EventBox()
+ self.scroll_left_event.add(self.scroll_left)
+ self.scroll_left_event.set_size_request(55, -1)
+ hbox.pack_start(self.scroll_left_event, False)
+
+ self.viewport = _TrayViewport(gtk.ORIENTATION_HORIZONTAL)
+ hbox.pack_start(self.viewport)
+ self.viewport.show()
+
+ self.scroll_right = _TrayScrollButton('go-right', _NEXT_PAGE)
+ self.scroll_right_event = gtk.EventBox()
+ self.scroll_right_event.add(self.scroll_right)
+ self.scroll_right_event.set_size_request(55, -1)
+ hbox.pack_start(self.scroll_right_event, False)
+
+ self.scroll_left.set_focus_on_click(False)
+ self.scroll_left_event.modify_bg(gtk.STATE_NORMAL, sugar.graphics.style.COLOR_TOOLBAR_GREY.get_gdk_color())
+ self.scroll_left.modify_bg(gtk.STATE_ACTIVE, sugar.graphics.style.COLOR_BUTTON_GREY.get_gdk_color())
+
+ self.scroll_right.set_focus_on_click(False)
+ self.scroll_right_event.modify_bg(gtk.STATE_NORMAL, sugar.graphics.style.COLOR_TOOLBAR_GREY.get_gdk_color())
+ self.scroll_right.modify_bg(gtk.STATE_ACTIVE, sugar.graphics.style.COLOR_BUTTON_GREY.get_gdk_color())
+
+ self.scroll_left.viewport = self.viewport
+ self.scroll_right.viewport = self.viewport
+
+ self.connect_after("size-allocate", self._sizeAllocateCb)
+
+ def _sizeAllocateCb(self, widget, event ):
+ self.viewport.notify('can-scroll')
+
+ def get_children(self):
+ return self.viewport.traybar.get_children()
+
+ def add_item(self, item, index=-1):
+ self.viewport.traybar.insert(item, index)
+
+ def remove_item(self, item):
+ self.viewport.traybar.remove(item)
+
+ def get_item_index(self, item):
+ return self.viewport.traybar.get_item_index(item)
+
+ def scroll_to_end(self):
+ self.viewport._scroll_to_end() \ No newline at end of file
diff --git a/utils.py b/utils.py
new file mode 100644
index 0000000..5085d66
--- /dev/null
+++ b/utils.py
@@ -0,0 +1,110 @@
+import base64
+import rsvg
+import re
+import os
+import cairo
+import gc
+import gtk
+from hashlib import md5
+import time
+from time import strftime
+
+from sugar import util
+import _camera
+
+def getStringFromPixbuf(pixbuf):
+ data = [""]
+ pixbuf.save_to_callback(_saveDataToBufferCb, "png", {}, data)
+ return base64.b64encode(str(data[0]))
+
+
+def _saveDataToBufferCb(buf, data):
+ data[0] += buf
+ return True
+
+
+def getPixbufFromString(str):
+ pbl = gtk.gdk.PixbufLoader()
+ data = base64.b64decode( str )
+ pbl.write(data)
+ pbl.close()
+ return pbl.get_pixbuf()
+
+
+def loadSvg( data, stroke, fill ):
+ if ((stroke == None) or (fill == None)):
+ return rsvg.Handle( data=data )
+
+ entity = '<!ENTITY fill_color "%s">' % fill
+ data = re.sub('<!ENTITY fill_color .*>', entity, data)
+
+ entity = '<!ENTITY stroke_color "%s">' % stroke
+ data = re.sub('<!ENTITY stroke_color .*>', entity, data)
+
+ return rsvg.Handle( data=data )
+
+
+def getUniqueFilepath( path, i ):
+ pathOb = os.path.abspath( path )
+ newPath = os.path.join( os.path.dirname(pathOb), str( str(i) + os.path.basename(pathOb) ) )
+ if (os.path.exists(newPath)):
+ i = i + 1
+ return getUniqueFilepath( pathOb, i )
+ else:
+ return os.path.abspath( newPath )
+
+
+def md5File( filepath ):
+ md = md5()
+ f = file( filepath, 'rb' )
+ md.update( f.read() )
+ digest = md.hexdigest()
+ hash = util.printable_hash(digest)
+ return hash
+
+
+def generateThumbnail( pixbuf, scale, thumbw, thumbh ):
+ #need to generate thumbnail version here
+ thumbImg = cairo.ImageSurface(cairo.FORMAT_ARGB32, thumbw, thumbh)
+ tctx = cairo.Context(thumbImg)
+ img = _camera.cairo_surface_from_gdk_pixbuf(pixbuf)
+ tctx.scale(scale, scale)
+ tctx.set_source_surface(img, 0, 0)
+ tctx.paint()
+ gc.collect()
+ return thumbImg
+
+
+def scaleSvgToDim( handle, dim ):
+ #todo...
+ scale = 1.0
+
+ svgDim = handle.get_dimension_data()
+ if (svgDim[0] > dim[0]):
+ pass
+
+ return scale
+
+
+def getDateString( when ):
+ #todo: internationalize the date
+ return strftime( "%a, %b %d, %I:%M:%S %p", time.localtime(when) )
+
+
+def grayScalePixBuf2( pb, copy ):
+ arr = pb.get_pixels_array()
+ if (copy):
+ arr = arr.copy()
+ for row in arr:
+ for pxl in row:
+ y = 0.3*pxl[0][0]+0.59*pxl[1][0]+0.11*pxl[2][0]
+ pxl[0][0] = y
+ pxl[1][0] = y
+ pxl[2][0] = y
+ return gtk.gdk.pixbuf_new_from_array(arr, pb.get_colorspace(), pb.get_bits_per_sample())
+
+
+def grayScalePixBuf( pb, copy ):
+ pb2 = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, False, 8, pb.get_width(), pb.get_height())
+ pb.saturate_and_pixelate(pb2, 0, 0)
+ return pb2 \ No newline at end of file
diff --git a/webviewer.py b/webviewer.py
new file mode 100644
index 0000000..8ce8201
--- /dev/null
+++ b/webviewer.py
@@ -0,0 +1,148 @@
+# Copyright (C) 2006, Red Hat, Inc.
+# Copyright (C) 2007, One Laptop Per Child
+# Copyright (c) 2008, Media Modifications Ltd.
+#
+# 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 St, Fifth Floor, Boston, MA 02110-1301 USA
+
+from sugar import env
+
+import logging
+import gobject
+import gtk
+import os
+import hulahop
+hulahop.startup(os.path.join(env.get_profile_path(), 'gecko'))
+import xpcom
+from xpcom.nsError import *
+from xpcom import components
+from xpcom.components import interfaces
+from hulahop.webview import WebView
+
+#import sessionstore
+#from dnd import DragDropHooks
+
+class WebViewer(WebView):
+ def __init__(self):
+ WebView.__init__(self)
+
+ window_creator = WindowCreator(self)
+ cls = components.classes['@mozilla.org/embedcomp/window-watcher;1']
+ window_watcher = cls.getService(interfaces.nsIWindowWatcher)
+ window_watcher.setWindowCreator(window_creator)
+
+ self.connect('realize', self._realize_cb)
+
+ def _realize_cb(self, widget):
+ #drag_drop_hooks = DragDropHooks(self)
+
+ cls = components.classes['@mozilla.org/embedcomp/command-params;1']
+ cmd_params = cls.createInstance('nsICommandParams')
+ #cmd_params.setISupportsValue('addhook', drag_drop_hooks)
+
+ requestor = self.browser.queryInterface(interfaces.nsIInterfaceRequestor)
+ command_manager = requestor.getInterface(interfaces.nsICommandManager)
+ command_manager.doCommand('cmd_clipboardDragDropHook', cmd_params, self.dom_window)
+
+ def get_session(self):
+ return sessionstore.get_session(self)
+
+ def set_session(self, session_data):
+ return sessionstore.set_session(self, session_data)
+
+class WindowCreator:
+ _com_interfaces_ = interfaces.nsIWindowCreator
+
+ def __init__(self, browser):
+ self._popup_creators = []
+ self._browser = browser
+
+ def createChromeWindow(self, parent, chrome_flags):
+ logging.debug('createChromeWindow: %r %r' % (parent, chrome_flags))
+
+ popup_creator = _PopupCreator(self._browser.get_toplevel())
+ popup_creator.connect('popup-created', self._popup_created_cb)
+
+ self._popup_creators.append(popup_creator)
+
+ browser = popup_creator.get_embed()
+
+ if chrome_flags & interfaces.nsIWebBrowserChrome.CHROME_OPENAS_CHROME:
+ logging.debug('Creating chrome window.')
+ browser.is_chrome = True
+ item = browser.browser.queryInterface(interfaces.nsIDocShellTreeItem)
+ item.itemType = interfaces.nsIDocShellTreeItem.typeChromeWrapper
+ else:
+ logging.debug('Creating browser window.')
+ item = browser.browser.queryInterface(interfaces.nsIDocShellTreeItem)
+ item.itemType = interfaces.nsIDocShellTreeItem.typeContentWrapper
+
+ browser.realize()
+
+ return browser.browser.containerWindow
+
+ def _popup_created_cb(self, creator):
+ self._popup_creators.remove(creator)
+
+class _PopupCreator(gobject.GObject):
+ __gsignals__ = {
+ 'popup-created': (gobject.SIGNAL_RUN_FIRST,
+ gobject.TYPE_NONE, ([])),
+ }
+
+ def __init__(self, parent_window):
+ gobject.GObject.__init__(self)
+
+ logging.debug('Creating the popup widget')
+
+ self._parent_window = parent_window
+
+ self._dialog = gtk.Window()
+ self._dialog.set_resizable(True)
+
+ self._dialog.realize()
+ self._dialog.window.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DIALOG)
+
+ self._embed = Browser()
+ self._vis_sid = self._embed.connect('notify::visible', self._notify_visible_cb)
+ self._dialog.add(self._embed)
+
+ def _notify_visible_cb(self, embed, param):
+ self._embed.disconnect(self._vis_sid)
+
+ if self._embed.type == Browser.TYPE_POPUP or self._embed.is_chrome:
+ logging.debug('Show the popup')
+ self._embed.show()
+ self._dialog.set_transient_for(self._parent_window)
+ self._dialog.show()
+ else:
+ logging.debug('Open a new activity for the popup')
+ self._dialog.remove(self._embed)
+ self._dialog.destroy()
+ self._dialog = None
+
+ # FIXME We need a better way to handle this.
+ # It seem like a pretty special case though, I doubt
+ # other activities will need something similar.
+ from webactivity import WebActivity
+ from sugar.activity import activityfactory
+ from sugar.activity.activityhandle import ActivityHandle
+ handle = ActivityHandle(activityfactory.create_activity_id())
+ activity = WebActivity(handle, self._embed)
+ activity.show()
+
+ self.emit('popup-created')
+
+ def get_embed(self):
+ return self._embed \ No newline at end of file