Merge branch 'master' of github.com:kelvan/gotoVienna
[pywienerlinien] / gotovienna-qml
index d0ba500..d2dc8fa 100755 (executable)
@@ -1,23 +1,85 @@
-#!/usr/env/python
+#!/usr/bin/env python
 
 """Public transport information for Vienna"""
 
 __author__ = 'kelvan <kelvan@logic.at>'
-__version__ = '1.0'
-__website__ = 'https://github.com/kelvan/gotoVienna/'
+__version__ = '0.9.0'
+__website__ = 'http://tinyurl.com/gotoVienna'
 __license__ = 'GNU General Public License v3 or later'
 
-from PySide.QtCore import *
-from PySide.QtGui import *
-from PySide.QtDeclarative import *
+from datetime import datetime
+
+from PySide.QtCore import QAbstractListModel, QModelIndex, QObject, Slot, Signal
+from PySide.QtGui import QApplication
+from PySide.QtDeclarative import QDeclarativeView
 
 from gotovienna.utils import *
 from gotovienna.realtime import *
+from gotovienna.gps import *
+from gotovienna.update import *
+from gotovienna.config import config as conf
 
 import urllib2
 import os
 import sys
 import threading
+from datetime import time
+
+class Config(QObject):
+    def __init__(self):
+        QObject.__init__(self)
+
+    @Slot(result=bool)
+    def getGpsEnabled(self):
+        return conf.getGpsEnabled()
+
+    @Slot(bool, result=unicode)
+    def setGpsEnabled(self, val):
+        # TODO
+        return conf.setGpsEnabled(val)
+
+    @Slot(result=unicode)
+    def getLastUpdate(self):
+        # TODO
+        return conf.getLastStationsUpdate()
+
+    @Slot(result=unicode)
+    def updateStations(self):
+        # TODO
+        try:
+            update_stations()
+            return datetime.now().strftime('%c')
+        except Exception as e:
+            print e
+            return ''
+
+    @Slot(result=bool)
+    def checkStationsUpdate(self):
+        # FIXME exception handling foo
+        try:
+            return check_stations_update()
+        except:
+            return False
+
+class AboutInfo(QObject):
+    def __init__(self):
+        QObject.__init__(self)
+
+    @Slot(result=unicode)
+    def getAppName(self):
+        return u'gotoVienna %s' % __version__
+
+    @Slot(result=unicode)
+    def getWebsiteURL(self):
+        return __website__
+
+    @Slot(result=unicode)
+    def getCopyright(self):
+        return 'Copyright 2011, 2012 %s' % __author__
+
+    @Slot(result=unicode)
+    def getLicense(self):
+        return __license__
 
 class GotoViennaListModel(QAbstractListModel):
     def __init__(self, objects=None):
@@ -58,6 +120,7 @@ class Gui(QObject):
 
         self.current_line = ''
         self.current_stations = []
+        self.current_departures = []
 
     @Slot(int, result=str)
     def get_direction(self, idx):
@@ -87,10 +150,101 @@ class Gui(QObject):
 
         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
+
+    departuresLoaded = Signal()
+
+    @Slot(str)
+    def load_departures_test(self, **args):
+        """ valid args combinations
+            station
+            line, station
+        """
+        def load_async():
+            if args.has_key('station'):
+                if args.has_key('line'):
+                    self.current_departures = map(self.map_departure, \
+                                                  self.itip.get_departures(args['line'], args['station']))
+                    #print self.current_departures
+                    self.departuresLoaded.emit()
+                else:
+                    self.current_departures = map(self.map_departure, \
+                                                  sort_departures(self.itip.get_departures_by_station(station)))
+            else:
+                raise KeyError('Missing valid argument combination')
+
+        threading.Thread(target=load_async).start()
+
+    @Slot(str)
+    def load_departures(self, url):
+        def load_async():
+            self.current_departures = map(self.map_departure, \
+                                          self.itip.get_departures(url))
+            #print self.current_departures
+            self.departuresLoaded.emit()
+
+        threading.Thread(target=load_async).start()
+
+    @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.departuresLoaded.emit()
+
+        threading.Thread(target=load_async).start()
+
+    @Slot(float, float)
+    def load_nearby_departures(self, lat, lon):
+        def load_async():
+            self.current_departures = []
+            try:
+                stations = get_nearby_stations(lat, lon)
+                print stations
+                for station in stations:
+                    print station
+                    try:
+                        self.current_departures += self.itip.get_departures_by_station(station)
+                    except Exception as e:
+                        print e.message
+                self.current_departures = map(self.map_departure, \
+                                              sort_departures(self.current_departures))
+                #print self.current_departures
+            except Exception as e:
+                print e.message
+
+            print 'loaded'
+            self.departuresLoaded.emit()
+
+        threading.Thread(target=load_async).start()
+
+    @Slot(str, str, str, result=str)
+    def get_directions_url(self, line, direction, station):
+        return self.itip.get_url_from_direction(line, direction, station)
+
     @Slot(result='QStringList')
     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:
+            return get_nearby_stations(lat, lon)
+        except BaseException as e:
+            # No/wrong stations.db file
+            return []
+
     @Slot(str, str)
     def search(self, line, station):
         line = line.upper()
@@ -118,12 +272,17 @@ if __name__ == '__main__':
 
     view = QDeclarativeView()
 
+    aboutInfo = AboutInfo()
+    config = Config()
+
     # instantiate the Python object
     itip = Gui()
 
     # expose the object to QML
     context = view.rootContext()
     context.setContextProperty('itip', itip)
+    context.setContextProperty('aboutInfo', aboutInfo)
+    context.setContextProperty('config', config)
 
     if os.path.abspath(__file__).startswith('/usr/bin/'):
         # Assume system-wide installation, QML from /usr/share/