From 55e7d088850f2cea95e1bf10cbfabd65a671ddba Mon Sep 17 00:00:00 2001 From: Mario Iannotta Date: Wed, 11 Sep 2019 21:05:32 +0200 Subject: [PATCH] Add initial project --- .gitignore | 3 + QuickLookFramework.xcodeproj/project.pbxproj | 522 +++++++++++++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcshareddata/xcschemes/Deploy.xcscheme | 80 +++ .../xcschemes/QuickLookFramework.xcscheme | 80 +++ .../xcshareddata/xcschemes/Run.xcscheme | 80 +++ QuickLookFramework/Extensions/Bundle+.swift | 13 + QuickLookFramework/Extensions/String+.swift | 29 + QuickLookFramework/GeneratePreviewForURL.m | 38 ++ QuickLookFramework/GenerateThumbnailForURL.m | 22 + .../Helpers/CommandLineHandler.swift | 85 +++ QuickLookFramework/Info.plist | 61 ++ .../Models/FrameworkInfoPlist.swift | 81 +++ QuickLookFramework/UI/Main.storyboard | 625 ++++++++++++++++++ .../UI/PreviewViewController.swift | 112 ++++ QuickLookFramework/main.c | 218 ++++++ Scripts/deploy.sh | 5 + Scripts/run.sh | 2 + 19 files changed, 2071 insertions(+) create mode 100644 QuickLookFramework.xcodeproj/project.pbxproj create mode 100644 QuickLookFramework.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 QuickLookFramework.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 QuickLookFramework.xcodeproj/xcshareddata/xcschemes/Deploy.xcscheme create mode 100644 QuickLookFramework.xcodeproj/xcshareddata/xcschemes/QuickLookFramework.xcscheme create mode 100644 QuickLookFramework.xcodeproj/xcshareddata/xcschemes/Run.xcscheme create mode 100644 QuickLookFramework/Extensions/Bundle+.swift create mode 100644 QuickLookFramework/Extensions/String+.swift create mode 100644 QuickLookFramework/GeneratePreviewForURL.m create mode 100644 QuickLookFramework/GenerateThumbnailForURL.m create mode 100644 QuickLookFramework/Helpers/CommandLineHandler.swift create mode 100644 QuickLookFramework/Info.plist create mode 100644 QuickLookFramework/Models/FrameworkInfoPlist.swift create mode 100644 QuickLookFramework/UI/Main.storyboard create mode 100644 QuickLookFramework/UI/PreviewViewController.swift create mode 100644 QuickLookFramework/main.c create mode 100644 Scripts/deploy.sh create mode 100644 Scripts/run.sh diff --git a/.gitignore b/.gitignore index 312d1f6..835f3c3 100644 --- a/.gitignore +++ b/.gitignore @@ -66,3 +66,6 @@ fastlane/report.xml fastlane/Preview.html fastlane/screenshots/**/*.png fastlane/test_output + + +Test/ diff --git a/QuickLookFramework.xcodeproj/project.pbxproj b/QuickLookFramework.xcodeproj/project.pbxproj new file mode 100644 index 0000000..701b333 --- /dev/null +++ b/QuickLookFramework.xcodeproj/project.pbxproj @@ -0,0 +1,522 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 50; + objects = { + +/* Begin PBXAggregateTarget section */ + AC96BACC232505AC00636EF7 /* Deploy */ = { + isa = PBXAggregateTarget; + buildConfigurationList = AC96BACF232505AC00636EF7 /* Build configuration list for PBXAggregateTarget "Deploy" */; + buildPhases = ( + AC96BAD0232505B900636EF7 /* ShellScript */, + ); + dependencies = ( + ); + name = Deploy; + productName = BuildAndCopy; + }; + AC96BAD923250A2600636EF7 /* Run */ = { + isa = PBXAggregateTarget; + buildConfigurationList = AC96BADA23250A2600636EF7 /* Build configuration list for PBXAggregateTarget "Run" */; + buildPhases = ( + AC96BADD23250A2A00636EF7 /* ShellScript */, + ); + dependencies = ( + ); + name = Run; + productName = Run; + }; +/* End PBXAggregateTarget section */ + +/* Begin PBXBuildFile section */ + AC96BAD52325096E00636EF7 /* deploy.sh in Resources */ = {isa = PBXBuildFile; fileRef = AC96BAD42325096E00636EF7 /* deploy.sh */; }; + AC96BAD72325098500636EF7 /* run.sh in Resources */ = {isa = PBXBuildFile; fileRef = AC96BAD62325098500636EF7 /* run.sh */; }; + AC96BAE023251A8100636EF7 /* PreviewViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC96BADF23251A8100636EF7 /* PreviewViewController.swift */; }; + AC96BAE223251CE900636EF7 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = AC96BAE123251CE900636EF7 /* Main.storyboard */; }; + AC96BAE423256BF700636EF7 /* FrameworkInfoPlist.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC96BAE323256BF700636EF7 /* FrameworkInfoPlist.swift */; }; + AC96BAE923256C9900636EF7 /* Bundle+.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC96BAE823256C9900636EF7 /* Bundle+.swift */; }; + AC96BAEB232575A500636EF7 /* CommandLineHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC96BAEA232575A500636EF7 /* CommandLineHandler.swift */; }; + ACBB0A402327E361008656A9 /* String+.swift in Sources */ = {isa = PBXBuildFile; fileRef = ACBB0A3F2327E361008656A9 /* String+.swift */; }; + ACE7B0D923239B4300A8E2F1 /* GenerateThumbnailForURL.m in Sources */ = {isa = PBXBuildFile; fileRef = ACE7B0D823239B4300A8E2F1 /* GenerateThumbnailForURL.m */; }; + ACE7B0DB23239B4300A8E2F1 /* GeneratePreviewForURL.m in Sources */ = {isa = PBXBuildFile; fileRef = ACE7B0DA23239B4300A8E2F1 /* GeneratePreviewForURL.m */; }; + ACE7B0DD23239B4300A8E2F1 /* main.c in Sources */ = {isa = PBXBuildFile; fileRef = ACE7B0DC23239B4300A8E2F1 /* main.c */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + AC96BAD42325096E00636EF7 /* deploy.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = deploy.sh; sourceTree = ""; }; + AC96BAD62325098500636EF7 /* run.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = run.sh; sourceTree = ""; }; + AC96BADF23251A8100636EF7 /* PreviewViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreviewViewController.swift; sourceTree = ""; }; + AC96BAE123251CE900636EF7 /* Main.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = Main.storyboard; sourceTree = ""; }; + AC96BAE323256BF700636EF7 /* FrameworkInfoPlist.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FrameworkInfoPlist.swift; sourceTree = ""; }; + AC96BAE823256C9900636EF7 /* Bundle+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Bundle+.swift"; sourceTree = ""; }; + AC96BAEA232575A500636EF7 /* CommandLineHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CommandLineHandler.swift; sourceTree = ""; }; + ACBB0A3F2327E361008656A9 /* String+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+.swift"; sourceTree = ""; }; + ACE7B0D523239B4300A8E2F1 /* QuickLookFramework.qlgenerator */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = QuickLookFramework.qlgenerator; sourceTree = BUILT_PRODUCTS_DIR; }; + ACE7B0D823239B4300A8E2F1 /* GenerateThumbnailForURL.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GenerateThumbnailForURL.m; sourceTree = ""; }; + ACE7B0DA23239B4300A8E2F1 /* GeneratePreviewForURL.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GeneratePreviewForURL.m; sourceTree = ""; }; + ACE7B0DC23239B4300A8E2F1 /* main.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = main.c; sourceTree = ""; }; + ACE7B0DE23239B4300A8E2F1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + ACE7B0D223239B4300A8E2F1 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + AC96BAD32325095E00636EF7 /* Scripts */ = { + isa = PBXGroup; + children = ( + AC96BAD42325096E00636EF7 /* deploy.sh */, + AC96BAD62325098500636EF7 /* run.sh */, + ); + path = Scripts; + sourceTree = ""; + }; + AC96BAE523256C7800636EF7 /* UI */ = { + isa = PBXGroup; + children = ( + AC96BADF23251A8100636EF7 /* PreviewViewController.swift */, + AC96BAE123251CE900636EF7 /* Main.storyboard */, + ); + path = UI; + sourceTree = ""; + }; + AC96BAE623256C8900636EF7 /* Models */ = { + isa = PBXGroup; + children = ( + AC96BAE323256BF700636EF7 /* FrameworkInfoPlist.swift */, + ); + path = Models; + sourceTree = ""; + }; + AC96BAE723256C9300636EF7 /* Extensions */ = { + isa = PBXGroup; + children = ( + AC96BAE823256C9900636EF7 /* Bundle+.swift */, + ACBB0A3F2327E361008656A9 /* String+.swift */, + ); + path = Extensions; + sourceTree = ""; + }; + AC96BAEC232575A800636EF7 /* Helpers */ = { + isa = PBXGroup; + children = ( + AC96BAEA232575A500636EF7 /* CommandLineHandler.swift */, + ); + path = Helpers; + sourceTree = ""; + }; + ACE7B0CB23239B4300A8E2F1 = { + isa = PBXGroup; + children = ( + ACE7B0D723239B4300A8E2F1 /* QuickLookFramework */, + AC96BAD32325095E00636EF7 /* Scripts */, + ACE7B0D623239B4300A8E2F1 /* Products */, + ); + sourceTree = ""; + }; + ACE7B0D623239B4300A8E2F1 /* Products */ = { + isa = PBXGroup; + children = ( + ACE7B0D523239B4300A8E2F1 /* QuickLookFramework.qlgenerator */, + ); + name = Products; + sourceTree = ""; + }; + ACE7B0D723239B4300A8E2F1 /* QuickLookFramework */ = { + isa = PBXGroup; + children = ( + ACE7B0DC23239B4300A8E2F1 /* main.c */, + ACE7B0DA23239B4300A8E2F1 /* GeneratePreviewForURL.m */, + ACE7B0D823239B4300A8E2F1 /* GenerateThumbnailForURL.m */, + ACE7B0DE23239B4300A8E2F1 /* Info.plist */, + AC96BAE723256C9300636EF7 /* Extensions */, + AC96BAEC232575A800636EF7 /* Helpers */, + AC96BAE623256C8900636EF7 /* Models */, + AC96BAE523256C7800636EF7 /* UI */, + ); + path = QuickLookFramework; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + ACE7B0D023239B4300A8E2F1 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + ACE7B0D423239B4300A8E2F1 /* QuickLookFramework */ = { + isa = PBXNativeTarget; + buildConfigurationList = ACE7B0E123239B4300A8E2F1 /* Build configuration list for PBXNativeTarget "QuickLookFramework" */; + buildPhases = ( + ACE7B0D023239B4300A8E2F1 /* Headers */, + ACE7B0D123239B4300A8E2F1 /* Sources */, + ACE7B0D223239B4300A8E2F1 /* Frameworks */, + ACE7B0D323239B4300A8E2F1 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = QuickLookFramework; + productName = QuickLookFramework; + productReference = ACE7B0D523239B4300A8E2F1 /* QuickLookFramework.qlgenerator */; + productType = "com.apple.product-type.bundle"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + ACE7B0CC23239B4300A8E2F1 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1020; + ORGANIZATIONNAME = "Mario Iannotta"; + TargetAttributes = { + AC96BACC232505AC00636EF7 = { + CreatedOnToolsVersion = 10.2; + }; + AC96BAD923250A2600636EF7 = { + CreatedOnToolsVersion = 10.2; + }; + ACE7B0D423239B4300A8E2F1 = { + CreatedOnToolsVersion = 10.2; + LastSwiftMigration = 1020; + }; + }; + }; + buildConfigurationList = ACE7B0CF23239B4300A8E2F1 /* Build configuration list for PBXProject "QuickLookFramework" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = ACE7B0CB23239B4300A8E2F1; + productRefGroup = ACE7B0D623239B4300A8E2F1 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + ACE7B0D423239B4300A8E2F1 /* QuickLookFramework */, + AC96BACC232505AC00636EF7 /* Deploy */, + AC96BAD923250A2600636EF7 /* Run */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + ACE7B0D323239B4300A8E2F1 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + AC96BAE223251CE900636EF7 /* Main.storyboard in Resources */, + AC96BAD72325098500636EF7 /* run.sh in Resources */, + AC96BAD52325096E00636EF7 /* deploy.sh in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + AC96BAD0232505B900636EF7 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "sh \"${SRCROOT}/Scripts/deploy.sh\"\n"; + }; + AC96BADD23250A2A00636EF7 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "sh \"${SRCROOT}/Scripts/run.sh\"\n"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + ACE7B0D123239B4300A8E2F1 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ACE7B0D923239B4300A8E2F1 /* GenerateThumbnailForURL.m in Sources */, + AC96BAEB232575A500636EF7 /* CommandLineHandler.swift in Sources */, + ACBB0A402327E361008656A9 /* String+.swift in Sources */, + AC96BAE423256BF700636EF7 /* FrameworkInfoPlist.swift in Sources */, + AC96BAE023251A8100636EF7 /* PreviewViewController.swift in Sources */, + AC96BAE923256C9900636EF7 /* Bundle+.swift in Sources */, + ACE7B0DB23239B4300A8E2F1 /* GeneratePreviewForURL.m in Sources */, + ACE7B0DD23239B4300A8E2F1 /* main.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + AC96BACD232505AC00636EF7 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = X9253HG4XT; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + AC96BACE232505AC00636EF7 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = X9253HG4XT; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + AC96BADB23250A2600636EF7 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = X9253HG4XT; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + AC96BADC23250A2600636EF7 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = X9253HG4XT; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + ACE7B0DF23239B4300A8E2F1 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "Mac Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + }; + name = Debug; + }; + ACE7B0E023239B4300A8E2F1 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "Mac Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = macosx; + }; + name = Release; + }; + ACE7B0E223239B4300A8E2F1 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + DEVELOPMENT_TEAM = X9253HG4XT; + INFOPLIST_FILE = QuickLookFramework/Info.plist; + INSTALL_PATH = /Library/QuickLook; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@loader_path/../Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.marioiannotta.QuickLookFramework; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + WRAPPER_EXTENSION = qlgenerator; + }; + name = Debug; + }; + ACE7B0E323239B4300A8E2F1 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + DEVELOPMENT_TEAM = X9253HG4XT; + INFOPLIST_FILE = QuickLookFramework/Info.plist; + INSTALL_PATH = /Library/QuickLook; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@loader_path/../Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.marioiannotta.QuickLookFramework; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + WRAPPER_EXTENSION = qlgenerator; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + AC96BACF232505AC00636EF7 /* Build configuration list for PBXAggregateTarget "Deploy" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + AC96BACD232505AC00636EF7 /* Debug */, + AC96BACE232505AC00636EF7 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + AC96BADA23250A2600636EF7 /* Build configuration list for PBXAggregateTarget "Run" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + AC96BADB23250A2600636EF7 /* Debug */, + AC96BADC23250A2600636EF7 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + ACE7B0CF23239B4300A8E2F1 /* Build configuration list for PBXProject "QuickLookFramework" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + ACE7B0DF23239B4300A8E2F1 /* Debug */, + ACE7B0E023239B4300A8E2F1 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + ACE7B0E123239B4300A8E2F1 /* Build configuration list for PBXNativeTarget "QuickLookFramework" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + ACE7B0E223239B4300A8E2F1 /* Debug */, + ACE7B0E323239B4300A8E2F1 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = ACE7B0CC23239B4300A8E2F1 /* Project object */; +} diff --git a/QuickLookFramework.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/QuickLookFramework.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..a6573ac --- /dev/null +++ b/QuickLookFramework.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/QuickLookFramework.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/QuickLookFramework.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/QuickLookFramework.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/QuickLookFramework.xcodeproj/xcshareddata/xcschemes/Deploy.xcscheme b/QuickLookFramework.xcodeproj/xcshareddata/xcschemes/Deploy.xcscheme new file mode 100644 index 0000000..8d812f8 --- /dev/null +++ b/QuickLookFramework.xcodeproj/xcshareddata/xcschemes/Deploy.xcscheme @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/QuickLookFramework.xcodeproj/xcshareddata/xcschemes/QuickLookFramework.xcscheme b/QuickLookFramework.xcodeproj/xcshareddata/xcschemes/QuickLookFramework.xcscheme new file mode 100644 index 0000000..781fb66 --- /dev/null +++ b/QuickLookFramework.xcodeproj/xcshareddata/xcschemes/QuickLookFramework.xcscheme @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/QuickLookFramework.xcodeproj/xcshareddata/xcschemes/Run.xcscheme b/QuickLookFramework.xcodeproj/xcshareddata/xcschemes/Run.xcscheme new file mode 100644 index 0000000..d70061f --- /dev/null +++ b/QuickLookFramework.xcodeproj/xcshareddata/xcschemes/Run.xcscheme @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/QuickLookFramework/Extensions/Bundle+.swift b/QuickLookFramework/Extensions/Bundle+.swift new file mode 100644 index 0000000..58f8b39 --- /dev/null +++ b/QuickLookFramework/Extensions/Bundle+.swift @@ -0,0 +1,13 @@ +// +// Bundle+.swift +// QuickLookFramework +// +// Created by Mario on 08/09/2019. +// Copyright © 2019 Mario Iannotta. All rights reserved. +// + +import Foundation + +extension Bundle { + +} diff --git a/QuickLookFramework/Extensions/String+.swift b/QuickLookFramework/Extensions/String+.swift new file mode 100644 index 0000000..ff3c407 --- /dev/null +++ b/QuickLookFramework/Extensions/String+.swift @@ -0,0 +1,29 @@ +// +// String+.swift +// QuickLookFramework +// +// Created by Mario on 10/09/2019. +// Copyright © 2019 Mario Iannotta. All rights reserved. +// + +import Foundation + +extension String { + + subscript(bounds: CountableClosedRange) -> String { + let start = index(startIndex, offsetBy: bounds.lowerBound) + let end = index(startIndex, offsetBy: bounds.upperBound) + return String(self[start...end]) + } + + subscript(bounds: CountableRange) -> String { + let start = index(startIndex, offsetBy: bounds.lowerBound) + let end = index(startIndex, offsetBy: bounds.upperBound) + return String(self[start.. String { + return String(self[index(startIndex, offsetBy: at)]) + } + +} diff --git a/QuickLookFramework/GeneratePreviewForURL.m b/QuickLookFramework/GeneratePreviewForURL.m new file mode 100644 index 0000000..1edf793 --- /dev/null +++ b/QuickLookFramework/GeneratePreviewForURL.m @@ -0,0 +1,38 @@ +#include +#include +#include +#include +#include +#import "QuickLookFramework-Swift.h" + +OSStatus GeneratePreviewForURL(void *thisInterface, + QLPreviewRequestRef preview, + CFURLRef url, CFStringRef contentTypeUTI, + CFDictionaryRef options); + +void CancelPreviewGeneration(void *thisInterface, QLPreviewRequestRef preview); + +OSStatus GeneratePreviewForURL(void *thisInterface, QLPreviewRequestRef + preview, CFURLRef + url, CFStringRef + contentTypeUTI, + CFDictionaryRef options) { + @autoreleasepool { + NSSize canvasSize = NSMakeSize(600, 600); + CGContextRef cgContext = QLPreviewRequestCreateContext(preview, *(CGSize *)&canvasSize, false, NULL); + if (cgContext) { + NSGraphicsContext* context = [NSGraphicsContext graphicsContextWithCGContext:(void *)cgContext flipped:NO]; + if (context) { + [NSGraphicsContext saveGraphicsState]; + [NSGraphicsContext setCurrentContext:context]; + [PreviewViewController showWithUrl:(__bridge NSURL *)url context:context]; + [NSGraphicsContext restoreGraphicsState]; + } + QLPreviewRequestFlushContext(preview, cgContext); + CFRelease(cgContext); + } + } + return noErr; +} + +void CancelPreviewGeneration(void *thisInterface, QLPreviewRequestRef preview) { } diff --git a/QuickLookFramework/GenerateThumbnailForURL.m b/QuickLookFramework/GenerateThumbnailForURL.m new file mode 100644 index 0000000..bad314d --- /dev/null +++ b/QuickLookFramework/GenerateThumbnailForURL.m @@ -0,0 +1,22 @@ +#include +#include +#include + +OSStatus GenerateThumbnailForURL(void *thisInterface, + QLThumbnailRequestRef thumbnail, + CFURLRef url, CFStringRef + contentTypeUTI, CFDictionaryRef + options, CGSize maxSize); + +void CancelThumbnailGeneration(void *thisInterface, QLThumbnailRequestRef thumbnail); + +OSStatus GenerateThumbnailForURL(void *thisInterface, + QLThumbnailRequestRef thumbnail, + CFURLRef url, + CFStringRef contentTypeUTI, + CFDictionaryRef options, + CGSize maxSize) { + return noErr; +} + +void CancelThumbnailGeneration(void *thisInterface, QLThumbnailRequestRef thumbnail) { } diff --git a/QuickLookFramework/Helpers/CommandLineHandler.swift b/QuickLookFramework/Helpers/CommandLineHandler.swift new file mode 100644 index 0000000..7e59318 --- /dev/null +++ b/QuickLookFramework/Helpers/CommandLineHandler.swift @@ -0,0 +1,85 @@ +// +// CommandLineHandler.swift +// QuickLookFramework +// +// Created by Mario on 08/09/2019. +// Copyright © 2019 Mario Iannotta. All rights reserved. +// + +import Foundation + +struct CommandLineHandler { + + private struct Commands { + let findFile = "cd %@; find . -name %@" + let listArchitectures = "cd %@; lipo -info %@" + let fetchSize = "cd %@; du -hs" + let fetchCreationDate = "cd %@; GetFileInfo -d ." + let fetchModificationDate = "cd %@; GetFileInfo -m ." + } + + init(path: String) { + self.path = path + } + + private let commands = Commands() + private let path: String + + private func executeCommand(_ command: String) -> String { + let task = Process() + task.launchPath = "/bin/bash" + task.arguments = ["-c", command] + let pipe = Pipe() + task.standardOutput = pipe + task.launch() + let data = pipe.fileHandleForReading.readDataToEndOfFile() + return String(data: data, encoding: .utf8)?.droppingFinalCharacter ?? "" + } + + func findFile(named fileName: String) -> [String]? { + let findFile = String(format: commands.findFile, path, fileName) + return executeCommand(findFile).components(separatedBy: .newlines) + } + + func listArchitectures(frameworkName: String) -> [String] { + let listArchitecturesCommand = String(format: commands.listArchitectures, path, frameworkName) + return executeCommand(listArchitecturesCommand) + .components(separatedBy: ": ") + .last? + .components(separatedBy: " ") + .dropLast() ?? [] + } + + func fetchSize() -> String? { + let fetchSizeCommand = String(format: commands.fetchSize, path) + guard + let rawSize = executeCommand(fetchSizeCommand) + .components(separatedBy: "\t") + .first? + .trimmingCharacters(in: .whitespaces), + let rawUnit = rawSize.last.flatMap({ "\($0)B" }) + else { + return nil + } + return [String(rawSize.dropLast()), rawUnit].joined(separator: " ") + } + + func fetchCreationDate() -> String? { + let fetchCreationDateCommand = String(format: commands.fetchCreationDate, path) + return executeCommand(fetchCreationDateCommand) + } + + func fetchModificationDate() -> String? { + let fetchModificationDateCommand = String(format: commands.fetchModificationDate, path) + return executeCommand(fetchModificationDateCommand) + } + +} + +private extension String { + + var droppingFinalCharacter: String? { + return String(dropLast()) + } + +} diff --git a/QuickLookFramework/Info.plist b/QuickLookFramework/Info.plist new file mode 100644 index 0000000..0210d0a --- /dev/null +++ b/QuickLookFramework/Info.plist @@ -0,0 +1,61 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDocumentTypes + + + CFBundleTypeRole + QLGenerator + LSItemContentTypes + + com.apple.framework + + + + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + CFPlugInDynamicRegisterFunction + + CFPlugInDynamicRegistration + NO + CFPlugInFactories + + DE9F6A6E-9EEA-4D1E-BBA5-0ABD4073778F + QuickLookGeneratorPluginFactory + + CFPlugInTypes + + 5E2D9680-5022-40FA-B806-43349622E5B9 + + DE9F6A6E-9EEA-4D1E-BBA5-0ABD4073778F + + + CFPlugInUnloadFunction + + NSHumanReadableCopyright + Copyright © 2019 Mario Iannotta. All rights reserved. + QLNeedsToBeRunInMainThread + + QLPreviewHeight + 600 + QLPreviewWidth + 800 + QLSupportsConcurrentRequests + + QLThumbnailMinimumSize + 17 + + diff --git a/QuickLookFramework/Models/FrameworkInfoPlist.swift b/QuickLookFramework/Models/FrameworkInfoPlist.swift new file mode 100644 index 0000000..fb74f16 --- /dev/null +++ b/QuickLookFramework/Models/FrameworkInfoPlist.swift @@ -0,0 +1,81 @@ +// +// FrameworkInfoPlist.swift +// QuickLookFramework +// +// Created by Mario on 08/09/2019. +// Copyright © 2019 Mario Iannotta. All rights reserved. +// + +import Foundation + +struct FrameworkInfoPlist: Decodable { + + enum CodingKeys: String, CodingKey { + case bundleName = "CFBundleName" + case bundleIdentifier = "CFBundleIdentifier" + case bundleVersionNumber = "CFBundleShortVersionString" + case bundleBuildNumber = "CFBundleVersion" + case platform = "DTPlatformName" + case deviceFamilies = "UIDeviceFamily" + case sdkVersion = "DTSDKName" + case xcodeVersion = "DTXcode" + case minimumOSVersion = "MinimumOSVersion" + } + + enum DeviceFamily: Int, Decodable { + case iPhone = 1 + case iPad = 2 + case tv = 3 + case watch = 4 + + var name: String { + switch self { + case .iPhone: + return "iPhone" + case .iPad: + return "iPad" + case .tv: + return "Apple TV" + case .watch: + return "Apple Watch" + } + } + } + + let bundleName: String? + let bundleIdentifier: String? + private let bundleVersionNumber: String? + private let bundleBuildNumber: String? + let platform: String? + private let deviceFamilies: [DeviceFamily]? + let sdkVersion: String? + let xcodeVersion: String? + let minimumOSVersion: String? + + var bundleVersion: String? { + return [bundleVersionNumber, bundleBuildNumber] + .compactMap { $0 } + .joined(separator: " - Build ") + } + var deviceFamiliesDescription: String? { + return deviceFamilies? + .compactMap { $0.name } + .joined(separator: ", ") + } + + init?(plistURL: URL) { + guard + let data = try? Data(contentsOf: plistURL) + else { + return nil + } + let plistDecoder = PropertyListDecoder() + do { + self = try plistDecoder.decode(FrameworkInfoPlist.self, from: data) + } catch let error { + print(error) + return nil + } + } + +} diff --git a/QuickLookFramework/UI/Main.storyboard b/QuickLookFramework/UI/Main.storyboard new file mode 100644 index 0000000..51349b6 --- /dev/null +++ b/QuickLookFramework/UI/Main.storyboard @@ -0,0 +1,625 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/QuickLookFramework/UI/PreviewViewController.swift b/QuickLookFramework/UI/PreviewViewController.swift new file mode 100644 index 0000000..6874bb4 --- /dev/null +++ b/QuickLookFramework/UI/PreviewViewController.swift @@ -0,0 +1,112 @@ +// +// PreviewViewController.swift +// QuickLookFramework +// +// Created by Mario on 08/09/2019. +// Copyright © 2019 Mario Iannotta. All rights reserved. +// + +import Foundation +import Cocoa + +public class PreviewViewController: NSViewController { + + // MARK: - Factory method + + @objc + public static func show(url: NSURL, context: NSGraphicsContext) { + let storyboard = NSStoryboard(name: "Main", bundle: Bundle(for: self)) + guard + let viewController = storyboard.instantiateInitialController() as? PreviewViewController + else { return } + viewController.url = url as URL + viewController.view.displayIgnoringOpacity(viewController.view.frame, in: context) + } + + // MARK: - IBOutlets + + @IBOutlet private weak var titleTextField: NSTextField! + @IBOutlet private weak var bundleNameTextField: NSTextField! + @IBOutlet private weak var bundleIdentifierTextField: NSTextField! + @IBOutlet private weak var bundleVersionTextField: NSTextField! + @IBOutlet private weak var architecturesTextField: NSTextField! + @IBOutlet private weak var minimumOSVersionTextField: NSTextField! + @IBOutlet private weak var supportedPlatformsTextField: NSTextField! + @IBOutlet private weak var deviceFamilyTextField: NSTextField! + @IBOutlet private weak var sdkTextField: NSTextField! + @IBOutlet private weak var xcodeTextField: NSTextField! + @IBOutlet private weak var sizeTextField: NSTextField! + @IBOutlet private weak var createdDateTextField: NSTextField! + @IBOutlet private weak var modifiedDateTextField: NSTextField! + + // MARK: - Private properties + + private var url: URL? + + public override func viewDidLoad() { + super.viewDidLoad() + guard + let frameworkURL = url, + let frameworkName = frameworkURL + .lastPathComponent + .components(separatedBy: ".framework") + .first + else { return } + + let commandLineHandler = CommandLineHandler(path: frameworkURL.path) + titleTextField.stringValue = frameworkURL.lastPathComponent + sizeTextField.stringValue = commandLineHandler.fetchSize() ?? "-" + createdDateTextField.stringValue = commandLineHandler.fetchCreationDate() ?? "-" + modifiedDateTextField.stringValue = commandLineHandler.fetchModificationDate() ?? "-" + + fillPlistDrivenFields(frameworkURL: frameworkURL, commandLineHandler: commandLineHandler) + + architecturesTextField.stringValue = commandLineHandler + .listArchitectures(frameworkName: frameworkName) + .joined(separator: ", ") + } + + private func fillPlistDrivenFields(frameworkURL: URL, commandLineHandler: CommandLineHandler) { + guard + let plist = commandLineHandler + .findFile(named: "Info.plist")? + .sorted(by: { $0.count < $1.count }) // let's assume that if we have mulitple Info.plist, the right one is the one nearest to the root + .first + .flatMap({ "\($0.dropFirst(2))" }) // remove the first two characters "./" + .flatMap({ frameworkURL.appendingPathComponent($0) }) + .flatMap({ FrameworkInfoPlist(plistURL: $0) }) + else { return } + bundleNameTextField.stringValue = plist.bundleName ?? "-" + bundleIdentifierTextField.stringValue = plist.bundleIdentifier ?? "-" + bundleVersionTextField.stringValue = plist.bundleVersion ?? "-" + minimumOSVersionTextField.stringValue = plist.minimumOSVersion ?? "-" + sdkTextField.stringValue = plist.sdkVersion ?? "-" + xcodeTextField.stringValue = getPrettyXCodeVersion(rawXcodeVersion: plist.xcodeVersion ?? "") ?? "-" + deviceFamilyTextField.stringValue = plist.deviceFamiliesDescription ?? "-" + supportedPlatformsTextField.stringValue = plist.platform ?? "-" + } + + private func getPrettyXCodeVersion(rawXcodeVersion: String) -> String? { + guard + rawXcodeVersion.count == 4 + else { + return nil + } + let major = rawXcodeVersion[0..<2] + let minor = rawXcodeVersion[2] + let patch = rawXcodeVersion[3] + return [major, minor, patch] + .compactMap { value -> Int? in + guard + let valueAsInt = Int(value), + valueAsInt > 0 + else { + return nil + } + return valueAsInt + } + .compactMap { String($0) } + .joined(separator: ".") + } +} + diff --git a/QuickLookFramework/main.c b/QuickLookFramework/main.c new file mode 100644 index 0000000..c4b8f76 --- /dev/null +++ b/QuickLookFramework/main.c @@ -0,0 +1,218 @@ +//============================================================================== +// +// DO NO MODIFY THE CONTENT OF THIS FILE +// +// This file contains the generic CFPlug-in code necessary for your generator +// To complete your generator implement the function in GenerateThumbnailForURL/GeneratePreviewForURL.c +// +//============================================================================== + + + + + + +#include +#include +#include +#include + +// ----------------------------------------------------------------------------- +// constants +// ----------------------------------------------------------------------------- + +// Don't modify this line +#define PLUGIN_ID "407C5198-EF45-425A-BAAD-D6BDB37607AD" + +// +// Below is the generic glue code for all plug-ins. +// +// You should not have to modify this code aside from changing +// names if you decide to change the names defined in the Info.plist +// + + +// ----------------------------------------------------------------------------- +// typedefs +// ----------------------------------------------------------------------------- + +// The thumbnail generation function to be implemented in GenerateThumbnailForURL.c +OSStatus GenerateThumbnailForURL(void *thisInterface, QLThumbnailRequestRef thumbnail, CFURLRef url, CFStringRef contentTypeUTI, CFDictionaryRef options, CGSize maxSize); +void CancelThumbnailGeneration(void* thisInterface, QLThumbnailRequestRef thumbnail); + +// The preview generation function to be implemented in GeneratePreviewForURL.c +OSStatus GeneratePreviewForURL(void *thisInterface, QLPreviewRequestRef preview, CFURLRef url, CFStringRef contentTypeUTI, CFDictionaryRef options); +void CancelPreviewGeneration(void *thisInterface, QLPreviewRequestRef preview); + +// The layout for an instance of QuickLookGeneratorPlugIn +typedef struct __QuickLookGeneratorPluginType +{ + void *conduitInterface; + CFUUIDRef factoryID; + UInt32 refCount; +} QuickLookGeneratorPluginType; + +// ----------------------------------------------------------------------------- +// prototypes +// ----------------------------------------------------------------------------- +// Forward declaration for the IUnknown implementation. +// + +QuickLookGeneratorPluginType *AllocQuickLookGeneratorPluginType(CFUUIDRef inFactoryID); +void DeallocQuickLookGeneratorPluginType(QuickLookGeneratorPluginType *thisInstance); +HRESULT QuickLookGeneratorQueryInterface(void *thisInstance,REFIID iid,LPVOID *ppv); +void *QuickLookGeneratorPluginFactory(CFAllocatorRef allocator,CFUUIDRef typeID); +ULONG QuickLookGeneratorPluginAddRef(void *thisInstance); +ULONG QuickLookGeneratorPluginRelease(void *thisInstance); + +// ----------------------------------------------------------------------------- +// myInterfaceFtbl definition +// ----------------------------------------------------------------------------- +// The QLGeneratorInterfaceStruct function table. +// +static QLGeneratorInterfaceStruct myInterfaceFtbl = { + NULL, + QuickLookGeneratorQueryInterface, + QuickLookGeneratorPluginAddRef, + QuickLookGeneratorPluginRelease, + NULL, + NULL, + NULL, + NULL +}; + + +// ----------------------------------------------------------------------------- +// AllocQuickLookGeneratorPluginType +// ----------------------------------------------------------------------------- +// Utility function that allocates a new instance. +// You can do some initial setup for the generator here if you wish +// like allocating globals etc... +// +QuickLookGeneratorPluginType *AllocQuickLookGeneratorPluginType(CFUUIDRef inFactoryID) +{ + QuickLookGeneratorPluginType *theNewInstance; + + theNewInstance = (QuickLookGeneratorPluginType *)malloc(sizeof(QuickLookGeneratorPluginType)); + memset(theNewInstance,0,sizeof(QuickLookGeneratorPluginType)); + + /* Point to the function table Malloc enough to store the stuff and copy the filler from myInterfaceFtbl over */ + theNewInstance->conduitInterface = malloc(sizeof(QLGeneratorInterfaceStruct)); + memcpy(theNewInstance->conduitInterface,&myInterfaceFtbl,sizeof(QLGeneratorInterfaceStruct)); + + /* Retain and keep an open instance refcount for each factory. */ + theNewInstance->factoryID = CFRetain(inFactoryID); + CFPlugInAddInstanceForFactory(inFactoryID); + + /* This function returns the IUnknown interface so set the refCount to one. */ + theNewInstance->refCount = 1; + return theNewInstance; +} + +// ----------------------------------------------------------------------------- +// DeallocQuickLookGeneratorPluginType +// ----------------------------------------------------------------------------- +// Utility function that deallocates the instance when +// the refCount goes to zero. +// In the current implementation generator interfaces are never deallocated +// but implement this as this might change in the future +// +void DeallocQuickLookGeneratorPluginType(QuickLookGeneratorPluginType *thisInstance) +{ + CFUUIDRef theFactoryID; + + theFactoryID = thisInstance->factoryID; + /* Free the conduitInterface table up */ + free(thisInstance->conduitInterface); + + /* Free the instance structure */ + free(thisInstance); + if (theFactoryID){ + CFPlugInRemoveInstanceForFactory(theFactoryID); + CFRelease(theFactoryID); + } +} + +// ----------------------------------------------------------------------------- +// QuickLookGeneratorQueryInterface +// ----------------------------------------------------------------------------- +// Implementation of the IUnknown QueryInterface function. +// +HRESULT QuickLookGeneratorQueryInterface(void *thisInstance,REFIID iid,LPVOID *ppv) +{ + CFUUIDRef interfaceID; + + interfaceID = CFUUIDCreateFromUUIDBytes(kCFAllocatorDefault,iid); + + if (CFEqual(interfaceID,kQLGeneratorCallbacksInterfaceID)){ + /* If the Right interface was requested, bump the ref count, + * set the ppv parameter equal to the instance, and + * return good status. + */ + ((QLGeneratorInterfaceStruct *)((QuickLookGeneratorPluginType *)thisInstance)->conduitInterface)->GenerateThumbnailForURL = GenerateThumbnailForURL; + ((QLGeneratorInterfaceStruct *)((QuickLookGeneratorPluginType *)thisInstance)->conduitInterface)->CancelThumbnailGeneration = CancelThumbnailGeneration; + ((QLGeneratorInterfaceStruct *)((QuickLookGeneratorPluginType *)thisInstance)->conduitInterface)->GeneratePreviewForURL = GeneratePreviewForURL; + ((QLGeneratorInterfaceStruct *)((QuickLookGeneratorPluginType *)thisInstance)->conduitInterface)->CancelPreviewGeneration = CancelPreviewGeneration; + ((QLGeneratorInterfaceStruct *)((QuickLookGeneratorPluginType*)thisInstance)->conduitInterface)->AddRef(thisInstance); + *ppv = thisInstance; + CFRelease(interfaceID); + return S_OK; + }else{ + /* Requested interface unknown, bail with error. */ + *ppv = NULL; + CFRelease(interfaceID); + return E_NOINTERFACE; + } +} + +// ----------------------------------------------------------------------------- +// QuickLookGeneratorPluginAddRef +// ----------------------------------------------------------------------------- +// Implementation of reference counting for this type. Whenever an interface +// is requested, bump the refCount for the instance. NOTE: returning the +// refcount is a convention but is not required so don't rely on it. +// +ULONG QuickLookGeneratorPluginAddRef(void *thisInstance) +{ + ((QuickLookGeneratorPluginType *)thisInstance )->refCount += 1; + return ((QuickLookGeneratorPluginType*) thisInstance)->refCount; +} + +// ----------------------------------------------------------------------------- +// QuickLookGeneratorPluginRelease +// ----------------------------------------------------------------------------- +// When an interface is released, decrement the refCount. +// If the refCount goes to zero, deallocate the instance. +// +ULONG QuickLookGeneratorPluginRelease(void *thisInstance) +{ + ((QuickLookGeneratorPluginType*)thisInstance)->refCount -= 1; + if (((QuickLookGeneratorPluginType*)thisInstance)->refCount == 0){ + DeallocQuickLookGeneratorPluginType((QuickLookGeneratorPluginType*)thisInstance ); + return 0; + }else{ + return ((QuickLookGeneratorPluginType*) thisInstance )->refCount; + } +} + +// ----------------------------------------------------------------------------- +// QuickLookGeneratorPluginFactory +// ----------------------------------------------------------------------------- +void *QuickLookGeneratorPluginFactory(CFAllocatorRef allocator,CFUUIDRef typeID) +{ + QuickLookGeneratorPluginType *result; + CFUUIDRef uuid; + + /* If correct type is being requested, allocate an + * instance of kQLGeneratorTypeID and return the IUnknown interface. + */ + if (CFEqual(typeID,kQLGeneratorTypeID)){ + uuid = CFUUIDCreateFromString(kCFAllocatorDefault,CFSTR(PLUGIN_ID)); + result = AllocQuickLookGeneratorPluginType(uuid); + CFRelease(uuid); + return result; + } + /* If the requested type is incorrect, return NULL. */ + return NULL; +} + diff --git a/Scripts/deploy.sh b/Scripts/deploy.sh new file mode 100644 index 0000000..f86cdb7 --- /dev/null +++ b/Scripts/deploy.sh @@ -0,0 +1,5 @@ +xcodebuild -target QuickLookFramework +rm -r ~/Library/QuickLook/QuickLookFramework.qlgenerator +cp -r "${SRCROOT}/build/Release/QuickLookFramework.qlgenerator" ~/Library/QuickLook +rm -r "${SRCROOT}/build/" +killall quicklookd || true diff --git a/Scripts/run.sh b/Scripts/run.sh new file mode 100644 index 0000000..442c149 --- /dev/null +++ b/Scripts/run.sh @@ -0,0 +1,2 @@ +sh "${SRCROOT}/Scripts/deploy.sh" +qlmanage -p ~/Desktop/Nomosi.framework