← Back to team overview

ubuntu-touch-coreapps-reviewers team mailing list archive

[Merge] lp:~renatofilho/ubuntu-calendar-app/optimize into lp:ubuntu-calendar-app

 

Renato Araujo Oliveira Filho has proposed merging lp:~renatofilho/ubuntu-calendar-app/optimize into lp:ubuntu-calendar-app with lp:~renatofilho/ubuntu-calendar-app/optimize-page-load as a prerequisite.

Commit message:
Optimize MonthComponent

Requested reviews:
  Kunal Parmar (pkunal-parmar)
  Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot): continuous-integration
  Jenkins Bot (ubuntu-core-apps-jenkins-bot): continuous-integration

For more details, see:
https://code.launchpad.net/~renatofilho/ubuntu-calendar-app/optimize/+merge/283858
-- 
Your team Ubuntu Calendar Developers is subscribed to branch lp:ubuntu-calendar-app.
=== modified file 'DayView.qml'
--- DayView.qml	2016-01-25 19:10:48 +0000
+++ DayView.qml	2016-01-25 19:10:48 +0000
@@ -25,8 +25,8 @@
     id: dayViewPage
     objectName: "dayViewPage"
 
-    property var currentDay: new Date()
-    property bool isCurrentPage: false
+    property var anchorDate: new Date()
+    readonly property var currentDate: dayViewPath.currentItem.startDay
 
     signal dateSelected(var date);
 
@@ -39,7 +39,8 @@
         iconName: "calendar-today"
         text: i18n.tr("Today")
         onTriggered: {
-            currentDay = new Date()
+            dayViewPath.scrollToBegginer()
+            anchorDate = new Date()
         }
     }
 
@@ -57,7 +58,7 @@
             id:monthYear
             objectName:"monthYearLabel"
             fontSize: "x-large"
-            text: currentDay.toLocaleString(Qt.locale(),i18n.tr("MMMM yyyy"))
+            text: currentDate.toLocaleString(Qt.locale(),i18n.tr("MMMM yyyy"))
             font.capitalization: Font.Capitalize
         }
     }
@@ -66,74 +67,53 @@
         id: dayViewPath
         objectName: "dayViewPath"
 
-        property var startDay: currentDay
         //This is used to scroll all view together when currentItem scrolls
         property var childContentY;
 
         anchors.fill: parent
 
-        onNextItemHighlighted: {
-            //next day
-            currentDay = currentDay.addDays(1);
-        }
-
-        onPreviousItemHighlighted: {
-            //previous day
-            currentDay = currentDay.addDays(-1);
-        }
-
-        delegate: Loader {
+        delegate: TimeLineBaseComponent {
+            id: timeLineView
+            objectName: "DayComponent-"+index
+
             width: parent.width
             height: parent.height
-            asynchronous: !dayViewPath.isCurrentItem
-            sourceComponent: delegateComponent
-
-            Component {
-                id: delegateComponent
-
-                TimeLineBaseComponent {
-                    id: timeLineView
-                    objectName: "DayComponent-"+index
-
-                    type: ViewType.ViewTypeDay
-                    anchors.fill: parent
-
-                    isActive: parent.PathView.isCurrentItem
-                    contentInteractive: parent.PathView.isCurrentItem
-                    startDay: dayViewPath.startDay.addDays(dayViewPath.indexType(index))
-                    keyboardEventProvider: dayViewPath
-
-                    Component.onCompleted: {
-                        if(dayViewPage.isCurrentPage){
-                            timeLineView.scrollToCurrentTime();
-                        }
-                    }
-
-                    Connections{
-                        target: dayViewPage
-                        onIsCurrentPageChanged:{
-                            if(dayViewPage.isCurrentPage){
-                                timeLineView.scrollToCurrentTime();
-                            }
-                        }
-                    }
-
-                    //get contentY value from PathView, if its not current Item
-                    Binding{
-                        target: timeLineView
-                        property: "contentY"
-                        value: dayViewPath.childContentY;
-                        when: !parent.PathView.isCurrentItem
-                    }
-
-                    //set PathView's contentY property, if its current item
-                    Binding{
-                        target: dayViewPath
-                        property: "childContentY"
-                        value: contentY
-                        when: parent.PathView.isCurrentItem
-                    }
-                }
+
+            type: ViewType.ViewTypeDay
+            isActive: PathView.isCurrentItem
+            contentInteractive: PathView.isCurrentItem
+            startDay: anchorDate.addDays(dayViewPath.loopCurrentIndex + dayViewPath.indexType(index))
+            keyboardEventProvider: dayViewPath
+
+            Component.onCompleted: {
+                if(dayViewPage.active){
+                    timeLineView.scrollToCurrentTime();
+                }
+            }
+
+            Connections{
+                target: dayViewPage
+                onActiveChanged: {
+                    if(dayViewPage.active){
+                        timeLineView.scrollToCurrentTime();
+                    }
+                }
+            }
+
+            //get contentY value from PathView, if its not current Item
+            Binding{
+                target: timeLineView
+                property: "contentY"
+                value: dayViewPath.childContentY;
+                when: !parent.PathView.isCurrentItem
+            }
+
+            //set PathView's contentY property, if its current item
+            Binding{
+                target: dayViewPath
+                property: "childContentY"
+                value: contentY
+                when: parent.PathView.isCurrentItem
             }
         }
     }

=== modified file 'MonthComponent.qml'
--- MonthComponent.qml	2016-01-25 19:10:48 +0000
+++ MonthComponent.qml	2016-01-25 19:10:48 +0000
@@ -17,6 +17,7 @@
  */
 import QtQuick 2.4
 import Ubuntu.Components 1.3
+
 import "dateExt.js" as DateExt
 import "colorUtils.js" as Color
 
@@ -25,12 +26,11 @@
     objectName: "MonthComponent"
 
     property bool isCurrentItem;
-
-    property bool showEvents: false
-
-    property var currentMonth;
+    property int currentYear;
+    property int currentMonth;
+
     property var isYearView;
-    property var selectedDay;
+    property var highlightedDate;
     property bool displayWeekNumber:false;
 
     property string dayLabelFontSize: "medium"
@@ -40,91 +40,59 @@
 
     property alias dayLabelDelegate : dayLabelRepeater.delegate
     property alias dateLabelDelegate : dateLabelRepeater.delegate
+    readonly property alias monthStartDate: intern.monthStart
 
     signal monthSelected(var date);
     signal dateSelected(var date);
     signal dateHighlighted(var date);
 
-    //creatng timer only if we need to show events in month
-    Loader {
-        id: timerLoader
-        sourceComponent: showEvents ? timerComp : undefined
-    }
-
-    // Timer to delay creation of Model, There seems some problem fetching events if we create Model immediatly
-    Component {
-        id: timerComp
-        Timer{
-           interval: 200; running: true; repeat: false
-           onTriggered: {
-                modelLoader.sourceComponent = modelComponent
-           }
-        }
-    }
-
-    Loader{
-        id: modelLoader
-    }
-
-    Component{
-        id: modelComponent
-        EventListModel {
-            id: mainModel
-            startPeriod: intern.monthStart.midnight();
-            endPeriod: intern.monthStart.addDays((/*monthGrid.rows * cols */ 42 )-1).endOfDay()
-            filter: eventModel.filter
-            onModelChanged: {
-                intern.eventStatus = Qt.binding(function() { return mainModel.containsItems(startPeriod, endPeriod, 86400/*24*60*60*/)});
-            }
-        }
+    function updateEvents(events) {
+        intern.eventStatus = events
     }
 
     QtObject{
         id: intern
 
-        property var eventStatus;
-
-        property int curMonthDate: currentMonth.getDate()
-        property int curMonth: currentMonth.getMonth()
-        property int curMonthYear: currentMonth.getFullYear()
+        property var eventStatus: new Array(42)
 
         property var today: DateExt.today()
         property int todayDate: today.getDate()
         property int todayMonth: today.getMonth()
         property int todayYear: today.getFullYear()
 
-
         //date from month will start, this date might be from previous month
-        property var monthStart: currentMonth.weekStart( Qt.locale().firstDayOfWeek )
+        property var currentDate: new Date(root.currentYear, root.currentMonth, 1, 0, 0, 0, 0)
+        property var monthStart: currentDate.weekStart( Qt.locale().firstDayOfWeek )
         property int monthStartDate: monthStart.getDate()
         property int monthStartMonth: monthStart.getMonth()
         property int monthStartYear: monthStart.getFullYear()
-
         property int daysInStartMonth: Date.daysInMonth(monthStartYear, monthStartMonth)
-        property int daysInCurMonth:  Date.daysInMonth(curMonthYear,curMonth)
 
         //check if current month is start month
-        property bool isCurMonthStartMonth: curMonthDate === monthStartDate
-                                            && curMonth === monthStartMonth
-                                            && curMonthYear === monthStartYear
+        property bool isCurMonthStartMonth: root.currentMonth === monthStartMonth &&
+                                            root.currentYear === monthStartYear
 
         //check current month is same as today's month
-        property bool isCurMonthTodayMonth: todayYear === curMonthYear && todayMonth == curMonth
+        property bool isCurMonthTodayMonth: todayYear === root.currentYear &&
+                                            todayMonth == root.currentMonth
         //offset from current month's first date to start date of current month
         property int offset: isCurMonthStartMonth ? -1 : (daysInStartMonth - monthStartDate)
 
         property int dateFontSize: FontUtils.sizeToPixels(root.dateLabelFontSize)
         property int dayFontSize: FontUtils.sizeToPixels(root.dayLabelFontSize)
 
-        property int selectedIndex: -1
-
-        function findSelectedDayIndex(){
-            if(!selectedDay) {
+        property int highlightedIndex: root.isCurrentItem &&
+                                       root.highlightedDate ?
+                                           intern.indexByDate(root.highlightedDate) : -1
+        function indexByDate(date){
+            if (!date) {
                 return -1;
             }
 
-            if( todayMonth === selectedDay.getMonth() && selectedDay.getFullYear() === todayYear){
-                return selectedDay.getDate() +
+            if ((root.currentMonth === date.getMonth()) &&
+                (root.currentYear === date.getFullYear())) {
+
+                return date.getDate() +
                        (Date.daysInMonth(monthStartYear, monthStartMonth) - monthStartDate);
             } else {
                 return -1;
@@ -132,14 +100,40 @@
         }
     }
 
-    onSelectedDayChanged: {
-        if( isCurrentItem ) {
-            intern.selectedIndex = intern.findSelectedDayIndex();
+    UbuntuShape{
+        id: todayShape
+
+        visible: root.isCurrentItem && intern.isCurMonthTodayMonth && monthGrid.todayItem != null
+        color: (monthGrid.highlightedItem === monthGrid.todayItem) ? UbuntuColors.darkGrey : UbuntuColors.orange
+        width: parent ? Math.min(parent.height, parent.width) / 1.3 : 0
+        height: width
+        parent: monthGrid.todayItem
+        anchors.centerIn: parent
+        z: -1
+        Rectangle {
+            anchors.fill: parent
+            anchors.margins: units.gu(0.5)
+            color: UbuntuColors.orange
+            radius: 5
         }
     }
 
-    onCurrentMonthChanged: {
-        intern.selectedIndex = -1;
+    UbuntuShape{
+        id: highlightedShape
+
+        visible: monthGrid.highlightedItem && (monthGrid.highlightedItem != monthGrid.todayItem)
+        color: UbuntuColors.darkGrey
+        width: parent ? Math.min(parent.height, parent.width) / 1.3 : 0
+        height: width
+        parent: monthGrid.highlightedItem
+        anchors.centerIn: parent
+        z: -1
+        Rectangle {
+            anchors.fill: parent
+            anchors.margins: units.gu(0.5)
+            color: UbuntuColors.lightGrey
+            radius: 5
+        }
     }
 
     Column{
@@ -165,8 +159,8 @@
                 ViewHeader{
                     id: monthHeader
                     anchors.fill: parent
-                    month: intern.curMonth
-                    year: intern.curMonthYear
+                    month: root.currentMonth
+                    year: root.currentYear
 
                     monthLabelFontSize: root.monthLabelFontSize
                     yearLabelFontSize: root.yearLabelFontSize
@@ -184,9 +178,11 @@
 
                 property int dayWidth: width / 7;
 
-                width: parent.width
-                anchors.horizontalCenter: parent.horizontalCenter
-                anchors.verticalCenter: parent.verticalCenter
+                anchors{
+                    left: parent.left
+                    right: parent.right
+                    verticalCenter: parent.verticalCenter
+                }
 
                 Repeater{
                     id: dayLabelRepeater
@@ -196,23 +192,43 @@
             }
         }
 
-        Grid{
+        Grid {
             id: monthGrid
             objectName: "monthGrid"
 
-            width: parent.width
-            height: parent.height - monthGrid.y
-
             property int dayWidth: width / 7 /*cols*/;
             property int dayHeight: height / 6/*rows*/;
-
-            rows: 6
+            property var todayItem: null
+            readonly property var highlightedItem: intern.highlightedIndex != -1 ?
+                                                       dateLabelRepeater.itemAt(intern.highlightedIndex) : null
+            anchors {
+                left: parent.left
+                right: parent.right
+            }
+            height: parent.height - monthGrid.y
             columns: 7
 
             Repeater{
                 id: dateLabelRepeater
-                model: 42 //monthGrid.rows * monthGrid.columns
-                delegate: defaultDateLabelComponent
+                model: 42
+                delegate: MonthComponentDateDelegate {
+                    property var delegateDate: intern.monthStart.addDays(index)
+
+                    date: delegateDate.getDate()
+                    isCurrentMonth: delegateDate.getMonth() === root.currentMonth
+                    showEvent: intern.eventStatus[index] === true
+
+                    isToday: intern.todayDate == date && intern.isCurMonthTodayMonth
+                    isSelected: intern.highlightedIndex == index
+                    width: monthGrid.dayWidth
+                    height: monthGrid.dayHeight
+
+                    onIsTodayChanged: {
+                        if (isToday) {
+                            monthGrid.todayItem = this
+                        }
+                    }
+                }
             }
         }
     }
@@ -299,52 +315,9 @@
     }
 
     Component{
-        id: defaultDateLabelComponent
-        MonthComponentDateDelegate{
-            date: {
-                //try to find date from index and month's first week's first date
-                var temp = intern.daysInStartMonth - intern.offset + index
-                //date exceeds days in startMonth,
-                //this means previous month is over and we are now in current month
-                //to get actual date we need to remove number of days in startMonth
-                if( temp > intern.daysInStartMonth ) {
-                    temp = temp - intern.daysInStartMonth
-                    //date exceeds days in current month
-                    // this means date is from next month
-                    //to get actual date we need to remove number of days in current month
-                    if( temp > intern.daysInCurMonth ) {
-                        temp = temp - intern.daysInCurMonth
-                    }
-                }
-                return temp;
-            }
-
-            isCurrentMonth: {
-                //remove offset from index
-                //if index falls in 1 to no of days in current month
-                //then date is inside current month
-                var temp = index - intern.offset
-                return (temp >= 1 && temp <= intern.daysInCurMonth)
-            }
-
-            isToday: intern.todayDate == date && intern.isCurMonthTodayMonth
-
-            isSelected: showEvents && intern.selectedIndex == index
-
-            width: parent.dayWidth
-            height: parent.dayHeight
-            fontSize: intern.dateFontSize
-            showEvent: showEvents
-                        && intern.eventStatus !== undefined
-                        && intern.eventStatus[index] !== undefined
-                        && intern.eventStatus[index]
-        }
-    }
-
-    Component{
         id: dafaultDayLabelComponent
 
-        Label{
+        Text {
             id: weekDay
             objectName: "weekDay" + index
             width: parent.dayWidth

=== modified file 'MonthComponentDateDelegate.qml'
--- MonthComponentDateDelegate.qml	2016-01-25 19:10:48 +0000
+++ MonthComponentDateDelegate.qml	2016-01-25 19:10:48 +0000
@@ -9,27 +9,12 @@
     property bool isToday;
     property bool showEvent;
     property alias fontSize: dateLabel.font.pixelSize
-
     property bool isSelected: false
 
-    Loader {
-        sourceComponent: (isToday && isCurrentMonth) || isSelected ? highLightComp : undefined
-
-        onSourceComponentChanged: {
-            width = Qt.binding( function() {
-                var width = dateRootItem.height > dateRootItem.width ? dateRootItem.width :dateRootItem.height
-                return ( width / 1.3 );
-            });
-            height = Qt.binding ( function() { return width} );
-            anchors.centerIn = Qt.binding( function() { return dateLabel});
-        }
-    }
-
-    Label {
+    Text {
         id: dateLabel
         anchors.centerIn: parent
         text: date
-        fontSize: root.dateLabelFontSize
         color: {
             if( isCurrentMonth ) {
                 if( isToday || isSelected ) {
@@ -47,46 +32,19 @@
         }
     }
 
-    Loader{
-        sourceComponent: showEvent ? eventIndicatorComp : undefined
-        onSourceComponentChanged: {
-            width = Qt.binding( function() { return units.gu(0.8)})
-            height = Qt.binding( function() { return width })
-            anchors.horizontalCenter = Qt.binding( function() { return  parent.horizontalCenter })
-            anchors.top = Qt.binding( function() { return parent.verticalCenter })
-            anchors.topMargin = Qt.binding( function() {
-                var w = (dateRootItem.height > dateRootItem.width ? dateRootItem.width :dateRootItem.height)/1.3
-                return (w/2) + units.gu(0.1)
-            });
-        }
-    }
-
-    Component{
-        id: eventIndicatorComp
-        Rectangle {
-            anchors.fill: parent
-            radius: height/2
-            color: "black"
-        }
-    }
-
-    Component{
-        id: highLightComp
-        UbuntuShape{
-            color: {
-                if( isToday && !isSelected ) {
-                    "#DD4814"
-                } else {
-                    "gray"
-                }
-            }
-
-            Rectangle{
-                anchors.fill: parent
-                anchors.margins: units.gu(0.5)
-                color: isToday ? "#DD4814" : "darkgray"
-            }
-        }
+    Rectangle {
+        id: eventIndicator
+
+        width: units.gu(0.8)
+        height: width
+        anchors {
+            horizontalCenter: parent.horizontalCenter
+            top: parent.verticalCenter
+            topMargin: ((Math.min(parent.height, dateRootItem.width) / 1.3) / 2) + units.gu(0.1)
+        }
+        radius: height/2
+        color:"black"
+        visible: showEvent
     }
 
     MouseArea {
@@ -113,7 +71,6 @@
                     //If monthView is clicked then open selected DayView
                     root.dateSelected(selectedDate);
                 } else {
-                    intern.selectedIndex = index
                     root.dateHighlighted(selectedDate)
                 }
             }

=== modified file 'MonthView.qml'
--- MonthView.qml	2016-01-25 19:10:48 +0000
+++ MonthView.qml	2016-01-25 19:10:48 +0000
@@ -24,8 +24,10 @@
     id: monthViewPage
     objectName: "monthViewPage"
 
-    property var currentMonth: DateExt.today();
+    property var anchorDate: DateExt.today();
+    readonly property var currentDate: monthViewPath.currentItem.indexDate
     property var selectedDay;
+    property var highlightedDate;
 
     signal dateSelected(var date);
     signal dateHighlighted(var date);
@@ -38,7 +40,8 @@
         iconName: "calendar-today"
         text: i18n.tr("Today")
         onTriggered: {
-            currentMonth = new Date().midnight()
+            monthViewPath.scrollToBegginer()
+            anchorDate = new Date().midnight()
         }
     }
 
@@ -58,7 +61,7 @@
             // TRANSLATORS: this is a time formatting string,
             // see http://qt-project.org/doc/qt-5/qml-qtqml-date.html#details for valid expressions.
             // It's used in the header of the month and week views
-            text: currentMonth.toLocaleString(Qt.locale(),i18n.tr("MMMM yyyy"))
+            text: currentDate.toLocaleString(Qt.locale(),i18n.tr("MMMM yyyy"))
             font.capitalization: Font.Capitalize
         }
     }
@@ -67,66 +70,28 @@
         id: monthViewPath
         objectName: "monthViewPath"
 
-        property var startMonth: currentMonth;
-
-        anchors.top:parent.top
-
-        width:parent.width
-        height: parent.height
-
-        onNextItemHighlighted: {
-            nextMonth();
-        }
-
-        onPreviousItemHighlighted: {
-            previousMonth();
-        }
-
-        function nextMonth() {
-            currentMonth = addMonth(currentMonth, 1);
-        }
-
-        function previousMonth() {
-            currentMonth = addMonth(currentMonth, -1);
-        }
-
-        function addMonth(date,month) {
-            return  new Date(date.getFullYear(), date.getMonth() + month, 1, 0, 0, 0);
-        }
-
-        delegate: Loader {
+        anchors.fill: parent
+
+        delegate: MonthWithEventsComponent {
+            property var indexDate: monthViewPath.loopCurrentIndex === 0 ?
+                                        anchorDate : anchorDate.addMonths(monthViewPath.loopCurrentIndex + monthViewPath.indexType(index))
+
+            currentMonth: indexDate.getMonth()
+            currentYear: indexDate.getFullYear()
+
             width: parent.width - units.gu(4)
             height: parent.height
-
-            sourceComponent: delegateComponent
-            asynchronous: index !== monthViewPath.currentIndex
-
-            Component {
-                id: delegateComponent
-
-                MonthComponent {
-                    isCurrentItem: index === monthViewPath.currentIndex
-
-                    showEvents: true
-
-                    displayWeekNumber: mainView.displayWeekNumber;
-
-                    anchors.fill: parent
-
-                    currentMonth: monthViewPath.addMonth(monthViewPath.startMonth,
-                                                         monthViewPath.indexType(index));
-
-                    selectedDay: monthViewPage.selectedDay
-                    isYearView: false
-
-                    onDateSelected: {
-                        monthViewPage.dateSelected(date);
-                    }
-
-                    onDateHighlighted: {
-                        monthViewPage.dateHighlighted(date);
-                    }
-                }
+            isCurrentItem: (index === monthViewPath.currentIndex)
+            displayWeekNumber: mainView.displayWeekNumber
+            highlightedDate: monthViewPage.highlightedDate
+            isYearView: false
+
+            onDateSelected: {
+                monthViewPage.dateSelected(date);
+            }
+            onDateHighlighted: {
+                monthViewPage.highlightedDate = date
+                monthViewPage.dateHighlighted(date);
             }
         }
     }

=== modified file 'PathViewBase.qml'
--- PathViewBase.qml	2016-01-25 19:10:48 +0000
+++ PathViewBase.qml	2016-01-25 19:10:48 +0000
@@ -20,8 +20,7 @@
 PathView {
     id: root
 
-    model: 3
-    snapMode: PathView.SnapOneItem
+    readonly property alias loopCurrentIndex: intern.loopCurrentIndex
 
     signal nextItemHighlighted();
     signal previousItemHighlighted();
@@ -29,6 +28,8 @@
     signal scrollUp();
     signal scrollDown();
 
+    model: 3
+    snapMode: PathView.SnapOneItem
     preferredHighlightBegin: 0.5
     preferredHighlightEnd: 0.5
 
@@ -68,6 +69,11 @@
         }
     }
 
+    function scrollToBegginer()
+    {
+        intern.loopCurrentIndex = intern.previousIndex = currentIndex = 0
+    }
+
     Keys.onLeftPressed:{
         root.decrementCurrentIndex();
     }
@@ -98,15 +104,17 @@
         intern.previousIndex = currentIndex
 
         if ( diff > 0 ) {
-            root.nextItemHighlighted();
+            intern.loopCurrentIndex++
         }
         else {
-            root.previousItemHighlighted();
+            intern.loopCurrentIndex--
         }
     }
 
     QtObject{
         id: intern
+
+        property int loopCurrentIndex: 0
         property int previousIndex: root.currentIndex
     }
 }

=== modified file 'TimeLineBaseComponent.qml'
--- TimeLineBaseComponent.qml	2016-01-25 19:10:48 +0000
+++ TimeLineBaseComponent.qml	2016-01-25 19:10:48 +0000
@@ -111,28 +111,33 @@
     }
 
     Timer{
-       interval: 200; running: true; repeat: false
-       onTriggered: {
-           mainModel = modelComponent.createObject();
-           activityLoader.running = Qt.binding( function (){ return mainModel.isLoading;});
-       }
-    }
-
-    Component {
-        id: modelComponent
-        EventListModel {
-            id: mainModel
-            startPeriod: startDay.midnight();
-            endPeriod: type == ViewType.ViewTypeWeek ? startPeriod.addDays(7).endOfDay(): startPeriod.endOfDay()
-            filter: eventModel.filter
+        interval: 200
+        running: true
+        repeat: false
+        onTriggered: {
+            mainModel.filter = eventModel.filter
         }
     }
 
+    InvalidFilter {
+        id: invalidFilter
+    }
+
+    EventListModel {
+        id: mainModel
+
+        filter: invalidFilter // delay event filter in case the user is scrolling too fast
+        startPeriod: startDay.midnight();
+        endPeriod: type == ViewType.ViewTypeWeek ? startPeriod.addDays(7).endOfDay(): startPeriod.endOfDay()
+    }
+
     ActivityIndicator {
         id: activityLoader
+        objectName : "activityIndicator"
+
         visible: running
-        objectName : "activityIndicator"
         anchors.centerIn: parent
+        running: mainModel.isLoading
         z:2
     }
 
@@ -183,7 +188,7 @@
 
                 property int delegateWidth: {
                     if( type == ViewType.ViewTypeWeek ) {
-                        width/3 - units.gu(1) /*partial visible area*/
+                        width/3 - units.gu(1) // partial visible area
                     } else {
                         width
                     }

=== modified file 'WeekView.qml'
--- WeekView.qml	2016-01-25 19:10:48 +0000
+++ WeekView.qml	2016-01-25 19:10:48 +0000
@@ -25,8 +25,10 @@
     id: weekViewPage
     objectName: "weekViewPage"
 
-    property var dayStart: new Date();
-    property var firstDay: dayStart.weekStart(Qt.locale().firstDayOfWeek);
+    property var anchorDate: new Date();
+    readonly property var currentDate: weekViewPath.currentItem.item.startDay
+
+    property var firstDayOfWeek: currentDate.weekStart(Qt.locale().firstDayOfWeek);
     property bool isCurrentPage: false
     property var selectedDay;
 
@@ -61,7 +63,7 @@
             id:monthYear
             objectName:"monthYearLabel"
             fontSize: "x-large"
-            text: i18n.tr(dayStart.toLocaleString(Qt.locale(),i18n.tr("MMMM yyyy")))
+            text: i18n.tr(currentDate.toLocaleString(Qt.locale(),i18n.tr("MMMM yyyy")))
             font.capitalization: Font.Capitalize
         }
     }
@@ -75,22 +77,6 @@
         //This is used to scroll all view together when currentItem scrolls
         property var childContentY;
 
-        onNextItemHighlighted: {
-            nextWeek();
-        }
-
-        onPreviousItemHighlighted: {
-            previousWeek();
-        }
-
-        function nextWeek() {
-            dayStart = firstDay.addDays(7);
-        }
-
-        function previousWeek(){
-            dayStart = firstDay.addDays(-7);
-        }
-
         delegate: Loader {
             id: timelineLoader
             width: parent.width
@@ -104,10 +90,10 @@
                 TimeLineBaseComponent {
                     id: timeLineView
 
+                    anchors.fill: parent
                     type: ViewType.ViewTypeWeek
-                    anchors.fill: parent
+                    startDay: anchorDate.addDays((weekViewPath.loopCurrentIndex + weekViewPath.indexType(index)) * 7)
                     isActive: parent.PathView.isCurrentItem
-                    startDay: firstDay.addDays( weekViewPath.indexType(index) * 7)
                     keyboardEventProvider: weekViewPath
                     selectedDay: weekViewPage.selectedDay
 
@@ -128,7 +114,7 @@
                         onTriggered:{
                             if( isActive )
                                 timeLineView.scrollTocurrentDate();
-                        }
+                            }
                     }
 
                     Connections{

=== modified file 'YearView.qml'
--- YearView.qml	2016-01-25 19:10:48 +0000
+++ YearView.qml	2016-01-25 19:10:48 +0000
@@ -24,14 +24,15 @@
     id: yearViewPage
     objectName: "yearViewPage"
 
-    property int currentYear: DateExt.today().getFullYear();
+    property int anchorYear: new Date().getFullYear()
+    readonly property int currentYear: yearPathView.currentItem.year
+
     signal monthSelected(var date);
 
-    Keys.forwardTo: [yearPathView]
-
-    function refreshCurrentYear(year) {
-        currentYear = year;
-        var yearViewDelegate = yearPathView.currentItem.item;
+    function refreshCurrentYear(year)
+    {
+        anchorYear = year;
+        var yearViewDelegate = yearPathView.currentItem;
         yearViewDelegate.refresh();
     }
 
@@ -41,10 +42,14 @@
         iconName: "calendar-today"
         text: i18n.tr("Today")
         onTriggered: {
-            currentYear = new Date().getFullYear()
+            yearPathView.scrollToBegginer()
+            anchorYear = new Date().getFullYear()
         }
     }
 
+    Keys.forwardTo: [yearPathView]
+    title: i18n.tr("Year %1").arg(currentYear)
+
     head {
         actions: [
             calendarTodayAction,
@@ -54,48 +59,27 @@
             commonHeaderActions.syncCalendarAction,
             commonHeaderActions.settingsAction
         ]
-        contents: Label {
-            id:year
-            objectName:"yearLabel"
-            fontSize: "x-large"
-            text: i18n.tr("Year %1").arg(currentYear)
-        }
     }
 
+    flickable: null
+
     PathViewBase {
         id: yearPathView
         objectName: "yearPathView"
 
         anchors.fill: parent
-
-        onNextItemHighlighted: {
-            currentYear = currentYear + 1;
-        }
-
-        onPreviousItemHighlighted: {
-            currentYear = currentYear - 1;
-        }
-
-        delegate: Loader {
-            width: parent.width
-            height: parent.height
-            anchors.top: parent.top
-
-            asynchronous: index !== yearPathView.currentIndex
-            sourceComponent: delegateComponent
-
-            Component{
-                id: delegateComponent
-
-                YearViewDelegate{
-                    focus: index == yearPathView.currentIndex
-
-                    scrollMonth: 0;
-                    isCurrentItem: index == yearPathView.currentIndex
-                    year: (currentYear + yearPathView.indexType(index))
-
-                    anchors.fill: parent
-                }
+        snapMode: PathView.NoSnap
+
+        delegate: YearViewDelegate{
+            width: PathView.view.width
+            height: PathView.view.height
+            focus: index == yearPathView.currentIndex
+
+            scrollMonth: 0;
+            isCurrentItem: (index == yearPathView.currentIndex)
+            year: (anchorYear + yearPathView.loopCurrentIndex + yearPathView.indexType(index))
+            onMonthSelected: {
+                yearViewPage.monthSelected(date)
             }
         }
     }

=== modified file 'YearViewDelegate.qml'
--- YearViewDelegate.qml	2016-01-25 19:10:48 +0000
+++ YearViewDelegate.qml	2016-01-25 19:10:48 +0000
@@ -3,24 +3,35 @@
 
 GridView{
     id: yearView
-    clip: true
 
     property int scrollMonth;
     property bool isCurrentItem;
     property int year;
-
+    readonly property var currentDate: new Date()
+    readonly property int currentYear: currentDate.getFullYear()
+    readonly property int currentMonth: currentDate.getMonth()
     readonly property int minCellWidth: units.gu(30)
+
+    signal monthSelected(var date);
+
+    function refresh() {
+        scrollMonth = 0;
+        if(year == currentYear) {
+            scrollMonth = currentMonth
+        }
+        yearView.positionViewAtIndex(scrollMonth, GridView.Beginning);
+    }
+
+    // Does not increase cash buffer if user is scolling
+    cacheBuffer: PathView.view.flicking || PathView.view.dragging || !isCurrentItem ? 0 : 6 * cellHeight
+
     cellWidth: Math.floor(Math.min.apply(Math, [3, 4].map(function(n)
     { return ((width / n >= minCellWidth) ? width / n : width / 2) })))
-
     cellHeight: cellWidth * 1.4
 
+    clip: true
     model: 12 /* months in a year */
 
-    onYearChanged: {
-        refresh();
-    }
-
     //scroll in case content height changed
     onHeightChanged: {
         yearView.positionViewAtIndex(scrollMonth, GridView.Beginning);
@@ -30,68 +41,36 @@
         yearView.positionViewAtIndex(scrollMonth, GridView.Beginning);
     }
 
-    function refresh() {
-        scrollMonth = 0;
-        var today = new Date();
-        if(year == today.getFullYear()) {
-            scrollMonth = today.getMonth();
-        }
-        yearView.positionViewAtIndex(scrollMonth, GridView.Beginning);
-    }
-
-    Connections{
-        target: yearPathView
-        onScrollUp: {
-            scrollMonth -= 2;
-            if(scrollMonth < 0) {
-                scrollMonth = 0;
-            }
-            yearView.positionViewAtIndex(scrollMonth, GridView.Beginning);
-        }
-
-        onScrollDown: {
-            scrollMonth += 2;
-            var visibleMonths = yearView.height / cellHeight;
-            if( scrollMonth >= (11 - visibleMonths)) {
-                scrollMonth = (11 - visibleMonths);
-            }
-            yearView.positionViewAtIndex(scrollMonth, GridView.Beginning);
-        }
-    }
-
-    delegate: Loader {
+    delegate: Item {
         width: yearView.cellWidth
         height: yearView.cellHeight
 
-        sourceComponent: delegateComponent
-        asynchronous: !yearView.focus
-
-        Component {
-            id: delegateComponent
-
-            Item {
-                anchors.fill: parent
-                anchors.margins: units.gu(0.5)
-
-                MonthComponent {
-                    id: monthComponent
-                    objectName: "monthComponent" + index
-                    showEvents: false
-                    currentMonth: new Date(yearView.year, index, 1, 0, 0, 0, 0)
-                    displayWeekNumber: mainView.displayWeekNumber;
-                    isCurrentItem: yearView.focus
-
-                    isYearView: true
-                    anchors.fill: parent
-
-                    dayLabelFontSize:"x-small"
-                    dateLabelFontSize: "medium"
-                    monthLabelFontSize: "medium"
-                    yearLabelFontSize: "medium"
-
-                    onMonthSelected: {
-                        yearViewPage.monthSelected(date);
-                    }
+        UbuntuShape {
+            radius: "medium"
+            anchors {
+                fill: parent
+                margins: units.gu(0.5)
+            }
+
+            MonthComponent {
+                id: monthComponent
+                objectName: "monthComponent" + index
+
+                anchors {
+                    margins: units.gu(0.5)
+                    fill: parent
+                }
+
+                currentYear: yearView.year
+                currentMonth: index
+                isCurrentItem: yearView.focus
+                isYearView: true
+                dayLabelFontSize:"x-small"
+                dateLabelFontSize: "medium"
+                monthLabelFontSize: "medium"
+                yearLabelFontSize: "medium"
+                onMonthSelected: {
+                    yearView.monthSelected(date);
                 }
             }
         }

=== modified file 'calendar.qml'
--- calendar.qml	2016-01-25 19:10:48 +0000
+++ calendar.qml	2016-01-25 19:10:48 +0000
@@ -443,7 +443,6 @@
 
                     asynchronous: true
                     sourceComponent: agendaViewComp
-                    active: false
                     // Load page on demand and keep it on memory until the application is closed
                     enabled: tabs.isReady && (tabs.selectedTab == agendaTab)
                     onEnabledChanged: {
@@ -454,89 +453,92 @@
                 }
             }
         }
-    }
-
-    Component {
-        id: yearViewComp
-
-        YearView {
-            onMonthSelected: {
-                var now = DateExt.today();
-                if ((date.getMonth() === now.getMonth()) &&
-                    (date.getFullYear() === now.getFullYear())) {
-                    tabs.currentDay = now;
-                } else {
-                    tabs.currentDay = date.midnight();
-                }
-                tabs.selectedTabIndex = monthTab.index;
-            }
-            onActiveChanged: {
-                if (active) {
-                    refreshCurrentYear(DateExt.today().getFullYear())
-                }
-            }
-        }
-    }
-
-    Component {
-        id: monthViewComp
-
-        MonthView {
-            onDateSelected: {
-                tabs.currentDay = date;
-                tabs.selectedTabIndex = dayTab.index
-            }
-            onActiveChanged: {
-                if (active)
-                    currentMonth = tabs.currentDay.midnight()
-            }
-        }
-    }
-
-    Component {
-        id: weekViewComp
-
-        WeekView {
-            onDayStartChanged: {
-                tabs.currentDay = dayStart
-            }
-            onDateSelected: {
-                tabs.currentDay = date;
-                tabs.selectedTabIndex = dayTab.index
-            }
-            onActiveChanged: {
-                if (active)
-                    dayStart = tabs.currentDay
-            }
-        }
-    }
-
-    Component {
-        id: dayViewComp
-
-        DayView {
-            onCurrentDayChanged: {
-                tabs.currentDay = currentDay;
-            }
-
-            onDateSelected: {
-                tabs.currentDay = date
-            }
-
-            onActiveChanged: {
-                if (active)
-                    currentDay = tabs.currentDay;
-            }
-        }
-    }
-
-    Component {
-        id: agendaViewComp
-
-        AgendaView {
-            onDateSelected: {
-                tabs.currentDay = date;
-                tabs.selectedTabIndex = dayTab.index
+
+        Component {
+            id: yearViewComp
+
+            YearView {
+                onMonthSelected: {
+                    var now = DateExt.today();
+                    if ((date.getMonth() === now.getMonth()) &&
+                        (date.getFullYear() === now.getFullYear())) {
+                        tabs.currentDay = now;
+                    } else {
+                        tabs.currentDay = date.midnight();
+                    }
+                    tabs.selectedTabIndex = monthTab.index;
+                }
+                onActiveChanged: {
+                    if (active) {
+                        refreshCurrentYear(tabs.currentDay.getFullYear())
+                    }
+                }
+            }
+        }
+
+        Component {
+            id: monthViewComp
+
+            MonthView {
+                onDateSelected: {
+                    tabs.currentDay = date
+                    tabs.selectedTabIndex = dayTab.index
+                }
+                onActiveChanged: {
+                    if (active) {
+                        anchorDate = tabs.currentDay.midnight()
+                    }
+                }
+            }
+        }
+
+        Component {
+            id: weekViewComp
+
+            WeekView {
+                onCurrentDateChanged: {
+                    tabs.currentDay = currentDate
+                }
+                onDateSelected: {
+                    tabs.currentDay = date;
+                    tabs.selectedTabIndex = dayTab.index;
+                }
+                onActiveChanged: {
+                    if (active) {
+                        anchorDate = tabs.currentDay.midnight()
+                    }
+                }
+            }
+        }
+
+        Component {
+            id: dayViewComp
+
+            DayView {
+                onCurrentDateChanged: {
+                    tabs.currentDay = currentDate;
+                }
+
+                onDateSelected: {
+                    tabs.currentDay = date
+                }
+
+                onActiveChanged: {
+                    if (active) {
+                        anchorDate = tabs.currentDay
+                    }
+                }
+            }
+        }
+
+        Component {
+            id: agendaViewComp
+
+            AgendaView {
+                onDateSelected: {
+                    tabs.currentDay = date;
+                    tabs.selectedTabIndex = dayTab.index;
+                }
             }
         }
     }

=== modified file 'po/com.ubuntu.calendar.pot'
--- po/com.ubuntu.calendar.pot	2015-11-23 07:15:20 +0000
+++ po/com.ubuntu.calendar.pot	2016-01-25 19:10:48 +0000
@@ -8,7 +8,7 @@
 msgstr ""
 "Project-Id-Version: \n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-11-23 15:14+0800\n"
+"POT-Creation-Date: 2016-01-12 12:03-0300\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@xxxxxx>\n"
@@ -263,7 +263,7 @@
 msgid "After Date"
 msgstr ""
 
-#: ../MonthComponent.qml:260
+#: ../MonthComponent.qml:263
 msgid "Wk"
 msgstr ""
 
@@ -416,7 +416,7 @@
 msgid "All Day"
 msgstr ""
 
-#: ../YearView.qml:61
+#: ../YearView.qml:48
 #, qt-format
 msgid "Year %1"
 msgstr ""


Follow ups