diff --git a/shell_integration/MacOSX/OwnCloudFinder/FinishedIconCache.h b/shell_integration/MacOSX/OwnCloudFinder/FinishedIconCache.h new file mode 100644 index 000000000..031b1e339 --- /dev/null +++ b/shell_integration/MacOSX/OwnCloudFinder/FinishedIconCache.h @@ -0,0 +1,24 @@ +// +// FinishedIconCache.h +// OwnCloudFinder +// +// Created by Markus Goetz on 01/10/14. +// +// + +#import +#import + +@interface FinishedIconCache : NSObject { + NSCache *_cache; + long long _hits; + long long _misses; +} + ++ (FinishedIconCache*)sharedInstance; + +- (NSImage*)getIcon:(NSString*)fileName overlayIconIndex:(int)idx width:(float)w height:(float)h; +- (void)registerIcon:(NSImage*)icon withFileName:(NSString*)fileName overlayIconIndex:(int)idx width:(float)w height:(float)h; + + +@end diff --git a/shell_integration/MacOSX/OwnCloudFinder/FinishedIconCache.m b/shell_integration/MacOSX/OwnCloudFinder/FinishedIconCache.m new file mode 100644 index 000000000..bce2f61f7 --- /dev/null +++ b/shell_integration/MacOSX/OwnCloudFinder/FinishedIconCache.m @@ -0,0 +1,83 @@ +// +// FinishedIconCache.m +// OwnCloudFinder +// +// Created by Markus Goetz on 01/10/14. +// +// + +#import "FinishedIconCache.h" + + +@interface FinishedIconCacheItem : NSObject +@property (nonatomic, retain) NSImage *icon; +@property (nonatomic) NSTimeInterval maxAge; +@end + +@implementation FinishedIconCacheItem +@synthesize icon; +@synthesize maxAge; +- (void)dealloc { + NSLog(@"RELEASE %@ %@", self, self.icon); + [self.icon release]; + [super dealloc]; +} +@end + +@implementation FinishedIconCache + +static FinishedIconCache* sharedInstance = nil; + +- init +{ + self = [super init]; + if (self) + { + _cache = [[NSCache alloc] init]; + _cache.totalCostLimit = (2880 * 1800); // mbp15 screen size + _hits = 0; + _misses = 0; + } + return self; +} + ++ (FinishedIconCache*)sharedInstance +{ + @synchronized(self) + { + if (sharedInstance == nil) + { + sharedInstance = [[self alloc] init]; + } + } + return sharedInstance; +} + + +- (NSImage*)getIcon:(NSString*)fileName overlayIconIndex:(int)idx width:(float)w height:(float)h +{ + NSString *cacheKey = [NSString stringWithFormat:@"%@--%d--%f%f", fileName, idx, w,h]; + FinishedIconCacheItem *item = [_cache objectForKey:cacheKey]; + if (item) { + if (item.maxAge > [[[NSDate alloc] init] timeIntervalSinceReferenceDate]) { + _hits++; + return item.icon; + } + } + _misses++; + return NULL; +} + +- (void)registerIcon:(NSImage*)icon withFileName:(NSString*)fileName overlayIconIndex:(int)idx width:(float)w height:(float)h +{ + NSString *cacheKey = [NSString stringWithFormat:@"%@--%d--%f%f", fileName, idx, w, h]; + FinishedIconCacheItem *item = [[FinishedIconCacheItem alloc] init]; + item.icon = icon; + // max age between 1 sec and 5 sec + item.maxAge = [[[NSDate alloc] init] timeIntervalSinceReferenceDate] + 1.0 + 4.0*((double)arc4random() / 0x100000000); + [_cache setObject:item forKey:cacheKey cost:w*h]; + [item release]; + //NSLog(@"CACHE hit/miss ratio: %f", (float)_hits/(float)_misses); +} + +@end diff --git a/shell_integration/MacOSX/OwnCloudFinder/IconOverlayHandlers.m b/shell_integration/MacOSX/OwnCloudFinder/IconOverlayHandlers.m index d51cea9a9..d856c8b9c 100644 --- a/shell_integration/MacOSX/OwnCloudFinder/IconOverlayHandlers.m +++ b/shell_integration/MacOSX/OwnCloudFinder/IconOverlayHandlers.m @@ -15,6 +15,7 @@ #import #import "ContentManager.h" #import "IconCache.h" +#import "FinishedIconCache.h" #import "IconOverlayHandlers.h" #import "Finder/Finder.h" @@ -69,7 +70,6 @@ NSURL* url = [node previewItemURL]; - NSError *error; BOOL isDir; if ([[NSFileManager defaultManager] fileExistsAtPath:[url path] isDirectory:&isDir] == NO) { NSLog(@"ERROR: Could not determine file type of %@", [url path]); @@ -83,15 +83,26 @@ { NSImage* icon = [arg1 _nsImage]; - [icon lockFocus]; - - CGContextRef myContext = [[NSGraphicsContext currentContext] graphicsPort]; + // Use the short term icon cache that possibly has the finished icon + FinishedIconCache *finishedIconCache = [FinishedIconCache sharedInstance]; + NSImage *finishedImage = [finishedIconCache getIcon:[url path] overlayIconIndex:imageIndex width:[icon size].width height:[icon size].height]; + if (finishedImage) { + //NSLog(@"X Got finished image from cache %@ %@", finishedImage, [url path]); + return [[[IKImageWrapper alloc] initWithNSImage:finishedImage] autorelease];; + } else { + //NSLog(@"X Need to redraw %@", [url path]); + } NSImage* iconimage = [[IconCache sharedInstance] getIcon:[NSNumber numberWithInt:[imageIndex intValue]]]; if (iconimage != nil) { + [icon lockFocus]; + + CGContextRef myContext = [[NSGraphicsContext currentContext] graphicsPort]; + CGRect destRect = CGRectMake(0, 0, [icon size].width, [icon size].height); + CGImageRef cgImage = [iconimage CGImageForProposedRect:&destRect context:[NSGraphicsContext currentContext] hints:nil]; @@ -103,9 +114,11 @@ NSLog(@"No image given!!!!!11 %@", [url path]); } + [icon unlockFocus]; } - [icon unlockFocus]; + // Insert into cache + [finishedIconCache registerIcon:icon withFileName:[url path] overlayIconIndex:imageIndex width:[icon size].width height:[icon size].height]; return [[[IKImageWrapper alloc] initWithNSImage:icon] autorelease]; } diff --git a/shell_integration/MacOSX/OwnCloudFinder/OwnCloudFinder.xcodeproj/project.pbxproj b/shell_integration/MacOSX/OwnCloudFinder/OwnCloudFinder.xcodeproj/project.pbxproj index 32f8851c5..1cbda1c71 100644 --- a/shell_integration/MacOSX/OwnCloudFinder/OwnCloudFinder.xcodeproj/project.pbxproj +++ b/shell_integration/MacOSX/OwnCloudFinder/OwnCloudFinder.xcodeproj/project.pbxproj @@ -10,6 +10,7 @@ 0B13ECAE173C687400548DA1 /* GCDAsyncSocket.m in Sources */ = {isa = PBXBuildFile; fileRef = 0B13ECAD173C686A00548DA1 /* GCDAsyncSocket.m */; settings = {COMPILER_FLAGS = "-fobjc-arc"; }; }; 0B13ECAF173C687900548DA1 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0BFC9ACB173C57E400CDD329 /* Security.framework */; }; 0BFAF21C16F8E6C10017EA7E /* JSONKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 0BFAF21B16F8E6C10017EA7E /* JSONKit.m */; }; + 5BB74A8719DBF9BB001BAAAC /* FinishedIconCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 5BB74A8619DBF9BB001BAAAC /* FinishedIconCache.m */; }; 692C18A516660C4700BF6A53 /* ContextMenuHandlers.m in Sources */ = {isa = PBXBuildFile; fileRef = 692C18A416660C4600BF6A53 /* ContextMenuHandlers.m */; }; 692C18A9166617F500BF6A53 /* IconOverlayHandlers.m in Sources */ = {isa = PBXBuildFile; fileRef = 692C18A8166617F500BF6A53 /* IconOverlayHandlers.m */; }; 692C18AC1666392700BF6A53 /* MenuManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 692C18AB1666392700BF6A53 /* MenuManager.m */; }; @@ -32,6 +33,8 @@ 0BFAF21A16F8E6C10017EA7E /* JSONKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSONKit.h; sourceTree = ""; }; 0BFAF21B16F8E6C10017EA7E /* JSONKit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JSONKit.m; sourceTree = ""; }; 0BFC9ACB173C57E400CDD329 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; + 5BB74A8519DBF9BB001BAAAC /* FinishedIconCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FinishedIconCache.h; sourceTree = ""; }; + 5BB74A8619DBF9BB001BAAAC /* FinishedIconCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FinishedIconCache.m; sourceTree = ""; }; 692C18A316660C4600BF6A53 /* ContextMenuHandlers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ContextMenuHandlers.h; sourceTree = ""; }; 692C18A416660C4600BF6A53 /* ContextMenuHandlers.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ContextMenuHandlers.m; sourceTree = ""; }; 692C18A7166617F500BF6A53 /* IconOverlayHandlers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IconOverlayHandlers.h; sourceTree = ""; }; @@ -117,6 +120,8 @@ 69948B351636D50E0093B6CE /* ContentManager.m */, 8C99F6921622D145002D2135 /* IconCache.h */, 8C99F6931622D145002D2135 /* IconCache.m */, + 5BB74A8519DBF9BB001BAAAC /* FinishedIconCache.h */, + 5BB74A8619DBF9BB001BAAAC /* FinishedIconCache.m */, 692C18AA1666392700BF6A53 /* MenuManager.h */, 692C18AB1666392700BF6A53 /* MenuManager.m */, ); @@ -226,6 +231,7 @@ 8C99F6941622D145002D2135 /* IconCache.m in Sources */, 69948B361636D50E0093B6CE /* ContentManager.m in Sources */, 6993878616494C000044E4DF /* RequestManager.m in Sources */, + 5BB74A8719DBF9BB001BAAAC /* FinishedIconCache.m in Sources */, 692C18A516660C4700BF6A53 /* ContextMenuHandlers.m in Sources */, 692C18A9166617F500BF6A53 /* IconOverlayHandlers.m in Sources */, 692C18AC1666392700BF6A53 /* MenuManager.m in Sources */,