浏览代码

Consistency with loading icons synchronously and on the background

Source commit: 0bdfb9f8178925db1afcaee2e6c778821badba72
Martin Prikryl 2 年之前
父节点
当前提交
bea96d44ed
共有 3 个文件被更改,包括 100 次插入109 次删除
  1. 1 1
      source/forms/ScpCommander.cpp
  2. 1 1
      source/forms/ScpCommander.h
  3. 98 107
      source/packages/filemng/DirView.pas

+ 1 - 1
source/forms/ScpCommander.cpp

@@ -2118,7 +2118,7 @@ void __fastcall TScpCommanderForm::RemotePathLabelPathClick(
 }
 }
 //---------------------------------------------------------------------------
 //---------------------------------------------------------------------------
 void __fastcall TScpCommanderForm::LocalDirViewFileIconForName(
 void __fastcall TScpCommanderForm::LocalDirViewFileIconForName(
-  TObject * /*Sender*/, TListItem * /*Item*/, UnicodeString & FileName)
+  TObject * /*Sender*/, UnicodeString & FileName)
 {
 {
   UnicodeString PartialExt = Configuration->PartialExt;
   UnicodeString PartialExt = Configuration->PartialExt;
   if (AnsiSameText(ExtractFileExt(FileName), PartialExt))
   if (AnsiSameText(ExtractFileExt(FileName), PartialExt))

+ 1 - 1
source/forms/ScpCommander.h

@@ -487,7 +487,7 @@ __published:
   void __fastcall RemotePathLabelPathClick(TCustomPathLabel *Sender,
   void __fastcall RemotePathLabelPathClick(TCustomPathLabel *Sender,
     UnicodeString Path);
     UnicodeString Path);
   void __fastcall LocalDirViewFileIconForName(TObject *Sender,
   void __fastcall LocalDirViewFileIconForName(TObject *Sender,
-          TListItem *Item, UnicodeString &FileName);
+          UnicodeString &FileName);
   void __fastcall LocalDirViewUpdateStatusBar(TObject *Sender,
   void __fastcall LocalDirViewUpdateStatusBar(TObject *Sender,
           const TStatusFileInfo &FileInfo);
           const TStatusFileInfo &FileInfo);
   void __fastcall RemoteDirViewUpdateStatusBar(TObject *Sender,
   void __fastcall RemoteDirViewUpdateStatusBar(TObject *Sender,

+ 98 - 107
source/packages/filemng/DirView.pas

@@ -87,7 +87,7 @@ type
 {Additional events:}
 {Additional events:}
 type
 type
   TDirViewFileSizeChanged = procedure(Sender: TObject; Item: TListItem) of object;
   TDirViewFileSizeChanged = procedure(Sender: TObject; Item: TListItem) of object;
-  TDirViewFileIconForName = procedure(Sender: TObject; Item: TListItem; var FileName: string) of object;
+  TDirViewFileIconForName = procedure(Sender: TObject; var FileName: string) of object;
 
 
 type
 type
   TDirView = class;
   TDirView = class;
@@ -225,6 +225,8 @@ type
     procedure WMDestroy(var Msg: TWMDestroy); message WM_DESTROY;
     procedure WMDestroy(var Msg: TWMDestroy); message WM_DESTROY;
     procedure CMRecreateWnd(var Message: TMessage); message CM_RECREATEWND;
     procedure CMRecreateWnd(var Message: TMessage); message CM_RECREATEWND;
     procedure Load(DoFocusSomething: Boolean); override;
     procedure Load(DoFocusSomething: Boolean); override;
+    procedure DoFetchIcon(
+      FilePath: string; IsSpecialExt: Boolean; CanTimeout: Boolean; FileRec: PFileRec; var ImageIndex: Integer; var TypeName: string);
     function GetFileInfo(
     function GetFileInfo(
       CanUsePIDL: Boolean; PIDL: PItemIDList; Path: string; CanTimeout: Boolean;
       CanUsePIDL: Boolean; PIDL: PItemIDList; Path: string; CanTimeout: Boolean;
       dwFileAttributes: DWORD; var psfi: TSHFileInfoW; uFlags: UINT): DWORD_PTR;
       dwFileAttributes: DWORD; var psfi: TSHFileInfoW; uFlags: UINT): DWORD_PTR;
@@ -669,12 +671,9 @@ end; {SetIndex}
 
 
 procedure TIconUpdateThread.Execute;
 procedure TIconUpdateThread.Execute;
 var
 var
-  FileInfo: TShFileInfo;
   Count: Integer;
   Count: Integer;
-  Eaten: ULONG;
-  ShAttr: ULONG;
-  FileIconForName: string;
-  ForceByName: Boolean;
+  IsSpecialExt: Boolean;
+  TypeName: string;
 begin
 begin
   if Assigned(FOwner.TopItem) then FIndex := FOwner.TopItem.Index
   if Assigned(FOwner.TopItem) then FIndex := FOwner.TopItem.Index
     else FIndex := 0;
     else FIndex := 0;
@@ -694,24 +693,8 @@ begin
       CurrentItemData.IconEmpty then
       CurrentItemData.IconEmpty then
     begin
     begin
       try
       try
-        ForceByName := False;
-        FileIconForName := CurrentFilePath;
-        if Assigned(FOwner.FOnFileIconForName) then
-        begin
-          FOwner.FOnFileIconForName(FOwner, nil, FileIconForName);
-          ForceByName := (FileIconForName <> CurrentFilePath);
-        end;
-
-        if not Assigned(CurrentItemData.PIDL) then
-        begin
-          ShAttr := 0;
-          FOwner.FDesktopFolder.ParseDisplayName(FOwner.ParentForm.Handle, nil,
-            PChar(CurrentFilePath), Eaten, CurrentItemData.PIDL, ShAttr);
-        end;
-
-        FOwner.GetFileInfo(
-          (not ForceByName), CurrentItemData.PIDL, FileIconForName, False,
-          0, FileInfo, SHGFI_TYPENAME or SHGFI_USEFILEATTRIBUTES or SHGFI_SYSICONINDEX);
+        IsSpecialExt := MatchesFileExt(CurrentItemData.FileExt, SpecialExtensions);
+        FOwner.DoFetchIcon(CurrentFilePath, IsSpecialExt, False, @CurrentItemData, FSyncIcon, TypeName);
       except
       except
         {Capture exceptions generated by the shell}
         {Capture exceptions generated by the shell}
         FSyncIcon := UnKnownFileIcon;
         FSyncIcon := UnKnownFileIcon;
@@ -721,7 +704,6 @@ begin
         FreePIDL(CurrentItemData.PIDL);
         FreePIDL(CurrentItemData.PIDL);
         Break;
         Break;
       end;
       end;
-      FSyncIcon := FileInfo.iIcon;
       if FSyncIcon <> CurrentItemData.ImageIndex then
       if FSyncIcon <> CurrentItemData.ImageIndex then
         FNewIcons := True;
         FNewIcons := True;
       if not Terminated then
       if not Terminated then
@@ -1786,18 +1768,99 @@ begin
   end;
   end;
 end;
 end;
 
 
+procedure TDirView.DoFetchIcon(
+  FilePath: string; IsSpecialExt: Boolean; CanTimeout: Boolean; FileRec: PFileRec; var ImageIndex: Integer; var TypeName: string);
+var
+  Eaten: ULONG;
+  shAttr: ULONG;
+  FileInfo: TShFileInfo;
+  ForceByName: Boolean;
+  FileIconForName: string;
+begin
+  {Fetch the Item FQ-PIDL:}
+  if not Assigned(FileRec^.PIDL) and IsSpecialExt then
+  begin
+    try
+      ShAttr := 0;
+      FDesktopFolder.ParseDisplayName(
+        ParentForm.Handle, nil, PChar(FilePath), Eaten, FileRec^.PIDL, ShAttr);
+    except
+    end;
+  end;
+
+  if FileRec^.IsDirectory then
+  begin
+    if FDriveType = DRIVE_FIXED then
+    begin
+      try
+        {Retrieve icon and typename for the directory}
+        GetFileInfo(True, FileRec^.PIDL, FilePath, False, 0, FileInfo, SHGFI_TYPENAME or SHGFI_SYSICONINDEX);
+
+        if (FileInfo.iIcon <= 0) or (FileInfo.iIcon > SmallImages.Count) then
+        begin
+          {Invalid icon returned: retry with access file attribute flag:}
+          GetFileInfo(
+            False, nil, FilePath, False,
+            FILE_ATTRIBUTE_DIRECTORY, FileInfo, SHGFI_TYPENAME or SHGFI_SYSICONINDEX or SHGFI_USEFILEATTRIBUTES);
+        end;
+        TypeName := FileInfo.szTypeName;
+        ImageIndex := FileInfo.iIcon;
+      except
+        {Capture exceptions generated by the shell}
+        TypeName := StdDirTypeName;
+        ImageIndex := StdDirIcon;
+      end;
+    end
+      else
+    begin
+      TypeName := StdDirTypeName;
+      ImageIndex := StdDirIcon;
+    end;
+  end
+    else
+  begin
+    {Retrieve icon and typename for the file}
+    try
+      ForceByName := False;
+      FileIconForName := FilePath;
+      if Assigned(OnFileIconForName) then
+      begin
+        OnFileIconForName(Self, FileIconForName);
+        ForceByName := (FileIconForName <> FilePath);
+      end;
+      // Files with PIDL are typically .exe files.
+      // It may take long to retrieve an icon from exe file.
+      // We typically do not get here, now that we have UseIconUpdateThread enabled.
+      if GetFileInfo(
+           (not ForceByName), FileRec^.PIDL, FileIconForName, CanTimeout, FILE_ATTRIBUTE_NORMAL, FileInfo,
+           SHGFI_TYPENAME or SHGFI_USEFILEATTRIBUTES or SHGFI_SYSICONINDEX) = 0 then
+      begin
+        if Assigned(FileRec^.PIDL) then
+        begin
+          FileInfo.iIcon := DefaultExeIcon;
+        end;
+      end;
+      TypeName := FileInfo.szTypeName;
+      ImageIndex := FileInfo.iIcon;
+
+    except
+      {Capture exceptions generated by the shell}
+      ImageIndex := UnKnownFileIcon;
+    end;
+  end;
+end;
+
 procedure TDirView.GetDisplayData(Item: TListItem; FetchIcon: Boolean);
 procedure TDirView.GetDisplayData(Item: TListItem; FetchIcon: Boolean);
 var
 var
   FileInfo: TShFileInfo;
   FileInfo: TShFileInfo;
   IsSpecialExt: Boolean;
   IsSpecialExt: Boolean;
-  ForceByName: Boolean;
-  Eaten: ULONG;
-  shAttr: ULONG;
-  FileIconForName, FullName: string;
+  FileRec: PFileRec;
+  FilePath: string;
   FileAttributes: UINT;
   FileAttributes: UINT;
 begin
 begin
   Assert(Assigned(Item) and Assigned(Item.Data));
   Assert(Assigned(Item) and Assigned(Item.Data));
-  with PFileRec(Item.Data)^ do
+  FileRec := PFileRec(Item.Data);
+  with FileRec^ do
   begin
   begin
     IsSpecialExt := MatchesFileExt(FileExt, SpecialExtensions);
     IsSpecialExt := MatchesFileExt(FileExt, SpecialExtensions);
 
 
@@ -1805,87 +1868,15 @@ begin
 
 
     if Empty or FetchIcon then
     if Empty or FetchIcon then
     begin
     begin
+      FilePath := FPath + '\' + FileName;
       if FetchIcon then
       if FetchIcon then
       begin
       begin
-        {Fetch the Item FQ-PIDL:}
-        if not Assigned(PIDL) and IsSpecialExt then
-        begin
-          try
-            ShAttr := 0;
-            FDesktopFolder.ParseDisplayName(ParentForm.Handle, nil,
-              PChar(FPath + '\' + FileName), Eaten, PIDL, ShAttr);
-          except
-          end;
-        end;
-
-        if IsDirectory then
-        begin
-          if FDriveType = DRIVE_FIXED then
-          begin
-            try
-              {Retrieve icon and typename for the directory}
-              GetFileInfo(True, PIDL, FPath + '\' + FileName, False, 0, FileInfo, SHGFI_TYPENAME or SHGFI_SYSICONINDEX);
-
-              if (FileInfo.iIcon <= 0) or (FileInfo.iIcon > SmallImages.Count) then
-              begin
-                {Invalid icon returned: retry with access file attribute flag:}
-                GetFileInfo(False, nil, FPath + '\' + FileName, False,
-                  FILE_ATTRIBUTE_DIRECTORY, FileInfo, SHGFI_TYPENAME or SHGFI_SYSICONINDEX or SHGFI_USEFILEATTRIBUTES);
-              end;
-              TypeName := FileInfo.szTypeName;
-              ImageIndex := FileInfo.iIcon;
-              IconEmpty := False;
-            {Capture exceptions generated by the shell}
-            except
-              ImageIndex := StdDirIcon;
-              IconEmpty := False;
-            end; {Except}
-          end
-            else
-          begin
-            TypeName := StdDirTypeName;
-            ImageIndex := StdDirIcon;
-            IconEmpty  := False;
-          end;
-        end
-          else
-        begin
-          {Retrieve icon and typename for the file}
-          try
-            ForceByName := False;
-            FullName := FPath + '\' + FileName;
-            FileIconForName := FullName;
-            if Assigned(OnFileIconForName) then
-            begin
-              OnFileIconForName(Self, Item, FileIconForName);
-              ForceByName := (FileIconForName <> FullName);
-            end;
-            // Files with PIDL are typically .exe files.
-            // It may take long to retrieve an icon from exe file.
-            // We typically do not get here, now that we have UseIconUpdateThread enabled.
-            if GetFileInfo(
-                 (not ForceByName), PIDL, FileIconForName, True, FILE_ATTRIBUTE_NORMAL, FileInfo,
-                 SHGFI_TYPENAME or SHGFI_USEFILEATTRIBUTES or SHGFI_SYSICONINDEX) = 0 then
-            begin
-              if Assigned(PIDL) then
-              begin
-                FileInfo.iIcon := DefaultExeIcon;
-              end;
-            end;
-            TypeName := FileInfo.szTypeName;
-            ImageIndex := FileInfo.iIcon;
-            IconEmpty := False;
-
-          {Capture exceptions generated by the shell}
-          except
-            ImageIndex := UnKnownFileIcon;
-            IconEmpty := False;
-          end; {Except}
-        end;
+        DoFetchIcon(FilePath, IsSpecialExt, True, FileRec, ImageIndex, TypeName);
+        IconEmpty := False;
 
 
         if Length(TypeName) = 0 then
         if Length(TypeName) = 0 then
           TypeName := Format(STextFileExt, [FileExt]);
           TypeName := Format(STextFileExt, [FileExt]);
-      end {If FetchIcon}
+      end
         else
         else
       begin
       begin
         try
         try
@@ -1893,7 +1884,7 @@ begin
             else FileAttributes := FILE_ATTRIBUTE_NORMAL;
             else FileAttributes := FILE_ATTRIBUTE_NORMAL;
 
 
           GetFileInfo(
           GetFileInfo(
-            False, nil, FPath + '\' + FileName, False, FileAttributes, FileInfo,
+            False, nil, FilePath, False, FileAttributes, FileInfo,
             SHGFI_TYPENAME or SHGFI_USEFILEATTRIBUTES);
             SHGFI_TYPENAME or SHGFI_USEFILEATTRIBUTES);
           TypeName := FileInfo.szTypeName;
           TypeName := FileInfo.szTypeName;
         except
         except