menufw/hierarchynavigator/hnengine/src/hnengine.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Wed, 15 Sep 2010 12:00:00 +0300
branchRCL_3
changeset 93 b01126ce0bec
parent 88 3321d3e205b6
child 102 ba63c83f4716
permissions -rw-r--r--
Revision: 201035 Kit: 201036

/*
* Copyright (c) 2007-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:
*
*/


#include <uri8.h>
#include <mmf/common/mmfcontrollerpluginresolver.h>
#include <sacls.h>
#include <apgtask.h>
#include <centralrepository.h>
#include <AknUtils.h>

#include "hnengine.h"
#include "hnconvutils.h"
#include "hncontrollerinterface.h"
#include "hnfilter.h"
#include "hnsuitemodelcontainer.h"
#include "hnsuitemodel.h"
#include "hnserviceglobals.h"
#include "hnglobals.h"
#include "hnmdsuite.h"
#include "hnitemid.h"
#include "hnliwutils.h"
#include "hnrepositorymanager.h"
#include "menudebug.h"
#include "hnrepositorymanager.h"
#include "hnsuiteobserver.h"
#include "hnmdbasekey.h"
#include "hnitemsorder.h"

_LIT8(  KAnd8,                      "&" );
_LIT8(  KEquals8,                   "=" );

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

// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
//
void CHnEngine::ConstructL()
    {
    iEEnv = CEikonEnv::Static();
    iSuiteContainer = CHnSuiteModelContainer::NewL( *this , iControllerInterface );
    iMetaDataModel = CHnMdModel::NewL( this, iSuiteContainer );
    iLight = CHWRMLight::NewL(this);
    }

// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
//
EXPORT_C CHnEngine* CHnEngine::NewL( MHnControllerInterface& aController )
    {
    CHnEngine* self = CHnEngine::NewLC( aController );
    CleanupStack::Pop( self );
    return self;
    }

// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
//
EXPORT_C CHnEngine* CHnEngine::NewLC( MHnControllerInterface& aController )
    {
    CHnEngine* self = new( ELeave ) CHnEngine( aController );
    CleanupStack::PushL( self );
    self->ConstructL();
    return self;
    }

// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
//
CHnEngine::CHnEngine( MHnControllerInterface& aController ):
    iControllerInterface( aController )
    {
    }

// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
//
CHnEngine::~CHnEngine()
    {
    delete iLight;
    if( iSuiteContainer )
        {
        iSuiteContainer->RemoveLiwObjects();
        }
    delete iMetaDataModel;
    delete iSuiteContainer;
    }

// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
//
TInt CHnEngine::GetSuiteModelsCountL()
    {
    return iSuiteContainer->GetSuiteModelCount();
    }

// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
//
TBool CHnEngine::SuiteModelLoadedL( TInt aId )
    {
    TBool ret( EFalse );
    TInt count( iSuiteContainer->GetSuiteModelCount() );
    for( int i=0; i<count; i++ )
        {
        CHnSuiteModel* suite = iSuiteContainer->GetSuiteModel( i );
        if( suite->GetItemsOrder()->GetSuiteId() == aId )
            {
            ret = ETrue;
            break;
            }
        }
    return ret;
    }

// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
//
CHnSuiteModel* CHnEngine::GetLastSuiteModelL()
    {
    return iSuiteContainer->GetLastSuiteModel();
    }

// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
//
CHnSuiteModel* CHnEngine::GetParentSuiteModelL()
    {
    return iSuiteContainer->GetParentSuiteModel();
    }

// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
//
EXPORT_C TInt CHnEngine::TriggerHnEventL( const TInt aHnEventId,
        const TInt aRecipientId, CLiwGenericParamList* aEventParameters )
    {
    TInt ret = iSuiteContainer->OfferHnEventL( aHnEventId, aRecipientId,
            aEventParameters);
    return ret;
    }

// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
//
void CHnEngine::HighlightPlacementFromUriL( const TDesC8& aUriFragment )
    {
    TLex8 lexFrag( aUriFragment );
    TInt highLight( 0 );
    if( !( lexFrag.Val( highLight ) ) )
        {
        iSuiteContainer->GetLastSuiteModel()->SetSuiteHighlightL( highLight );
        iControllerInterface.HandleSuiteEventL( ESuiteHighlightChanged,
                iSuiteContainer->GetLastSuiteModel() );
        }
    }

// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
//
TInt CHnEngine::LoadSuiteFromUriL( const TDesC8& aSuiteName,
        const TDesC8& aUriQuery, const TDesC8& aUriFragment )
    {
    TInt error( KErrNone );

    if( !( aSuiteName.Compare( KRoot8 ) ) )
        {
        CLiwGenericParamList* uriParams =
      UriQueryToLiwListLC( aUriQuery, aUriFragment, aSuiteName );
        CLiwGenericParamList* params = CLiwGenericParamList::NewLC();
        params->AppendL( iMetaDataModel->GetSuiteParameters( 0 ) );
        params->AppendL( *uriParams );
        ResetModelsL();
        iMetaDataModel->QueueForeground( CHnMdModel::EWhenAnySuiteIsEvaluated );
        error = InitializeL( *params );
        CleanupStack::PopAndDestroy( params );
        CleanupStack::PopAndDestroy( uriParams );
        }
    else
        {
        CLiwGenericParamList* params =
      UriQueryToLiwListLC( aUriQuery, aUriFragment, aSuiteName );

        HBufC* suiteName = HnConvUtils::Str8ToStrLC( aSuiteName );
        params->AppendL( TLiwGenericParam( KNewSuiteParamNameEn,
            TLiwVariant( *suiteName ) ) );

        error = HandleNewSuiteLoadedEventL( *params );

        CleanupStack::PopAndDestroy( suiteName );
        CleanupStack::PopAndDestroy( params );
        }

    return error;
    }

// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
//
TBool CHnEngine::SuitesAreTheSameL( const TDesC& aLastSuiteName,
    const TDesC8& aFirstSuiteName )
    {
    RBuf8 lastSuiteName;
    CleanupClosePushL( lastSuiteName );
    lastSuiteName.CreateL( aLastSuiteName.Length() );
    lastSuiteName.Copy( aLastSuiteName );
    TBool suitesAreTheSame( !lastSuiteName.Compare( aFirstSuiteName ) );
    CleanupStack::PopAndDestroy( &lastSuiteName );
    return suitesAreTheSame;
    }

// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
//
void CHnEngine::HandleTheSameSuitesL( TBool aNextExists, const TDesC8& aParams )
    {
    RBuf exitMode;
    CleanupClosePushL( exitMode );
    CLiwGenericParamList* params = UriQueryToLiwListLC( aParams, KNullDesC8, KNullDesC8 );
    HnLiwUtils::GetStringL( *params, KExitModeParams, exitMode );

    if ( !exitMode.Compare( KExitModeHide ) )
        {
        // set parameters
        iSuiteContainer->GetLastSuiteModel()->SetExitMode( EExitModeHide );
        }

    CleanupStack::PopAndDestroy( params );
    CleanupStack::PopAndDestroy( &exitMode );

    if ( !aNextExists )
        {
        // refresh if necessary
        iControllerInterface.NotifyUiRefreshL( ERefreshSuite );
        }
    }
// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
//
EXPORT_C void CHnEngine::LoadSuitesFromUriL( const TDesC8& aUri )
  {
    DEBUG(("_MM_:CHnEngine::LoadSuitesFromUriL IN"));
    DEBUG8(("_MM_:\tURI: %S",&aUri));

    TBool consumed( EFalse );

    if( aUri.Find( KSetFocusWithPref ) != KErrNotFound )
        {
        LoadFromCrL( aUri );
        consumed = ETrue;
        }
    else if( aUri.Find( KOpenItemWithPref ) != KErrNotFound )
        {
        LoadItemFromCrL( aUri );
        consumed = ETrue;
        }

    if( !consumed )
        {
        consumed = HandleActionL( aUri );
        }

    if( !consumed )
        {
        LoadSuitesL( aUri );
        }

    DEBUG(("_MM_:CHnEngine::LoadSuitesFromUriL OUT"));
    }

// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
//
TInt CHnEngine::HandleModelEventL( const TDesC& aEventName,
                                CLiwGenericParamList& aParams )
    {
    TInt ret(KErrNotFound);

    if ( aEventName == KNewSuiteLoadedMdEvent )
        {
        // This handles new suite creation, putting its visual model
        // onto the stack eventually.
        ret = HandleNewSuiteLoadedEventL( aParams );
        }
    else if ( aEventName == KBackMdEvent )
        {
        const TDesC& suiteName = iSuiteContainer->GetLastSuiteModel()->SuiteName();
        ret = HandleBackEventL( suiteName );
        }
    else if (aEventName == KReevaluateMdEvent )
        {
        // This event triggers reevaluate on the model.
        // aParams holds liw packed filter.
        ret = HandleReevaluateEventL( aParams );
        }
    else if (aEventName == KSwitchWidgetMdEvent )
        {
        // Widget change is requested.
        ret = HandleWidgetChangeL( aParams );
        }
    else if (aEventName == KRefreshUiMdEvent )
        {
        // Refresh of the whole of the UI is refreshed
        iControllerInterface.NotifyUiRefreshL( ERefreshSuite );
        ret = KErrNone;
        }
    else if (aEventName == KRefreshToolbarMdEvent )
        {
        // Just the toolbar in UI is refreshed
        iControllerInterface.NotifyUiRefreshL( ERefreshToolbar );
        ret = KErrNone;
        }
    else if (aEventName == KStartEditModeMdEvent )
        {
        // Starting edit mode
        iControllerInterface.NotifyUiRefreshL( EStartEditMode );
        ret = KErrNone;
        }
    else if (aEventName == KStopEditModeMdEvent )
        {
        // Stopping edit mode
        iControllerInterface.NotifyUiRefreshL( EStopEditMode );
        ret = KErrNone;
        }
    else if (aEventName == KSetFocusEvent )
        {
        // SetFocus
        ret = HandleSetFocusEventL( aParams );
        }
    else if (aEventName == KAppGainForeground )
      {
      //force matrix gain foreground
        DEBUG(("_MM_:CHnEngine::HandleModelEventL EForegroundGain"));
        iControllerInterface.NotifyUiRefreshL( EForegroundGain );
        ret = KErrNone;
      }
    else if (aEventName == KAppGainBackground )
      {
      //force matrix gain background
        DEBUG(("_MM_:CHnEngine::HandleModelEventL EBackgroundGain"));
        iControllerInterface.NotifyUiRefreshL( EBackgroundGain );
        ret = KErrNone;
      }

    return ret;
    }

// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
//
TInt CHnEngine::HandleWidgetChangeL(
        CLiwGenericParamList& aParams )
    {
    THnSuiteWidgetType type = EChangeWidget;
    TInt pos( 0 );
    const TLiwGenericParam* param = NULL;
    param = aParams.FindFirst( pos,  KWidgetTypeAttrName8 );
    if ( pos != KErrNotFound )
        {
        TPtrC widgetType( KNullDesC );
        param->Value().Get( widgetType );
        if ( widgetType.Compare( KWidgetTypeList ) == 0 )
            type = EListWidget;
        else if ( widgetType.Compare( KWidgetTypeGrid ) == 0 )
            type = EGridWidget;
        else if ( widgetType.Compare( KWidgetTypeCoverFlow ) == 0 )
            type = ECoverFlowWidget;
        }

    CHnSuiteModel* model  = iSuiteContainer->GetLastSuiteModel();
    return HandleWidgetChangeL( model->SuiteName(), type );
    }

// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
//
TInt CHnEngine::HandleWidgetChangeL( const TDesC& aSuiteName,
        THnSuiteWidgetType aType )
    {
    DEBUG(("_MM_:CMatrixMenuAppUi::HandleWidgetChangeL IN"));
    TInt ret( KErrGeneral );

    CHnRepositoryManager* rep = CHnRepositoryManager::NewLC();
    THnSuiteWidgetType type( EUnspecified );
    TInt err( rep->ReadSuiteWidgetTypeL( aSuiteName, type ) );

    if( ( !err || err == KErrNotFound ) && type != EUnspecified )
        {
        ret = rep->StoreSuiteWidgetTypeL( aSuiteName, aType );
        }
    CleanupStack::PopAndDestroy( rep );
    DEBUG(("_MM_:CMatrixMenuAppUi::HandleWidgetChangeL OUT"));
    return ret;
    }

// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
//
TInt CHnEngine::HandleReevaluateEventL(
        CLiwGenericParamList& aParams )
    {
    TInt ret(KErrNone);
    // Paths to retrieve filter values
    _LIT8( KGenreGlobalPath, "filter:genre");
    _LIT8( KIdGlobalPath, "filter:id");
    _LIT8( KGenrePath, "filter:[%d]/genre");
    _LIT8( KItemPath, "filter:[%d]/item");

    CHnFilter* filter = CHnFilter::NewLC();

    TLiwGenericParam param;
    param.PushL();
    aParams.AtL(0, param);
    ASSERT( !param.Name().Compare( KFilterElementItem8 ) );

    TLiwVariant suiteIdVariant;
    suiteIdVariant.PushL();
    TLiwVariant genreVariant;
    genreVariant.PushL();
    TInt idFound =
        HnLiwUtils::GetVariantL( aParams, KIdGlobalPath(), suiteIdVariant );
    TInt found =
        HnLiwUtils::GetVariantL(aParams, KGenreGlobalPath(), genreVariant );
    if (idFound != KErrNotFound)
        {
        filter->SetSuiteId( suiteIdVariant.AsTInt32() );
        filter->SetEvaluateSuiteL( ETrue );
        }
    else if (found != KErrNotFound && found != KErrBadDescriptor)
        {
        filter->SetSuiteNameL( genreVariant.AsDes() );
        filter->SetEvaluateSuiteL( ETrue );
        }
    else
        {
        filter->SetEvaluateSuiteL( EFalse );
        // For each entry in the fitler list....
        for ( int i=0; i< param.Value().AsList()->Count(); i++ )
            {
            RBuf8 path;
            CleanupClosePushL( path );
            path.CreateL( KGenrePath().Length() );
            path.Format( KGenrePath, i );
            TLiwVariant genreVariant;
            HnLiwUtils::GetVariantL(aParams, path, genreVariant );
            path.Close();
            path.CreateL( KItemPath().Length() );
            path.Format( KItemPath, i );
            TLiwVariant itemVariant;
            HnLiwUtils::GetVariantL(aParams, path, itemVariant );
            CleanupStack::PopAndDestroy( &path );

            TPtrC suiteName;
            TPtrC itemId;
            genreVariant.Get(suiteName);
            itemVariant.Get(itemId);

            CHnItemId* itemIdObject = CHnItemId::NewLC(suiteName, itemId);
            filter->AppendItemIdL( itemIdObject );
            CleanupStack::Pop( itemIdObject );

            genreVariant.Reset();
            itemVariant.Reset();
            }
        }
    CleanupStack::PopAndDestroy( &genreVariant );
    CleanupStack::PopAndDestroy( &suiteIdVariant );
    CleanupStack::PopAndDestroy( &param );
    iMetaDataModel->EvaluateL( *filter );
    CleanupStack::PopAndDestroy( filter );
    return ret;
    }

// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
//
TInt CHnEngine::HandleBackEventL( const TDesC& aGenre, TInt aIterations )
    {
    return iMetaDataModel->HandleBackEventL(
            iSuiteContainer, aGenre, aIterations );
    }

// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
//
TInt CHnEngine::HandleNewSuiteLoadedEventL(
        CLiwGenericParamList& aParams )
    {
    DEBUG(("_MM_:CHnEngine::HandleNewSuiteLoadedEventL IN"));
    TInt err( KErrNone );
    const TLiwGenericParam* param =
        aParams.FindFirst( err, KNewSuiteParamNameEn );
    if( err != KErrNotFound )
        {
        TPtrC genre;
        param->Value().Get( genre );
        DEBUG16(("_MM_:\tSuite genre name: %S",&genre));
        // load and evaluate the suite
        if( genre.Compare( KFolderSuite) )
            {
            //only folder suite is supported
            User::Leave( KErrNotSupported );
            }
        err = iMetaDataModel->LoadSuiteL( genre, &aParams );
        if ( !err )
            {
            GetLastSuiteModelL()->RegisterSuiteObserverL( &iControllerInterface, EPriorityNull );
            CHnFilter* filter = CHnFilter::NewLC();
            filter->SetSuiteNameL( genre );
            filter->SetEvaluateSuiteL( ETrue );
            if ( iEditMode )
                {
                iMetaDataModel->SetModeL( EMdModeEdit );
                }
            else
                {
                iMetaDataModel->SetModeL( EMdModeNormal );
                }

            TRAP( err, iMetaDataModel->EvaluateL( *filter ) );

            CleanupStack::PopAndDestroy( filter );
            if ( err )
                {
                iMetaDataModel->DeleteLastSuite();
                iSuiteContainer->PopSuiteModelL( genre );
                }
            }
        else
            {
            // show error note to User
            HBufC* message( NULL );
            switch ( err )
                {
                case KErrPathNotFound :
                    {
                    message = KDebugNoteDirNotFound().AllocL();
                    }
                    break;
                case KErrNotFound :
                    {
                    message = KDebugNoteFileNotFound().AllocL();
                    }
                    break;
                default :
                    {
                    message = HBufC::NewL( KDebugNoteOtherError().Length() +
                                            KMaxLength );
                    message->Des().AppendFormat( KDebugNoteOtherError, err );
                    }
                    break;
                }
            iEEnv->AlertWin( *message );
            delete message;
            }
        }
    DEBUG(("_MM_:\tReturned error code: %d",err));
    DEBUG(("_MM_:CHnEngine::HandleNewSuiteLoadedEventL OUT"));

    return err;
    }

// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
//
TInt CHnEngine::HandleSetFocusEventL( const CLiwGenericParamList& aParams  )
    {
    // Triggering event in hierarchy navigator, specifying
    // that suite given by the name genre has been
    DEBUG(("_MM_:CHnEngine::HandleSetFocusEventL IN"));

    TInt posSuite( 0 );
    TInt posItem( 0 );
    TInt64 suiteCustomId( KErrNotFound );
    TInt64 itemCustomId( KErrNotFound );

  // Get suite's and item's custom ids.
  const TLiwGenericParam* paramSuiteId = aParams.FindFirst( posSuite,  KSuiteCustomId8 );
  const TLiwGenericParam* paramItemId = aParams.FindFirst( posItem,  KItemCustomId8 );


  if ( posSuite >= 0 && posItem >= 0 )
      {
      suiteCustomId = paramSuiteId->Value().AsTInt64();
      itemCustomId = paramItemId->Value().AsTInt64();

      // Get matching suite.
      CHnSuiteModel* suiteModel = iSuiteContainer->GetMatchingSuiteModel( suiteCustomId );

      if ( suiteModel )
        {
        // If suite is not null, then find matching item model.
        TInt index( KErrNotFound );
        CHnItemModel* itemModel = suiteModel->GetMatchingItemModelL( itemCustomId, index );

        if ( itemModel )
          {
          // If itemModel is not null then set highlight and set highligh
          // on matching item.
          suiteModel->SetSuiteHighlightL( index );
            iControllerInterface.HandleSuiteEventL( ESuiteHighlightChanged, suiteModel );
          }
        else
          {
          suiteModel->QueueFocus( itemCustomId );
          }
        }
      }

    DEBUG(("_MM_:CHnEngine::HandleSetFocusEventL OUT"));
    return KErrNone;
    }

// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
//
TInt CHnEngine::HandleMoveFocusBeforeDeleteEventL(
        const CLiwGenericParamList& /* aParams */  )
    {
    // Triggering event in hierarchy navigator, specifying
    // that suite given by the name genre has been
    DEBUG(("_MM_:CHnEngine::HandleMoveFocusBeforeDeleteEventL IN"));

    TInt currentHighlight( GetLastSuiteModelL()->GetSuiteHighlight() );
    TInt itemsCount( GetLastSuiteModelL()->GetItemModelsCount() );

    TInt shift( 0 );
    if( AknLayoutUtils::PenEnabled() && iEditMode )
        {
        // add empty item
        shift = 1;
        }
    if( currentHighlight == itemsCount - shift - 1 )
        {
        GetLastSuiteModelL()->SetSuiteHighlightL( currentHighlight - 1 );
        }
    else
        {
        GetLastSuiteModelL()->SetSuiteHighlightL( currentHighlight + 1 );
        }
    iControllerInterface.HandleSuiteEventL(
            ESuiteHighlightChanged, GetLastSuiteModelL() );

    DEBUG(("_MM_:CHnEngine::HandleMoveFocusBeforeDeleteEventL OUT"));
    return KErrNone;
    }

// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
//
TInt CHnEngine::HandleRefreshIconsEventL( const CLiwGenericParamList& /* aParams */ )
    {
    iMetaDataModel->EvaluateL();
    return KErrNone;
    }

// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
//
TInt CHnEngine::HandleDisableActionsForItemL( const CLiwGenericParamList& aParams )
    {
    TInt pos( 0 );
    aParams.FindFirst( pos, KItemCustomId8 );
    if ( pos != KErrNotFound )
        {
        TInt itemCustomId = aParams[pos].Value().AsTInt32();
        TInt itemId = 0;
        CHnItemModel* itemModel =
                iSuiteContainer->GetLastSuiteModel()->GetMatchingItemModelL(
                        itemCustomId, itemId );
        if ( itemModel )
            {
            itemModel->DeleteAllActionModels();
            }
        }
    return KErrNone;
    }

// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
//
//void CHnEngine::InstallChangeL( TInt aStatus )
//    {
//    switch ( aStatus)
//        {
//        case EInstOpNone:
//            {
//            break;
//            }
//        case EInstOpInstall:
//        case EInstOpUninstall:
//            {
//            iMetaDataModel->ReleaseLocalization();
//            break;
//            }
//        }
//    }
// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
//
EXPORT_C TInt CHnEngine::InitializeL( CLiwGenericParamList& aParam )
    {
    DEBUG(("_MM_:CMatrixMenuAppUi::InitializeL IN"));
    User::LeaveIfError( HandleNewSuiteLoadedEventL( aParam ) );
    DEBUG(("_MM_:CMatrixMenuAppUi::InitializeL OUT"));
    // This is an interface method so some value has to be returned.
    return KErrNone;
    }

// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
//
void CHnEngine::ParseSuiteUriPathL( const TDesC8& aUriPath,
        CDesC8ArrayFlat& aOutput )
    {
    DEBUG(("_MM_:CHnEngine::ParseSuiteUriPathL IN"));
    DEBUG(("_MM_:\tURI path: %S",&aUriPath));
    if ( aUriPath.Length() )
        {
        // copy the path so we can freely trim already parsed chunks
        RBuf8 buf( aUriPath.AllocL() );
        CleanupClosePushL( buf );

        // get rid of the initial slash
        if ( buf[0] == KSlash8()[0] )
            {
            buf.Delete( 0, 1 );
            DEBUG(("_MM_:\tDeleted leading slash"));
            }

        // get the first chunk
        TInt slashPos = buf.Find( KSlash8 );
        TPtrC8 chunkPtr;
        if ( slashPos != KErrNotFound )
            {
            chunkPtr.Set( buf.Left( slashPos ) );
            }
        else
            {
            // no slash - one chunk path
            chunkPtr.Set( buf );
            }

        while ( chunkPtr.Length() )
            {
            aOutput.AppendL( chunkPtr );
            DEBUG8(( "_MM_:\t\tParsed segment: %S", &chunkPtr ));

            // get rid of the parsed chunk and get a new one
            if ( slashPos != KErrNotFound )
                {
                // also remove the trailing slash
                buf.Delete( 0, chunkPtr.Length() + 1 );
                slashPos = buf.Find( KSlash8 );
                if ( slashPos != KErrNotFound )
                    {
                    chunkPtr.Set( buf.Left( slashPos ) );
                    }
                else
                    {
                    // last chunk
                    chunkPtr.Set( buf );
                    }
                }
            else
                {
                // no slashes found, this was the last one
                break;
                }
            }

        CleanupStack::PopAndDestroy( &buf );
        }
    DEBUG(("_MM_:CHnEngine::ParseSuiteUriPathL OUT"));
    }

// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
//
EXPORT_C void CHnEngine::ResetModelsL()
    {
    MMPERF(("CHnEngine::ResetModelsL - START"));

    iControllerInterface.NotifyUiRefreshL( ERemoveLiwObjects );

    if( iSuiteContainer )
        {
        iSuiteContainer->RemoveLiwObjects();
        }
    delete iMetaDataModel;
    iMetaDataModel = NULL;
    delete iSuiteContainer;
    iSuiteContainer = NULL;

    iSuiteContainer = CHnSuiteModelContainer::NewL( *this , iControllerInterface );
    MMPERF(("CHnEngine::ResetModelsL - suite container ready"));

    iMetaDataModel = CHnMdModel::NewL( this, iSuiteContainer );

    MMPERF(("CHnEngine::ResetModelsL - DONE"));
    }

// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
//
CLiwGenericParamList* CHnEngine::UriQueryToLiwListLC(
        const TDesC8& aUriQuery, const TDesC8& aUriFragment, const TDesC8& aSuiteName )
    {
    CLiwGenericParamList* list = CLiwGenericParamList::NewLC();

    CLiwDefaultMap* map = CLiwDefaultMap::NewL();
    map->PushL();

    RPointerArray< HBufC8 > params = SplitL( aUriQuery, KAnd8 );

    for( TInt i = 0; i < params.Count(); i++ )
        {
        RPointerArray< HBufC8 > paramValue = SplitL( *params[ i ], KEquals8 );
        CleanupResetAndDestroyPushL( paramValue );
        ASSERT( paramValue.Count() == 2 );
        map->InsertL( *paramValue[ 0 ], TLiwVariant( *paramValue[ 1 ] ) );
        CleanupStack::PopAndDestroy( &paramValue );
        }

    if ( aUriFragment.Length() > 0 && aSuiteName.Length() > 0 )
        {
        map->InsertL( KUriHighlight, TLiwVariant( aUriFragment ) );
        map->InsertL( KUriHighlightSuite, TLiwVariant( aSuiteName ) );
        }

    list->AppendL( TLiwGenericParam(  KParams8, TLiwVariant( map )));

    params.ResetAndDestroy();
    CleanupStack::PopAndDestroy( map );

    return list;
    }

// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
//
RPointerArray< HBufC8 > CHnEngine::SplitL( const TDesC8& aSource,
        const TDesC8& aSeparator )
    {
    RPointerArray< HBufC8 > tokens;
    CleanupResetAndDestroyPushL( tokens );

    if ( aSource.Length() > 0 && aSeparator.Length() > 0 )
        {
        TPtrC8 tmpSource = aSource;
        TPtrC8 token( KNullDesC8 );

        while( ETrue )
            {
            TInt length = tmpSource.Find( aSeparator );

            if( aSeparator == HnLogicalRelations::KParamUid8
                    && length != KErrNotFound )
                {
                TInt ampPos( KErrNotFound );
                do
                    {
                    ampPos = tmpSource.Mid(
                            length + HnLogicalRelations::KParamUid8().Length() ).
                                Find( HnLogicalRelations::KLogicalAnd8 );
                    if( ampPos >= 0 )
                        {
                        length += (ampPos + HnLogicalRelations::KParamUid8().Length());
                        ampPos = 0;
                        }
                    else if( (length + HnLogicalRelations::KParamUid8().Length())
                                == tmpSource.Length())
                        {
                        length = KErrNotFound;
                        }
                    }while( !ampPos );
                }

            if ( length >= 0 )
                {
                token.Set( tmpSource.Mid( 0, length ) );
                tokens.AppendL( token.AllocL() );
                tmpSource.Set( tmpSource.Mid( length + 1 ) );
                if( aSeparator == HnLogicalRelations::KLogicalEqual8 )
                    {
                    token.Set( tmpSource );
                    tokens.AppendL( token.AllocL() );
                    break;
                    }
                }
            else
                {
                token.Set( tmpSource );
                tokens.AppendL( token.AllocL() );
                break;
                }
            }
        }
    CleanupStack::Pop( &tokens );
    return tokens;
    }

// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
//
void CHnEngine::SetEditModeL( TBool aEditMode )
    {
    iEditMode = aEditMode;
    if ( aEditMode )
        {
        iMetaDataModel->SetModeL( EMdModeEdit );
        }
    else
        {
        iMetaDataModel->SetModeL( EMdModeNormal );
        }
    //The suite on top of the stack is probably displayed.
    //Switching to edit mode has some dramatic ui impact,
    //thus when parts of the suite will get displayed
    //it may look awkward thus the suite on top of the stack
    //is marked as uninitialized, therefore ui will be able to
    //react only to the ready suite model.
    if (AknLayoutUtils::PenEnabled() || (!AknLayoutUtils::PenEnabled() && iEditMode))
        {
        GetLastSuiteModelL()->GetItemsOrder()->MarkSuiteUninitialized();
        iMetaDataModel->EvaluateL();
        }
    }

// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
//
TBool CHnEngine::IsOnlyRootConfLoaded()
    {
    return ( iSuiteContainer &&
            iSuiteContainer->GetSuiteModelCount() == KModelCountForRoot );
    }

// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
//

EXPORT_C void CHnEngine::HandleRequestL( const CLiwGenericParamList& aParam,
                                CLiwGenericParamList* /*aOutput*/ )
    {
    TInt pos( 0 );
    aParam.FindFirst( pos, KHnRequest );
    if (pos != KErrNotFound)
        {
        TPtrC8 command = aParam[pos].Value().AsData();
        if( command == KSetFocus )
            {
            HandleSetFocusEventL( aParam );
            }
        else if( command == KMoveFocusBeforeDelete )
            {
            HandleMoveFocusBeforeDeleteEventL( aParam );
            }
        else if( command == KRefreshIcons )
            {
            HandleRefreshIconsEventL( aParam );
            }
        else if (command == KEvaluateMdModel)
            {
            GetLastSuiteModelL()->GetItemsOrder()->MarkSuiteUninitialized();
            iMetaDataModel->EvaluateL();
            }
        else if ( command == KDisableActionsForItem )
            {
            HandleDisableActionsForItemL( aParam );
            }
        }
    }

// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
//
void CHnEngine::LoadFromCrL( const TDesC8& aUri )
    {
    HBufC8* uriBuf = HBufC8::NewLC( aUri.Length() );
    uriBuf->Des().Copy( aUri );

    TUriParser8 parser;
    parser.Parse( *uriBuf );
    User::LeaveIfError( parser.IsSchemeValid() ? KErrNone : KErrPathNotFound );

    const TDesC8& query = parser.Extract( EUriQuery );
    RPointerArray< HBufC8 > params = SplitL( query, HnLogicalRelations::KParamUid8);

    TBuf8< KApaMaxAppGroupName + KTimeStampBufferLength + KUidStringLength + 2> item;

    for( TInt i = 0; i < params.Count(); i++ )
        {
        RPointerArray< HBufC8 > paramValue = SplitL( *params[ i ], HnLogicalRelations::KLogicalEqual8 );
        CleanupResetAndDestroyPushL( paramValue );
        ASSERT( paramValue.Count() == 2 );

        if ( !paramValue[0]->Compare(KMcsAppGroupName8) )
          {
          TBuf8< KApaMaxAppGroupName > appgrname;
          if( paramValue[1]->Length()<= KApaMaxAppGroupName )
              {
              appgrname.Append( *paramValue[1] );
              }

          //get current time
          TTime currentTime;
          currentTime.HomeTime();
          TDateTime date(currentTime.DateTime());
          item.Format(KCRepTimeFormat, &appgrname , date.Year(), date.Month(),
            date.Day(), date.Hour(), date.Minute(), date.Second(), date.MicroSecond());
          }
        else if ( !paramValue[0]->Compare( KKeyTypeUid ) )
          {
          item.Append( KComma8 );
            if( paramValue[1]->Length()<=KUidStringLength )
                {
                item.Append( *paramValue[1] );
                }
          }
        CleanupStack::PopAndDestroy( &paramValue );
        }

    TBuf< KApaMaxAppGroupName + KTimeStampBufferLength + KUidStringLength + 2> item1;
    item1.Copy(item);
    CRepository *cenRep = CRepository::NewLC( KCRUidMenu );
    cenRep->Set(KMenuShowFolder, item1);
    CleanupStack::PopAndDestroy( cenRep );

    params.ResetAndDestroy();
    CleanupStack::PopAndDestroy( uriBuf );
  }
// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
//
void CHnEngine::LightStatusChanged(TInt aTarget,
        CHWRMLight::TLightStatus aStatus)
    {
        DEBUG(("_Mm_:CHnEngine::LightStatusChanged: target %d, status %d - IN", aTarget, aStatus));
    if (CHWRMLight::EPrimaryDisplay == aTarget
            || CHWRMLight::EPrimaryDisplayAndKeyboard == aTarget)
        {
        switch (aStatus)
            {
            case CHWRMLight::ELightOn:
                {
                TRAP_IGNORE( iControllerInterface.NotifyUiRefreshL(ELightOn) );
                break;
                }
            case CHWRMLight::ELightOff:
                {
                TRAP_IGNORE( iControllerInterface.NotifyUiRefreshL(ELightOff) );
                break;
                }
            }
        }
        DEBUG(("_Mm_:CMmAppUi::LightStatusChanged - OUT"));
    }

// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
//
TBool CHnEngine::HandleActionL( const TDesC8& aUri )
    {
    TBool exitActionConsumed( EFalse );

    HBufC8* uriBuf = HBufC8::NewLC( aUri.Length() );
    uriBuf->Des().Copy( aUri );

    TUriParser8 parser;
    parser.Parse( *uriBuf );
    User::LeaveIfError( parser.IsSchemeValid() ? KErrNone : KErrPathNotFound );

    const TDesC8& host8 = parser.Extract( EUriHost );
    const TDesC8& query = parser.Extract( EUriQuery );

    RBuf action;
    CleanupClosePushL( action );
    CLiwGenericParamList* paramsUri = UriQueryToLiwListLC( query, KNullDesC8, KNullDesC8 );
    HnLiwUtils::GetStringL( *paramsUri, KActionParams, action );

    if( !action.Compare( KActionExit ) )
        {
        RBuf host;
        host.CreateL( host8.Length() );
        CleanupClosePushL( host );
        host.Copy( host8 );
        CHnSuiteModel* suiteModel = iSuiteContainer->GetSuiteModel( host );
        TBool exitHideHostNotFound( ETrue );
        if( suiteModel && suiteModel->ExitMode() == EExitModeHide )
            {
            exitHideHostNotFound = EFalse;
            }

        if( exitHideHostNotFound )
            {
            //send to foreground
            CLiwGenericParamList* pl = CLiwGenericParamList::NewL();
            CleanupStack::PushL( pl );
            HandleModelEventL( KAppGainForeground, *pl );
            CleanupStack::PopAndDestroy( pl );
            }
        else
            {
            //send to background
            CLiwGenericParamList* pl = CLiwGenericParamList::NewL();
            CleanupStack::PushL( pl );
            HandleModelEventL( KAppGainBackground, *pl );
            CleanupStack::PopAndDestroy( pl );
            }

        if( exitHideHostNotFound && iSuiteContainer->GetLastSuiteModel() == suiteModel )
            {
            HandleBackEventL( host, 1 );
            }
        else
            {
            //reset to root
            CLiwGenericParamList* params = CLiwGenericParamList::NewLC();
            params->AppendL( iMetaDataModel->GetSuiteParameters( 0 ) );
            ResetModelsL();
            InitializeL( *params );
            CleanupStack::PopAndDestroy( params );
            }

        CleanupStack::PopAndDestroy( &host );
        exitActionConsumed = ETrue;
        }

    CleanupStack::PopAndDestroy( paramsUri );
    CleanupStack::PopAndDestroy( &action );
    CleanupStack::PopAndDestroy( uriBuf );
    return exitActionConsumed;
    }

// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
//
void CHnEngine::LoadSuitesL( const TDesC8& aUri )
    {
    TBool sendToForeground(EFalse);
    HBufC8* uriBuf = HBufC8::NewLC( aUri.Length() );
    uriBuf->Des().Copy( aUri );

    TUriParser8 parser;
    parser.Parse( *uriBuf );
    User::LeaveIfError( parser.IsSchemeValid() ? KErrNone : KErrPathNotFound );

    CDesC8ArrayFlat* suiteNameArray = new( ELeave ) CDesC8ArrayFlat( KDefaultGranularity ) ;
    CleanupStack::PushL( suiteNameArray );

    const TDesC8& host = parser.Extract( EUriHost );
    RBuf8 host8;
    CleanupClosePushL( host8 );
    if (host.Compare( KNullDesC8 ))
        {
        host8.CreateL( host );
        host8.LowerCase();
        suiteNameArray->AppendL( host8 );
        DEBUG8(( "_MM_:\tURI host part: %S", &host8 ));
        }

    const TDesC8& path = parser.Extract( EUriPath );
    if (path.Compare( KNullDesC8 ))
        {
        HBufC8* path8 = HBufC8::NewLC( path.Length() );
        path8->Des().Copy( path );
        path8->Des().LowerCase();
        ParseSuiteUriPathL( *path8, *suiteNameArray );
        CleanupStack::PopAndDestroy( path8 );
        }

    TBool suiteExists( EFalse );
    iMetaDataModel->IgnoreEvaluations( ETrue );
    iMetaDataModel->QueueForeground( CHnMdModel::EWhenAnySuiteIsEvaluated );

    if( host8.Length() == 0 || ( host8.Length() > 0 &&
            !iMetaDataModel->SuiteModelExistsL( host8 ) ) )
        {
        suiteNameArray->Reset();
        suiteNameArray->AppendL( KRoot8 );
        }

    for( TInt i = 0; i < suiteNameArray->Count(); ++i )
        {
        suiteExists = iMetaDataModel->SuiteModelExistsL(
                ( *suiteNameArray )[i] );
        TBool nextExists = i < suiteNameArray->Count() - 1 &&
                iMetaDataModel->SuiteModelExistsL( ( *suiteNameArray )[i + 1] );
        TBool isLast = ( i == ( suiteNameArray->Count() - 1 ) );

        TBool turnOnEvaluation = ( suiteExists && ( !nextExists || isLast ) );
        if( turnOnEvaluation || !suiteExists )
            {
            iMetaDataModel->IgnoreEvaluations( EFalse );
            }

        TInt err( KErrNone );

        // Ignore loading new suite if the last suite in model is the same
        // as first one in the uri.
        if ( i == 0 )
            {
            if ( SuitesAreTheSameL( iMetaDataModel->GetLastSuite()->SuiteName(), (*suiteNameArray)[i] ) )
                {
                HandleTheSameSuitesL( nextExists, parser.Extract( EUriQuery ) );
                sendToForeground = ETrue;
                continue;
                }
            }

        if( suiteExists )
            {
            if (!nextExists)
                {
                // Tricky: queue foreground so that if the suite is evaluated synchronously
                // the foreground will be gained.
                iMetaDataModel->QueueForeground( CHnMdModel::EWhenAnySuiteIsEvaluated );
                }
            err = LoadSuiteFromUriL(
                    ( *suiteNameArray )[i], parser.Extract( EUriQuery ), parser.Extract( EUriFragment ) );
            if ( KErrNone == err && !nextExists && iMetaDataModel->IsForegroundQueued() )
                {
                // Tricky: if foreground is still queued it means that the suite is evaluated
                // asynchronously. Override the previos foreground queue setting with one
                // that will be effective only if the last loaded suite is evaluated.
                iMetaDataModel->QueueForeground( CHnMdModel::EWhenCurrentTopSuiteIsEvaluated );
                }
            if ( err != KErrNone )
                {
                sendToForeground = ETrue;
                }
            }

        if( !suiteExists || err != KErrNone || !nextExists )
            {
            CHnFilter* filter = CHnFilter::NewLC();

            filter->SetSuiteId(
                    iSuiteContainer->GetLastSuiteModel()->CustomId() );

            filter->SetEvaluateSuiteL( ETrue );
            iMetaDataModel->IgnoreEvaluations( EFalse );

            TRAPD( err, iMetaDataModel->EvaluateL( *filter ) );

            CleanupStack::PopAndDestroy( filter );
            if( err )
                {
                iMetaDataModel->DeleteLastSuite();
                iSuiteContainer->PopSuiteModelL(
                        HnConvUtils::Str8ToStr( ( *suiteNameArray )[i] )->Des() );
                sendToForeground = ETrue;
                }
            break;
            }
        }

    // set highlight only when path is valid!
    if( suiteExists )
        {
        HighlightPlacementFromUriL( parser.Extract( EUriFragment ) );
        }

    CleanupStack::PopAndDestroy( &host8 );
    CleanupStack::PopAndDestroy( suiteNameArray );
    CleanupStack::PopAndDestroy( uriBuf );

    //    send to foreground
    if ( sendToForeground )
        {
        CLiwGenericParamList* pl = CLiwGenericParamList::NewL();
        CleanupStack::PushL( pl );
        HandleModelEventL( KAppGainForeground, *pl );
        CleanupStack::PopAndDestroy( pl );
        iMetaDataModel->QueueForeground( CHnMdModel::ENever );
        }

    }
// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
//
void CHnEngine::LoadItemFromCrL( const TDesC8& aUri )
    {
    HBufC8* uriBuf = HBufC8::NewLC( aUri.Length() );
    uriBuf->Des().Copy( aUri );

    TUriParser8 parser;
    parser.Parse( *uriBuf );
    User::LeaveIfError( parser.IsSchemeValid() ? KErrNone : KErrPathNotFound );

    const TDesC8& query = parser.Extract( EUriQuery );

    if( query.Compare( KNullDesC8 ) )
        {
        TBuf8<KMaxLength> item;
        RPointerArray<HBufC8> paramValue = SplitL( query,
                HnLogicalRelations::KLogicalEqual8 );
        CleanupResetAndDestroyPushL( paramValue );
        ASSERT( paramValue.Count() == 2 );

        if( !paramValue[0]->Compare( KId8 ) )
            {
            if( paramValue[1]->Length() <= KUidStringLength )
                {
                item.Append( *paramValue[1] );
                }
            }
        CleanupStack::PopAndDestroy( &paramValue );

        TBuf<KMaxLength> item1;
        item1.Copy( item );
        CRepository *cenRep = CRepository::NewLC( KCRUidMenu );
        cenRep->Set( KMenuOpenItem, item1 );
        CleanupStack::PopAndDestroy( cenRep );
        }
    CleanupStack::PopAndDestroy( uriBuf );
    }

// End of file