diff -r 000000000000 -r e686773b3f54 phonebookengines/contactsmodel/cntsrv/src/CViewSubSessions.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/phonebookengines/contactsmodel/cntsrv/src/CViewSubSessions.cpp Tue Feb 02 10:12:17 2010 +0200 @@ -0,0 +1,1135 @@ +// Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// + +/** + @file + @internalComponent + @released +*/ + + +#include "cntviewprivate.h" +#include "CViewSubSessions.h" +#include "CCntIpcCodes.h" +#include "CCntDbManager.h" +#include "CCntServer.h" +#include +#include "CCntLogger.h" +#include "CCntStateMachine.h" + + +extern void DebugLogViewNotification(const TDesC& aMethod, const TContactViewEvent& aEvent); + + +CViewSubSessionQueue::CViewSubSessionQueue() + { + } + + +CViewSubSessionQueue::~CViewSubSessionQueue() + { + iEvents.Close(); + } + + +void CViewSubSessionQueue::QueueEvent(const TContactViewEvent& aEvent) + { + const TInt KInvalidValueForRemoteView = -1; + + TBool haveToAddEventInQueue = ETrue; + + if (iRequestPending) + { + if(aEvent.iEventType == TContactViewEvent::EItemAdded) + { + // is this first event sent? If yes and if the event is an + // EItemAdded event send first a fake event. + // This is because all EItemAdded should be sorted before send them + + TContactViewEvent event; + event.iEventType = TContactViewEvent::EItemAdded; + event.iContactId = KInvalidValueForRemoteView; + event.iInt = KInvalidValueForRemoteView; + SendEventL(event); + } + else + { + SendEventL(aEvent); + haveToAddEventInQueue = EFalse; + } + } + + if (haveToAddEventInQueue && !iQueueError) + { + // There are two requirements for this queue of events: + // 1. The iInt values for events in the Q at any given point in time + // should match the index of the underlying localview array. i.e If the addition/removal + // of a contact has caused the position of other contacts items to change in the underlying localview + // then previous events sent by them in this Q will have old iInt values and these need to be corrected. + + // 2. When the client gets these events in order, it should have a valid view after every event, + // ie. if we have 2 additions, at positions 0 and 1, + // we cannot send the event for addition at position 1 before the addition at position 0. + // + // These requirements are fulfilled using the following algorithm. + // Events are inserted in the queue using following two condition + // 1. EItemAdded - + // 1.1 Find if an existing EItemAdded events iInt is greater or equal with incoming events iInt. + // if found,insert event before the found one and increment the iInt of the rest event by 1 + // 1.2 if no match is found with same iInt, modify its iInt value with incoming events iInt, + // then append to the event queue. + // 1.3 If no EItemAdded events are in queue, append this one to Queue. + // 2. EItemRemoved - + // 2.1 Find if an existing EItemAdded events iInt matches with incoming EItemRemoved events iInt. + // if found, then remove that EItemAdded event from the Queue and decrement rest of the + // events iInt by 1. + // 2.2 if no match is found with same iInt, then insert the event before next greater iInt event + // and then decerement the iInt value of rest of the event by 1. + // 2.3 if no events greater than this then append this one to Queue. + + TContactViewEvent event; + event.iEventType = aEvent.iEventType; + event.iContactId = aEvent.iContactId; + event.iInt = aEvent.iInt; + TInt eventsCount = iEvents.Count(); + TUint pos=0; + if( event.iEventType == TContactViewEvent::EItemAdded ) + { + TInt lastItemRemovedPosition = KErrNotFound; + //first check if this add event is not generated by a contact item change + for( pos=0; pos= aEvent.iInt && + iEvents[pos].iContactId != aEvent.iContactId) + { + if( iEvents[pos].iEventType == TContactViewEvent::EItemRemoved || iEvents[pos].iEventType == TContactViewEvent::EItemAdded) + { + iEvents[pos].iInt++; + } + } + } + iQueueError = iEvents.Insert(aEvent, lastItemRemovedPosition); + } + else + { + iQueueError = iEvents.Append(aEvent); + } + } + else + { + TBool haveToAppendEvent = ETrue; + for( pos=0; pos= event.iInt) + { + iQueueError = iEvents.Insert(event, pos); + eventsCount=iEvents.Count(); + for(TUint loop=pos+1; loopQ:"), event); + } + } + + +void CViewSubSessionQueue::RequestEvent(const RMessage2& aMessage) + { + __ASSERT_DEBUG(!iRequestPending,User::Leave(KErrAlreadyExists)); // can only leave in debug mode + if (!iRequestPending) + { + iMessage=aMessage; + iRequestPending=ETrue; + if (iQueueError) + { + TContactViewEvent errorEvent(TContactViewEvent::EServerError,iQueueError); + iQueueError=KErrNone; + SendEventL(errorEvent); + } + else if (iEvents.Count()>0) + { + SendEventL(iEvents[0]); + iEvents.Remove(0); + } + } + } + + +void CViewSubSessionQueue::CancelEventRequest() + { + if (iRequestPending) + { + iMessage.Complete(KErrCancel); + iRequestPending=EFalse; + } + } + +/** +Send contact view event. + +@leave KErrNotFound In debug mode only, if there is a queue error. +@leave KErrNotReady In debug mode only, if there is already an existing request still pending. +@leave KErrBadDescriptor If there is a error writing aEvent to the RMessage2 to be sent. +*/ +void CViewSubSessionQueue::SendEventL(const TContactViewEvent& aEvent) + { + __ASSERT_DEBUG(!iQueueError,User::Leave(KErrNotFound)); + + if (!iRequestPending) + { + return; + } + + DEBUG_PRINTVN2(__VERBOSE_DEBUG__,_L("[CNTMODEL] CViewSubSessionQueue::SendEventL(): Q->:"), aEvent); + + TRAPD(err,iMessage.WriteL(KSlot0,TPckgC(aEvent))); + if (err) + { + iRequestPending=EFalse; + User::Leave(KErrBadDescriptor);//iMessage is completed in CCntSession::ServiceError() + } + else + { + iMessage.Complete(KErrNone); + } + + iRequestPending=EFalse; + } + + +/** +Called if derived class ServiceL()'s do not consume the opcode. +*/ +TInt CViewSubSessionBase::ServiceL(const RMessage2& aMessage) + { + TInt reply(KErrNone); + switch (aMessage.Function()) + { + case ECntViewCount: + CountL(aMessage); + break; + case ECntViewAt: + reply=AtL(aMessage); + break; + case ECntViewContactAtLength: + reply=ContactAtLengthL(aMessage); + break; + case ECntViewContactAt: + ContactAtL(aMessage); + break; + case ECntViewFind: + FindL(aMessage); + break; + case ECntAllFieldsLength: + reply=GetAllFieldsLengthL(aMessage); + break; + case ECntAllFieldsText: + GetAllFieldsTextL(aMessage); + break; + case ECntContactMatchingCriteriaExternalizedSize: + ContactMatchingCriteriaExternalizedSizeL(aMessage); + break; + case ECntGetContactMatchingCriteria: + GetContactMatchingCriteriaL(aMessage); + break; + case ECntGetIncludedTypes: + GetIncludedTypesL(aMessage); + break; + case ECntRequestViewEvent: + RequestViewEvent(aMessage); + reply=KErrNoComplete; + break; + case ECntCancelRequestViewEvent: + CancelRequestViewEvent(); + break; + case ECntGetContactIds: + GetContactIdsL(aMessage); + break; + case ECntSendPluginUidToServer: + SendPluginUidToServer(aMessage); + break; + case ECntGetContactsMatchingFilter: + GetContactsMatchingFilterL(aMessage); + break; + case ECntGetSortPluginUidFromServer: + GetSortPluginUidFromServerL(aMessage); + break; + default: + User::Leave(KErrNotFound); + break; + } + return reply; + } + + +CViewSubSessionBase::~CViewSubSessionBase() + { + delete iQueue; + delete iSortableText; + delete iContact; + DeleteFindContacts(); + } + + +CViewSubSessionBase::CViewSubSessionBase(CViewManager& aViewManager) : iViewManager(aViewManager),iContact(0) + { + } + + +void CViewSubSessionBase::ConstructL() + { + iQueue = new(ELeave) CViewSubSessionQueue(); + } + + +void CViewSubSessionBase::CountL(const RMessage2& aMessage) const + { + TPckgBuf pckg(iView->CountL()); + aMessage.WriteL(0,pckg); + } + + +TInt CViewSubSessionBase::AtL(const RMessage2& aMessage) const + { + TInt reply = KErrNone; + const TInt index=aMessage.Int0(); + __ASSERT_ALWAYS(index>=0,User::Leave(KErrUnderflow)); + if(!(indexCountL())) + { + // Index is out of bounds. + reply=KErrNotFound; + return reply; + } + TPckgBuf pckg(iView->AtL(index)); + aMessage.WriteL(1,pckg); + return reply; + } + + +void CViewSubSessionBase::ContactAtL(const RMessage2& aMessage) const + { + const TInt externalizedSize=iContact->ExternalizedSize(); + HBufC8* buf=HBufC8::NewLC(externalizedSize); + TPtr8 bufPtr(buf->Des()); + RDesWriteStream writeStream(bufPtr); + CleanupClosePushL(writeStream); + writeStream << *iContact; + bufPtr.SetLength(externalizedSize); + aMessage.WriteL(0,*buf); + CleanupStack::PopAndDestroy(2); // writeStream, buf. + } + + +/** +Return the size of the externalized contact data. + +@param aMessage.Int0() Index. +@param aMessage.Ptr1() Package buffer to return size. +*/ +TInt CViewSubSessionBase::ContactAtLengthL(const RMessage2& aMessage) + { + TInt reply=KErrNone; + TInt index = aMessage.Int0(); + + __ASSERT_ALWAYS(index>=0,User::Leave(KErrUnderflow)); + + if(!(indexCountL())) + { + // Index is out of bounds. + reply=KErrNotFound; + return reply; + } + + const CViewContact& contact=iView->ContactAtL(index); + + delete iContact; + iContact=NULL; + iContact = CViewContact::NewL(contact); + + //Always keep server side local view in memory saving mode, so we + //change the view contact object stored in iView into lightweight object + const_cast(contact).ChangeToLightweightObject(); + + const TInt externalizedSize=iContact->ExternalizedSize(); + TPckgBuf pckg(externalizedSize); + aMessage.WriteL(1,pckg); + + return reply; + } + + +void CViewSubSessionBase::GetIncludedTypesL(const RMessage2& aMessage) + { + TPckgBuf pckg(iView->ContactViewPreferences()); + aMessage.WriteL(0,pckg); + } + + +void CViewSubSessionBase::DeleteFindContacts() + { + iContacts.ResetAndDestroy(); + } + + +#ifdef _DEBUG +void CViewSubSessionBase::HandleContactViewEvent(const CContactViewBase& aView,const TContactViewEvent& aEvent) +#else +void CViewSubSessionBase::HandleContactViewEvent(const CContactViewBase& /*aView*/,const TContactViewEvent& aEvent) +#endif + { + ASSERT(&aView==iView); + iQueue->QueueEvent(aEvent); + } + + +/** +Match an array of search strings against the contacts in the view. + +The descriptor from the client contains a flag at the start to indicate if a +prefix or substring search has been requested. + +@param aMessage.Ptr0() Size of contact data to read (to client). +@param aMessage.Int1() Size of descriptor (from client). +@param aMessage.Ptr2() Descriptor (from client). +*/ +void CViewSubSessionBase::ContactMatchingCriteriaExternalizedSizeL(const RMessage2& aMessage) + { + TPckgBuf size; + aMessage.ReadL(1,size); + const TInt bufferSize = size(); + + // Restore buffer. + CBufFlat* buffer = CBufFlat::NewL(bufferSize); + CleanupStack::PushL(buffer); + buffer->ExpandL(0,bufferSize); + TPtr8 des(buffer->Ptr(0)); + aMessage.ReadL(2,des); + + // Internalize the data from the stream. + RBufReadStream readStream(*buffer); + CleanupClosePushL(readStream); + + TBool prefixSearch = readStream.ReadUint32L(); + const TInt numFindWords = readStream.ReadUint32L(); + CPtrC16Array* findDesArray = new(ELeave) CPtrC16Array(numFindWords); + CleanupStack::PushL(findDesArray); + + TInt findWordLength=0; + for (TInt i=0; iAppendL(*findword); + } + + DeleteFindContacts(); + + if (prefixSearch) + iView->ContactsMatchingPrefixL(*findDesArray,iContacts); + else + iView->ContactsMatchingCriteriaL(*findDesArray,iContacts); + + findDesArray->Reset(); + + CleanupStack::PopAndDestroy(numFindWords); + CleanupStack::PopAndDestroy(3, buffer); + + // Compute contacts externalized size. + const TInt contactsCount = iContacts.Count(); + TInt contactsExternalizedSize=0; + contactsExternalizedSize+=sizeof(TInt32); + for (TInt jj=0;jjExternalizedSize(); + } + + TPckgBuf pckg(contactsExternalizedSize); + aMessage.WriteL(0,pckg); + } + + +/** +Write matching contacts back to client. + +@param aMessage.Ptr0() Descriptor to write array of matching contacts. +*/ +void CViewSubSessionBase::GetContactMatchingCriteriaL(const RMessage2& aMessage) + { + // Compute contacts externalized size. + const TInt contactsCount = iContacts.Count(); + TInt contactsExternalizedSize=0; + contactsExternalizedSize+=sizeof(TInt32); + for (TInt jj=0;jjExternalizedSize(); + } + + HBufC8* buf=HBufC8::NewLC(contactsExternalizedSize); + TPtr8 bufPtr(buf->Des()); + RDesWriteStream writeStream(bufPtr); + CleanupClosePushL(writeStream); + + writeStream.WriteUint32L(contactsCount); + for (TInt ii=0;ii pckg(iView->FindL(aMessage.Int0())); + aMessage.WriteL(1,pckg); + } + + +TInt CViewSubSessionBase::GetAllFieldsLengthL(const RMessage2& aMessage) + { + TInt reply = KErrNone; + TInt index = aMessage.Int0(); + + __ASSERT_ALWAYS(index>=0,User::Leave(KErrUnderflow)); + + if(!(indexCountL())) + { + // Index is out of bounds. + reply=KErrNotFound; + return reply; + } + + TBuf<256> bufPtr;// = buf->Des(); + aMessage.ReadL(1,bufPtr); + + // Create sortable text from all fields of view contact at specified index. + delete iSortableText; + iSortableText=NULL; + HBufC* allfields=iView->AllFieldsLC(index,bufPtr); + CleanupStack::Pop(); // allfields + iSortableText=allfields; + + TPckgBuf pckg(iSortableText->Length()); + aMessage.WriteL(2,pckg); + + return reply; + } + + +void CViewSubSessionBase::GetAllFieldsTextL(const RMessage2& aMessage) + { + TPtrC8 narrowPtr((TUint8*)iSortableText->Ptr(),iSortableText->Size()); + aMessage.WriteL(0,narrowPtr); + } + + +void CViewSubSessionBase::RequestViewEvent(const RMessage2& aMessage) + { + iQueue->RequestEvent(aMessage); + } + + +void CViewSubSessionBase::CancelRequestViewEvent() + { + iQueue->CancelEventRequest(); + } + + +/** +Provides conversion between view indexes and contact IDs. + +@param aMessage.Int0() Buffer size (from client). +@param aMessage.Ptr1() Descriptor containing indices (from client). +@param aMessage.Ptr2() Descriptor containing contact IDs (to client). +*/ +void CViewSubSessionBase::GetContactIdsL(const RMessage2& aMessage) + { + TPckgBuf size; + aMessage.ReadL(0,size); + const TInt bufferSize = size(); + + CBufFlat* buffer = CBufFlat::NewL(bufferSize); + CleanupStack::PushL(buffer); + buffer->ExpandL(0,bufferSize); + TPtr8 des(buffer->Ptr(0)); + aMessage.ReadL(1,des); + + RBufReadStream readStream(*buffer); + CleanupClosePushL(readStream); + const TInt count = readStream.ReadUint32L(); + + CArrayFixFlat* indexes = new(ELeave) CArrayFixFlat(8); + CleanupStack::PushL(indexes); + + for (TInt i=0; iAppendL(index); + } + + CContactIdArray* array = CContactIdArray::NewLC(); + iView->GetContactIdsL(*indexes, *array); + + HBufC8* buf=HBufC8::NewLC(bufferSize); + TPtr8 bufPtr(buf->Des()); + RDesWriteStream writeStream(bufPtr); + CleanupClosePushL(writeStream); + writeStream << *array; + bufPtr.SetLength(bufferSize); + aMessage.WriteL(2,*buf); + + CleanupStack::PopAndDestroy(6, buffer); // &writeStream, buf, array, indexes, &readStream, buffer + } + + +void CViewSubSessionBase::SendPluginUidToServer(const RMessage2& aMessage) + { + TUid uid; + uid.iUid = aMessage.Int0(); + iView->SetViewFindConfigPlugin(uid); + } + + +/** +Filter server-side view based on filter supplied by client. The IDs of matching +contact items are externalized to the client-side. + +@param aMessage.Int0() Filter (from client). +@param aMessage.Ptr1() Descriptor containing matching contact IDs (to client). +*/ +void CViewSubSessionBase::GetContactsMatchingFilterL(const RMessage2& aMessage) + { + const TInt filter(aMessage.Int0()); + + RArray array; + CleanupClosePushL(array); + TContactIdWithMapping idMap; + + // Filter view contacts. + const TInt viewCount(iView->CountL()); + for (TInt i=0;iContactAtL(i); + if(contact.ContactMatchesFilter(filter)) + { + idMap.iId=contact.Id(); + idMap.iMapping=i; + User::LeaveIfError(array.Append(idMap)); + } + } + + // Externalize array to client. + const TInt count(array.Count()); + const TInt maxBufSize = (1+(array.Count()*2))*sizeof(TInt); + HBufC8* buf=HBufC8::NewLC(maxBufSize); + TPtr8 bufPtr(buf->Des()); + RDesWriteStream writeStream(bufPtr); + CleanupClosePushL(writeStream); + writeStream.WriteUint32L(count); + for (TInt j=0; jGetViewSortPluginImplUid(); + TPckgBuf pckg(uid.iUid); + aMessage.WriteL(0,pckg); + } + + +CViewSubSession* CViewSubSession::NewL(CViewManager& aViewManager,const RMessage2& aMessage) + { + CViewSubSession* self=new(ELeave) CViewSubSession(aViewManager); + CleanupClosePushL (*self); + self->ConstructL(aMessage); + CleanupStack::Pop(); // self. + return self; + } + + +/** +Attempt to consume opcode. If the opcode is not consumed then the base class +ServiceL() is called. +*/ +TInt CViewSubSession::ServiceL(const RMessage2& aMessage) + { + switch (aMessage.Function()) + { + case ECntViewSortOrderExternalizedSize: + ExternalizedSortOrderSizeL(aMessage); + break; + case ECntGetViewSortOrder: + GetSortOrderL(aMessage); + break; + default: + return CViewSubSessionBase::ServiceL(aMessage); + } + return 0; + } + + +CViewSubSession::~CViewSubSession() + { + iViewManager.CloseView(View(),*this); + } + + +CViewSubSession::CViewSubSession(CViewManager& aViewManager) : CViewSubSessionBase(aViewManager) + { + } + + +void CViewSubSession::ConstructL(const RMessage2& aMessage) + { + CViewSubSessionBase::ConstructL(); + + RContactViewSortOrder sortOrder; + CleanupClosePushL(sortOrder); + TContactViewPreferences contactsToInclude; + + TUid sortPluginImplUid; + HBufC8* sortPluginName = UnpackageSortOrderAndPluginDetailsLC(aMessage,sortOrder,contactsToInclude,sortPluginImplUid); + + iView = &iViewManager.OpenViewL(sortOrder,*this,contactsToInclude,sortPluginImplUid,*sortPluginName); + + CleanupStack::PopAndDestroy(2, &sortOrder); // sortPluginName, sortOrder + } + + +void CViewSubSession::UnpackageSortOrderL(const RMessage2& aMessage,RContactViewSortOrder& aSortOrder,TContactViewPreferences& aContactTypes) const + { + HBufC8* buf=HBufC8::NewLC(aMessage.Int0()); + + TPtr8 bufPtr(buf->Des()); + aMessage.ReadL(1,bufPtr); + RDesReadStream readStream(bufPtr); + CleanupClosePushL(readStream); + + readStream >> (TInt32&)aContactTypes; + readStream >> aSortOrder; + + CleanupStack::PopAndDestroy(2); //readstream, buf. + } + + +HBufC8* CViewSubSession::UnpackageSortOrderAndPluginDetailsLC(const RMessage2& aMessage,RContactViewSortOrder& aSortOrder,TContactViewPreferences& aContactTypes,TUid& aSortPluginImplUid) const + { + HBufC8* buf=HBufC8::NewLC(aMessage.Int0()); + + TPtr8 bufPtr(buf->Des()); + TInt32 nameLen; + aMessage.ReadL(1,bufPtr); + RDesReadStream readStream(bufPtr); + CleanupClosePushL(readStream); + + readStream >> (TInt32&)aContactTypes; + readStream >> aSortOrder; + + // Extract sort plugin UID. + aSortPluginImplUid.iUid = readStream.ReadInt32L(); + + // Extract sort plugin name. + nameLen = readStream.ReadInt32L(); + HBufC8* pluginNameBuf = HBufC8::NewLC(nameLen); + TPtr8 pluginNamePtr = pluginNameBuf->Des(); + readStream.ReadL(pluginNamePtr, nameLen); + CleanupStack::Pop(pluginNameBuf); + CleanupStack::PopAndDestroy(2); //readstream, buf. + + CleanupStack::PushL(pluginNameBuf); + return pluginNameBuf; + } + + +CContactLocalView& CViewSubSession::View() const + { + return STATIC_CAST(CContactLocalView&,*iView); + } + + +void CViewSubSession::ExternalizedSortOrderSizeL(const RMessage2& aMessage) const + { + TPckgBuf pckg(View().SortOrder().ExternalizedSize()); + aMessage.WriteL(0,pckg); + } + + +void CViewSubSession::GetSortOrderL(const RMessage2& aMessage) const + { + const RContactViewSortOrder& sortOrder=View().SortOrder(); + const TInt externalizedSize=sortOrder.ExternalizedSize(); + HBufC8* buf=HBufC8::NewLC(externalizedSize); + TPtr8 bufPtr(buf->Des()); + RDesWriteStream writeStream(bufPtr); + CleanupClosePushL(writeStream); + writeStream << sortOrder; + bufPtr.SetLength(externalizedSize); + aMessage.WriteL(0,*buf); + CleanupStack::PopAndDestroy(2); // writeStream, buf. + } + + +CNamedViewSubSession* CNamedViewSubSession::NewL(CViewManager& aViewManager,const RMessage2& aMessage) + { + CNamedViewSubSession* self=new(ELeave) CNamedViewSubSession(aViewManager); + CleanupStack::PushL(self); + self->ConstructL(aMessage); + CleanupStack::Pop(); // self. + return self; + } + + +/** +Attempt to consume opcode. If the opcode is not consumed then the base class +ServiceL() is called. +*/ +TInt CNamedViewSubSession::ServiceL(const RMessage2& aMessage) + { + switch (aMessage.Function()) + { + case ECntChangeViewSortOrder: + ChangeSortOrderL(aMessage); + break; + default: + return CViewSubSession::ServiceL(aMessage); + } + return 0; + } + + +CNamedViewSubSession::~CNamedViewSubSession() + { + iViewManager.CloseNamedView(View(),*this); + } + + +CNamedViewSubSession::CNamedViewSubSession(CViewManager& aViewManager) : CViewSubSession(aViewManager) + { + } + + +void CNamedViewSubSession::ConstructL(const RMessage2& aMessage) + { + CViewSubSessionBase::ConstructL(); + + // Read sort order. + RContactViewSortOrder sortOrder; + CleanupClosePushL(sortOrder); + TContactViewPreferences contactsToInclude; + TUid sortPluginImplUid; + HBufC8* sortPluginName = UnpackageSortOrderAndPluginDetailsLC(aMessage,sortOrder,contactsToInclude,sortPluginImplUid); + + // Create a descriptor of the correct length. + HBufC* nameBuf=HBufC::NewLC(aMessage.GetDesLengthL(2)); + TPtr wideNameBufPtr(nameBuf->Des()); + // Extract the name of the view from the message. + aMessage.ReadL(2, wideNameBufPtr); + + // Open view using name provided. + iView = &iViewManager.OpenNamedViewL(wideNameBufPtr,sortOrder,*this,contactsToInclude,sortPluginImplUid,*sortPluginName); + + CleanupStack::PopAndDestroy(3,&sortOrder); // nameBuf, sortPluginName, sortOrder + + sortOrder.Close(); + } + + +void CNamedViewSubSession::ChangeSortOrderL(const RMessage2& aMessage) + { + RContactViewSortOrder newSortOrder; + TContactViewPreferences contactsToInclude; + UnpackageSortOrderL(aMessage,newSortOrder,contactsToInclude); + View().ChangeSortOrderL(newSortOrder); + newSortOrder.Close(); + } + + +CContactNamedLocalView& CNamedViewSubSession::View() const + { + return STATIC_CAST(CContactNamedLocalView&,*iView); + } + + +CViewManager* CViewManager::NewL(MLplPersistenceLayerFactory& aFactory,CCntDbManager& aManager) + { + CViewManager* self =new (ELeave) CViewManager(aFactory,aManager); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + + +CContactLocalView& CViewManager::OpenViewL(const RContactViewSortOrder& aSortOrder,MContactViewObserver& aObserver,TContactViewPreferences aContactTypeToInclude, const TUid aSortPluginImplUid, const TDesC8& aSortPluginName) + { + // Check to see if there is already a view with the required sort order, + // preferences and sort plugin. + const TInt numViews=iLocalViews.Count(); + for (TInt ii=0;iiClose(aObserver); + User::Leave(error); + } + + return *viewHandle.iLocalView; + } + + +CContactNamedLocalView& CViewManager::OpenNamedViewL(const TDesC& aName,const RContactViewSortOrder& aSortOrder,MContactViewObserver& aObserver,TContactViewPreferences aContactTypeToInclude, const TUid aSortPluginImplUid, const TDesC8& aSortPluginName) + { + // Check to see if named view already exists. + const TInt numViews=iNamedLocalViews.Count(); + for (TInt ii=0;iiClose(aObserver); + User::Leave(error); + } + + return *newNamedView; + } + + +void CViewManager::CloseView(const CContactLocalView& aView,MContactViewObserver& aObserver) + { + const TInt count = iLocalViews.Count(); + + // Be tolerant to view not being found, since a leave may have occured + // before the CViewSubSession derived object has had a chance to call + // OpenViewL(). + for (TInt index = 0; index < count; index++) + { + // Found it? + if (iLocalViews[index].iLocalView == &aView) + { + if(iLocalViews[index].iLocalView->Close(aObserver)) + { + // Removed last reference to the Local View so un-Register this + // view as an observer of database events with the associated + // CCntDbManager. + iManager.UnRegisterDatabaseEventObserver(*iLocalViews[index].iLocalView); + iLocalViews.Remove(index); + } + break; + } + } + } + + +void CViewManager::CloseNamedView(const CContactNamedLocalView& aView,MContactViewObserver& aObserver) + { + TInt index = iNamedLocalViews.Find(&aView); + + // Be tolerant to view not being found, since a leave may have occured + // before the CNamedViewSubSession derived object has had a chance to call + // OpenViewL(). + if (index != KErrNotFound) + { + if (iNamedLocalViews[index]->Close(aObserver)) + { + // Removed last reference to the Local View so un-Register this view + // as an observer of database events with the associated + // CCntDbManager. + iManager.UnRegisterDatabaseEventObserver(*iNamedLocalViews[index]); + iNamedLocalViews.Remove(index); + } + } + } + + +CViewManager::CViewManager(MLplPersistenceLayerFactory& aFactory,CCntDbManager& aManager) : + iFactory(aFactory), + iManager(aManager) + { + } + + +CViewManager::~CViewManager() + { + iLocalViews.Close(); + iNamedLocalViews.Close(); + } + + +void CViewManager::ConstructL() + { + } + + +#if defined(_DEBUG) +void CViewManager::GetDefinitionsOfExistingViewsL(RPointerArray& aViewDefs) + { + __ASSERT_DEBUG(aViewDefs.Count() == 0, User::Leave(KErrArgument)); + + TInt i; + CContactDefaultViewDefinition* viewDef; + + // Anonymous views. + for (i = 0; i < iLocalViews.Count(); i++) + { + CContactLocalView* view = iLocalViews[i].iLocalView; + viewDef = CContactDefaultViewDefinition::NewLC(CContactDefaultViewDefinition::ERemoteView, + KNullDesC, view->SortOrderL(), + view->ContactViewPreferences(), + KNullDesC8/*pluginName*/); + aViewDefs.AppendL(viewDef); + CleanupStack::Pop(viewDef); + } + + // Named views. + for (i = 0; i < iNamedLocalViews.Count(); i++) + { + CContactNamedLocalView* view = iNamedLocalViews[i]; + viewDef = CContactDefaultViewDefinition::NewLC(CContactDefaultViewDefinition::ENamedRemoteView, + view->Name(), view->SortOrderL(), + view->ContactViewPreferences(), + KNullDesC8/*pluginName*/); + aViewDefs.AppendL(viewDef); + CleanupStack::Pop(viewDef); + } + } +#else +void CViewManager::GetDefinitionsOfExistingViewsL(RPointerArray& ) + { + } +#endif // _DEBUG