LCOV - code coverage report
Current view: directory - toolkit/components/filepicker - nsFileView.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 443 0 0.0 %
Date: 2012-06-02 Functions: 81 0 0.0 %

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

Generated by: LCOV version 1.7