menucontentsrv/enginc/menueng.h
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Thu, 17 Dec 2009 08:54:17 +0200
changeset 0 79c6a41cd166
child 82 ace62b58f4b2
permissions -rw-r--r--
Revision: 200949 Kit: 200951

/*
* 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:
*
*/

#ifndef __MENUENG_H__
#define __MENUENG_H__

#include <e32base.h>
#include <xcfwengine.h>
#include <xcfwtree.h> // for RNodeArray
#include "mcsmenunotifier.h" // for notification events

// FORWARD DECLARATION

class TMenuItem;
class CXCFWTree;
class MXCFWNode;
class CMenuEngObjectFactoryProxy;
class CMenuEngObject;
class CMenuEngIdManager;
class MMenuEngObserver;
class MMenuEngOperation;
class MMenuEngFilter;
class MMenuEngVisitor;

/**
* Event notification data.
*/
class TMenuEngNotify
    {

public:     // construction

    /**
    * Constructor.
    * @param aFolder Folder.
    * @param aEvents Events.
    */
    TMenuEngNotify( TInt aFolder, TInt aEvents )
        : iFolder( aFolder ), iEvents( aEvents ) {}

public:     // data

    TInt iFolder; ///< Folder.
    TInt iEvents; ///< Events.

    };

/**
* Menu Engine.
*/
NONSHARABLE_CLASS( CMenuEng ): public CActive, public MXCFWEngineObserver
    {

public:     // construction

    /**
    * Destructor.
    */
    IMPORT_C virtual ~CMenuEng();

    /**
    * Two-phased constructor.
    * @param aName Name.
    * @param aObserver Observer.
    * @return The created object.
    */
    IMPORT_C static CMenuEng* NewL(
        const TDesC& aName,
        MMenuEngObserver& aObserver );

protected:  // construction

    /**
    * Constructor.
    * @param aObserver Observer.
    */
    CMenuEng( MMenuEngObserver& aObserver );

    /**
    * Second phase constructor.
    * @param aName Name.
    */
    void ConstructL( const TDesC& aName );

public:     // new methods

    enum TState /// State machine states.
        {
        ENull = 0, ///< Initial state.
        ELoadRamFile, ///< Loading RAM file.
        ELoadRomFile, ///< Loading ROM file.
        ESaveFile, ///< Saving TEMP file and replacing RAM file.
        EExecuteOp, ///< Operation scheduled for execution or being executed.
        EReady, ///< Idle.
        EDead ///< Unrecoverable error; final state.
        };

    /**
    * Queue an operation for execution.
    * Queued operations are scheduled for execution by the Engine.
    * @param aOperation Operation.
    */
    IMPORT_C void QueueOperationL( MMenuEngOperation& aOperation );

    /**
    * Dequeue an operation (remove from the operation queue). Safe to call
    * if not queued.
    * @param aOperation Operation.
    */
    IMPORT_C void DequeueOperation( MMenuEngOperation& aOperation );

    /**
    * Traverse a subtree of the item tree.
    * @param aFolder traversal starts at this folder.
    * @param aVisitor Visitor visiting the nodes and controlling the traversal.
    */
    IMPORT_C void TraverseFolderL(
        TInt aFolder,
        MMenuEngVisitor& aVisitor ) const;

    /**
    * Create a new object. Owner is the caller. The object is not added to
    * the engine yet, but it has an ID already. It can be used to AddL() item.
    * @param aType Type.
    * @return Created object. Owner is the caller.
    */
    IMPORT_C CMenuEngObject* NewObjectL( const TDesC& aType );

    /**
    * Returns current engine state.
    * @return Current state.
    */
	inline TState State() const;
	
	/*
	* Gets legacy format
	* @return legacy format
	*/
	IMPORT_C TBool GetOnceLegacyFormat();

public:     // data query (read access)

    // Read-access methods can be called any time.
    // There is a short startup period during which the engine data is not
    // ready yet; calls made in that period leave with KErrNotReady.
    // When the engine becomes ready, an (0 ,EItemsAddedRemoved) event is
    // sent to the observer.

    /**
    * Get ID of root folder.
    * @param aId ID of root folder.
    */
    IMPORT_C void RootFolderL( TInt& aId ) const;

    /**
    * Get parent folder of item.
    * @param aId Item ID.
    * @param aParentId ID of parent folder.
    */
    IMPORT_C void ParentFolderL( TInt aId, TInt& aParentId ) const;

    /**
    * Get item header.
    * @param aId Item ID.
    * @param aItem Item header is returned here.
    */
    IMPORT_C void GetItemL( TInt aId, TMenuItem& aItem ) const;

    /**
    * Get list of items.
    * @param aItemArray Array receiving item list. Existing content not touched
    * (new items are appended).
    * @param aFolder Get items from this folder.
    * @param aFilter Filter criteria or NULL for unfiltered results.
    * @param aRecursive ETrue to recurse folders, EFalse for immediate
    * children only.
    */
    IMPORT_C void GetItemsL(
        RArray<TMenuItem>& aItemArray,
        TInt aFolder,
        const MMenuEngFilter* aFilter,
        TBool aRecursive ) const;

    /**
    * Get object.
    * @param aId Item ID.
    * @return Object.
    */
    IMPORT_C const CMenuEngObject& ObjectL( TInt aId ) const;

public:     // data manipulation (write access).

    // All write-access methods methods must be wrapped in MMenuEngOperation
    // objects (scheduled execution), otherwise they leave with KErrLocked.

    /**
    * Remove item.
    * @param aId ID of item to be removed.
    */
    IMPORT_C void RemoveL( TInt aId );

    /**
    * Move items to another folder.
    * @param aItems ID-s of items to be to be moved. All items must be in
    * the same folder.
    * @param aFolder Target folder.
    * @param aMoveBefore. In the target folder, items will be inserted before
    * this item (if found). If the target folder contains no item with that ID,
    * the moved items are appended to the end of existing items. Pass 0 to
    * append to the end.
    */
    IMPORT_C void MoveToFolderL(
        RArray<TInt>& aItems,
        TInt aFolder,
        TInt aMoveBefore );

    /**
    * Move item to a different position in its current folder.
    * @param aId ID of item to be to be reordered.
    * @param aMoveBefore. Move the item before this item (if found).
    * If aMoveBefore is not found, the item is moved to the end.
    */
    IMPORT_C void ReorderL( TInt aId, TInt aMoveBefore );

    /**
    * Add new object.
    * @param aObject Object to be added. Note, the object must have been
    * created with NewObjectL of THIS engine (or the call fails)!
    * Ownership taken.
    * @param aFolder Parent folder.
    * @param aMoveBefore. Move the item before this item (if found).
    * If aMoveBefore is not found, the item is added to the end.
    */
    IMPORT_C void AddL(
        CMenuEngObject& aObject,
        TInt aFolder,
        TInt aInsertBefore );

    /**
    * Get modifiable object. Note: when this method is called, the engine
    * marks the object as changed (without checking if there was really
    * a change or not). Therefore, it is advisable to use ObjectL() to
    * investigate an object, and only call ModifiableObjectL if changes are
    * really needed. This results in better performace, as it avoids
    * unnecessary saving.
    * @param aId Item ID.
    * @param aEvent event for engine to append.
    * @return Modifiable object. Already marked as changed.
    */
    IMPORT_C CMenuEngObject& ModifiableObjectL( TInt aId,
    		TInt aEvent = RMenuNotifier::EItemAttributeChanged );

    
    /**
    * Append new notification to the list of pending notifications.
    * @param aFolder Folder.
    * @param aEvents Events.
    */
    IMPORT_C void AppendNotifyL( TInt aFolder, TInt aEvents );
    
    
    IMPORT_C TBool Exist( TInt aId ) const;

private:    // from CActive

    /**
    * Outstanding request completed.
    */
    void RunL();

    /**
    * Cancel outstanding request.
    */
    void DoCancel();

    /**
    * Handle error.
    * @param aError Error code.
    * @return KErrNone.
    */
    TInt RunError( TInt aError );

private:    // from MXCFWEngineObserver

    /**
    * Called when Engine parsing / saving state changes.
    * @param aEvent Engine event
    */
    void HandleEngineEventL( TXCFWEngineEvent aEvent );

    /**
    * Called when there's an error during parsing / saving.
    * @param aErrorCode Error code
    */
    void HandleEngineErrorL( TInt aErrorCode );        

private:    // types

    enum TFile /// File selector.
        {
        ERomFile, ///< Factory file in ROM.
        ERamFile, ///< Working file in RAM.
        ETempFile, ///< Temp file for saving (RAM).
        };

private:    // new methods

    /**
    * Get object from node.
    * @param aNode Node.
    * @return Object.
    */
    inline CMenuEngObject& Object( MXCFWNode& aNode ) const;

    /**
    * Tree is up, perform structure check.
    * @param aTree Tree.
    * @return The root folder node.
    */
    MXCFWNode& CheckTreeL( MXCFWTree& aTree ) const;

    /**
    * Sanity ID check for all nodes in the tree.
    * @param aTree Tree.
    * @return ETrue if ID-s are OK.
    */
    TBool DebugSanityCheck( MXCFWTree& aTree ) const;

    /**
    * Wait for data xml file to load.
    */
    void ActiveWaitForFileLoadL();

    /**
    * Sanity ID check for one nodes in the tree.
    * @param aNode Node.
    * @return ETrue if ID is OK.
    */
    TBool DebugSanityCheck( MXCFWNode& aNode ) const;

    /**
    * Find node by ID, leave with KErrNotFound if not found.
    * @param aId ID.
    * @return Node.
    */
    MXCFWNode& NodeL( TInt aId ) const;

    /**
    * Find folder node by ID, leave with KErrNotFound if not found or not
    * folder.
    * @param aId ID.
    * @return Folder node.
    */
    MXCFWNode& FolderNodeL( TInt aId ) const;

    /**
    * Find child of aParent with given id, or NULL. Not recursive.
    * @param aParent Folder.
    * @param aId Child ID.
    * @return Child or NULL.
    */
    MXCFWNode* Child( MXCFWNode& aParent, TInt aId );

    /**
    * Cancel all operations in the queue.
    */
    void CancelAllOperations();

    /**
    * Validate content filename. Leave with KErrArgument if not valid.
    * @param aName Content filename (without extension).
    */
    void ValidateNameL( const TDesC& aName );

    /**
    * Generate filename of content file.
    * @param aFname Generated filename is returned here.
    * @param aSelector Filename selector.
    */
    void GetFileNameL( TFileName& aFname, TFile aSelector );

    /**
    * Traverse a node.
    * @param aNode Node.
    * @param aVisitor Visitor visiting the nodes and controlling the traversal.
    */
    TBool TraverseNodeL( MXCFWNode& aNode, MMenuEngVisitor& aVisitor ) const;

    /**
    * Tree is up; create and initialize ID manager and tree ID-s.
    * @param aRootNode Root node.
    */
    void InitIdManagerL( MXCFWNode& aRootNode );

    /**
    * Read id_seed from the tree.
    * @param aIdSeed ID seed.
    */
    void GetIdSeedL( TInt& aIdSeed );

    /**
    * Write the id_seed to the tree.
    * @param aSeed ID seed.
    */
    void SetIdSeedL( TInt aSeed );

private:    // state machine parts

    /**
    * Self-completion: go to RunL() asynchronously.
    * @param aError Error code.
    */
    void SelfComplete( TInt aError );

    /**
    * Initiate loading RAM file.
    */
    void LoadRamFileL();

    /**
    * Initiate loading ROM file.
    */
    void LoadRomFileL();

    /**
    * Initiate saving to TEMP file.
    */
    void SaveTempFileL();

    /**
    * Replace RAM file with TEMP file.
    */
    void ReplaceRamFileL();

    /**
    * Complete current operation, if any.
    * @param aError Completion code.
    */
    void CompleteCurrentOperation( TInt aError );

    /**
    * Start executing next operation, if any.
    */
    void ExecuteOperationL();

    /**
    * Save changes, if any.
    */
    void SaveChangesL();

private:    // data

    RBuf iName; ///< Own.
    RBuf iTempFileName; ///< Own.
    RBuf iRamFileName; ///< Own.
    TBool iChanged; ///< ETrue if there are unsaved changes.
    MMenuEngObserver& iObserver;
    TState iState; ///< State.
    CXCFWTree* iTree; ///< DOM tree. Own.
    CXCFWEngine* iEngine; ///< XML Engline. Own.
    CMenuEngObjectFactoryProxy* iObjectFactory; ///< Object factory. Own.
    TInt iRoot; ///< Cached root folder id.
    RPointerArray<MMenuEngOperation> iOperations; ///< Pending operations.
    MMenuEngOperation* iCurrentOperation; ///< Operation being served.
    RArray<TMenuEngNotify> iNotifyQueue; ///< Events for notifiers.
    RFs iFs; ///< File Server Session. Own.
    CMenuEngIdManager* iIdManager; ///< ID manager. Owned.
    CActiveSchedulerWait* iActiveWait;
    /*
    * Legacy format
    */
    TBool iLegacyFormat;
    /**
     * True if the last saving was unsuccessful
     */
    TBool iDiskWasFullAndRamFileWasNotCreated;
    };

// -----------------------------------------------------------------------------
// CMenuEng::State
// -----------------------------------------------------------------------------
// 
CMenuEng::TState CMenuEng::State() const
    {
    return iState;
    }

#endif // __MENUENG_H__