taskswitcher/server/src/tsdatalist.cpp
changeset 117 c63ee96dbe5f
equal deleted inserted replaced
115:3ab5c078b490 117:c63ee96dbe5f
       
     1 /*
       
     2  * Copyright (c) 2008 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:  File containing application list classes
       
    15  *
       
    16  */
       
    17 
       
    18 //INCLUDES:
       
    19 #include <mmf/common/mmfcontrollerpluginresolver.h> // for CleanupResetAndDestroyPushL
       
    20 #include <apgwgnam.h>
       
    21 #include <bitstd.h>
       
    22 #include <AknIconUtils.h> // avkon
       
    23 #include <apgicnfl.h> // fbsbitmap
       
    24 #include <AknIconSrvClient.h> 
       
    25 #include <fbs.h>
       
    26 #include <apgwgnam.h>
       
    27 #include <QSizeF>
       
    28 #include <camenuiconutility.h>
       
    29 
       
    30 #include "tsdatalist.h"
       
    31 #include "tsentrykeygenerator.h"
       
    32 #include "tsscreenshotmsg.h"
       
    33 #include "tsunregscreenshotmsg.h"
       
    34 #include "tsvisibilitymsg.h"
       
    35 
       
    36 // size for the created app icons
       
    37 const TInt KAppIconWidth = 128;
       
    38 const TInt KAppIconHeight = 128;
       
    39 
       
    40 //uids to be hidden
       
    41 const TUid KHsApplicationUid = { 0x20022F35 };
       
    42 
       
    43 // ================= MEMBER FUNCTIONS =======================
       
    44 
       
    45 // --------------------------------------------------------------------------
       
    46 /**
       
    47  * Two-phased constructor.
       
    48  */
       
    49 CTsDataList* CTsDataList::NewL(MTsResourceManager& resources,
       
    50                                      MTsWindowGroupsMonitor &monitor, 
       
    51                                      MTsDataObserver& observer)
       
    52 {
       
    53     CTsDataList* self = new (ELeave) CTsDataList(resources, monitor, observer);
       
    54     CleanupStack::PushL(self);
       
    55     self->ConstructL();
       
    56     CleanupStack::Pop(self);
       
    57     return self;
       
    58 }
       
    59 
       
    60 // --------------------------------------------------------------------------
       
    61 /**
       
    62  * Constructor.
       
    63  */
       
    64 CTsDataList::CTsDataList(MTsResourceManager& resources,
       
    65                          MTsWindowGroupsMonitor &monitor, 
       
    66                          MTsDataObserver& observer) 
       
    67 :
       
    68     CTsWindowGroupsObserver(monitor),
       
    69     mResources(resources),
       
    70     mObserver(observer)
       
    71 {
       
    72 }
       
    73 
       
    74 // --------------------------------------------------------------------------
       
    75 /*
       
    76  * Destructor
       
    77  */
       
    78 CTsDataList::~CTsDataList()
       
    79 {
       
    80     mData.ResetAndDestroy();
       
    81     mVisibleData.Close();
       
    82     mHiddenUids.Close();
       
    83     RFbsSession::Disconnect();
       
    84     RAknIconSrvClient::Disconnect();
       
    85     delete mDefaultIcon;
       
    86 }
       
    87 
       
    88 // --------------------------------------------------------------------------
       
    89 /**
       
    90  * Performs 2nd phase construction.
       
    91  */
       
    92 void CTsDataList::ConstructL()
       
    93 {
       
    94     BaseConstructL();
       
    95     mHiddenUids.AppendL(KHsApplicationUid);
       
    96     User::LeaveIfError(RFbsSession::Connect());
       
    97     RAknIconSrvClient::Connect();
       
    98     mDefaultIcon = HbIcon2CFbsBitmapL(HbIcon("qtg_large_application"));
       
    99 }
       
   100 
       
   101 // --------------------------------------------------------------------------
       
   102 /**
       
   103  * Returns a reference to the current content.
       
   104  * Also performs sanity checks, e.g. associates application icons
       
   105  * when no screenshot has been received.
       
   106  * @return  ref to content array
       
   107  */
       
   108 const RTsFswArray& CTsDataList::Data() const
       
   109 {
       
   110     return mVisibleData;
       
   111 }
       
   112 
       
   113 // --------------------------------------------------------------------------
       
   114 /**
       
   115  * Interface implementation
       
   116  * @see MTsWindowGroupsObserver HandleWindowGroupChanged
       
   117  */
       
   118 void CTsDataList::HandleWindowGroupChanged(MTsResourceManager &, 
       
   119                                               const TArray<RWsSession::TWindowGroupChainInfo> &wgList)
       
   120 {
       
   121     TRAP_IGNORE(RTsFswArray newAppsList;
       
   122                 CleanupResetAndDestroyPushL(newAppsList);
       
   123                 CollectAppsL(newAppsList, wgList);
       
   124                 FitDataToList(newAppsList);
       
   125                 CleanupStack::PopAndDestroy(&newAppsList);
       
   126                 );
       
   127 }
       
   128 
       
   129 // --------------------------------------------------------------------------
       
   130 /**
       
   131  * Adds running apps to the list.
       
   132  * @param   appsList    array to add to
       
   133  */
       
   134 void CTsDataList::CollectAppsL(RTsFswArray& appsList, 
       
   135                                const TArray<RWsSession::TWindowGroupChainInfo> &wgList)
       
   136 {
       
   137     for (TInt i = 0; i < wgList.Count(); ++i) {
       
   138         TTsEntryKey key;
       
   139         TInt err = TsEntryKeyGeneraror::Generate(key, wgList[i].iId, wgList);
       
   140         
       
   141         //skip this entry if it is already on list or generate key failed
       
   142         if (err!=KErrNone || FindEntry(appsList, key) >= 0) {
       
   143             continue;
       
   144         }
       
   145 
       
   146         // get window group name
       
   147         CApaWindowGroupName* windowName = CApaWindowGroupName::NewLC(mResources.WsSession(), key.WindowGroupId());
       
   148         TUid appUid = windowName->AppUid();
       
   149         
       
   150          // get screen number (-1=console, 0=main screen, 1=cover ui)
       
   151         TInt appScreen = 0;
       
   152         TInt scrNumErr = mResources.ApaSession().GetDefaultScreenNumber( appScreen, appUid );
       
   153         
       
   154         if (appUid.iUid && !windowName->Hidden() && (appScreen == 0 || appScreen == -1) && scrNumErr == KErrNone ) {
       
   155             AddEntryL(key, appUid, windowName, appsList);
       
   156         }
       
   157 
       
   158         CleanupStack::PopAndDestroy(windowName);
       
   159     }
       
   160 }
       
   161 
       
   162 // --------------------------------------------------------------------------
       
   163 /**
       
   164  * Called from CollectTasksL for each entry in the task list.
       
   165  * @param   key       entry key
       
   166  * @param   appUid     application uid
       
   167  * @param   wgName     window group name or NULL
       
   168  * @param   newList    list to add to
       
   169  */
       
   170 void CTsDataList::AddEntryL(const TTsEntryKey& key, const TUid& appUid,
       
   171     CApaWindowGroupName* wgName, RTsFswArray& newList)
       
   172 {
       
   173     CTsEntry* entry = CTsEntry::NewLC(key, mObserver);
       
   174 
       
   175     // check if present in old list and if yes then take some of the old data
       
   176     TBool found = ConsiderOldDataL(key);
       
   177 
       
   178     // if not present previously then find out app name
       
   179     // and check if screenshot is already available
       
   180     if (!found) {
       
   181         entry->SetAppUid(appUid);       
       
   182         
       
   183         HBufC* name = FindAppNameLC(wgName, appUid, key.WindowGroupId());
       
   184         if (name) {
       
   185             entry->SetAppNameL(*name);
       
   186         }
       
   187         CleanupStack::PopAndDestroy(name);
       
   188                  
       
   189         CFbsBitmap* iconBitmap = GetAppIconL(appUid);
       
   190         //transfer ownership to entry
       
   191         entry->SetAppIcon(iconBitmap);
       
   192     }
       
   193     
       
   194     if (wgName) {
       
   195         entry->SetCloseableApp(!wgName->IsSystem());
       
   196     }
       
   197     
       
   198     // add to new list, ownership is transferred
       
   199     newList.AppendL(entry);
       
   200     CleanupStack::Pop(entry);
       
   201 }
       
   202 
       
   203 // --------------------------------------------------------------------------
       
   204 /**
       
   205  * Checks if there is an entry for same app in the content list.
       
   206  * If yes then it takes some of the data for the entry that
       
   207  * will correspond to the same app in the refreshed content list.
       
   208  * @param   key      new key in content list
       
   209  * @return  ETrue if app was found
       
   210  */
       
   211 TBool CTsDataList::ConsiderOldDataL(const TTsEntryKey& key)
       
   212 {
       
   213     for (TInt entryIdx = 0, oldCount = mData.Count(); entryIdx < oldCount; ++entryIdx) {
       
   214         if (mData[entryIdx]->Key() == key) {
       
   215             return ETrue;
       
   216         }
       
   217     }
       
   218     return EFalse;
       
   219 }
       
   220 
       
   221 // --------------------------------------------------------------------------
       
   222 /**
       
   223  * Finds out the application name.
       
   224  * @param   windowName window group name or NULL
       
   225  * @param   appUId     application uid
       
   226  * @param   wgId       window group id
       
   227  * @return  application name, ownership transferred to caller
       
   228  */
       
   229 HBufC* CTsDataList::FindAppNameLC(CApaWindowGroupName* windowName, const TUid& appUid, TInt wgId)
       
   230 {
       
   231     //Retrieve the app name
       
   232     TApaAppInfo info;
       
   233     mResources.ApaSession().GetAppInfo(info, appUid);
       
   234     TPtrC caption = info.iShortCaption;
       
   235 
       
   236     HBufC* tempName = 0;
       
   237     if (!caption.Length() && windowName) // if not set - use thread name instead
       
   238     {
       
   239         if (windowName->Caption().Length()) {
       
   240             tempName = windowName->Caption().AllocL();
       
   241             //put on cleanupstack after the if
       
   242         }
       
   243         else {
       
   244             TThreadId threadId;
       
   245             TInt err = mResources.WsSession().GetWindowGroupClientThreadId(wgId, threadId);
       
   246             if (err == KErrNone) {
       
   247                 RThread thread;
       
   248                 CleanupClosePushL(thread);
       
   249                 err = thread.Open(threadId);
       
   250                 if (err == KErrNone) {
       
   251                     tempName = thread.Name().AllocL(); // codescanner::forgottoputptroncleanupstack
       
   252                     // tempName put on cleanupstack after the if
       
   253                 }
       
   254                 CleanupStack::PopAndDestroy(&thread);
       
   255             }
       
   256         }
       
   257     }
       
   258     else {
       
   259         tempName = caption.AllocL();
       
   260         //put on cleanupstack after the if
       
   261     }
       
   262     CleanupStack::PushL(tempName);
       
   263     return tempName;
       
   264 }
       
   265 
       
   266 // --------------------------------------------------------------------------
       
   267 /**
       
   268  * Fit existing class contained data list into give one.
       
   269  * Data is being changed with application type consideration that is based 
       
   270  * on aConsiderWidgets param. 
       
   271  * Function removes or add entries into data depend on given list.
       
   272  * @param   listToFit          list with actual data  
       
   273  */
       
   274 void CTsDataList::FitDataToList(RTsFswArray& listToFit)
       
   275 {
       
   276     TBool changed = EFalse;
       
   277     TInt listCount = listToFit.Count();
       
   278     TInt dataCount = mData.Count();
       
   279 
       
   280     //remove items that dont't exists in newly collected list      
       
   281     for (TInt i = dataCount - 1; i >= 0; --i) {
       
   282         if (!CheckIfExists(*mData[i], listToFit)) {
       
   283             delete mData[i];
       
   284             mData.Remove(i);
       
   285             changed = ETrue;
       
   286         }
       
   287     }
       
   288     RArray<TTsEntryKey> allKeys;
       
   289     
       
   290     //add new items at start
       
   291     for (TInt i = listToFit.Count() - 1; i >= 0; --i) {
       
   292         allKeys.Insert(listToFit[i]->Key(), 0);
       
   293         if (!CheckIfExists(*listToFit[i], mData)) {
       
   294             HideEntryIfNotAllowed(listToFit[i]);            
       
   295             mData.Insert(listToFit[i], 0);
       
   296             
       
   297             TTime currentTimestamp;
       
   298             currentTimestamp.UniversalTime();
       
   299             mData[0]->SetTimestamp(currentTimestamp);
       
   300         
       
   301             listToFit[i] = 0;
       
   302             changed = ETrue;
       
   303         }
       
   304     }
       
   305     //establish order
       
   306     TBool orderChanged = EstablishOrder(allKeys);
       
   307     
       
   308     //update entries data
       
   309     TBool dataChanged = UpdateEntryData(listToFit);
       
   310     RebuildVisibleDataListL();
       
   311     if (changed || orderChanged || dataChanged) {
       
   312         mObserver.DataChanged();
       
   313     }
       
   314     allKeys.Close();
       
   315 }
       
   316 
       
   317 // --------------------------------------------------------------------------
       
   318 /**
       
   319  * Checks if there is an entry for same app in the given list.
       
   320  * @param   entry      entry
       
   321  * @param   newList    ref to list
       
   322  * @return  ETrue if app was found
       
   323  */
       
   324 
       
   325 TBool CTsDataList::CheckIfExists(const CTsEntry& entry, const RTsFswArray& list) const
       
   326 {
       
   327     TBool exists(EFalse);
       
   328     TInt pos = FindEntry(list, entry.Key());
       
   329     if (pos >= 0) {
       
   330         exists = ETrue;
       
   331     }
       
   332     return exists;
       
   333 }
       
   334 
       
   335 // --------------------------------------------------------------------------
       
   336 /**
       
   337  * Retrieves the bitmap for the icon of the given app.
       
   338  * @param   appUid application uid
       
   339  * @return  app CFbsBitmap
       
   340  */
       
   341 CFbsBitmap* CTsDataList::GetAppIconL(const TUid& aAppUid)
       
   342 {
       
   343 	HbIcon icon = CaMenuIconUtility::getApplicationIcon(aAppUid.iUid, QSizeF(KAppIconWidth, KAppIconHeight));    
       
   344     CFbsBitmap* iconBitmap = HbIcon2CFbsBitmapL(icon);
       
   345     if (!iconBitmap) {
       
   346         iconBitmap = new(ELeave) CFbsBitmap;
       
   347         TInt err = KErrNotFound;
       
   348         if(mDefaultIcon) {
       
   349             err = iconBitmap->Duplicate(mDefaultIcon->Handle());
       
   350         }
       
   351         if (KErrNone!=err) {
       
   352             delete iconBitmap;
       
   353             iconBitmap = NULL;
       
   354         }
       
   355     }    
       
   356     return iconBitmap; 
       
   357     }
       
   358 
       
   359 // --------------------------------------------------------------------------
       
   360 /**
       
   361  * Converts HbIcon to CFbsBitmap
       
   362  * @param   icon icon to be coverted
       
   363  * @return  CFbsBitmap
       
   364  */
       
   365 CFbsBitmap* CTsDataList::HbIcon2CFbsBitmapL(const HbIcon& icon)
       
   366 {
       
   367     QIcon qicon = icon.qicon();
       
   368     QPixmap pixmap = qicon.pixmap(QSize(KAppIconWidth, KAppIconHeight));
       
   369     CFbsBitmap* retValue = NULL;
       
   370     if (!pixmap.isNull()) {
       
   371         retValue = pixmap.toSymbianCFbsBitmap();
       
   372     }
       
   373     return retValue; 
       
   374 }
       
   375 // --------------------------------------------------------------------------
       
   376 TBool CTsDataList::isSupported(TInt function) const
       
   377 {
       
   378     return (RegisterScreenshotMessage == function ||
       
   379             UnregisterScreenshotMessage == function ||
       
   380             VisibilityChange == function);
       
   381 }
       
   382 
       
   383 // --------------------------------------------------------------------------
       
   384 void CTsDataList::handleDataL(TInt function,RReadStream& dataStream)
       
   385 {
       
   386     switch(function){
       
   387     case RegisterScreenshotMessage:
       
   388         registerScreenshotL(dataStream);
       
   389         break;
       
   390     case UnregisterScreenshotMessage:
       
   391         unregisterScreenshotL(dataStream);
       
   392         break;
       
   393     case VisibilityChange:
       
   394         changeVisibilityL(dataStream);
       
   395         break;
       
   396     }
       
   397 }
       
   398 
       
   399 // --------------------------------------------------------------------------
       
   400 void CTsDataList::registerScreenshotL(RReadStream& dataStream)
       
   401 {
       
   402     CTsScreenshotMsg* msg = CTsScreenshotMsg::NewLC(dataStream);
       
   403     const TInt pos = FindEntry(mData, GenerateKeyL(msg->windowGroupId()));
       
   404     User::LeaveIfError(pos);
       
   405     mData[pos]->SetScreenshotL(msg->screenshot(), msg->priority());
       
   406     CleanupStack::PopAndDestroy(msg);
       
   407 }
       
   408 // --------------------------------------------------------------------------
       
   409 void CTsDataList::unregisterScreenshotL(RReadStream& dataStream)
       
   410 {
       
   411 
       
   412     CTsUnregisterScreenshotMsg* msg = CTsUnregisterScreenshotMsg::NewLC(dataStream);
       
   413     const TInt pos = FindEntry(mData, GenerateKeyL(msg->windowGroupId()));
       
   414     User::LeaveIfError(pos);
       
   415     mData[pos]->RemoveScreenshotL();
       
   416     CleanupStack::PopAndDestroy(msg);
       
   417 }
       
   418 // --------------------------------------------------------------------------
       
   419 void CTsDataList::changeVisibilityL(RReadStream& dataStream)
       
   420 {
       
   421     CTsVisibilitMsg* msg = CTsVisibilitMsg::NewLC(dataStream);
       
   422     const TInt pos = FindEntry(mData, GenerateKeyL(msg->windowGroupId()));
       
   423     User::LeaveIfError(pos);
       
   424     msg->visibility() == mData[pos]->GetVisibility() ? User::Leave(KErrInUse) : 
       
   425                                                        mData[pos]->SetVisibility(msg->visibility());
       
   426     CleanupStack::PopAndDestroy(msg);
       
   427     RebuildVisibleDataListL();
       
   428     mObserver.DataChanged();
       
   429 }
       
   430 
       
   431 // --------------------------------------------------------------------------
       
   432 /**
       
   433  * Checks if given uid is on hidden list
       
   434  * @param   aUid uid to be checked
       
   435  * @return  ETrue if uid is on hidden list
       
   436  */
       
   437 TBool CTsDataList::IsHiddenUid(TUid uid)
       
   438 {
       
   439     return mHiddenUids.Find(uid) >= 0 ? ETrue : EFalse;
       
   440 }
       
   441 
       
   442 // --------------------------------------------------------------------------
       
   443 /**
       
   444  * Finds entry in array
       
   445  * @param   list list to find
       
   446  * @param   key finding key
       
   447  * @return   position or KErrNotFound
       
   448  */
       
   449 TInt CTsDataList::FindEntry(const RTsFswArray& list, const TTsEntryKey& key) const
       
   450 {
       
   451     TInt pos(KErrNotFound);
       
   452     for (TInt entryIdx = 0; entryIdx < list.Count(); ++entryIdx) {
       
   453         if (list[entryIdx]->Key() == key) {
       
   454             pos = entryIdx;
       
   455             break;
       
   456         }
       
   457     }
       
   458     return pos;
       
   459 }
       
   460 
       
   461 // --------------------------------------------------------------------------
       
   462 /**
       
   463  * Establish entry order accridung to aKeyList, all keys MUST be in iData
       
   464  * @param   keyList reference key list
       
   465  * @return   ETrue if changes occured
       
   466  */
       
   467 TBool CTsDataList::EstablishOrder(const RArray<TTsEntryKey>& keyList)
       
   468 {
       
   469     TBool changed(EFalse);
       
   470     TInt lastChangedItem(KErrNotFound);
       
   471     __ASSERT_ALWAYS(mData.Count() == keyList.Count(), User::Panic(_L("EstablishOrder 1"), KErrBadHandle) );
       
   472     for (TInt i = 0; i < keyList.Count(); i++) {
       
   473         const TTsEntryKey& currentdataKey = mData[i]->Key();
       
   474         const TTsEntryKey& referenceKey = keyList[i];
       
   475         if (!(currentdataKey == referenceKey)) {
       
   476             TInt foundPos = FindEntry(mData, referenceKey);
       
   477             __ASSERT_ALWAYS(foundPos>=0, User::Panic(_L("EstablishOrder 2"), KErrBadHandle) );
       
   478             CTsEntry* entry = mData[foundPos];
       
   479             mData.Remove(foundPos);
       
   480             mData.Insert(entry, i);
       
   481             changed = ETrue;
       
   482             lastChangedItem = i;
       
   483         }
       
   484     }
       
   485     
       
   486     TTime currentTimestamp;
       
   487     currentTimestamp.UniversalTime();
       
   488     for (TInt i = lastChangedItem; i >= 0; --i) {
       
   489         mData[i]->SetTimestamp(currentTimestamp);            
       
   490     }
       
   491     
       
   492     return changed;
       
   493 }
       
   494 
       
   495 // --------------------------------------------------------------------------
       
   496 /**
       
   497  * Updates entry data on mData according to list
       
   498  * @param   list reference entires list
       
   499  * @return   ETrue if changes occured
       
   500  */
       
   501 TBool CTsDataList::UpdateEntryData(const RTsFswArray& list)
       
   502 {
       
   503     __ASSERT_ALWAYS(mData.Count() == list.Count(), User::Panic(_L("UpdateEntryData 1"), KErrBadHandle) );
       
   504     TBool changed(EFalse);
       
   505     for (TInt i=0; i<list.Count(); i++) {
       
   506         if(list[i]) {
       
   507             __ASSERT_ALWAYS(mData[i]->Key() == list[i]->Key(), User::Panic(_L("UpdateEntryData 12"), KErrBadHandle) );
       
   508             if(mData[i]->CloseableApp() != list[i]->CloseableApp()) {
       
   509                 mData[i]->SetCloseableApp(list[i]->CloseableApp());
       
   510                 changed = ETrue;
       
   511             }
       
   512         }
       
   513     }
       
   514     return changed;
       
   515 }
       
   516 
       
   517 // --------------------------------------------------------------------------
       
   518 /**
       
   519  * Function generate task key using window group id
       
   520  * @param wgId - window group id of running application
       
   521  * @param entry key 
       
   522  */
       
   523 TTsEntryKey CTsDataList::GenerateKeyL(TInt wgId)
       
   524 {
       
   525    RArray<RWsSession::TWindowGroupChainInfo> allWgIds;
       
   526    CleanupClosePushL(allWgIds);
       
   527    User::LeaveIfError(mResources.WsSession().WindowGroupList(0, &allWgIds));
       
   528    TTsEntryKey key;
       
   529    User::LeaveIfError(TsEntryKeyGeneraror::Generate(key, wgId, allWgIds.Array()));
       
   530    CleanupStack::PopAndDestroy(&allWgIds);   
       
   531    return key;
       
   532 }
       
   533 
       
   534 // --------------------------------------------------------------------------
       
   535 /**
       
   536  * Hides entrie if exist on mHiddenUids
       
   537  * @param   entry
       
   538  */
       
   539 void CTsDataList::HideEntryIfNotAllowed(CTsEntry* entry)
       
   540 {    
       
   541     TUid uid = entry->AppUid();
       
   542     if(mHiddenUids.Find(uid) >= 0) {
       
   543         entry->SetVisibility(Invisible);
       
   544     }
       
   545 
       
   546 }
       
   547 
       
   548 void CTsDataList::RebuildVisibleDataListL()
       
   549 {
       
   550     mVisibleData.Reset();
       
   551 
       
   552     RArray<TInt> visibleItems(mData.Count() ? mData.Count() : 1);
       
   553     CleanupClosePushL(visibleItems);
       
   554     for (TInt iter = 0; iter < mData.Count(); ++iter) {
       
   555         if (Visible == mData[iter]->GetVisibility()) {
       
   556             visibleItems.AppendL(iter);
       
   557         }
       
   558     }
       
   559 
       
   560     for (TInt iter = 0; iter < visibleItems.Count(); ++iter) {
       
   561         mVisibleData.AppendL(mData[visibleItems[iter]]);
       
   562     }
       
   563     CleanupStack::PopAndDestroy(&visibleItems);    
       
   564 }
       
   565 // end of file