mirror of
https://github.com/doublecmd/doublecmd.git
synced 2026-06-21 09:58:13 +00:00
FIX: MacPreview - open only supported file types (issue #1481)
(cherry picked from commit d2bef610d8)
This commit is contained in:
parent
0e02e9303c
commit
88342a221c
2 changed files with 221 additions and 2 deletions
|
|
@ -25,8 +25,21 @@ library MacPreview;
|
|||
{$mode objfpc}{$H+}
|
||||
{$modeswitch objectivec1}
|
||||
|
||||
// Uniform Type Identifiers framework is available from macOS 11
|
||||
// TODO: Switch to Uniform Type Identifiers framework also under
|
||||
// x86_64 target when we drop an old macOS support
|
||||
{$IF DEFINED(CPUAARCH64)}
|
||||
{$DEFINE BIG_SUR}
|
||||
{$ENDIF}
|
||||
|
||||
uses
|
||||
SysUtils, WlxPlugin, CocoaAll, QuickLookUI;
|
||||
SysUtils, WlxPlugin, CocoaAll, QuickLookUI, CFPropertyList
|
||||
{$IF DEFINED(BIG_SUR)}
|
||||
, UniformTypeIdentifiers
|
||||
{$ELSE}
|
||||
, MacOSAll
|
||||
{$ENDIF}
|
||||
;
|
||||
|
||||
type
|
||||
TQLPItem = objcclass(NSObject, QLPreviewItemProtocol)
|
||||
|
|
@ -42,6 +55,20 @@ type
|
|||
function acceptsFirstResponder: ObjCBOOL; override;
|
||||
end;
|
||||
|
||||
var
|
||||
QLContentTypes: NSMutableArray;
|
||||
{$IF DEFINED(BIG_SUR)}
|
||||
QLContentUTTypes: NSMutableArray;
|
||||
{$ENDIF}
|
||||
|
||||
const
|
||||
ExcludeList: array[0..2] of PAnsiChar =
|
||||
(
|
||||
'public.plain-text',
|
||||
'public.json',
|
||||
'public.xml'
|
||||
);
|
||||
|
||||
// copy from uMyDarwin
|
||||
function StringToNSString(const S: String): NSString;
|
||||
begin
|
||||
|
|
@ -67,6 +94,147 @@ begin
|
|||
end;
|
||||
end;
|
||||
|
||||
procedure AddContentType(AType: NSString);
|
||||
{$IF NOT DEFINED(BIG_SUR)}
|
||||
begin
|
||||
QLContentTypes.addObject(AType);
|
||||
end;
|
||||
{$ELSE}
|
||||
var
|
||||
anObject: id;
|
||||
begin
|
||||
QLContentTypes.addObject(AType);
|
||||
anObject:= UTType.typeWithIdentifier(AType);
|
||||
if Assigned(anObject) then QLContentUTTypes.addObject(anObject);
|
||||
end;
|
||||
{$ENDIF}
|
||||
|
||||
function CheckContentType(const Name: String; FileType: NSString): Boolean;
|
||||
var
|
||||
Index: Integer;
|
||||
begin
|
||||
// Special case
|
||||
if (Name = 'Text.qlgenerator') then
|
||||
begin
|
||||
for Index:= 0 to High(ExcludeList) do
|
||||
begin
|
||||
if StrComp(FileType.UTF8String, ExcludeList[Index]) = 0 then
|
||||
Exit(False)
|
||||
end;
|
||||
end;
|
||||
Result:= True;
|
||||
end;
|
||||
|
||||
procedure ParseFile(const Path, Name: String);
|
||||
var
|
||||
Data: NSData;
|
||||
I, J: Integer;
|
||||
Dict: NSDictionary;
|
||||
FileType: NSString;
|
||||
DocumentTypes, ContentTypes: NSArray;
|
||||
begin
|
||||
Data:= NSData.dataWithContentsOfFile(StringToNSString(Path + Name + '/Contents/Info.plist'));
|
||||
if Assigned(Data) then
|
||||
begin
|
||||
Dict:= NSDictionary(NSPropertyListSerialization.propertyListWithData_options_format_error(Data, NSPropertyListImmutable, nil, nil));
|
||||
if Assigned(Dict) then
|
||||
begin
|
||||
DocumentTypes:= NSArray(Dict.valueForKey(StringToNSString('CFBundleDocumentTypes')));
|
||||
if Assigned(DocumentTypes) then
|
||||
begin
|
||||
for I:= 0 to Integer(DocumentTypes.count) - 1 do
|
||||
begin
|
||||
Dict:= NSDictionary(DocumentTypes.objectAtIndex(I));
|
||||
ContentTypes:= NSArray(Dict.valueForKey(StringToNSString('LSItemContentTypes')));
|
||||
if Assigned(ContentTypes) then
|
||||
begin
|
||||
for J:= 0 to Integer(ContentTypes.count - 1) do
|
||||
begin
|
||||
FileType:= NSString(ContentTypes.objectAtIndex(J));
|
||||
if CheckContentType(Name, FileType) then AddContentType(FileType);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure ParseFolder(const Path: String);
|
||||
var
|
||||
FindData: TSearchRec;
|
||||
begin
|
||||
if FindFirst(Path + '*.qlgenerator', faDirectory, FindData) = 0 then
|
||||
begin
|
||||
repeat
|
||||
ParseFile(Path, FindData.Name);
|
||||
until FindNext(FindData) <> 0;
|
||||
FindClose(FindData);
|
||||
end;
|
||||
end;
|
||||
|
||||
function CheckFile(const FileName: String): Boolean;
|
||||
{$IF NOT DEFINED(BIG_SUR)}
|
||||
var
|
||||
Index: Integer;
|
||||
QLType: NSString;
|
||||
FileType: NSString;
|
||||
begin
|
||||
FileType:= NSWorkspace.sharedWorkspace.typeOfFile_error(StringToNSString(FileName), nil);
|
||||
if (FileType = nil) then
|
||||
begin
|
||||
Result:= False;
|
||||
end
|
||||
else begin
|
||||
for Index:= 0 to QLContentTypes.Count - 1 do
|
||||
begin
|
||||
QLType:= NSString(QLContentTypes.objectAtIndex(Index));
|
||||
// Direct comparison
|
||||
if (FileType.compare(QLType) = NSOrderedSame) then
|
||||
Exit(True);
|
||||
// Conforms checking
|
||||
if UTTypeConformsTo(CFStringRef(FileType), CFStringRef(QLType)) then
|
||||
Exit(True);
|
||||
end;
|
||||
Result:= False;
|
||||
end;
|
||||
end;
|
||||
{$ELSE}
|
||||
var
|
||||
Index: Integer;
|
||||
FileExt: String;
|
||||
QLUTType: UTType;
|
||||
QLType: NSString;
|
||||
FileType: NSString;
|
||||
FileUTType: UTType;
|
||||
begin
|
||||
FileExt:= ExtractOnlyFileExt(FileName);
|
||||
FileUTType:= UTType.typeWithFilenameExtension(StringToNSString(FileExt));
|
||||
if (FileUTType = nil) then
|
||||
begin
|
||||
Result:= False;
|
||||
end
|
||||
else begin
|
||||
FileType:= FileUTType.identifier;
|
||||
// Direct comparison
|
||||
for Index:= 0 to QLContentTypes.Count - 1 do
|
||||
begin
|
||||
QLType:= NSString(QLContentTypes.objectAtIndex(Index));
|
||||
if (FileType.compare(QLType) = NSOrderedSame) then
|
||||
Exit(True);
|
||||
end;
|
||||
// Conforms checking
|
||||
for Index:= 0 to QLContentUTTypes.Count - 1 do
|
||||
begin
|
||||
QLUTType:= UTType(QLContentUTTypes.objectAtIndex(Index));
|
||||
if FileUTType.conformsToType(QLUTType) then
|
||||
Exit(True);
|
||||
end;
|
||||
Result:= False;
|
||||
end;
|
||||
end;
|
||||
{$ENDIF}
|
||||
|
||||
function TQLPItem.previewItemURL: NSURL;
|
||||
begin
|
||||
Result:= url;
|
||||
|
|
@ -100,6 +268,9 @@ function ListLoad( ParentWin:THandle; FileToLoad:pchar; {%H-}ShowFlags:integer):
|
|||
var
|
||||
view: QLPreviewView;
|
||||
begin
|
||||
if not CheckFile(FileToLoad) then
|
||||
Exit(wlxInvalidHandle);
|
||||
|
||||
view:= DCQLPreview.alloc.init;
|
||||
view.setAutostarts( true );
|
||||
view.setShouldCloseWithWindow( false );
|
||||
|
|
@ -122,6 +293,9 @@ function ListLoadNext( {%H-}ParentWin,PluginWin:THandle; FileToLoad:pchar; {%H-}
|
|||
var
|
||||
view: QLPreviewView;
|
||||
begin
|
||||
if not CheckFile(FileToLoad) then
|
||||
Exit(LISTPLUGIN_ERROR);
|
||||
|
||||
view:= QLPreviewView(PluginWin);
|
||||
|
||||
// workaround for the bug of MacOS Quick Look:
|
||||
|
|
@ -140,6 +314,17 @@ begin
|
|||
QLPreviewView(ListWin).removeFromSuperview;
|
||||
end;
|
||||
|
||||
procedure ListSetDefaultParams(dps: PListDefaultParamStruct); cdecl;
|
||||
begin
|
||||
QLContentTypes:= NSMutableArray.alloc.init;
|
||||
{$IF DEFINED(BIG_SUR)}
|
||||
QLContentUTTypes:= NSMutableArray.alloc.init;
|
||||
{$ENDIF}
|
||||
ParseFolder('/Library/QuickLook/');
|
||||
ParseFolder('/System/Library/QuickLook/');
|
||||
ParseFolder(IncludeTrailingBackslash(GetUserDir) + 'Library/QuickLook/');
|
||||
end;
|
||||
|
||||
procedure ListGetDetectString(DetectString:pchar;maxlen:integer); cdecl;
|
||||
begin
|
||||
StrLCopy(DetectString, '(EXT!="")', MaxLen);
|
||||
|
|
@ -149,7 +334,8 @@ exports
|
|||
ListLoad,
|
||||
ListLoadNext,
|
||||
ListCloseWindow,
|
||||
ListGetDetectString;
|
||||
ListGetDetectString,
|
||||
ListSetDefaultParams;
|
||||
|
||||
end.
|
||||
|
||||
|
|
|
|||
33
plugins/wlx/MacPreview/src/UniformTypeIdentifiers.pas
Normal file
33
plugins/wlx/MacPreview/src/UniformTypeIdentifiers.pas
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
unit UniformTypeIdentifiers;
|
||||
|
||||
{$mode delphi}
|
||||
{$modeswitch objectivec1}
|
||||
|
||||
interface
|
||||
|
||||
{$linkframework UniformTypeIdentifiers}
|
||||
|
||||
uses
|
||||
SysUtils, CocoaAll;
|
||||
|
||||
type
|
||||
UTType = objcclass external(NSObject, NSCopyingProtocol, NSSecureCodingProtocol)
|
||||
public
|
||||
class function typeWithIdentifier(identifier: NSString): id; message 'typeWithIdentifier:';
|
||||
class function typeWithFilenameExtension(filenameExtension: NSString): id; message 'typeWithFilenameExtension:';
|
||||
|
||||
function identifier: NSString; message 'identifier';
|
||||
function conformsToType(type_: UTType): ObjCBOOL; message 'conformsToType:';
|
||||
|
||||
// NSCopyingProtocol
|
||||
function copyWithZone(zone: NSZonePtr): id; message 'copyWithZone:';
|
||||
// NSCodingProtocol
|
||||
procedure encodeWithCoder(aCoder: NSCoder); message 'encodeWithCoder:';
|
||||
function initWithCoder(aDecoder: NSCoder): id; message 'initWithCoder:';
|
||||
// NSSecureCodingProtocol
|
||||
class function supportsSecureCoding: ObjCBOOL; message 'supportsSecureCoding';
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
end.
|
||||
Loading…
Add table
Add a link
Reference in a new issue