idlefw/plugins/mcsplugin/settings/src/mcspluginsettingsapplist.cpp
changeset 0 79c6a41cd166
child 1 844b978f8d5e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/idlefw/plugins/mcsplugin/settings/src/mcspluginsettingsapplist.cpp	Thu Dec 17 08:54:17 2009 +0200
@@ -0,0 +1,633 @@
+/*
+* Copyright (c) 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:  Application list for settings listbox
+*
+*/
+
+
+#include <e32cmn.h>
+#include <msvuids.h>        // For KMsvRootIndexEntryIdValue
+#include <SenduiMtmUids.h>
+#include <StringLoader.h>
+#include <aistrcnv.h>
+#include <featmgr.h>
+#include <mcsmenuitem.h>
+#include <mcsmenufilter.h>
+
+#include "mcspluginsettingsapplist.h"
+#include "mcspluginsettingsmodel.h"
+#include "mcspluginwatcher.h"
+
+_LIT( KMyMenuData, "matrixmenudata" );
+_LIT( KMenuTypeShortcut, "menu:shortcut" );
+_LIT( KMenuAttrRefcount, "ref_count" );
+_LIT( KMenuParamMailbox, "mailbox:" );
+_LIT( KMenuAttrParameter, "param" );
+_LIT( KMenuAttrLocked, "locked" );
+_LIT( KMenuIconFile, "aimcsplugin.mif" );
+_LIT( KMenuIconId, "16388" );
+_LIT( KMenuMaskId, "16389" );
+_LIT( KMailboxUid, "0x100058c5" );
+_LIT( KInitialRefCount, "1" );
+_LIT( KMCSFolder, "mcsplugin_folder" );
+_LIT( KSuiteName, "suite_name" );
+_LIT8( KItemLocked, "locked");
+_LIT8( KProperValueFolder, "folder" );
+_LIT8( KProperValueSuite, "suite" );
+
+
+
+// ======== MEMBER FUNCTIONS ========
+
+// ---------------------------------------------------------------------------
+// First-phase construction
+// ---------------------------------------------------------------------------
+//
+CMCSPluginSettingsAppList::CMCSPluginSettingsAppList()
+    {
+    iMCSPluginFolderId = 0;
+    }
+
+// ---------------------------------------------------------------------------
+// Second-phase construction
+// ---------------------------------------------------------------------------
+//
+void CMCSPluginSettingsAppList::ConstructL()
+    {
+    iMsvSession = CMsvSession::OpenAsObserverL(*this);
+
+    iMenu.OpenL( KMyMenuData );
+    iSaveWatcher = CMCSPluginWatcher::NewL( CMCSPluginWatcher::EOperation );
+    iUpdateWatcher = CMCSPluginWatcher::NewL( CMCSPluginWatcher::EOperation );
+    iRemoveWatcher = CMCSPluginWatcher::NewL( CMCSPluginWatcher::EOperation );
+    }
+
+// ---------------------------------------------------------------------------
+// Two-phased constructor
+// ---------------------------------------------------------------------------
+//
+CMCSPluginSettingsAppList* CMCSPluginSettingsAppList::NewL()
+    {
+    CMCSPluginSettingsAppList* self = new (ELeave) CMCSPluginSettingsAppList();
+    CleanupStack::PushL(self);
+    self->ConstructL();
+    CleanupStack::Pop(self);
+    return self;
+    }
+
+// ---------------------------------------------------------------------------
+// Destructor
+// ---------------------------------------------------------------------------
+//
+CMCSPluginSettingsAppList::~CMCSPluginSettingsAppList()
+    {
+    delete iMsvSession;
+
+    iListItems.ResetAndDestroy();
+    iMenu.Close();
+    delete iSaveWatcher;
+    delete iUpdateWatcher;
+    delete iRemoveWatcher;
+    
+    }
+
+// ---------------------------------------------------------------------------
+// From MDesCArray
+// Returns the number of descriptor elements in a descriptor array.
+// ---------------------------------------------------------------------------
+//
+TInt CMCSPluginSettingsAppList::MdcaCount() const
+    {
+    return iListItems.Count();
+    }
+
+// ---------------------------------------------------------------------------
+// From MDesCArray
+// Indexes into a descriptor array.
+// ---------------------------------------------------------------------------
+//
+TPtrC CMCSPluginSettingsAppList::MdcaPoint( TInt aIndex ) const
+    {
+    if (aIndex < 0 || aIndex >= iListItems.Count())
+        {
+        TPtrC ret(KNullDesC);
+        return ret;
+        }
+    CMenuItem* item = iListItems[aIndex];
+    TBool attrExists;
+    TPtrC itm; 
+    TRAP_IGNORE( 
+        itm.Set( item->GetAttributeL( KMenuAttrLongName, attrExists ) );
+        )
+    return itm;
+    }
+
+// ---------------------------------------------------------------------------
+// From class MMsvSessionObserver.
+// Handles an event from the message server.
+// ---------------------------------------------------------------------------
+//
+void CMCSPluginSettingsAppList::HandleSessionEventL(
+                                                  TMsvSessionEvent /*aEvent*/, 
+                                                  TAny* /*aArg1*/, 
+                                                  TAny* /*aArg2*/,
+                                                  TAny* /*aArg3*/ )
+    {
+
+    }
+
+// ---------------------------------------------------------------------------
+// Starts the asynchronous application list initialization.
+// ---------------------------------------------------------------------------
+//
+void CMCSPluginSettingsAppList::StartL()
+    {
+    iListItems.ResetAndDestroy();
+    AddMailboxesL();
+    AddStaticItemsL();
+    }
+
+// ---------------------------------------------------------------------------
+// Iterates thru the application list and tries to find a menuitem which 
+// matches given property map from HSPS
+// ---------------------------------------------------------------------------
+//
+TSettingItem CMCSPluginSettingsAppList::FindItemL( 
+        RPointerArray<HSPluginSettingsIf::CPropertyMap>& aProperties )
+    {
+    TBool attrExists( EFalse );
+    TSettingItem settingItem = { KErrNotFound, EApplication, EFalse };
+    TBool isFolder = EFalse;
+    TBool isSuite = EFalse;
+
+    // check if the item is folder or suite
+    for ( TInt j = 0; j < aProperties.Count(); j++ )
+        {
+        if( aProperties[j]->Name() == KType )
+            {
+
+            if ( aProperties[j]->Value() == KProperValueFolder )
+                {
+                isFolder = ETrue;
+                }
+
+            if ( aProperties[j]->Value() == KProperValueSuite )
+                {
+                isSuite = ETrue;
+                }          
+            break;
+            }
+        }   
+
+    TBool itemFound( EFalse );
+    
+    // compare name/value pairs with every menu item in the list
+    for ( TInt i = 0; i < iListItems.Count() && !itemFound; i++ )
+        {
+        TBool match( ETrue );
+        CMenuItem* item = iListItems[ i ];
+
+        for ( TInt j = 0; j < aProperties.Count() && match; j++ )
+            {
+            // type and locked properties skipped
+            if ( aProperties[j]->Name() != KType &&
+                 aProperties[j]->Name() != KItemLocked )
+                {
+                HBufC* attrName( NULL );
+                attrName = AiUtility::CopyToBufferL( attrName,
+                        aProperties[j]->Name());
+                CleanupStack::PushL( attrName );
+                TPtrC attr = item->GetAttributeL( *attrName, attrExists );
+
+                HBufC* attrValue( NULL );
+                attrValue = AiUtility::CopyToBufferL( attrValue,
+                        aProperties[j]->Value());
+                CleanupStack::PushL( attrValue );
+
+                // in case of folder, we just have to compare id
+                // which is stored in param attribute
+                if ( isFolder && *attrName == KMenuAttrParameter )
+                    {
+                    // convert id to integer
+                    TInt id;
+                    TLex16 lextmp( attrValue->Ptr() );
+                    lextmp.Val( id );
+
+                    if ( item->Id() != id )
+                        {
+                        match = EFalse;
+                        }
+                    CleanupStack::PopAndDestroy( attrValue );
+                    CleanupStack::PopAndDestroy( attrName );
+                    break;
+                    }
+
+                // in case of suite, we just have to compare suite_name
+                // which is stored in param attribute
+                if ( isSuite && *attrName == KMenuAttrParameter )
+                    {
+                    TBool exists;
+                    TPtrC suitename = item->GetAttributeL( KSuiteName, exists );
+
+                    if ( !exists || suitename != *attrValue )
+                        {
+                        match = EFalse;
+                        }
+                    CleanupStack::PopAndDestroy( attrValue );
+                    CleanupStack::PopAndDestroy( attrName );
+                    break;
+                    }
+
+                // otherwise, compare attributes from HSPS and from menuitem
+                // if there is no match, move to the next item in the list
+                if ( attr != *attrValue )
+                    {
+                    match = EFalse;
+                    }
+                CleanupStack::PopAndDestroy( attrValue );
+                CleanupStack::PopAndDestroy( attrName );
+                }
+            }
+
+        if ( match )
+            {
+            settingItem.id = i;
+            settingItem.type = EApplication;
+            itemFound = ETrue;
+            }
+        }
+    return settingItem;
+    }
+
+
+// ---------------------------------------------------------------------------
+// Returns menuitems at given index. Since this method is called during
+// adding the item to the Desktop widget, we also have to increment
+// ref_count attribute if the item is run-time generated (i.e. Mailbox)
+// ---------------------------------------------------------------------------
+//
+CMenuItem& CMCSPluginSettingsAppList::ItemL( const TInt& aIndex )
+    {
+
+    CMenuItem* menuItem( NULL );
+    
+    // check if index in within the list boundaries
+    if ( aIndex >= 0 && aIndex < iListItems.Count() )
+        {
+
+        menuItem = iListItems[ aIndex ];
+
+        TBool hasParam = EFalse;
+        CleanupStack::PushL( menuItem );
+        TPtrC param = menuItem->GetAttributeL( KMenuAttrParameter, hasParam ); 
+        CleanupStack::Pop( menuItem );
+
+        // if item is a mailbox, add it to MCS
+        // (if it is not already there)
+        if ( hasParam && param.Find( KMenuParamMailbox ) != KErrNotFound )
+            {
+
+            // set up a filter for finding the mailbox
+            // with given ID in MCS
+            CMenuFilter* filter = CMenuFilter::NewL();
+            CleanupStack::PushL( filter );
+
+            filter->SetType( KMenuTypeShortcut );
+            filter->HaveAttributeL( KMenuAttrParameter, param );
+
+            // search menu from the Root folder with the filter
+            const TInt rootId = iMenu.RootFolderL();
+            RArray<TMenuItem> itemArray;
+            CleanupClosePushL( itemArray );
+            iMenu.GetItemsL( itemArray, rootId, filter, ETrue );
+                
+            // save the number of findings
+            TInt count( itemArray.Count() );
+
+            // if MenuItem does not exist in MCS
+            if ( count == 0 )
+                {
+                // save the item into Matrixmenudata.xml
+                // the "op" variable is cleaned up by iSaveWatcher when asynchronous 
+                // operation finishes
+                CleanupStack::PushL( menuItem );
+                CMenuOperation* op = menuItem->SaveL( iSaveWatcher->iStatus );
+                CleanupStack::Pop( menuItem );
+                iSaveWatcher->Watch( op ); 
+                }
+            else
+                {
+                // Item already exists in MCS
+                // If it has reference counter, increment it before returning.
+                CMenuItem* itm = CMenuItem::OpenL( iMenu, itemArray[ 0 ] );
+
+                TInt newRefCount = UpdateMenuItemsRefCountL( itm, 1 );
+                if ( newRefCount > -1 )
+                    {
+                    CleanupStack::PushL( itm );
+                    CMenuOperation* op = itm->SaveL( iSaveWatcher->iStatus );
+                    CleanupStack::PopAndDestroy( itm );
+                    iSaveWatcher->Watch( op );
+                    }
+                }
+            CleanupStack::PopAndDestroy( &itemArray );
+            CleanupStack::PopAndDestroy( filter );
+            }
+        }
+    return *menuItem;
+    }
+
+// ---------------------------------------------------------------------------
+// Helper method for comparing names of two menuitems. Used to sort the list
+// of items.
+// ---------------------------------------------------------------------------
+//
+TInt CMCSPluginSettingsAppList::CompareNameL( const CMenuItem& aFirst,
+                                              const CMenuItem& aSecond )
+    {
+    TBool exists( EFalse );
+    CMenuItem& first = const_cast<CMenuItem&>(aFirst);
+    CMenuItem& second = const_cast<CMenuItem&>(aSecond);
+    
+    TPtrC name1 = first.GetAttributeL( KMenuAttrLongName, exists );
+    TPtrC name2 = second.GetAttributeL( KMenuAttrLongName, exists );
+    
+    return name1.CompareC( name2 );
+    }
+
+// ---------------------------------------------------------------------------
+// Adds the static list items to the application list.
+// ---------------------------------------------------------------------------
+//
+void CMCSPluginSettingsAppList::AddStaticItemsL()
+    {
+    TLinearOrder<CMenuItem> sortMethod( CMCSPluginSettingsAppList::CompareNameL );
+    
+    CMenuFilter* filter = CMenuFilter::NewL();
+    CleanupStack::PushL( filter );
+
+    // skip run-time generated items
+    filter->DoNotHaveAttributeL( KMenuAttrRefcount );
+    filter->DoNotHaveAttributeL( KMenuAttrLocked );
+    const TInt rootId = iMenu.RootFolderL();
+    RArray<TMenuItem> itemArray;
+    CleanupClosePushL( itemArray );
+    iMenu.GetItemsL( itemArray, rootId, filter, ETrue );
+    
+    TInt count( itemArray.Count() );
+    
+    for ( TInt i = 0; i < count; i++ )
+        {
+        TPtrC type = itemArray[ i ].Type();
+        
+        // we add applications, shortcuts, folders and suites to the list
+        if ( type == KMenuTypeApp || type == KMenuTypeShortcut || 
+             type == KMenuTypeFolder || type == KMenuTypeSuite )
+            {
+            CMenuItem* menuItem = CMenuItem::OpenL( iMenu, itemArray[ i ] );
+            CleanupStack::PushL( menuItem );
+
+            // only non-hidden and non-missing items should be offered to the user
+            if ( ( menuItem->Flags() & TMenuItem::EHidden ) == EFalse &&
+                 ( menuItem->Flags() & TMenuItem::EMissing ) == EFalse )
+                {
+                User::LeaveIfError( iListItems.InsertInOrderAllowRepeats( menuItem, sortMethod ) );
+                CleanupStack::Pop( menuItem );
+                }
+            else 
+                {
+                CleanupStack::PopAndDestroy( menuItem );
+                }
+            menuItem = NULL;
+            }
+        }
+
+    CleanupStack::PopAndDestroy( &itemArray );
+    CleanupStack::PopAndDestroy( filter );
+    }
+
+
+// ---------------------------------------------------------------------------
+// Returns the root entry containing mailboxes.
+// ---------------------------------------------------------------------------
+//
+CMsvEntry* CMCSPluginSettingsAppList::GetRootEntryL()
+    {
+    return iMsvSession->GetEntryL(KMsvRootIndexEntryIdValue);
+    }
+
+// ---------------------------------------------------------------------------
+// Adds remote mailboxes to the application list.
+// ---------------------------------------------------------------------------
+//
+void CMCSPluginSettingsAppList::AddMailboxesL()
+    {
+    
+    iListItems.ResetAndDestroy();
+    CMsvEntry* rootEntry = GetRootEntryL();
+    CleanupStack::PushL(rootEntry);
+    TBuf<255> mailboxId;
+    
+    for ( TInt i = rootEntry->Count() - 1; i >= 0; --i )
+        {
+        const TMsvEntry& tentry = (*rootEntry)[i];
+
+        if (tentry.iMtm == KSenduiMtmImap4Uid || tentry.iMtm == KSenduiMtmPop3Uid)
+            {
+            mailboxId.Num( tentry.Id() );  
+            AddMailboxL( tentry.iDetails, mailboxId );
+            }
+        }
+    CleanupStack::PopAndDestroy(rootEntry);
+    }
+
+// ---------------------------------------------------------------------------
+// Adds a mailbox to the list.
+// ---------------------------------------------------------------------------
+//
+void CMCSPluginSettingsAppList::AddMailboxL( const TDesC& aMailbox,
+                                             const TDesC& aMailboxId )
+    {
+        // prepare param value
+        HBufC* params = HBufC::NewLC( KMenuParamMailbox().Length() + aMailboxId.Length() );
+        params->Des().Copy( KMenuParamMailbox );
+        params->Des().Append( aMailboxId );
+        TPtrC paramValue( params->Des() );
+
+        TLinearOrder<CMenuItem> sortMethod( CMCSPluginSettingsAppList::CompareNameL );
+        CMenuItem* newItem = CMenuItem::CreateL( iMenu, 
+                                                 KMenuTypeShortcut, 
+                                                 GetMCSPluginFolderIdL(), 
+                                                 0 );
+        CleanupStack::PushL( newItem );
+
+        // mailbox is a shortcut item with "mailbox:mailboxID" parameter
+        newItem->SetAttributeL( KMenuAttrUid, KMailboxUid );
+        newItem->SetAttributeL( KMenuAttrLongName, aMailbox );
+        newItem->SetAttributeL( KMenuAttrParameter, paramValue );
+        newItem->SetAttributeL( KMenuAttrRefcount, KInitialRefCount );
+
+        // setting icon for the shortcut
+        newItem->SetAttributeL( KMenuAttrIconFile, KMenuIconFile );
+        newItem->SetAttributeL( KMenuAttrIconId, KMenuIconId );
+        newItem->SetAttributeL( KMenuAttrMaskId, KMenuMaskId );
+
+        // append the item into iListItems lists
+        User::LeaveIfError( iListItems.InsertInOrderAllowRepeats( newItem, sortMethod ) );
+        CleanupStack::Pop( newItem );
+        CleanupStack::PopAndDestroy( params );
+    }
+
+// ---------------------------------------------------------------------------
+// Removes run-time generated menuitem (i.e. Mailbox) from MCS
+// If the item at given index is not run-time generated, return
+// ---------------------------------------------------------------------------
+//
+void CMCSPluginSettingsAppList::RemoveMenuItemL( TInt aIndex )
+    {
+
+    if ( aIndex < 0 || aIndex > iListItems.Count() - 1 )
+        {
+        return;
+        }
+
+    CMenuItem* menuItem = iListItems[ aIndex ];
+    
+    TBool hasParam = ETrue;
+    TPtrC param = menuItem->GetAttributeL( KMenuAttrParameter, hasParam );
+
+    if ( !hasParam )
+        {
+        // nothing to do
+        return;
+        }
+
+    // set up a filter for finding the mailbox
+    // with given ID in MCS
+    CMenuFilter* filter = CMenuFilter::NewL();
+    CleanupStack::PushL( filter );
+
+    filter->SetType( KMenuTypeShortcut );
+    filter->HaveAttributeL( KMenuAttrParameter, param );
+
+    // search menu from the Root folder with the filter
+    const TInt rootId = iMenu.RootFolderL();
+    RArray<TMenuItem> itemArray;
+    CleanupClosePushL( itemArray );
+    iMenu.GetItemsL( itemArray, rootId, filter, ETrue );
+
+    // save the number of findings
+    TInt count( itemArray.Count() );
+    
+    if ( count > 0 )
+        {
+        // Item already exists in MCS
+        // If it has reference counter, increment it before returning.
+        CMenuItem* itm = CMenuItem::OpenL( iMenu, itemArray[ 0 ] );
+        
+        // decrement ref_count attribute 
+        TInt newRefCount = UpdateMenuItemsRefCountL( itm, -1 );
+        if ( newRefCount > 0 )
+            {
+            CleanupStack::PushL( itm ); 
+            CMenuOperation* op = itm->SaveL( iUpdateWatcher->iStatus );
+            CleanupStack::Pop( itm );
+            iUpdateWatcher->Watch( op );
+            }
+        else if ( newRefCount == 0 )
+            {
+            // counter reached 0 -> item is not referenced by any shortcut
+            // so remove it from MCS
+            if ( iRemoveWatcher->IsActive() )
+               {
+               return;
+               }
+            CMenuOperation* op = iMenu.RemoveL( itm->Id(), iRemoveWatcher->iStatus );
+            iRemoveWatcher->Watch( op );
+            }
+            delete itm;
+        }
+    CleanupStack::PopAndDestroy( &itemArray );
+    CleanupStack::PopAndDestroy( filter );
+    }
+
+// ---------------------------------------------------------------------------
+// Gets MCS Plugin folder ID. This hidden folder in matrixmenudata.xml is used 
+// for storing run-time generated menuitems
+// ---------------------------------------------------------------------------
+//
+TInt CMCSPluginSettingsAppList::GetMCSPluginFolderIdL()
+    {
+    
+    if ( iMCSPluginFolderId == 0 )
+        {
+        CMenuItem* item( NULL );
+        CMenuFilter* filter = CMenuFilter::NewL();
+        CleanupStack::PushL( filter );
+        filter->SetType( KMenuTypeFolder );
+        filter->HaveAttributeL( KMenuAttrLongName, KMCSFolder );
+        const TInt rootId = iMenu.RootFolderL();
+        RArray<TMenuItem> itemArray;
+        CleanupClosePushL( itemArray );
+        iMenu.GetItemsL( itemArray, rootId, filter, ETrue );
+        if ( itemArray.Count() > 0 )
+            {
+            item = CMenuItem::OpenL( iMenu, itemArray[ 0 ] );
+            iMCSPluginFolderId = item->Id();
+            }
+        else 
+            {
+            iMCSPluginFolderId = iMenu.RootFolderL();
+            }
+        CleanupStack::PopAndDestroy( &itemArray );
+        CleanupStack::PopAndDestroy( filter ); 
+        delete item; 
+        }
+    return iMCSPluginFolderId;
+    
+    }
+
+// ---------------------------------------------------------------------------
+// Helper method for updating ref_count attribute of run-time generated 
+// menuitems
+// ---------------------------------------------------------------------------
+//
+TInt CMCSPluginSettingsAppList::UpdateMenuItemsRefCountL( CMenuItem* aItem, 
+                                                          TInt aValueToAdd )
+    {
+    
+    TBool exists = EFalse;
+    CleanupStack::PushL( aItem ); 
+    TPtrC param = aItem->GetAttributeL( KMenuAttrRefcount, exists );
+    CleanupStack::Pop( aItem );
+    if ( exists )
+        {
+        TInt references;
+        TLex16 lextmp( param );
+        lextmp.Val( references );
+        references += aValueToAdd;
+        TBuf<128> buf;
+        buf.NumUC( references );
+        // set new ref_count
+        CleanupStack::PushL( aItem ); 
+        aItem->SetAttributeL( KMenuAttrRefcount, buf );
+        CleanupStack::Pop( aItem );
+        // return new ref_count
+        return references;
+        }
+    return -1;
+    }
+
+
+// End of File.