def __init__(self):
QMainWindow.__init__(self)
+ # _s is used to keep a reference to the Search object, so it does
+ # not get destroyed when it falls out of scope (the QML view is
+ # destroyed as soon as the Search object is destroyed!)
+ self._s = None
self.setupUi(self)
self.connect(self.btnSearch, SIGNAL("clicked()"), self.search)
if not origin and destination:
self.btnSearch.setText("Search - Missing input")
else:
- s = Search(origin, destination, \
+ self._s = Search(origin, destination, \
origin_type=self.types[self.comboOrigin.currentIndex()], \
destination_type=self.types[self.comboDestination.currentIndex()])
- try:
- s.open_browser()
- except webbrowser.Error:
- self.btnSearch.setText("Error starting webbrowser")
- return False
- self.btnSearch.setText("Search - Opening webbrowser")
+ self._s.open_qml()
return True
--- /dev/null
+
+import Qt 4.7
+
+ListView {
+ id: lv
+ width: 800
+ height: 400
+ delegate: OverviewItem {
+ onShowDetails: lv.showDetails(details)
+ }
+
+ states: [
+ State {
+ name: 'overview'
+ },
+ State {
+ name: 'details'
+ PropertyChanges {
+ target: detailsRect
+ opacity: 1
+ scale: 1
+ }
+ }
+ ]
+
+ Rectangle {
+ id: detailsRect
+ width: parent.width - 50
+ height: parent.height - 50
+ anchors.centerIn: parent
+ scale: 0
+ opacity: 0
+ color: '#aaa'
+
+ border {
+ color: '#888'
+ width: 10
+ }
+
+ Behavior on opacity { PropertyAnimation { duration: 250 }}
+
+ Behavior on scale {
+ PropertyAnimation {
+ duration: 500
+ easing.type: Easing.InCubic
+ }
+ }
+
+ Text {
+ id: detailsTitle
+
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.top: parent.top
+ horizontalAlignment: Text.AlignHCenter
+ anchors.topMargin: 20
+ font.pixelSize: 30
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: lv.state = 'overview'
+ }
+ }
+
+ function showDetails(details) {
+ detailsTitle.text = 'FIXME - show details for ' + details.time_from
+ lv.state = 'details'
+ }
+}
+
--- /dev/null
+import Qt 4.7
+
+Rectangle {
+ anchors.left: parent.left
+ anchors.right: parent.right
+ height: 70
+ color: (index%2)?'#eee':'#ddd'
+
+ signal showDetails(variant details)
+
+ Text {
+ id: datum
+ anchors.left: parent.left
+ anchors.top: parent.top
+ anchors.bottom: parent.bottom
+ verticalAlignment: Text.AlignVCenter
+ text: modelData.date
+ font.pixelSize: 20
+ anchors.leftMargin: 30
+ anchors.rightMargin: 30
+ width: parent.width * .2
+ }
+
+ Text {
+ id: time_from
+ anchors.left: datum.right
+ anchors.bottom: parent.verticalCenter
+ text: 'von ' + modelData.time_from
+ verticalAlignment: Text.AlignBottom
+ width: parent.width * .2
+ visible: modelData.time_from != '-'
+ }
+
+ Text {
+ id: time_to
+ anchors.left: datum.right
+ anchors.top: parent.verticalCenter
+ text: 'bis ' + modelData.time_to
+ anchors.rightMargin: 40
+ verticalAlignment: Text.AlignTop
+ width: time_from.width
+ visible: modelData.time_to != '-'
+ }
+
+ Text {
+ id: dauer
+ text: 'Dauer: ' + modelData.duration + ' (' + modelData.change + ' x umsteigen)'
+ font.pixelSize: 17
+ anchors.left: time_from.right
+ anchors.top: parent.top
+ anchors.bottom: parent.bottom
+ verticalAlignment: Text.AlignVCenter
+ width: parent.width * .3
+ }
+
+ Text {
+ id: price
+ text: 'EUR ' + modelData.price
+ anchors.right: parent.right
+ anchors.top: parent.top
+ anchors.bottom: parent.bottom
+ verticalAlignment: Text.AlignVCenter
+ width: parent.width * .1
+ horizontalAlignment: Text.AlignRight
+ anchors.rightMargin: 20
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: parent.showDetails(modelData)
+ }
+}
+# -*- coding: utf-8 -*-
+
import urllib
import sys
from datetime import datetime
import webbrowser
import urllib2
+from parseHtml import Parser
+
+from PySide.QtDeclarative import QDeclarativeView
+
+def QMLModel(overview):
+ # Mapping from the "overview" data structure to a "plain" data
+ # structure to be used as model for the qml listview
+ r = []
+ for item in overview:
+ d = {
+ 'date': item['date'].strftime('%d.%m.%Y') if item['date'] else u'Fußweg',
+ 'duration': item['duration'].strftime('%H:%M'),
+ 'price': item['price'],
+ 'change': item['change'],
+ }
+
+ if len(item['time']) == 2 and all(x is not None for x in item['time']):
+ d.update({
+ 'time_from': item['time'][0].strftime('%H:%M'),
+ 'time_to': item['time'][1].strftime('%H:%M'),
+ })
+ else:
+ d.update({'time_from': '-', 'time_to': '-'})
+
+ r.append(d)
+ return r
+
class Search:
self.destination = destination
self.origin_type = origin_type
self.destination_type = destination_type
+ self.view = None
+ self.qml_model = None
def get_html(self, dtime=datetime.now()):
return urllib2.urlopen('%s?%s' % (settings.action, self.get_parameter(dtime)))
def open_browser(self, dtime=datetime.now()):
webbrowser.open('%s?%s' % (settings.action, self.get_parameter(dtime)))
+ def open_qml(self, dtime=datetime.now()):
+ p = Parser(self.get_html(dtime))
+ self.qml_model = QMLModel(p.overview)
+ self.view = QDeclarativeView()
+ self.view.setResizeMode(QDeclarativeView.SizeRootObjectToView)
+ self.view.setSource('ui/Overview.qml')
+ self.view.rootObject().setProperty('model', self.qml_model)
+ self.view.show()
+
def get_datetime(self, dtime):
return (dtime.strftime('%d.%m.%Y'), dtime.strftime('%H:%M'))