Skip to content

Commit

Permalink
Merge pull request #1970 from quicksilver/i1957
Browse files Browse the repository at this point in the history
keep NSBundle calls on a single thread
  • Loading branch information
pjrobertson committed Nov 13, 2014
2 parents 7d7f803 + 133d750 commit d10a283
Show file tree
Hide file tree
Showing 2 changed files with 126 additions and 123 deletions.
9 changes: 3 additions & 6 deletions Quicksilver/Code-QuickStepCore/QSResourceManager.h
@@ -1,18 +1,15 @@




#import <Foundation/Foundation.h>

extern id QSRez;

@interface QSResourceManager : NSObject {
NSMutableDictionary *resourceDict;
QSThreadSafeMutableDictionary *resourceDict;
NSString *resourceOverrideFolder;
NSDictionary *resourceOverrideList;
dispatch_queue_t resourceQueue;
}

+ (id)sharedInstance;
+ (instancetype)sharedInstance;
+ (NSImage *)imageNamed:(NSString *)name;
+ (NSImage *)imageNamed:(NSString *)name inBundle:(NSBundle *)bundle;
- (NSImage *)imageNamed:(NSString *)name;
Expand Down
240 changes: 123 additions & 117 deletions Quicksilver/Code-QuickStepCore/QSResourceManager.m
@@ -1,14 +1,15 @@
#import "QSResourceManager.h"
#import "QSRegistry.h"
#import "QSLocalization.h"
#import "QSGCD.h"

#define gSysIconBundle @"/System/Library/CoreServices/CoreTypes.bundle"

QSResourceManager * QSRez;

@implementation QSResourceManager

+ (id)sharedInstance {
+ (instancetype)sharedInstance {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
QSRez = [[self alloc] init];
Expand All @@ -26,7 +27,9 @@ + (NSImage *)imageNamed:(NSString *)name inBundle:(NSBundle *)bundle {

- (id)init {
if (self = [super init]) {
resourceDict = [NSMutableDictionary dictionaryWithContentsOfFile: [[NSBundle mainBundle] pathForResource:@"ResourceLocations" ofType:@"plist"]];
NSMutableDictionary *locations = [NSMutableDictionary dictionaryWithContentsOfFile: [[NSBundle mainBundle] pathForResource:@"ResourceLocations" ofType:@"plist"]];
resourceDict = [[QSThreadSafeMutableDictionary alloc] init];
[resourceDict setDictionary:locations];

resourceOverrideList = nil;

Expand All @@ -38,13 +41,16 @@ - (id)init {
} else {
resourceOverrideFolder = nil;
}

resourceQueue = dispatch_queue_create("QSResourceManagerQueue", DISPATCH_QUEUE_SERIAL);
}
return self;
}

- (NSImage *)sysIconNamed:(NSString *)name {
NSString *path = [[NSBundle bundleWithPath:gSysIconBundle] pathForResource:name ofType:@"icns"];
__block NSString *path;
QSGCDQueueSync(resourceQueue, ^{
path = [[NSBundle bundleWithPath:gSysIconBundle] pathForResource:name ofType:@"icns"];
});
if (!path) return nil;
return [[NSImage alloc] initByReferencingFile:path];
}
Expand All @@ -55,91 +61,88 @@ - (NSString *)pathForImageNamed:(NSString *)name {
}

- (NSImage *)imageWithExactName:(NSString *)name {
@synchronized(self) {
NSImage *image = [NSImage imageNamed:name];
if (!image && resourceOverrideList) {
NSString *file = [resourceOverrideList objectForKey:name];
if (file)
image = [[NSImage alloc] initByReferencingFile:[resourceOverrideFolder stringByAppendingPathComponent:file]];
[image setName:name];

}
NSImage *image = [NSImage imageNamed:name];
if (!image && resourceOverrideList) {
NSString *file = [resourceOverrideList objectForKey:name];
if (file)
image = [[NSImage alloc] initByReferencingFile:[resourceOverrideFolder stringByAppendingPathComponent:file]];
[image setName:name];

id locator = [resourceDict objectForKey:name];
if ([locator isKindOfClass:[NSNull class]]) return nil;
if (locator)
image = [self imageWithLocatorInformation:locator];
return image;
}

id locator = [resourceDict objectForKey:name];
if ([locator isKindOfClass:[NSNull class]]) return nil;
if (locator)
image = [self imageWithLocatorInformation:locator];
return image;
}

- (NSImage *)imageNamed:(NSString *)name {
return [self imageNamed:name inBundle:nil];
}

- (NSImage *)imageNamed:(NSString *)name inBundle:(NSBundle *)bundle {
@synchronized(self) {
if (!name) {
return nil;
}

NSImage *image = [NSImage imageNamed:name];
if (image) {
return image;
}

if (!image && resourceOverrideList) {
NSString *file = [resourceOverrideList objectForKey:name];
if (file) {
image = [[NSImage alloc] initByReferencingFile:[resourceOverrideFolder stringByAppendingPathComponent:file]];
}
[image setName:name];
if (!name) {
return nil;
}

__block NSImage *image = [NSImage imageNamed:name];
if (image) {
return image;
}

if (!image && resourceOverrideList) {
NSString *file = [resourceOverrideList objectForKey:name];
if (file) {
image = [[NSImage alloc] initByReferencingFile:[resourceOverrideFolder stringByAppendingPathComponent:file]];
}

[image setName:name];
}

QSGCDQueueSync(resourceQueue, ^{
if (!image && bundle) { image = [bundle imageNamed:name]; }

if (image) { return image; }

id locator = [resourceDict objectForKey:name];
if ([locator isKindOfClass:[NSNull class]]) { return nil; }
if (locator) {
image = [self imageWithLocatorInformation:locator];
} else if (!image && ([name hasPrefix:@"/"] || [name hasPrefix:@"~"])) { // !!! Andre Berg 20091007: Try iconForFile first if name looks like ordinary path
NSString *path = [name stringByStandardizingPath];
if ([[NSImage imageUnfilteredFileTypes] containsObject:[path pathExtension]]) {
image = [[NSImage alloc] initByReferencingFile:path];
} else {
image = [[NSWorkspace sharedWorkspace] iconForFile:path];
}
} else {// Try the systemicons bundle
image = [self sysIconNamed:name];
if (!image) { // Try by bundle id
image = [self imageWithLocatorInformation:[NSDictionary dictionaryWithObjectsAndKeys:name, @"bundle", nil]];
}
}
if (!image && [locator isKindOfClass:[NSString class]]) {
image = [self imageNamed:locator];
});

if (image) { return image; }

id locator = [resourceDict objectForKey:name];
if ([locator isKindOfClass:[NSNull class]]) { return nil; }
if (locator) {
image = [self imageWithLocatorInformation:locator];
} else if (!image && ([name hasPrefix:@"/"] || [name hasPrefix:@"~"])) { // !!! Andre Berg 20091007: Try iconForFile first if name looks like ordinary path
NSString *path = [name stringByStandardizingPath];
if ([[NSImage imageUnfilteredFileTypes] containsObject:[path pathExtension]]) {
image = [[NSImage alloc] initByReferencingFile:path];
} else {
image = [[NSWorkspace sharedWorkspace] iconForFile:path];
}

if(!image) {
SEL selector = NSSelectorFromString([NSString stringWithFormat:@"%@Image", name]);
if ([self respondsToSelector:selector]) {
image = ((NSImage* (*)(id, SEL))[self methodForSelector:selector])(self, selector);
}
} else {// Try the systemicons bundle
image = [self sysIconNamed:name];
if (!image) { // Try by bundle id
image = [self imageWithLocatorInformation:[NSDictionary dictionaryWithObjectsAndKeys:name, @"bundle", nil]];
}

if (!image) {
[resourceDict setObject:[NSNull null] forKey:name];
} else {
[image setName:name];
}
if (!image && [locator isKindOfClass:[NSString class]]) {
image = [self imageNamed:locator];
}

if(!image) {
SEL selector = NSSelectorFromString([NSString stringWithFormat:@"%@Image", name]);
if ([self respondsToSelector:selector]) {
image = ((NSImage* (*)(id, SEL))[self methodForSelector:selector])(self, selector);
}
return image;
}

if (!image) {
[resourceDict setObject:[NSNull null] forKey:name];
} else {
[image setName:name];
}
return image;
}

- (NSString *)pathWithLocatorInformation:(id)locator {
@synchronized(self) {
NSString *path = nil;
__block NSString *path = nil;
if ([locator isKindOfClass:[NSString class]]) {
if (![locator length]) return nil;
if ([locator hasPrefix:@"["]) {
Expand All @@ -159,34 +162,34 @@ - (NSString *)pathWithLocatorInformation:(id)locator {
if (path) break;
}
} else if ([locator isKindOfClass:[NSDictionary class]]) {
NSWorkspace *workspace = [NSWorkspace sharedWorkspace];
NSString *bundleID = [locator objectForKey:@"bundle"];
NSBundle *bundle = [QSReg bundleWithIdentifier:bundleID];
if (!bundle)
bundle = [NSBundle bundleWithPath:[workspace absolutePathForAppBundleWithIdentifier:bundleID]];

NSString *resourceName = [locator objectForKey:@"resource"];
// NSString *type = [locator objectForKey:@"type"];
NSString *subPath = [locator objectForKey:@"path"];

NSString *basePath = [bundle bundlePath];
// NSString *basePath = [workspace absolutePathForAppBundleWithIdentifier:bundle];
// NSLog(@"loc %@ %@", locator, path);

if (resourceName) {
path = [bundle pathForResource:[resourceName stringByDeletingPathExtension]
ofType:[resourceName pathExtension]];
} else if (subPath) {
path = [basePath stringByAppendingPathComponent:subPath]; ;
}

QSGCDQueueSync(resourceQueue, ^{
NSWorkspace *workspace = [NSWorkspace sharedWorkspace];
NSString *bundleID = [locator objectForKey:@"bundle"];
NSBundle *bundle = [QSReg bundleWithIdentifier:bundleID];
if (!bundle)
bundle = [NSBundle bundleWithPath:[workspace absolutePathForAppBundleWithIdentifier:bundleID]];

NSString *resourceName = [locator objectForKey:@"resource"];
// NSString *type = [locator objectForKey:@"type"];
NSString *subPath = [locator objectForKey:@"path"];

NSString *basePath = [bundle bundlePath];
// NSString *basePath = [workspace absolutePathForAppBundleWithIdentifier:bundle];
// NSLog(@"loc %@ %@", locator, path);

if (resourceName) {
path = [bundle pathForResource:[resourceName stringByDeletingPathExtension]
ofType:[resourceName pathExtension]];
} else if (subPath) {
path = [basePath stringByAppendingPathComponent:subPath]; ;
}
});
}
return path;
}
}

- (NSImage *)imageWithLocatorInformation:(id)locator {
NSImage *image = nil;
__block NSImage *image = nil;
if ([locator isKindOfClass:[NSArray class]]) {
NSUInteger i;
for (i = 0; i<[(NSArray *)locator count]; i++) {
Expand All @@ -198,28 +201,29 @@ - (NSImage *)imageWithLocatorInformation:(id)locator {
}

if (!image && [locator isKindOfClass:[NSDictionary class]]) {
NSWorkspace *workspace = [NSWorkspace sharedWorkspace];
NSString *bundleID = [locator objectForKey:@"bundle"];
NSBundle *bundle = [QSReg bundleWithIdentifier:bundleID];

if (!bundle) {
bundle = [NSBundle bundleWithPath:[workspace absolutePathForAppBundleWithIdentifier:bundleID]];
}
if(bundle != nil) {
image = [workspace iconForFile:[bundle bundlePath]];
} else {
// try and find an icon for the file type
if ([locator objectForKey:@"type"]) {
image = [workspace iconForFileType:[locator objectForKey:@"type"]];
}
}

QSGCDQueueSync(resourceQueue, ^{
NSWorkspace *workspace = [NSWorkspace sharedWorkspace];
NSString *bundleID = [locator objectForKey:@"bundle"];
NSBundle *bundle = [QSReg bundleWithIdentifier:bundleID];

if (!bundle) {
bundle = [NSBundle bundleWithPath:[workspace absolutePathForAppBundleWithIdentifier:bundleID]];
}
if(bundle != nil) {
image = [workspace iconForFile:[bundle bundlePath]];
} else {
// try and find an icon for the file type
if ([locator objectForKey:@"type"]) {
image = [workspace iconForFileType:[locator objectForKey:@"type"]];
}
}

#ifdef DEBUG
if(!image) {
NSLog(@"Unable to locate bundle with identifier %@, using locator %@", bundleID, locator);
}
if(!image) {
NSLog(@"Unable to locate bundle with identifier %@, using locator %@", bundleID, locator);
}
#endif
});
}
return image;
}
Expand All @@ -235,9 +239,11 @@ - (BOOL)handleInfo:(id)info ofType:(NSString *)type fromBundle:(NSBundle *)bundl
if ([type isEqualToString:@"QSResourceAdditions"]) {
[self addResourcesFromDictionary:info]; // inBundle:bundle];
} else {
if (QSGetLocalizationStatus())
[NSBundle registerLocalizationBundle:bundle forLanguage:info];
}
if (QSGetLocalizationStatus())
QSGCDQueueSync(resourceQueue, ^{
[NSBundle registerLocalizationBundle:bundle forLanguage:info];
});
}
return YES;
}
@end

0 comments on commit d10a283

Please sign in to comment.