• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/ap/gpl/transmission/transmission-2.73/macosx/QuickLookPlugin/
1#import "transmission.h"
2#import "NSStringAdditions.h"
3
4OSStatus GeneratePreviewForURL(void *thisInterface, QLPreviewRequestRef preview, CFURLRef url, CFStringRef contentTypeUTI, CFDictionaryRef options);
5void CancelPreviewGeneration(void *thisInterface, QLPreviewRequestRef preview);
6
7NSString * 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
34OSStatus 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    //we need this call to ensure NSApp is initialized (not done automatically for plugins)
41    [NSApplication sharedApplication];
42    
43    //try to parse the torrent file
44    tr_info inf;
45    tr_ctor * ctor = tr_ctorNew(NULL);
46    tr_ctorSetMetainfoFromFile(ctor, [[(NSURL *)url path] UTF8String]);
47    const int err = tr_torrentParse(ctor, &inf);
48    tr_ctorFree(ctor);
49    if (err)
50        return noErr;
51    
52    NSBundle * bundle = [NSBundle bundleWithIdentifier: @"org.m0k.transmission.QuickLookPlugin"];
53    
54    NSURL * styleURL = [bundle URLForResource: @"style" withExtension: @"css"];
55    NSString * styleContents = [NSString stringWithContentsOfURL: styleURL encoding: NSUTF8StringEncoding error: NULL];
56    
57    NSMutableString * htmlString = [NSMutableString string];
58    [htmlString appendFormat: @"<html><style type=\"text/css\">%@</style><body>", styleContents];
59    
60    NSMutableDictionary * allImgProps = [NSMutableDictionary dictionary];
61    
62    NSString * name = [NSString stringWithUTF8String: inf.name];
63    NSString * fileTypeString = inf.isMultifile ? NSFileTypeForHFSTypeCode(kGenericFolderIcon) : [name pathExtension];
64    
65    const NSUInteger width = 32;
66    [htmlString appendFormat: @"<h2><img class=\"icon\" src=\"%@\" width=\"%ld\" height=\"%ld\" />%@</h2>", generateIconData(fileTypeString, width, allImgProps), width, width, name];
67    
68    NSString * fileSizeString = [NSString stringForFileSize: inf.totalSize];
69    if (inf.isMultifile)
70    {
71        NSString * fileCountString;
72        if (inf.fileCount == 1)
73            fileCountString = NSLocalizedStringFromTableInBundle(@"1 file", nil, bundle, "quicklook file count");
74        else
75            fileCountString= [NSString stringWithFormat: NSLocalizedStringFromTableInBundle(@"%@ files", nil, bundle, "quicklook file count"), [NSString formattedUInteger: inf.fileCount]];
76        fileSizeString = [NSString stringWithFormat: @"%@, %@", fileCountString, fileSizeString];
77    }
78    [htmlString appendFormat: @"<p>%@</p>", fileSizeString];
79    
80    NSString * dateCreatedString = inf.dateCreated > 0 ? [NSDateFormatter localizedStringFromDate: [NSDate dateWithTimeIntervalSince1970: inf.dateCreated] dateStyle: NSDateFormatterLongStyle timeStyle: NSDateFormatterShortStyle] : nil;
81    NSString * creatorString = inf.creator ? [NSString stringWithUTF8String: inf.creator] : nil;
82    if ([creatorString isEqualToString: @""]) creatorString = nil;
83    NSString * creationString = nil;
84    if (dateCreatedString && creatorString)
85        creationString = [NSString stringWithFormat: NSLocalizedStringFromTableInBundle(@"Created on %@ with %@", nil, bundle, "quicklook creation info"), dateCreatedString, creatorString];
86    else if (dateCreatedString)
87        creationString = [NSString stringWithFormat: NSLocalizedStringFromTableInBundle(@"Created on %@", nil, bundle, "quicklook creation info"), dateCreatedString];
88    else if (creatorString)
89        creationString = [NSString stringWithFormat: NSLocalizedStringFromTableInBundle(@"Created with %@", nil, bundle, "quicklook creation info"), creatorString];
90    if (creationString)
91        [htmlString appendFormat: @"<p>%@</p>", creationString];
92    
93    if (inf.comment)
94    {
95        NSString * comment = [NSString stringWithUTF8String: inf.comment];
96        if (![comment isEqualToString: @""])
97            [htmlString appendFormat: @"<p>%@</p>", comment];
98    }
99    
100    NSMutableArray * lists = [NSMutableArray array];
101    
102    if (inf.webseedCount > 0)
103    {
104        NSMutableString * listSection = [NSMutableString string];
105        [listSection appendString: @"<table>"];
106        
107        NSString * headerTitleString = inf.webseedCount == 1 ? NSLocalizedStringFromTableInBundle(@"1 Web Seed", nil, bundle, "quicklook web seed header") : [NSString stringWithFormat: NSLocalizedStringFromTableInBundle(@"%@ Web Seeds", nil, bundle, "quicklook web seed header"), [NSString formattedUInteger: inf.webseedCount]];
108        [listSection appendFormat: @"<tr><th>%@</th></tr>", headerTitleString];
109        
110        for (int i = 0; i < inf.webseedCount; ++i)
111            [listSection appendFormat: @"<tr><td>%s<td></tr>", inf.webseeds[i]];
112        
113        [listSection appendString:@"</table>"];
114        
115        [lists addObject: listSection];
116    }
117    
118    if (inf.trackerCount > 0)
119    {
120        NSMutableString * listSection = [NSMutableString string];
121        [listSection appendString: @"<table>"];
122        
123        NSString * headerTitleString = inf.trackerCount == 1 ? NSLocalizedStringFromTableInBundle(@"1 Tracker", nil, bundle, "quicklook tracker header") : [NSString stringWithFormat: NSLocalizedStringFromTableInBundle(@"%@ Trackers", nil, bundle, "quicklook tracker header"), [NSString formattedUInteger: inf.trackerCount]];
124        [listSection appendFormat: @"<tr><th>%@</th></tr>", headerTitleString];
125        
126#warning handle tiers?
127        for (int i = 0; i < inf.trackerCount; ++i)
128            [listSection appendFormat: @"<tr><td>%s<td></tr>", inf.trackers[i].announce];
129        
130        [listSection appendString:@"</table>"];
131        
132        [lists addObject: listSection];
133    }
134    
135    if (inf.isMultifile)
136    {
137        NSMutableString * listSection = [NSMutableString string];
138        [listSection appendString: @"<table>"];
139        
140        NSString * fileTitleString = inf.fileCount == 1 ? NSLocalizedStringFromTableInBundle(@"1 File", nil, bundle, "quicklook file header") : [NSString stringWithFormat: NSLocalizedStringFromTableInBundle(@"%@ Files", nil, bundle, "quicklook file header"), [NSString formattedUInteger: inf.fileCount]];
141        [listSection appendFormat: @"<tr><th>%@</th></tr>", fileTitleString];
142        
143#warning display size?
144#warning display folders?
145        for (int i = 0; i < inf.fileCount; ++i)
146        {
147            NSString * fullFilePath = [NSString stringWithUTF8String: inf.files[i].name];
148            NSCAssert([fullFilePath hasPrefix: [name stringByAppendingString: @"/"]], @"Expected file path %@ to begin with %@/", fullFilePath, name);
149            
150            NSString * shortenedFilePath = [fullFilePath substringFromIndex: [name length]+1];
151            
152            const NSUInteger width = 16;
153            [listSection appendFormat: @"<tr><td><img class=\"icon\" src=\"%@\" width=\"%ld\" height=\"%ld\" />%@<td></tr>", generateIconData([shortenedFilePath pathExtension], width, allImgProps), width, width, shortenedFilePath];
154        }
155        
156        [listSection appendString:@"</table>"];
157        
158        [lists addObject: listSection];
159    }
160    
161    if ([lists count] > 0)
162        [htmlString appendFormat: @"<hr/><br>%@", [lists componentsJoinedByString: @"<br>"]];
163    
164    [htmlString appendString: @"</body></html>"];
165    
166    tr_metainfoFree(&inf);
167    
168    NSDictionary * props = @{ (NSString *)kQLPreviewPropertyTextEncodingNameKey : @"UTF-8",
169                                (NSString *)kQLPreviewPropertyMIMETypeKey : @"text/html",
170                                (NSString *)kQLPreviewPropertyAttachmentsKey : allImgProps };
171    
172    QLPreviewRequestSetDataRepresentation(preview, (CFDataRef)[htmlString dataUsingEncoding: NSUTF8StringEncoding], kUTTypeHTML, (CFDictionaryRef)props);
173    
174    return noErr;
175}
176
177void CancelPreviewGeneration(void *thisInterface, QLPreviewRequestRef preview)
178{
179    // Implement only if supported
180}
181