homesync/contentmanager/mediaservant/src/msmultiselectiondialog.cpp
changeset 0 7f85d04be362
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/homesync/contentmanager/mediaservant/src/msmultiselectiondialog.cpp	Thu Dec 17 08:52:00 2009 +0200
@@ -0,0 +1,489 @@
+/*
+* 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