← Back to team overview

ubuntu-touch-coreapps-reviewers team mailing list archive

[Merge] lp:~nik90/ubuntu-weather-app/finish-listitem-migration into lp:ubuntu-weather-app/reboot

 

Nekhelesh Ramananthan has proposed merging lp:~nik90/ubuntu-weather-app/finish-listitem-migration into lp:ubuntu-weather-app/reboot.

Commit message:

* Finished the migration to the new SDK list items
* Locked weather app in the Portrait orientation until we get some landscape designs
* Made the page with bottom edge animation less jarring when it reaches the top by adding a fake header (similar to what the clock app does)

Requested reviews:
  Ubuntu Weather Developers (ubuntu-weather-dev)

For more details, see:
https://code.launchpad.net/~nik90/ubuntu-weather-app/finish-listitem-migration/+merge/263136

This MP implements the following,

* Finish the migration to the new SDK list items
* Lock weather app in the Portrait orientation until we get some landscape designs
* Make the page with bottom edge animation less jarring when it reaches the top by adding a fake header (similar to what the clock app does)
-- 
Your team Ubuntu Weather Developers is requested to review the proposed merge of lp:~nik90/ubuntu-weather-app/finish-listitem-migration into lp:ubuntu-weather-app/reboot.
=== modified file 'app/components/CMakeLists.txt'
--- app/components/CMakeLists.txt	2015-03-03 18:37:59 +0000
+++ app/components/CMakeLists.txt	2015-06-26 15:22:05 +0000
@@ -1,5 +1,3 @@
-add_subdirectory(ListItemActions)
-
 file(GLOB COMPONENTS_QML_JS_FILES *.qml *.js)
 
 add_custom_target(ubuntu-weather-app_components_QMlFiles ALL SOURCES ${COMPONENTS_QML_JS_FILES})

=== added file 'app/components/FakeHeader.qml'
--- app/components/FakeHeader.qml	1970-01-01 00:00:00 +0000
+++ app/components/FakeHeader.qml	2015-06-26 15:22:05 +0000
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2014 Canonical Ltd
+  *
+   * This file is part of Ubuntu Clock App
+    *
+     * Ubuntu Clock App is free software: you can redistribute it and/or modify
+      * it under the terms of the GNU General Public License version 3 as
+       * published by the Free Software Foundation.
+        *
+         * Ubuntu Clock App is distributed in the hope that it will be useful,
+          * but WITHOUT ANY WARRANTY; without even the implied warranty of
+           * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+            * GNU General Public License for more details.
+             *
+              * You should have received a copy of the GNU General Public License
+               * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+                */
+
+import QtQuick 2.4
+import Ubuntu.Components 1.2
+
+Column {
+    id: fakeHeader
+
+    height: units.gu(9)
+
+    Rectangle {
+        height: units.gu(7)
+        width: parent.width
+        color: Theme.palette.normal.background
+    }
+
+    Rectangle {
+        color: "#C9C9C9"
+        height: units.gu(2)
+        anchors.left: parent.left
+        anchors.right: parent.right
+    }
+}

=== removed directory 'app/components/ListItemActions'
=== removed file 'app/components/ListItemActions/CMakeLists.txt'
--- app/components/ListItemActions/CMakeLists.txt	2015-03-03 18:37:59 +0000
+++ app/components/ListItemActions/CMakeLists.txt	1970-01-01 00:00:00 +0000
@@ -1,5 +0,0 @@
-file(GLOB LISTITEMACTIONS_QML_JS_FILES *.qml *.js)
-
-add_custom_target(ubuntu-weather-app_listitemactions_QMlFiles ALL SOURCES ${LISTITEMACTIONS_QML_JS_FILES})
-
-install(FILES ${LISTITEMACTIONS_QML_JS_FILES} DESTINATION ${UBUNTU-WEATHER_APP_DIR}/components/ListItemActions)

=== removed file 'app/components/ListItemActions/CheckBox.qml'
--- app/components/ListItemActions/CheckBox.qml	2015-06-18 01:45:57 +0000
+++ app/components/ListItemActions/CheckBox.qml	1970-01-01 00:00:00 +0000
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2012-2014, 2015 Canonical, Ltd.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 3.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-import QtQuick 2.4
-import Ubuntu.Components 1.2
-
-CheckBox {
-    checked: root.selected
-    width: implicitWidth
-    // disable item mouse area to avoid conflicts with parent mouse area
-    __mouseArea.enabled: false
-}

=== removed file 'app/components/ListItemActions/Remove.qml'
--- app/components/ListItemActions/Remove.qml	2015-06-18 01:42:03 +0000
+++ app/components/ListItemActions/Remove.qml	1970-01-01 00:00:00 +0000
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2014, 2015 Andrew Hayzen <ahayzen@xxxxxxxxx>
- *                    Daniel Holm <d.holmen@xxxxxxxxx>
- *                    Victor Thompson <victor.thompson@xxxxxxxxx>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 3.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-import QtQuick 2.4
-import Ubuntu.Components 1.2
-
-Action {
-    id: removeAction
-    iconName: "delete"
-    objectName: "swipeDeleteAction"
-    text: i18n.tr("Remove")
-}

=== removed file 'app/components/ListItemReorderComponent.qml'
--- app/components/ListItemReorderComponent.qml	2015-06-18 01:42:03 +0000
+++ app/components/ListItemReorderComponent.qml	1970-01-01 00:00:00 +0000
@@ -1,106 +0,0 @@
-/*
- * Copyright (C) 2013, 2014, 2015
- *      Andrew Hayzen <ahayzen@xxxxxxxxx>
- *      Nekhelesh Ramananthan <krnekhelesh@xxxxxxxxx>
- *      Victor Thompson <victor.thompson@xxxxxxxxx>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 3.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-import QtQuick 2.4
-import Ubuntu.Components 1.2
-
-
-Item {
-    id: actionReorder
-    width: units.gu(4)
-
-    Icon {
-        anchors {
-            horizontalCenter: parent.horizontalCenter
-            verticalCenter: parent.verticalCenter
-        }
-        name: "navigation-menu"  // TODO: use proper image
-        height: width
-        width: units.gu(3)
-    }
-
-    MouseArea {
-        id: actionReorderMouseArea
-        anchors {
-            fill: parent
-        }
-        property int startY: 0
-        property int startContentY: 0
-
-        onPressed: {
-            root.parent.parent.interactive = false;  // stop scrolling of listview
-            startY = root.y;
-            startContentY = root.parent.parent.contentY;
-            root.z += 10;  // force ontop of other elements
-
-            console.debug("Reorder listitem pressed", root.y)
-        }
-        onMouseYChanged: root.y += mouse.y - (root.height / 2);
-        onReleased: {
-            console.debug("Reorder diff by position", getDiff());
-
-            var diff = getDiff();
-
-            // Remove the height of the actual item if moved down
-            if (diff > 0) {
-                diff -= 1;
-            }
-
-            root.parent.parent.interactive = true;  // reenable scrolling
-
-            if (diff === 0) {
-                // Nothing has changed so reset the item
-                // z index is restored after animation
-                resetListItemYAnimation.start();
-            }
-            else {
-                var newIndex = index + diff;
-
-                if (newIndex < 0) {
-                    newIndex = 0;
-                }
-                else if (newIndex > root.parent.parent.count - 1) {
-                    newIndex = root.parent.parent.count - 1;
-                }
-
-                root.z -= 10;  // restore z index
-                reorder(index, newIndex)
-            }
-        }
-
-        function getDiff() {
-            // Get the amount of items that have been passed over (by centre)
-            return Math.round((((root.y - startY) + (root.parent.parent.contentY - startContentY)) / root.height) + 0.5);
-        }
-    }
-
-    SequentialAnimation {
-        id: resetListItemYAnimation
-        UbuntuNumberAnimation {
-            target: root;
-            property: "y";
-            to: actionReorderMouseArea.startY
-        }
-        ScriptAction {
-            script: {
-                root.z -= 10;  // restore z index
-            }
-        }
-    }
-}

=== removed file 'app/components/ListItemWithActions.qml'
--- app/components/ListItemWithActions.qml	2015-06-18 01:42:03 +0000
+++ app/components/ListItemWithActions.qml	1970-01-01 00:00:00 +0000
@@ -1,496 +0,0 @@
-/*
- * Copyright (C) 2012-2015 Canonical, Ltd.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 3.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-import QtQuick 2.4
-import Ubuntu.Components 1.2
-import Ubuntu.Components.ListItems 1.0 as ListItem
-
-
-Item {
-    id: root
-    width: parent.width
-
-    property Action leftSideAction: null
-    property list<Action> rightSideActions
-    property double defaultHeight: units.gu(8)
-    property bool locked: false
-    property Action activeAction: null
-    property var activeItem: null
-    property bool triggerActionOnMouseRelease: false
-    property color color: Theme.palette.normal.background
-    property color selectedColor: "#E6E6E6"
-    property bool selected: false
-    property bool selectionMode: false
-    property alias internalAnchors: mainContents.anchors
-    default property alias contents: mainContents.children
-
-    readonly property double actionWidth: units.gu(4)
-    readonly property double leftActionWidth: units.gu(10)
-    readonly property double actionThreshold: actionWidth * 0.4
-    readonly property double threshold: 0.4
-    readonly property string swipeState: main.x == 0 ? "Normal" : main.x > 0 ? "LeftToRight" : "RightToLeft"
-    readonly property alias swipping: mainItemMoving.running
-    readonly property bool _showActions: mouseArea.pressed || swipeState != "Normal" || swipping
-
-    property alias _main: main  // CUSTOM
-    property alias pressed: mouseArea.pressed  // CUSTOM
-
-    /* internal */
-    property var _visibleRightSideActions: filterVisibleActions(rightSideActions)
-
-    signal itemClicked(var mouse)
-    signal itemPressAndHold(var mouse)
-
-    function returnToBoundsRTL(direction)
-    {
-        var actionFullWidth = actionWidth + units.gu(2)
-
-        // go back to normal state if swipping reverse
-        if (direction === "LTR") {
-            updatePosition(0)
-            return
-        } else if (!triggerActionOnMouseRelease) {
-            updatePosition(-rightActionsView.width + units.gu(2))
-            return
-        }
-
-        var xOffset = Math.abs(main.x)
-        var index = Math.min(Math.floor(xOffset / actionFullWidth), _visibleRightSideActions.length)
-        var newX = 0
-
-        if (index === _visibleRightSideActions.length) {
-            newX = -(rightActionsView.width - units.gu(2))
-        } else if (index >= 1) {
-            newX = -(actionFullWidth * index)
-        }
-
-        updatePosition(newX)
-    }
-
-    function returnToBoundsLTR(direction)
-    {
-        var finalX = leftActionWidth
-        if ((direction === "RTL") || (main.x <= (finalX * root.threshold)))
-            finalX = 0
-        updatePosition(finalX)
-    }
-
-    function returnToBounds(direction)
-    {
-        if (main.x < 0) {
-            returnToBoundsRTL(direction)
-        } else if (main.x > 0) {
-            returnToBoundsLTR(direction)
-        } else {
-            updatePosition(0)
-        }
-    }
-
-    function contains(item, point, marginX)
-    {
-        var itemStartX = item.x - marginX
-        var itemEndX = item.x + item.width + marginX
-        return (point.x >= itemStartX) && (point.x <= itemEndX) &&
-               (point.y >= item.y) && (point.y <= (item.y + item.height));
-    }
-
-    function getActionAt(point)
-    {
-        if (leftSideAction && contains(leftActionViewLoader.item, point, 0)) {
-            return leftSideAction
-        } else if (contains(rightActionsView, point, 0)) {
-            var newPoint = root.mapToItem(rightActionsView, point.x, point.y)
-            for (var i = 0; i < rightActionsRepeater.count; i++) {
-                var child = rightActionsRepeater.itemAt(i)
-                if (contains(child, newPoint, units.gu(1))) {
-                    return i
-                }
-            }
-        }
-        return -1
-    }
-
-    function updateActiveAction()
-    {
-        if (triggerActionOnMouseRelease &&
-            (main.x <= -(root.actionWidth + units.gu(2))) &&
-            (main.x > -(rightActionsView.width - units.gu(2)))) {
-            var actionFullWidth = actionWidth + units.gu(2)
-            var xOffset = Math.abs(main.x)
-            var index = Math.min(Math.floor(xOffset / actionFullWidth), _visibleRightSideActions.length)
-            index = index - 1
-            if (index > -1) {
-                root.activeItem = rightActionsRepeater.itemAt(index)
-                root.activeAction = root._visibleRightSideActions[index]
-            }
-        } else {
-            root.activeAction = null
-        }
-    }
-
-    function resetSwipe()
-    {
-        updatePosition(0)
-    }
-
-    function filterVisibleActions(actions)
-    {
-        var visibleActions = []
-        for(var i = 0; i < actions.length; i++) {
-            var action = actions[i]
-            if (action.visible) {
-                visibleActions.push(action)
-            }
-        }
-        return visibleActions
-    }
-
-    function updatePosition(pos)
-    {
-        if (!root.triggerActionOnMouseRelease && (pos !== 0)) {
-            mouseArea.state = pos > 0 ? "RightToLeft" : "LeftToRight"
-        } else {
-            mouseArea.state = ""
-        }
-        main.x = pos
-    }
-
-    // CUSTOM remove animation
-    SequentialAnimation {
-        id: removeAnimation
-
-        property var action
-
-        UbuntuNumberAnimation {
-            target: root
-            duration: UbuntuAnimation.BriskDuration
-            property: "height";
-            to: 0
-        }
-        ScriptAction {
-            script: removeAnimation.action.trigger()
-        }
-    }
-
-    states: [
-        State {
-            name: "select"
-            when: selectionMode || selected
-            PropertyChanges {
-                target: selectionIcon
-                source: Qt.resolvedUrl("ListItemActions/CheckBox.qml")
-                anchors.leftMargin: units.gu(2)
-            }
-            PropertyChanges {
-                target: root
-                locked: true
-            }
-            PropertyChanges {
-                target: main
-                x: 0
-            }
-        }
-    ]
-
-    height: defaultHeight
-    //clip: height !== defaultHeight  // CUSTOM
-
-    Loader {  // CUSTOM
-        id: leftActionViewLoader
-        anchors {
-            top: parent.top
-            bottom: parent.bottom
-            right: main.left
-        }
-        asynchronous: true
-        sourceComponent: leftSideAction ? leftActionViewComponent : undefined
-    }
-
-    Component {  // CUSTOM
-        id: leftActionViewComponent
-
-        Rectangle {
-            id: leftActionView
-            width: root.leftActionWidth + actionThreshold
-            color: UbuntuColors.red
-
-            Icon {
-                id: leftActionIcon
-                anchors {
-                    centerIn: parent
-                    horizontalCenterOffset: actionThreshold / 2
-                }
-                objectName: "swipeDeleteAction"  // CUSTOM
-                name: leftSideAction && _showActions ? leftSideAction.iconName : ""
-                color: Theme.palette.selected.field
-                height: units.gu(3)
-                width: units.gu(3)
-            }
-        }
-    }
-
-    //Rectangle {
-    Item {  // CUSTOM
-       id: rightActionsView
-
-       anchors {
-           top: main.top
-           left: main.right
-           bottom: main.bottom
-       }
-       visible: _visibleRightSideActions.length > 0
-       width: rightActionsRepeater.count > 0 ? rightActionsRepeater.count * (root.actionWidth + units.gu(2)) + root.actionThreshold + units.gu(2) : 0
-       // color: "white"  // CUSTOM
-
-       Row {
-           anchors{
-               top: parent.top
-               left: parent.left
-               leftMargin: units.gu(2)
-               right: parent.right
-               rightMargin: units.gu(2)
-               bottom: parent.bottom
-           }
-           spacing: units.gu(2)
-           Repeater {
-               id: rightActionsRepeater
-
-               model: _showActions ? _visibleRightSideActions : []
-               Item {
-                   property alias image: img
-
-                   height: rightActionsView.height
-                   width: root.actionWidth
-
-                   Icon {
-                       id: img
-
-                       anchors.centerIn: parent
-                       objectName: rightSideActions[index].objectName  // CUSTOM
-                       width: units.gu(3)
-                       height: units.gu(3)
-                       name: modelData.iconName
-                       color: root.activeAction === modelData ? UbuntuColors.orange : UbuntuColors.coolGrey  // CUSTOM
-                   }
-               }
-           }
-       }
-    }
-
-    Rectangle {
-        id: main
-        objectName: "mainItem"
-
-        anchors {
-            top: parent.top
-            bottom: parent.bottom
-        }
-
-        width: parent.width
-        color: root.selected ? root.selectedColor : root.color
-
-        Loader {
-            id: selectionIcon
-
-            anchors {
-                left: main.left
-                verticalCenter: main.verticalCenter
-            }
-            asynchronous: true  // CUSTOM
-            width: (status === Loader.Ready) ? item.implicitWidth : 0
-            visible: (status === Loader.Ready) && (item.width === item.implicitWidth)
-
-            Behavior on width {
-                NumberAnimation {
-                    duration: UbuntuAnimation.SnapDuration
-                }
-            }
-        }
-
-        Item {
-            id: mainContents
-
-            anchors {
-                left: selectionIcon.right
-                //leftMargin: units.gu(2)  // CUSTOM
-                top: parent.top
-                //topMargin: units.gu(1)  // CUSTOM
-                right: parent.right
-                //rightMargin: units.gu(2)  // CUSTOM
-                bottom: parent.bottom
-                //bottomMargin: units.gu(1)  // CUSTOM
-            }
-        }
-
-        Behavior on x {
-            UbuntuNumberAnimation {
-                id: mainItemMoving
-
-                easing.type: Easing.OutElastic
-                duration: UbuntuAnimation.SlowDuration
-            }
-        }
-    }
-
-    SequentialAnimation {
-        id: triggerAction
-
-        property var currentItem: root.activeItem ? root.activeItem.image : null
-
-        running: false
-        ParallelAnimation {
-            UbuntuNumberAnimation {
-                target: triggerAction.currentItem
-                property: "opacity"
-                from: 1.0
-                to: 0.0
-                duration: UbuntuAnimation.SlowDuration
-                easing {type: Easing.InOutBack; }
-            }
-            UbuntuNumberAnimation {
-                target: triggerAction.currentItem
-                properties: "width, height"
-                from: units.gu(3)
-                to: root.actionWidth
-                duration: UbuntuAnimation.SlowDuration
-                easing {type: Easing.InOutBack; }
-            }
-        }
-        PropertyAction {
-            target: triggerAction.currentItem
-            properties: "width, height"
-            value: units.gu(3)
-        }
-        PropertyAction {
-            target: triggerAction.currentItem
-            properties: "opacity"
-            value: 1.0
-        }
-        ScriptAction {
-            script: {
-                root.activeAction.triggered(root)
-                mouseArea.state = ""
-            }
-        }
-        PauseAnimation {
-            duration: 500
-        }
-        UbuntuNumberAnimation {
-            target: main
-            property: "x"
-            to: 0
-        }
-    }
-
-    MouseArea {
-        id: mouseArea
-
-        property bool locked: root.locked || ((root.leftSideAction === null) && (root._visibleRightSideActions.count === 0))  // CUSTOM
-        property bool manual: false
-        property string direction: "None"
-        property real lastX: -1
-
-        anchors.fill: parent
-        drag {
-            target: locked ? null : main
-            axis: Drag.XAxis
-            minimumX: rightActionsView.visible ? -(rightActionsView.width) : 0
-            maximumX: leftSideAction ? leftActionViewLoader.item.width : 0
-            threshold: root.actionThreshold
-        }
-
-        states: [
-            State {
-                name: "LeftToRight"
-                PropertyChanges {
-                    target: mouseArea
-                    drag.maximumX: 0
-                }
-            },
-            State {
-                name: "RightToLeft"
-                PropertyChanges {
-                    target: mouseArea
-                    drag.minimumX: 0
-                }
-            }
-        ]
-
-        onMouseXChanged: {
-            var offset = (lastX - mouseX)
-            if (Math.abs(offset) <= root.actionThreshold) {
-                return
-            }
-            lastX = mouseX
-            direction = offset > 0 ? "RTL" : "LTR";
-        }
-
-        onPressed: {
-            lastX = mouse.x
-        }
-
-        onReleased: {
-            if (root.triggerActionOnMouseRelease && root.activeAction) {
-                triggerAction.start()
-            } else {
-                root.returnToBounds()
-                root.activeAction = null
-            }
-            lastX = -1
-            direction = "None"
-        }
-        onClicked: {
-            if (selectionMode) {  // CUSTOM - selecting a listitem should toggle selection if in selectionMode
-                selected = !selected
-                return
-            } else if (main.x === 0) {
-                root.itemClicked(mouse)
-            } else if (main.x > 0) {
-                var action = getActionAt(Qt.point(mouse.x, mouse.y))
-                if (action && action !== -1) {
-                    //action.triggered(root)
-                    removeAnimation.action = action  // CUSTOM - use our animation instead
-                    removeAnimation.start()  // CUSTOM
-                }
-            } else {
-                var actionIndex = getActionAt(Qt.point(mouse.x, mouse.y))
-
-                if (actionIndex !== -1 && actionIndex !== leftSideAction) {  // CUSTOM - can be leftAction
-                    root.activeItem = rightActionsRepeater.itemAt(actionIndex)
-                    root.activeAction = root.rightSideActions[actionIndex]
-                    triggerAction.start()
-                    return
-                }
-            }
-            root.resetSwipe()
-        }
-
-        onPositionChanged: {
-            if (mouseArea.pressed) {
-                updateActiveAction()
-
-                listItemSwiping(index)  // CUSTOM - tells other listitems to dismiss any swipe
-            }
-        }
-        onPressAndHold: {
-            if (main.x === 0) {
-                root.itemPressAndHold(mouse)
-            }
-        }
-
-        z: -1
-    }
-}

=== modified file 'app/components/MultiSelectHeadState.qml'
--- app/components/MultiSelectHeadState.qml	2015-06-18 01:42:03 +0000
+++ app/components/MultiSelectHeadState.qml	2015-06-26 15:22:05 +0000
@@ -21,18 +21,29 @@
 
 PageHeadState {
     id: selectionState
+
+    property ListView listview
+    property bool removable: false
+    property Page thisPage
+
+    signal removed(var selectedItems)
+
+    head: thisPage.head
+    name: "selection"
+
     actions: [
         Action {
             iconName: "select"
             text: i18n.tr("Select All")
             onTriggered: {
-                if (listview.selectedItems.length === listview.model.count) {
+                if (listview.selectedItems.length === listview.count) {
                     listview.clearSelection()
                 } else {
                     listview.selectAll()
                 }
             }
         },
+
         Action {
             enabled: listview.selectedItems.length > 0
             iconName: "delete"
@@ -41,32 +52,17 @@
 
             onTriggered: {
                 removed(listview.selectedItems)
-
                 listview.closeSelection()
             }
         }
-
     ]
+
     backAction: Action {
         text: i18n.tr("Cancel selection")
         iconName: "back"
         onTriggered: {
             listview.clearSelection()
-            listview.state = "normal"
+            thisPage.state = "default"
         }
     }
-    head: thisPage.head
-    name: "selection"
-
-    PropertyChanges {
-        target: thisPage.head
-        backAction: selectionState.backAction
-        actions: selectionState.actions
-    }
-
-    property ListView listview
-    property bool removable: false
-    property Page thisPage
-
-    signal removed(var selectedItems)
 }

=== modified file 'app/components/MultiSelectListView.qml'
--- app/components/MultiSelectListView.qml	2015-06-18 01:42:03 +0000
+++ app/components/MultiSelectListView.qml	2015-06-26 15:22:05 +0000
@@ -20,21 +20,24 @@
 import QtQuick 2.4
 import Ubuntu.Components 1.2
 
-
 WeatherListView {
-    property var selectedItems: []
-
     signal clearSelection()
     signal closeSelection()
     signal selectAll()
-
-    onClearSelection: selectedItems = []
+    signal reorder(int from, int to)
+
+    onClearSelection: {
+        ViewItems.selectedIndices = []
+    }
+
     onCloseSelection: {
         clearSelection()
-        state = "normal"
+        ViewItems.selectMode = false
+        ViewItems.dragMode = false
     }
+
     onSelectAll: {
-        var tmp = selectedItems
+        var tmp = []
 
         for (var i=0; i < model.count; i++) {
             if (tmp.indexOf(i) === -1) {
@@ -42,11 +45,27 @@
             }
         }
 
-        selectedItems = tmp
+        ViewItems.selectedIndices = tmp
     }
+
     onVisibleChanged: {
         if (!visible) {
             closeSelection()
         }
     }
+
+    moveDisplaced: Transition {
+        UbuntuNumberAnimation {
+            property: "y"
+        }
+    }
+
+    ViewItems.onDragUpdated: {
+        if (event.status === ListItemDrag.Moving) {
+            event.accept = false
+        } else if (event.status === ListItemDrag.Dropped) {
+            model.move(event.from, event.to, 1)
+            reorder(event.from, event.to)
+        }
+    }
 }

=== modified file 'app/components/PageWithBottomEdge.qml'
--- app/components/PageWithBottomEdge.qml	2015-06-18 01:45:57 +0000
+++ app/components/PageWithBottomEdge.qml	2015-06-26 15:22:05 +0000
@@ -77,7 +77,7 @@
     property bool reloadBottomEdgePage: true
 
     readonly property alias bottomEdgePage: edgeLoader.item
-    readonly property bool isReady: ((bottomEdge.y === 0) && bottomEdgePageLoaded && edgeLoader.item.active)
+    readonly property bool isReady: ((bottomEdge.y === fakeHeader.height) && bottomEdgePageLoaded && edgeLoader.item.active)
     readonly property bool isCollapsed: (bottomEdge.y === page.height)
     readonly property bool bottomEdgePageLoaded: (edgeLoader.status == Loader.Ready)
 
@@ -91,7 +91,6 @@
     signal bottomEdgeReleased()
     signal bottomEdgeDismissed()
 
-
     function showBottomEdgePage(source, properties)
     {
         edgeLoader.setSource(source, properties)
@@ -152,6 +151,9 @@
 
         property bool hidden: (activeFocus === false) || ((bottomEdge.y - units.gu(1)) < tip.y)
 
+        // CUSTOM
+        property bool isAnimating: true
+
         enabled: mouseArea.enabled
         visible: page.bottomEdgeEnabled
         anchors {
@@ -167,6 +169,10 @@
                     UbuntuNumberAnimation {
                         duration: UbuntuAnimation.SnapDuration
                     }
+                    // CUSTOM
+                    ScriptAction {
+                        script: tip.isAnimating = false
+                    }
                 }
             }
         }
@@ -232,7 +238,6 @@
             left: parent.left
             right: parent.right
             bottom: parent.bottom
-
         }
         height: bottomEdge.tipHeight
         z: 1
@@ -265,12 +270,31 @@
         }
     }
 
+    // CUSTOM fake header to make the page with bottom edge transition smoother
+    FakeHeader {
+        id: fakeHeader
+
+        anchors {
+            left: parent.left
+            right: parent.right
+        }
+        y: -fakeHeader.height + (fakeHeader.height * (page.height - bottomEdge.y)) / (page.height - fakeHeader.height)
+        z: bgVisual.z + 1
+
+        Behavior on y {
+            UbuntuNumberAnimation {
+                duration: UbuntuAnimation.SnapDuration
+            }
+        }
+    }
+
     Rectangle {
         id: bottomEdge
         objectName: "bottomEdge"
 
         readonly property int tipHeight: units.gu(3)
-        readonly property int pageStartY: 0
+        // CUSTOM value
+        readonly property int pageStartY: fakeHeader.height
 
         z: 1
         color: Theme.palette.normal.background
@@ -281,6 +305,7 @@
         }
         height: page.height
         y: height
+
         visible: !page.isCollapsed
         state: "collapsed"
         states: [
@@ -290,6 +315,11 @@
                     target: bottomEdge
                     y: bottomEdge.height
                 }
+                // CUSTOM
+                PropertyChanges {
+                    target: fakeHeader
+                    y: -fakeHeader.height
+                }
             },
             State {
                 name: "expanded"
@@ -297,6 +327,11 @@
                     target: bottomEdge
                     y: bottomEdge.pageStartY
                 }
+                // CUSTOM
+                PropertyChanges {
+                    target: fakeHeader
+                    y: 0
+                }
             },
             State {
                 name: "floating"
@@ -313,12 +348,20 @@
                 to: "expanded"
                 SequentialAnimation {
                     alwaysRunToEnd: true
-
-                    SmoothedAnimation {
-                        target: bottomEdge
-                        property: "y"
-                        duration: UbuntuAnimation.FastDuration
-                        easing.type: Easing.Linear
+                    ParallelAnimation {
+                        SmoothedAnimation {
+                            target: bottomEdge
+                            property: "y"
+                            duration: UbuntuAnimation.FastDuration
+                            easing.type: Easing.Linear
+                        }
+                        // CUSTOM
+                        SmoothedAnimation {
+                            target: fakeHeader
+                            property: "y"
+                            duration: UbuntuAnimation.FastDuration
+                            easing.type: Easing.Linear
+                        }
                     }
                     SmoothedAnimation {
                         target: edgeLoader
@@ -353,17 +396,24 @@
                             edgeLoader.item.active = false
                         }
                     }
-                    SmoothedAnimation {
-                        target: bottomEdge
-                        property: "y"
-                        duration: UbuntuAnimation.SlowDuration
+                    ParallelAnimation {
+                        SmoothedAnimation {
+                            target: bottomEdge
+                            property: "y"
+                            duration: UbuntuAnimation.SlowDuration
+                        }
+                        // CUSTOM
+                        SmoothedAnimation {
+                            target: fakeHeader
+                            property: "y"
+                            duration: UbuntuAnimation.SlowDuration
+                        }
                     }
                     ScriptAction {
                         script: {
                             // destroy current bottom page
                             if (page.reloadBottomEdgePage) {
                                 edgeLoader.active = false
-                                // tip will receive focus on page active true
                             } else {
                                 tip.forceActiveFocus()
                             }
@@ -379,10 +429,10 @@
             Transition {
                 from: "floating"
                 to: "collapsed"
-                SmoothedAnimation {
+                // MODIFIED
+                UbuntuNumberAnimation {
                     target: bottomEdge
-                    property: "y"
-                    duration: UbuntuAnimation.FastDuration
+                    property: "opacity"
                 }
             }
         ]

=== removed file 'app/components/WeatherListItem.qml'
--- app/components/WeatherListItem.qml	2015-06-21 15:02:05 +0000
+++ app/components/WeatherListItem.qml	1970-01-01 00:00:00 +0000
@@ -1,137 +0,0 @@
-/*
- * Copyright (C) 2013, 2014, 2015
- *      Andrew Hayzen <ahayzen@xxxxxxxxx>
- *      Nekhelesh Ramananthan <krnekhelesh@xxxxxxxxx>
- *      Victor Thompson <victor.thompson@xxxxxxxxx>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 3.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-import QtQuick 2.4
-import Ubuntu.Components 1.2
-
-ListItemWithActions {
-    id: root
-
-    property int listItemIndex: index
-    property bool multiselectable: false
-    property int previousListItemIndex: -1
-    property bool reorderable: false
-
-    signal reorder(int from, int to)
-
-    onItemPressAndHold: {
-        if (multiselectable) {
-            selectionMode = true
-        }
-    }
-
-    onListItemIndexChanged: {
-        var i = parent.parent.selectedItems.lastIndexOf(previousListItemIndex)
-
-        if (i !== -1) {
-            parent.parent.selectedItems[i] = listItemIndex
-        }
-
-        previousListItemIndex = listItemIndex
-    }
-
-    onSelectedChanged: {
-        if (selectionMode) {
-            var tmp = parent.parent.selectedItems
-
-            if (selected) {
-                if (parent.parent.selectedItems.indexOf(listItemIndex) === -1) {
-                    tmp.push(listItemIndex)
-                    parent.parent.selectedItems = tmp
-                }
-            } else {
-                tmp.splice(parent.parent.selectedItems.indexOf(listItemIndex), 1)
-                parent.parent.selectedItems = tmp
-            }
-        }
-    }
-
-    onSelectionModeChanged: {
-        if (reorderable && selectionMode) {
-            resetSwipe()
-        }
-
-        for (var j=0; j < _main.children.length; j++) {
-            if (_main.children[j] !== actionReorderLoader) {
-                _main.children[j].anchors.rightMargin = reorderable && selectionMode ? actionReorderLoader.width + units.gu(2) : 0
-            }
-        }
-
-        parent.parent.state = selectionMode ? "multiselectable" : "normal"
-
-        if (!selectionMode) {
-            selected = false
-        }
-    }
-
-    /* Highlight the listitem on press */
-    Rectangle {
-        id: listItemBrighten
-        color: root.pressed ? UbuntuColors.coolGrey : "transparent"
-        opacity: 0.1
-        height: root.height
-        x: root.x - parent.x  // -parent.x due to selectionIcon in ListItemWithActions
-        width: root.width
-    }
-
-    /* Reorder Component */
-    Loader {
-        id: actionReorderLoader
-        active: reorderable && selectionMode && root.parent.parent.selectedItems.length === 0
-        anchors {
-            bottom: parent.bottom
-            right: parent.right
-            rightMargin: units.gu(1)
-            top: parent.top
-        }
-        asynchronous: true
-        source: "ListItemReorderComponent.qml"
-    }
-
-    Item {
-        Connections {  // Only allow one ListItem to be swiping at any time
-            target: weatherApp
-            onListItemSwiping: {
-                if (i !== index) {
-                    root.resetSwipe();
-                }
-            }
-        }
-
-        Connections {  // Connections from signals in the ListView
-            target: root.parent.parent
-            onClearSelection: selected = false
-            onFlickingChanged: {
-                if (root.parent.parent.flicking) {
-                    root.resetSwipe()
-                }
-            }
-            onSelectAll: selected = true
-            onStateChanged: selectionMode = root.parent.parent.state === "multiselectable"
-        }
-    }
-
-    Component.onCompleted: {  // reload settings as delegates are destroyed
-        if (parent.parent.selectedItems.indexOf(index) !== -1) {
-            selected = true
-        }
-
-        selectionMode = root.parent.parent.state === "multiselectable"
-    }
-}

=== modified file 'app/components/WeatherListView.qml'
--- app/components/WeatherListView.qml	2015-06-18 01:42:03 +0000
+++ app/components/WeatherListView.qml	2015-06-26 15:22:05 +0000
@@ -20,8 +20,7 @@
 import QtQuick 2.4
 import Ubuntu.Components 1.2
 
-
-ListView {
+UbuntuListView {
     Component.onCompleted: {
         // FIXME: workaround for qtubuntu not returning values depending on the grid unit definition
         // for Flickable.maximumFlickVelocity and Flickable.flickDeceleration

=== modified file 'app/ui/AddLocationPage.qml'
--- app/ui/AddLocationPage.qml	2015-06-21 20:14:39 +0000
+++ app/ui/AddLocationPage.qml	2015-06-26 15:22:05 +0000
@@ -234,7 +234,7 @@
                 if (storage.addLocation(citiesModel.get(index))) {
                     mainPageStack.pop()
                 } else {
-                    PopupUtils.open(locationExistsComponent, addPage)
+                    PopupUtils.open(locationExistsComponent, addLocationPage)
                 }
             }
         }

=== modified file 'app/ui/LocationsPage.qml'
--- app/ui/LocationsPage.qml	2015-06-21 13:28:09 +0000
+++ app/ui/LocationsPage.qml	2015-06-26 15:22:05 +0000
@@ -18,39 +18,61 @@
 
 import QtQuick 2.4
 import Ubuntu.Components 1.2
-import Ubuntu.Components.ListItems 0.1 as ListItem
+import Ubuntu.Components.ListItems 1.0 as ListItems
 import "../components"
-import "../components/ListItemActions"
-
 
 Page {
     id: locationsPage
+
     // Set to null otherwise the first delegate appears +header.height down the page
     flickable: null
     title: i18n.tr("Locations")
 
-    state: locationsListView.state === "multiselectable" ? "selection" : "default"
+    state: "default"
     states: [
         PageHeadState {
-            id: defaultState
             name: "default"
+            head: locationsPage.head
             actions: [
                 Action {
                     iconName: "add"
-                    onTriggered: mainPageStack.push(Qt.resolvedUrl("AddLocationPage.qml"))
+                    onTriggered: {
+                        mainPageStack.push(Qt.resolvedUrl("AddLocationPage.qml"))
+                    }
                 }
             ]
-            PropertyChanges {
-                target: locationsPage.head
-                actions: defaultState.actions
+            backAction: Action {
+                iconName: "down"
+                onTriggered: {
+                    pageStack.pop()
+                }
             }
         },
-        MultiSelectHeadState {
-            listview: locationsListView
-            removable: true
-            thisPage: locationsPage
 
-            onRemoved: storage.removeMultiLocations(selectedItems.slice())
+        PageHeadState {
+            name: "selection"
+            head: locationsPage.head
+            when: locationsListView.ViewItems.selectMode
+            backAction: Action {
+                iconName: "back"
+                onTriggered: {
+                    locationsListView.closeSelection()
+                    locationsPage.state = "default"
+                }
+            }
+            actions: [
+                Action {
+                    iconName: "delete"
+                    enabled: locationsListView.ViewItems.selectedIndices.length !== 0
+                    onTriggered: {
+                        for (var i=0; i<locationsListView.ViewItems.selectedIndices.length; i++) {
+                            storage.removeLocation(locationsListView.ViewItems.selectedIndices[i])
+                        }
+                        locationsListView.closeSelection()
+                        locationsPage.state = "default"
+                    }
+                }
+            ]
         }
     ]
 
@@ -58,27 +80,29 @@
         id: currentLocationModel
     }
 
+    ListModel {
+        id: locationsModel
+    }
+
     MultiSelectListView {
         id: locationsListView
-        anchors {
-            fill: parent
-        }
-        model: ListModel {
-            id: locationsModel
-        }
+
+        clip: true
+        anchors.fill: parent
+        model: locationsModel
+
         header: MultiSelectListView {
             id: currentLocationListView
-            anchors {
-                left: parent.left
-                right: parent.right
-            }
-            height: units.gu(8)
+
+            width: parent.width
+            height: units.gu(7)
             interactive: false
             model: currentLocationModel
-            delegate: WeatherListItem {
+
+            delegate: ListItem {
                 id: currentLocationListItem
 
-                onItemClicked: {
+                onClicked: {
                     settings.current = index;
                     pageStack.pop()
                 }
@@ -147,32 +171,38 @@
                     horizontalAlignment: Text.AlignRight
                     text: temp + settings.tempScale
                 }
+
+                ListItems.ThinDivider { anchors.bottom: parent.bottom }
             }
         }
 
-        delegate: WeatherListItem {
+        onReorder: {
+            console.debug("Move: ", from, to);
+            storage.moveLocation(from, to);
+        }
+
+        delegate: ListItem {
             id: locationsListItem
-            leftSideAction: Remove {
-                onTriggered: storage.removeLocation(index)
-            }
-            multiselectable: true
-            reorderable: true
-
-            onItemClicked: {
-                settings.current = index + 1;
-                pageStack.pop()
-            }
-            onReorder: {
-                console.debug("Move: ", from, to);
-
-                storage.moveLocation(from, to);
-            }
-
-            ListItem.ThinDivider {
-                anchors {
-                    top: parent.top
+
+            leadingActions: ListItemActions {
+                actions: [
+                    Action {
+                        iconName: 'delete'
+                        onTriggered: storage.removeLocation(index)
+                    }
+                ]
+            }
+
+            onPressAndHold: {
+                ListView.view.ViewItems.selectMode = !ListView.view.ViewItems.selectMode
+                ListView.view.ViewItems.dragMode = !ListView.view.ViewItems.dragMode
+            }
+
+            onClicked: {
+                if (!selectMode) {
+                    settings.current = index + 1;
+                    pageStack.pop()
                 }
-                visible: index == 0
             }
 
             Item {
@@ -236,12 +266,6 @@
                     visible: locationsPage.state === "default"
                 }
             }
-
-            ListItem.ThinDivider {
-                anchors {
-                    bottom: parent.bottom
-                }
-            }
         }
     }
 

=== modified file 'po/com.ubuntu.weather.pot'
--- po/com.ubuntu.weather.pot	2015-06-21 20:14:39 +0000
+++ po/com.ubuntu.weather.pot	2015-06-26 15:22:05 +0000
@@ -8,7 +8,7 @@
 msgstr ""
 "Project-Id-Version: ubuntu-weather-app\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-06-21 20:10+0000\n"
+"POT-Creation-Date: 2015-06-26 15:05+0000\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@xxxxxx>\n"
@@ -50,19 +50,15 @@
 msgid "Today"
 msgstr ""
 
-#: ../app/components/ListItemActions/Remove.qml:26
-msgid "Remove"
-msgstr ""
-
-#: ../app/components/MultiSelectHeadState.qml:27
+#: ../app/components/MultiSelectHeadState.qml:37
 msgid "Select All"
 msgstr ""
 
-#: ../app/components/MultiSelectHeadState.qml:39
+#: ../app/components/MultiSelectHeadState.qml:50
 msgid "Delete"
 msgstr ""
 
-#: ../app/components/MultiSelectHeadState.qml:51
+#: ../app/components/MultiSelectHeadState.qml:61
 msgid "Cancel selection"
 msgstr ""
 
@@ -106,11 +102,11 @@
 msgid "OK"
 msgstr ""
 
-#: ../app/ui/HomePage.qml:31 ../app/ui/LocationsPage.qml:30
+#: ../app/ui/HomePage.qml:31 ../app/ui/LocationsPage.qml:29
 msgid "Locations"
 msgstr ""
 
-#: ../app/ui/LocationsPage.qml:104
+#: ../app/ui/LocationsPage.qml:128
 msgid "Current Location"
 msgstr ""
 

=== modified file 'ubuntu-weather-app.desktop.in.in'
--- ubuntu-weather-app.desktop.in.in	2015-01-23 23:15:52 +0000
+++ ubuntu-weather-app.desktop.in.in	2015-06-26 15:22:05 +0000
@@ -10,3 +10,4 @@
 X-Ubuntu-Touch=true
 X-Ubuntu-Default-Department-ID=accessories
 X-Ubuntu-Splash-Color=#F5F5F5
+X-Ubuntu-Supported-Orientations=portrait


Follow ups