mpx/commonframework/common/src/mpxcollectionpath.cpp
changeset 0 a2952bb97e68
child 48 b7b49303d0c0
equal deleted inserted replaced
-1:000000000000 0:a2952bb97e68
       
     1 /*
       
     2 * Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  implementation of collection path
       
    15 *
       
    16 */
       
    17 
       
    18 #include <s32strm.h>
       
    19 #include <e32panic.h>
       
    20 #include <mpxuser.h>
       
    21 #include <mpxcmn.h>
       
    22 #include <mpxattribute.h>
       
    23 #include <mpxdata.h>
       
    24 #include "mpxcollectionpath.h"
       
    25 
       
    26 /**
       
    27 * Encapsulates single node in collection hierarchy level. A node represents a
       
    28 * level of the collection path
       
    29 */
       
    30 NONSHARABLE_CLASS(CMPXCollectionPathNode) : public CBase
       
    31     {
       
    32 public:
       
    33     static CMPXCollectionPathNode* NewL();
       
    34     static CMPXCollectionPathNode* NewLC();
       
    35     static CMPXCollectionPathNode* NewLC(const CMPXCollectionPathNode& aNode);
       
    36     virtual ~CMPXCollectionPathNode();
       
    37 public:
       
    38     /**
       
    39     * Sets current item at this level
       
    40     */
       
    41     void Set(const TMPXItemId& aId, TInt aIndex);
       
    42 
       
    43     /**
       
    44     * Sets the next level open mode
       
    45     */
       
    46     void Set(TMPXOpenMode aRequest);
       
    47 
       
    48     /**
       
    49     * Sets the next level open attributes
       
    50     */
       
    51     void SetL(const TArray<TMPXAttribute>& aAttrs);
       
    52 
       
    53     /**
       
    54     * Current index
       
    55     */
       
    56     TInt Index() const;
       
    57 
       
    58     /**
       
    59     * Current Id
       
    60     */
       
    61     const TMPXItemId& Id() const;
       
    62 
       
    63     /**
       
    64     * Open mode for next level
       
    65     */
       
    66     TMPXOpenMode OpenMode() const;
       
    67 
       
    68     /**
       
    69     * Open attributes for next level
       
    70     */
       
    71     const TArray<TMPXAttribute> OpenAttributes() const;
       
    72 
       
    73 public:
       
    74     void ExternalizeL(RWriteStream& aStream) const;
       
    75     void InternalizeL(RReadStream& aStream);
       
    76 
       
    77 private:
       
    78     CMPXCollectionPathNode();
       
    79     void ConstructL(const CMPXCollectionPathNode& aNode);
       
    80     void ConstructL();
       
    81 
       
    82 private:
       
    83     TMPXItemId iId;
       
    84     TInt iIndex;
       
    85     TMPXOpenMode iOpenMode;
       
    86     RArray<TMPXAttribute> iAttrs; // Open attributes for next level
       
    87     };
       
    88 
       
    89 
       
    90 // -----------------------------------------------------------------------------
       
    91 // CMPXCollectionPathNode::NewL
       
    92 // -----------------------------------------------------------------------------
       
    93 //
       
    94 CMPXCollectionPathNode* CMPXCollectionPathNode::NewL()
       
    95     {
       
    96     CMPXCollectionPathNode* self = NewLC();
       
    97     CleanupStack::Pop(self);
       
    98     return self;
       
    99     }
       
   100 
       
   101 // -----------------------------------------------------------------------------
       
   102 // CMPXCollectionPathNode::NewLC
       
   103 // -----------------------------------------------------------------------------
       
   104 //
       
   105 CMPXCollectionPathNode* CMPXCollectionPathNode::NewLC()
       
   106     {
       
   107     CMPXCollectionPathNode* self = new(ELeave) CMPXCollectionPathNode();
       
   108     CleanupStack::PushL(self);
       
   109     self->ConstructL();
       
   110     return self;
       
   111     }
       
   112 
       
   113 // -----------------------------------------------------------------------------
       
   114 // CMPXCollectionPathNode::NewLC
       
   115 // -----------------------------------------------------------------------------
       
   116 //
       
   117 CMPXCollectionPathNode* CMPXCollectionPathNode::NewLC(
       
   118     const CMPXCollectionPathNode& aNode)
       
   119     {
       
   120     CMPXCollectionPathNode* self = new(ELeave) CMPXCollectionPathNode();
       
   121     CleanupStack::PushL(self);
       
   122     self->ConstructL(aNode);
       
   123     return self;
       
   124     }
       
   125 
       
   126 // -----------------------------------------------------------------------------
       
   127 // CMPXCollectionPathNode::ConstructL
       
   128 // -----------------------------------------------------------------------------
       
   129 //
       
   130 void CMPXCollectionPathNode::ConstructL()
       
   131     {
       
   132     }
       
   133 
       
   134 // -----------------------------------------------------------------------------
       
   135 // CMPXCollectionPathNode::ConstructL
       
   136 // -----------------------------------------------------------------------------
       
   137 //
       
   138 void CMPXCollectionPathNode::ConstructL(
       
   139     const CMPXCollectionPathNode& aNode)
       
   140     {
       
   141     iId=aNode.iId;
       
   142     iIndex=aNode.iIndex;
       
   143     iOpenMode=aNode.iOpenMode;
       
   144     ::CopyArrayL<TMPXAttribute>(aNode.iAttrs.Array(), iAttrs);
       
   145     }
       
   146 
       
   147 // -----------------------------------------------------------------------------
       
   148 // CMPXCollectionPathNode::CMPXCollectionPathNode
       
   149 // -----------------------------------------------------------------------------
       
   150 //
       
   151 CMPXCollectionPathNode::CMPXCollectionPathNode()
       
   152 :   iId(KMPXInvalidItemId),
       
   153     iIndex(KErrNotFound),
       
   154     iOpenMode(EMPXOpenGroupOrPlaylist)
       
   155     {
       
   156     }
       
   157 
       
   158 // -----------------------------------------------------------------------------
       
   159 // CMPXCollectionPathNode::~CMPXCollectionPathNode
       
   160 // -----------------------------------------------------------------------------
       
   161 //
       
   162 CMPXCollectionPathNode::~CMPXCollectionPathNode()
       
   163     {
       
   164     iAttrs.Close();
       
   165     }
       
   166 
       
   167 // -----------------------------------------------------------------------------
       
   168 // CMPXCollectionPathNode::Set
       
   169 // -----------------------------------------------------------------------------
       
   170 //
       
   171 void CMPXCollectionPathNode::Set(const TMPXItemId& aId, TInt aIndex)
       
   172     {
       
   173     iId=aId;
       
   174     iIndex=aIndex;
       
   175     }
       
   176 
       
   177 // -----------------------------------------------------------------------------
       
   178 // CMPXCollectionPathNode::Set
       
   179 // -----------------------------------------------------------------------------
       
   180 //
       
   181 void CMPXCollectionPathNode::Set(TMPXOpenMode aMode)
       
   182     {
       
   183     iOpenMode=aMode;
       
   184     }
       
   185 
       
   186 // -----------------------------------------------------------------------------
       
   187 // CMPXCollectionPathNode::Set
       
   188 // -----------------------------------------------------------------------------
       
   189 //
       
   190 void CMPXCollectionPathNode::SetL(const TArray<TMPXAttribute>& aAttrs)
       
   191     {
       
   192     ::CopyArrayL(aAttrs, iAttrs);
       
   193     }
       
   194 
       
   195 // -----------------------------------------------------------------------------
       
   196 // CMPXCollectionPathNode::Index
       
   197 // -----------------------------------------------------------------------------
       
   198 //
       
   199 TInt CMPXCollectionPathNode::Index() const
       
   200     {
       
   201     return iIndex;
       
   202     }
       
   203 
       
   204 // -----------------------------------------------------------------------------
       
   205 // CMPXCollectionPathNode::Id
       
   206 // -----------------------------------------------------------------------------
       
   207 //
       
   208 const TMPXItemId& CMPXCollectionPathNode::Id() const
       
   209     {
       
   210     return iId;
       
   211     }
       
   212 
       
   213 // -----------------------------------------------------------------------------
       
   214 // CMPXCollectionPathNode::OpenMode
       
   215 // -----------------------------------------------------------------------------
       
   216 //
       
   217 TMPXOpenMode CMPXCollectionPathNode::OpenMode() const
       
   218     {
       
   219     return iOpenMode;
       
   220     }
       
   221 
       
   222 // -----------------------------------------------------------------------------
       
   223 // CMPXCollectionPathNode::OpenAttributes
       
   224 // -----------------------------------------------------------------------------
       
   225 //
       
   226 const TArray<TMPXAttribute> CMPXCollectionPathNode::OpenAttributes() const
       
   227     {
       
   228     return iAttrs.Array();
       
   229     }
       
   230 
       
   231 // -----------------------------------------------------------------------------
       
   232 // Externalize object
       
   233 // -----------------------------------------------------------------------------
       
   234 //
       
   235 void CMPXCollectionPathNode::ExternalizeL(RWriteStream& aStream) const
       
   236     {
       
   237     aStream.WriteUint32L(iId.iId1);
       
   238     aStream.WriteUint32L(iId.iId2);
       
   239     aStream.WriteInt32L(iIndex);
       
   240     aStream.WriteInt32L(iOpenMode);
       
   241     ::ExternalizeL(iAttrs.Array(), aStream);
       
   242     }
       
   243 
       
   244 // -----------------------------------------------------------------------------
       
   245 // Internalize object
       
   246 // -----------------------------------------------------------------------------
       
   247 //
       
   248 void CMPXCollectionPathNode::InternalizeL(RReadStream& aStream)
       
   249     {
       
   250     TUint32 id1 = aStream.ReadUint32L();
       
   251     TUint32 id2 = aStream.ReadUint32L();
       
   252     iId=TMPXItemId( id1, id2 );
       
   253     iIndex=aStream.ReadInt32L();
       
   254     iOpenMode=static_cast<TMPXOpenMode>(aStream.ReadInt32L());
       
   255     iAttrs.Reset();
       
   256     ::InternalizeL(iAttrs, aStream);
       
   257     }
       
   258 
       
   259 // ============================== MEMBER FUNCTIONS =============================
       
   260 
       
   261 // -----------------------------------------------------------------------------
       
   262 // Two-phased constructor.
       
   263 // -----------------------------------------------------------------------------
       
   264 //
       
   265 EXPORT_C CMPXCollectionPath* CMPXCollectionPath::NewL()
       
   266     {
       
   267     CMPXCollectionPath* p = new(ELeave) CMPXCollectionPath();
       
   268     CleanupStack::PushL(p);
       
   269     p->ConstructL();
       
   270     CleanupStack::Pop(p);
       
   271     return p;
       
   272     }
       
   273 
       
   274 // -----------------------------------------------------------------------------
       
   275 // Two-phased constructor.
       
   276 // -----------------------------------------------------------------------------
       
   277 //
       
   278 EXPORT_C CMPXCollectionPath* CMPXCollectionPath::NewL(
       
   279     const CMPXCollectionPath& aPath)
       
   280     {
       
   281     CMPXCollectionPath* p = new(ELeave) CMPXCollectionPath();
       
   282     CleanupStack::PushL(p);
       
   283     p->ConstructL(aPath);
       
   284     CleanupStack::Pop(p);
       
   285     return p;
       
   286     }
       
   287 
       
   288 // -----------------------------------------------------------------------------
       
   289 // Two-phased constructor.
       
   290 // -----------------------------------------------------------------------------
       
   291 //
       
   292 EXPORT_C CMPXCollectionPath* CMPXCollectionPath::NewL(
       
   293     RReadStream& aStream)
       
   294     {
       
   295     CMPXCollectionPath* p = new(ELeave) CMPXCollectionPath();
       
   296     CleanupStack::PushL(p);
       
   297     p->ConstructL(aStream);
       
   298     CleanupStack::Pop(p);
       
   299     return p;
       
   300     }
       
   301 
       
   302 // -----------------------------------------------------------------------------
       
   303 // Destructor
       
   304 // -----------------------------------------------------------------------------
       
   305 //
       
   306 EXPORT_C CMPXCollectionPath::~CMPXCollectionPath()
       
   307     {
       
   308     iNodeArray.ResetAndDestroy();
       
   309     iNodeArray.Close();
       
   310     iIds.Close();
       
   311     iSelection.Close();
       
   312     }
       
   313 
       
   314 // -----------------------------------------------------------------------------
       
   315 // Default constructor
       
   316 // -----------------------------------------------------------------------------
       
   317 //
       
   318 CMPXCollectionPath::CMPXCollectionPath() : iInvalidId(KMPXInvalidItemId)
       
   319     {
       
   320     }
       
   321 
       
   322 // ----------------------------------------------------------------------------
       
   323 // 2nd phase constructor.
       
   324 // ----------------------------------------------------------------------------
       
   325 //
       
   326 void CMPXCollectionPath::ConstructL(const CMPXCollectionPath& aPath)
       
   327     {
       
   328     iNodeArray.ResetAndDestroy();
       
   329     TInt count = aPath.iNodeArray.Count();
       
   330     for (TInt i=0; i<count; ++i)
       
   331         {
       
   332         CMPXCollectionPathNode* node =
       
   333             CMPXCollectionPathNode::NewLC(*(aPath.iNodeArray[i]));
       
   334         iNodeArray.AppendL(node);
       
   335         CleanupStack::Pop(node);
       
   336         }
       
   337     ::CopyArrayL(aPath.iIds.Array(),iIds);
       
   338     ::CopyArrayL(aPath.iSelection.Array(),iSelection);
       
   339     }
       
   340 
       
   341 // ----------------------------------------------------------------------------
       
   342 // 2nd phase constructor.
       
   343 // ----------------------------------------------------------------------------
       
   344 //
       
   345 void CMPXCollectionPath::ConstructL()
       
   346     {
       
   347     }
       
   348 
       
   349 // ----------------------------------------------------------------------------
       
   350 // 2nd phase constructor.
       
   351 // ----------------------------------------------------------------------------
       
   352 //
       
   353 void CMPXCollectionPath::ConstructL(RReadStream& aStream)
       
   354     {
       
   355     InternalizeL(aStream);
       
   356     }
       
   357 
       
   358 // -----------------------------------------------------------------------------
       
   359 // Advances path to next item
       
   360 // -----------------------------------------------------------------------------
       
   361 //
       
   362 EXPORT_C TBool CMPXCollectionPath::operator++()
       
   363     {
       
   364     TBool ret(EFalse);
       
   365     TInt index=Index();
       
   366     if (index < Count()-1)
       
   367         {
       
   368         Set(++index);
       
   369         ret=ETrue;
       
   370         } // else the last one, no more to go and return false
       
   371     return ret;
       
   372     }
       
   373 
       
   374 // -----------------------------------------------------------------------------
       
   375 // Advances path to previous item
       
   376 // -----------------------------------------------------------------------------
       
   377 //
       
   378 EXPORT_C TBool CMPXCollectionPath::operator--()
       
   379     {
       
   380     TBool ret=EFalse;
       
   381     TInt index=Index();
       
   382     if (index>0)
       
   383         {
       
   384         Set(--index);
       
   385         ret=ETrue;
       
   386         } // else the first one, no more to go and return false
       
   387     return ret;
       
   388     }
       
   389 
       
   390 // -----------------------------------------------------------------------------
       
   391 // Sets path to first item
       
   392 // -----------------------------------------------------------------------------
       
   393 //
       
   394 EXPORT_C void CMPXCollectionPath::SetToFirst()
       
   395     {
       
   396     Set(0);
       
   397     }
       
   398 
       
   399 // -----------------------------------------------------------------------------
       
   400 // Sets path to last item
       
   401 // -----------------------------------------------------------------------------
       
   402 //
       
   403 EXPORT_C void CMPXCollectionPath::SetToLast()
       
   404     {
       
   405     Set(Count()-1);
       
   406     }
       
   407 
       
   408 // -----------------------------------------------------------------------------
       
   409 // Change current item by index at top level
       
   410 // -----------------------------------------------------------------------------
       
   411 //
       
   412 EXPORT_C void CMPXCollectionPath::Set(TInt aIndex)
       
   413     {
       
   414     MPX_ASSERT(Levels());
       
   415     CMPXCollectionPathNode& topLevel = TopLevel();
       
   416     // RArray will panic if aIndex out of bound
       
   417     topLevel.Set(iIds[aIndex], aIndex);
       
   418     }
       
   419 
       
   420 // -----------------------------------------------------------------------------
       
   421 // Change current item by id at top level
       
   422 // -----------------------------------------------------------------------------
       
   423 //
       
   424 EXPORT_C void CMPXCollectionPath::Set(const TMPXItemId& aId)
       
   425     {
       
   426     TInt index=IndexOfId(aId);
       
   427     MPX_ASSERT(KErrNotFound!=index && Levels());
       
   428     CMPXCollectionPathNode& topLevel = TopLevel();
       
   429     topLevel.Set(aId, index);
       
   430     }
       
   431 
       
   432 // -----------------------------------------------------------------------------
       
   433 // Set open mode for next level
       
   434 // -----------------------------------------------------------------------------
       
   435 //
       
   436 EXPORT_C void CMPXCollectionPath::Set(TMPXOpenMode aMode)
       
   437     {
       
   438     MPX_ASSERT(Levels());
       
   439     TopLevel().Set(aMode);
       
   440     }
       
   441 
       
   442 // -----------------------------------------------------------------------------
       
   443 // Set open attrobutes for next level
       
   444 // -----------------------------------------------------------------------------
       
   445 //
       
   446 EXPORT_C void CMPXCollectionPath::Set(const TArray<TMPXAttribute>& aAttrs)
       
   447     { // DEPRECATED
       
   448     TRAP_IGNORE(SetL(aAttrs));
       
   449     }
       
   450 
       
   451 // -----------------------------------------------------------------------------
       
   452 // Set open attrobutes for next level
       
   453 // -----------------------------------------------------------------------------
       
   454 //
       
   455 EXPORT_C void CMPXCollectionPath::SetL(const TArray<TMPXAttribute>& aAttrs)
       
   456     {
       
   457     MPX_ASSERT(Levels());
       
   458     TopLevel().SetL(aAttrs);
       
   459     }
       
   460 
       
   461 // -----------------------------------------------------------------------------
       
   462 //  Select an item by id in the path
       
   463 // -----------------------------------------------------------------------------
       
   464 //
       
   465 EXPORT_C void CMPXCollectionPath::SelectL(const TMPXItemId& aId)
       
   466     {
       
   467     TInt index=IndexOfId(aId);
       
   468     MPX_ASSERT(KErrNotFound != index);
       
   469     SelectL(index);
       
   470     }
       
   471 
       
   472 // -----------------------------------------------------------------------------
       
   473 //  Select an item by index in the path
       
   474 // -----------------------------------------------------------------------------
       
   475 //
       
   476 EXPORT_C void CMPXCollectionPath::SelectL(TInt aIndex)
       
   477     {
       
   478     MPX_ASSERT_EX(aIndex>=0 && aIndex<iIds.Count(), EBadArrayIndex);
       
   479     TInt err = iSelection.InsertInOrder(aIndex);
       
   480     if (KErrNone!=err && KErrAlreadyExists!=err)
       
   481         { // ignore duplicated items
       
   482         User::Leave(err);
       
   483         }
       
   484     }
       
   485 
       
   486 // -----------------------------------------------------------------------------
       
   487 //  Select an item by index in the path
       
   488 // -----------------------------------------------------------------------------
       
   489 //
       
   490 EXPORT_C void CMPXCollectionPath::SelectAllL()
       
   491     {
       
   492     iSelection.Reset();
       
   493     for (TInt i=0; i < iIds.Count(); ++i)
       
   494         {
       
   495         iSelection.AppendL(i);
       
   496         }
       
   497     }
       
   498 
       
   499 // -----------------------------------------------------------------------------
       
   500 //  Deselects an item by id in the path
       
   501 // -----------------------------------------------------------------------------
       
   502 //
       
   503 EXPORT_C void CMPXCollectionPath::Deselect(const TMPXItemId& aId)
       
   504     {
       
   505     TInt index=IndexOfId(aId);
       
   506     MPX_ASSERT(KErrNotFound != index);
       
   507     Deselect(index);
       
   508     }
       
   509 
       
   510 // -----------------------------------------------------------------------------
       
   511 //  Deselects an item by index in the path
       
   512 // -----------------------------------------------------------------------------
       
   513 //
       
   514 EXPORT_C void CMPXCollectionPath::Deselect(TInt aIndex)
       
   515     {
       
   516     MPX_ASSERT_EX(aIndex>=0 && aIndex<iIds.Count(), EBadArrayIndex);
       
   517     TInt index(iSelection.FindInOrder(aIndex));
       
   518     MPX_ASSERT(KErrNotFound !=index);
       
   519     iSelection.Remove(index);
       
   520     }
       
   521 
       
   522 // -----------------------------------------------------------------------------
       
   523 //  Select an item by index in the path
       
   524 // -----------------------------------------------------------------------------
       
   525 //
       
   526 EXPORT_C void CMPXCollectionPath::DeselectAll()
       
   527     {
       
   528     iSelection.Reset();
       
   529     }
       
   530 
       
   531 // -----------------------------------------------------------------------------
       
   532 //  Removes an item in the path
       
   533 // -----------------------------------------------------------------------------
       
   534 //
       
   535 EXPORT_C void CMPXCollectionPath::Remove(const TMPXItemId& aId)
       
   536     {
       
   537     TInt index=IndexOfId(aId);
       
   538     MPX_ASSERT(KErrNotFound != index);
       
   539     Remove(index);
       
   540     }
       
   541 
       
   542 // -----------------------------------------------------------------------------
       
   543 //  Removes an item in the path
       
   544 // -----------------------------------------------------------------------------
       
   545 //
       
   546 EXPORT_C void CMPXCollectionPath::Remove(TInt aIndex)
       
   547     {
       
   548     iIds.Remove(aIndex);
       
   549     TInt ret = iSelection.FindInOrder(aIndex);
       
   550     if (KErrNotFound != ret)
       
   551         {
       
   552         iSelection.Remove(ret);
       
   553         TInt count = iSelection.Count();
       
   554         for (TInt i=ret; i<count; i++)
       
   555             {
       
   556             --iSelection[i];
       
   557             }
       
   558         }
       
   559     }
       
   560 
       
   561 // -----------------------------------------------------------------------------
       
   562 //  Query selection
       
   563 // -----------------------------------------------------------------------------
       
   564 //
       
   565 EXPORT_C TBool CMPXCollectionPath::IsSelected(const TMPXItemId& aId) const
       
   566     {
       
   567     TBool ret(EFalse);
       
   568     TInt index=IndexOfId(aId);
       
   569     if (KErrNotFound != index)
       
   570         {
       
   571         ret = IsSelected(index);
       
   572         }
       
   573     return ret;
       
   574     }
       
   575 
       
   576 // -----------------------------------------------------------------------------
       
   577 //  Query selection
       
   578 // -----------------------------------------------------------------------------
       
   579 //
       
   580 EXPORT_C TBool CMPXCollectionPath::IsSelected(TInt aIndex) const
       
   581     {
       
   582     return iSelection.FindInOrder(aIndex) != KErrNotFound;
       
   583     }
       
   584 
       
   585 // -----------------------------------------------------------------------------
       
   586 //  Clears selection
       
   587 // -----------------------------------------------------------------------------
       
   588 //
       
   589 EXPORT_C void CMPXCollectionPath::ClearSelection()
       
   590     {
       
   591     iSelection.Reset();
       
   592     }
       
   593 
       
   594 // -----------------------------------------------------------------------------
       
   595 // Array of currently selected indices
       
   596 // -----------------------------------------------------------------------------
       
   597 //
       
   598 EXPORT_C TArray<TInt> CMPXCollectionPath::Selection() const
       
   599     {
       
   600     return iSelection.Array();
       
   601     }
       
   602 
       
   603 // -----------------------------------------------------------------------------
       
   604 // Current selected IDs
       
   605 // -----------------------------------------------------------------------------
       
   606 //
       
   607 EXPORT_C void CMPXCollectionPath::SelectionL(RArray<TMPXItemId>& aIds) const
       
   608     {
       
   609     aIds.Reset();
       
   610     TInt idCount(iIds.Count());
       
   611     TInt selCount(iSelection.Count());
       
   612     for  (TInt i=0; i<selCount; ++i)
       
   613         {
       
   614         TInt idIndex(iSelection[i]);
       
   615         if (idIndex < idCount)
       
   616             {
       
   617             aIds.AppendL(iIds[idIndex]);
       
   618             }
       
   619         }
       
   620     }
       
   621 
       
   622 // -----------------------------------------------------------------------------
       
   623 // Update the item id at a particular index
       
   624 // -----------------------------------------------------------------------------
       
   625 //
       
   626 EXPORT_C void CMPXCollectionPath::Update( TInt aIndex, TMPXItemId& aNewId )
       
   627     {
       
   628     MPX_ASSERT( aIndex >= 0 && aIndex < iIds.Count() );
       
   629     iIds[aIndex] = aNewId;
       
   630     }
       
   631 
       
   632 // -----------------------------------------------------------------------------
       
   633 // Index of current item at top level
       
   634 // -----------------------------------------------------------------------------
       
   635 //
       
   636 EXPORT_C TInt CMPXCollectionPath::Index() const
       
   637     {
       
   638     TInt ret(KErrNotFound);
       
   639     if (Levels())
       
   640         {
       
   641         ret = TopLevel().Index();
       
   642         }
       
   643     return ret;
       
   644     }
       
   645 
       
   646 // -----------------------------------------------------------------------------
       
   647 // Return current item id at top level
       
   648 // -----------------------------------------------------------------------------
       
   649 //
       
   650 EXPORT_C const TMPXItemId& CMPXCollectionPath::Id() const
       
   651     {
       
   652     if (Levels())
       
   653         {
       
   654         return TopLevel().Id();
       
   655         }
       
   656     else
       
   657         {
       
   658         return iInvalidId;
       
   659         }
       
   660     }
       
   661 
       
   662 // -----------------------------------------------------------------------------
       
   663 // Returns the number of items at top level
       
   664 // -----------------------------------------------------------------------------
       
   665 //
       
   666 EXPORT_C TInt CMPXCollectionPath::Count() const
       
   667     {
       
   668     return iIds.Count();
       
   669     }
       
   670 
       
   671 // -----------------------------------------------------------------------------
       
   672 // Returns the open mode for the next level
       
   673 // -----------------------------------------------------------------------------
       
   674 //
       
   675 EXPORT_C TMPXOpenMode CMPXCollectionPath::OpenNextMode() const
       
   676     {
       
   677     return Levels() ? TopLevel().OpenMode():EMPXOpenGroupOrPlaylist;
       
   678     }
       
   679 
       
   680 // -----------------------------------------------------------------------------
       
   681 // Returns the open mode for the previous level
       
   682 // -----------------------------------------------------------------------------
       
   683 //
       
   684 EXPORT_C TMPXOpenMode CMPXCollectionPath::OpenPreviousMode() const
       
   685     {
       
   686     TInt n=Levels();
       
   687     return n>1?iNodeArray[n-2]->OpenMode():EMPXOpenGroupOrPlaylist;
       
   688     }
       
   689 
       
   690 // -----------------------------------------------------------------------------
       
   691 // Index from id
       
   692 // -----------------------------------------------------------------------------
       
   693 //
       
   694 EXPORT_C TInt CMPXCollectionPath::IndexOfId(const TMPXItemId& aId) const
       
   695     {
       
   696     TInt ret(KErrNotFound);
       
   697     for (TInt i=iIds.Count(); --i>=0; )
       
   698         {
       
   699         if (aId == iIds[i])
       
   700             {
       
   701             ret = i;
       
   702             break;
       
   703             }
       
   704         }
       
   705     return ret;
       
   706     }
       
   707 
       
   708 // -----------------------------------------------------------------------------
       
   709 // Return item id at top specific level for a specific item
       
   710 // -----------------------------------------------------------------------------
       
   711 //
       
   712 EXPORT_C const TMPXItemId& CMPXCollectionPath::IdOfIndex( TInt aIndex ) const
       
   713     {
       
   714     if( aIndex >=0 && aIndex < iIds.Count() )
       
   715         {
       
   716         return iIds[aIndex];
       
   717         }
       
   718     else
       
   719         {
       
   720         return iInvalidId;
       
   721         }
       
   722     }
       
   723 
       
   724 // -----------------------------------------------------------------------------
       
   725 // Return item index at a specific level
       
   726 // -----------------------------------------------------------------------------
       
   727 //
       
   728 EXPORT_C TInt CMPXCollectionPath::Index(TInt aLevel) const
       
   729     {
       
   730     MPX_ASSERT(aLevel>=0 && aLevel < Levels());
       
   731     return iNodeArray[aLevel]->Index();
       
   732     }
       
   733 
       
   734 // -----------------------------------------------------------------------------
       
   735 // Return item id at a specific level
       
   736 // -----------------------------------------------------------------------------
       
   737 //
       
   738 EXPORT_C const TMPXItemId& CMPXCollectionPath::Id(TInt aLevel) const
       
   739     {
       
   740     if( aLevel < iNodeArray.Count() && aLevel >= 0 )
       
   741         {
       
   742         return iNodeArray[aLevel]->Id();
       
   743         }
       
   744     else
       
   745         {
       
   746         return iInvalidId;
       
   747         }
       
   748     }
       
   749 
       
   750 // -----------------------------------------------------------------------------
       
   751 // Returns the depth into the collection
       
   752 // -----------------------------------------------------------------------------
       
   753 //
       
   754 EXPORT_C TInt CMPXCollectionPath::Levels() const
       
   755     {
       
   756     return iNodeArray.Count();
       
   757     }
       
   758 
       
   759 // -----------------------------------------------------------------------------
       
   760 // Remove a level from path
       
   761 // -----------------------------------------------------------------------------
       
   762 //
       
   763 EXPORT_C void CMPXCollectionPath::Back()
       
   764     {
       
   765     TInt levels = Levels();
       
   766     MPX_ASSERT(levels > 0);
       
   767     CMPXCollectionPathNode* node = iNodeArray[levels-1];
       
   768     iNodeArray.Remove(levels-1);
       
   769     delete node;
       
   770     iIds.Reset();
       
   771     iSelection.Reset();
       
   772     }
       
   773 
       
   774 // -----------------------------------------------------------------------------
       
   775 // Append a new level
       
   776 // -----------------------------------------------------------------------------
       
   777 //
       
   778 EXPORT_C void CMPXCollectionPath::AppendL(const TArray<TMPXItemId>& aIds)
       
   779     {
       
   780     iIds.Reset();
       
   781     iSelection.Reset();
       
   782     CMPXCollectionPathNode* node(NULL);
       
   783     if (aIds.Count())
       
   784         {
       
   785         ::CopyArrayL(aIds, iIds);
       
   786         node = CMPXCollectionPathNode::NewLC();
       
   787         node->Set(iIds[0], 0);
       
   788         iNodeArray.AppendL(node);
       
   789         CleanupStack::Pop(node);
       
   790         }
       
   791     else
       
   792         {// add a level in order to support back
       
   793         node = CMPXCollectionPathNode::NewLC();
       
   794         node->Set(iInvalidId, KErrNotFound);
       
   795         iNodeArray.AppendL(node);
       
   796         CleanupStack::Pop(node);
       
   797         }
       
   798     }
       
   799 
       
   800 // -----------------------------------------------------------------------------
       
   801 // Append a new level
       
   802 // -----------------------------------------------------------------------------
       
   803 //
       
   804 EXPORT_C void CMPXCollectionPath::AppendL(const TMPXItemId& aId)
       
   805     {
       
   806     RArray<TMPXItemId> ids;
       
   807     CleanupClosePushL(ids);
       
   808     ids.AppendL(aId);
       
   809     AppendL(ids.Array());
       
   810     CleanupStack::PopAndDestroy(&ids);
       
   811     }
       
   812 
       
   813 // -----------------------------------------------------------------------------
       
   814 // Append an id
       
   815 // -----------------------------------------------------------------------------
       
   816 //
       
   817 EXPORT_C void CMPXCollectionPath::InsertL(const TMPXItemId& aId, TInt aPos)
       
   818     {
       
   819     MPX_ASSERT(iIds.Count());
       
   820     iIds.InsertL(aId, aPos);
       
   821     // update the selection
       
   822     for (TInt i=0; i<iSelection.Count(); ++i)
       
   823         {
       
   824         TInt& sel = iSelection[i];
       
   825         if (sel >=aPos)
       
   826             {
       
   827             ++sel;
       
   828             }
       
   829         }
       
   830     }
       
   831 
       
   832 // -----------------------------------------------------------------------------
       
   833 // Resets the collection path object
       
   834 // -----------------------------------------------------------------------------
       
   835 //
       
   836 EXPORT_C void CMPXCollectionPath::Reset()
       
   837     {
       
   838     iNodeArray.ResetAndDestroy();
       
   839     iIds.Reset();
       
   840     iSelection.Reset();
       
   841     }
       
   842 
       
   843 // -----------------------------------------------------------------------------
       
   844 // Creates a collection path pointing to the container
       
   845 // -----------------------------------------------------------------------------
       
   846 //
       
   847 EXPORT_C CMPXCollectionPath* CMPXCollectionPath::ContainerPathL() const
       
   848     {
       
   849     CMPXCollectionPath* p = CMPXCollectionPath::NewL();
       
   850     CleanupStack::PushL( p );
       
   851 
       
   852     TInt count = iNodeArray.Count() - 1;  // Copy up to container level
       
   853     for (TInt i=0; i<count; ++i)
       
   854         {
       
   855         CMPXCollectionPathNode* node =
       
   856             CMPXCollectionPathNode::NewLC(*iNodeArray[i]);
       
   857         p->iNodeArray.AppendL(node);
       
   858         CleanupStack::Pop(node);
       
   859         }
       
   860 
       
   861     CleanupStack::Pop( p );
       
   862     return p;
       
   863     }
       
   864 
       
   865 // -----------------------------------------------------------------------------
       
   866 // Update collection path. When a item changed in the collection plugin,
       
   867 // collection plugin calls back collection context, which in turn updates
       
   868 // its collection paths by calling this function
       
   869 // -----------------------------------------------------------------------------
       
   870 //
       
   871 EXPORT_C TInt CMPXCollectionPath::HandleChange(
       
   872     const TUid& aCollectionId,
       
   873     const TMPXItemId& aId,
       
   874     const TMPXItemId& aDeprecatedId,
       
   875     CMPXCollectionPath::TMPXCollectionPathChange aChange,
       
   876     TInt& aSelection )
       
   877     {
       
   878     TBool updated(EPathUnchanged);
       
   879     aSelection = KErrNotFound;
       
   880 
       
   881     if (aChange == CMPXCollectionPath::EAdded)
       
   882         {
       
   883         updated = EPathModified;
       
   884         }
       
   885     else if (aChange == CMPXCollectionPath::EGroupModified )
       
   886         {
       
   887         TInt levels( Levels() );
       
   888         if( levels > 0 )
       
   889             {
       
   890             // Check if the collection id is correct
       
   891             if (iNodeArray[ECollectionUid]->Id() ==
       
   892                 TMPXItemId(aCollectionId.iUid) && levels > 1)
       
   893                 {
       
   894                 // Check if the container level is the one modified
       
   895                 if( aId == Id( levels-2 ) )
       
   896                     {
       
   897                     updated = EPathModified;
       
   898                     }
       
   899                 }
       
   900             }
       
   901         }
       
   902     else if (aChange == CMPXCollectionPath::EDeleted ||
       
   903              aChange == CMPXCollectionPath::EModified)
       
   904         {
       
   905         TInt levels = Levels();
       
   906         if (levels > 0)
       
   907             {
       
   908             // check collection id level, aka root level
       
   909             if (iNodeArray[ECollectionUid]->Id() ==
       
   910                 TMPXItemId(aCollectionId.iUid) && levels > 1)
       
   911                 {
       
   912                 // check node array except top level and root level.
       
   913                 for (TInt i=ECollectionRoot+1; i<levels-1; ++i)
       
   914                     {
       
   915                     if (iNodeArray[i]->Id() == aId ||
       
   916                         (aDeprecatedId != 0 && iNodeArray[i]->Id() == aDeprecatedId))
       
   917                         {
       
   918                         if( aChange == CMPXCollectionPath::EModified &&
       
   919                             aDeprecatedId != 0 )
       
   920                             {
       
   921                             // If the item is modified and the item id is updated
       
   922                             // we simply replace the node level item id with the new
       
   923                             // item id
       
   924                             //
       
   925                             // Continue and check other levels if any other
       
   926                             // levels are using this ID. ie: all songs of an artist
       
   927                             // The item IDs need to be unique across all levels, but
       
   928                             // can have duplicates. This is in the case of a playlist with
       
   929                             // more than 1 instance of a song
       
   930                             //
       
   931                             CMPXCollectionPathNode* node = iNodeArray[i];
       
   932                             node->Set( aId, Index(i) );
       
   933                             updated = EPathModified;
       
   934                             }
       
   935                         else
       
   936                             {
       
   937                             // Trim the path and break out of the loop
       
   938                             aSelection = Index(i);
       
   939                             for (TInt j=Levels()-1; j>i; --j)
       
   940                                 {
       
   941                                 CMPXCollectionPathNode* node = iNodeArray[j];
       
   942                                 iNodeArray.Remove(j);
       
   943                                 delete node;
       
   944                                 }
       
   945                             updated = EPathClipped;
       
   946                             break;
       
   947                             }
       
   948                         }
       
   949                     }
       
   950                  // Check the top level
       
   951                  if (!updated)
       
   952                     {
       
   953                     TMPXItemId search = aDeprecatedId != 0? aDeprecatedId : aId;
       
   954                     TInt temp(KErrNotFound);
       
   955 
       
   956                     // Unmatched ids in the item ID,
       
   957                     // try to look for an exact match first
       
   958                     //
       
   959                     if( search.iId1 != search.iId2 )
       
   960                         {
       
   961                         for (TInt i=iIds.Count(); --i>=0; )
       
   962                             {
       
   963                             if (search == iIds[i] )
       
   964                                 {
       
   965                                 temp = i;
       
   966                                 break;
       
   967                                 }
       
   968                             }
       
   969                         }
       
   970                     // Still not found, check for approximate equal
       
   971                     //
       
   972                     if( KErrNotFound == temp )
       
   973                         {
       
   974                         for (TInt i=iIds.Count(); --i>=0; )
       
   975                             {
       
   976                             if (search.ApproxEqual(iIds[i]))
       
   977                                 {
       
   978                                 temp = i;
       
   979                                 break;
       
   980                                 }
       
   981                             }
       
   982                         }
       
   983                     if (KErrNotFound != temp)
       
   984                         { // Improvement: only remove item deleted
       
   985                         updated = EPathModified;
       
   986                         aSelection = temp;
       
   987                         }
       
   988                     }
       
   989 
       
   990                 // Only clean up level if the path has been clipped
       
   991                 if (updated == EPathClipped )
       
   992                     {
       
   993                     // Reset top level
       
   994                     iIds.Reset();
       
   995                     iSelection.Reset();
       
   996                     }
       
   997                 }
       
   998             }
       
   999         }
       
  1000     return updated;
       
  1001     }
       
  1002 
       
  1003 // -----------------------------------------------------------------------------
       
  1004 // CMPXCollectionPath::OpenAttributes
       
  1005 // -----------------------------------------------------------------------------
       
  1006 //
       
  1007 EXPORT_C const TArray<TMPXAttribute> CMPXCollectionPath::OpenAttributes() const
       
  1008     {
       
  1009     MPX_ASSERT(Levels()>0);
       
  1010     return TopLevel().OpenAttributes();
       
  1011     }
       
  1012 
       
  1013 // -----------------------------------------------------------------------------
       
  1014 // Get top level items
       
  1015 // -----------------------------------------------------------------------------
       
  1016 //
       
  1017 EXPORT_C const TArray<TMPXItemId> CMPXCollectionPath::Items() const
       
  1018     {
       
  1019     MPX_ASSERT(Levels()>0);
       
  1020     return iIds.Array();
       
  1021     }
       
  1022 
       
  1023 // -----------------------------------------------------------------------------
       
  1024 // Internalize object
       
  1025 // -----------------------------------------------------------------------------
       
  1026 //
       
  1027 EXPORT_C void CMPXCollectionPath::InternalizeL(RReadStream& aStream)
       
  1028     {
       
  1029     (void)aStream.ReadInt32L(); // Discard object type
       
  1030     iNodeArray.ResetAndDestroy();
       
  1031     ::InternalizeCObjectArrayL(iNodeArray, aStream);
       
  1032     iIds.Reset();
       
  1033     MPXUser::InternalizeL(iIds, aStream);
       
  1034     iSelection.Reset();
       
  1035     ::InternalizeL(iSelection, aStream);
       
  1036     }
       
  1037 
       
  1038 // -----------------------------------------------------------------------------
       
  1039 // Externalize object
       
  1040 // -----------------------------------------------------------------------------
       
  1041 //
       
  1042 EXPORT_C void CMPXCollectionPath::ExternalizeL(RWriteStream& aStream) const
       
  1043     {
       
  1044     aStream.WriteInt32L(MMPXData::EPath);
       
  1045     ::ExternalizeL(iNodeArray.Array(), aStream);
       
  1046     MPXUser::ExternalizeL(iIds.Array(), aStream);
       
  1047     ::ExternalizeL(iSelection.Array(), aStream);
       
  1048     }
       
  1049 
       
  1050 // -----------------------------------------------------------------------------
       
  1051 // Top level
       
  1052 // -----------------------------------------------------------------------------
       
  1053 //
       
  1054 CMPXCollectionPathNode& CMPXCollectionPath::TopLevel()
       
  1055     {
       
  1056     MPX_ASSERT(Levels() > 0);
       
  1057     return *iNodeArray[Levels()-1];
       
  1058     }
       
  1059 
       
  1060 // -----------------------------------------------------------------------------
       
  1061 // Top level
       
  1062 // -----------------------------------------------------------------------------
       
  1063 //
       
  1064 const CMPXCollectionPathNode& CMPXCollectionPath::TopLevel() const
       
  1065     {
       
  1066     MPX_ASSERT(Levels() > 0);
       
  1067     return *iNodeArray[Levels()-1];
       
  1068     }