diff -r 000000000000 -r f979ecb2b13e calendarui/views/src/calendaylistboxmodel.cpp --- /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 // Calendar commands +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include // TCalenInstanceId +#include +#include +#include "CalendarVariant.hrh" +#ifdef RD_CALEN_MIDNIGHT_VISUALIZATION +#include +#endif // RD_CALEN_MIDNIGHT_VISUALIZATION +#include +#include + +//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 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& 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* lineWidths = new( ELeave )CArrayFixFlat( 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& aLayoutTable, + CArrayFixFlat& aCellArray, + MCalenServices& aServices, + /*CCalInstanceView* aInstanceView*/ + TTime aCurrentDay) + { + TRACE_ENTRY_POINT; + + iItemTextArray->Reset(); + TBool isAllDayEvent; + RPointerArray 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 (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* 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 +