#import "transmission.h" #import "NSStringAdditions.h" OSStatus GeneratePreviewForURL(void *thisInterface, QLPreviewRequestRef preview, CFURLRef url, CFStringRef contentTypeUTI, CFDictionaryRef options); void CancelPreviewGeneration(void *thisInterface, QLPreviewRequestRef preview); NSString * generateIconData(NSString * fileExtension, NSUInteger width, NSMutableDictionary * allImgProps) { NSString * rawFilename = ![fileExtension isEqualToString: @""] ? fileExtension : @"blank_file_name_transmission"; NSString * iconFileName = [NSString stringWithFormat: @"%ldx%@.tiff", width, rawFilename]; //we need to do this once per file extension, per size if (!allImgProps[iconFileName]) { NSImage * icon = [[NSWorkspace sharedWorkspace] iconForFileType: fileExtension]; const NSRect iconFrame = NSMakeRect(0.0, 0.0, width, width); NSImage * renderedIcon = [[NSImage alloc] initWithSize: iconFrame.size]; [renderedIcon lockFocus]; [icon drawInRect: iconFrame fromRect: NSZeroRect operation: NSCompositeCopy fraction: 1.0]; [renderedIcon unlockFocus]; NSData * iconData = [renderedIcon TIFFRepresentation]; [renderedIcon release]; NSDictionary * imgProps = @{ (NSString *)kQLPreviewPropertyMIMETypeKey : @"image/png", (NSString *)kQLPreviewPropertyAttachmentDataKey : iconData }; [allImgProps setObject: imgProps forKey: iconFileName]; } return [@"cid:" stringByAppendingString: iconFileName]; } OSStatus GeneratePreviewForURL(void *thisInterface, QLPreviewRequestRef preview, CFURLRef url, CFStringRef contentTypeUTI, CFDictionaryRef options) { // Before proceeding make sure the user didn't cancel the request if (QLPreviewRequestIsCancelled(preview)) return noErr; //try to parse the torrent file tr_info inf; tr_ctor * ctor = tr_ctorNew(NULL); tr_ctorSetMetainfoFromFile(ctor, [[(NSURL *)url path] UTF8String]); const int err = tr_torrentParse(ctor, &inf); tr_ctorFree(ctor); if (err) return noErr; NSURL * styleURL = [[NSBundle bundleWithIdentifier: @"org.m0k.transmission.QuickLookPlugin"] URLForResource: @"style" withExtension: @"css"]; NSString * styleContents = [NSString stringWithContentsOfURL: styleURL encoding: NSUTF8StringEncoding error: NULL]; NSMutableString * htmlString = [NSMutableString string]; [htmlString appendFormat: @"", styleContents]; NSMutableDictionary * allImgProps = [NSMutableDictionary dictionary]; NSString * name = [NSString stringWithUTF8String: inf.name]; NSString * fileTypeString = inf.isMultifile ? NSFileTypeForHFSTypeCode(kGenericFolderIcon) : [name pathExtension]; const NSUInteger width = 32; [htmlString appendFormat: @"

%@

", generateIconData(fileTypeString, width, allImgProps), width, width, name]; NSString * fileSizeString = [NSString stringForFileSize: inf.totalSize]; if (inf.isMultifile) { NSString * fileCountString; if (inf.fileCount == 1) fileCountString = NSLocalizedString(@"1 file", "quicklook file count"); else fileCountString= [NSString stringWithFormat: NSLocalizedString(@"%@ files", "quicklook file count"), [NSString formattedUInteger: inf.fileCount]]; fileSizeString = [NSString stringWithFormat: @"%@, %@", fileCountString, fileSizeString]; } [htmlString appendFormat: @"

%@

", fileSizeString]; if (inf.comment) { NSString * comment = [NSString stringWithUTF8String: inf.comment]; if (![comment isEqualToString: @""]) [htmlString appendFormat: @"

%@

", comment]; } [htmlString appendString: @"
"]; if (inf.webseedCount > 0) { [htmlString appendString: @"

"]; NSString * headerTitleString = inf.webseedCount == 1 ? NSLocalizedString(@"1 Web Seed", "quicklook web seed header") : [NSString stringWithFormat: NSLocalizedString(@"%@ Web Seeds", "quicklook web seed header"), [NSString formattedUInteger: inf.webseedCount]]; [htmlString appendFormat: @"", headerTitleString]; for (int i = 0; i < inf.webseedCount; ++i) [htmlString appendFormat: @"", inf.webseeds[i]]; [htmlString appendString:@"
%@
%s
"]; } if (inf.trackerCount > 0) { [htmlString appendString: @"

"]; NSString * headerTitleString = inf.trackerCount == 1 ? NSLocalizedString(@"1 Tracker", "quicklook tracker header") : [NSString stringWithFormat: NSLocalizedString(@"%@ Trackers", "quicklook tracker header"), [NSString formattedUInteger: inf.trackerCount]]; [htmlString appendFormat: @"", headerTitleString]; #warning handle tiers? for (int i = 0; i < inf.trackerCount; ++i) [htmlString appendFormat: @"", inf.trackers[i].announce]; [htmlString appendString:@"
%@
%s
"]; } if (inf.isMultifile) { [htmlString appendString: @"

"]; NSString * fileTitleString = inf.fileCount == 1 ? NSLocalizedString(@"1 File", "quicklook file header") : [NSString stringWithFormat: NSLocalizedString(@"%@ Files", "quicklook file header"), [NSString formattedUInteger: inf.fileCount]]; [htmlString appendFormat: @"", fileTitleString]; #warning display size? #warning display folders? for (int i = 0; i < inf.fileCount; ++i) { NSString * fullFilePath = [NSString stringWithUTF8String: inf.files[i].name]; NSCAssert([fullFilePath hasPrefix: [name stringByAppendingString: @"/"]], @"Expected file path %@ to begin with %@/", fullFilePath, name); NSString * shortenedFilePath = [fullFilePath substringFromIndex: [name length]+1]; const NSUInteger width = 16; [htmlString appendFormat: @"", generateIconData([shortenedFilePath pathExtension], width, allImgProps), width, width, shortenedFilePath]; } [htmlString appendString:@"
%@
%@
"]; } [htmlString appendString: @""]; tr_metainfoFree(&inf); NSDictionary * props = @{ (NSString *)kQLPreviewPropertyTextEncodingNameKey : @"UTF-8", (NSString *)kQLPreviewPropertyMIMETypeKey : @"text/html", (NSString *)kQLPreviewPropertyAttachmentsKey : allImgProps }; QLPreviewRequestSetDataRepresentation(preview, (CFDataRef)[htmlString dataUsingEncoding: NSUTF8StringEncoding], kUTTypeHTML, (CFDictionaryRef)props); return noErr; } void CancelPreviewGeneration(void *thisInterface, QLPreviewRequestRef preview) { // Implement only if supported }