calendarwidgetplugin/src/contentlayouthandler.cpp
changeset 0 db1bf15cefff
child 1 f8e7eccf5f96
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/calendarwidgetplugin/src/contentlayouthandler.cpp	Tue Jul 06 11:55:49 2010 +0300
@@ -0,0 +1,1207 @@
+/*
+* 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: Homescreen calendar widget's content layout handler.
+*
+*/
+
+// System includes
+#include <HbColorScheme>
+#include <QDateTime>
+#include <HbLabel>
+#include <HbDocumentLoader>
+#include <HbCore>
+#include <HbFrameDrawer>
+#include <HbFrameItem>
+#include <QTimer>
+#ifndef TEST
+#include <agendautil.h>
+#else
+#include "mockagendautil.h"
+#endif
+#include <agendaentry.h>
+#include <xqsettingsmanager.h>
+#include <xqsettingskey.h>
+#include <calnotification.h>
+#include <QGraphicsLayout>
+#include <QPointF>
+#include <xqaiwrequest.h>
+#include <xqappmgr.h>
+#include <QCoreApplication>
+
+// User includes
+#include "contentlayouthandler.h"
+#include "calendarwidgetdebug.h"
+#include "datetimeobserver.h"
+
+// Local constants
+namespace {
+    const HbFrameDrawer::FrameType REMINDER_FRAME_TYPE = HbFrameDrawer::OnePiece;
+    const char *CONTENT_CONTAINER = "contentContainer";
+    const char *UPPER_LABEL_SHORT = "upperLabelShort";
+    const char *UPPER_LABEL_LONG = "upperLabelLong";
+    const char *MIDDLE_LABEL = "middleLabel";
+    const char *LOWER_LABEL = "lowerLabel";
+    const char *REMINDER_ICON_LABEL = "reminderLabel";
+    const char *REMINDER_IMAGE_NAME = "qtg_small_reminder";
+    const char *HIGHLIGHT_IMAGE_NAME = "qtg_fr_hsitems_pressed";
+    //same color applies to upper and middle labels
+    const char *UPPER_LABEL_COLOR = "qtc_hs_list_item_title_normal";
+    const char *LOWER_LABEL_COLOR = "qtc_hs_list_item_content_normal";
+    const char *HIGHLIGHT_LABEL_COLOR = "qtc_hs_list_item_pressed";
+    // time constants
+    const int KHalfHour = 30;
+    const int KSecondInMillisec = 1000;
+    const int KSecondsInMinute = 60;
+    const int KToday = 1;
+    const int KComingDays = 0;
+    const int KDaysInWeek = 7;
+    const int KHourMinuteSeparatorIndex = 1;
+    const int KPassedEventTimeoutSecs = 1800; // Half hour
+    
+    //from DateIconLayoutHandler
+    const HbFrameDrawer::FrameType DATE_ICON_BACKGROUND_FRAME_TYPE = HbFrameDrawer::OnePiece;
+    const char *ICON_CONTAINER = "iconContainer";
+    const char *DATE_ICON_LABEL = "iconLabel";
+    const char *DATE_ICON_DAYNUMBER = "dayNumber";
+    const char *DATE_ICON_MONTHLABEL = "month";
+    const char *DATE_ICON_HIGHLIGHTLABEL = "iconHighlight";
+    const char *NUMBER_LABEL_COLOR = "qtc_hs_cal";
+    const char *MONTH_LABEL_COLOR = "qtc_hs_list_item_title_normal";
+    //const char *HIGHLIGHT_LABEL_COLOR = "qtc_hs_list_item_pressed";
+    const char *DATE_BACKGROUND = "qtg_large_calendar_dynamic";
+    //const char *HIGHLIGHT_IMAGE_NAME = "qtg_fr_hsitems_pressed";
+    
+    //From MainLayoutHandler
+    const char WIDGET[] = "CalendarWidget";
+    const char *BACKGROUND_LABEL = "widgetBackground";
+    const char *SEPARATOR_LABEL = "separatorLabel";
+    const char *SEPARATOR_IMAGE_NAME = "qtg_graf_divider_v_thin";
+    const char *BACKGROUND_IMAGE_NAME = "qtg_fr_hswidget_normal";
+    const HbFrameDrawer::FrameType BACKGROUND_FRAME_TYPE = HbFrameDrawer::NinePieces;
+    const HbFrameDrawer::FrameType SEPARATOR_FRAME_TYPE = HbFrameDrawer::OnePiece;
+}
+
+// ======== MEMBER FUNCTIONS ========
+
+/*
+ * ContentLayoutHandler::ContentLayoutHandler()
+ */
+ContentLayoutHandler::ContentLayoutHandler()
+        : mContainer(0),
+          mReminderLabel(0),
+          mUpperLabelShort(0),
+          mUpperLabelLong(0),
+          mMiddleLabel(0),
+          mLowerLabel(0),
+          mIconContainer(0),
+          mIconLabel(0),
+          mNumberLabel(0),
+          mMonthLabel(0),
+          mHighlightLabel(0),
+          mDateIconFrameDrawer(0),
+          mReminderDrawer(0),
+          mEventTimer(0),
+          mAgendaUtil(0),
+          mCalendarKeyManager(0),
+          mDateHighlightActive(0),
+          mContentHighlightActive(0)
+{
+    LOGS("ContentLayoutHandler::ContentLayoutHandler");
+
+    mCalendarKeyManager = new XQSettingsManager();
+    unsigned long int key = (unsigned long int)ECalPubSubEventNotification;
+    XQSettingsKey calendarKey(XQSettingsKey::TargetPublishAndSubscribe,
+        KCalPubSubCategory.iUid, key);
+    mCalendarKeyManager->startMonitoring(calendarKey);
+    connect(mCalendarKeyManager, SIGNAL(valueChanged(XQSettingsKey, QVariant)),
+        this, SLOT(calendarChanged(XQSettingsKey, QVariant)));
+}
+
+/*
+ * ContentLayoutHandler::~ContentLayoutHandler()
+ */
+ContentLayoutHandler::~ContentLayoutHandler()
+{
+    LOGS("ContentLayoutHandler::~ContentLayoutHandler");
+    unsigned long int key = (unsigned long int)ECalPubSubEventNotification;
+    XQSettingsKey calendarKey(XQSettingsKey::TargetPublishAndSubscribe,
+        KCalPubSubCategory.iUid, key);
+    mCalendarKeyManager->stopMonitoring(calendarKey);
+    delete mCalendarKeyManager;
+}
+
+/*
+ * ContentLayoutHandler::initializeLayout()
+ */
+void ContentLayoutHandler::initializeLayout(const HbDocumentLoader &layoutLoader,
+    QObject *owner)
+{
+    this->setParent(owner);
+    this->setObjectName("contentlayouthandler");
+    
+    //From MainLayoutHandler
+    mWidget = (HbWidget*)layoutLoader.findWidget(WIDGET);
+    mBgLabel = qobject_cast<HbLabel*>(layoutLoader.findWidget(BACKGROUND_LABEL));
+    mSeparatorLabel = qobject_cast<HbLabel*>(layoutLoader.findWidget(QString(SEPARATOR_LABEL)));
+
+    // Discontinue initialization of the main widget is missing
+    if (!mWidget) {
+        return;
+    }
+
+    addItem(mWidget);
+    mWidget->setVisible(true);
+
+    // Create main background drawer
+    if (mBgLabel) {
+        HbFrameDrawer* backgroundFrameDrawer = new HbFrameDrawer(BACKGROUND_IMAGE_NAME,
+            BACKGROUND_FRAME_TYPE);
+        mBackgroundLayoutItem = new HbFrameItem(backgroundFrameDrawer);
+        mBgLabel->setBackgroundItem(mBackgroundLayoutItem);
+    }
+    
+    // Create separator graphics drawer
+    HbFrameDrawer* separatorFrameDrawer = new HbFrameDrawer(SEPARATOR_IMAGE_NAME,
+        SEPARATOR_FRAME_TYPE);
+    mSeparatorLayoutItem = new HbFrameItem(separatorFrameDrawer);
+    mSeparatorLabel->setBackgroundItem(mSeparatorLayoutItem);
+
+    setPreferredSize(mWidget->preferredSize());
+    //END
+    
+    //From DateIconLayoutHandler
+    mIconContainer = qobject_cast<HbWidget*>(layoutLoader.findWidget(QString(ICON_CONTAINER)));
+    mIconLabel = qobject_cast<HbLabel*>(layoutLoader.findWidget(QString(DATE_ICON_LABEL)));
+    mNumberLabel = qobject_cast<HbLabel*>(layoutLoader.findWidget(QString(DATE_ICON_DAYNUMBER)));
+    mMonthLabel = qobject_cast<HbLabel*>(layoutLoader.findWidget(QString(DATE_ICON_MONTHLABEL)));
+    mHighlightLabel = qobject_cast<HbLabel*>(layoutLoader.findWidget(QString(DATE_ICON_HIGHLIGHTLABEL)));
+
+    // Create background drawer only if day container loading succeeded
+    if (mIconLabel) {
+        mDateIconFrameDrawer = new HbFrameDrawer(DATE_BACKGROUND, DATE_ICON_BACKGROUND_FRAME_TYPE);
+        HbFrameItem* dateIconFrameItem = new HbFrameItem(mDateIconFrameDrawer);
+        mIconLabel->setBackgroundItem(dateIconFrameItem);
+    }
+
+    setCalendarIconContent();
+    setLabelsColor();
+
+    // The icon label should never show text
+    if (mIconLabel) {
+        mIconLabel->clear();
+    }
+    if (mHighlightLabel) {
+        mHighlightLabel->clear();
+    }
+
+    
+    mDateObserver = new DateTimeObserver();
+    connect(mDateObserver, SIGNAL(completed()), this, SIGNAL(dateChanged()));
+    connect(this, SIGNAL(dateChanged()), this, SLOT(updateLayout()));
+    //END
+    
+    // Get widget handles
+    mContainer = qobject_cast<HbWidget*>(
+        layoutLoader.findWidget(QString(CONTENT_CONTAINER)));
+    mUpperLabelShort = qobject_cast<HbLabel*>(
+        layoutLoader.findWidget(QString(UPPER_LABEL_SHORT)));
+    mUpperLabelLong = qobject_cast<HbLabel*>(
+        layoutLoader.findWidget(QString(UPPER_LABEL_LONG)));
+    mMiddleLabel = qobject_cast<HbLabel*>(
+        layoutLoader.findWidget(QString(MIDDLE_LABEL)));
+    mLowerLabel = qobject_cast<HbLabel*>(
+        layoutLoader.findWidget(QString(LOWER_LABEL)));
+    mReminderLabel = qobject_cast<HbLabel*>(
+        layoutLoader.findWidget(QString(REMINDER_ICON_LABEL)));
+
+    // Create reminder icon drawer only if reminder label loading succeeded.
+    if (mReminderLabel) {
+        // Make sure there's no text in reminder icon label
+        mReminderLabel->clear();
+        // Create drawer for reminder icon
+        mReminderDrawer = new HbFrameDrawer(REMINDER_IMAGE_NAME,
+            REMINDER_FRAME_TYPE);
+        //ownership transferred
+        HbFrameItem* reminderFrameItem = new HbFrameItem(mReminderDrawer);
+        //ownership transferred
+        mReminderLabel->setBackgroundItem(reminderFrameItem);
+    }
+
+    setLabelsColor();
+    hideLabels();
+    createAgendaUtilsInstance();
+    initializeTimer();
+}
+
+/*
+ * ContentLayoutHandler::calendarChanged()
+ */
+void ContentLayoutHandler::calendarChanged(const XQSettingsKey& key,
+    const QVariant& value)
+{
+    LOGS("ContentLayoutHandler::calendarChanged");
+    Q_UNUSED(key);
+    Q_UNUSED(value);
+    updateLayout();
+}
+
+/*
+ * ContentLayoutHandler::updateLayout()
+ */
+void ContentLayoutHandler::updateLayout()
+{
+    LOGS("ContentLayoutHandler::updateLayout");
+    decorateContent();
+    setTimerForNextUpdate();
+    //From DateIconLayoutHandler
+    setCalendarIconContent();
+}
+
+/*
+ * ContentLayoutHandler::onThemeChange()
+ */
+void ContentLayoutHandler::onThemeChange()
+{
+    LOGS("ContentLayoutHandler::onThemeChange");
+    if (mReminderDrawer) {
+        mReminderDrawer->themeChanged();
+    }
+    
+    if (mDateIconFrameDrawer) {
+        mDateIconFrameDrawer->themeChanged();
+    }
+    
+    if (mBackgroundLayoutItem) {
+        mBackgroundLayoutItem->frameDrawer().themeChanged();
+    }
+    if (mSeparatorLayoutItem) {
+        mSeparatorLayoutItem->frameDrawer().themeChanged();
+    }
+    
+    setLabelsColor();
+}
+
+/*
+ * ContentLayoutHandler::createAgendaUtilsInstance()
+ */
+void ContentLayoutHandler::createAgendaUtilsInstance()
+{
+    LOGS("ContentLayoutHandler::createAgendaUtilsInstance");
+    mAgendaUtil = new AgendaUtil(this);
+    connect(mAgendaUtil, SIGNAL(entryViewCreationCompleted(int)),
+        this, SLOT(updateLayout()));
+}
+
+/*
+ * ContentLayoutHandler::initializeTimer()
+ */
+void ContentLayoutHandler::initializeTimer()
+{
+    LOGS("ContentLayoutHandler::initializeTimer");
+    mEventTimer = new QTimer();
+    mEventTimer->setSingleShot(true);
+    connect(mEventTimer, SIGNAL(timeout()), this, SLOT(eventTimerExpired()));
+    setTimerForNextUpdate();
+}
+
+/*
+ * ContentLayoutHandler::hideLabels()
+ */
+void ContentLayoutHandler::hideLabels()
+{
+    LOGS("ContentLayoutHandler::hideLabels");
+    setLabelVisible(mMiddleLabel, false);
+    setLabelVisible(mUpperLabelShort, false);
+    setLabelVisible(mUpperLabelLong, false);
+    setLabelVisible(mLowerLabel, false);
+    setLabelVisible(mReminderLabel, false);
+}
+
+/*
+ * ContentLayoutHandler::setLabelsColor()
+ */
+void ContentLayoutHandler::setLabelsColor()
+{
+    LOGS("ContentLayoutHandler::setLabelsColor");
+    
+    // --- Content layout ---
+    
+    // Choose text colors according to highlight state
+    QString upperLabelColorAttribute;
+    QString lowerLabelColorAttribute;
+    if (mContentHighlightActive) {
+        upperLabelColorAttribute = HIGHLIGHT_LABEL_COLOR;
+        lowerLabelColorAttribute = HIGHLIGHT_LABEL_COLOR;
+    }
+    else {
+        upperLabelColorAttribute = UPPER_LABEL_COLOR;
+        lowerLabelColorAttribute = LOWER_LABEL_COLOR;
+    }
+    QColor upperLabelTextColor(HbColorScheme::color(upperLabelColorAttribute));
+    QColor lowerLabelTextColor(HbColorScheme::color(lowerLabelColorAttribute));
+    
+    // Set upper and middle label text color
+    if (upperLabelTextColor.isValid()) {
+        if (mUpperLabelShort) {
+            mUpperLabelShort->setTextColor(upperLabelTextColor);
+        }
+        if (mUpperLabelLong) {
+            mUpperLabelLong->setTextColor(upperLabelTextColor);
+        }
+        if (mMiddleLabel) {
+            mMiddleLabel->setTextColor(upperLabelTextColor);
+        }
+    }
+
+    // Set lower label text color
+    if (lowerLabelTextColor.isValid()) {
+        if (mLowerLabel) {
+            mLowerLabel->setTextColor(lowerLabelTextColor);
+        }
+    }
+    
+    // --- DateIconLayoutHandler ---
+    QString numberLabelColorAttribute;
+    QString monthLabelColorAttribute;
+    if (mDateHighlightActive) {
+        numberLabelColorAttribute = NUMBER_LABEL_COLOR;
+        monthLabelColorAttribute = HIGHLIGHT_LABEL_COLOR;
+    }
+    else {
+        numberLabelColorAttribute = NUMBER_LABEL_COLOR;
+        monthLabelColorAttribute = MONTH_LABEL_COLOR;
+    }
+    QColor numberLabelTextColor(HbColorScheme::color(numberLabelColorAttribute));
+    QColor monthLabelTextColor(HbColorScheme::color(monthLabelColorAttribute));
+    
+    // Set day number label text color
+    if (numberLabelTextColor.isValid()) {
+        if (mNumberLabel) {
+            mNumberLabel->setTextColor(numberLabelTextColor);
+        }
+    }
+    // Set month label text color
+    if (monthLabelTextColor.isValid()) {
+        if (mMonthLabel) {
+            mMonthLabel->setTextColor(monthLabelTextColor);
+        }
+    }
+}
+
+/*
+ * ContentLayoutHandler::eventTimerExpired
+ */
+void ContentLayoutHandler::eventTimerExpired()
+{
+    LOGS("ContentLayoutHandler::eventTimerExpired");
+    decorateContent();
+    setTimerForNextUpdate();
+}
+
+/*
+ * ContentLayoutHandler::timeToNextCheck()
+ */
+int ContentLayoutHandler::timeToNextCheck()
+{
+    LOGS("ContentLayoutHandler::timeToNextCheck");
+    QDateTime now = currentDateTime();
+    int secondsToNextCheck = 0;
+    int currentSeconds = 0;
+    currentSeconds = now.toTime_t();
+    int entryStartTimeSeconds = 0;
+    int entryEndTimeSeconds = 0;
+    int indexEntryToCheck = firstEntryIndex();
+
+    QDateTime startTime = mAgendaEntryList.at(indexEntryToCheck).startTime();
+    QDateTime endTime = mAgendaEntryList.at(indexEntryToCheck).endTime();
+    entryStartTimeSeconds = startTime.toTime_t();
+    entryEndTimeSeconds = endTime.toTime_t();
+
+    //check if the event is bigger than half hour
+    if ((entryEndTimeSeconds - entryStartTimeSeconds) < (KHalfHour * KSecondsInMinute)) {
+        secondsToNextCheck = entryEndTimeSeconds - currentSeconds;
+    }
+    else {
+        //check that it's not an all time event.
+        //if it's an all day event there's no need to set the timer because there is already a date check and the widget content
+        //will be updated anyway.
+        if (!isAllDayEvent(mAgendaEntryList.at(indexEntryToCheck))) {
+            secondsToNextCheck = entryStartTimeSeconds + KHalfHour * KSecondsInMinute
+                - currentSeconds;
+        }
+    }
+
+    int mSecsToNextCheck = 0;
+    if (secondsToNextCheck > INT_MAX / KSecondInMillisec) {
+        mSecsToNextCheck = INT_MAX;
+    }
+    else {
+        //seconds to milliseconds
+        mSecsToNextCheck = secondsToNextCheck * KSecondInMillisec;
+    }
+
+    return mSecsToNextCheck;
+}
+
+/*
+ * ContentLayoutHandler::firstEntryIndex()
+ */
+int ContentLayoutHandler::firstEntryIndex()
+{
+    int indexEntryToCheck = 0;
+    LOGS("ContentLayoutHandler::firstEntryIndex()");
+
+    //let's find the first non all day event in the list
+    while (isAllDayEvent(mAgendaEntryList.at(indexEntryToCheck))
+        && (indexEntryToCheck < mAgendaEntryList.count() - 1)) {
+        indexEntryToCheck++;
+    }
+
+    //if we found the first valid non all day event as last in the array then we have to keep that index
+    if ((indexEntryToCheck == mAgendaEntryList.count() - 1)
+        && isAllDayEvent(mAgendaEntryList.at(indexEntryToCheck))) {
+        indexEntryToCheck = 0;
+    }
+
+    return indexEntryToCheck;
+}
+
+/*
+ * ContentLayoutHandler::decorateContent()
+ */
+void ContentLayoutHandler::decorateContent()
+{
+    LOGS("ContentLayoutHandler::decorateContent");
+    updateList();
+
+    if (mAgendaEntryList.count()) {
+        removeTodosFrom();
+        //it removes the events that are shorter than 30 minutes and are already passed
+        removePassedEvents();
+    }
+
+    //there might be only ToDos. Let's check again.
+    if (mAgendaEntryList.count()) {
+        int endEventIndex = 0;
+        if (todayHasValidEvents()) {
+            int numOverlappingEvents = checkOverlappingEvents(0, endEventIndex);
+            if (!numOverlappingEvents) {
+                showNextEvent();
+            }
+            else {
+                showOverlappingEvents(KToday, numOverlappingEvents, endEventIndex);
+            }
+        }
+        else {
+            int numOverlappingEvents = checkOverlappingEvents(0, endEventIndex);
+            if (!numOverlappingEvents) {
+                showNextDaysEvent();
+            }
+            else {
+                showOverlappingEvents(KComingDays, numOverlappingEvents, endEventIndex);
+            }
+        }
+    }
+    else {
+        showNoEventsNextWeek();
+    }
+    
+    QDateTime date;
+    if (mAgendaEntryList.count()) {
+        date = mAgendaEntryList.at(0).startTime();
+    }
+    else {
+        date = QDateTime::currentDateTime();
+    }
+    
+    emit currentDate(date);
+}
+
+/*
+ * ContentLayoutHandler::updateList()
+ */
+void ContentLayoutHandler::updateList()
+{
+    LOGS("ContentLayoutHandler::updateList");
+    
+    // Calculate start of event fetching range
+    QDateTime previousMidnight(currentDateTime().date(), QTime(0, 0));
+    QDateTime passedEventStart(currentDateTime().addSecs(-KPassedEventTimeoutSecs));
+    QDateTime rangeStart;
+    if (previousMidnight < passedEventStart) {
+        rangeStart = previousMidnight;
+    }
+    else {
+        rangeStart = passedEventStart;
+    }
+
+    // Calculate end of event fetching range
+    QDateTime rangeEnd(previousMidnight.addDays(KDaysInWeek+1));
+    
+    // Fetch events
+    mAgendaEntryList = mAgendaUtil->fetchEntriesInRange(rangeStart, rangeEnd);
+    
+    QString agenda_count = "count: "
+        + QString::number(mAgendaEntryList.count(), 10);
+    LOGS(agenda_count);
+    sortList();
+}
+
+/*
+ * ContentLayoutHandler::removePassedEvents()
+ */
+void ContentLayoutHandler::removePassedEvents()
+{
+    LOGS("ContentLayoutHandler::removePassedEvents");
+    for (int i = 0; i < mAgendaEntryList.count(); i++) {
+        //add half hour
+        QDateTime entryStartTime =
+            mAgendaEntryList.at(i).startTime().addSecs(KHalfHour * KSecondsInMinute);
+        LOGS(entryStartTime.toString());
+        LOGS(currentDateTime());
+        //if the entry start time plus half hour is less than current time or it is not but the entry duration is less than half hour (endtime < currenttime)
+        //and the entry is not an all day event then remove it because it is passed.
+        if (((entryStartTime < currentDateTime())
+            || (mAgendaEntryList.at(i).endTime() < currentDateTime()))
+            && !isAllDayEvent(mAgendaEntryList.at(i))) {
+            mAgendaEntryList.removeAt(i);
+            i--;
+        }
+    }
+}
+
+/*
+ * ContentLayoutHandler::currentDateFormat()
+ */
+QString ContentLayoutHandler::currentDateFormat()
+{
+    LOGS("ContentLayoutHandler::currentDateFormat");
+    QString format;
+    HbExtendedLocale locale;
+    switch (locale.dateStyle()) {
+        case HbExtendedLocale::American:
+        case HbExtendedLocale::Japanese:
+            format = QString("MMM dd");
+            break;
+        case HbExtendedLocale::European:
+            format = QString("dd MMM");
+            break;
+        default:
+            format = QString("dd:MM");
+            break;
+    }        
+    return format;
+}
+
+/*
+ * ContentLayoutHandler::currentTimeFormat()
+ */
+QString ContentLayoutHandler::currentTimeFormat()
+{
+    LOGS("ContentLayoutHandler::currentTimeFormat");
+    QString format;
+    HbExtendedLocale locale;
+    QChar separator = locale.timeSeparator(KHourMinuteSeparatorIndex);
+    format = QString("hh") + separator + QString("mm");
+    if (locale.timeStyle() == HbExtendedLocale::Time12) {
+        if (locale.amPmSymbolPosition() == HbExtendedLocale::Before) {
+            if (locale.amPmSpace()) {
+                format.prepend(' ');
+            }
+            format.prepend("ap");
+        }
+        else {
+            if (locale.amPmSpace()) {
+                format.append(' ');
+            }
+            format.append("ap");
+        }    
+    }
+    return format;
+}
+
+/*
+ * ContentLayoutHandler::showNextDaysEvent()
+ */
+void ContentLayoutHandler::showNextDaysEvent()
+{
+    LOGS("ContentLayoutHandler::showNextDaysEvent");
+    setLabelVisible(mMiddleLabel, false);
+    setLabelVisible(mUpperLabelShort, true);
+    setLabelVisible(mLowerLabel, true);
+    QString day = mAgendaEntryList.at(0).startTime().date().toString(currentDateFormat());
+    QString startTime = mAgendaEntryList.at(0).startTime().time().toString(currentTimeFormat());
+    QString endTime = mAgendaEntryList.at(0).endTime().time().toString(currentTimeFormat());
+    QString description = mAgendaEntryList.at(0).summary();
+    if (!isAllDayEvent(mAgendaEntryList.at(0))) {
+        //if not all day event show the start time
+        if (mAgendaEntryList.at(0).startTime().date() == mAgendaEntryList.at(0).endTime().date()) {
+            setLabelText(mUpperLabelShort, day + " " + startTime + " " + description);
+            setLabelText(mLowerLabel, hbTrId("txt_calendar_widget_v_dblist_val_no_events_tod"));
+        }
+        else {
+            //if the end date is different from the starting date show that information
+            setLabelText(mUpperLabelShort, day + " " + startTime + "-"
+                + mAgendaEntryList.at(0).endTime().date().toString(currentDateFormat()) + " "
+                + description);
+            setLabelText(mLowerLabel, hbTrId("txt_calendar_widget_v_dblist_val_no_events_tod"));
+        }
+    }
+    else {
+        // It's an all day event
+        if (isOneDayAllDayEvent(mAgendaEntryList.at(0))) {
+            // It's a one day all day event
+            setLabelText(mUpperLabelShort, day + " " + description);
+            setLabelText(mLowerLabel, hbTrId("txt_calendar_widget_v_dblist_val_no_events_tod"));
+        }
+        else {
+            // It's a multiple day all day event
+            setLabelText(mUpperLabelShort, day + " - "
+                + mAgendaEntryList.at(0).endTime().date().addDays(-1).toString(currentDateFormat()) + " "
+                + description);
+            setLabelText(mLowerLabel, hbTrId("txt_calendar_widget_v_dblist_val_no_events_tod"));
+        }
+    }
+
+    int timeoffset = mAgendaEntryList.at(0).alarm().timeOffset();
+    if (mAgendaEntryList.at(0).alarm().timeOffset()
+        && mAgendaEntryList.at(0).alarm().timeOffset() != -1) {
+        setLabelVisible(mReminderLabel, true);
+    }
+    else {
+        setLabelVisible(mReminderLabel, false);
+    }
+}
+
+/*
+ * ContentLayoutHandler::showOverlappingEvents()
+ */
+void ContentLayoutHandler::showOverlappingEvents(int when, int numOverlappingEvents,
+    int aEndEventIndex)
+{
+    LOGS("ContentLayoutHandler::showOverlappingEvents");
+    if (when == KToday) {
+        setLabelVisible(mMiddleLabel, false);
+        setLabelVisible(mUpperLabelShort, true);
+        setLabelVisible(mLowerLabel, true);
+        QString startTime = mAgendaEntryList.at(0).startTime().time().toString(currentTimeFormat());
+        QString endTime = calculateEndTime(aEndEventIndex);
+        QString day = mAgendaEntryList.at(0).startTime().date().toString(currentDateFormat());
+        if (!isAllDayEvent(mAgendaEntryList.at(0))) {
+            if (mAgendaEntryList.at(0).startTime().date()
+                == mAgendaEntryList.at(aEndEventIndex).endTime().date()) {
+                //if not all day event show the start time and end time
+                setLabelText(mUpperLabelShort, startTime + "-" + endTime);
+                setLowerLabelOverlapping(numOverlappingEvents);
+            }
+            else {
+                setLabelText(mUpperLabelShort, startTime + "-"
+                    + mAgendaEntryList.at(aEndEventIndex).endTime().date().toString(
+                        currentDateFormat()) + " "
+                    + mAgendaEntryList.at(aEndEventIndex).endTime().time().toString(
+                        currentTimeFormat()));
+                setLowerLabelOverlapping(numOverlappingEvents);
+            }
+        }
+        else {
+            // It's an all day event
+            if (isOneDayAllDayEvent(mAgendaEntryList.at(0))) {
+                // It's a one day all day event
+                setLabelText(mUpperLabelShort, day);
+                setLowerLabelOverlapping(numOverlappingEvents);
+            }
+            else {
+                // It's a multiple day all day event
+                setLabelText(mUpperLabelShort, day + " - "
+                    + mAgendaEntryList.at(0).endTime().date().addDays(-1).toString(currentDateFormat()));
+                setLowerLabelOverlapping(numOverlappingEvents);
+            }
+        }
+    }
+    else {
+        setLabelVisible(mMiddleLabel, false);
+        setLabelVisible(mUpperLabelShort, true);
+        setLabelVisible(mLowerLabel, true);
+        QString day = mAgendaEntryList.at(0).startTime().date().toString(currentDateFormat());
+        QString startTime = mAgendaEntryList.at(0).startTime().time().toString(currentTimeFormat());
+        QString endTime = calculateEndTime(aEndEventIndex);
+        if (!isAllDayEvent(mAgendaEntryList.at(0))) {
+            if (mAgendaEntryList.at(0).startTime().date()
+                == mAgendaEntryList.at(aEndEventIndex).endTime().date()) {
+                //if not all day event show the start time and end time
+                setLabelText(mUpperLabelShort, day + " " + startTime + "-" + endTime);
+                setLowerLabelOverlapping(numOverlappingEvents);
+            }
+            else {
+                setLabelText(mUpperLabelShort, day + " " + startTime + "-"
+                    + mAgendaEntryList.at(0).endTime().date().toString(currentDateFormat()));
+                setLowerLabelOverlapping(numOverlappingEvents);
+            }
+        }
+        else {
+            // It's an all day event
+            if (isOneDayAllDayEvent(mAgendaEntryList.at(0))) {
+                // It's a one day all day event
+                setLabelText(mUpperLabelShort, day);
+                setLowerLabelOverlapping(numOverlappingEvents);
+            }
+            else {
+                // It's a multiple day all day event
+                setLabelText(mUpperLabelShort, day + " - "
+                    + mAgendaEntryList.at(0).endTime().date().addDays(-1).toString(currentDateFormat()));
+                setLowerLabelOverlapping(numOverlappingEvents);
+            }
+        }
+    }
+
+    // Never show reminder icon for overlapping events
+    setLabelVisible(mReminderLabel, false);
+}
+
+/*
+ * ContentLayoutHandler::calculateEndTime()
+ */
+QString ContentLayoutHandler::calculateEndTime(int& aEndEventIndex)
+{
+    LOGS("ContentLayoutHandler::calculateEndTime");
+    QDateTime current = mAgendaEntryList.at(0).endTime();
+    int endTimeIndex = 0;
+    for (int i = 0; i < aEndEventIndex + 1; i++) {
+        if (mAgendaEntryList.at(i).endTime() > current) {
+            current = mAgendaEntryList.at(i).endTime();
+            endTimeIndex = i;
+        }
+    }
+
+    aEndEventIndex = endTimeIndex;
+    return current.time().toString(currentTimeFormat());
+}
+
+/*
+ * ContentLayoutHandler::showNextEvent()
+ */
+void ContentLayoutHandler::showNextEvent()
+{
+    LOGS("ContentLayoutHandler::showNextEvent");
+    setLabelVisible(mMiddleLabel, false);
+    setLabelVisible(mUpperLabelShort, true);
+    setLabelVisible(mLowerLabel, true);
+    QString startTime = mAgendaEntryList.at(0).startTime().time().toString(currentTimeFormat());
+    QString endTime = mAgendaEntryList.at(0).endTime().time().toString(currentTimeFormat());
+    QString description = mAgendaEntryList.at(0).summary();
+    if (!isAllDayEvent(mAgendaEntryList.at(0))) {
+        //if not all day event show the start time and end time
+        if (mAgendaEntryList.at(0).startTime().date() == mAgendaEntryList.at(0).endTime().date()) {
+            setLabelText(mUpperLabelShort, startTime + "-" + endTime);
+            setLabelText(mLowerLabel, description);
+        }
+        else {
+            //if the end date is different from the starting date show that information
+            setLabelText(mUpperLabelShort, startTime + "-"
+                + mAgendaEntryList.at(0).endTime().date().toString(currentDateFormat()) + " "
+                + endTime);
+            setLabelText(mLowerLabel, description);
+        }
+    }
+    else {
+        // It's an all day event
+        if (isOneDayAllDayEvent(mAgendaEntryList.at(0))) {
+            // It's a one day all day event
+            setLabelText(mUpperLabelShort,
+                mAgendaEntryList.at(0).startTime().date().toString(currentDateFormat()));
+            setLabelText(mLowerLabel, description);
+        }
+        else {
+            // It's a multiple day all day event
+            setLabelText(mUpperLabelShort,
+                mAgendaEntryList.at(0).startTime().date().toString(currentDateFormat())
+                + " - " + mAgendaEntryList.at(0).endTime().date().addDays(-1).toString(
+                currentDateFormat()));
+            setLabelText(mLowerLabel, description);
+        }
+    }
+
+    //check if reminder is set
+    if (mAgendaEntryList.at(0).alarm().timeOffset()
+        && mAgendaEntryList.at(0).alarm().timeOffset() != -1) {
+        setLabelVisible(mReminderLabel, true);
+    }
+    else {
+        setLabelVisible(mReminderLabel, false);
+    }
+}
+
+/*
+ * ContentLayoutHandler::showNoEventsNextWeek()
+ */
+void ContentLayoutHandler::showNoEventsNextWeek()
+{
+    LOGS("ContentLayoutHandler::showNoEventsNextWeek");
+    setLabelText(mMiddleLabel, hbTrId("txt_calendar_widget_v_dblist_val_no_events_ox"));
+    setLabelVisible(mMiddleLabel, true);
+    setLabelVisible(mUpperLabelShort, false);
+    setLabelVisible(mLowerLabel, false);
+    setLabelVisible(mReminderLabel, false);
+}
+
+/*
+ * ContentLayoutHandler::checkOverlappingEvents()
+ */
+int ContentLayoutHandler::checkOverlappingEvents(ulong id, int& aEndEventIndex)
+{
+    LOGS("ContentLayoutHandler::checkOverlappingEvents");
+    int overlappingEvents = 0;
+    AgendaEntry entry = mAgendaEntryList.at(id);
+    for (int i = id + 1; i < mAgendaEntryList.count(); i++) {
+        if ((entry.startTime() <= mAgendaEntryList.at(i).startTime())
+            && (entry.endTime() >= mAgendaEntryList.at(i).startTime())
+            && entry.startTime().date() == mAgendaEntryList.at(i).startTime().date()) {
+            aEndEventIndex = i;
+            overlappingEvents++;
+        }
+    }
+    if (overlappingEvents) {
+        //if there are overlapping events we have to count one more
+        //because the minumum is two.
+        overlappingEvents++;
+    }
+
+    return overlappingEvents;
+}
+
+/*
+ * ContentLayoutHandler::sortList()
+ */
+void ContentLayoutHandler::sortList()
+{
+    LOGS("ContentLayoutHandler::sortList");
+    for (int i = 0; i < mAgendaEntryList.count() - 1; i++) {
+        for (int j = i + 1; j < mAgendaEntryList.count(); j++) {
+            if (mAgendaEntryList.at(i).startTime() > mAgendaEntryList.at(j).startTime()) {
+                //TODO: Maintain an array of integer ?
+                mAgendaEntryList.swap(i, j);
+            }
+        }
+    }
+}
+
+/*
+ * ContentLayoutHandler::todayHasValidEvents()
+ */
+bool ContentLayoutHandler::todayHasValidEvents()
+{
+    LOGS("ContentLayoutHandler::todayHasValidEvents");
+    QDateTime currentTime = currentDateTime();
+    bool hasValidEvents = false;
+    for (int i = 0; i < mAgendaEntryList.count(); i++) {
+        if ((mAgendaEntryList.at(i).endTime() >= currentTime)
+            && (mAgendaEntryList.at(i).startTime().date() == currentTime.date())) {
+            hasValidEvents = true;
+        }
+    }
+
+    return hasValidEvents;
+}
+
+/*
+ * ContentLayoutHandler::removeTodosFrom()
+ */
+void ContentLayoutHandler::removeTodosFrom()
+{
+    LOGS("ContentLayoutHandler::removeTodosFrom");
+    for (int i = 0; i < mAgendaEntryList.count();) {
+        if ((mAgendaEntryList.at(i).type() == AgendaEntry::TypeTodo)
+            || (mAgendaEntryList.at(i).type() == AgendaEntry::TypeNote)
+            || (mAgendaEntryList.at(i).type() == AgendaEntry::TypeUnknown)) {
+            mAgendaEntryList.removeAt(i);
+        }
+        else {
+            //nothing has been removed. Increment the counter.
+            i++;
+        }
+    }
+}
+
+void ContentLayoutHandler::handleOk(const QVariant& var)
+{
+    Q_UNUSED(var);
+
+    LOGS("ContentLayoutHandler::handleOk");
+    mTestResult = 0;
+    emit requestComplete();
+}
+
+void ContentLayoutHandler::handleError(int err, const QString& str)
+{
+    Q_UNUSED(str);
+
+    LOGS("ContentLayoutHandler::handleError");
+    mTestResult = err;
+    emit requestError();
+}
+
+void ContentLayoutHandler::highlightOn(QPointF &point)
+{
+    // --- Content layout ---
+    
+    if (mContainer) {
+        if (mContainer->sceneBoundingRect().contains(point)) {
+            LOGS("[[[Highlight signal in Content area]]]");
+            if (!mContentHighlightActive) {
+                HbFrameDrawer* highlightDrawer = new HbFrameDrawer(HIGHLIGHT_IMAGE_NAME,
+                    HbFrameDrawer::NinePieces);
+                HbFrameItem* highlightItem = new HbFrameItem(highlightDrawer);
+                mContainer->setBackgroundItem(highlightItem);
+                mContentHighlightActive = true; // must be done before setLabelsColor
+                setLabelsColor();
+                mContainer->update();
+            }
+        }
+    }
+    
+    // --- Date layout ---
+    
+    // TODO Don't highlight if already highlighted
+   
+    if (mIconContainer) {
+        if (mIconContainer->sceneBoundingRect().contains(point)) {
+            LOGS("[[[Highlight signal in dateicon area]]]");
+            if (!mDateHighlightActive) {
+                HbFrameDrawer* highlightDrawer = new HbFrameDrawer(HIGHLIGHT_IMAGE_NAME,
+                    HbFrameDrawer::NinePieces);
+                HbFrameItem* highlightItem = new HbFrameItem(highlightDrawer);
+                if (mHighlightLabel) {
+                    mHighlightLabel->setBackgroundItem(highlightItem);
+                }
+                mDateHighlightActive = true; // must be done before setLabelsColor
+                setLabelsColor();
+                if (mHighlightLabel) {
+                    mHighlightLabel->update();
+                }
+            }
+        }
+    }
+}
+
+void ContentLayoutHandler::highlightOff()
+{
+    // --- Content layout ---
+    
+    if (mContentHighlightActive) {
+        QGraphicsItem* background1 = mContainer->backgroundItem();
+        if (background1) {
+            background1->hide();
+        }
+        mContentHighlightActive = false; // must be done before setLabelsColor
+        setLabelsColor();
+        mContainer->update();
+    }
+    
+    // --- Date layout ---
+    
+    if (mDateIconFrameDrawer) {
+        QGraphicsItem* background2 = mHighlightLabel->backgroundItem();
+        if (background2) {
+            background2->hide();
+        }
+        mDateHighlightActive = false; // must be done before setLabelsColor
+        setLabelsColor();
+        mHighlightLabel->update();
+    }
+}
+
+//TEST FUNCTIONS
+
+/*
+ * ContentLayoutHandler::testId()
+ */
+int ContentLayoutHandler::testId()
+{
+    return mTestID;
+}
+
+/*
+ * ContentLayoutHandler::setTestId()
+ */
+void ContentLayoutHandler::setTestId(int testID)
+{
+    mTestID = testID;
+}
+
+/*
+ * ContentLayoutHandler::testResult()
+ */
+int ContentLayoutHandler::testResult()
+{
+    return mTestResult;
+}
+
+/*
+ * ContentLayoutHandler::setTestResult
+ */
+void ContentLayoutHandler::setTestResult(int testResult)
+{
+    mTestResult = testResult;
+}
+
+/*
+ * ContentLayoutHandler::setTimerForNextUpdate()
+ */
+void ContentLayoutHandler::setTimerForNextUpdate()
+{
+    if (mAgendaEntryList.count()) {
+        int msecsToNextEvent = timeToNextCheck();
+        if (msecsToNextEvent > 0) {
+            mEventTimer->start(msecsToNextEvent);
+        }
+    }
+}
+
+QDateTime ContentLayoutHandler::currentDateTime()
+{
+#ifdef TEST
+    return QDateTime(QDate(2010, 1, 1), QTime(9, 0, 0));
+#else
+    return QDateTime::currentDateTime();
+#endif
+}
+
+void ContentLayoutHandler::setLabelText(HbLabel* label, QString text)
+{
+    if (label) {
+        label->setPlainText(text);
+
+        if (label == mUpperLabelShort) {
+            if (mUpperLabelLong) {
+                mUpperLabelLong->setPlainText(text);
+            }
+        }
+    }
+}
+
+void ContentLayoutHandler::setLabelVisible(HbLabel* label, bool visible)
+{
+    // State transition table
+    //  R = reminder label, L = long upper label, S = short upper label
+    //  rows = current state (label visibility), columns = action
+    //          [hide R]  [show R]  [hide S]  [show S]
+    // 0 (slr)   0 (slr)   1 (slR)   0 (slr)   2 (sLr)
+    // 1 (slR)   0 (slr)   1 (slR)   1 (slR)   5 (SlR)
+    // 2 (sLr)   2 (sLr)   5 (SlR)   0 (slr)   2 (sLr)
+    // 3 (sLR)   2 (sLr)   5 (SlR)   1 (slR)   5 (SlR)
+    // 4 (Slr)   2 (sLr)   5 (SlR)   0 (slr)   2 (sLr)
+    // 5 (SlR)   2 (sLr)   5 (SlR)   1 (slR)   5 (SlR)
+    // 6 (SLr)   2 (sLr)   5 (SlR)   0 (slr)   2 (sLr)
+    // 7 (SLR)   2 (sLr)   5 (SlR)   1 (slR)   5 (SlR)
+    const int stateTransition[] =
+        {0,1,0,2,
+         0,1,1,5,
+         2,5,0,2,
+         2,5,1,5,
+         2,5,0,2, 
+         2,5,1,5,
+         2,5,0,2,
+         2,5,1,5};
+    
+    // Logic for showing correct upper label
+    if (label == mUpperLabelShort || label == mReminderLabel) {
+        // Make sure all three labels exists
+        if (mUpperLabelShort && mUpperLabelLong && mReminderLabel) {
+            int currentState = 0;
+            currentState += (mReminderLabel->isVisible() ? 1 : 0);
+            currentState += (mUpperLabelLong->isVisible()  ? 2 : 0);
+            currentState += (mUpperLabelShort->isVisible() ? 4 : 0);
+
+            int action = -1;
+            if (label == mReminderLabel) {
+                if (visible) {
+                    action = 1;
+                }
+                else {
+                    action = 0;
+                }
+            }
+            else if (label == mUpperLabelShort) {
+                if (visible) {
+                    action = 3;
+                }
+                else {
+                    action = 2;
+                }
+            }
+            
+            int newState = stateTransition[currentState * 4 + action];
+            
+            if (newState != currentState) {
+                mReminderLabel->setVisible(newState & 1);
+                mUpperLabelLong->setVisible(newState & 2);
+                mUpperLabelShort->setVisible(newState & 4);
+            }
+        }
+    }
+    else { // Other labels
+        if (label) {
+            label->setVisible(visible);
+        }
+    }
+}
+
+bool ContentLayoutHandler::isAllDayEvent(AgendaEntry entry)
+{
+    if (entry.startTime().time() == QTime(0, 0)
+        && entry.endTime().time() == QTime(0, 0)
+        && entry.startTime().date() < entry.endTime().date()) {
+        return true;
+    }
+    else {
+        return false;
+    }
+}
+
+bool ContentLayoutHandler::isOneDayAllDayEvent(AgendaEntry entry)
+{
+    if (isAllDayEvent(entry)
+        && entry.startTime().date().addDays(1) == entry.endTime().date()) {
+        return true;
+    }
+    else {
+        return false;
+    }
+}
+
+void ContentLayoutHandler::setLowerLabelOverlapping(int numberOfEvents)
+{
+    QString trString(hbTrId("txt_calendar_widget_v_dblist_val_l1_events"));
+    // TODO: Remove the replacing of the parameter, once localized
+    //       string is corrected.
+    setLabelText(mLowerLabel, trString.replace("%Ln", "%L1").arg(numberOfEvents));
+}
+
+//from DateIconLayoutHandler
+/*
+ * ContentLayoutHandler::setCalendarIconContent()
+ */
+void ContentLayoutHandler::setCalendarIconContent()
+{
+    LOGS("ContentLayoutHandler::setCalendarIconContent");
+    if (mNumberLabel) {
+        mNumberLabel->setPlainText(QString::number(QDateTime::currentDateTime().date().day(), 10));
+    }
+    if (mMonthLabel) {
+        mMonthLabel->setPlainText(QLocale::system().monthName(
+            QDateTime::currentDateTime().date().month()));
+    }
+}
+
+//End of file