--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/calendarui/views/src/calendaylistboxmodel.cpp Tue Feb 02 10:12:19 2010 +0200
@@ -0,0 +1,924 @@
+/*
+* Copyright (c) 2002 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: List Box Model class for Calendar Day view
+ *
+*/
+
+#include <calencommands.hrh> // Calendar commands
+#include <AknBidiTextUtils.h>
+#include <AknUtils.h>
+#include <eikenv.h>
+#include <PUAcodes.hrh>
+#include <StringLoader.h>
+#include <txtrich.h>
+#include <calentry.h>
+#include <calinstance.h>
+#include <calrrule.h>
+#include <calalarm.h>
+#include <centralrepository.h>
+#include <Calendar.rsg>
+#include <calsession.h>
+#include <caleninstanceid.h> // TCalenInstanceId
+#include <calenviewutils.h>
+#include <calenagendautils.h>
+#include "CalendarVariant.hrh"
+#ifdef RD_CALEN_MIDNIGHT_VISUALIZATION
+#include <calendateutils.h>
+#endif // RD_CALEN_MIDNIGHT_VISUALIZATION
+#include <calcalendarinfo.h>
+#include <calenservices.h>
+
+//debug
+#include "calendarui_debug.h"
+#include "calendaylistboxmodel.h"
+#include "calencontroller.h"
+#include "CalendarVariant.hrh"
+#include "calendaylistbox.h"
+#include "calentodoview.h" // for priorities
+#include "calendar.hrh"
+#include "CalendarPrivateCRKeys.h"
+#include "calenglobaldata.h"
+
+// LOCAL CONSTANTS AND MACROS
+_LIT(KDesTimeSpace, " ");
+_LIT(KDesSeparator, "\t");
+_LIT(KIconSeperatorFormat, "%d\t"); // Day LB icon seperator format
+
+#ifdef RD_CALEN_MIDNIGHT_VISUALIZATION
+_LIT(KUnicodeRightwardsArrow, "\x2192"); // ->
+_LIT(KUnicodeLeftwardsArrow, "\x2190"); // <-
+_LIT(K24hFmt12am, " 00"); // already starts at hr 00
+_LIT(K24hFmt12pm, "24 ");
+#endif // RD_CALEN_MIDNIGHT_VISUALIZATION
+
+
+const TInt KTimedNoteMaxLines(4);
+const TInt KHypenBufSize(4);
+const TInt KNonTimedNoteMaxLines(1);
+
+// KMaxColumnDataLength is Avkon defined minimal maximum length for column texts.
+const TInt KMaxLengthOfDisplayedText(KTimedNoteMaxLines * KMaxColumnDataLength);
+
+// =========================== MEMBER FUNCTIONS ===============================
+
+// ----------------------------------------------------------------------------
+// CCalenDayListBoxModel::CCalenDayListBoxModel
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// ----------------------------------------------------------------------------
+//
+CCalenDayListBoxModel::CCalenDayListBoxModel()
+ {
+ TRACE_ENTRY_POINT;
+ TRACE_EXIT_POINT;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenDayListBoxModel::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CCalenDayListBoxModel::ConstructL( const CCalenDayContainer* aDayContainer )
+ {
+ TRACE_ENTRY_POINT;
+
+ iDayContainer = aDayContainer;
+ iItemTextArray = new(ELeave) CDesCArrayFlat(5);
+
+ // Read time formats
+ iTimeFormat = StringLoader::LoadL( R_QTN_TIME_USUAL_WITH_ZERO );
+
+ TRACE_EXIT_POINT;
+ }
+
+void CCalenDayListBoxModel::UpdateLayoutValues( TInt aLayoutVariant,
+TBool aMidnightVisualization)
+ {
+ TRACE_ENTRY_POINT;
+
+ CCalenDayListBox::ReadLayout(
+ aLayoutVariant,
+ iLocale,
+ iLaf.iGfxA,
+ iLaf.iTextA,
+ iLaf.iTextB,
+ iLaf.iTextC,
+ iLaf.iIconA,
+ iLaf.iIconB,
+ aMidnightVisualization );
+
+ TRACE_EXIT_POINT;
+ }
+
+// Destructor
+CCalenDayListBoxModel::~CCalenDayListBoxModel()
+ {
+ TRACE_ENTRY_POINT;
+
+ delete iTimeFormat;
+ delete iItemTextArray;
+
+ TRACE_EXIT_POINT;
+ }
+
+// -----------------------------------------------------------------------------
+// CCalenDayListBoxModel::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CCalenDayListBoxModel* CCalenDayListBoxModel::NewL( const CCalenDayContainer* aDayContainer )
+ {
+ TRACE_ENTRY_POINT;
+
+ CCalenDayListBoxModel* self =
+ new( ELeave ) CCalenDayListBoxModel();
+
+ CleanupStack::PushL( self );
+ self->ConstructL( aDayContainer );
+ CleanupStack::Pop( self );
+
+ TRACE_EXIT_POINT;
+ return self;
+ }
+
+// ----------------------------------------------------------------------------
+// CCalenDayListBoxModel::?member_function
+// ?implementation_description
+// (other items were commented in a header).
+// ----------------------------------------------------------------------------
+//
+CDesCArrayFlat* CCalenDayListBoxModel::ItemTextArray()
+ {
+ TRACE_ENTRY_POINT;
+
+ TRACE_EXIT_POINT;
+ return iItemTextArray;
+ }
+
+// ----------------------------------------------------------------------------
+// CCalenDayListBoxModel::?member_function
+// ?implementation_description
+// (other items were commented in a header).
+// ----------------------------------------------------------------------------
+//
+void CCalenDayListBoxModel::GetEntryTextDataL(CCalEntry& aEntry,
+ TDes& aBuf) const
+ {
+ TRACE_ENTRY_POINT;
+
+ const TInt maxLen( aBuf.MaxLength() - KTimedNoteMaxLines * KAknBidiExtraSpacePerLine );
+ CalenViewUtils::GetSummaryLocationTextL( aEntry, aBuf, maxLen );
+
+ TRACE_EXIT_POINT;
+ }
+
+#ifndef RD_CALEN_MIDNIGHT_VISUALIZATION
+// ----------------------------------------------------------------------------
+// CCalenDayListBoxModel::?member_function
+// ?implementation_description
+// (other items were commented in a header).
+// ----------------------------------------------------------------------------
+//
+void CCalenDayListBoxModel::LimitStartAndEndTime(TTime& aCurrentDay,
+ TTime& aStart,
+ TTime& aEnd)
+ {
+ TRACE_ENTRY_POINT;
+
+ TTimeIntervalDays days(aCurrentDay.DaysFrom(TTime(TInt64(0))));
+ TTimeIntervalDays startDays(aStart.DaysFrom(TTime(TInt64(0))));
+ TTimeIntervalDays endDays(aEnd.DaysFrom(TTime(TInt64(0))));
+
+ // set start time to 00:00, if event starts before current day
+ if (startDays != days)
+ {
+ aStart = TTime(TInt64(0)) + startDays;
+ }
+
+ // Set end time to 23:59, if event continues to next day
+ if (endDays != days)
+ {
+ TDateTime endDate = aEnd.DateTime();
+ endDate.SetHour(ECalenMaxHour);
+ endDate.SetMinute(ECalenMaxMinute);
+ aEnd = endDate;
+ }
+
+ TRACE_EXIT_POINT;
+ }
+
+// ----------------------------------------------------------------------------
+// CCalenDayListBoxModel::?member_function
+// ?implementation_description
+// (other items were commented in a header).
+// ----------------------------------------------------------------------------
+//
+void CCalenDayListBoxModel::InsertTimeL(TDes& aBuf,
+ const TTime& aTime)
+ {
+ TRACE_ENTRY_POINT;
+
+ TBuf<32> timeDes;
+ aTime.FormatL( timeDes, *iTimeFormat );
+ AknTextUtils::DisplayTextLanguageSpecificNumberConversion( timeDes );
+ AknBidiTextUtils::ConvertToVisualAndClipL( timeDes,
+ *iLaf.iTextA.Font(),
+ iLaf.iTextA.TextRect().Width(),
+ iLaf.iTextA.TextRect().Width() );
+ aBuf.Append(timeDes);
+
+ TRACE_EXIT_POINT;
+ }
+
+#else // Midnight is ON
+
+void CCalenDayListBoxModel::InsertTimeL(TDes& aBuf, const TTime& aTime, const TTimeStringFormat aInsert)
+ {
+ TRACE_ENTRY_POINT;
+
+ TBuf<32> timeDes;
+ switch(aInsert)
+ {
+ case EInsertTimeGiven:
+ aTime.FormatL( timeDes, *iTimeFormat );
+ break;
+
+ case EInsert00:
+ timeDes = K24hFmt12am();
+ break;
+
+ case EInsert24:
+ timeDes = K24hFmt12pm();
+ break;
+
+ default:
+ ASSERT(KErrArgument);
+ }
+
+
+ AknTextUtils::DisplayTextLanguageSpecificNumberConversion( timeDes );
+ AknBidiTextUtils::ConvertToVisualAndClipL( timeDes,
+ *iLaf.iTextA.Font(),
+ iLaf.iTextA.TextRect().Width(),
+ iLaf.iTextA.TextRect().Width() );
+ aBuf.Append(timeDes);
+
+ TRACE_EXIT_POINT;
+ }
+
+
+#endif // RD_CALEN_MIDNIGHT_VISUALIZATION
+
+
+// ----------------------------------------------------------------------------
+// CCalenDayListBoxModel::?member_function
+// ?implementation_description
+// (other items were commented in a header).
+// ----------------------------------------------------------------------------
+//
+#ifdef RD_CALEN_MIDNIGHT_VISUALIZATION
+void CCalenDayListBoxModel::InsertHyphenL(TDes& aBuf,
+ const TTime& aStart,
+ const TTime& aEnd)
+
+#else // keep the old definition
+void CCalenDayListBoxModel::InsertHyphen(TDes& aBuf,
+ const TTime& aStart,
+ const TTime& aEnd)
+#endif //RD_CALEN_MIDNIGHT_VISUALIZATION
+ {
+ TRACE_ENTRY_POINT;
+
+ if (aStart != aEnd)
+ {
+
+ TBuf<KHypenBufSize> hyphen;
+ hyphen.Append(TChar(KPuaCodeNarrowDash));
+
+#ifdef RD_CALEN_MIDNIGHT_VISUALIZATION
+
+ AknBidiTextUtils::ConvertToVisualAndClipL( hyphen,
+ *iLaf.iTextB.Font(),
+ iLaf.iTextB.TextRect().Width(),
+ iLaf.iTextB.TextRect().Width() );
+ aBuf.Append(hyphen);
+#else
+ aBuf.Append(hyphen);
+#endif // RD_CALEN_MIDNIGHT_VISUALIZATION
+ }
+
+ TRACE_EXIT_POINT;
+ }
+
+// ---------------------------------------------------------
+// CCalenDayListBoxModel::LastLineWidth
+// Calculates a last line width
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+TInt CCalenDayListBoxModel::LastLineWidthL(TInt aWidth, CCalEntry& aEntry) const
+ {
+ TRACE_ENTRY_POINT;
+
+ CCalAlarm* alarmObj = aEntry.AlarmL();
+ TBool alarm( alarmObj ? ETrue : EFalse );
+ delete alarmObj;
+
+ TCalRRule ignore;
+ TBool repeat(CalenAgendaUtils::IsRepeatingL(aEntry));
+
+ TBool priority( EFalse );
+
+ if( aEntry.EntryTypeL() == CCalEntry::ETodo &&
+ aEntry.PriorityL() != ETodoPriorityNormal )
+ {
+ priority = ETrue;
+ }
+
+ // Check if this entry has any geovalues for the location field
+ CCalGeoValue* geovalue = aEntry.GeoValueL();
+ TBool mapIcon( geovalue ? ETrue : EFalse);
+ delete geovalue;
+
+ TInt width( aWidth );
+
+ // FIXME, actually these should be read from LAF!
+
+ if( alarm && repeat || alarm && priority || repeat && priority || mapIcon && alarm || mapIcon && repeat || mapIcon && priority)
+ {
+ width = aWidth -( iLaf.iIconB.Rect().Width() + iLaf.iIconA.Rect().Width() );
+ }
+ else if( alarm || repeat || priority || mapIcon)
+ {
+ width = aWidth - iLaf.iIconA.Rect().Width();
+ }
+ width = width - KAknBidiExtraSpacePerLine;
+
+ TRACE_EXIT_POINT;
+ return width;
+ }
+
+// ---------------------------------------------------------
+// CCalenDayListBoxModel::WrapTextL
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+HBufC* CCalenDayListBoxModel::WrapTextL(
+ CCalEntry& aEntry,
+ CArrayFixFlat<TPtrC>& aLineArray) const
+ {
+ TRACE_ENTRY_POINT;
+
+ // This is rather complicated algorithm to calculate how many
+ // lines given text takes.
+ //
+ // (Note: in below description of problem and solution we for simplicity
+ // consider only meeting entries with maximum of 4 lines of text, but
+ // code handles Todos, Day Events and Anniversaries with max 1 line
+ // of text. It should be easy to adapt it to have different maximum number
+ // of lines.)
+ //
+ // As UI spec says, textual representation of entry
+ // (subject + location) takes as many lines as it needs.
+ // If it doesn't fit to maximum number of lines (4), it is
+ // truncated.
+ //
+ // Problem is that last line of entry might contain less space for
+ // text than previous lines, as it can contain icons for alarm, repeat
+ // and priority. Because Avkon APIs for text wrapping and truncating
+ // cannot handle situation, in which line count is not defined AND
+ // last line length varies, we have to programmatically try
+ // to wrap and fit text first to 1 line, then to 2 lines, then to
+ // 3 lines and finally truncate it to 4 lines.
+
+ TBool isTimed =
+ aEntry.EntryTypeL() == CCalEntry::EAppt ||
+ aEntry.EntryTypeL() == CCalEntry::EReminder;
+ const TInt KMaxLines =
+ isTimed ? KTimedNoteMaxLines : KNonTimedNoteMaxLines;
+
+ const TInt KLineWidth = iLaf.iTextC.TextRect().Width();
+
+ CArrayFixFlat<TInt>* lineWidths = new( ELeave )CArrayFixFlat<TInt>( 5 );
+ CleanupStack::PushL( lineWidths );
+
+ // last line width is always dependent on icons and is thus calculated.
+ // We insert last line width to line widths buffer here, and try to fit
+ // text to this single line. After that we always add line with normal
+ // width BEFORE this last line.
+ // I.e.
+ // 1st try: { LastLineWidth }
+ // 2nd try: { NormalLineWidth, LastLineWidth }
+ // 3rd try: { NormalLineWidth, NormalLineWidth, LastLineWidth }
+ // ...
+ lineWidths->AppendL( LastLineWidthL( KLineWidth, aEntry ) );
+
+ // Get entry text
+ HBufC* text = HBufC::NewLC( KMaxLengthOfDisplayedText );
+ TPtr textPtr = text->Des();
+ GetEntryTextDataL( aEntry, textPtr );
+
+ // First we try to fit text to [1, max_lines - 1] (i.e. 1,2 or 3 lines)
+ TBool doesFit = EFalse;
+ HBufC* visualText = NULL;
+ while ( ! doesFit && lineWidths->Count() < KMaxLines )
+ {
+ // Convert*WholeTextL wraps all text, so that if it doesn't
+ // fit to given lines, it uses last line width to wrap remaining
+ // texts. This is useful, because we then know did it fit or not.
+ //
+ // Note that it constructs new text buffer (visualText) that
+ // has to be destroyed, if it's not used. If it's used, this
+ // text has to be returned to caller and caller takes care of
+ // destroying. This memory management is unfortunately complicated,
+ // so be careful if you modify.
+ visualText =
+ AknBidiTextUtils::ConvertToVisualAndWrapToArrayWholeTextL(
+ *text,
+ *lineWidths,
+ *iLaf.iTextC.Font(),
+ aLineArray);
+ CleanupStack::PushL( visualText );
+
+ // If amount of splitted lines is same (or less than) currently
+ // tried lines, we can fit text to this amount of lines.
+ TInt triedLines = lineWidths->Count();
+ if ( aLineArray.Count() <= triedLines )
+ {
+ doesFit = ETrue;
+ // In case Avkon method wraps text to less lines than we tried
+ // it means that text fits to less lines, but icons has to
+ // be put to empty line after text!
+ // We have to manually add that empty line.
+ if ( aLineArray.Count() < triedLines )
+ {
+ aLineArray.AppendL( TPtrC(KNullDesC) );
+ }
+ break; // exit from loop, we could fit text.
+ }
+ else
+ {
+ // Release visualText buffer and reset line array, because
+ // we couldn't fit text on this try.
+ CleanupStack::PopAndDestroy( visualText );
+ visualText = NULL;
+ aLineArray.Reset();
+
+ // Prepend normal line width, and try again with more lines.
+ // (Note: last line width stays last, because we prepend)
+ lineWidths->InsertL( 0, KLineWidth );
+ }
+ }
+
+ HBufC* result = NULL;
+ if ( doesFit )
+ {
+ // If we could fit, we return visualText and caller has
+ // to memory manage it. TPtrs in aLineArray points to this text
+ // buffer.
+ result = visualText;
+ CleanupStack::Pop( visualText );
+ CleanupStack::PopAndDestroy( text );
+ }
+ else
+ {
+ // If we couldn't fit before, we wrap text to max lines and truncate
+ // it with ellipsis.
+ TInt triedLines = lineWidths->Count();
+
+ // truncate and add ellipsis
+ TPtr truncatedText = text->Des();
+ const TBool KUseEllipsis = ETrue;
+ AknBidiTextUtils::ConvertToVisualAndWrapToArrayL(
+ truncatedText,
+ *lineWidths,
+ *iLaf.iTextC.Font(),
+ aLineArray,
+ KUseEllipsis );
+
+ // In case Avkon method wrapped text to less lines than we tried
+ // it means that text fits to less lines, but icons has to
+ // be put to empty line after text!
+ // We have to manually add that empty line.
+ if ( aLineArray.Count() < triedLines )
+ {
+ aLineArray.AppendL( TPtrC(KNullDesC) );
+ }
+
+ // We return original text, because
+ // AknBidiTextUtils::ConvertToVisualAndWrapToArrayL
+ // modifies that and TPtrs in aLineArray points to that buffer
+ result = text;
+ CleanupStack::Pop( text );
+ }
+
+ CleanupStack::PopAndDestroy( lineWidths );
+
+ TRACE_EXIT_POINT;
+ return result;
+ };
+
+// ----------------------------------------------------------------------------
+// CCalenDayListBoxModel::?member_function
+// ?implementation_description
+// (other items were commented in a header).
+// ----------------------------------------------------------------------------
+//
+void CCalenDayListBoxModel::CreateListBoxDataL(
+ CArrayFixFlat<CCalenDayContainer::SItemInfo>& aLayoutTable,
+ CArrayFixFlat<TInt>& aCellArray,
+ MCalenServices& aServices,
+ /*CCalInstanceView* aInstanceView*/
+ TTime aCurrentDay)
+ {
+ TRACE_ENTRY_POINT;
+
+ iItemTextArray->Reset();
+ TBool isAllDayEvent;
+ RPointerArray<CCalCalendarInfo> calendarInfoList;
+ aServices.GetAllCalendarInfoL(calendarInfoList);
+ CleanupClosePushL(calendarInfoList);
+
+ HBufC* listItemData = HBufC::NewLC(ECalenCharsInLine);
+
+ // iterate layout
+ for (TInt loop(0); loop < aLayoutTable.Count(); ++loop)
+ {
+ CCalenDayContainer::SItemInfo& itemInfo = aLayoutTable[loop];
+
+ CCalEntry& entry = itemInfo.iTmpInstance->Entry();
+ isAllDayEvent = EFalse;
+ if (entry.EntryTypeL() == CCalEntry::EAppt || entry.EntryTypeL()
+ == CCalEntry::EEvent)
+ {
+ isAllDayEvent = CalenViewUtils::IsAlldayEventL(
+ *itemInfo.iTmpInstance);
+ }
+ TCalCollectionId collectionId =
+ itemInfo.iTmpInstance->InstanceIdL().iCollectionId;
+ HBufC* calendarFileName = aServices.GetCalFileNameForCollectionId(collectionId).AllocLC();
+ TInt index = calendarInfoList.Find( *calendarFileName,
+ CCalenDayListBoxModel::CalendarInfoIdentifierL );
+
+ CleanupStack::PopAndDestroy(calendarFileName);
+
+ if (index != KErrNotFound && calendarInfoList[index]->Enabled())
+ {
+ itemInfo.iColor = calendarInfoList[index]->Color().Value();
+ TPtr ptr = listItemData->Des();
+ ptr.Zero();
+
+ TTime start(TInt64(0));
+ TTime end(TInt64(0));
+
+ if ((entry.EntryTypeL() == CCalEntry::EAppt || entry.EntryTypeL()
+ == CCalEntry::EReminder) && (!isAllDayEvent))
+ {
+ // meeting notes
+ // \t14:00\t-\t
+ // 0 1 2
+ //
+ // no icon
+ ptr.Append(KDesSeparator);
+
+ TTimeIntervalMinutes duration;
+ entry.EndTimeL().TimeLocalL().MinutesFrom(
+ entry.StartTimeL().TimeLocalL(), duration);
+ start = itemInfo.iTmpInstance->Time().TimeLocalL();
+ end = start + duration;
+#ifdef RD_CALEN_MIDNIGHT_VISUALIZATION
+ InsertStartTimeL(ptr, start, aCurrentDay);
+#else
+ LimitStartAndEndTime( aCurrentDay, start, end );
+
+ InsertTimeL(ptr, start);
+#endif // RD_CALEN_MIDNIGHT_VISUALIZATION
+ if (!AknLayoutUtils::LayoutMirrored())
+ {
+ ptr.Append(KDesSeparator);
+ }
+
+#ifdef RD_CALEN_MIDNIGHT_VISUALIZATION
+ InsertHyphenL(ptr, start, end);
+#else
+ InsertHyphen(ptr, start, end);
+#endif // RD_CALEN_MIDNIGHT_VISUALIZATION
+ if (AknLayoutUtils::LayoutMirrored())
+ {
+ ptr.Append(KDesSeparator);
+ }
+
+ ptr.Append(KDesSeparator);
+ }
+ else
+ // Set icons and times for entry
+ {
+ // non-timed notes
+ TBuf<3> icon;
+ icon.Num(
+ static_cast<TInt64> (iDayContainer->IconIndexFromEntryL(
+ entry, isAllDayEvent)));
+ // icon\t\t\t
+ // 0 1 2
+ // gfxA textA textB
+ ptr.Append(icon);
+ ptr.Append(KDesSeparator);
+ ptr.Append(KDesSeparator);
+ ptr.Append(KDesSeparator);
+ }
+
+ // textLines contain
+ CArrayFixFlat<TPtrC>* textLines = new (ELeave) CArrayFixFlat<
+ TPtrC> (5);
+ CleanupStack::PushL(textLines);
+
+ // After WrapTextL call, visualText contains wrapped text in
+ // memory buffer, textLines contain text pointers
+ // (into visualText memory buffer) of beginning of each line of text.
+ HBufC* visualText = WrapTextL(entry, *textLines);
+ CleanupStack::PushL(visualText);
+
+ // Put first line of text to current list line
+ if (textLines->Count())
+ {
+ ptr.Append(textLines->At(0));
+ }
+
+ TBool isEndDisplayed = ETrue;
+ // For subsequent text lines, we create separate list lines.
+ if ((end != start) && (!isAllDayEvent))
+ {
+ isEndDisplayed = EFalse;
+ }
+ for (TInt i(1); i < textLines->Count() || !isEndDisplayed; i++)
+ {
+ if (itemInfo.iTopLine == KIndexError)
+ {
+ itemInfo.iTopLine = iItemTextArray->Count();
+ }
+ iItemTextArray->AppendL(*listItemData);
+ ptr.Zero();
+ ptr.Append(KDesSeparator);
+ // Sets an end time in second line
+ if (!isEndDisplayed)
+ {
+ __ASSERT_ALWAYS( i == 1, User::Invariant() );
+
+#ifdef RD_CALEN_MIDNIGHT_VISUALIZATION
+ InsertEndTimeL(ptr, end, aCurrentDay);
+#else
+ InsertTimeL(ptr, end);
+#endif // RD_CALEN_MIDNIGHT_VISUALIZATION
+ isEndDisplayed = ETrue;
+ }
+ else
+ {
+ ptr.Append(KDesTimeSpace);
+ }
+ ptr.Append(KDesSeparator);
+ ptr.Append(KDesSeparator);
+ if (i < textLines->Count())
+ {
+ ptr.Append(textLines->At(i));
+ }
+ }
+
+ // end of last line (also for non-timed notes)
+ ptr.Append(KDesSeparator);
+
+ CleanupStack::PopAndDestroy(visualText);
+ CleanupStack::PopAndDestroy(textLines);
+
+ // Alarm, repeat and priority icons
+ iDayContainer->InsertAdditionalIconsL(entry,
+ KIconSeperatorFormat(), ptr);
+
+ // append created list item data to array of list items
+ aCellArray.AppendL(iItemTextArray->Count());
+
+ if (itemInfo.iTopLine == KIndexError)
+ {
+ itemInfo.iTopLine = iItemTextArray->Count();
+ }
+ iItemTextArray->AppendL(*listItemData);
+ }
+ }
+ CleanupStack::PopAndDestroy(listItemData);
+ CleanupStack::PopAndDestroy(&calendarInfoList);
+
+ TRACE_EXIT_POINT;
+ }
+
+#ifdef RD_CALEN_MIDNIGHT_VISUALIZATION
+void CCalenDayListBoxModel::InsertStartTimeL(TDes& aBuf,
+ const TTime& aStartTime,
+ const TTime& aCurrentDay)
+ {
+ TRACE_ENTRY_POINT;
+
+ TBuf<6> arrow;
+ TBuf<50> formattedStartTime;
+ TBool mirrored( AknLayoutUtils::LayoutMirrored() );
+
+ if(StartsBeforeFocusedDay(aStartTime, aCurrentDay))
+ {
+ arrow = GetArrowIndicator(mirrored);
+
+ // need to format end time acc.to 12hr or 24hr format
+ if(TimeFormat() == ETime24)
+ {
+ // 24 hour. show 00 only
+ InsertTimeL(formattedStartTime, aStartTime, EInsert00);
+ }
+ else
+ {
+ // 12 hour. show hh:mm am/pm
+ formattedStartTime = GetFormattedStartTimeL(aCurrentDay);
+ }
+ }
+ else
+ {
+ // meeting starts after 12:00 am on current day
+ // add start time as it is
+ InsertTimeL( formattedStartTime, aStartTime );
+ }
+
+ if(mirrored)
+ {
+ // For mirrored UI layouts:
+ aBuf.Append(formattedStartTime);
+ aBuf.Append(arrow);
+ }
+ else
+ {
+ // For western UI layouts:
+ aBuf.Append(arrow);
+ aBuf.Append(formattedStartTime);
+ }
+
+ TRACE_EXIT_POINT;
+ }
+
+TBool CCalenDayListBoxModel::StartsBeforeFocusedDay(const TTime& aStartTime,
+const TTime& aFocusedTime)
+ {
+ TRACE_ENTRY_POINT;
+
+ const TTime focusedDay12am = CalenDateUtils::BeginningOfDay(aFocusedTime);
+ if(aStartTime < focusedDay12am)
+ {
+ TRACE_EXIT_POINT;
+ return ETrue;
+ }
+
+ TRACE_EXIT_POINT;
+ return EFalse;
+ }
+
+TBool CCalenDayListBoxModel::EndsAfterFocusedDay(const TTime& aEndTime,
+const TTime& aFocusedTime)
+ {
+ TRACE_ENTRY_POINT;
+
+ const TTime nextDay12am = CalenDateUtils::BeginningOfDay(aFocusedTime)
+ + TTimeIntervalDays(1);
+
+ if(aEndTime >= nextDay12am)
+ {
+ TRACE_EXIT_POINT;
+ return ETrue;
+ }
+
+ TRACE_EXIT_POINT;
+ return EFalse;
+ }
+
+const TDesC& CCalenDayListBoxModel::GetArrowIndicator(const TBool aMirroredLayout)
+ {
+ TRACE_ENTRY_POINT;
+
+ if(aMirroredLayout)
+ {
+ // unicode leftwards arrow for right to left layouts
+ TRACE_EXIT_POINT;
+ return KUnicodeLeftwardsArrow;
+ }
+
+ // unicode rightwards arrow for left to right layouts
+ TRACE_EXIT_POINT;
+ return KUnicodeRightwardsArrow;
+ }
+
+const TDesC& CCalenDayListBoxModel::GetFormattedStartTimeL(const TTime& aFocusedTime)
+ {
+ TRACE_ENTRY_POINT;
+
+ iFormattedStartTime.Zero();
+ const TTime focusedDay12am = CalenDateUtils::BeginningOfDay(aFocusedTime);
+ InsertTimeL(iFormattedStartTime, focusedDay12am);
+
+ TRACE_EXIT_POINT;
+ return iFormattedStartTime;
+ }
+
+const TDesC& CCalenDayListBoxModel::GetFormattedEndTimeL(const TTime& aFocusedTime)
+ {
+ TRACE_ENTRY_POINT;
+
+ iFormattedEndTime.Zero();
+ const TTime focusedDay24hrs = CalenDateUtils::BeginningOfDay(aFocusedTime)
+ + TTimeIntervalDays(1);
+
+ InsertTimeL(iFormattedEndTime, focusedDay24hrs);
+
+ TRACE_EXIT_POINT;
+ return iFormattedEndTime;
+ }
+
+void CCalenDayListBoxModel::InsertEndTimeL(TDes& aBuf,
+ const TTime& aEndTime,
+ const TTime& aCurrentDay)
+ {
+ TRACE_ENTRY_POINT;
+
+ TBuf<6> arrow;
+ TBuf<50> formattedEndTime;
+ TBool mirrored( AknLayoutUtils::LayoutMirrored() );
+
+ if(EndsAfterFocusedDay(aEndTime, aCurrentDay))
+ {
+ arrow = GetArrowIndicator(mirrored);
+
+ // need to format end time acc.to 12hr or 24hr format
+ if(TimeFormat() == ETime24)
+ {
+ // 24 hour. show 24 only
+ InsertTimeL(formattedEndTime, aEndTime, EInsert24);
+ }
+ else
+ {
+ // 12 hour. show hh:mm am/pm
+ formattedEndTime = GetFormattedEndTimeL(aCurrentDay);
+ }
+ }
+ else
+ {
+ // meeting does not continue after 24:00 on current day
+ // add start time as it is
+ InsertTimeL( formattedEndTime, aEndTime );
+ }
+
+ if(mirrored)
+ {
+ // For Mirrored Layouts:
+ aBuf.Append(arrow);
+ aBuf.Append(formattedEndTime);
+ }
+ else
+ {
+ // For Western Layouts:
+ aBuf.Append(formattedEndTime);
+ aBuf.Append(arrow);
+ }
+
+ TRACE_EXIT_POINT;
+ }
+
+TTimeFormat CCalenDayListBoxModel::TimeFormat() const
+ {
+ TLocale locale;
+ return locale.TimeFormat();
+ }
+#endif // RD_CALEN_MIDNIGHT_VISUALIZATION
+
+
+// -----------------------------------------------------------------------------
+// CCalenDayListBoxModel::CalendarInfoIdentifierL
+// Searches for the index in calendar info list based on calendar file name
+// -----------------------------------------------------------------------------
+//
+TBool CCalenDayListBoxModel::CalendarInfoIdentifierL(
+ const HBufC* aName, const CCalCalendarInfo& aCalendarInfo)
+ {
+ TRACE_ENTRY_POINT;
+ TBool retVal = EFalse;
+ HBufC* calendarFileName = aCalendarInfo.FileNameL().AllocLC();
+ retVal = calendarFileName->CompareF(*aName);
+ CleanupStack::PopAndDestroy(calendarFileName);
+ TRACE_EXIT_POINT;
+ return (!retVal);
+ }
+
+// End of File
+