calendarui/views/src/calenmonthgrid.cpp
changeset 45 b6db4fd4947b
parent 23 fd30d51f876b
child 51 0b38fc5b94c6
--- a/calendarui/views/src/calenmonthgrid.cpp	Mon May 03 12:30:32 2010 +0300
+++ b/calendarui/views/src/calenmonthgrid.cpp	Mon Jun 28 15:22:02 2010 +0530
@@ -16,14 +16,13 @@
  */
 
 // System includes
-#include <qtimer.h>
-#include <hbmenu.h>
-#include <hbaction.h>
-#include <hbmainwindow.h>
 #include <hbgridview.h>
 #include <hbabstractviewitem.h>
 #include <hbstyleloader.h>
 #include <hbcolorscheme.h>
+#include <hbpangesture.h>
+#include <hbswipegesture.h>
+#include <hbdeviceprofile.h>
 
 // User includes
 #include "calenmonthgrid.h"
@@ -32,10 +31,13 @@
 #include "calenmonthview.h"
 #include "calendateutils.h"
 #include "calencommon.h"
+#include "calenconstants.h"
 
 // Constants
-#define SCROLL_SPEEED 1000 
+#define SCROLL_SPEEED 3000 
 #define GRIDLINE_WIDTH 0.075 //units
+#define MAX_PAN_DIRECTION_THRESHOLD 50
+#define MIN_PAN_DIRECTION_THRESHOLD 20
 
 /*!
  \class CalenMonthGrid
@@ -53,7 +55,7 @@
 	mIsPanGesture(false),
 	mIsAtomicScroll(true),
 	mView(NULL),
-	mCurrentRow(0),
+	mCurrentRow(-100),
 	mIsNonActiveDayFocused(false),
 	mIgnoreItemActivated(false),
 	mGridBorderColor(Qt::gray)
@@ -66,33 +68,30 @@
 	setSelectionMode(HbGridView::NoSelection);
 	setUniformItemSizes(true);
 	setVerticalScrollBarPolicy(HbScrollArea::ScrollBarAlwaysOff);
-	setClampingStyle(HbScrollArea::StrictClamping );
+	setClampingStyle(HbScrollArea::StrictClamping);
+	setEnabledAnimations(HbAbstractItemView::None);
+	setFrictionEnabled(false);
+	setFlag(QGraphicsItem::ItemHasNoContents, false);
+	resetTransform();
 	
 	// Get the content widget of the scroll area to draw the grid lines
 	mContentWidget = contentWidget();
 	
-	// Get the color of the grid lines
+	// Get the all required colors 
+	// Color of the grid lines
 	mGridLineColor = HbColorScheme::color("qtc_cal_grid_line");
 	
-	// Create the prototype
-	CalenGridItemPrototype* gridItemPrototype = new CalenGridItemPrototype(this);
-	// Create the model
-	mModel = new QStandardItemModel(14*KCalenDaysInWeek, 1, this);
-	// Set the mode and the prototype
-	setModel(mModel,gridItemPrototype);
+	// Get the localised dates well before
+	// TODO: Need to update the mLocalisedDates when user changes the
+	// phone language keeping calendar application in background
+	HbExtendedLocale locale = HbExtendedLocale::system();
+	for (int i = 1; i <= 31; i++) {
+		mLocalisedDates.append(locale.toString(i));
+	}
 	
-	// Register the widgetml and css files
-	HbStyleLoader::registerFilePath(":/");
-	
-	// Set the layout name
-	setLayoutName("calendarCustomGridItem");
-	
+	// Connect to scrolling finished signal
 	connect(this, SIGNAL(scrollingEnded()), this,
 			SLOT(scrollingFinished()));
-	
-	// Connect to item activated signal
-	connect(this, SIGNAL(activated(const QModelIndex &)), this,
-				SLOT(itemActivated(const QModelIndex &)));
 }
 
 /*!
@@ -100,6 +99,7 @@
  */
 CalenMonthGrid::~CalenMonthGrid()
 {
+	// Nothing Yet
 }
 
 /*!
@@ -114,55 +114,66 @@
  Updates the model with the proper dates and sets the required user roles
  */
 void CalenMonthGrid::updateMonthGridModel(QList<CalenMonthData> &monthDataArray,
-                        int indexToBeScrolled)
+                        int indexToBeScrolled, bool isFirstTime)
 {
-	// Check the counts
-	int dataCount = monthDataArray.count();
-	int rowCount = mModel->rowCount();
-	int countDiff = dataCount - rowCount;
-	if (countDiff < 0) {
-		// Delete extra rows in the model
-		mModel->removeRows(dataCount,abs(countDiff));
-	} else if (countDiff > 0) {
-		// Add the necessary number of rows
-		mModel->insertRows(rowCount,countDiff);
+	int loopStart = 0;
+	int loopEnd = monthDataArray.count();
+	if (isFirstTime) {
+		// Create the model with only 42 items as visible to the user
+		mModel = new QStandardItemModel(KCalenDaysInWeek * KNumOfVisibleRows, 
+		                                1, this);
+		loopStart = (mView->rowsInPrevMonth()) * KCalenDaysInWeek;
+		loopEnd = loopStart + (KCalenDaysInWeek * KNumOfVisibleRows);
+	} else {
+		// Block the signals generated by model, this is being done as
+		// we want to avoid the overload of view listening to signals
+		mModel->blockSignals(true);
+		
+		// Check the counts
+		int dataCount = monthDataArray.count();
+		int rowCount = mModel->rowCount();
+		int countDiff = dataCount - rowCount;
+		if (countDiff < 0) {
+			// Delete extra rows in the model
+			mModel->removeRows(dataCount,abs(countDiff));
+		} else if (countDiff > 0) {
+			// Add the necessary number of rows
+			mModel->insertRows(rowCount,countDiff);
+		}
+		loopEnd = dataCount;
 	}
+	
 	QDateTime currDate = mView->getCurrentDay();
 	QDateTime currDateTime = CalenDateUtils::beginningOfDay(currDate);
 	QDateTime activeDay = mView->getActiveDay();
 	QDateTime activeDateTime = CalenDateUtils::beginningOfDay(activeDay);
 	
 	QModelIndex currentIndex;
-	
-	// Get the default text color to be set
-	QColor textColor = HbColorScheme::color("qtc_cal_month_notactive_dates");
-	HbExtendedLocale locale = HbExtendedLocale::system();
-	for (int i = 0; i < dataCount; i++) {
+	int modelIndex = 0;
+	for (int i = loopStart; i < loopEnd; i++) {
 		QDateTime dateTime = monthDataArray[i].Day();
-		currentIndex = mModel->index(i, 0);
-		// Get the localised string for the day
-		QString date = locale.toString(dateTime.date().day());
+		currentIndex = mModel->index(modelIndex++, 0);
 		
 		// Create the variant list to contain the date to depict a grid item
 		QVariantList itemData;
 		
-		// NOTE: Add the data in the order mentioned in the 
+		// !!!NOTE!!!: Add the data in the order mentioned in the 
 		// CalendarNamespace::DataRole enum. Dont change the order.
-		itemData << date; 
+		itemData << mLocalisedDates.at(dateTime.date().day()-1); 
 		
 		// Check for active day
 		if (activeDateTime == CalenDateUtils::beginningOfDay(dateTime)) {
-			mCurrentRow = currentIndex.row();
-			// Set the focus icon
-			itemData << QString("qtg_fr_cal_focused_day_ind");
+			mCurrentRow = i;
+			// Set the focus attribute to true
+			itemData << true;
 		} else {
 			// reset the highlight
-			itemData << QString("");
+			itemData << false;
 		}
 
 		// Check for current day
 		if (currDateTime == CalenDateUtils::beginningOfDay(dateTime)) {
-			// Set the underline icon
+			// Set the underline attribute to true
 			itemData << true;
 		} else {			
 			itemData << false;
@@ -170,61 +181,166 @@
 
 		// Check for events
 		if (monthDataArray[i].HasEvents()) {
-			// Set the underline icon
-			itemData << QString("qtg_graf_cal_event_ind");
+			// Set the event indicator attribute
+			itemData << true;
 		} else {
-			itemData << QString("");
+			itemData << false;
 		}
 		
 		// Add default text color
-		itemData << textColor;
+		if (monthDataArray[i].isActive()) {
+			itemData << true;
+		} else {
+			itemData << false;
+		}
 		mModel->itemFromIndex(currentIndex)->setData(itemData);
 	}
+	
+	if (isFirstTime) {
+		// Color of the today indicator
+		QColor todayIndColor = HbColorScheme::color("qtc_cal_month_current_day");
+		// Color of the active dates
+		QColor mActiveTextColor = 
+								HbColorScheme::color("qtc_cal_month_active_dates");
+		// Color of the inactive dates
+		QColor mInActiveTextColor = 
+							HbColorScheme::color("qtc_cal_month_notactive_dates");
+		
+		// Create the prototype
+		CalenGridItemPrototype* gridItemPrototype = new CalenGridItemPrototype(
+						todayIndColor, mActiveTextColor, mInActiveTextColor, this);
+		
+		// Set the mode and the prototype
+		setModel(mModel,gridItemPrototype);
+		
+		// Register the widgetml and css files
+		HbStyleLoader::registerFilePath(":/");
+		
+		// Set the layout name
+		setLayoutName("calendarCustomGridItem");
+	} else {
+		// Since, we have finished setData, Now unblock the signals
+		mModel->blockSignals(false);
+		
+		// Since till now, we had blocked signals being generated frm the mode
+		// view will be unaware of the items that we added. Hence, inform the view
+		// explicitly in one shot
+		QModelIndex leftIndex = mModel->index(0, 0);
+		QModelIndex rightIndex = mModel->index(loopEnd-1, 0);
+		dataChanged(leftIndex, rightIndex);
+		
+		// NOTE: To make sure that we always display proper month,
+		// two calls have been  made to scrollTo(), one with top
+		// visible item and other with bottom visible item
+		// Calculate the first visible item in the grid
+		QModelIndex firstVisibleIndex = mModel->index(indexToBeScrolled - 
+								(KNumOfVisibleRows * KCalenDaysInWeek - 1), 0);
+		scrollTo(firstVisibleIndex);
+		
+		
+		// Calculate the last visible item in the grid
+		QModelIndex lastVisibleIndex = mModel->index(indexToBeScrolled, 0);
+		scrollTo(lastVisibleIndex);
+	}
 	mMonthDataArray = monthDataArray;
-	
-	// Get the active month
-	QDateTime activeDate = mView->getActiveDay();
-	// Set the text color properly
-	setActiveDates(activeDate.date());
-	
-	// NOTE: To make sure that we always display proper month,
-	// two calls have been  made to scrollTo(), one with top
-	// visible item and other with bottom visible item
-    // Calculate the first visible item in the grid
-    QModelIndex firstVisibleIndex = mModel->index(indexToBeScrolled - 
-                                        (KNumOfVisibleRows * KCalenDaysInWeek - 1), 0);
-    scrollTo(firstVisibleIndex);
-    
-    
-    // Calculate the last visible item in the grid
-    QModelIndex lastVisibleIndex = mModel->index(indexToBeScrolled, 0);
-    scrollTo(lastVisibleIndex);
 }
 
 /*!
- Listens for down gesture
+	Updates the view with jprevious month dates when calendar is opened for the 
+	first time to improve the opening time
  */
-void CalenMonthGrid::downGesture (int value)
-{
-	Q_UNUSED(value)	
-	mDirection = down;
-	// Before we start scrolling, setthe active text color to previous month
-	QDateTime activeDate = mView->getActiveDay();
-	setActiveDates(activeDate.addMonths(-1).date());
-	HbScrollArea::downGesture(SCROLL_SPEEED);
+void CalenMonthGrid::updateMonthGridWithInActiveMonths(
+										QList<CalenMonthData> &monthDataArray)
+{	
+	mMonthDataArray = monthDataArray;
+		
+	// Prepend the required rows
+	handlePrependingRows(monthDataArray);
+	
+	// Append the required rows
+	handleAppendingRows(monthDataArray);
+	
+	int rowsInPrevMonth = mView->rowsInPrevMonth();
+	
+	// Calculate the proper index to be scrolled to
+	int itemToBeScrolled = rowsInPrevMonth * KCalenDaysInWeek;
+	QModelIndex indexToBeScrolled = mModel->index(itemToBeScrolled, 0);
+	mIsAtomicScroll = true;
+	scrollTo(indexToBeScrolled);
+		
+	// Scroll to proper index
+	itemToBeScrolled = ((rowsInPrevMonth + KNumOfVisibleRows) * 
+								   KCalenDaysInWeek) - 1;
+	indexToBeScrolled = mModel->index(itemToBeScrolled, 0);
+	mIsAtomicScroll = true;
+	scrollTo(indexToBeScrolled);
+	
+	// Update the sart position of the content widget
+	mStartPos = mContentWidget->pos();
+	
+	// Now connect to the signal which gets emitted when any item on the grid 
+	// is tapped.
+	connect(this, SIGNAL(activated(const QModelIndex &)), this,
+						SLOT(itemActivated(const QModelIndex &)));
 }
 
 /*!
- Listens for Up gesture
+	Updates the view with just event indicators
  */
-void CalenMonthGrid::upGesture (int value)
+void CalenMonthGrid::updateMonthGridWithEventIndicators(
+										QList<CalenMonthData> &monthDataArray)
+{
+	mMonthDataArray = monthDataArray;
+	for(int i = 0; i < monthDataArray.count(); i++) {
+		// Check if the day has events
+		if (monthDataArray[i].HasEvents()) {
+			QModelIndex itemIndex = mModel->index(i,0);
+			QVariant itemData = itemIndex.data(Qt::UserRole + 1);
+			QVariantList list = itemData.toList();
+			list.replace(CalendarNamespace::CalendarMonthEventRole, true);
+			mModel->itemFromIndex(itemIndex)->setData(list);
+		}
+	}
+}
+
+/*!
+ Scrolls the content dowmwards
+ */
+void CalenMonthGrid::downGesture()
 {
-	Q_UNUSED(value)	
-	mDirection = up;
-	// Before we start scrolling, setthe active text color to future month
-	QDateTime activeDate = mView->getActiveDay();
-	setActiveDates(activeDate.addMonths(1).date());
-	HbScrollArea::upGesture(SCROLL_SPEEED);
+    // Make sure that content widget is properly placed
+    if (mIsNonActiveDayFocused) {
+        mIsAtomicScroll = true;
+        int itemToBeScrolled = mView->rowsInPrevMonth() * KCalenDaysInWeek;
+        QModelIndex indexToBeScrolled  = mModel->index(itemToBeScrolled, 0);
+        scrollTo(indexToBeScrolled);
+    }
+    mDirection = down;
+    mIsAtomicScroll = false;
+    setAttribute(Hb::InteractionDisabled);
+    QPointF targetPos(0.0, 0.0);
+    scrollContentsTo(targetPos,500);
+}
+
+/*!
+ Scrolls the content upwards
+ */
+void CalenMonthGrid::upGesture()
+{
+    // Make sure that content widget is properly placed
+    if (mIsNonActiveDayFocused) {
+        mIsAtomicScroll = true;
+        int itemToBeScrolled = mView->rowsInPrevMonth() * KCalenDaysInWeek;
+        itemToBeScrolled += KNumOfVisibleRows * KCalenDaysInWeek;
+        QModelIndex indexToBeScrolled  = mModel->index(itemToBeScrolled, 0);
+        scrollTo(indexToBeScrolled);
+    }
+    mDirection = up;
+    mIsAtomicScroll = false;
+    setAttribute(Hb::InteractionDisabled);
+    QPointF targetPos(0.0, mStartPos.y() - size().height());
+    scrollContentsTo(-targetPos,500);
+	
 }
 
 /*!
@@ -232,7 +348,6 @@
  */
 void CalenMonthGrid::mousePressEvent(QGraphicsSceneMouseEvent* event)
 {
-	mPressedPos = event->pos();
 	// Pass it to parent
 	HbGridView::mousePressEvent(event);
 }
@@ -242,43 +357,88 @@
  */
 void CalenMonthGrid::mouseReleaseEvent(QGraphicsSceneMouseEvent* event)
 {
-	int posDiff = mPressedPos.y() - event->pos().y();
-	if (posDiff < -50) {
-		mDirection = down;
-	} else if (posDiff > 50){
-		mDirection = up;
+	// Pass it grid view if pan gesture is not in progress else pass it to
+	// scrollarea. Problem here is, if we pass to gridview when panning, then 
+	// its emitting item activated signal simply becasue of which focus item
+	// is getting changed when you finish the pan / shake
+	if (!mIsPanGesture) {
+		HbGridView::mouseReleaseEvent(event);
+	} else {
+		HbScrollArea::mouseReleaseEvent(event);
 	}
-	// Pass it to parent
-	HbGridView::mouseReleaseEvent(event);
 }
 
 /*!
- Listens for pan gesture
+    Function to list for all the gesture events
  */
-void  CalenMonthGrid::panGesture(const QPointF &  delta)
+void CalenMonthGrid::gestureEvent(QGestureEvent *event)
 {
-	if (!mIsPanGesture) {
-		mIsPanGesture = true;
-		mIgnoreItemActivated = true;
-		
-		// Get to know the direction of the gesture
-		if (delta.y() > 0) {
-			mDirection = down;
-		} else {
-			mDirection = up;
-		}
-	} else { // This case is when user changes the direction while panning
-		// without lifting the finger
-		// Check if direction has changed
-		if (((delta.y() > 0) && (mDirection == up))
-			|| ((delta.y() < 0) && (mDirection == down))) {
-			// Direction has changed, ignore this pan
-			return;
-		}
-	}
-	// Call the parent class to perform the pan gesture
-	// When scrolling finished, month grid will adjust to show the proper month
-	HbScrollArea::panGesture(delta);
+   if(HbPanGesture *gesture = qobject_cast<HbPanGesture *>(event->gesture(Qt::PanGesture))) {
+        if (gesture->state() == Qt::GestureStarted) {
+            setAttribute(Hb::InteractionDisabled);
+            mIsAtomicScroll = false;
+            if (!mIsPanGesture) {
+                mDirection = invalid;
+                mStartPos = mContentWidget->pos();
+                // TODO: This work aroung till framework provides an api
+                // to know the direciton of the pan, until then we need
+                // calculate the direction explicitly
+                // Get to know the direction of the gesture
+                // Use our defined threshold temporarily till scrollarea 
+                // frm orbit side is made clever enough not to scroll in other direction
+                // apart frm the registered scroll direction
+                QPointF delta = gesture->delta();
+                if (abs(delta.x()) > MAX_PAN_DIRECTION_THRESHOLD) {
+                    // Now see if y coord diff has crossed threshold
+                    if (delta.y() > MAX_PAN_DIRECTION_THRESHOLD) {
+                        mIsPanGesture = true;
+                        mIgnoreItemActivated = true;
+                        mDirection = down;
+                    } else if (delta.y() < -MAX_PAN_DIRECTION_THRESHOLD){
+                        mIsPanGesture = true;
+                        mIgnoreItemActivated = true;
+                        mDirection = up;
+                    } else {
+                        event->accept(Qt::PanGesture);
+                        return;
+                    }
+                } else if (abs(delta.x()) < MAX_PAN_DIRECTION_THRESHOLD) {
+                   if (delta.y() > MIN_PAN_DIRECTION_THRESHOLD) {
+                        mIsPanGesture = true;
+                        mIgnoreItemActivated = true;
+                        mDirection = down;
+                   } else if (delta.y() < -MIN_PAN_DIRECTION_THRESHOLD){
+                        mIsPanGesture = true;
+                        mIgnoreItemActivated = true;
+                        mDirection = up;
+                   }else {
+                       event->accept(Qt::PanGesture);
+                       return;
+                   }
+                } 
+            }
+        }
+    } else if(HbSwipeGesture *gesture = qobject_cast<HbSwipeGesture *>(event->gesture(Qt::SwipeGesture))) {
+        if (gesture->state() == Qt::GestureStarted) {
+            setAttribute(Hb::InteractionDisabled);
+            mIsAtomicScroll = false;
+            mDirection = invalid;
+            if (gesture->sceneVerticalDirection() == QSwipeGesture::Down) {
+                mDirection = down;
+            } else if (gesture->sceneVerticalDirection() == QSwipeGesture::Up) {
+                mDirection = up;
+            } else {
+                event->accept(Qt::SwipeGesture);
+                return;
+            }
+        }
+    }
+   
+   if (mDirection!= invalid) {
+        // Call the parent class to perform the pan gesture
+        // When scrolling finished, month grid will adjust to show the proper month
+        HbScrollArea::gestureEvent(event);
+   }
 }
 
 /*!
@@ -286,42 +446,100 @@
  */
 void CalenMonthGrid::scrollingFinished()
 {
-	
 	if (mIsPanGesture) {
-		mIsPanGesture = false;
-		if (mDirection == up) {
-			// Make a request for upgesture
-			upGesture(SCROLL_SPEEED);
-			return; // return immediately
-		} else if (mDirection == down) {
-			// Make a request for upgesture
-			downGesture(SCROLL_SPEEED);
-			return; // return immediately
+		handlePanGestureFinished();
+	} else if(!mIsAtomicScroll) {
+		QDateTime activeDate = mView->getActiveDay();
+		if(mDirection == down) { // down gesture
+			if (!mIsNonActiveDayFocused) {
+				setActiveDates(activeDate.addMonths(-1).date());
+			}
+			prependRows();
+		} else if (mDirection == up) { //up gesture
+			if (!mIsNonActiveDayFocused) {
+				setActiveDates(activeDate.addMonths(1).date());
+			}
+			appendRows();
 		}
-	} else if(!mIsAtomicScroll) {
-		// Before we do anything, set the focus to proper date
-		// Set it only when non active day was focussed. When inactive day
-		// was focussed, we need to focus the same day
-		if (!mIsNonActiveDayFocused) {
-			setFocusToProperDay();
-		}
-		// To improve the performance, lets start the timer for 10 ms, 
-		// return immediately and do the other things after that
-		QTimer::singleShot(10, this, SLOT(timerExpired()));
+		mDirection = invalid;
 	} else {
         mIsAtomicScroll = false;
+        mDirection = invalid;
 	}
 	mIgnoreItemActivated = false;
+	setAttribute(Hb::InteractionDisabled, false);
 }
 
-void CalenMonthGrid::timerExpired()
+/*!
+ Function to handle completion of pan gesture
+ */
+void CalenMonthGrid::handlePanGestureFinished()
 {
-	if(mDirection == down) { // down gesture
-		prependRows();
-	} else if (mDirection == up) { //up gesture
-		appendRows();
+	mIsPanGesture = false;
+	// Get the first item that is visible
+	QList<HbAbstractViewItem *> list = visibleItems();
+	HbAbstractViewItem* item = list[0];
+	QModelIndex modelIndex = item->modelIndex();
+	
+	// Get the date which is visible at the above row
+	QDateTime date = mMonthDataArray[modelIndex.row()].Day();
+	
+	// Check if this date belong to current active month or 
+	// previous month else future month
+	QDateTime activeMonth = mView->getActiveDay();
+	QDateTime prevMonth = activeMonth.addMonths(-1);
+	QDateTime nextMonth = activeMonth.addMonths(1);
+	int month = date.date().month();
+	if (month == activeMonth.date().month()) {
+		// Then pan is completed on current month
+		// Check if the date is more than half of the current month or it is
+		// more than or equal to half of the future month
+		if (date.date().day() > (activeMonth.date().daysInMonth()) / 2 ||
+				date.addDays(KNumOfVisibleRows*KCalenDaysInWeek).date().day() >=
+				(prevMonth.date().daysInMonth()) / 2) {
+			// up gesture to bring the next month
+			upGesture();
+		} else {
+			// we should again show the current month by scrolling downwards
+			mDirection = down;
+			mIsAtomicScroll = true;
+			setAttribute(Hb::InteractionDisabled);
+			scrollContentsTo(-mStartPos,500);
+		}
+	} else if (month == prevMonth.date().month()) {
+		// first visible item belongs to previous month
+		// Check if the date is more than half of the previous month
+		if (date.date().day() > (prevMonth.date().daysInMonth()) / 2) {
+			// we should again show the current month by scrolling upwards
+			mDirection = up;
+			mIsAtomicScroll = true;
+			setAttribute(Hb::InteractionDisabled);
+			scrollContentsTo(-mStartPos,500);
+		} else {
+			// down gesture to show the previous month
+			downGesture();
+		}
+	} else if (month == prevMonth.addMonths(-1).date().month()) {
+		// first visible date belong to previous to previous month
+		// hence, scroll down to bring the previous month
+		downGesture();
+	} else if (month == nextMonth.date().month()) {
+		// first visible item belongs to next month
+		// Check if the date is more than half of the next month
+		if (date.date().day() > (nextMonth.date().daysInMonth()) / 2) {
+			// up gesture to bring the next month
+			upGesture();
+		} else {
+			// we should again show the current month by scrolling upwards
+			mDirection = invalid;
+			setAttribute(Hb::InteractionDisabled);
+			scrollContentsTo(-mStartPos,500);
+		}
+	} else if (month == nextMonth.addMonths(1).date().month()) {
+		// first visible date belongs to next to next month
+		// hence, scroll up to show the next month
+		upGesture();
 	}
-	mDirection = invalid;
 }
 
 /*!
@@ -330,43 +548,84 @@
  */
 void CalenMonthGrid::prependRows()
 {
+	// Before we do anything, set the focus to proper date
+	// Set it only when non active day was focussed. When inactive day
+	// was focussed, we need to focus the same day
+	if (!mIsNonActiveDayFocused) {
+		setFocusToProperDay();
+	}
+	
+	// Block the signals generated by model, this is being done as
+	// we want to avoid the overload of view listening to signals
+	mModel->blockSignals(true);
+		
 	mIsNonActiveDayFocused = false;
-	QDateTime currDate = mView->getCurrentDay();
-	QDateTime currDateTime = CalenDateUtils::beginningOfDay( currDate );
+	
 	int rowsInFutMonthEarlier = mView->rowsInFutMonth();
 	int rowsInPrevMonthEarlier = mView->rowsInPrevMonth();
 	
+	// remove the cells in the future month
+	int deleteFromIndex = (rowsInPrevMonthEarlier + KNumOfVisibleRows) * KCalenDaysInWeek;
+	int numOfIndices = rowsInFutMonthEarlier * KCalenDaysInWeek;
+	
 	// Get the updated dates from the view
 	mView->updateModelWithPrevMonth();
 	QList<CalenMonthData > monthDataList = mView->monthDataList();
 	mMonthDataArray = monthDataList;
-	int listCount = monthDataList.count();
-	// Get the updated rows to be inserted
-	int rowsInPrevMonth = mView->rowsInPrevMonth();
-	int rowsInFutMonth = mView->rowsInFutMonth();
+	
+	// Prepend the required rows
+	handlePrependingRows(monthDataList);
+		
+	// Since, we have finished setData, Now unblock the signals
+	mModel->blockSignals(false);
 	
-	// remove the cells in the future month
-	int deleteFromIndex = (rowsInPrevMonthEarlier + KNumOfVisibleRows) * KCalenDaysInWeek;
-	int numOfIndices = rowsInFutMonthEarlier * KCalenDaysInWeek;
-	int count = mModel->rowCount();
+	int rowsInPrevMonth = mView->rowsInPrevMonth();
+	int countToBeAdded = rowsInPrevMonth * KCalenDaysInWeek;
+		
+	// Since till now, we had blocked signals being generated frm the model
+	// view will be unaware of the items that we added. Hence, inform the view
+	// explicitly in one shot
+	QModelIndex leftIndex = mModel->index(0, 0);
+	QModelIndex rightIndex = mModel->index(countToBeAdded-1, 0);
+	dataChanged(leftIndex, rightIndex);
+		
+	// Now remove the necessary items frm the model
+	mModel->removeRows(deleteFromIndex+countToBeAdded, numOfIndices);
+	mIsAtomicScroll = true;
+	int itemToBeScrolled = rowsInPrevMonth * KCalenDaysInWeek;
+	QModelIndex indexToBeScrolled  = mModel->index(itemToBeScrolled, 0);
+	scrollTo(indexToBeScrolled);
 	
-	count = mModel->rowCount();
+	// Scroll to proper index
+	itemToBeScrolled = ((rowsInPrevMonth + KNumOfVisibleRows) * 
+								   KCalenDaysInWeek) - 1;
+	indexToBeScrolled = mModel->index(itemToBeScrolled, 0);
+	mIsAtomicScroll = true;
+	scrollTo(indexToBeScrolled);
+	// Update the mCurrentRow
+	mCurrentRow += countToBeAdded;
 	
+	// Update the sart position of the content widget
+	mStartPos = mContentWidget->pos();
+}
+
+/*!
+	Helper function that prepends the required rows to the model
+ */
+void CalenMonthGrid::handlePrependingRows(QList<CalenMonthData > &monthDataList)
+{
+	QDateTime currDate = mView->getCurrentDay();
+	QDateTime currDateTime = CalenDateUtils::beginningOfDay( currDate );
+	int rowsInPrevMonth = mView->rowsInPrevMonth();
 	// Add the new days
 	int countToBeAdded = rowsInPrevMonth * KCalenDaysInWeek;
 	
 	mModel->insertRows(0, countToBeAdded);
-	count = mModel->rowCount();
-	
-	// Get the default text color to be set
-	QColor textColor = HbColorScheme::color("qtc_cal_month_notactive_dates");
-	HbExtendedLocale locale = HbExtendedLocale::system();
 	
 	for (int i = 0; i < countToBeAdded; i++) {
 		QDateTime dateTime = monthDataList[i].Day();
 		
 		// Get the localised string for the day
-		QString date = locale.toString(dateTime.date().day());
 		QModelIndex currentIndex = mModel->index(i, 0);
 		
 		// Create the variant list to contain the date to depict a grid item
@@ -374,14 +633,14 @@
 		
 		// NOTE: Add the data in the order mentioned in the 
 		// CalendarNamespace::DataRole enum. Dont change the order.
-		itemData << date;
+		itemData << mLocalisedDates.at(dateTime.date().day()-1);;
 				
-		// Diable the focus role
-		itemData << QString("");
+		// Disable the focus role
+		itemData << false;
 		
 		// Check for current day
 		if  (currDateTime == CalenDateUtils::beginningOfDay( dateTime )) {
-			// Set the underline icon
+			// Set the underline icon attribute
 			itemData << true;
 		} else {
 			itemData << false;
@@ -389,39 +648,18 @@
 		
 		// Update the event indicators
 		if (monthDataList[i].HasEvents()) {
-			// Set the event indicator icon
-			itemData << QString("qtg_graf_cal_event_ind");
+			// Set the event indicator attribute
+			itemData << true;
 		} else {
-			itemData << QString("");
+			itemData << false;
 		}
 		
 		// Add default text color
-		
-		itemData << textColor;
+		itemData << false;
 		
 		// Set the data to model
 		mModel->itemFromIndex(currentIndex)->setData(itemData);
 	}
-	
-	// Update the mCurrentRow
-	mCurrentRow += countToBeAdded;
-	// Scroll to proper index
-	int itemToBeScrolled = ((rowsInPrevMonth + KNumOfVisibleRows) * 
-								   KCalenDaysInWeek) - 1;
-	QModelIndex indexToBeScrolled = mModel->index(itemToBeScrolled, 0);
-	QMap<int, QVariant> data;
-	data = mModel->itemData(indexToBeScrolled);
-	QVariant value = data.value(Qt::DisplayRole);
-	int date = value.toInt();
-	mIsAtomicScroll = true;
-	scrollTo(indexToBeScrolled);
-	
-	// Now remove the necessary items frm the model
-	mModel->removeRows(deleteFromIndex+countToBeAdded, numOfIndices);
-	mIsAtomicScroll = true;
-	itemToBeScrolled = rowsInPrevMonth * KCalenDaysInWeek;
-	indexToBeScrolled = mModel->index(itemToBeScrolled, 0);
-	scrollTo(indexToBeScrolled);
 }
 
 /*!
@@ -430,9 +668,19 @@
  */
 void CalenMonthGrid::appendRows()
 {
+	// Before we do anything, set the focus to proper date
+	// Set it only when non active day was focussed. When inactive day
+	// was focussed, we need to focus the same day
+	if (!mIsNonActiveDayFocused) {
+		setFocusToProperDay();
+	}
+	
+	// Block the signals generated by model, this is being done as
+	// we want to avoid the overload of view listening to signals
+	mModel->blockSignals(true);
+	
 	mIsNonActiveDayFocused = false;
-	QDateTime currDate = mView->getCurrentDay();
-	QDateTime currDateTime = CalenDateUtils::beginningOfDay( currDate );
+	
 	int rowsInFutMonth = mView->rowsInFutMonth();
 	int rowsInPrevMonth = mView->rowsInPrevMonth();
 	// remove the cells in the previous month
@@ -442,40 +690,80 @@
 	mView->updateModelWithFutureMonth();
 	QList<CalenMonthData > monthDataList = mView->monthDataList();
 	mMonthDataArray = monthDataList;
-	// Get the updated rows to be inserted
+	
+	// Get the model count before we add any rows into the mode
+	int rowCount = mModel->rowCount();
+	// Append the required rows
+	handleAppendingRows(monthDataList);
+	
+	// Since, we have finished setData, Now unblock the signals
+	mModel->blockSignals(false);
+	
+	// Since till now, we had blocked signals being generated frm the mode
+	// view will be unaware of the items that we added. Hence, inform the view
+	// explicitly in one shot
+	QModelIndex leftIndex = mModel->index(rowCount-1, 0);
+	QModelIndex rightIndex = mModel->index(mModel->rowCount()-1, 0);
+	dataChanged(leftIndex, rightIndex);
+		
+	// Update the mCurrentRow
+	mCurrentRow -= (countToBeDeleted);
+	for (int i = 0; i < countToBeDeleted; i++) {
+		mModel->removeRow(0);
+	}
+	
+	mIsAtomicScroll = true;
+	
+	rowsInFutMonth = mView->rowsInFutMonth();
 	rowsInPrevMonth = mView->rowsInPrevMonth();
-	rowsInFutMonth = mView->rowsInFutMonth();
+	
+	// Calculate the proper index to be scrolled to
+	int itemToBeScrolled = rowsInPrevMonth * KCalenDaysInWeek;
+	QModelIndex indexToBeScrolled = mModel->index(itemToBeScrolled, 0);
+	scrollTo(indexToBeScrolled);
+	
+	itemToBeScrolled = ((rowsInPrevMonth + KNumOfVisibleRows) * 
+									   KCalenDaysInWeek) - 1;
+	indexToBeScrolled = mModel->index(itemToBeScrolled, 0);
+	mIsAtomicScroll = true;
+	scrollTo(indexToBeScrolled);
+	
+	// Update the sart position of the content widget
+    mStartPos = mContentWidget->pos();
+}
+
+/*!
+	Helper function that appends the required rows to the model
+ */
+void CalenMonthGrid::handleAppendingRows(QList<CalenMonthData > &monthDataList)
+{
+	QDateTime currDate = mView->getCurrentDay();
+	QDateTime currDateTime = CalenDateUtils::beginningOfDay( currDate );
+	int rowsInFutMonth = mView->rowsInFutMonth();
 	int countToBeAdded = rowsInFutMonth * KCalenDaysInWeek;
 	int lastVisibleIndex = monthDataList.count() - countToBeAdded;
 	
 	int rowCount = mModel->rowCount();
 	mModel->insertRows(rowCount, countToBeAdded);
 	
-	// Get the default text color to be set
-	QColor textColor = HbColorScheme::color("qtc_cal_month_notactive_dates");
 	for (int i = 0; i < countToBeAdded; i++) {
-		QMap<int, QVariant> data;
 		QModelIndex currentIndex = mModel->index(rowCount + i, 0);
 				
 		QDateTime dateTime = monthDataList[lastVisibleIndex + i].Day();
-		HbExtendedLocale locale = HbExtendedLocale::system();
-		// Get the localised string for the day
-		QString date = locale.toString(dateTime.date().day());
-		data.insert(CalendarNamespace::CalendarMonthDayRole, date);
 		
 		// Create the variant list to contain the date to depict a grid item
 		QVariantList itemData;
 		
 		// NOTE: Add the data in the order mentioned in the 
 		// CalendarNamespace::DataRole enum. Dont change the order.
-		itemData << date;
+		itemData << mLocalisedDates.at(dateTime.date().day()-1);;
 		
 		// Disable the focus role
-		itemData << QString("");
+		itemData << false;
 		
 		// Check for current day
 		if (currDateTime == CalenDateUtils::beginningOfDay( dateTime )) {
-			// Set the underline icon
+			// Set the underline icon attribute
 			itemData << true;
 		} else {
 			itemData << false;
@@ -483,30 +771,18 @@
 		
 		// Update the event indicators
 		if (monthDataList[lastVisibleIndex + i].HasEvents()) {
-			// Set the underline icon
-			itemData << QString("qtg_graf_cal_event_ind");
+			// Set the event indicator attribute
+			itemData << true;
 		} else {
-			itemData << QString("");
+			itemData << false;
 		}
 		
 		// Add default text color
-		itemData << textColor;
+		itemData << false;
 				
 		// Set the data to model
 		mModel->itemFromIndex(currentIndex)->setData(itemData);
 	}
-	
-	// Update the mCurrentRow
-	mCurrentRow -= (countToBeDeleted);
-	for (int i = 0; i < countToBeDeleted; i++) {
-		mModel->removeRow(0);
-	}
-	mIsAtomicScroll = true;
-	
-	// Calculate the proper index to be scrolled to
-	int itemToBeScrolled = rowsInPrevMonth * KCalenDaysInWeek;
-	QModelIndex indexToBeScrolled = mModel->index(itemToBeScrolled, 0);
-	scrollTo(indexToBeScrolled);
 }
 
 /*!
@@ -521,14 +797,18 @@
 	mIsNonActiveDayFocused = false;
 	// Check if the same item has been tapped twice
 	if (mCurrentRow == index.row()) {
-		// Launch the agenda view
+		// Launch the Day view
 		mView->launchDayView();
 	} else {
 		// Reset the focus attribute to this item		
 		QModelIndex itemIndex = mModel->index(mCurrentRow,0);
+		if(itemIndex.row() < 0 || itemIndex.row() >= mModel->rowCount() ||
+				itemIndex.column() < 0 || itemIndex.column() > mModel->columnCount()) {
+			return;
+		}
 		QVariant itemData = itemIndex.data(Qt::UserRole + 1);
 		QVariantList list = itemData.toList();
-		list.replace(CalendarNamespace::CalendarMonthFocusRole, QString(""));
+		list.replace(CalendarNamespace::CalendarMonthFocusRole, false);
 		mModel->itemFromIndex(itemIndex)->setData(list);
 		
 		// Inform view to update the context and preview panes
@@ -537,7 +817,7 @@
 		itemData = itemIndex.data(Qt::UserRole + 1);
 		list = itemData.toList();
 		list.replace(CalendarNamespace::CalendarMonthFocusRole, 
-						 QString("qtg_fr_cal_focused_day_ind"));
+								 true);
 		mModel->itemFromIndex(itemIndex)->setData(list);
 		// Check if inactive date is tapped
 		QDateTime activeMonth = mView->getActiveDay();
@@ -547,17 +827,19 @@
 			mIsNonActiveDayFocused = true;
 			mNonActiveFocusedDay = mMonthDataArray[mCurrentRow].Day();
 			
-			// Get the current active month
-			QDateTime activeMonth = mView->getActiveDay();
-			// Add one month to it
+			// Add one month to active month
 			activeMonth = activeMonth.addMonths(1);
 			if (activeMonth.date().month() == 
 				mNonActiveFocusedDay.date().month()) {
+				mDirection = up;
 				// up gesture
-				upGesture(SCROLL_SPEEED);
+				upGesture();
+				setActiveDates(activeMonth.date());
 			} else {
+				mDirection = down;
 				// down gesture
-				downGesture(SCROLL_SPEEED);
+				downGesture();
+				setActiveDates(activeMonth.addMonths(-2).date());
 			}
 		} 
 		mView->setContextForActiveDay(index.row());
@@ -588,7 +870,7 @@
 	QModelIndex index = mModel->index(mCurrentRow,0);
 	QVariant itemData = index.data(Qt::UserRole + 1);
 	QVariantList list = itemData.toList();
-	list.replace(CalendarNamespace::CalendarMonthFocusRole, QString(""));
+	list.replace(CalendarNamespace::CalendarMonthFocusRole, false);
 	mModel->itemFromIndex(index)->setData(list);
 	
 	// Search for this date in the model
@@ -598,7 +880,7 @@
 			itemData = index.data(Qt::UserRole + 1);
 			list = itemData.toList();
 			list.replace(CalendarNamespace::CalendarMonthFocusRole,
-							 QString("qtg_fr_cal_focused_day_ind"));
+										 true);
 			mModel->itemFromIndex(index)->setData(list);
 			mCurrentRow = i;
 			mView->setContextForActiveDay(i);
@@ -635,15 +917,12 @@
 	end = firstDateInGrid.daysTo(endOfActiveMonth);
 	
 	// Set the active text color
-	QColor textColor = HbColorScheme::color("qtc_cal_month_active_dates");
-	if (textColor.isValid()) {
-		for (int i = start; i < end; i++) {	
-			QModelIndex index = mModel->index(i,0);
-			QVariant itemData = index.data(Qt::UserRole + 1);
-			QVariantList list = itemData.toList();
-			list.replace(CalendarNamespace::CalendarMonthTextColorRole, textColor);
-			mModel->itemFromIndex(index)->setData(list);
-		}
+	for (int i = start; i < end; i++) {	
+		QModelIndex index = mModel->index(i,0);
+		QVariant itemData = index.data(Qt::UserRole + 1);
+		QVariantList list = itemData.toList();
+		list.replace(CalendarNamespace::CalendarMonthTextColorRole, true);
+		mModel->itemFromIndex(index)->setData(list);
 	}
 	
 	// Now set the inactive text color to those which were active before the swipe
@@ -683,15 +962,12 @@
 	}
 	
 	// Set the inactive text color
-	textColor = HbColorScheme::color("qtc_cal_month_notactive_dates");
-	if (textColor.isValid()) {
-		for (int i = start; i < end; i++) {		
-			QModelIndex index = mModel->index(i,0);
-			QVariant itemData = index.data(Qt::UserRole + 1);
-			QVariantList list = itemData.toList();
-			list.replace(CalendarNamespace::CalendarMonthTextColorRole, textColor);
-			mModel->itemFromIndex(index)->setData(list);
-		}
+	for (int i = start; i < end; i++) {		
+		QModelIndex index = mModel->index(i,0);
+		QVariant itemData = index.data(Qt::UserRole + 1);
+		QVariantList list = itemData.toList();
+		list.replace(CalendarNamespace::CalendarMonthTextColorRole, false);
+		mModel->itemFromIndex(index)->setData(list);
 	}
 }
 
@@ -719,6 +995,29 @@
     Q_UNUSED(newOrientation)
 	// We are overriding this function to avoid the default behavior of
 	// hbgridview on orientation change as it swaps the row and column counts
+	// Calculate the proper index to be scrolled to
+	int rowsInPrevMonth;
+    int itemToBeScrolled;
+    QModelIndex indexToBeScrolled;
+	if (newOrientation == Qt::Horizontal) {
+		rowsInPrevMonth = mView->rowsInPrevMonth();
+		itemToBeScrolled = rowsInPrevMonth * KCalenDaysInWeek;
+		indexToBeScrolled = mModel->index(itemToBeScrolled, 0);
+		mIsAtomicScroll = true;
+		scrollTo(indexToBeScrolled);
+	} else {
+		rowsInPrevMonth = mView->rowsInPrevMonth();
+		itemToBeScrolled = rowsInPrevMonth * KCalenDaysInWeek;
+		indexToBeScrolled = mModel->index(itemToBeScrolled, 0);
+		mIsAtomicScroll = true;
+		scrollTo(indexToBeScrolled);
+		
+		itemToBeScrolled = ((rowsInPrevMonth + KNumOfVisibleRows) * 
+				KCalenDaysInWeek) - 1;
+		indexToBeScrolled = mModel->index(itemToBeScrolled, 0);
+		mIsAtomicScroll = true;
+		scrollTo(indexToBeScrolled);
+	}
 }
 
 /*!
@@ -730,29 +1029,51 @@
 {
 	Q_UNUSED(option);
 	Q_UNUSED(widget);
+	painter->setRenderHint(QPainter::NonCosmeticDefaultPen);
 	
 	// Set the required attributes to the pen
 	QPen pen;
+	HbDeviceProfile deviceProf;
+	qreal unitValue = deviceProf.unitValue();
+	qreal widthInPixels = GRIDLINE_WIDTH * unitValue;
 	pen.setStyle(Qt::SolidLine);
-	pen.setWidth(GRIDLINE_WIDTH);
+	pen.setWidth(widthInPixels);
 	if (mGridLineColor.isValid()) {
 		pen.setBrush(mGridLineColor);
 	} else {
 		pen.setBrush(mGridBorderColor);
 	}
-	// Set the pen to the painter
+	//store the old pen first
+    QPen oldPen = painter->pen();
+	// Set the new pen to the painter
 	painter->setPen(pen);
 	
 	// Get the sizes of content widget
 	qreal contentHeight = mContentWidget->size().height();
 	qreal contentWidth = mContentWidget->size().width();
+	qreal rowWidth = 0.0;
+	int numOfRows = 0;
+	QPointF startPoint = mContentWidget->pos();
 	
-	// Get the num of rows
-	int numOfRows = mModel->rowCount() / KCalenDaysInWeek;
-	// Draw horizontal lines
-	qreal rowWidth = contentHeight / numOfRows;
+	// NOTE!!!: There is a filcker when we blindly draw equally spaced lines
+	// on complete content widget when scrolling is finished. This happens only
+	// when content widget size is changed due to the change in total number
+	// of rows when we append or prepend rows. Hence, to avoid this, we draw
+	// lines on complete content widget only when it is scrolling.
+	// That means, as soon as scrolling is finished, we will end up drawing 
+	// only 6 lines that are visible to the user.
+	if (mDirection == invalid) {
+		// Start point is left most point on the screen
+		startPoint = QPointF(0,0);
+		rowWidth = size().height() / KNumOfVisibleRows;
+		numOfRows = KNumOfVisibleRows;
+	} else {
+		// Get the num of rows
+		numOfRows = mModel->rowCount() / KCalenDaysInWeek;
+		// Draw horizontal lines
+		rowWidth = contentHeight / numOfRows;
+	}
 	
-	QPointF startPoint = mContentWidget->pos();
 	QPointF endPoint(startPoint.x() + contentWidth, 
 	                 startPoint.y());
 	
@@ -780,6 +1101,8 @@
 	
 	// Draw the lines for the points in the vector list
 	painter->drawLines(pointList);
+	// Set the old pen back
+	painter->setPen(oldPen);
 }
 
 // End of File