diff -r 5b6f26637ad3 -r f4a778e096c2 phonebookui/Phonebook2/UIControls/src/CPbk2ThumbnailManager.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/phonebookui/Phonebook2/UIControls/src/CPbk2ThumbnailManager.cpp Wed Sep 01 12:29:52 2010 +0100 @@ -0,0 +1,1222 @@ +/* +* Copyright (c) 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: Thumbnail manager for the social phonebook. +* +*/ + + +// class header +#include "CPbk2ThumbnailManager.h" + +// external includes +#include +#include +#include +#include +#include +#include +#include +#include +#include //tresource reader +#include + +//INTERNAL +#include "CPbk2ContactViewListBox.h" +#include "CPbk2IconArray.h" + + +// Virtual Phonebook +#include +#include +#include +#include +#include + +//Pbk2 +#include +#include + +namespace { + +// Default size for thumbnail images +#define KDefaultThumbnailSize TSize(36,36) +// icon offset. Thumbnail indexing starts from 10000 in CPbk2IconArray, so that there is 0 - 9999 indexes free for +// phonebook's own icons +const TInt KIconIndexOffset = 10000; +// loading limit for thumbnails +const TInt KLoadingLimit = 100; +// loading queue limit +const TInt KQueueLimit = 25; +// Denotes Start Index for an item in the any Queue +const TInt KStartIndex = 0; +// Granularity of the thumbnail array +const TInt KThumbnailArrayGranularity = 200; + +} + +/* + * Helper class for mapping between contact link + image + index on listbox + */ +NONSHARABLE_CLASS( CPbk2TmItem ) : public CBase + { +public: // constructor & destructor + + // Takes ownership of items + static CPbk2TmItem* NewL( MVPbkContactLink* aLink, + TInt aListboxIndex ); + ~CPbk2TmItem(); + +public: //new functions + + /* + * Returns contact link + */ + inline MVPbkContactLink* GetLink(); + + + /* + * Returns corresponding bitmap + */ + inline CFbsBitmap* GetBitmap(); + + /* + * Returns index on listbox + */ + inline TInt GetListboxIndex() const; + + + /* + * Returns index on Pbk2IconArray + */ + inline TInt GetIconArrayIndex() const; + + + /* + * Returns icon id + */ + inline const TPbk2IconId& GetIconId() const; + + /* + * Getter for has thumbnail flag + */ + inline TBool HasThumbnail(); + + /* + * deletes link and bitmap + */ + inline void DeleteBitmap(); + + /* + * Setter for bitmap, deletes old one if set + */ + inline void SetBitmap( CFbsBitmap* aBitmap ); + + + /* + * Setter for listbox index + */ + inline void SetListboxIndex( TInt aIndex ); + + /* + * Setter for Pbk2IconArray index + */ + inline void SetIconArrayIndexAndId( TInt aIndex, TPbk2IconId aId ); + + /* + * Setter for has thumbnail flag + */ + inline void SetHasThumbnail( TBool aValue ); + + /* + * Compare function for sorting + */ + static TInt CompareByListboxIndex( + const CPbk2TmItem& aItem1, const CPbk2TmItem& aItem2 ); + +private: // constructor + + CPbk2TmItem( MVPbkContactLink* aLink, + TInt aListboxIndex ); + +private: //data + // OWN: contact link + MVPbkContactLink* iLink; + // OWN: thumbnail + CFbsBitmap* iBitmap; + // index to listbox + TInt iIndexOnListbox; + // index to icon array + TInt iPbkIconArrayIndex; + // icon id + TPbk2IconId iIconId; + // informs whether the item has thumbnail image on contact database + TBool iHasThumbnail; + }; + + +// -------------------------------------------------------------------------- +// CPbk2TmItem::NewL +// -------------------------------------------------------------------------- +// +CPbk2TmItem* CPbk2TmItem::NewL( MVPbkContactLink* aLink, + TInt aListboxIndex ) + { + CPbk2TmItem* self = new( ELeave )CPbk2TmItem( aLink, + aListboxIndex ); + return self; + } + +// -------------------------------------------------------------------------- +// CPbk2TmItem::CPbk2TmItem +// -------------------------------------------------------------------------- +// +CPbk2TmItem::CPbk2TmItem( MVPbkContactLink* aLink, + TInt aListboxIndex ): + iLink( aLink ), + iIndexOnListbox( aListboxIndex ), + iHasThumbnail( EFalse ) + { + } + +// -------------------------------------------------------------------------- +// CPbk2TmItem::~CPbk2TmItem +// -------------------------------------------------------------------------- +// +CPbk2TmItem::~CPbk2TmItem() + { + delete iLink; + delete iBitmap; + } + +// -------------------------------------------------------------------------- +// CPbk2TmItem::CompareByListboxIndex +// -------------------------------------------------------------------------- +// +TInt CPbk2TmItem::CompareByListboxIndex( + const CPbk2TmItem& aItem1, const CPbk2TmItem& aItem2 ) + { + TInt i = aItem1.GetListboxIndex(); + TInt j = aItem2.GetListboxIndex(); + return i-j; + } + +// -------------------------------------------------------------------------- +// CPbk2TmItem::GetLink +// -------------------------------------------------------------------------- +// +inline MVPbkContactLink* CPbk2TmItem::GetLink() + { + return iLink; + } + +// -------------------------------------------------------------------------- +// CPbk2TmItem::GetBitmap +// -------------------------------------------------------------------------- +// +inline CFbsBitmap* CPbk2TmItem::GetBitmap() + { + return iBitmap; + } + + +// -------------------------------------------------------------------------- +// CPbk2TmItem::GetListboxIndex +// -------------------------------------------------------------------------- +// +inline TInt CPbk2TmItem::GetListboxIndex() const + { + return iIndexOnListbox; + } + + +// -------------------------------------------------------------------------- +// CPbk2TmItem::GetIconArrayIndex +// -------------------------------------------------------------------------- +// +inline TInt CPbk2TmItem::GetIconArrayIndex() const + { + return iPbkIconArrayIndex; + } + + +// -------------------------------------------------------------------------- +// CPbk2TmItem::HasThumbnail +// -------------------------------------------------------------------------- +// +inline TBool CPbk2TmItem::HasThumbnail() + { + return iHasThumbnail; + } + +// -------------------------------------------------------------------------- +// CPbk2TmItem::GetIconId +// -------------------------------------------------------------------------- +// +inline const TPbk2IconId& CPbk2TmItem::GetIconId() const + { + return iIconId; + } + +// -------------------------------------------------------------------------- +// CPbk2TmItem::ClearValues +// -------------------------------------------------------------------------- +// +inline void CPbk2TmItem::DeleteBitmap( ) + { + delete iBitmap; + iBitmap = NULL; + } + + +// -------------------------------------------------------------------------- +// CPbk2TmItem::SetBitmap +// -------------------------------------------------------------------------- +// +inline void CPbk2TmItem::SetBitmap( CFbsBitmap* aBitmap ) + { + delete iBitmap; + iBitmap = aBitmap; + } + + +// -------------------------------------------------------------------------- +// CPbk2TmItem::SetListboxIndex +// -------------------------------------------------------------------------- +// +inline void CPbk2TmItem::SetListboxIndex( TInt aIndex ) + { + iIndexOnListbox = aIndex; + } + + +// -------------------------------------------------------------------------- +// CPbk2TmItem::SetIconArrayIndexAndId +// -------------------------------------------------------------------------- +// +inline void CPbk2TmItem::SetIconArrayIndexAndId( TInt aIndex, TPbk2IconId aId ) + { + iPbkIconArrayIndex = aIndex; + iIconId = aId; + } + +// -------------------------------------------------------------------------- +// CPbk2TmItem::SetHasThumbnail +// -------------------------------------------------------------------------- +// +inline void CPbk2TmItem::SetHasThumbnail( TBool aValue ) + { + iHasThumbnail = aValue; + } + + +/*********************************** THUMBNAIL MANAGER ************************************/ + + +// -------------------------------------------------------------------------- +// CPbk2ThumbnailManager* CPbk2ThumbnailManager::NewL +// -------------------------------------------------------------------------- +// +EXPORT_C CPbk2ThumbnailManager* CPbk2ThumbnailManager::NewL( CVPbkContactManager& aContactManager ) + { + CPbk2ThumbnailManager* self = new (ELeave) CPbk2ThumbnailManager( aContactManager ); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(); + return self; + } + +// -------------------------------------------------------------------------- +// CPbk2ThumbnailManager::CPbk2ThumbnailManager +// -------------------------------------------------------------------------- +// +CPbk2ThumbnailManager::CPbk2ThumbnailManager( + CVPbkContactManager& aContactManager ) : + iState( EIdle ), + iContactThumbnails( KThumbnailArrayGranularity ), + iContactManager( aContactManager ), + iDefaultIconIndex( KErrNotFound ) + { + } + +// -------------------------------------------------------------------------- +// CPbk2ThumbnailManager::~CPbk2ThumbnailManager() +// -------------------------------------------------------------------------- +// +CPbk2ThumbnailManager::~CPbk2ThumbnailManager() + { + if( iView ) + { + iView->RemoveObserver(*this ); + iView->RemoveStackObserver( *this ); + } + + delete iInProgressItemToBeRemoved; + delete iThumbOperation; + delete iManager; + delete iRetrieveOperation; + delete iStoreContact; + iContactThumbnails.ResetAndDestroy(); + iLoadingQueue.Reset(); + iPriorityArray.Reset(); + } + +// -------------------------------------------------------------------------- +// CPbk2ThumbnailManager::ConstructL() +// -------------------------------------------------------------------------- +// +void CPbk2ThumbnailManager::ConstructL() + { + // image manager + iManager = CPbk2ImageManager::NewL( iContactManager ); + // read file type for thumbnail field + ReadFieldTypeL(); + } + +// -------------------------------------------------------------------------- +// CPbk2ThumbnailManager::SetObserver() +// -------------------------------------------------------------------------- +// +void CPbk2ThumbnailManager::SetObserver( MPbk2ThumbnailManagerObserver& aObserver ) + { + iObserver = &aObserver; + } + +// -------------------------------------------------------------------------- +// CPbk2ThumbnailManager::RemoveObserver() +// -------------------------------------------------------------------------- +// +void CPbk2ThumbnailManager::RemoveObserver() + { + iObserver = NULL; + } + +// -------------------------------------------------------------------------- +// CPbk2ThumbnailManager::ThumbnailCount() +// -------------------------------------------------------------------------- +// +TInt CPbk2ThumbnailManager::ThumbnailCount() + { + return iContactThumbnails.Count(); + } + +// -------------------------------------------------------------------------- +// CPbk2ThumbnailManager::GetPbkIconIndexL() +// -------------------------------------------------------------------------- +// +TInt CPbk2ThumbnailManager::GetPbkIconIndexL( + TInt aListboxIndex, + const MVPbkContactLink& aContactLink ) + { + TInt arrIndex = iDefaultIconIndex; + + // check that requested thumbnail is allready added to thumbnail array + if( Rng( 0, aListboxIndex, iContactThumbnails.Count() - 1 ) ) + { + CPbk2TmItem* item = iContactThumbnails[ aListboxIndex ]; + if( !item ) + { + item = CPbk2TmItem::NewL( aContactLink.CloneLC(), aListboxIndex ); + CleanupStack::Pop(); // link + // set default icon index + item->SetIconArrayIndexAndId( iDefaultIconIndex,iDefaultIconId ); + item->SetHasThumbnail( ETrue ); + iContactThumbnails[ aListboxIndex ] = item; + iIsCacheClean = EFalse; + } + + // if item has a thumbnail image, but it is not loaded yet ( queue ) + if( item->HasThumbnail() && !item->GetBitmap() ) + { + TBool reOrderItem = ETrue; + TInt res = iLoadingQueue.Find( item ); + //remove from array if duplicate + if( res != KErrNotFound ) + { + // if item's position is 0 or 1, dont reorder + if( res <= 1 ) + { + reOrderItem = EFalse; + } + // else remove item from the array for reordering + else + { + iLoadingQueue.Remove( res ); + } + } + + // if item is to be reordered + if( reOrderItem ) + { + // if there are more than 2 items + if( iLoadingQueue.Count() > 2 && iState == ELoading ) + { + // insert to second position, first one is under loading + iLoadingQueue.Insert( item, 1 ); + } + // else append to first or second + else + { + iLoadingQueue.Append( item ); + } + } + + //if idle, start loading + if( iState == EIdle ) + { + StartLoading(); + } + } + else + { + arrIndex = item->GetIconArrayIndex(); + } + } + return arrIndex; + } + +// -------------------------------------------------------------------------- +// CPbk2ThumbnailManager::SetDefaultIconId() +// -------------------------------------------------------------------------- +// +void CPbk2ThumbnailManager::SetDefaultIconId( TPbk2IconId aDefaultIconId ) + { + if( iIconArray ) + { + iDefaultIconIndex = iIconArray->FindIcon( aDefaultIconId ); + } + iDefaultIconId = aDefaultIconId; + } + +// -------------------------------------------------------------------------- +// CPbk2ThumbnailManager::GetDefaultIconIndex() +// -------------------------------------------------------------------------- +// +const TPbk2IconId& CPbk2ThumbnailManager::GetDefaultIconId() + { + return iDefaultIconId; + } + +// -------------------------------------------------------------------------- +// CPbk2ThumbnailManager::SetPbkIconArray() +// -------------------------------------------------------------------------- +// +void CPbk2ThumbnailManager::SetPbkIconArray( CPbk2IconArray* aIconArray ) + { + iIconArray = aIconArray; + } + +// -------------------------------------------------------------------------- +// CPbk2ThumbnailManager::RemoveIconArray() +// -------------------------------------------------------------------------- +// +void CPbk2ThumbnailManager::RemoveIconArray() + { + // no more icon array + iIconArray = NULL; + const TInt count = iContactThumbnails.Count(); + + // set all the indexes to default because there is no items in icon array to refer to + for( TInt i = 0; i < count; ++i ) + { + CPbk2TmItem* item = iContactThumbnails[i]; + if( item ) + { + item->SetIconArrayIndexAndId( iDefaultIconIndex, iDefaultIconId ); + } + } + iIconIdCounter = 0; + } + +// -------------------------------------------------------------------------- +// CPbk2ThumbnailManager::DecreaseIndexes() +// -------------------------------------------------------------------------- +// +void CPbk2ThumbnailManager::ResetIndexes() + { + // go through items + const TInt count = iContactThumbnails.Count(); + for( TInt i = 0; i < count; ++i ) + { + CPbk2TmItem* item = iContactThumbnails[i]; + if( item ) + { + item->SetListboxIndex( i ); + } + } + } + +// -------------------------------------------------------------------------- +// CPbk2ThumbnailManager::Reset() +// -------------------------------------------------------------------------- +// +void CPbk2ThumbnailManager::Reset() + { + // clear cache + iContactThumbnails.ResetAndDestroy(); + iPriorityArray.Reset(); + + // reset operations and queue + delete iRetrieveOperation; + iRetrieveOperation = NULL; + delete iThumbOperation; + iThumbOperation = NULL; + iState = EIdle; + iLoadingQueue.Reset(); + } + +// -------------------------------------------------------------------------- +// CPbk2ThumbnailManager::SetThumbnailIconSize() +// -------------------------------------------------------------------------- +// +void CPbk2ThumbnailManager::SetThumbnailIconSize( TSize aSize ) + { + iIconSize = aSize; + } + +// -------------------------------------------------------------------------- +// CPbk2ThumbnailManager::GetThumbnailIconSize() +// -------------------------------------------------------------------------- +// +const TSize& CPbk2ThumbnailManager::GetThumbnailIconSize() + { + return iIconSize; + } + +// -------------------------------------------------------------------------- +// CPbk2ThumbnailManager::SetContactViewL() +// -------------------------------------------------------------------------- +// +void CPbk2ThumbnailManager::SetContactViewL( MPbk2FilteredViewStack* aView ) + { + if( iView ) + { + iView->RemoveObserver(*this ); + iView->RemoveStackObserver( *this ); + } + + iView = aView; + if( iView ) + { + iView->AddObserverL( *this ); + iView->AddStackObserverL( *this ); + } + FlushCache(); + } + +// -------------------------------------------------------------------------- +// CPbk2ThumbnailManager::RemoveThumbnail() +// -------------------------------------------------------------------------- +// +void CPbk2ThumbnailManager::RemoveThumbnail( + const MVPbkContactLink& /*aContactLink*/, TInt aListboxIndex ) + { + const TInt count = iContactThumbnails.Count(); + if( count > aListboxIndex ) + { + CPbk2TmItem* item = iContactThumbnails[aListboxIndex]; + iContactThumbnails.Remove( aListboxIndex ); + ResetIndexes(); + if( item ) + { + // check that the icon is not a default icon + if( item->GetIconArrayIndex() != iDefaultIconIndex ) + { + if( iIconArray ) + { + //inform icon array to remove the icon + iIconArray->RemoveIcon( item->GetIconId() ); + } + //update indexes after that + UpdateIconIndexes(); + } + + // remove from priority list + const TInt priIndex = iPriorityArray.Find( item->GetLink() ); + if( priIndex != KErrNotFound ) + { + iPriorityArray.Remove( priIndex ); + } + + // remove from loading queue + const TInt loadIndex = iLoadingQueue.Find( item ); + if( loadIndex != KErrNotFound ) + { + iLoadingQueue.Remove( loadIndex ); + } + + // inform observer + if( iObserver ) + { + iObserver->ThumbnailRemoved( *item->GetLink(), aListboxIndex ); + } + + //The item at 0th position, denotes the current item + //whose thumbnail load is in progress. + if ( KStartIndex == loadIndex && !iInProgressItemToBeRemoved ) + { + //Remove it when its safe + iInProgressItemToBeRemoved = item; + } + else + { + //can be safely deleted immediately + delete item; + } + } + } + } + +// -------------------------------------------------------------------------- +// CPbk2ThumbnailManager::UpdateIconIndexes() +// -------------------------------------------------------------------------- +// +void CPbk2ThumbnailManager::UpdateIconIndexes( ) + { + // if icon array exists + if( iIconArray ) + { + const TInt count = iContactThumbnails.Count(); + for( TInt i = 0; i < count; ++i ) + { + CPbk2TmItem* item = iContactThumbnails[ i ]; + if( item && !( iDefaultIconId == item->GetIconId() ) ) + { + // icon is removed from the CPbk2IconArray, update indexes + TPbk2IconId id = item->GetIconId(); + item->SetIconArrayIndexAndId( iIconArray->FindIcon( id ), id ); + } + } + } + } + +// -------------------------------------------------------------------------- +// CPbk2ThumbnailManager::DuplicateBitmapL() +// -------------------------------------------------------------------------- +// +CFbsBitmap* CPbk2ThumbnailManager::DuplicateBitmapL( CFbsBitmap* aSourceBitmap ) + { + //Target bitmap. + CFbsBitmap* dstbitmap = new (ELeave) CFbsBitmap; + CleanupStack::PushL( dstbitmap ); + + //Get the handle to source bitmap + TInt srchandle = aSourceBitmap->Handle(); + + //Duplicate the bitmap handle. Increases the RefCount of bitmap + //managed but Fbs Server + User::LeaveIfError( dstbitmap->Duplicate( srchandle ) ); + CleanupStack::Pop( dstbitmap ); + return dstbitmap; + } + +// -------------------------------------------------------------------------- +// CPbk2ThumbnailManager::StartLoading() +// -------------------------------------------------------------------------- +// +void CPbk2ThumbnailManager::StartLoading() + { + //its safe to delete the item here + if ( iInProgressItemToBeRemoved ) + { + delete iInProgressItemToBeRemoved; + iInProgressItemToBeRemoved = NULL; + } + + TInt count = iLoadingQueue.Count(); + + // limit loading queue + while( count > KQueueLimit ) + { + iLoadingQueue.Remove( --count ); + } + + if( count ) + { + // manager is loading + iState = ELoading; + // take first item from the queue + CPbk2TmItem* item = iLoadingQueue[KStartIndex]; + // take first item from the loading queue + TRAPD( err, iRetrieveOperation = + iContactManager.RetrieveContactL( *item->GetLink(), *this ) ); + if( err ) + { + // error occured -> remove item from the queue and continue + iLoadingQueue.Remove( KStartIndex ); + //load next one + StartLoading(); + } + } + // no more items + else + { + // loading queue is empty, inform observer + if( iObserver ) + { + iObserver->LoadingFinished(); + } + // default state + iState = EIdle; + } + } + +// -------------------------------------------------------------------------- +// CPbk2ThumbnailManager::VPbkSingleContactOperationComplete +// -------------------------------------------------------------------------- +// +void CPbk2ThumbnailManager::VPbkSingleContactOperationComplete + ( MVPbkContactOperationBase& /*aOperation*/ , MVPbkStoreContact* aContact ) + { + delete iRetrieveOperation; + iRetrieveOperation = NULL; + + delete iStoreContact; + iStoreContact = aContact; + + // store contact found, fetch thumbnail for it + DoLoadThumbnail( *iStoreContact ); + } + +// -------------------------------------------------------------------------- +// CPbk2ThumbnailManager::VPbkSingleContactOperationFailed +// -------------------------------------------------------------------------- +// +void CPbk2ThumbnailManager::VPbkSingleContactOperationFailed + ( MVPbkContactOperationBase& /*aOperation*/ ,TInt /*aError*/ ) + { + if( iObserver && !iInProgressItemToBeRemoved && iLoadingQueue.Count() ) + { + //inform observer + //We should not inform the observer with wrong index, + //hence check for iInProgressItemToBeRemoved + iObserver->ThumbnailLoadingComplete( KErrNotFound, iLoadingQueue[ KStartIndex ]->GetListboxIndex() ); + + //remove item from the queue + iLoadingQueue.Remove( KStartIndex ); + } + //next + StartLoading(); + } + +// -------------------------------------------------------------------------- +// CPbk2ThumbnailManager::DoLoadThumbnail() +// -------------------------------------------------------------------------- +// +void CPbk2ThumbnailManager::DoLoadThumbnail( + MVPbkBaseContact& aContact ) + { + TInt err = KErrNotFound; + + //if the item in progress has been removed then it will be filled in iInProgressItemToBeRemoved + //If such condition arises then we need not load the thumbnail at all + + // check if the contact has an image + if( !iInProgressItemToBeRemoved && iManager->HasImage( aContact, *iFieldType ) && iLoadingQueue.Count() ) + { + // contact has a thumbnail + iLoadingQueue[ KStartIndex ]->SetHasThumbnail( ETrue ); + + /* + * If priority array is full, this function removes first item from the array and + * frees all the allocations related. + */ + MakeRoomForNextThumbnail(); + + // if there is room, load thumbnail + if( iPriorityArray.Count() <= KLoadingLimit ) + { + //add current item to priority array + iPriorityArray.Append( iLoadingQueue[ KStartIndex ]->GetLink() ); + + // start loading picture for the current item + delete iThumbOperation; + iThumbOperation = NULL; + // Define parameters for thumbnail + TPbk2ImageManagerParams params; + // if iconsize is not set + if( iIconSize.iHeight == 0 && iIconSize.iWidth == 0 ) + { + iIconSize = KDefaultThumbnailSize; + } + // set params + params.iSize = iIconSize; + params.iFlags = TPbk2ImageManagerParams::EScaleImage | + TPbk2ImageManagerParams::EUseSpeedOptimizedScaling | + TPbk2ImageManagerParams::ECropImage ; + params.iDisplayMode = EColor16MU; + // fetch the image + TRAP( err, iThumbOperation = + iManager->GetImageAsyncL( ¶ms, aContact, *iFieldType, *this ) ); + } + // no room at this moment + else + { + //has image, but cannot load it + err = KErrNone; + //remove item from the queue + iLoadingQueue.Remove( KStartIndex ); + // start loading next one + StartLoading(); + } + } + + // contact has no image or error occured, move to next contact + if( err ) + { + if ( !iInProgressItemToBeRemoved && iLoadingQueue.Count() ) + { + if( iObserver ) + { + //inform observer + iObserver->ThumbnailLoadingComplete( KErrNotFound, iLoadingQueue[ KStartIndex ]->GetListboxIndex() ); + } + //no thumbnail + iLoadingQueue[ KStartIndex ]->SetHasThumbnail( EFalse ); + // set default icon index and id + iLoadingQueue[ KStartIndex ]->SetIconArrayIndexAndId( iDefaultIconIndex, iDefaultIconId ); + //remove item from the queue + iLoadingQueue.Remove( KStartIndex ); + } + // start loading next one + StartLoading(); + } + } + +// -------------------------------------------------------------------------- +// CPbk2ThumbnailManager::MakeRoomForNextThumbnail +// -------------------------------------------------------------------------- +// +void CPbk2ThumbnailManager::MakeRoomForNextThumbnail() + { + // if the loading limit for thumbnails is reached and optimizing is on, make room for next thumbnail + if( iPriorityArray.Count() >= KLoadingLimit ) + { + // remove first one from the queue + CPbk2TmItem* rem = NULL; + const TInt count = iContactThumbnails.Count(); + for( TInt i = 0; i < count; ++i ) + { + CPbk2TmItem* item = iContactThumbnails[ i ]; + if( item && item->GetLink()->IsSame( *iPriorityArray[ KStartIndex ] ) ) + { + rem = item; + break; + } + } + // if item was found + if( rem ) + { + // remove from priority array + iPriorityArray.Remove( 0 ); + + //remove icon from Pbk2IconArray + if( iIconArray && rem->GetIconArrayIndex() != iDefaultIconIndex ) + { + iIconArray->RemoveIcon( rem->GetIconId() ); + } + // remove memory allocations from heap + rem->DeleteBitmap(); + //set default icon id and index + rem->SetIconArrayIndexAndId( iDefaultIconIndex,iDefaultIconId ); + //update indexes for other items + UpdateIconIndexes(); + } + } + } + +// -------------------------------------------------------------------------- +// CPbk2ThumbnailManager::Pbk2ImageGetComplete +// -------------------------------------------------------------------------- +// +void CPbk2ThumbnailManager::Pbk2ImageGetComplete + ( MPbk2ImageOperation& /*aOperation*/, CFbsBitmap* aBitmap ) + { + //if the item in progress has been removed then it will be filled in iInProgressItemToBeRemoved + //If such condition arises then we need not load the thumbnail at all + + // store loaded bitmap + if ( !iInProgressItemToBeRemoved && iLoadingQueue.Count() ) + { + iLoadingQueue[ KStartIndex ]->SetBitmap( aBitmap ); + + // inform the observer + if( iObserver ) + { + // if icon array exists + if( iIconArray ) + { + //create icon and pass it to the array + TPbk2IconId iconID( TUid::Uid( KPbk2UID3 ), iIconIdCounter + KIconIndexOffset ); + iIconIdCounter++; + + TRAPD( err, AppendIconL( iconID, aBitmap ) ); + if( err == KErrNone ) + { + // set icond index and id + iLoadingQueue[ KStartIndex ]->SetIconArrayIndexAndId( iIconArray->FindIcon( iconID ), iconID ); + // inform observer + iObserver->ThumbnailLoadingComplete( KErrNone, iLoadingQueue[ KStartIndex ]->GetListboxIndex() ); + } + } + } + + //remove item from the queue + iLoadingQueue.Remove( KStartIndex ); + } + else + { + //None to take ownership. so delete here + delete aBitmap; + } + + // delete operation + delete iThumbOperation; + iThumbOperation = NULL; + // next + StartLoading(); + } + +// -------------------------------------------------------------------------- +// CPbk2ThumbnailManager::Pbk2ImageGetFailed +// -------------------------------------------------------------------------- +// +void CPbk2ThumbnailManager::Pbk2ImageGetFailed + ( MPbk2ImageOperation& /*aOperation*/, TInt /*aError*/ ) + { + delete iThumbOperation; + iThumbOperation = NULL; + + if( iObserver && !iInProgressItemToBeRemoved && iLoadingQueue.Count() ) + { + //inform observer + //We should not inform the observer with wrong index, + //hence check for iInProgressItemToBeRemoved + iObserver->ThumbnailLoadingComplete( KErrNotFound, iLoadingQueue[ KStartIndex ]->GetListboxIndex() ); + + //remove item from the queue + iLoadingQueue.Remove( KStartIndex ); + } + + // next + StartLoading(); + } + +// -------------------------------------------------------------------------- +// CPbk2ThumbnailManager::ContactViewReady +// -------------------------------------------------------------------------- +// +void CPbk2ThumbnailManager::ContactViewReady( MVPbkContactViewBase& aView ) + { + TRAP_IGNORE( DoContactViewReadyL( aView ) ); + } + +// -------------------------------------------------------------------------- +// CPbk2ThumbnailManager::DoContactViewReadyL +// -------------------------------------------------------------------------- +// +void CPbk2ThumbnailManager::DoContactViewReadyL( MVPbkContactViewBase& aView ) + { + FlushCache(); + PreCreateThumbnailArrayL( aView ); + } + +// -------------------------------------------------------------------------- +// CPbk2ThumbnailManager::PreCreateThumbnailArrayL +// -------------------------------------------------------------------------- +// +void CPbk2ThumbnailManager::PreCreateThumbnailArrayL( MVPbkContactViewBase& aView ) + { + iContactThumbnails.ResetAndDestroy(); + const TInt contactCount = aView.ContactCountL(); + for( TInt i = 0; i < contactCount; ++i ) + { + iContactThumbnails.AppendL( NULL ); + } + } + +// -------------------------------------------------------------------------- +// CPbk2ThumbnailManager::FlushCache +// -------------------------------------------------------------------------- +// +void CPbk2ThumbnailManager::FlushCache() + { + // reset operations + delete iRetrieveOperation; + iRetrieveOperation = NULL; + delete iThumbOperation; + iThumbOperation = NULL; + iState = EIdle; + + if( !iIsCacheClean ) // prevent unnecessary work if cache is already cleaned + { + iIsCacheClean = ETrue; + const TInt count = iContactThumbnails.Count(); + for ( TInt i = count - 1; i >= 0; --i ) + { + CPbk2TmItem* item = iContactThumbnails[i]; + if ( item ) + { + // check that the icon is not a default icon + if( iIconArray && item->GetIconArrayIndex() != iDefaultIconIndex ) + { + iIconArray->RemoveIcon( item->GetIconId() ); + } + + delete item; + iContactThumbnails[i] = NULL; + } + } + } + + // reset loading queue and cache priority + iLoadingQueue.Reset(); + iPriorityArray.Reset(); + } + +// -------------------------------------------------------------------------- +// CPbk2ThumbnailManager::ContactViewUnavailable +// -------------------------------------------------------------------------- +// +void CPbk2ThumbnailManager::ContactViewUnavailable( + MVPbkContactViewBase& /*aView*/ ) + { + // ignored + } + +// -------------------------------------------------------------------------- +// CPbk2ThumbnailManager::ContactAddedToView +// -------------------------------------------------------------------------- +// +void CPbk2ThumbnailManager::ContactAddedToView( + MVPbkContactViewBase& /*aView*/, + TInt aIndex, + const MVPbkContactLink& /*aContactLink*/ ) + { + // Because contact events and contact view are not always in sync we need to + // flush the whole cache. + FlushCache(); + iContactThumbnails.Insert( NULL, aIndex ); + } + +// -------------------------------------------------------------------------- +// CPbk2ThumbnailManager::ContactRemovedFromView +// -------------------------------------------------------------------------- +// +void CPbk2ThumbnailManager::ContactRemovedFromView( + MVPbkContactViewBase& /*aView*/, + TInt aIndex, + const MVPbkContactLink& /*aContactLink*/ ) + { + // Because contact events and contact view are not always in sync we need to + // flush the whole cache. + FlushCache(); + iContactThumbnails.Remove( aIndex ); + } + +// -------------------------------------------------------------------------- +// CPbk2ThumbnailManager::ContactViewError +// -------------------------------------------------------------------------- +// +void CPbk2ThumbnailManager::ContactViewError( + MVPbkContactViewBase& /*aView*/, + TInt /*aError*/, + TBool /*aErrorNotified*/ ) + { + // ignored + } + +// -------------------------------------------------------------------------- +// CPbk2ThumbnailManager::TopViewChangedL +// -------------------------------------------------------------------------- +// +void CPbk2ThumbnailManager::TopViewChangedL( MVPbkContactViewBase& /*aOldView*/ ) + { + FlushCache(); + if( iView ) + { + PreCreateThumbnailArrayL( *iView ); + } + } + +// -------------------------------------------------------------------------- +// CPbk2ThumbnailManager::TopViewUpdatedL +// -------------------------------------------------------------------------- +// +void CPbk2ThumbnailManager::TopViewUpdatedL() + { + } + +// -------------------------------------------------------------------------- +// CPbk2ThumbnailManager::BaseViewChangedL +// -------------------------------------------------------------------------- +// +void CPbk2ThumbnailManager::BaseViewChangedL() + { + } + +// -------------------------------------------------------------------------- +// CPbk2ThumbnailManager::ViewStackError +// -------------------------------------------------------------------------- +// +void CPbk2ThumbnailManager::ViewStackError( TInt /*aError*/ ) + { + } + +// -------------------------------------------------------------------------- +// CPbk2ThumbnailManager::ContactAddedToBaseView +// -------------------------------------------------------------------------- +// +void CPbk2ThumbnailManager::ContactAddedToBaseView( + MVPbkContactViewBase& /*aBaseView*/, + TInt /*aIndex*/, + const MVPbkContactLink& /*aContactLink*/ ) + { + } + +// -------------------------------------------------------------------------- +// CPbk2ThumbnailManager::ReadFieldTypeL +// -------------------------------------------------------------------------- +// +void CPbk2ThumbnailManager::ReadFieldTypeL() + { + TResourceReader reader; + CCoeEnv::Static()->CreateResourceReaderLC + ( reader, R_PBK2_THUMBNAIL_FIELD_TYPE ); + const TInt count = reader.ReadInt16(); + + TVPbkFieldTypeMapping mapping( reader ); + iFieldType = mapping.FindMatch( iContactManager.FieldTypes() ); + if( !iFieldType ) + { + User::Leave( KErrNotFound ); + } + CleanupStack::PopAndDestroy(); // CreateResourceReaderLC + } + + +// -------------------------------------------------------------------------- +// CPbk2ThumbnailManager::AppendIconL +// -------------------------------------------------------------------------- +// +void CPbk2ThumbnailManager::AppendIconL( + TPbk2IconId& aIcon, CFbsBitmap* aBitmap ) + { + // create icon + CGulIcon* icon = CGulIcon::NewLC(); + icon->SetBitmap( DuplicateBitmapL( aBitmap ) ); + iIconArray->AppendIconL( icon, aIcon ); + CleanupStack::Pop( icon ); + } + +// end of file