logsui/AppSrc/CLogsDetailAdapter.cpp
changeset 0 e686773b3f54
child 21 9da50d567e3c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/logsui/AppSrc/CLogsDetailAdapter.cpp	Tue Feb 02 10:12:17 2010 +0200
@@ -0,0 +1,800 @@
+/*
+* Copyright (c) 2002 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: 
+*     Adapts data from logsmodel to logs ui component (listbox) format
+*
+*/
+
+
+// INCLUDE FILES
+#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
+#include <logfilterandeventconstants.hrh>
+#endif
+#include <logcli.h>     // clogclient
+#include <eiklabel.h>   // ceiklabel
+#include <AknUtils.h>
+#include <aknlists.h>   //caknsingleheadingstylelistbox
+
+#include <Logs.rsg>     // detail view's event type texts.
+
+#include "CLogsDetailAdapter.h"
+#include "CLogsDetailView.h"
+#include "MLogsEventGetter.h"
+#include "MLogsGetEvent.h"
+#include "CPhoneNumberFormat.h"
+
+#include "LogsConstants.hrh"
+#include "LogsConsts.h"
+#include "CLogsEngine.h"
+#include <LogsApiConsts.h>  //additional event uids
+
+// CONSTANTS
+//_LIT(KPanic,"LogsDetailAdapter");
+
+// ================= MEMBER FUNCTIONS =======================
+
+
+// ----------------------------------------------------------------------------
+// CLogsDetailAdapter::CLogsDetailAdapter
+// ----------------------------------------------------------------------------
+//
+CLogsDetailAdapter::CLogsDetailAdapter( 
+    CAknSingleHeadingStyleListBox* aListBox, 
+    CLogsDetailView* aView  ) :
+        iEngine( aView->Engine()), 
+        iGetter( aView->Engine()->GetEventL()), 
+        iListBox( aListBox ), 
+        iView( aView )
+    {
+    }
+    
+// ----------------------------------------------------------------------------
+// CLogsDetailAdapter::ConstructL
+// ----------------------------------------------------------------------------
+//
+void CLogsDetailAdapter::ConstructL()
+    {
+    CEikonEnv* env = CEikonEnv::Static();
+    iDirection = env->AllocReadResourceL(R_LOGS_DETAIL_DIRECTION_TEXT);
+    iType = env->AllocReadResourceL(R_LOGS_DETAIL_TYPE_TEXT);
+    iStatus  = env->AllocReadResourceL(R_LOGS_DETAIL_STATUS_TEXT);
+    iDuration = env->AllocReadResourceL(R_LOGS_DETAIL_DURATION_TEXT);
+    iAmount = env->AllocReadResourceL(R_LOGS_DETAIL_NUMBER_TEXT);
+
+    iSentAmount = env->AllocReadResourceL(R_LOGS_DETAIL_SENT_TEXT);
+    iReceivedAmount = env->AllocReadResourceL(R_LOGS_DETAIL_RECEIVED_TEXT);
+
+    iAmountKB = env->AllocReadResourceL(R_LOGS_DETAIL_VIEW_KB_TEXT);
+    iNbr = env->AllocReadResourceL(R_LOGS_DETAIL_TELNO_TEXT);
+    iUnknownNumber = env->AllocReadResourceL(R_DLOGS_DETAILS_UNKNOWN_NUMBER);
+
+    iDirectionIn = env->AllocReadResourceL(R_LOGS_DIR_IN_TEXT);
+    iDirectionOut = env->AllocReadResourceL(R_LOGS_DIR_OUT_TEXT);
+    iDirectionMissed = env->AllocReadResourceL(R_LOGS_DIR_MISSED_TEXT);
+    iEventTypeVoice = env->AllocReadResourceL(R_LOGS_ET_CALL_TEXT);
+    iEventTypeSMS = env->AllocReadResourceL(R_LOGS_ET_SMS_TEXT);
+    iEventTypeMMS = env->AllocReadResourceL(R_LOGS_ET_MMS_TEXT);
+    iEventTypeData = env->AllocReadResourceL(R_LOGS_ET_DATA_TEXT);
+    iEventTypeGPRS = env->AllocReadResourceL(R_LOGS_ET_PACKET_TEXT); 
+    iEventTypeWLAN = env->AllocReadResourceL(R_LOGS_ET_WLAN_TEXT); 
+    iEventTypeFax = env->AllocReadResourceL(R_LOGS_ET_FAX_TEXT);
+    iEventTypeVideo = env->AllocReadResourceL(R_LOGS_ET_VIDEO_TEXT);
+
+    iEventTypePoC = env->AllocReadResourceL(R_LOGS_ET_POC_TEXT);
+    iEventTypePoCInfo = env->AllocReadResourceL(R_LOGS_ET_POC_INFO_TEXT);    
+    
+    iEventTypeVoIP = env->AllocReadResourceL(R_LOGS_ET_VOIP_TEXT);
+
+    iPoCAddr = env->AllocReadResourceL(R_LOGS_ET_POC_ADDR);
+    iVoIPCallFrom = env->AllocReadResourceL(R_LOGS_ET_VOIP_CALL_FROM);
+    iVoIPCallTo = env->AllocReadResourceL(R_LOGS_ET_VOIP_CALL_TO);
+
+    //Read strings from Symbian Log engine
+    CLogClient* logClient = iEngine->CLogClientRef();   
+    logClient->GetString( iEventStatusPendingTxt, R_LOG_DEL_PENDING );
+    logClient->GetString( iEventStatusSentTxt, R_LOG_DEL_SENT );
+    logClient->GetString( iEventStatusFailedTxt, R_LOG_DEL_FAILED );
+    logClient->GetString( iEventStatusNoDeliveryTxt, R_LOG_DEL_NONE );
+    logClient->GetString( iEventStatusDeliveredTxt, R_LOG_DEL_DONE );
+    logClient->GetString( iEventStatusNotSentTxt, R_LOG_DEL_NOT_SENT );
+
+    iEventStatusDelivered = env->AllocReadResourceL(
+                                            R_LOGS_STATUS_DELIVERED_TEXT);
+    iEventStatusPending = env->AllocReadResourceL(R_LOGS_STATUS_PENDING_TEXT);
+    iEventStatusFailed = env->AllocReadResourceL(R_LOGS_STATUS_FAILURE_TEXT);
+    iEventStatusSent = env->AllocReadResourceL(R_LOGS_STATUS_SENT_TEXT);
+    iDurationFormat = env->AllocReadResourceL(R_QTN_TIME_DURAT_LONG_WITH_ZERO);
+
+    iNumberFirstRow = HBufC::NewL( KLogsSipUriMaxLen );
+    iNumberSecondRow = HBufC::NewL( KLogsSipUriMaxLen );
+
+    iPhoneNbrFormatter = CPhoneNumberFormat::NewL();
+    LineFont();
+    iTextWidth = 0;  
+    }
+
+// ----------------------------------------------------------------------------
+// CLogsDetailAdapter::NewL
+// ----------------------------------------------------------------------------
+//
+CLogsDetailAdapter* CLogsDetailAdapter::NewL( 
+    CAknSingleHeadingStyleListBox* aListBox, 
+    CLogsDetailView* aView )  
+    {
+    CLogsDetailAdapter* self = new (ELeave) CLogsDetailAdapter( aListBox, aView ); 
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop();
+    return self;
+    }
+
+// ----------------------------------------------------------------------------
+// CLogsDetailAdapter::~CLogsDetailAdapter
+// ----------------------------------------------------------------------------
+//
+CLogsDetailAdapter::~CLogsDetailAdapter()
+    {
+    delete iDirection;
+    delete iType;
+    delete iStatus;
+    delete iDuration;
+    delete iAmount;
+    delete iAmountKB;
+    delete iNbr;
+    delete iUnknownNumber;
+    delete iDirectionIn;
+    delete iDirectionOut;
+    delete iDirectionMissed;
+
+    delete iEventTypeVoice;
+    delete iEventTypeSMS;
+    delete iEventTypeMMS;
+    delete iEventTypeData;
+    delete iEventTypeGPRS;
+    delete iEventTypeWLAN;
+    delete iEventTypeFax;
+    delete iEventTypeVideo; 
+
+    delete iEventTypePoC; 
+    delete iEventTypePoCInfo;     
+    delete iEventTypeVoIP; 
+    delete iPoCAddr;
+    delete iVoIPCallFrom;
+    delete iVoIPCallTo;
+
+    delete iEventStatusDelivered;
+    delete iEventStatusPending;
+    delete iEventStatusFailed;
+    delete iEventStatusSent;
+           
+    delete iDurationFormat;
+    
+    delete iNumberFirstRow;
+    delete iNumberSecondRow;
+    delete iSentAmount;
+    delete iReceivedAmount;
+    delete iPhoneNbrFormatter;
+    
+    delete iDisplayRows;    
+    }
+
+// ----------------------------------------------------------------------------
+// CLogsDetailAdapter::UpdateL
+// ----------------------------------------------------------------------------
+//
+void CLogsDetailAdapter::UpdateL() 
+    {
+    iDisplayRowNumber = 0;
+    
+    const MLogsEventGetter* event = iEngine->GetEventL()->Event();  
+    const CLogEvent* logDbEvent = iEngine->GetEventL()->LogEvent();  
+
+    CDesCArrayFlat* newDisplayRows = new ( ELeave ) CDesCArrayFlat( 10 );
+    CleanupStack::PushL( newDisplayRows );
+
+    //1) Rows 1 and 2 show always direction and type of event
+    DirectionRow( event );
+    newDisplayRows->AppendL( iBuffer );
+    iDisplayRowNumber++;
+
+    TypeRow( event );
+    newDisplayRows->AppendL( iBuffer );
+    iDisplayRowNumber++;
+
+    //2) Contents of rows 3-> depend on event type (and available data)
+    //Status row of message from CLogEvent (only for sms/mms)    
+    if( StatusRow( logDbEvent, event ) ) 
+        {
+        newDisplayRows->AppendL( iBuffer );
+        iDisplayRowNumber++;
+        }
+    
+    //Duration. For missed and Poc calls shouldn't exist (=0), for other calls and wlan+gprs
+    //duration shown if non-zero in the event (e.g. for gprs, duration is not updated
+    //until context is closed, so first we don't show duration). For MO calls show even if zero.
+    TBool showDuration( EFalse );
+    
+    if( (( event->EventUid().iUid == KLogCallEventType || //For MO voip and MO cs 
+           event->LogsEventData()->VoIP() ) &&            //show duration even when
+           event->Direction() == EDirOut ))               //it is zero
+        {
+        showDuration = ETrue;
+        }
+    else if( logDbEvent->Duration() > 0 )                 //For other show if available
+        {
+        showDuration = ETrue;
+        }
+        
+    if( showDuration &&
+        !event->LogsEventData()->PoC() &&   //Exclude Poc, missed calls, messages just in case would 
+        event->Direction() != EDirMissed && //wrongly contain garbage in duration (should never happen)
+        event->EventUid().iUid != KLogShortMessageEventType &&
+        event->EventUid().iUid != KLogsEngMmsEventType )
+        {
+        DurationRow( logDbEvent );
+        newDisplayRows->AppendL( iBuffer );
+        iDisplayRowNumber++;
+        }
+
+    //Size. Number of message pdu's from CLogEvent (only for sms/mms)
+    if( AmountRow( event )) //logDbEvent ) ) 
+        {
+        newDisplayRows->AppendL( iBuffer );
+        iDisplayRowNumber++;
+        }
+
+    //Sent data (gprs, wlan, poc, voip)
+    if( event->LogsEventData()->DataSent() > 0  ||          //voip, poc, only if > 0
+        event->EventUid().iUid == KLogsEngWlanEventType ||  //for wlan & gprs show also zero 
+        event->EventUid().iUid == KLogPacketDataEventType )
+        {
+        SentAmountRow( event );
+        newDisplayRows->AppendL( iBuffer );
+        iDisplayRowNumber++;
+        }
+        
+    //Received data (gprs, wlan, poc, voip)
+    if( event->LogsEventData()->DataReceived() > 0 ||
+        event->EventUid().iUid == KLogsEngWlanEventType ||  
+        event->EventUid().iUid == KLogPacketDataEventType )
+        {
+        ReceivedAmountRow( event );
+        newDisplayRows->AppendL( iBuffer );
+        iDisplayRowNumber++;
+        }
+
+    //Number. Show if available, however for emergency calls not shown
+    if( iView->PhoneNumberAvailable( event ) && event->EventType() != ETypeEmerg)      
+        {
+        TBool split = SplitNumber( event, *iListboxFont, iTextWidth );
+        TelRow( event );
+        newDisplayRows->AppendL( iBuffer );
+        iDisplayRowNumber++;
+        
+        if( split )
+            {
+            TelRow( event, ESecondRow );
+            newDisplayRows->AppendL( iBuffer );
+            iDisplayRowNumber++;
+            }
+        }
+
+    //Uri. Show if available 
+    if( iView->SipUriAvailable( event ))       
+        {
+        if( event->Direction() == EDirIn || event->Direction() == EDirMissed )    
+            {
+            event->LogsEventData()->VoIP() ? iBuffer.Copy( iVoIPCallFrom->Des() ) :
+                                             iBuffer.Copy( iPoCAddr->Des() );
+            }
+        else 
+            {
+            event->LogsEventData()->VoIP() ? iBuffer.Copy( iVoIPCallTo->Des() ) :
+                                             iBuffer.Copy( iPoCAddr->Des() );
+            }
+        iBuffer.Append( KTab );            
+        
+        TBool split = SplitNumber( event, *iListboxFont, iTextWidth, ETrue );            
+        iBuffer.Append( *iNumberFirstRow );
+        newDisplayRows->AppendL( iBuffer );                        
+        iDisplayRowNumber++;
+
+        if( split )
+            {
+            iBuffer.Copy( KTab );
+            iBuffer.Append( *iNumberSecondRow );
+            newDisplayRows->AppendL( iBuffer );
+            iDisplayRowNumber++;
+            }
+        }
+
+    //Update display array
+    CleanupStack::Pop( newDisplayRows );            
+    delete iDisplayRows;
+    iDisplayRows = newDisplayRows; 
+    }
+
+
+// ----------------------------------------------------------------------------
+// CLogsDetailAdapter::MdcaCount
+// ----------------------------------------------------------------------------
+//
+TInt CLogsDetailAdapter::MdcaCount() const
+    {  
+    return iDisplayRowNumber;
+    }
+
+// ----------------------------------------------------------------------------
+// CLogsDetailAdapter::MdcaPoint
+// ----------------------------------------------------------------------------
+//
+TPtrC16 CLogsDetailAdapter::MdcaPoint( TInt aIndex ) const
+    {
+    return iDisplayRows->MdcaPoint( aIndex );
+    }
+
+// ----------------------------------------------------------------------------
+// CLogsDetailAdapter::StatusRow
+// ----------------------------------------------------------------------------
+//
+TBool CLogsDetailAdapter::StatusRow( const CLogEvent* aCLogEvent,
+                                     const MLogsEventGetter* aEvent ) const
+    {
+    TBool rc( EFalse );
+    
+    //Skip events that are not MO originated
+    if( aEvent->Direction() != EDirOut &&
+        aEvent->Direction() != EDirOutAlt ) 
+        {
+        return rc;
+        }
+    
+    TDes& des = MUTABLE_CAST( TBuf<KLogsDetailsListAdaptorArrayLen>&,
+                              iBuffer );
+
+    des.Copy( iStatus->Des() );
+    des.Append( KTab );
+
+    switch( aCLogEvent->EventType().iUid )
+        {
+        case KLogShortMessageEventType:   
+        case KLogsEngMmsEventType:
+            {
+            if( aCLogEvent->Status() == iEventStatusFailedTxt ||
+                aCLogEvent->Status() == iEventStatusNotSentTxt )
+                {
+                des.Append( iEventStatusFailed->Des() );
+                }
+            else if( aCLogEvent->Status() == iEventStatusSentTxt )
+                {
+                des.Append( iEventStatusSent->Des() );
+                }
+            else if( aCLogEvent->Status() == iEventStatusDeliveredTxt )
+                {
+                des.Append( iEventStatusDelivered->Des() );
+                }
+            else
+                {
+                // Show "Pending" for other statuses: iEventStatusPendingTxt, 
+                // iEventStatusNoDeliveryTxt, ... 
+                des.Append( iEventStatusPending->Des() );
+                }
+            rc = ETrue;
+
+            break;
+            }
+        default:
+            break;
+        } // switch
+
+    return rc;
+    }
+
+// ----------------------------------------------------------------------------
+// CLogsDetailAdapter::DurationRow
+// ----------------------------------------------------------------------------
+//
+TBool CLogsDetailAdapter::DurationRow( const CLogEvent* aEvent ) const
+    {
+    TDes& des = MUTABLE_CAST( TBuf<KLogsDetailsListAdaptorArrayLen>&,
+                              iBuffer );
+    des.Copy( iDuration->Des() );
+    des.Append( KTab );
+
+    TInt32 duration( aEvent->Duration() );
+    TInt64 seconds = MAKE_TINT64( 0, duration );  //TInt64 seconds( 0, duration );
+    TTime time = seconds * 1000000;
+        
+    TDateTime dateTime = time.DateTime();
+    
+    if ( dateTime.Day() > 99 )
+        {
+        return EFalse;
+        }
+
+    if ( dateTime.Day() > 0 )
+        {
+        TBuf<KLogsDetailsListAdaptorArrayLen> buf;
+        buf.AppendNum( dateTime.Day() );
+        AknTextUtils::LanguageSpecificNumberConversion( buf ); 
+        des.Append( buf );
+        des.Append(KSpace);
+        }
+        
+    TRAPD( err, TimeFormattingL( time ) );
+    
+    if( err )
+        {
+        des.Append( KSpace ); 
+        }
+
+    return ETrue;
+    }
+
+// ----------------------------------------------------------------------------
+// CLogsDetailAdapter::TimeFormattingL
+// ----------------------------------------------------------------------------
+//
+void CLogsDetailAdapter::TimeFormattingL( TTime& aTime ) const
+    {
+    TDes& des = MUTABLE_CAST( TBuf<KLogsDetailsListAdaptorArrayLen>&,
+                              iBuffer );
+    TBuf<KLogsPhoneNumberMaxLen> buffer;
+    aTime.FormatL( buffer, *iDurationFormat );
+    AknTextUtils::LanguageSpecificNumberConversion( buffer ); 
+    des.Append( buffer );
+    }
+
+// ----------------------------------------------------------------------------
+// CLogsDetailAdapter::AmountRow
+//
+// Size row for SMS and MMS events 
+// ----------------------------------------------------------------------------
+//
+TBool CLogsDetailAdapter::AmountRow( const MLogsEventGetter* aEvent ) const
+    {
+    TBool rc( EFalse );
+    TDes& des = MUTABLE_CAST( TBuf<KLogsDetailsListAdaptorArrayLen>&,
+                              iBuffer );
+    des.Copy( iAmount->Des() );
+    des.Append( KTab );
+
+    TBuf<KLogsPhoneNumberMaxLen> buf;
+    buf.Zero();
+
+    switch( aEvent->EventUid().iUid )
+        {
+        case KLogShortMessageEventType:   
+        case KLogsEngMmsEventType:
+            {
+            buf.AppendNum( aEvent->LogsEventData()->MsgPartsNumber() );
+            AknTextUtils::LanguageSpecificNumberConversion(buf);
+            des.Append( buf );
+            rc = ETrue;
+            break;
+            }
+        default:
+            break;
+        } // switch
+
+    return rc;
+    }
+
+// ----------------------------------------------------------------------------
+// CLogsDetailAdapter::TelRow
+//
+// Tel no for certain types of rows   
+// ----------------------------------------------------------------------------
+//
+TBool CLogsDetailAdapter::TelRow( const MLogsEventGetter* aEvent,
+                                    TRowNumber aRowNumber ) const
+    {
+    TDes& des = MUTABLE_CAST( TBuf<KLogsDetailsListAdaptorArrayLen>&,
+                              iBuffer );
+
+    if( aRowNumber == EFirstRow )
+        {
+        des.Copy( iNbr->Des() );
+        des.Append( KTab );
+        switch( aEvent->EventType() )
+            {
+            //For unknown numbers we show "Tel no Unknown" row.
+            case ETypeUnknown:
+                des.Append( *iUnknownNumber );
+                break;
+
+			//For Private and Payphone numbers we don't show the "Tel no" row at all.. 
+
+            case ETypeUsual:
+                des.Append( *iNumberFirstRow );
+                break;
+
+            default:
+                break;
+            }
+        }
+    else
+        {
+        des.Copy( KTab );
+        des.Append( *iNumberSecondRow );
+        }
+
+    return ETrue;
+    }
+
+// ----------------------------------------------------------------------------
+// CLogsDetailAdapter::SplitNumber
+//
+// If number is too long to fit to one row, we split it to two rows
+// Sets iNumberSplitted to ETrue (+Returns true) if number was splitted
+// ----------------------------------------------------------------------------
+//
+TBool CLogsDetailAdapter::SplitNumber( 
+    const MLogsEventGetter* aEvent,
+    const CFont& aFont, 
+    TInt aMaxWidthInPixels,
+    TBool aPreferUri ) const
+    {
+    MUTABLE_CAST( CLogsDetailAdapter*, this )->iNumberSplitted = EFalse;
+    TPtr firstRow( iNumberFirstRow->Des() );
+    TPtr secondRow( iNumberSecondRow->Des() );
+    firstRow.Zero();
+    secondRow.Zero();
+
+    TBuf<KLogsSipUriMaxLen> clippedText;
+
+    if( iView->PhoneNumberAvailable( aEvent ) && !aPreferUri )  
+        {
+        TBuf<KLogsPhoneNumberMaxLen> tmp;
+        iPhoneNbrFormatter->DTMFStrip( *(aEvent->Number()), tmp );   
+        iPhoneNbrFormatter->PhoneNumberFormat( tmp, clippedText );
+        }
+    else if( iView->SipUriAvailable( aEvent ) && aPreferUri )   //If no number, show instead url if available            
+        {
+        iEngine->ConvertToUnicode( aEvent->LogsEventData()->Url(), clippedText );
+        }
+    else
+        {
+        clippedText.Zero();
+        }
+
+    TInt textPixels( aFont.TextWidthInPixels( clippedText ) );
+
+    if ( textPixels <= aMaxWidthInPixels )                       //Fits to one row
+        {
+        firstRow.Copy( clippedText );
+        return EFalse;
+        }
+
+    //Two rows needed
+    MUTABLE_CAST( CLogsDetailAdapter*, this )->iNumberSplitted = ETrue;
+    TInt excessPixels;
+    TInt cutOff( aFont.TextCount( clippedText, aMaxWidthInPixels, excessPixels ) );
+    
+    //Does the remaining fit fully to two rows
+    if ( textPixels + excessPixels <= aMaxWidthInPixels * 2 ||  //Phone number fits to two rows
+         aPreferUri )                                           //or we use sip-uri (can be right-clipped on 2nd row)
+        {
+        secondRow.Copy( clippedText.Mid( cutOff ) );            // second row
+        firstRow.Copy( clippedText.Left( cutOff ) );            // first row
+        return ETrue;
+        }
+    
+    //Phone number did not fit to two rows, so we need cut the first row from the beginning
+    //We have to first reverse the string because we are interested in length of characters *after*
+    //cutoff point (non-monospaced font, so chars are not necessarily equally wide on both sides of cutoff)
+    Reverse( clippedText );
+    secondRow.Copy( clippedText.Left( cutOff ) );    // second row
+    Reverse( secondRow ); //convert back to normal order
+    TPtrC remainingChars(clippedText.Mid(cutOff) );//first row    
+
+    _LIT(KDots, "...");
+    TInt acceptedWidth = aMaxWidthInPixels - aFont.TextWidthInPixels( KDots );
+
+    //Create the first row in reversed order and then convert it back to normal order
+    TInt cutOff2( aFont.TextCount( remainingChars, acceptedWidth ));
+    firstRow.Append( remainingChars.Left( cutOff2 ) );
+    if( firstRow.Length() + 4 < firstRow.MaxLength() )    //Magic number 4=length of KDots + length of Directionality Marker
+        {
+        firstRow.Append( 0x202A );   //A&H: In mirrored layout we need this Directionality Marker to render the three dots 
+                                     //     correctly on left side of the number string. Similar issue as in SAKA-6689Q4.
+        firstRow.Append( KDots );                                                                 
+        }
+    Reverse( firstRow );//convert back to normal order
+
+    return ETrue;
+    }
+
+
+// ----------------------------------------------------------------------------
+// CLogsDetailAdapter::DirectionRow
+// ----------------------------------------------------------------------------
+//
+TBool CLogsDetailAdapter::DirectionRow( const MLogsEventGetter* aEvent ) const
+    {
+    TDes& des = MUTABLE_CAST( TBuf<KLogsDetailsListAdaptorArrayLen>&,
+                              iBuffer );
+
+    des.Copy( iDirection->Des() );
+    des.Append( KTab );
+
+    switch( aEvent->Direction() )
+        {
+        case EDirIn:
+            des.Append( iDirectionIn->Des() );
+            break;
+        case EDirOut:
+            des.Append( iDirectionOut->Des() );
+            break;
+        case EDirMissed:
+            des.Append( iDirectionMissed->Des() );
+            break;
+        default:
+            break;
+        }
+
+    return ETrue;
+    }
+
+// ----------------------------------------------------------------------------
+// CLogsDetailAdapter::TypeRow
+// ----------------------------------------------------------------------------
+//
+TBool CLogsDetailAdapter::TypeRow( const MLogsEventGetter* aEvent ) const
+    {
+    TDes& des = MUTABLE_CAST( TBuf<KLogsDetailsListAdaptorArrayLen>&,
+                              iBuffer );
+
+    des.Copy( iType->Des() );
+    des.Append( KTab );
+
+     switch( aEvent->EventUid().iUid )
+        {
+        case KLogCallEventType:
+            //Currently Voice, VT, PoC and VoIP are shown as mutually exclusive. This may change in the future, e.g.
+            //VoIP and VT types may be both in the same event 
+            if( aEvent->LogsEventData()->VT() )      
+                {
+                des.Append( iEventTypeVideo->Des() );
+                }
+            else if( aEvent->LogsEventData()->PoC() )
+                {
+                des.Append( iEventTypePoC->Des() );
+                }
+            else if( aEvent->LogsEventData()->VoIP() )
+                {
+                des.Append( iEventTypeVoIP->Des() );
+                }
+            else
+                {
+                des.Append( iEventTypeVoice->Des() );
+                }
+
+            break;
+
+        case KLogsEngPocInfoEventType:            
+            des.Append( iEventTypePoCInfo->Des() );
+            break;
+
+        case KLogDataEventType:            
+            des.Append( iEventTypeData->Des() );
+            break;
+
+        case KLogFaxEventType:             
+            des.Append( iEventTypeFax->Des() );
+            break;
+                
+        case KLogShortMessageEventType:           
+            des.Append( iEventTypeSMS->Des() );
+            break;
+
+        case KLogsEngMmsEventType:
+            des.Append( iEventTypeMMS->Des() );
+            break;
+               
+        case KLogPacketDataEventType:             
+            des.Append( iEventTypeGPRS->Des() );
+            break;
+
+        case KLogsEngWlanEventType:
+            des.Append( iEventTypeWLAN->Des() );
+            break;
+
+        default:
+            break;
+        }
+
+    return ETrue;
+    }
+
+// ----------------------------------------------------------------------------
+// CLogsDetailAdapter::SentAmountRow
+// ----------------------------------------------------------------------------
+//
+TBool CLogsDetailAdapter::SentAmountRow( const MLogsEventGetter* aEvent ) const
+    {
+    TDes& des = MUTABLE_CAST( TBuf<KLogsDetailsListAdaptorArrayLen>&, iBuffer );
+
+    des.Copy( iSentAmount->Des() ); 
+    des.Append( KTab );
+
+    TBuf<KLogsPhoneNumberMaxLen> buf;
+    buf.Zero();
+    
+    buf.Format( *iAmountKB, I64INT(aEvent->LogsEventData()->DataSent() / 1024) ); //iAmountKB: R_LOGS_DETAIL_VIEW_KB_TEXT
+    AknTextUtils::LanguageSpecificNumberConversion( buf ); 
+    des.Append( buf );
+    return ETrue;
+    }
+
+// ----------------------------------------------------------------------------
+// CLogsDetailAdapter::ReceivedAmountRow
+// ----------------------------------------------------------------------------
+//
+TBool CLogsDetailAdapter::ReceivedAmountRow( const MLogsEventGetter* aEvent ) const
+    {
+    TDes& des = MUTABLE_CAST( TBuf<KLogsDetailsListAdaptorArrayLen>&, iBuffer );
+
+    des.Copy( iReceivedAmount->Des() );
+    des.Append( KTab );
+
+    TBuf<KLogsPhoneNumberMaxLen> buf;
+    buf.Zero();
+
+    buf.Format( *iAmountKB, aEvent->LogsEventData()->DataReceived() / 1024 ); //iAmountKB: R_LOGS_DETAIL_VIEW_KB_TEXT
+    AknTextUtils::LanguageSpecificNumberConversion( buf ); 
+    des.Append( buf );
+    return ETrue;
+    }
+
+// ----------------------------------------------------------------------------
+// CLogsDetailAdapter::SetLineWidth
+//
+// Sets the maximum width in pixels for the detail line. This needs to be called from controller's
+// SizeChanged() method.
+// ----------------------------------------------------------------------------
+//
+void CLogsDetailAdapter::SetLineWidth(TInt aTextWidth)
+    {
+    iTextWidth = aTextWidth;
+    iListboxFont = LineFont();  //Update font too as probably it has also changed.
+    }
+    
+// ----------------------------------------------------------------------------
+// CLogsDetailAdapter::LineFont
+// ----------------------------------------------------------------------------
+//
+const CFont* CLogsDetailAdapter::LineFont()
+    {
+    TAknTextLineLayout line = AknLayout::List_pane_texts__single_heading__Line_2(0 );  //Same in CLogsDetailControlContainer::SizeChanged
+    TAknLayoutText text;
+    text.LayoutText( iListBox->Rect(), line );  
+    return text.Font();   // text.Font() not owned
+    } 
+
+// ----------------------------------------------------------------------------
+// CLogsDetailAdapter::Reverse
+// ----------------------------------------------------------------------------
+//
+void CLogsDetailAdapter::Reverse(TDes& aText ) const
+    {
+    for(int i=0,j=aText.Length() - 1; i < j ; i++, j--)
+        {
+        TUint16 tmp = aText[i];
+        aText[i] =  aText[j];
+        aText[j] = tmp;
+        }
+    }
+
+//  End of File