LCOV - code coverage report
Current view: top level - toolkit/components/filepicker - nsFileView.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 429 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 81 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : #include "DateTimeFormat.h"
       7             : #include "nsIFileView.h"
       8             : #include "nsITreeView.h"
       9             : #include "mozilla/ModuleUtils.h"
      10             : #include "nsITreeSelection.h"
      11             : #include "nsITreeColumns.h"
      12             : #include "nsITreeBoxObject.h"
      13             : #include "nsIFile.h"
      14             : #include "nsString.h"
      15             : #include "nsReadableUtils.h"
      16             : #include "nsCRT.h"
      17             : #include "nsPrintfCString.h"
      18             : #include "nsQuickSort.h"
      19             : #include "nsIAtom.h"
      20             : #include "nsIAutoCompleteResult.h"
      21             : #include "nsIAutoCompleteSearch.h"
      22             : #include "nsISimpleEnumerator.h"
      23             : #include "nsAutoPtr.h"
      24             : #include "nsIMutableArray.h"
      25             : #include "nsTArray.h"
      26             : #include "mozilla/Attributes.h"
      27             : 
      28             : #include "nsWildCard.h"
      29             : 
      30             : class nsIDOMDataTransfer;
      31             : 
      32             : #define NS_FILECOMPLETE_CID { 0xcb60980e, 0x18a5, 0x4a77, \
      33             :                             { 0x91, 0x10, 0x81, 0x46, 0x61, 0x4c, 0xa7, 0xf0 } }
      34             : #define NS_FILECOMPLETE_CONTRACTID "@mozilla.org/autocomplete/search;1?name=file"
      35             : 
      36             : class nsFileResult final : public nsIAutoCompleteResult
      37             : {
      38             : public:
      39             :   // aSearchString is the text typed into the autocomplete widget
      40             :   // aSearchParam is the picker's currently displayed directory
      41             :   nsFileResult(const nsAString& aSearchString, const nsAString& aSearchParam);
      42             : 
      43             :   NS_DECL_ISUPPORTS
      44             :   NS_DECL_NSIAUTOCOMPLETERESULT
      45             : 
      46             :   nsTArray<nsString> mValues;
      47             :   nsString mSearchString;
      48             :   uint16_t mSearchResult;
      49             : private:
      50           0 :   ~nsFileResult() = default;
      51             : };
      52             : 
      53           0 : NS_IMPL_ISUPPORTS(nsFileResult, nsIAutoCompleteResult)
      54             : 
      55           0 : nsFileResult::nsFileResult(const nsAString& aSearchString,
      56           0 :                            const nsAString& aSearchParam):
      57           0 :   mSearchString(aSearchString)
      58             : {
      59           0 :   if (aSearchString.IsEmpty())
      60           0 :     mSearchResult = RESULT_IGNORED;
      61             :   else {
      62           0 :     int32_t slashPos = mSearchString.RFindChar('/');
      63           0 :     mSearchResult = RESULT_FAILURE;
      64           0 :     nsCOMPtr<nsIFile> directory;
      65           0 :     nsDependentSubstring parent(Substring(mSearchString, 0, slashPos + 1));
      66           0 :     if (!parent.IsEmpty() && parent.First() == '/')
      67           0 :       NS_NewLocalFile(parent, true, getter_AddRefs(directory));
      68           0 :     if (!directory) {
      69           0 :       if (NS_FAILED(NS_NewLocalFile(aSearchParam, true, getter_AddRefs(directory))))
      70           0 :         return;
      71           0 :       if (slashPos > 0)
      72           0 :         directory->AppendRelativePath(Substring(mSearchString, 0, slashPos));
      73             :     }
      74           0 :     nsCOMPtr<nsISimpleEnumerator> dirEntries;
      75           0 :     if (NS_FAILED(directory->GetDirectoryEntries(getter_AddRefs(dirEntries))))
      76           0 :       return;
      77           0 :     mSearchResult = RESULT_NOMATCH;
      78           0 :     bool hasMore = false;
      79           0 :     nsDependentSubstring prefix(Substring(mSearchString, slashPos + 1));
      80           0 :     while (NS_SUCCEEDED(dirEntries->HasMoreElements(&hasMore)) && hasMore) {
      81           0 :       nsCOMPtr<nsISupports> nextItem;
      82           0 :       dirEntries->GetNext(getter_AddRefs(nextItem));
      83           0 :       nsCOMPtr<nsIFile> nextFile(do_QueryInterface(nextItem));
      84           0 :       nsAutoString fileName;
      85           0 :       nextFile->GetLeafName(fileName);
      86           0 :       if (StringBeginsWith(fileName, prefix)) {
      87           0 :         fileName.Insert(parent, 0);
      88           0 :         if (mSearchResult == RESULT_NOMATCH && fileName.Equals(mSearchString))
      89           0 :           mSearchResult = RESULT_IGNORED;
      90             :         else
      91           0 :           mSearchResult = RESULT_SUCCESS;
      92           0 :         bool isDirectory = false;
      93           0 :         nextFile->IsDirectory(&isDirectory);
      94           0 :         if (isDirectory)
      95           0 :           fileName.Append('/');
      96           0 :         mValues.AppendElement(fileName);
      97             :       }
      98             :     }
      99           0 :     mValues.Sort();
     100             :   }
     101             : }
     102             : 
     103           0 : NS_IMETHODIMP nsFileResult::GetSearchString(nsAString & aSearchString)
     104             : {
     105           0 :   aSearchString.Assign(mSearchString);
     106           0 :   return NS_OK;
     107             : }
     108             : 
     109           0 : NS_IMETHODIMP nsFileResult::GetSearchResult(uint16_t *aSearchResult)
     110             : {
     111           0 :   NS_ENSURE_ARG_POINTER(aSearchResult);
     112           0 :   *aSearchResult = mSearchResult;
     113           0 :   return NS_OK;
     114             : }
     115             : 
     116           0 : NS_IMETHODIMP nsFileResult::GetDefaultIndex(int32_t *aDefaultIndex)
     117             : {
     118           0 :   NS_ENSURE_ARG_POINTER(aDefaultIndex);
     119           0 :   *aDefaultIndex = -1;
     120           0 :   return NS_OK;
     121             : }
     122             : 
     123           0 : NS_IMETHODIMP nsFileResult::GetErrorDescription(nsAString & aErrorDescription)
     124             : {
     125           0 :   aErrorDescription.Truncate();
     126           0 :   return NS_OK;
     127             : }
     128             : 
     129           0 : NS_IMETHODIMP nsFileResult::GetMatchCount(uint32_t *aMatchCount)
     130             : {
     131           0 :   NS_ENSURE_ARG_POINTER(aMatchCount);
     132           0 :   *aMatchCount = mValues.Length();
     133           0 :   return NS_OK;
     134             : }
     135             : 
     136           0 : NS_IMETHODIMP nsFileResult::GetValueAt(int32_t index, nsAString & aValue)
     137             : {
     138           0 :   aValue = mValues[index];
     139           0 :   if (aValue.Last() == '/')
     140           0 :     aValue.Truncate(aValue.Length() - 1);
     141           0 :   return NS_OK;
     142             : }
     143             : 
     144           0 : NS_IMETHODIMP nsFileResult::GetLabelAt(int32_t index, nsAString & aValue)
     145             : {
     146           0 :   return GetValueAt(index, aValue);
     147             : }
     148             : 
     149           0 : NS_IMETHODIMP nsFileResult::GetCommentAt(int32_t index, nsAString & aComment)
     150             : {
     151           0 :   aComment.Truncate();
     152           0 :   return NS_OK;
     153             : }
     154             : 
     155           0 : NS_IMETHODIMP nsFileResult::GetStyleAt(int32_t index, nsAString & aStyle)
     156             : {
     157           0 :   if (mValues[index].Last() == '/')
     158           0 :     aStyle.AssignLiteral("directory");
     159             :   else
     160           0 :     aStyle.AssignLiteral("file");
     161           0 :   return NS_OK;
     162             : }
     163             : 
     164           0 : NS_IMETHODIMP nsFileResult::GetImageAt(int32_t index, nsAString & aImage)
     165             : {
     166           0 :   aImage.Truncate();
     167           0 :   return NS_OK;
     168             : }
     169           0 : NS_IMETHODIMP nsFileResult::GetFinalCompleteValueAt(int32_t index,
     170             :                                                     nsAString & aValue)
     171             : {
     172           0 :   return GetValueAt(index, aValue);
     173             : }
     174             : 
     175           0 : NS_IMETHODIMP nsFileResult::RemoveValueAt(int32_t rowIndex, bool removeFromDb)
     176             : {
     177           0 :   return NS_OK;
     178             : }
     179             : 
     180           0 : class nsFileComplete final : public nsIAutoCompleteSearch
     181             : {
     182             :   ~nsFileComplete() = default;
     183             : public:
     184             :   NS_DECL_ISUPPORTS
     185             :   NS_DECL_NSIAUTOCOMPLETESEARCH
     186             : };
     187             : 
     188           0 : NS_IMPL_ISUPPORTS(nsFileComplete, nsIAutoCompleteSearch)
     189             : 
     190             : NS_IMETHODIMP
     191           0 : nsFileComplete::StartSearch(const nsAString& aSearchString,
     192             :                             const nsAString& aSearchParam,
     193             :                             nsIAutoCompleteResult *aPreviousResult,
     194             :                             nsIAutoCompleteObserver *aListener)
     195             : {
     196           0 :   NS_ENSURE_ARG_POINTER(aListener);
     197           0 :   RefPtr<nsFileResult> result = new nsFileResult(aSearchString, aSearchParam);
     198           0 :   NS_ENSURE_TRUE(result, NS_ERROR_OUT_OF_MEMORY);
     199           0 :   return aListener->OnSearchResult(this, result);
     200             : }
     201             : 
     202             : NS_IMETHODIMP
     203           0 : nsFileComplete::StopSearch()
     204             : {
     205           0 :   return NS_OK;
     206             : }
     207             : 
     208             : #define NS_FILEVIEW_CID { 0xa5570462, 0x1dd1, 0x11b2, \
     209             :                          { 0x9d, 0x19, 0xdf, 0x30, 0xa2, 0x7f, 0xbd, 0xc4 } }
     210             : 
     211             : class nsFileView : public nsIFileView,
     212             :                    public nsITreeView
     213             : {
     214             : public:
     215             :   nsFileView();
     216             :   nsresult Init();
     217             : 
     218             :   NS_DECL_ISUPPORTS
     219             :   NS_DECL_NSIFILEVIEW
     220             :   NS_DECL_NSITREEVIEW
     221             : 
     222             : protected:
     223             :   virtual ~nsFileView();
     224             : 
     225             :   void FilterFiles();
     226             :   void ReverseArray(nsTArray<nsCOMPtr<nsIFile> >& aArray);
     227             :   void SortArray(nsTArray<nsCOMPtr<nsIFile> >& aArray);
     228             :   void SortInternal();
     229             : 
     230             :   nsTArray<nsCOMPtr<nsIFile> > mFileList;
     231             :   nsTArray<nsCOMPtr<nsIFile> > mDirList;
     232             :   nsTArray<nsCOMPtr<nsIFile> > mFilteredFiles;
     233             : 
     234             :   nsCOMPtr<nsIFile> mDirectoryPath;
     235             :   nsCOMPtr<nsITreeBoxObject> mTree;
     236             :   nsCOMPtr<nsITreeSelection> mSelection;
     237             : 
     238             :   int16_t mSortType;
     239             :   int32_t mTotalRows;
     240             : 
     241             :   nsTArray<char16_t*> mCurrentFilters;
     242             : 
     243             :   bool mShowHiddenFiles;
     244             :   bool mDirectoryFilter;
     245             :   bool mReverseSort;
     246             : };
     247             : 
     248             : // Factory constructor
     249           0 : NS_GENERIC_FACTORY_CONSTRUCTOR(nsFileComplete)
     250           0 : NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsFileView, Init)
     251             : NS_DEFINE_NAMED_CID(NS_FILECOMPLETE_CID);
     252             : NS_DEFINE_NAMED_CID(NS_FILEVIEW_CID);
     253             : 
     254             : static const mozilla::Module::CIDEntry kFileViewCIDs[] = {
     255             :   { &kNS_FILECOMPLETE_CID, false, nullptr, nsFileCompleteConstructor },
     256             :   { &kNS_FILEVIEW_CID, false, nullptr, nsFileViewConstructor },
     257             :   { nullptr }
     258             : };
     259             : 
     260             : static const mozilla::Module::ContractIDEntry kFileViewContracts[] = {
     261             :   { NS_FILECOMPLETE_CONTRACTID, &kNS_FILECOMPLETE_CID },
     262             :   { NS_FILEVIEW_CONTRACTID, &kNS_FILEVIEW_CID },
     263             :   { nullptr }
     264             : };
     265             : 
     266             : static const mozilla::Module kFileViewModule = {
     267             :   mozilla::Module::kVersion,
     268             :   kFileViewCIDs,
     269             :   kFileViewContracts
     270             : };
     271             : 
     272             : NSMODULE_DEFN(nsFileViewModule) = &kFileViewModule;
     273             : 
     274           0 : nsFileView::nsFileView() :
     275             :   mSortType(-1),
     276             :   mTotalRows(0),
     277             :   mShowHiddenFiles(false),
     278             :   mDirectoryFilter(false),
     279           0 :   mReverseSort(false)
     280             : {
     281           0 : }
     282             : 
     283           0 : nsFileView::~nsFileView()
     284             : {
     285           0 :   uint32_t count = mCurrentFilters.Length();
     286           0 :   for (uint32_t i = 0; i < count; ++i)
     287           0 :     free(mCurrentFilters[i]);
     288           0 : }
     289             : 
     290             : nsresult
     291           0 : nsFileView::Init()
     292             : {
     293           0 :   return NS_OK;
     294             : }
     295             : 
     296             : // nsISupports implementation
     297             : 
     298           0 : NS_IMPL_ISUPPORTS(nsFileView, nsITreeView, nsIFileView)
     299             : 
     300             : // nsIFileView implementation
     301             : 
     302             : NS_IMETHODIMP
     303           0 : nsFileView::SetShowHiddenFiles(bool aShowHidden)
     304             : {
     305           0 :   if (aShowHidden != mShowHiddenFiles) {
     306           0 :     mShowHiddenFiles = aShowHidden;
     307             : 
     308             :     // This could be better optimized, but since the hidden
     309             :     // file functionality is not currently used, this will be fine.
     310           0 :     SetDirectory(mDirectoryPath);
     311             :   }
     312             : 
     313           0 :   return NS_OK;
     314             : }
     315             : 
     316             : NS_IMETHODIMP
     317           0 : nsFileView::GetShowHiddenFiles(bool* aShowHidden)
     318             : {
     319           0 :   *aShowHidden = mShowHiddenFiles;
     320           0 :   return NS_OK;
     321             : }
     322             : 
     323             : NS_IMETHODIMP
     324           0 : nsFileView::SetShowOnlyDirectories(bool aOnlyDirs)
     325             : {
     326           0 :   if (aOnlyDirs == mDirectoryFilter)
     327           0 :     return NS_OK;
     328             : 
     329           0 :   mDirectoryFilter = aOnlyDirs;
     330           0 :   uint32_t dirCount = mDirList.Length();
     331           0 :   if (mDirectoryFilter) {
     332           0 :     int32_t rowDiff = mTotalRows - dirCount;
     333             : 
     334           0 :     mFilteredFiles.Clear();
     335           0 :     mTotalRows = dirCount;
     336           0 :     if (mTree)
     337           0 :       mTree->RowCountChanged(mTotalRows, -rowDiff);
     338             :   } else {
     339             :     // Run the filter again to get the file list back
     340           0 :     FilterFiles();
     341             : 
     342           0 :     SortArray(mFilteredFiles);
     343           0 :     if (mReverseSort)
     344           0 :       ReverseArray(mFilteredFiles);
     345             : 
     346           0 :     if (mTree)
     347           0 :       mTree->RowCountChanged(dirCount, mTotalRows - dirCount);
     348             :   }
     349             : 
     350           0 :   return NS_OK;
     351             : }
     352             : 
     353             : NS_IMETHODIMP
     354           0 : nsFileView::GetShowOnlyDirectories(bool* aOnlyDirs)
     355             : {
     356           0 :   *aOnlyDirs = mDirectoryFilter;
     357           0 :   return NS_OK;
     358             : }
     359             : 
     360             : NS_IMETHODIMP
     361           0 : nsFileView::GetSortType(int16_t* aSortType)
     362             : {
     363           0 :   *aSortType = mSortType;
     364           0 :   return NS_OK;
     365             : }
     366             : 
     367             : NS_IMETHODIMP
     368           0 : nsFileView::GetReverseSort(bool* aReverseSort)
     369             : {
     370           0 :   *aReverseSort = mReverseSort;
     371           0 :   return NS_OK;
     372             : }
     373             : 
     374             : NS_IMETHODIMP
     375           0 : nsFileView::Sort(int16_t aSortType, bool aReverseSort)
     376             : {
     377           0 :   if (aSortType == mSortType) {
     378           0 :     if (aReverseSort == mReverseSort)
     379           0 :       return NS_OK;
     380             : 
     381           0 :     mReverseSort = aReverseSort;
     382           0 :     ReverseArray(mDirList);
     383           0 :     ReverseArray(mFilteredFiles);
     384             :   } else {
     385           0 :     mSortType = aSortType;
     386           0 :     mReverseSort = aReverseSort;
     387           0 :     SortInternal();
     388             :   }
     389             : 
     390           0 :   if (mTree)
     391           0 :     mTree->Invalidate();
     392             : 
     393           0 :   return NS_OK;
     394             : }
     395             : 
     396             : NS_IMETHODIMP
     397           0 : nsFileView::SetDirectory(nsIFile* aDirectory)
     398             : {
     399           0 :   NS_ENSURE_ARG_POINTER(aDirectory);
     400             : 
     401           0 :   nsCOMPtr<nsISimpleEnumerator> dirEntries;
     402           0 :   aDirectory->GetDirectoryEntries(getter_AddRefs(dirEntries));
     403             : 
     404           0 :   if (!dirEntries) {
     405             :     // Couldn't read in the directory, this can happen if the user does not
     406             :     // have permission to list it.
     407           0 :     return NS_ERROR_FAILURE;
     408             :   }
     409             : 
     410           0 :   mDirectoryPath = aDirectory;
     411           0 :   mFileList.Clear();
     412           0 :   mDirList.Clear();
     413             : 
     414           0 :   bool hasMore = false;
     415             : 
     416           0 :   while (NS_SUCCEEDED(dirEntries->HasMoreElements(&hasMore)) && hasMore) {
     417           0 :     nsCOMPtr<nsISupports> nextItem;
     418           0 :     dirEntries->GetNext(getter_AddRefs(nextItem));
     419           0 :     nsCOMPtr<nsIFile> theFile = do_QueryInterface(nextItem);
     420             : 
     421           0 :     bool isDirectory = false;
     422           0 :     if (theFile) {
     423           0 :       theFile->IsDirectory(&isDirectory);
     424             : 
     425           0 :       if (isDirectory) {
     426             :         bool isHidden;
     427           0 :         theFile->IsHidden(&isHidden);
     428           0 :         if (mShowHiddenFiles || !isHidden) {
     429           0 :           mDirList.AppendElement(theFile);
     430             :         }
     431             :       }
     432             :       else {
     433           0 :         mFileList.AppendElement(theFile);
     434             :       }
     435             :     }
     436             :   }
     437             : 
     438           0 :   if (mTree) {
     439           0 :     mTree->BeginUpdateBatch();
     440           0 :     mTree->RowCountChanged(0, -mTotalRows);
     441             :   }
     442             : 
     443           0 :   FilterFiles();
     444           0 :   SortInternal();
     445             : 
     446           0 :   if (mTree) {
     447           0 :     mTree->EndUpdateBatch();
     448           0 :     mTree->ScrollToRow(0);
     449             :   }
     450             : 
     451           0 :   return NS_OK;
     452             : }
     453             : 
     454             : NS_IMETHODIMP
     455           0 : nsFileView::SetFilter(const nsAString& aFilterString)
     456             : {
     457           0 :   uint32_t filterCount = mCurrentFilters.Length();
     458           0 :   for (uint32_t i = 0; i < filterCount; ++i)
     459           0 :     free(mCurrentFilters[i]);
     460           0 :   mCurrentFilters.Clear();
     461             : 
     462           0 :   nsAString::const_iterator start, iter, end;
     463           0 :   aFilterString.BeginReading(iter);
     464           0 :   aFilterString.EndReading(end);
     465             : 
     466             :   while (true) {
     467             :     // skip over delimiters
     468           0 :     while (iter != end && (*iter == ';' || *iter == ' '))
     469           0 :       ++iter;
     470             : 
     471           0 :     if (iter == end)
     472           0 :       break;
     473             : 
     474           0 :     start = iter; // start of a filter
     475             : 
     476             :     // we know this is neither ';' nor ' ', skip to next char
     477           0 :     ++iter;
     478             : 
     479             :     // find next delimiter or end of string
     480           0 :     while (iter != end && (*iter != ';' && *iter != ' '))
     481           0 :       ++iter;
     482             : 
     483           0 :     char16_t* filter = ToNewUnicode(Substring(start, iter));
     484           0 :     if (!filter)
     485           0 :       return NS_ERROR_OUT_OF_MEMORY;
     486             : 
     487           0 :     if (!mCurrentFilters.AppendElement(filter)) {
     488           0 :       free(filter);
     489           0 :       return NS_ERROR_OUT_OF_MEMORY;
     490             :     }
     491             : 
     492           0 :     if (iter == end)
     493           0 :       break;
     494             : 
     495           0 :     ++iter; // we know this is either ';' or ' ', skip to next char
     496           0 :   }
     497             : 
     498           0 :   if (mTree) {
     499           0 :     mTree->BeginUpdateBatch();
     500           0 :     uint32_t count = mDirList.Length();
     501           0 :     mTree->RowCountChanged(count, count - mTotalRows);
     502             :   }
     503             : 
     504           0 :   mFilteredFiles.Clear();
     505             : 
     506           0 :   FilterFiles();
     507             : 
     508           0 :   SortArray(mFilteredFiles);
     509           0 :   if (mReverseSort)
     510           0 :     ReverseArray(mFilteredFiles);
     511             : 
     512           0 :   if (mTree)
     513           0 :     mTree->EndUpdateBatch();
     514             : 
     515           0 :   return NS_OK;
     516             : }
     517             : 
     518             : NS_IMETHODIMP
     519           0 : nsFileView::GetSelectedFiles(nsIArray** aFiles)
     520             : {
     521           0 :   *aFiles = nullptr;
     522           0 :   if (!mSelection)
     523           0 :     return NS_OK;
     524             : 
     525             :   int32_t numRanges;
     526           0 :   mSelection->GetRangeCount(&numRanges);
     527             : 
     528           0 :   uint32_t dirCount = mDirList.Length();
     529             :   nsCOMPtr<nsIMutableArray> fileArray =
     530           0 :     do_CreateInstance(NS_ARRAY_CONTRACTID);
     531           0 :   NS_ENSURE_STATE(fileArray);
     532             : 
     533           0 :   for (int32_t range = 0; range < numRanges; ++range) {
     534             :     int32_t rangeBegin, rangeEnd;
     535           0 :     mSelection->GetRangeAt(range, &rangeBegin, &rangeEnd);
     536             : 
     537           0 :     for (int32_t itemIndex = rangeBegin; itemIndex <= rangeEnd; ++itemIndex) {
     538           0 :       nsIFile* curFile = nullptr;
     539             : 
     540           0 :       if (itemIndex < (int32_t) dirCount)
     541           0 :         curFile = mDirList[itemIndex];
     542             :       else {
     543           0 :         if (itemIndex < mTotalRows)
     544           0 :           curFile = mFilteredFiles[itemIndex - dirCount];
     545             :       }
     546             : 
     547           0 :       if (curFile)
     548           0 :         fileArray->AppendElement(curFile, false);
     549             :     }
     550             :   }
     551             : 
     552           0 :   fileArray.forget(aFiles);
     553           0 :   return NS_OK;
     554             : }
     555             : 
     556             : 
     557             : // nsITreeView implementation
     558             : 
     559             : NS_IMETHODIMP
     560           0 : nsFileView::GetRowCount(int32_t* aRowCount)
     561             : {
     562           0 :   *aRowCount = mTotalRows;
     563           0 :   return NS_OK;
     564             : }
     565             : 
     566             : NS_IMETHODIMP
     567           0 : nsFileView::GetSelection(nsITreeSelection** aSelection)
     568             : {
     569           0 :   *aSelection = mSelection;
     570           0 :   NS_IF_ADDREF(*aSelection);
     571           0 :   return NS_OK;
     572             : }
     573             : 
     574             : NS_IMETHODIMP
     575           0 : nsFileView::SetSelection(nsITreeSelection* aSelection)
     576             : {
     577           0 :   mSelection = aSelection;
     578           0 :   return NS_OK;
     579             : }
     580             : 
     581             : NS_IMETHODIMP
     582           0 : nsFileView::GetRowProperties(int32_t aIndex, nsAString& aProps)
     583             : {
     584           0 :   return NS_OK;
     585             : }
     586             : 
     587             : NS_IMETHODIMP
     588           0 : nsFileView::GetCellProperties(int32_t aRow, nsITreeColumn* aCol,
     589             :                               nsAString& aProps)
     590             : {
     591           0 :   uint32_t dirCount = mDirList.Length();
     592             : 
     593           0 :   if (aRow < (int32_t) dirCount)
     594           0 :     aProps.AppendLiteral("directory");
     595           0 :   else if (aRow < mTotalRows)
     596           0 :     aProps.AppendLiteral("file");
     597             : 
     598           0 :   return NS_OK;
     599             : }
     600             : 
     601             : NS_IMETHODIMP
     602           0 : nsFileView::GetColumnProperties(nsITreeColumn* aCol, nsAString& aProps)
     603             : {
     604           0 :   return NS_OK;
     605             : }
     606             : 
     607             : NS_IMETHODIMP
     608           0 : nsFileView::IsContainer(int32_t aIndex, bool* aIsContainer)
     609             : {
     610           0 :   *aIsContainer = false;
     611           0 :   return NS_OK;
     612             : }
     613             : 
     614             : NS_IMETHODIMP
     615           0 : nsFileView::IsContainerOpen(int32_t aIndex, bool* aIsOpen)
     616             : {
     617           0 :   *aIsOpen = false;
     618           0 :   return NS_OK;
     619             : }
     620             : 
     621             : NS_IMETHODIMP
     622           0 : nsFileView::IsContainerEmpty(int32_t aIndex, bool* aIsEmpty)
     623             : {
     624           0 :   *aIsEmpty = false;
     625           0 :   return NS_OK;
     626             : }
     627             : 
     628             : NS_IMETHODIMP
     629           0 : nsFileView::IsSeparator(int32_t aIndex, bool* aIsSeparator)
     630             : {
     631           0 :   *aIsSeparator = false;
     632           0 :   return NS_OK;
     633             : }
     634             : 
     635             : NS_IMETHODIMP
     636           0 : nsFileView::IsSorted(bool* aIsSorted)
     637             : {
     638           0 :   *aIsSorted = (mSortType >= 0);
     639           0 :   return NS_OK;
     640             : }
     641             : 
     642             : NS_IMETHODIMP
     643           0 : nsFileView::CanDrop(int32_t aIndex, int32_t aOrientation,
     644             :                     nsIDOMDataTransfer* dataTransfer, bool* aCanDrop)
     645             : {
     646           0 :   *aCanDrop = false;
     647           0 :   return NS_OK;
     648             : }
     649             : 
     650             : NS_IMETHODIMP
     651           0 : nsFileView::Drop(int32_t aRow, int32_t aOrientation, nsIDOMDataTransfer* dataTransfer)
     652             : {
     653           0 :   return NS_OK;
     654             : }
     655             : 
     656             : NS_IMETHODIMP
     657           0 : nsFileView::GetParentIndex(int32_t aRowIndex, int32_t* aParentIndex)
     658             : {
     659           0 :   *aParentIndex = -1;
     660           0 :   return NS_OK;
     661             : }
     662             : 
     663             : NS_IMETHODIMP
     664           0 : nsFileView::HasNextSibling(int32_t aRowIndex, int32_t aAfterIndex,
     665             :                            bool* aHasSibling)
     666             : {
     667           0 :   *aHasSibling = (aAfterIndex < (mTotalRows - 1));
     668           0 :   return NS_OK;
     669             : }
     670             : 
     671             : NS_IMETHODIMP
     672           0 : nsFileView::GetLevel(int32_t aIndex, int32_t* aLevel)
     673             : {
     674           0 :   *aLevel = 0;
     675           0 :   return NS_OK;
     676             : }
     677             : 
     678             : NS_IMETHODIMP
     679           0 : nsFileView::GetImageSrc(int32_t aRow, nsITreeColumn* aCol,
     680             :                         nsAString& aImageSrc)
     681             : {
     682           0 :   return NS_OK;
     683             : }
     684             : 
     685             : NS_IMETHODIMP
     686           0 : nsFileView::GetProgressMode(int32_t aRow, nsITreeColumn* aCol,
     687             :                             int32_t* aProgressMode)
     688             : {
     689           0 :   return NS_OK;
     690             : }
     691             : 
     692             : NS_IMETHODIMP
     693           0 : nsFileView::GetCellValue(int32_t aRow, nsITreeColumn* aCol,
     694             :                          nsAString& aCellValue)
     695             : {
     696           0 :   return NS_OK;
     697             : }
     698             : 
     699             : NS_IMETHODIMP
     700           0 : nsFileView::GetCellText(int32_t aRow, nsITreeColumn* aCol,
     701             :                         nsAString& aCellText)
     702             : {
     703           0 :   uint32_t dirCount = mDirList.Length();
     704             :   bool isDirectory;
     705           0 :   nsIFile* curFile = nullptr;
     706             : 
     707           0 :   if (aRow < (int32_t) dirCount) {
     708           0 :     isDirectory = true;
     709           0 :     curFile = mDirList[aRow];
     710           0 :   } else if (aRow < mTotalRows) {
     711           0 :     isDirectory = false;
     712           0 :     curFile = mFilteredFiles[aRow - dirCount];
     713             :   } else {
     714             :     // invalid row
     715           0 :     aCellText.SetCapacity(0);
     716           0 :     return NS_OK;
     717             :   }
     718             : 
     719             :   const char16_t* colID;
     720           0 :   aCol->GetIdConst(&colID);
     721           0 :   if (NS_LITERAL_STRING("FilenameColumn").Equals(colID)) {
     722           0 :     curFile->GetLeafName(aCellText);
     723           0 :   } else if (NS_LITERAL_STRING("LastModifiedColumn").Equals(colID)) {
     724             :     PRTime lastModTime;
     725           0 :     curFile->GetLastModifiedTime(&lastModTime);
     726             :     // XXX FormatPRTime could take an nsAString&
     727           0 :     nsAutoString temp;
     728           0 :     mozilla::DateTimeFormat::FormatPRTime(kDateFormatShort, kTimeFormatSeconds,
     729           0 :                                           lastModTime * 1000, temp);
     730           0 :     aCellText = temp;
     731             :   } else {
     732             :     // file size
     733           0 :     if (isDirectory)
     734           0 :       aCellText.SetCapacity(0);
     735             :     else {
     736             :       int64_t fileSize;
     737           0 :       curFile->GetFileSize(&fileSize);
     738           0 :       CopyUTF8toUTF16(nsPrintfCString("%" PRId64, fileSize), aCellText);
     739             :     }
     740             :   }
     741             : 
     742           0 :   return NS_OK;
     743             : }
     744             : 
     745             : NS_IMETHODIMP
     746           0 : nsFileView::SetTree(nsITreeBoxObject* aTree)
     747             : {
     748           0 :   mTree = aTree;
     749           0 :   return NS_OK;
     750             : }
     751             : 
     752             : NS_IMETHODIMP
     753           0 : nsFileView::ToggleOpenState(int32_t aIndex)
     754             : {
     755           0 :   return NS_OK;
     756             : }
     757             : 
     758             : NS_IMETHODIMP
     759           0 : nsFileView::CycleHeader(nsITreeColumn* aCol)
     760             : {
     761           0 :   return NS_OK;
     762             : }
     763             : 
     764             : NS_IMETHODIMP
     765           0 : nsFileView::SelectionChanged()
     766             : {
     767           0 :   return NS_OK;
     768             : }
     769             : 
     770             : NS_IMETHODIMP
     771           0 : nsFileView::CycleCell(int32_t aRow, nsITreeColumn* aCol)
     772             : {
     773           0 :   return NS_OK;
     774             : }
     775             : 
     776             : NS_IMETHODIMP
     777           0 : nsFileView::IsEditable(int32_t aRow, nsITreeColumn* aCol,
     778             :                        bool* aIsEditable)
     779             : {
     780           0 :   *aIsEditable = false;
     781           0 :   return NS_OK;
     782             : }
     783             : 
     784             : NS_IMETHODIMP
     785           0 : nsFileView::IsSelectable(int32_t aRow, nsITreeColumn* aCol,
     786             :                          bool* aIsSelectable)
     787             : {
     788           0 :   *aIsSelectable = false;
     789           0 :   return NS_OK;
     790             : }
     791             : 
     792             : NS_IMETHODIMP
     793           0 : nsFileView::SetCellValue(int32_t aRow, nsITreeColumn* aCol,
     794             :                          const nsAString& aValue)
     795             : {
     796           0 :   return NS_OK;
     797             : }
     798             : 
     799             : NS_IMETHODIMP
     800           0 : nsFileView::SetCellText(int32_t aRow, nsITreeColumn* aCol,
     801             :                         const nsAString& aValue)
     802             : {
     803           0 :   return NS_OK;
     804             : }
     805             : 
     806             : NS_IMETHODIMP
     807           0 : nsFileView::PerformAction(const char16_t* aAction)
     808             : {
     809           0 :   return NS_OK;
     810             : }
     811             : 
     812             : NS_IMETHODIMP
     813           0 : nsFileView::PerformActionOnRow(const char16_t* aAction, int32_t aRow)
     814             : {
     815           0 :   return NS_OK;
     816             : }
     817             : 
     818             : NS_IMETHODIMP
     819           0 : nsFileView::PerformActionOnCell(const char16_t* aAction, int32_t aRow,
     820             :                                 nsITreeColumn* aCol)
     821             : {
     822           0 :   return NS_OK;
     823             : }
     824             : 
     825             : // Private methods
     826             : 
     827             : void
     828           0 : nsFileView::FilterFiles()
     829             : {
     830           0 :   uint32_t count = mDirList.Length();
     831           0 :   mTotalRows = count;
     832           0 :   count = mFileList.Length();
     833           0 :   mFilteredFiles.Clear();
     834           0 :   uint32_t filterCount = mCurrentFilters.Length();
     835             : 
     836           0 :   for (uint32_t i = 0; i < count; ++i) {
     837           0 :     nsIFile* file = mFileList[i];
     838           0 :     bool isHidden = false;
     839           0 :     if (!mShowHiddenFiles)
     840           0 :       file->IsHidden(&isHidden);
     841             : 
     842           0 :     nsAutoString ucsLeafName;
     843           0 :     if(NS_FAILED(file->GetLeafName(ucsLeafName))) {
     844             :       // need to check return value for GetLeafName()
     845           0 :       continue;
     846             :     }
     847             : 
     848           0 :     if (!isHidden) {
     849           0 :       for (uint32_t j = 0; j < filterCount; ++j) {
     850           0 :         bool matched = false;
     851           0 :         if (!nsCRT::strcmp(mCurrentFilters.ElementAt(j),
     852             :                            u"..apps"))
     853             :         {
     854           0 :           file->IsExecutable(&matched);
     855             :         } else
     856           0 :           matched = (NS_WildCardMatch(ucsLeafName.get(),
     857           0 :                                       mCurrentFilters.ElementAt(j),
     858           0 :                                       true) == MATCH);
     859             : 
     860           0 :         if (matched) {
     861           0 :           mFilteredFiles.AppendElement(file);
     862           0 :           ++mTotalRows;
     863           0 :           break;
     864             :         }
     865             :       }
     866             :     }
     867             :   }
     868           0 : }
     869             : 
     870             : void
     871           0 : nsFileView::ReverseArray(nsTArray<nsCOMPtr<nsIFile> >& aArray)
     872             : {
     873           0 :   uint32_t count = aArray.Length();
     874           0 :   for (uint32_t i = 0; i < count/2; ++i) {
     875             :     // If we get references to the COMPtrs in the array, and then .swap() them
     876             :     // we avoid AdRef() / Release() calls.
     877           0 :     nsCOMPtr<nsIFile>& element = aArray[i];
     878           0 :     nsCOMPtr<nsIFile>& element2 = aArray[count - i - 1];
     879           0 :     element.swap(element2);
     880             :   }
     881           0 : }
     882             : 
     883             : static int
     884           0 : SortNameCallback(const void* aElement1, const void* aElement2, void* aContext)
     885             : {
     886           0 :   nsIFile* file1 = *static_cast<nsIFile* const *>(aElement1);
     887           0 :   nsIFile* file2 = *static_cast<nsIFile* const *>(aElement2);
     888             : 
     889           0 :   nsAutoString leafName1, leafName2;
     890           0 :   file1->GetLeafName(leafName1);
     891           0 :   file2->GetLeafName(leafName2);
     892             : 
     893           0 :   return Compare(leafName1, leafName2);
     894             : }
     895             : 
     896             : static int
     897           0 : SortSizeCallback(const void* aElement1, const void* aElement2, void* aContext)
     898             : {
     899           0 :   nsIFile* file1 = *static_cast<nsIFile* const *>(aElement1);
     900           0 :   nsIFile* file2 = *static_cast<nsIFile* const *>(aElement2);
     901             : 
     902             :   int64_t size1, size2;
     903           0 :   file1->GetFileSize(&size1);
     904           0 :   file2->GetFileSize(&size2);
     905             : 
     906           0 :   if (size1 == size2)
     907           0 :     return 0;
     908             : 
     909           0 :   return size1 < size2 ? -1 : 1;
     910             : }
     911             : 
     912             : static int
     913           0 : SortDateCallback(const void* aElement1, const void* aElement2, void* aContext)
     914             : {
     915           0 :   nsIFile* file1 = *static_cast<nsIFile* const *>(aElement1);
     916           0 :   nsIFile* file2 = *static_cast<nsIFile* const *>(aElement2);
     917             : 
     918             :   PRTime time1, time2;
     919           0 :   file1->GetLastModifiedTime(&time1);
     920           0 :   file2->GetLastModifiedTime(&time2);
     921             : 
     922           0 :   if (time1 == time2)
     923           0 :     return 0;
     924             : 
     925           0 :   return time1 < time2 ? -1 : 1;
     926             : }
     927             : 
     928             : void
     929           0 : nsFileView::SortArray(nsTArray<nsCOMPtr<nsIFile> >& aArray)
     930             : {
     931             :   // We assume the array to be in filesystem order, which
     932             :   // for our purposes, is completely unordered.
     933             : 
     934             :   int (*compareFunc)(const void*, const void*, void*);
     935             : 
     936           0 :   switch (mSortType) {
     937             :   case sortName:
     938           0 :     compareFunc = SortNameCallback;
     939           0 :     break;
     940             :   case sortSize:
     941           0 :     compareFunc = SortSizeCallback;
     942           0 :     break;
     943             :   case sortDate:
     944           0 :     compareFunc = SortDateCallback;
     945           0 :     break;
     946             :   default:
     947           0 :     return;
     948             :   }
     949             : 
     950           0 :   uint32_t count = aArray.Length();
     951             : 
     952           0 :   nsIFile** array = new nsIFile*[count];
     953           0 :   for (uint32_t i = 0; i < count; ++i) {
     954           0 :     array[i] = aArray[i];
     955             :   }
     956             : 
     957           0 :   NS_QuickSort(array, count, sizeof(nsIFile*), compareFunc, nullptr);
     958             : 
     959           0 :   for (uint32_t i = 0; i < count; ++i) {
     960             :     // Use swap() to avoid refcounting.
     961           0 :     aArray[i].swap(array[i]);
     962             :   }
     963             : 
     964           0 :   delete[] array;
     965             : }
     966             : 
     967             : void
     968           0 : nsFileView::SortInternal()
     969             : {
     970           0 :   SortArray(mDirList);
     971           0 :   SortArray(mFilteredFiles);
     972             : 
     973           0 :   if (mReverseSort) {
     974           0 :     ReverseArray(mDirList);
     975           0 :     ReverseArray(mFilteredFiles);
     976             :   }
     977           0 : }

Generated by: LCOV version 1.13