imstutils/imconversationview/imcvuiengine/src/cimcvenginechatcontainer.cpp
changeset 0 5e5d6b214f4f
child 21 2b7283837edb
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/imstutils/imconversationview/imcvuiengine/src/cimcvenginechatcontainer.cpp	Tue Feb 02 10:12:18 2010 +0200
@@ -0,0 +1,579 @@
+/*
+* Copyright (c) 2007-2008 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:  container class for im messages
+*
+*/
+
+
+#include "cimcvenginechatcontainer.h"
+
+#include "cimcvenginemessagecontainer.h"
+#include "mimcvenginenewmsgobserver.h"
+#include "mimcvenginemessage.h"
+#include <hal.h>
+#include "imcvlogger.h"
+#include "mimcvenginechatlistobserver.h"
+
+
+#include <hal.h>
+
+const TInt KMinAvailableMemory = 0x32000; // 200kb
+
+//-----------------------------------------------------------------------------
+// CIMCVEngineChatContainer::CIMCVEngineChatContainer
+// ( Other items commented in header )
+//-----------------------------------------------------------------------------
+CIMCVEngineChatContainer::CIMCVEngineChatContainer(TInt aServiceId):
+    iServiceId( aServiceId )
+	{	
+	}
+
+//-----------------------------------------------------------------------------
+// CIMCVEngineChatContainer::CIMCVEngineChatContainer
+// ( Other items commented in header )
+//-----------------------------------------------------------------------------
+CIMCVEngineChatContainer::~CIMCVEngineChatContainer()
+	{
+	iChatContainer.ResetAndDestroy();	
+	iSendContainer.ResetAndDestroy();
+	iNewMsgObserver = NULL;
+	iChatListObservers.Reset();
+	}
+	
+//-----------------------------------------------------------------------------
+// CIMCVEngineChatContainer::NewL
+// ( Other items commented in header )
+//-----------------------------------------------------------------------------
+CIMCVEngineChatContainer* CIMCVEngineChatContainer::NewL(TInt aServiceId)
+	{
+	CIMCVEngineChatContainer* self = 
+	        new ( ELeave ) CIMCVEngineChatContainer(aServiceId);
+
+	return self;
+	}	
+	
+//-----------------------------------------------------------------------------
+// CIMCVEngineChatContainer::MessageReadInterfaceL
+// ( Other items commented in header )
+//-----------------------------------------------------------------------------
+MIMCVEngineMessageReadInterface& CIMCVEngineChatContainer::MessageReadInterfaceL(                  
+                 TInt aServiceId, 
+                 const TDesC& aTargetId,
+                 const TDesC& aDisplayName,
+                 const TDesC8& aContactLink,
+                 MIMCVEngineMessageReadInterface::TContainerType aType )
+	{
+	return *ChatL( ChatL( aServiceId, aTargetId,aDisplayName,aContactLink,aType ) );
+	}
+	
+//-----------------------------------------------------------------------------
+// CIMCVEngineChatContainer::MessageWriteInterfaceL
+// ( Other items commented in header )
+//-----------------------------------------------------------------------------
+MIMCVEngineMessageWriteInterface& CIMCVEngineChatContainer::MessageWriteInterfaceL(                 
+                TInt aServiceId, 
+                const TDesC& aTargetId,
+                const TDesC& aDisplayName,
+                const TDesC8& aContactLink,
+                MIMCVEngineMessageReadInterface::TContainerType aType )
+	{
+	return *ChatL( ChatL( aServiceId, aTargetId, aDisplayName, aContactLink , aType ) );
+	}
+
+//-----------------------------------------------------------------------------
+// CIMCVEngineChatContainer::DeleteChatL
+// ( Other items commented in header )
+//-----------------------------------------------------------------------------
+void CIMCVEngineChatContainer::DeleteChatL(  
+		                            TInt aServiceId,
+		                            const TDesC& aTargetId )
+    {
+    // Find out if chat exist or not. ChatExists() not used, 
+    // because we need index.
+    CIMCVEngineMessageContainer* tempChat = CreateContainerLC(                         
+                        aServiceId, 
+                        aTargetId,
+                        KNullDesC,
+                        KNullDesC8,
+                        *this, 
+                        MIMCVEngineMessageReadInterface::ENoneContainer );
+	TInt index( FindChat( *tempChat ) );
+	CleanupStack::PopAndDestroy( tempChat );
+
+    // If index is positive  value, Chat exists and we can remove it.	
+	if( index >= 0 )
+	    {
+        CIMCVEngineMessageContainer* target = ChatL( index, EFalse );
+
+        // Get count of pending messages before removing chat
+        TInt ignore;
+        TInt pendignMsgs = MessagesPendingCount( ignore );
+
+        RemoveChat( index );
+        
+        // Check if removed chat had unread messages
+        if( pendignMsgs != MessagesPendingCount( ignore ) )
+            {
+            // Notify about changed unread count
+            HandleChatEventL( EUnreadCountChanged );
+            }
+            
+        // Observers are notified, delete target.
+        delete target;
+	    }    
+	else if( index != KErrNotFound ) 
+	    {
+	    // some other error than not found occurred. Inform caller.
+	    User::Leave( index );
+	    }	   
+    }
+    
+//-----------------------------------------------------------------------------
+// CIMCVEngineChatContainer::CloseAllContainers
+// ( Other items commented in header )
+//-----------------------------------------------------------------------------
+void CIMCVEngineChatContainer::CloseAllContainers()
+    {
+    IM_CV_LOGS(TXT("CIMCVEngineChatContainer::CloseAllContainers() START") );
+    TInt count( iChatListObservers.Count() );
+    for( TInt a( 0 ); a < count; ++a )
+        {
+    	IM_CV_LOGS(TXT("CIMCVEngineChatContainer::CloseAllContainers() closing container ") );    
+        iChatListObservers[ a ]->HandleChatListEvent( iServiceId, EChatAllItemDeleted, NULL  );
+        }   
+	iChatContainer.ResetAndDestroy();
+	IM_CV_LOGS(TXT("CIMCVEngineChatContainer::CloseAllContainers() End") );
+	}
+  
+//-----------------------------------------------------------------------------
+// CIMCVEngineChatContainer::ChatCount
+// ( Other items commented in header )
+//-----------------------------------------------------------------------------
+TInt CIMCVEngineChatContainer::ChatCount() const
+    {
+    return iChatContainer.Count();
+    }
+    
+//-----------------------------------------------------------------------------
+// CIMCVEngineChatContainer::ChatAt
+// ( Other items commented in header )
+//-----------------------------------------------------------------------------
+MIMCVEngineMessageReadInterface& CIMCVEngineChatContainer::ChatAt( TInt aIndex ) const
+    {
+    //__CHAT_ASSERT_DEBUG( aIndex >= 0 && aIndex < ChatCount() )
+    return *iChatContainer[ aIndex ];    
+    }
+    
+
+//-----------------------------------------------------------------------------
+// CIMCVEngineChatContainer::RegisterNewMsgObserver
+// ( Other items commented in header )
+//-----------------------------------------------------------------------------
+void CIMCVEngineChatContainer::RegisterNewMsgObserver( MIMCVEngineNewMsgObserver* aObserver )
+    {
+    iNewMsgObserver = aObserver;
+    }
+
+//-----------------------------------------------------------------------------
+// CIMCVEngineChatContainer::UnregisterNewMsgObserver
+// ( Other items commented in header )
+//-----------------------------------------------------------------------------
+void CIMCVEngineChatContainer::UnregisterNewMsgObserver()
+    {
+    iNewMsgObserver = NULL;
+    }
+  
+//-----------------------------------------------------------------------------
+// CIMCVEngineChatContainer::RegisterChatListObserver
+// ( Other items commented in header )
+//-----------------------------------------------------------------------------
+TInt CIMCVEngineChatContainer::RegisterChatListObserver( MIMCVEngineChatListObserver* aObserver )
+    {
+    TInt index = iChatListObservers.Find( aObserver );
+    if( index == KErrNotFound )
+        {
+        return iChatListObservers.Append( aObserver );
+        }
+    return KErrAlreadyExists;
+    }
+
+//-----------------------------------------------------------------------------
+// CIMCVEngineChatContainer::UnregisterChatListObserver
+// ( Other items commented in header )
+//-----------------------------------------------------------------------------
+TInt CIMCVEngineChatContainer::UnregisterChatListObserver( MIMCVEngineChatListObserver* aObserver )
+    {
+    TInt index = iChatListObservers.Find( aObserver );
+    if( index >= 0 )
+        {
+        iChatListObservers.Remove( index );
+        return KErrNone;
+        }
+    return index;
+    }
+    
+//-----------------------------------------------------------------------------
+// CIMCVEngineChatContainer::PendingMessagesCount
+// ( Other items commented in header )
+//-----------------------------------------------------------------------------
+TInt CIMCVEngineChatContainer::MessagesPendingCount( TInt& aCountOfChats,
+    MIMCVEngineMessageReadInterface::TUnreadFilter aUnreadFilter
+    /*= MIMCVEngineMessageReadInterface::EUnreadAll*/ ) const
+    {
+    TInt count( ChatCount() );
+    TInt pendingCount( 0 );
+    aCountOfChats = 0;
+    for( TInt a( 0 ); a < count; ++a )
+        {
+        TInt unreadCount = ChatAt( a ).UnreadCount( aUnreadFilter );
+        if( unreadCount > 0 )
+            {
+            pendingCount += unreadCount;
+            ++aCountOfChats;
+            }        
+        }
+    return pendingCount;
+    }
+
+    
+//-----------------------------------------------------------------------------
+// CIMCVEngineChatContainer::MessageInterface
+// ( Other items commented in header )
+//-----------------------------------------------------------------------------
+TBool CIMCVEngineChatContainer::FreeMemoryIfNeededL( TInt aSize )
+	{
+	//CHAT_DP_FUNC_ENTER( "CIMCVEngineChatContainer::FreeMemoryIfNeededL" );
+	
+    TInt halSize;
+    TInt biggestBlock;
+
+    HAL::Get( HALData::EMemoryRAMFree, halSize );	
+    TInt maxHeap = Min( User::Heap().MaxLength(), halSize );	
+	TInt available = maxHeap - ( User::Heap().Size() - User::Heap().Available( biggestBlock ) );
+	TInt memoryNeed = KMinAvailableMemory + aSize;
+		
+    TTime oldestUnread;
+    TInt unreadIndex;
+    
+    IM_CV_LOGS(TXT( "CIMCVEngineChatContainer::FreeMemoryIfNeededL, heapSize = %d"), maxHeap );
+    IM_CV_LOGS(TXT( "****heapSize, available, need = %d, %d, %d"), 
+                              maxHeap, available, memoryNeed );
+        
+    TBool ready = EFalse;
+    TBool memLowNotified = EFalse;
+    while( !ready )
+        {
+        TBool freeMemoryNeeded( EFalse );
+        if( iExternalMemoryHandler )
+            {
+            freeMemoryNeeded = !iExternalMemoryHandler->FreeMemoryIfNeededL( aSize );
+            }
+        if( freeMemoryNeeded || memoryNeed > available )
+            {
+            // we have to react.
+            TInt count = ChatCount();
+            
+            // Check how much memory can be made free
+            TInt freeableBytes = 0;
+            for( TInt i = 0; i < count; ++i )
+                {
+                TBool locked = iChatContainer[i]->IsLocked();
+                if ( iChatContainer[i]->AllMessagesCount() && !locked )
+                    {
+                    freeableBytes += iChatContainer[i]->ContainerSizeInBytes();
+                    }
+                }
+            
+            if ( ( ( available + freeableBytes ) < memoryNeed )
+                && !memLowNotified )
+                {
+                // Can't free enough memory
+                return EFalse;
+                }
+            
+            oldestUnread.HomeTime();
+            unreadIndex = KErrNotFound;            
+            
+            for( TInt a( 0 ); a < count; ++a )
+                {
+                MIMCVEngineMessageReadInterface& chat = ChatAt( a );
+                TBool locked = iChatContainer[ a ]->IsLocked();
+                if( iChatContainer[ a ]->AllMessagesCount() && !locked )
+                    {
+                    MIMCVEngineMessage& message = iChatContainer[ a ]->MessageFromAll( 0 );
+                    if( oldestUnread > message.TimeStamp() )
+                        {
+                        oldestUnread = message.TimeStamp();
+                        unreadIndex = a;                        
+                        }
+                    }
+                }
+                
+            if( unreadIndex == KErrNotFound )
+                {
+                return EFalse;
+                }
+            else
+                {
+                // Inform observers about memory handling
+                if ( !memLowNotified )
+                    {
+                    HandleChatEventL( EMemoryLow );
+                    memLowNotified = ETrue;
+                    }                
+                iChatContainer[ unreadIndex ]->DeleteMessageFromAll( 0 );
+                }
+	        available = maxHeap - ( User::Heap().Size() - User::Heap().Available( biggestBlock ) );
+            IM_CV_LOGS(TXT( "****heapSize, available, need = %d, %d, %d"), 
+                                      maxHeap, available, memoryNeed );
+            }
+        else
+            {
+            ready = ETrue;
+            }                    
+        }
+	//CHAT_DP_FUNC_DONE( "CIMCVEngineChatContainer::FreeMemoryIfNeededL" );           
+	return ETrue;
+	}
+	
+//-----------------------------------------------------------------------------
+// CIMCVEngineChatContainer::HandleChatEventL
+// ( Other items commented in header )
+//-----------------------------------------------------------------------------    
+void CIMCVEngineChatContainer::HandleChatEventL( TChatEventType aEvent, 
+                                        MIMCVEngineMessage* aMessage )
+    {
+    if( iNewMsgObserver )
+        {
+        iNewMsgObserver->HandleChatEventL( aEvent, aMessage );
+        }
+    }
+
+
+//-----------------------------------------------------------------------------
+// CIMCVEngineChatContainer::ChatL
+// ( Other items commented in header )
+//-----------------------------------------------------------------------------
+TInt CIMCVEngineChatContainer::ChatL(                 
+                 TInt aServiceId, 
+                 const TDesC& aTargetId,
+                 const TDesC& aDisplayName,
+                 const TDesC8& aContactLink,
+                 MIMCVEngineMessageReadInterface::TContainerType aType 
+                               /*= MIMCVEngineMessageReadInterface::ENoneContainer*/ )
+	{
+    IM_CV_LOGS(TXT("CIMCVEngineChatContainer::ChatL aName= %S"),&aDisplayName );
+
+    IM_CV_LOGS(TXT("CIMCVEngineChatContainer::ChatL aLink= %S"),&aContactLink);  
+
+	CIMCVEngineMessageContainer* tempChat = 
+	     CreateContainerLC( aServiceId, aTargetId, aDisplayName, aContactLink, *this, aType );
+		
+	TInt index( FindChat( *tempChat ) );
+	if( index == KErrNotFound )
+		{
+        IM_CV_LOGS(TXT("CIMCVEngineChatContainer::ChatL,Chat not found creating with aName %S"),&aDisplayName );  
+        IM_CV_LOGS(TXT("CIMCVEngineChatContainer::ChatL,Chat not found creating with xspId %S"),&aTargetId );  
+		
+		TLinearOrder< CIMCVEngineMessageContainer > order( 
+		                                    CIMCVEngineMessageContainer::OrderUid );
+		// User::LeaveIfError returns value if value is positive.
+		iLatestType = tempChat->ContainerType();
+		switch( iLatestType )
+		    {
+		    case MIMCVEngineMessageReadInterface::EChatContainer:
+		        {
+                User::LeaveIfError( iChatContainer.InsertInOrder( tempChat, 
+                                                                  order ) );			                                                  
+		        index = FindChat( *tempChat );
+    	        iChatContainer[ index ]->SetChatObserver( this );	
+    	        
+    	        HandleChatListEvent( EChatItemAdded, *tempChat );
+                break;
+		        }
+		    case MIMCVEngineMessageReadInterface::ESendContainer:
+		        {
+                User::LeaveIfError( iSendContainer.InsertInOrder( tempChat, 
+                                                                  order ) );
+		        
+		        index = FindChat( *tempChat );
+                break;
+		        }
+		    default:
+		        {
+		        User::Leave( KErrArgument );
+		        break;
+		        }
+		    }		
+		CleanupStack::Pop( tempChat );
+		}
+	else
+	    {
+	    // if contact link is null
+	    if(!(iChatContainer[ index ]->ContactLink().Length()))
+	        {
+	        if(	(aContactLink.Length() > 0) && (iLatestType == MIMCVEngineMessageReadInterface::EChatContainer))
+	            {		
+	            iChatContainer[ index ]->SetLinkL(aContactLink);
+	            }
+	        }
+	    CleanupStack::PopAndDestroy( tempChat );
+	    }
+		
+	return User::LeaveIfError( index );
+	}
+	
+//-----------------------------------------------------------------------------
+// CIMCVEngineChatContainer::ChatL
+// ( Other items commented in header )
+//-----------------------------------------------------------------------------
+CIMCVEngineMessageContainer* CIMCVEngineChatContainer::ChatL( TInt aIndex, 
+                                              TBool aResetLatest /* = ETrue*/ )
+    {
+    MIMCVEngineMessageReadInterface::TContainerType type = iLatestType;
+    
+    if( aResetLatest )
+        {
+        iLatestType = MIMCVEngineMessageReadInterface::ENoneContainer;
+        }
+    
+    switch( type )
+        {
+        
+        case MIMCVEngineMessageReadInterface::EChatContainer:
+            {
+            return iChatContainer[ aIndex ];
+            }
+        case MIMCVEngineMessageReadInterface::ESendContainer:
+            {
+            return iSendContainer[ aIndex ];
+            }
+        default:
+            {
+            User::Leave( KErrArgument );
+            break;
+            }
+        }
+    // Can never get this far
+    //__CHAT_ASSERT_DEBUG( EFalse );
+    return NULL;
+    }
+    
+//-----------------------------------------------------------------------------
+// CIMCVEngineChatContainer::RemoveChatL
+// ( Other items commented in header )
+//-----------------------------------------------------------------------------
+void CIMCVEngineChatContainer::RemoveChat( TInt aIndex, 
+                                   TBool aResetLatest /* = ETrue */ )
+    {
+    MIMCVEngineMessageReadInterface::TContainerType type = iLatestType;
+    
+    if( aResetLatest )
+        {
+        iLatestType = MIMCVEngineMessageReadInterface::ENoneContainer;
+        }
+    
+    switch( type )
+        {
+        case MIMCVEngineMessageReadInterface::EChatContainer:
+            {
+            HandleChatListEvent( EChatItemDeleted, *iChatContainer[aIndex] );
+            iChatContainer.Remove( aIndex );            
+            break;
+            }
+        case MIMCVEngineMessageReadInterface::ESendContainer:
+            {
+            
+            iSendContainer.Remove( aIndex );
+            break;
+            }
+        default:
+            {
+            break;
+            }
+        }    
+    }
+	
+//-----------------------------------------------------------------------------
+// CIMCVEngineChatContainer::FindChat
+// ( Other items commented in header )
+//-----------------------------------------------------------------------------
+TInt CIMCVEngineChatContainer::FindChat( const CIMCVEngineMessageContainer& aChat )
+	{
+	
+	TInt index( 0 );
+    TLinearOrder< CIMCVEngineMessageContainer > order( CIMCVEngineMessageContainer::OrderUid );
+    TInt status = iChatContainer.FindInOrder( &aChat, index, order );
+    if( status == KErrNone )
+        {
+        iLatestType = MIMCVEngineMessageReadInterface::EChatContainer;
+        return index;
+        }
+                   
+    iLatestType = MIMCVEngineMessageReadInterface::ESendContainer;
+    status = iSendContainer.FindInOrder( &aChat, index, order );
+    return ( status == KErrNone ? index : status );
+	}
+	
+//-----------------------------------------------------------------------------
+// CIMCVEngineChatContainer::CreateContainerLC
+// ( Other items commented in header )
+//-----------------------------------------------------------------------------
+CIMCVEngineMessageContainer* CIMCVEngineChatContainer::CreateContainerLC(                               
+                              TInt aServiceId, 
+                              const TDesC& aTargetId,
+                              const TDesC& aDisplayName,  
+                              const TDesC8& aContactLink,
+                              MIMCVEngineBufferMemoryHandler& aMemoryHandler, 
+                              MIMCVEngineMessageReadInterface::TContainerType aType )
+    {
+    
+    CIMCVEngineMessageContainer* messageContainer = CIMCVEngineMessageContainer::NewL(                                                     
+                                                    aServiceId, 
+                                                    aTargetId,
+                                                    aDisplayName,
+                                                    aContactLink,
+                                                    aMemoryHandler, 
+                                                    aType );
+    CleanupStack::PushL( messageContainer );
+    return messageContainer;
+    }
+
+
+// ---------------------------------------------------------
+// CIMCVEngineChatContainer::MemoryHandler
+// ---------------------------------------------------------
+//
+MIMCVEngineBufferMemoryHandler& CIMCVEngineChatContainer::MemoryHandler() 
+    {
+    return *this;   
+    }
+        
+
+// ---------------------------------------------------------
+// CIMCVEngineChatContainer::HandleChatListEvent
+// ---------------------------------------------------------
+//
+void CIMCVEngineChatContainer::HandleChatListEvent( TChatListEventType aEvent, 
+								MIMCVEngineMessageReadInterface& aContainerInfo ) 
+	{
+ 	IM_CV_LOGS (TXT("CIMCVENGINECHATCONTAINER :: HANDLECHATLISTEVENT"));
+	// Inform all observer about chat event.
+    //TInt count( iChatListObservers.Count() );  //kept for reference
+    for( TInt a( 0 ); a <  iChatListObservers.Count() ; ++a )
+        {
+        iChatListObservers[ a ]->HandleChatListEvent( iServiceId, aEvent, &aContainerInfo );
+        }	
+	}
+// end of file