Added first version of mapping utility
authorjaviplx <javiplx@gmail.com>
Fri, 14 May 2010 22:56:12 +0000 (22:56 +0000)
committerjaviplx <javiplx@gmail.com>
Fri, 14 May 2010 22:56:12 +0000 (22:56 +0000)
git-svn-id: file:///svnroot/wifihood/trunk/wifiscanner@3 c51dfc6a-5949-4919-9c8e-f207a149c383

setup.py
wifiview [new file with mode: 0755]
wifiview.desktop [new file with mode: 0644]

index c0c0423..0a7c3b7 100755 (executable)
--- a/setup.py
+++ b/setup.py
@@ -9,9 +9,9 @@ setup(name='wifihood',
       description='WifiHood scanner application',
       author='Javier Palacios',
       author_email='javiplx@gmail.com',
-      scripts=['wifiscanner'],
+      scripts=['wifiscanner', 'wifiview'],
       data_files = [
-                   ( 'share/applications/hildon' , [ 'wifiscanner.desktop'] )
+                   ( 'share/applications/hildon' , [ 'wifiscanner.desktop' , 'wifiview.desktop' ] )
                    ],
       packages=['wifimap']
       )
diff --git a/wifiview b/wifiview
new file mode 100755 (executable)
index 0000000..0b07de9
--- /dev/null
+++ b/wifiview
@@ -0,0 +1,265 @@
+#!/usr/bin/env python
+
+import gtk
+import gobject
+
+import urllib2
+import math
+
+import os
+
+class mapWidget(gtk.Image):
+
+  def __init__(self):
+
+    gtk.Image.__init__(self)
+
+    # Maximum width should be 800, but actually gets reduced
+    self.win_x , self.win_y = 800 , 480
+
+    p = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, True, 8, self.win_x, self.win_y)
+    self.set_from_pixbuf(p)
+
+    zoom = 11
+    #lat = 40.4400226381
+    #lon = -3.6880185362
+    lat = 40.40491 
+    lon = -3.6774
+    self.reftile_x , self.reftile_y = self.lon2tilex( lon , zoom ) , self.lat2tiley( lat , zoom )
+    # Half the size of a tile
+    self.refpix_x , self.refpix_y = 128 , 128
+    self.refpix_x , self.refpix_y = 0 , 0
+
+    self.composeMap()
+
+  def lon2tilex ( self , lon , zoom=11 ) :
+    return int( ( lon + 180 ) / 360 * 2 ** zoom )
+
+  def lat2tiley ( self , lat , zoom=11 ) :
+    lat = lat * math.pi / 180
+    return int( ( 1 - math.log( math.tan( lat ) + 1 / math.cos( lat ) ) / math.pi ) / 2 * 2 ** zoom )
+
+  def composeMap( self ) :
+    center_x , center_y = self.win_x / 2 , self.win_y / 2
+
+    # To get the central pixel in the window center, we must shift to the tile origin
+    center_x -= self.refpix_x
+    center_y -= self.refpix_y
+
+    # Ranges should be long enough as to fill the screen
+    # Maybe they should be decided based on self.win_x, self.win_y
+    for i in range(-3,4) :
+      for j in range(-3,4) :
+        file = self.tilename( i , j )
+        if file is None :
+          pixbuf = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, False, 8, 256, 256 )
+          pixbuf.fill( 0x00000000 )
+        else :
+          try :
+            pixbuf = gtk.gdk.pixbuf_new_from_file( file )
+          except gobject.GError , ex :
+            print "Corrupted file %s" % ( file )
+            os.unlink( file )
+            #file = self.tilename( self.reftile_x + i , self.reftile_y + j )
+            file = self.tilename( i , j )
+            try :
+              pixbuf = gtk.gdk.pixbuf_new_from_file( file )
+            except :
+              print "Total failure for tile for %s,%s" % ( self.reftile_x + i , self.reftile_y + j )
+              pixbuf = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, False, 8, 256, 256 )
+
+        dest_x = 256 * i + center_x
+        dest_y = 256 * j + center_y
+
+        init_x = 0
+        size_x = 256
+        if dest_x < 0 :
+           init_x = abs(dest_x)
+           size_x = 256 + dest_x
+           dest_x = 0
+        if dest_x + 256 > self.win_x :
+           size_x = self.win_x - dest_x
+
+        init_y = 0
+        size_y = 256
+        if dest_y < 0 :
+           init_y = abs(dest_y)
+           size_y = 256 + dest_y
+           dest_y = 0
+        if dest_y + 256 > self.win_y :
+           size_y = self.win_y - dest_y
+
+        if ( size_x > 0 and size_y > 0 ) and ( init_x < 256 and init_y < 256 ) :
+            pixbuf.copy_area( init_x, init_y, size_x, size_y, self.get_pixbuf(), dest_x , dest_y )
+        del(pixbuf)
+
+  def tilename ( self , x , y , zoom=11 ) :
+    file = self.tile2file( self.reftile_x + x , self.reftile_y + y , zoom )
+    try :
+      os.stat(file)
+    except :
+    #  if mapDownload :
+      if False :
+        try :
+          # useful members : response.code, response.headers
+          response = urllib2.urlopen( "http://tile.openstreetmap.org/%s/%s/%s.png" % ( zoom , x , y ) )
+          if response.geturl() == "http://tile.openstreetmap.org/11/0/0.png" :
+              return None
+          fd = open( file , 'w' )
+          fd.write( response.read() )
+          fd.close()
+        except :
+          return None
+      else :
+        return None
+    return file
+
+  def tile2file( self , tilex , tiley , zoom=11 ) :
+    basedir = "/home/user/MyDocs/.maps/OpenStreetMap I"
+    rootdir = "%s/%s" % ( basedir , zoom )
+    if not os.path.isdir( rootdir ) :
+      os.mkdir(rootdir)
+    rootsubdir = "%s/%s" % ( rootdir , tilex )
+    if not os.path.isdir( rootsubdir ) :
+      os.mkdir(rootsubdir)
+    return "%s/%s.png" % ( rootsubdir , tiley )
+
+  def Shift( self , dx , dy ) :
+    self.hide()
+
+    tile_x , tile_y = ( self.refpix_x - dx ) / 256 , ( self.refpix_y - dy ) / 256
+    self.reftile_x += tile_x
+    self.reftile_y += tile_y
+
+    self.refpix_x -= dx + 256 * tile_x
+    self.refpix_y -= dy + 256 * tile_y
+
+    self.composeMap()
+    self.show()
+
+  def Up( self ) :
+    self.hide()
+    self.reftile_y -= 1
+    self.composeMap()
+    self.show()
+
+  def Down( self ) :
+    self.hide()
+    self.reftile_y += 1
+    self.composeMap()
+    self.show()
+
+  def Right( self ) :
+    self.hide()
+    self.reftile_x += 1
+    self.composeMap()
+    self.show()
+
+  def Left( self ) :
+    self.hide()
+    self.reftile_x -= 1
+    self.composeMap()
+    self.show()
+
+class MapWindow:
+
+    def delete_event(self, widget, event, data=None):
+        # If you return FALSE in the "delete_event" signal handler,
+        # GTK will emit the "destroy" signal. Returning TRUE means
+        # you don't want the window to be destroyed.
+        # This is useful for popping up 'are you sure you want to quit?'
+        # type dialogs.
+        print "delete event occurred"
+
+        # Change FALSE to TRUE and the main window will not be destroyed
+        # with a "delete_event".
+        return False
+
+    def destroy(self, widget, data=None):
+        print "destroy signal occurred"
+        gtk.main_quit()
+
+    def press_event ( self, widget, event, *args ) :
+      # FIXME : Set only if far enough from borders
+      border_x = 40
+      border_y = 30
+      print "press  ",event.get_coords(),event.get_root_coords()
+      if event.x > border_x and event.y > border_y and event.x < ( self.size_x - border_x ) and event.y < ( self.size_y - border_y ) :
+        self.click_x = event.x
+        self.click_y = event.y
+
+    def release_event ( self, widget, event, *args ) :
+      min_shift = 50
+      print "unpress",event.get_coords(),event.get_root_coords()
+      if self.click_x is not None and self.click_y is not None :
+        delta_x = int( event.x - self.click_x )
+        delta_y = int( event.y - self.click_y )
+        shift = math.sqrt( delta_x * delta_x + delta_y * delta_y )
+        if shift > min_shift :
+          self.map.Shift(delta_x, delta_y)
+        #  if delta_x > 100 :
+        #    self.map.Left()
+        #  elif delta_x < -100 :
+        #    self.map.Right()
+        #  elif delta_y > 100 :
+        #    self.map.Up()
+        #  elif delta_y < -100 :
+        #    self.map.Down()
+      self.click_x , self.click_y = None , None
+
+    def screen_event ( self, widget, event, *args ) :
+      print "REDIOS",event
+      print "      ",widget
+      print "      ",args
+
+
+    def on_button_press ( self, widget, event, *args ) :
+      print "HOLA",event
+
+    def on_key_press ( self, widget, event, *args ) :
+      if event.keyval == gtk.keysyms.Up :
+          self.map.Up()
+      elif event.keyval == gtk.keysyms.Down :
+          self.map.Down()
+      elif event.keyval == gtk.keysyms.Right :
+          self.map.Right()
+      elif event.keyval == gtk.keysyms.Left :
+          self.map.Left()
+      else :
+          print "UNKNOWN",event.keyval
+
+    def __init__(self):
+
+        self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
+    
+        self.window.connect("delete_event", self.delete_event)
+        self.window.connect("destroy", self.destroy)
+
+        self.window.set_border_width(10)
+    
+        self.window.connect("key-press-event", self.on_key_press)
+        
+        # To get explicit GDK_BUTTON_PRESS instead of paired GDK_LEAVE_NOTIFY & GDK_ENTER_NOTIFY
+#        self.window.add_events(gtk.gdk.BUTTON_MOTION_MASK | gtk.gdk.BUTTON_PRESS_MASK | gtk.gdk.BUTTON_RELEASE_MASK | gtk.gdk.POINTER_MOTION_MASK)
+        self.window.set_events( gtk.gdk.BUTTON_PRESS_MASK | gtk.gdk.BUTTON_RELEASE_MASK )
+        #
+#        self.window.connect('motion_notify_event', self.screen_event)
+        self.window.connect('button_press_event', self.press_event)
+        self.window.connect('button_release_event', self.release_event)
+        #
+        self.map = mapWidget()
+        self.window.add( self.map )
+    
+        # and the window
+        self.window.show_all()
+
+        self.size_x , self.size_y = 800 , 480
+        self.click_x , self.click_y = None , None
+
+    def main(self):
+        gtk.main()
+
+if __name__ == "__main__":
+    map = MapWindow()
+    map.main()
+
diff --git a/wifiview.desktop b/wifiview.desktop
new file mode 100644 (file)
index 0000000..62d3250
--- /dev/null
@@ -0,0 +1,8 @@
+[Desktop Entry]
+Encoding=UTF-8
+Version=1.0
+Type=Application
+Name=WifiMap
+Exec=/usr/bin/mapview
+Icon=/usr/share/pixmaps/python.xpm
+Maemo-Display-Name=WifiMap