├── .gitignore ├── CSVDocument.h ├── CSVDocument.m ├── CSVRowObject.h ├── CSVRowObject.m ├── English.lproj ├── InfoPlist.strings └── Localizable.strings ├── GeneratePreviewForURL.m ├── GenerateThumbnailForURL.m ├── German.lproj └── Localizable.strings ├── INSTALL.rtf ├── Info.plist ├── LICENSE.txt ├── NOTICE.txt ├── QuickLookCSV.xcodeproj ├── pp.pbxuser ├── pp.perspectivev3 ├── project.pbxproj └── project.xcworkspace │ └── contents.xcworkspacedata ├── README.md ├── Style.css ├── Test ├── test.csv ├── testHeight.csv ├── testMini.csv └── testWidth.csv └── main.c /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | .DS_Store 3 | */build/* 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | xcuserdata 13 | profile 14 | *.moved-aside 15 | DerivedData 16 | .idea/ 17 | *.hmap 18 | 19 | -------------------------------------------------------------------------------- /CSVDocument.h: -------------------------------------------------------------------------------- 1 | // 2 | // CSVDocument.h 3 | // QuickLookCSV 4 | // 5 | // Created by Pascal Pfiffner on 03.07.09. 6 | // This sourcecode is released under the Apache License, Version 2.0 7 | // http://www.apache.org/licenses/LICENSE-2.0.html 8 | // 9 | 10 | #import 11 | 12 | 13 | /** 14 | * An object representing data in a CSV file. 15 | */ 16 | @interface CSVDocument : NSObject 17 | 18 | @property (copy, nonatomic) NSString *separator; 19 | @property (copy, nonatomic) NSArray *rows; 20 | @property (copy, nonatomic) NSArray *columnKeys; 21 | 22 | @property (nonatomic, assign) BOOL autoDetectSeparator; 23 | 24 | - (NSUInteger)numRowsFromCSVString:(NSString *)string error:(NSError **)error; 25 | - (NSUInteger)numRowsFromCSVString:(NSString *)string maxRows:(NSUInteger)maxRows error:(NSError **)error; 26 | 27 | - (BOOL)isFirstColumn:(NSString *)columnKey; 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /CSVDocument.m: -------------------------------------------------------------------------------- 1 | // 2 | // CSVDocument.m 3 | // QuickLookCSV 4 | // 5 | // Created by Pascal Pfiffner on 03.07.09. 6 | // This sourcecode is released under the Apache License, Version 2.0 7 | // http://www.apache.org/licenses/LICENSE-2.0.html 8 | // 9 | 10 | #import "CSVDocument.h" 11 | #import "CSVRowObject.h" 12 | 13 | #define AUTODETECT_NUM_FIRST_CHARS 1000 14 | 15 | 16 | @implementation CSVDocument 17 | 18 | 19 | - (id)init 20 | { 21 | if ((self = [super init])) { 22 | self.separator = @","; 23 | } 24 | 25 | return self; 26 | } 27 | 28 | 29 | 30 | #pragma mark Parsing from String 31 | /** 32 | * Parse the given string into CSV rows. 33 | */ 34 | - (NSUInteger)numRowsFromCSVString:(NSString *)string error:(NSError **)error 35 | { 36 | return [self numRowsFromCSVString:string maxRows:0 error:error]; 37 | } 38 | 39 | /** 40 | * Parse the given string into CSV rows, up to a given number of rows if "maxRows" is greater than 0. 41 | */ 42 | - (NSUInteger)numRowsFromCSVString:(NSString *)string maxRows:(NSUInteger)maxRows error:(NSError **)error 43 | { 44 | NSUInteger numRows = 0; 45 | 46 | // String is non-empty 47 | if ([string length] > 0) { 48 | NSMutableArray *thisRows = [NSMutableArray array]; 49 | NSMutableArray *thisColumnKeys = [NSMutableArray array]; 50 | 51 | // Check whether the file uses ";" or TAB as separator by comparing relative occurrences in the first AUTODETECT_NUM_FIRST_CHARS chars 52 | if (_autoDetectSeparator) { 53 | self.separator = @","; 54 | 55 | NSUInteger testStringLength = ([string length] > AUTODETECT_NUM_FIRST_CHARS) ? AUTODETECT_NUM_FIRST_CHARS : [string length]; 56 | NSString *testString = [string substringToIndex:testStringLength]; 57 | NSArray *possSeparators = @[@";", @" ", @"|"]; 58 | 59 | for (NSString *s in possSeparators) { 60 | if ([[testString componentsSeparatedByString:s] count] > [[testString componentsSeparatedByString:_separator] count]) { 61 | self.separator = s; 62 | } 63 | } 64 | } 65 | 66 | // Get newline character set 67 | NSMutableCharacterSet *newlineCharacterSet = [NSMutableCharacterSet whitespaceAndNewlineCharacterSet]; 68 | [newlineCharacterSet formIntersectionWithCharacterSet:[[NSCharacterSet whitespaceCharacterSet] invertedSet]]; 69 | 70 | // Characters where the parser should stop 71 | NSMutableCharacterSet *importantCharactersSet = [NSMutableCharacterSet characterSetWithCharactersInString:[NSString stringWithFormat:@"%@\"", _separator]]; 72 | [importantCharactersSet formUnionWithCharacterSet:newlineCharacterSet]; 73 | 74 | 75 | // Create scanner and scan the string 76 | // ideas for the following block from Drew McCormack >> http://www.macresearch.org/cocoa-scientists-part-xxvi-parsing-csv-data 77 | BOOL insideQuotes = NO; // needed to determine whether we're inside doublequotes 78 | BOOL finishedRow = NO; // used for the inner while loop 79 | BOOL isNewColumn = NO; 80 | BOOL skipWhitespace = (NSNotFound == [_separator rangeOfCharacterFromSet:[NSCharacterSet whitespaceCharacterSet]].location); 81 | NSMutableDictionary *columns = nil; 82 | NSMutableString *currentCellString = [NSMutableString string]; 83 | NSUInteger colIndex = 0; 84 | 85 | NSScanner *scanner = [NSScanner scannerWithString:string]; 86 | [scanner setCharactersToBeSkipped:nil]; 87 | while (![scanner isAtEnd]) { 88 | 89 | // we'll end up here after every row 90 | insideQuotes = NO; 91 | finishedRow = NO; 92 | columns = ([thisColumnKeys count] > 0) ? [NSMutableDictionary dictionaryWithCapacity:[thisColumnKeys count]] : [NSMutableDictionary dictionary]; 93 | [currentCellString setString:@""]; 94 | colIndex = 0; 95 | 96 | // Scan row up to the next terminator 97 | while (!finishedRow) { 98 | NSString *tempString; 99 | NSString *colKey; 100 | if ([thisColumnKeys count] > colIndex) { 101 | colKey = thisColumnKeys[colIndex]; 102 | isNewColumn = NO; 103 | } 104 | else { 105 | colKey = [NSString stringWithFormat:@"col_%lu", (unsigned long)colIndex]; 106 | isNewColumn = YES; 107 | } 108 | 109 | 110 | // Scan characters into our string 111 | if ([scanner scanUpToCharactersFromSet:importantCharactersSet intoString:&tempString] ) { 112 | [currentCellString appendString:tempString]; 113 | } 114 | 115 | 116 | // found the separator 117 | if ([scanner scanString:_separator intoString:NULL]) { 118 | if (insideQuotes) { // Separator character inside double quotes 119 | [currentCellString appendString:_separator]; 120 | } 121 | else { // This is a column separating comma 122 | columns[colKey] = [currentCellString copy]; 123 | if (isNewColumn) { 124 | [thisColumnKeys addObject:colKey]; 125 | } 126 | 127 | // on to the next column/cell! 128 | [currentCellString setString:@""]; 129 | if (skipWhitespace) { 130 | [scanner scanCharactersFromSet:[NSCharacterSet whitespaceCharacterSet] intoString:NULL]; 131 | } 132 | colIndex++; 133 | } 134 | } 135 | 136 | 137 | // found a doublequote (") 138 | else if ([scanner scanString:@"\"" intoString:NULL]) { 139 | if (insideQuotes && [scanner scanString:@"\"" intoString:NULL]) { // Replace double - doublequotes with a single doublequote in our string. 140 | [currentCellString appendString:@"\""]; 141 | } 142 | else { // Start or end of a quoted string. 143 | insideQuotes = !insideQuotes; 144 | } 145 | } 146 | 147 | 148 | // found a newline 149 | else if ([scanner scanCharactersFromSet:newlineCharacterSet intoString:&tempString]) { 150 | if (insideQuotes) { // We're inside quotes - add line break to column text 151 | [currentCellString appendString:tempString]; 152 | } 153 | else { // End of row 154 | columns[colKey] = [currentCellString copy]; 155 | if (isNewColumn) { 156 | [thisColumnKeys addObject:colKey]; 157 | } 158 | 159 | finishedRow = YES; 160 | } 161 | } 162 | 163 | 164 | // found the end 165 | else if ([scanner isAtEnd]) { 166 | columns[colKey] = [currentCellString copy]; 167 | if (isNewColumn) { 168 | [thisColumnKeys addObject:colKey]; 169 | } 170 | 171 | finishedRow = YES; 172 | } 173 | } 174 | 175 | 176 | // one row scanned - add to the lines array 177 | if ([columns count] > 0) { 178 | CSVRowObject *newRow = [CSVRowObject newWithDictionary:columns]; 179 | [thisRows addObject:newRow]; 180 | } 181 | 182 | numRows++; 183 | if ((maxRows > 0) && (numRows > maxRows)) { 184 | break; 185 | } 186 | } 187 | 188 | // finished scanning our string 189 | self.rows = thisRows; 190 | self.columnKeys = thisColumnKeys; 191 | } 192 | 193 | // empty string 194 | else if (nil != error) { 195 | NSDictionary *errorDict = @{@"userInfo": @"Cannot parse an empty string"}; 196 | *error = [NSError errorWithDomain:NSCocoaErrorDomain code:1 userInfo:errorDict]; 197 | } 198 | 199 | return numRows; 200 | } 201 | 202 | 203 | 204 | #pragma mark - Document Properties 205 | - (BOOL)isFirstColumn:(NSString *)columnKey 206 | { 207 | if ((nil != _columnKeys) && ([_columnKeys count] > 0)) { 208 | return [columnKey isEqualToString:_columnKeys[0]]; 209 | } 210 | 211 | return NO; 212 | } 213 | 214 | 215 | @end 216 | -------------------------------------------------------------------------------- /CSVRowObject.h: -------------------------------------------------------------------------------- 1 | // 2 | // CSVRowObject.h 3 | // QuickLookCSV 4 | // 5 | // Created by Pascal Pfiffner on 03.07.09. 6 | // This sourcecode is released under the Apache License, Version 2.0 7 | // http://www.apache.org/licenses/LICENSE-2.0.html 8 | // 9 | 10 | #import 11 | 12 | 13 | /** 14 | * Data contained in one row of CSV data. 15 | */ 16 | @interface CSVRowObject : NSObject 17 | 18 | @property (copy, nonatomic) NSDictionary *columns; 19 | 20 | + (CSVRowObject *)newWithDictionary:(NSMutableDictionary *)dict; 21 | 22 | - (NSString *)columns:(NSArray *)columnKeys combinedByString:(NSString *)sepString; 23 | - (NSString *)columnForKey:(NSString *)columnKey; 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /CSVRowObject.m: -------------------------------------------------------------------------------- 1 | // 2 | // CSVRowObject.m 3 | // QuickLookCSV 4 | // 5 | // Created by Pascal Pfiffner on 03.07.09. 6 | // This sourcecode is released under the Apache License, Version 2.0 7 | // http://www.apache.org/licenses/LICENSE-2.0.html 8 | // 9 | 10 | #import "CSVRowObject.h" 11 | 12 | 13 | @implementation CSVRowObject 14 | 15 | 16 | /** 17 | * Instantiates an object with the given row-dictionary. 18 | */ 19 | + (CSVRowObject *)newWithDictionary:(NSMutableDictionary *)dict 20 | { 21 | CSVRowObject *row = [CSVRowObject new]; 22 | 23 | if (dict) { 24 | row.columns = dict; 25 | } 26 | 27 | return row; 28 | } 29 | 30 | 31 | 32 | #pragma mark Returning Columns 33 | - (NSString *)columns:(NSArray *)columnKeys combinedByString:(NSString *)sepString 34 | { 35 | NSString *rowString = nil; 36 | 37 | if ((nil != columnKeys) && (nil != _columns)) { 38 | rowString = [[_columns objectsForKeys:columnKeys notFoundMarker:@""] componentsJoinedByString:sepString]; 39 | } 40 | 41 | return rowString; 42 | } 43 | 44 | - (NSString *)columnForKey:(NSString *)columnKey 45 | { 46 | NSString *cellString = nil; 47 | 48 | if ((nil != columnKey) && (nil != _columns)) { 49 | cellString = _columns[columnKey]; 50 | } 51 | 52 | return cellString; 53 | } 54 | 55 | 56 | @end 57 | -------------------------------------------------------------------------------- /English.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/p2/quicklook-csv/e20ac8a762cb3985fdc312401e03ba8991f02877/English.lproj/InfoPlist.strings -------------------------------------------------------------------------------- /English.lproj/Localizable.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/p2/quicklook-csv/e20ac8a762cb3985fdc312401e03ba8991f02877/English.lproj/Localizable.strings -------------------------------------------------------------------------------- /GeneratePreviewForURL.m: -------------------------------------------------------------------------------- 1 | // 2 | // GeneratePreviewForURL.m 3 | // QuickLookCSV 4 | // 5 | // Created by Pascal Pfiffner on 03.07.2009. 6 | // This sourcecode is released under the Apache License, Version 2.0 7 | // http://www.apache.org/licenses/LICENSE-2.0.html 8 | // 9 | 10 | #include 11 | #include 12 | #include 13 | #import 14 | #import "CSVDocument.h" 15 | #import "CSVRowObject.h" 16 | 17 | #define MAX_ROWS 500 18 | 19 | static char* htmlReadableFileEncoding(NSStringEncoding stringEncoding); 20 | static char* humanReadableFileEncoding(NSStringEncoding stringEncoding); 21 | static char* formatFilesize(float bytes); 22 | 23 | 24 | /** 25 | * Generates a preview for the given file. 26 | * 27 | * This function parses the CSV and generates an HTML string that can be presented by QuickLook. 28 | */ 29 | OSStatus GeneratePreviewForURL(void *thisInterface, QLPreviewRequestRef preview, CFURLRef url, CFStringRef contentTypeUTI, CFDictionaryRef options) 30 | { 31 | @autoreleasepool { 32 | NSError *theErr = nil; 33 | NSURL *myURL = (__bridge NSURL *)url; 34 | 35 | // Load document data using NSStrings house methods 36 | // For huge files, maybe guess file encoding using `file --brief --mime` and use NSFileHandle? Not for now... 37 | NSStringEncoding stringEncoding; 38 | NSString *fileString = [NSString stringWithContentsOfURL:myURL usedEncoding:&stringEncoding error:&theErr]; 39 | 40 | // We could not open the file, probably unknown encoding; try ISO-8859-1 41 | if (!fileString) { 42 | stringEncoding = NSISOLatin1StringEncoding; 43 | fileString = [NSString stringWithContentsOfURL:myURL encoding:stringEncoding error:&theErr]; 44 | 45 | // Still no success, give up 46 | if (!fileString) { 47 | if (nil != theErr) { 48 | NSLog(@"Error opening the file: %@", theErr); 49 | } 50 | 51 | return noErr; 52 | } 53 | } 54 | 55 | 56 | // Parse the data if still interested in the preview 57 | if (false == QLPreviewRequestIsCancelled(preview)) { 58 | CSVDocument *csvDoc = [CSVDocument new]; 59 | csvDoc.autoDetectSeparator = YES; 60 | 61 | NSUInteger numRowsParsed = [csvDoc numRowsFromCSVString:fileString maxRows:MAX_ROWS error:NULL]; 62 | 63 | // Create HTML of the data if still interested in the preview 64 | if (false == QLPreviewRequestIsCancelled(preview)) { 65 | NSBundle *myBundle = [NSBundle bundleForClass:[CSVDocument class]]; 66 | 67 | NSString *cssPath = [myBundle pathForResource:@"Style" ofType:@"css"]; 68 | NSString *css = [[NSString alloc] initWithContentsOfFile:cssPath encoding:NSUTF8StringEncoding error:NULL]; 69 | 70 | NSString *path = [myURL path]; 71 | NSDictionary *fileAttributes = [[NSFileManager defaultManager] attributesOfItemAtPath:path error:nil]; 72 | 73 | // compose the html 74 | NSMutableString *html = [[NSMutableString alloc] initWithString:@"\n"]; 75 | [html appendString:@"\n"]; 76 | [html appendFormat:@"\n", htmlReadableFileEncoding(stringEncoding)]; 77 | [html appendString:@"
%lu %@, %@ %@
", 91 | (unsigned long)[csvDoc.columnKeys count], 92 | (1 == [csvDoc.columnKeys count]) ? NSLocalizedString(@"column", nil) : NSLocalizedString(@"columns", nil), 93 | numRows, 94 | (1 == numRowsParsed) ? NSLocalizedString(@"row", nil) : NSLocalizedString(@"rows", nil) 95 | ]; 96 | [html appendFormat:@"
%s, %@-%@, %s
", 97 | formatFilesize([fileAttributes[NSFileSize] floatValue]), 98 | NSLocalizedString(separatorDesc, nil), 99 | NSLocalizedString(@"Separated", nil), 100 | humanReadableFileEncoding(stringEncoding) 101 | ]; 102 | 103 | // add the table rows 104 | BOOL altRow = NO; 105 | for (CSVRowObject *row in csvDoc.rows) { 106 | [html appendFormat:@"\n"]; 109 | 110 | altRow = !altRow; 111 | } 112 | 113 | [html appendString:@"
", altRow ? @" class=\"alt_row\"" : @""]; 107 | [html appendString:[row columns:csvDoc.columnKeys combinedByString:@""]]; 108 | [html appendString:@"
\n"]; 114 | 115 | // not all rows were parsed, show hint 116 | if (numRowsParsed > MAX_ROWS) { 117 | NSString *rowsHint = [NSString stringWithFormat:NSLocalizedString(@"Only the first %i rows are being displayed", nil), MAX_ROWS]; 118 | [html appendFormat:@"
%@
", rowsHint]; 119 | } 120 | [html appendString:@""]; 121 | 122 | // feed the HTML 123 | CFDictionaryRef properties = (__bridge CFDictionaryRef)@{}; 124 | QLPreviewRequestSetDataRepresentation(preview, 125 | (__bridge CFDataRef)[html dataUsingEncoding:stringEncoding], 126 | kUTTypeHTML, 127 | properties 128 | ); 129 | } 130 | } 131 | } 132 | 133 | return noErr; 134 | } 135 | 136 | void CancelPreviewGeneration(void* thisInterface, QLPreviewRequestRef preview) 137 | { 138 | } 139 | 140 | 141 | 142 | #pragma mark - Output Utilities 143 | /** 144 | * To be used for the generated HTML. 145 | */ 146 | static char* htmlReadableFileEncoding(NSStringEncoding stringEncoding) 147 | { 148 | if (NSUTF8StringEncoding == stringEncoding || 149 | NSUnicodeStringEncoding == stringEncoding) { 150 | return "utf-8"; 151 | } 152 | if (NSASCIIStringEncoding == stringEncoding) { 153 | return "ascii"; 154 | } 155 | if (NSISOLatin1StringEncoding == stringEncoding) { 156 | return "iso-8859-1"; 157 | } 158 | if (NSMacOSRomanStringEncoding == stringEncoding) { 159 | return "x-mac-roman"; 160 | } 161 | if (NSUTF16BigEndianStringEncoding == stringEncoding || 162 | NSUTF16LittleEndianStringEncoding == stringEncoding) { 163 | return "utf-16"; 164 | } 165 | if (NSUTF32StringEncoding == stringEncoding || 166 | NSUTF32BigEndianStringEncoding == stringEncoding || 167 | NSUTF32LittleEndianStringEncoding == stringEncoding) { 168 | return "utf-32"; 169 | } 170 | if (NSShiftJISStringEncoding == stringEncoding) { 171 | return "shift_jis"; 172 | } 173 | 174 | return "utf-8"; 175 | } 176 | 177 | 178 | static char* humanReadableFileEncoding(NSStringEncoding stringEncoding) 179 | { 180 | if (NSUTF8StringEncoding == stringEncoding || 181 | NSUnicodeStringEncoding == stringEncoding) { 182 | return "UTF-8"; 183 | } 184 | if (NSASCIIStringEncoding == stringEncoding) { 185 | return "ASCII-text"; 186 | } 187 | if (NSISOLatin1StringEncoding == stringEncoding) { 188 | return "ISO-8859-1"; 189 | } 190 | if (NSMacOSRomanStringEncoding == stringEncoding) { 191 | return "Mac-Roman"; 192 | } 193 | if (NSUTF16BigEndianStringEncoding == stringEncoding || 194 | NSUTF16LittleEndianStringEncoding == stringEncoding) { 195 | return "UTF-16"; 196 | } 197 | if (NSUTF32StringEncoding == stringEncoding || 198 | NSUTF32BigEndianStringEncoding == stringEncoding || 199 | NSUTF32LittleEndianStringEncoding == stringEncoding) { 200 | return "UTF-32"; 201 | } 202 | if (NSShiftJISStringEncoding == stringEncoding) { 203 | return "Shift_JIS"; 204 | } 205 | 206 | return "UTF-8"; 207 | } 208 | 209 | 210 | static char* formatFilesize(float bytes) { 211 | if (bytes < 1) { 212 | return ""; 213 | } 214 | 215 | char *format[] = { "%.0f", "%.0f", "%.2f", "%.2f", "%.2f", "%.2f" }; 216 | char *unit[] = { "Byte", "KB", "MB", "GB", "TB", "PB" }; 217 | int i = 0; 218 | while (bytes > 1000) { 219 | bytes /= 1000; // Since OS X 10.7 (or 10.6?) Apple uses "kilobyte" and no longer "Kilobyte" or "kibibyte" 220 | i++; 221 | } 222 | 223 | char formatString[10]; 224 | static char result[9]; // longest string can be "999 Byte" or "999.99 GB" 225 | sprintf(formatString, "%s %s", format[i], unit[i]); 226 | sprintf(result, formatString, bytes); 227 | 228 | return result; 229 | } 230 | 231 | 232 | -------------------------------------------------------------------------------- /GenerateThumbnailForURL.m: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #import 5 | #import "CSVDocument.h" 6 | #import "CSVRowObject.h" 7 | 8 | #define THUMB_SIZE 512.0 9 | #define ASPECT 0.8 // aspect ratio 10 | #define NUM_ROWS 18 11 | #define BADGE_CSV @"csv" 12 | #define BADGE_TSV @"tab" 13 | 14 | static CGContextRef createRGBABitmapContext(CGSize pixelSize); 15 | //static CGContextRef createVectorContext(CGSize pixelSize) 16 | 17 | 18 | /** 19 | * Generate a thumbnail for file. 20 | * 21 | * This function's job is to create thumbnail for designated file as fast as possible. 22 | */ 23 | OSStatus GenerateThumbnailForURL(void *thisInterface, QLThumbnailRequestRef thumbnail, CFURLRef url, CFStringRef contentTypeUTI, CFDictionaryRef options, CGSize maxSize) 24 | { 25 | @autoreleasepool { 26 | NSURL *myURL = (__bridge NSURL *)url; 27 | NSError *theErr = nil; 28 | 29 | // Load document data using NSStrings house methods 30 | // For huge files, maybe guess file encoding using `file --brief --mime` and use NSFileHandle? Not for now... 31 | NSStringEncoding stringEncoding; 32 | NSString *fileString = [NSString stringWithContentsOfURL:myURL usedEncoding:&stringEncoding error:&theErr]; 33 | 34 | // We could not open the file, probably unknown encoding; try ISO-8859-1 35 | if (!fileString) { 36 | stringEncoding = NSISOLatin1StringEncoding; 37 | fileString = [NSString stringWithContentsOfURL:myURL encoding:stringEncoding error:&theErr]; 38 | 39 | // Still no success, give up 40 | if (!fileString) { 41 | if (nil != theErr) { 42 | NSLog(@"Error opening the file: %@", theErr); 43 | } 44 | 45 | return noErr; 46 | } 47 | } 48 | 49 | 50 | // Parse the data if still interested in the thumbnail 51 | if (false == QLThumbnailRequestIsCancelled(thumbnail)) { 52 | CSVDocument *csvDoc = [CSVDocument new]; 53 | csvDoc.autoDetectSeparator = YES; 54 | NSUInteger gotRows = [csvDoc numRowsFromCSVString:fileString maxRows:NUM_ROWS error:NULL]; 55 | 56 | CGFloat rowHeight = ceilf(THUMB_SIZE / MIN(MAX(4, gotRows), NUM_ROWS)); 57 | CGFloat fontSize = roundf(0.666 * rowHeight); 58 | 59 | // Draw an icon if still interested in the thumbnail 60 | if ((gotRows > 0) && (false == QLThumbnailRequestIsCancelled(thumbnail))) { 61 | CGRect maxBounds = CGRectMake(0.f, 0.f, THUMB_SIZE, THUMB_SIZE); 62 | CGRect usedBounds = CGRectMake(0.f, 0.f, 0.f, 0.f); 63 | CGFloat badgeMaxSize = THUMB_SIZE; 64 | 65 | CGContextRef context = createRGBABitmapContext(maxBounds.size); 66 | //CGContextRef context = createVectorContext(maxBounds.size); 67 | if (context) { 68 | //CGPDFContextBeginPage(context, NULL); 69 | 70 | // Flip CoreGraphics coordinate system 71 | CGContextScaleCTM(context, 1.f, -1.f); 72 | CGContextTranslateCTM(context, 0, -maxBounds.size.height); 73 | 74 | // Create colors 75 | CGColorRef borderColor = CGColorCreateGenericRGB(0.67f, 0.67f, 0.67f, 1.f); 76 | CGColorRef rowBG = CGColorCreateGenericRGB(1.f, 1.f, 1.f, 1.f); 77 | CGColorRef altRowBG = CGColorCreateGenericRGB(0.9f, 0.9f, 0.9f, 1.f); 78 | 79 | CGFloat borderWidth = 1.f; 80 | 81 | // We use NSGraphicsContext for the strings due to easier string drawing :P 82 | NSGraphicsContext *nsContext = [NSGraphicsContext graphicsContextWithGraphicsPort:(void *)context flipped:YES]; 83 | [NSGraphicsContext setCurrentContext:nsContext]; 84 | if (nil != nsContext) { 85 | NSFont *myFont = [NSFont systemFontOfSize:fontSize]; 86 | NSColor *rowTextColor = [NSColor colorWithCalibratedWhite:0.25f alpha:1.f]; 87 | NSDictionary *stringAttributes = @{NSFontAttributeName: myFont, 88 | NSForegroundColorAttributeName: rowTextColor}; 89 | 90 | CGFloat textXPadding = 5.f; 91 | CGFloat cellX = 0.f; 92 | CGFloat maxCellStringWidth; 93 | 94 | // loop each column 95 | for (NSString *colKey in csvDoc.columnKeys) { 96 | if (cellX > maxBounds.size.width) { 97 | break; 98 | } 99 | 100 | CGRect rowRect = CGRectMake(cellX, 0.f, maxBounds.size.width - cellX, rowHeight); 101 | maxCellStringWidth = 0.f; 102 | BOOL isFirstColumn = [csvDoc isFirstColumn:colKey]; 103 | BOOL altRow = NO; 104 | 105 | // loop rows of this column 106 | for (CSVRowObject *row in csvDoc.rows) { 107 | 108 | // Draw background 109 | if (isFirstColumn) { 110 | CGContextSetFillColorWithColor(context, altRow ? altRowBG : rowBG); 111 | CGContextFillRect(context, rowRect); 112 | } 113 | 114 | // Draw border 115 | else { 116 | CGContextMoveToPoint(context, cellX + borderWidth / 2, rowRect.origin.y); 117 | CGContextAddLineToPoint(context, cellX + borderWidth / 2, rowRect.origin.y + rowRect.size.height); 118 | CGContextSetStrokeColorWithColor(context, borderColor); 119 | CGContextStrokePath(context); 120 | } 121 | 122 | // Draw text 123 | NSRect textRect = NSRectFromCGRect(rowRect); 124 | textRect.size.width -= 2 * textXPadding; 125 | textRect.origin.x += textXPadding; 126 | NSString *cellString = [row columnForKey:colKey]; 127 | NSSize cellSize = [cellString sizeWithAttributes:stringAttributes]; 128 | [cellString drawWithRect:textRect options:NSStringDrawingUsesLineFragmentOrigin attributes:stringAttributes]; 129 | 130 | if (cellSize.width > maxCellStringWidth) { 131 | maxCellStringWidth = cellSize.width; 132 | } 133 | altRow = !altRow; 134 | rowRect.origin.y += rowHeight; 135 | 136 | // adjust usedBounds 137 | if (usedBounds.size.height < rowRect.origin.y) { 138 | usedBounds.size.height = rowRect.origin.y; 139 | } 140 | } 141 | 142 | cellX += maxCellStringWidth + 2 * textXPadding; 143 | usedBounds.size.width = cellX; 144 | } 145 | 146 | // adjust the bounds to respect our fixed aspect ratio - portrait 147 | //NSLog(@"%@ is: %.2fx%.2f -- max: %.2fx%.2f", myURL, usedBounds.size.width, usedBounds.size.height, maxBounds.size.width, maxBounds.size.height); 148 | if ((usedBounds.size.width > maxBounds.size.width && usedBounds.size.height > maxBounds.size.height) 149 | || (usedBounds.size.width <= usedBounds.size.height)) { 150 | badgeMaxSize = usedBounds.size.height; 151 | usedBounds.size.width = usedBounds.size.height * ASPECT; 152 | } 153 | 154 | // landscape 155 | else { 156 | badgeMaxSize = usedBounds.size.width; 157 | 158 | CGFloat my_height = usedBounds.size.width * ASPECT; 159 | if (usedBounds.size.height < my_height) { 160 | CGRect missingRect = CGRectMake(0.f, usedBounds.size.height, ceilf(usedBounds.size.width), ceilf(my_height - usedBounds.size.height)); 161 | CGContextSetFillColorWithColor(context, rowBG); 162 | CGContextFillRect(context, missingRect); 163 | } 164 | usedBounds.size.height = my_height; 165 | } 166 | } 167 | 168 | //CGPDFContextEndPage(context); 169 | 170 | CGColorRelease(borderColor); 171 | CGColorRelease(rowBG); 172 | CGColorRelease(altRowBG); 173 | 174 | // Create a CGImage 175 | CGImageRef fullImage = CGBitmapContextCreateImage(context); 176 | CGImageRef usedImage = CGImageCreateWithImageInRect(fullImage, usedBounds); 177 | CGImageRelease(fullImage); 178 | 179 | // Draw the image to the thumbnail request 180 | CGContextRef thumbContext = QLThumbnailRequestCreateContext(thumbnail, usedBounds.size, false, NULL); 181 | CGContextDrawImage(thumbContext, usedBounds, usedImage); 182 | CGImageRelease(usedImage); 183 | 184 | // we no longer need the bitmap data; free (malloc'ed by createRGBABitmapContext() ) 185 | char *contextData = CGBitmapContextGetData(context); 186 | if (contextData) { 187 | free(contextData); 188 | } 189 | 190 | // Draw the CSV badge to the icon 191 | NSGraphicsContext *thumbNsContext = [NSGraphicsContext graphicsContextWithGraphicsPort:(void *)thumbContext flipped:NO]; 192 | [NSGraphicsContext setCurrentContext:thumbNsContext]; 193 | if (nil != thumbNsContext) { 194 | NSString *badgeString = [@" " isEqualToString:csvDoc.separator] ? BADGE_TSV : BADGE_CSV; 195 | CGFloat badgeFontSize = ceilf(badgeMaxSize * 0.28f); 196 | NSFont *badgeFont = [NSFont boldSystemFontOfSize:badgeFontSize]; 197 | NSColor *badgeColor = [NSColor colorWithCalibratedRed:0.05f green:0.25f blue:0.1f alpha:1.f]; 198 | NSShadow *badgeShadow = [NSShadow new]; 199 | [badgeShadow setShadowOffset:NSMakeSize(0.f, 0.f)]; 200 | [badgeShadow setShadowBlurRadius:badgeFontSize * 0.01f]; 201 | [badgeShadow setShadowColor:[NSColor whiteColor]]; 202 | 203 | // Set attributes and draw 204 | NSDictionary *badgeAttributes = @{NSFontAttributeName: badgeFont, 205 | NSForegroundColorAttributeName: badgeColor, 206 | NSShadowAttributeName: badgeShadow}; 207 | 208 | NSSize badgeSize = [badgeString sizeWithAttributes:badgeAttributes]; 209 | CGFloat badge_x = (usedBounds.size.width / 2) - (badgeSize.width / 2); 210 | CGFloat badge_y = 0.025f * badgeMaxSize; 211 | NSRect badgeRect = NSMakeRect(badge_x, badge_y, 0.f, 0.f); 212 | badgeRect.size = badgeSize; 213 | 214 | [badgeString drawWithRect:badgeRect options:NSStringDrawingUsesLineFragmentOrigin attributes:badgeAttributes]; 215 | } 216 | 217 | 218 | // Clean up 219 | QLThumbnailRequestFlushContext(thumbnail, thumbContext); 220 | CGContextRelease(thumbContext); 221 | CGContextRelease(context); 222 | } 223 | } 224 | } 225 | } 226 | 227 | return noErr; 228 | } 229 | 230 | void CancelThumbnailGeneration(void* thisInterface, QLThumbnailRequestRef thumbnail) 231 | { 232 | } 233 | 234 | 235 | 236 | #pragma mark - Creating a bitmap context 237 | static CGContextRef createRGBABitmapContext(CGSize pixelSize) 238 | { 239 | NSUInteger width = pixelSize.width; 240 | NSUInteger height = pixelSize.height; 241 | NSUInteger bitmapBytesPerRow = width * 4; // 1 byte per component r g b a 242 | NSUInteger bitmapBytes = bitmapBytesPerRow * height; 243 | 244 | // allocate needed bytes 245 | void *bitmapData = malloc(bitmapBytes); 246 | if (NULL == bitmapData) { 247 | fprintf(stderr, "Oops, could not allocate bitmap data!"); 248 | return NULL; 249 | } 250 | 251 | // create the context 252 | CGColorSpaceRef colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); 253 | CGContextRef context = CGBitmapContextCreate(bitmapData, width, height, 8, bitmapBytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast); 254 | CGColorSpaceRelease(colorSpace); 255 | 256 | // context creation fail 257 | if (NULL == context) { 258 | free(bitmapData); 259 | fprintf(stderr, "Oops, could not create the context!"); 260 | return NULL; 261 | } 262 | 263 | return context; 264 | } 265 | 266 | /* 267 | static CGContextRef createVectorContext(CGSize pixelSize) 268 | { 269 | CGRect mediaBox = CGRectMake(0.f, 0.f, 0.f, 0.f); 270 | mediaBox.size = pixelSize; 271 | 272 | // allocate needed bytes 273 | CFMutableDataRef data = CFDataCreateMutable(kCFAllocatorDefault, 0); // unlimited size; hopefully we won't regret this :) 274 | if (NULL == bitmapData) { 275 | fprintf(stderr, "Oops, could not allocate mutable data!"); 276 | return NULL; 277 | } 278 | 279 | // create the context 280 | CGDataConsumerRef consumer = CGDataConsumerCreateWithCFData(data); 281 | CGContextRef context = CGPDFContextCreate(consumer, &mediaBox, NULL); 282 | CGDataConsumerRelease(consumer); 283 | 284 | // context creation fail 285 | if (NULL == context) { 286 | free(bitmapData); 287 | fprintf(stderr, "Oops, could not create the context!"); 288 | return NULL; 289 | } 290 | 291 | return context; 292 | 293 | 294 | // Don't forget creating pages 295 | // CGPDFContextBeginPage(pdfContext, NULL); 296 | // CGPDFContextEndPage(pdfContext); 297 | 298 | // and release the data 299 | // CFRelease(data); 300 | } // */ 301 | 302 | -------------------------------------------------------------------------------- /German.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | /* 2 | Localized.strings 3 | QuickLookCSV 4 | 5 | Created by Pascal Pfiffner on 03.07.09. 6 | This sourcecode is released under the Apache License, Version 2.0 7 | http://www.apache.org/licenses/LICENSE-2.0.html 8 | */ 9 | 10 | "column" = "Spalte"; 11 | "columns" = "Spalten"; 12 | "row" = "Zeile"; 13 | "rows" = "Zeilen"; 14 | "Tab" = "Tab"; 15 | "Comma" = "Komma"; 16 | "Separated" = "getrennt"; 17 | "Only the first %i rows are being displayed" = "Nur die ersten %i Zeilen werden angezeigt"; 18 | -------------------------------------------------------------------------------- /INSTALL.rtf: -------------------------------------------------------------------------------- 1 | {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340 2 | {\fonttbl\f0\fswiss\fcharset0 Helvetica;\f1\fnil\fcharset0 Monaco;} 3 | {\colortbl;\red255\green255\blue255;\red36\green70\blue183;} 4 | \vieww14400\viewh14000\viewkind0 5 | \pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardirnatural 6 | 7 | \f0\b\fs48 \cf0 Installation 8 | \fs50 \ 9 | 10 | \b0\fs28 \ 11 | \pard\tx566\tx6423\sl336\slmult1\pardirnatural 12 | \cf0 Place the file 13 | \b QuickLookCSV.qlgenerator 14 | \b0 into:\ 15 | \pard\tx566\tx6423\sl336\slmult1\pardirnatural 16 | 17 | \f1\fs26 \cf0 \cf2 ~/Library/QuickLook/ 18 | \f0\fs28 \cf0 to install it for yourself only\ 19 | 20 | \f1\fs26 \cf2 (Macintosh HD)/Library/QuickLook/ 21 | \f0\fs28 \cf0 to install it for all users of your Mac\ 22 | If the QuickLook-folder does not exist, simply create it manually.\ 23 | \ 24 | This is version 25 | \b 1.3 26 | \b0 of the plugin.\ 27 | {\field{\*\fldinst{HYPERLINK "http://code.google.com/p/quicklook-csv/"}}{\fldrslt http://code.google.com/p/quicklook-csv/}}\ 28 | {\field{\*\fldinst{HYPERLINK "https://github.com/p2/quicklook-csv"}}{\fldrslt https://github.com/p2/quicklook-csv}} (issue reports and pull requests)\ 29 | } -------------------------------------------------------------------------------- /Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleDocumentTypes 8 | 9 | 10 | CFBundleTypeExtensions 11 | 12 | tsv 13 | tab 14 | 15 | CFBundleTypeMIMETypes 16 | 17 | text/tab-separated-values 18 | 19 | CFBundleTypeName 20 | Tab 21 | CFBundleTypeRole 22 | QLGenerator 23 | LSItemContentTypes 24 | 25 | public.tab-separated-values-text 26 | 27 | LSTypeIsPackage 28 | 29 | NSPersistentStoreTypeKey 30 | XML 31 | 32 | 33 | CFBundleTypeExtensions 34 | 35 | csv 36 | 37 | CFBundleTypeMIMETypes 38 | 39 | text/csv 40 | 41 | CFBundleTypeName 42 | CSV 43 | CFBundleTypeRole 44 | QLGenerator 45 | LSItemContentTypes 46 | 47 | public.comma-separated-values-text 48 | 49 | NSPersistentStoreTypeKey 50 | XML 51 | 52 | 53 | CFBundleExecutable 54 | ${EXECUTABLE_NAME} 55 | CFBundleIconFile 56 | 57 | CFBundleIdentifier 58 | com.google.code.quicklookcsv 59 | CFBundleInfoDictionaryVersion 60 | 6.0 61 | CFBundleName 62 | ${PRODUCT_NAME} 63 | CFBundleShortVersionString 64 | 1.3 65 | CFBundleVersion 66 | 1.3 67 | CFPlugInDynamicRegisterFunction 68 | 69 | CFPlugInDynamicRegistration 70 | NO 71 | CFPlugInFactories 72 | 73 | B096F0B5-6A04-4D69-9F69-44EDA8DF7FE8 74 | QuickLookGeneratorPluginFactory 75 | 76 | CFPlugInTypes 77 | 78 | 5E2D9680-5022-40FA-B806-43349622E5B9 79 | 80 | B096F0B5-6A04-4D69-9F69-44EDA8DF7FE8 81 | 82 | 83 | CFPlugInUnloadFunction 84 | 85 | QLNeedsToBeRunInMainThread 86 | 87 | QLPreviewHeight 88 | 600 89 | QLPreviewWidth 90 | 800 91 | QLSupportsConcurrentRequests 92 | 93 | QLThumbnailMinimumSize 94 | 17 95 | UTImportedTypeDeclarations 96 | 97 | 98 | UTTypeConformsTo 99 | 100 | public.text 101 | 102 | UTTypeDescription 103 | Comma Separated Values 104 | UTTypeIdentifier 105 | public.comma-separated-values-text 106 | UTTypeReferenceURL 107 | http://tools.ietf.org/html/rfc4180 108 | UTTypeTagSpecification 109 | 110 | public.filename-extension 111 | 112 | csv 113 | 114 | public.mime-type 115 | text/csv 116 | 117 | 118 | 119 | UTTypeConformsTo 120 | 121 | public.text 122 | 123 | UTTypeDescription 124 | Tab Separated Values 125 | UTTypeIdentifier 126 | public.tab-separated-values-text 127 | UTTypeReferenceURL 128 | http://www.iana.org/assignments/media-types/text/tab-separated-values 129 | UTTypeTagSpecification 130 | 131 | public.filename-extension 132 | 133 | tsv 134 | tab 135 | 136 | public.mime-type 137 | text/tab-separated-values 138 | 139 | 140 | 141 | 142 | 143 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright 2017 Pascal Pfiffner 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /NOTICE.txt: -------------------------------------------------------------------------------- 1 | QuickLookCSV 2 | Copyright 2009-2017 Pascal Pfiffner 3 | 4 | This product includes software developed by Pascal Pfiffner which is freely available on [github.com/p2](https://github.com/p2/quicklook-csv). 5 | -------------------------------------------------------------------------------- /QuickLookCSV.xcodeproj/pp.pbxuser: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | 089C1669FE841209C02AAC07 /* Project object */ = { 4 | activeBuildConfigurationName = Release; 5 | activeSDKPreference = macosx10.5; 6 | activeTarget = 8D57630D048677EA00EA77CD /* QuickLookCSV */; 7 | addToTargets = ( 8 | 8D57630D048677EA00EA77CD /* QuickLookCSV */, 9 | ); 10 | breakpoints = ( 11 | ); 12 | codeSenseManager = EEB3ED190FFE215D00B7462F /* Code sense */; 13 | perUserDictionary = { 14 | "PBXConfiguration.PBXBreakpointsDataSource.v1:1CA23EDF0692099D00951B8B" = { 15 | PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; 16 | PBXFileTableDataSourceColumnSortingKey = PBXBreakpointsDataSource_BreakpointID; 17 | PBXFileTableDataSourceColumnWidthsKey = ( 18 | 20, 19 | 20, 20 | 10, 21 | 20, 22 | 10, 23 | 10, 24 | 10, 25 | 20, 26 | ); 27 | PBXFileTableDataSourceColumnsKey = ( 28 | PBXBreakpointsDataSource_ActionID, 29 | PBXBreakpointsDataSource_TypeID, 30 | PBXBreakpointsDataSource_BreakpointID, 31 | PBXBreakpointsDataSource_UseID, 32 | PBXBreakpointsDataSource_LocationID, 33 | PBXBreakpointsDataSource_ConditionID, 34 | PBXBreakpointsDataSource_IgnoreCountID, 35 | PBXBreakpointsDataSource_ContinueID, 36 | ); 37 | }; 38 | PBXConfiguration.PBXFileTableDataSource3.PBXExecutablesDataSource = { 39 | PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; 40 | PBXFileTableDataSourceColumnSortingKey = PBXExecutablesDataSource_NameID; 41 | PBXFileTableDataSourceColumnWidthsKey = ( 42 | 22, 43 | 300, 44 | 711, 45 | ); 46 | PBXFileTableDataSourceColumnsKey = ( 47 | PBXExecutablesDataSource_ActiveFlagID, 48 | PBXExecutablesDataSource_NameID, 49 | PBXExecutablesDataSource_CommentsID, 50 | ); 51 | }; 52 | PBXConfiguration.PBXFileTableDataSource3.PBXFileTableDataSource = { 53 | PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; 54 | PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID; 55 | PBXFileTableDataSourceColumnWidthsKey = ( 56 | 20, 57 | 10, 58 | 20, 59 | 48, 60 | 43, 61 | 43, 62 | 20, 63 | ); 64 | PBXFileTableDataSourceColumnsKey = ( 65 | PBXFileDataSource_FiletypeID, 66 | PBXFileDataSource_Filename_ColumnID, 67 | PBXFileDataSource_Built_ColumnID, 68 | PBXFileDataSource_ObjectSize_ColumnID, 69 | PBXFileDataSource_Errors_ColumnID, 70 | PBXFileDataSource_Warnings_ColumnID, 71 | PBXFileDataSource_Target_ColumnID, 72 | ); 73 | }; 74 | PBXConfiguration.PBXTargetDataSource.PBXTargetDataSource = { 75 | PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; 76 | PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID; 77 | PBXFileTableDataSourceColumnWidthsKey = ( 78 | 20, 79 | 10, 80 | 60, 81 | 20, 82 | 48, 83 | 43, 84 | 43, 85 | ); 86 | PBXFileTableDataSourceColumnsKey = ( 87 | PBXFileDataSource_FiletypeID, 88 | PBXFileDataSource_Filename_ColumnID, 89 | PBXTargetDataSource_PrimaryAttribute, 90 | PBXFileDataSource_Built_ColumnID, 91 | PBXFileDataSource_ObjectSize_ColumnID, 92 | PBXFileDataSource_Errors_ColumnID, 93 | PBXFileDataSource_Warnings_ColumnID, 94 | ); 95 | }; 96 | PBXPerProjectTemplateStateSaveDate = 286568158; 97 | PBXWorkspaceStateSaveDate = 286568158; 98 | }; 99 | perUserProjectItems = { 100 | EE2E1EFE105C37370016E6EB /* PBXTextBookmark */ = EE2E1EFE105C37370016E6EB /* PBXTextBookmark */; 101 | EE2E1F02105C37370016E6EB /* PBXTextBookmark */ = EE2E1F02105C37370016E6EB /* PBXTextBookmark */; 102 | EE2E1F03105C37370016E6EB /* PBXTextBookmark */ = EE2E1F03105C37370016E6EB /* PBXTextBookmark */; 103 | EE2E1F05105C37370016E6EB /* PBXTextBookmark */ = EE2E1F05105C37370016E6EB /* PBXTextBookmark */; 104 | EE309FE610FE851300AADFE8 /* PBXTextBookmark */ = EE309FE610FE851300AADFE8 /* PBXTextBookmark */; 105 | EE8830A610013E43005590AE /* PBXTextBookmark */ = EE8830A610013E43005590AE /* PBXTextBookmark */; 106 | EE8830A710013E43005590AE /* PBXTextBookmark */ = EE8830A710013E43005590AE /* PBXTextBookmark */; 107 | EE8830A810013E43005590AE /* PBXTextBookmark */ = EE8830A810013E43005590AE /* PBXTextBookmark */; 108 | EE8E9E0711147D890092500D /* PBXTextBookmark */ = EE8E9E0711147D890092500D /* PBXTextBookmark */; 109 | EE8E9E0811147D890092500D /* PlistBookmark */ = EE8E9E0811147D890092500D /* PlistBookmark */; 110 | EE8E9E1211147DC10092500D /* PBXTextBookmark */ = EE8E9E1211147DC10092500D /* PBXTextBookmark */; 111 | EE8E9E4A1114AEF10092500D /* PBXTextBookmark */ = EE8E9E4A1114AEF10092500D /* PBXTextBookmark */; 112 | EE8E9E7B1114B36B0092500D /* PBXTextBookmark */ = EE8E9E7B1114B36B0092500D /* PBXTextBookmark */; 113 | EEA3A593104879AB00AA5FA8 /* PBXTextBookmark */ = EEA3A593104879AB00AA5FA8 /* PBXTextBookmark */; 114 | }; 115 | sourceControlManager = EEB3ED180FFE215D00B7462F /* Source Control */; 116 | userBuildSettings = { 117 | }; 118 | }; 119 | 089C167EFE841241C02AAC07 /* English */ = { 120 | uiCtxt = { 121 | sepNavIntBoundsRect = "{{0, 0}, {1027, 769}}"; 122 | sepNavSelRange = "{200, 0}"; 123 | sepNavVisRange = "{0, 200}"; 124 | }; 125 | }; 126 | 08FB77B6FE84183AC02AAC07 /* main.c */ = { 127 | uiCtxt = { 128 | sepNavIntBoundsRect = "{{0, 0}, {1027, 3600}}"; 129 | sepNavSelRange = "{6213, 0}"; 130 | sepNavVisRange = "{0, 1838}"; 131 | }; 132 | }; 133 | 2C05A19B06CAA52B00D84F6F /* GeneratePreviewForURL.m */ = { 134 | uiCtxt = { 135 | sepNavIntBoundsRect = "{{0, 0}, {1027, 3040}}"; 136 | sepNavSelRange = "{3368, 0}"; 137 | sepNavVisRange = "{1890, 2264}"; 138 | }; 139 | }; 140 | 61E3BCFA0870B4F2002186A0 /* GenerateThumbnailForURL.m */ = { 141 | uiCtxt = { 142 | sepNavIntBoundsRect = "{{0, 0}, {1027, 4672}}"; 143 | sepNavSelRange = "{2430, 0}"; 144 | sepNavVisRange = "{5592, 1881}"; 145 | }; 146 | }; 147 | 8D57630D048677EA00EA77CD /* QuickLookCSV */ = { 148 | activeExec = 0; 149 | }; 150 | 8D576317048677EA00EA77CD /* Info.plist */ = { 151 | uiCtxt = { 152 | sepNavWindowFrame = "{{15, 39}, {1298, 834}}"; 153 | }; 154 | }; 155 | EE2E1EFE105C37370016E6EB /* PBXTextBookmark */ = { 156 | isa = PBXTextBookmark; 157 | fRef = EEB3EDCE0FFE38D800B7462F /* CSVDocument.m */; 158 | name = "CSVDocument.m: 89"; 159 | rLen = 0; 160 | rLoc = 396; 161 | rType = 0; 162 | vrLen = 2106; 163 | vrLoc = 1754; 164 | }; 165 | EE5A62571147A10D00E79E92 /* PBXTextBookmark */ = { 166 | isa = PBXTextBookmark; 167 | fRef = EE77BE4B0FFEB207008B09DE /* English */; 168 | name = "Localizable.strings: 12"; 169 | rLen = 31; 170 | rLoc = 255; 171 | rType = 0; 172 | vrLen = 441; 173 | vrLoc = 0; 174 | }; 175 | EE5A62581147A10D00E79E92 /* PBXTextBookmark */ = { 176 | isa = PBXTextBookmark; 177 | fRef = EE77BE9D0FFEB3F1008B09DE /* German */; 178 | name = "Localizable.strings: 13"; 179 | rLen = 0; 180 | rLoc = 288; 181 | rType = 0; 182 | vrLen = 443; 183 | vrLoc = 0; 184 | }; 185 | 186 | EE5A62731147AB3600E79E92 /* PBXTextBookmark */ = { 187 | isa = PBXTextBookmark; 188 | fRef = 2C05A19B06CAA52B00D84F6F /* GeneratePreviewForURL.m */; 189 | name = "GeneratePreviewForURL.m: 89"; 190 | rLen = 0; 191 | rLoc = 3567; 192 | rType = 0; 193 | vrLen = 2107; 194 | vrLoc = 2919; 195 | }; 196 | EE309FE610FE851300AADFE8 /* PBXTextBookmark */ = { 197 | isa = PBXTextBookmark; 198 | fRef = EE883106100141B9005590AE /* INSTALL.rtf */; 199 | name = "INSTALL.rtf: 8"; 200 | rLen = 0; 201 | rLoc = 276; 202 | rType = 0; 203 | vrLen = 332; 204 | vrLoc = 0; 205 | }; 206 | EE77BE4B0FFEB207008B09DE /* English */ = { 207 | uiCtxt = { 208 | sepNavIntBoundsRect = "{{0, 0}, {1047, 844}}"; 209 | sepNavSelRange = "{255, 31}"; 210 | sepNavVisRange = "{0, 441}"; 211 | }; 212 | }; 213 | EE77BE9D0FFEB3F1008B09DE /* German */ = { 214 | uiCtxt = { 215 | sepNavIntBoundsRect = "{{0, 0}, {1047, 844}}"; 216 | sepNavSelRange = "{288, 0}"; 217 | sepNavVisRange = "{0, 443}"; 218 | }; 219 | }; 220 | EE8830A610013E43005590AE /* PBXTextBookmark */ = { 221 | isa = PBXTextBookmark; 222 | fRef = EEB3EDD30FFE3B7F00B7462F /* CSVRowObject.h */; 223 | name = "CSVRowObject.h: 24"; 224 | rLen = 0; 225 | rLoc = 579; 226 | rType = 0; 227 | vrLen = 585; 228 | vrLoc = 0; 229 | }; 230 | EE8830A710013E43005590AE /* PBXTextBookmark */ = { 231 | isa = PBXTextBookmark; 232 | fRef = EEB3EDD40FFE3B7F00B7462F /* CSVRowObject.m */; 233 | name = "CSVRowObject.m: 66"; 234 | rLen = 0; 235 | rLoc = 1173; 236 | rType = 0; 237 | vrLen = 781; 238 | vrLoc = 397; 239 | }; 240 | EE883106100141B9005590AE /* INSTALL.rtf */ = { 241 | uiCtxt = { 242 | sepNavIntBoundsRect = "{{0, 0}, {1049, 844}}"; 243 | sepNavSelRange = "{276, 0}"; 244 | sepNavVisRect = "{{0, 0}, {1049, 844}}"; 245 | }; 246 | }; 247 | EE8E9E0711147D890092500D /* PBXTextBookmark */ = { 248 | isa = PBXTextBookmark; 249 | fRef = 61E3BCFA0870B4F2002186A0 /* GenerateThumbnailForURL.m */; 250 | name = "GenerateThumbnailForURL.m: 66"; 251 | rLen = 0; 252 | rLoc = 2430; 253 | rType = 0; 254 | vrLen = 1881; 255 | vrLoc = 5592; 256 | }; 257 | EE8E9E0811147D890092500D /* PlistBookmark */ = { 258 | isa = PlistBookmark; 259 | fRef = 8D576317048677EA00EA77CD /* Info.plist */; 260 | fallbackIsa = PBXBookmark; 261 | isK = 0; 262 | kPath = ( 263 | ); 264 | name = "/Users/pp/Programming/Cocoa/quicklook-csv/Info.plist"; 265 | rLen = 0; 266 | rLoc = 9223372036854775808; 267 | }; 268 | EE8E9E1211147DC10092500D /* PBXTextBookmark */ = { 269 | isa = PBXTextBookmark; 270 | fRef = 089C167EFE841241C02AAC07 /* English */; 271 | name = "InfoPlist.strings: 5"; 272 | rLen = 0; 273 | rLoc = 200; 274 | rType = 0; 275 | vrLen = 200; 276 | vrLoc = 0; 277 | }; 278 | EE8E9E4A1114AEF10092500D /* PBXTextBookmark */ = { 279 | isa = PBXTextBookmark; 280 | fRef = 2C05A19B06CAA52B00D84F6F /* GeneratePreviewForURL.m */; 281 | name = "GeneratePreviewForURL.m: 128"; 282 | rLen = 0; 283 | rLoc = 4631; 284 | rType = 0; 285 | vrLen = 2025; 286 | vrLoc = 1347; 287 | }; 288 | EE8E9E7B1114B36B0092500D /* PBXTextBookmark */ = { 289 | isa = PBXTextBookmark; 290 | fRef = 2C05A19B06CAA52B00D84F6F /* GeneratePreviewForURL.m */; 291 | name = "GeneratePreviewForURL.m: 86"; 292 | rLen = 0; 293 | rLoc = 3368; 294 | rType = 0; 295 | vrLen = 2264; 296 | vrLoc = 1890; 297 | }; 298 | EEA3A593104879AB00AA5FA8 /* PBXTextBookmark */ = { 299 | isa = PBXTextBookmark; 300 | fRef = 08FB77B6FE84183AC02AAC07 /* main.c */; 301 | name = "main.c: 151"; 302 | rLen = 0; 303 | rLoc = 6213; 304 | rType = 0; 305 | vrLen = 1838; 306 | vrLoc = 0; 307 | }; 308 | EEB3ED180FFE215D00B7462F /* Source Control */ = { 309 | isa = PBXSourceControlManager; 310 | fallbackIsa = XCSourceControlManager; 311 | isSCMEnabled = 0; 312 | scmConfiguration = { 313 | repositoryNamesForRoots = { 314 | "" = ""; 315 | }; 316 | }; 317 | }; 318 | EEB3ED190FFE215D00B7462F /* Code sense */ = { 319 | isa = PBXCodeSenseManager; 320 | indexTemplatePath = ""; 321 | }; 322 | EEB3EDCD0FFE38D800B7462F /* CSVDocument.h */ = { 323 | uiCtxt = { 324 | sepNavIntBoundsRect = "{{0, 0}, {1047, 844}}"; 325 | sepNavSelRange = "{323, 10}"; 326 | sepNavVisRange = "{0, 840}"; 327 | }; 328 | }; 329 | EEB3EDCE0FFE38D800B7462F /* CSVDocument.m */ = { 330 | uiCtxt = { 331 | sepNavIntBoundsRect = "{{0, 0}, {1027, 3424}}"; 332 | sepNavSelRange = "{2635, 0}"; 333 | sepNavVisRange = "{1754, 2106}"; 334 | }; 335 | }; 336 | EEB3EDD30FFE3B7F00B7462F /* CSVRowObject.h */ = { 337 | uiCtxt = { 338 | sepNavIntBoundsRect = "{{0, 0}, {1013, 772}}"; 339 | sepNavSelRange = "{579, 0}"; 340 | sepNavVisRange = "{0, 585}"; 341 | }; 342 | }; 343 | EEB3EDD40FFE3B7F00B7462F /* CSVRowObject.m */ = { 344 | uiCtxt = { 345 | sepNavIntBoundsRect = "{{0, 0}, {1013, 1120}}"; 346 | sepNavSelRange = "{1170, 0}"; 347 | sepNavVisRange = "{397, 781}"; 348 | }; 349 | }; 350 | EEB3EE850FFE513200B7462F /* Style.css */ = { 351 | uiCtxt = { 352 | sepNavIntBoundsRect = "{{0, 0}, {1027, 769}}"; 353 | sepNavSelRange = "{343, 0}"; 354 | sepNavVisRange = "{0, 828}"; 355 | }; 356 | }; 357 | } 358 | -------------------------------------------------------------------------------- /QuickLookCSV.xcodeproj/pp.perspectivev3: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ActivePerspectiveName 6 | Project 7 | AllowedModules 8 | 9 | 10 | BundleLoadPath 11 | 12 | MaxInstances 13 | n 14 | Module 15 | PBXSmartGroupTreeModule 16 | Name 17 | Groups and Files Outline View 18 | 19 | 20 | BundleLoadPath 21 | 22 | MaxInstances 23 | n 24 | Module 25 | PBXNavigatorGroup 26 | Name 27 | Editor 28 | 29 | 30 | BundleLoadPath 31 | 32 | MaxInstances 33 | n 34 | Module 35 | XCTaskListModule 36 | Name 37 | Task List 38 | 39 | 40 | BundleLoadPath 41 | 42 | MaxInstances 43 | n 44 | Module 45 | XCDetailModule 46 | Name 47 | File and Smart Group Detail Viewer 48 | 49 | 50 | BundleLoadPath 51 | 52 | MaxInstances 53 | 1 54 | Module 55 | PBXBuildResultsModule 56 | Name 57 | Detailed Build Results Viewer 58 | 59 | 60 | BundleLoadPath 61 | 62 | MaxInstances 63 | 1 64 | Module 65 | PBXProjectFindModule 66 | Name 67 | Project Batch Find Tool 68 | 69 | 70 | BundleLoadPath 71 | 72 | MaxInstances 73 | n 74 | Module 75 | XCProjectFormatConflictsModule 76 | Name 77 | Project Format Conflicts List 78 | 79 | 80 | BundleLoadPath 81 | 82 | MaxInstances 83 | n 84 | Module 85 | PBXBookmarksModule 86 | Name 87 | Bookmarks Tool 88 | 89 | 90 | BundleLoadPath 91 | 92 | MaxInstances 93 | n 94 | Module 95 | PBXClassBrowserModule 96 | Name 97 | Class Browser 98 | 99 | 100 | BundleLoadPath 101 | 102 | MaxInstances 103 | n 104 | Module 105 | PBXCVSModule 106 | Name 107 | Source Code Control Tool 108 | 109 | 110 | BundleLoadPath 111 | 112 | MaxInstances 113 | n 114 | Module 115 | PBXDebugBreakpointsModule 116 | Name 117 | Debug Breakpoints Tool 118 | 119 | 120 | BundleLoadPath 121 | 122 | MaxInstances 123 | n 124 | Module 125 | XCDockableInspector 126 | Name 127 | Inspector 128 | 129 | 130 | BundleLoadPath 131 | 132 | MaxInstances 133 | n 134 | Module 135 | PBXOpenQuicklyModule 136 | Name 137 | Open Quickly Tool 138 | 139 | 140 | BundleLoadPath 141 | 142 | MaxInstances 143 | 1 144 | Module 145 | PBXDebugSessionModule 146 | Name 147 | Debugger 148 | 149 | 150 | BundleLoadPath 151 | 152 | MaxInstances 153 | 1 154 | Module 155 | PBXDebugCLIModule 156 | Name 157 | Debug Console 158 | 159 | 160 | BundleLoadPath 161 | 162 | MaxInstances 163 | n 164 | Module 165 | XCSnapshotModule 166 | Name 167 | Snapshots Tool 168 | 169 | 170 | BundlePath 171 | /Developer/Library/PrivateFrameworks/DevToolsInterface.framework/Resources 172 | Description 173 | AIODescriptionKey 174 | DockingSystemVisible 175 | 176 | Extension 177 | perspectivev3 178 | FavBarConfig 179 | 180 | PBXProjectModuleGUID 181 | EEB3ED570FFE2B1100B7462F 182 | XCBarModuleItemNames 183 | 184 | XCBarModuleItems 185 | 186 | 187 | FirstTimeWindowDisplayed 188 | 189 | Identifier 190 | com.apple.perspectives.project.defaultV3 191 | MajorVersion 192 | 34 193 | MinorVersion 194 | 0 195 | Name 196 | All-In-One 197 | Notifications 198 | 199 | OpenEditors 200 | 201 | PerspectiveWidths 202 | 203 | 1352 204 | 1352 205 | 206 | Perspectives 207 | 208 | 209 | ChosenToolbarItems 210 | 211 | XCToolbarPerspectiveControl 212 | NSToolbarSeparatorItem 213 | active-target-popup 214 | active-platform-popup 215 | active-buildstyle-popup 216 | action 217 | NSToolbarFlexibleSpaceItem 218 | debugger-enable-breakpoints 219 | build-and-go 220 | com.apple.ide.PBXToolbarStopButton 221 | get-info 222 | NSToolbarFlexibleSpaceItem 223 | com.apple.pbx.toolbar.searchfield 224 | 225 | ControllerClassBaseName 226 | 227 | IconName 228 | WindowOfProject 229 | Identifier 230 | perspective.project 231 | IsVertical 232 | 233 | Layout 234 | 235 | 236 | ContentConfiguration 237 | 238 | PBXBottomSmartGroupGIDs 239 | 240 | 1C37FBAC04509CD000000102 241 | 1C37FAAC04509CD000000102 242 | 1C37FABC05509CD000000102 243 | 1C37FABC05539CD112110102 244 | E2644B35053B69B200211256 245 | 1C37FABC04509CD000100104 246 | 1CC0EA4004350EF90044410B 247 | 1CC0EA4004350EF90041110B 248 | 1C77FABC04509CD000000102 249 | 250 | PBXProjectModuleGUID 251 | 1CA23ED40692098700951B8B 252 | PBXProjectModuleLabel 253 | Files 254 | PBXProjectStructureProvided 255 | yes 256 | PBXSmartGroupTreeModuleColumnData 257 | 258 | PBXSmartGroupTreeModuleColumnWidthsKey 259 | 260 | 234 261 | 262 | PBXSmartGroupTreeModuleColumnsKey_v4 263 | 264 | MainColumn 265 | 266 | 267 | PBXSmartGroupTreeModuleOutlineStateKey_v7 268 | 269 | PBXSmartGroupTreeModuleOutlineStateExpansionKey 270 | 271 | 089C166AFE841209C02AAC07 272 | 08FB77AFFE84173DC02AAC07 273 | 089C167CFE841241C02AAC07 274 | 8D5B49A704867FD3000E48DA 275 | 089C1671FE841209C02AAC07 276 | 19C28FB6FE9D52B211CA2CBB 277 | 1C37FBAC04509CD000000102 278 | 1C77FABC04509CD000000102 279 | 280 | PBXSmartGroupTreeModuleOutlineStateSelectionKey 281 | 282 | 283 | 23 284 | 22 285 | 0 286 | 287 | 288 | PBXSmartGroupTreeModuleOutlineStateVisibleRectKey 289 | {{0, 0}, {234, 848}} 290 | 291 | PBXTopSmartGroupGIDs 292 | 293 | XCIncludePerspectivesSwitch 294 | 295 | 296 | GeometryConfiguration 297 | 298 | Frame 299 | {{0, 0}, {251, 866}} 300 | GroupTreeTableConfiguration 301 | 302 | MainColumn 303 | 234 304 | 305 | RubberWindowFrame 306 | 122 121 1352 907 0 0 1680 1028 307 | 308 | Module 309 | PBXSmartGroupTreeModule 310 | Proportion 311 | 251pt 312 | 313 | 314 | Dock 315 | 316 | 317 | BecomeActive 318 | 319 | ContentConfiguration 320 | 321 | PBXProjectModuleGUID 322 | EEB3ED3A0FFE2B1100B7462F 323 | PBXProjectModuleLabel 324 | GeneratePreviewForURL.m 325 | PBXSplitModuleInNavigatorKey 326 | 327 | Split0 328 | 329 | PBXProjectModuleGUID 330 | EEB3ED3B0FFE2B1100B7462F 331 | PBXProjectModuleLabel 332 | GeneratePreviewForURL.m 333 | _historyCapacity 334 | 0 335 | bookmark 336 | EE8E9E7B1114B36B0092500D 337 | history 338 | 339 | EE8830A610013E43005590AE 340 | EE8830A710013E43005590AE 341 | EEA3A593104879AB00AA5FA8 342 | EE2E1EFE105C37370016E6EB 343 | EE2E1F05105C37370016E6EB 344 | EE309FE610FE851300AADFE8 345 | EE8E9E0711147D890092500D 346 | EE8E9E0811147D890092500D 347 | EE8E9E1211147DC10092500D 348 | EE8E9E4A1114AEF10092500D 349 | 350 | 351 | SplitCount 352 | 1 353 | 354 | StatusBarVisibility 355 | 356 | XCSharingToken 357 | com.apple.Xcode.CommonNavigatorGroupSharingToken 358 | 359 | GeometryConfiguration 360 | 361 | Frame 362 | {{0, 0}, {1096, 861}} 363 | RubberWindowFrame 364 | 122 121 1352 907 0 0 1680 1028 365 | 366 | Module 367 | PBXNavigatorGroup 368 | Proportion 369 | 861pt 370 | 371 | 372 | Proportion 373 | 0pt 374 | Tabs 375 | 376 | 377 | ContentConfiguration 378 | 379 | PBXProjectModuleGUID 380 | 1CA23EDF0692099D00951B8B 381 | PBXProjectModuleLabel 382 | Detail 383 | 384 | GeometryConfiguration 385 | 386 | Frame 387 | {{10, 27}, {1096, -27}} 388 | RubberWindowFrame 389 | 122 121 1352 907 0 0 1680 1028 390 | 391 | Module 392 | XCDetailModule 393 | 394 | 395 | ContentConfiguration 396 | 397 | PBXProjectModuleGUID 398 | 1CA23EE00692099D00951B8B 399 | PBXProjectModuleLabel 400 | Project Find 401 | 402 | GeometryConfiguration 403 | 404 | Frame 405 | {{10, 27}, {1096, 231}} 406 | 407 | Module 408 | PBXProjectFindModule 409 | 410 | 411 | ContentConfiguration 412 | 413 | PBXCVSModuleFilterTypeKey 414 | 1032 415 | PBXProjectModuleGUID 416 | 1CA23EE10692099D00951B8B 417 | PBXProjectModuleLabel 418 | SCM Results 419 | 420 | GeometryConfiguration 421 | 422 | Frame 423 | {{10, 31}, {603, 297}} 424 | 425 | Module 426 | PBXCVSModule 427 | 428 | 429 | ContentConfiguration 430 | 431 | PBXProjectModuleGUID 432 | XCMainBuildResultsModuleGUID 433 | PBXProjectModuleLabel 434 | Build Results 435 | XCBuildResultsTrigger_Collapse 436 | 1021 437 | XCBuildResultsTrigger_Open 438 | 1011 439 | 440 | GeometryConfiguration 441 | 442 | Frame 443 | {{0, 0}, {568, 405}} 444 | 445 | Module 446 | PBXBuildResultsModule 447 | 448 | 449 | 450 | 451 | Proportion 452 | 1096pt 453 | 454 | 455 | Name 456 | Project 457 | ServiceClasses 458 | 459 | XCModuleDock 460 | PBXSmartGroupTreeModule 461 | XCModuleDock 462 | PBXNavigatorGroup 463 | XCDockableTabModule 464 | XCDetailModule 465 | PBXProjectFindModule 466 | PBXCVSModule 467 | PBXBuildResultsModule 468 | 469 | TableOfContents 470 | 471 | EE8E9E4C1114AEF10092500D 472 | 1CA23ED40692098700951B8B 473 | EE8E9E4D1114AEF10092500D 474 | EEB3ED3A0FFE2B1100B7462F 475 | EE8E9E4E1114AEF10092500D 476 | 1CA23EDF0692099D00951B8B 477 | 1CA23EE00692099D00951B8B 478 | 1CA23EE10692099D00951B8B 479 | XCMainBuildResultsModuleGUID 480 | 481 | ToolbarConfigUserDefaultsMinorVersion 482 | 2 483 | ToolbarConfiguration 484 | xcode.toolbar.config.defaultV3 485 | 486 | 487 | ChosenToolbarItems 488 | 489 | XCToolbarPerspectiveControl 490 | NSToolbarSeparatorItem 491 | active-combo-popup 492 | NSToolbarFlexibleSpaceItem 493 | debugger-enable-breakpoints 494 | build-and-go 495 | go 496 | NSToolbarFlexibleSpaceItem 497 | debugger-fix-and-continue 498 | debugger-restart-executable 499 | debugger-pause 500 | debugger-step-over 501 | debugger-step-into 502 | debugger-step-out 503 | debugger-step-instruction 504 | 505 | ControllerClassBaseName 506 | PBXDebugSessionModule 507 | IconName 508 | DebugTabIcon 509 | Identifier 510 | perspective.debug 511 | IsVertical 512 | 513 | Layout 514 | 515 | 516 | ContentConfiguration 517 | 518 | PBXProjectModuleGUID 519 | 1CCC7628064C1048000F2A68 520 | PBXProjectModuleLabel 521 | Debugger Console 522 | 523 | GeometryConfiguration 524 | 525 | Frame 526 | {{0, 0}, {1352, 435}} 527 | 528 | Module 529 | PBXDebugCLIModule 530 | Proportion 531 | 435pt 532 | 533 | 534 | ContentConfiguration 535 | 536 | Debugger 537 | 538 | HorizontalSplitView 539 | 540 | _collapsingFrameDimension 541 | 0.0 542 | _indexOfCollapsedView 543 | 0 544 | _percentageOfCollapsedView 545 | 0.0 546 | isCollapsed 547 | yes 548 | sizes 549 | 550 | {{0, 0}, {676, 213}} 551 | {{0, 213}, {676, 213}} 552 | 553 | 554 | VerticalSplitView 555 | 556 | _collapsingFrameDimension 557 | 0.0 558 | _indexOfCollapsedView 559 | 0 560 | _percentageOfCollapsedView 561 | 0.0 562 | isCollapsed 563 | yes 564 | sizes 565 | 566 | {{0, 0}, {676, 426}} 567 | {{676, 0}, {676, 426}} 568 | 569 | 570 | 571 | LauncherConfigVersion 572 | 8 573 | PBXProjectModuleGUID 574 | 1CCC7629064C1048000F2A68 575 | PBXProjectModuleLabel 576 | Debug 577 | 578 | GeometryConfiguration 579 | 580 | DebugConsoleVisible 581 | None 582 | DebugConsoleWindowFrame 583 | {{200, 200}, {500, 300}} 584 | DebugSTDIOWindowFrame 585 | {{200, 200}, {500, 300}} 586 | Frame 587 | {{0, 440}, {1352, 426}} 588 | PBXDebugSessionStackFrameViewKey 589 | 590 | DebugVariablesTableConfiguration 591 | 592 | Name 593 | 120 594 | Value 595 | 85 596 | Summary 597 | 446 598 | 599 | Frame 600 | {{0, 213}, {676, 213}} 601 | 602 | 603 | Module 604 | PBXDebugSessionModule 605 | Proportion 606 | 426pt 607 | 608 | 609 | Name 610 | Debug 611 | ServiceClasses 612 | 613 | XCModuleDock 614 | PBXDebugCLIModule 615 | PBXDebugSessionModule 616 | PBXDebugProcessAndThreadModule 617 | PBXDebugProcessViewModule 618 | PBXDebugThreadViewModule 619 | PBXDebugStackFrameViewModule 620 | PBXNavigatorGroup 621 | 622 | TableOfContents 623 | 624 | EE3B87E71112F48500FE62FB 625 | 1CCC7628064C1048000F2A68 626 | 1CCC7629064C1048000F2A68 627 | EE3B87E81112F48500FE62FB 628 | EE3B87E91112F48500FE62FB 629 | EE3B87EA1112F48500FE62FB 630 | EE3B87EB1112F48500FE62FB 631 | EEB3ED3A0FFE2B1100B7462F 632 | 633 | ToolbarConfigUserDefaultsMinorVersion 634 | 2 635 | ToolbarConfiguration 636 | xcode.toolbar.config.debugV3 637 | 638 | 639 | PerspectivesBarVisible 640 | 641 | ShelfIsVisible 642 | 643 | SourceDescription 644 | file at '/Developer/Library/PrivateFrameworks/DevToolsInterface.framework/Resources/XCPerspectivesSpecification.xcperspec' 645 | StatusbarIsVisible 646 | 647 | TimeStamp 648 | 0.0 649 | ToolbarDisplayMode 650 | 2 651 | ToolbarIsVisible 652 | 653 | ToolbarSizeMode 654 | 1 655 | Type 656 | Perspectives 657 | UpdateMessage 658 | 659 | WindowJustification 660 | 5 661 | WindowOrderList 662 | 663 | /Users/pp/Cocoa/quicklook-csv/QuickLookCSV.xcodeproj 664 | 665 | WindowString 666 | 122 121 1352 907 0 0 1680 1028 667 | WindowToolsV3 668 | 669 | 670 | Identifier 671 | windowTool.debugger 672 | Layout 673 | 674 | 675 | Dock 676 | 677 | 678 | ContentConfiguration 679 | 680 | Debugger 681 | 682 | HorizontalSplitView 683 | 684 | _collapsingFrameDimension 685 | 0.0 686 | _indexOfCollapsedView 687 | 0 688 | _percentageOfCollapsedView 689 | 0.0 690 | isCollapsed 691 | yes 692 | sizes 693 | 694 | {{0, 0}, {317, 164}} 695 | {{317, 0}, {377, 164}} 696 | 697 | 698 | VerticalSplitView 699 | 700 | _collapsingFrameDimension 701 | 0.0 702 | _indexOfCollapsedView 703 | 0 704 | _percentageOfCollapsedView 705 | 0.0 706 | isCollapsed 707 | yes 708 | sizes 709 | 710 | {{0, 0}, {694, 164}} 711 | {{0, 164}, {694, 216}} 712 | 713 | 714 | 715 | LauncherConfigVersion 716 | 8 717 | PBXProjectModuleGUID 718 | 1C162984064C10D400B95A72 719 | PBXProjectModuleLabel 720 | Debug - GLUTExamples (Underwater) 721 | 722 | GeometryConfiguration 723 | 724 | DebugConsoleDrawerSize 725 | {100, 120} 726 | DebugConsoleVisible 727 | None 728 | DebugConsoleWindowFrame 729 | {{200, 200}, {500, 300}} 730 | DebugSTDIOWindowFrame 731 | {{200, 200}, {500, 300}} 732 | Frame 733 | {{0, 0}, {694, 380}} 734 | RubberWindowFrame 735 | 321 238 694 422 0 0 1440 878 736 | 737 | Module 738 | PBXDebugSessionModule 739 | Proportion 740 | 100% 741 | 742 | 743 | Proportion 744 | 100% 745 | 746 | 747 | Name 748 | Debugger 749 | ServiceClasses 750 | 751 | PBXDebugSessionModule 752 | 753 | StatusbarIsVisible 754 | 1 755 | TableOfContents 756 | 757 | 1CD10A99069EF8BA00B06720 758 | 1C0AD2AB069F1E9B00FABCE6 759 | 1C162984064C10D400B95A72 760 | 1C0AD2AC069F1E9B00FABCE6 761 | 762 | ToolbarConfiguration 763 | xcode.toolbar.config.debugV3 764 | WindowString 765 | 321 238 694 422 0 0 1440 878 766 | WindowToolGUID 767 | 1CD10A99069EF8BA00B06720 768 | WindowToolIsVisible 769 | 0 770 | 771 | 772 | Identifier 773 | windowTool.build 774 | Layout 775 | 776 | 777 | Dock 778 | 779 | 780 | ContentConfiguration 781 | 782 | PBXProjectModuleGUID 783 | 1CD0528F0623707200166675 784 | PBXProjectModuleLabel 785 | <No Editor> 786 | PBXSplitModuleInNavigatorKey 787 | 788 | Split0 789 | 790 | PBXProjectModuleGUID 791 | 1CD052900623707200166675 792 | 793 | SplitCount 794 | 1 795 | 796 | StatusBarVisibility 797 | 1 798 | 799 | GeometryConfiguration 800 | 801 | Frame 802 | {{0, 0}, {500, 215}} 803 | RubberWindowFrame 804 | 192 257 500 500 0 0 1280 1002 805 | 806 | Module 807 | PBXNavigatorGroup 808 | Proportion 809 | 218pt 810 | 811 | 812 | BecomeActive 813 | 1 814 | ContentConfiguration 815 | 816 | PBXProjectModuleGUID 817 | XCMainBuildResultsModuleGUID 818 | PBXProjectModuleLabel 819 | Build 820 | 821 | GeometryConfiguration 822 | 823 | Frame 824 | {{0, 222}, {500, 236}} 825 | RubberWindowFrame 826 | 192 257 500 500 0 0 1280 1002 827 | 828 | Module 829 | PBXBuildResultsModule 830 | Proportion 831 | 236pt 832 | 833 | 834 | Proportion 835 | 458pt 836 | 837 | 838 | Name 839 | Build Results 840 | ServiceClasses 841 | 842 | PBXBuildResultsModule 843 | 844 | StatusbarIsVisible 845 | 1 846 | TableOfContents 847 | 848 | 1C78EAA5065D492600B07095 849 | 1C78EAA6065D492600B07095 850 | 1CD0528F0623707200166675 851 | XCMainBuildResultsModuleGUID 852 | 853 | ToolbarConfiguration 854 | xcode.toolbar.config.buildV3 855 | WindowString 856 | 192 257 500 500 0 0 1280 1002 857 | 858 | 859 | Identifier 860 | windowTool.find 861 | Layout 862 | 863 | 864 | Dock 865 | 866 | 867 | Dock 868 | 869 | 870 | ContentConfiguration 871 | 872 | PBXProjectModuleGUID 873 | 1CDD528C0622207200134675 874 | PBXProjectModuleLabel 875 | <No Editor> 876 | PBXSplitModuleInNavigatorKey 877 | 878 | Split0 879 | 880 | PBXProjectModuleGUID 881 | 1CD0528D0623707200166675 882 | 883 | SplitCount 884 | 1 885 | 886 | StatusBarVisibility 887 | 1 888 | 889 | GeometryConfiguration 890 | 891 | Frame 892 | {{0, 0}, {781, 167}} 893 | RubberWindowFrame 894 | 62 385 781 470 0 0 1440 878 895 | 896 | Module 897 | PBXNavigatorGroup 898 | Proportion 899 | 781pt 900 | 901 | 902 | Proportion 903 | 50% 904 | 905 | 906 | BecomeActive 907 | 1 908 | ContentConfiguration 909 | 910 | PBXProjectModuleGUID 911 | 1CD0528E0623707200166675 912 | PBXProjectModuleLabel 913 | Project Find 914 | 915 | GeometryConfiguration 916 | 917 | Frame 918 | {{8, 0}, {773, 254}} 919 | RubberWindowFrame 920 | 62 385 781 470 0 0 1440 878 921 | 922 | Module 923 | PBXProjectFindModule 924 | Proportion 925 | 50% 926 | 927 | 928 | Proportion 929 | 428pt 930 | 931 | 932 | Name 933 | Project Find 934 | ServiceClasses 935 | 936 | PBXProjectFindModule 937 | 938 | StatusbarIsVisible 939 | 1 940 | TableOfContents 941 | 942 | 1C530D57069F1CE1000CFCEE 943 | 1C530D58069F1CE1000CFCEE 944 | 1C530D59069F1CE1000CFCEE 945 | 1CDD528C0622207200134675 946 | 1C530D5A069F1CE1000CFCEE 947 | 1CE0B1FE06471DED0097A5F4 948 | 1CD0528E0623707200166675 949 | 950 | WindowString 951 | 62 385 781 470 0 0 1440 878 952 | WindowToolGUID 953 | 1C530D57069F1CE1000CFCEE 954 | WindowToolIsVisible 955 | 0 956 | 957 | 958 | Identifier 959 | windowTool.snapshots 960 | Layout 961 | 962 | 963 | Dock 964 | 965 | 966 | Module 967 | XCSnapshotModule 968 | Proportion 969 | 100% 970 | 971 | 972 | Proportion 973 | 100% 974 | 975 | 976 | Name 977 | Snapshots 978 | ServiceClasses 979 | 980 | XCSnapshotModule 981 | 982 | StatusbarIsVisible 983 | Yes 984 | ToolbarConfiguration 985 | xcode.toolbar.config.snapshots 986 | WindowString 987 | 315 824 300 550 0 0 1440 878 988 | WindowToolIsVisible 989 | Yes 990 | 991 | 992 | Identifier 993 | windowTool.debuggerConsole 994 | Layout 995 | 996 | 997 | Dock 998 | 999 | 1000 | BecomeActive 1001 | 1 1002 | ContentConfiguration 1003 | 1004 | PBXProjectModuleGUID 1005 | 1C78EAAC065D492600B07095 1006 | PBXProjectModuleLabel 1007 | Debugger Console 1008 | 1009 | GeometryConfiguration 1010 | 1011 | Frame 1012 | {{0, 0}, {700, 358}} 1013 | RubberWindowFrame 1014 | 149 87 700 400 0 0 1440 878 1015 | 1016 | Module 1017 | PBXDebugCLIModule 1018 | Proportion 1019 | 358pt 1020 | 1021 | 1022 | Proportion 1023 | 358pt 1024 | 1025 | 1026 | Name 1027 | Debugger Console 1028 | ServiceClasses 1029 | 1030 | PBXDebugCLIModule 1031 | 1032 | StatusbarIsVisible 1033 | 1 1034 | TableOfContents 1035 | 1036 | 1C530D5B069F1CE1000CFCEE 1037 | 1C530D5C069F1CE1000CFCEE 1038 | 1C78EAAC065D492600B07095 1039 | 1040 | ToolbarConfiguration 1041 | xcode.toolbar.config.consoleV3 1042 | WindowString 1043 | 149 87 440 400 0 0 1440 878 1044 | WindowToolGUID 1045 | 1C530D5B069F1CE1000CFCEE 1046 | WindowToolIsVisible 1047 | 0 1048 | 1049 | 1050 | Identifier 1051 | windowTool.scm 1052 | Layout 1053 | 1054 | 1055 | Dock 1056 | 1057 | 1058 | ContentConfiguration 1059 | 1060 | PBXProjectModuleGUID 1061 | 1C78EAB2065D492600B07095 1062 | PBXProjectModuleLabel 1063 | <No Editor> 1064 | PBXSplitModuleInNavigatorKey 1065 | 1066 | Split0 1067 | 1068 | PBXProjectModuleGUID 1069 | 1C78EAB3065D492600B07095 1070 | 1071 | SplitCount 1072 | 1 1073 | 1074 | StatusBarVisibility 1075 | 1 1076 | 1077 | GeometryConfiguration 1078 | 1079 | Frame 1080 | {{0, 0}, {452, 0}} 1081 | RubberWindowFrame 1082 | 743 379 452 308 0 0 1280 1002 1083 | 1084 | Module 1085 | PBXNavigatorGroup 1086 | Proportion 1087 | 0pt 1088 | 1089 | 1090 | BecomeActive 1091 | 1 1092 | ContentConfiguration 1093 | 1094 | PBXProjectModuleGUID 1095 | 1CD052920623707200166675 1096 | PBXProjectModuleLabel 1097 | SCM 1098 | 1099 | GeometryConfiguration 1100 | 1101 | ConsoleFrame 1102 | {{0, 259}, {452, 0}} 1103 | Frame 1104 | {{0, 7}, {452, 259}} 1105 | RubberWindowFrame 1106 | 743 379 452 308 0 0 1280 1002 1107 | TableConfiguration 1108 | 1109 | Status 1110 | 30 1111 | FileName 1112 | 199 1113 | Path 1114 | 197.09500122070312 1115 | 1116 | TableFrame 1117 | {{0, 0}, {452, 250}} 1118 | 1119 | Module 1120 | PBXCVSModule 1121 | Proportion 1122 | 262pt 1123 | 1124 | 1125 | Proportion 1126 | 266pt 1127 | 1128 | 1129 | Name 1130 | SCM 1131 | ServiceClasses 1132 | 1133 | PBXCVSModule 1134 | 1135 | StatusbarIsVisible 1136 | 1 1137 | TableOfContents 1138 | 1139 | 1C78EAB4065D492600B07095 1140 | 1C78EAB5065D492600B07095 1141 | 1C78EAB2065D492600B07095 1142 | 1CD052920623707200166675 1143 | 1144 | ToolbarConfiguration 1145 | xcode.toolbar.config.scmV3 1146 | WindowString 1147 | 743 379 452 308 0 0 1280 1002 1148 | 1149 | 1150 | Identifier 1151 | windowTool.breakpoints 1152 | IsVertical 1153 | 0 1154 | Layout 1155 | 1156 | 1157 | Dock 1158 | 1159 | 1160 | BecomeActive 1161 | 1 1162 | ContentConfiguration 1163 | 1164 | PBXBottomSmartGroupGIDs 1165 | 1166 | 1C77FABC04509CD000000102 1167 | 1168 | PBXProjectModuleGUID 1169 | 1CE0B1FE06471DED0097A5F4 1170 | PBXProjectModuleLabel 1171 | Files 1172 | PBXProjectStructureProvided 1173 | no 1174 | PBXSmartGroupTreeModuleColumnData 1175 | 1176 | PBXSmartGroupTreeModuleColumnWidthsKey 1177 | 1178 | 168 1179 | 1180 | PBXSmartGroupTreeModuleColumnsKey_v4 1181 | 1182 | MainColumn 1183 | 1184 | 1185 | PBXSmartGroupTreeModuleOutlineStateKey_v7 1186 | 1187 | PBXSmartGroupTreeModuleOutlineStateExpansionKey 1188 | 1189 | 1C77FABC04509CD000000102 1190 | 1191 | PBXSmartGroupTreeModuleOutlineStateSelectionKey 1192 | 1193 | 1194 | 0 1195 | 1196 | 1197 | PBXSmartGroupTreeModuleOutlineStateVisibleRectKey 1198 | {{0, 0}, {168, 350}} 1199 | 1200 | PBXTopSmartGroupGIDs 1201 | 1202 | XCIncludePerspectivesSwitch 1203 | 0 1204 | 1205 | GeometryConfiguration 1206 | 1207 | Frame 1208 | {{0, 0}, {185, 368}} 1209 | GroupTreeTableConfiguration 1210 | 1211 | MainColumn 1212 | 168 1213 | 1214 | RubberWindowFrame 1215 | 315 424 744 409 0 0 1440 878 1216 | 1217 | Module 1218 | PBXSmartGroupTreeModule 1219 | Proportion 1220 | 185pt 1221 | 1222 | 1223 | ContentConfiguration 1224 | 1225 | PBXProjectModuleGUID 1226 | 1CA1AED706398EBD00589147 1227 | PBXProjectModuleLabel 1228 | Detail 1229 | 1230 | GeometryConfiguration 1231 | 1232 | Frame 1233 | {{190, 0}, {554, 368}} 1234 | RubberWindowFrame 1235 | 315 424 744 409 0 0 1440 878 1236 | 1237 | Module 1238 | XCDetailModule 1239 | Proportion 1240 | 554pt 1241 | 1242 | 1243 | Proportion 1244 | 368pt 1245 | 1246 | 1247 | MajorVersion 1248 | 3 1249 | MinorVersion 1250 | 0 1251 | Name 1252 | Breakpoints 1253 | ServiceClasses 1254 | 1255 | PBXSmartGroupTreeModule 1256 | XCDetailModule 1257 | 1258 | StatusbarIsVisible 1259 | 1 1260 | TableOfContents 1261 | 1262 | 1CDDB66807F98D9800BB5817 1263 | 1CDDB66907F98D9800BB5817 1264 | 1CE0B1FE06471DED0097A5F4 1265 | 1CA1AED706398EBD00589147 1266 | 1267 | ToolbarConfiguration 1268 | xcode.toolbar.config.breakpointsV3 1269 | WindowString 1270 | 315 424 744 409 0 0 1440 878 1271 | WindowToolGUID 1272 | 1CDDB66807F98D9800BB5817 1273 | WindowToolIsVisible 1274 | 1 1275 | 1276 | 1277 | Identifier 1278 | windowTool.debugAnimator 1279 | Layout 1280 | 1281 | 1282 | Dock 1283 | 1284 | 1285 | Module 1286 | PBXNavigatorGroup 1287 | Proportion 1288 | 100% 1289 | 1290 | 1291 | Proportion 1292 | 100% 1293 | 1294 | 1295 | Name 1296 | Debug Visualizer 1297 | ServiceClasses 1298 | 1299 | PBXNavigatorGroup 1300 | 1301 | StatusbarIsVisible 1302 | 1 1303 | ToolbarConfiguration 1304 | xcode.toolbar.config.debugAnimatorV3 1305 | WindowString 1306 | 100 100 700 500 0 0 1280 1002 1307 | 1308 | 1309 | Identifier 1310 | windowTool.bookmarks 1311 | Layout 1312 | 1313 | 1314 | Dock 1315 | 1316 | 1317 | Module 1318 | PBXBookmarksModule 1319 | Proportion 1320 | 166pt 1321 | 1322 | 1323 | Proportion 1324 | 166pt 1325 | 1326 | 1327 | Name 1328 | Bookmarks 1329 | ServiceClasses 1330 | 1331 | PBXBookmarksModule 1332 | 1333 | StatusbarIsVisible 1334 | 0 1335 | WindowString 1336 | 538 42 401 187 0 0 1280 1002 1337 | 1338 | 1339 | Identifier 1340 | windowTool.projectFormatConflicts 1341 | Layout 1342 | 1343 | 1344 | Dock 1345 | 1346 | 1347 | Module 1348 | XCProjectFormatConflictsModule 1349 | Proportion 1350 | 100% 1351 | 1352 | 1353 | Proportion 1354 | 100% 1355 | 1356 | 1357 | Name 1358 | Project Format Conflicts 1359 | ServiceClasses 1360 | 1361 | XCProjectFormatConflictsModule 1362 | 1363 | StatusbarIsVisible 1364 | 0 1365 | WindowContentMinSize 1366 | 450 300 1367 | WindowString 1368 | 50 850 472 307 0 0 1440 877 1369 | 1370 | 1371 | Identifier 1372 | windowTool.classBrowser 1373 | Layout 1374 | 1375 | 1376 | Dock 1377 | 1378 | 1379 | BecomeActive 1380 | 1 1381 | ContentConfiguration 1382 | 1383 | OptionsSetName 1384 | Hierarchy, all classes 1385 | PBXProjectModuleGUID 1386 | 1CA6456E063B45B4001379D8 1387 | PBXProjectModuleLabel 1388 | Class Browser - NSObject 1389 | 1390 | GeometryConfiguration 1391 | 1392 | ClassesFrame 1393 | {{0, 0}, {369, 96}} 1394 | ClassesTreeTableConfiguration 1395 | 1396 | PBXClassNameColumnIdentifier 1397 | 208 1398 | PBXClassBookColumnIdentifier 1399 | 22 1400 | 1401 | Frame 1402 | {{0, 0}, {616, 353}} 1403 | MembersFrame 1404 | {{0, 105}, {369, 395}} 1405 | MembersTreeTableConfiguration 1406 | 1407 | PBXMemberTypeIconColumnIdentifier 1408 | 22 1409 | PBXMemberNameColumnIdentifier 1410 | 216 1411 | PBXMemberTypeColumnIdentifier 1412 | 94 1413 | PBXMemberBookColumnIdentifier 1414 | 22 1415 | 1416 | PBXModuleWindowStatusBarHidden2 1417 | 1 1418 | RubberWindowFrame 1419 | 597 125 616 374 0 0 1280 1002 1420 | 1421 | Module 1422 | PBXClassBrowserModule 1423 | Proportion 1424 | 354pt 1425 | 1426 | 1427 | Proportion 1428 | 354pt 1429 | 1430 | 1431 | Name 1432 | Class Browser 1433 | ServiceClasses 1434 | 1435 | PBXClassBrowserModule 1436 | 1437 | StatusbarIsVisible 1438 | 0 1439 | TableOfContents 1440 | 1441 | 1C78EABA065D492600B07095 1442 | 1C78EABB065D492600B07095 1443 | 1CA6456E063B45B4001379D8 1444 | 1445 | ToolbarConfiguration 1446 | xcode.toolbar.config.classbrowser 1447 | WindowString 1448 | 597 125 616 374 0 0 1280 1002 1449 | 1450 | 1451 | Identifier 1452 | windowTool.refactoring 1453 | IncludeInToolsMenu 1454 | 0 1455 | Layout 1456 | 1457 | 1458 | Dock 1459 | 1460 | 1461 | BecomeActive 1462 | 1 1463 | GeometryConfiguration 1464 | 1465 | Frame 1466 | {0, 0}, {500, 335} 1467 | RubberWindowFrame 1468 | {0, 0}, {500, 335} 1469 | 1470 | Module 1471 | XCRefactoringModule 1472 | Proportion 1473 | 100% 1474 | 1475 | 1476 | Proportion 1477 | 100% 1478 | 1479 | 1480 | Name 1481 | Refactoring 1482 | ServiceClasses 1483 | 1484 | XCRefactoringModule 1485 | 1486 | WindowString 1487 | 200 200 500 356 0 0 1920 1200 1488 | 1489 | 1490 | 1491 | 1492 | -------------------------------------------------------------------------------- /QuickLookCSV.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 2C05A19C06CAA52B00D84F6F /* GeneratePreviewForURL.m in Sources */ = {isa = PBXBuildFile; fileRef = 2C05A19B06CAA52B00D84F6F /* GeneratePreviewForURL.m */; }; 11 | 61E3BCFB0870B4F2002186A0 /* GenerateThumbnailForURL.m in Sources */ = {isa = PBXBuildFile; fileRef = 61E3BCFA0870B4F2002186A0 /* GenerateThumbnailForURL.m */; }; 12 | 8D576312048677EA00EA77CD /* main.c in Sources */ = {isa = PBXBuildFile; fileRef = 08FB77B6FE84183AC02AAC07 /* main.c */; settings = {ATTRIBUTES = (); }; }; 13 | 8D576314048677EA00EA77CD /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0AA1909FFE8422F4C02AAC07 /* CoreFoundation.framework */; }; 14 | 8D5B49A804867FD3000E48DA /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 8D5B49A704867FD3000E48DA /* InfoPlist.strings */; }; 15 | C86B05270671AA6E00DD9006 /* CoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C86B05260671AA6E00DD9006 /* CoreServices.framework */; }; 16 | EE77BE9C0FFEB3EA008B09DE /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = EE77BE9B0FFEB3EA008B09DE /* Localizable.strings */; }; 17 | EEB3ED1C0FFE217E00B7462F /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EEB3ED1B0FFE217E00B7462F /* Cocoa.framework */; }; 18 | EEB3EDCF0FFE38D800B7462F /* CSVDocument.h in Headers */ = {isa = PBXBuildFile; fileRef = EEB3EDCD0FFE38D800B7462F /* CSVDocument.h */; }; 19 | EEB3EDD00FFE38D800B7462F /* CSVDocument.m in Sources */ = {isa = PBXBuildFile; fileRef = EEB3EDCE0FFE38D800B7462F /* CSVDocument.m */; }; 20 | EEB3EDD50FFE3B7F00B7462F /* CSVRowObject.h in Headers */ = {isa = PBXBuildFile; fileRef = EEB3EDD30FFE3B7F00B7462F /* CSVRowObject.h */; }; 21 | EEB3EDD60FFE3B8000B7462F /* CSVRowObject.m in Sources */ = {isa = PBXBuildFile; fileRef = EEB3EDD40FFE3B7F00B7462F /* CSVRowObject.m */; }; 22 | EEB3EE860FFE513200B7462F /* Style.css in Resources */ = {isa = PBXBuildFile; fileRef = EEB3EE850FFE513200B7462F /* Style.css */; }; 23 | F28CFBFD0A3EC0AF000ABFF5 /* ApplicationServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F28CFBFC0A3EC0AF000ABFF5 /* ApplicationServices.framework */; }; 24 | F28CFC030A3EC0C6000ABFF5 /* QuickLook.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F28CFC020A3EC0C6000ABFF5 /* QuickLook.framework */; }; 25 | /* End PBXBuildFile section */ 26 | 27 | /* Begin PBXFileReference section */ 28 | 089C167EFE841241C02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = ""; }; 29 | 08FB77B6FE84183AC02AAC07 /* main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = main.c; sourceTree = ""; }; 30 | 0AA1909FFE8422F4C02AAC07 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = /System/Library/Frameworks/CoreFoundation.framework; sourceTree = ""; }; 31 | 2C05A19B06CAA52B00D84F6F /* GeneratePreviewForURL.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratePreviewForURL.m; sourceTree = ""; }; 32 | 61E3BCFA0870B4F2002186A0 /* GenerateThumbnailForURL.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = GenerateThumbnailForURL.m; sourceTree = ""; }; 33 | 8D576316048677EA00EA77CD /* QuickLookCSV.qlgenerator */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = QuickLookCSV.qlgenerator; sourceTree = BUILT_PRODUCTS_DIR; }; 34 | 8D576317048677EA00EA77CD /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; 35 | C86B05260671AA6E00DD9006 /* CoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreServices.framework; path = /System/Library/Frameworks/CoreServices.framework; sourceTree = ""; }; 36 | EE77BE4B0FFEB207008B09DE /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/Localizable.strings; sourceTree = ""; }; 37 | EE77BE9D0FFEB3F1008B09DE /* German */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = German; path = German.lproj/Localizable.strings; sourceTree = ""; }; 38 | EE801DFA16375DC800090402 /* test.csv */ = {isa = PBXFileReference; lastKnownFileType = text; name = test.csv; path = Test/test.csv; sourceTree = ""; }; 39 | EE801DFB16375DC800090402 /* testHeight.csv */ = {isa = PBXFileReference; lastKnownFileType = text; name = testHeight.csv; path = Test/testHeight.csv; sourceTree = ""; }; 40 | EE801DFC16375DC800090402 /* testWidth.csv */ = {isa = PBXFileReference; lastKnownFileType = text; name = testWidth.csv; path = Test/testWidth.csv; sourceTree = ""; }; 41 | EE801DFE163763E200090402 /* testMini.csv */ = {isa = PBXFileReference; lastKnownFileType = text; name = testMini.csv; path = Test/testMini.csv; sourceTree = ""; }; 42 | EE883106100141B9005590AE /* INSTALL.rtf */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; path = INSTALL.rtf; sourceTree = ""; }; 43 | EE89E06C16BDC64900B7E61A /* README.md */ = {isa = PBXFileReference; lastKnownFileType = text; path = README.md; sourceTree = ""; }; 44 | EEB3ED1B0FFE217E00B7462F /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = ""; }; 45 | EEB3EDCD0FFE38D800B7462F /* CSVDocument.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSVDocument.h; sourceTree = ""; }; 46 | EEB3EDCE0FFE38D800B7462F /* CSVDocument.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSVDocument.m; sourceTree = ""; }; 47 | EEB3EDD30FFE3B7F00B7462F /* CSVRowObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSVRowObject.h; sourceTree = ""; }; 48 | EEB3EDD40FFE3B7F00B7462F /* CSVRowObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSVRowObject.m; sourceTree = ""; }; 49 | EEB3EE850FFE513200B7462F /* Style.css */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.css; path = Style.css; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.css; }; 50 | F28CFBFC0A3EC0AF000ABFF5 /* ApplicationServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ApplicationServices.framework; path = /System/Library/Frameworks/ApplicationServices.framework; sourceTree = ""; }; 51 | F28CFC020A3EC0C6000ABFF5 /* QuickLook.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuickLook.framework; path = /System/Library/Frameworks/QuickLook.framework; sourceTree = ""; }; 52 | /* End PBXFileReference section */ 53 | 54 | /* Begin PBXFrameworksBuildPhase section */ 55 | 8D576313048677EA00EA77CD /* Frameworks */ = { 56 | isa = PBXFrameworksBuildPhase; 57 | buildActionMask = 2147483647; 58 | files = ( 59 | 8D576314048677EA00EA77CD /* CoreFoundation.framework in Frameworks */, 60 | C86B05270671AA6E00DD9006 /* CoreServices.framework in Frameworks */, 61 | F28CFBFD0A3EC0AF000ABFF5 /* ApplicationServices.framework in Frameworks */, 62 | F28CFC030A3EC0C6000ABFF5 /* QuickLook.framework in Frameworks */, 63 | EEB3ED1C0FFE217E00B7462F /* Cocoa.framework in Frameworks */, 64 | ); 65 | runOnlyForDeploymentPostprocessing = 0; 66 | }; 67 | /* End PBXFrameworksBuildPhase section */ 68 | 69 | /* Begin PBXGroup section */ 70 | 089C166AFE841209C02AAC07 /* QuickLookCSV */ = { 71 | isa = PBXGroup; 72 | children = ( 73 | EE89E06C16BDC64900B7E61A /* README.md */, 74 | EE883106100141B9005590AE /* INSTALL.rtf */, 75 | 08FB77AFFE84173DC02AAC07 /* Source */, 76 | 089C167CFE841241C02AAC07 /* Resources */, 77 | 089C1671FE841209C02AAC07 /* External Frameworks and Libraries */, 78 | 19C28FB6FE9D52B211CA2CBB /* Products */, 79 | ); 80 | name = QuickLookCSV; 81 | sourceTree = ""; 82 | }; 83 | 089C1671FE841209C02AAC07 /* External Frameworks and Libraries */ = { 84 | isa = PBXGroup; 85 | children = ( 86 | EEB3ED1B0FFE217E00B7462F /* Cocoa.framework */, 87 | F28CFC020A3EC0C6000ABFF5 /* QuickLook.framework */, 88 | F28CFBFC0A3EC0AF000ABFF5 /* ApplicationServices.framework */, 89 | C86B05260671AA6E00DD9006 /* CoreServices.framework */, 90 | 0AA1909FFE8422F4C02AAC07 /* CoreFoundation.framework */, 91 | ); 92 | name = "External Frameworks and Libraries"; 93 | sourceTree = ""; 94 | }; 95 | 089C167CFE841241C02AAC07 /* Resources */ = { 96 | isa = PBXGroup; 97 | children = ( 98 | EE77BE9B0FFEB3EA008B09DE /* Localizable.strings */, 99 | EEB3EE850FFE513200B7462F /* Style.css */, 100 | 8D576317048677EA00EA77CD /* Info.plist */, 101 | 8D5B49A704867FD3000E48DA /* InfoPlist.strings */, 102 | EE801DFA16375DC800090402 /* test.csv */, 103 | EE801DFB16375DC800090402 /* testHeight.csv */, 104 | EE801DFC16375DC800090402 /* testWidth.csv */, 105 | EE801DFE163763E200090402 /* testMini.csv */, 106 | ); 107 | name = Resources; 108 | sourceTree = ""; 109 | }; 110 | 08FB77AFFE84173DC02AAC07 /* Source */ = { 111 | isa = PBXGroup; 112 | children = ( 113 | 61E3BCFA0870B4F2002186A0 /* GenerateThumbnailForURL.m */, 114 | 2C05A19B06CAA52B00D84F6F /* GeneratePreviewForURL.m */, 115 | 08FB77B6FE84183AC02AAC07 /* main.c */, 116 | EEB3EDCD0FFE38D800B7462F /* CSVDocument.h */, 117 | EEB3EDCE0FFE38D800B7462F /* CSVDocument.m */, 118 | EEB3EDD30FFE3B7F00B7462F /* CSVRowObject.h */, 119 | EEB3EDD40FFE3B7F00B7462F /* CSVRowObject.m */, 120 | ); 121 | name = Source; 122 | sourceTree = ""; 123 | }; 124 | 19C28FB6FE9D52B211CA2CBB /* Products */ = { 125 | isa = PBXGroup; 126 | children = ( 127 | 8D576316048677EA00EA77CD /* QuickLookCSV.qlgenerator */, 128 | ); 129 | name = Products; 130 | sourceTree = ""; 131 | }; 132 | /* End PBXGroup section */ 133 | 134 | /* Begin PBXHeadersBuildPhase section */ 135 | 8D57630E048677EA00EA77CD /* Headers */ = { 136 | isa = PBXHeadersBuildPhase; 137 | buildActionMask = 2147483647; 138 | files = ( 139 | EEB3EDCF0FFE38D800B7462F /* CSVDocument.h in Headers */, 140 | EEB3EDD50FFE3B7F00B7462F /* CSVRowObject.h in Headers */, 141 | ); 142 | runOnlyForDeploymentPostprocessing = 0; 143 | }; 144 | /* End PBXHeadersBuildPhase section */ 145 | 146 | /* Begin PBXNativeTarget section */ 147 | 8D57630D048677EA00EA77CD /* QuickLookCSV */ = { 148 | isa = PBXNativeTarget; 149 | buildConfigurationList = 2CA3261E0896AD4900168862 /* Build configuration list for PBXNativeTarget "QuickLookCSV" */; 150 | buildPhases = ( 151 | 8D57630E048677EA00EA77CD /* Headers */, 152 | 8D57630F048677EA00EA77CD /* Resources */, 153 | 8D576311048677EA00EA77CD /* Sources */, 154 | 8D576313048677EA00EA77CD /* Frameworks */, 155 | EEAD58EE16376AE2002ABAF7 /* ShellScript */, 156 | ); 157 | buildRules = ( 158 | ); 159 | dependencies = ( 160 | ); 161 | name = QuickLookCSV; 162 | productInstallPath = /Library/QuickLook; 163 | productName = QuickLookCSV; 164 | productReference = 8D576316048677EA00EA77CD /* QuickLookCSV.qlgenerator */; 165 | productType = "com.apple.product-type.bundle"; 166 | }; 167 | /* End PBXNativeTarget section */ 168 | 169 | /* Begin PBXProject section */ 170 | 089C1669FE841209C02AAC07 /* Project object */ = { 171 | isa = PBXProject; 172 | attributes = { 173 | LastUpgradeCheck = 0450; 174 | }; 175 | buildConfigurationList = 2CA326220896AD4900168862 /* Build configuration list for PBXProject "QuickLookCSV" */; 176 | compatibilityVersion = "Xcode 3.2"; 177 | developmentRegion = English; 178 | hasScannedForEncodings = 1; 179 | knownRegions = ( 180 | en, 181 | ); 182 | mainGroup = 089C166AFE841209C02AAC07 /* QuickLookCSV */; 183 | projectDirPath = ""; 184 | projectRoot = ""; 185 | targets = ( 186 | 8D57630D048677EA00EA77CD /* QuickLookCSV */, 187 | ); 188 | }; 189 | /* End PBXProject section */ 190 | 191 | /* Begin PBXResourcesBuildPhase section */ 192 | 8D57630F048677EA00EA77CD /* Resources */ = { 193 | isa = PBXResourcesBuildPhase; 194 | buildActionMask = 2147483647; 195 | files = ( 196 | 8D5B49A804867FD3000E48DA /* InfoPlist.strings in Resources */, 197 | EEB3EE860FFE513200B7462F /* Style.css in Resources */, 198 | EE77BE9C0FFEB3EA008B09DE /* Localizable.strings in Resources */, 199 | ); 200 | runOnlyForDeploymentPostprocessing = 0; 201 | }; 202 | /* End PBXResourcesBuildPhase section */ 203 | 204 | /* Begin PBXShellScriptBuildPhase section */ 205 | EEAD58EE16376AE2002ABAF7 /* ShellScript */ = { 206 | isa = PBXShellScriptBuildPhase; 207 | buildActionMask = 2147483647; 208 | files = ( 209 | ); 210 | inputPaths = ( 211 | ); 212 | outputPaths = ( 213 | ); 214 | runOnlyForDeploymentPostprocessing = 0; 215 | shellPath = /bin/sh; 216 | shellScript = "if [ 'Release' == $CONFIGURATION ]; then\n cd ~/Desktop\n if [ ! -e \"QuickLook CSV\" ]; then\n mkdir \"QuickLook CSV\"\n fi\n\n cd \"QuickLook CSV\"\n ln -s ~/Library/QuickLook \"Plugins (User)\"\n ln -s /Library/QuickLook \"Plugins (System Wide)\"\n\n cp ${SRCROOT}/INSTALL.rtf ./\n \n mkdir \"Test Files\"\n cp ${SRCROOT}/Test/* \"Test Files\"\nfi"; 217 | }; 218 | /* End PBXShellScriptBuildPhase section */ 219 | 220 | /* Begin PBXSourcesBuildPhase section */ 221 | 8D576311048677EA00EA77CD /* Sources */ = { 222 | isa = PBXSourcesBuildPhase; 223 | buildActionMask = 2147483647; 224 | files = ( 225 | 8D576312048677EA00EA77CD /* main.c in Sources */, 226 | 2C05A19C06CAA52B00D84F6F /* GeneratePreviewForURL.m in Sources */, 227 | 61E3BCFB0870B4F2002186A0 /* GenerateThumbnailForURL.m in Sources */, 228 | EEB3EDD00FFE38D800B7462F /* CSVDocument.m in Sources */, 229 | EEB3EDD60FFE3B8000B7462F /* CSVRowObject.m in Sources */, 230 | ); 231 | runOnlyForDeploymentPostprocessing = 0; 232 | }; 233 | /* End PBXSourcesBuildPhase section */ 234 | 235 | /* Begin PBXVariantGroup section */ 236 | 8D5B49A704867FD3000E48DA /* InfoPlist.strings */ = { 237 | isa = PBXVariantGroup; 238 | children = ( 239 | 089C167EFE841241C02AAC07 /* English */, 240 | ); 241 | name = InfoPlist.strings; 242 | sourceTree = ""; 243 | }; 244 | EE77BE9B0FFEB3EA008B09DE /* Localizable.strings */ = { 245 | isa = PBXVariantGroup; 246 | children = ( 247 | EE77BE4B0FFEB207008B09DE /* English */, 248 | EE77BE9D0FFEB3F1008B09DE /* German */, 249 | ); 250 | name = Localizable.strings; 251 | sourceTree = ""; 252 | }; 253 | /* End PBXVariantGroup section */ 254 | 255 | /* Begin XCBuildConfiguration section */ 256 | 2CA3261F0896AD4900168862 /* Debug */ = { 257 | isa = XCBuildConfiguration; 258 | buildSettings = { 259 | ARCHS = "$(ARCHS_STANDARD_64_BIT)"; 260 | COMBINE_HIDPI_IMAGES = YES; 261 | COPY_PHASE_STRIP = NO; 262 | GCC_DYNAMIC_NO_PIC = NO; 263 | GCC_MODEL_TUNING = G5; 264 | GCC_OPTIMIZATION_LEVEL = 0; 265 | GCC_PRECOMPILE_PREFIX_HEADER = NO; 266 | INFOPLIST_FILE = Info.plist; 267 | INSTALL_PATH = /Library/QuickLook; 268 | MACOSX_DEPLOYMENT_TARGET = 10.6.8; 269 | PRODUCT_NAME = QuickLookCSV; 270 | WRAPPER_EXTENSION = qlgenerator; 271 | }; 272 | name = Debug; 273 | }; 274 | 2CA326200896AD4900168862 /* Release */ = { 275 | isa = XCBuildConfiguration; 276 | buildSettings = { 277 | ARCHS = "$(ARCHS_STANDARD_64_BIT)"; 278 | COMBINE_HIDPI_IMAGES = YES; 279 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 280 | GCC_MODEL_TUNING = G5; 281 | GCC_PRECOMPILE_PREFIX_HEADER = NO; 282 | INFOPLIST_FILE = Info.plist; 283 | INSTALL_PATH = /Library/QuickLook; 284 | MACOSX_DEPLOYMENT_TARGET = 10.6.8; 285 | PRODUCT_NAME = QuickLookCSV; 286 | WRAPPER_EXTENSION = qlgenerator; 287 | }; 288 | name = Release; 289 | }; 290 | 2CA326230896AD4900168862 /* Debug */ = { 291 | isa = XCBuildConfiguration; 292 | buildSettings = { 293 | ARCHS = "$(NATIVE_ARCH_ACTUAL)"; 294 | CLANG_ENABLE_OBJC_ARC = YES; 295 | GCC_C_LANGUAGE_STANDARD = c99; 296 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 297 | GCC_WARN_UNUSED_VARIABLE = YES; 298 | MACOSX_DEPLOYMENT_TARGET = 10.6; 299 | ONLY_ACTIVE_ARCH = YES; 300 | SDKROOT = macosx; 301 | }; 302 | name = Debug; 303 | }; 304 | 2CA326240896AD4900168862 /* Release */ = { 305 | isa = XCBuildConfiguration; 306 | buildSettings = { 307 | ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; 308 | CLANG_ENABLE_OBJC_ARC = YES; 309 | GCC_C_LANGUAGE_STANDARD = c99; 310 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 311 | GCC_WARN_UNUSED_VARIABLE = YES; 312 | MACOSX_DEPLOYMENT_TARGET = 10.6; 313 | SDKROOT = macosx; 314 | }; 315 | name = Release; 316 | }; 317 | /* End XCBuildConfiguration section */ 318 | 319 | /* Begin XCConfigurationList section */ 320 | 2CA3261E0896AD4900168862 /* Build configuration list for PBXNativeTarget "QuickLookCSV" */ = { 321 | isa = XCConfigurationList; 322 | buildConfigurations = ( 323 | 2CA3261F0896AD4900168862 /* Debug */, 324 | 2CA326200896AD4900168862 /* Release */, 325 | ); 326 | defaultConfigurationIsVisible = 0; 327 | defaultConfigurationName = Release; 328 | }; 329 | 2CA326220896AD4900168862 /* Build configuration list for PBXProject "QuickLookCSV" */ = { 330 | isa = XCConfigurationList; 331 | buildConfigurations = ( 332 | 2CA326230896AD4900168862 /* Debug */, 333 | 2CA326240896AD4900168862 /* Release */, 334 | ); 335 | defaultConfigurationIsVisible = 0; 336 | defaultConfigurationName = Release; 337 | }; 338 | /* End XCConfigurationList section */ 339 | }; 340 | rootObject = 089C1669FE841209C02AAC07 /* Project object */; 341 | } 342 | -------------------------------------------------------------------------------- /QuickLookCSV.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | A QuickLook Plugin for CSV Files 2 | ================================ 3 | 4 | Quick look **CSV files** for Mac OS X 10.5 and newer. 5 | Supports files separated by comma (`,`), tabs (`⇥`), semicolons (`;`) pipes (`|`). 6 | The plugin will generate Icons and show a preview, along with some information (like num rows/columns). 7 | Many thanks to Ted Fischer for valuable input and testing of version 1.1! 8 | 9 | Installation 10 | ------------ 11 | 12 | In order to use this Plugin, download [QuickLookCSV.dmg][dmg], open it by double-clicking and in there you will find the actual Plugin named **QuickLookCSV.qlgenerator**. 13 | 14 | Place the Plugin into `~/Library/QuickLook/` to install it for yourself only, or into `(Macintosh HD)/Library/QuickLook/` to install it for all users of your Mac. 15 | If the QuickLook-folder does not exist, simply create it manually. 16 | There are aliases to these directories in the disk image you have just downloaded, so you might be able to just drag the plugin onto one of the two aliases to install. 17 | 18 | Contributing 19 | ------------ 20 | 21 | If you're interested in contributing, fork the repo and send me a pull request via [GitHub][]. 22 | 23 | File Maker TSV Files 24 | -------------------- 25 | 26 | Some hacks were made in earlier versions to support FileMaker tab-separated-value files. 27 | Those hacks have been removed in Version 1.3. 28 | If this means your files no longer preview correctly, [download version 1.2][1.2] again, but please [let me know][issues]. 29 | 30 | 31 | Screenshots 32 | ----------- 33 | 34 | ![Icons](http://pp.hillrippers.ch/blog/2009/07/05/QuickLook%20Plugin%20for%20CSV%20files/Icons.png) 35 | ![Preview](http://pp.hillrippers.ch/blog/2009/07/05/QuickLook%20Plugin%20for%20CSV%20files/Preview_2.png) 36 | 37 | [dmg]: https://github.com/p2/quicklook-csv/releases/download/1.3/QuickLookCSV-1.3.dmg 38 | [github]: https://github.com/p2/quicklook-csv 39 | [issues]: https://github.com/p2/quicklook-csv/issues 40 | [1.2]: https://github.com/p2/quicklook-csv/releases/tag/1.2 41 | 42 | 43 | License 44 | ------- 45 | 46 | This work is [Apache 2](./LICENSE.txt) licensed: [NOTICE.txt](./NOTICE.txt). 47 | -------------------------------------------------------------------------------- /Style.css: -------------------------------------------------------------------------------- 1 | /* 2 | Style.css 3 | QuickLookCSV 4 | 5 | Created by Pascal Pfiffner on 03.07.09. 6 | This sourcecode is released under the Apache License, Version 2.0 7 | http://www.apache.org/licenses/LICENSE-2.0.html 8 | */ 9 | 10 | body { 11 | margin: 20px; 12 | font: small normal 'Lucida Grande', 'Helvetica Neue', sans-serif; 13 | background-color: rgb(242,242,242); 14 | } 15 | table { 16 | min-width: 100%; 17 | border: 1px solid rgb(170,170,170); border-collapse: separate; border-spacing: 0; -webkit-border-radius: 3px; 18 | box-shadow: 0 1px 0 rgba(255,255,255,0.8); 19 | } 20 | tr { background-color:white; } 21 | td { 22 | margin: 0; padding: 0.2em 0.4em; 23 | vertical-align: top; 24 | font-size: small; 25 | border-left: 1px solid rgb(170,170,170); 26 | } 27 | td:first-child { border-left: none; } 28 | tr:first-child td:first-child { -webkit-border-top-left-radius: 3px; } 29 | tr:first-child td:last-child { -webkit-border-top-right-radius: 3px; } 30 | tr:last-child td:first-child { -webkit-border-bottom-left-radius: 3px; } 31 | tr:last-child td:last-child { -webkit-border-bottom-right-radius: 3px; } 32 | 33 | .file_info { margin:0.5em 2px; color:rgb(20,20,20); text-shadow:rgba(255,255,255,0.8) 0 1px 0; } 34 | .alt_row { background-color:rgb(230,230,230); } 35 | .truncated_rows { margin:0.5em 2px; color:rgb(20,20,20); text-shadow:rgba(255,255,255,0.8) 0 1px 0; } 36 | -------------------------------------------------------------------------------- /Test/test.csv: -------------------------------------------------------------------------------- 1 | x,y,ex,ey 2 | 1.1,1.2,1.3,1.4 3 | 2.1,2.2,2.3,2.4 4 | 3.1,3.2,3.3,3.4 5 | 4.1,4.2,4.3,4.4 -------------------------------------------------------------------------------- /Test/testHeight.csv: -------------------------------------------------------------------------------- 1 | x,y,ex,ey 2 | 1.1,1.2,1.3,1.4 3 | 2.1,2.2,2.3,2.4 -------------------------------------------------------------------------------- /Test/testMini.csv: -------------------------------------------------------------------------------- 1 | x,y -------------------------------------------------------------------------------- /Test/testWidth.csv: -------------------------------------------------------------------------------- 1 | x,y 2 | 1.1,1.2 3 | 2.1,2.2 4 | 3.1,3.2 5 | 4.1,4.2 6 | 5.1,5.2 7 | 6.1,6.2 -------------------------------------------------------------------------------- /main.c: -------------------------------------------------------------------------------- 1 | //============================================================================== 2 | // 3 | // DO NO MODIFY THE CONTENT OF THIS FILE 4 | // 5 | // This file contains the generic CFPlug-in code necessary for your generator 6 | // To complete your generator implement the function in GenerateThumbnailForURL/GeneratePreviewForURL.c 7 | // 8 | //============================================================================== 9 | 10 | 11 | 12 | 13 | 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | // ----------------------------------------------------------------------------- 21 | // constants 22 | // ----------------------------------------------------------------------------- 23 | 24 | // Don't modify this line 25 | #define PLUGIN_ID "B096F0B5-6A04-4D69-9F69-44EDA8DF7FE8" 26 | 27 | // 28 | // Below is the generic glue code for all plug-ins. 29 | // 30 | // You should not have to modify this code aside from changing 31 | // names if you decide to change the names defined in the Info.plist 32 | // 33 | 34 | 35 | // ----------------------------------------------------------------------------- 36 | // typedefs 37 | // ----------------------------------------------------------------------------- 38 | 39 | // The thumbnail generation function to be implemented in GenerateThumbnailForURL.c 40 | OSStatus GenerateThumbnailForURL(void *thisInterface, QLThumbnailRequestRef thumbnail, CFURLRef url, CFStringRef contentTypeUTI, CFDictionaryRef options, CGSize maxSize); 41 | void CancelThumbnailGeneration(void* thisInterface, QLThumbnailRequestRef thumbnail); 42 | 43 | // The preview generation function to be implemented in GeneratePreviewForURL.c 44 | OSStatus GeneratePreviewForURL(void *thisInterface, QLPreviewRequestRef preview, CFURLRef url, CFStringRef contentTypeUTI, CFDictionaryRef options); 45 | void CancelPreviewGeneration(void *thisInterface, QLPreviewRequestRef preview); 46 | 47 | // The layout for an instance of QuickLookGeneratorPlugIn 48 | typedef struct __QuickLookGeneratorPluginType 49 | { 50 | void *conduitInterface; 51 | CFUUIDRef factoryID; 52 | UInt32 refCount; 53 | } QuickLookGeneratorPluginType; 54 | 55 | // ----------------------------------------------------------------------------- 56 | // prototypes 57 | // ----------------------------------------------------------------------------- 58 | // Forward declaration for the IUnknown implementation. 59 | // 60 | 61 | QuickLookGeneratorPluginType *AllocQuickLookGeneratorPluginType(CFUUIDRef inFactoryID); 62 | void DeallocQuickLookGeneratorPluginType(QuickLookGeneratorPluginType *thisInstance); 63 | HRESULT QuickLookGeneratorQueryInterface(void *thisInstance,REFIID iid,LPVOID *ppv); 64 | void *QuickLookGeneratorPluginFactory(CFAllocatorRef allocator,CFUUIDRef typeID); 65 | ULONG QuickLookGeneratorPluginAddRef(void *thisInstance); 66 | ULONG QuickLookGeneratorPluginRelease(void *thisInstance); 67 | 68 | // ----------------------------------------------------------------------------- 69 | // myInterfaceFtbl definition 70 | // ----------------------------------------------------------------------------- 71 | // The QLGeneratorInterfaceStruct function table. 72 | // 73 | static QLGeneratorInterfaceStruct myInterfaceFtbl = { 74 | NULL, 75 | QuickLookGeneratorQueryInterface, 76 | QuickLookGeneratorPluginAddRef, 77 | QuickLookGeneratorPluginRelease, 78 | NULL, 79 | NULL, 80 | NULL, 81 | NULL 82 | }; 83 | 84 | 85 | // ----------------------------------------------------------------------------- 86 | // AllocQuickLookGeneratorPluginType 87 | // ----------------------------------------------------------------------------- 88 | // Utility function that allocates a new instance. 89 | // You can do some initial setup for the generator here if you wish 90 | // like allocating globals etc... 91 | // 92 | QuickLookGeneratorPluginType *AllocQuickLookGeneratorPluginType(CFUUIDRef inFactoryID) 93 | { 94 | QuickLookGeneratorPluginType *theNewInstance; 95 | 96 | theNewInstance = (QuickLookGeneratorPluginType *)malloc(sizeof(QuickLookGeneratorPluginType)); 97 | memset(theNewInstance,0,sizeof(QuickLookGeneratorPluginType)); 98 | 99 | /* Point to the function table Malloc enough to store the stuff and copy the filler from myInterfaceFtbl over */ 100 | theNewInstance->conduitInterface = malloc(sizeof(QLGeneratorInterfaceStruct)); 101 | memcpy(theNewInstance->conduitInterface,&myInterfaceFtbl,sizeof(QLGeneratorInterfaceStruct)); 102 | 103 | /* Retain and keep an open instance refcount for each factory. */ 104 | theNewInstance->factoryID = CFRetain(inFactoryID); 105 | CFPlugInAddInstanceForFactory(inFactoryID); 106 | 107 | /* This function returns the IUnknown interface so set the refCount to one. */ 108 | theNewInstance->refCount = 1; 109 | return theNewInstance; 110 | } 111 | 112 | // ----------------------------------------------------------------------------- 113 | // DeallocQuickLookGeneratorPluginType 114 | // ----------------------------------------------------------------------------- 115 | // Utility function that deallocates the instance when 116 | // the refCount goes to zero. 117 | // In the current implementation generator interfaces are never deallocated 118 | // but implement this as this might change in the future 119 | // 120 | void DeallocQuickLookGeneratorPluginType(QuickLookGeneratorPluginType *thisInstance) 121 | { 122 | CFUUIDRef theFactoryID; 123 | 124 | theFactoryID = thisInstance->factoryID; 125 | /* Free the conduitInterface table up */ 126 | free(thisInstance->conduitInterface); 127 | 128 | /* Free the instance structure */ 129 | free(thisInstance); 130 | if (theFactoryID){ 131 | CFPlugInRemoveInstanceForFactory(theFactoryID); 132 | CFRelease(theFactoryID); 133 | } 134 | } 135 | 136 | // ----------------------------------------------------------------------------- 137 | // QuickLookGeneratorQueryInterface 138 | // ----------------------------------------------------------------------------- 139 | // Implementation of the IUnknown QueryInterface function. 140 | // 141 | HRESULT QuickLookGeneratorQueryInterface(void *thisInstance,REFIID iid,LPVOID *ppv) 142 | { 143 | CFUUIDRef interfaceID; 144 | 145 | interfaceID = CFUUIDCreateFromUUIDBytes(kCFAllocatorDefault,iid); 146 | 147 | if (CFEqual(interfaceID,kQLGeneratorCallbacksInterfaceID)){ 148 | /* If the Right interface was requested, bump the ref count, 149 | * set the ppv parameter equal to the instance, and 150 | * return good status. 151 | */ 152 | ((QLGeneratorInterfaceStruct *)((QuickLookGeneratorPluginType *)thisInstance)->conduitInterface)->GenerateThumbnailForURL = GenerateThumbnailForURL; 153 | ((QLGeneratorInterfaceStruct *)((QuickLookGeneratorPluginType *)thisInstance)->conduitInterface)->CancelThumbnailGeneration = CancelThumbnailGeneration; 154 | ((QLGeneratorInterfaceStruct *)((QuickLookGeneratorPluginType *)thisInstance)->conduitInterface)->GeneratePreviewForURL = GeneratePreviewForURL; 155 | ((QLGeneratorInterfaceStruct *)((QuickLookGeneratorPluginType *)thisInstance)->conduitInterface)->CancelPreviewGeneration = CancelPreviewGeneration; 156 | ((QLGeneratorInterfaceStruct *)((QuickLookGeneratorPluginType*)thisInstance)->conduitInterface)->AddRef(thisInstance); 157 | *ppv = thisInstance; 158 | CFRelease(interfaceID); 159 | return S_OK; 160 | }else{ 161 | /* Requested interface unknown, bail with error. */ 162 | *ppv = NULL; 163 | CFRelease(interfaceID); 164 | return E_NOINTERFACE; 165 | } 166 | } 167 | 168 | // ----------------------------------------------------------------------------- 169 | // QuickLookGeneratorPluginAddRef 170 | // ----------------------------------------------------------------------------- 171 | // Implementation of reference counting for this type. Whenever an interface 172 | // is requested, bump the refCount for the instance. NOTE: returning the 173 | // refcount is a convention but is not required so don't rely on it. 174 | // 175 | ULONG QuickLookGeneratorPluginAddRef(void *thisInstance) 176 | { 177 | ((QuickLookGeneratorPluginType *)thisInstance )->refCount += 1; 178 | return ((QuickLookGeneratorPluginType*) thisInstance)->refCount; 179 | } 180 | 181 | // ----------------------------------------------------------------------------- 182 | // QuickLookGeneratorPluginRelease 183 | // ----------------------------------------------------------------------------- 184 | // When an interface is released, decrement the refCount. 185 | // If the refCount goes to zero, deallocate the instance. 186 | // 187 | ULONG QuickLookGeneratorPluginRelease(void *thisInstance) 188 | { 189 | ((QuickLookGeneratorPluginType*)thisInstance)->refCount -= 1; 190 | if (((QuickLookGeneratorPluginType*)thisInstance)->refCount == 0){ 191 | DeallocQuickLookGeneratorPluginType((QuickLookGeneratorPluginType*)thisInstance ); 192 | return 0; 193 | }else{ 194 | return ((QuickLookGeneratorPluginType*) thisInstance )->refCount; 195 | } 196 | } 197 | 198 | // ----------------------------------------------------------------------------- 199 | // QuickLookGeneratorPluginFactory 200 | // ----------------------------------------------------------------------------- 201 | void *QuickLookGeneratorPluginFactory(CFAllocatorRef allocator,CFUUIDRef typeID) 202 | { 203 | QuickLookGeneratorPluginType *result; 204 | CFUUIDRef uuid; 205 | 206 | /* If correct type is being requested, allocate an 207 | * instance of kQLGeneratorTypeID and return the IUnknown interface. 208 | */ 209 | if (CFEqual(typeID,kQLGeneratorTypeID)){ 210 | uuid = CFUUIDCreateFromString(kCFAllocatorDefault,CFSTR(PLUGIN_ID)); 211 | result = AllocQuickLookGeneratorPluginType(uuid); 212 | CFRelease(uuid); 213 | return result; 214 | } 215 | /* If the requested type is incorrect, return NULL. */ 216 | return NULL; 217 | } 218 | 219 | --------------------------------------------------------------------------------