--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/calendarui/views/src/calenagendaviewwidget.cpp Thu Jul 22 16:32:51 2010 +0100
@@ -0,0 +1,1142 @@
+/*
+* 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: CalenAgendaViewWidget implementation
+*
+*/
+
+// System includes
+#include <QStandardItemModel>
+#include <QGraphicsSceneEvent>
+#include <QDir>
+#include <QPluginLoader>
+#include <hbi18ndef.h>
+#include <hbextendedlocale.h>
+#include <hbgroupbox.h>
+#include <hbmenu.h>
+#include <hbaction.h>
+#include <hbmainwindow.h>
+#include <hbstyleloader.h>
+#include <hbdatetimepicker.h>
+#include <hbdialog.h>
+#include <xqsettingsmanager.h>
+#include <agendautil.h>
+#include <NotesEditorInterface>
+
+// User includes
+#include "calenagendaviewwidget.h"
+#include "calencommon.h"
+#include "calenagendaview.h"
+#include "calendocloader.h"
+#include "calenservices.h"
+#include "calencontext.h"
+#include "calendateutils.h"
+#include "CalenUid.h"
+#include "caleneventlistviewitem.h"
+#include "calenpluginlabel.h"
+#include "calendarprivatecrkeys.h"
+
+// Constants
+const QString singleSpace(" ");
+const QString doubleSpace(" ");
+const QString space(" ");
+const QString singleHyphen("-");
+const QString customLayout("custom");
+const char *stretchLayout("stretchItem");
+const QString toDoIcon("qtg_small_todo");
+const QString reminderIcon("qtg_mono_alarm");
+const QString locationIcon("qtg_mono_location");
+const QString repeatIcon("qtg_mono_repeat");
+// TODO: Replace with actual image name once its available
+//const QString allDayIcon("qtg_small_allday");
+const QString allDayIcon(":/qgn_indi_cdr_meeting_layer0.svg");
+const QString exceptionIcon("qtg_mono_repeat_exception");
+const int singleColumn(1);
+
+// ----------------------------------------------------------------------------
+// CalenAgendaViewWidget::CalenAgendaViewWidget
+// Rest of the details are commented in the header
+// ----------------------------------------------------------------------------
+//
+EXPORT_C CalenAgendaViewWidget::CalenAgendaViewWidget(MCalenServices &services,
+ CalenDocLoader *docLoader) :
+mServices(services),
+mDocLoader(docLoader),
+mRegionalInfoGroupBox(NULL),
+mLongTapEventFlag(false),
+mNotesPluginLoaded(false)
+{
+ // Construct the list view prototype
+ mListViewPrototype = new CalenEventListViewItem(this);
+
+ // Create the list model
+ mListModel = new QStandardItemModel(this);
+
+ // Register the custom docml and css to provide our own style to the list items
+ HbStyleLoader::registerFilePath(":/");
+
+ //Create the setting manager
+ mSettingsManager = new XQSettingsManager(this);
+}
+
+// ----------------------------------------------------------------------------
+// CalenAgendaViewWidget::~CalenAgendaViewWidget
+// Rest of the details are commented in the header
+// ----------------------------------------------------------------------------
+//
+EXPORT_C CalenAgendaViewWidget::~CalenAgendaViewWidget()
+{
+ // Unload notes editor if loaded.
+ if (mNotesEditorPluginLoader) {
+ mNotesEditorPluginLoader->unload();
+ delete mNotesEditorPluginLoader;
+ mNotesEditorPluginLoader = 0;
+ }
+
+ if (mListViewPrototype) {
+ delete mListViewPrototype;
+ mListViewPrototype = NULL;
+ }
+ if (mListModel) {
+ // Do not delete the model since its owned by the view
+ mListModel->clear();
+ }
+ if (mSettingsManager) {
+ delete mSettingsManager;
+ mSettingsManager = NULL;
+ }
+}
+
+// ----------------------------------------------------------------------------
+// CalenAgendaViewWidget::setupWidget
+// Rest of the details are commented in the header
+// ----------------------------------------------------------------------------
+//
+void CalenAgendaViewWidget::setupWidget(CalenAgendaView *view)
+{
+ // Store the view for future reference
+ mView = view;
+
+ if (!mDocLoader) {
+ // Nothing much can be done. Simply return
+ return;
+ }
+
+ // Initialize the child widgets
+ initChildWidgets();
+}
+
+// ----------------------------------------------------------------------------
+// CalenAgendaViewWidget::showWidget
+// Rest of the details are commented in the header
+// ----------------------------------------------------------------------------
+//
+void CalenAgendaViewWidget::showWidget()
+{
+ // Get the date for which this view has been launched
+ mDate = mServices.Context().focusDateAndTime();
+
+ // Set the heading text
+ setHeadingText();
+
+ // Get the instance list
+ getInstanceList();
+
+ // Check if regional information needs to be shown
+ // and add it or remove it
+ showHideRegionalInformation();
+
+ // Load the appropriate section based on the number of events for the day
+ if (0 == mInstanceArray.count()) {
+ // There are no entries for the day
+ // Load and show the empty list section
+ bool loadSuccess = false;
+
+ // Hide the list which shows the events
+ mEventsList->hide();
+
+ // Show the empty list text
+ mEmptyListLabel->show();
+
+ // Get the current device orientation
+ int orientation = mServices.MainWindow().orientation();
+ if (Qt::Vertical == orientation) {
+ mDocLoader->load(CALEN_AGENDAVIEW_XML_FILE, "emptyList", &loadSuccess);
+ } else {
+ mDocLoader->load(CALEN_AGENDAVIEW_XML_FILE, "emptyLandscape", &loadSuccess);
+ }
+ if (!loadSuccess) {
+ qFatal("calenagendaviewwidget.cpp : Unable to load empty list section");
+ }
+ } else {
+ // Hide the empty view label
+ mEmptyListLabel->hide();
+
+ // Show the events list
+ mEventsList->show();
+
+ // There are one or more events. Load the non-empty section
+ bool loadSuccess = false;
+ mDocLoader->load(CALEN_AGENDAVIEW_XML_FILE, "nonEmptyList", &loadSuccess);
+ if (!loadSuccess) {
+ qFatal("calenagendaviewwidget.cpp : Unable to load non-empty list section");
+ }
+ // Now populate the list with the events
+ populateListWidget();
+ }
+}
+
+// ----------------------------------------------------------------------------
+// CalenAgendaViewWidget::orientationChanged
+// Rest of the details are commented in the header
+// ----------------------------------------------------------------------------
+//
+void CalenAgendaViewWidget::orientationChanged(Qt::Orientation orientation)
+{
+ // Load the appropriate section based on the number of events for the day
+ if (0 == mInstanceArray.count()) {
+ // There are no entries for the day
+ // Load and show the empty list section
+ bool loadSuccess = false;
+
+ // Hide the list which shows the events
+ mEventsList->hide();
+
+ // Show the empty list text
+ mEmptyListLabel->show();
+
+ if (Qt::Vertical == orientation) {
+ mDocLoader->load(CALEN_AGENDAVIEW_XML_FILE, "emptyList", &loadSuccess);
+ } else {
+ mDocLoader->load(CALEN_AGENDAVIEW_XML_FILE, "emptyLandscape", &loadSuccess);
+ }
+ if (!loadSuccess) {
+ qFatal("calenagendaviewwidget.cpp : Unable to load empty list section");
+ }
+ } else {
+ // Hide the empty view label
+ mEmptyListLabel->hide();
+
+ // Show the events list
+ mEventsList->show();
+
+ // There are one or more events. Load the non-empty section
+ bool loadSuccess = false;
+ mDocLoader->load(CALEN_AGENDAVIEW_XML_FILE, "nonEmptyList", &loadSuccess);
+ if (!loadSuccess) {
+ qFatal("calenagendaviewwidget.cpp : Unable to load non-empty list section");
+ }
+ handleListItemStretching(orientation);
+ }
+}
+
+// ----------------------------------------------------------------------------
+// CalenAgendaViewWidget::handleLocaleChange
+// Rest of the details are commented in the header
+// ----------------------------------------------------------------------------
+//
+void CalenAgendaViewWidget::handleLocaleChange()
+{
+
+}
+
+// ----------------------------------------------------------------------------
+// CalenAgendaViewWidget::setContextFromHighlight
+// Rest of the details are commented in the header
+// ----------------------------------------------------------------------------
+//
+void CalenAgendaViewWidget::setContextFromHighlight(AgendaEntry entry)
+{
+ if (entry.isTimedEntry()) {
+ // Timed entry.
+ QDateTime start = entry.startTime();
+ // start.setDate(mDate.date());
+ mServices.Context().setFocusDateAndTimeAndInstance(start,
+ TCalenInstanceId::create(entry));
+ } else {
+ // Untimed entry.
+ if (CalenDateUtils::onSameDay(TCalenInstanceId::create(entry).mInstanceTime,
+ mDate)) {
+ mServices.Context().setInstanceId(TCalenInstanceId::create(entry));
+ } else {
+ // Multi-day untimed note (either multi-day day note or weird todo).
+ // Focus on the instance and set the focus time to the highlighted day.
+ mServices.Context().setFocusDateAndTimeAndInstance(mDate,
+ TCalenInstanceId::create(entry));
+ }
+ }
+}
+
+// ----------------------------------------------------------------------------
+// CalenAgendaViewWidget::initChildWidgets
+// Rest of the details are commented in the header
+// ----------------------------------------------------------------------------
+//
+void CalenAgendaViewWidget::initChildWidgets()
+{
+ // Get the pointer to the events list
+ mEventsList = static_cast<HbListView*> (mDocLoader->findWidget(CALEN_AGENDAVIEW_LISTWIDGET));
+ if (!mEventsList) {
+ qFatal("calenagendaviewwidget.cpp : Unable to find the events list");
+ }
+ // NOTE: Layout name MUST be same as the name mentioned in the css
+ mEventsList->setLayoutName(customLayout);
+
+ // TODO : remove this line after gestures are available
+ mEventsList->installEventFilter(mView);
+
+ // Connect to the long press and activation signals
+ connect(mEventsList, SIGNAL(longPressed(HbAbstractViewItem*, const QPointF&)),
+ this, SLOT(itemLongPressed(HbAbstractViewItem*, const QPointF&)));
+ connect(mEventsList, SIGNAL(activated(const QModelIndex&)), this,
+ SLOT(itemActivated(const QModelIndex&)));
+
+ // Get the pointer to label from the loader.
+ mHeadingLabel = qobject_cast<HbGroupBox*> (mDocLoader->findWidget(CALEN_AGENDAVIEW_HEADING));
+ if (!mHeadingLabel) {
+ qFatal("calenagendaviewwidget.cpp : Unable to find heading widget");
+ }
+
+ // Get the pointer to the empty view label
+ mEmptyListLabel = qobject_cast<HbLabel*> (mDocLoader->findWidget("noEventsLabel"));
+ if (!mEmptyListLabel) {
+ qFatal("calenagendaviewwidget.cpp : Unable to find empty list label");
+ }
+ HbWidget *headingPluginWidget =
+ qobject_cast<HbWidget*> (mDocLoader->findWidget(CALEN_AGENDAVIEW_HEADING_REGIONALPLUGIN_WIDGET));
+
+ mRegionalPluginLayout = static_cast<QGraphicsLinearLayout*>(headingPluginWidget->layout());
+
+}
+
+// ----------------------------------------------------------------------------
+// CalenAgendaViewWidget::populateListWidget
+// Rest of the details are commented in the header
+// ----------------------------------------------------------------------------
+//
+void CalenAgendaViewWidget::populateListWidget()
+{
+ // Recycle the list items so that only needed rows
+ // are added or removed
+ if (mInstanceArray.count() == 0) {
+ // Reset the list
+ mEventsList->reset();
+ // Clear the model to ensure it does not have any old items
+ mListModel->clear();
+ return;
+ } else if (mInstanceArray.count() > mListModel->rowCount()) {
+ // There are more events than the number of items
+ // in the list. Add more rows
+ mListModel->insertRows(0, mInstanceArray.count() - mListModel->rowCount());
+ } else if (mInstanceArray.count() < mListModel->rowCount()) {
+ // There are less number of events than the number
+ // of items in the list. Remove the extra rows
+ mListModel->removeRows(0, mListModel->rowCount() - mInstanceArray.count());
+ }
+ mListModel->setColumnCount(singleColumn);
+
+ // Add all the events to the list
+ for (int index = 0; index < mInstanceArray.count(); index++) {
+ // Get each of the entry details
+ AgendaEntry entry = mInstanceArray[index];
+ // Create a list item for each entry
+ createListItem(index, entry);
+ }
+ // Add the item on to the list widget
+ mEventsList->setModel(mListModel, mListViewPrototype);
+
+ // Now get the item to scroll to
+ int scrollToIndex = getIndexToScrollTo();
+ if (mListModel->rowCount() > 0) {
+ // Scroll to the index only if index is valid
+ mEventsList->scrollTo(mListModel->index(scrollToIndex, 0));
+ }
+}
+
+// ----------------------------------------------------------------------------
+// CalenAgendaViewWidget::getInstanceList
+// Rest of the details are commented in the header
+// ----------------------------------------------------------------------------
+//
+void CalenAgendaViewWidget::getInstanceList()
+{
+ // Clear the previous instance list
+ mInstanceArray.clear();
+
+ // Check if the date is valid
+ if (!CalenDateUtils::isValidDay(mDate)) {
+ mDate = CalenDateUtils::today();
+ }
+
+ // Set the filter flags to fetch all relevant entries
+ AgendaUtil::FilterFlags filter = AgendaUtil::FilterFlags(AgendaUtil::IncludeAnniversaries |
+ AgendaUtil::IncludeAppointments |
+ AgendaUtil::IncludeEvents |
+ AgendaUtil::IncludeReminders |
+ AgendaUtil::IncludeIncompletedTodos);
+
+ // Fetch the instance list from the agenda interface
+ mInstanceArray = mServices.agendaInterface()->createEntryIdListForDay(mDate, filter);
+
+}
+
+// ----------------------------------------------------------------------------
+// CalenAgendaViewWidget::setDateToLabel
+// Rest of the details are commented in the header
+// ----------------------------------------------------------------------------
+//
+void CalenAgendaViewWidget::setHeadingText()
+ {
+ // Format the date as per the device locale settings
+ HbExtendedLocale systemLocale = HbExtendedLocale::system();
+
+ // Get localised name of the day from locale
+ QString dayString = systemLocale.dayName(mDate.date().dayOfWeek());
+ // Append a single space
+ dayString.append(singleSpace);
+ // Set the heading
+ // Append the date which is formatted as per the locale
+ mHeadingLabel->setHeading(hbTrId(
+ "txt_calendar_subhead_1_2").arg(dayString).arg(
+ systemLocale.format(mDate.date(), r_qtn_date_usual_with_zero)));
+}
+
+// ----------------------------------------------------------------------------
+// CalenAgendaViewWidget::createListItem
+// Rest of the details are commented in the header
+// ----------------------------------------------------------------------------
+//
+void CalenAgendaViewWidget::createListItem(int index, AgendaEntry entry)
+{
+ if (index < 0 || entry.isNull()) {
+ // Not a valid index or entry. Dont do anything
+ return;
+ }
+ // Check if the entry is a timed entry
+ // TODO: Right now, only appointment/meeting type is being handled
+ // Handle other timed entry types like reminder etc
+ if (entry.isTimedEntry()) {
+ // Get the text and icon data for the entry
+ addTimedEventToList(index, entry);
+ } else {
+ addNonTimedEventToList(index, entry);
+ }
+}
+
+// ----------------------------------------------------------------------------
+// CalenAgendaViewWidget::addTimedEventToList
+// Rest of the details are commented in the header
+// ----------------------------------------------------------------------------
+//
+void CalenAgendaViewWidget::addTimedEventToList(int index, AgendaEntry entry)
+{
+ // Create text and icon list to set to the model
+ QVariantList textData;
+ QVariantList iconData;
+ bool twoLines = false;
+
+ /**
+ * IMPORTANT NOTE: All the text and icon items must be
+ * inserted into the variant list in a specific order.
+ * If not, chaos will set it!!!
+ * On a more serious note, the mesh layout depends on the
+ * fact that the icons and text data will be added in a
+ * particular order. If one of the items go missing, the
+ * layout might get messed up. Also in case a particular item
+ * is not required to be added in the middle of the list, an
+ * empty QVariant must be added to indicate to the list view
+ * that the item must be removed from the layout.
+ * Do not mess with the order in case you are not sure what
+ * you are exactly doing.
+ */
+
+ // The first icon to show to-do or all day should not be shown
+ // Append empty data to the icons list
+ iconData << QVariant();
+
+ // Check if alarm is enabled for the entry
+ if (entry.alarm().isNull()) {
+ // Insert a blank icon. Else the next icon
+ // will get replaced in this icon's position
+ iconData << QVariant();
+ } else {
+ iconData << HbIcon(reminderIcon);
+ }
+
+ // Check if the entry is recurring
+ if (entry.isRepeating()) {
+ iconData << HbIcon(repeatIcon);
+ } else if (!entry.recurrenceId().isNull()) {
+ // This is an exceptional entry
+ iconData << HbIcon(exceptionIcon);
+ } else {
+ // Insert a blank icon. Else the next icon
+ // will get replaced in this icon's position
+ iconData << QVariant();
+ }
+
+ HbExtendedLocale locale = HbExtendedLocale::system();
+ // Get the start time and format as per the locale
+ QDateTime startTime = entry.startTime();
+ QTime eventStartTime;
+
+ if (CalenDateUtils::beginningOfDay(startTime)
+ < CalenDateUtils::beginningOfDay(mDate)) {
+ // event is started previous day, show StarTime as 12:00 am in Agendaview,
+ eventStartTime.setHMS(00, 00, 00);
+ } else {
+ eventStartTime = entry.startTime().time();
+ }
+ QString eventTime = locale.format(eventStartTime, r_qtn_time_usual_with_zero);
+
+ // Get the event end time
+ QDateTime endTime = entry.endTime();
+ QTime eventEndTime;
+
+ if (CalenDateUtils::beginningOfDay(endTime)
+ > CalenDateUtils::beginningOfDay(mDate)) {
+ // event has MidNight crossover, show EndTime as 11:59pm in Agendaview,
+ eventEndTime.setHMS(23, 59, 59);
+ } else {
+ eventEndTime = entry.endTime().time();
+ }
+
+ if (eventStartTime < eventEndTime) {
+ // Raise the flag to indicate that the list item
+ // would wrap to two lines
+ twoLines = true;
+ // Append '-' to indicate an end time is present
+ eventTime.append(singleHyphen);
+ } else {
+ // To align the subject properly if the start and endtime are same
+ eventTime.append(doubleSpace);
+ }
+
+ // Add the event time to the text list
+ // This MUST be the first item to be added to the list
+ textData << eventTime;
+
+ // Get the entry subject
+ QString subject = entry.summary();
+ if (subject.isEmpty() || subject.isNull()) {
+ // No subject. Add "(No subject)" text
+ subject.append(hbTrId("txt_calendar_dblist_unnamed"));
+ }
+ // Add the subject to the text list
+ // This MUST be the second item in the list
+ textData << subject;
+
+ // Check if the entry has location
+ // TODO: This must change to check for geo-location
+ // This MUST be the third item in the list
+ if (entry.location().isEmpty()) {
+ // Insert a blank icon. Else the next icon
+ // will get replaced in this icon's position
+ iconData << QVariant();
+ if (twoLines) {
+ /**
+ * NOTE: If the primary text is wrapping to two
+ * lines, then the location must be set as blank
+ * since the bottom of the list item is anchored to
+ * the bottom of the secondary text. Else the bottom
+ * of the list will overlap on the primary text
+ */
+ textData << singleSpace;
+ } else {
+ /**
+ * Else, set the secondary text to empty to indicate
+ * to the list view to remove the item itself and
+ * shrink its size to a single line size
+ */
+ textData << QVariant();
+ }
+ } else {
+ // TODO: Location icon must be shown
+ // only if valid geo-coordinates are present
+ if (!entry.geoValue().isNull()){
+ iconData << HbIcon(locationIcon);
+ }
+ else {
+ iconData << HbIcon();
+ }
+ textData << entry.location();
+ }
+ // Add the end time to the list item
+ if (eventStartTime < eventEndTime) {
+ QString endtime = locale.format(eventEndTime, r_qtn_time_usual_with_zero);
+ endtime.append(singleSpace);
+ textData << endtime;
+ }else {
+ textData<<QString(space);
+ }
+ // Get the list model index and set the text and icon data
+ QModelIndex listIndex = mListModel->index(index, 0);
+ mListModel->setData(listIndex, textData, Qt::DisplayRole);
+ mListModel->setData(listIndex, iconData, Qt::DecorationRole);
+
+ // Disable item stretching by removing the dynamic property
+ HbListViewItem *listViewItem = static_cast<HbListViewItem*>
+ (mEventsList->itemByIndex(mListModel->index(index, 0)));
+ if (listViewItem) {
+ listViewItem->setProperty(stretchLayout, false);
+ }
+}
+
+// ----------------------------------------------------------------------------
+// CalenAgendaViewWidget::addNonTimedEventToList
+// Rest of the details are commented in the header
+// ----------------------------------------------------------------------------
+//
+void CalenAgendaViewWidget::addNonTimedEventToList(int index, AgendaEntry entry)
+{
+ QVariantList textData;
+ QVariantList iconData;
+
+ /**
+ * IMPORTANT NOTE: All the text and icon items must be
+ * inserted into the variant list in a specific order.
+ * If not, chaos will set it!!!
+ * On a more serious note, the mesh layout depends on the
+ * fact that the icons and text data will be added in a
+ * particular order. If one of the items go missing, the
+ * layout might get messed up. Also in case a particular item
+ * is not required to be added in the middle of the list, an
+ * empty QVariant must be added to indicate to the list view
+ * that the item must be removed from the layout.
+ * Do not mess with the order in case you are not sure what
+ * you are exactly doing.
+ */
+
+ // The first column text has to be empty
+ textData << QVariant();
+
+ // Get the entry subject
+ QString subject = entry.summary();
+ if (subject.isEmpty() || subject.isNull()) {
+ // No subject. Add "(No subject)" text
+ subject.append(hbTrId("txt_calendar_dblist_unnamed"));
+ }
+ // Add the subject to the text list
+ // This MUST be the second item in the list
+ textData << subject;
+
+ // Get the entry type
+ AgendaEntry::Type entryType = entry.type();
+
+ if (entryType == AgendaEntry::TypeAnniversary) {
+ // Nothing to do as of now as anniversary events
+ // cannot be created
+ // TODO: To be handled in case of sync
+ } else if (entryType == AgendaEntry::TypeEvent) {
+ // This is an all day event
+ // Append the all-day icon
+ iconData << HbIcon(allDayIcon);
+
+ // Check if alarm is enabled for the entry
+ if (entry.alarm().isNull()) {
+ // Insert a blank icon. Else next text item will get shifted to left
+ iconData << HbIcon();
+ } else {
+ // if entry is not repeating in place of reminder icon put a blank
+ // icon and move reminder icon to the place of repeating icon
+ if (!entry.isRepeating()) {
+ iconData << HbIcon();
+ }
+ iconData << HbIcon(reminderIcon);
+ }
+
+ // Check if the entry is recurring
+ if (entry.isRepeating()) {
+ iconData << HbIcon(repeatIcon);
+ } else {
+ // put the blank icon only when both reminder and repeating icons
+ // are not there
+ if (entry.alarm().isNull()) {
+ iconData << HbIcon();
+ }
+ }
+
+ // Append the location
+ if (!entry.location().isEmpty()) {
+ textData << entry.location();
+ // TODO: Location icon must be shown
+ // only if valid geo-coordinates are present
+ if (!entry.geoValue().isNull()){
+ iconData << HbIcon(locationIcon);
+ }else {
+ iconData << HbIcon();
+ }
+ } else {
+ textData << QVariant();
+ }
+ // The fourth text item has to be empty
+ textData << QVariant();
+
+ } else if (entryType == AgendaEntry::TypeTodo) {
+ // Append the to-do icon
+ iconData << HbIcon(toDoIcon);
+
+ // Get the due date
+ QDateTime dueDate = entry.endTime();
+
+ // Append the date first
+ QString dueDateString(hbTrId("txt_calendar_dblist_val_due_on_1"));
+ QString dueText;
+ dueText.setNum(dueDate.date().day());
+ dueText.append(singleSpace);
+
+ // Append the month name next
+ HbExtendedLocale locale = HbExtendedLocale::system();
+ QString month = locale.monthName(dueDate.date().month());
+ dueText.append(month);
+ dueText.append(singleSpace);
+
+ // Append the year
+ QString year;
+ year.setNum(dueDate.date().year());
+ dueText.append(year);
+
+ textData << dueDateString.arg(dueText);
+
+ // The fourth text item has to be empty
+ textData << QVariant();
+
+ // Check if alarm is enabled for the entry
+ if (entry.alarm().isNull()) {
+ // Insert a blank icon. Else next text item will get shifted to left
+ iconData << HbIcon();
+ } else {
+ // if entry is not repeating in place of reminder icon put a blank
+ // icon and move reminder icon to the place of repeating icon
+ if (!entry.isRepeating()) {
+ iconData << HbIcon();
+ }
+ iconData << HbIcon(reminderIcon);
+ }
+
+ // Check if the entry is recurring
+ if (entry.isRepeating()) {
+ iconData << HbIcon(repeatIcon);
+ } else {
+ // Insert the blank icon only when both reminder and repeating icons
+ // are not there
+ if (entry.alarm().isNull()) {
+ iconData << HbIcon();
+ }
+ }
+ }
+
+ // Get the list model index and set the text and icon data
+ QModelIndex listIndex = mListModel->index(index, 0);
+ mListModel->setData(listIndex, textData, Qt::DisplayRole);
+ mListModel->setData(listIndex, iconData, Qt::DecorationRole);
+
+ // Enable item stretching by adding the dynamic property
+ HbListViewItem *listViewItem = static_cast<HbListViewItem*>
+ (mEventsList->itemByIndex(mListModel->index(index, 0)));
+ Qt::Orientation orientation = mServices.MainWindow().orientation();
+ // Apply stretch only for landscape orientation
+ if (listViewItem) {
+ if (Qt::Horizontal == orientation) {
+ listViewItem->setProperty(stretchLayout, true);
+ } else {
+ listViewItem->setProperty(stretchLayout, false);
+ }
+ }
+}
+
+// ----------------------------------------------------------------------------
+// CalenAgendaViewWidget::handleListItemStretching
+// Rest of the details are commented in the header
+// ----------------------------------------------------------------------------
+//
+void CalenAgendaViewWidget::handleListItemStretching(Qt::Orientation orientation)
+{
+ if (mInstanceArray.count() == 0) {
+ // Nothing much to do. Simply return
+ return;
+ }
+ for(int index = 0; index < mInstanceArray.count() ; index ++) {
+ AgendaEntry entry = mInstanceArray[index];
+ if (!entry.isNull()) {
+ AgendaEntry::Type eventType = entry.type();
+ switch(eventType) {
+ // Apply the stretching to only to-do's,
+ // anniversary and all-day event types
+ case AgendaEntry::TypeTodo:
+ case AgendaEntry::TypeEvent:
+ case AgendaEntry::TypeAnniversary:
+ {
+ // Get the list view item corresponding to the index
+ HbListViewItem *listItem = static_cast<HbListViewItem*>
+ (mEventsList->itemByIndex(mListModel->index(index, 0)));
+ if (listItem) {
+ if (orientation == Qt::Horizontal) {
+ // Set a dynamic property to indicate that this list item
+ // must be stretched in landscape.
+ // NOTE: Property name MUST match the name specified in
+ // css file, else wierd things might happen
+ listItem->setProperty(stretchLayout, true);
+ }
+ }
+ }
+ break;
+ default:
+ {
+ HbListViewItem *listItem = static_cast<HbListViewItem*>
+ (mEventsList->itemByIndex(mListModel->index(index, 0)));
+ if (listItem) {
+ listItem->setProperty(stretchLayout, false);
+ }
+ break;
+ }
+ }
+ }
+ }
+}
+
+// ----------------------------------------------------------------------------
+// CalenAgendaViewWidget::getIndexToScrollTo
+// Rest of the details are commented in the header
+// ----------------------------------------------------------------------------
+//
+int CalenAgendaViewWidget::getIndexToScrollTo()
+{
+ int scrollIndex = 0;
+ TCalenInstanceId instanceId = mServices.Context().instanceId();
+ if (instanceId == TCalenInstanceId::nullInstanceId()) {
+ // If the instance is not set, then scroll to zero index
+ return scrollIndex;
+ }
+
+ for (int index = 0 ; index < mInstanceArray.count() ; index++) {
+ AgendaEntry entry = mInstanceArray[index];
+ if (entry.id() == instanceId.mEntryLocalUid) {
+ // Match found.
+ scrollIndex = index;
+ break;
+ }
+ }
+ return scrollIndex;
+}
+
+// ----------------------------------------------------------------------------
+// CalenAgendaViewWidget::showHideRegionalInformation
+// To Show and hide regional plugin label depends upon settings
+// ----------------------------------------------------------------------------
+//
+void CalenAgendaViewWidget::showHideRegionalInformation()
+{
+ if (mView->pluginEnabled()) {
+ XQSettingsKey regionalInfo(XQSettingsKey::TargetCentralRepository,
+ KCRUidCalendar, KCalendarShowRegionalInfo);
+
+ int showRegionalInfo =
+ mSettingsManager->readItemValue(regionalInfo).toUInt();
+ if (showRegionalInfo) {
+
+ if (!mRegionalInfoGroupBox) {
+ mRegionalInfoGroupBox = new HbGroupBox();
+ CalenPluginLabel *regionalInfo = new CalenPluginLabel(
+ mServices, this);
+ regionalInfo->setFontSpec(HbFontSpec(HbFontSpec::Primary));
+ mRegionalInfoGroupBox->setContentWidget(regionalInfo);
+ mRegionalPluginLayout->insertItem(1, mRegionalInfoGroupBox);
+ }
+ QString *pluginString = mView->pluginText();
+ HbLabel *pluginInfoLabel = qobject_cast <HbLabel *>
+ (mRegionalInfoGroupBox->contentWidget());
+ pluginInfoLabel->setPlainText(*pluginString);
+ }
+ } else {
+ if (mRegionalInfoGroupBox) {
+ mRegionalPluginLayout->removeItem(mRegionalInfoGroupBox);
+ delete mRegionalInfoGroupBox;
+ mRegionalInfoGroupBox = NULL;
+ }
+ }
+}
+
+// ----------------------------------------------------------------------------
+// CalenAgendaViewWidget::createNewEvent
+// Rest of the details are commented in the header
+// ----------------------------------------------------------------------------
+//
+void CalenAgendaViewWidget::createNewEvent()
+{
+ // Issue a command to launch editor to create
+ // a new event
+ mServices.IssueCommandL(ECalenNewMeeting);
+}
+
+// ----------------------------------------------------------------------------
+// CalenAgendaViewWidget::editEntry
+// Rest of the details are commented in the header
+// ----------------------------------------------------------------------------
+//
+void CalenAgendaViewWidget::editEntry()
+{
+ // Check if the selected index is valid
+ if (mSelectedIndex < 0 || mSelectedIndex > mInstanceArray.count()) {
+ return;
+ }
+
+ // Get the entry details first
+ AgendaEntry entry = mInstanceArray[mSelectedIndex];
+ if (AgendaEntry::TypeTodo == entry.type()) {
+ // Load the notes editor plugin if not loaded.
+ if (!mNotesPluginLoaded) {
+ // Launch the to-do editor using notes editor plugin api
+ QDir dir(NOTES_EDITOR_PLUGIN_PATH);
+ QString pluginName = dir.absoluteFilePath(NOTES_EDITOR_PLUGIN_NAME);
+
+ // Create NotesEditor plugin loader object.
+ mNotesEditorPluginLoader = new QPluginLoader(pluginName);
+
+ // Load the plugin
+ mNotesPluginLoaded = mNotesEditorPluginLoader->load();
+ }
+
+ QObject *plugin = qobject_cast<QObject*> (
+ mNotesEditorPluginLoader->instance());
+
+ NotesEditorInterface* interface =
+ qobject_cast<NotesEditorInterface*>(plugin);
+
+ interface->edit(entry, mServices.agendaInterface());
+
+ connect(
+ interface, SIGNAL(editingCompleted(bool)),
+ this, SLOT(noteEditingCompleted(bool)));
+ } else {
+ // Set the context
+ setContextFromHighlight(entry);
+ // Issue a command to launch the editor to edit this entry
+ mServices.IssueCommandL(ECalenEditCurrentEntry);
+ }
+}
+
+// ----------------------------------------------------------------------------
+// CalenAgendaViewWidget::viewEntry
+// Rest of the details are commented in the header
+// ----------------------------------------------------------------------------
+//
+void CalenAgendaViewWidget::viewEntry()
+{
+ // Get the entry details first
+ AgendaEntry entry = mInstanceArray[mSelectedIndex];
+
+ // Set the context
+ setContextFromHighlight(entry);
+
+ // Launch the event viewer.
+ mServices.IssueCommandL(ECalenEventView);
+}
+
+
+// ----------------------------------------------------------------------------
+// CalenAgendaViewWidget::deleteEntry
+// Rest of the details are commented in the header
+// ----------------------------------------------------------------------------
+//
+void CalenAgendaViewWidget::deleteEntry()
+{
+ // Check if the selected index is valid
+ if (mSelectedIndex < 0 || mSelectedIndex > mInstanceArray.count()) {
+ return;
+ }
+
+ // Get the entry details
+ AgendaEntry entry = mInstanceArray[mSelectedIndex];
+ // Set the context
+ setContextFromHighlight(entry);
+ // Issue the command to delete the entry
+ mServices.IssueCommandL(ECalenDeleteCurrentEntry);
+}
+
+// ----------------------------------------------------------------------------
+// CalenAgendaViewWidget::markAsDone
+// Rest of the details are commented in the header
+// ----------------------------------------------------------------------------
+//
+void CalenAgendaViewWidget::markAsDone()
+{
+ // Check if the selected index is valid
+ if (mSelectedIndex < 0 || mSelectedIndex > mInstanceArray.count()) {
+ return;
+ }
+
+ // Get the entry details
+ AgendaEntry entry = mInstanceArray[mSelectedIndex];
+
+ // Check again if the event is of type to-to
+ if (AgendaEntry::TypeTodo == entry.type()) {
+ // Set the status of the to-do as completed
+ entry.setStatus(AgendaEntry::TodoCompleted);
+ // Update the completed date and time
+ entry.setCompletedDateTime(mDate);
+
+ // Update the entry in the database
+ mServices.agendaInterface()->setCompleted(entry, true, mDate);
+ mServices.IssueCommandL(ECalenStartActiveStep);
+ }
+}
+
+// ----------------------------------------------------------------------------
+// CalenAgendaViewWidget::itemLongPressed
+// Rest of the details are commented in the header
+// ----------------------------------------------------------------------------
+//
+void CalenAgendaViewWidget::itemLongPressed(HbAbstractViewItem* listViewItem,
+ const QPointF& coords)
+{
+ mLongTapEventFlag = true;
+ // Update the selection index first
+ mSelectedIndex = listViewItem->modelIndex().row();
+
+ if (mSelectedIndex < 0 || mSelectedIndex > mInstanceArray.count()) {
+ // Invalid index
+ return;
+ }
+
+ AgendaEntry entry = mInstanceArray[mSelectedIndex];
+
+ // Create new menu.
+ HbMenu *contextMenu = new HbMenu();
+
+ // Add the open option
+ HbAction *openAction = contextMenu->addAction(
+ hbTrId("txt_common_menu_open"));
+
+ // Check the type of event
+ if (AgendaEntry::TypeTodo == entry.type()) {
+ // Add an option to mark the note as complete
+ HbAction *completeAction = contextMenu->addAction(
+ hbTrId("txt_calendar_menu_mark_as_done"));
+ }
+
+ // Add the edit option
+ HbAction *editAction = contextMenu->addAction(
+ hbTrId("txt_common_menu_edit"));
+
+ // Add the delete option
+ HbAction *deleteAction = contextMenu->addAction(
+ hbTrId("txt_common_menu_delete"));
+
+ contextMenu->setDismissPolicy(HbMenu::TapAnywhere);
+
+ // Show context sensitive menu.
+ // Param const QPointF& coordinate - is a longpress position.
+ contextMenu->setPreferredPos(coords);
+ connect(contextMenu, SIGNAL(aboutToClose()),
+ this,
+ SLOT(contextMenuClosed()));
+
+ contextMenu->open(this, SLOT(contextManuTriggered(HbAction *)));
+}
+
+// ----------------------------------------------------------------------------
+// CalenAgendaViewWidget::itemActivated
+// Rest of the details are commented in the header
+// ----------------------------------------------------------------------------
+//
+void CalenAgendaViewWidget::itemActivated(const QModelIndex &index)
+{
+ // Update the selection index first
+ mSelectedIndex = index.row();
+
+ // Check if the selected index is valid
+ if (mSelectedIndex < 0 || mSelectedIndex > mInstanceArray.count()) {
+ return;
+ }
+ if( !mLongTapEventFlag ) {
+ // Open the event for viewing
+ viewEntry();
+ }
+}
+
+// ----------------------------------------------------------------------------
+// CalenAgendaViewWidget::itemActivated
+// Rest of the details are commented in the header
+// ----------------------------------------------------------------------------
+//
+void CalenAgendaViewWidget::noteEditingCompleted(bool status)
+{
+ // We need to refresh the list since user
+ // might have marked the to-do as complete or
+ // edited it or deleted it. So get the instance
+ // list again
+ if (status) {
+ mServices.IssueCommandL(ECalenStartActiveStep);
+ }
+}
+
+// ----------------------------------------------------------------------------
+// CalenAgendaViewWidget::goToToday
+// Rest of the details are commented in the header
+// ----------------------------------------------------------------------------
+//
+void CalenAgendaViewWidget::goToToday()
+{
+ // First check if we are not already
+ // showing today's agenda
+ if (mDate == CalenDateUtils::today()) {
+ return;
+ }
+
+ // Set the context for the current day
+ mServices.Context().setFocusDate(CalenDateUtils::today());
+
+ mView->refreshViewOnGoToDate();
+}
+
+// ----------------------------------------------------------------------------
+// CalenAgendaViewWidget::contextMenuClosed
+// Rest of the details are commented in the header
+// ----------------------------------------------------------------------------
+//
+void CalenAgendaViewWidget::contextMenuClosed()
+{
+ mLongTapEventFlag = false;
+}
+
+// ----------------------------------------------------------------------------
+// CalenAgendaViewWidget::contextManuTriggered
+// Rest of the details are commented in the header
+// ----------------------------------------------------------------------------
+//
+void CalenAgendaViewWidget::contextManuTriggered(HbAction *action)
+{
+ if (action->text() == hbTrId("txt_common_menu_open")) {
+ viewEntry();
+ } else if (action->text() == hbTrId("txt_calendar_menu_mark_as_done")) {
+ markAsDone();
+ } else if (action->text() == hbTrId("txt_common_menu_edit")) {
+ editEntry();
+ } else {
+ if (action->text() == hbTrId("txt_common_menu_delete")) {
+ deleteEntry();
+ }
+ }
+}
+// ----------------------------------------------------------------------------
+// CalenAgendaViewWidget::clearListModel
+// clears the list model
+// ----------------------------------------------------------------------------
+//
+void CalenAgendaViewWidget::clearListModel()
+ {
+ mListModel->clear();
+ }
+
+// End of file --Don't remove this.