Add support for QuickLook in 10.6+

In 10.6 Apple removed the private QL API that existed in 10.5 and added a new public API. However they did not port the new API back to 10.5 so we have to do some work to get it working in both.

This patch has GitX choose the correct version at run time.
    - The delegate code is based on Apple's QuickLookDownloader example project
    - added three of the public API methods to CWQuickLook.h to avoid warnings about unknown method calls
    - In ApplicationController try to load the public API first then load the private one if it fails
    - Created PBQLTextView, a subclass of NSTextView to allow the space key event to toggle the preview panel
    - PBGitHistoryView.xib:
        - set the text view's class to PBQLTextView
        - connected the history controller to the controller outlet
        - bound the quick look button's enabled binding to File's Owner.selectedCommitDetailsIndex
        - added "Quick Look" to the quick look button's tooltip
    - The commit list table view toggles the panel if the tree view is active
    - changed name of the toggle IBAction method which caused MainMenu.xib and PBGitHistoryView.xib to update
This commit is contained in:
Nathan Kinsinger
2010-03-21 15:52:46 -06:00
parent 9236b801a8
commit 6a8f495318
11 changed files with 272 additions and 50 deletions
+3 -2
View File
@@ -28,8 +28,9 @@
#endif
if(self = [super init]) {
if(![[NSBundle bundleWithPath:@"/System/Library/PrivateFrameworks/QuickLookUI.framework"] load])
NSLog(@"Could not load QuickLook");
if(![[NSBundle bundleWithPath:@"/System/Library/Frameworks/Quartz.framework/Frameworks/QuickLookUI.framework"] load])
if(![[NSBundle bundleWithPath:@"/System/Library/PrivateFrameworks/QuickLookUI.framework"] load])
NSLog(@"Could not load QuickLook");
self.cliProxy = [PBCLIProxy new];
}
+7
View File
@@ -1,5 +1,12 @@
@interface QLPreviewPanel : NSPanel
+ (id)sharedPreviewPanel;
// part of the public QL API
+ (BOOL)sharedPreviewPanelExists;
- (void)reloadData;
- (void)setDataSource:(id)source;
// the private QL API
+ (id)_previewPanel;
+ (BOOL)isSharedPreviewPanelLoaded;
- (id)initWithContentRect:(struct _NSRect)fp8 styleMask:(unsigned int)fp24 backing:(unsigned int)fp28 defer:(BOOL)fp32;
+16 -4
View File
@@ -3,16 +3,15 @@
<data>
<int key="IBDocument.SystemTarget">1050</int>
<string key="IBDocument.SystemVersion">10C540</string>
<string key="IBDocument.InterfaceBuilderVersion">759</string>
<string key="IBDocument.InterfaceBuilderVersion">762</string>
<string key="IBDocument.AppKitVersion">1038.25</string>
<string key="IBDocument.HIToolboxVersion">458.00</string>
<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="NS.object.0">759</string>
<string key="NS.object.0">762</string>
</object>
<object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
<bool key="EncodedWithXMLCoder">YES</bool>
<integer value="339"/>
</object>
<object class="NSArray" key="IBDocument.PluginDependencies">
<bool key="EncodedWithXMLCoder">YES</bool>
@@ -2723,7 +2722,7 @@
<string>showAddRemoteSheet:</string>
<string>showCommitsFromTree:</string>
<string>showInFinderAction:</string>
<string>toggleQuickView:</string>
<string>toggleQLPreviewPanel:</string>
</object>
<object class="NSMutableArray" key="dict.values">
<bool key="EncodedWithXMLCoder">YES</bool>
@@ -3888,5 +3887,18 @@
<bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
<string key="IBDocument.LastKnownRelativeProjectPath">../GitX.xcodeproj</string>
<int key="IBDocument.defaultPropertyAccessControl">3</int>
<object class="NSMutableDictionary" key="IBDocument.LastKnownImageSizes">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSArray" key="dict.sortedKeys">
<bool key="EncodedWithXMLCoder">YES</bool>
<string>NSMenuCheckmark</string>
<string>NSMenuMixedState</string>
</object>
<object class="NSMutableArray" key="dict.values">
<bool key="EncodedWithXMLCoder">YES</bool>
<string>{9, 8}</string>
<string>{7, 2}</string>
</object>
</object>
</data>
</archive>
+6
View File
@@ -70,6 +70,7 @@
D8A4BD071134AD2900E92D51 /* CherryPickTemplate.png in Resources */ = {isa = PBXBuildFile; fileRef = D8A4BD041134AD2900E92D51 /* CherryPickTemplate.png */; };
D8A4BD081134AD2900E92D51 /* MergeTemplate.png in Resources */ = {isa = PBXBuildFile; fileRef = D8A4BD051134AD2900E92D51 /* MergeTemplate.png */; };
D8A4BD091134AD2900E92D51 /* RebaseTemplate.png in Resources */ = {isa = PBXBuildFile; fileRef = D8A4BD061134AD2900E92D51 /* RebaseTemplate.png */; };
D8E105471157C18200FC28A4 /* PBQLTextView.m in Sources */ = {isa = PBXBuildFile; fileRef = D8E105461157C18200FC28A4 /* PBQLTextView.m */; };
D8E3B2B810DC9FB2001096A3 /* ScriptingBridge.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D8E3B2B710DC9FB2001096A3 /* ScriptingBridge.framework */; };
D8E3B34D10DCA958001096A3 /* PBCreateTagSheet.m in Sources */ = {isa = PBXBuildFile; fileRef = D8E3B34C10DCA958001096A3 /* PBCreateTagSheet.m */; };
D8FDD9F711432A12005647F6 /* PBCloneRepositoryPanel.xib in Resources */ = {isa = PBXBuildFile; fileRef = D8FDD9F511432A12005647F6 /* PBCloneRepositoryPanel.xib */; };
@@ -286,6 +287,8 @@
D8A4BD051134AD2900E92D51 /* MergeTemplate.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = MergeTemplate.png; path = Images/MergeTemplate.png; sourceTree = "<group>"; };
D8A4BD061134AD2900E92D51 /* RebaseTemplate.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = RebaseTemplate.png; path = Images/RebaseTemplate.png; sourceTree = "<group>"; };
D8C1B77210E875CF009B7F8B /* English */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = English; path = English.lproj/PBRemoteProgressSheet.xib; sourceTree = "<group>"; };
D8E105451157C18200FC28A4 /* PBQLTextView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBQLTextView.h; sourceTree = "<group>"; };
D8E105461157C18200FC28A4 /* PBQLTextView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PBQLTextView.m; sourceTree = "<group>"; };
D8E3B2B710DC9FB2001096A3 /* ScriptingBridge.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ScriptingBridge.framework; path = /System/Library/Frameworks/ScriptingBridge.framework; sourceTree = "<absolute>"; };
D8E3B34B10DCA958001096A3 /* PBCreateTagSheet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBCreateTagSheet.h; sourceTree = "<group>"; };
D8E3B34C10DCA958001096A3 /* PBCreateTagSheet.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PBCreateTagSheet.m; sourceTree = "<group>"; };
@@ -729,6 +732,8 @@
F53EE3590E06BBA00022B925 /* CWQuickLook.h */,
F51308590E0740F2000C8BCD /* PBQLOutlineView.h */,
F513085A0E0740F2000C8BCD /* PBQLOutlineView.m */,
D8E105451157C18200FC28A4 /* PBQLTextView.h */,
D8E105461157C18200FC28A4 /* PBQLTextView.m */,
91B103CA0E898EC300C84364 /* PBIconAndTextCell.h */,
91B103CB0E898EC300C84364 /* PBIconAndTextCell.m */,
F5140DC70E8A8EB20091E9F3 /* RoundedRectangle.h */,
@@ -1175,6 +1180,7 @@
D828A4111127B1C400F09D11 /* PBSourceViewBadge.m in Sources */,
D8295D2A1130A1DC00C838E8 /* PBGitHistoryList.m in Sources */,
D8295DE01130E43900C838E8 /* PBGitHistoryGrapher.m in Sources */,
D8E105471157C18200FC28A4 /* PBQLTextView.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
+8 -5
View File
@@ -28,12 +28,15 @@
return;
}
if ([character isEqualToString:@" "])
{
if ([event modifierFlags] & NSShiftKeyMask)
[webView scrollPageUp: self];
if ([character isEqualToString:@" "]) {
if (controller.selectedCommitDetailsIndex == 0) {
if ([event modifierFlags] & NSShiftKeyMask)
[webView scrollPageUp:self];
else
[webView scrollPageDown:self];
}
else
[webView scrollPageDown: self];
[controller toggleQLPreviewPanel:self];
}
else if ([character rangeOfCharacterFromSet:[NSCharacterSet characterSetWithCharactersInString:@"jkcv"]].location == 0)
[webController sendKey: character];
+3 -1
View File
@@ -15,6 +15,7 @@
@class PBGitSidebarController;
@class PBGitGradientBarView;
@class PBRefController;
@class QLPreviewPanel;
@interface PBGitHistoryController : PBViewController {
IBOutlet PBRefController *refController;
@@ -24,6 +25,7 @@
IBOutlet NSOutlineView* fileBrowser;
IBOutlet NSTableView* commitList;
IBOutlet PBCollapsibleSplitView *historySplitView;
QLPreviewPanel* previewPanel;
IBOutlet PBGitGradientBarView *upperToolbarView;
IBOutlet NSButton *mergeButton;
@@ -56,7 +58,7 @@
- (void) selectCommit: (NSString*) commit;
- (IBAction) refresh: sender;
- (IBAction) toggleQuickView: sender;
- (IBAction) toggleQLPreviewPanel:(id)sender;
- (IBAction) openSelectedFile: sender;
- (void) updateQuicklookForce: (BOOL) force;
+115 -23
View File
@@ -245,36 +245,49 @@
}
- (IBAction) toggleQuickView: sender
- (IBAction) toggleQLPreviewPanel:(id)sender
{
id panel = [QLPreviewPanel sharedPreviewPanel];
if ([panel isOpen]) {
[panel closePanel];
} else {
[[QLPreviewPanel sharedPreviewPanel] makeKeyAndOrderFrontWithEffect:1];
[self updateQuicklookForce: YES];
if ([[QLPreviewPanel sharedPreviewPanel] respondsToSelector:@selector(setDataSource:)]) {
// Public QL API
if ([QLPreviewPanel sharedPreviewPanelExists] && [[QLPreviewPanel sharedPreviewPanel] isVisible])
[[QLPreviewPanel sharedPreviewPanel] orderOut:nil];
else
[[QLPreviewPanel sharedPreviewPanel] makeKeyAndOrderFront:nil];
}
else {
// Private QL API (10.5 only)
if ([[QLPreviewPanel sharedPreviewPanel] isOpen])
[[QLPreviewPanel sharedPreviewPanel] closePanel];
else {
[[QLPreviewPanel sharedPreviewPanel] makeKeyAndOrderFrontWithEffect:1];
[self updateQuicklookForce:YES];
}
}
}
- (void) updateQuicklookForce: (BOOL) force
- (void) updateQuicklookForce:(BOOL)force
{
if (!force && ![[QLPreviewPanel sharedPreviewPanel] isOpen])
return;
NSArray* selectedFiles = [treeController selectedObjects];
if ([selectedFiles count] == 0)
return;
NSMutableArray* fileNames = [NSMutableArray array];
for (PBGitTree* tree in selectedFiles) {
NSString* s = [tree tmpFileNameForContents];
if (s)
[fileNames addObject:[NSURL fileURLWithPath: s]];
if ([[QLPreviewPanel sharedPreviewPanel] respondsToSelector:@selector(setDataSource:)]) {
// Public QL API
[previewPanel reloadData];
}
else {
// Private QL API (10.5 only)
NSArray *selectedFiles = [treeController selectedObjects];
NSMutableArray *fileNames = [NSMutableArray array];
for (PBGitTree *tree in selectedFiles) {
NSString *filePath = [tree tmpFileNameForContents];
if (filePath)
[fileNames addObject:[NSURL fileURLWithPath:filePath]];
}
if ([fileNames count])
[[QLPreviewPanel sharedPreviewPanel] setURLs:fileNames currentIndex:0 preservingDisplayState:YES];
}
[[QLPreviewPanel sharedPreviewPanel] setURLs:fileNames currentIndex:0 preservingDisplayState:YES];
}
- (IBAction) refresh: sender
@@ -535,6 +548,85 @@
[repository rebaseBranch:headRef onRefish:selectedCommit];
}
}
#pragma mark -
#pragma mark Quick Look Public API support
@protocol QLPreviewItem;
#pragma mark (QLPreviewPanelController)
- (BOOL) acceptsPreviewPanelControl:(id)panel
{
return YES;
}
- (void)beginPreviewPanelControl:(id)panel
{
// This document is now responsible of the preview panel
// It is allowed to set the delegate, data source and refresh panel.
previewPanel = panel;
[previewPanel setDelegate:self];
[previewPanel setDataSource:self];
}
- (void)endPreviewPanelControl:(id)panel
{
// This document loses its responsisibility on the preview panel
// Until the next call to -beginPreviewPanelControl: it must not
// change the panel's delegate, data source or refresh it.
previewPanel = nil;
}
#pragma mark <QLPreviewPanelDataSource>
- (NSInteger)numberOfPreviewItemsInPreviewPanel:(id)panel
{
return [[fileBrowser selectedRowIndexes] count];
}
- (id <QLPreviewItem>)previewPanel:(id)panel previewItemAtIndex:(NSInteger)index
{
PBGitTree *treeItem = (PBGitTree *)[[treeController selectedObjects] objectAtIndex:index];
NSURL *previewURL = [NSURL fileURLWithPath:[treeItem tmpFileNameForContents]];
return (<QLPreviewItem>)previewURL;
}
#pragma mark <QLPreviewPanelDelegate>
- (BOOL)previewPanel:(id)panel handleEvent:(NSEvent *)event
{
// redirect all key down events to the table view
if ([event type] == NSKeyDown) {
[fileBrowser keyDown:event];
return YES;
}
return NO;
}
// This delegate method provides the rect on screen from which the panel will zoom.
- (NSRect)previewPanel:(id)panel sourceFrameOnScreenForPreviewItem:(id <QLPreviewItem>)item
{
NSInteger index = [fileBrowser rowForItem:[[treeController selectedNodes] objectAtIndex:0]];
if (index == NSNotFound) {
return NSZeroRect;
}
NSRect iconRect = [fileBrowser frameOfCellAtColumn:0 row:index];
// check that the icon rect is visible on screen
NSRect visibleRect = [fileBrowser visibleRect];
if (!NSIntersectsRect(visibleRect, iconRect)) {
return NSZeroRect;
}
// convert icon rect to screen coordinates
iconRect = [fileBrowser convertRectToBase:iconRect];
iconRect.origin = [[fileBrowser window] convertBaseToScreen:iconRect.origin];
return iconRect;
}
@end
+69 -14
View File
@@ -3,7 +3,7 @@
<data>
<int key="IBDocument.SystemTarget">1050</int>
<string key="IBDocument.SystemVersion">10C540</string>
<string key="IBDocument.InterfaceBuilderVersion">759</string>
<string key="IBDocument.InterfaceBuilderVersion">762</string>
<string key="IBDocument.AppKitVersion">1038.25</string>
<string key="IBDocument.HIToolboxVersion">458.00</string>
<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
@@ -15,13 +15,13 @@
</object>
<object class="NSMutableArray" key="dict.values">
<bool key="EncodedWithXMLCoder">YES</bool>
<string>759</string>
<string>759</string>
<string>762</string>
<string>762</string>
</object>
</object>
<object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
<bool key="EncodedWithXMLCoder">YES</bool>
<integer value="3"/>
<integer value="312"/>
</object>
<object class="NSArray" key="IBDocument.PluginDependencies">
<bool key="EncodedWithXMLCoder">YES</bool>
@@ -1400,14 +1400,6 @@
</object>
<int key="connectionID">62</int>
</object>
<object class="IBConnectionRecord">
<object class="IBActionConnection" key="connection">
<string key="label">toggleQuickView:</string>
<reference key="source" ref="1001"/>
<reference key="destination" ref="16222431"/>
</object>
<int key="connectionID">66</int>
</object>
<object class="IBConnectionRecord">
<object class="IBBindingConnection" key="connection">
<string key="label">selectedIndex: selectedCommitDetailsIndex</string>
@@ -1926,6 +1918,38 @@
</object>
<int key="connectionID">393</int>
</object>
<object class="IBConnectionRecord">
<object class="IBActionConnection" key="connection">
<string key="label">toggleQLPreviewPanel:</string>
<reference key="source" ref="1001"/>
<reference key="destination" ref="16222431"/>
</object>
<int key="connectionID">395</int>
</object>
<object class="IBConnectionRecord">
<object class="IBOutletConnection" key="connection">
<string key="label">controller</string>
<reference key="source" ref="75600241"/>
<reference key="destination" ref="1001"/>
</object>
<int key="connectionID">396</int>
</object>
<object class="IBConnectionRecord">
<object class="IBBindingConnection" key="connection">
<string key="label">enabled: selectedCommitDetailsIndex</string>
<reference key="source" ref="16222431"/>
<reference key="destination" ref="1001"/>
<object class="NSNibBindingConnector" key="connector">
<reference key="NSSource" ref="16222431"/>
<reference key="NSDestination" ref="1001"/>
<string key="NSLabel">enabled: selectedCommitDetailsIndex</string>
<string key="NSBinding">enabled</string>
<string key="NSKeyPath">selectedCommitDetailsIndex</string>
<int key="NSNibBindingConnectorVersion">2</int>
</object>
</object>
<int key="connectionID">398</int>
</object>
</object>
<object class="IBMutableOrderedSet" key="objectRecords">
<object class="NSArray" key="orderedObjects">
@@ -2480,6 +2504,7 @@
<string>-3.IBPluginDependency</string>
<string>10.IBPluginDependency</string>
<string>11.IBPluginDependency</string>
<string>12.CustomClassName</string>
<string>12.IBPluginDependency</string>
<string>13.IBPluginDependency</string>
<string>14.IBPluginDependency</string>
@@ -2568,6 +2593,7 @@
<string>46.IBEditorWindowLastContentRect</string>
<string>46.IBPluginDependency</string>
<string>48.IBPluginDependency</string>
<string>49.IBAttributePlaceholdersKey</string>
<string>49.IBPluginDependency</string>
<string>50.IBPluginDependency</string>
<string>51.IBPluginDependency</string>
@@ -2581,6 +2607,7 @@
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>PBQLTextView</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
@@ -2737,6 +2764,14 @@
<string>{{627, 791}, {852, 432}}</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<object class="NSMutableDictionary">
<string key="NS.key.0">ToolTip</string>
<object class="IBToolTipAttribute" key="NS.object.0">
<string key="name">ToolTip</string>
<reference key="object" ref="16222431"/>
<string key="toolTip">Quick Look</string>
</object>
</object>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
@@ -2762,7 +2797,7 @@
</object>
</object>
<nil key="sourceID"/>
<int key="maxID">393</int>
<int key="maxID">398</int>
</object>
<object class="IBClassDescriber" key="IBDocument.Classes">
<object class="NSMutableArray" key="referencedPartialClassDescriptions">
@@ -2842,7 +2877,7 @@
<string>showAddRemoteSheet:</string>
<string>showCommitsFromTree:</string>
<string>showInFinderAction:</string>
<string>toggleQuickView:</string>
<string>toggleQLPreviewPanel:</string>
</object>
<object class="NSMutableArray" key="dict.values">
<bool key="EncodedWithXMLCoder">YES</bool>
@@ -2958,6 +2993,18 @@
<string key="minorKey">PBQLOutlineView.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">PBQLTextView</string>
<string key="superclassName">NSTextView</string>
<object class="NSMutableDictionary" key="outlets">
<string key="NS.key.0">controller</string>
<string key="NS.object.0">PBGitHistoryController</string>
</object>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">PBQLTextView.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">PBRefController</string>
<string key="superclassName">NSObject</string>
@@ -3049,6 +3096,10 @@
<object class="IBPartialClassDescription">
<string key="className">PBViewController</string>
<string key="superclassName">NSViewController</string>
<object class="NSMutableDictionary" key="actions">
<string key="NS.key.0">refresh:</string>
<string key="NS.object.0">id</string>
</object>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">PBViewController.h</string>
@@ -3847,7 +3898,9 @@
<string>AddBranchTemplate</string>
<string>AddLabelTemplate</string>
<string>CherryPickTemplate</string>
<string>DetailViewTemplate</string>
<string>MergeTemplate</string>
<string>NSPathTemplate</string>
<string>NSQuickLookTemplate</string>
<string>RebaseTemplate</string>
</object>
@@ -3856,7 +3909,9 @@
<string>{20, 12}</string>
<string>{23, 12}</string>
<string>{18.5143, 12.3429}</string>
<string>{17, 17}</string>
<string>{16.4571, 12.3429}</string>
<string>{16, 9}</string>
<string>{19, 11}</string>
<string>{16.4571, 13.3714}</string>
</object>
+1 -1
View File
@@ -28,7 +28,7 @@
- (void) keyDown: (NSEvent *) event
{
if ([[event characters] isEqualToString:@" "]) {
[controller toggleQuickView:self];
[controller toggleQLPreviewPanel:self];
return;
}
+19
View File
@@ -0,0 +1,19 @@
//
// PBQLTextView.h
// GitX
//
// Created by Nathan Kinsinger on 3/22/10.
// Copyright 2010 Nathan Kinsinger. All rights reserved.
//
#import <Cocoa/Cocoa.h>
@class PBGitHistoryController;
@interface PBQLTextView : NSTextView {
IBOutlet PBGitHistoryController *controller;
}
@end
+25
View File
@@ -0,0 +1,25 @@
//
// PBQLTextView.m
// GitX
//
// Created by Nathan Kinsinger on 3/22/10.
// Copyright 2010 Nathan Kinsinger. All rights reserved.
//
#import "PBQLTextView.h"
#import "PBGitHistoryController.h"
@implementation PBQLTextView
- (void) keyDown: (NSEvent *) event
{
if ([[event characters] isEqualToString:@" "]) {
[controller toggleQLPreviewPanel:self];
return;
}
[super keyDown:event];
}
@end