phonebookui/Phonebook2/UIControls/src/cpbk2contactviewdoublelistboxmodel.cpp
branchRCL_3
changeset 32 2828b4d142c0
parent 23 5586b4d2ec3e
child 39 a6539d1e8e43
--- a/phonebookui/Phonebook2/UIControls/src/cpbk2contactviewdoublelistboxmodel.cpp	Tue Apr 27 16:23:35 2010 +0300
+++ b/phonebookui/Phonebook2/UIControls/src/cpbk2contactviewdoublelistboxmodel.cpp	Tue May 11 16:00:21 2010 +0300
@@ -39,6 +39,7 @@
 #include <MVPbkContactViewBase.h>
 #include <MVPbkViewContact.h>
 #include <MVPbkContactLink.h>
+#include <MVPbkContactViewBase.h>
 
 // CONSTANTS
 namespace {
@@ -64,17 +65,272 @@
 // rest 56 are reserved for icon data
 const TInt KMaxTxtLength = 100;
 
+const TInt KDataElementCacheSize = 20;
 }
 
+/**
+ * Cache for data elements, cache is made to avoid performance problems that 
+ * caused in cases when avkon implementation calls multiple times MdcaPoint function with same index
+ * Cached items must be deleted when there is any change in contact list.
+ */
+NONSHARABLE_CLASS( CDataElementCache ) : 
+        public CBase,
+        public MVPbkContactViewObserver,
+        public MPbk2FilteredViewStackObserver
+    {
+public:
+    static CDataElementCache* NewL(MPbk2FilteredViewStack& aView);
+    ~CDataElementCache();
+
+    void AppendL( CPbk2ContactViewDoubleListboxDataElement* aDataElement );
+    CPbk2ContactViewDoubleListboxDataElement* Element( TInt aListIndex );
+    
+private:    // From MVPbkContactViewObserver
+     void ContactViewReady(
+             MVPbkContactViewBase& aView );
+     void ContactViewUnavailable(
+             MVPbkContactViewBase& aView );
+     void ContactAddedToView(
+             MVPbkContactViewBase& aView,
+             TInt aIndex,
+             const MVPbkContactLink& aContactLink );
+     void ContactRemovedFromView(
+             MVPbkContactViewBase& aView,
+             TInt aIndex,
+             const MVPbkContactLink& aContactLink );
+     void ContactViewError(
+             MVPbkContactViewBase& aView,
+             TInt aError,
+             TBool aErrorNotified );
+
+private:    // From MPbk2FilteredViewStackObserver
+      void TopViewChangedL(
+              MVPbkContactViewBase& aOldView );
+      void TopViewUpdatedL();
+      void BaseViewChangedL();
+      void ViewStackError(
+              TInt aError );
+      void ContactAddedToBaseView( 
+              MVPbkContactViewBase& aBaseView,
+              TInt aIndex,
+              const MVPbkContactLink& aContactLink ); 
+     
+private:
+    inline CDataElementCache( MPbk2FilteredViewStack& aView );
+    inline void ConstructL();
+    inline void Reset();
+
+private:    
+    RPointerArray<CPbk2ContactViewDoubleListboxDataElement> iCache;
+    MPbk2FilteredViewStack& iView;
+    };
+
+// --------------------------------------------------------------------------
+// CDataElementCache::NewL
+// --------------------------------------------------------------------------
+//
+CDataElementCache* CDataElementCache::NewL( MPbk2FilteredViewStack& aView )
+    {
+    CDataElementCache* self = new (ELeave) CDataElementCache(aView);
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+// --------------------------------------------------------------------------
+// CDataElementCache::CDataElementCache
+// --------------------------------------------------------------------------
+//
+inline CDataElementCache::CDataElementCache( MPbk2FilteredViewStack& aView )
+: iCache( KDataElementCacheSize ), 
+  iView( aView )
+    {
+    }
+
+// --------------------------------------------------------------------------
+// CDataElementCache::ConstructL
+// --------------------------------------------------------------------------
+//
+inline void CDataElementCache::ConstructL()
+    {
+    iView.AddObserverL(*this);
+    iView.AddStackObserverL(*this);
+    }
+
+// --------------------------------------------------------------------------
+// CDataElementCache::~CDataElementCache
+// --------------------------------------------------------------------------
+//
+CDataElementCache::~CDataElementCache()
+    {
+    Reset();
+    iView.RemoveObserver(*this);
+    iView.RemoveStackObserver(*this);
+    }
+
+// --------------------------------------------------------------------------
+// CDataElementCache::AppendL
+// --------------------------------------------------------------------------
+//
+void CDataElementCache::AppendL( 
+        CPbk2ContactViewDoubleListboxDataElement* aDataElement )
+    {
+    iCache.InsertL( aDataElement, 0 );
+    const TInt cacheItemCount( iCache.Count() );
+    if( cacheItemCount > KDataElementCacheSize )
+        {
+        delete iCache[cacheItemCount - 1];
+        iCache.Remove(cacheItemCount - 1);
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CDataElementCache::Reset
+// --------------------------------------------------------------------------
+//
+inline void CDataElementCache::Reset()
+    {
+    iCache.ResetAndDestroy();
+    }
+
+// --------------------------------------------------------------------------
+// CDataElementCache::Element
+// --------------------------------------------------------------------------
+//
+CPbk2ContactViewDoubleListboxDataElement* 
+CDataElementCache::Element( TInt aListIndex )
+    {
+    const TInt cacheItemCount( iCache.Count() );
+    for( TInt i = 0 ; i < cacheItemCount ; ++i )
+        {
+        CPbk2ContactViewDoubleListboxDataElement* p = iCache[i];
+        if( p->ListIndex() == aListIndex )
+            {
+            return p;
+            }
+        }
+    return NULL;
+    }
+
+// --------------------------------------------------------------------------
+// CDataElementCache::ContactViewReady
+// --------------------------------------------------------------------------
+//
+void CDataElementCache::ContactViewReady(
+        MVPbkContactViewBase& /*aView*/ )
+    {
+    Reset();
+    }
+
+// --------------------------------------------------------------------------
+// CDataElementCache::ContactViewUnavailable
+// --------------------------------------------------------------------------
+//
+void CDataElementCache::ContactViewUnavailable(
+        MVPbkContactViewBase& /*aView*/ )
+    {
+    Reset();
+    }
+
+// --------------------------------------------------------------------------
+// CDataElementCache::ContactAddedToView
+// --------------------------------------------------------------------------
+//
+void CDataElementCache::ContactAddedToView(
+        MVPbkContactViewBase& /*aView*/,
+        TInt /*aIndex*/,
+        const MVPbkContactLink& /*aContactLink*/ )
+    {
+    Reset();
+    }
+
+// --------------------------------------------------------------------------
+// CDataElementCache::ContactRemovedFromView
+// --------------------------------------------------------------------------
+//
+void CDataElementCache::ContactRemovedFromView(
+        MVPbkContactViewBase& /*aView*/,
+        TInt /*aIndex*/,
+        const MVPbkContactLink& /*aContactLink*/ )
+    {
+    Reset();
+    }
+
+// --------------------------------------------------------------------------
+// CDataElementCache::ContactViewError
+// --------------------------------------------------------------------------
+//
+void CDataElementCache::ContactViewError(
+        MVPbkContactViewBase& /*aView*/,
+        TInt /*aError*/,
+        TBool /*aErrorNotified*/ )
+    {
+    Reset();
+    }
+
+// --------------------------------------------------------------------------
+// CDataElementCache::TopViewChangedL
+// --------------------------------------------------------------------------
+//
+void CDataElementCache::TopViewChangedL(
+        MVPbkContactViewBase& /*aOldView*/ )
+    {
+    Reset();
+    }
+
+// --------------------------------------------------------------------------
+// CDataElementCache::TopViewUpdatedL
+// --------------------------------------------------------------------------
+//
+void CDataElementCache::TopViewUpdatedL()
+    {
+    Reset();
+    }
+
+// --------------------------------------------------------------------------
+// CDataElementCache::BaseViewChangedL
+// --------------------------------------------------------------------------
+//
+void CDataElementCache::BaseViewChangedL()
+    {
+    Reset();
+    }
+
+// --------------------------------------------------------------------------
+// CDataElementCache::ViewStackError
+// --------------------------------------------------------------------------
+//
+void CDataElementCache::ViewStackError(
+        TInt /*aError*/ )
+    {
+    Reset();
+    }
+
+// --------------------------------------------------------------------------
+// CDataElementCache::ContactAddedToBaseView
+// --------------------------------------------------------------------------
+//
+void CDataElementCache::ContactAddedToBaseView( 
+        MVPbkContactViewBase& /*aBaseView*/,
+        TInt /*aIndex*/,
+        const MVPbkContactLink& /*aContactLink*/ ) 
+    {
+    Reset();
+    }
+
+
 // --------------------------------------------------------------------------
 // CPbk2ContactViewDoubleListBoxModel::CPbk2ContactViewDoubleListBoxModel
 // --------------------------------------------------------------------------
 //
 CPbk2ContactViewDoubleListBoxModel::CPbk2ContactViewDoubleListBoxModel(
     CPbk2ContactViewListBoxModel::TParams& aParams,
-    CPbk2ThumbnailManager& aThumbManager ) :
+    CPbk2ThumbnailManager& aThumbManager,
+    MPbk2FilteredViewStack& aFilteredViewStack ) :
     CPbk2ContactViewListBoxModel( aParams ),
-    iThumbManager( aThumbManager )
+    iThumbManager( aThumbManager ),
+    iFilteredViewStack( aFilteredViewStack )
     {
     TAny* object = aParams.iUiExtension->ContactUiControlExtensionExtension
             ( TUid::Uid( KPbk2ContactUiControlExtensionExtensionUID ) );
@@ -88,6 +344,7 @@
 //
 CPbk2ContactViewDoubleListBoxModel::~CPbk2ContactViewDoubleListBoxModel()
     {
+    delete iDataElementCache;
     }
 
 // --------------------------------------------------------------------------
@@ -96,43 +353,118 @@
 //
 CPbk2ContactViewDoubleListBoxModel* CPbk2ContactViewDoubleListBoxModel::NewL(
     CPbk2ContactViewListBoxModel::TParams& aParams,
-    CPbk2ThumbnailManager& aThumbManager )
+    CPbk2ThumbnailManager& aThumbManager,
+    MPbk2FilteredViewStack& aFilteredViewStack )
     {
     CPbk2ContactViewDoubleListBoxModel* self =
-        new ( ELeave ) CPbk2ContactViewDoubleListBoxModel( aParams, aThumbManager );
+        new ( ELeave ) CPbk2ContactViewDoubleListBoxModel( 
+                aParams, aThumbManager, aFilteredViewStack );
 
     CleanupStack::PushL(self);
     self->ConstructL( aParams.iStoreProperties, aParams.iUiExtension );
+    self->iDataElementCache = CDataElementCache::NewL( aFilteredViewStack );
     CleanupStack::Pop();
     return self;
     }
 
 // --------------------------------------------------------------------------
+// CPbk2ContactViewDoubleListBoxModel::FormatBufferL
+// --------------------------------------------------------------------------
+//
+void CPbk2ContactViewDoubleListBoxModel::FormatBufferL( const TInt aIndex ) const
+    {
+    PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING
+        ("CPbk2ContactViewDoubleListBoxModel::FormatBufferL(0x%x,%d), begin"),
+        this);
+    CPbk2ContactViewDoubleListboxDataElement* element = 
+            iDataElementCache->Element( aIndex );
+    if( element )
+        {
+        FormatBufferForElementDataL(*element, aIndex);
+        }
+    else
+        {
+        const MVPbkViewContact& contact = iView->ContactAtL(aIndex);
+        FormatBufferForContactL(contact, aIndex );
+        }
+    
+    PBK2_DEBUG_PRINT(PBK2_DEBUG_STRING
+        ("CPbk2ContactViewDoubleListBoxModel::FormatBufferL(0x%x,%d), end"),
+        this);
+    }
+
+
+// --------------------------------------------------------------------------
+// CPbk2ContactViewDoubleListBoxModel::FormatBufferForElementDataL
+// --------------------------------------------------------------------------
+//
+void CPbk2ContactViewDoubleListBoxModel::FetchDataFromExtension(
+        CPbk2ContactViewDoubleListboxDataElement& aDataElement,
+        TInt aIndex ) const
+    {
+    // Get element data from extension
+    // 
+    if( iDoubleListExtensionPoint )
+        {
+        TRAPD( err, 
+            iDoubleListExtensionPoint->FormatDataL( 
+                    *(aDataElement.ContactLink()), aDataElement ) );
+        if( err )
+            {
+            // extension's errors are ignored.  
+            PBK2_DEBUG_PRINT( PBK2_DEBUG_STRING(
+            "CPbk2ContactViewDoubleListBoxModel::FormatBufferForElementDataL format error %d"),
+                err );
+            }
+        }
+
+    // Clip secondary text if it's a phone number 
+    if( MPbk2DoubleListboxDataElement::ETypePhoneNumber == 
+        aDataElement.TextType( MPbk2DoubleListboxDataElement::EStatusText ) && 
+        iClipListBoxText )
+        {
+        TPtr secondary( aDataElement.TextPtr( 
+            MPbk2DoubleListboxDataElement::EStatusText ) );
+        iClipListBoxText->ClipFromBeginning( 
+            secondary, aIndex, KSecondaryTextColumn );
+        }    
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2ContactViewDoubleListBoxModel::FormatBufferForElementDataL
+// --------------------------------------------------------------------------
+//
+void CPbk2ContactViewDoubleListBoxModel::FormatBufferForElementDataL(
+    CPbk2ContactViewDoubleListboxDataElement& aDataElement, 
+    TInt aIndex ) const
+    {
+    FetchDataFromExtension(aDataElement, aIndex);
+
+    // start fill the new buffer for the avkon list
+    iBuffer.Zero();
+
+    AppendThumbnailL( aDataElement, aIndex );
+    
+    // Format line buffer based on element's content
+    FormatBufferFromElement( aDataElement );
+    }
+
+// --------------------------------------------------------------------------
 // CPbk2ContactViewDoubleListBoxModel::FormatBufferForContactL
 // --------------------------------------------------------------------------
 //
 void CPbk2ContactViewDoubleListBoxModel::FormatBufferForContactL(
-    const MVPbkViewContact& aViewContact, TInt aIndex ) const
+    const MVPbkViewContact& aViewContact, 
+    TInt aIndex ) const
     {
-    // Reset buffer
-    iBuffer.Zero();
-    
+    MVPbkContactLink* link = aViewContact.CreateLinkLC();
     CPbk2ContactViewDoubleListboxDataElement* element = 
-        CPbk2ContactViewDoubleListboxDataElement::NewLC();
+        CPbk2ContactViewDoubleListboxDataElement::NewL( link, aIndex );
+    CleanupStack::Pop();    // link
+    CleanupStack::PushL( element );
 
-    // Fill data element cells
-    
-    // (1) Add thumbnail icon
-    //
-    TInt index = iThumbManager.GetPbkIconIndexL( aIndex, aViewContact );
-    if( index != KErrNotFound )
-        {
-        iBuffer.AppendNum( index );
-        }
-    iBuffer.Append( KListColumnSeparator );
-
-    // (2) Add contact name
-    //
+    // get data for element
+    // get user name
     HBufC* name = NULL;
     if( FeatureManager::FeatureSupported( KFeatureIdFfContactsCompanyNames ))
         {
@@ -164,12 +496,8 @@
         MPbk2DoubleListboxDataElement::ETypeGenericText );
     CleanupStack::Pop( name );
 
-    // (3) Secondary text 
-    // 
-    // => Empty by default
-  
-    // (4) Trailing icon
-    //
+
+    // get icons
     RArray<TPbk2IconId> ids;
     CleanupClosePushL( ids );
     iContactIcons->GetIconIdsForContactL( aViewContact, ids );
@@ -184,33 +512,18 @@
     CleanupStack::PopAndDestroy( &ids );
 
     // Get element data from extension
-    if( iDoubleListExtensionPoint )
-        {
-        TRAPD( err, 
-            iDoubleListExtensionPoint->FormatDataL( aViewContact, *element ) );
-        if( err )
-            {
-            // extension's errors are ignored.  
-            PBK2_DEBUG_PRINT( PBK2_DEBUG_STRING(
-            "CPbk2ContactViewDoubleListBoxModel::FormatBufferForContactL format error %d"),
-                err );
-            }
-        }
+    FetchDataFromExtension( *element, aIndex );
 
-    // Clip secondary text if it's a phone number 
-    if( MPbk2DoubleListboxDataElement::ETypePhoneNumber == 
-        element->TextType( MPbk2DoubleListboxDataElement::EStatusText ) && iClipListBoxText )
-        {
-        TPtr secondary( element->TextPtr( 
-            MPbk2DoubleListboxDataElement::EStatusText ) );
-        iClipListBoxText->ClipFromBeginning( 
-            secondary, aIndex, KSecondaryTextColumn );
-        }
+    // start format data for the avkon list
+    iBuffer.Zero();
+    
+    AppendThumbnailL( *element, aIndex );
     
     // Format line buffer based on element's content
     FormatBufferFromElement( *element );
     
-    CleanupStack::PopAndDestroy( element ); 
+    iDataElementCache->AppendL( element );
+    CleanupStack::Pop( element ); 
     }
 
 // --------------------------------------------------------------------------
@@ -225,9 +538,6 @@
     //   [thumbnail icon] \t [contact name] \t [secondary text] \t
     //   [trailing icon]
 
-    // (1) Thumbnail icon
-    // No element support needed for thumbnail at the moment 
-
     // (2) Contact name
     AppendName( aElement.TextPtr( 
             MPbk2DoubleListboxDataElement::EName ).Left( KMaxTxtLength ) );
@@ -243,6 +553,25 @@
     }
 
 // --------------------------------------------------------------------------
+// CPbk2ContactViewDoubleListBoxModel::AppendThumbnailL
+// --------------------------------------------------------------------------
+//
+void CPbk2ContactViewDoubleListBoxModel::AppendThumbnailL( 
+        CPbk2ContactViewDoubleListboxDataElement& aDataElement, 
+        TInt aIndex ) const
+    {
+    // (1) Add thumbnail icon
+    //
+    TInt index = iThumbManager.GetPbkIconIndexL( 
+            aIndex, *(aDataElement.ContactLink()) );
+    if( index != KErrNotFound )
+        {
+        iBuffer.AppendNum( index );
+        }
+    iBuffer.Append( KListColumnSeparator );
+    }
+
+// --------------------------------------------------------------------------
 // CPbk2ContactViewDoubleListBoxModel::AppendText
 // --------------------------------------------------------------------------
 //