homesync/contentmanager/mediaservant/src/msmultiselectiondialog.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Thu, 17 Dec 2009 08:52:00 +0200
changeset 0 7f85d04be362
permissions -rw-r--r--
Revision: 200947 Kit: 200951

/*
* Copyright (c) 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:  CMSMultiselectionDialog class implementation
*
*/



// INCLUDE FILES
#include <akntitle.h>
#include <avkon.mbg>
#include <aknlists.h>
#include <akncheckboxsettingpage.h>
#include <mediaservant.rsg>

#include "msmultiselectiondialog.h"
#include "mediaservant.hrh"
#include "msconstants.h"
#include "msdebug.h"


//CONSTANTS

// Reserved list items at a time
const TInt KListGranularity = 10;
// Used for item icon definition
_LIT(KOneSlashT, "1\t");


// --------------------------------------------------------------------------
// CMSMultiselectionDialog::NewL
// --------------------------------------------------------------------------
//
CMSMultiselectionDialog* CMSMultiselectionDialog::NewL(
                                            CSelectionItemList* aItemArray,
                                            const TDesC& aTitle )
    {
    LOG(_L("[UPNP_HOMECONNECT]\t CMSMultiselectionDialog::NewL"));

    CMSMultiselectionDialog* self =
                    CMSMultiselectionDialog::NewLC( aItemArray, aTitle );                        
    CleanupStack::Pop(self);

    return self;
    }

// --------------------------------------------------------------------------
// CMSMultiselectionDialog::NewLC
// --------------------------------------------------------------------------
//
CMSMultiselectionDialog* CMSMultiselectionDialog::NewLC(
                                            CSelectionItemList* aItemArray,
                                            const TDesC& aTitle )
    {
    LOG(_L("[UPNP_HOMECONNECT]\t CMSMultiselectionDialog::NewLC"));

    CMSMultiselectionDialog* self =
                        new(ELeave) CMSMultiselectionDialog( aItemArray );

    CleanupStack::PushL(self);
    self->ConstructL( aTitle );

    return self;
    }
    
// --------------------------------------------------------------------------
// CMSMultiselectionDialog::ConstructL
// Symbian 2nd phase constructor can leave.
// --------------------------------------------------------------------------
//
void CMSMultiselectionDialog::ConstructL( const TDesC& aTitle )
    {
    LOG(_L("[UPNP_HOMECONNECT]\t CMSMultiselectionDialog::\
    ConstructL"));

    // base class call
    // menubar id has no effect because options menu is not used
    CAknSelectionListDialog::ConstructL( R_MS_MENUBAR_MAIN_VIEW );
    
    // keep safe previous view title
    iPreviousTitle = HBufC::NewL( KMaxFileName );

    // set dialog title
    CEikStatusPane* statusPane =
                    (( CAknAppUi* )iEikonEnv->EikAppUi() )->StatusPane();
    iTitlePane = (CAknTitlePane*)statusPane->ControlL(
                    TUid::Uid(EEikStatusPaneUidTitle));
    // keep previous title safe
    iPreviousTitle->Des().Copy( *iTitlePane->Text() );
    // set new title
    iTitlePane->SetTextL(aTitle);
    }


// --------------------------------------------------------------------------
// CMSMultiselectionDialog::CMSMultiselectionDialog
// C++ default constructor can NOT contain any code, that
// might leave.
// --------------------------------------------------------------------------
//
CMSMultiselectionDialog::CMSMultiselectionDialog(
                                CSelectionItemList* aItemArray)
: CAknSelectionListDialog(iSelectedItem, NULL, NULL),
  iItemArray (aItemArray)
    {
    LOG(_L("[UPNP_HOMECONNECT]\t CMSMultiselectionDialog:: \
    CMSMultiselectionDialog"));
    }

// --------------------------------------------------------------------------
// CMSMultiselectionDialog::CMSMultiselectionDialog
// C++ default destructor.
// --------------------------------------------------------------------------
//
CMSMultiselectionDialog::~CMSMultiselectionDialog()
    {
    LOG(_L("[UPNP_HOMECONNECT]\t CMSMultiselectionDialog:: \
    ~CMSMultiselectionDialog"));

    // set previous title back
    if( iTitlePane )
        {
        TInt error = KErrNone;
        TRAP( error, iTitlePane->SetTextL( *iPreviousTitle ) );
        if( error )
            {
            TRACE( Print(_L("[UPNP_HOMECONNECT]\t CMSMultiselectionDialog\
                  SetTextL error %d\n"),error ) );
            }
        }
    
    delete iPreviousTitle;

    delete iInternalItemArray;

    delete iNaviDecorator;
    }


// --------------------------------------------------------------------------
// CMSMultiselectionDialog::OkToExitL(TInt aButtonId)
// called by framework when the softkey is pressed
// --------------------------------------------------------------------------
//
TBool CMSMultiselectionDialog::OkToExitL(TInt aButtonId)
    {
    LOG(_L("[UPNP_HOMECONNECT]\t CMSMultiselectionDialog::\
    OkToExitL"));

    TBool retval = ETrue;
    
    // When using middle softkey list update must be called from
    // this way because dialog doesn't receive middle softkey key
    // event.
    if ( aButtonId == EAknSoftkeyChange )
        {
        HandleSelectionKeyPressL();
        // don't exit dialog
        retval = EFalse;
        }

    if ( retval ) 
        {
        // Update item selections to the list
        UpdateAllSelectionsL();

        // Clear navi pane text
        iNaviPane->Pop( iNaviDecorator );

        if ( aButtonId == EAknSoftkeyBack )
            {
            iAvkonAppUi->ProcessCommandL( EEikCmdExit );
            }
        }

    return retval;
    }


// --------------------------------------------------------------------------
// CMSMultiselectionDialog::PreLayoutDynInitL()
// called by framework before dialog is shown
// --------------------------------------------------------------------------
//
void CMSMultiselectionDialog::PreLayoutDynInitL()
    {
    LOG(_L("[UPNP_HOMECONNECT]\t CMSMultiselectionDialog:: \
    PreLayoutDynInitL"));

    iListBox = static_cast<CAknSingleGraphicStyleListBox*>
                            (Control(EMultiSelectionListBoxId));

    // display find box
    SetupFind(CAknSelectionListDialog::EFixedFind);

    CAknIconArray* icons = new (ELeave) CAknIconArray(2); //magic: icon count
    CleanupStack::PushL( icons );

    MAknsSkinInstance* skin = AknsUtils::SkinInstance();
    TFileName iconsPath( AknIconUtils::AvkonIconFileName() );

    AppendIconToArrayL( icons, skin,
                        iconsPath,
                        KAknsIIDQgnPropCheckboxOn,
                        EMbmAvkonQgn_indi_checkbox_on,
                        EMbmAvkonQgn_indi_checkbox_on_mask );

    AppendIconToArrayL( icons, skin,
                        iconsPath,
                        KAknsIIDQgnPropCheckboxOff,
                        EMbmAvkonQgn_indi_checkbox_off,
                        EMbmAvkonQgn_indi_checkbox_off_mask );


    iListBox->ItemDrawer()->ColumnData()->SetIconArray(icons);
    CleanupStack::Pop(icons);

    GenerateInternalArrayL();

    CEikStatusPane* statusPane=iEikonEnv->AppUiFactory()->StatusPane();

    // Set empty navi pane text
    iNaviPane = static_cast<CAknNavigationControlContainer*>
            ( statusPane->ControlL( TUid::Uid( EEikStatusPaneUidNavi ) ) );
                // ownership of decorator is transfered to application
    iNaviDecorator = iNaviPane->CreateNavigationLabelL( _L("") );
    iNaviPane->PushL( *iNaviDecorator );

    iListBox->ActivateL();
    CAknSelectionListDialog::PreLayoutDynInitL();
    }

// --------------------------------------------------------------------------
// CMSMultiselectionDialog::HandleSelectionKeyPressL()
// handles middle softkey press
// --------------------------------------------------------------------------
//
void CMSMultiselectionDialog::HandleSelectionKeyPressL()
    {
    LOG(_L("[UPNP_HOMECONNECT]\t CMSMultiselectionDialog::\
    HandleSelectionKeyPressL"));
    // Make special selection handling
    HandleSelectionsL();
    }

// --------------------------------------------------------------------------
// CMSMultiselectionSettingPage::HandlePointerEventL
// called by framework when the pointer device is pressed
// --------------------------------------------------------------------------
//
void CMSMultiselectionDialog::HandlePointerEventL(
                                const TPointerEvent& aPointerEvent ) 
	{
	CCoeControl::HandlePointerEventL( aPointerEvent );
	
	if ( TPointerEvent::EButton1Up == aPointerEvent.iType )
		{
		HandleSelectionKeyPressL();
		}
	}

// --------------------------------------------------------------------------
// CMSMultiselectionDialog::AppendIconToArray
// Load a possibly skinned icon (with mask) and append it to an
// icon array.
// --------------------------------------------------------------------------
//
void CMSMultiselectionDialog::AppendIconToArrayL(CAknIconArray* aArray,
                                               MAknsSkinInstance* aSkin,
                                               const TDesC& aMbmFile,
                                               const TAknsItemID& aID,
                                               TInt aBitmapId,
                                               TInt aMaskId) const
    {
    LOG(_L("[UPNP_HOMECONNECT]\t CMSMultiselectionDialog::\
    AppendIconToArrayL"));

    __ASSERT_DEBUG( aArray, User::Leave(KErrArgument) );

    CFbsBitmap* bitmap = NULL;
    CFbsBitmap* mask = NULL;

    AknsUtils::CreateIconLC(aSkin, aID,
        bitmap, mask, aMbmFile, aBitmapId, aMaskId);

    CGulIcon* icon = CGulIcon::NewL(bitmap, mask);
    icon->SetBitmapsOwnedExternally(EFalse);

    // icon now owns the bitmaps, no need to keep on cleanup stack.
    CleanupStack::Pop(2); // mask, bitmap
    bitmap = NULL;
    mask = NULL;

    CleanupStack::PushL(icon);

    aArray->AppendL(icon);

    // aArray now owns the icon, no need to delete.
    CleanupStack::Pop(icon);
    }

// --------------------------------------------------------------------------
// CMSMultiselectionDialog::GenerateInternalArrayL
// Creates an internal array shown by listbox
// --------------------------------------------------------------------------
//
void CMSMultiselectionDialog::GenerateInternalArrayL()
    {
    LOG(_L("[UPNP_HOMECONNECT]\t CMSMultiselectionDialog::\
    GenerateInternalArrayL"));


    // delete existing array
    delete iInternalItemArray;
    iInternalItemArray = 0;

    // Make a new owned text array from the input one:
    iInternalItemArray = new(ELeave)CDesCArrayFlat( KListGranularity );
    TInt count = iItemArray->Count();

    for (TInt index = 0; index < count; index++)
        {
        // Fill up the control-owned space for the modified buffers:
        TInt newLen =
            ((*iItemArray)[index]->ItemText()).Length() +
            KOneSlashT().Length();

        HBufC* newText = HBufC::NewMaxLC( newLen );

        TPtr newTPtr = newText->Des();        
        newTPtr.Copy( ((*iItemArray)[index])->ItemText() );
        
        // replace '\t' with space
        TInt offset = newTPtr.Find( KSlashT );
        if ( offset >= 0 )
            {
            TInt replaceCount = KSlashT().Length();
            newTPtr.Replace( offset, replaceCount, KSPaceT );    
            }        
        
        newTPtr.Insert( 0, KOneSlashT ); // magic: insert to the beginning
        
        // A copy of the new buffer goes to the internal itemarray:                
        iInternalItemArray->AppendL(newTPtr);
        CleanupStack::PopAndDestroy( newText );
        }

    CTextListBoxModel* model=iListBox->Model();
    model->SetItemTextArray(iInternalItemArray);
    model->SetOwnershipType(ELbmDoesNotOwnItemArray);

    // Transfer the selected status from
    // the input array into the listbox view
    SetAllSelectionsL();
    }

// --------------------------------------------------------------------------
// CMSMultiselectionDialog::SetAllSelectionsL
// Sets selection status of items
// --------------------------------------------------------------------------
//
void CMSMultiselectionDialog::SetAllSelectionsL()
    {
    LOG(_L("[UPNP_HOMECONNECT]\t CMSMultiselectionDialog::\
    SetAllSelectionsL"));

    TInt count = iItemArray->Count();

    CListBoxView* view = iListBox->View();

    for (TInt index = 0; index < count; index++)
        {
        if ( (*iItemArray)[ index ]->SelectionStatus() )
            {
            view->SelectItemL( index );
            }
        else
            {
            view->DeselectItem( index );
            }
        }
    }

// --------------------------------------------------------------------------
// CMSMultiselectionSettingPage::HandleSelectionsL
// Removes selection marks from other items if first one is selected
// --------------------------------------------------------------------------
//
void CMSMultiselectionDialog::HandleSelectionsL()
    {
    LOG(_L("[MediaServant]\t CMSMultiselectionDialog::\
    HandleSelectionsL"));
    CAknListBoxFilterItems* filter =
                    static_cast < CAknFilteredTextListBoxModel* >
                    ( iListBox->Model() )->Filter();
    const CArrayFix<TInt>* indexes = iListBox->View()->SelectionIndexes();
    if ( indexes->Count() )
        {
        TKeyArrayFix sortKey(0,ECmpTUint);
        TInt dummy;
        if ( FindBox()->TextLength() == 0 ||
             filter->VisibleItemIndex( 0 ) != KErrNotFound )
            {
            // Check if first item is selected
            if ( indexes->Find(0, sortKey, dummy) == 0 )
                {
                // clear all
                iListBox->View()->ClearSelection();
                
                // select current item
                iListBox->View()->SelectItemL( iListBox->CurrentItemIndex() );
                }
            else // first item not selected
                {
                // check if first item is highlighted
                if ( iListBox->CurrentItemIndex() == 0 )
                    {
                    // remove all selections...
                    iListBox->View()->ClearSelection();
                    }
                //...and toggle highlighted item
                iListBox->View()->ToggleItemL( iListBox->CurrentItemIndex() );
                
                // check if we don't have selected items
                if ( indexes->Count() == 0 )
                    {
                    // check the first one
                    iListBox->View()->SelectItemL(0);
                    }
                }
            }
        else
            {
            //...and toggle highlighted item
            iListBox->View()->ToggleItemL( iListBox->CurrentItemIndex() );

            // check if we don't have selected items
            if ( indexes->Count() == 0 )
                {
                // check the first one
                iListBox->View()->SelectItemL(0);
                }
            }
        }
    else // no items selected
        {
        iListBox->View()->SelectItemL(0);
        }
    }

// --------------------------------------------------------------------------
// CMSMultiselectionDialog::UpdateAllSelectionsL
// Updates selection status of the items in the item array
// --------------------------------------------------------------------------
//
void CMSMultiselectionDialog::UpdateAllSelectionsL()
    {
    LOG(_L("[UPNP_HOMECONNECT]\t CMSMultiselectionDialog::\
    UpdateAllSelectionsL"));

    TInt count = iItemArray->Count();

    CAknListBoxFilterItems* filter
                = static_cast < CAknFilteredTextListBoxModel* >
                                ( iListBox->Model() )->Filter();
    // reset filtering so that real selected indexes can be get
    filter->ResetFilteringL();

    CListBoxView* view = iListBox->View();

    for (TInt index = 0; index < count; index++)
        {
        (*iItemArray)[ index ]->SetSelectionStatus(
                                    view->ItemIsSelected( index ) );
        }
    }

// End of file