UPD: refactoring File related from uMyDarwin to uDarwinFileUtil

(cherry picked from commit 83d2cfa181)
This commit is contained in:
rich2014 2025-12-09 23:16:57 +08:00 committed by Alexander Koblov
commit 49df0f028b
8 changed files with 167 additions and 161 deletions

View file

@ -148,7 +148,7 @@ uses
{$IFDEF UNIX}
BaseUnix, uUsersGroups, LazUTF8, DCUnix, uMyUnix,
{$IFDEF DARWIN}
uMyDarwin,
uMyDarwin, uDarwinFileUtil,
{$ENDIF}
{$IFDEF LINUX}
statx,
@ -431,7 +431,7 @@ begin
end;
{$IFDEF DARWIN}
if pSearchRecord^.Name<>'..' then
MacOSSpecificProperty := uMyDarwin.getMacOSSpecificFileProperty(AFilePath);
MacOSSpecificProperty := TDarwinFileUtil.getSpecificProperty(AFilePath);
{$ENDIF}
end;
@ -489,7 +489,7 @@ begin
{$ENDIF}
{$IFDEF DARWIN}
Result.MacOSSpecificProperty := uMyDarwin.getMacOSSpecificFileProperty(AFilePath);
Result.MacOSSpecificProperty := TDarwinFileUtil.getSpecificProperty(AFilePath);
{$ENDIF}
// Set name after assigning Attributes property, because it is used to get extension.
@ -764,7 +764,7 @@ begin
{$IFDEF DARWIN}
if (AFile.Name<>'..') and (fpMacOSSpecific in PropertiesToSet) then
MacOSSpecificProperty := uMyDarwin.getMacOSSpecificFileProperty(sFullPath);
MacOSSpecificProperty := TDarwinFileUtil.getSpecificProperty(sFullPath);
{$ENDIF}
PropertiesToSet:= PropertiesToSet * fpVariantAll;

View file

@ -10,7 +10,7 @@ uses
LCLType, Forms, Menus,
fMain, uDCUtils, uLng,
uFileView, uBriefFileView, uColumnsFileView, uThumbFileView,
uMyDarwin, uDarwinUtil, uDarwinFinder, uDarwinFinderModel, uDarwinFileView,
uMyDarwin, uDarwinUtil, uDarwinFileUtil, uDarwinFinder, uDarwinFinderModel, uDarwinFileView,
CocoaAll, CocoaConfig, CocoaToolBar, Cocoa_Extra;
procedure initCocoaModernFormConfig;
@ -213,7 +213,7 @@ var
cocoaItem: NSMenuItem;
cocoaImage: NSImage;
begin
folderName:= getMacOSDisplayNameFromPath( COMMON_FOLDERS[tag] );
folderName:= TDarwinFileUtil.getDisplayName( COMMON_FOLDERS[tag] );
lclItem:= TMenuItem.Create( menu );
lclItem.Caption:= folderName;
lclItem.onClick:= @toolBarMenuHandler.goToFolder;

View file

@ -9,9 +9,14 @@ interface
uses
Classes, SysUtils,
uDebug, uLog,
MacOSAll, CocoaAll, Cocoa_Extra, CocoaUtils;
uFileProperty, uDisplayFile,
MacOSAll, CocoaAll, Cocoa_Extra,
uDarwinUtil, uDarwinFinderModel;
type
{ TDarwinFileUtil }
TDarwinFileUtil = class
private class var
NetFS: TLibHandle;
@ -23,18 +28,29 @@ type
public class var
isMountSupported: Boolean;
public
class function mount(const serverAddress: String): Boolean;
class function unmountAndEject(const path: String): Boolean;
class function mount( const serverAddress: String ): Boolean;
class function unmountAndEject( const path: String ): Boolean;
class function getSpecificProperty( const path: String ): TFileMacOSSpecificProperty;
class function getDisplayName( const path: String ): String;
class function getUniqueIcon( const path: String ): NSImage;
end;
implementation
const
ICON_SPECIAL_FOLDER_EXT_STRING = '.app;.musiclibrary;.imovielibrary;.tvlibrary;.photoslibrary;.theater;.saver;.xcode;.xcodeproj;.xcworkspace;.playground;.scptd;.action;.workflow;.prefpane;.appex;.kext;.xpc;.bundle;.qlgenerator;.mdimporter;.systemextension;.fcpbundle;.fcpxmld;';
ICON_SPECIAL_PARENT_FOLDER_STRING = '/;/System;/Applications;/Volumes;/Users;~;~/Music;~/Pictures;~/Movies;';
var
ICON_SPECIAL_FOLDER_EXT: NSString;
ICON_SPECIAL_PARENT_FOLDER: NSString;
class function TDarwinFileUtil.mount(const serverAddress: String): Boolean;
var
sharePath: NSURL;
mountPoints: CFArrayRef = nil;
begin
sharePath:= NSURL.URLWithString(StrToNSString(serverAddress));
sharePath:= NSURL.URLWithString(StringToNSString(serverAddress));
if Assigned(NetFSMountURLSync) then
Result:= NetFSMountURLSync(CFURLRef(sharePath), nil, nil, nil, nil, nil, @mountPoints) = 0
else begin
@ -65,7 +81,7 @@ var
url: NSURL;
options: NSFileManagerUnmountOptions = 0;
begin
url:= NSURL.fileURLWithPath( StrToNSString(path) );
url:= NSURL.fileURLWithPath( StringToNSString(path) );
if allPartitions then
options:= NSFileManagerUnmountAllPartitionsAndEjectDisk;
NSFileManager.defaultManager.unmountVolumeAtURL_options_completionHandler( url, options, self.onComplete );
@ -90,6 +106,129 @@ begin
Result:= TUnmountManager.unmount( path, True );
end;
class function TDarwinFileUtil.getSpecificProperty(const path: String
): TFileMacOSSpecificProperty;
var
url: NSURL;
function toPrimaryColors(const tagNames: NSArray): TFileFinderTagPrimaryColors;
var
visualTagNames: NSMutableArray;
tagName: NSString;
tag: TFinderTag;
iSource: NSUInteger;
iDest: Integer;
colorIndex: Integer;
begin
visualTagNames:= NSMutableArray.new;
for iSource:= 0 to tagNames.count-1 do begin
tagName:= NSString( tagNames.objectAtIndex(iSource) );
tag:= TFinderTags.getTagOfName( tagName );
if tag.colorIndex <= 0 then
continue;
visualTagNames.addObject( tagName );
end;
iSource:= 0;
if visualTagNames.count > 3 then
iSource:= visualTagNames.count - 3;
for iDest:=0 to 2 do begin
colorIndex:= -1;
if iSource < visualTagNames.count then begin
tagName:= NSString( visualTagNames.objectAtIndex(iSource) );
tag:= TFinderTags.getTagOfName( tagName );
colorIndex:= tag.colorIndex;
end;
Result.indexes[iDest]:= colorIndex;
inc( iSource );
end;
visualTagNames.release;
end;
function getTagPrimaryColors: TFileFinderTagPrimaryColors;
var
tagNames: NSArray;
begin
Result.intValue:= -1;
tagNames:= uDarwinFinderModelUtil.getTagNamesOfFile( url );
if tagNames = nil then
Exit;
Result:= toPrimaryColors( tagNames );
end;
function isSeedFile: Boolean;
var
name: NSString;
status: NSString;
begin
name:= url.lastPathComponent;
if name.isEqualToString(NSSTR('..')) then
Exit( False );
if name.hasPrefix(NSSTR('.')) and name.hasSuffix(NSSTR('.icloud')) then
Exit( True );
url.getResourceValue_forKey_error( @status, NSURLUbiquitousItemDownloadingStatusKey, nil );
if status = nil then
Exit( False );
Result:= NOT status.isEqualToString( NSURLUbiquitousItemDownloadingStatusCurrent );
end;
begin
Result:= TFileMacOSSpecificProperty.Create;
url:= NSURL.fileURLWithPath( StringToNSString(path) );
Result.FinderTagPrimaryColors:= getTagPrimaryColors;
Result.IsiCloudSeedFile:= isSeedFile;
end;
class function TDarwinFileUtil.getDisplayName(const path: String): String;
var
cocoaPath: NSString;
displayName: NSString;
begin
cocoaPath:= StringToNSString(path).stringByStandardizingPath;
displayName:= NSFileManager.defaultManager.displayNameAtPath( cocoaPath );
Result:= displayName.UTF8String;
end;
class function TDarwinFileUtil.getUniqueIcon(const path: String): NSImage;
function hasUniqueIcon( const path: String ): Boolean;
var
pathRef: FSRef;
catalogInfo: FSCatalogInfo;
pFinderInfo: FileInfoPtr;
begin
FSPathMakeRef( pchar(path), pathRef, nil );
FSGetCatalogInfo( pathRef, kFSCatInfoFinderInfo, @catalogInfo, nil, nil, nil );
pFinderInfo:= FileInfoPtr( @catalogInfo.finderInfo );
Result:= (pFinderInfo^.finderFlags and kHasCustomIcon) <> 0;
end;
function hasSpecialFolderExt( const path: String ): Boolean;
var
ext: NSString;
begin
ext:= StringToNSString(path).pathExtension.lowercaseString;
ext:= NSSTR('.').stringByAppendingString(ext).stringByAppendingString(NSSTR(';'));
Result:= ICON_SPECIAL_FOLDER_EXT.containsString( ext );
end;
function inSpecialParentFolder( const path: String ): Boolean;
var
parentPath: NSString;
begin
parentPath:= StringToNSString(path).stringByDeletingLastPathComponent;
parentPath:= parentPath.stringByAppendingString(NSSTR(';'));
Result:= ICON_SPECIAL_PARENT_FOLDER.containsString( parentPath );
end;
begin
Result:= nil;
if hasUniqueIcon(path) or hasSpecialFolderExt(path) or inSpecialParentFolder(path) then
Result:= NSWorkspace.sharedWorkspace.iconForFile( StringToNSString(path) );
end;
procedure Initialize;
begin
TDarwinFileUtil.NetFS:= LoadLibrary('/System/Library/Frameworks/NetFS.framework/NetFS');
@ -103,6 +242,12 @@ begin
@TDarwinFileUtil.FSMountServerVolumeSync:= GetProcAddress(TDarwinFileUtil.CoreServices, 'FSMountServerVolumeSync');
end;
TDarwinFileUtil.isMountSupported:= Assigned(TDarwinFileUtil.NetFSMountURLSync) or Assigned(TDarwinFileUtil.FSMountServerVolumeSync);
ICON_SPECIAL_FOLDER_EXT:= StringToNSString( ICON_SPECIAL_FOLDER_EXT_STRING );
ICON_SPECIAL_FOLDER_EXT.retain;
ICON_SPECIAL_PARENT_FOLDER:= StringToNSString( ICON_SPECIAL_PARENT_FOLDER_STRING );
ICON_SPECIAL_PARENT_FOLDER:= ICON_SPECIAL_PARENT_FOLDER.stringByReplacingOccurrencesOfString_withString( NSSTR('~'), NSHomeDirectory );
ICON_SPECIAL_PARENT_FOLDER.retain;
end;
procedure Finalize;

View file

@ -18,7 +18,7 @@ interface
uses
Classes, SysUtils,
MacOSAll, CocoaAll, CocoaUtils,
uMyDarwin, uLog;
uMyDarwin, uDarwinFileUtil, uLog;
type
io_object_t = mach_port_t;
@ -335,7 +335,7 @@ end;
function TDarwinIOVolumns.getDisplayName(const fs: PDarwinStatfs): String;
begin
if fs^.mountpoint = PathDelim then begin
Result:= getMacOSDisplayNameFromPath( PathDelim );
Result:= TDarwinFileUtil.getDisplayName( PathDelim );
if Result = EmptyStr then
Result:= 'System';
end else begin

View file

@ -13,7 +13,8 @@ uses
uFileSource, uFileSourceOperationTypes, uFileSourceManager,
uFileSourceWatcher, uMountedFileSource, uVfsModule,
uDCUtils, uLng, uGlobs,
uMyDarwin, uDarwinApplication, uDarwinFSWatch, uDarwinSimpleFSWatch, uDarwinImageUtil,
uMyDarwin, uDarwinApplication, uDarwinFSWatch, uDarwinSimpleFSWatch,
uDarwinFileUtil, uDarwinImageUtil,
CocoaAll, CocoaUtils;
type
@ -740,7 +741,7 @@ end;
function TiCloudDriveFileSource.getDefaultPointForPath(const path: String): String;
begin
Result:= getMacOSDisplayNameFromPath( path );
Result:= TDarwinFileUtil.getDisplayName( path );
end;
class function TiCloudDriveFileSource.GetFileSource: TiCloudDriveFileSource;
@ -770,7 +771,7 @@ var
displayName: String;
begin
path:= uDCUtils.ReplaceTilde( iCloudDriveConfig.path.drive );
displayName:= getMacOSDisplayNameFromPath( path );
displayName:= TDarwinFileUtil.getDisplayName( path );
Result:= PathDelim + displayName + PathDelim;
end;
@ -799,7 +800,7 @@ begin
if aFile.Name = '..' then
Result:= Inherited
else
Result:= getMacOSDisplayNameFromPath( aFile.FullPath );
Result:= TDarwinFileUtil.getDisplayName( aFile.FullPath );
end;
function TiCloudDriveFileSource.QueryContextMenu(AFiles: TFiles; var AMenu: TPopupMenu): Boolean;

View file

@ -8,7 +8,7 @@ interface
uses
Classes, SysUtils, fgl, Graphics,
CocoaAll, CocoaUtils,
uDCUtils, uMyDarwin,
uDCUtils, uMyDarwin, uDarwinFileUtil,
uiCloudDriveConfig;
type
@ -142,7 +142,7 @@ begin
appPath:= appBasePath.stringByAppendingString( appName );
app:= TiCloudApp.Create;
app.appName:= appName.UTF8String;
app.displayName:= getMacOSDisplayNameFromPath( appPath.UTF8String );
app.displayName:= TDarwinFileUtil.getDisplayName( appPath.UTF8String );
app.contentCount:= contentCountOfApp( appPath );
app.icon:= createAppImage( app.appName );
Result.Add( app );

View file

@ -62,10 +62,6 @@ procedure openSystemSecurityPreferences_PrivacyAllFiles;
procedure openNewInstance();
function getMacOSDisplayNameFromPath(const path: String): String;
function getMacOSFileUniqueIcon(const path: String ): NSImage;
// Workarounds for FPC RTL Bug
// copied from ptypes.inc and modified fstypename only
{$if defined(cpuarm) or defined(cpuaarch64) or defined(iphonesim)}
@ -121,7 +117,6 @@ procedure performMacOSService( serviceName: String );
procedure showQuickLookPanel;
procedure showEditFinderTagsPanel( const Sender: id; const control: TWinControl );
function getMacOSSpecificFileProperty( const path: String ): TFileMacOSSpecificProperty;
// MacOS Sharing
procedure showMacOSSharingServiceMenu;
@ -149,14 +144,6 @@ implementation
uses
DynLibs;
const
ICON_SPECIAL_FOLDER_EXT_STRING = '.app;.musiclibrary;.imovielibrary;.tvlibrary;.photoslibrary;.theater;.saver;.xcode;.xcodeproj;.xcworkspace;.playground;.scptd;.action;.workflow;.prefpane;.appex;.kext;.xpc;.bundle;.qlgenerator;.mdimporter;.systemextension;.fcpbundle;.fcpxmld;';
ICON_SPECIAL_PARENT_FOLDER_STRING = '/;/System;/Applications;/Volumes;/Users;~;~/Music;~/Pictures;~/Movies;';
var
ICON_SPECIAL_FOLDER_EXT: NSString;
ICON_SPECIAL_PARENT_FOLDER: NSString;
procedure onMainMenuCreate( menu: NSMenu );
var
lclForm: TObject;
@ -432,11 +419,6 @@ procedure Initialize;
begin
MacosServiceMenuHelper:= TMacosServiceMenuHelper.Create;
DarwinFileViewDrawHelper:= TDarwinFileViewDrawHelper.Create;
ICON_SPECIAL_FOLDER_EXT:= StringToNSString( ICON_SPECIAL_FOLDER_EXT_STRING );
ICON_SPECIAL_FOLDER_EXT.retain;
ICON_SPECIAL_PARENT_FOLDER:= StringToNSString( ICON_SPECIAL_PARENT_FOLDER_STRING );
ICON_SPECIAL_PARENT_FOLDER:= ICON_SPECIAL_PARENT_FOLDER.stringByReplacingOccurrencesOfString_withString( NSSTR('~'), NSHomeDirectory );
ICON_SPECIAL_PARENT_FOLDER.retain;
end;
procedure Finalize;
@ -588,128 +570,6 @@ begin
uDarwinFinderUtil.popoverFileTagsEditor( filenames, handler.onClose, view , NSMaxYEdge );
end;
function getMacOSSpecificFileProperty( const path: String ): TFileMacOSSpecificProperty;
var
url: NSURL;
function toPrimaryColors(const tagNames: NSArray): TFileFinderTagPrimaryColors;
var
visualTagNames: NSMutableArray;
tagName: NSString;
tag: TFinderTag;
iSource: NSUInteger;
iDest: Integer;
colorIndex: Integer;
begin
visualTagNames:= NSMutableArray.new;
for iSource:= 0 to tagNames.count-1 do begin
tagName:= NSString( tagNames.objectAtIndex(iSource) );
tag:= TFinderTags.getTagOfName( tagName );
if tag.colorIndex <= 0 then
continue;
visualTagNames.addObject( tagName );
end;
iSource:= 0;
if visualTagNames.count > 3 then
iSource:= visualTagNames.count - 3;
for iDest:=0 to 2 do begin
colorIndex:= -1;
if iSource < visualTagNames.count then begin
tagName:= NSString( visualTagNames.objectAtIndex(iSource) );
tag:= TFinderTags.getTagOfName( tagName );
colorIndex:= tag.colorIndex;
end;
Result.indexes[iDest]:= colorIndex;
inc( iSource );
end;
visualTagNames.release;
end;
function getTagPrimaryColors: TFileFinderTagPrimaryColors;
var
tagNames: NSArray;
begin
Result.intValue:= -1;
tagNames:= uDarwinFinderModelUtil.getTagNamesOfFile( url );
if tagNames = nil then
Exit;
Result:= toPrimaryColors( tagNames );
end;
function isSeedFile: Boolean;
var
name: NSString;
status: NSString;
begin
name:= url.lastPathComponent;
if name.isEqualToString(NSSTR('..')) then
Exit( False );
if name.hasPrefix(NSSTR('.')) and name.hasSuffix(NSSTR('.icloud')) then
Exit( True );
url.getResourceValue_forKey_error( @status, NSURLUbiquitousItemDownloadingStatusKey, nil );
if status = nil then
Exit( False );
Result:= NOT status.isEqualToString( NSURLUbiquitousItemDownloadingStatusCurrent );
end;
begin
Result:= TFileMacOSSpecificProperty.Create;
url:= NSURL.fileURLWithPath( StrToNSString(path) );
Result.FinderTagPrimaryColors:= getTagPrimaryColors;
Result.IsiCloudSeedFile:= isSeedFile;
end;
function getMacOSDisplayNameFromPath(const path: String): String;
var
cocoaPath: NSString;
displayName: NSString;
begin
cocoaPath:= StringToNSString(path).stringByStandardizingPath;
displayName:= NSFileManager.defaultManager.displayNameAtPath( cocoaPath );
Result:= displayName.UTF8String;
end;
function hasUniqueIcon( const path: String ): Boolean;
var
pathRef: FSRef;
catalogInfo: FSCatalogInfo;
pFinderInfo: FileInfoPtr;
begin
FSPathMakeRef( pchar(path), pathRef, nil );
FSGetCatalogInfo( pathRef, kFSCatInfoFinderInfo, @catalogInfo, nil, nil, nil );
pFinderInfo:= FileInfoPtr( @catalogInfo.finderInfo );
Result:= (pFinderInfo^.finderFlags and kHasCustomIcon) <> 0;
end;
function hasSpecialFolderExt( const path: String ): Boolean;
var
ext: NSString;
begin
ext:= StringToNSString(path).pathExtension.lowercaseString;
ext:= NSSTR('.').stringByAppendingString(ext).stringByAppendingString(NSSTR(';'));
Result:= ICON_SPECIAL_FOLDER_EXT.containsString( ext );
end;
function inSpecialParentFolder( const path: String ): Boolean;
var
parentPath: NSString;
begin
parentPath:= StringToNSString(path).stringByDeletingLastPathComponent;
parentPath:= parentPath.stringByAppendingString(NSSTR(';'));
Result:= ICON_SPECIAL_PARENT_FOLDER.containsString( parentPath );
end;
function getMacOSFileUniqueIcon( const path: String ): NSImage;
begin
Result:= nil;
if hasUniqueIcon(path) or hasSpecialFolderExt(path) or inSpecialParentFolder(path) then
Result:= NSWorkspace.sharedWorkspace.iconForFile( StringToNSString(path) );
end;
initialization
Initialize;

View file

@ -56,7 +56,7 @@ uses
{$ELSEIF DEFINED(UNIX)}
, DCFileAttributes
{$IF DEFINED(DARWIN)}
, CocoaAll, MacOSAll, CocoaUtils, uDarwinUtil, uMyDarwin
, CocoaAll, MacOSAll, CocoaUtils, uDarwinUtil, uDarwinFileUtil, uMyDarwin
{$ELSEIF NOT DEFINED(HAIKU)}
, Math, Contnrs, uGio, uXdg
{$IFDEF GTK2_FIX}
@ -1256,7 +1256,7 @@ begin
FPixmapsLock.Acquire;
try
image:= getMacOSFileUniqueIcon(AFullPath);
image:= TDarwinFileUtil.getUniqueIcon(AFullPath);
if image = nil then
Exit;