widgetmodel/alfwidgetmodel/src/alfmodel.cpp
branchRCL_3
changeset 26 0e9bb658ef58
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/widgetmodel/alfwidgetmodel/src/alfmodel.cpp	Wed Sep 01 12:23:18 2010 +0100
@@ -0,0 +1,487 @@
+/*
+* Copyright (c) 2006 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:   Model Class used by widgets.
+*
+*/
+
+
+
+
+//INCLUDES 
+#include <alf/ialfmodelchangeobserver.h> 
+#include <osn/alfptrvector.h>
+#include <memory>
+
+#include <alf/alfmodel.h>
+#include "alf/alfmodeloperation.h"
+#include <alf/alfvarianttype.h>
+#include <alf/alfexceptions.h>
+//#include "alf/alfperf.h"
+#include <osn/osnnew.h>
+
+using osncore::AlfPtrVector;
+using std::auto_ptr;
+
+// Forward declared inside the Alf namespace
+namespace Alf
+    {
+    
+    
+class AlfModelImpl
+    {
+public :
+	AlfModelImpl():mDataSource(0)
+	    {
+	    }
+
+	~AlfModelImpl()
+	    {
+        delete mDataSource;
+	    mObserverArray.clear();
+		}
+		
+    /**
+     * Array of Observers for the Model individual observers not owned
+     */
+    AlfPtrVector<IAlfModelChangeObserver> mObserverArray;
+    
+    /**
+     * Data Source for the Model owned
+     */ 
+    IAlfVariantType* mDataSource;
+    };
+
+
+////////////////////// AlfModel //////////////////////
+
+// ============================ MEMBER FUNCTIONS ==============================
+
+
+// ---------------------------------------------------------------------------
+// Description : Constructor - 
+// ---------------------------------------------------------------------------
+//
+OSN_EXPORT AlfModel::AlfModel()
+    {
+    }
+
+// ---------------------------------------------------------------------------
+// Description : Constructor - 
+// Data Source for the model is passed
+// ---------------------------------------------------------------------------
+//
+OSN_EXPORT AlfModel::AlfModel( IAlfVariantType* aDataSource )
+    {
+    mData.reset( new(EMM) AlfModelImpl() );
+    mData->mDataSource  = aDataSource;  
+    mData->mObserverArray.setAutoDelete(false);
+    }
+
+// ---------------------------------------------------------------------------
+// Description : Class Destructor
+// ---------------------------------------------------------------------------
+//
+OSN_EXPORT AlfModel::~AlfModel()
+    {
+    }
+
+// ---------------------------------------------------------------------------
+// Description : Adds model change observers
+// ---------------------------------------------------------------------------
+//
+OSN_EXPORT void AlfModel::addModelChangeObserver(
+    IAlfModelChangeObserver& aObserver)
+    {
+    if(mData->mObserverArray.findRef(&aObserver)<0)
+    	{
+	    mData->mObserverArray.resize(mData->mObserverArray.count()+1);
+	    mData->mObserverArray.insert(mData->mObserverArray.count(),
+	                                 &aObserver);
+    	aObserver.modelChanged( *this );
+    	}
+    }
+    
+    
+    
+// ---------------------------------------------------------------------------
+// Description : Removes model change observers
+// ---------------------------------------------------------------------------
+//
+OSN_EXPORT void AlfModel::removeModelChangeObserver(
+    IAlfModelChangeObserver& aObserver)
+    {
+    for ( int i = 0; i < mData->mObserverArray.count(); ++i )
+    	{
+    	if(mData->mObserverArray[i]==&aObserver)
+    	 {
+    	  mData->mObserverArray.remove( i );
+		  return;
+    	 }
+    	}
+    }
+
+
+// ---------------------------------------------------------------------------
+// Description : Sets the data for the model
+// ---------------------------------------------------------------------------
+//
+OSN_EXPORT void AlfModel::setData(IAlfVariantType* aData)
+    {
+    if( mData->mDataSource != 0 )
+        {
+        delete mData->mDataSource;
+        mData->mDataSource=0;
+        }
+    mData->mDataSource = aData;
+
+    for ( int i = 0; i < mData->mObserverArray.count(); ++i )
+        {
+        mData->mObserverArray[i]->modelChanged( *this );
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// Description : Returns the Data Source
+// ---------------------------------------------------------------------------
+//
+OSN_EXPORT IAlfVariantType* AlfModel::data() const
+    {
+    return  mData->mDataSource;
+    }
+
+// ---------------------------------------------------------------------------
+// Description : notifies, that the model is changed.
+// ---------------------------------------------------------------------------
+//    
+OSN_EXPORT void AlfModel::notifyModelChanged()
+    {
+    //Notify all the observers
+    for ( int i = 0; i < mData->mObserverArray.count(); ++i )
+        {
+        mData->mObserverArray[i]->modelChanged(*this);
+        }    
+    }
+
+// ---------------------------------------------------------------------------
+// Description : Clears the Data Source
+// ---------------------------------------------------------------------------
+//
+OSN_EXPORT void AlfModel::clearModel()
+    {
+    //Delete the Model
+    if( mData->mDataSource != 0 )
+        {
+        delete mData->mDataSource;
+        mData->mDataSource=0;        
+        }
+    //Notify all the observers
+    for ( int i = 0; i < mData->mObserverArray.count(); ++i )
+        {
+        mData->mObserverArray[i]->modelChanged(*this);
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// From class IAlfInterfaceBase.
+// Static getter for interfaces provided by the widget,
+// the control, or the model.
+// ---------------------------------------------------------------------------
+//
+OSN_EXPORT IAlfInterfaceBase* AlfModel::makeInterface( const IfId& aType)
+    {
+    UString param(aType.mImplementationId);
+    if ( param == IAlfModel::type().mImplementationId )
+        {
+        return this;
+        }
+    return 0;
+    }
+
+//----------------------------------------------------------------------------
+//Add a  number of data fields in the model data. All model change
+//observers are notified about the change.  Internal API not exported
+//-----------------------------------------------------------------------------
+void AlfModel::addData(AlfModelOperation* aAddOperation)
+    {
+    IAlfVariantType* newData = 0;
+    IAlfVariantType* parentData = 0;
+    try
+        {
+        //ALF_PERF_START( perfdata, "AlfModel-AddData-Adding")
+        newData = aAddOperation->getNewData();     
+        parentData  = aAddOperation->parentData(*data());
+        int index = aAddOperation->index();
+        
+        if(parentData->type()== IAlfVariantType::EBranch &&
+               newData->type() == IAlfVariantType::EMap )
+            {
+            // This is actually the same as updating the data,
+            // since we can not have multiple branch or child data maps
+            if ( index == 0 )
+                {
+                // Set data for the branch
+                parentData->branch()->setData( newData->map() );
+                }
+            else if ( index == 1 )
+                {
+                // Set data for the branch children
+                parentData->branch()->setChildData( newData->map() );
+                }
+            }
+        else if(parentData->type()== IAlfVariantType::EMap)
+            {
+            parentData->map()->addItem( newData,
+                                   aAddOperation->newDataName() );
+            }
+        else if(parentData->type()== IAlfVariantType::EContainer )
+            {
+            parentData->container()->addItem(index, newData);
+            }
+        //ALF_PERF_STOP( perfdata, "AlfModel-AddData-Adding")
+        }
+	catch(AlfDataException& e)	        
+        {
+        newData = 0;
+        parentData = 0;
+        ALF_THROW(AlfDataException,EInvalidModelOperation,"AlfModel")
+        // Note the aAddOperation is not deleted. In case of exception the user
+        // should delete this object 
+        }
+    }
+    
+//-----------------------------------------------------------------------------
+//Remove a  number of data fields in the model data. All model change
+//observers are notified about the change.
+//----------------------------------------------------------------------------- 
+void AlfModel::removeData(AlfModelOperation* aRemoveOperation)
+    {
+    IAlfVariantType* parentData = 0;
+
+    try
+        {
+        //ALF_PERF_START( perfdata, "AlfModel-RemoveData-Removing")
+        parentData  = aRemoveOperation->parentData(*data());         
+        int index = aRemoveOperation->index();
+
+        if(parentData->type()== IAlfVariantType::EBranch )
+            {
+            if ( index == 0 )
+                {
+                // Remove the branch data
+                parentData->branch()->setData( 0 );
+                }
+            else if ( index == 1 )
+                {
+                // Remove the branch children data
+                parentData->branch()->setChildData( 0 );
+                }
+            }
+        else if(parentData->type()== IAlfVariantType::EMap)
+            {
+            parentData->map()->removeItem(index);
+            }
+        else if(parentData->type()== IAlfVariantType::EContainer )
+            {
+            parentData->container()->removeItem(index);
+            }    
+        //ALF_PERF_STOP( perfdata, "AlfModel-RemoveData-Removing")
+        }
+    catch(AlfDataException& e)
+        {
+        parentData = 0;
+        ALF_THROW(AlfDataException,EInvalidModelOperation,"AlfModel")
+        // Note the aRemoveOperation is not deleted. In case of exception the
+        // user should delete this object	
+        }
+    }
+
+
+void AlfModel::updateData(AlfModelOperation* aUpdateOperation)
+    {
+    IAlfVariantType* newData = 0;
+    IAlfVariantType* parentData = 0;
+
+    try
+        {
+        //ALF_PERF_START( perfdata, "AlfModel-UpdateData-Updating")
+        newData= aUpdateOperation->getNewData();
+
+        parentData  = aUpdateOperation->parentData(*data());
+        int index = aUpdateOperation->index();
+
+        if(parentData->type()== IAlfVariantType::EBranch &&
+                newData->type() == IAlfVariantType::EMap )
+            {
+            if ( index == 0 )
+                {
+                // Update the branch data
+                parentData->branch()->setData( newData->map() );
+                }
+            else if ( index == 1 )
+                {
+                // Update the data for the branch children
+                parentData->branch()->setChildData( newData->map() );
+                }
+            }
+        else if(parentData->type()== IAlfVariantType::EMap)
+            {
+            parentData->map()->replaceItem(index, newData);
+            }
+        else if(parentData->type()== IAlfVariantType::EContainer )
+            {
+            parentData->container()->replaceItem(index,newData);
+            }
+        //ALF_PERF_STOP( perfdata, "AlfModel-UpdateData-Updating")
+        }
+    catch(AlfDataException& e)
+        {
+        parentData=0;
+        newData=0;
+        ALF_THROW(AlfDataException,EInvalidModelOperation,"AlfModel")
+        //Note the aUpdateOperation is not deleted. In case of exception the user should delete this object
+        }
+    }
+
+//----------------------------------------------------------------------------
+//Add a  number of data fields in the model data. All model change
+//observers are notified about the change. 
+//----------------------------------------------------------------------------- 
+OSN_EXPORT void AlfModel::addData(
+    int aNumContainerIndices, int* aContainerIndices, IAlfVariantType* aData)
+    {
+    auto_ptr<AlfModelOperation> op( AlfModelOperation::create(
+    AlfModelOperation::EOperationAdd,
+    aNumContainerIndices,
+    aContainerIndices,
+    aData ) );
+
+    executeOperation( op.get() );
+    }
+
+//-----------------------------------------------------------------------------
+//Remove a  number of data fields in the model data. All model change
+//observers are notified about the change.
+//----------------------------------------------------------------------------- 
+OSN_EXPORT void AlfModel::removeData(
+    int aNumContainerIndices, int* aContainerIndices)
+    {
+    auto_ptr<AlfModelOperation> op( AlfModelOperation::create(
+    AlfModelOperation::EOperationRemove,
+    aNumContainerIndices,
+    aContainerIndices ) );
+
+    executeOperation( op.get() );
+    }
+
+//-----------------------------------------------------------------------------
+//Remove a  number of data fields in the model data. All model change
+//observers are notified about the change.
+//----------------------------------------------------------------------------- 
+OSN_EXPORT void AlfModel::updateData(
+    int aNumContainerIndices, int* aContainerIndices, IAlfVariantType* aData)
+    {
+    auto_ptr<AlfModelOperation> op( AlfModelOperation::create(
+    AlfModelOperation::EOperationUpdate,
+    aNumContainerIndices,
+    aContainerIndices,
+    aData ) );
+
+    executeOperation( op.get() );
+    }
+
+//-----------------------------------------------------------------------------
+    /**
+    *  Api for executing batch operations
+    * 
+    *  @param aOperationsArray  - An RPOinterArray containing the list of 
+    *                             operations to be executed in batch.
+    *  @since S60 ?S60_version 
+    */  
+//----------------------------------------------------------------------------- 
+OSN_EXPORT void AlfModel::executeOperations(
+    AlfPtrVector<AlfModelOperation>&  aOperationsArray)
+    {
+    int index = 0;
+    int count = aOperationsArray.count();  
+    int obsvrCount = mData->mObserverArray.count();
+    AlfModelOperation* tempOperation=0;
+
+    for ( index = 0; index < obsvrCount; index++ )
+        {
+        mData->mObserverArray[index]->dataChanging( aOperationsArray );
+        }
+
+    for ( index = 0; index < count; index++ )
+        {
+        tempOperation = aOperationsArray[index];
+        switch( tempOperation->operation() )
+            {
+            case AlfModelOperation::EOperationAdd:                 
+                 this->addData( tempOperation );
+                break;
+            case AlfModelOperation::EOperationRemove:                   
+                 this->removeData( tempOperation );
+                break;
+            case AlfModelOperation::EOperationUpdate:
+                 this->updateData( tempOperation );
+            default:
+                break;
+         
+            }
+        }
+
+    for ( index = 0; index < obsvrCount; index++ )
+        {
+        mData->mObserverArray[index]->dataChanged();
+        }
+    }
+
+//-----------------------------------------------------------------------------
+    /**
+    *  Api for executing one operation at a Time
+    * 
+    *  @param aOperation    - An Operation to be executed on the model.
+    *  @since S60 ?S60_version 
+    */  
+//----------------------------------------------------------------------------- 
+OSN_EXPORT void AlfModel::executeOperation(AlfModelOperation* aOperation)
+    {
+    int index = 0;
+    int obsvrCount = mData->mObserverArray.count();
+
+    for ( index = 0; index < obsvrCount; index++ )
+        {
+        mData->mObserverArray[index]->dataChanging( *aOperation );
+        }
+
+    switch(aOperation->operation())
+        {
+        case AlfModelOperation::EOperationAdd:                 
+             this->addData(aOperation);
+            break;
+        case AlfModelOperation::EOperationRemove:                   
+             this->removeData(aOperation);
+            break;
+        case AlfModelOperation::EOperationUpdate:
+             this->updateData(aOperation);
+        default:
+            break;
+        }
+
+    for ( index = 0; index < obsvrCount; index++ )
+        {
+        mData->mObserverArray[index]->dataChanged();
+        }
+    }
+} // Alf