diff -r 12af337248b1 -r bd7edf625bdd calendarui/organizerplugin/aiagendaplugin2/src/aicalendarplugin2.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/calendarui/organizerplugin/aiagendaplugin2/src/aicalendarplugin2.cpp Wed Sep 01 12:32:31 2010 +0100 @@ -0,0 +1,1594 @@ +/* +* Copyright (c) 2005-2006 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: + * +*/ + +#include "aicalendarplugin2.h" +#include "aicalendarplugin2contentmodel.h" +#include "AIAgendaPluginEngineIf.h" +#include "aicalendarplugin2constantdata.h" +#include "aicalendarplugin2data.h" +#include "aicalendarplugin2constants.hrh" +#include "aicalendarplugin2uids.hrh" + +#include +#include +#include +#include +#include + +#include +#include +#include + +// CONSTANTS + +const TInt KAI2CurrentIconLoadSizeX = 40; +const TInt KAI2CurrentIconLoadSizeY = 40; + +const TInt KAI2InternalIdForNoEvents = -357; +const TInt KAI2InternalIdForNoMoreEvents = -38; +const TInt KAI2InternalIdForNextEvent = -44; +const TInt KAI2InternalIdForNextEvents = -45; +const TInt KAI2InternalIdForNextEventTomorrow = -762; + +enum TAi2CalIcons + { + // Lets be explicit to maintain readability + KAi2IconCalendar = 0, + KAi2MeetingIcon, // 1 + KAi2Memo, // 2 + KAi2Anniversary, // 3 + KAi2UncompeledTodo // 4 + }; + +_LIT( KResourceDrive, "z:" ); +_LIT( KCalendarBitmapFile, "calendar.mif" ); +_LIT( KAIPluginIconBitmapFile, "aicalendarplugin2.mif" ); +_LIT( KCalendarResourceFile, "calendar.rsc" ); +_LIT( KAIPluginTextsResourceFileName, "aicalendarplugin2res.rsc"); + +_LIT16( KHexPrefix16, "0x" ); + + +TInt ParseInt + ( TInt32& aValue, const TDesC16& aStringValue ) + { + const TInt pos = aStringValue.FindF( KHexPrefix16 ); + if (pos != KErrNotFound) + { + TLex16 lex( aStringValue.Mid( pos + KHexPrefix16().Length() ) ); + // Hex parsing needs unsigned int + TUint32 value = 0; + const TInt parseResult = lex.Val( value, EHex ); + if ( parseResult == KErrNone ) + { + aValue = value; + } + return parseResult; + } + else + { + TLex16 lex( aStringValue ); + return lex.Val(aValue); + } + } + +TInt GetTimedItemLineNeed( + RPointerArray& /*aArray*/, + TInt /*aArrayOffset*/ ) + { + // Multiline cale + return 1; + } + +TInt GetTimedArrayLineNeed( + RPointerArray& aArray, TInt aSpaceTaken ) + { + // Multiline cale + return aArray.Count() * aSpaceTaken; + } + +TInt CalculateStartIndexBackwards( + RPointerArray& aArray, + TInt aLinesAvailable, + TInt spaceUse, + TBool aHasPriority ) + { + TInt i = aArray.Count() - 1; + TInt totalSpace = 0; + for( ; i >= 0; --i ) + { + if( totalSpace + spaceUse >= aLinesAvailable ) + { + if( totalSpace + spaceUse > aLinesAvailable ) + { + ++i; + } + break; + } + totalSpace += spaceUse; + } + if( i >= aArray.Count() ) + { + i = aArray.Count() - 1; + } + else if( ( ( i < 0 ) && aHasPriority ) ||// <- if there is little space left only priority item are + // fitted to the screen + ( aLinesAvailable > aArray.Count() ) )// <- if theres lot of space, make sure to fit us too + { + i = 0; + } + return i; + } + +// Provide a key pair value table for ECOM. +// Used to identify the correct construction function for the requested interface. +const TImplementationProxy ImplementationTable[] = + { + IMPLEMENTATION_PROXY_ENTRY( AI_UID_ECOM_IMPLEMENTATION_CONTENTPUBLISHER_CALENDARPLUGIN, + CAICalendarPlugin2::NewL ) + }; + +// ============================ MEMBER FUNCTIONS =============================== + +CAICalendarPlugin2* CAICalendarPlugin2::NewL() + { + CAICalendarPlugin2* self = new( ELeave )CAICalendarPlugin2; + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop( self ); + return self; + } + +CAICalendarPlugin2::CAICalendarPlugin2() + : iActualLinesInUse( KAICal2DefaultActualLines ), + iNonTimedItemReservation( KAICal2DefaultItemReservation ) + { + } + +void CAICalendarPlugin2::ConstructL() + { + if( !iCalendarResourceFileOffset ) + { + TFileName resFile; + resFile.Append( KResourceDrive ); + resFile.Append( KDC_APP_RESOURCE_DIR ); + resFile.Append( KCalendarResourceFile ); + BaflUtils::NearestLanguageFile( CCoeEnv::Static()->FsSession(), resFile ); + iCalendarResourceFileOffset = CCoeEnv::Static()->AddResourceFileL( resFile ); + } + + if( !iTextResourceFileOffset ) + { + TFileName resFile; + resFile.Append( KResourceDrive ); + resFile.Append( KDC_RESOURCE_FILES_DIR ); + resFile.Append( KAIPluginTextsResourceFileName ); + BaflUtils::NearestLanguageFile( CCoeEnv::Static()->FsSession(), resFile ); + iTextResourceFileOffset = CCoeEnv::Static()->AddResourceFileL( resFile ); + } + + iCalendarIconFileName = HBufC::NewL( KResourceDrive().Length() + + KDC_APP_BITMAP_DIR().Length() + + KCalendarBitmapFile().Length() ); + iCalendarIconFileName->Des().Append( KResourceDrive ); + iCalendarIconFileName->Des().Append( KDC_APP_BITMAP_DIR ); + iCalendarIconFileName->Des().Append( KCalendarBitmapFile ); + + iPluginIconFileName = HBufC::NewL( KResourceDrive().Length() + + KDC_APP_BITMAP_DIR().Length() + + KAIPluginIconBitmapFile().Length() ); + iPluginIconFileName->Des().Append( KResourceDrive ); + iPluginIconFileName->Des().Append( KDC_APP_BITMAP_DIR ); + iPluginIconFileName->Des().Append( KAIPluginIconBitmapFile ); + + iConstantData = CAICalendarPlugin2ConstantData::NewL(); + iEventData = CAICalendarPlugin2Data::NewL(); + iStrParser = AiUtility::CreateStrParserL(); + } + +CAICalendarPlugin2::~CAICalendarPlugin2() + { + if( iCalendarResourceFileOffset ) + { + CCoeEnv::Static()->DeleteResourceFile( iCalendarResourceFileOffset ); + } + if( iTextResourceFileOffset ) + { + CCoeEnv::Static()->DeleteResourceFile( iTextResourceFileOffset ); + } + delete iEngine; + delete iEventData; + delete iConstantData; + Release( iStrParser ); + + iBitmaps.ResetAndDestroy(); + iMasks.ResetAndDestroy(); + + delete iPluginIconFileName; + delete iCalendarIconFileName; + iPublishedDataStore.Reset(); + iNewCollectedDataStore.Reset(); + delete iPrevUid; + } + +void CAICalendarPlugin2::CreateBitmapSkinnedIconL( const TAknsItemID& aSkinIconId, + const TDesC& aFilename, + TInt aNormalIconId, + TInt aNormalMaskId, + CFbsBitmap*& aBitmap, + CFbsBitmap*& aMask ) + { + AknsUtils::CreateIconLC( AknsUtils::SkinInstance(), + aSkinIconId, + aBitmap, + aMask, + aFilename, + aNormalIconId, + aNormalMaskId ); + + CleanupStack::Pop( 2 ); // bitmap, mask, cant use pop param here, we dont know + // the push order of the CreateIconLC + } + +void CAICalendarPlugin2::CreateIconsL(void) + { + CFbsBitmap* bitmap; + CFbsBitmap* mask; + iBitmaps.ResetAndDestroy(); + iMasks.ResetAndDestroy(); + + TSize iconSize( TSize( KAI2CurrentIconLoadSizeX, + KAI2CurrentIconLoadSizeY ) ); + /** + * Creation order!: + * Calendar icon + * Meeting icon + * Note icon + * Anniversary icon + * Uncompleted to-do icon + * + **/ + CreateBitmapSkinnedIconL( KAknsIIDQgnIndiAiCale, + *iPluginIconFileName, + EMbmAicalendarplugin2Qgn_indi_ai_cale, + EMbmAicalendarplugin2Qgn_indi_ai_cale_mask, + bitmap, mask ); + + // These bitmaps are permanently owned by arrays here. + // Only duplicates are provided to system, are they can + // do whatever they want to them. + User::LeaveIfError( iBitmaps.Append( bitmap ) ); + User::LeaveIfError( iMasks.Append( mask ) ); + User::LeaveIfError( + AknIconUtils::SetSize( bitmap, iconSize ) ); + + CreateBitmapSkinnedIconL( KAknsIIDQgnIndiCdrMeeting, + *iCalendarIconFileName, + EMbmCalendarQgn_indi_cdr_meeting, + EMbmCalendarQgn_indi_cdr_meeting_mask, + bitmap, mask ); + User::LeaveIfError( iBitmaps.Append( bitmap ) ); + User::LeaveIfError( iMasks.Append( mask ) ); + User::LeaveIfError( + AknIconUtils::SetSize( bitmap, iconSize ) ); + + CreateBitmapSkinnedIconL( KAknsIIDQgnIndiCdrReminder, + *iCalendarIconFileName, + EMbmCalendarQgn_indi_cdr_reminder, + EMbmCalendarQgn_indi_cdr_reminder_mask, + bitmap, mask ); + User::LeaveIfError( iBitmaps.Append( bitmap ) ); + User::LeaveIfError( iMasks.Append( mask ) ); + User::LeaveIfError( + AknIconUtils::SetSize( bitmap, iconSize ) ); + + CreateBitmapSkinnedIconL( KAknsIIDQgnIndiCdrBirthday, + *iCalendarIconFileName, + EMbmCalendarQgn_indi_cdr_birthday, + EMbmCalendarQgn_indi_cdr_birthday_mask, + bitmap, mask ); + User::LeaveIfError( iBitmaps.Append( bitmap ) ); + User::LeaveIfError( iMasks.Append( mask ) ); + User::LeaveIfError( + AknIconUtils::SetSize( bitmap, iconSize ) ); + + CreateBitmapSkinnedIconL( KAknsIIDQgnPropTodoUndone, + *iCalendarIconFileName, + EMbmCalendarQgn_indi_cdr_todo, + EMbmCalendarQgn_indi_cdr_todo_mask, + bitmap, mask ); + User::LeaveIfError( iBitmaps.Append( bitmap ) ); + User::LeaveIfError( iMasks.Append( mask ) ); + User::LeaveIfError( + AknIconUtils::SetSize( bitmap, iconSize ) ); + + iBitmaps.Compress(); + iMasks.Compress(); + } + +void CAICalendarPlugin2::Resume( TResumeReason aReason ) + { + TRAP_IGNORE( DoResumeL( aReason ) ); + } + +void CAICalendarPlugin2::DoResumeL( TResumeReason aReason ) + { + if( aReason == EForeground ) + { + if( !iEngine ) + { + iEngine = CAIAgendaPluginEngineIf::NewL( *this, ECalendarAndTodoObserver ); + } + else + { + iEngine->Refresh(); + } + } + } + +void CAICalendarPlugin2::Suspend( TSuspendReason aReason ) + { + if ( aReason == EGeneralThemeChange ) + { + // Reset for republishing. Especially icons! + iPublishedDataStore.Reset(); + } + } + +void CAICalendarPlugin2::Start( TStartReason /*aReason*/ ) + { + } + +void CAICalendarPlugin2::Stop( TStopReason /*aReason*/ ) + { + delete iEngine; + iEngine = NULL; + iPublishedDataStore.Reset(); + } + +void CAICalendarPlugin2::SubscribeL( MAiContentObserver& aObserver ) + { + iEventData->AppendObserverL( aObserver ); + } + +void CAICalendarPlugin2::ConfigureL( RAiSettingsItemArray& aSettings ) + { + // Receive the settings for this plugin from the user(theme or similar). + // There are four settings we need for the current implementation to work + // properly: + // + // 1) total item count of the UI = EPluginEventItemCount + // + // 2) the vertical space taken by timed item (relative to the size of non timed item) + // = EPluginTimedEventLineCount + // + // 3) the vertical space taken by non timed item (relative to the size of timed item) + // = EPluginNonTimedEventLineCount + // + // 4) the amount of lines we reserve for non timed events if many timed and non timed + // events are present = EPluginNonTimedReservedItems + // + // In the current 2.6.2006 specification for example (Navibar theme), we have non timed items + // half the vertical size of timed items. Timed items take 2 lines visible space and + // non timed take 1 line of visible space. We need to able to show at maximum 6 + // non timed items, so we need total 6 items (1 line items). As timed items take + // 2 lines we can fit three of them in to the view (no setting need/can be calculated) + // as stated in the specification. If many timed and non timed calendar events are + // present we always reserve 2 times for non timed events. + // So the setting to satisfy the UI spec of the "Navibar UI" are 6, 2, 1, 2 + // + // + for( TInt i = 0; i < aSettings.Count(); ++i ) + { + MAiPluginSettingsItem& item = (aSettings[i])->AiPluginSettingsItem(); + TInt32 value = 0; + if( ParseInt( value, item.Value() ) != KErrNone ) + { + continue; + } + if( value < 0 ) + { + continue; + } + + if( item.Key() == EPluginEventItemCount ) + { + iActualLinesInUse = value; + continue; + } + else if( item.Key() == EPluginTimedEventLineCount ) + { + iEventData->SetSpaceTakenByTimedEvent( value ); + continue; + } + else if( item.Key() == EPluginNonTimedEventLineCount ) + { + iEventData->SetSpaceTakenByNonTimedEvent( value ); + continue; + } + else if( item.Key() == EPluginNonTimedReservedItems ) + { + iNonTimedItemReservation = value; + continue; + } + else if( item.Key() == EPluginAppendEndTimeToOngoingItems ) + { + iConstantData->iAppendEndTimeToOngoingItems = value; + continue; + } + else if( item.Key() == EPluginUseAlternatePublishForUpcomingAndOngoingItems ) + { + iConstantData->iUseAlternatePublish = value; + continue; + } + else if( item.Key() == EPluginOpenInViewerOrEditor ) + { + iConstantData->iOpenInViewer = !value; + continue; + } + else if( item.Key() == EPluginDaysToHandleAsNotToday ) + { + iConstantData->iDaysToHandleAsNotToday = value; + continue; + } + else if( item.Key() == EPluginOpenFirstValidOnIndexZero ) + { + iConstantData->iOpenFirstValid = value; + continue; + } + else if ( item.Key() == EPluginPublishInfoWithAlternateId ) + { + iConstantData->iUseAlternateInfoPublish = value; + continue; + } + + } + // Last op, free array and items + aSettings.ResetAndDestroy(); + } + +TAny* CAICalendarPlugin2::GetProperty( TProperty aProperty ) + { + TAny* result( NULL ); + + TRAP_IGNORE( result = iConstantData->GetPropertyL( aProperty ) ); + + return result; + } + + +void CAICalendarPlugin2::HandleEvent( TInt aEvent, const TDesC& aParam ) + { + if( aEvent == EAICalendarPlugin2EventItemSelected ) + { + TInt32 index = 0; + if( ParseInt( index, aParam ) != KErrNone ) + { + return; + } + + // Other "out of bounds" checked inside launch method. + if( index > iActualLinesInUse ) + { + // invalid index + return; + } + iEventData->LaunchCalendarApplication( index, iConstantData->iOpenFirstValid ); + } + } + +void CAICalendarPlugin2::PluginDataChanged( + const RPointerArray& aEntryArray, + TBool aHadEvents ) + { + iEventData->SetHadExpiredEvents( aHadEvents ); + + iEventData->ClearDataArrays(); + + TRAP_IGNORE( + FillDataArraysL( aEntryArray ); + PublishDataArraysL(); + ); + } + +void CAICalendarPlugin2::FillDataArraysL( + const RPointerArray& aEntryArray ) + { + /** + * [uses icon y/n] time formatting | subject and location formatting + * + * [Y] 13:05-14:00 subject, location... // normal day event + * [Y] 00:00-08:00 subject, location... // event starting yesterday + * [Y] 19:00-23:59 subject, location... // event ends tomorrow + * [Y] 16:50-16:50 subject, location... // event with no duration + * [Y] 25/8/04 16:00- subject... // normal not today event + * [Y] subject... // normal non timed event + * [Y] 25/8/04 subject... // not today non timed event + * 26.10.2006 Tuomas Karjagin: - all item now will use icons + * - end time removed from normal not today. + **/ + + // extract new data from CAgnEntry objects + TInt daynoteIndex = 0; // to insert day notes in correct order... + delete iPrevUid; + iPrevUid = NULL; + + for( TInt eventArrayIndex = 0, count = aEntryArray.Count(); + eventArrayIndex < count; + eventArrayIndex++ ) + { + CAiCalendarPlugin2EventItem* eventItem = CAiCalendarPlugin2EventItem::NewL( + *aEntryArray[eventArrayIndex], + *iConstantData ); + CleanupStack::PushL( eventItem ); + + // Multiple-day Todos contain multiple eventItems + // Showing only one and deleting the rest + if ( ( iPrevUid ) && ( eventItem->Type() == EPluginItemToDo ) + && ( iPrevUid->Compare( *( eventItem->iUid ) ) == 0 ) ) + { + CleanupStack::PopAndDestroy( eventItem ); + } + else + { + delete iPrevUid; + iPrevUid = NULL; + iPrevUid = eventItem->iUid->AllocL(); + + // Append item ot correct array, method increments daynoteIndex if required + if( iEventData->AppendItemToCorrectArray( *eventItem, + daynoteIndex ) != KErrNone ) + { + // Append not allowed, destroy item and proceed + CleanupStack::PopAndDestroy( eventItem ); + } + else + { + // Item accepted and ownership transferred + CleanupStack::Pop( eventItem ); + } + } + } + delete iPrevUid; + iPrevUid = NULL; + iEventData->SortArrayByTime( iEventData->FutureItemArray() ); + iEventData->SortArrayByTime( iEventData->TomorrowEventArray() ); + } + + +void CAICalendarPlugin2::PublishDataArraysL() + { + + // We publish only to the first registered observer. + // If needed edit the publishing helper function to + // publish to all. + if( iEventData->ObserverArray().Count() <= 0 ) + { + // If no observers registered, return immediate + iEventData->ClearDataArrays(); + return; + } + iCurrentObserver = (iEventData->ObserverArray())[0]; + iCurrentObserver->StartTransaction( reinterpret_cast(this) ); + iNewCollectedDataStore.Reset(); + iNewCollectedDataStore.Append( 0 ); // always append the not used zero + // this because publishes start from 1 + // so we dont need to -1 everywhere + + /************************************************************************** + * Current publish order description, based on the Active Idle UI spec + * + * Last update date: 19/09/2006, UI Spec date 08/09/2006 + * + * --- Last change item was to swap 3 and 4. Pre calculation part is + * --- no longer required but left in the code so that they can be restored + * --- just by moving the for loop again, no other changes required. + * + * Sections are accordingly numbered in the code below: + * + * 0) Publish "No (more calendar) events for today" if no (more) + * events today. + * + * 1) If there are on going meetings/appointments and extra room for these + * after all non timer and upcoming meetings have been published, + * publish as many on going events as fits in to the view. These + * are only published if there is left over space = low priority. + * + * 2) Publish as many timed events for today as fits in to view, but + * reserve space for todays non timed event if any. Reserve as many + * lines as is in the spec, currently up to 2 lines are reserved. + * These are top priority items. + * + * 3) Publish non timed event for today. Use all space left from 1), 2) + * and 3) if necessary. These are top priority items. + * + * 4) These are only published if there is left over space = low priority. + * + * 5) Publish empty content to the rest of the items. + * + * NOTES: Care must be taken when changes are made to this system. + * Extensive testing recommended when making even the smallest + * change. + * + **************************************************************************/ + + TInt lineUsage = 0; + TInt publishIndex = 1; // publishes start from 1, because 0 is "reserved" + // according to spec! maybe to.do: add a setting for this. + const TInt cstSpaceTakenByTimed = iEventData->SpaceTakenByTimedEvent(); + const TInt cstSpaceTakenByNonTimed = iEventData->SpaceTakenByNonTimedEvent(); + + // SPACE VALUES INCLUDES CONSIDERATION TO 1 line - 2 lines space reservation + const TInt cstTotalNonTimedTodaySpace = iEventData->NonTimedEventArray().Count() * + cstSpaceTakenByNonTimed; + + const TInt cstMinLinesForTodayNonTimed = Min( cstTotalNonTimedTodaySpace, + iNonTimedItemReservation * + cstSpaceTakenByNonTimed ); + + + // Simplify total today item count, calculate it ready here + const TInt cstTotalTimedTodayItemCount = iEventData->TotalTimedTodayItemCount(); + + RArray& focusDataArray = iEventData->FocusDataArray(); + focusDataArray.Reset(); + + // First item always occupied by title line. + TAiCalendarFocusData titleFocusItem; + titleFocusItem.iType = EAI2CalOpenToday; + focusDataArray.Append( titleFocusItem ); + + TBool cleanInfo = ETrue; + // The "+ 1" in "lineUsage + 1" + // and "upcoming2HrsIndex + nonTimedIndex + futureTimedIndex + futureNonTimedIndex + ongoingIndex + ongoing30Index + upcomingIndex + nonCalendarEventItemIndex + 1" + // derives from the fact that we do not publish to index 0 + // it is specified as reserved. + + /** + * 0) + */ + if( iEventData->TotalTodayItemCount() == 0 && + iEventData->LongOngoingArray().Count() == 0 ) + { + // hadExpiredEvents tells us if we had any events today, when + // there are no upcoming event for today. Then we can choose + // proper text to display. + + Clean( EAICalendarPlugin2EventSubject, lineUsage + 1 ); + Clean( EAICalendarPlugin2EventLocation, lineUsage + 1 ); + Clean( EAICalendarPlugin2EventTimeStart, lineUsage + 1 ); + Clean( EAICalendarPlugin2EventTimeEnd, lineUsage + 1 ); + Clean( EAICalendarPlugin2EventTextSecondLine, lineUsage + 1 ); + Clean( EAICalendarPlugin2TimeStartAndSubject, lineUsage + 1 ); + + if( ( iEventData->TomorrowEventArray().Count() > 0 ) && + ( iConstantData->iDaysToHandleAsNotToday == KAIRangeTomorrowOnly ) ) + { + if ( !iConstantData->iUseAlternateInfoPublish ) + { + CleanInfo(); + } + TTime eventTime = (iEventData->TomorrowEventArray())[0]->Time(); + // display "Next event tomorrow:" + if( !( CompareChecksums( publishIndex, + KAI2InternalIdForNextEventTomorrow ) ) ) + { + PublishIconL( EAICalendarPlugin2NoEventsForToday, publishIndex ); + iCurrentObserver->Publish( *this, + EAICalendarPlugin2EventTextFirstLine, + EAICalendarPlugin2NextEventTomorrow, + lineUsage + 1 ); // Text line 1 + iCurrentObserver->Publish( *this, + EAICalendarPlugin2EventSubject, + EAICalendarPlugin2NextEventTomorrow, + lineUsage + 1 ); // Text line 1 + iCurrentObserver->Publish( *this, + EAICalendarPlugin2TimeStartAndSubject, + EAICalendarPlugin2NextEventTomorrow, + lineUsage + 1 ); // Text line 1 + } + ++lineUsage; + ++publishIndex; + + TAiCalendarFocusData focusItem; + focusItem.iType = EAI2CalOpenOnEventDay; + focusItem.iEntryTime = eventTime; + focusDataArray.Append( focusItem ); + } + else if( ( ( iEventData->NotTodayItemArray().Count() > 0 ) && + ( iConstantData->iDaysToHandleAsNotToday > 0 ) ) || + ( ( iEventData->TomorrowEventArray().Count() > 0 ) && + ( iConstantData->iDaysToHandleAsNotToday > KAIRangeTomorrowOnly ) ) ) + { + if ( !iConstantData->iUseAlternateInfoPublish ) + { + CleanInfo(); + } + TTime eventTime; + if( iEventData->TomorrowEventArray().Count() > 0 ) + { + eventTime = (iEventData->TomorrowEventArray())[0]->Time(); + } + else + { + eventTime = (iEventData->NotTodayItemArray())[0]->Time(); + } + + // display "Next event(s):" + if( iEventData->NotTodayItemArray().Count() == 1 ) + { + if( !( CompareChecksums( publishIndex, + KAI2InternalIdForNextEvent ) ) ) + { + PublishIconL( EAICalendarPlugin2NoEventsForToday, publishIndex ); + iCurrentObserver->Publish( *this, + EAICalendarPlugin2EventTextFirstLine, + EAICalendarPlugin2NextEvent, + lineUsage + 1 ); // Text line 1 + iCurrentObserver->Publish( *this, + EAICalendarPlugin2EventSubject, + EAICalendarPlugin2NextEvent, + lineUsage + 1 ); // Text line 1 + iCurrentObserver->Publish( *this, + EAICalendarPlugin2TimeStartAndSubject, + EAICalendarPlugin2NextEvent, + lineUsage + 1 ); // Text line 1 + } + } + else + { + if( !( CompareChecksums( publishIndex, + KAI2InternalIdForNextEvents ) ) ) + { + PublishIconL( EAICalendarPlugin2NoEventsForToday, publishIndex ); + iCurrentObserver->Publish( *this, + EAICalendarPlugin2EventTextFirstLine, + EAICalendarPlugin2NextEvents, + lineUsage + 1 ); // Text line 1 + iCurrentObserver->Publish( *this, + EAICalendarPlugin2EventSubject, + EAICalendarPlugin2NextEvents, + lineUsage + 1 ); // Text line 1 + iCurrentObserver->Publish( *this, + EAICalendarPlugin2TimeStartAndSubject, + EAICalendarPlugin2NextEvents, + lineUsage + 1 ); // Text line 1 + } + } + ++lineUsage; + ++publishIndex; + + TAiCalendarFocusData focusItem; + focusItem.iType = EAI2CalOpenOnEventDay; + focusItem.iEntryTime = eventTime; + focusDataArray.Append( focusItem ); + } + else if( ( iEventData->FutureItemArray().Count() > 0 ) || + ( ( iEventData->TomorrowEventArray().Count() > 0 ) && + ( iConstantData->iDaysToHandleAsNotToday == 0 ) ) ) + { + if ( !iConstantData->iUseAlternateInfoPublish ) + { + CleanInfo(); + } + CAiCalendarPlugin2EventItem* item = NULL; + if( ( iEventData->TomorrowEventArray().Count() > 0 ) && + ( iConstantData->iDaysToHandleAsNotToday == 0 ) ) + { + item = (iEventData->TomorrowEventArray())[0]; + } + else + { + item = (iEventData->FutureItemArray())[0]; + } + + TTime eventTime = item->Time(); + const TDesC& nextOn = iConstantData->MakeEventOnL(eventTime); + + if( !( CompareChecksums( 0, item->CreateChecksumFromString( nextOn ) ) ) ) + { + // this change publish next event information to calendar info text instead of calendar entry text + // some languages needs two rows for publishing + cleanInfo = EFalse; + // display "Next event on: [day of the week] [date]" + + PublishIconL( EAICalendarPlugin2NoEventsForToday, publishIndex); + + iCurrentObserver->Publish( *this, EAICalendarPlugin2TimeStartAndSubject, nextOn, publishIndex); + + } + ++lineUsage; + ++publishIndex; + + TAiCalendarFocusData focusItem; + focusItem.iType = EAI2CalOpenOnEventDay; + focusItem.iEntryTime = eventTime; + focusDataArray.Append( focusItem ); + + PublishFutureItemsForArrayL( + iEventData->TomorrowEventArray(), + publishIndex, // reference passed and updated inside + lineUsage, // reference passed and updated inside + iActualLinesInUse); + + + PublishFutureItemsForArrayL( + iEventData->FutureItemArray(), + publishIndex, // reference passed and updated inside + lineUsage, // reference passed and updated inside + iActualLinesInUse); + + // 5) Clean the rest + + for( ; publishIndex <= iActualLinesInUse; ++publishIndex ) + { + CleanAll( publishIndex ); + + TAiCalendarFocusData focusItem2; + focusItem2.iType = EAI2CalOpenToday; + focusDataArray.Append( focusItem2 ); + } + + if( ( iPublishedDataStore.Count() == 0 ) || + ( iPublishedDataStore.Count() != iNewCollectedDataStore.Count() ) ) + { + iPublishedDataStore.Reset(); + for( TInt i = 0; i < iNewCollectedDataStore.Count(); ++i ) + { + iPublishedDataStore.Append( iNewCollectedDataStore[i] ); + } + iCurrentObserver->Commit( reinterpret_cast(this) ); + } + else + { + iCurrentObserver->CancelTransaction( reinterpret_cast(this) ); + } + + iEventData->ClearDataArrays(); + return; + } + else if( !iConstantData->iUseAlternatePublish ) + { + if ( iConstantData->iUseAlternateInfoPublish ) + { + Clean( EAICalendarPlugin2EventTextFirstLine, lineUsage + 1 ); + Clean( EAICalendarPlugin2TimeStartAndSubject, lineUsage + 1 ); + } + else + { + CleanInfo(); + } + // display ""No Calendar events for today or next 7 days" + // or "No more Calendar events for today or next 7 days" + if( !iEventData->HadExpiredEvents() ) + { + if( !( CompareChecksums( publishIndex, + KAI2InternalIdForNoMoreEvents ) ) ) + { + if( !iConstantData->iUseAlternateInfoPublish ) + { + PublishIconL( EAICalendarPlugin2NoEventsForToday, + publishIndex ); + iCurrentObserver->Publish( *this, + EAICalendarPlugin2EventTextFirstLine, + EAICalendarPlugin2NoEventsForToday, + lineUsage + 1 ); // Text line 1 + iCurrentObserver->Publish( *this, + EAICalendarPlugin2EventSubject, + EAICalendarPlugin2NoEventsForToday, + lineUsage + 1 ); // Text line 1 + } + // In case theme instructs us we need to publish the status + // texts and icons to a different location + else + { + cleanInfo = EFalse; + PublishIconL( EAICalendarPlugin2NoEventsForToday, + 0, + EAICalendarPlugin2InfoIcon); + iCurrentObserver->Publish( *this, + EAICalendarPlugin2InfoText, + EAICalendarPlugin2NoEventsForToday, + 0); // Text line 1 + } + } + } + else + { + if( !( CompareChecksums( publishIndex, + KAI2InternalIdForNoEvents ) ) ) + { + if( !iConstantData->iUseAlternateInfoPublish ) + { + PublishIconL( EAICalendarPlugin2NoEventsForToday, publishIndex ); + iCurrentObserver->Publish( *this, + EAICalendarPlugin2EventTextFirstLine, + EAICalendarPlugin2NoMoreEventsForToday, + lineUsage + 1 ); // Text line 1 + iCurrentObserver->Publish( *this, + EAICalendarPlugin2EventSubject, + EAICalendarPlugin2NoMoreEventsForToday, + lineUsage + 1 ); // Text line 1 + } + // In case theme instructs us we need to publish the status + // texts and icons to a different location + else + { + cleanInfo = EFalse; + PublishIconL( EAICalendarPlugin2NoEventsForToday, + 0, + EAICalendarPlugin2InfoIcon); + iCurrentObserver->Publish( *this, + EAICalendarPlugin2InfoText, + EAICalendarPlugin2NoMoreEventsForToday, + 0 ); // Text line 1 + } + } + } + ++lineUsage; + ++publishIndex; + + TAiCalendarFocusData focusItem; + focusItem.iType = EAI2CalOpenToday; + focusDataArray.Append( focusItem ); + } + } + + const TInt cstMaxLinesForTimedEvents = + ( iActualLinesInUse - cstMinLinesForTodayNonTimed ); + + /** + * -1) Really old ongoing timed events need full set of info. + */ + const TInt cstLinesReserved3 = + GetTimedArrayLineNeed( iEventData->Upcoming2HrsArray(), iEventData->SpaceTakenByTimedEvent() ) + + GetTimedArrayLineNeed( iEventData->Ongoing30MinArray(), iEventData->SpaceTakenByTimedEvent() ) + + GetTimedArrayLineNeed( iEventData->UpcomingArray(), iEventData->SpaceTakenByTimedEvent() ) + + GetTimedArrayLineNeed( iEventData->OngoingArray(), iEventData->SpaceTakenByTimedEvent() ) + + cstTotalNonTimedTodaySpace; + const TInt startIndex3 = CalculateStartIndexBackwards( + iEventData->LongOngoingArray(), + iActualLinesInUse - cstLinesReserved3, + ( iConstantData->iUseAlternatePublish ? + 1 :iEventData->SpaceTakenByTimedEvent() ), + EFalse ); + if( startIndex3 >= 0 ) + { + PublishTodayTimedItemsForArrayL( + iEventData->LongOngoingArray(), + publishIndex, // reference passed and updated inside + lineUsage, // reference passed and updated inside + cstMaxLinesForTimedEvents, + startIndex3, + cstLinesReserved3 ); + } + + /** + * 1) Ongoing today timed events need full set of info. + */ + const TInt cstLinesReserved = + GetTimedArrayLineNeed( iEventData->Upcoming2HrsArray(), iEventData->SpaceTakenByTimedEvent() ) + + GetTimedArrayLineNeed( iEventData->Ongoing30MinArray(), iEventData->SpaceTakenByTimedEvent() ) + + GetTimedArrayLineNeed( iEventData->UpcomingArray(), iEventData->SpaceTakenByTimedEvent() ) + + cstTotalNonTimedTodaySpace; + const TInt startIndex = CalculateStartIndexBackwards( + iEventData->OngoingArray(), + iActualLinesInUse - cstLinesReserved, + ( iConstantData->iUseAlternatePublish ? + 1 :iEventData->SpaceTakenByTimedEvent() ), + ETrue ); + + if( startIndex >= 0 ) + { + PublishTodayTimedItemsForArrayL( + iEventData->OngoingArray(), + publishIndex, // reference passed and updated inside + lineUsage, // reference passed and updated inside + cstMaxLinesForTimedEvents, + startIndex, + cstLinesReserved ); + } + + /** + * Ongoing not older than 30min today timed events. + */ + const TInt cstLinesReserved2 = + GetTimedArrayLineNeed( iEventData->Upcoming2HrsArray(), iEventData->SpaceTakenByTimedEvent() ) + + cstMinLinesForTodayNonTimed; + const TInt startIndex2 = CalculateStartIndexBackwards( + iEventData->Ongoing30MinArray(), + iActualLinesInUse - cstLinesReserved2, + iEventData->SpaceTakenByTimedEvent() , + ETrue ); + + if( startIndex2 >= 0 ) + { + PublishTodayTimedItemsForArrayL( + iEventData->Ongoing30MinArray(), + publishIndex, // reference passed and updated inside + lineUsage, // reference passed and updated inside + cstMaxLinesForTimedEvents, + startIndex2, + cstLinesReserved2 ); + } + + /** + * Upcoming today timed events. + */ + PublishTodayTimedItemsForArrayL( + iEventData->Upcoming2HrsArray(), + publishIndex, // reference passed and updated inside + lineUsage, // reference passed and updated inside + cstMaxLinesForTimedEvents ); + + PublishTodayTimedItemsForArrayL( + iEventData->UpcomingArray(), + publishIndex, // reference passed and updated inside + lineUsage, // reference passed and updated inside + cstMaxLinesForTimedEvents ); + + /** + * 3) Non timed events only need combined icon and subject/location string. + * Other fields are cleaned. + */ + for( TInt nonTimedIndex = 0; ( nonTimedIndex < iEventData->NonTimedEventArray().Count() ) && + ( lineUsage + cstSpaceTakenByNonTimed <= iActualLinesInUse ) + ; ++nonTimedIndex ) + { + if( !( CompareChecksums( publishIndex, + iEventData->NonTimedEventArray()[nonTimedIndex]->Checksum() ) ) ) + { + PublishIconL( iEventData->NonTimedEventArray()[nonTimedIndex]->IconId(), publishIndex ); + + Clean( EAICalendarPlugin2EventTextSecondLine, publishIndex ); + + PublishNonTimedEventTexts( *iEventData->NonTimedEventArray()[nonTimedIndex], + publishIndex ); + } + lineUsage += cstSpaceTakenByNonTimed; + ++publishIndex; + focusDataArray.Append( iEventData->NonTimedEventArray()[nonTimedIndex]->FocusData() ); + } + + if( iConstantData->iDaysToHandleAsNotToday > 0 ) + { + /** + * 4) Future items + */ + PublishFutureItemsForArrayL( + iEventData->TomorrowEventArray(), + publishIndex, // reference passed and updated inside + lineUsage, // reference passed and updated inside + iActualLinesInUse); + + PublishFutureItemsForArrayL( + iEventData->NotTodayItemArray(), + publishIndex, // reference passed and updated inside + lineUsage, // reference passed and updated inside + iActualLinesInUse); + } + + /** + * 5) Clean the rest + */ + for( ; publishIndex <= iActualLinesInUse; ++publishIndex ) + { + CleanAll( publishIndex ); + + TAiCalendarFocusData focusItem; + focusItem.iType = EAI2CalOpenToday; + focusDataArray.Append( focusItem ); + } + + if ( cleanInfo ) + { + CleanInfo(); + } + + if( ( iPublishedDataStore.Count() == 0 ) || + ( iPublishedDataStore.Count() != iNewCollectedDataStore.Count() ) ) + { + iPublishedDataStore.Reset(); + for( TInt i = 0; i < iNewCollectedDataStore.Count(); ++i ) + { + iPublishedDataStore.Append( iNewCollectedDataStore[i] ); + } + iCurrentObserver->Commit( reinterpret_cast(this) ); + } + else + { + iCurrentObserver->CancelTransaction( reinterpret_cast(this) ); + } + + iEventData->ClearDataArrays(); + + } + +void CAICalendarPlugin2::PublishTodayTimedItemsForArrayL( + RPointerArray& aArray, + TInt& aPublishIndex, + TInt& aLineUsage, + TInt aMaxLinesAvailable, + TInt aArrayOffset, + TInt aExtraLineReservation ) + { + TInt spaceTakenByNext = GetTimedItemLineNeed( aArray, aArrayOffset ); + if( ( ( &aArray == &iEventData->OngoingArray() ) && !iConstantData->iUseAlternatePublish ) || + &aArray == &iEventData->Ongoing30MinArray() ) + { + spaceTakenByNext =iEventData->SpaceTakenByTimedEvent(); + } + TInt spaceTaken = aLineUsage; + TInt index = 0; + for( ; ( ( index + aArrayOffset ) < aArray.Count() ) && + ( ( iActualLinesInUse - ( aExtraLineReservation + spaceTakenByNext + spaceTaken ) ) >= 0 ) && + ( ( aLineUsage + spaceTakenByNext ) <= aMaxLinesAvailable ) + ; ++index ) + { + const TInt pbIndex = index + aArrayOffset; + + if( !( CompareChecksums( aPublishIndex, aArray[index]->Checksum(), ETrue ) ) ) + { + PublishIconL( aArray[pbIndex]->IconId(), aPublishIndex ); + } + + if( aArray[pbIndex]->Type() == EPluginItemOlderOnGoingEvent && + iConstantData->iUseAlternatePublish ) + { + if( !( CompareChecksums( aPublishIndex, aArray[index]->Checksum() ) ) ) + { + iCurrentObserver->Clean( *this, + EAICalendarPlugin2EventTextSecondLine, + aPublishIndex ); + + PublishTimedEventTexts( *aArray[pbIndex], aPublishIndex, aLineUsage ); + } + else + { + // increase line usage only + aLineUsage += spaceTakenByNext; + } + } + else + { + if( !( CompareChecksums( aPublishIndex, aArray[index]->Checksum() ) ) ) + { + iCurrentObserver->Clean( *this, + EAICalendarPlugin2EventTextFirstLine, + aPublishIndex ); + + PublishTimeRelatedTexts( *aArray[pbIndex], aPublishIndex, aLineUsage ); + } + else + { + // increase line usage only + aLineUsage += spaceTakenByNext; + } + } + + ++aPublishIndex; + iEventData->FocusDataArray().Append( aArray[pbIndex]->FocusData() ); + spaceTaken += spaceTakenByNext; + if( ( ( &aArray == &iEventData->OngoingArray() ) && !iConstantData->iUseAlternatePublish ) || + &aArray == &iEventData->Ongoing30MinArray() ) + { + spaceTakenByNext =iEventData->SpaceTakenByTimedEvent(); + } + else + { + spaceTakenByNext = GetTimedItemLineNeed( aArray, pbIndex + 1 ); + } + } + } + +void CAICalendarPlugin2::PublishFutureItemsForArrayL( + RPointerArray& aArray, + TInt& aPublishIndex, + TInt& aLineUsage, + TInt aMaxLinesAvailable ) + { + TInt index = 0; + + TInt spaceTakenByNext = GetTimedItemLineNeed( aArray, index ); + + for( ; ( index < aArray.Count() ) + ; ++index ) + { + if( !( ( aLineUsage + spaceTakenByNext ) <= aMaxLinesAvailable ) ) + { + spaceTakenByNext = GetTimedItemLineNeed( aArray, index + 1 ); + continue; + } + if( !( CompareChecksums( aPublishIndex, aArray[index]->Checksum(), ETrue ) ) ) + { + PublishIconL( aArray[index]->IconId(), aPublishIndex ); + } + + if( aArray[index]->Type() == EPluginItemMeeting && iConstantData->iUseAlternatePublish ) + { + if( !( CompareChecksums( aPublishIndex, aArray[index]->Checksum() ) ) ) + { + iCurrentObserver->Clean( *this, + EAICalendarPlugin2EventTextSecondLine, + aPublishIndex ); + + PublishTimedEventTexts( *aArray[index], aPublishIndex, aLineUsage ); + } + else + { + // increase line usage only + aLineUsage += spaceTakenByNext; + } + } + else if( aArray[index]->Type() == EPluginItemMeeting ) + { + if( !( CompareChecksums( aPublishIndex, aArray[index]->Checksum() ) ) ) + { + PublishTimeRelatedTexts( *aArray[index], aPublishIndex, aLineUsage ); + } + else + { + // increase line usage only + aLineUsage += spaceTakenByNext; + } + } + else + { + if( !( CompareChecksums( aPublishIndex, aArray[index]->Checksum() ) ) ) + { + Clean( EAICalendarPlugin2EventTextSecondLine, aPublishIndex ); + + PublishNonTimedEventTexts( *aArray[index], + aPublishIndex ); + } + // increase line usage + aLineUsage += iEventData->SpaceTakenByNonTimedEvent(); + } + + ++aPublishIndex; + + iEventData->FocusDataArray().Append( aArray[index]->FocusData() ); + spaceTakenByNext = GetTimedItemLineNeed( aArray, index + 1 ); + } + + } + + +void CAICalendarPlugin2::CleanAll( TInt aIndex ) + { + CleanTimeRelated( aIndex ); + CleanTexts( aIndex ); + CleanIcon( aIndex ); + } + +void CAICalendarPlugin2::CleanTimeRelated( TInt aIndex ) + { + iCurrentObserver->Clean( *this, + EAICalendarPlugin2EventTextFirstLine, + aIndex ); + iCurrentObserver->Clean( *this, + EAICalendarPlugin2EventTimeStart, + aIndex ); + iCurrentObserver->Clean( *this, + EAICalendarPlugin2EventTimeEnd, + aIndex ); + iCurrentObserver->Clean( *this, + EAICalendarPlugin2TimeStartAndSubject, + aIndex); + } + +void CAICalendarPlugin2::CleanTexts( TInt aIndex ) + { + iCurrentObserver->Clean( *this, + EAICalendarPlugin2EventTextSecondLine, + aIndex ); + iCurrentObserver->Clean( *this, + EAICalendarPlugin2EventSubject, + aIndex ); + iCurrentObserver->Clean( *this, + EAICalendarPlugin2EventLocation, + aIndex ); + iCurrentObserver->Clean( *this, + EAICalendarPlugin2TimeStartAndSubject, + aIndex); + } + +void CAICalendarPlugin2::CleanIcon( TInt aIndex ) + { + iCurrentObserver->Clean( *this, + EAICalendarPlugin2EventIcon, + aIndex ); + } + +void CAICalendarPlugin2::Clean( TInt aItem, TInt aIndex ) + { + iCurrentObserver->Clean( *this, + aItem, + aIndex ); + } + +void CAICalendarPlugin2::CleanInfo() + { + iCurrentObserver->Clean( *this, + EAICalendarPlugin2InfoText, + 0); + + iCurrentObserver->Clean( *this, + EAICalendarPlugin2InfoIcon, + 0); + } + +void CAICalendarPlugin2::PublishTimedEventTexts( CAiCalendarPlugin2EventItem& aData, + TInt aIndex, + TInt& aLineUsage ) + { + // here the first line - second line mix is intentional. see below comment + if( aData.FirstLineText() != KNullDesC ) + { + iCurrentObserver->Publish( *this, + EAICalendarPlugin2EventTextFirstLine, + aData.FirstLineText(), + aIndex ); + ++aLineUsage; + } + else + { + iCurrentObserver->Clean( *this, + EAICalendarPlugin2EventTextFirstLine, + aIndex ); + } + + // Separate field publishes + iCurrentObserver->Publish( *this, + EAICalendarPlugin2EventTimeStart, + aData.StartTimeText(), + aIndex ); + iCurrentObserver->Publish( *this, + EAICalendarPlugin2EventTimeEnd, + aData.EndTimeText(), + aIndex ); + iCurrentObserver->Publish( *this, + EAICalendarPlugin2EventSubject, + aData.SubjectText(), + aIndex ); + iCurrentObserver->Publish( *this, + EAICalendarPlugin2EventLocation, + aData.LocationText(), + aIndex ); + iCurrentObserver->Publish( *this, + EAICalendarPlugin2TimeStartAndSubject, + aData.SubjectTimeString( ETrue ), + aIndex); + } + +void CAICalendarPlugin2::PublishNonTimedEventTexts( CAiCalendarPlugin2EventItem& aData, + TInt aIndex ) + { + // here the first line - second line mix is intentional. see above comment + iCurrentObserver->Publish( *this, + EAICalendarPlugin2EventTextFirstLine, + aData.SecondLineText(), + aIndex ); + + // Separate field publishes + if( aData.StartTimeText().Length() > 0 ) + { + iCurrentObserver->Publish( *this, + EAICalendarPlugin2EventTimeStart, + aData.StartTimeText(), + aIndex ); + } + else + { + Clean( EAICalendarPlugin2EventTimeStart, aIndex ); + } + if( aData.EndTimeText().Length() > 0 ) + { + iCurrentObserver->Publish( *this, + EAICalendarPlugin2EventTimeEnd, + aData.EndTimeText(), + aIndex ); + } + else + { + Clean( EAICalendarPlugin2EventTimeEnd, aIndex ); + } + iCurrentObserver->Publish( *this, + EAICalendarPlugin2EventSubject, + aData.SubjectText(), + aIndex ); + iCurrentObserver->Publish( *this, + EAICalendarPlugin2EventLocation, + aData.LocationText(), + aIndex ); + + iCurrentObserver->Publish( *this, + EAICalendarPlugin2TimeStartAndSubject, + aData.SubjectTimeString( ETrue ), + aIndex ); + } + +void CAICalendarPlugin2::PublishTimeRelatedTexts( CAiCalendarPlugin2EventItem& aData, + TInt aIndex, + TInt& aLineUsage ) + { + // here the first line - second line mix is intentional. see above comments + if( aData.SecondLineText() != KNullDesC ) + { + iCurrentObserver->Publish( *this, + EAICalendarPlugin2EventTextSecondLine, + aData.SecondLineText(), + aIndex ); + ++aLineUsage; + } + else if( aData.FirstLineText() != KNullDesC ) + { + iCurrentObserver->Publish( *this, + EAICalendarPlugin2EventTextSecondLine, + aData.FirstLineText(), + aIndex ); + ++aLineUsage; + } + else + { + iCurrentObserver->Clean( *this, + EAICalendarPlugin2EventTextSecondLine, + aIndex ); + } + + // Separate field publishes + iCurrentObserver->Publish( *this, + EAICalendarPlugin2EventTimeStart, + aData.StartTimeText(), + aIndex ); + iCurrentObserver->Publish( *this, + EAICalendarPlugin2EventTimeEnd, + aData.EndTimeText(), + aIndex ); + iCurrentObserver->Publish( *this, + EAICalendarPlugin2EventSubject, + aData.SubjectText(), + aIndex ); + iCurrentObserver->Publish( *this, + EAICalendarPlugin2EventLocation, + aData.LocationText(), + aIndex ); + + iCurrentObserver->Publish( *this, + EAICalendarPlugin2TimeStartAndSubject, + aData.SubjectTimeString( ETrue ), + aIndex ); + } + +void CAICalendarPlugin2::PublishIconL( const TInt aIconId, TInt aIndex, TInt aContent ) + { + CGulIcon* icon = NULL; + CFbsBitmap* bitmap3 = NULL; + CFbsBitmap* mask3 = NULL; + TAknsItemID skinIconId; + + HBufC* bitmapFile = iCalendarIconFileName; + + TInt bitmapId = 0; + TInt maskId = 0; + + // Map events to MBM id's and load from correct file + switch( aIconId ) + { + case EAICalendarPlugin2IconAppt: + case EAICalendarPlugin2IconMeetingAccepted: + case EAICalendarPlugin2IconMeetingNotAnswered: + case EAICalendarPlugin2IconMeetingTentative: + { + skinIconId.Set( KAknsIIDQgnIndiCdrMeeting ); + bitmapId = EMbmCalendarQgn_indi_cdr_meeting; + maskId = EMbmCalendarQgn_indi_cdr_meeting_mask; + break; + } + case EAICalendarPlugin2IconTodo: // Uncompleted To-Do icon + { + skinIconId.Set( KAknsIIDQgnIndiCdrTodo ); + bitmapId = EMbmCalendarQgn_indi_cdr_todo; + maskId = EMbmCalendarQgn_indi_cdr_todo_mask; + break; + } + case EAICalendarPlugin2IconMemo: // Memo icon + { + skinIconId.Set( KAknsIIDQgnIndiCdrReminder ); + bitmapId = EMbmCalendarQgn_indi_cdr_reminder; + maskId = EMbmCalendarQgn_indi_cdr_reminder_mask; + break; + } + case EAICalendarPlugin2IconAnniv: // Anniversary icon + { + skinIconId.Set( KAknsIIDQgnIndiCdrBirthday ); + bitmapId = EMbmCalendarQgn_indi_cdr_birthday; + maskId = EMbmCalendarQgn_indi_cdr_birthday_mask; + break; + } + case EAICalendarPlugin2NoMoreEventsForToday: + case EAICalendarPlugin2NoEventsForToday: + { + skinIconId.Set( KAknsIIDQgnIndiAiCale ); + bitmapId = EMbmAicalendarplugin2Qgn_indi_ai_cale; + maskId = EMbmAicalendarplugin2Qgn_indi_ai_cale_mask; + bitmapFile = iPluginIconFileName; + break; + } + default: + { + return; + } + } + + CreateBitmapSkinnedIconL( skinIconId, + *bitmapFile, + bitmapId, + maskId, + bitmap3, mask3 ); + + // icon will own the bitmaps + CleanupStack::PushL( bitmap3 ); + CleanupStack::PushL( mask3 ); + icon = CGulIcon::NewL( bitmap3, mask3 ); + CleanupStack::Pop( 2, bitmap3 ); + + TInt err = iCurrentObserver->PublishPtr( *this, + aContent, + icon, + aIndex ); + if( err != KErrNone ) + { + delete icon; + } + } + +void CAICalendarPlugin2::PublishIconL( const TInt aIconId, TInt aIndex ) + { + PublishIconL( aIconId, aIndex, EAICalendarPlugin2EventIcon ); + } + +TBool CAICalendarPlugin2::CompareChecksums( + TInt aChecksumIndex, + TInt aItemChecksum, + TBool aIsIcon ) + { + if( !aIsIcon ) + { + iNewCollectedDataStore.Append( aItemChecksum ); + } + if( ( iPublishedDataStore.Count() > aChecksumIndex ) && + ( iPublishedDataStore[aChecksumIndex] == aItemChecksum ) ) + { + // checksum match + return ETrue; + } + iPublishedDataStore.Reset(); + return EFalse; + } + +// ======== GLOBAL FUNCTIONS ======== + +// Return an instance of the proxy table. + +EXPORT_C const TImplementationProxy* ImplementationGroupProxy( TInt& aTableCount ) + { + aTableCount = sizeof( ImplementationTable ) / sizeof( TImplementationProxy ); + return ImplementationTable; + } + +// End of File