X-Git-Url: https://vcs.maemo.org/git/?a=blobdiff_plain;f=gotovienna-qml;h=4393d0e6eb27b506dea68ec26b0e97d810187bd6;hb=HEAD;hp=2ba243ed65b12244843220af15b491a727e3001e;hpb=5a7604ed608be9e3e5466583f5a30ce7965d5540;p=pywienerlinien diff --git a/gotovienna-qml b/gotovienna-qml index 2ba243e..4393d0e 100755 --- a/gotovienna-qml +++ b/gotovienna-qml @@ -3,14 +3,14 @@ """Public transport information for Vienna""" __author__ = 'kelvan ' -__version__ = '0.9.0' +__version__ = '0.9.1' __website__ = 'http://tinyurl.com/gotoVienna' __license__ = 'GNU General Public License v3 or later' 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 @@ 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,38 +84,104 @@ class AboutInfo(QObject): def getLicense(self): return __license__ -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 - - 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) +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 index.isValid(): - if role == 0: - return self.get_object(index) - return None - + 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 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): @@ -150,19 +219,41 @@ class Gui(QObject): threading.Thread(target=load_async).start() - def map_departure(self, dep): - dep['lowfloor'] = 1 if dep['lowfloor'] else 0 - if type(dep['time']) == time: - dep['time'] = dep['time'].strftime('%H:%M') - 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_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)) + self.departureModel.setDepartures(self.itip.get_departures(url)) #print self.current_departures self.departuresLoaded.emit() @@ -171,9 +262,7 @@ class Gui(QObject): @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() @@ -210,10 +299,6 @@ class Gui(QObject): 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: @@ -222,27 +307,6 @@ class Gui(QObject): # 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) @@ -251,15 +315,20 @@ if __name__ == '__main__': 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/