--- /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