iaupdate/IAD/ui/src/iaupdatehistorycontainer.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Wed, 13 Oct 2010 14:40:19 +0300
branchRCL_3
changeset 81 42552535c1ac
parent 66 8b7f4e561641
permissions -rw-r--r--
Revision: 201038 Kit: 201041

/*
* Copyright (c) 2007-2010 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:   This module contains the implementation of 
*                CIAUpdateHistoryContainer class member functions.
*
*/




#include <coemain.h>
#include <aknlists.h> // For the listbox
#include <barsread.h> // TResourceReader
#include <avkon.mbg>
#include <AknIconArray.h> 
#include <gulicon.h>
#include <AknsUtils.h>
#include <StringLoader.h> 
#include <e32std.h>
#include <data_caging_path_literals.hrh>
#include <iaupdate.rsg>
#include <iaupdate.mbg>

#include "iaupdatehistorycontainer.h"
#include "iaupdatehistory.h"
#include "iaupdatehistoryitem.h"
#include "iaupdateutils.h"


// MACROS
_LIT(KIAUpdateIconFileName, "IAUpdate.mif");
// Format for TTime
// See: C++ API reference » Date and Time Handling » Using TTime 
_LIT( KDateFormat, "%*D%*M%Y%/0%4%/1%5" );
_LIT( KTimeFormat, "%-B%:0%J%:1%T%+B" );
_LIT( KIconIndexFormat, "%d" );
_LIT( KTabulator, "\t" );

//CONSTANTS
// Item list granularity
const TInt KListGranularity( 8 );
// There will be two images. One for error and for success.
const TInt KListIconGranularity( 2 );
const TInt KTimeLength( 48 );
// Icon index length is always one because an index is either zero or one
const TInt iconIndexLength( 1 );

// -----------------------------------------------------------------------------
// CIAUpdateHistoryContainer::NewL
// Two-phased constructor.
// -----------------------------------------------------------------------------
//
CIAUpdateHistoryContainer* CIAUpdateHistoryContainer::NewL( const TRect& aRect )
    {
    CIAUpdateHistoryContainer* self = 
        CIAUpdateHistoryContainer::NewLC( aRect );
    CleanupStack::Pop(self);
    return self;
    }

// -----------------------------------------------------------------------------
// CIAUpdateHistoryContainer::NewLC
// 
// -----------------------------------------------------------------------------
//
CIAUpdateHistoryContainer* CIAUpdateHistoryContainer::NewLC( const TRect& aRect )
    {
    CIAUpdateHistoryContainer* self = 
        new (ELeave) CIAUpdateHistoryContainer();
    CleanupStack::PushL( self );
    self->ConstructL( aRect );
    return self;
    }

// -----------------------------------------------------------------------------
// CIAUpdateHistoryContainer::CIAUpdateHistoryContainer
// C++ default constructor can NOT contain any code, that
// might leave.
// -----------------------------------------------------------------------------
//
CIAUpdateHistoryContainer::CIAUpdateHistoryContainer() 
: CCoeControl()
    {
    }

// -----------------------------------------------------------------------------
// CIAUpdateHistoryContainer::~CIAUpdateHistoryContainer
// Destructor
// -----------------------------------------------------------------------------
//
CIAUpdateHistoryContainer::~CIAUpdateHistoryContainer()
    {
    delete iListBox;
    }

// -----------------------------------------------------------------------------
// CIAUpdateHistoryContainer::ConstructL
// Symbian 2nd phase constructor can leave.
// -----------------------------------------------------------------------------
//
void CIAUpdateHistoryContainer::ConstructL( const TRect& aRect )
    {
    // Create a window for this application view
    CreateWindowL();

    // Create list box
    iListBox = new( ELeave ) CAknDoubleGraphicStyleListBox();
    iListBox->SetContainerWindowL( *this );
    
    TResourceReader reader;
    // Inserts reader into the cleanupstack.
    iEikonEnv->CreateResourceReaderLC( reader, R_IAUPDATE_HISTORY_LIST );
    iListBox->ConstructFromResourceL( reader );
    CleanupStack::PopAndDestroy();

    iListBox->EnableStretching( EFalse );
    iListBox->ItemDrawer()->ColumnData()->EnableMarqueeL( ETrue );

    // Setup scroll bars
    iListBox->CreateScrollBarFrameL( ETrue );
    iListBox->
        ScrollBarFrame()->
            SetScrollBarVisibilityL( 
                CEikScrollBarFrame::EOff, 
                CEikScrollBarFrame::EOff );    
    // Create item text array
    iItemTextArray = new( ELeave ) CDesCArrayFlat( KListGranularity );    
    iListBox->Model()->SetItemTextArray( iItemTextArray );
    // Ownership of the array is transferred.
    iListBox->Model()->SetOwnershipType( ELbmOwnsItemArray );
        
    HBufC* text = StringLoader::LoadLC( R_IAUPDATE_NO_UPDATES_DONE );    
    iListBox->View()->SetListEmptyTextL( *text );
    CleanupStack::PopAndDestroy( text );

    // Create icon array
    
    CFbsBitmap* bitmap( NULL );
    CFbsBitmap* mask( NULL );

    CArrayPtr<CGulIcon>* iconArray = 
        new( ELeave ) CAknIconArray( KListIconGranularity );    
    CleanupStack::PushL( iconArray );
    
    HBufC* iconFilePath = HBufC::NewLC( KDC_APP_BITMAP_DIR().Length() + 
                                        KIAUpdateIconFileName().Length() );
    TPtr ptr = iconFilePath->Des();
    ptr.Append( KDC_APP_BITMAP_DIR );
    ptr.Append( KIAUpdateIconFileName );
    
    MAknsSkinInstance* skin = AknsUtils::SkinInstance();
    
        
    // This method puts both aBitmap and aMask in the cleanup stack.
    AknsUtils::CreateIconLC(
        skin,
        KAknsIIDQgnPropCaleAccepted,
        bitmap, 
        mask, 
        *iconFilePath, 
        EMbmIaupdateQgn_prop_cale_accepted, 
        EMbmIaupdateQgn_prop_cale_accepted_mask );
    CGulIcon* icon = CGulIcon::NewLC();
    icon->SetBitmap( bitmap );
    icon->SetMask( mask );
    icon->SetBitmapsOwnedExternally( EFalse );
    iconArray->AppendL( icon );
    CleanupStack::Pop( icon );
    CleanupStack::Pop( mask );
    CleanupStack::Pop( bitmap );

    // This method puts both aBitmap and aMask in the cleanup stack.
    AknsUtils::CreateIconLC(
        skin,
        KAknsIIDQgnPropSwupdFailed,
        bitmap, 
        mask, 
        *iconFilePath, 
        EMbmIaupdateQgn_prop_swupd_failed, 
        EMbmIaupdateQgn_prop_swupd_failed_mask);
    icon = CGulIcon::NewLC();
    icon->SetBitmap( bitmap );
    icon->SetMask( mask );
    icon->SetBitmapsOwnedExternally( EFalse );
    iconArray->AppendL( icon );
    CleanupStack::Pop( icon );
    CleanupStack::Pop( mask );
    CleanupStack::Pop( bitmap );
    
    CleanupStack::PopAndDestroy( iconFilePath );    
    CleanupStack::Pop( iconArray );
    iListBox->ItemDrawer()->ColumnData()->SetIconArray( iconArray );

    // Set the windows size
    SetRect( aRect );

    // Activate the window, which makes it ready to be drawn
    ActivateL();
    }

// -----------------------------------------------------------------------------
// CIAUpdateHistoryContainer::RefreshL
// 
// -----------------------------------------------------------------------------
//    
void CIAUpdateHistoryContainer::RefreshL( MIAUpdateHistory& aHistory )
    {
    iItemTextArray->Reset();
    
    MIAUpdateHistoryItem* item( NULL ); 
    const RPointerArray< MIAUpdateHistoryItem >& items =
        aHistory.Items();
    TInt iconIndex( 0 );
    for( TInt i = 0; i < items.Count(); ++i ) 
        {
        item = items[i];                
        iconIndex = 0;
        if ( item->LastOperationErrorCode() != KErrNone
             || item->StateL() != MIAUpdateHistoryItem::EInstalled )
            {
            // If there was an error in the last operation
            // or if the node has not been installed, 
            // then use the second icon that is for
            // error situations.
            iconIndex = 1;
            }
        HBufC* nodeStateDescription = NodeStateDescriptionLC( *item );
        TPtr ptr = nodeStateDescription->Des();
        AknTextUtils::DisplayTextLanguageSpecificNumberConversion( ptr ); 
 
        HBufC* name = item->Name().AllocLC();
        TBuf<iconIndexLength> iconIndexBuf;
        iconIndexBuf.Format( KIconIndexFormat, iconIndex );

        HBufC* buffer = HBufC::NewLC( iconIndexBuf.Length() +
                                      KTabulator.iTypeLength + 
                                      name->Length() + 
                                      KTabulator.iTypeLength +
                                      nodeStateDescription->Length() );  

        buffer->Des() = iconIndexBuf;
        buffer->Des() += KTabulator();
        buffer->Des() += *name;
        buffer->Des() += KTabulator();
        buffer->Des() += *nodeStateDescription;        
         
        iItemTextArray->AppendL( *buffer );
                 
        CleanupStack::PopAndDestroy( buffer );
        CleanupStack::PopAndDestroy( name );
        CleanupStack::PopAndDestroy( nodeStateDescription );
        }    
    
    if ( items.Count() > 0 )
        {
    	iListBox->
        ScrollBarFrame()->
            SetScrollBarVisibilityL( 
                CEikScrollBarFrame::EOn, CEikScrollBarFrame::EAuto ); 
        }
    else
        {
        iListBox->
        ScrollBarFrame()->
            SetScrollBarVisibilityL( 
                CEikScrollBarFrame::EOff,CEikScrollBarFrame::EOff );	
        }     
    iListBox->HandleItemAdditionL();        
    }


// -----------------------------------------------------------------------------
// CIAUpdateHistoryContainer::OfferKeyEventL
// 
// -----------------------------------------------------------------------------
//
TKeyResponse CIAUpdateHistoryContainer::OfferKeyEventL( const TKeyEvent& aKeyEvent, 
                                                        TEventCode aType )
    {
    TKeyResponse response = EKeyWasNotConsumed;    

    if( aType == EEventKey )
        {
        switch( aKeyEvent.iCode )
            {
            // Up and down arrow actions are delegated to the listbox
            case EKeyUpArrow:
            case EKeyDownArrow:
                response = iListBox->OfferKeyEventL( aKeyEvent, aType );        
                break;
                
            case EKeyOK:
                // Nothing to do here
                break;
                
            default:
                // Nothing to do here
                break;
            }
        }

    return response;        
    }
    
// -----------------------------------------------------------------------------
// CIAUpdateHistoryContainer::SizeChanged
// 
// -----------------------------------------------------------------------------
//
void CIAUpdateHistoryContainer::SizeChanged()
    {
    iListBox->SetRect( Rect() );
    }

// -----------------------------------------------------------------------------
// CIAUpdateHistoryContainer::CountComponentControls
// 
// -----------------------------------------------------------------------------
//
TInt CIAUpdateHistoryContainer::CountComponentControls() const
    {
    return 1;
    }

// -----------------------------------------------------------------------------
// CIAUpdateHistoryContainer::ComponentControl
// 
// -----------------------------------------------------------------------------
//
CCoeControl* CIAUpdateHistoryContainer::ComponentControl( TInt aIndex ) const
    {
    CCoeControl* control( NULL );

    switch( aIndex )
        {
        case 0:
            control = iListBox;
            break;
            
        default:
            break;
        }

    return control;
    }
    
    
// ---------------------------------------------------------------------------
// CIAUpdateHistoryContainer::HandleResourceChange
// 
// ---------------------------------------------------------------------------
//
void CIAUpdateHistoryContainer::HandleResourceChange( TInt aType )
    {
	CCoeControl::HandleResourceChange( aType );

    if ( aType == KEikDynamicLayoutVariantSwitch ) //Handle change in layout orientation
        {
        TRect mainPaneRect;
        AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::EMainPane, mainPaneRect );
        SetRect( mainPaneRect );
		DrawNow();
		}
    }

// -----------------------------------------------------------------------------
// CIAUpdateHistoryContainer::NodeStateDescriptionLC
// 
// -----------------------------------------------------------------------------
//
HBufC* CIAUpdateHistoryContainer::NodeStateDescriptionLC( const MIAUpdateHistoryItem& aItem )
    {
    HBufC* stateDescription( NULL );

    MIAUpdateHistoryItem::TIAHistoryItemState state( aItem.StateL() );
    TInt errorCode( aItem.LastOperationErrorCode() );

    HBufC* timeDes = HBufC::NewLC( KTimeLength );
    TPtr tmpDes = timeDes->Des();
    
    // Get the current local time
    TTime currentTime( 0 );
    currentTime.HomeTime();

    TTime lastOperationTime = aItem.LastOperationTime();
    // Get the local time from the unviversal time.
    TLocale locale;
    lastOperationTime += locale.UniversalTimeOffset();
    
    if ( lastOperationTime - locale.UniversalTimeOffset() == 0 )
        {
        // Because the origianal universal operation time was zero, the given time
        // is not correct. Set the time string empty. So, we will not give wrong information.
        tmpDes.Copy( KNullDesC() );
        }
    else if ( currentTime.DayNoInYear() != lastOperationTime.DayNoInYear()
         || currentTime.DaysFrom( lastOperationTime ).Int() > 0 )
        {
        // Day has changed.
        // Just to be sure, other checking is done because year may have also changed.
        lastOperationTime.FormatL( tmpDes, KDateFormat() );       
        }
    else
        {
        // Same day
        lastOperationTime.FormatL( tmpDes, KTimeFormat() );       
        }      
    
    if ( errorCode == KErrNoMemory )
        {
        // Last operation could not be completed because we were out of memory.
        // Show this error text.
        stateDescription = StringLoader::LoadLC( R_IAUPDATE_TEXT_UPDATE_NO_MEMORY,
                                                 *timeDes ); 
        }
    else 
        {
        switch( state )
            {
            case MIAUpdateHistoryItem::EInstalled:
                if ( errorCode == KErrNone )
                    {
                    // Because item is installed successfully, everything has gone ok.
                    stateDescription = StringLoader::LoadLC( R_IAUPDATE_TEXT_UPDATE_SUCCESSFULL,
                                                             *timeDes );                    
                    }
                else if ( errorCode == KErrCancel )
                    {
                    // For some reason, the state says that an item has been installed,
                    // but the error code is cancel. In this case, trust the error code.
                    stateDescription = StringLoader::LoadLC( R_IAUPDATE_TEXT_INSTALL_CANCELLED,
                                                             *timeDes );
                    }
                else
                    {
                    // If everything goes ok, then the item should be installed.
                    // So, something has gone wrong because we are here. So,
                    // give the install failed message
                    stateDescription = StringLoader::LoadLC( R_IAUPDATE_TEXT_INSTALL_FAILED,
                                                             *timeDes );
                    }                
                break;

            case MIAUpdateHistoryItem::EDownloaded:
                if ( errorCode == KErrCancel )
                    {
                    // Because item has been downloaded but the error code is cancel
                    // this means that the install has been cancelled
                    stateDescription = StringLoader::LoadLC( R_IAUPDATE_TEXT_INSTALL_CANCELLED,
                                                             *timeDes );
                    }
                else
                    {
                    // If everything goes ok, then the item should be installed.
                    // So, something has gone wrong because we are here. So,
                    // give the install failed message
                    stateDescription = StringLoader::LoadLC( R_IAUPDATE_TEXT_INSTALL_FAILED,
                                                             *timeDes );
                    }
                break;

            case MIAUpdateHistoryItem::EPurchased:
                if ( errorCode == KErrCancel )
                    {
                    // Because item has been purchased but the error code is cancel
                    // this means that the download has been cancelled
                    stateDescription = StringLoader::LoadLC( R_IAUPDATE_TEXT_DOWNLOAD_CANCELLED,
                                                             *timeDes );
                    }
                else
                    {
                    // If everything goes ok, then the item should be installed.
                    // So, something has gone wrong because we are here. So,
                    // give the download failed message
                    stateDescription = StringLoader::LoadLC( R_IAUPDATE_TEXT_DOWNLOAD_FAILED,
                                                             *timeDes );
                    }
                break;
                                
            default:
                // We should never come here.
                stateDescription = KNullDesC().AllocLC();
                break;
            }        
        }
   
    CleanupStack::Pop( stateDescription );
    CleanupStack::PopAndDestroy( timeDes );
    CleanupStack::PushL( stateDescription );
         
    return stateDescription;
    }