idlefw/plugins/mcsplugin/publisher/src/mcsplugin.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Mon, 18 Jan 2010 20:32:13 +0200
changeset 2 b7904b40483f
parent 0 79c6a41cd166
child 9 d0529222e3f0
permissions -rw-r--r--
Revision: 201001 Kit: 201003

/*
* 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:  MCS plugin publisher
*
*/


#include <ecom/ecom.h>
#include <ecom/implementationproxy.h>
#include <gulicon.h>
#include <aicontentobserver.h>
#include <aiutility.h>
#include <aistrcnv.h>
#include <mcsmenuitem.h>

#include <aknskinsinternalcrkeys.h> // For working with settings API
#include <centralrepository.h> // Headers Used for CRepository

#include "mcspluginuids.hrh"
#include "mcsplugin.h"
#include "mcsplugindata.h"
#include "mcspluginengine.h"
#include "aipluginsettings.h"


const TUint KPluginNameSeprator =  '/';

const TInt KImplUidMCSPlugin = AI_UID_ECOM_IMPLEMENTATION_CONTENTPUBLISHER_MCSPLUGIN;
// CONST CLASS VARIABLES
const TImplementationProxy KImplementationTable[] =
    {
    IMPLEMENTATION_PROXY_ENTRY( KImplUidMCSPlugin, CMCSPlugin::NewL ) 
    };

_LIT( KEventNameLaunchByIndex,  "LaunchByIndex" );
_LIT( KEventNameShowSettings,   "ShowSettings" );
_LIT( KContentItemTypeText, "text" );
_LIT( KContentItemTypeImage, "image" );

// ======== LOCAL FUNCTIONS ========

// ======== MEMBER FUNCTIONS ========

// ---------------------------------------------------------------------------
// Symbian 2nd phase constructor can leave
// ---------------------------------------------------------------------------
//
CMCSPlugin* CMCSPlugin::NewL()
    {
    CMCSPlugin* self = new (ELeave) CMCSPlugin;
    CleanupStack::PushL( self );
    self->ConstructL();
    CleanupStack::Pop( self );
 
    return self;
    }
    
// ---------------------------------------------------------------------------
// Default constructor
// ---------------------------------------------------------------------------
//
CMCSPlugin::CMCSPlugin()
    {
    }
    
// ---------------------------------------------------------------------------
// Symbian 2nd phase constructor can leave
// ---------------------------------------------------------------------------
//
void CMCSPlugin::ConstructL()
    { 
    iInfo.iUid.iUid = AI_UID_ECOM_IMPLEMENTATION_CONTENTPUBLISHER_MCSPLUGIN; 
    // We need to Query Central Repository
    iRepository  = CRepository::NewL( KCRUidPersonalisation );

    // Setting up watcher which calls HandleNotifyL method 
    // everytime the SkinUID changes in central repository
    iRepositoryWatcher = CMCSPluginWatcher::NewL( CMCSPluginWatcher::ENotify );
    iRepository->NotifyRequest( KPslnActiveSkinUid, iRepositoryWatcher->iStatus );
    iRepositoryWatcher->WatchNotify( this );
    }

// ---------------------------------------------------------------------------
// Handle Skin UID change
// ---------------------------------------------------------------------------
//
void CMCSPlugin::HandleNotifyL()
    {

    // Skin ID has changed. Set all MenuItems on Widget dirty
    // and re-publish to update icons
    if ( iEngine )
        {
        TInt dataCount = iEngine->MenuItemCount();
        for ( TInt i = 0; i < dataCount; i++ )
            {
            iEngine->MenuDataL( i ).SetDirty( ETrue );
            }
        PublishL();
        }

    // Skin ID Notification must be activated again
    iRepositoryWatcher->Cancel();
    iRepository->NotifyRequest( KPslnActiveSkinUid, iRepositoryWatcher->iStatus );
    iRepositoryWatcher->WatchNotify( this );
    }
    
// ---------------------------------------------------------------------------
// Destructor
// Deletes all data created to heap
// ---------------------------------------------------------------------------
//
CMCSPlugin::~CMCSPlugin()
    {
    Release( iContent );
    
    if ( iEngine )
        {
        TRAP_IGNORE( iEngine->CleanMCSItemsL() );
        }
    
    delete iEngine;
    iObservers.Close();
    
    DeleteContentModel();

    if ( iRepository )
        {
        delete iRepository;
        iRepository = NULL;
        }

    if ( iRepositoryWatcher )
        {
        iRepositoryWatcher->Cancel();
        delete iRepositoryWatcher;
        iRepositoryWatcher = NULL;
        }
    }

// ---------------------------------------------------------------------------
// Publishes the all the items
// ---------------------------------------------------------------------------
//
void CMCSPlugin::PublishL()
    {
    
    if ( !iEngine )
        {
        iEngine = CMCSPluginEngine::NewL( *this, iInfo.iNamespace );
        }

    TInt err( KErrNone );
    TInt observers( iObservers.Count() );
    TInt transactionId = reinterpret_cast<TInt>( this );
    TInt menuItems ( iEngine->MenuItemCount() );

    for ( TInt i = 0; i < observers; i++ )
        {
        MAiContentObserver* observer = iObservers[ i ];
        err = observer->StartTransaction( transactionId );
        if ( err == KErrNotSupported )
            {
            return;
            }
        // Publish content to all items
        for ( TInt j = 0; j < menuItems; j++ )
            {
            // Index has to start from 1 ( j + 1 )
            PublishLItemL( *observer, iEngine->MenuDataL( j ), ( j + 1 ) );
            }// shortcut count
        if ( err == KErrNone )
            {
            err = observer->Commit( transactionId );
            if ( err == KErrNotSupported )
                {
                return;
                }
            }
        }//observers

    // Set all items not dirty.
    for ( TInt j = 0; j < menuItems; j++ )
        {
        iEngine->MenuDataL( j ).SetDirty( EFalse );
        }
    }

// ---------------------------------------------------------------------------
// Publishes one item to given index
// ---------------------------------------------------------------------------
//
void CMCSPlugin::PublishLItemL( MAiContentObserver& aObserver, TMCSData& aData, TInt aIndex )
    {

    if( !aData.IsDirty() )
        {
        return;
        }

    CMenuItem* item = iEngine->FetchMenuItemL( aData.MenuItem() );
    CleanupStack::PushL( item );
    // One widget item has iDataCount number of elements
    for ( TInt i = 0; i < iDataCount; i++ )
        {
        if ( iContentModel[i].type == KAiContentTypeBitmap )
            {
            //Publish image
            if ( aObserver.CanPublish( *this, i, aIndex ) )
                {
                CGulIcon* icon = iEngine->ItemIconL( *item, TPtrC16( ( const TText16* ) iContentModel[ i ].cid ) );
                aObserver.PublishPtr( *this, i, icon , aIndex );
                }
            }
        else if ( iContentModel[ i ].type == KAiContentTypeText )
            {
            //Publish  text
            if ( aObserver.CanPublish( *this, i, aIndex ) )
                {
                TPtrC name = iEngine->ItemTextL( *item, TPtrC16( ( const TText16* ) iContentModel[ i ].cid ) );
                aObserver.Publish( *this, i, name, aIndex );
                }
            }
        }//content items

    CleanupStack::PopAndDestroy( item );

    }

// ---------------------------------------------------------------------------
// From class CAiContentPublisher
// Plug-in is requested to unload its engines due backup operation
// ---------------------------------------------------------------------------
//
void CMCSPlugin::Stop( TAiTransitionReason aReason )
    {
    
    if ( aReason == EAiBackupRestoreStarted )
        {
        Suspend( aReason );
        }

    }

// ---------------------------------------------------------------------------
// From class CAiContentPublisher
// Plug-in is instructed that it is allowed to consume CPU resources
// ---------------------------------------------------------------------------
//
void CMCSPlugin::Resume( TAiTransitionReason aReason )
    {
    if( aReason == EAiIdleBackground )
        {
        return;
        }

    if ( aReason == EAiBackupRestoreEnded )
        {
        if ( iEngine )
            {
            TRAP_IGNORE( iEngine->ResumeL() );
            }
        }

    TRAP_IGNORE( DoResumeL( aReason ) );
    return;
    }

// ---------------------------------------------------------------------------
// From class CAiContentPublisher
// Plug-in is instructed that it is not allowed to consume CPU resources
// ---------------------------------------------------------------------------
//
void CMCSPlugin::Suspend( TAiTransitionReason aReason )
    {
    if ( aReason == EAiBackupRestoreStarted && iEngine )
        {
        iEngine->Suspend();
        }
    }

// ---------------------------------------------------------------------------
// From class CAiContentPublisher
// The plug-in MUST maintain a registry of subscribers and send 
// notification to all of them whenever the state changes or new content
// is available
// ---------------------------------------------------------------------------
//
void CMCSPlugin::SubscribeL( MAiContentObserver& aObserver )
    { 
    iObservers.AppendL( &aObserver );
    }
   
// ---------------------------------------------------------------------------
// Compare method to exclude the similar content items from array.
// ---------------------------------------------------------------------------
//
TInt CMCSPlugin::CompareItems( const MAiPluginSettings& aFirst,
        const MAiPluginSettings& aSecond )
    {
    MAiPluginSettings& first = const_cast<MAiPluginSettings&>(aFirst);
    MAiPluginSettings& second = const_cast<MAiPluginSettings&>(aSecond);
    return first.AiPluginContentItem().Name().CompareC(second.AiPluginContentItem().Name());    
    }

// ---------------------------------------------------------------------------
// From class CAiContentPublisher
// Plug-ins take ownership of the settings array, so it must either
// store it in a member or free it.
// Creates dynamic content model.
// ---------------------------------------------------------------------------
//
void CMCSPlugin::ConfigureL( RAiSettingsItemArray& aSettings )
    {
    
    TLinearOrder<MAiPluginSettings> sortMethod( CMCSPlugin::CompareItems );
    RAiSettingsItemArray contentItemsArr;

    TInt count = aSettings.Count();
    for ( TInt i = 0; i < count; i++ )
       {
       MAiPluginSettings* pluginSetting = aSettings[ i ];
       if( pluginSetting->AiPluginItemType() == EAiPluginContentItem )
           {
           MAiPluginContentItem& contItem = pluginSetting->AiPluginContentItem();
           TPtrC name = contItem.Name();
           TPtrC type = contItem.Type();
           contentItemsArr.InsertInOrder( pluginSetting, sortMethod );
           }

       }
    iDataCount = contentItemsArr.Count();
    if ( iDataCount > 0 )
        {
        // Create the dynamic content Model
        DeleteContentModel();
        iContentModel = new ( ELeave ) TAiContentItem[ iDataCount ];
        for ( TInt i = 0; i < iDataCount; i++ )
            {
            iContentModel[i].id = i;
            MAiPluginContentItem& contentItem = ( contentItemsArr[ i ] )->AiPluginContentItem();

            if( contentItem.Type() == KContentItemTypeText )
                {
                // text
                iContentModel[i].type = KAiContentTypeText;
                }
            if( contentItem.Type() == KContentItemTypeImage )
                {
                // image
                iContentModel[i].type = KAiContentTypeBitmap;
                }
            TInt pos = contentItem.Name().Locate( KPluginNameSeprator );
            
            HBufC* contentId = HBufC::NewL( contentItem.Name().Length() );
            CleanupStack::PushL( contentId );
            TPtr ptr = contentId->Des();
            ptr = contentItem.Name().Mid( pos + 1 );
            TInt sizeOfContentId = ptr.Size() +sizeof( wchar_t );
            iContentModel[i].cid = static_cast<const wchar_t*>( User::AllocL( sizeOfContentId ) );
            Mem::Copy((TAny*)iContentModel[i].cid, ptr.PtrZ(), sizeOfContentId);
            CleanupStack::PopAndDestroy( contentId );
            }
        iContent = AiUtility::CreateContentItemArrayIteratorL( iContentModel, iDataCount );
        }
    contentItemsArr.Reset();
    // We own the array so destroy it
    aSettings.ResetAndDestroy();
    }

// ---------------------------------------------------------------------------
// From class CAiContentPublisher
// Returns the extension interface. Actual type depends on the passed 
// aUid argument.
// ---------------------------------------------------------------------------
//
TAny* CMCSPlugin::Extension( TUid aUid )
    {    
    if (aUid == KExtensionUidProperty)
           {
        return static_cast<MAiPropertyExtension*>(this);
        }
    else if (aUid == KExtensionUidEventHandler)
        {
        return static_cast<MAiEventHandlerExtension*>(this);
        }
    else
        {    
        return NULL;
        }
    }

// ---------------------------------------------------------------------------
// From class MAiPropertyExtension
// Read property of publisher plug-in.
// ---------------------------------------------------------------------------
//
TAny* CMCSPlugin::GetPropertyL( TInt aProperty )
    {
    TAny* property = NULL;
    
    switch ( aProperty )
        {
        case EAiPublisherInfo:
            {
             property = static_cast<TAiPublisherInfo*>( &iInfo );
            break;  
            }       
    
        case EAiPublisherContent:
            {
            property = static_cast<MAiContentItemIterator*>( iContent );
            break;    
            }
        }
    return property;
    }

// ---------------------------------------------------------------------------
// From class MAiPropertyExtension
// Write property value to optimize the content model.
// ---------------------------------------------------------------------------
//
void CMCSPlugin::SetPropertyL( TInt aProperty, TAny* aValue )
    {  
    switch ( aProperty )
        {
		case EAiPublisherInfo:
			{
			if( aValue )
			    {
    		    const TAiPublisherInfo* info = static_cast<const TAiPublisherInfo*>( aValue );
	    	    iInfo.iName.Copy(info->iName);
	    	    iInfo.iNamespace.Copy(info->iNamespace);
			    }
		    break;
		    }
		default:
		    break;         
        }
    }
 
// ---------------------------------------------------------------------------
// From class MAiEventHandlerExtension.
// Handles an event sent by the AI framework.
// ---------------------------------------------------------------------------
//
void CMCSPlugin::HandleEvent( TInt /*aEvent*/, const TDesC& /*aParam*/ )
    {
    // We have no way of reporting errors to framework so just ignore them.
    //TRAP_IGNORE( iEngine->HandleEventL(aEvent, aParam ));
    } 

// ---------------------------------------------------------------------------
// From class MAiEventHandlerExtension.
// Handles an event sent by the AI framework.
// ---------------------------------------------------------------------------
//
void CMCSPlugin::HandleEvent( const TDesC& aEventName, const TDesC& aParam )
    {
    if ( iEngine )
        {
        if( aEventName == KEventNameLaunchByIndex )
            {
            // We have no way of reporting errors to framework so just ignore them.
            TInt32 index;
            AiUtility::ParseInt( index, aParam );
            TRAP_IGNORE( iEngine->LaunchItemL( index - 1 ));
            }
        else if( aEventName == KEventNameShowSettings )
            {
            TRAP_IGNORE( iEngine->ShowSettingsL() );
            }
        }
    }

// ---------------------------------------------------------------------------
// From class CAiContentPublisher
// framework instructs plug-in that it is allowed to consume CPU resources
// ---------------------------------------------------------------------------
//
void CMCSPlugin::DoResumeL( TAiTransitionReason /*aReason*/ )
    {
    PublishL();
    }
    
// ---------------------------------------------------------------------------
// Frees engine resources
// ---------------------------------------------------------------------------
//    
void CMCSPlugin::FreeEngine()
    {
    delete iEngine;
    iEngine = NULL;
    }

// ---------------------------------------------------------------------------
// Delete content model
// ---------------------------------------------------------------------------
//    
void CMCSPlugin::DeleteContentModel()
    {
    if( iContentModel )
        {
        for ( TInt i = 0; i < iDataCount; i++ )
            {             
            if( iContentModel[i].cid )
                {
                TAny* cell = static_cast<TAny*>( const_cast<wchar_t*>( iContentModel[i].cid ) );
                User::Free( cell ); // Originally allocated with User::Alloc, so delete
                                    // with correlating method.
                iContentModel[i].cid = NULL;
                }
            }
        
        delete iContentModel;
        iContentModel = NULL;        
        }    
    }
  
// ======== GLOBAL FUNCTIONS ========
// ---------------------------------------------------------------------------
// Constructs and returns an application object.
// ---------------------------------------------------------------------------
//
EXPORT_C const TImplementationProxy* ImplementationGroupProxy( 
    TInt& aTableCount )
    {
    aTableCount = sizeof( KImplementationTable ) / 
        sizeof( TImplementationProxy );
    return KImplementationTable;
    }