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