From: Florian Schweikert Date: Wed, 14 Mar 2012 22:39:37 +0000 (+0100) Subject: Merge branch 'master' of github.com:kelvan/gotoVienna X-Git-Url: http://git.maemo.org/git/?p=pywienerlinien;a=commitdiff_plain;h=ec5e6afed4ebefcd4ea8a234fdd82b7d6e231a3f;hp=-c Merge branch 'master' of github.com:kelvan/gotoVienna Conflicts: gotovienna-qml --- ec5e6afed4ebefcd4ea8a234fdd82b7d6e231a3f diff --combined gotovienna-qml index 033f537,9ebfa55..190018c --- a/gotovienna-qml +++ b/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): @@@ -165,13 -206,13 +219,13 @@@ 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() @@@ -199,7 -240,8 +253,7 @@@ @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() @@@ -208,7 -250,9 +262,7 @@@ @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() @@@ -245,6 -289,10 +299,6 @@@ 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: @@@ -253,6 -301,27 +307,6 @@@ # 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) @@@ -261,18 -330,19 +315,21 @@@ 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 --- a/qml/MapView.qml +++ /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 index c5a1c4f,1ec034a..9a49eba --- a/qml/ResultRealtime.qml +++ b/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 @@@ -107,10 -116,10 +107,10 @@@ 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 @@@ -157,7 -166,9 +157,7 @@@ } } - model: ListModel { - id: departuresModel - } + model: resultModel delegate: departureDelegate visible: !resultRealtime.busy && isCorrectInput()