As one approach for providing thumbnail and preview data to Quick Look, the application can store that data as part of the document data. The generator can then access it and return it to Quick Look in a call to QLThumbnailRequestSetImageWithData
or QLPreviewRequestSetDataRepresentation
. This approach permits a quick response time for the generator, but at the expense of a larger document file.
To illustrate how your generator might provide previews and thumbnails using this approach, the following listings show modifications to the code for the Sketch application that writes a thumbnail image as part of the document data. “Sketch example project: adding a thumbnail property” shows how you might define a property of the NSDocument
subclass to hold the image data.
Listing 7-1 Sketch example project: adding a thumbnail property
@interface SKTDrawDocument : NSDocument { |
@private |
NSMutableArray *_graphics; |
// ...other instance variables here... |
NSData *_thumbnail; |
} |
// ...existing methods here... |
- (NSData *)thumbnail; |
Implement the thumbnail
accessor method to return the thumbnail image. To the the NSDocument
method that prepares the document data for writing out to a file (dataOfType:error:
) are added the lines of code in “Sketch example project: including the thumbnail with the document data” indicated by the “new” labels.
Listing 7-2 Sketch example project: including the thumbnail with the document data
static NSString *SKTThumbnailImageKey = @"SketchThumbnail"; // new |
- (NSData *)dataOfType:(NSString *)typeName error:(NSError **)outError { |
NSData *data,; |
NSArray *graphics = [self graphics]; |
NSPrintInfo *printInfo = [self printInfo]; |
NSWorkspace *workspace = [NSWorkspace sharedWorkspace]; |
BOOL useTypeConformance = [workspace respondsToSelector:@selector(type:conformsToType:)]; |
if ((useTypeConformance && [workspace type:SKTDrawDocumentNewTypeName conformsToType:typeName]) || [typeName isEqualToString:SKTDrawDocumentOldTypeName]) { |
NSData *tiffRep; // new |
NSMutableDictionary *properties = [NSMutableDictionary dictionary]; |
[properties setObject:[NSNumber numberWithInt:SKTDrawDocumentCurrentVersion] forKey:SKTDrawDocumentVersionKey]; |
[properties setObject:[SKTGraphic propertiesWithGraphics:graphics] forKey:SKTDrawDocumentGraphicsKey]; |
[properties setObject:[NSArchiver archivedDataWithRootObject:printInfo] forKey:SKTDrawDocumentPrintInfoKey]; |
tiffRep = [self TIFFDataWithGraphics:graphics error:outError]; // new |
[properties setObject:tiffRep forKey:SKTThumbnailImageKey]; // new |
data = [NSPropertyListSerialization dataFromPropertyList:properties format:NSPropertyListBinaryFormat_v1_0 errorDescription:NULL]; |
} else if ((useTypeConformance && [workspace type:(NSString *)kUTTypePDF conformsToType:typeName]) || [typeName isEqualToString:NSPDFPboardType]) { |
data = [SKTRenderingView pdfDataWithGraphics:graphics]; |
} else { |
NSParameterAssert((useTypeConformance && [workspace type:(NSString *)kUTTypeTIFF conformsToType:typeName]) || [typeName isEqualToString:NSTIFFPboardType]); |
data = [SKTRenderingView tiffDataWithGraphics:graphics error:outError]; |
} |
return data; |
} |
In the corresponding NSDocument
method for reading document data back in (readFromData:ofType:error:
) “unpack” the thumbnail from the dictionary of document properties:
_thumbnail = [[properties objectForKey:SKTThumbnailImageKey] retain]; |
Now implementing the generator for Sketch is a simple matter of accessing the thumbnail image data and passing it to Quick Look in a call to QLThumbnailRequestSetImageWithData
, as shown in “Returning the stored thumbnail image to Quick Look.” (For previews, the corresponding function is QLPreviewRequestSetDataRepresentation
.)
Listing 7-3 Returning the stored thumbnail image to Quick Look
OSStatus GenerateThumbnailForURL(void *thisInterface, QLThumbnailRequestRef thumbnail, CFURLRef url, CFStringRef contentTypeUTI, CFDictionaryRef options, CGSize maxSize) |
{ |
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; |
SKTDrawDocument* document = [[[SKTDrawDocument alloc] init] autorelease]; |
if(![document readFromURL:(NSURL *)url ofType:(NSString *)contentTypeUTI]) { |
[pool release]; |
return noErr; |
} |
if ([document respondsToSelector:@selector(thumbnail)]) { // runtime verification |
NSData *tiffData = [document thumbnail]; |
if (tiffData != nil) { |
NSDictionary *props = [NSDictionary dictionaryWithObject:@"public.tiff" forKey:(NSString *)kCGImageSourceTypeIdentifierHint]; |
QLThumbnailRequestSetImageWithData(thumbnail, (CFDataRef)tiffData, (CFDictionaryRef)props); |
[pool release]; |
return noErr; |
} |
} |
NSSize canvasSize = [document canvasSize]; |
CGContextRef cgContext = QLThumbnailRequestCreateContext(thumbnail, *(CGSize *)&canvasSize, false, NULL); |
if(cgContext) { |
NSGraphicsContext* context = [NSGraphicsContext graphicsContextWithGraphicsPort:(void *)cgContext flipped:YES]; |
if(context) { |
[document drawDocumentInContext:context]; |
} |
QLThumbnailRequestFlushContext(thumbnail, cgContext); |
CFRelease(cgContext); |
} |
[pool release]; |
return noErr; |
} |
In the call to QLThumbnailRequestSetImageWithData
, the generator indicates the image format to Quick Look with the kCGImageSourceTypeIdentifierHint
property. Note that this example checks whether the class of the document object implements the thumbnail
accessor method (to exclude prior versions of the application) and, if so, it checks whether thumbnail data is returned. If it isn’t, it draws the thumbnail image in a Quick Look–provided graphics context.
Last updated: 2009-07-20