Changeset aab194c


Ignore:
Timestamp:
10/28/10 22:42:58 (4 years ago)
Author:
xkolman2 <xkolman2@…>
Branches:
master
Children:
deb7311
Parents:
20ea28b
git-author:
xkolman2 <xkolman2@…> (10/28/10 22:42:58)
git-committer:
xkolman2 <xkolman2@…> (10/28/10 22:42:58)
Message:

new & working listable menu implementation
reworked POI functionality
improved logging
pango for larger text areas
various improvements and fixes

git-svn-id: https://nlp.fi.muni.cz/svn/gps_navigace/trunk@210 0858a4d0-ffff-46e5-938e-62b5ecb34222

Location:
modules
Files:
4 added
12 edited

Legend:

Unmodified
Added
Removed
  • modules/mod_log.py

    r20ea28b raab194c  
    3939 
    4040  def handleMessage(self, message, type, args): 
    41     if message == "checkLoggingStatus": 
     41    if message == "checkLoggingStatus": # check if logging was enabled 
    4242      self.checkLoggingStatus() 
    4343 
     
    5757      except: 
    5858        print "debug log: creating log folder failed" 
    59  
    60     timeString = time.strftime("%Y%m%d#%H-%M-%S", time.gmtime()) 
    61     fileName = 'modrana_stdout_%s.log.txt' % timeString 
    62     return("" + logFolderPath + "/" + fileName) 
     59    units = self.m.get('units', None) 
     60    if units: 
     61      timeHashString = units.getTimeHashString() 
     62      fileName = 'modrana_stdout_%s.log.txt' % timeHashString 
     63      return("" + logFolderPath + "/" + fileName) 
    6364 
    6465  def checkLoggingStatus(self): 
  • modules/mod_menu.py

    r85efb4b raab194c  
    2020from base_module import ranaModule 
    2121import cairo 
     22import pango 
     23import pangocairo 
    2224import time 
    2325import math 
    2426import geo 
    25 from listable_menu import listable_menu 
    2627 
    2728def getModule(m,d): 
     
    167168    self.drawScalebar(cr, proj,x1,y1,w) 
    168169 
    169  
     170  def needRedraw(self): 
     171    """conveninece function for asking for redraw""" 
     172    self.set('needRedraw', True) 
     173 
     174  def showText(self,cr,text,x,y,widthLimit=None,fontsize=40): 
     175    pg = pangocairo.CairoContext(cr) 
     176    # create a layout for your drawing area 
     177    layout = pg.create_layout() 
     178    layout.set_markup(text) 
     179    layout.set_font_description(pango.FontDescription("Sans Serif %d" % fontsize)) 
     180    (lw,lh) = layout.get_size() 
     181    if lw == 0 or lh == 0: 
     182      return # no need to draw this + avoid a division by zero 
     183    if(widthLimit and lw > widthLimit): 
     184      scale = float(pango.SCALE) 
     185      factor = ((widthLimit/(lw/scale))) 
     186      factor = min(factor, 1.0) 
     187      cr.move_to(x,y) 
     188      cr.save() 
     189      cr.scale(factor,factor) 
     190      pg.show_layout(layout) 
     191      cr.restore() 
     192    else: 
     193      cr.move_to(x,y) 
     194      pg.show_layout(layout) 
     195 
     196## this ca be used when I can get it to behave like the old show_text based method 
     197#  def drawText(self,cr,text,x,y,w,h,border=0): 
     198#    """pango based text drawing method""" 
     199#    if(not text): 
     200#      return 
     201#    # Put a border around the area 
     202#    if(border != 0): 
     203#      x += w * border 
     204#      y += h * border 
     205#      w *= (1-2*border) 
     206#      h *= (1-2*border) 
     207#    pg = pangocairo.CairoContext(cr) 
     208#    # create a layout for your drawing area 
     209#    layout = pg.create_layout() 
     210#    layout.set_markup(text) 
     211#    layout.set_font_description(pango.FontDescription("Sans Serif 60")) 
     212#    (lw,lh) = layout.get_size() 
     213#    if lw == 0 or lh == 0: 
     214#      return # no need to draw this + avoid a division by zero 
     215#    scale = float(pango.SCALE) 
     216##    factor = min(((w)/(lw/scale)),((h)/(lh/scale))) 
     217#    factorW = (w)/(lw/scale) 
     218#    factorH = (h)/(lh/scale) 
     219##    factor = min(factor, 1.0) 
     220#    factor = min(factorW, factorH) 
     221#    cr.move_to(x,y) 
     222#    cr.save() 
     223#    cr.scale(factor,factor) 
     224#    ratio = max(lw / w, lh / h) 
     225#    cr.set_font_size(60 / ratio) 
     226#    pg.show_layout(layout) 
     227#    cr.restore() 
    170228 
    171229  def drawText(self,cr,text,x,y,w,h,border=0): 
     
    249307    (x1,y1,w,h) = self.get('viewport', None) 
    250308 
    251     list = self.lists.get(menuName, None) 
    252     if(list != None): 
    253       m = self.m.get(list, None) 
    254       if(m != None): 
    255         listHelper = listable_menu(cr,x1,y1,w,h, self.m.get('clickHandler', None), self.listOffset) 
    256         m.drawList(cr, menuName, listHelper) 
     309#    list = self.lists.get(menuName, None) 
     310#    if(list != None): 
     311#      m = self.m.get(list, None) 
     312#      if(m != None): 
     313#        listHelper = listable_menu(cr,x1,y1,w,h, self.m.get('clickHandler', None), self.listOffset) 
     314#        m.drawList(cr, menuName, listHelper) 
     315#      return 
     316 
     317    # Is it a list ? 
     318    if menuName in self.lists.keys(): # TODO: optimize this 
     319      print "drawing list: %s" % menuName 
     320      self.lists[menuName].draw(cr) # draw the list 
    257321      return 
    258322     
     
    266330      return 
    267331 
     332 
     333 
     334#    if(list != None): 
     335#      m = self.m.get(list, None) 
     336#      if(m != None): 
     337#        listHelper = listable_menu(cr,x1,y1,w,h, self.m.get('clickHandler', None), self.listOffset) 
     338#        m.drawList(cr, menuName, listHelper) 
     339#      return 
    268340 
    269341#    device = self.device 
     
    377449 
    378450 
    379   def addListableMenu(self, items, parrentAction, descFunction=None, drawFunction=None): 
    380     if descFunction == None: # use default description function 
    381       pass 
     451  def addListableMenu(self, name, items, parrentAction, descFunction=None, drawFunction=None): 
     452    newListableMenu = self.listableMenu(name, self, items, parrentAction, descFunction, drawFunction,4) 
     453    self.lists[name] = newListableMenu 
     454    return newListableMenu 
     455       
    382456 
    383457  class listableMenu: 
    384     def __init__(self, menus, items, parrentAction, descFunction=None, drawFunction=None, displayedItems=3): 
     458    """a listable menu object""" 
     459    def __init__(self, name, menus, items, parrentAction, descFunction=None, drawFunction=None, displayedItems=3): 
     460      """use custom item and description drawing functions, or use the default ones""" 
    385461      self.descFunction = descFunction 
    386462      if descFunction==None: 
     
    392468      self.displayedItems = displayedItems 
    393469      self.items = items 
    394       self.parrentAction = parrentMenu 
     470      self.parrentAction = parrentAction 
    395471      self.menus = menus 
    396  
    397  
     472      self.name = name 
    398473 
    399474    def describeListItem(self, item, index, maxIndex): 
     475      """default item description function 
     476         -> get the needed strings for the default item drawing function""" 
    400477      (mainText, secText, action) = item 
    401       indexString = "%d/%d" % (index,maxIndex) 
     478      indexString = "%d/%d" % (index+1,maxIndex) 
    402479      return(mainText, secText, indexString, action) 
    403480 
     
    406483      if descFunction==None: 
    407484        descFunction=self.describeListItem 
     485 
     486      # * get the data for this button 
     487      (mainText, secText, indexString, action) = descFunction(item, index, len(self.items)) 
    408488      # * draw the background 
    409       self.menus.drawButton(x,y,w,h,'','generic', action) 
     489      self.menus.drawButton(cr,x,y,w,h,'','generic', action) 
    410490 
    411491      # * draw the text 
    412       (mainText, secText, indexString) = descFunction(item, index, len(self.items)) 
    413  
    414492      border = 20 
    415493 
    416494      # 1st line: option name 
    417       self.menus.drawText(cr, title+":", x+border, y+border, w-2*border) 
    418  
     495      self.menus.drawText(cr, mainText, x+border, y+border, w-2*border,20) 
    419496      # 2nd line: current value 
    420       self.menus.drawText(cr, valueDescription, x + 0.15 * w, y + 0.6 * dy, w * 0.85 - border) 
    421  
     497      self.menus.drawText(cr, secText, x + 0.15 * w, y + 0.6 * h, w * 0.85 - border, 20) 
    422498      # in corner: row number 
    423       self.menus.drawText(cr, "%d/%d" % (index+1, numItems), x+0.85*w, y+3*border, w * 0.15 - border, 20) 
    424  
    425  
    426     def drawMenu(self, cr): 
    427       """draw a listable menu""" 
    428       (e1,e2,e3,e4,alloc) = self.menuModule.threePlusOneMenuCoords() 
     499      self.menus.drawText(cr, indexString, x+0.85*w, y+3*border, w * 0.15 - border, 20) 
     500 
     501    def draw(self, cr): 
     502      """draw the listable menu""" 
     503      (e1,e2,e3,e4,alloc) = self.menus.threePlusOneMenuCoords() 
    429504      (x1,y1) = e1 
    430505      (x2,y2) = e2 
     
    433508      (w,h,dx,dy) = alloc 
    434509 
     510      # controls 
    435511      # * parent menu 
    436       self.menuModule.drawButton(cr, x1, y1, dx, dy, "", "up", parrentAction) 
     512      self.menus.drawButton(cr, x1, y1, dx, dy, "", "up", self.parrentAction) 
    437513      # * scroll up 
    438       self.menuModule.drawButton(cr, x2, y2, dx, dy, "", "up_list", "options:up") 
     514      self.menus.drawButton(cr, x2, y2, dx, dy, "", "up_list", "ml:menu:listMenu:%s;up" % self.name) 
    439515      # * scroll down 
    440       self.menuModule.drawButton(cr, x3, y3, dx, dy, "", "down_list", "options:down") 
    441  
     516      self.menus.drawButton(cr, x3, y3, dx, dy, "", "down_list", "ml:menu:listMenu:%s;down" % self.name) 
    442517 
    443518      id = self.index 
    444       nrItems = self.displayedItems 
     519 
     520      # get the number of rows 
     521      globalCount = self.menus.get('listableMenuRows', None) # try to get the global one 
     522      if globalCount==None: 
     523        nrItems = self.displayedItems # use the default value 
     524      else: 
     525        nrItems = int(globalCount) # use the global one 
    445526      visibleItems = self.items[id:(id+nrItems)] 
    446527      if len(visibleItems): # there must be a nonzero amount of items to avoid a division by zero 
     
    449530        itemBoxH = h-y4 
    450531        itemW = itemBoxW 
    451         itemH = itemBoxH/len(visibleItems) 
     532#        itemH = itemBoxH/len(visibleItems) 
     533        itemH = itemBoxH/nrItems 
    452534        for item in visibleItems: 
    453535          self.drawFunction(cr,item,x4,y4,itemW,itemH,id) #draw the item 
     
    458540      if self.index>=1: 
    459541        self.index = self.index -1 
     542        self.menus.needRedraw() 
    460543    def scrollDown(self): 
    461544      if (self.index + 1) < len(self.items): 
    462545        self.index = self.index + 1 
     546        self.menus.needRedraw() 
    463547    def reset(self): 
    464548      self.index = 0 
    465        
    466  
    467  
    468  
    469549 
    470550 
     
    541621     
    542622  def setupPoiMenu(self): 
    543     self.clearMenu('poi', "set:menu:None") 
    544     for i in("Show map", "Go to", "Delete"): 
    545       self.addItem('poi', i, i, 'set:menu:showPOI') 
    546        
    547     self.addItem('poi', 'Route to', 'generic', "set:menu:showPOIRoute") 
    548     self.addItem('poi', 'route#clear', 'generic', "route:clear|set:menu:main") 
     623    self.clearMenu('poi', "set:menu:main") 
     624    self.addItem('poi', 'POI#list', 'generic', "showPOI:setupCategoryList|set:menu:POICategories") 
     625    self.addItem('poi', 'POI#add new', 'generic', "set:menu:POIAddFromWhere") 
     626    POISelectedAction1 = "showPOI:centerOnActivePOI" 
     627    self.addItem('poi', 'POI#go to', 'generic', "ml:showPOI:setupCategoryList:%s|set:menu:POICategories" % POISelectedAction1) 
     628    POISelectedAction2 = "showPOI:routeToActivePOI" 
     629    self.addItem('poi', 'POI#route to', 'generic', "ml:showPOI:setupCategoryList:%s|set:menu:POICategories" % POISelectedAction2) 
     630    self.addItem('poi', 'search#online', 'generic', "set:menu:searchWhere") 
     631 
     632    self.addPOIPOIAddFromWhereMenu() # chain the "add from where menu" 
     633 
     634  def addPOIPOIAddFromWhereMenu(self): 
     635    self.clearMenu('POIAddFromWhere', "set:menu:poi") 
     636    self.addItem('POIAddFromWhere', 'entry#manual', 'generic', "ms:showPOI:storePOI:manualEntry") 
     637    self.addItem('POIAddFromWhere', 'position#current', 'generic', "ms:showPOI:storePOI:currentPosition") 
     638 
     639 
    549640 
    550641  def setupEditBatchMenu(self): 
     
    623714#    self.addItem('data2', '5 km', 'generic', 'set:downloadSize:4|mapData:download|set:menu:editBatch') 
    624715    self.addItem('data2', '1 km', 'generic', 'set:downloadSize:1|set:menu:%s' % nextMenu) 
     716    self.addItem('data2', '2 km', 'generic', 'set:downloadSize:2|set:menu:%s' % nextMenu) 
    625717    self.addItem('data2', '5 km', 'generic', 'set:downloadSize:4|set:menu:%s' % nextMenu) 
    626718    self.addItem('data2', '10 km', 'generic', 'set:downloadSize:8|set:menu:%s' % nextMenu) 
     
    646738     self.addItem('route', 'Point to Point', 'generic', 'set:menu:None|route:selectTwoPoints') 
    647739     self.addItem('route', 'Here to Point#Point to Here', 'generic', 'set:menu:None|route:selectOnePoint') 
    648      self.addItem('route', 'Here to POI', 'generic', 'set:menu:showPOIRoute') 
     740     POISelectedAction2 = "showPOI:routeToActivePOI" 
     741     self.addItem('route', 'Here to POI', 'generic', "ml:showPOI:setupCategoryList:%s|set:menu:POICategories" % POISelectedAction2) 
    649742     self.addItem('route', 'to Address#Address', 'generic', 'set:menu:showAdressRoute') 
    650743     self.addItem('route', 'Clear', 'generic', 'route:clear|set:menu:None') 
     
    654747    self.clearMenu('main', "set:menu:None") 
    655748    #self.addItem('main', 'map', 'generic', 'set:menu:layers') 
    656     self.addItem('main', 'places', 'city', 'set:menu:placenames_categories') 
     749#    self.addItem('main', 'places', 'city', 'set:menu:placenames_categories') 
    657750#    self.addItem('main', 'waypoints', 'waypoints', 'set:menu:waypoints_categories') 
    658751    self.addItem('main', 'route', 'route', 'set:menu:route') 
     
    688781    border = 30 
    689782    spacing = 20 
    690     lines = text.split('|') 
     783    lines = text.split('\n') 
    691784    lineCount = len(lines) 
    692785    lineSpace = (h-2*spacing)/lineCount 
     
    741834    dy = h1 / rows 
    742835 
    743     if w1>h1: 
    744 #        buttons = "landscape" 
     836    if w1>h1: # landscape 
    745837      (elem1) = (x1, y1) 
    746838      (elem2) = (x1, y1+1*dy) 
     
    749841 
    750842 
    751     elif w1<=h1: 
    752 #        buttons = "portrait" 
     843    elif w1<=h1: # portrait 
    753844      (elem1) = (x1, y1) 
    754845      (elem2) = (x1+dx, y1) 
     
    821912        self.showText(cr, "%d/%d" % (index+1, numItems), x4+0.85*w, y + 0.42 * dy, w * 0.15 - border, 20) 
    822913 
    823   def drawThreePlusOneMenu(self, cr, menuName, parent, button1, button2, box): 
     914  def drawThreePlusOneMenu(self, cr, menuName, parentAction, button1, button2, box): 
    824915    """draw a three plus on menu""" 
    825916    (e1,e2,e3,e4,alloc) = self.threePlusOneMenuCoords() 
     
    835926 
    836927    # * draw "escape" button 
    837     self.drawButton(cr, x1, y1, dx, dy, "", "up", "%s:reset|set:menu:%s" % (menuName, parent)) 
     928    self.drawButton(cr, x1, y1, dx, dy, "", "up", "%s:reset|%s" % (menuName, parentAction)) 
    838929    # * draw the first button 
    839930    self.drawButton(cr, x2, y2, dx, dy, text1, icon1, action1) 
     
    886977 
    887978 
    888  
    889  
    890   def showText(self,cr,text,x,y,widthLimit=None,fontsize=40): 
     979  def showTextOld(self,cr,text,x,y,widthLimit=None,fontsize=40): 
     980    """DEPRECIATED shof text funtion""" 
    891981    if(text): 
    892982      cr.set_font_size(fontsize) 
     
    9671057    messageList = message.split('#') 
    9681058    message = messageList[0] 
    969     if (message == "rebootDataMenu"): 
     1059    if message=='listMenu': 
     1060      """manipulate a listable menu 
     1061         argument number one is name of the listable menu to manipulate""" 
     1062      listMenuName = args[0] 
     1063      print listMenuName 
     1064      if listMenuName in self.lists.keys(): # do we have this menu ? 
     1065        if args[1]=="up": 
     1066          self.lists[listMenuName].scrollUp() 
     1067        elif args[1]=="down": 
     1068          self.lists[listMenuName].scrollDown() 
     1069 
     1070    elif (message == "rebootDataMenu"): 
    9701071      self.setupDataMenu() # we are returning from the batch menu, data menu needs to be "rebooted" 
    9711072      self.set('editBatchMenuActive', False) 
  • modules/mod_messages.py

    r3890765 raab194c  
    5959 
    6060      elif(module == 'ml'): # short for message + list of strings 
    61         (module, key, semicolonSepList) = text.split(':', 3) 
     61        tokens = text.split(':', 2) 
     62        module = tokens[0] 
     63        key = tokens[1] 
     64        semicolonSepList = tokens[2] 
    6265        list = semicolonSepList.split(';') 
    6366        m = self.m.get(module, None) 
     
    6871 
    6972      elif(module == 'md'): # short for message + dictionary of string:string key:value pairs 
    70         (module, key, semicolonSepDict) = text.split(':', 3) 
     73        tokens = text.split(':', 3) 
     74        module = tokens[0] 
     75        mainKey = tokens[1] 
     76        semicolonSepDict = tokens[2] 
    7177        d = {} 
    7278        for keyValue in semicolonSepDict.split(';'): 
    73           (key, value) = keyValue.split('=',1) 
    74           d[key] = value 
     79          kvList = keyValue.split('=',1) 
     80          if len(kvList)>=2: 
     81            (key,value) = (kvList[0],kvList[1]) 
     82            d[key] = value 
    7583        m = self.m.get(module, None) 
    7684        if(m != None): 
    77           m.handleMessage(key,'md',d) 
     85          m.handleMessage(mainKey,'md',d) 
    7886        else: 
    7987          print "Message addressed to %s which isn't loaded" % module 
  • modules/mod_notification.py

    r4062e3b raab194c  
    3939  def handleMessage(self, message, type, args): 
    4040    """the first part is the message, that will be displayed, 
    41        there can also by some parameters, delimited by #""" 
    42     list = message.split('#') 
    43     # TODO: support setting timeout and position 
    44     timeout = self.timeout 
    45     self.position = 'middle' 
    46     self.notificationText = list[0] 
    47     self.draw = True # enable drawing of notifications 
    48     if len(list) == 2: 
    49       try: 
    50         timeout = int(list[1]) # override the default timeout 
    51       except: 
    52         print "notification: wrong timeout, using default 5 secconds" 
    53     self.expirationTimestamp = time.time() + timeout 
    54     self.set('needRedraw', True) # make sure the notification is displayed 
     41       there can also by some parameters, delimited by # 
     42       NEW: you can also use a message list for the notification 
     43            firts goes the message, then the timeout in secconds 
     44       """ 
     45 
     46    if type=='ml' and message=='m': 
     47      """advanced message list based notification""" 
     48      if args: 
     49        timeout = self.timeout 
     50        self.position = 'middle' 
     51        self.notificationText = args[0] 
     52        self.draw = True # enable drawing of notifications 
     53        if len(args) >= 2: 
     54          timeout=int(args[1]) 
     55          self.expirationTimestamp = time.time() + timeout 
     56           
     57        self.set('needRedraw', True) # make sure the notification is displayed 
     58    else: 
     59      list = message.split('#') 
     60      # TODO: support setting timeout and position 
     61      timeout = self.timeout 
     62      self.position = 'middle' 
     63      self.notificationText = list[0] 
     64      self.draw = True # enable drawing of notifications 
     65      if len(list) == 2: 
     66        try: 
     67          timeout = int(list[1]) # override the default timeout 
     68        except: 
     69          print "notification: wrong timeout, using default 5 secconds" 
     70      self.expirationTimestamp = time.time() + timeout 
     71      self.set('needRedraw', True) # make sure the notification is displayed 
    5572 
    5673 
     
    94111      self.draw = False # we are finished, disable drawing notifications 
    95112 
    96  
    97  
    98  
    99  
    100  
    101  
    102  
    103  
    104113if(__name__ == "__main__"): 
    105114  a = example({}, {}) 
  • modules/mod_options.py

    rfde6225 raab194c  
    105105                   "view", 
    106106                   "24h") 
     107 
     108    self.addOption("Listable menu rows", "listableMenuRows", 
     109                 [(2,"2 rows"), 
     110                  (3,"3 rows"), 
     111                  (4,"4 rows"), 
     112                  (5,"5 rows"), 
     113                  (6,"6 rows")], 
     114                   "view", 
     115                   4) 
    107116      
    108117    self.addBoolOption("Centre map", "centred", "view", True) 
     118 
     119 
     120 
    109121 
    110122    self.addOption("Network", "network", 
     
    218230       "Navigation", 
    219231       30) 
     232 
     233 
     234    # * POI 
     235    self.addOption("POI database", "POIDBFilename", 
     236      [("poi.db","shared with Mappero (EXPERIMENTAL)","storePOI:reconnectToDb"), 
     237       ("modrana_poi.db","modRana only (default)", "storePOI:reconnectToDb")], 
     238       "POI", 
     239       "modrana_poi.db") 
     240 
     241    """EportPOIDatabaseToCSV is just a dummy value, 
     242       we just need to send a dump message to storePOI""" 
     243    self.addOption("Export POI Database to CSV", "EportPOIDatabaseToCSV", 
     244      [("dump","click to export","storePOI:dumpToCSV"), 
     245       ("dump","click to export","storePOI:dumpToCSV")], 
     246       "POI", 
     247       "dump") 
     248 
    220249 
    221250 
  • modules/mod_route.py

    r4062e3b raab194c  
    180180      self.set('needRedraw', True) # show the new route 
    181181 
    182     elif(message == "route"): # simple route, from here to selected point 
    183       # disable the point selection guis 
    184       self.selectTwoPoints = False 
    185       self.selectOnePoint = False 
    186       toPos = self.get("selectedPos", None) 
    187       if(toPos): 
    188         toLat,toLon = [float(a) for a in toPos.split(",")] 
    189  
    190         fromPos = self.get("pos", None) 
    191         if(fromPos): 
    192           (fromLat, fromLon) = fromPos 
    193           print "Routing %f,%f to %f,%f" % (fromLat, fromLon, toLat, toLon) 
    194  
    195           # TODO: wait message (would it be needed when using internet routing ?) 
    196           self.doRoute(fromLat, fromLon, toLat, toLon) 
    197           self.set('needRedraw', True) # show the new route 
     182    elif(message == "route"): # find a route 
     183      if (type=='md'): # mesage-list based routing 
     184        if args: 
     185          type = args['type'] 
     186          if type=='ll2ll': 
     187            (fromLat,fromLon) = (float(args['fromLat']),float(args['fromLon'])) 
     188            (toLat,toLon) = (float(args['toLat']),float(args['toLon'])) 
     189            print "Routing %f,%f to %f,%f" % (fromLat, fromLon, toLat, toLon) 
     190            try: 
     191              self.doRoute(fromLat, fromLon, toLat, toLon) 
     192            except: 
     193              self.sendMessage('ml:notification:m:No route found;3') 
     194            self.set('needRedraw', True) # show the new route 
     195      else: # simple route, from here to selected point 
     196        # disable the point selection guis 
     197        self.selectTwoPoints = False 
     198        self.selectOnePoint = False 
     199        toPos = self.get("selectedPos", None) 
     200        if(toPos): 
     201          toLat,toLon = [float(a) for a in toPos.split(",")] 
     202 
     203          fromPos = self.get("pos", None) 
     204          if(fromPos): 
     205            (fromLat, fromLon) = fromPos 
     206            print "Routing %f,%f to %f,%f" % (fromLat, fromLon, toLat, toLon) 
     207 
     208            # TODO: wait message (would it be needed when using internet routing ?) 
     209            self.doRoute(fromLat, fromLon, toLat, toLon) 
     210            self.set('needRedraw', True) # show the new route 
    198211 
    199212    elif(message == 'storeRoute'): 
     
    265278          self.doRoute(pLat, pLon, dLat, dLon) 
    266279 
    267  
    268  
    269  
    270  
    271  
    272        
    273280 
    274281  def doRoute(self, fromLat, fromLon, toLat, toLon): 
     
    735742      # if called from the osd menu, go back to map at escape 
    736743      if menuName == 'currentRouteBackToMap': 
    737         parent = 'None' 
     744        parent = 'set:menu:None' 
    738745      else: 
    739         parent = 'route' 
     746        parent = 'set:menu:route' 
    740747 
    741748      if self.route == []: 
     
    757764        steps = len(dir['Directions']['Routes'][0]['Steps']) # number of steps 
    758765 
    759 #        for step in dir['Directions']['Routes'][0]['Steps']: 
    760 #          print step 
    761  
    762  
    763766        start = "" 
    764767        startAddress = self.start[2] 
    765768        (lat1,lon1) = (self.start[0],self.start[1]) 
    766769        for item in startAddress.split(','): 
    767           start += "|%s" % item 
    768     #    start += "|(%f,%f)" % (lat1,lon1) 
     770          start += "\n%s" % item 
     771    #    start += "\n(%f,%f)" % (lat1,lon1) 
    769772 
    770773        destination = "" 
     
    772775        (lat2,lon2) = (self.destination[0],self.destination[1]) 
    773776        for item in destinationAddress.split(','): 
    774           destination += "|%s" % item 
    775     #    destination += "|(%f,%f)" % (lat2,lon2) 
     777          destination += "\n%s" % item 
     778    #    destination += "\n(%f,%f)" % (lat2,lon2) 
    776779 
    777780        text = "%s" % start 
    778         text+= "|%s" % destination 
    779         text+= "||%s in about %s and %s steps" % (distance, duration, steps) 
    780         text+= "|(%f,%f)->(%f,%f)" % (lat1,lon1,lat2,lon2) 
     781        text+= "\n%s" % destination 
     782        text+= "\n\n%s in about %s and %s steps" % (distance, duration, steps) 
     783        text+= "\n(%f,%f)->(%f,%f)" % (lat1,lon1,lat2,lon2) 
    781784 
    782785        self.text = text 
     
    788791      if self.once: 
    789792        self.once = False 
    790  
    791 #        entry = self.m.get('textEntry', None) 
    792 #        entry.entryBox("Enter destination") 
    793793 
    794794      box = (text , "set:menu:currentRoute") 
     
    818818 
    819819 
    820 #      print self.get('textEntry', "") 
    821 #      print self.get('textEntryDone', "") 
    822 #      print self.expectTextEntry 
    823 #      print self.startAddress 
    824 #      print self.destinationAddress 
    825  
    826  
    827820      (e1,e2,e3,e4,alloc) = menus.threePlusOneMenuCoords() 
    828821      (x1,y1) = e1 
  • modules/mod_search.py

    r6483ffa raab194c  
    387387 
    388388    # * draw details from the search result 
    389     text = "%s (%s)" % (result['titleNoFormatting'],distanceString) 
     389    text = "\n%s (%s)" % (result['titleNoFormatting'],distanceString) 
    390390 
    391391    try: # the adress can be unknown 
    392 #      print result['addressLines'] 
    393392      for addressLine in result['addressLines']: 
    394         text += "|%s" % addressLine 
     393        text += "\n%s" % addressLine 
    395394    except: 
    396       text += "|%s" % "no adress found" 
     395      text += "\n%s" % "no adress found" 
    397396 
    398397    try: # it seems, that this entry is no guarantied 
     
    401400        if phoneNumber['type'] != "": 
    402401          type = " (%s)" % phoneNumber['type'] 
    403         text += "|%s%s" % (phoneNumber['number'], type) 
     402        text += "\n%s%s" % (phoneNumber['number'], type) 
    404403    except: 
    405       text += "|%s" % "no phone numbers found" 
    406  
    407     text += "|coordinates: %f, %f" % (lat,lon) 
     404      text += "\n%s" % "no phone numbers found" 
     405 
     406    text += "\ncoordinates: %f, %f" % (lat,lon) 
    408407 
    409408    menus.drawTextToSquare(cr, x4, y4, w4, h4, text) # display the text in the box 
     
    532531      m.clearMenu('searchResultTools', 'set:menu:searchResultsItem') 
    533532      m.addItem('searchResultTools', "results#clear", 'generic', 'search:clearSearch|set:menu:None') 
    534       m.addItem('searchResultTools', "add to POI", "generic", "search:reset|search:storePOI|set:menu:searchResults") 
     533      m.addItem('searchResultTools', "add to POI", "generic", "search:reset|search:storePOI") 
    535534    # TODO: add "find route to" 
    536535 
  • modules/mod_showPOI.py

    r4062e3b raab194c  
    1919#--------------------------------------------------------------------------- 
    2020from base_module import ranaModule 
     21import geo 
     22import math 
    2123 
    2224def getModule(m,d): 
     
    2830  def __init__(self, m, d): 
    2931    ranaModule.__init__(self, m, d) 
    30     self.scroll = 0 
     32    self.activePOI = None 
     33    self.listMenusDirty = False 
     34    self.drawActivePOI = False 
    3135     
    32    
     36 
    3337  def drawMenu(self, cr, menuName): 
    34     if menuName == 'showPOI' or menuName == 'showPOIDetail' or menuName == 'showPOIRoute': 
    35       store = self.m.get('storePOI', None) 
    36       if store == None: 
    37         print "showPOI: no POI storage module, quiting" 
    38         return 
    39       points = store.points 
    40  
    41       menus = self.m.get('menu', None) 
    42       if menus == None: 
    43         return 
    44       if menuName == 'showPOI': 
    45         parent = 'poi' 
    46         menus.drawListableMenuControls(cr, menuName, parent, menuName) 
    47         menus.drawListableMenuItems(cr, points, self.scroll, self.describeItem) 
    48       if menuName == 'showPOIDetail': 
    49         parent = 'showPOI' 
    50         button1 = ("map#show on", "generic", "set:menu:None") 
    51         button2 = ("tools", "tools", "set:menu:showPOIDetail") 
    52         activePOINr = int(self.get('activePOINr', 0)) 
    53         point = points[activePOINr] 
    54         text = point.description + "|coordinates: %f, %f" % (point.lat, point.lon) 
    55         box = (text , "set:menu:showPOIDetail") 
    56         menus.drawThreePlusOneMenu(cr, menuName, parent, button1, button2, box) 
    57       if menuName == 'showPOIRoute': 
    58         parent = 'poi' 
    59         scrollMenu = 'showPOI' 
    60         menus.drawListableMenuControls(cr, menuName, parent, scrollMenu) 
    61         menus.drawListableMenuItems(cr, points, self.scroll, self.describeItem4Routing) 
    62  
    63  
    64   def describeItem(self, index, category, list): 
    65     action = "set:activePOINr:%d|set:menu:showPOIDetail" % index 
    66 #    action += "|set:searchResultsItemNr:%d" % list[index][2] # here we use the ABSOLUTE index, not the relative one 
    67  
    68     name = "%s" % list[index].name 
    69  
    70 #    units = self.m.get('units', None) 
    71 #    distanceString = units.km2CurrentUnitString(list[index][0]) # use correct units 
    72  
    73     if list[index].category == 'gls': 
    74       description = "Google Local Search result" 
    75     else: 
    76       description = "" 
    77  
    78     return( 
    79       name, 
    80       description, 
    81       action) 
    82  
    83   def describeItem4Routing(self, index, category, list): 
    84     """override the default action""" 
    85     (name, description, action) = self.describeItem(index, category, list) 
    86  
    87     lat = list[index].lat 
    88     lon = list[index].lon 
    89     action = "set:selectedPos:%f,%f|route:route|set:menu:None" % (lat,lon) 
    90  
    91     return( 
    92       name, 
    93       description, 
    94       action) 
     38    """make the POI Object draw the menu :D""" 
     39    if menuName=='POIDetail': 
     40      self.activePOI.drawMenu(cr) 
     41    elif menuName=='POIDetailTools': 
     42      self.activePOI.drawToolsMenu(cr) 
    9543 
    9644  def drawMapOverlay(self, cr): 
    97     pass 
     45    if self.drawActivePOI: 
     46      proj = self.m.get('projection', None) 
     47      if proj and self.activePOI: 
     48        lat = self.activePOI.getLat() 
     49        lon = self.activePOI.getLon() 
     50        name = self.activePOI.getName() 
     51        distanceString = "" 
     52        pos = self.get('pos', None) 
     53        units = self.m.get('units', None) 
     54        if pos and units: 
     55          (lat1,lon1) = pos # current position coordinates 
     56          kiloMetricDistance = geo.distance(lat,lon,lat1,lon1) 
     57          unitString = units.km2CurrentUnitString(kiloMetricDistance, 0, True) 
     58          distanceString = " (%s)" % unitString 
     59 
     60 
     61        text = "" + name + distanceString 
     62         
     63        (x,y) = proj.ll2xy(lat, lon) 
     64        # draw the highlighting circle 
     65        cr.set_line_width(8) 
     66        cr.set_source_rgba(0.1, 0.6, 0.1, 0.55) # highlight circle color 
     67        cr.arc(x, y, 15, 0, 2.0 * math.pi) 
     68        cr.stroke() 
     69        cr.fill() 
     70 
     71        # draw the point 
     72        cr.set_source_rgb(0.0, 0.0, 0.0) 
     73        cr.set_line_width(10) 
     74        cr.arc(x, y, 3, 0, 2.0 * math.pi) 
     75        cr.stroke() 
     76        cr.set_source_rgb(0.0, 0.0, 1.0) 
     77        cr.set_line_width(8) 
     78        cr.arc(x, y, 2, 0, 2.0 * math.pi) 
     79        cr.stroke() 
     80 
     81        # draw a caption with transparent background 
     82        cr.set_font_size(25) 
     83        extents = cr.text_extents(text) # get the text extents 
     84        (w,h) = (extents[2], extents[3]) 
     85        border = 2 
     86        cr.set_line_width(2) 
     87        cr.set_source_rgba(0.1, 0.6, 0.1, 0.45) # trasparent blue 
     88        (rx,ry,rw,rh) = (x - border+12, y + border+h*0.2 + 6, w + 4*border, -(h*1.4)) 
     89        cr.rectangle(rx,ry,rw,rh) # create the transparent background rectangle 
     90        cr.fill() 
     91 
     92        # register clickable area 
     93        click = self.m.get('clickHandler', None) 
     94        if click: 
     95          """ make the POI caption clickable""" 
     96          click.registerXYWH(rx,ry-(-rh),rw,-rh, "set:menu:POIDetail") 
     97        cr.fill() 
     98 
     99        # draw the actual text 
     100#        cr.set_source_rgba(1, 1, 0, 0.95) # slightly trasparent white 
     101        cr.set_source_rgba(1, 1, 1, 0.95) # slightly trasparent white 
     102        cr.move_to(x+15,y+7) 
     103        cr.show_text(text) # show the trasparent result caption 
     104        cr.stroke() 
    98105 
    99106  def handleMessage(self, message, type, args): 
    100     if(message == "up"): 
    101       if(self.scroll > 0): 
    102         self.scroll -= 1 
    103         self.set('needRedraw', True) 
    104     if(message == "down"): 
    105       print "down" 
    106       self.scroll += 1 
    107       self.set('needRedraw', True) 
    108     if(message == "reset"): 
    109       self.scroll = 0 
    110       self.set("needRedraw", True) 
    111  
    112  
    113  
    114  
     107    # messages that need the store and/or menus go here 
     108    store = self.m.get('storePOI', None) 
     109    menus = self.m.get('menu', None) 
     110    if store and menus: 
     111      if(message == "setupCategoryList"): 
     112        if type=='ml': 
     113          """this is used for executing something special instead of going to the POIDetail menu 
     114             after a POI is selected""" 
     115          POISelectedAction = args[0] 
     116          action = "ml:showPOI:setupPOIList:%s;%s|set:menu:POIList" % ("%d",POISelectedAction) 
     117        else: 
     118          action = "ms:showPOI:setupPOIList:%d|set:menu:POIList" 
     119        usedCategories = store.getUsedCategories() 
     120        # convert cat_id to actions 
     121        i = 0 
     122        for item in usedCategories: 
     123          (label,desc,cat_id) = item 
     124          buttonAction = action % cat_id 
     125          usedCategories[i] = (label,desc,buttonAction) 
     126          i = i + 1 
     127        menus.addListableMenu('POICategories', usedCategories,"set:menu:poi") 
     128      elif message=='setupPOIList': 
     129        if args: 
     130          if type=='ms': 
     131            catId = int(args) 
     132            action = 'set:menu:POIDetail' # use the default action 
     133          elif type=='ml': 
     134            """if the message is a message list, execute a custom action instead of the default POI detail menu 
     135               TODO: use this even for selecting the POIDetail menu ?""" 
     136            print args 
     137            catId=int(args[0]) 
     138            action = args[1] 
     139          poiFromCategory = store.getAllPOIFromCategory(catId) 
     140          # convert the output to a listable menu comaptible state 
     141          i = 0 
     142          for item in poiFromCategory: 
     143            (label,lat,lon,poi_id) = item 
     144            subText = "lat: %f, lon: %f" % (lat,lon) 
     145            buttonAction = "ms:showPOI:setActivePOI:%d|%s" % (poi_id,action) 
     146            poiFromCategory[i] = (label,subText,buttonAction) 
     147            i = i + 1 
     148          menus.addListableMenu("POIList",poiFromCategory, 'set:menu:POICategories') 
     149      elif type=='ms' and message=='setActivePOI': 
     150        if args: 
     151          POIId = int(args) 
     152          self.activePOI = store.getPOI(POIId) 
     153      elif type=='ms' and message=='storePOI': 
     154        if args == "manualEntry": 
     155          """add all POI info manually""" 
     156          entry = self.m.get('textEntry', None) 
     157          if entry: 
     158            self.activePOI = store.getEmptyPOI() # set a blank POI as active 
     159            # start the chain of entry boxes 
     160            entry.entryBox(self,'newName','POI name',"") 
     161        elif args == "currentPosition": 
     162          """add current position as a new POI""" 
     163          entry = self.m.get('textEntry', None) 
     164          if entry: 
     165            pos = self.get('pos', None) 
     166            if pos: 
     167              self.activePOI = store.getEmptyPOI() # set a blank POI as active 
     168              (lat,lon) = pos 
     169              self.activePOI.setLat(lat, commit=False) 
     170              self.activePOI.setLon(lon, commit=False) 
     171              # start the entry box chain 
     172              entry.entryBox(self,'newCurrentPositionName','POI name',"") 
     173 
     174      elif type=='ms' and message=='editActivePOI': 
     175        entry = self.m.get('textEntry', None) 
     176        if args: 
     177          if entry: 
     178            if args=='name': 
     179              name = self.activePOI.getName() 
     180              entry.entryBox(self,'name','POI name',name) 
     181            if args=='description': 
     182              description = self.activePOI.getDescription() 
     183              entry.entryBox(self,'description','POI Description',description) 
     184            if args=='lat': 
     185              lat = str(self.activePOI.getLat()) 
     186              entry.entryBox(self,'lat','POI Latitude',lat) 
     187            if args=='lon': 
     188              lon = str(self.activePOI.getLon()) 
     189              entry.entryBox(self,'lon','POI Longitude',lon) 
     190 
     191      elif type=='ml' and message=='setupPOICategoryChooser': 
     192        """setup a category chooser menu""" 
     193        if args: 
     194          (menu,key) = args 
     195          cats = store.getCategories() 
     196          i = 0 
     197          for cat in cats: 
     198            (label,desc,cat_id) = cat 
     199            action = "ms:%s:%s:%d" % (menu,key,cat_id) 
     200            cats[i] = (label,desc,action) 
     201            i = i + 1 
     202          menus.addListableMenu('POICategoryChooser', cats,"set:menu:poi") 
     203 
     204      elif type=='ms' and message=='setCatAndCommit': 
     205        """selecting the category is the final stage of adding a POI""" 
     206        if args: 
     207          # set the category 
     208          catId = int(args) 
     209          self.activePOI.setCategory(catId, commit=False) 
     210          # comit the new POI to db 
     211          self.activePOI.storeToDb() 
     212          # mark list menus for regeneration 
     213          self.listMenusDirty = True 
     214          # go to the new POI menu 
     215          self.set('menu', 'POIDetail') 
     216 
     217      elif message=='checkMenus': 
     218        """check if the POI menus are "dirty" and need to be regenerated""" 
     219        if self.listMenusDirty: 
     220          self.sendMessage('showPOI:setupCategoryList') 
     221          if self.activePOI: 
     222            catId = self.activePOI.getCatId() 
     223            self.sendMessage('ms:showPOI:setupPOIList:%d' % catId) 
     224          self.listMenusDirty = False 
     225 
     226      elif message == 'listMenusDirty': 
     227        """something regarding the POI changed 
     228           ,the menus might not be up to date 
     229           and may need a regen""" 
     230        self.listMenusDirty = True 
     231 
     232 
     233      elif message == 'askDeleteActivePOI': 
     234        ask = self.m.get('askMenu', None) 
     235        if ask: 
     236          id = self.activePOI.getId() 
     237          name = self.activePOI.getName() 
     238          question = "Do you really want to delete:\n%s\nfrom the POI database ?" % name 
     239          yesAction = "ms:storePOI:deletePOI:%d|set:menu:poi" % id 
     240          noAction = "set:menu:POIDetailTools" 
     241          ask.setupAskYesNo(question, yesAction, noAction) 
     242 
     243      elif message == 'centerOnActivePOI': 
     244        """something regarding the POI changed 
     245           ,the menus might not be up to date 
     246           and may need a regen""" 
     247        self.activePOI.showOnMap() 
     248 
     249      elif message == 'routeToActivePOI': 
     250        """something regarding the POI changed 
     251           ,the menus might not be up to date 
     252           and may need a regen""" 
     253        self.activePOI.routeFrom('currentPosition') 
     254        self.activePOI.showOnMap() 
     255 
     256      elif message == 'drawActivePOI': 
     257        print "DRAW" 
     258        self.drawActivePOI = True 
     259 
     260      elif message == 'dontDrawActivePOI': 
     261        self.drawActivePOI = False 
     262 
     263 
     264  def handleTextEntryResult(self, key, result): 
     265    # TODO: add input checking 
     266    entry = self.m.get('textEntry', None) 
     267    if key=='name': 
     268      self.activePOI.setName(result) 
     269    elif key=='description': 
     270      self.activePOI.setDescription(result) 
     271    elif key=='lat': 
     272      self.activePOI.setLat(float(result)) 
     273    elif key=='lon': 
     274      self.activePOI.setLon(float(result)) 
     275 
     276    # new  poi will be coomited at once, so we disable the autocommit 
     277    # also, the events are chained, so one netry box follows the other 
     278    elif key=='newName': 
     279      self.activePOI.setName(result,commit=False) 
     280      entry.entryBox(self,'newDescription','POI Description',"") 
     281    elif key=='newDescription': 
     282      self.activePOI.setDescription(result,commit=False) 
     283      entry.entryBox(self,'newLat','POI Latitude',"") 
     284    elif key=='newLat': 
     285      self.activePOI.setLat(result,commit=False) 
     286      entry.entryBox(self,'newLon','POI Longitude',"") 
     287    elif key=='newLon': 
     288      self.activePOI.setLon(result,commit=False) 
     289      """final step: 
     290      setup the category chooser menu, 
     291      and make sure the POI is commited after a cetegory is chosen 
     292      """ 
     293      self.sendMessage('ml:notification:Select a category for this POI:2') 
     294      self.sendMessage('ml:showPOI:setupPOICategoryChooser:showPOI;setCatAndCommit') 
     295      self.set('menu', 'POICategoryChooser') 
     296 
     297    # "current position as a new POI" entry chain 
     298    elif key=='newCurrentPositionName': 
     299      self.activePOI.setName(result,commit=False) 
     300      entry.entryBox(self,'newCurrentPositionDescription','POI Description',"") 
     301    elif key=='newCurrentPositionDescription': 
     302      self.activePOI.setDescription(result,commit=False) 
     303      # setting the category is the last step 
     304      self.sendMessage('ml:notification:Select a category for this POI:2') 
     305      self.sendMessage('ml:showPOI:setupPOICategoryChooser:showPOI;setCatAndCommit') 
     306      self.set('menu', 'POICategoryChooser') 
    115307 
    116308if(__name__ == "__main__"): 
  • modules/mod_storePOI.py

    r4062e3b raab194c  
    1919#--------------------------------------------------------------------------- 
    2020from base_module import ranaModule 
    21 import time 
    2221import cPickle 
    2322import os 
     23import sqlite3 
     24import csv 
    2425 
    2526def getModule(m,d): 
     
    3132  def __init__(self, m, d): 
    3233    ranaModule.__init__(self, m, d) 
    33     self.folder = self.get('POIFolder', 'data/poi/') 
    34     self.GLSResultFolder = self.folder + 'gls/' 
    35     self.filename = self.folder + 'poi.txt' 
    36     self.points = [] 
    37 #    self.points['GLS'] = [] 
    38     self.load() 
     34    self.db = None 
     35    self.tempOnlinePOI = None # temporary slot for an uncommited POI from online search 
     36 
     37  def firstTime(self): 
     38    self.connectToDb() 
     39    self.checkImport() # check if there ary any old POI to import 
     40 
     41  def connectToDb(self): 
     42    """connect to the database""" 
     43    POIFolderPath = self.dmod.getPOIFolderPath() 
     44    POIDBFilename = self.get('POIDBFilename', 'modrana_poi.db') 
     45    DBPath = "" + POIFolderPath + "/" + POIDBFilename 
     46 
     47    if os.path.exists(DBPath): # connect to db 
     48      try: 
     49        self.db = sqlite3.connect(DBPath) 
     50        print "connection to POI db in %s estabilshed" % DBPath 
     51      except Exception, e: 
     52        print "connecting to POI database failed:\n%s" % e 
     53    else: # create new db 
     54      try: 
     55        self.db = self.createDatabase(DBPath) 
     56      except Exception, e: 
     57        print "creating POI database failed:\n%s" % e 
     58 
     59  def disconnectFromDb(self): 
     60    print "storePOI: disconnecting from db" 
     61    self.db.close() 
     62         
     63  def createDatabase(self, path): 
     64    """create a new database, including tables and initial data 
     65    return the connection object""" 
     66    print "storePOI: creating new database file in:\n%s" % path 
     67    conn = sqlite3.connect(path) 
     68 
     69    # create the category table 
     70    conn.execute('CREATE TABLE category (cat_id integer PRIMARY KEY,label text, desc text, enabled integer)') 
     71    # create the poi table 
     72    conn.execute('CREATE TABLE poi (poi_id integer PRIMARY KEY, lat real, lon real, label text, desc text, cat_id integer)') 
     73    # load the predefined categories 
     74    # (currently the same ones as in MaemoMapper) 
     75    defaultCats = [(1, u'Service Station', u'Stations for purchasing fuel for vehicles.', 1), 
     76                   (2, u'Residence', u'Houses, apartments, or other residences of import.', 1), 
     77                   (3, u'Restaurant', u'Places to eat or drink.', 1), 
     78                   (4, u'Shopping/Services', u'Places to shop or acquire services.', 1), 
     79                   (5, u'Recreation', u'Indoor or Outdoor places to have fun.', 1), 
     80                   (6, u'Transportation', u'Bus stops, airports, train stations, etc.', 1), 
     81                   (7, u'Lodging', u'Places to stay temporarily or for the night.', 1), 
     82                   (8, u'School', u'Elementary schools, college campuses, etc.', 1), 
     83                   (9, u'Business', u'General places of business.', 1), 
     84                   (10, u'Landmark', u'General landmarks.', 1), 
     85                   (11, u'Other', u'Miscellaneous category for everything else.', 1)] 
     86    for cat in defaultCats: 
     87      conn.execute('insert into category values(?,?,?,?)', cat) 
     88    # commit the chnages 
     89    conn.commit() 
     90    print "storePoi: new database file has been created" 
     91    return conn 
     92 
     93  def storePOI(self,POI): 
     94    """store a POI object to the database""" 
     95    if self.db: 
     96      values = POI.getDbOrder() 
     97      query = "replace into poi values(?,?,?,?,?,?)" 
     98      self.db.execute(query,values) 
     99      self.db.commit() 
     100 
     101  def deletePOI(self,id): 
     102    """delete a poi with given ID from the database""" 
     103    self.db.execute('delete from poi where poi_id=?', [id]) 
     104    self.db.commit() 
     105 
     106  def getCategories(self): 
     107    """return a list of all available categories""" 
     108    if self.db: 
     109      return self.db.execute('select label,desc,cat_id from category').fetchall() 
     110 
     111  def getUsedCategories(self): 
     112    """return list of categories that have at least one POI""" 
     113    if self.db: 
     114      # find which POI categories are actually used 
     115      # TODO: investigate how this scales for many points 
     116      usedCatIds = self.db.execute('select distinct cat_id from poi').fetchall() 
     117      usedCategories = [] 
     118      for catId in usedCatIds: 
     119        nameDescription = self.db.execute('select label,desc,cat_id from category where cat_id=?', catId).fetchone() 
     120        if nameDescription: 
     121          usedCategories.append(nameDescription) 
     122      return usedCategories #this should be a list of used category ids 
     123    else: 
     124      return None 
     125 
     126  def getCategoryForId(self, catId): 
     127    """return cat_id,label, desc, enabled froa agiven cat_id""" 
     128    result = self.db.execute('select cat_id,label,desc,enabled from category where cat_id=?', [catId]).fetchone() 
     129    return result 
     130 
     131  def getAllPOIFromCategory(self, catId): 
     132    """return a list of POI from a given category""" 
     133    if self.db: 
     134      result = self.db.execute('select label,lat,lon,poi_id from poi where cat_id=?', [catId]).fetchall() 
     135      return result 
     136    else: 
     137      return None 
     138 
     139  def getPOI(self, POIId): 
     140    """return a complete POI row from db fow a given POI Id""" 
     141    if self.db: 
     142      result = self.db.execute('select poi_id, lat, lon, label, desc, cat_id from poi where poi_id=?',[POIId]).fetchone() 
     143      if result: 
     144        (poi_id,lat,lon,label,desc,cat_id) = result 
     145        # make it more usable 
     146        POIObject = self.POI(self,label,desc,lat,lon,cat_id,poi_id) 
     147        return POIObject 
     148      else: 
     149        return None 
     150    else: 
     151      return None 
     152 
     153  class POI: 
     154    """this class reperesents a POI""" 
     155    def __init__(self,callaback,label,description,lat,lon,catId,id=None): 
     156      self.callback = callaback 
     157      self.id=id 
     158      self.lat=lat 
     159      self.lon=lon 
     160      self.label= u'%s' % label 
     161      self.description= u'%s' % description 
     162      self.categoryId=catId 
     163 
     164    def getMenus(self): 
     165      """convenience function for getting the menus object""" 
     166      return self.callback.m.get('menu', None) 
     167 
     168    def getId(self): 
     169      return self.id 
     170 
     171    def getLat(self): 
     172      return self.lat 
     173 
     174    def getLon(self): 
     175      return self.lon 
     176 
     177    def getName(self): 
     178      return self.label 
     179 
     180    def getDescription(self): 
     181      return self.description 
     182 
     183    def getCatId(self): 
     184      return self.categoryId 
     185 
     186    def getDbOrder(self): 
     187      """get the variables in the order, they are stored in the database""" 
     188      return ( 
     189              self.getId(), 
     190              self.getLat(), 
     191              self.getLon(), 
     192              self.getName(), 
     193              self.getDescription(), 
     194              self.getCatId() 
     195              ) 
     196 
     197    def drawMenu(self,cr): 
     198      menus = self.getMenus() 
     199      if menus: 
     200        button1 = ('map#show on', 'generic', 'mapView:recentre %f %f|showPOI:drawActivePOI|set:menu:None' % (self.lat,self.lon)) 
     201        button2 = ('tools', 'tools', 'set:menu:POIDetailTools') 
     202        if self.label!=None and self.lat!=None and self.lon!=None and self.description!=None: 
     203          text = "%s\nlat:%f lon:%f\n%s" % (self.label,self.lat,self.lon,self.description) 
     204        else: 
     205          text = "POI is being initialized" 
     206        box = (text ,'') 
     207        menus.drawThreePlusOneMenu(cr, 'POIDetail', 'showPOI:checkMenus|set:menu:POIList', button1, button2, box) 
    39208     
    40   def load(self): 
    41     """load POI from file""" 
    42 #    start = time.clock() 
     209    def drawToolsMenu(self,cr): 
     210      # setup the tools submenu 
     211      menus = self.getMenus() 
     212      if menus: 
     213        menus.clearMenu('POIDetailTools', "set:menu:POIDetail") 
     214        menus.addItem('POIDetailTools', 'here#route', 'generic', 'showPOI:routeToActivePOI') 
     215        menus.addItem('POIDetailTools', 'name#edit', 'generic', 'ms:showPOI:editActivePOI:name') 
     216        menus.addItem('POIDetailTools', 'description#edit', 'generic', 'ms:showPOI:editActivePOI:description') 
     217        menus.addItem('POIDetailTools', 'latitude#edit', 'generic', 'ms:showPOI:editActivePOI:lat') 
     218        menus.addItem('POIDetailTools', 'longitude#edit', 'generic', 'ms:showPOI:editActivePOI:lon') 
     219        menus.addItem('POIDetailTools', 'category#change', 'generic', 'ml:showPOI:setupPOICategoryChooser:showPOI;setCatAndCommit|set:menu:POICategoryChooser') 
     220        menus.addItem('POIDetailTools', 'POI#delete', 'generic', 'showPOI:askDeleteActivePOI') 
     221 
     222    def getValues(self): 
     223      return([self.id,self.lat,self.lon,self.label,self.description,self.categoryId]) 
     224 
     225    def setName(self, newLabel, commit=True): 
     226      self.label = u'%s' % newLabel 
     227      if commit: 
     228        self.storeToDb() 
     229 
     230    def setDescription(self, newDescription, commit=True): 
     231      self.description = u'%s' % newDescription 
     232      if commit: 
     233        self.storeToDb() 
     234 
     235    def setLat(self, lat, commit=True): 
     236      self.lat = float(lat) 
     237      if commit: 
     238        self.storeToDb() 
     239 
     240    def setLon(self, lon, commit=True): 
     241      self.lon = float(lon) 
     242      if commit: 
     243        self.storeToDb() 
     244 
     245    def setCategory(self, newCatId, commit=True): 
     246      self.categoryId = newCatId 
     247      if commit: 
     248        self.storeToDb() 
     249 
     250 
     251    def storeToDb(self): 
     252      """store this POI object to the database""" 
     253      self.callback.storePOI(self) 
     254 
     255    def showOnMap(self): 
     256      """recentre to this POI and active point and label drawing""" 
     257      self.callback.sendMessage('mapView:recentre %f %f|showPOI:drawActivePOI|set:menu:None' % (self.lat,self.lon)) 
     258 
     259    def routeFrom(self, fromWhere): 
     260      if fromWhere == 'currentPosition': # route from current position to this POI 
     261        pos = self.callback.get('pos', None) 
     262        if pos: 
     263          (fromLat, fromLon) = pos 
     264          self.callback.sendMessage('md:route:route:type=ll2ll;fromLat=%f;fromLon=%f;toLat=%f;toLon=%f;' % (fromLat,fromLon,self.getLat(),self.getLon())) 
     265 
     266  def getEmptyPOI(self): 
     267    """get a POI with all variables set to None""" 
     268    POIObject = self.POI(self,None,None,None,None,None,None) 
     269    return POIObject 
     270 
     271  def checkImport(self): 
     272    """check if there are any POI in the old format 
     273       and try to import them to the db (into the "other" category) 
     274       then rename the old poi file to prevent multiple imports""" 
     275 
     276    oldPOIPath = "data/poi/poi.txt" 
     277    if os.path.exists(oldPOIPath): 
     278      try: 
     279        renamedOldPOIPath = "data/poi/imported_old_poi.txt" 
     280        print "storePOI:importing old POI from: %s" % oldPOIPath 
     281        points = self.loadOld(oldPOIPath) 
     282        if points: 
     283          for point in points: 
     284            # create a new POI object 
     285            label = point.name 
     286            description = point.description.replace('|','\n') 
     287            lat = point.lat 
     288            lon = point.lon 
     289            catId = 11 
     290            newPOI = self.POI(self,label,description,lat,lon,catId) 
     291            newPOI.storeToDb() 
     292          print "storePOI: imported %d old POI" % len(points) 
     293          os.rename(oldPOIPath,renamedOldPOIPath) 
     294          print "storePOI: old POI file moved to: %s" % renamedOldPOIPath 
     295          self.sendMessage('ml:notification:m:%d old POI imported to category "Other";10' % len(points)) 
     296      except Exception, e: 
     297        print "storePOI: import of old POI failed:\n%s" % e 
     298 
     299 
     300     
     301  def loadOld(self, path): 
     302    """load POI from file - depreciated, used sqlite for POI storage""" 
    43303    try: 
    44       f = open(self.filename, 'r') 
    45       self.points = cPickle.load(f) 
     304      f = open(path, 'r') 
     305      points = cPickle.load(f) 
    46306      f.close() 
    47     except: 
    48       print "storePOI: loding POI from file failed" 
    49 #    print "Loading POI took %1.2f ms" % (1000 * (time.clock() - start)) 
    50   def save(self): 
    51     """save all poi in the main list to file""" 
    52     try: 
    53       f = open(self.filename, 'w') 
    54       cPickle.dump(self.points, f) 
    55       f.close() 
    56     except: 
    57       print "storePoi: saving POI to file failed" 
    58  
     307      return points 
     308    except Exception, e: 
     309      print "storePOI: loding POI from file failed:\n%s" % e 
     310      return None 
     311 
     312#  def saveOld(self): 
     313#    """save all poi in the main list to file""" 
     314#    try: 
     315#      f = open(self.filename, 'w') 
     316#      cPickle.dump(self.points, f) 
     317#      f.close() 
     318#    except: 
     319#      print "storePoi: saving POI to file failed" 
     320 
     321 
     322  def handleMessage(self, message, type, args): 
     323    if type=='ms' and message=='deletePOI': 
     324      """remove a poi with given id from database""" 
     325      if args: 
     326        id = int(args) 
     327        self.deletePOI(id) # remove the poi from database 
     328        # notify the showPOI module, that it might need to rebuild its menus 
     329        self.sendMessage('showPOI:listMenusDirty') 
     330    elif type=='ms' and message=='setCatAndCommit': 
     331      """set category and as this is the last needed input, 
     332         commit the new POI to db""" 
     333      catId = int(args) 
     334      # set the category to the one the user just selected 
     335      self.tempOnlinePOI.setCategory(catId, commit=False) 
     336      # commit the new online result based POI to db 
     337      self.tempOnlinePOI.storeToDb() 
     338      # signal that the showPOI menus may need to be regenerated 
     339      self.sendMessage('showPOI:listMenusDirty') 
     340      catInfo = self.getCategoryForId(catId) 
     341      catName = catInfo[1] 
     342      POIName = self.tempOnlinePOI.getName() 
     343      self.set('menu', 'searchResultsItem') 
     344      self.sendMessage('ml:notification:m:%s has been saved to %s;5' % (POIName, catName)) 
     345 
     346    elif message == "reconnectToDb": 
     347      """this means, that we need to reconnect the database connection 
     348         * this is used for example as a notification, 
     349          that the user changed the default POI db path""" 
     350      self.disconnectFromDb() 
     351      self.connectToDb() 
     352 
     353    elif message == "dumpToCSV": 
     354      """dump db to CSV file""" 
     355      self.set('menu', None) 
     356      self.dumpToCSV() 
     357 
     358  def handleTextEntryResult(self, key, result): 
     359    if key=='onlineResultName': 
     360      """like this, the user can edit the name of the 
     361         result before saving it to POI""" 
     362      self.tempOnlinePOI.setName(result, commit=False) 
     363      self.sendMessage('ml:notification:m:Select a category for the new POI;3') 
     364      self.sendMessage('ml:showPOI:setupPOICategoryChooser:storePOI;setCatAndCommit') 
     365      self.set('menu', 'POICategoryChooser') 
     366 
     367  def dumpToCSV(self): 
     368    """dump the db content as a CSV file""" 
     369    units = self.m.get('units', None) 
     370    POIFolderPath = self.dmod.getPOIFolderPath() 
     371    self.sendMessage('ml:notification:m:POI export starting;5') 
     372    if units and self.db: 
     373      try: 
     374        filenameHash = units.getTimeHashString() 
     375 
     376        def CSVdump(path, rows): 
     377          """dump given list of rows to file""" 
     378          f = open(path, 'wb') 
     379          writer = csv.writer(f) 
     380          for row in rows: 
     381            writer.writerow(row) 
     382          f.close() 
     383 
     384        # dump the categories 
     385        rows = self.db.execute('select * from category').fetchall() 
     386        path = "" + POIFolderPath + "/" + filenameHash + "_category_dump.csv" 
     387        CSVdump(path, rows) 
     388 
     389        # dump the POI 
     390        rows = self.db.execute('select * from poi').fetchall() 
     391        path = "" + POIFolderPath + "/" + filenameHash + "_poi_dump.csv" 
     392        CSVdump(path, rows) 
     393 
     394        self.sendMessage('ml:notification:m:POI exported to: %s;5' % POIFolderPath) 
     395      except Exception, e: 
     396        print "storePOI: CSV dump failed:\n%s" % e 
     397        self.sendMessage('ml:notification:m:POI export failed;5') 
     398 
     399  def shutdown(self): 
     400    """disconnect from the database on shutdown""" 
     401    self.disconnectFromDb() 
    59402 
    60403  def storeGLSResult(self, result): 
     404    """store a Google Local Search result to file""" 
    61405    name = result['titleNoFormatting'] 
    62406    lat = float(result['lat']) 
    63407    lon = float(result['lng']) 
    64     category = "gls" 
    65  
    66     newPOI = POI(name, category, lat, lon) 
     408 
     409    newPOI = self.getEmptyPOI() 
     410    newPOI.setName(name, commit=False) 
     411    newPOI.setLat(lat, commit=False) 
     412    newPOI.setLon(lon, commit=False) 
    67413 
    68414    text = "%s" % (result['titleNoFormatting']) 
     
    70416    try: # the adress can be unknown 
    71417      for addressLine in result['addressLines']: 
    72         text += "|%s" % addressLine 
     418        text += "\n%s" % addressLine 
    73419    except: 
    74       text += "|%s" % "no adress found" 
     420      text += "\n%s" % "no adress found" 
    75421 
    76422    try: # it seems, that this entry is no guarantied 
     
    79425        if phoneNumber['type'] != "": 
    80426          type = " (%s)" % phoneNumber['type'] 
    81         text += "|%s%s" % (phoneNumber['number'], type) 
     427        text += "\n%s%s" % (phoneNumber['number'], type) 
    82428    except: 
    83       text += "|%s" % "no phone numbers found" 
    84  
    85     newPOI.setDescription(text) 
    86      
    87     self.points.append(newPOI) 
    88     self.save() 
     429      text += "\n%s" % "no phone numbers found" 
     430 
     431    newPOI.setDescription(text, commit=False) 
     432    self.tempOnlinePOI = newPOI 
     433 
     434    # start the name and description entry chain 
     435    entry = self.m.get('textEntry', None) 
     436    if entry: 
     437      entry.entryBox(self,'onlineResultName','POI Name',name) 
    89438 
    90439class POI(): 
    91   """A basic class representing a POI.""" 
     440  """A basic class representing a POI. 
     441     DEPRECIATED, use the new version in the main class 
     442     this is there only becuase it is needed for import of old POI""" 
    92443  def __init__(self, name, category, lat, lon): 
    93444    self.name = name 
  • modules/mod_tracklog.py

    r9a48ffd raab194c  
    507507 
    508508      if not self.loggingEnabled: 
    509         text+= "|||%s" % self.generateLogName() 
     509        text+= "\n\n\n%s" % self.generateLogName() 
    510510      else: 
    511         text+= "|||%s" % self.currentLogName 
    512  
    513       text+= "||logging interval %d s, saving every %d s" % (self.logInterval, self.saveInterval) 
     511        text+= "\n\n\n%s" % self.currentLogName 
     512 
     513      text+= "\n\nlogging interval %d s, saving every %d s" % (self.logInterval, self.saveInterval) 
    514514      if self.loggingStartTimestamp: 
    515515        elapsedSeconds = (int(time.time()) - self.loggingStartTimestamp) 
    516         text+= "|elapsed time: %s" % time.strftime('%H:%M:%S', time.gmtime(elapsedSeconds)) 
     516        text+= "\nelapsed time: %s" % time.strftime('%H:%M:%S', time.gmtime(elapsedSeconds)) 
    517517 
    518518      currentSpeed = self.get('speed',0)       
     
    522522        else: 
    523523          currentSpeedString = "%f kmh" % currentSpeed 
    524         text+="||current speed: %s" % currentSpeedString 
     524        text+="\n\ncurrent speed: %s" % currentSpeedString 
    525525      else: 
    526         text+="||current speed unknown" 
     526        text+="\n\ncurrent speed unknown" 
    527527 
    528528      if self.maxSpeed: 
     
    533533          avgString = "%f kmh" % self.avgSpeed 
    534534          maxString = "%f kmh" % self.maxSpeed 
    535         text+= "||max: %s, average: %s" % (maxString, avgString) 
     535        text+= "\n\nmax: %s, average: %s" % (maxString, avgString) 
    536536 
    537537      if self.distance: 
     
    541541        else: 
    542542          distanceString = "%f km" % self.distance 
    543         text+= "||distance traveled %s" % distanceString 
     543        text+= "\n\ndistance traveled %s" % distanceString 
    544544 
    545545      box = (text , "set:menu:tracklog") 
     546      print text 
    546547      menus.drawSixPlusOneMenu(cr, menuName, parent, fiveButtons, box) 
    547548 
  • modules/mod_tracklogManager.py

    r4062e3b raab194c  
    281281        pointcount = 0 
    282282 
    283       text = "number of points: %d|" % pointcount 
     283      text = "number of points: %d\n" % pointcount 
    284284      if track.elevation == True: 
    285         text += "|maximum elevation: %d meters|minimum elevation: %d meters" % (track.routeInfo['maxElevation'], track.routeInfo['minElevation']) 
    286         text += "|elevation of the first point: %d meters" % track.routeInfo['firstElevation'] 
    287         text += "|elevation of the last point: %d meters" % track.routeInfo['lastElevation'] 
     285        text += "\nmaximum elevation: %d meters\nminimum elevation: %d meters" % (track.routeInfo['maxElevation'], track.routeInfo['minElevation']) 
     286        text += "\nelevation of the first point: %d meters" % track.routeInfo['firstElevation'] 
     287        text += "\nelevation of the last point: %d meters" % track.routeInfo['lastElevation'] 
    288288 
    289289      menus.drawTextToSquare(cr, x4, y4+dy, w, h1-(y4+dy), text) 
  • modules/mod_units.py

    r8e9d419 raab194c  
    216216      return time.strftime("%H:%M") 
    217217 
     218  def getTimeHashString(self): 
     219    return time.strftime("%Y%m%d#%H-%M-%S", time.gmtime()) 
     220 
    218221 
    219222if(__name__ == "__main__"): 
Note: See TracChangeset for help on using the changeset viewer.