LCOV - app.info - toolkit/components/filepicker/nsFileView.cpp

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-04-21 | 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