chxavfileviewwindow.cpp
上传用户:dangjiwu
上传日期:2013-07-19
资源大小:42019k
文件大小:52k
源码类别:

Symbian

开发平台:

Visual C++

  1. /************************************************************************
  2.  * chxCHXAvFileViewWindow.cpp
  3.  * -----------------------
  4.  *
  5.  * Synopsis:
  6.  * Contains the implementation of the CHXAvFileViewWindow.  This is the class
  7.  * that implements the object that is controlled by the CHXAvFileView
  8.  * object.  This class creates and manages the actual controls of the file 
  9.  * view.
  10.  *
  11.  * Target:
  12.  * Symbian OS
  13.  *
  14.  *
  15.  * (c) 1995-2003 RealNetworks, Inc. Patents pending. All rights reserved.
  16.  *
  17.  ************************************************************************/
  18. // Standard includes...
  19. #include <eiklbo.h> 
  20. #include <aknlists.h>
  21. #include <coemain.h>
  22. #include <coeutils.h>
  23. #include <akntabgrp.h>
  24. #include <akntabgrp.h>
  25. #include <aknnavide.h>
  26. #include <akntitle.h>
  27. #include <aknsfld.h>
  28. #include <aknutils.h>
  29. #include <akniconarray.h> 
  30. #include <aknselectionlist.h>
  31. #include <eikfutil.h>
  32. #include <f32file.h> // TSwitch, CFileMan
  33. #include <barsread.h> //TResourceReader
  34. #include <SenduiMtmUids.h>
  35. #include <sendui.h>
  36. #include <SendNorm.rsg>
  37. // Helix includes...
  38. #include "hxassert.h"
  39. #include "ihxpckts.h"
  40. #include "hxstring.h"
  41. #include "hxurl.h"
  42. // Includes from this project...
  43. #include "chxavcleanupstack.h"
  44. #include "chxavfileviewwindow.h"
  45. #include "chxavnamedisplaytrait.h"
  46. #include "chxavfileview.h"
  47. #include "chxavramparser.h"
  48. #include "hxsym_debug.h"
  49. #include "hxsym_leaveutil.h"
  50. #include "hxsym_mmc_utils.h"
  51. #include "chxavcleanstring.h"
  52. #include "chxavurlrep.h"
  53. #include "chxavfolderdisplayinfo.h"
  54. #include "chxavmediafolderinfo.h"
  55. #include "chxavplayerui.h"
  56. #include "chxavfileutil.h"
  57. #include "chxavplayer.h"
  58. #include "chxavplaylist.h"
  59. #include "realplayer.hrh"
  60. #include "realplayer.rsg"
  61. #include "player_uids.h"
  62. #include "chxavurlrep.h"
  63. #include "realplayer.mbg"
  64. #include "r1p.hlp.hrh"
  65. namespace
  66. {
  67. // Order is important! must match TFileViewIconImageIds
  68. CHXAvMisc::ImageInfo const theirListBoxIcons[] =
  69. {
  70.     // mark icon must be first
  71.     { EMbmAvkonQgn_indi_marked_grid_add, EMbmAvkonQgn_indi_marked_grid_add_mask }, // EMarkIcon
  72.     { EMbmAvkonQgn_prop_folder_large, EMbmAvkonQgn_prop_folder_large_mask }, // EFolderIcon
  73.     { EMbmAvkonQgn_prop_group_large, EMbmAvkonQgn_prop_group_large_mask } // EVideosFolderIcon
  74. };
  75. CHXAvMisc::ImageInfo const ourListBoxIcons[] =
  76. {
  77.     { EMbmRealplayerQgn_prop_media_sub, EMbmRealplayerQgn_prop_media_sub_mask }, // EMediaIcon
  78.     { EMbmRealplayerQgn_prop_network_sub, EMbmRealplayerQgn_prop_network_sub_mask }  // EPlaylistIcon
  79. };
  80. // these must match order of icons above; localized folder ids specified in .rss (not here)
  81. TInt ToImageIndex(CHXAvFile::FileType type)
  82. {
  83.     HX_ASSERT(type != CHXAvFile::ftUnknown);
  84.     switch(type)
  85.     {
  86.     case CHXAvFile::ftRam:
  87.         // playlist icon
  88. return EPlaylistIcon;
  89.     case CHXAvFile::ftLink:
  90.         // link icon
  91. return EPlaylistIcon;
  92.     case CHXAvFile::ftFolder:
  93.         // folder icon
  94. return EFolderIcon;
  95.     default: 
  96.         // media icon for everything else
  97. return EMediaIcon;
  98.     }
  99. }
  100. } // local
  101. /*
  102.  * CHXAvFileViewWindow
  103.  * -------------------
  104.  * constructor
  105.  *
  106.  */
  107. CHXAvFileViewWindow::CHXAvFileViewWindow() 
  108. : CHXAvNameDisplayTrait(true)
  109. , m_pListBox(0) 
  110. , m_pFileView(0) 
  111. , m_playerUI(0) 
  112. , m_wpNaviPane(0) 
  113. , m_wpTabGroup(0) 
  114. , m_bHideTabs(false)
  115. , m_shiftMarkState(smNotMarking)
  116. {
  117. }
  118. /*
  119.  * ~CHXAvFileViewWindow
  120.  * --------------------
  121.  * Dtor.
  122.  *
  123.  */
  124. CHXAvFileViewWindow::~CHXAvFileViewWindow()
  125. {
  126.     HX_DELETE(m_pListBox);
  127.     CleanUpTabs();
  128. }
  129. /*
  130.  * CleanUpTabs
  131.  * -----------
  132.  *
  133.  */
  134. void CHXAvFileViewWindow::CleanUpTabs()
  135. {
  136.     if(m_wpNaviPane)
  137.     {
  138.         if(m_spDecoratedTabGroup)
  139.         {
  140.             // restore navipane
  141.     m_wpNaviPane->Pop(m_spDecoratedTabGroup.Ptr());
  142.         }
  143. m_wpNaviPane = 0;
  144.     }
  145.     m_spDecoratedTabGroup = 0;
  146.     m_wpTabGroup = 0;
  147. }
  148. /* 
  149.  * CreateTabsL
  150.  * -----------
  151.  *
  152.  */
  153. void 
  154. CHXAvFileViewWindow::CreateTabsL(TInt idxInitTab)
  155. {
  156.     if(0 == m_wpNaviPane)
  157.     {
  158.         // get handle to the navi pane control
  159.         CEikStatusPane* pStatusPane = iEikonEnv->AppUiFactory()->StatusPane();
  160. m_wpNaviPane 
  161.             = static_cast<CAknNavigationControlContainer*>(
  162.             pStatusPane->ControlL(TUid::Uid(EEikStatusPaneUidNavi)) );
  163.     }
  164.     // create tab group control to decorate navi pane
  165.     m_spDecoratedTabGroup = m_wpNaviPane->CreateTabGroupL();
  166.     m_wpTabGroup 
  167.         = static_cast<CAknTabGroup*>(m_spDecoratedTabGroup->DecoratedControl());
  168.     // two tabs
  169.     const TInt tabWidthFlag = EAknTabWidthWithTwoTabs;
  170.     m_wpTabGroup->SetTabFixedWidthL(tabWidthFlag);
  171.     // create tabs for tab control
  172.     TInt count = m_spPageInfo->Nelements();
  173.     for(TInt idx = 0; idx < count; ++idx)
  174.     {
  175.         CHXAvFileViewPageInfoPtr pInfo = (*m_spPageInfo)[idx];
  176.         CHXAvMisc::ImageInfo imgInfo = pInfo->GetTabInfo();
  177.         CHXAvMisc::AddTabL(m_wpTabGroup, pInfo->GetTabImageFilePath(), idx, imgInfo.idxImg, imgInfo.idxImgMask);
  178.     }
  179.     // activate the default tab
  180.     m_wpTabGroup->SetActiveTabByIndex(idxInitTab);
  181.     
  182. }
  183. ////////////////////////////////////////////////////////////////////
  184. //
  185. void CHXAvFileViewWindow::UpdateTopAndBottomL()
  186. {
  187.     UpdateNaviPaneL();
  188.     CHXAvMisc::UpdateScrollBar(m_pListBox);
  189. }
  190. ////////////////////////////////////////////////////////////////////
  191. // 
  192. void CHXAvFileViewWindow::UpdateNaviPaneL()
  193. {
  194.     DPRINTF(SYMP_INFO, ("CHXAvFileViewWindow::UpdateNaviPaneL()n"));
  195.     if(m_wpNaviPane)
  196.     {
  197.         if(m_spDecoratedTabGroup && !m_bHideTabs)
  198.         {
  199.             m_wpNaviPane->PushL(*m_spDecoratedTabGroup);
  200.         }
  201.         else
  202.         {
  203.             m_wpNaviPane->PushDefaultL();
  204.         }
  205.     }
  206. }
  207. ////////////////////////////////////////////////////////////
  208. // called when drive state changed (or may have changed)
  209. void CHXAvFileViewWindow::ReloadCurrentPageL()
  210. {
  211.     LoadPageL(m_wpTabGroup->ActiveTabIndex());
  212. }
  213. ////////////////////////////////////////////////////////////
  214. // called when drive goes away or current folder goes aways
  215. void CHXAvFileViewWindow::ResetCurrentPageInfoToRootL()
  216. {
  217.     m_spCurrentPage->Indexes().RemoveAll();
  218.     m_spCurrentPage->SetCurrentIndex(0);
  219.     m_spCurrentPage->FolderInfo()->SetCurrentPathL(KNullDesC);
  220. }
  221. ////////////////////////////////////////////////////////////
  222. //
  223. // update drive state and reset page related data that may be 
  224. // invalidated by the change
  225. //
  226. // return 'true' if page needs to be rebuilt (because state has changed)
  227. //
  228. bool CHXAvFileViewWindow::DoUpdateAndCheckDriveStateL()
  229. {
  230.     // query drive for current state info
  231.     CHXAvMediaFolderInfo* pFolderInfo = m_spCurrentPage->FolderInfo();
  232.     TUint32 flags = pFolderInfo->UpdateDriveInfoCheckState();
  233.     if( flags & CHXAvMediaFolderInfo::VOLID_CHANGED )
  234.     {
  235.         // volume id has changed since we last looked at this drive
  236.         // reset current path and folder index stack - they apply
  237.         // to a different drive volume
  238.         ResetCurrentPageInfoToRootL();
  239.     }
  240.     return flags != 0;
  241. }
  242. ////////////////////////////////////////////////////////////
  243. // 
  244. // set current page and re-build view to reflect contents of the page
  245. //
  246. void CHXAvFileViewWindow::LoadPageL(TInt idxPage)
  247. {
  248.     HX_ASSERT(idxPage >= 0);
  249.     HX_ASSERT(idxPage < m_spPageInfo->Nelements());
  250.     m_spCurrentPage = (*m_spPageInfo)[idxPage];
  251.     // make sure drive info is up-to-date (handle case of removable drive)
  252.     DoUpdateAndCheckDriveStateL();
  253.     // handle case where saved current path info becomes invalid
  254.     // since we last displayed it (external delete/rename); invalid
  255.     // root handled by file store init
  256.     if(!m_spCurrentPage->FolderInfo()->IsCurrentPathValid())
  257.     {
  258.         ResetCurrentPageInfoToRootL();
  259.     }
  260.     // set text to show if view is empty
  261.     InitEmptyListTextL();
  262.     // init file store model and ui helpers
  263.     InitFileStoreL();
  264.     // init listbox contents
  265.     TInt idxCurrent = m_spCurrentPage->GetSelectedItemIndex();
  266.     RefreshListBoxL(idxCurrent);
  267.     
  268.     // title, navipane, etc.
  269.     m_pFileView->UpdateViewStateL();
  270.     DrawNow();
  271.        
  272. }
  273. ////////////////////////////////////////////////////////////
  274. // LoadPageL() helper
  275. //
  276. // re-init file store (and related file ui)
  277. //
  278. // assumes drive info is up-to-date
  279. //
  280. void CHXAvFileViewWindow::InitFileStoreL()
  281. {
  282.     m_spStore = 0;
  283.     m_spFileUI = 0;
  284.     CHXAvMediaFolderInfo* pFolderInfo = m_spCurrentPage->FolderInfo();
  285.     const CHXAvFile::DriveInfo info = pFolderInfo->GetDriveInfo();
  286.     // only create a file store if drive is accessible
  287.     if( CHXAvFile::dsAccessible == info.state )
  288.     {
  289.         //
  290.         // re-create file store (for underlying access to associated
  291.         // media folder) and ui handler 
  292.         //
  293.         m_spStore = new (ELeave) CHXAvFileStore();
  294.         // trap in case path/drive is bad somehow
  295.         TRAPD(err, 
  296.         m_spStore->ConstructL(
  297.         pFolderInfo->GetRoot(), 
  298.         pFolderInfo->GetCurrentPath(),
  299.         m_spCurrentPage->IsAutoCreateRoot()) );
  300.         if(KErrNone == err)
  301.         {   
  302.             m_spFileUI = new (ELeave) CHXAvFileUI();
  303.             m_spFileUI->ConstructL(m_playerUI, m_spStore);
  304.             // stop watching for drive events (store will watch for us)
  305.             m_fsWatcher.StopWatching();
  306.             // request file system events from file store
  307.             CHXAvCompositeCommand& handler = m_spStore->GetEventHandler();
  308.             CHXAvCommand& cmd = MakeCommand(this, &CHXAvFileViewWindow::OnFileSystemEvent);
  309.             handler.AppendL(cmd);
  310.         }
  311.         else
  312.         {
  313.             // abandon these
  314.             m_spStore = 0;
  315.             m_spFileUI = 0;
  316.             // don't leave; default to inaccessible media store state
  317.             CHXAvMessageDialog::DoAlertInfoL(CHXAvCleanString(R_ERR_OPEN_FOLDER_FAILED)());
  318.         }
  319.     }
  320.     if( !m_spStore )
  321.     {
  322.         // normally store watches for us; in this case we want to detect
  323.         BeginWatchingForDriveEventsL();
  324.     }
  325.     
  326. }
  327. ////////////////////////////////////////////////////////////
  328. // LoadPageL() helper
  329. //
  330. // set text to display when page is empty (empty folder or invalid drive)
  331. //
  332. // assumes drive info is up-to-date
  333. //
  334. void CHXAvFileViewWindow::InitEmptyListTextL()
  335. {
  336.     DPRINTF(SYMP_INFO, ("CHXAvFileViewWindow::InitEmptyListTextL()n"));
  337.     TInt idEmptyList = R_AVP_FILE_FOLDER_EMPTY_TEXT;
  338.     CHXAvMediaFolderInfo* pFolderInfo = m_spCurrentPage->FolderInfo();
  339.     const CHXAvFile::DriveInfo info = pFolderInfo->GetDriveInfo();
  340.     if( pFolderInfo->IsMmcFolder() )
  341.     {
  342.         // non-accessible text only applies to mmc (unexpected for flash)
  343.         switch( info.state )
  344.         {
  345.         case CHXAvFile::dsAccessible:
  346.             idEmptyList = R_AVP_FILE_FOLDER_EMPTY_TEXT; 
  347.             break;
  348.         case CHXAvFile::dsCorrupted:
  349.             idEmptyList = R_AVP_MMC_CORRUPT;
  350.             break;
  351.         case CHXAvFile::dsLocked:
  352.             idEmptyList = R_AVP_MMC_LOCKED; 
  353.             break;
  354.         default: 
  355.             idEmptyList = R_AVP_MMC_NOT_INSERTED;
  356.             break;
  357.         }
  358.     }
  359.     m_pListBox->View()->SetListEmptyTextL(CHXAvCleanString(idEmptyList)());
  360. }
  361. ////////////////////////////////////////////////////////////
  362. // called when no store for current page
  363. void CHXAvFileViewWindow::BeginWatchingForDriveEventsL()
  364. {
  365.     HX_ASSERT(!m_spStore);
  366.     // watch all drives; we can't specify an actual drive
  367.     m_fsWatcher.SetWatchPathL(KNullDesC); 
  368.     m_fsWatcher.SetNotifyType(ENotifyAll);  
  369.             
  370.     // delay notifications to minimize potential for receiving flood of events
  371.     m_fsWatcher.SetNotificationDelay(2000);
  372.     m_fsWatcher.StartWatching();
  373. }
  374. /* 
  375.  * ConstructL
  376.  * ----------
  377.  *
  378.  */
  379. void CHXAvFileViewWindow::ConstructL(const TRect& rc, CHXAvPlayerUI* pPlayerUi, CHXAvFileView* pFileView,
  380.      const refptr<CHXAvFileViewPageInfoVector>& spPageInfo,
  381.      TInt idxCurrentPage)
  382. {
  383.     HX_ASSERT(pPlayerUi);
  384.     HX_ASSERT(pFileView);
  385.     HX_ASSERT(spPageInfo);
  386.     HX_ASSERT(spPageInfo->Nelements() > 0);
  387.     HX_ASSERT(idxCurrentPage < spPageInfo->Nelements());
  388.     m_playerUI = pPlayerUi;
  389.     m_pFileView = pFileView;
  390.     m_spPageInfo = spPageInfo;
  391.     // callback to rebuild current page after drive goes away
  392.     const CHXAvCommand& cmd =
  393.         MakeCommand(this, &CHXAvFileViewWindow::ReloadCurrentPageL);
  394.     m_cbReloadPage.ConstructL(cmd);
  395.     // for watching for mount events (when no store for current drive)
  396.     m_fsWatcher.ConstructL();
  397.     m_fsWatcher.SetEventActionL(MakeCommand(this, &CHXAvFileViewWindow::OnFileSystemEvent));
  398.     // create main view window and listbox
  399.     CreateWindowL();
  400.     CreateFileViewListBoxL();
  401.     SetRect(rc);
  402.     // only create tabs if there is more than one storage location
  403.     if(m_spPageInfo->Nelements() > 1)
  404.     {
  405.         CreateTabsL(idxCurrentPage);
  406.     }
  407.     // build and show initial page
  408.     LoadPageL(idxCurrentPage);
  409.     ActivateL();   
  410. }
  411. ////////////////////////////////////////////////////////////
  412. // called when we receive notification that something has
  413. // changed on the file system (and we know it isn't for an
  414. // mmc drive swap); since filesystem event notification does
  415. // not specify exactly what changed, we act as through current
  416. // directory view must be updated
  417. //
  418. void CHXAvFileViewWindow::HandlePossibleCurrentFolderChangeL()
  419. {
  420.     HX_ASSERT(m_spStore);
  421.     // check possibility that current store path (current folder in view)
  422.     // has been deleted or renamed
  423.     if(CHXAvFile::PathExists(m_spStore->GetFullPath()))
  424.     {
  425.         // assume current folder needs updating (hard to tell for sure)
  426.         TInt idxHilight = m_pListBox->CurrentItemIndex();
  427.         if( idxHilight >= 0 ) // -1 == empty
  428.         {
  429.            //
  430.            // get name of last item hilighted; we want to keep it
  431.            // hilighted (if possible) as contents of directory change
  432.            // from external fs events; we need to copy it
  433.            // since RefreshListBoxL() updates the entry list
  434.            //
  435.            const CHXAvFileStore::Entries& entries = m_spStore->GetEntries();
  436.            HX_ASSERT(idxHilight < entries.Nelements());
  437.            const TEntry& entry = entries[idxHilight].m_entry;
  438.            HBufC* pSearchName = entry.iName.AllocL();
  439.            AUTO_PUSH_POP_DEL(pSearchName);
  440.            RefreshListBoxL(idxHilight, *pSearchName);
  441.         }
  442.         else
  443.         {
  444.            // nothing was previously hilighted
  445.            RefreshListBoxL();
  446.         }
  447.     }
  448.     else
  449.     {
  450.        // reload current page; we could be smarter and try to go up to parent
  451.        ResetCurrentPageInfoToRootL();
  452.        m_cbReloadPage.Set(1);
  453.     }
  454. }
  455. ////////////////////////////////////////////////////////////
  456. // usually called when store detects an generated event; when
  457. // store does not exist (because drive/path not present), we
  458. // watch for possible drive mount/unmount events via our own
  459. // filesystem watcher (and may receive events that way)
  460. //
  461. void CHXAvFileViewWindow::OnFileSystemEvent()
  462. {
  463.     DPRINTF(SYMP_FILE, ("CHXAvFileViewWindow::OnFileSystemEvent(): something changed...n"));
  464.     TRAPD(err, HandleFileSystemEventL());
  465.     DPRINTF(SYMP_FILE, ("CHXAvFileViewWindow::OnFileSystemEvent(): handler err = %ldn", err));
  466. }
  467. // OnFileSystemEvent helper
  468. void CHXAvFileViewWindow::HandleFileSystemEventL()
  469. {
  470.    bool bStateChanged = DoUpdateAndCheckDriveStateL();
  471.    if( !m_spStore )
  472.    {
  473.         DPRINTF(SYMP_INFO, ("OnFileSystemEvent(): no store; drive added?"));
  474.        
  475.         // previously unavailable drive possibly mounted
  476.         if( bStateChanged )
  477.         {
  478.             // drive state for current page has changed; rebuild everything
  479.             ReloadCurrentPageL();
  480.         }
  481.    }
  482.    else
  483.    {
  484.         if(bStateChanged)
  485.         {
  486.             // current drive state has changed (possibly unmounted);since
  487.             // we handle this by possibly destroying the (now invalid) current
  488.             // store, which is calling us here, we handle this in a separate callback
  489.             m_cbReloadPage.Set(1);
  490.         }
  491.         else
  492.         {
  493.             // update contents (if current drive is accessible)
  494.             CHXAvMediaFolderInfo* pFolderInfo = m_spCurrentPage->FolderInfo();
  495.             const CHXAvFile::DriveInfo info = pFolderInfo->GetDriveInfo();
  496.             if( CHXAvFile::dsAccessible == info.state  )
  497.             {
  498.                 // we don't know for sure that this event affects our view (we assume it does)
  499.                 HandlePossibleCurrentFolderChangeL();
  500.             }
  501.         }
  502.     }
  503. }
  504. ////////////////////////////////////////////////////
  505. //
  506. bool CHXAvFileViewWindow::HilightItemIsPlaylist() const
  507. {
  508.     TInt idxItem = m_pListBox->CurrentItemIndex();
  509.     const CHXAvFile::FileInfo& info = GetFileInfoL(idxItem);
  510.     bool bIsPlaylist = (info.m_type == CHXAvFile::ftRam || info.m_type == CHXAvFile::ftLink);
  511.     if(bIsPlaylist)
  512.     {
  513.         // verify that playlist is well-formed by attempting to parse it
  514.         CHXAvPlaylistPtr spList = CreatePlaylist(info.m_entry);
  515.         if( !spList || 0 == spList->Length() )
  516.         {
  517.             // corrupt or otherwise not-editable
  518.             bIsPlaylist = false;
  519.         }
  520.     }
  521.     return bIsPlaylist;
  522. }
  523. ////////////////////////////////////////////////////
  524. // true if current item corresponds to a file
  525. bool CHXAvFileViewWindow::HilightItemIsFile() const
  526. {
  527.     TInt idxItem = m_pListBox->CurrentItemIndex();
  528.     const CHXAvFile::FileInfo& info = GetFileInfoL(idxItem);
  529.     return !info.m_entry.IsDir();
  530. }
  531. ////////////////////////////////////////////////////
  532. // return true if hilighted item is in the mark list
  533. bool CHXAvFileViewWindow::HilightItemIsMarked() const
  534. {
  535.     const CArrayFix<TInt>* pSelectedItems = 
  536. m_pListBox->SelectionIndexes();
  537.     TInt idxItem = m_pListBox->CurrentItemIndex();
  538.     HX_ASSERT(idxItem != -1); // call HasHilightItem() first
  539.     for(TInt idx = 0; idx < pSelectedItems->Count(); ++idx)
  540.     {
  541. if (idxItem == (*pSelectedItems)[idx])
  542. {
  543.     // index was in the list and therefore marked
  544.     return true;
  545. }
  546.     }
  547.     return false;
  548. }
  549. ////////////////////////////////////////////////////////////
  550. // get an in-range index closest to idxWanted
  551. //
  552. // return:
  553. //
  554. //   -1 if list is empty
  555. //   idx of last item if wanted index is beyond the last item
  556. //   idxWanted if it is in range
  557. //
  558. TInt CHXAvFileViewWindow::GetBestIndex(TInt idxWanted) const
  559. {
  560.     HX_ASSERT(idxWanted >= 0);
  561.     // make sure best index is valid; just in case
  562.     TInt idxBest = (idxWanted >= 0) ? idxWanted : 0;
  563.     TInt itemCount = m_pListBox->Model()->NumberOfItems();
  564.     if( idxBest >= itemCount )
  565.     {
  566. // wanted index is invalid (beyond last item)
  567. if( itemCount > 0)
  568. {
  569.     // next best is last item
  570.     idxBest = itemCount - 1;
  571. }
  572. else
  573. {
  574.     // empty list
  575.     idxBest = -1;
  576. }
  577.     }
  578.     return idxBest;
  579. }
  580. //
  581. // args:
  582. //
  583. //   currentItemName     -   if not empty, we try to set current index to item that matches this name
  584. //                           if specified, must be provided in full significant name format, e.g. "foo.rm"
  585. //
  586. //   idxLastCurrentItem  -   preserve index at last or closest to last current item if preferred name
  587. //                           not mathched or specified
  588. //
  589. void 
  590. CHXAvFileViewWindow::SetListBoxSelectionAndDrawL(TInt idxLastCurrentItem, 
  591.                                      const TDesC& currentItemName)
  592. {
  593.     HX_ASSERT(m_pListBox);
  594.     HX_ASSERT(m_spStore);
  595.     m_pListBox->Reset();
  596.     m_pListBox->ClearSelection();
  597.     
  598.     // ensure zero (not -1) if no current item
  599.     idxLastCurrentItem = max(idxLastCurrentItem, 0); 
  600.     // determine current hilight item
  601.     TInt idxCurrent = -1;
  602.     if(currentItemName.Length() > 0)
  603.     {
  604.         // trim possible folder suffix (entries don't keep suffix in name)
  605.         TPtrC ptrName = CHXAvFile::GetEnsureNoFolderSuffix(currentItemName);
  606.         
  607. // see if we can find a match for the given name
  608. const CHXAvFileStore::Entries& entries = m_spStore->GetEntries();
  609. for(TInt idx = 0; idx < entries.Nelements(); ++idx)
  610. {
  611.     const TEntry& entry = entries[idx].m_entry;
  612.     if (0 == entry.iName.CompareF(ptrName))
  613.     {
  614. // found it
  615. idxCurrent = idx;
  616. break;
  617.     }
  618. }
  619.     }
  620.     if( idxCurrent == -1 )
  621.     {
  622. idxCurrent = GetBestIndex(idxLastCurrentItem);
  623.     }
  624.     // check again...
  625.     if( idxCurrent >= 0 ) // -1 = empty
  626.     {
  627.         HX_ASSERT(idxCurrent < m_pListBox->Model()->NumberOfItems());
  628. m_pListBox->SetCurrentItemIndex(idxCurrent);
  629.     }
  630.     
  631.     CHXAvMisc::UpdateScrollBar(m_pListBox);
  632.     m_pListBox->DrawNow();
  633. }
  634. ////////////////////////////////////////////////////////////
  635. // rebuild and redraw listbox contents
  636. //
  637. void 
  638. CHXAvFileViewWindow::RefreshListBoxL(TInt idxLastCurrentItem, 
  639.                                      const TDesC& currentItemName)
  640. {
  641.     HX_ASSERT(m_spStore);
  642.     
  643.     // create new list of items and transfer ownership to the listbox
  644.     CDesCArrayFlat* pItems = CreateListItemsL();
  645.     AUTO_PUSH_POP(pItems);
  646.     CTextListBoxModel* pModel = m_pListBox->Model();
  647.     pModel->SetItemTextArray(pItems);
  648.     pModel->SetOwnershipType(ELbmOwnsItemArray);
  649.     
  650.     SetListBoxSelectionAndDrawL(idxLastCurrentItem, currentItemName);
  651. }
  652. ////////////////////////////////////////////////////
  653. // allocate list box item text for given folder entry
  654. //
  655. //
  656. // main text: folder name
  657. // sub text : count of contents
  658. //
  659. HBufC* 
  660. CHXAvFileViewWindow::AllocFolderItemTextL(const TEntry& entry) const
  661. {
  662.     HX_ASSERT(entry.IsDir());
  663.     
  664.     // create full path to this folder
  665.     TParse parse;
  666.     parse.Set(m_spStore->GetFullPath(), 0, 0);
  667.     parse.AddDir(entry.iName); // iName relative to base path (does not start with '/')
  668.     // find folder child count (nanoplayer files + child folders)
  669.     TInt childCount = 0;
  670.     const bool bIncludeFolders = true;
  671.     HXSYM_LEAVE_IF_ERR(
  672.         CHXAvFile::GetFolderChildCount(parse.FullName(), childCount, 
  673.         bIncludeFolders, CHXAvFile::FilterIncludeNanoPlayerFiles));
  674.    
  675.     _LIT(KSubTextFormat, "%d");
  676.     TBuf<40> bufSubText;
  677.     bufSubText.Format(KSubTextFormat, childCount);
  678.     // this handles localized dirs that may be on mmc
  679.     CHXAvFolderDisplayInfo displayInfo;
  680.     displayInfo.SetFolderPathL(parse.FullName());
  681.     HBufC* pItemText = CHXAvMisc::AllocGrListItemL(displayInfo.GetDisplayText(), bufSubText, ToImageIndex(CHXAvFile::ftFolder));
  682.     
  683.     return pItemText;
  684. }
  685. ////////////////////////////////////////////////
  686. // try to create playlist object for given file entry
  687. CHXAvPlaylistPtr 
  688. CHXAvFileViewWindow::CreatePlaylist(const TEntry& entry) const
  689. {
  690.     HX_ASSERT(!entry.IsDir());
  691.     // get full path to this file
  692.     TFileName* pPath = CHXAvFile::AllocFileNameL(m_spStore->GetFullPath(), entry.iName);
  693.     AUTO_PUSH_POP_DEL(pPath);
  694.     CHXString strPath;
  695.     CHXAvStringUtils::DesToString(*pPath, strPath);
  696.     // try to parse it as a ram file
  697.     return CHXAvRAMParser::Parse(strPath);
  698. }
  699. ////////////////////////////////////////////////
  700. //
  701. HBufC* 
  702. CHXAvFileViewWindow::AllocPlayListDescriptionL(const CHXAvFile::FileInfo& info) const
  703.     HX_ASSERT(info.m_type == CHXAvFile::ftRam || info.m_type == CHXAvFile::ftLink);
  704.     HBufC* pListText = 0;
  705.     TInt count = 0;
  706.     CHXAvPlaylistPtr spPlaylist = CreatePlaylist(info.m_entry);
  707.     if( spPlaylist)
  708.     {
  709.         // this is a ram file (or a convincing imposter)
  710.         count = spPlaylist->Length();
  711.         
  712. if (count == 1)
  713. {
  714.             CHXAvPlaylistItr iter(*spPlaylist);
  715.             
  716.             // set display text to first and only playlist item
  717.     const CHXAvURLRep& url = iter.Current();
  718.             if( url.Host().GetLength() > 0 )
  719.             {
  720.                 CHXAvCleanString text(url.Host());
  721.                 pListText =  text().AllocL();
  722.             }
  723.         }
  724.     }
  725.     
  726.     if(!pListText)
  727.     {
  728.         // set display text to count of items in playlist
  729.         CHXAvCleanString text(R_AVP_LINK_COUNT, count);
  730.         pListText =  text().AllocL();
  731.     }
  732.     return pListText;
  733. }
  734. ////////////////////////////////////////////////////
  735. // allocate list box item text for given file entry
  736. //
  737. //
  738. // main text: file name
  739. // sub text : size in bytes if file/ url if ram link
  740. //
  741. HBufC* 
  742. CHXAvFileViewWindow::AllocFileItemTextL(const CHXAvFile::FileInfo& info) const
  743. {
  744.     const TEntry& entry = info.m_entry; 
  745.     HX_ASSERT(!entry.IsDir());
  746.     TFileName* pPath = CHXAvFile::AllocFileNameL(GetFullPath(),
  747.       entry.iName);
  748.     AUTO_PUSH_POP_DEL(pPath);
  749.     HBufC* pInfoText = 0;
  750.     if( (CHXAvFile::ftRam == info.m_type) || (CHXAvFile::ftLink == info.m_type) )
  751.     {
  752.         // show playlist description
  753.         pInfoText = AllocPlayListDescriptionL(info);
  754.     }
  755.     else
  756.     {
  757.         // not a playlist file; show size
  758.         pInfoText = CHXAvMisc::AllocFileSizeDescL(entry.iSize);
  759.     }
  760.     AUTO_PUSH_POP_DEL(pInfoText);
  761.     NameExt pair = GetDisplayText(entry.iName);
  762.     HBufC* pListText = CHXAvMisc::AllocGrListItemL(pair.first, *pInfoText, ToImageIndex(info.m_type));
  763.     return pListText;
  764. }
  765. ////////////////////////////////////////////////////////////
  766. // allocate formatted list box items for current dircectory
  767. //
  768. void 
  769. CHXAvFileViewWindow::AddListItemsForCurrentPathL(CDesCArrayFlat*& pItems) const
  770. {
  771.     HX_ASSERT(m_spStore);
  772.     // re-build local disk directory entry table
  773.     const CHXAvFileStore::Entries& entries = m_spStore->UpdateEntriesL();
  774.     TInt count = entries.Nelements();
  775.     for(TInt idx = 0; idx < count; ++idx)
  776.     {
  777.         const CHXAvFile::FileInfo& info = GetFileInfoL(idx);
  778.         const TEntry& entry = info.m_entry;
  779.         // skip system/hidden files
  780.         if(! CHXAvUtil::ShouldHideFromUser(entry) )
  781.         {
  782.     HBufC* pItemText = 0;
  783.             // show only folders and files that we can play
  784.     if (info.m_type == CHXAvFile::ftFolder)
  785.             {
  786. pItemText = AllocFolderItemTextL(entry);
  787.             }
  788.     else if (CHXAvFile::IsNanoPlayerFileType(info.m_type))
  789.             {
  790. pItemText = AllocFileItemTextL(info);
  791.             }
  792.             
  793.     if (pItemText)
  794.     {
  795. AUTO_PUSH_POP_DEL(pItemText);
  796. pItems->AppendL(*pItemText); // this copies buffer
  797.     }
  798. }
  799.     }
  800. }
  801. ////////////////////////////////////////////////////////////
  802. //
  803. // create array of listbox items (in list-box item format)
  804. // from current entry info
  805. //
  806. // list-box item format for double item large graphic listbox
  807. // is:
  808. //
  809. // [icon idx]t{item text}t{sub-text}
  810. //
  811. CDesCArrayFlat* 
  812. CHXAvFileViewWindow::CreateListItemsL() const
  813. {
  814.     CDesCArrayFlat* pItems = new (ELeave) CDesCArrayFlat(20 /*granularity*/);
  815.     AUTO_PUSH_POP(pItems); // out
  816.     if( m_spStore )
  817.     {
  818.         AddListItemsForCurrentPathL(pItems);
  819.     }
  820.    
  821.     return pItems;
  822. }
  823. ////////////////////////////////////////////////////////////
  824. // 42 X 29 (their folder = 42 x 36; mark icon = 13 x 13) for large icons
  825. void CHXAvFileViewWindow::CreateAndAddIconsL()
  826. {
  827.     CAknIconArray* pIcons = new (ELeave) CAknIconArray(3);
  828.     AUTO_PUSH_POP(pIcons);
  829.     // order is important!
  830.     CHXAvMisc::AddIconHelperL(CHXAvMisc::KAVPAvkonImagePath, theirListBoxIcons, ARRAY_COUNT(theirListBoxIcons), pIcons);
  831.     CHXAvMisc::AddIconHelperL(m_playerUI->GetAppImageFilePath(), ourListBoxIcons, ARRAY_COUNT(ourListBoxIcons), pIcons);
  832.     // transfer icon array ownership to list box (CEikColumnListBox uses ColumnData())
  833.     m_pListBox->ItemDrawer()->FormattedCellData()->SetIconArrayL(pIcons);
  834. }
  835. ////////////////////////////////////////////////////////////
  836. // return full path to current folder
  837. const TDesC& 
  838. CHXAvFileViewWindow::GetFullPath() const
  839. {
  840.     if( m_spStore )
  841.     {
  842.         return m_spStore->GetFullPath();
  843.     }
  844.     return m_spCurrentPage->FolderInfo()->GetRoot();
  845. }
  846. /* 
  847.  * SyncToCurrentPageL
  848.  * ------------------
  849.  *
  850.  */
  851. void 
  852. CHXAvFileViewWindow::SyncToCurrentPageL()
  853. {
  854.     m_spStore = 0;
  855.     m_spFileUI = 0;
  856.     TInt idEmptyList = R_AVP_FILE_FOLDER_EMPTY_TEXT;
  857.     CHXAvMediaFolderInfo* pFolderInfo = m_spCurrentPage->FolderInfo();
  858.     bool bIsMmc = pFolderInfo->IsMmcFolder();
  859.     const CHXAvFile::DriveInfo info = pFolderInfo->GetDriveInfo();
  860.     switch( info.state )
  861.     {
  862.     case CHXAvFile::dsAccessible:
  863.         // normal case: accessible drive
  864.         InitFileStoreL();
  865.         idEmptyList = R_AVP_FILE_FOLDER_EMPTY_TEXT;
  866.         break;
  867.     case CHXAvFile::dsCorrupted:
  868.         idEmptyList = bIsMmc ? R_AVP_MMC_CORRUPT : R_AVP_FILE_FOLDER_EMPTY_TEXT;
  869.         break;
  870.     case CHXAvFile::dsLocked:
  871.         idEmptyList = bIsMmc ? R_AVP_MMC_LOCKED : R_AVP_FILE_FOLDER_EMPTY_TEXT; 
  872.         break;
  873.     default: 
  874.         idEmptyList = bIsMmc ? R_AVP_MMC_NOT_INSERTED : R_AVP_FILE_FOLDER_EMPTY_TEXT;
  875.         break;
  876.     }
  877.     m_pListBox->View()->SetListEmptyTextL(CHXAvCleanString(idEmptyList)());
  878. }
  879. ////////////////////////////////////////////
  880. // CCoeControl
  881. void CHXAvFileViewWindow::GetHelpContext(TCoeHelpContext& aContext) const
  882. {
  883.     aContext = TCoeHelpContext( CHXAvMisc::KHelpUID, KRP_HLP_LIST );
  884. }
  885. /*
  886.  * ComponentControl
  887.  * ----------------
  888.  * Return a pointer to the ith component of this control.
  889.  *
  890.  */ 
  891. CCoeControl *
  892. CHXAvFileViewWindow::ComponentControl(TInt aIndex) const
  893. {   
  894.     HX_ASSERT(0 == aIndex);
  895.     return m_pListBox;
  896. }
  897. /*
  898.  * CountComponentControls
  899.  * ----------------------
  900.  * Return the number of subcontrols in this control.
  901.  *
  902.  */
  903. TInt CHXAvFileViewWindow::CountComponentControls() const
  904. {
  905.     return 1;   
  906. }
  907. /*
  908.  * SizeChanged
  909.  * -----------
  910.  * The size of this control has changed so adjust the child controls.
  911.  *
  912.  */
  913. void CHXAvFileViewWindow::SizeChanged()
  914. {
  915.     TRect rc = Rect();
  916.     if (m_pListBox)
  917.     {
  918. m_pListBox->SetRect(rc);
  919.     }
  920. }
  921. //////////////////////////////////////
  922. //
  923. // assumes we are using listbox with scrolling
  924. // loop (wrapping) behavior specified
  925. //
  926. TKeyResponse CHXAvFileViewWindow::HandleShiftMarkKeyL(TInt keyCode)
  927. {
  928.     // default: consume arrow key so current item does not change
  929.     TKeyResponse response = EKeyWasConsumed; 
  930.     const CHXAvFileStore::Entries& entries = m_spStore->GetEntries();
  931.     TInt idxThis = m_pListBox->CurrentItemIndex();
  932.     if( !entries[idxThis].m_entry.IsDir() )
  933.     {
  934.         TInt idxEnd = m_pListBox->Model()->NumberOfItems();
  935.     
  936.         TInt idxNext = idxThis + 1;
  937.         if( idxNext >= idxEnd )
  938.         {
  939.             idxNext = 0;
  940.         }
  941.         TInt idxPrev = idxThis - 1;
  942.         if( idxPrev < 0 )
  943.         {
  944.             idxPrev = idxEnd - 1;
  945.         }
  946.         TInt idxNextToSelect = (EKeyUpArrow == keyCode ? idxPrev : idxNext);
  947.         
  948.         if (!entries[idxNextToSelect].m_entry.IsDir())
  949.         {
  950.             // allow arrow key to pass to listbox so it changes current item
  951.             response = EKeyWasNotConsumed;
  952.             // mark current item
  953.             if( m_shiftMarkState == smShiftMark )
  954.             {
  955.                 m_pListBox->View()->SelectItemL(idxThis);
  956.             }
  957.             else
  958.             {
  959.                 m_pListBox->View()->DeselectItem(idxThis);
  960.             }
  961.       
  962.             // mark next item
  963.             if( m_shiftMarkState == smShiftMark )
  964.             {
  965.                 m_pListBox->View()->SelectItemL(idxNextToSelect);
  966.             }
  967.             else
  968.             {
  969.                 m_pListBox->View()->DeselectItem(idxNextToSelect);
  970.             }
  971.         }
  972.     }
  973.     return response;
  974. }
  975. //////////////////////////////////////
  976. //
  977. TKeyResponse CHXAvFileViewWindow::HandleEventKeyEventL(const TKeyEvent& event)
  978. {
  979.     TKeyResponse response = EKeyWasNotConsumed;
  980.     DPRINTF(SYMP_WSEVENTS, ("CHXAvFileViewWindow::HandleEventKeyEventL(): event key: code = %dn", event.iCode));
  981.     if( event.iModifiers & EModifierShift)
  982.     {
  983.         //
  984.         // shift + key
  985.         //
  986.         switch( event.iCode )
  987.         {
  988.             case EKeyOK: // selection key
  989.             case EKeyEnter: // 'enter' on keyboard
  990.                 DPRINTF(SYMP_WSEVENTS, ("CHXAvFileViewWindow::HandleEventKeyEventL(): shift + ok (or enter)n"));
  991.                 if( HasHilightItem() && HilightItemIsFile() )
  992.                 {
  993.                     TInt cmd = (HilightItemIsMarked() ? EAknCmdUnmark : EAknCmdMark);
  994.                     UserMarkL(cmd);
  995.                     response = EKeyWasConsumed;
  996.                 }
  997.                 break;
  998.             case EKeyUpArrow:
  999.             case EKeyDownArrow:
  1000.                 DPRINTF(SYMP_WSEVENTS, ("CHXAvFileViewWindow::HandleEventKeyEventL(): shift + arrown"));
  1001.                 response = HandleShiftMarkKeyL(event.iCode);
  1002.                 break;
  1003.             default:
  1004.                 break;
  1005.         }
  1006.     }
  1007.     else
  1008.     {
  1009.         //
  1010.         // key alone
  1011.         //
  1012.         switch( event.iCode )
  1013.         {
  1014.         case EKeyOK:
  1015.         case EKeyEnter:
  1016.             DPRINTF(SYMP_WSEVENTS, ("CHXAvFileViewWindow::HandleEventKeyEventL(): ok button clickn"));
  1017.             if(IsDriveLocked())
  1018.             {
  1019.                 // do 'unlock drive' ui if current drive is locked
  1020.                 UserUnlockDriveL();
  1021.                 response = EKeyWasConsumed;
  1022.             } // else, see HandleListBoxEventL()
  1023.             break;
  1024.         case EKeyBackspace: // 0x0d ('c')
  1025.         case EKeyDelete: // 0x7f (keyboard delete)
  1026.             UserDeleteSelectedItemsL();
  1027.             response = EKeyWasConsumed;
  1028.             break;
  1029.         case EKeyLeftArrow:
  1030. case EKeyRightArrow:
  1031.     //
  1032.     // these go to tab control
  1033.     //
  1034.     if( m_wpTabGroup )
  1035.     {
  1036. if( EKeyWasConsumed == m_wpTabGroup->OfferKeyEventL(event, EEventKey) )
  1037. {
  1038.     TInt idxTab = m_wpTabGroup->ActiveTabIndex();
  1039.                     // save current folder in view and hilighted item before switching
  1040.                     SaveCurrentPageInfoL();
  1041.     LoadPageL(idxTab);
  1042.     response = EKeyWasConsumed;
  1043. }
  1044.     }
  1045.     break;
  1046.         default:
  1047.             break;
  1048.         }
  1049.     }
  1050.     //
  1051.     // give list box next crack (only for EEventKey, since
  1052.     // listbox always returns EKeyWasConsumed and we want
  1053.     // ignored keys to be forwarded to parent control
  1054.     // 
  1055.     if( (EKeyWasNotConsumed == response) && m_pListBox )
  1056.     {
  1057. response = m_pListBox->OfferKeyEventL(event, EEventKey);
  1058.     }
  1059.     return response;
  1060. }
  1061. /*
  1062.  * OfferKeyEventL
  1063.  * --------------
  1064.  * A key event is occurring.
  1065.  *
  1066.  */
  1067. TKeyResponse CHXAvFileViewWindow::OfferKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType)
  1068. {
  1069.     TKeyResponse response = EKeyWasNotConsumed;
  1070.     DPRINTF(SYMP_WSEVENTS, ("CHXAvFileViewWindow::OfferKeyEventL():  code = %d; sc = %dn", aKeyEvent.iCode, aKeyEvent.iScanCode));
  1071.     switch(aType)
  1072.     {
  1073.     case EEventKey:
  1074.         // see aKeyEvent.iCode
  1075. response = HandleEventKeyEventL(aKeyEvent);
  1076. break;
  1077.     case EEventKeyUp:
  1078.         // see aKeyEvent.iScanCode
  1079. response = HandleKeyUpEventL(aKeyEvent);
  1080. break;
  1081.     case EEventKeyDown:
  1082.         // see aKeyEvent.iScanCode
  1083. response = HandleKeyDownEventL(aKeyEvent);
  1084. break;
  1085.     default:
  1086.         /* do nothing */
  1087.         break;
  1088.     }
  1089.     return response;
  1090. }
  1091. /*
  1092.  * CreateFileViewListBoxL
  1093.  * ----------------------
  1094.  * Create the file view list box.
  1095.  *
  1096.  */
  1097. void CHXAvFileViewWindow::CreateFileViewListBoxL()
  1098. {
  1099.     HX_DELETE(m_pListBox);
  1100.     
  1101.     //
  1102.     // list entries for 'CAknDoubleLargeStyleListBox' should look like:
  1103.     //
  1104.     // {idxIcon}t{top text}t{bottom text}
  1105.     //
  1106.     // CEikColumnListBox derived
  1107.     m_pListBox = new (ELeave) CAknDoubleLargeStyleListBox();
  1108.     TInt flags = EAknGenericListBoxFlags | EAknListBoxMultipleSelection | EAknListBoxLoopScrolling;     
  1109.     m_pListBox->ConstructL(this, flags);
  1110.     m_pListBox->SetMopParent(this);
  1111.     CreateAndAddIconsL();
  1112.     m_pListBox->CreateScrollBarFrameL( ETrue );
  1113.     m_pListBox->ScrollBarFrame()->SetScrollBarVisibilityL(CEikScrollBarFrame::EOn, CEikScrollBarFrame::EAuto);
  1114.     m_pListBox->SetListBoxObserver(this);
  1115.     // set default message that is displayed when a folder is empty
  1116.     m_pListBox->View()->SetListEmptyTextL(CHXAvCleanString(R_AVP_FILE_FOLDER_EMPTY_TEXT)());
  1117.     m_pListBox->ActivateL();
  1118. }
  1119. ////////////////////////////////////////////
  1120. // MEikListBoxObserver
  1121. void CHXAvFileViewWindow::HandleListBoxEventL(CEikListBox* /*aListBox*/,TListBoxEvent aEventType)
  1122. {
  1123.     DPRINTF(SYMP_INFO, ("CHXAvFileViewWindow::HandleListBoxEventL(): type = %dn", aEventType));
  1124.     if( aEventType == MEikListBoxObserver::EEventEnterKeyPressed ||
  1125. aEventType == MEikListBoxObserver::EEventItemClicked )
  1126.     {
  1127.         // selection button was clicked; this is only called if an item is selected
  1128. if(GetMarkedItemCount() == 0)
  1129. {
  1130.     // open the hilighted item
  1131.     UserOpenCurrentItemL();
  1132. else
  1133. {
  1134.             m_pFileView->HandleCommandL(EShowDefaultMenu);
  1135. }
  1136.     }
  1137. }
  1138. ////////////////////////////////////////////////////////////
  1139. // show contents of child folder
  1140. //
  1141. TInt CHXAvFileViewWindow::SwitchToChildFolderAndRefreshL(const TDesC& folder)
  1142. {
  1143.     HX_ASSERT(m_spStore);
  1144.     TInt idxItem = m_pListBox->CurrentItemIndex();
  1145.     HX_ASSERT(idxItem != -1);
  1146.     TRAPD(err, m_spStore->SwitchToChildFolderL(folder));
  1147.     if(KErrNone == err)
  1148.     {
  1149. //
  1150. // remember the current index so we can re-set
  1151. // to it in case user opts to return back to this
  1152. // parent folder
  1153. //
  1154.         HX_ASSERT(m_spCurrentPage);
  1155. m_spCurrentPage->Indexes().Push((void *)idxItem);
  1156. RefreshListBoxL();
  1157. m_pFileView->UpdateViewStateL();
  1158.     } 
  1159.     return err;
  1160. }
  1161. /*
  1162.  * UserOpenCurrentItemL
  1163.  * --------------------
  1164.  * Called by the user when they hit Play command in the file view.
  1165.  * We either open up the directory or play the file that is currently selected.
  1166.  *
  1167.  */
  1168. void 
  1169. CHXAvFileViewWindow::UserOpenCurrentItemL()
  1170. {
  1171.     HX_ASSERT(GetMarkedItemCount() == 0); // can't open when items are in selection list!
  1172.     TInt idxItem = m_pListBox->CurrentItemIndex();
  1173.     const TEntry& entry = GetFileInfoL(idxItem).m_entry;
  1174.     if( entry.IsDir())
  1175.     {
  1176. // "open folder"
  1177. TInt err = SwitchToChildFolderAndRefreshL(entry.iName);
  1178. if(err != KErrNone)
  1179. {
  1180.             CHXAvMessageDialog::DoAlertErrorL(CHXAvCleanString(R_ERR_OPEN_FOLDER_FAILED)());
  1181.     // refresh current folder; perhaps view is out of sync with file system
  1182.     RefreshListBoxL(idxItem);
  1183. }
  1184.     }
  1185.     else
  1186.     {
  1187. // "open file"
  1188. TFileName* pPath = CHXAvFile::AllocFileNameL(GetFullPath(), entry.iName);
  1189.         AUTO_PUSH_POP_DEL(pPath);
  1190.         HBufC* pUrl = CHXAvFile::AllocFileUrlL(*pPath);
  1191. AUTO_PUSH_POP_DEL(pUrl);
  1192. m_playerUI->ActivatePlayViewL(*pUrl);
  1193.     }
  1194. }
  1195. /*
  1196.  * GetFileInfoL
  1197.  * ------------
  1198.  * get file entry info for current item, with debug checks
  1199.  *
  1200.  */
  1201. const CHXAvFile::FileInfo& 
  1202. CHXAvFileViewWindow::GetFileInfoL(TInt idx) const
  1203. {
  1204.     HX_ASSERT(m_spStore);   
  1205.     const CHXAvFileStore::Entries& entries = m_spStore->GetEntries();
  1206.     HX_ASSERT(idx >= 0);
  1207.     HX_ASSERT(idx < entries.Nelements());
  1208.     return entries[idx];
  1209. }
  1210. ////////////////////////////////////////////////////////////
  1211. //
  1212. void CHXAvFileViewWindow::UserSwitchToParentFolderAndRefreshL()
  1213. {
  1214.     HX_ASSERT(m_spStore);
  1215.     HX_ASSERT(m_spCurrentPage);
  1216.     bool bAtRoot = m_spStore->IsAtRoot();
  1217.     HX_ASSERT(!bAtRoot);
  1218.     
  1219.     m_spStore->SwitchToParentFolderL();
  1220.     // get last index
  1221.     TInt idx = (TInt)(m_spCurrentPage->Indexes().TopOfStack());
  1222.     m_spCurrentPage->Indexes().Pop();
  1223.     RefreshListBoxL(idx);
  1224.     m_pFileView->UpdateViewStateL();
  1225.       
  1226. }
  1227. ////////////////////////////////////////////////////////////
  1228. // prompt for a new folder and create it (relative to current path)
  1229. //
  1230. void CHXAvFileViewWindow::UserNewFolderL()
  1231. {
  1232.     TInt err = m_spFileUI->DoNewFolderL(R_PROMPT_NEW_FOLDER_NAME);
  1233.     if(KErrNone == err)
  1234.     {
  1235.         // set focus to new folder item
  1236.         TPtrC ptrName = m_spFileUI->GetLastNewItemName();
  1237.         if( err != KErrNone )
  1238.         {
  1239.             ptrName.Set(KNullDesC);
  1240.         }
  1241.         TInt idxCurrent = m_pListBox->CurrentItemIndex();
  1242.         RefreshListBoxL(idxCurrent, ptrName);       
  1243.     }
  1244. }
  1245. ////////////////////////////////////////////////////////////
  1246. //
  1247. // delete selected items, or delete current hilighted item
  1248. //
  1249. void CHXAvFileViewWindow::UserDeleteSelectedItemsL()
  1250. {
  1251.     TInt idxHilightItem = m_pListBox->CurrentItemIndex();
  1252.     const CArrayFix<TInt>* pSelectedItems = m_pListBox->SelectionIndexes();
  1253.     //utVector<TInt> removeIndexes;
  1254.     TInt selectedCount = pSelectedItems->Count();
  1255.     TInt err = KErrCancel;
  1256.     if( selectedCount > 0)
  1257.     {
  1258. // delete marked items
  1259. err = m_spFileUI->DoDeleteItemsL(*pSelectedItems);
  1260.     }
  1261.     else if(idxHilightItem >= 0) // -1 == empty view
  1262.     {
  1263. // no mark list; delete hilight item
  1264. err = m_spFileUI->DoDeleteItemL(idxHilightItem);
  1265.     }
  1266. #if(0)
  1267.     if(removeIndexes.Nelements() > 0)
  1268.     {
  1269.         RefreshListBoxL(removeIndexes, idxHilightItem);
  1270.     }
  1271. #endif
  1272. }
  1273. ////////////////////////////////////////////////////
  1274. // rename the currently hilighted file or folder
  1275. //
  1276. void CHXAvFileViewWindow::UserRenameCurrentItemL()
  1277. {
  1278.     HX_ASSERT(GetMarkedItemCount() == 0); // can't rename when selection list exists!
  1279.     TInt idxItem = m_pListBox->CurrentItemIndex();
  1280.     HX_ASSERT(idxItem >= 0);
  1281.     TInt err = m_spFileUI->DoRenameL(idxItem, R_PROMPT_ENTER_NEW_NAME);
  1282.     if(KErrNone == err)
  1283.     {
  1284.         // set focus to newly renamed item
  1285.         TPtrC ptrName = m_spFileUI->GetLastNewItemName();
  1286.         if( err != KErrNone )
  1287.         {
  1288.             ptrName.Set(KNullDesC);
  1289.         }
  1290.         // update selection to new name
  1291.         TInt idxCurrent = m_pListBox->CurrentItemIndex();
  1292.         RefreshListBoxL(idxCurrent, ptrName);
  1293.     }
  1294. }
  1295. ////////////////////////////////////////////////////////////
  1296. // move selected items, or move current hilighted item, to
  1297. // user-specified folder (relative to root)
  1298. //
  1299. void CHXAvFileViewWindow::UserCopySelectedItemsL()
  1300. {
  1301.     TInt idxHilightItem = m_pListBox->CurrentItemIndex();
  1302.     const CArrayFix<TInt>* pSelectedItems = m_pListBox->SelectionIndexes();
  1303.     TInt err = KErrNone;
  1304.     if( pSelectedItems->Count() > 0)
  1305.     {
  1306.         //XXXLCM implement
  1307. //err = m_spFileUI->DoCopyItemsL(*pSelectedItems, R_PROMPT_COPY_TO);
  1308.     }
  1309.     else
  1310.     {
  1311.         HX_ASSERT(idxHilightItem >= 0);
  1312. //err = m_spFileUI->DoCopyItemL(idxHilightItem, R_PROMPT_COPY_TO);
  1313.     }
  1314. }
  1315. ////////////////////////////////////////////////////////////
  1316. // move selected items, or move current hilighted item, to
  1317. // user-specified folder (relative to root)
  1318. //
  1319. void CHXAvFileViewWindow::UserMoveSelectedItemsL()
  1320. {
  1321.     TInt idxHilightItem = m_pListBox->CurrentItemIndex();
  1322.     const CArrayFix<TInt>* pSelectedItems = m_pListBox->SelectionIndexes();
  1323.     TInt err = KErrNone;
  1324.     if( pSelectedItems->Count() > 0)
  1325.     {
  1326. err = m_spFileUI->DoMoveItemsL(*pSelectedItems, R_PROMPT_MOVE_TO);
  1327.     }
  1328.     else
  1329.     {
  1330.         HX_ASSERT(idxHilightItem >= 0);
  1331. err = m_spFileUI->DoMoveItemL(idxHilightItem, R_PROMPT_MOVE_TO);
  1332.     }
  1333. }
  1334. ////////////////////////////////////////////////////////////
  1335. // send  selected items as attachments via the selected mtm
  1336. //
  1337. void CHXAvFileViewWindow::UserSendSelectedItemsL(TInt command,
  1338.       CSendAppUi* pSendAppUi)
  1339. {
  1340.     TSendingCapabilities caps(0, 1024,
  1341.       TSendingCapabilities::ESupportsAttachments);
  1342.     if (pSendAppUi->CommandIsValidL(command, caps, NULL ))
  1343.     {
  1344. CDesCArray* pSelectedNames = new (ELeave) CDesCArrayFlat(4);
  1345. AUTO_PUSH_POP_DEL(pSelectedNames);
  1346. const CArrayFix<TInt>* pSelectedItems = m_pListBox->SelectionIndexes();
  1347. if (pSelectedItems->Count() > 0)
  1348. {
  1349.     for (TInt i = 0; i < pSelectedItems->Count(); ++i)
  1350.     {
  1351. TFileName* pName = m_spStore->AllocFullPathL((*pSelectedItems)[i]);
  1352. AUTO_PUSH_POP_DEL(pName);
  1353. pSelectedNames->AppendL(*pName);
  1354.     }
  1355. }
  1356. else
  1357. {
  1358.     TFileName* pName = 
  1359. m_spStore->AllocFullPathL(m_pListBox->CurrentItemIndex());
  1360.     AUTO_PUSH_POP_DEL(pName);
  1361.     pSelectedNames->AppendL(*pName);
  1362. }
  1363. pSendAppUi->CreateAndSendMessageL(command, NULL, pSelectedNames);
  1364.     }
  1365. }
  1366. ////////////////////////////////////////////////////////////////////
  1367. //
  1368. void CHXAvFileViewWindow::UserMarkL(TInt command)
  1369. {
  1370.     HX_ASSERT(m_spStore);
  1371.     HX_ASSERT(m_pListBox != 0);
  1372.     if(command == EAknMarkAll)
  1373.     {
  1374. //
  1375. // handle this ourselves since we don't want to mark folders
  1376. //
  1377. CArrayFixFlat<TInt>* pSelections = new (ELeave) CArrayFixFlat<TInt>(20);
  1378. AUTO_PUSH_POP_DEL(pSelections);
  1379. const CHXAvFileStore::Entries& entries = m_spStore->GetEntries();
  1380. TInt count =  entries.Nelements();
  1381. for(TInt idx = 0; idx < count; ++idx)
  1382. {
  1383.     if( !entries[idx].m_entry.IsDir() )
  1384.     {
  1385. // add index to file
  1386. pSelections->AppendL(idx);
  1387.     }
  1388. }
  1389. m_pListBox->SetSelectionIndexesL(pSelections);
  1390. m_pListBox->DrawNow();
  1391.     }
  1392.     else
  1393.     {
  1394. AknSelectionService::HandleMarkableListProcessCommandL(command, m_pListBox);
  1395.     }
  1396. }
  1397. ////////////////////////////////////////////////////
  1398. // get number of items (files) in view that are not
  1399. // in the selection list
  1400. TInt CHXAvFileViewWindow::GetUnmarkedItemCount() const
  1401. {
  1402.     HX_ASSERT(m_spStore);
  1403.     TInt totalCount = m_spStore->GetCurrentFolderFileCount();
  1404.     TInt markedCount = GetMarkedItemCount();
  1405.     HX_ASSERT(totalCount >= markedCount);
  1406.     return totalCount - markedCount;
  1407. }
  1408. //////////////////////////////////////
  1409. //
  1410. bool CHXAvFileViewWindow::IsDriveLocked() const
  1411. {
  1412.     bool bIsLocked = false;
  1413.     CHXAvMediaFolderInfo* pFolderInfo = m_spCurrentPage->FolderInfo();
  1414.     if(pFolderInfo)
  1415.     {
  1416.         TInt idx = CHXAvFile::GetDriveIndex(pFolderInfo->GetRoot());
  1417.         bIsLocked = CHXAvFile::IsDriveLocked(idx);
  1418.     }
  1419.     return bIsLocked;
  1420. }
  1421. ////////////////////////////////////////////////////////////
  1422. //
  1423. void CHXAvFileViewWindow::OnCompleteUnlockAttempt(TInt err)
  1424. {
  1425.     if( KErrNone == err )
  1426.     {
  1427.         // drive was unlocked
  1428.         ReloadCurrentPageL();
  1429.     }
  1430. }
  1431. ////////////////////////////////////////////////////////////
  1432. // attempt to unlock drive for current store
  1433. void CHXAvFileViewWindow::UserUnlockDriveL()
  1434. {
  1435.     // m_memCardUnlock.DoUiL();
  1436.     TInt idx = CHXAvFile::GetDriveIndex(GetFullPath());
  1437.     TInt err = util::DoUnlockDriveUi(idx);
  1438.     OnCompleteUnlockAttempt(err);
  1439. }
  1440. ////////////////////////////////////////////////////////////////////
  1441. // called when page is deactivating/going away
  1442. //
  1443. // save state (current path and index) for current page so we can restore
  1444. // state in case user returns back to page later on
  1445. //
  1446. void CHXAvFileViewWindow::SaveCurrentPageInfoL()
  1447. {
  1448.     if(m_spStore && m_spCurrentPage)
  1449.     {
  1450.         HX_ASSERT(m_pListBox != 0);
  1451.         m_spCurrentPage->FolderInfo()->SetCurrentPathL(m_spStore->GetCurrentPath());
  1452.         m_spCurrentPage->SetCurrentIndex(m_pListBox->CurrentItemIndex());
  1453.     }
  1454. }
  1455. ////////////////////////////////////////////////////////////
  1456. //
  1457. void CHXAvFileViewWindow::UserEditCurrentItemL()
  1458. {
  1459.     HX_ASSERT(GetMarkedItemCount() == 0); // can't open when items are in selection list!
  1460.     TInt idxItem = m_pListBox->CurrentItemIndex();    
  1461.     const CHXAvFile::FileInfo& info = GetFileInfoL(idxItem);
  1462.     const TEntry& entry = info.m_entry;
  1463.     HX_ASSERT(CHXAvFile::ftRam == info.m_type);
  1464.     HX_ASSERT(!entry.IsDir());
  1465.     TFileName* pPath = CHXAvFile::AllocFileNameL(GetFullPath(), entry.iName);
  1466.     AUTO_PUSH_POP_DEL(pPath);
  1467.     // hide tabs while dialog is up
  1468.     m_bHideTabs = true; // in case switch away, then activate
  1469.     UpdateNaviPaneL();
  1470.     m_playerUI->DoEditPlaylistL(*pPath);
  1471.   
  1472.     // make sure ram file is still valid
  1473.     CHXAvFile::FileType fileType = CHXAvFile::GetFileType(*pPath);
  1474.     if(!CHXAvFile::IsNanoPlayerFileType(fileType))
  1475.     {
  1476.         // user made unusable file; delete it since it will no longer be recognized and show in our view
  1477.         m_spStore->DeleteFileL(*pPath);
  1478.     }
  1479.     // show tabs again
  1480.     m_bHideTabs = false;
  1481.     UpdateNaviPaneL();
  1482.     // after edit, refresh list box to reflect possible changes (e.g. in file size, link count)
  1483.     TInt idxCurrent = m_pListBox->CurrentItemIndex();
  1484.     RefreshListBoxL(idxCurrent);
  1485. }
  1486. //////////////////////////////////////
  1487. //
  1488. TKeyResponse CHXAvFileViewWindow::HandleKeyDownEventL(const TKeyEvent& event)
  1489. {
  1490.     if(EStdKeyLeftShift == event.iScanCode)
  1491.     {
  1492.         DPRINTF(SYMP_WSEVENTS, ("CHXAvFileViewWindow::HandleKeyDownEventL(): shift downn"));
  1493.         //HX_ASSERT(smNotMarking == m_shiftMarkState);
  1494.         // note: we do not always get key up
  1495.         if(HasHilightItem() && HilightItemIsFile())
  1496.         {
  1497.             m_shiftMarkState = (HilightItemIsMarked() ? smShiftUnMark : smShiftMark);
  1498.         }
  1499.     }
  1500.     return EKeyWasNotConsumed;
  1501. }
  1502. //////////////////////////////////////
  1503. //
  1504. TKeyResponse CHXAvFileViewWindow::HandleKeyUpEventL(const TKeyEvent& event)
  1505. {
  1506.     if(EStdKeyLeftShift == event.iScanCode)
  1507.     {
  1508.         DPRINTF(SYMP_INFO, ("CHXAvFileViewWindow::HandleKeyUpEventL(): shift upn"));
  1509.         m_shiftMarkState = smNotMarking;
  1510.     }
  1511. #if defined(SYMBIANPLAYER_INCLUDE_LOCK_DRIVE_UI)
  1512.     else if( event.iScanCode == EStdKeyHash)
  1513.     {
  1514.         if( !CHXAvFile::IsDriveLocked(CHXAvMisc::KIdxMmcDrive))
  1515.         {
  1516.             util::DoLockDriveUiL();
  1517.         }
  1518.     }
  1519. #endif
  1520.     return EKeyWasNotConsumed;
  1521. }
  1522. /*
  1523.  * GetCurrentPageIndex
  1524.  * -------------------
  1525.  * Return the index of the current page.
  1526.  *
  1527.  */
  1528. TInt 
  1529. CHXAvFileViewWindow::GetCurrentPageIndex() const
  1530. {
  1531.     TInt idx = 0;
  1532.     if( m_wpTabGroup )
  1533.     {
  1534.         idx = m_wpTabGroup->ActiveTabIndex();
  1535.     }
  1536.     return idx;
  1537. }
  1538. #if(0)
  1539. //////////////////////////////////////
  1540. // optimized version of refreshlistbox
  1541. //
  1542. // update list info and listbox model after actual folder
  1543. // items corresponding to given indexes have been removed
  1544. //
  1545. // called after move or delete
  1546. //
  1547. // idHilightItem is the index for the last known current item
  1548. // (i.e., just before the move or delete took place)
  1549. //
  1550. void CHXAvFileViewWindow::RefreshListBoxL(const Vector<TInt>& removeIndexes,
  1551.     TInt idxHilightItem)
  1552. {
  1553.     CDesCArray* pTextItems = GetModelTextArray();
  1554.     HX_ASSERT(pTextItems);
  1555.     if(m_spStore)
  1556.     {
  1557.         //
  1558.         // update model text
  1559.         //
  1560.         // the fact that descriptor array deletion causes indexes
  1561.         // to change necessitates this weird way of deleting model
  1562.         // items
  1563.         //
  1564.         TInt idxItem = 0;
  1565.         TInt idxNextRemoveIndex = 0;
  1566.         
  1567.         TInt count = pTextItems->Count();
  1568.         for( TInt idxDelete = 0; idxDelete < count; ++idxDelete)
  1569.         {
  1570.     if( idxNextRemoveIndex >= removeIndexes.Nelements() )
  1571.     {
  1572.         // all items have been removed
  1573.         break;
  1574.     }
  1575.     if( idxDelete == removeIndexes[idxNextRemoveIndex] )
  1576.     {
  1577.         ++idxNextRemoveIndex;
  1578.         pTextItems->Delete(idxItem);
  1579.         continue;
  1580.     }
  1581.     // only update this index if an item not deleted
  1582.     ++idxItem;
  1583.         }
  1584.         // scrunch up the list box model
  1585.         pTextItems->Compress();
  1586.         //
  1587.         // update list info items
  1588.         //
  1589.         m_spStore->RemoveEntries(removeIndexes);
  1590.         // update the listbox UI and redraw
  1591.         m_pListBox->HandleItemRemovalL();
  1592.         if(m_pListBox->CurrentItemIndex() == -1)
  1593.         {
  1594.     // hilight item was deleted; set hilight to next best index
  1595.     idxHilightItem = GetBestIndex(idxHilightItem);
  1596.             HX_ASSERT(idxHilightItem < pTextItems->Count());
  1597.     m_pListBox->SetCurrentItemIndex(idxHilightItem);
  1598.         }
  1599.         
  1600.     }
  1601.     else
  1602.     {
  1603.         pTextItems->Reset();
  1604.     }
  1605.     CHXAvMisc:UpdateScrollBar(m_pListBox);
  1606.     m_pListBox->DrawNow();
  1607. }
  1608. #endif