0a82381fc0c261fa69ca1f4a6adc7c43c59486fc
[pywienerlinien] / gotovienna-qml
1 #!/usr/env/python
2
3 """Public transport information for Vienna"""
4
5 __author__ = 'kelvan <kelvan@logic.at>'
6 __version__ = '0.8.1'
7 __website__ = 'https://github.com/kelvan/gotoVienna/'
8 __license__ = 'GNU General Public License v3 or later'
9
10 from datetime import datetime
11
12 from PySide.QtCore import QAbstractListModel, QModelIndex, QObject, Slot, Signal
13 from PySide.QtGui import QApplication
14 from PySide.QtDeclarative import QDeclarativeView
15
16 from gotovienna.utils import *
17 from gotovienna.realtime import *
18 from gotovienna.gps import *
19
20 import urllib2
21 import os
22 import sys
23 import threading
24
25 class GotoViennaListModel(QAbstractListModel):
26     def __init__(self, objects=None):
27         QAbstractListModel.__init__(self)
28         if objects is None:
29             objects = []
30         self._objects = objects
31         self.setRoleNames({0: 'modelData'})
32
33     def set_objects(self, objects):
34         self._objects = objects
35
36     def get_objects(self):
37         return self._objects
38
39     def get_object(self, index):
40         return self._objects[index.row()]
41
42     def rowCount(self, parent=QModelIndex()):
43         return len(self._objects)
44
45     def data(self, index, role):
46         if index.isValid():
47             if role == 0:
48                 return self.get_object(index)
49         return None
50
51
52 class Gui(QObject):
53     def __init__(self):
54         QObject.__init__(self)
55         self.itip = ITipParser()
56         self.lines = []
57
58         # Read line names in categorized/sorted order
59         for _, lines in categorize_lines(self.itip.lines):
60             self.lines.extend(lines)
61
62         self.current_line = ''
63         self.current_stations = []
64         self.current_departures = []
65
66     @Slot(int, result=str)
67     def get_direction(self, idx):
68         return self.current_stations[idx][0]
69
70     @Slot(str, str, result='QStringList')
71     def get_stations(self, line, direction):
72         print 'line:', line, 'current line:', self.current_line
73         for dx, stations in self.current_stations:
74             print 'dx:', dx, 'direction:', direction
75             if dx == direction:
76                 return [stationname for stationname, url in stations]
77
78         return ['no stations found']
79
80     directionsLoaded = Signal()
81
82     @Slot(str)
83     def load_directions(self, line):
84         def load_async():
85             stations = sorted(self.itip.get_stations(line).items())
86
87             self.current_line = line
88             self.current_stations = stations
89
90             self.directionsLoaded.emit()
91
92         threading.Thread(target=load_async).start()
93
94     departuresLoaded = Signal()
95
96     @Slot(str)
97     def load_departures(self, url):
98         def load_async():
99             self.current_departures = [x['ftime'] for x in
100                     self.itip.get_departures(url)]
101             print self.current_departures
102             self.departuresLoaded.emit()
103
104         threading.Thread(target=load_async).start()
105
106     @Slot(str, str, str, result=str)
107     def get_directions_url(self, line, direction, station):
108         return self.itip.get_url_from_direction(line, direction, station)
109
110     @Slot(result='QStringList')
111     def get_lines(self):
112         return self.lines
113
114     @Slot(result='QStringList')
115     def get_departures(self):
116         return self.current_departures
117
118     @Slot(float, float, result=str)
119     def get_nearby_stations(self, lat, lon):
120         try:
121             return ', '.join(get_nearby_stations(lat, lon))
122         except Exception as e:
123             print e.message
124             return ''
125
126     @Slot(str, str)
127     def search(self, line, station):
128         line = line.upper()
129         station = station.decode('utf-8')
130         print line, station
131
132         if line not in self.lines:
133             return "Invalid line"
134
135         try:
136             stations = sorted(self.itip.get_stations(line).items())
137             print stations
138             headers, stations = zip(*stations)
139             print headers
140             print stations
141             details = [(direction, name, url) for direction, stops in stations
142                         for name, url in stops if match_station(station, name)]
143             print details
144         except urllib2.URLError as e:
145             print e.message
146             return e.message
147
148 if __name__ == '__main__':
149     app = QApplication(sys.argv)
150
151     view = QDeclarativeView()
152
153     # instantiate the Python object
154     itip = Gui()
155
156     # expose the object to QML
157     context = view.rootContext()
158     context.setContextProperty('itip', itip)
159
160     if os.path.abspath(__file__).startswith('/usr/bin/'):
161         # Assume system-wide installation, QML from /usr/share/
162         view.setSource('/usr/share/gotovienna/qml/main.qml')
163     else:
164         # Assume test from source directory, use relative path
165         view.setSource(os.path.join(os.path.dirname(__file__), 'qml/main.qml'))
166
167     view.showFullScreen()
168
169     sys.exit(app.exec_())
170