replaced get_departures with DataModel in pyside
authorFlorian Schweikert <kelvan@logic.at>
Wed, 14 Mar 2012 21:32:18 +0000 (22:32 +0100)
committerFlorian Schweikert <kelvan@logic.at>
Wed, 14 Mar 2012 21:32:18 +0000 (22:32 +0100)
gotovienna-qml
gotovienna/realtime.py
qml/ResultRealtime.qml

index d2dc8fa..033f537 100755 (executable)
@@ -9,8 +9,8 @@ __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 *
@@ -81,38 +81,53 @@ 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 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,13 +165,13 @@ 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
+    #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()
 
@@ -184,8 +199,7 @@ class Gui(QObject):
     @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()
 
@@ -194,9 +208,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()
@@ -233,10 +245,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:
@@ -245,27 +253,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)
@@ -274,16 +261,18 @@ if __name__ == '__main__':
 
     aboutInfo = AboutInfo()
     config = Config()
+    departureModel = DepartureModel()
 
     # instantiate the Python object
-    itip = Gui()
+    itip = Gui(departureModel)
 
     # expose the object to QML
     context = view.rootContext()
     context.setContextProperty('itip', itip)
     context.setContextProperty('aboutInfo', aboutInfo)
     context.setContextProperty('config', config)
-
+    context.setContextProperty('resultModel', departureModel)
+    
     if os.path.abspath(__file__).startswith('/usr/bin/'):
         # Assume system-wide installation, QML from /usr/share/
         view.setSource('/usr/share/gotovienna/qml/main.qml')
index ad43db2..a7ccde2 100644 (file)
@@ -194,8 +194,12 @@ class ITipParser:
         if msg and len(msg) > 0 and unicode(msg[0].text).find(u'technischen St') > 0:
             print '\n'.join(map(lambda x: x.text.replace('&nbsp;', ''), msg))
             return []
-
-        lines = bs.find('form', {'name': 'mainform'}).table.findAll('tr')[1]
+        
+        mainform = bs.find('form', {'name': 'mainform'})
+        if not mainform:
+            return []
+        
+        lines = mainform.table.findAll('tr')[1]
 
         if len(lines.findAll('td', {'class': 'info'})) > 0:
             station = lines.span.text.replace('&nbsp;', '')
index 1ec034a..c5a1c4f 100644 (file)
@@ -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)
-            }
         }
     }
 
@@ -75,7 +66,7 @@ Item {
                     spacing: 10
                     Text {
                         id: l
-                        text: line // <----
+                        text: model.line // <----
                         anchors.verticalCenter: parent.verticalCenter
                         //width: 70
                         font.pixelSize: UIConstants.FONT_XLARGE
@@ -89,7 +80,7 @@ Item {
 
                         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
@@ -99,7 +90,7 @@ Item {
 
                         Text {
                             id: d
-                            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
@@ -116,10 +107,10 @@ Item {
                 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
@@ -166,9 +157,7 @@ Item {
             }
         }
 
-        model: ListModel {
-            id: departuresModel
-        }
+        model: resultModel
         delegate: departureDelegate
 
         visible: !resultRealtime.busy && isCorrectInput()