appinstaller/AppMngr2/src/appmngr2listcontainer.cpp
changeset 0 ba25891c3a9e
child 9 51c0f5edf5ef
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/appinstaller/AppMngr2/src/appmngr2listcontainer.cpp	Thu Dec 17 08:51:10 2009 +0200
@@ -0,0 +1,484 @@
+/*
+* Copyright (c) 2008-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:   Base class for AppMngr2 list view containers
+*
+*/
+
+
+#include "appmngr2listcontainer.h"      // CAppMngr2ListContainer
+#include "appmngr2appui.h"              // CAppMngr2AppUi
+#include "appmngr2model.h"              // CAppMngr2Model
+#include "appmngr2listview.h"           // CAppMngr2ListView
+#include "appmngr2.hrh"                 // Icon IDs
+#include <appmngr2runtime.h>            // CAppMngr2Runtime
+#include <appmngr2infobase.h>           // CAppMngr2InfoBase
+#include <appmngr2debugutils.h>         // FLOG macros
+#include <aknlists.h>                   // CAknDoubleLargeStyleListBox
+#include <eiktxlbm.h>                   // CTextListBoxModel
+#include <AknIconArray.h>               // CAknIconArray
+#include <StringLoader.h>               // StringLoader
+#include <gulicon.h>                    // CGulIcon
+
+const TInt KGranularity = 8;
+const TInt KSpaceForTabsAndIconIndexes = 9; // 3 tabs + 2 * 3 digits
+_LIT( KItemFormatFull,  "%d\t%S\t%S\t%d" );
+_LIT( KItemFormatNoInd, "%d\t%S\t%S" );
+
+
+// ======== MEMBER FUNCTIONS ========
+
+// ---------------------------------------------------------------------------
+// CAppMngr2ListContainer::CAppMngr2ListContainer()
+// ---------------------------------------------------------------------------
+//
+CAppMngr2ListContainer::CAppMngr2ListContainer( CAppMngr2ListView& aView )
+        : iView( aView )
+    {
+    }
+
+// ---------------------------------------------------------------------------
+// CAppMngr2ListContainer::~CAppMngr2ListContainer()
+// ---------------------------------------------------------------------------
+//
+CAppMngr2ListContainer::~CAppMngr2ListContainer()
+    {
+    delete iListBox;
+    delete iItemArray;
+    }
+
+// ---------------------------------------------------------------------------
+// CAppMngr2ListContainer::OfferKeyEventL()
+// ---------------------------------------------------------------------------
+//
+TKeyResponse CAppMngr2ListContainer::OfferKeyEventL(
+        const TKeyEvent& aKeyEvent, TEventCode aType )
+    {
+    TKeyResponse response = iListBox->OfferKeyEventL( aKeyEvent, aType ); 
+    if( aKeyEvent.iCode == EKeyUpArrow || aKeyEvent.iCode == EKeyDownArrow )
+        {
+        iView.UpdateMiddleSoftkeyCommandL();
+        iView.CurrentItemSelectedByUser( ETrue );
+        }
+    return response;
+    }
+
+// ---------------------------------------------------------------------------
+// CAppMngr2ListContainer::HandleResourceChange()
+// ---------------------------------------------------------------------------
+//
+void CAppMngr2ListContainer::HandleResourceChange( TInt aType )
+    {
+    CCoeControl::HandleResourceChange( aType );
+
+    if( aType == KAknsMessageSkinChange )
+        {
+        TRAP_IGNORE( LoadIconsL() );
+        }
+
+    if( aType == KEikDynamicLayoutVariantSwitch )
+        {
+        TRect mainPaneRect;
+        if( AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::EMainPane,
+                mainPaneRect ) )
+            {
+            SetRect( mainPaneRect );
+            }
+        DrawDeferred();
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CAppMngr2ListContainer::SizeChanged()
+// ---------------------------------------------------------------------------
+//
+void CAppMngr2ListContainer::SizeChanged()
+    {
+    if( iListBox )
+        {
+        iListBox->SetRect( Rect() );
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CAppMngr2ListContainer::CountComponentControls()
+// ---------------------------------------------------------------------------
+//
+TInt CAppMngr2ListContainer::CountComponentControls() const
+    {
+    return 1;   // always only iListBox
+    }
+
+// ---------------------------------------------------------------------------
+// CAppMngr2ListContainer::ComponentControl()
+// ---------------------------------------------------------------------------
+//
+CCoeControl* CAppMngr2ListContainer::ComponentControl( TInt /*aIndex*/ ) const
+    {
+    return iListBox;
+    }
+
+// ---------------------------------------------------------------------------
+// CAppMngr2ListContainer::HandleListBoxEventL()
+// ---------------------------------------------------------------------------
+//
+void CAppMngr2ListContainer::HandleListBoxEventL( CEikListBox* /*aListBox*/,
+        TListBoxEvent aEventType )
+    {
+    if( aEventType == EEventItemClicked || aEventType == EEventItemSingleClicked )
+        {
+        iView.UpdateMiddleSoftkeyCommandL();
+        iView.CurrentItemSelectedByUser( ETrue );
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CAppMngr2ListContainer::IsListEmpty()
+// ---------------------------------------------------------------------------
+//
+TBool CAppMngr2ListContainer::IsListEmpty() const
+    {
+    if( iItemArray )
+        {
+        return ( iItemArray->Count() == 0 );
+        }
+    return ETrue;
+    }
+
+// ---------------------------------------------------------------------------
+// CAppMngr2ListContainer::HandleGenericCommandL()
+// ---------------------------------------------------------------------------
+//
+void CAppMngr2ListContainer::HandleGenericCommandL( TInt aCommand )
+    {
+    if( !IsListEmpty() )
+        {
+        CAppMngr2InfoBase& currentItem = CurrentItem();
+        if( currentItem.SupportsGenericCommand( aCommand ) )
+            {
+            Model().HandleCommandL( currentItem, aCommand );
+            }
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CAppMngr2ListContainer::RefreshL()
+// ---------------------------------------------------------------------------
+//
+void CAppMngr2ListContainer::RefreshL( TBool aPreserveSelectedItem,
+        TBool& aSelectedItemChanged, TInt aMoreRefreshesExpected )
+    {
+    FLOG( "CAppMngr2ListContainer::RefreshL( %d )", aPreserveSelectedItem );
+    
+    // Record the item text of the current item if selection must be preserved in
+    // the current item. The item text is used to identify the item later, so that
+    // it can be selected again.
+    HBufC* itemText = NULL;
+    TInt currentItemIndex = iListBox->CurrentItemIndex();
+    if( aPreserveSelectedItem && currentItemIndex >= 0 )
+        {
+        itemText = (*iItemArray)[ currentItemIndex ].AllocL();
+        CleanupStack::PushL( itemText );
+        }
+
+    SetEmptyTextL( aMoreRefreshesExpected );    // defines empty text in first refresh
+    CreateItemArrayL();                         // resets the item array
+    PopulateItemArrayL();                       // fills in new items
+    iListBox->HandleItemAdditionL();            // re-calculates size and scrollbar
+    
+    // If selection must be preserved, search the item in new item array
+    // and select it again. Make sure to delete itemText if it was allocated.
+    TBool currentItemSet = EFalse;
+    TInt itemCount = iItemArray->Count();
+    if( itemText )
+        {
+        for( TInt index = 0; index < itemCount && !currentItemSet; index++ )
+            {
+            if( itemText->Compare( (*iItemArray)[ index ] ) == 0 )
+                {
+                iListBox->SetCurrentItemIndex( index );
+                currentItemSet = ETrue;
+                }
+            }
+        CleanupStack::PopAndDestroy( itemText );
+        }
+    
+    // If item is not found (it may have been deleted), then tell to the
+    // caller that the selected item was changed and select another item
+    // from the same row number than the previously selected item.
+    aSelectedItemChanged = !currentItemSet;
+    if( aSelectedItemChanged )
+        {
+        if( currentItemIndex >= itemCount )
+            {
+            currentItemIndex = itemCount - 1;
+            }
+        if( currentItemIndex < 0 )
+            {
+            currentItemIndex = 0;
+            }
+        if( currentItemIndex != iListBox->CurrentItemIndex() )
+            {
+            iListBox->SetCurrentItemIndex( currentItemIndex );
+            }
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CAppMngr2ListContainer::ConstructL()
+// ---------------------------------------------------------------------------
+//
+void CAppMngr2ListContainer::ConstructL( const TRect& aRect )
+    {
+    CreateWindowL();
+    SetRect( aRect );
+    iListBox = new (ELeave) CAknDoubleLargeStyleListBox;
+    iListBox->SetContainerWindowL( *this );
+    iListBox->ConstructL( this, EAknListBoxSelectionList );
+    iListBox->SetListBoxObserver( this );
+    
+    // Dont display default "(no data)" empty text
+    iListBox->View()->SetListEmptyTextL( KNullDesC );
+
+    LoadIconsL();
+    CreateItemArrayL();
+    PopulateItemArrayL();
+    
+    iListBox->CreateScrollBarFrameL();
+    iListBox->ScrollBarFrame()->SetScrollBarVisibilityL(
+            CEikScrollBarFrame::EOff, CEikScrollBarFrame::EAuto );
+    iListBox->SetRect( aRect.Size() );
+    
+    // Enable marquee effect
+    iListBox->ItemDrawer()->ColumnData()->EnableMarqueeL( ETrue );
+    }
+
+// ---------------------------------------------------------------------------
+// CAppMngr2ListContainer::Model()
+// ---------------------------------------------------------------------------
+//
+CAppMngr2Model& CAppMngr2ListContainer::Model() const
+    {
+    return reinterpret_cast<CAppMngr2AppUi*>( iEikonEnv->EikAppUi() )->Model();
+    }
+
+// ---------------------------------------------------------------------------
+// CAppMngr2ListContainer::LoadIconsL()
+// ---------------------------------------------------------------------------
+//
+void CAppMngr2ListContainer::LoadIconsL()
+    {
+    CAknIconArray* iconArray = new ( ELeave ) CAknIconArray( KGranularity );
+    CleanupStack::PushL( iconArray );
+    Model().LoadIconsL( *iconArray );
+    delete iListBox->ItemDrawer()->ColumnData()->IconArray();
+    iListBox->ItemDrawer()->ColumnData()->SetIconArray( iconArray );
+    CleanupStack::Pop( iconArray );
+    iItemSpecificIcons = 0;
+    }
+
+// ---------------------------------------------------------------------------
+// CAppMngr2ListContainer::CreateItemArrayL()
+// ---------------------------------------------------------------------------
+//
+void CAppMngr2ListContainer::CreateItemArrayL()
+    {
+    if( iItemArray )
+        {
+        iListBox->Model()->SetItemTextArray( NULL );
+        delete iItemArray;
+        iItemArray = NULL;
+        }
+    iItemArray = new ( ELeave ) CDesCArrayFlat( KGranularity );
+    iListBox->Model()->SetItemTextArray( iItemArray );
+    iListBox->Model()->SetOwnershipType( ELbmDoesNotOwnItemArray );
+    }
+
+// ---------------------------------------------------------------------------
+// CAppMngr2ListContainer::PopulateItemArrayL()
+// ---------------------------------------------------------------------------
+//
+void CAppMngr2ListContainer::PopulateItemArrayL()
+    {
+    FLOG( "CAppMngr2ListContainer::PopulateItemArrayL()" );
+    
+    CArrayPtr<CGulIcon>* iconArray = iListBox->ItemDrawer()->ColumnData()->IconArray();
+    DeleteItemSpecificIcons( *iconArray );
+    
+    TInt count = ItemCount();
+    for( TInt index = 0; index < count; index++ )
+        {
+        const CAppMngr2InfoBase& appInfo = ItemInfo( index );
+
+        // Get name and details
+        TPtrC name = appInfo.Name();
+        TPtrC size = appInfo.Details();
+
+        // Get icon indexes that plugin loaded in LoadIconsL()
+        TInt iconIndexBase;
+        TInt iconIndexMax;
+        Model().GetIconIndexesL( appInfo.Runtime().RuntimeUid(),
+                iconIndexBase, iconIndexMax );
+        
+        // Get list icon index from plugin
+        TInt iconIndex = appInfo.IconIndex();
+        
+        // Convert index into the range of 0 .. (icons - 1)
+        if( iconIndex == EAppMngr2UseSpecificIcon )
+            {
+            CGulIcon* icon = NULL;
+            TRAP_IGNORE( icon = appInfo.SpecificIconL() );
+            if( icon )
+                {
+                CleanupStack::PushL( icon );
+                iconIndex = iconArray->Count();
+                iconArray->AppendL( icon );
+                CleanupStack::Pop( icon );
+                iItemSpecificIcons++;
+                }
+            else
+                {
+                iconIndex = EAppMngr2IconIndex_QgnPropUnknown;
+                }
+            }
+        else
+            {
+            // There are no default list icons that plugins could use, so
+            // this must be list icon that plugin has loaded in LoadIconsL().
+            // Icons (of this plugin) are indexed from iconIndexBase.
+            iconIndex += iconIndexBase;
+
+            // Plugin should use only those icons it has provided. Use
+            // default unknown icon if plugin tries to use icons that
+            // another plugin has loaded.
+            if( iconIndex < iconIndexBase || iconIndex >= iconIndexMax )
+                {
+                iconIndex = EAppMngr2IconIndex_QgnPropUnknown;
+                }
+            }
+        // Sanity check - index must be in range, otherwise list panics 
+        if( iconIndex < 0 || iconIndex >= iconArray->Count() )
+            {
+            iconIndex = EAppMngr2IconIndex_QgnPropUnknown;
+            }
+
+        // Get indicator icon index from plugin
+        TInt indIconIndex = appInfo.IndicatorIconIndex();
+        
+        // Convert indicator icon index into the range of 0 .. (icons-1) or
+        // leave special value EAppMngr2NoIndicatorIcon in it
+        if( indIconIndex == EAppMngr2UseSpecificIcon )
+            {
+            CGulIcon* icon = NULL;
+            TRAP_IGNORE( icon = appInfo.SpecificIndicatorIconL() );
+            if( icon )
+                {
+                CleanupStack::PushL( icon );
+                indIconIndex = iconArray->Count();
+                iconArray->AppendL( icon );
+                CleanupStack::Pop( icon );
+                iItemSpecificIcons++;
+                }
+            else
+                {
+                indIconIndex = EAppMngr2NoIndicatorIcon;
+                }
+            }
+        else
+            {
+            // EAppMngr2NoIndicatorIcon is special value that is handled later
+            if( indIconIndex != EAppMngr2NoIndicatorIcon )
+                {
+                // Default icon indexes (starting from EAppMngr2NoIndicatorIcon) are
+                // all above the icon index range reserved for plugins
+                if( indIconIndex > EAppMngr2NoIndicatorIcon )
+                    {
+                    // Use default icons, indexes start from zero
+                    indIconIndex -= ( EAppMngr2NoIndicatorIcon + 1 );
+                    }
+                else
+                    {
+                    // Use item specific icons, indexes start from iconIndexBase
+                    indIconIndex += iconIndexBase;
+                    }
+                }
+            }
+        // Sanity check - icon index must be in range, otherwise list panics
+        if( ( indIconIndex != EAppMngr2NoIndicatorIcon ) &&
+                ( indIconIndex < 0 || indIconIndex >= iconArray->Count() ) )
+            {
+            indIconIndex = EAppMngr2NoIndicatorIcon;
+            }
+
+        // Construct line to be displayed
+        HBufC* temp = HBufC::NewLC( name.Length() + size.Length() + KSpaceForTabsAndIconIndexes );
+        TPtr line = temp->Des();
+        if( indIconIndex == EAppMngr2NoIndicatorIcon )
+            {
+            line.AppendFormat( KItemFormatNoInd, iconIndex, &name, &size );
+            }
+        else
+            {
+            line.AppendFormat( KItemFormatFull, iconIndex, &name, &size, indIconIndex );
+            }
+        iItemArray->AppendL( line );
+        FLOG( "CAppMngr2ListContainer::PopulateItemArrayL(): %S", temp );
+        CleanupStack::PopAndDestroy( temp );
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CAppMngr2ListContainer::DeleteItemSpecificIcons()
+// ---------------------------------------------------------------------------
+//
+void CAppMngr2ListContainer::DeleteItemSpecificIcons( CArrayPtr<CGulIcon>& aIconArray )
+    {
+    if( iItemSpecificIcons )
+        {
+        TInt iconArrayCount = aIconArray.Count();
+        TInt firstItemSpecificIcon = iconArrayCount - iItemSpecificIcons;
+        for( TInt index = firstItemSpecificIcon; index < iconArrayCount; index++ )
+            {
+            delete aIconArray[ index ];
+            }
+        aIconArray.Delete( firstItemSpecificIcon, iItemSpecificIcons );
+        iItemSpecificIcons = 0;
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CAppMngr2ListContainer::SetEmptyTextL()
+// ---------------------------------------------------------------------------
+//
+void CAppMngr2ListContainer::SetEmptyTextL( TInt aMoreRefreshesExpected )
+    {
+    // Set empty text if it is not already set
+    CListBoxView* view = iListBox->View();
+    if( view )
+        {
+        const TDesC* text = view->EmptyListText();
+        if( text == NULL || text->Length() == 0 )
+            {
+            // The first refresh may happen too soon. If there are no items
+            // to be displayed, and more refreshes are still expected, then
+            // do not set the empty text yet -- it would be displayed.
+            if( ItemCount() > 0 || !aMoreRefreshesExpected )
+                {
+                HBufC* emptyText = StringLoader::LoadLC( ListEmptyTextResourceId() );
+                view->SetListEmptyTextL( *emptyText );
+                CleanupStack::PopAndDestroy( emptyText );
+                }
+            }
+        }
+    }
+