1 | #import "transmission.h" |
---|
2 | #import "NSStringAdditions.h" |
---|
3 | |
---|
4 | OSStatus GeneratePreviewForURL(void *thisInterface, QLPreviewRequestRef preview, CFURLRef url, CFStringRef contentTypeUTI, CFDictionaryRef options); |
---|
5 | void CancelPreviewGeneration(void *thisInterface, QLPreviewRequestRef preview); |
---|
6 | |
---|
7 | NSString * generateIconData(NSString * fileExtension, NSUInteger width, NSMutableDictionary * allImgProps) |
---|
8 | { |
---|
9 | NSString * rawFilename = ![fileExtension isEqualToString: @""] ? fileExtension : @"blank_file_name_transmission"; |
---|
10 | NSString * iconFileName = [NSString stringWithFormat: @"%ldx%@.tiff", width, rawFilename]; //we need to do this once per file extension, per size |
---|
11 | |
---|
12 | if (![allImgProps objectForKey: iconFileName]) |
---|
13 | { |
---|
14 | NSImage * icon = [[NSWorkspace sharedWorkspace] iconForFileType: fileExtension]; |
---|
15 | |
---|
16 | const NSRect iconFrame = NSMakeRect(0.0, 0.0, width, width); |
---|
17 | NSImage * renderedIcon = [[NSImage alloc] initWithSize: iconFrame.size]; |
---|
18 | [renderedIcon lockFocus]; |
---|
19 | [icon drawInRect: iconFrame fromRect: NSZeroRect operation: NSCompositeCopy fraction: 1.0]; |
---|
20 | [renderedIcon unlockFocus]; |
---|
21 | |
---|
22 | NSData * iconData = [renderedIcon TIFFRepresentation]; |
---|
23 | [renderedIcon release]; |
---|
24 | |
---|
25 | NSDictionary * imgProps = @{ |
---|
26 | (NSString *)kQLPreviewPropertyMIMETypeKey : @"image/png", |
---|
27 | (NSString *)kQLPreviewPropertyAttachmentDataKey : iconData }; |
---|
28 | [allImgProps setObject: imgProps forKey: iconFileName]; |
---|
29 | } |
---|
30 | |
---|
31 | return [@"cid:" stringByAppendingString: iconFileName]; |
---|
32 | } |
---|
33 | |
---|
34 | OSStatus GeneratePreviewForURL(void *thisInterface, QLPreviewRequestRef preview, CFURLRef url, CFStringRef contentTypeUTI, CFDictionaryRef options) |
---|
35 | { |
---|
36 | // Before proceeding make sure the user didn't cancel the request |
---|
37 | if (QLPreviewRequestIsCancelled(preview)) |
---|
38 | return noErr; |
---|
39 | |
---|
40 | //try to parse the torrent file |
---|
41 | tr_info inf; |
---|
42 | tr_ctor * ctor = tr_ctorNew(NULL); |
---|
43 | tr_ctorSetMetainfoFromFile(ctor, [[(NSURL *)url path] UTF8String]); |
---|
44 | const int err = tr_torrentParse(ctor, &inf); |
---|
45 | tr_ctorFree(ctor); |
---|
46 | if (err) |
---|
47 | return noErr; |
---|
48 | |
---|
49 | NSURL * styleURL = [[NSBundle bundleWithIdentifier: @"org.m0k.transmission.QuickLookPlugin"] URLForResource: @"style" withExtension: @"css"]; |
---|
50 | NSString * styleContents = [NSString stringWithContentsOfURL: styleURL encoding: NSUTF8StringEncoding error: NULL]; |
---|
51 | |
---|
52 | NSMutableString * htmlString = [NSMutableString string]; |
---|
53 | [htmlString appendFormat: @"<html><style type=\"text/css\">%@</style><body>", styleContents]; |
---|
54 | |
---|
55 | NSMutableDictionary * allImgProps = [NSMutableDictionary dictionary]; |
---|
56 | |
---|
57 | NSString * name = [NSString stringWithUTF8String: inf.name]; |
---|
58 | NSString * fileTypeString = inf.isMultifile ? NSFileTypeForHFSTypeCode(kGenericFolderIcon) : [name pathExtension]; |
---|
59 | |
---|
60 | const NSUInteger width = 32; |
---|
61 | [htmlString appendFormat: @"<h2><img class=\"icon\" src=\"%@\" width=\"%ld\" height=\"%ld\">%@</h2>", generateIconData(fileTypeString, width, allImgProps), width, width, name]; |
---|
62 | |
---|
63 | NSString * fileSizeString = [NSString stringForFileSize: inf.totalSize]; |
---|
64 | if (inf.isMultifile) |
---|
65 | { |
---|
66 | NSString * fileCountString; |
---|
67 | if (inf.fileCount == 1) |
---|
68 | fileCountString = NSLocalizedString(@"1 file", "quicklook file count"); |
---|
69 | else |
---|
70 | fileCountString= [NSString stringWithFormat: NSLocalizedString(@"%@ files", "quicklook file count"), [NSString formattedUInteger: inf.fileCount]]; |
---|
71 | fileSizeString = [NSString stringWithFormat: @"%@, %@", fileCountString, fileSizeString]; |
---|
72 | } |
---|
73 | [htmlString appendFormat: @"<p>%@</p>", fileSizeString]; |
---|
74 | |
---|
75 | NSString * dateCreatedString = inf.dateCreated > 0 ? [NSDateFormatter localizedStringFromDate: [NSDate dateWithTimeIntervalSince1970: inf.dateCreated] dateStyle: NSDateFormatterLongStyle timeStyle: NSDateFormatterShortStyle] : nil; |
---|
76 | NSString * creatorString = inf.creator ? [NSString stringWithUTF8String: inf.creator] : nil; |
---|
77 | if ([creatorString isEqualToString: @""]) creatorString = nil; |
---|
78 | NSString * creationString = nil; |
---|
79 | if (dateCreatedString && creatorString) |
---|
80 | creationString = [NSString stringWithFormat: NSLocalizedString(@"Created on %@ with %@", "quicklook creation info"), dateCreatedString, creatorString]; |
---|
81 | else if (dateCreatedString) |
---|
82 | creationString = [NSString stringWithFormat: NSLocalizedString(@"Created on %@", "quicklook creation info"), dateCreatedString]; |
---|
83 | else if (creatorString) |
---|
84 | creationString = [NSString stringWithFormat: NSLocalizedString(@"Created with %@", "quicklook creation info"), creatorString]; |
---|
85 | if (creationString) |
---|
86 | [htmlString appendFormat: @"<p>%@</p>", creationString]; |
---|
87 | |
---|
88 | if (inf.comment) |
---|
89 | { |
---|
90 | NSString * comment = [NSString stringWithUTF8String: inf.comment]; |
---|
91 | if (![comment isEqualToString: @""]) |
---|
92 | [htmlString appendFormat: @"<p>%@</p>", comment]; |
---|
93 | } |
---|
94 | |
---|
95 | [htmlString appendString: @"<hr/>"]; |
---|
96 | |
---|
97 | if (inf.webseedCount > 0) |
---|
98 | { |
---|
99 | [htmlString appendString: @"<br><br><table>"]; |
---|
100 | |
---|
101 | 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]]; |
---|
102 | [htmlString appendFormat: @"<tr><th>%@</th></tr>", headerTitleString]; |
---|
103 | |
---|
104 | for (int i = 0; i < inf.webseedCount; ++i) |
---|
105 | [htmlString appendFormat: @"<tr><td>%s<td></tr>", inf.webseeds[i]]; |
---|
106 | |
---|
107 | [htmlString appendString:@"</table>"]; |
---|
108 | } |
---|
109 | |
---|
110 | if (inf.trackerCount > 0) |
---|
111 | { |
---|
112 | [htmlString appendString: @"<br><br><table>"]; |
---|
113 | |
---|
114 | NSString * headerTitleString = inf.trackerCount == 1 ? NSLocalizedString(@"1 Tracker", "quicklook tracker header") : [NSString stringWithFormat: NSLocalizedString(@"%@ Trackers", "quicklook tracker header"), [NSString formattedUInteger: inf.trackerCount]]; |
---|
115 | [htmlString appendFormat: @"<tr><th>%@</th></tr>", headerTitleString]; |
---|
116 | |
---|
117 | #warning handle tiers? |
---|
118 | for (int i = 0; i < inf.trackerCount; ++i) |
---|
119 | [htmlString appendFormat: @"<tr><td>%s<td></tr>", inf.trackers[i].announce]; |
---|
120 | |
---|
121 | [htmlString appendString:@"</table>"]; |
---|
122 | } |
---|
123 | |
---|
124 | if (inf.isMultifile) |
---|
125 | { |
---|
126 | [htmlString appendString: @"<br><br><table>"]; |
---|
127 | |
---|
128 | NSString * fileTitleString = inf.fileCount == 1 ? NSLocalizedString(@"1 File", "quicklook file header") : [NSString stringWithFormat: NSLocalizedString(@"%@ Files", "quicklook file header"), [NSString formattedUInteger: inf.fileCount]]; |
---|
129 | [htmlString appendFormat: @"<tr><th>%@</th></tr>", fileTitleString]; |
---|
130 | |
---|
131 | #warning display size? |
---|
132 | #warning display folders? |
---|
133 | for (int i = 0; i < inf.fileCount; ++i) |
---|
134 | { |
---|
135 | NSString * fullFilePath = [NSString stringWithUTF8String: inf.files[i].name]; |
---|
136 | NSCAssert([fullFilePath hasPrefix: [name stringByAppendingString: @"/"]], @"Expected file path %@ to begin with %@/", fullFilePath, name); |
---|
137 | |
---|
138 | NSString * shortenedFilePath = [fullFilePath substringFromIndex: [name length]+1]; |
---|
139 | |
---|
140 | const NSUInteger width = 16; |
---|
141 | [htmlString appendFormat: @"<tr><td><img class=\"icon\" src=\"%@\" width=\"%ld\" height=\"%ld\">%@<td></tr>", generateIconData([shortenedFilePath pathExtension], width, allImgProps), width, width, shortenedFilePath]; |
---|
142 | } |
---|
143 | |
---|
144 | [htmlString appendString:@"</table>"]; |
---|
145 | } |
---|
146 | |
---|
147 | [htmlString appendString: @"</body></html>"]; |
---|
148 | |
---|
149 | tr_metainfoFree(&inf); |
---|
150 | |
---|
151 | NSDictionary * props = @{ (NSString *)kQLPreviewPropertyTextEncodingNameKey : @"UTF-8", |
---|
152 | (NSString *)kQLPreviewPropertyMIMETypeKey : @"text/html", |
---|
153 | (NSString *)kQLPreviewPropertyAttachmentsKey : allImgProps }; |
---|
154 | |
---|
155 | QLPreviewRequestSetDataRepresentation(preview, (CFDataRef)[htmlString dataUsingEncoding: NSUTF8StringEncoding], kUTTypeHTML, (CFDictionaryRef)props); |
---|
156 | |
---|
157 | return noErr; |
---|
158 | } |
---|
159 | |
---|
160 | void CancelPreviewGeneration(void *thisInterface, QLPreviewRequestRef preview) |
---|
161 | { |
---|
162 | // Implement only if supported |
---|
163 | } |
---|