--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mpx/commonframework/common/src/mpxcollectionpath.cpp Thu Dec 17 08:55:47 2009 +0200
@@ -0,0 +1,1068 @@
+/*
+* 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: implementation of collection path
+*
+*/
+
+#include <s32strm.h>
+#include <e32panic.h>
+#include <mpxuser.h>
+#include <mpxcmn.h>
+#include <mpxattribute.h>
+#include <mpxdata.h>
+#include "mpxcollectionpath.h"
+
+/**
+* Encapsulates single node in collection hierarchy level. A node represents a
+* level of the collection path
+*/
+NONSHARABLE_CLASS(CMPXCollectionPathNode) : public CBase
+ {
+public:
+ static CMPXCollectionPathNode* NewL();
+ static CMPXCollectionPathNode* NewLC();
+ static CMPXCollectionPathNode* NewLC(const CMPXCollectionPathNode& aNode);
+ virtual ~CMPXCollectionPathNode();
+public:
+ /**
+ * Sets current item at this level
+ */
+ void Set(const TMPXItemId& aId, TInt aIndex);
+
+ /**
+ * Sets the next level open mode
+ */
+ void Set(TMPXOpenMode aRequest);
+
+ /**
+ * Sets the next level open attributes
+ */
+ void SetL(const TArray<TMPXAttribute>& aAttrs);
+
+ /**
+ * Current index
+ */
+ TInt Index() const;
+
+ /**
+ * Current Id
+ */
+ const TMPXItemId& Id() const;
+
+ /**
+ * Open mode for next level
+ */
+ TMPXOpenMode OpenMode() const;
+
+ /**
+ * Open attributes for next level
+ */
+ const TArray<TMPXAttribute> OpenAttributes() const;
+
+public:
+ void ExternalizeL(RWriteStream& aStream) const;
+ void InternalizeL(RReadStream& aStream);
+
+private:
+ CMPXCollectionPathNode();
+ void ConstructL(const CMPXCollectionPathNode& aNode);
+ void ConstructL();
+
+private:
+ TMPXItemId iId;
+ TInt iIndex;
+ TMPXOpenMode iOpenMode;
+ RArray<TMPXAttribute> iAttrs; // Open attributes for next level
+ };
+
+
+// -----------------------------------------------------------------------------
+// CMPXCollectionPathNode::NewL
+// -----------------------------------------------------------------------------
+//
+CMPXCollectionPathNode* CMPXCollectionPathNode::NewL()
+ {
+ CMPXCollectionPathNode* self = NewLC();
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+// -----------------------------------------------------------------------------
+// CMPXCollectionPathNode::NewLC
+// -----------------------------------------------------------------------------
+//
+CMPXCollectionPathNode* CMPXCollectionPathNode::NewLC()
+ {
+ CMPXCollectionPathNode* self = new(ELeave) CMPXCollectionPathNode();
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ return self;
+ }
+
+// -----------------------------------------------------------------------------
+// CMPXCollectionPathNode::NewLC
+// -----------------------------------------------------------------------------
+//
+CMPXCollectionPathNode* CMPXCollectionPathNode::NewLC(
+ const CMPXCollectionPathNode& aNode)
+ {
+ CMPXCollectionPathNode* self = new(ELeave) CMPXCollectionPathNode();
+ CleanupStack::PushL(self);
+ self->ConstructL(aNode);
+ return self;
+ }
+
+// -----------------------------------------------------------------------------
+// CMPXCollectionPathNode::ConstructL
+// -----------------------------------------------------------------------------
+//
+void CMPXCollectionPathNode::ConstructL()
+ {
+ }
+
+// -----------------------------------------------------------------------------
+// CMPXCollectionPathNode::ConstructL
+// -----------------------------------------------------------------------------
+//
+void CMPXCollectionPathNode::ConstructL(
+ const CMPXCollectionPathNode& aNode)
+ {
+ iId=aNode.iId;
+ iIndex=aNode.iIndex;
+ iOpenMode=aNode.iOpenMode;
+ ::CopyArrayL<TMPXAttribute>(aNode.iAttrs.Array(), iAttrs);
+ }
+
+// -----------------------------------------------------------------------------
+// CMPXCollectionPathNode::CMPXCollectionPathNode
+// -----------------------------------------------------------------------------
+//
+CMPXCollectionPathNode::CMPXCollectionPathNode()
+: iId(KMPXInvalidItemId),
+ iIndex(KErrNotFound),
+ iOpenMode(EMPXOpenGroupOrPlaylist)
+ {
+ }
+
+// -----------------------------------------------------------------------------
+// CMPXCollectionPathNode::~CMPXCollectionPathNode
+// -----------------------------------------------------------------------------
+//
+CMPXCollectionPathNode::~CMPXCollectionPathNode()
+ {
+ iAttrs.Close();
+ }
+
+// -----------------------------------------------------------------------------
+// CMPXCollectionPathNode::Set
+// -----------------------------------------------------------------------------
+//
+void CMPXCollectionPathNode::Set(const TMPXItemId& aId, TInt aIndex)
+ {
+ iId=aId;
+ iIndex=aIndex;
+ }
+
+// -----------------------------------------------------------------------------
+// CMPXCollectionPathNode::Set
+// -----------------------------------------------------------------------------
+//
+void CMPXCollectionPathNode::Set(TMPXOpenMode aMode)
+ {
+ iOpenMode=aMode;
+ }
+
+// -----------------------------------------------------------------------------
+// CMPXCollectionPathNode::Set
+// -----------------------------------------------------------------------------
+//
+void CMPXCollectionPathNode::SetL(const TArray<TMPXAttribute>& aAttrs)
+ {
+ ::CopyArrayL(aAttrs, iAttrs);
+ }
+
+// -----------------------------------------------------------------------------
+// CMPXCollectionPathNode::Index
+// -----------------------------------------------------------------------------
+//
+TInt CMPXCollectionPathNode::Index() const
+ {
+ return iIndex;
+ }
+
+// -----------------------------------------------------------------------------
+// CMPXCollectionPathNode::Id
+// -----------------------------------------------------------------------------
+//
+const TMPXItemId& CMPXCollectionPathNode::Id() const
+ {
+ return iId;
+ }
+
+// -----------------------------------------------------------------------------
+// CMPXCollectionPathNode::OpenMode
+// -----------------------------------------------------------------------------
+//
+TMPXOpenMode CMPXCollectionPathNode::OpenMode() const
+ {
+ return iOpenMode;
+ }
+
+// -----------------------------------------------------------------------------
+// CMPXCollectionPathNode::OpenAttributes
+// -----------------------------------------------------------------------------
+//
+const TArray<TMPXAttribute> CMPXCollectionPathNode::OpenAttributes() const
+ {
+ return iAttrs.Array();
+ }
+
+// -----------------------------------------------------------------------------
+// Externalize object
+// -----------------------------------------------------------------------------
+//
+void CMPXCollectionPathNode::ExternalizeL(RWriteStream& aStream) const
+ {
+ aStream.WriteUint32L(iId.iId1);
+ aStream.WriteUint32L(iId.iId2);
+ aStream.WriteInt32L(iIndex);
+ aStream.WriteInt32L(iOpenMode);
+ ::ExternalizeL(iAttrs.Array(), aStream);
+ }
+
+// -----------------------------------------------------------------------------
+// Internalize object
+// -----------------------------------------------------------------------------
+//
+void CMPXCollectionPathNode::InternalizeL(RReadStream& aStream)
+ {
+ TUint32 id1 = aStream.ReadUint32L();
+ TUint32 id2 = aStream.ReadUint32L();
+ iId=TMPXItemId( id1, id2 );
+ iIndex=aStream.ReadInt32L();
+ iOpenMode=static_cast<TMPXOpenMode>(aStream.ReadInt32L());
+ iAttrs.Reset();
+ ::InternalizeL(iAttrs, aStream);
+ }
+
+// ============================== MEMBER FUNCTIONS =============================
+
+// -----------------------------------------------------------------------------
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CMPXCollectionPath* CMPXCollectionPath::NewL()
+ {
+ CMPXCollectionPath* p = new(ELeave) CMPXCollectionPath();
+ CleanupStack::PushL(p);
+ p->ConstructL();
+ CleanupStack::Pop(p);
+ return p;
+ }
+
+// -----------------------------------------------------------------------------
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CMPXCollectionPath* CMPXCollectionPath::NewL(
+ const CMPXCollectionPath& aPath)
+ {
+ CMPXCollectionPath* p = new(ELeave) CMPXCollectionPath();
+ CleanupStack::PushL(p);
+ p->ConstructL(aPath);
+ CleanupStack::Pop(p);
+ return p;
+ }
+
+// -----------------------------------------------------------------------------
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CMPXCollectionPath* CMPXCollectionPath::NewL(
+ RReadStream& aStream)
+ {
+ CMPXCollectionPath* p = new(ELeave) CMPXCollectionPath();
+ CleanupStack::PushL(p);
+ p->ConstructL(aStream);
+ CleanupStack::Pop(p);
+ return p;
+ }
+
+// -----------------------------------------------------------------------------
+// Destructor
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CMPXCollectionPath::~CMPXCollectionPath()
+ {
+ iNodeArray.ResetAndDestroy();
+ iNodeArray.Close();
+ iIds.Close();
+ iSelection.Close();
+ }
+
+// -----------------------------------------------------------------------------
+// Default constructor
+// -----------------------------------------------------------------------------
+//
+CMPXCollectionPath::CMPXCollectionPath() : iInvalidId(KMPXInvalidItemId)
+ {
+ }
+
+// ----------------------------------------------------------------------------
+// 2nd phase constructor.
+// ----------------------------------------------------------------------------
+//
+void CMPXCollectionPath::ConstructL(const CMPXCollectionPath& aPath)
+ {
+ iNodeArray.ResetAndDestroy();
+ TInt count = aPath.iNodeArray.Count();
+ for (TInt i=0; i<count; ++i)
+ {
+ CMPXCollectionPathNode* node =
+ CMPXCollectionPathNode::NewLC(*(aPath.iNodeArray[i]));
+ iNodeArray.AppendL(node);
+ CleanupStack::Pop(node);
+ }
+ ::CopyArrayL(aPath.iIds.Array(),iIds);
+ ::CopyArrayL(aPath.iSelection.Array(),iSelection);
+ }
+
+// ----------------------------------------------------------------------------
+// 2nd phase constructor.
+// ----------------------------------------------------------------------------
+//
+void CMPXCollectionPath::ConstructL()
+ {
+ }
+
+// ----------------------------------------------------------------------------
+// 2nd phase constructor.
+// ----------------------------------------------------------------------------
+//
+void CMPXCollectionPath::ConstructL(RReadStream& aStream)
+ {
+ InternalizeL(aStream);
+ }
+
+// -----------------------------------------------------------------------------
+// Advances path to next item
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TBool CMPXCollectionPath::operator++()
+ {
+ TBool ret(EFalse);
+ TInt index=Index();
+ if (index < Count()-1)
+ {
+ Set(++index);
+ ret=ETrue;
+ } // else the last one, no more to go and return false
+ return ret;
+ }
+
+// -----------------------------------------------------------------------------
+// Advances path to previous item
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TBool CMPXCollectionPath::operator--()
+ {
+ TBool ret=EFalse;
+ TInt index=Index();
+ if (index>0)
+ {
+ Set(--index);
+ ret=ETrue;
+ } // else the first one, no more to go and return false
+ return ret;
+ }
+
+// -----------------------------------------------------------------------------
+// Sets path to first item
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXCollectionPath::SetToFirst()
+ {
+ Set(0);
+ }
+
+// -----------------------------------------------------------------------------
+// Sets path to last item
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXCollectionPath::SetToLast()
+ {
+ Set(Count()-1);
+ }
+
+// -----------------------------------------------------------------------------
+// Change current item by index at top level
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXCollectionPath::Set(TInt aIndex)
+ {
+ MPX_ASSERT(Levels());
+ CMPXCollectionPathNode& topLevel = TopLevel();
+ // RArray will panic if aIndex out of bound
+ topLevel.Set(iIds[aIndex], aIndex);
+ }
+
+// -----------------------------------------------------------------------------
+// Change current item by id at top level
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXCollectionPath::Set(const TMPXItemId& aId)
+ {
+ TInt index=IndexOfId(aId);
+ MPX_ASSERT(KErrNotFound!=index && Levels());
+ CMPXCollectionPathNode& topLevel = TopLevel();
+ topLevel.Set(aId, index);
+ }
+
+// -----------------------------------------------------------------------------
+// Set open mode for next level
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXCollectionPath::Set(TMPXOpenMode aMode)
+ {
+ MPX_ASSERT(Levels());
+ TopLevel().Set(aMode);
+ }
+
+// -----------------------------------------------------------------------------
+// Set open attrobutes for next level
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXCollectionPath::Set(const TArray<TMPXAttribute>& aAttrs)
+ { // DEPRECATED
+ TRAP_IGNORE(SetL(aAttrs));
+ }
+
+// -----------------------------------------------------------------------------
+// Set open attrobutes for next level
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXCollectionPath::SetL(const TArray<TMPXAttribute>& aAttrs)
+ {
+ MPX_ASSERT(Levels());
+ TopLevel().SetL(aAttrs);
+ }
+
+// -----------------------------------------------------------------------------
+// Select an item by id in the path
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXCollectionPath::SelectL(const TMPXItemId& aId)
+ {
+ TInt index=IndexOfId(aId);
+ MPX_ASSERT(KErrNotFound != index);
+ SelectL(index);
+ }
+
+// -----------------------------------------------------------------------------
+// Select an item by index in the path
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXCollectionPath::SelectL(TInt aIndex)
+ {
+ MPX_ASSERT_EX(aIndex>=0 && aIndex<iIds.Count(), EBadArrayIndex);
+ TInt err = iSelection.InsertInOrder(aIndex);
+ if (KErrNone!=err && KErrAlreadyExists!=err)
+ { // ignore duplicated items
+ User::Leave(err);
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// Select an item by index in the path
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXCollectionPath::SelectAllL()
+ {
+ iSelection.Reset();
+ for (TInt i=0; i < iIds.Count(); ++i)
+ {
+ iSelection.AppendL(i);
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// Deselects an item by id in the path
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXCollectionPath::Deselect(const TMPXItemId& aId)
+ {
+ TInt index=IndexOfId(aId);
+ MPX_ASSERT(KErrNotFound != index);
+ Deselect(index);
+ }
+
+// -----------------------------------------------------------------------------
+// Deselects an item by index in the path
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXCollectionPath::Deselect(TInt aIndex)
+ {
+ MPX_ASSERT_EX(aIndex>=0 && aIndex<iIds.Count(), EBadArrayIndex);
+ TInt index(iSelection.FindInOrder(aIndex));
+ MPX_ASSERT(KErrNotFound !=index);
+ iSelection.Remove(index);
+ }
+
+// -----------------------------------------------------------------------------
+// Select an item by index in the path
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXCollectionPath::DeselectAll()
+ {
+ iSelection.Reset();
+ }
+
+// -----------------------------------------------------------------------------
+// Removes an item in the path
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXCollectionPath::Remove(const TMPXItemId& aId)
+ {
+ TInt index=IndexOfId(aId);
+ MPX_ASSERT(KErrNotFound != index);
+ Remove(index);
+ }
+
+// -----------------------------------------------------------------------------
+// Removes an item in the path
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXCollectionPath::Remove(TInt aIndex)
+ {
+ iIds.Remove(aIndex);
+ TInt ret = iSelection.FindInOrder(aIndex);
+ if (KErrNotFound != ret)
+ {
+ iSelection.Remove(ret);
+ TInt count = iSelection.Count();
+ for (TInt i=ret; i<count; i++)
+ {
+ --iSelection[i];
+ }
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// Query selection
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TBool CMPXCollectionPath::IsSelected(const TMPXItemId& aId) const
+ {
+ TBool ret(EFalse);
+ TInt index=IndexOfId(aId);
+ if (KErrNotFound != index)
+ {
+ ret = IsSelected(index);
+ }
+ return ret;
+ }
+
+// -----------------------------------------------------------------------------
+// Query selection
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TBool CMPXCollectionPath::IsSelected(TInt aIndex) const
+ {
+ return iSelection.FindInOrder(aIndex) != KErrNotFound;
+ }
+
+// -----------------------------------------------------------------------------
+// Clears selection
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXCollectionPath::ClearSelection()
+ {
+ iSelection.Reset();
+ }
+
+// -----------------------------------------------------------------------------
+// Array of currently selected indices
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TArray<TInt> CMPXCollectionPath::Selection() const
+ {
+ return iSelection.Array();
+ }
+
+// -----------------------------------------------------------------------------
+// Current selected IDs
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXCollectionPath::SelectionL(RArray<TMPXItemId>& aIds) const
+ {
+ aIds.Reset();
+ TInt idCount(iIds.Count());
+ TInt selCount(iSelection.Count());
+ for (TInt i=0; i<selCount; ++i)
+ {
+ TInt idIndex(iSelection[i]);
+ if (idIndex < idCount)
+ {
+ aIds.AppendL(iIds[idIndex]);
+ }
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// Update the item id at a particular index
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXCollectionPath::Update( TInt aIndex, TMPXItemId& aNewId )
+ {
+ MPX_ASSERT( aIndex >= 0 && aIndex < iIds.Count() );
+ iIds[aIndex] = aNewId;
+ }
+
+// -----------------------------------------------------------------------------
+// Index of current item at top level
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TInt CMPXCollectionPath::Index() const
+ {
+ TInt ret(KErrNotFound);
+ if (Levels())
+ {
+ ret = TopLevel().Index();
+ }
+ return ret;
+ }
+
+// -----------------------------------------------------------------------------
+// Return current item id at top level
+// -----------------------------------------------------------------------------
+//
+EXPORT_C const TMPXItemId& CMPXCollectionPath::Id() const
+ {
+ if (Levels())
+ {
+ return TopLevel().Id();
+ }
+ else
+ {
+ return iInvalidId;
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// Returns the number of items at top level
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TInt CMPXCollectionPath::Count() const
+ {
+ return iIds.Count();
+ }
+
+// -----------------------------------------------------------------------------
+// Returns the open mode for the next level
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TMPXOpenMode CMPXCollectionPath::OpenNextMode() const
+ {
+ return Levels() ? TopLevel().OpenMode():EMPXOpenGroupOrPlaylist;
+ }
+
+// -----------------------------------------------------------------------------
+// Returns the open mode for the previous level
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TMPXOpenMode CMPXCollectionPath::OpenPreviousMode() const
+ {
+ TInt n=Levels();
+ return n>1?iNodeArray[n-2]->OpenMode():EMPXOpenGroupOrPlaylist;
+ }
+
+// -----------------------------------------------------------------------------
+// Index from id
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TInt CMPXCollectionPath::IndexOfId(const TMPXItemId& aId) const
+ {
+ TInt ret(KErrNotFound);
+ for (TInt i=iIds.Count(); --i>=0; )
+ {
+ if (aId == iIds[i])
+ {
+ ret = i;
+ break;
+ }
+ }
+ return ret;
+ }
+
+// -----------------------------------------------------------------------------
+// Return item id at top specific level for a specific item
+// -----------------------------------------------------------------------------
+//
+EXPORT_C const TMPXItemId& CMPXCollectionPath::IdOfIndex( TInt aIndex ) const
+ {
+ if( aIndex >=0 && aIndex < iIds.Count() )
+ {
+ return iIds[aIndex];
+ }
+ else
+ {
+ return iInvalidId;
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// Return item index at a specific level
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TInt CMPXCollectionPath::Index(TInt aLevel) const
+ {
+ MPX_ASSERT(aLevel>=0 && aLevel < Levels());
+ return iNodeArray[aLevel]->Index();
+ }
+
+// -----------------------------------------------------------------------------
+// Return item id at a specific level
+// -----------------------------------------------------------------------------
+//
+EXPORT_C const TMPXItemId& CMPXCollectionPath::Id(TInt aLevel) const
+ {
+ if( aLevel < iNodeArray.Count() && aLevel >= 0 )
+ {
+ return iNodeArray[aLevel]->Id();
+ }
+ else
+ {
+ return iInvalidId;
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// Returns the depth into the collection
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TInt CMPXCollectionPath::Levels() const
+ {
+ return iNodeArray.Count();
+ }
+
+// -----------------------------------------------------------------------------
+// Remove a level from path
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXCollectionPath::Back()
+ {
+ TInt levels = Levels();
+ MPX_ASSERT(levels > 0);
+ CMPXCollectionPathNode* node = iNodeArray[levels-1];
+ iNodeArray.Remove(levels-1);
+ delete node;
+ iIds.Reset();
+ iSelection.Reset();
+ }
+
+// -----------------------------------------------------------------------------
+// Append a new level
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXCollectionPath::AppendL(const TArray<TMPXItemId>& aIds)
+ {
+ iIds.Reset();
+ iSelection.Reset();
+ CMPXCollectionPathNode* node(NULL);
+ if (aIds.Count())
+ {
+ ::CopyArrayL(aIds, iIds);
+ node = CMPXCollectionPathNode::NewLC();
+ node->Set(iIds[0], 0);
+ iNodeArray.AppendL(node);
+ CleanupStack::Pop(node);
+ }
+ else
+ {// add a level in order to support back
+ node = CMPXCollectionPathNode::NewLC();
+ node->Set(iInvalidId, KErrNotFound);
+ iNodeArray.AppendL(node);
+ CleanupStack::Pop(node);
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// Append a new level
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXCollectionPath::AppendL(const TMPXItemId& aId)
+ {
+ RArray<TMPXItemId> ids;
+ CleanupClosePushL(ids);
+ ids.AppendL(aId);
+ AppendL(ids.Array());
+ CleanupStack::PopAndDestroy(&ids);
+ }
+
+// -----------------------------------------------------------------------------
+// Append an id
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXCollectionPath::InsertL(const TMPXItemId& aId, TInt aPos)
+ {
+ MPX_ASSERT(iIds.Count());
+ iIds.InsertL(aId, aPos);
+ // update the selection
+ for (TInt i=0; i<iSelection.Count(); ++i)
+ {
+ TInt& sel = iSelection[i];
+ if (sel >=aPos)
+ {
+ ++sel;
+ }
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// Resets the collection path object
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXCollectionPath::Reset()
+ {
+ iNodeArray.ResetAndDestroy();
+ iIds.Reset();
+ iSelection.Reset();
+ }
+
+// -----------------------------------------------------------------------------
+// Creates a collection path pointing to the container
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CMPXCollectionPath* CMPXCollectionPath::ContainerPathL() const
+ {
+ CMPXCollectionPath* p = CMPXCollectionPath::NewL();
+ CleanupStack::PushL( p );
+
+ TInt count = iNodeArray.Count() - 1; // Copy up to container level
+ for (TInt i=0; i<count; ++i)
+ {
+ CMPXCollectionPathNode* node =
+ CMPXCollectionPathNode::NewLC(*iNodeArray[i]);
+ p->iNodeArray.AppendL(node);
+ CleanupStack::Pop(node);
+ }
+
+ CleanupStack::Pop( p );
+ return p;
+ }
+
+// -----------------------------------------------------------------------------
+// Update collection path. When a item changed in the collection plugin,
+// collection plugin calls back collection context, which in turn updates
+// its collection paths by calling this function
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TInt CMPXCollectionPath::HandleChange(
+ const TUid& aCollectionId,
+ const TMPXItemId& aId,
+ const TMPXItemId& aDeprecatedId,
+ CMPXCollectionPath::TMPXCollectionPathChange aChange,
+ TInt& aSelection )
+ {
+ TBool updated(EPathUnchanged);
+ aSelection = KErrNotFound;
+
+ if (aChange == CMPXCollectionPath::EAdded)
+ {
+ updated = EPathModified;
+ }
+ else if (aChange == CMPXCollectionPath::EGroupModified )
+ {
+ TInt levels( Levels() );
+ if( levels > 0 )
+ {
+ // Check if the collection id is correct
+ if (iNodeArray[ECollectionUid]->Id() ==
+ TMPXItemId(aCollectionId.iUid) && levels > 1)
+ {
+ // Check if the container level is the one modified
+ if( aId == Id( levels-2 ) )
+ {
+ updated = EPathModified;
+ }
+ }
+ }
+ }
+ else if (aChange == CMPXCollectionPath::EDeleted ||
+ aChange == CMPXCollectionPath::EModified)
+ {
+ TInt levels = Levels();
+ if (levels > 0)
+ {
+ // check collection id level, aka root level
+ if (iNodeArray[ECollectionUid]->Id() ==
+ TMPXItemId(aCollectionId.iUid) && levels > 1)
+ {
+ // check node array except top level and root level.
+ for (TInt i=ECollectionRoot+1; i<levels-1; ++i)
+ {
+ if (iNodeArray[i]->Id() == aId ||
+ (aDeprecatedId != 0 && iNodeArray[i]->Id() == aDeprecatedId))
+ {
+ if( aChange == CMPXCollectionPath::EModified &&
+ aDeprecatedId != 0 )
+ {
+ // If the item is modified and the item id is updated
+ // we simply replace the node level item id with the new
+ // item id
+ //
+ // Continue and check other levels if any other
+ // levels are using this ID. ie: all songs of an artist
+ // The item IDs need to be unique across all levels, but
+ // can have duplicates. This is in the case of a playlist with
+ // more than 1 instance of a song
+ //
+ CMPXCollectionPathNode* node = iNodeArray[i];
+ node->Set( aId, Index(i) );
+ updated = EPathModified;
+ }
+ else
+ {
+ // Trim the path and break out of the loop
+ aSelection = Index(i);
+ for (TInt j=Levels()-1; j>i; --j)
+ {
+ CMPXCollectionPathNode* node = iNodeArray[j];
+ iNodeArray.Remove(j);
+ delete node;
+ }
+ updated = EPathClipped;
+ break;
+ }
+ }
+ }
+ // Check the top level
+ if (!updated)
+ {
+ TMPXItemId search = aDeprecatedId != 0? aDeprecatedId : aId;
+ TInt temp(KErrNotFound);
+
+ // Unmatched ids in the item ID,
+ // try to look for an exact match first
+ //
+ if( search.iId1 != search.iId2 )
+ {
+ for (TInt i=iIds.Count(); --i>=0; )
+ {
+ if (search == iIds[i] )
+ {
+ temp = i;
+ break;
+ }
+ }
+ }
+ // Still not found, check for approximate equal
+ //
+ if( KErrNotFound == temp )
+ {
+ for (TInt i=iIds.Count(); --i>=0; )
+ {
+ if (search.ApproxEqual(iIds[i]))
+ {
+ temp = i;
+ break;
+ }
+ }
+ }
+ if (KErrNotFound != temp)
+ { // Improvement: only remove item deleted
+ updated = EPathModified;
+ aSelection = temp;
+ }
+ }
+
+ // Only clean up level if the path has been clipped
+ if (updated == EPathClipped )
+ {
+ // Reset top level
+ iIds.Reset();
+ iSelection.Reset();
+ }
+ }
+ }
+ }
+ return updated;
+ }
+
+// -----------------------------------------------------------------------------
+// CMPXCollectionPath::OpenAttributes
+// -----------------------------------------------------------------------------
+//
+EXPORT_C const TArray<TMPXAttribute> CMPXCollectionPath::OpenAttributes() const
+ {
+ MPX_ASSERT(Levels()>0);
+ return TopLevel().OpenAttributes();
+ }
+
+// -----------------------------------------------------------------------------
+// Get top level items
+// -----------------------------------------------------------------------------
+//
+EXPORT_C const TArray<TMPXItemId> CMPXCollectionPath::Items() const
+ {
+ MPX_ASSERT(Levels()>0);
+ return iIds.Array();
+ }
+
+// -----------------------------------------------------------------------------
+// Internalize object
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXCollectionPath::InternalizeL(RReadStream& aStream)
+ {
+ (void)aStream.ReadInt32L(); // Discard object type
+ iNodeArray.ResetAndDestroy();
+ ::InternalizeCObjectArrayL(iNodeArray, aStream);
+ iIds.Reset();
+ MPXUser::InternalizeL(iIds, aStream);
+ iSelection.Reset();
+ ::InternalizeL(iSelection, aStream);
+ }
+
+// -----------------------------------------------------------------------------
+// Externalize object
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CMPXCollectionPath::ExternalizeL(RWriteStream& aStream) const
+ {
+ aStream.WriteInt32L(MMPXData::EPath);
+ ::ExternalizeL(iNodeArray.Array(), aStream);
+ MPXUser::ExternalizeL(iIds.Array(), aStream);
+ ::ExternalizeL(iSelection.Array(), aStream);
+ }
+
+// -----------------------------------------------------------------------------
+// Top level
+// -----------------------------------------------------------------------------
+//
+CMPXCollectionPathNode& CMPXCollectionPath::TopLevel()
+ {
+ MPX_ASSERT(Levels() > 0);
+ return *iNodeArray[Levels()-1];
+ }
+
+// -----------------------------------------------------------------------------
+// Top level
+// -----------------------------------------------------------------------------
+//
+const CMPXCollectionPathNode& CMPXCollectionPath::TopLevel() const
+ {
+ MPX_ASSERT(Levels() > 0);
+ return *iNodeArray[Levels()-1];
+ }