OS X用のQuick Lookプラグインの開発

クイックルックは、サムネイル(アイコン)とプレビュー(Finderでスペースバーを押してファイルの説明/内容を表示するウィンドウ)を作成するOS Xのアプリケーションです。 サポートされていないものについては、QLプラグインをインストールできます-アイコンジェネレーターおよび/またはプレビュー。 これらのフォーマットは.qlgenerator



で、 ~/Library/QuickLook



および/Library/QuickLook



に配置されます。



iOS、場合によってはOSXでアプリケーションを作成します。 最初の.mobileprovision



- Provisioningのプラグインを見たときに、サードパーティのQuickLookジェネレーターに.mobileprovision





.mobileprovision/.provisionprofile



デバイスのインストールが承認された証明書、iOSおよびOSXアプリケーションを展開するためのいくつかのパラメーターを含むプロファイル。



これは、Quick Lookプラグインなしでプロファイルフォルダーがどのように見えるかです。



TestFlightを使用してアプリケーションを自動的にデプロイするスクリプトでプロファイルを使用する場合など、プロファイルを直接選択する必要があります。 どのアプリケーションをどのプロファイルにするかを理解することは完全に不可能です。



まず、オープンソースのProvisioningを使用し始め、次に閉じましたが、より美しく詳細なipaqlを使用しましたipaqlの作成者がシステムがリリースされてからわずか6か月でOS X Mavericksとの互換性を追加し、アイコンの表示がまだ修正されていないため、オープンソリューションを作成する必要が生じました。



これが私が得たものです-ProvisionQLです。

アイコンとプレビューを作成するためにサポートされているファイルの種類:







猫の下で、Quick Lookプラグインを作成するときの基本的な手順について説明します。



プロジェクトのセットアップ



Xcodeで、新規プロジェクトを作成します:ファイル>新規>プロジェクト... OS X>システムプラグイン>クイックルックプラグイン。 基本的なテンプレートで、Info.plistを編集します。



CFBundleDocumentTypesを展開し、目的のファイルタイプをLSItemContentTypes配列に追加します。 リストとテーブルにアイコンを生成するために、QLThumbnailMinimumSizeを17から16に変更しました。QLPreviewHeightとQLPreviewWidthに注意してください-ジェネレーターがプレビューを生成する時間が長すぎる場合にのみ使用されます。 ipaの場合、zipアーカイブからいくつかのファイルを抽出する必要があります。これは非常に長い時間(0.06から0.12秒)です-私の場合、システムはplistの値を使用します。 ジェネレーターがすぐにプレビューを提供する場合、システムは提供する画像またはHTMLからウィンドウのサイズを変更します。



さらに、obj-cおよびFoundationクラスを好む場合は、 GenerateThumbnailForURL.c GeneratePreviewForURL.c



名前をGenerateThumbnailForURL.c GeneratePreviewForURL.c



に変更して、ヘッダーに追加してください。

 #import <Foundation/Foundation.h> #import <Cocoa/Cocoa.h>
      
      







なぜなら アイコン(GenerateThumbnailForURL)とプレビューウィンドウ(GeneratePreviewForURL)の両方を生成する必要があります-Shared.h / mの一般的なインクルード/インポートと機能を強調しました。 Shared.hを持ち込みます:

 #include <CoreFoundation/CoreFoundation.h> #include <CoreServices/CoreServices.h> #include <QuickLook/QuickLook.h> #import <Foundation/Foundation.h> #import <Cocoa/Cocoa.h> #import <Security/Security.h> #import <NSBezierPath+IOS7RoundedRect.h> static NSString * const kPluginBundleId = @"com.FerretSyndicate.ProvisionQL"; static NSString * const kDataType_ipa = @"com.apple.itunes.ipa"; static NSString * const kDataType_app = @"com.apple.application-bundle"; static NSString * const kDataType_ios_provision = @"com.apple.mobileprovision"; static NSString * const kDataType_ios_provision_old = @"com.apple.iphone.mobileprovision"; static NSString * const kDataType_osx_provision = @"com.apple.provisionprofile"; #define SIGNED_CODE 0 NSImage *roundCorners(NSImage *image); NSImage *imageFromApp(NSURL *URL, NSString *dataType, NSString *fileName); NSString *mainIconNameForApp(NSDictionary *appPropertyList); int expirationStatus(NSDate *date, NSCalendar *calendar);
      
      





ProvisionQLプロジェクトの最終構造:





NSBezierPath + IOS7RoundedRect-iOS7の丸いアイコンを正方形から切り取る機能。

Install.sh-プロジェクトのビルド時にジェネレーターを自動インストールするためのスクリプト:

 #!/bin/sh PRODUCT="${PRODUCT_NAME}.qlgenerator" QL_PATH=~/Library/QuickLook/ rm -rf "$QL_PATH/$PRODUCT" test -d "$QL_PATH" || mkdir -p "$QL_PATH" && cp -R "$BUILT_PRODUCTS_DIR/$PRODUCT" "$QL_PATH" qlmanage -r echo "$PRODUCT installed in $QL_PATH"
      
      





それを実行するには、ターゲット設定に移動し、メニューからエディター>ビルドフェーズの追加>実行スクリプトビルドフェーズの追加を選択し、プロジェクトフォルダー内のスクリプトへのパスを入力します。





プラグインのデバッグも必要になる場合があります。 なぜなら それ自体は実行可能ファイルではありません-プロジェクトスキーム設定に移動する必要があります-スキームの編集...>実行>情報>実行可能ファイル>その他> Cmd + Shft + G> / usr / bin /> Go> qlmanage:





次に、[引数]タブで、開始引数に-t



フラグ(アイコンのデバッグ用)または-p



(プレビューのデバッグ用)を指定し、テストファイルへのフルパスを指定します(私の場合、.ipaでアイコンレンダリングをテストしています)。





アイコン生成



この例では、事前に準備されたアイコン( defaultIcon.png )を表示する方法を示します。 ProvisionQLは、ipaファイルからのアイコン選択を実装し、デバイスの数とプロビジョニングのアクションステータス(期限切れかどうか)を表示します。



完成したGenerateThumbnailForURL.m



次のとおりです。

 #import "Shared.h" OSStatus GenerateThumbnailForURL(void *thisInterface, QLThumbnailRequestRef thumbnail, CFURLRef url, CFStringRef contentTypeUTI, CFDictionaryRef options, CGSize maxSize); void CancelThumbnailGeneration(void *thisInterface, QLThumbnailRequestRef thumbnail); /* ----------------------------------------------------------------------------- Generate a thumbnail for file This function's job is to create thumbnail for designated file as fast as possible ----------------------------------------------------------------------------- */ OSStatus GenerateThumbnailForURL(void *thisInterface, QLThumbnailRequestRef thumbnail, CFURLRef url, CFStringRef contentTypeUTI, CFDictionaryRef options, CGSize maxSize) { @autoreleasepool { NSString *dataType = (__bridge NSString *)contentTypeUTI; NSImage *appIcon; if([dataType isEqualToString:kDataType_app] || [dataType isEqualToString:kDataType_ipa]) { NSURL *iconURL = [[NSBundle bundleWithIdentifier:kPluginBundleId] URLForResource:@"defaultIcon" withExtension:@"png"]; appIcon = [[NSImage alloc] initWithContentsOfURL:iconURL]; } else { return noErr; } if (QLThumbnailRequestIsCancelled(thumbnail)) { return noErr; } NSSize canvasSize = appIcon.size; NSRect renderRect = NSMakeRect(0.0, 0.0, appIcon.size.width, appIcon.size.height); CGContextRef _context = QLThumbnailRequestCreateContext(thumbnail, canvasSize, false, NULL); if (_context) { NSGraphicsContext* _graphicsContext = [NSGraphicsContext graphicsContextWithGraphicsPort:(void *)_context flipped:NO]; [NSGraphicsContext setCurrentContext:_graphicsContext]; [appIcon drawInRect:renderRect]; //draw anything you want here QLThumbnailRequestFlushContext(thumbnail, _context); CFRelease(_context); } } return noErr; } void CancelThumbnailGeneration(void *thisInterface, QLThumbnailRequestRef thumbnail) { // Implement only if supported }
      
      





いくつかの点に注意する必要があります。





プレビュー生成



この例では、HTMLをプレビューとして取り込み、表示する方法を見ていきます。

最初にテンプレートtemplate.htmlを準備する必要があります(デザインのスタイルを含めることもできます)。

 <!DOCTYPE html> <html lang="en"> <body> <div> <h1>App info</h1> Name: <strong>__CFBundleDisplayName__</strong><br /> Version: __CFBundleShortVersionString__ (__CFBundleVersion__)<br /> BundleId: __CFBundleIdentifier__<br /> </div> </body> </html>
      
      





__KEY__



が選択されているものはすべて、ジェネレータから入力されます。



最終的なGeneratePreviewForURL.m



をもたらします。

 #import "Shared.h" OSStatus GeneratePreviewForURL(void *thisInterface, QLPreviewRequestRef preview, CFURLRef url, CFStringRef contentTypeUTI, CFDictionaryRef options); void CancelPreviewGeneration(void *thisInterface, QLPreviewRequestRef preview); /* ----------------------------------------------------------------------------- Generate a preview for file This function's job is to create preview for designated file ----------------------------------------------------------------------------- */ OSStatus GeneratePreviewForURL(void *thisInterface, QLPreviewRequestRef preview, CFURLRef url, CFStringRef contentTypeUTI, CFDictionaryRef options) { @autoreleasepool { NSURL *URL = (__bridge NSURL *)url; NSString *dataType = (__bridge NSString *)contentTypeUTI; NSData *appPlist = nil; if([dataType isEqualToString:kDataType_app]) { // get the embedded plist for the iOS app appPlist = [NSData dataWithContentsOfURL:[URL URLByAppendingPathComponent:@"Info.plist"]]; } else if([dataType isEqualToString:kDataType_ipa]) { // get the embedded plist from an app archive using: unzip -p <URL> <files to unzip> (piped to standart output) NSTask *unzipTask = [NSTask new]; [unzipTask setLaunchPath:@"/usr/bin/unzip"]; [unzipTask setStandardOutput:[NSPipe pipe]]; [unzipTask setArguments:@[@"-p", [URL path], @"Payload/*.app/Info.plist"]]; [unzipTask launch]; [unzipTask waitUntilExit]; appPlist = [[[unzipTask standardOutput] fileHandleForReading] readDataToEndOfFile]; } else { return noErr; } if(QLPreviewRequestIsCancelled(preview)) { return noErr; } NSMutableDictionary *synthesizedInfo = [NSMutableDictionary dictionary]; NSURL *htmlURL = [[NSBundle bundleWithIdentifier:kPluginBundleId] URLForResource:@"template" withExtension:@"html"]; NSMutableString *html = [NSMutableString stringWithContentsOfURL:htmlURL encoding:NSUTF8StringEncoding error:NULL]; NSDictionary *appPropertyList = [NSPropertyListSerialization propertyListWithData:appPlist options:0 format:NULL error:NULL]; [synthesizedInfo setObject:[appPropertyList objectForKey:@"CFBundleDisplayName"] forKey:@"CFBundleDisplayName"]; [synthesizedInfo setObject:[appPropertyList objectForKey:@"CFBundleIdentifier"] forKey:@"CFBundleIdentifier"]; [synthesizedInfo setObject:[appPropertyList objectForKey:@"CFBundleShortVersionString"] forKey:@"CFBundleShortVersionString"]; [synthesizedInfo setObject:[appPropertyList objectForKey:@"CFBundleVersion"] forKey:@"CFBundleVersion"]; for (NSString *key in [synthesizedInfo allKeys]) { NSString *replacementValue = [synthesizedInfo objectForKey:key]; NSString *replacementToken = [NSString stringWithFormat:@"__%@__", key]; [html replaceOccurrencesOfString:replacementToken withString:replacementValue options:0 range:NSMakeRange(0, [html length])]; } NSDictionary *properties = @{ // properties for the HTML data (__bridge NSString *)kQLPreviewPropertyTextEncodingNameKey : @"UTF-8", (__bridge NSString *)kQLPreviewPropertyMIMETypeKey : @"text/html" }; QLPreviewRequestSetDataRepresentation(preview, (__bridge CFDataRef)[html dataUsingEncoding:NSUTF8StringEncoding], kUTTypeHTML, (__bridge CFDictionaryRef)properties); } return noErr; } void CancelPreviewGeneration(void *thisInterface, QLPreviewRequestRef preview) { // Implement only if supported }
      
      







ご覧のとおり、まずInfo.plistを開いて(またはアーカイブから抽出します)、それからデータをsynthesizedInfo



保存します。 syntheticInfoのすべてのキーは、 template.html



からロードされた行に応じsynthesizedInfo



設定されます。 結果の文字列は、返されたデータ型をHTMLとして記述するパラメーターとともにqlmanageに返されます。



おわりに



このガイドによれば、独自の形式またはシステムが標準的に検出しない一般的な形式のアイコンをすばやく表示および生成するためのプラグインをすばやく作成できます。



ProvisionQLについては、プラグインタスクの一部として機能を改善するための提案やプールリクエストを喜んでいます。



All Articles