calendarui/views/src/calenpreviewpane.cpp
branchRCL_3
changeset 65 12af337248b1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/calendarui/views/src/calenpreviewpane.cpp	Tue Aug 31 15:13:43 2010 +0300
@@ -0,0 +1,538 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  CalenPreviewPane implementation.
+*
+*/
+
+
+// System includes
+#include <QtGui>
+#include <qfont.h>
+#include <qicon.h>
+#include <qpainter.h>
+#include <qevent.h>
+#include <hblabel.h>
+#include <hbmainwindow.h>
+#include <hbframeitem.h>
+#include <hbframedrawer.h>
+#include <hbfontspec.h>
+#include <hbcolorscheme.h>
+#include <hbtapgesture.h>
+#include <hbpangesture.h>
+#include <hbinstance.h>
+#include <hbinstantfeedback.h>
+#include <agendautil.h>
+#include <agendaentry.h>
+
+//user includes
+#include "calenagendautils.h"
+#include "calendateutils.h"
+#include "calencontext.h"
+#include "calenservices.h"
+#include "calenservices.h"
+#include "calencommon.h"
+#include "calenpreviewpane.h"
+#include "calenmonthview.h"
+#include "OstTraceDefinitions.h"
+#ifdef OST_TRACE_COMPILER_IN_USE
+#include "calenpreviewpaneTraces.h"
+#endif
+
+
+// Macros
+#define TWO_SECONDS_TIMER 2000 // millseconds
+#define SCROLLING_SPEED 10
+#define MAX_PAN_DIRECTION_THRESHOLD 50
+#define MIN_PAN_DIRECTION_THRESHOLD 10
+
+static const QString EMPTYSTRING(" ");
+
+/*!
+ Constructor
+ */
+CalenPreviewPane::CalenPreviewPane(MCalenServices& services, 
+							QGraphicsItem* parent)
+	: HbScrollArea(parent),mServices(services)
+{
+    OstTraceFunctionEntry0( CALENPREVIEWPANE_CALENPREVIEWPANE_ENTRY );
+    
+	// Create the timer
+	mTwoSecTimer = new QTimer(this);
+	mScrollDirection = invalid;
+	mIsNoEntriesAdded = true;
+	mIsGestureHandled = false;
+	mNoEntriesLabel = 0;
+	mHtDiff = 0.0;
+	mScrollDuration = 0;
+	mPreviewTextColor = HbColorScheme::color("qtc_cal_day_preview_text");
+	
+	setAcceptDrops(true);
+	setScrollDirections(Qt::Vertical);
+	setVerticalScrollBarPolicy(HbScrollArea::ScrollBarAlwaysOff);
+	
+	// Connect the scrollig finished signal
+	connect(this, SIGNAL(scrollingEnded()), this,
+				SLOT(scrollingFinished()));
+	
+	grabGesture(Qt::TapGesture);
+	grabGesture(Qt::PanGesture);
+
+	OstTraceFunctionExit0( CALENPREVIEWPANE_CALENPREVIEWPANE_EXIT );
+}
+
+/*!
+ Destructor
+ */
+CalenPreviewPane::~CalenPreviewPane()
+{
+    OstTraceFunctionEntry0( DUP1_CALENPREVIEWPANE_CALENPREVIEWPANE_ENTRY );
+    
+    OstTraceFunctionExit0( DUP1_CALENPREVIEWPANE_CALENPREVIEWPANE_EXIT );
+}
+
+/*!
+ Stores the "No Entries for today" label
+ */
+void CalenPreviewPane::setNoEntriesLabel(HbLabel* label)
+{
+    OstTraceFunctionEntry0( CALENPREVIEWPANE_SETNOENTRIESLABEL_ENTRY );
+    
+	mNoEntriesLabel = label;
+	
+	if (mPreviewTextColor.isValid()) {
+		mNoEntriesLabel->setTextColor(mPreviewTextColor);
+	}
+	OstTraceFunctionExit0( CALENPREVIEWPANE_SETNOENTRIESLABEL_EXIT );
+}
+
+/*!
+ Populates the preview with proper data
+ */
+void CalenPreviewPane::populateLabel(QDateTime date)
+{
+    OstTraceFunctionEntry0( CALENPREVIEWPANE_POPULATELABEL_ENTRY );
+    
+	mScrollDirection = up;
+	
+	// Scroll contents to zero position before we display to the user
+	// if it was scrolling already or timer was running
+	mNumOfScrolls = 0;
+	mScrollDuration = 0;
+	stopScrolling();
+	
+	mDate = date;
+	
+	// Get Instances for the day
+	GetInstanceListL();
+	
+	// Get the content of the scroll area
+	QGraphicsWidget* content = contentWidget();
+	// Adjust the layout
+	QGraphicsLinearLayout* layout = static_cast<QGraphicsLinearLayout *>
+															(content->layout());
+	int instanceCount = mInstanceArray.count();
+	HbFontSpec font(HbFontSpec::Secondary);
+	if (mIsNoEntriesAdded) {
+		if (!instanceCount) {
+			if (mPreviewTextColor.isValid()) {
+				mNoEntriesLabel->setTextColor(mPreviewTextColor);
+			}
+		    mNoEntriesLabel->setVisible(true);
+		    OstTraceFunctionExit0( CALENPREVIEWPANE_POPULATELABEL_EXIT );
+		    return;
+		} else {
+			// Remove the no entries label
+			mNoEntriesLabel->setVisible(false);
+		}
+	}
+	int count = layout->count();
+	int labelCount = mLabelList.count();
+	for (int i = 0; i < labelCount; i++) {
+		mLabelList.at(i)->clear();
+	}
+	if (instanceCount) {
+		mIsNoEntriesAdded = false;
+		// Parse the instances and add them to the layout
+		for (int i = 0; i <instanceCount; i++) {
+			HbLabel* label;
+			if(!count) {
+				label = new HbLabel(this);
+				
+				// Set the required font
+				label->setFontSpec(font);
+				
+				// Set the elide mode to right
+				label->setElideMode(Qt::ElideRight);
+				// Add the label to the list
+				mLabelList.append(label);
+				layout->addItem(label);
+			} else {
+				// Reuse the same label
+				label = mLabelList.at(i);
+				count--;
+			}
+			
+			if (mPreviewTextColor.isValid()) {
+				label->setTextColor(mPreviewTextColor);
+			}
+			QString summary = mInstanceArray[i].summary();
+			if(!summary.length()) {
+				// No summary display "Unnamed"
+				summary.append(hbTrId("txt_calendar_preview_unnamed"));
+			}
+			// Check the entry type, based on the type display time field in
+			// preview pane.
+			QString start;
+			if(mInstanceArray[i].type() != AgendaEntry::TypeTodo && 
+					mInstanceArray[i].type() != AgendaEntry::TypeAnniversary && 
+					!CalenAgendaUtils::isAlldayEvent(mInstanceArray[i])) {
+				QDateTime startTime = mInstanceArray[i].startTime();
+				// Check if event starts in past
+				checkStartTimeOfEvent(startTime);
+				HbExtendedLocale systemLocale =HbExtendedLocale::system();
+				start = systemLocale.format(startTime.time(), 
+				                                    r_qtn_time_usual_with_zero);
+				start.append(EMPTYSTRING);	
+			}
+			// Append summary to start time
+			QString text = start.append(summary);
+			label->setPlainText(text);
+			layout->setStretchFactor(label,0);
+		}
+		
+		// Cleanup the remaining labels
+		if (count) {
+			int layoutCount = layout->count();
+			int offset = layoutCount - count;
+			int labelCount = mLabelList.count();
+			for (int i = 0; i < count; i++) {
+				QGraphicsLayoutItem* item = layout->itemAt(offset);
+				layout->removeAt(offset);
+				int index = --labelCount;
+				mLabelList.removeAt(index);
+				if (item) {
+					delete item;
+				}
+			}
+		}
+	} else { // Delete all the items in the layout
+		// TODO: Need to see if we can clear all the items at one shot
+		// remove the items if any
+		for (int i = 0; i < count; i++) {
+			QGraphicsLayoutItem* item = layout->itemAt(0);
+			layout->removeAt(0);
+			// Clear the label text
+			mLabelList.at(i)->clear();
+			if (item) {
+				delete item;
+			}
+		}
+		// Clear the list
+		mLabelList.clear();
+		
+		if (mPreviewTextColor.isValid()) {
+			mNoEntriesLabel->setTextColor(mPreviewTextColor);
+		}
+		// Add the no entries text to the preview pane
+		mNoEntriesLabel->setVisible(true);
+		mIsNoEntriesAdded = true;
+	}
+	layout->activate();
+	
+	OstTraceFunctionExit0( DUP1_CALENPREVIEWPANE_POPULATELABEL_EXIT );
+}
+
+/*!
+ Fetches the instance for a given day
+ */
+void CalenPreviewPane::GetInstanceListL()
+{
+    OstTraceFunctionEntry0( CALENPREVIEWPANE_GETINSTANCELISTL_ENTRY );
+    
+	mInstanceArray.clear();
+
+	// Find Meetings, Remainders, Anniversaries and Day Notes
+	QDateTime dayStart( CalenDateUtils::beginningOfDay( mDate ) );
+
+	// Make a request to get all the entries for the mDate
+	AgendaUtil::FilterFlags filter = AgendaUtil::FilterFlags(
+										AgendaUtil::IncludeAnniversaries |
+										AgendaUtil::IncludeAppointments |
+											AgendaUtil::IncludeEvents |
+											AgendaUtil::IncludeIncompletedTodos | 
+										AgendaUtil::IncludeReminders);
+	mInstanceArray = mServices.agendaInterface()->
+									createEntryIdListForDay(dayStart, filter);
+	
+	OstTraceFunctionExit0( CALENPREVIEWPANE_GETINSTANCELISTL_EXIT );
+}
+
+/*!
+ Returns the date which this preview pane is representing
+ */
+QDateTime CalenPreviewPane::Date()
+{
+    OstTraceFunctionEntry0( CALENPREVIEWPANE_DATE_ENTRY );
+    
+	OstTraceFunctionExit0( CALENPREVIEWPANE_DATE_EXIT );
+	return mDate;
+}
+
+/*!
+ Starts the auto scroll on the preview pane
+ */
+void CalenPreviewPane::startAutoScroll()
+{
+    OstTraceFunctionEntry0( CALENPREVIEWPANE_STARTAUTOSCROLL_ENTRY );
+    
+	if (mIsNoEntriesAdded) {
+		scrollContentsTo(QPointF(0.0,0.0));
+		OstTraceFunctionExit0( CALENPREVIEWPANE_STARTAUTOSCROLL_EXIT );
+		return;
+	}
+	
+	// Stop the timer
+	mTwoSecTimer->stop();
+	
+	// Set the proper scroll direction
+	mScrollDirection = up;
+	
+	// Start the 2 seconds timer
+	mTwoSecTimer->setSingleShot(true);
+	connect(mTwoSecTimer, SIGNAL(timeout()), this, SLOT(onTwoSecondsTimeout()));
+	mTwoSecTimer->start(TWO_SECONDS_TIMER);
+	
+	OstTraceFunctionExit0( DUP1_CALENPREVIEWPANE_STARTAUTOSCROLL_EXIT );
+}
+
+/*!
+ Slot to handle two seconds timer time out
+ Starts the scrolling animation in required direction
+ */
+void CalenPreviewPane::onTwoSecondsTimeout()
+{
+    OstTraceFunctionEntry0( CALENPREVIEWPANE_ONTWOSECONDSTIMEOUT_ENTRY );
+    
+	mTwoSecTimer->stop();
+	disconnect(mTwoSecTimer, SIGNAL(timeout()), 
+										   this, SLOT(onTwoSecondsTimeout()));
+	
+	// Calculate the timer and the height difference of pane and its content
+	if (!mScrollDuration) {
+        qreal contentHeight = contentWidget()->size().height();
+        qreal paneHeight = size().height();
+        mHtDiff = contentHeight - paneHeight;
+        if (mHtDiff > 0) { // content is more than widget height, we need to scroll
+            mScrollDuration = mHtDiff / SCROLLING_SPEED;
+        }
+	}
+	
+    // Start the scrolling in the proper direction
+	if (mScrollDirection == up && mScrollDuration) {
+		// Start scrolling upwards
+		mScrollDirection = down;
+		mNumOfScrolls++;
+		QPointF targetPos(0.0, -mHtDiff);
+        scrollContentsTo(-targetPos, mScrollDuration * 1000);
+	} else if (mScrollDirection == down && mScrollDuration) {
+		mScrollDirection = up;
+		mNumOfScrolls++;
+		// Start scrolling downwards
+		QPointF targetPos(0.0, 0.0);
+        scrollContentsTo(targetPos, mScrollDuration * 1000);
+	}
+	
+	OstTraceFunctionExit0( CALENPREVIEWPANE_ONTWOSECONDSTIMEOUT_EXIT );
+}
+
+/*!
+ Slot to handle scrolling finished
+ Restarts the two seconds timer
+ */
+void CalenPreviewPane::scrollingFinished()
+{
+    OstTraceFunctionEntry0( CALENPREVIEWPANE_SCROLLINGFINISHED_ENTRY );
+    
+	// If we are here because of calling scrollContentsTo()
+	if (!mNumOfScrolls) {
+		OstTraceFunctionExit0( CALENPREVIEWPANE_SCROLLINGFINISHED_EXIT );
+		return;
+	}
+	// Now start the two seconds timer again
+	mTwoSecTimer->setSingleShot(true);
+	connect(mTwoSecTimer, SIGNAL(timeout()), this, SLOT(onTwoSecondsTimeout()));
+	mTwoSecTimer->start(TWO_SECONDS_TIMER);
+	
+	OstTraceFunctionExit0( DUP1_CALENPREVIEWPANE_SCROLLINGFINISHED_EXIT );
+}
+
+/*!
+    Function to listen for all gestures
+ */
+void CalenPreviewPane::gestureEvent(QGestureEvent *event)
+{
+    OstTraceFunctionEntry0( CALENPREVIEWPANE_GESTUREEVENT_ENTRY );
+    
+    if(HbPanGesture *gesture = qobject_cast<HbPanGesture *>(event->gesture(Qt::PanGesture))) {
+        if (gesture->state() == Qt::GestureUpdated) {
+            // Check if effect is not yet completed, ignore the current gesture if it is
+            if (mIsGestureHandled) {
+                OstTraceFunctionExit0( CALENPREVIEWPANE_GESTUREEVENT_EXIT );
+                return;
+            }
+            // TODO: This work around 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
+            QPointF delta = gesture->delta();
+            // Check the current orientation of the device and
+            // swap the vertical and horizontal distances in landscape
+            qreal horizontalDiff = 0.0;
+            qreal verticalDiff = 0.0;
+            if (hbInstance->allMainWindows().at(0)->orientation() == Qt::Vertical) {
+                horizontalDiff = delta.x();
+                verticalDiff = delta.y();
+            } else {
+                horizontalDiff = delta.y();
+                verticalDiff = delta.x();
+            }
+            if (abs(verticalDiff) > MAX_PAN_DIRECTION_THRESHOLD) {
+                // Now see if x coord diff has crossed threshold
+                if (horizontalDiff > MAX_PAN_DIRECTION_THRESHOLD) {
+                    mIsGestureHandled = true;
+                    // right gesture
+                    mView->handlePreviewPaneGesture(true);
+                    event->accept(Qt::PanGesture);
+                } else if (horizontalDiff < -MAX_PAN_DIRECTION_THRESHOLD){
+                    mIsGestureHandled = true;
+                    // left gesture
+                    mView->handlePreviewPaneGesture(false);
+                    event->accept(Qt::PanGesture);
+                } else {
+                    event->accept(Qt::PanGesture);
+                    OstTraceFunctionExit0( DUP1_CALENPREVIEWPANE_GESTUREEVENT_EXIT );
+                    return;
+                }
+            } else if (abs(verticalDiff) < MAX_PAN_DIRECTION_THRESHOLD) {
+               if (horizontalDiff > MIN_PAN_DIRECTION_THRESHOLD) {
+                   mIsGestureHandled = true;
+                   // right gesture
+                   mView->handlePreviewPaneGesture(true);
+                   event->accept(Qt::PanGesture);
+               } else if (horizontalDiff < -MIN_PAN_DIRECTION_THRESHOLD){
+                   mIsGestureHandled = true;
+                   // left gesture
+                   mView->handlePreviewPaneGesture(false);
+                   event->accept(Qt::PanGesture);
+               }else {
+                   event->accept(Qt::PanGesture);
+                   OstTraceFunctionExit0( DUP2_CALENPREVIEWPANE_GESTUREEVENT_EXIT );
+                   return;
+               }
+            }
+        }
+    } else if(QTapGesture *tapGesture = qobject_cast<QTapGesture *>(event->gesture(Qt::TapGesture))) {
+        if (tapGesture && tapGesture->state() == Qt::GestureFinished) {
+            	HbInstantFeedback::play(HbFeedback::Basic);
+                // Preview pane tapped
+            	// Stop the scrolling first
+            	stopScrolling();
+            	// Issue command to launch agenda view
+                mServices.IssueCommandL(ECalenAgendaView);
+                mView->disconnectAboutToQuitEvent();
+                event->accept(Qt::TapGesture);
+        }
+    }
+    
+    OstTraceFunctionExit0( DUP3_CALENPREVIEWPANE_GESTUREEVENT_EXIT );
+}
+
+/*!
+ Set monthview pointer
+ */
+void CalenPreviewPane::setView(CalenMonthView* view)
+{
+    OstTraceFunctionEntry0( CALENPREVIEWPANE_SETVIEW_ENTRY );
+    
+	mView = view;
+	
+	OstTraceFunctionExit0( CALENPREVIEWPANE_SETVIEW_EXIT );
+}
+
+/*!
+ Stops the auto scrolling
+ */
+void CalenPreviewPane::stopScrolling()
+{
+    OstTraceFunctionEntry0( CALENPREVIEWPANE_STOPSCROLLING_ENTRY );
+    
+    mTwoSecTimer->stop();
+	if (isScrolling()) {
+        mNumOfScrolls = 0; // required so that timer will not get started again in 
+        // scrollingFinished() slot
+        // Stop the scrolling by sending the foucs out event
+        QFocusEvent* focusEvent = new QFocusEvent(QFocusEvent::FocusOut, Qt::MouseFocusReason);
+        focusOutEvent(focusEvent); 
+        
+        // Set the contents position to zero
+		scrollContentsTo(QPointF(0.0,0.0));
+	}
+	
+	OstTraceFunctionExit0( CALENPREVIEWPANE_STOPSCROLLING_EXIT );
+}
+
+/*!
+ Checks if the start time of the event falls on the date for which preview
+ pane is being shown. If start time is in past, then time will be 12:00AM
+ */
+void CalenPreviewPane::checkStartTimeOfEvent(QDateTime &dateTime)
+{
+    // If event start time is in past
+    if (dateTime.date() < mDate.date()) {
+        // Set the time to 12:00AM of mDate
+        dateTime.setDate(mDate.date());
+        QTime time(0,0,0,0); // 0 means 12:00 AM
+        dateTime.setTime(time);
+    }
+}
+
+/*!
+ Sets the effect beign handled flag to true
+ */
+void CalenPreviewPane::effectStarted()
+{
+    mIsGestureHandled = true;
+}
+
+/*!
+ Resets the effect beign handled flag to true
+ */
+void CalenPreviewPane::effectFinished()
+{
+    mIsGestureHandled = false;
+}
+
+/*!
+ Slot to handle the change in theme
+ */
+void CalenPreviewPane::handleThemeChange()
+{
+    OstTraceFunctionEntry0( CALENPREVIEWPANE_HANDLETHEMECHANGE_ENTRY );
+    
+    mPreviewTextColor = HbColorScheme::color("qtc_cal_day_preview_text");
+    
+    OstTraceFunctionExit0( CALENPREVIEWPANE_HANDLETHEMECHANGE_EXIT );
+}
+
+// End of file  --Don't remove this.