Work in progress on QML
authorLuciano Montanaro <mikelima@cirulla.net>
Sat, 26 Oct 2013 15:27:56 +0000 (17:27 +0200)
committerLuciano Montanaro <mikelima@cirulla.net>
Sat, 26 Oct 2013 15:27:56 +0000 (17:27 +0200)
application/resources/sailfish/qml/cover/CoverPage.qml [new file with mode: 0644]
application/resources/sailfish/qml/main.qml [new file with mode: 0644]
application/resources/sailfish/qml/pages/StationListPage.js [new file with mode: 0644]
application/resources/sailfish/qml/pages/StationListPage.qml [new file with mode: 0644]
application/resources/sailfish/qml/pages/StationPage.qml [new file with mode: 0644]

diff --git a/application/resources/sailfish/qml/cover/CoverPage.qml b/application/resources/sailfish/qml/cover/CoverPage.qml
new file mode 100644 (file)
index 0000000..17ee438
--- /dev/null
@@ -0,0 +1,26 @@
+import QtQuick 2.0
+import Sailfish.Silica 1.0
+
+CoverBackground {
+    Label {
+        id: label
+        anchors.centerIn: parent
+        text: qsTr("Quando Parte")
+    }
+    
+/*
+    CoverActionList {
+        id: coverAction
+        
+        CoverAction {
+            iconSource: "image://theme/icon-cover-next"
+        }
+        
+        CoverAction {
+            iconSource: "image://theme/icon-cover-pause"
+        }
+    }
+*/
+}
+
+
diff --git a/application/resources/sailfish/qml/main.qml b/application/resources/sailfish/qml/main.qml
new file mode 100644 (file)
index 0000000..b3d3ca9
--- /dev/null
@@ -0,0 +1,9 @@
+import QtQuick 2.0
+import Sailfish.Silica 1.0
+import "pages"
+
+ApplicationWindow {
+    id: window
+    initialPage: StationListPage { }
+    cover: Qt.resolvedUrl("cover/CoverPage.qml")
+}
diff --git a/application/resources/sailfish/qml/pages/StationListPage.js b/application/resources/sailfish/qml/pages/StationListPage.js
new file mode 100644 (file)
index 0000000..858b36e
--- /dev/null
@@ -0,0 +1,47 @@
+var view = undefined
+var about = undefined
+
+function showAboutPage()
+{
+    var component = Qt.createComponent("AboutPage.qml")
+    if (component.status === Component.Ready) {
+        about = component.createObject(stationListPage)
+        pageStack.push(about)
+    } else
+        console.log('Cannot load component: ' + component.errorString());
+}
+
+function loadStation(name, code)
+{
+    var component = Qt.createComponent("StationPage.qml");
+    if (component.status === Component.Ready) {
+        view = component.createObject(stationListPage)
+        stationListPage.stationView = view
+        pageStack.push(view)
+
+        /*
+            XXX Ugliness ahead! Changing the name triggers the station
+            schedule to be fetched. So any extra data (the code specifically)
+            must be set before changing the name.
+         */
+        if (code !== undefined) view.code = code
+        view.name = name
+    }
+    else
+        console.log('Cannot load component: ' + component.errorString());
+}
+
+function highlightSearch(s, color)
+{
+    // TODO compile RegExp on change, or find a way to cleanly use
+    // stationListProxyModel.filterRegExp
+    if (searchField.text.length) {
+        var r = new RegExp(searchField.text, 'i')
+        var match = r.exec(s)
+        return s.replace(r, '<span style="text-decoration:underline;color:' + color + ';">' +
+                         match + '</span>')
+    } else {
+        return s
+    }
+}
+
diff --git a/application/resources/sailfish/qml/pages/StationListPage.qml b/application/resources/sailfish/qml/pages/StationListPage.qml
new file mode 100644 (file)
index 0000000..7d6deca
--- /dev/null
@@ -0,0 +1,104 @@
+import QtQuick 2.0
+import Sailfish.Silica 1.0
+import net.cirulla.quandoparte 1.0
+import "StationListPage.js" as Private
+
+Page {
+    property variant stationView
+    id: stationListPage
+    Binding {
+        target: stationListProxyModel
+        property: "searchPattern"
+        value: searchField.text
+    }
+    Binding {
+        target: stationListProxyModel
+        property: "sortingMode"
+        value: header.currentIndex
+    }
+    Binding {
+        target: stationListView
+        property: "section.property"
+        value: header.currentIndex === 0 ? "name" : ""
+    }
+    SilicaListView {
+        id: stationListView
+        clip: true
+        width: parent.width
+        cacheBuffer: 10
+        anchors.fill: parent
+        model:  stationListProxyModel
+        header: Column {
+            ComboBox {
+                id: header
+                currentIndex: stationListProxyModel.sortingMode
+                menu: ContextMenu {
+                    MenuItem {
+                        text: qsTr("by Name")
+                    }
+                    MenuItem {
+                        text: qsTr("by Distance")
+                    }
+                    MenuItem {
+                        text: qsTr("Recently Seen")
+                    }
+                }
+                label: qsTr("Stations")
+            }
+            SearchField {
+                id: searchField
+                placeholderText: qsTr("Search station...")
+            }
+        }
+        section {
+            criteria: ViewSection.FirstCharacter
+            delegate: Item {
+                width: parent.width
+                height: Theme.itemSizeSmall
+                anchors {
+                    margins: Theme.paddingMedium
+                }
+               Image {
+                   anchors {
+                       left: parent.left
+                       right: sectionLabel.left
+                       verticalCenter: parent.verticalCenter
+                       margins: Theme.paddingMedium
+                   }
+                   source: "image://theme/meegotouch-separator-" + (theme.inverted ? "inverted-" : "") + "background-horizontal"
+               }
+               Label {
+                   id: sectionLabel
+                   anchors {
+                       right: sectionRightMargin.left
+                       verticalCenter: parent.verticalCenter
+                   }
+                   text: section
+               }
+                Item {
+                    id: sectionRightMargin
+                    anchors {
+                        right: parent.right
+                    }
+                    width: Theme.paddingMedium
+                    height: Theme.paddingMedium
+                }
+            }
+            delegate: BackgroundItem {
+                id: listItem
+                height: Theme.itemSizeSmall
+                width: parent.width
+                Label {
+                    id: mainText
+                    x: Theme.paddingLarge
+                    text: Private.highlightSearch(model.name, Theme.highlightColor)
+                }
+                onClicked: Private.loadStation(model.name, model.code)
+            }
+        }
+    }
+    ScrollDecorator {
+        id: decorator
+        flickable: stationListView
+    }
+}
diff --git a/application/resources/sailfish/qml/pages/StationPage.qml b/application/resources/sailfish/qml/pages/StationPage.qml
new file mode 100644 (file)
index 0000000..555582a
--- /dev/null
@@ -0,0 +1,180 @@
+import QtQuick 2.0
+import Sailfish.Silica 1.0
+import net.cirulla.quandoparte 1.0
+
+Page {
+    property alias name: schedule.name
+    property alias code: schedule.code
+
+    tools: ToolBarLayout {
+        id: toolBar
+        ToolIcon {
+            iconId: "icon-m-toolbar-back" + (theme.inverted ? "-white": "")
+            onClicked: pageStack.pop()
+        }
+        ToolIcon {
+            iconId: "icon-m-toolbar-refresh" + (theme.inverted ? "-white": "")
+            onClicked: updateStation() }
+        ToolIcon {
+            iconId: "icon-m-toolbar-view-menu" + (theme.inverted ? "-white": "")
+            onClicked: menu.open()
+        }
+    }
+    PageHeader {
+        id: header
+        anchors.top: parent.top
+        selectedIndex: schedule.type
+        options: [
+            qsTr("Departures"),
+            qsTr("Arrivals")
+        ]
+    }
+    InfoBar {
+        id: infoBar
+        anchors.top: header.bottom
+        text: parent.name
+    }
+    Binding {
+        target: schedule
+        property: "type"
+        value: header.selectedIndex
+    }
+    LabelStyle {
+        id: labelStyle
+    }
+    Item {
+        id: view
+        anchors {
+            top: infoBar.bottom
+            bottom: parent.bottom
+            left: parent.left
+            right: parent.right
+        }
+        DroppedShadow {
+            id: shadow
+            anchors.top: view.top
+        }
+        ListView {
+            id: stationScheduleView
+            clip: true
+            visible: false
+            width: parent.width
+            cacheBuffer: 40
+            anchors {
+                top: shadow.top
+                bottom: parent.bottom
+            }
+            model: schedule
+            delegate: StationScheduleDelegate {
+                width: stationScheduleView.width
+                type: schedule.type
+                arrivalTime: model.arrivalTime
+                departureTime: model.departureTime
+                train: model.train
+                arrivalStation: model.arrivalStation
+                departureStation: model.departureStation
+                delay: model.delay
+                actualPlatform: model.actualPlatform
+                expectedPlatfrom: model.expectedPlatform
+            }
+        }
+        ScrollDecorator {
+            id: decorator
+            flickableItem: stationScheduleView
+        }
+        BusyIndicator {
+            id: busyIndicator
+            platformStyle: BusyIndicatorStyle {
+                size: "large"
+            }
+            anchors.centerIn: parent
+            running: visible
+        }
+        Item {
+            id: errorDisplay
+            anchors.centerIn: parent
+            Column {
+                anchors.centerIn: parent
+                spacing: UiConstants.DefaultMargin
+                Text {
+                    text: qsTr("Error!")
+                    width: parent.width
+                    font.pixelSize: UiConstants.HeaderFontPixelSize
+                    font.bold: UiConstants.HeaderFontBoldness
+                    horizontalAlignment: Text.AlignHCenter
+                }
+                Text {
+                    text: schedule.error
+                    width: parent.width
+                    font.pixelSize: UiConstants.HeaderFontPixelSize
+                    font.bold: UiConstants.DefaultFontBoldness
+                    horizontalAlignment: Text.AlignHCenter
+                }
+            }
+        }
+        states: [
+            State {
+                name: "loading"
+                when: !completed
+                PropertyChanges {
+                    target: stationScheduleView
+                    visible: false
+                }
+                PropertyChanges {
+                    target: errorDisplay
+                    visible: false
+                }
+                PropertyChanges {
+                    target: busyIndicator
+                    visible: true
+                }
+            },
+            State {
+                name: "ready"
+                PropertyChanges {
+                    target: stationScheduleView
+                    visible: true
+                }
+                PropertyChanges {
+                    target: errorDisplay
+                    visible: false
+                }
+                PropertyChanges {
+                    target: busyIndicator
+                    visible: false
+                }
+            },
+            State {
+                name: "error"
+                when: schedule.error
+                PropertyChanges {
+                    target: stationScheduleView
+                    visible: false
+                }
+                PropertyChanges {
+                    target: errorDisplay
+                    visible: true
+                }
+                PropertyChanges {
+                    target: busyIndicator
+                    visible: false
+                }
+            }
+        ]
+    }
+    StationScheduleModel {
+        id: schedule
+        onNameChanged: updateStation()
+        onLayoutChanged: if (error) view.state = "error"
+                         else view.state = "ready"
+    }
+    Component.onCompleted: {
+        updateTimer.timeout.connect(updateStation)
+        view.state = "loading"
+    }
+    function updateStation() {
+        view.state = "loading"
+        console.log("Updating station with " + schedule.name + ", " + schedule.code)
+        schedule.fetch(schedule.name, schedule.code)
+    }
+}