瀏覽代碼

Bug 902: Sorting find results

https://winscp.net/tracker/902

Source commit: 840e3b89b3b66c5805f5acd75ed893f91170e655
Martin Prikryl 6 年之前
父節點
當前提交
0548f74b20

+ 18 - 0
source/core/Common.cpp

@@ -904,6 +904,24 @@ int __fastcall CompareLogicalText(
   }
 }
 //---------------------------------------------------------------------------
+int __fastcall CompareNumber(__int64 Value1, __int64 Value2)
+{
+  int Result;
+  if (Value1 < Value2)
+  {
+    Result = -1;
+  }
+  else if (Value1 == Value2)
+  {
+    Result = 0;
+  }
+  else
+  {
+    Result = 1;
+  }
+  return Result;
+}
+//---------------------------------------------------------------------------
 bool ContainsTextSemiCaseSensitive(const UnicodeString & Text, const UnicodeString & SubText)
 {
   bool Result;

+ 1 - 0
source/core/Common.h

@@ -98,6 +98,7 @@ bool __fastcall SamePaths(const UnicodeString & Path1, const UnicodeString & Pat
 bool __fastcall IsPathToSameFile(const UnicodeString & Path1, const UnicodeString & Path2);
 int __fastcall CompareLogicalText(
   const UnicodeString & S1, const UnicodeString & S2, bool NaturalOrderNumericalSorting);
+int __fastcall CompareNumber(__int64 Value1, __int64 Value2);
 bool ContainsTextSemiCaseSensitive(const UnicodeString & Text, const UnicodeString & SubText);
 bool __fastcall IsReservedName(UnicodeString FileName);
 UnicodeString __fastcall ApiPath(UnicodeString Path);

+ 106 - 4
source/forms/FileFind.cpp

@@ -23,6 +23,7 @@
 #endif
 //---------------------------------------------------------------------------
 TFileFindDialog * FileFindDialog = NULL;
+static const int NoSort = 1;
 //---------------------------------------------------------------------------
 void __fastcall ShowFileFindDialog(
   TTerminal * Terminal, UnicodeString Directory, TFindEvent OnFind, TFocusFileEvent OnFocusFile,
@@ -59,7 +60,6 @@ __fastcall TFileFindDialog::TFileFindDialog(TComponent * Owner)
       LoadStr(MASK_HELP))));
 
   UpdateImages();
-  FileView->ShowColumnIcon = false;
 
   UseDesktopFont(FileView);
   UseDesktopFont(StatusBar);
@@ -71,7 +71,9 @@ __fastcall TFileFindDialog::TFileFindDialog(TComponent * Owner)
 __fastcall TFileFindDialog::~TFileFindDialog()
 {
   TFindFileConfiguration FormConfiguration = CustomWinConfiguration->FindFile;
-  FormConfiguration.ListParams = FileView->ColProperties->ParamsStr;
+  // | is there to make TCustomListViewColProperties.SetParamsStr stop there
+  // (and it allows adding new parameters to the col properties in the future)
+  FormConfiguration.ListParams = FORMAT(L"%s|/%d", (FileView->ColProperties->ParamsStr, 1));
   UnicodeString WindowParams = StoreFormSize(this);
   // this is particularly to prevent saving the form state
   // for the first time, keeping default positioning by a system
@@ -283,7 +285,47 @@ void __fastcall TFileFindDialog::Start()
 void __fastcall TFileFindDialog::FileFound(TTerminal * /*Terminal*/,
   const UnicodeString FileName, const TRemoteFile * AFile, bool & Cancel)
 {
-  TListItem * Item = FileView->Items->Add();
+  TListItem * Item;
+  int Count = FileView->Items->Count;
+  if ((GetColProperties()->SortColumn == NoSort) || (Count == 0))
+  {
+    Item = FileView->Items->Add();
+  }
+  else
+  {
+    TRemoteFile * FirstFile = static_cast<TRemoteFile *>(FileView->Items->Item[0]->Data);
+    TRemoteFile * LastFile = static_cast<TRemoteFile *>(FileView->Items->Item[Count - 1]->Data);
+    if (FilesCompare(AFile, FirstFile) < 0)
+    {
+      Item = FileView->Items->Insert(0);
+    }
+    else if (FilesCompare(LastFile, AFile) < 0)
+    {
+      Item = FileView->Items->Add();
+    }
+    else
+    {
+      int Start = 0;
+      int End = Count;
+      while (Start < End - 1)
+      {
+        int Index = (Start + End) / 2;
+        DebugAssert((Index >= 0) && (Index < End));
+        TRemoteFile * FileAtIndex = static_cast<TRemoteFile *>(FileView->Items->Item[Index]->Data);
+        int Compare = FilesCompare(AFile, FileAtIndex);
+        if (Compare <= 0)
+        {
+          End = Index;
+        }
+        else
+        {
+          Start = Index;
+        }
+      }
+      Item = FileView->Items->Insert(Start + 1);
+    }
+  }
+
   TRemoteFile * File = AFile->Duplicate(true);
   Item->Data = File;
 
@@ -374,7 +416,15 @@ void __fastcall TFileFindDialog::FormShow(TObject * /*Sender*/)
 
   UpdateFormPosition(this, poOwnerFormCenter);
   RestoreFormSize(CustomWinConfiguration->FindFile.WindowParams, this);
-  FileView->ColProperties->ParamsStr = CustomWinConfiguration->FindFile.ListParams;
+  UnicodeString S = CustomWinConfiguration->FindFile.ListParams;
+  UnicodeString ParamsStr = CutToChar(S, L'/', true);
+  FileView->ColProperties->ParamsStr = ParamsStr;
+  UnicodeString V = CutToChar(S, L'/', true);
+  if (StrToIntDef(V, 0) == 0)
+  {
+    // Old versions had non-sense (while unused) default to sorting by "Changed", ignore it.
+    GetColProperties()->SortColumn = NoSort;
+  }
 
   DebugAssert(FWindowParams.IsEmpty());
   if (FWindowParams.IsEmpty())
@@ -644,3 +694,55 @@ void __fastcall TFileFindDialog::EditActionExecute(TObject * /*Sender*/)
   FileListOperation(FOnEditFiles, FileDownloadFinished);
 }
 //---------------------------------------------------------------------------
+TIEListViewColProperties * TFileFindDialog::GetColProperties()
+{
+  return dynamic_cast<TIEListViewColProperties *>(FileView->ColProperties);
+}
+//---------------------------------------------------------------------------
+int TFileFindDialog::FilesCompare(const TRemoteFile * File1, const TRemoteFile * File2)
+{
+  int Result = 0;
+  switch (GetColProperties()->SortColumn)
+  {
+    case 0: // name
+      Result = CompareText(File1->FileName, File2->FileName);
+      break;
+
+    case NoSort: // directories
+      Result = 0; // default sort
+      break;
+
+    case 2: // size
+      Result = CompareNumber(File1->Size, File2->Size);
+      break;
+
+    case 3: // changed
+      Result = CompareFileTime(File1->Modification, File2->Modification);
+      break;
+  }
+
+  if (Result == 0)
+  {
+    Result = CompareText(UnixExtractFilePath(File1->FullFileName), UnixExtractFilePath(File2->FullFileName));
+
+    if (Result == 0)
+    {
+      Result = CompareText(File1->FileName, File2->FileName);
+    }
+  }
+
+  if (!GetColProperties()->SortAscending)
+  {
+    Result = -Result;
+  }
+  return Result;
+}
+//---------------------------------------------------------------------------
+void __fastcall TFileFindDialog::FileViewCompare(TObject *, TListItem * Item1, TListItem * Item2, int DebugUsedArg(Data), int & Compare)
+{
+  TRemoteFile * File1 = static_cast<TRemoteFile *>(Item1->Data);
+  TRemoteFile * File2 = static_cast<TRemoteFile *>(Item2->Data);
+
+  Compare = FilesCompare(File1, File2);
+}
+//---------------------------------------------------------------------------

+ 1 - 1
source/forms/FileFind.dfm

@@ -1476,7 +1476,6 @@ object FileFindDialog: TFileFindDialog
     Width = 434
     Height = 252
     Anchors = [akLeft, akTop, akRight, akBottom]
-    ColumnClick = False
     FullDrag = True
     ReadOnly = True
     RowSelect = True
@@ -1505,6 +1504,7 @@ object FileFindDialog: TFileFindDialog
         Caption = 'Changed'
         Width = 90
       end>
+    OnCompare = FileViewCompare
     OnContextPopup = FileViewContextPopup
     OnSelectItem = FileViewSelectItem
   end

+ 3 - 0
source/forms/FileFind.h

@@ -79,6 +79,7 @@ __published:
   void __fastcall SelectAllActionExecute(TObject *Sender);
   void __fastcall DownloadActionExecute(TObject *Sender);
   void __fastcall EditActionExecute(TObject *Sender);
+  void __fastcall FileViewCompare(TObject *Sender, TListItem *Item1, TListItem *Item2, int Data, int &Compare);
 
 public:
   __fastcall TFileFindDialog(TComponent * Owner);
@@ -135,6 +136,8 @@ private:
   void __fastcall FileDownloadFinished(const UnicodeString & FileName, bool Success);
   TListItem * __fastcall FileOperationFinished(const UnicodeString & FileName);
   void __fastcall FileListOperation(TFileListOperationEvent Operation, TFileOperationFinishedEvent OnFileOperationFinished);
+  TIEListViewColProperties * GetColProperties();
+  int FilesCompare(const TRemoteFile * File1, const TRemoteFile * File2);
 
   INTERFACE_HOOK;
 };

+ 0 - 19
source/forms/SynchronizeChecklist.cpp

@@ -881,25 +881,6 @@ void __fastcall TSynchronizeChecklistDialog::StatusBarMouseDown(
   }
 }
 //---------------------------------------------------------------------------
-int __fastcall TSynchronizeChecklistDialog::CompareNumber(__int64 Value1,
-  __int64 Value2)
-{
-  int Result;
-  if (Value1 < Value2)
-  {
-    Result = -1;
-  }
-  else if (Value1 == Value2)
-  {
-    Result = 0;
-  }
-  else
-  {
-    Result = 1;
-  }
-  return Result;
-}
-//---------------------------------------------------------------------------
 void __fastcall TSynchronizeChecklistDialog::ListViewCompare(
   TObject * /*Sender*/, TListItem * Item1, TListItem * Item2, int /*Data*/,
   int & Compare)

+ 0 - 1
source/forms/SynchronizeChecklist.h

@@ -179,7 +179,6 @@ protected:
   void __fastcall DeleteItem(TListItem * Item);
   void __fastcall CheckDirectory(bool Check);
   void __fastcall DoBrowse(TOperationSide Side);
-  static int __fastcall CompareNumber(__int64 Value1, __int64 Value2);
   void __fastcall ListViewHintShow(TCMHintShow & HintShow);
   void __fastcall StatusBarHintShow(TCMHintShow & HintShow);
 };

+ 1 - 0
source/packages/my/ListViewColProperties.pas

@@ -327,6 +327,7 @@ var
   OrderStr: string;
   PixelsPerInch: Integer;
 begin
+  // TFileFindDialog uses / as separator of its settings
   S := CutToChar(Value, '|', True);
   WidthsStr := CutToChar(S, '@', True);
   PixelsPerInch := LoadPixelsPerInch(S, FListView);

+ 1 - 1
source/windows/CustomWinConfiguration.cpp

@@ -113,7 +113,7 @@ void __fastcall TCustomWinConfiguration::Default()
   FSynchronizeChecklist.WindowParams = L"0;" + FormatDefaultWindowParams(ChecklistWidth, ChecklistHeight);
   FSynchronizeChecklist.ListParams = L"1;1|150,1;100,1;80,1;130,1;25,1;100,1;80,1;130,1;@" + SaveDefaultPixelsPerInch() + L"|0;1;2;3;4;5;6;7";
   FFindFile.WindowParams = FormatDefaultWindowSize(646, 481);
-  FFindFile.ListParams = L"3;1|125,1;181,1;80,1;122,1;@" + SaveDefaultPixelsPerInch() + L"|0;1;2;3";
+  FFindFile.ListParams = L"1;1|125,1;181,1;80,1;122,1;@" + SaveDefaultPixelsPerInch() + L"|0;1;2;3|/1";
   FConsoleWin.WindowSize = FormatDefaultWindowSize(570, 430);
   FLoginDialog.WindowSize = FormatDefaultWindowSize(640, 430);
   FLoginDialog.SiteSearch = isName;