Merge branch 'master' of github.com:kelvan/gotoVienna
authorFlorian Schweikert <kelvan@logic.at>
Wed, 14 Mar 2012 22:39:37 +0000 (23:39 +0100)
committerFlorian Schweikert <kelvan@logic.at>
Wed, 14 Mar 2012 22:39:37 +0000 (23:39 +0100)
Conflicts:
gotovienna-qml

1  2 
gotovienna-qml
qml/MapView.qml
qml/ResultRealtime.qml

diff --combined gotovienna-qml
@@@ -9,8 -9,8 +9,8 @@@ __license__ = 'GNU General Public Licen
  
  from datetime import datetime
  
 -from PySide.QtCore import QAbstractListModel, QModelIndex, QObject, Slot, Signal
 -from PySide.QtGui import QApplication
 +from PySide.QtCore import QAbstractListModel, QModelIndex, QObject, Slot, Signal, Qt
 +from PySide.QtGui import QApplication, QTextItem
  from PySide.QtDeclarative import QDeclarativeView
  
  from gotovienna.utils import *
@@@ -19,10 -19,13 +19,13 @@@ from gotovienna.gps import 
  from gotovienna.update import *
  from gotovienna.config import config as conf
  
+ from gotovienna import defaults
  import urllib2
  import os
  import sys
  import threading
+ import json
  from datetime import time
  
  class Config(QObject):
@@@ -81,53 -84,91 +84,104 @@@ class AboutInfo(QObject)
      def getLicense(self):
          return __license__
  
 +class DepartureModel(QAbstractListModel):
 +    LINE_ROLE = Qt.UserRole + 1
 +    DIRECTION_ROLE = Qt.UserRole + 2
 +    STATION_ROLE = Qt.UserRole + 3
 +    TIME_ROLE = Qt.UserRole + 4
 +    LOWFLOOR_ROLE = Qt.UserRole + 5
 +
 +    def __init__(self, parent=None):
 +        super(DepartureModel, self).__init__(parent)
 +        self._data = []
 +        
 +        self.keys = {}
 +        self.keys[DepartureModel.LINE_ROLE] = 'line'
 +        self.keys[DepartureModel.DIRECTION_ROLE] = 'direction'
 +        self.keys[DepartureModel.STATION_ROLE] = 'station'
 +        self.keys[DepartureModel.TIME_ROLE] = 'time'
 +        self.keys[DepartureModel.LOWFLOOR_ROLE] = 'lowfloor'
 +        self.setRoleNames(self.keys)
 +
 +    def rowCount(self, index):
 +        return len(self._data)
 +
 +    def data(self, index, role):
 +        if not index.isValid():
 +            return None
 +
 +        if index.row() > len(self._data):
 +            return None
 +            
 +        departure = self._data[index.row()]
 +        
 +        if self.keys.has_key(role):
 +            return departure[self.keys[role]]
 +        else:
 +            return None
 +            
 +    def setDepartures(self, dep):
 +        self.beginResetModel()
 +        self._data = dep
 +        self.endResetModel()
 +
+ class FavoriteManager(QObject):
+     def __init__(self):
+         QObject.__init__(self)
+         self._faves = []
+         if os.path.exists(defaults.favorites_file):
+             try:
+                 self._faves = json.load(open(defaults.favorites_file, 'r'))
+                 self._faves = map(tuple, self._faves)
+                 print 'faves loaded:', self._faves
+             except Exception, e:
+                 print 'faves load error:', e
+     @Slot(result=int)
+     def getCount(self):
+         result = len(self._faves)
+         print 'getCount->', result
+         return result
+     @Slot(int, result=unicode)
+     def getItem(self, index):
+         keys = ['gline', 'gdirection', 'gstation', 'sourceurl', 'isstation']
+         result = dict(zip(keys, self._faves[index]))
+         result['name'] = u'%(gline)s -> %(gdirection)s @ %(gstation)s' % result
+         result = json.dumps(result)
+         print 'getItem:', index, result
+         return result
+     def _persist(self):
+         print 'persist:', self._faves, '->', defaults.favorites_file
+         try:
+             fp = open(defaults.favorites_file, 'w')
+             json.dump(self._faves, fp)
+             fp.close()
+         except Exception, e:
+             print 'faves save error:', e
+     @Slot(unicode, unicode, unicode, unicode, bool, int, result=bool)
+     def isFavorite(self, gline, gdirection, gstation, sourceurl, isstation, x):
+         k = (gline, gdirection, gstation, sourceurl, isstation)
+         return (k in self._faves)
+     @Slot(unicode, unicode, unicode, unicode, bool)
+     def toggleFavorite(self, gline, gdirection, gstation, sourceurl, isstation):
+         k = (gline, gdirection, gstation, sourceurl, isstation)
+         if k in self._faves:
+             self._faves.remove(k)
+         else:
+             self._faves.append(k)
+         self._persist()
 -
 -class GotoViennaListModel(QAbstractListModel):
 -    def __init__(self, objects=None):
 -        QAbstractListModel.__init__(self)
 -        if objects is None:
 -            objects = []
 -        self._objects = objects
 -        self.setRoleNames({0: 'modelData'})
 -
 -    def set_objects(self, objects):
 -        self._objects = objects
 -        self.reset()
 -
 -    def get_objects(self):
 -        return self._objects
 -
 -    def get_object(self, index):
 -        return self._objects[index.row()]
 -
 -    def rowCount(self, parent=QModelIndex()):
 -        return len(self._objects)
 -
 -    def data(self, index, role):
 -        if index.isValid():
 -            if role == 0:
 -                return self.get_object(index)
 -        return None
 -
 -
  class Gui(QObject):
 -    def __init__(self):
 +    def __init__(self, depModel):
          QObject.__init__(self)
          self.itip = ITipParser()
          self.lines = []
 +        self.departureModel = depModel
  
          # Read line names in categorized/sorted order
          for _, lines in categorize_lines(self.itip.lines):
  
          threading.Thread(target=load_async).start()
  
 -    def map_departure(self, dep):
 -        """ prepare departure list for qml gui
 -        """
 -        dep['lowfloor'] = 1 if dep['lowfloor'] else 0
 -        dep['realtime'] = 1 if dep['realtime'] else 0
 -        dep['time'] = dep['ftime']
 -        return dep
 +    #def map_departure(self, dep):
 +    #    """ prepare departure list for qml gui
 +    #    """
 +    #    dep['lowfloor'] = 1 if dep['lowfloor'] else 0
 +    #    dep['realtime'] = 1 if dep['realtime'] else 0
 +    #    dep['time'] = dep['ftime']
 +    #    return dep
  
      departuresLoaded = Signal()
  
      @Slot(str)
      def load_departures(self, url):
          def load_async():
 -            self.current_departures = map(self.map_departure, \
 -                                          self.itip.get_departures(url))
 +            self.departureModel.setDepartures(self.itip.get_departures(url))
              #print self.current_departures
              self.departuresLoaded.emit()
  
      @Slot(str)
      def load_station_departures(self, station):
          def load_async():
 -            self.current_departures = map(self.map_departure, \
 -                                          sort_departures(self.itip.get_departures_by_station(station)))
 -            #print self.current_departures
 +            self.departureModel.setDepartures(sort_departures(self.itip.get_departures_by_station(station)))
              self.departuresLoaded.emit()
  
          threading.Thread(target=load_async).start()
      def get_lines(self):
          return self.lines
  
 -    @Slot(result='QVariant')
 -    def get_departures(self):
 -        return self.current_departures
 -
      @Slot(float, float, result='QStringList')
      def get_nearby_stations(self, lat, lon):
          try:
              # No/wrong stations.db file
              return []
  
 -    @Slot(str, str)
 -    def search(self, line, station):
 -        line = line.upper()
 -        station = station.decode('utf-8')
 -        print line, station
 -
 -        if line not in self.lines:
 -            return "Invalid line"
 -
 -        try:
 -            stations = sorted(self.itip.get_stations(line).items())
 -            print stations
 -            headers, stations = zip(*stations)
 -            print headers
 -            print stations
 -            details = [(direction, name, url) for direction, stops in stations
 -                        for name, url in stops if match_station(station, name)]
 -            print details
 -        except urllib2.URLError as e:
 -            print e.message
 -            return e.message
  
  if __name__ == '__main__':
      app = QApplication(sys.argv)
  
      aboutInfo = AboutInfo()
      config = Config()
 +    departureModel = DepartureModel()
  
      # instantiate the Python object
 -    itip = Gui()
 +    itip = Gui(departureModel)
  
+     favManager = FavoriteManager()
      # expose the object to QML
      context = view.rootContext()
      context.setContextProperty('itip', itip)
      context.setContextProperty('aboutInfo', aboutInfo)
      context.setContextProperty('config', config)
 +    context.setContextProperty('resultModel', departureModel)
-     
+     context.setContextProperty('favManager', favManager)
      if os.path.abspath(__file__).startswith('/usr/bin/'):
          # Assume system-wide installation, QML from /usr/share/
          view.setSource('/usr/share/gotovienna/qml/main.qml')
diff --combined qml/MapView.qml
index ad52fdf,ad52fdf..0000000
deleted file mode 100644,100644
+++ /dev/null
@@@ -1,35 -1,35 +1,0 @@@
--import QtQuick 1.1
--import Qt 4.7
--import QtMobility.location 1.2
--import com.nokia.meego 1.0
--
--Page {
--    tools: mapTools
--
--    ToolBarLayout {
--        id: mapTools
--        x: 0
--        y: 0
--        ToolIcon { iconId: "toolbar-back"; onClicked: { menu.close(); pageStack.pop(null,false); } }
--    }
--
--    Map {
--        id: map
--        plugin : Plugin {
--            name : "nokia"
--        }
--
--        anchors.fill: parent
--        size.width: parent.width
--        size.height: parent.height
--        zoomLevel: 7
--        //center: positionSource.position.coordinate
--        //objects: t_data.mapObjectsList
--
--
--        onZoomLevelChanged: {
--            console.log("Zoom changed")
--        }
--
--    }
--}
diff --combined qml/ResultRealtime.qml
@@@ -42,6 -42,15 +42,6 @@@ Item 
  
          onDeparturesLoaded: {
              busy = false
 -            departuresModel.clear()
 -
 -            var departures = itip.get_departures()
 -
 -            for (var d in departures) {
 -                console.log('time: ' + departures[d].time)
 -                var row = {'line': departures[d].line, 'station': departures[d].station, 'destination': departures[d].direction, 'departure': departures[d].time, 'lowfloor': departures[d].lowfloor}
 -                departuresModel.append(row)
 -            }
          }
      }
  
@@@ -66,7 -75,7 +66,7 @@@
                      spacing: 10
                      Text {
                          id: l
 -                        text: line // <----
 +                        text: model.line // <----
                          anchors.verticalCenter: parent.verticalCenter
                          //width: 70
                          font.pixelSize: UIConstants.FONT_XLARGE
@@@ -80,7 -89,7 +80,7 @@@
  
                          Text {
                              id: s
 -                            text: station // <----
 +                            text: model.station // <----
                              width: parent.parent.parent.width - l.width - dep.width - 15
                              elide: Text.ElideRight
                              font.pixelSize: UIConstants.FONT_LARGE
@@@ -90,7 -99,7 +90,7 @@@
  
                          Text {
                              id: d
-                             text: model.direction // <----
 -                            text: destination // <----
++                            text: model.direction // <---   -
                              width: parent.parent.parent.width - l.width - dep.width - 15
                              elide: Text.ElideRight
                              color: !theme.inverted ? UIConstants.COLOR_SECONDARY_FOREGROUND : UIConstants.COLOR_INVERTED_SECONDARY_FOREGROUND
                  Text {
                      id: dep
                      // FIXME strange int float transformation appears
 -                    text: departure
 +                    text: model.time
                      anchors.right: parent.right
                      anchors.rightMargin: UIConstants.DEFAULT_MARGIN
 -                    font.italic: lowfloor == 1
 +                    font.italic: lowfloor
                      font.bold: true
                      font.pixelSize: UIConstants.FONT_XLARGE
                      font.family: ExtrasConstants.FONT_FAMILY_LIGHT
              }
          }
  
 -        model: ListModel {
 -            id: departuresModel
 -        }
 +        model: resultModel
          delegate: departureDelegate
  
          visible: !resultRealtime.busy && isCorrectInput()