calendarui/views/src/calendayviewwidget.cpp
changeset 18 c198609911f9
child 23 fd30d51f876b
equal deleted inserted replaced
0:f979ecb2b13e 18:c198609911f9
       
     1 /*
       
     2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: CalenDayViewWidget implementation
       
    15 *
       
    16 */
       
    17 
       
    18 // System includes
       
    19 #include <QStandardItemModel>
       
    20 #include <QGraphicsSceneEvent>
       
    21 #include <hbi18ndef.h>
       
    22 #include <hbextendedlocale.h>
       
    23 #include <hbgroupbox.h>
       
    24 #include <hbmenu.h>
       
    25 #include <hbaction.h>
       
    26 #include <hbmainwindow.h>
       
    27 #include <hbstyleloader.h>
       
    28 #include <hbdatetimepicker.h>
       
    29 #include <hbdialog.h>
       
    30 #include <agendautil.h>
       
    31 #include <noteseditor.h>
       
    32 
       
    33 // User includes
       
    34 #include "calendayviewwidget.h"
       
    35 #include "calencommon.h"
       
    36 #include "calendayview.h"
       
    37 #include "calendocloader.h"
       
    38 #include "calenservices.h"
       
    39 #include "calencontext.h"
       
    40 #include "calendateutils.h"
       
    41 #include "CalenUid.h"
       
    42 #include "caleneventlistviewitem.h"
       
    43 
       
    44 // Constants
       
    45 static const QString singleSpace(" ");
       
    46 static const QString newLine("\n");
       
    47 static const QString customLayout("custom");
       
    48 static const char *stretchLayout("stretchItem");
       
    49 // TODO: Replace with actual image names later
       
    50 static const QString toDoIcon("qtg_small_todo");
       
    51 static const QString reminderIcon("qtg_mono_alarm");
       
    52 static const QString locationIcon("qtg_mono_location");
       
    53 static const QString repeatIcon("qtg_mono_repeat");
       
    54 static const QString allDayIcon(":/qgn_indi_cdr_meeting_layer0.svg");
       
    55 static const QString exceptionIcon(":/qtg_mono_exception.png");
       
    56 static const int singleColumn(1);
       
    57 
       
    58 // ----------------------------------------------------------------------------
       
    59 // CalenDayViewWidget::CalenDayViewWidget
       
    60 // Rest of the details are commented in the header
       
    61 // ----------------------------------------------------------------------------
       
    62 //
       
    63 CalenDayViewWidget::CalenDayViewWidget(MCalenServices &services,
       
    64                                        CalenDocLoader *docLoader) :
       
    65 mServices(services),
       
    66 mDocLoader(docLoader)
       
    67 {
       
    68     // Construct the list view prototype
       
    69     mListViewPrototype = new CalenEventListViewItem(this);
       
    70     
       
    71     // Create the list model
       
    72     mListModel = new QStandardItemModel(this);
       
    73     
       
    74     // Register the custom docml and css to provide our own style to the list items
       
    75     HbStyleLoader::registerFilePath(":/");
       
    76 }
       
    77 
       
    78 // ----------------------------------------------------------------------------
       
    79 // CalenDayViewWidget::~CalenDayViewWidget
       
    80 // Rest of the details are commented in the header
       
    81 // ----------------------------------------------------------------------------
       
    82 //    
       
    83 CalenDayViewWidget::~CalenDayViewWidget()
       
    84 {
       
    85     if (mListViewPrototype) {
       
    86         delete mListViewPrototype;
       
    87         mListViewPrototype = NULL;
       
    88     }
       
    89     if (mListModel) {
       
    90         // Do not delete the model since its owned by the view
       
    91         mListModel->clear();
       
    92     }
       
    93 }
       
    94 
       
    95 // ----------------------------------------------------------------------------
       
    96 // CalenDayViewWidget::setupWidget
       
    97 // Rest of the details are commented in the header
       
    98 // ----------------------------------------------------------------------------
       
    99 //    
       
   100 void CalenDayViewWidget::setupWidget(CalenDayView *view)
       
   101 {
       
   102     // Store the view for future reference
       
   103 	mView = view;
       
   104 	
       
   105 	if (!mDocLoader) {
       
   106 	    // Nothing much can be done. Simply return
       
   107 	    return;
       
   108 	}
       
   109 
       
   110 	// Initialize the child widgets
       
   111 	initChildWidgets();
       
   112 }
       
   113 
       
   114 // ----------------------------------------------------------------------------
       
   115 // CalenDayViewWidget::showWidget
       
   116 // Rest of the details are commented in the header
       
   117 // ----------------------------------------------------------------------------
       
   118 //
       
   119 void CalenDayViewWidget::showWidget()
       
   120 {
       
   121     // Get the date for which this view has been launched
       
   122     mDate = mServices.Context().focusDateAndTimeL();
       
   123         
       
   124     // Set the heading text
       
   125     setHeadingText();
       
   126 
       
   127     // Get the instance list
       
   128     getInstanceList();
       
   129 
       
   130     // Load the appropriate section based on the number of events for the day
       
   131     if (0 == mInstanceArray.count()) {
       
   132         // There are no entries for the day
       
   133         // Load and show the empty list section
       
   134         bool loadSuccess = false;
       
   135 
       
   136         // Hide the list which shows the events
       
   137         mEventsList->hide();
       
   138 
       
   139         // Show the empty list text
       
   140         mEmptyListLabel->show();
       
   141 
       
   142         // Get the current device orientation
       
   143         int orientation = mServices.MainWindow().orientation();
       
   144         if (Qt::Vertical == orientation) {
       
   145             mDocLoader->load(CALEN_DAYVIEW_XML_FILE, "emptyList", &loadSuccess);
       
   146         } else {
       
   147             mDocLoader->load(CALEN_DAYVIEW_XML_FILE, "emptyLandscape", &loadSuccess);
       
   148         }
       
   149         if (!loadSuccess) {
       
   150             qFatal("calendayviewwidget.cpp : Unable to load empty list section");
       
   151         }
       
   152     } else {
       
   153         // Hide the empty view label
       
   154         mEmptyListLabel->hide();
       
   155 
       
   156         // Show the events list
       
   157         mEventsList->show();
       
   158 
       
   159         // There are one or more events. Load the non-empty section
       
   160         bool loadSuccess = false;
       
   161         mDocLoader->load(CALEN_DAYVIEW_XML_FILE, "nonEmptyList", &loadSuccess);
       
   162         if (!loadSuccess) {
       
   163             qFatal("calendayviewwidget.cpp : Unable to load non-empty list section");
       
   164         }
       
   165         // Now populate the list with the events
       
   166         populateListWidget();
       
   167     }
       
   168 }
       
   169 
       
   170 // ----------------------------------------------------------------------------
       
   171 // CalenDayViewWidget::orientationChanged
       
   172 // Rest of the details are commented in the header
       
   173 // ----------------------------------------------------------------------------
       
   174 //
       
   175 void CalenDayViewWidget::orientationChanged(Qt::Orientation orientation)
       
   176 {
       
   177     // Load the appropriate section based on the number of events for the day
       
   178     if (0 == mInstanceArray.count()) {
       
   179         // There are no entries for the day
       
   180         // Load and show the empty list section
       
   181         bool loadSuccess = false;
       
   182 
       
   183         // Hide the list which shows the events
       
   184         mEventsList->hide();
       
   185 
       
   186         // Show the empty list text
       
   187         mEmptyListLabel->show();
       
   188 
       
   189         if (Qt::Vertical == orientation) {
       
   190             mDocLoader->load(CALEN_DAYVIEW_XML_FILE, "emptyList", &loadSuccess);
       
   191         } else {
       
   192             mDocLoader->load(CALEN_DAYVIEW_XML_FILE, "emptyLandscape", &loadSuccess);
       
   193         }
       
   194         if (!loadSuccess) {
       
   195             qFatal("calendayviewwidget.cpp : Unable to load empty list section");
       
   196         }
       
   197     } else {
       
   198         // Hide the empty view label
       
   199         mEmptyListLabel->hide();
       
   200 
       
   201         // Show the events list
       
   202         mEventsList->show();
       
   203 
       
   204         // There are one or more events. Load the non-empty section
       
   205         bool loadSuccess = false;
       
   206         mDocLoader->load(CALEN_DAYVIEW_XML_FILE, "nonEmptyList", &loadSuccess);
       
   207         if (!loadSuccess) {
       
   208             qFatal("calendayviewwidget.cpp : Unable to load non-empty list section");
       
   209         }
       
   210         handleListItemStretching(orientation);
       
   211     }
       
   212 }
       
   213 
       
   214 // ----------------------------------------------------------------------------
       
   215 // CalenDayViewWidget::handleLocaleChange
       
   216 // Rest of the details are commented in the header
       
   217 // ----------------------------------------------------------------------------
       
   218 //
       
   219 void CalenDayViewWidget::handleLocaleChange()
       
   220 {
       
   221     if(mListViewPrototype) {
       
   222         HbExtendedLocale locale = HbExtendedLocale::system();
       
   223         HbExtendedLocale::TimeStyle timeStyle = locale.timeStyle();
       
   224         if (HbExtendedLocale::Time12 == timeStyle) {
       
   225             mListViewPrototype->setTimeFormat12Hr(true);
       
   226         } else {
       
   227             mListViewPrototype->setTimeFormat12Hr(false);
       
   228         }
       
   229         
       
   230     }
       
   231 }
       
   232 
       
   233 // ----------------------------------------------------------------------------
       
   234 // CalenDayViewWidget::setContextFromHighlight
       
   235 // Rest of the details are commented in the header
       
   236 // ----------------------------------------------------------------------------
       
   237 //    
       
   238 void CalenDayViewWidget::setContextFromHighlight(AgendaEntry entry)
       
   239 {
       
   240     if (entry.isTimedEntry()) {
       
   241         // Timed entry.
       
   242         QDateTime start = entry.startTime();
       
   243         // start.setDate(mDate.date());
       
   244         mServices.Context().setFocusDateAndTimeAndInstanceL(start,
       
   245                                                             TCalenInstanceId::create(entry),
       
   246                                                             KCalenDayViewUidValue);
       
   247     } else {
       
   248         // Untimed entry.
       
   249         if (CalenDateUtils::onSameDay(TCalenInstanceId::create(entry).mInstanceTime,
       
   250                                       mDate)) {
       
   251             mServices.Context().setInstanceIdL(TCalenInstanceId::create(entry),
       
   252                                                KCalenDayViewUidValue);
       
   253         } else {
       
   254             // Multi-day untimed note (either multi-day day note or weird todo).
       
   255             // Focus on the instance and set the focus time to the highlighted day.
       
   256             mServices.Context().setFocusDateAndTimeAndInstanceL(mDate,
       
   257                                                                 TCalenInstanceId::create(entry),
       
   258                                                                 KCalenDayViewUidValue);
       
   259         }
       
   260     }
       
   261 }
       
   262 
       
   263 // ----------------------------------------------------------------------------
       
   264 // CalenDayViewWidget::initChildWidgets
       
   265 // Rest of the details are commented in the header
       
   266 // ----------------------------------------------------------------------------
       
   267 //
       
   268 void CalenDayViewWidget::initChildWidgets()
       
   269 {
       
   270     // Get the pointer to the events list
       
   271     mEventsList = static_cast<HbListView*> (mDocLoader->findWidget(CALEN_DAYVIEW_LISTWIDGET));
       
   272     if (!mEventsList) {
       
   273         qFatal("calendayviewwidget.cpp : Unable to find the events list");
       
   274     }
       
   275     // NOTE: Layout name MUST be same as the name mentioned in the css
       
   276     mEventsList->setLayoutName(customLayout);
       
   277     
       
   278     // TODO : remove this line after gestures are available
       
   279     mEventsList->installEventFilter(mView);
       
   280 
       
   281     // Connect to the long press and activation signals
       
   282     connect(mEventsList, SIGNAL(longPressed(HbAbstractViewItem*, const QPointF&)),
       
   283             this, SLOT(itemLongPressed(HbAbstractViewItem*, const QPointF&)));
       
   284     connect(mEventsList, SIGNAL(activated(const QModelIndex&)), this,
       
   285             SLOT(itemActivated(const QModelIndex&)));
       
   286     
       
   287     // Get the pointer to label from the loader.
       
   288     mHeadingLabel = qobject_cast<HbGroupBox*> (mDocLoader->findWidget(CALEN_DAYVIEW_HEADING));
       
   289     if (!mHeadingLabel) {
       
   290         qFatal("calendayviewwidget.cpp : Unable to find heading widget");
       
   291     }
       
   292     
       
   293     // Get the pointer to the empty view label
       
   294     mEmptyListLabel = qobject_cast<HbLabel*> (mDocLoader->findWidget("noEventsLabel"));
       
   295     if (!mEmptyListLabel) {
       
   296         qFatal("calendayviewwidget.cpp : Unable to find empty list label");
       
   297     }
       
   298 }
       
   299 
       
   300 // ----------------------------------------------------------------------------
       
   301 // CalenDayViewWidget::populateListWidget
       
   302 // Rest of the details are commented in the header
       
   303 // ----------------------------------------------------------------------------
       
   304 //    
       
   305 void CalenDayViewWidget::populateListWidget()
       
   306 {
       
   307     // Recycle the list items so that only needed rows
       
   308     // are added or removed
       
   309     if (mInstanceArray.count() == 0) {
       
   310         // Reset the list
       
   311         mEventsList->reset();
       
   312         // Clear the model to ensure it does not have any old items
       
   313         mListModel->clear();
       
   314         return;
       
   315     } else if (mInstanceArray.count() > mListModel->rowCount()) {
       
   316         // There are more events than the number of items
       
   317         // in the list. Add more rows
       
   318         mListModel->insertRows(0, mInstanceArray.count() - mListModel->rowCount());
       
   319     } else if (mInstanceArray.count() < mListModel->rowCount()) {
       
   320         // There are less number of events than the number
       
   321         // of items in the list. Remove the extra rows
       
   322         mListModel->removeRows(0, mListModel->rowCount() - mInstanceArray.count());
       
   323     }
       
   324     mListModel->setColumnCount(singleColumn);
       
   325     
       
   326     // Add all the events to the list
       
   327     for (int index = 0; index < mInstanceArray.count(); index++) {
       
   328         // Get each of the entry details
       
   329         AgendaEntry entry = mInstanceArray[index];
       
   330         // Create a list item for each entry
       
   331         createListItem(index, entry);
       
   332     }
       
   333     // Add the item on to the list widget
       
   334     mEventsList->setModel(mListModel, mListViewPrototype);
       
   335     
       
   336     // Now get the item to scroll to
       
   337     int scrollToIndex = getIndexToScrollTo();
       
   338     if (mListModel->rowCount() > 0) {
       
   339         // Scroll to the index only if index is valid
       
   340         mEventsList->scrollTo(mListModel->index(scrollToIndex, 0));
       
   341     }
       
   342 }
       
   343 
       
   344 // ----------------------------------------------------------------------------
       
   345 // CalenDayViewWidget::getInstanceList
       
   346 // Rest of the details are commented in the header
       
   347 // ----------------------------------------------------------------------------
       
   348 //    
       
   349 void CalenDayViewWidget::getInstanceList()
       
   350 {
       
   351     // Clear the previous instance list
       
   352     mInstanceArray.clear();
       
   353     
       
   354     // Check if the date is valid
       
   355     if (!CalenDateUtils::isValidDay(mDate)) {
       
   356         mDate = CalenDateUtils::today();
       
   357     }
       
   358     
       
   359     // Set the filter flags to fetch all relevant entries
       
   360     AgendaUtil::FilterFlags filter = AgendaUtil::FilterFlags(AgendaUtil::IncludeAnniversaries |
       
   361                                                              AgendaUtil::IncludeAppointments | 
       
   362                                                              AgendaUtil::IncludeEvents |
       
   363                                                              AgendaUtil::IncludeReminders |
       
   364                                                              AgendaUtil::IncludeIncompletedTodos);
       
   365     
       
   366     // Fetch the instance list from the agenda interface
       
   367     mInstanceArray = mServices.agendaInterface()->createEntryIdListForDay(mDate, filter);
       
   368     
       
   369     if (0 == mInstanceArray.count()) {
       
   370         // There are no events to populate
       
   371         // Hide the events list
       
   372         mEventsList->hide();
       
   373         // Show the empty list text
       
   374         mEmptyListLabel->show();
       
   375         // Inform the view about the change
       
   376         mView->hasEvents(false);
       
   377         return;
       
   378     } else {
       
   379         mView->hasEvents(true);
       
   380     }
       
   381 }
       
   382 
       
   383 // ----------------------------------------------------------------------------
       
   384 // CalenDayViewWidget::setDateToLabel
       
   385 // Rest of the details are commented in the header
       
   386 // ----------------------------------------------------------------------------
       
   387 //
       
   388 void CalenDayViewWidget::setHeadingText()
       
   389     {
       
   390     // Format the date as per the device locale settings
       
   391 	HbExtendedLocale systemLocale = HbExtendedLocale::system();
       
   392 	
       
   393 	// Get localised name of the day from locale
       
   394 	QString dayString = systemLocale.dayName(mDate.date().dayOfWeek());
       
   395 	// Append a single space
       
   396 	dayString.append(singleSpace);
       
   397 	// Set the heading
       
   398 	// Append the date which is formatted as per the locale
       
   399 	mHeadingLabel->setHeading(hbTrId(
       
   400 				"txt_calendar_subhead_1_2").arg(dayString).arg(
       
   401 				systemLocale.format(mDate.date(), r_qtn_date_usual_with_zero)));
       
   402 }
       
   403 
       
   404 // ----------------------------------------------------------------------------
       
   405 // CalenDayViewWidget::createListItem
       
   406 // Rest of the details are commented in the header
       
   407 // ----------------------------------------------------------------------------
       
   408 //
       
   409 void CalenDayViewWidget::createListItem(int index, AgendaEntry entry)
       
   410 {
       
   411     if (index < 0 || entry.isNull()) {
       
   412         // Not a valid index or entry. Dont do anything
       
   413         return;
       
   414     }
       
   415     // Check if the entry is a timed entry
       
   416     // TODO: Right now, only appointment/meeting type is being handled
       
   417     // Handle other timed entry types like reminder etc
       
   418     if (entry.isTimedEntry()) {
       
   419         // Get the text and icon data for the entry
       
   420         addTimedEventToList(index, entry);
       
   421     } else {
       
   422         addNonTimedEventToList(index, entry);
       
   423     }
       
   424 }
       
   425 
       
   426 // ----------------------------------------------------------------------------
       
   427 // CalenDayViewWidget::addTimedEventToList
       
   428 // Rest of the details are commented in the header
       
   429 // ----------------------------------------------------------------------------
       
   430 //
       
   431 void CalenDayViewWidget::addTimedEventToList(int index, AgendaEntry entry)
       
   432 {
       
   433     // Create text and icon list to set to the model
       
   434     QVariantList textData;
       
   435     QVariantList iconData;
       
   436     bool twoLines = false;
       
   437     
       
   438     /**
       
   439      * IMPORTANT NOTE: All the text and icon items must be
       
   440      * inserted into the variant list in a specific order.
       
   441      * If not, chaos will set it!!!
       
   442      * On a more serious note, the mesh layout depends on the
       
   443      * fact that the icons and text data will be added in a
       
   444      * particular order. If one of the items go missing, the
       
   445      * layout might get messed up. Also in case a particular item
       
   446      * is not required to be added in the middle of the list, an
       
   447      * empty QVariant must be added to indicate to the list view
       
   448      * that the item must be removed from the layout.
       
   449      * Do not mess with the order in case you are not sure what
       
   450      * you are exactly doing.
       
   451      */
       
   452     
       
   453     // The first icon to show to-do or all day should not be shown
       
   454     // Append empty data to the icons list
       
   455     iconData << QVariant();
       
   456 
       
   457     // Check if alarm is enabled for the entry       
       
   458     if (entry.alarm().isNull()) {
       
   459         // Insert a blank icon. Else the next icon
       
   460         // will get replaced in this icon's position
       
   461         iconData << QVariant();
       
   462     } else {
       
   463         iconData << HbIcon(reminderIcon);
       
   464     }
       
   465 
       
   466     // Check if the entry is recurring
       
   467     if (entry.isRepeating()) {
       
   468         iconData << HbIcon(repeatIcon);
       
   469     } else if (!entry.recurrenceId().isNull()) {
       
   470         // This is an exceptional entry
       
   471         iconData << HbIcon(exceptionIcon);
       
   472     } else {
       
   473         // Insert a blank icon. Else the next icon
       
   474         // will get replaced in this icon's position
       
   475         iconData << QVariant();
       
   476     }
       
   477 
       
   478     HbExtendedLocale locale = HbExtendedLocale::system();
       
   479     // Get the start time and format as per the locale
       
   480     QTime eventStartTime = entry.startTime().time();
       
   481     QString eventTime = locale.format(eventStartTime, r_qtn_time_usual_with_zero);
       
   482 
       
   483     // Get the event end time
       
   484     QTime eventEndTime = entry.endTime().time();
       
   485 
       
   486     if (eventStartTime < eventEndTime) {
       
   487         // Raise the flag to indicate that the list item
       
   488         // would wrap to two lines
       
   489         twoLines = true;
       
   490         // Append '-' to indicate an end time is present
       
   491         eventTime.append("-");
       
   492         // Append new line to wrap to next line
       
   493         eventTime.append(newLine);
       
   494         // Event is a not a zero duration meeting
       
   495         // Only in this case, append the end time
       
   496         eventTime.append(locale.format(eventEndTime, r_qtn_time_usual_with_zero));
       
   497     } else {
       
   498         // Append new line to wrap to next line
       
   499         eventTime.append(newLine);
       
   500     }
       
   501     // Add the event time to the text list
       
   502     // This MUST be the first item to be added to the list 
       
   503     textData << eventTime;
       
   504 
       
   505     // Get the entry subject
       
   506     QString subject = entry.summary();
       
   507     if (subject.isEmpty() || subject.isNull()) {
       
   508         // No subject. Add "(No subject)" text
       
   509         subject.append(hbTrId("txt_calendar_dblist_unnamed"));
       
   510     }
       
   511     // Add the subject to the text list
       
   512     // This MUST be the second item in the list
       
   513     textData << subject;
       
   514 
       
   515     // Check if the entry has location
       
   516     // TODO: This must change to check for geo-location
       
   517     // This MUST be the third item in the list
       
   518     if (entry.location().isEmpty()) {
       
   519         // Insert a blank icon. Else the next icon
       
   520         // will get replaced in this icon's position
       
   521         iconData << QVariant();
       
   522         if (twoLines) {
       
   523             /**
       
   524              * NOTE: If the primary text is wrapping to two
       
   525              * lines, then the location must be set as blank
       
   526              * since the bottom of the list item is anchored to
       
   527              * the bottom of the secondary text. Else the bottom
       
   528              * of the list will overlap on the primary text
       
   529              */
       
   530             textData << singleSpace;
       
   531         } else {
       
   532             /**
       
   533              * Else, set the secondary text to empty to indicate
       
   534              * to the list view to remove the item itself and 
       
   535              * shrink its size to a single line size
       
   536              */
       
   537             textData << QVariant();
       
   538         }
       
   539     } else {
       
   540         // TODO: Location icon must be shown
       
   541         // only if valid geo-coordinates are present
       
   542         // iconData << HbIcon(locationIcon);
       
   543         textData << entry.location();
       
   544     }
       
   545     
       
   546     // Get the list model index and set the text and icon data
       
   547     QModelIndex listIndex = mListModel->index(index, 0);
       
   548     mListModel->setData(listIndex, textData, Qt::DisplayRole);
       
   549     mListModel->setData(listIndex, iconData, Qt::DecorationRole);
       
   550     
       
   551     // Disable item stretching by removing the dynamic property
       
   552     HbListViewItem *listViewItem = static_cast<HbListViewItem*>
       
   553                                         (mEventsList->itemByIndex(mListModel->index(index, 0)));
       
   554     if (listViewItem) {
       
   555         listViewItem->setProperty(stretchLayout, false);
       
   556     }
       
   557 }
       
   558 
       
   559 // ----------------------------------------------------------------------------
       
   560 // CalenDayViewWidget::addNonTimedEventToList
       
   561 // Rest of the details are commented in the header
       
   562 // ----------------------------------------------------------------------------
       
   563 //
       
   564 void CalenDayViewWidget::addNonTimedEventToList(int index, AgendaEntry entry)
       
   565 {
       
   566     QVariantList textData;
       
   567     QVariantList iconData;
       
   568     
       
   569     /**
       
   570      * IMPORTANT NOTE: All the text and icon items must be
       
   571      * inserted into the variant list in a specific order.
       
   572      * If not, chaos will set it!!!
       
   573      * On a more serious note, the mesh layout depends on the
       
   574      * fact that the icons and text data will be added in a
       
   575      * particular order. If one of the items go missing, the
       
   576      * layout might get messed up. Also in case a particular item
       
   577      * is not required to be added in the middle of the list, an
       
   578      * empty QVariant must be added to indicate to the list view
       
   579      * that the item must be removed from the layout.
       
   580      * Do not mess with the order in case you are not sure what
       
   581      * you are exactly doing.
       
   582      */
       
   583     
       
   584     // The first column text has to be empty
       
   585     textData << QVariant();
       
   586     
       
   587     // Get the entry subject
       
   588     QString subject = entry.summary();
       
   589     if (subject.isEmpty() || subject.isNull()) {
       
   590         // No subject. Add "(No subject)" text
       
   591         subject.append(hbTrId("txt_calendar_dblist_unnamed"));
       
   592     }
       
   593     // Add the subject to the text list
       
   594     // This MUST be the second item in the list
       
   595     textData << subject;
       
   596     
       
   597     // Get the entry type
       
   598     AgendaEntry::Type entryType = entry.type();
       
   599         
       
   600     if (entryType == AgendaEntry::TypeAnniversary) {
       
   601         // Nothing to do as of now as anniversary events
       
   602         // cannot be created
       
   603         // TODO: To be handled in case of sync
       
   604     } else if (entryType == AgendaEntry::TypeEvent) {
       
   605         // This is an all day event
       
   606         // Append the all-day icon
       
   607         iconData << HbIcon(allDayIcon);
       
   608         
       
   609         // Check if alarm is enabled for the entry       
       
   610         if (entry.alarm().isNull()) {
       
   611             // Insert a blank icon. Else the next icon
       
   612             // will get replaced in this icon's position
       
   613             iconData << QVariant();
       
   614         } else {
       
   615             iconData << HbIcon(reminderIcon);
       
   616         }
       
   617 
       
   618         // Check if the entry is recurring
       
   619         if (entry.isRepeating()) {
       
   620             iconData << HbIcon(repeatIcon);
       
   621         } else {
       
   622             // Insert a blank icon. Else the next icon
       
   623             // will get replaced in this icon's position
       
   624             iconData << QVariant();
       
   625         }
       
   626         
       
   627         // Append the location
       
   628         if (!entry.location().isEmpty()) {
       
   629             textData << entry.location();
       
   630             // TODO: Location icon must be shown
       
   631             // only if valid geo-coordinates are present
       
   632             // iconData << HbIcon(locationIcon);
       
   633         } else {
       
   634             textData << singleSpace;
       
   635         }
       
   636         
       
   637     } else if (entryType == AgendaEntry::TypeTodo) {
       
   638         // Append the to-do icon
       
   639         iconData << HbIcon(toDoIcon);
       
   640         
       
   641         // Get the due date
       
   642         QDateTime dueDate = entry.endTime();
       
   643         
       
   644         // Append the date first
       
   645         QString dueDateString(hbTrId("txt_calendar_dblist_val_due_on_1"));
       
   646         QString dueText;
       
   647         dueText.setNum(dueDate.date().day());
       
   648         dueText.append(singleSpace);
       
   649         
       
   650         // Append the month name next
       
   651         HbExtendedLocale locale = HbExtendedLocale::system();
       
   652         QString month = locale.monthName(dueDate.date().month());
       
   653         dueText.append(month);
       
   654         dueText.append(singleSpace);
       
   655         
       
   656         // Append the year
       
   657         QString year;
       
   658         year.setNum(dueDate.date().year());
       
   659         dueText.append(year);
       
   660         
       
   661         textData << dueDateString.arg(dueText);
       
   662         
       
   663         // Check if alarm is enabled for the entry       
       
   664         if (entry.alarm().isNull()) {
       
   665             // Insert a blank icon. Else the next icon
       
   666             // will get replaced in this icon's position
       
   667             iconData << QVariant();
       
   668         } else {
       
   669             iconData << HbIcon(reminderIcon);
       
   670         }
       
   671         
       
   672         // Check if the entry is recurring
       
   673         if (entry.isRepeating()) {
       
   674             iconData << HbIcon(repeatIcon);
       
   675         } else {
       
   676             // Insert a blank icon. Else the next icon
       
   677             // will get replaced in this icon's position
       
   678             iconData << QVariant();
       
   679         }
       
   680     }
       
   681     
       
   682     // Get the list model index and set the text and icon data
       
   683     QModelIndex listIndex = mListModel->index(index, 0);
       
   684     mListModel->setData(listIndex, textData, Qt::DisplayRole);
       
   685     mListModel->setData(listIndex, iconData, Qt::DecorationRole);
       
   686     
       
   687     // Enable item stretching by adding the dynamic property
       
   688     HbListViewItem *listViewItem = static_cast<HbListViewItem*>
       
   689                                         (mEventsList->itemByIndex(mListModel->index(index, 0)));
       
   690     Qt::Orientation orientation = mServices.MainWindow().orientation();
       
   691     // Apply stretch only for landscape orientation
       
   692     if (listViewItem) {
       
   693         if (Qt::Horizontal == orientation) {
       
   694             listViewItem->setProperty(stretchLayout, true);
       
   695         } else {
       
   696             listViewItem->setProperty(stretchLayout, false);
       
   697         }
       
   698     }
       
   699 }
       
   700 
       
   701 // ----------------------------------------------------------------------------
       
   702 // CalenDayViewWidget::handleListItemStretching
       
   703 // Rest of the details are commented in the header
       
   704 // ----------------------------------------------------------------------------
       
   705 // 
       
   706 void CalenDayViewWidget::handleListItemStretching(Qt::Orientation orientation)
       
   707 {
       
   708     if (mInstanceArray.count() == 0) {
       
   709         // Nothing much to do. Simply return
       
   710         return;
       
   711     }
       
   712     for(int index = 0; index < mInstanceArray.count() ; index ++) {
       
   713         AgendaEntry entry = mInstanceArray[index];
       
   714         if (!entry.isNull()) {
       
   715             AgendaEntry::Type eventType = entry.type();
       
   716             switch(eventType) {
       
   717                 // Apply the stretching to only to-do's,
       
   718                 // anniversary and all-day event types
       
   719                 case AgendaEntry::TypeTodo:
       
   720                 case AgendaEntry::TypeEvent:
       
   721                 case AgendaEntry::TypeAnniversary:
       
   722                 {
       
   723                     // Get the list view item corresponding to the index
       
   724                     HbListViewItem *listItem = static_cast<HbListViewItem*>
       
   725                                                 (mEventsList->itemByIndex(mListModel->index(index, 0)));
       
   726                     if (listItem) {
       
   727                         if (orientation == Qt::Horizontal) {
       
   728                             // Set a dynamic property to indicate that this list item
       
   729                             // must be stretched in landscape.
       
   730                             // NOTE: Property name MUST match the name specified in
       
   731                             // css file, else wierd things might happen
       
   732                             listItem->setProperty(stretchLayout, true);
       
   733                         }
       
   734                     }
       
   735                 }
       
   736                     break;
       
   737                 default:
       
   738                 {
       
   739                     HbListViewItem *listItem = static_cast<HbListViewItem*>
       
   740                                                 (mEventsList->itemByIndex(mListModel->index(index, 0)));
       
   741                     if (listItem) {
       
   742                         listItem->setProperty(stretchLayout, false);
       
   743                     }
       
   744                     break;
       
   745                 }
       
   746             }
       
   747         }
       
   748     }
       
   749 }
       
   750 
       
   751 // ----------------------------------------------------------------------------
       
   752 // CalenDayViewWidget::getIndexToScrollTo
       
   753 // Rest of the details are commented in the header
       
   754 // ----------------------------------------------------------------------------
       
   755 //  
       
   756 int CalenDayViewWidget::getIndexToScrollTo()
       
   757 {
       
   758     int scrollIndex = 0;
       
   759     TCalenInstanceId instanceId = mServices.Context().instanceId();
       
   760     if (instanceId == TCalenInstanceId::nullInstanceId()) {
       
   761         // If the instance is not set, then scroll to zero index
       
   762         return scrollIndex;
       
   763     }
       
   764     
       
   765     for (int index = 0 ; index < mInstanceArray.count() ; index++) {
       
   766         AgendaEntry entry = mInstanceArray[index];
       
   767         if (entry.id() == instanceId.mEntryLocalUid) {
       
   768             // Match found.
       
   769             scrollIndex = index;
       
   770             break;
       
   771         }
       
   772     }
       
   773     return scrollIndex;
       
   774 }
       
   775 
       
   776 // ----------------------------------------------------------------------------
       
   777 // CalenDayViewWidget::createNewEvent
       
   778 // Rest of the details are commented in the header
       
   779 // ----------------------------------------------------------------------------
       
   780 //    
       
   781 void CalenDayViewWidget::createNewEvent()
       
   782 {
       
   783     // Issue a command to launch editor to create
       
   784     // a new event
       
   785 	mServices.IssueCommandL(ECalenNewMeeting);
       
   786 }
       
   787 
       
   788 // ----------------------------------------------------------------------------
       
   789 // CalenDayViewWidget::editEntry
       
   790 // Rest of the details are commented in the header
       
   791 // ----------------------------------------------------------------------------
       
   792 //    
       
   793 void CalenDayViewWidget::editEntry()
       
   794 {
       
   795     // Check if the selected index is valid
       
   796     if (mSelectedIndex < 0 || mSelectedIndex > mInstanceArray.count()) {
       
   797         return;
       
   798     }
       
   799     
       
   800     // Get the entry details first
       
   801     AgendaEntry entry = mInstanceArray[mSelectedIndex];
       
   802     if (AgendaEntry::TypeTodo == entry.type()) {
       
   803         // Launch the to-do editor
       
   804         mNotesEditor = new NotesEditor(mView);
       
   805         mNotesEditor->edit(entry);
       
   806         connect(mNotesEditor, SIGNAL(editingCompleted(bool)), this, SLOT(noteEditingCompleted(bool)));
       
   807     } else {
       
   808         // Set the context
       
   809         setContextFromHighlight(entry);
       
   810         // Issue a command to launch the editor to edit this entry
       
   811         mServices.IssueCommandL(ECalenEditCurrentEntry);
       
   812     }
       
   813 }
       
   814 
       
   815 // ----------------------------------------------------------------------------
       
   816 // CalenDayViewWidget::viewEntry
       
   817 // Rest of the details are commented in the header
       
   818 // ----------------------------------------------------------------------------
       
   819 //    
       
   820 void CalenDayViewWidget::viewEntry()
       
   821 {
       
   822     // Get the entry details first
       
   823     AgendaEntry entry = mInstanceArray[mSelectedIndex];
       
   824     
       
   825     // Set the context
       
   826     setContextFromHighlight(entry);
       
   827         
       
   828     // Launch the event viewer.
       
   829     mServices.IssueCommandL(ECalenEventView);
       
   830 }
       
   831 
       
   832 
       
   833 // ----------------------------------------------------------------------------
       
   834 // CalenDayViewWidget::deleteEntry
       
   835 // Rest of the details are commented in the header
       
   836 // ----------------------------------------------------------------------------
       
   837 //    
       
   838 void CalenDayViewWidget::deleteEntry()
       
   839 {
       
   840     // Check if the selected index is valid
       
   841 	if (mSelectedIndex < 0 || mSelectedIndex > mInstanceArray.count()) {
       
   842 		return;
       
   843 	}
       
   844 	
       
   845 	// Get the entry details
       
   846 	AgendaEntry entry = mInstanceArray[mSelectedIndex];
       
   847 	// Set the context
       
   848 	setContextFromHighlight(entry);
       
   849 	// Issue the command to delete the entry
       
   850 	mServices.IssueCommandL(ECalenDeleteCurrentEntry);
       
   851 }
       
   852 
       
   853 // ----------------------------------------------------------------------------
       
   854 // CalenDayViewWidget::markAsDone
       
   855 // Rest of the details are commented in the header
       
   856 // ----------------------------------------------------------------------------
       
   857 //  
       
   858 void CalenDayViewWidget::markAsDone()
       
   859 {
       
   860     // Check if the selected index is valid
       
   861     if (mSelectedIndex < 0 || mSelectedIndex > mInstanceArray.count()) {
       
   862         return;
       
   863     }
       
   864     
       
   865     // Get the entry details
       
   866     AgendaEntry entry = mInstanceArray[mSelectedIndex];
       
   867     
       
   868     // Check again if the event is of type to-to
       
   869     if (AgendaEntry::TypeTodo == entry.type()) {
       
   870         // Set the status of the to-do as completed
       
   871         entry.setStatus(AgendaEntry::TodoCompleted);
       
   872         // Update the completed date and time
       
   873         entry.setCompletedDateTime(mDate);
       
   874         
       
   875         // Update the entry in the database
       
   876         AgendaUtil agendaUtil;
       
   877         agendaUtil.setCompleted(entry, true, mDate);
       
   878 
       
   879 		mServices.IssueCommandL(ECalenStartActiveStep);
       
   880     }
       
   881 }
       
   882 
       
   883 // ----------------------------------------------------------------------------
       
   884 // CalenDayViewWidget::itemLongPressed
       
   885 // Rest of the details are commented in the header
       
   886 // ----------------------------------------------------------------------------
       
   887 //    
       
   888 void CalenDayViewWidget::itemLongPressed(HbAbstractViewItem* listViewItem,
       
   889                                          const QPointF& coords)
       
   890 {
       
   891     // Update the selection index first
       
   892     mSelectedIndex = listViewItem->modelIndex().row();
       
   893     
       
   894     if (mSelectedIndex < 0 || mSelectedIndex > mInstanceArray.count()) {
       
   895         // Invalid index
       
   896         return;
       
   897     }
       
   898 
       
   899     AgendaEntry entry = mInstanceArray[mSelectedIndex];
       
   900     
       
   901     // Create new menu.
       
   902     HbMenu *contextMenu = new HbMenu();
       
   903     
       
   904     // Add the open option
       
   905     HbAction *openAction = contextMenu->addAction(hbTrId("txt_common_menu_open"));
       
   906     connect(openAction, SIGNAL(triggered()), this, SLOT(viewEntry()));
       
   907     
       
   908     // Check the type of event
       
   909     if (AgendaEntry::TypeTodo == entry.type()) {
       
   910         // Add an option to mark the note as complete
       
   911         HbAction *completeAction = contextMenu->addAction(hbTrId("txt_calendar_menu_mark_as_done"));
       
   912         connect(completeAction, SIGNAL(triggered()), this, SLOT(markAsDone()));
       
   913     }
       
   914     
       
   915     // Add the edit option
       
   916     HbAction *editAction = contextMenu->addAction(hbTrId("txt_common_menu_edit"));
       
   917     connect(editAction, SIGNAL(triggered()), this, SLOT(editEntry()));
       
   918     
       
   919     // Add the delete option
       
   920     HbAction *deleteAction = contextMenu->addAction(hbTrId("txt_common_menu_delete"));
       
   921     connect(deleteAction, SIGNAL(triggered()), this, SLOT(deleteEntry()));
       
   922     
       
   923     contextMenu->setDismissPolicy(HbMenu::TapAnywhere);
       
   924 
       
   925     // Show context sensitive menu. 
       
   926     // Param const QPointF& coordinate - is a longpress position.
       
   927     contextMenu->exec(coords);
       
   928 }
       
   929 
       
   930 // ----------------------------------------------------------------------------
       
   931 // CalenDayViewWidget::itemActivated
       
   932 // Rest of the details are commented in the header
       
   933 // ----------------------------------------------------------------------------
       
   934 //    
       
   935 void CalenDayViewWidget::itemActivated(const QModelIndex &index)
       
   936 {
       
   937     // Update the selection index first
       
   938     mSelectedIndex = index.row();
       
   939 
       
   940     // Check if the selected index is valid
       
   941     if (mSelectedIndex < 0 || mSelectedIndex > mInstanceArray.count()) {
       
   942         return;
       
   943     }
       
   944     
       
   945     // Open the event for viewing
       
   946     viewEntry();
       
   947 }
       
   948 
       
   949 // ----------------------------------------------------------------------------
       
   950 // CalenDayViewWidget::itemActivated
       
   951 // Rest of the details are commented in the header
       
   952 // ----------------------------------------------------------------------------
       
   953 // 
       
   954 void CalenDayViewWidget::noteEditingCompleted(bool status)
       
   955 {
       
   956     Q_UNUSED(status);
       
   957     // Delete the notes editor instance
       
   958     mNotesEditor->deleteLater();
       
   959     
       
   960     // We need to refresh the list since user
       
   961     // might have marked the to-do as complete or
       
   962     // edited it or deleted it. So get the instance
       
   963     // list again
       
   964     if (status) {
       
   965         mServices.IssueCommandL(ECalenStartActiveStep);
       
   966     }
       
   967 }
       
   968 
       
   969 // ----------------------------------------------------------------------------
       
   970 // CalenDayViewWidget::goToToday
       
   971 // Rest of the details are commented in the header
       
   972 // ----------------------------------------------------------------------------
       
   973 // 
       
   974 void CalenDayViewWidget::goToToday()
       
   975 {
       
   976     // First check if we are not already
       
   977     // showing today's agenda
       
   978     if (mDate == CalenDateUtils::today()) {
       
   979         return;
       
   980     }
       
   981     
       
   982     // Set the context for the current day
       
   983     mServices.Context().setFocusDateL(CalenDateUtils::today(), KCalenDayViewUidValue);
       
   984     
       
   985     // Issue a command to re-populate the entire view
       
   986     mServices.IssueCommandL(ECalenStartActiveStep);
       
   987 }
       
   988 
       
   989 // ----------------------------------------------------------------------------
       
   990 // CalenDayViewWidget::deleteEntries
       
   991 // Rest of the details are commented in the header
       
   992 // ----------------------------------------------------------------------------
       
   993 // 
       
   994 void CalenDayViewWidget::deleteEntries()
       
   995 {
       
   996     // TODO: Show a checklist to allow multiple delete
       
   997 }
       
   998 
       
   999 // End of file	--Don't remove this.