diff --git a/Transmission.xcodeproj/project.pbxproj b/Transmission.xcodeproj/project.pbxproj index 6392cfad9..b80cf83f4 100644 --- a/Transmission.xcodeproj/project.pbxproj +++ b/Transmission.xcodeproj/project.pbxproj @@ -213,6 +213,7 @@ A2DA362B0CBC674900C2ED41 /* InfoFiles.png in Resources */ = {isa = PBXBuildFile; fileRef = A2DA36280CBC674900C2ED41 /* InfoFiles.png */; }; A2DA362C0CBC674900C2ED41 /* InfoPeers.png in Resources */ = {isa = PBXBuildFile; fileRef = A2DA36290CBC674900C2ED41 /* InfoPeers.png */; }; A2DF37070C220D03006523C1 /* CreatorWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = A2DF37050C220D03006523C1 /* CreatorWindowController.m */; }; + A2DF567D0DE323D3000795D5 /* QuickLook.h in Headers */ = {isa = PBXBuildFile; fileRef = A2DF567C0DE323D3000795D5 /* QuickLook.h */; }; A2E23AC60CB5E1930002BB25 /* InfoTabButtonCell.m in Sources */ = {isa = PBXBuildFile; fileRef = A2E23AC40CB5E1930002BB25 /* InfoTabButtonCell.m */; }; A2E9AA760C249AF400085DCF /* Create.png in Resources */ = {isa = PBXBuildFile; fileRef = A2E9AA750C249AF400085DCF /* Create.png */; }; A2ED7D8F0CEF431B00970975 /* FilterButton.m in Sources */ = {isa = PBXBuildFile; fileRef = A2ED7D8E0CEF431B00970975 /* FilterButton.m */; }; @@ -680,6 +681,7 @@ A2DA36290CBC674900C2ED41 /* InfoPeers.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = InfoPeers.png; path = macosx/Images/InfoPeers.png; sourceTree = ""; }; A2DF37040C220D03006523C1 /* CreatorWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CreatorWindowController.h; path = macosx/CreatorWindowController.h; sourceTree = ""; }; A2DF37050C220D03006523C1 /* CreatorWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CreatorWindowController.m; path = macosx/CreatorWindowController.m; sourceTree = ""; }; + A2DF567C0DE323D3000795D5 /* QuickLook.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = QuickLook.h; path = macosx/QuickLook.h; sourceTree = ""; }; A2E23AC30CB5E1930002BB25 /* InfoTabButtonCell.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = InfoTabButtonCell.h; path = macosx/InfoTabButtonCell.h; sourceTree = ""; }; A2E23AC40CB5E1930002BB25 /* InfoTabButtonCell.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; name = InfoTabButtonCell.m; path = macosx/InfoTabButtonCell.m; sourceTree = ""; }; A2E9AA750C249AF400085DCF /* Create.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Create.png; path = macosx/Images/Create.png; sourceTree = ""; }; @@ -949,6 +951,7 @@ A2FB701B0D95CAEA0001F331 /* GroupsController.m */, A2D307A20D9EC6870051FD27 /* BlocklistDownloader.h */, A2D307A30D9EC6870051FD27 /* BlocklistDownloader.m */, + A2DF567C0DE323D3000795D5 /* QuickLook.h */, ); name = Sources; sourceTree = ""; @@ -1478,6 +1481,7 @@ A2A4E9FF0DE1065B000CE197 /* md5.h in Headers */, A2A4EA000DE1065C000CE197 /* config.h in Headers */, A2A4EA010DE1065D000CE197 /* compat_unix.h in Headers */, + A2DF567D0DE323D3000795D5 /* QuickLook.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/macosx/FileOutlineController.h b/macosx/FileOutlineController.h index 1d84146fc..4e9a8d03a 100644 --- a/macosx/FileOutlineController.h +++ b/macosx/FileOutlineController.h @@ -32,6 +32,8 @@ Torrent * fTorrent; IBOutlet FileOutlineView * fOutline; + + BOOL fQuickLookAvailable; } - (void) setTorrent: (Torrent *) torrent; @@ -44,4 +46,13 @@ - (void) revealFile: (id) sender; +- (void) userDidPressSpaceInOutlineView: (id) outlineView; +- (void) userDidPressRightInOutlineView: (id) outlineView; +- (void) userDidPressLeftInOutlineView: (id) outlineView; + +- (BOOL) quickLookSelectedItems; +- (int) visibleRowWithURL: (NSURL*) url; + +- (void) fileTabClosed; + @end diff --git a/macosx/FileOutlineController.m b/macosx/FileOutlineController.m index ddd95c32c..1cbc8d89a 100644 --- a/macosx/FileOutlineController.m +++ b/macosx/FileOutlineController.m @@ -28,6 +28,9 @@ #import "FilePriorityCell.h" #import "NSApplicationAdditions.h" +#import "QuickLook.h" +#define QLPreviewPanel NSClassFromString(@"QLPreviewPanel") + #define ROW_SMALL_HEIGHT 18.0 typedef enum @@ -62,7 +65,13 @@ typedef enum [[fOutline tableColumnWithIdentifier: @"Check"] setHeaderToolTip: NSLocalizedString(@"Download", "file table -> header tool tip")]; [[fOutline tableColumnWithIdentifier: @"Priority"] setHeaderToolTip: NSLocalizedString(@"Priority", - "file table -> header tool tip")]; + "file table -> header tool tip")]; + + //load the QuickLook framework and set the delegate, no point on trying this on Tiger + //animation types: 0 = none; 1 = fade; 2 = zoom + fQuickLookAvailable = [[NSBundle bundleWithPath:@"/System/Library/PrivateFrameworks/QuickLookUI.framework"] load]; + if (fQuickLookAvailable) + [[[QLPreviewPanel sharedPreviewPanel] windowController] setDelegate: self]; } [fOutline setMenu: [self menu]]; @@ -70,6 +79,118 @@ typedef enum [self setTorrent: nil]; } +- (void) fileTabClosed +{ + if (fQuickLookAvailable) + { + if ([[QLPreviewPanel sharedPreviewPanel] isOpen]) + [[QLPreviewPanel sharedPreviewPanel] closeWithEffect: 1]; + } +} + +// This is the QuickLook delegate method +// It should return the frame for the item represented by the URL +// If an empty frame is returned then the panel will fade in/out instead +- (NSRect) previewPanel: (NSPanel *) panel frameForURL: (NSURL *) url +{ + NSRect frame = NSMakeRect(0, 0, 0, 0); + int row = [self visibleRowWithURL: url]; + + if (row != -1) + { + frame = [fOutline rectOfRow:row]; + frame.origin = [fOutline convertPoint: frame.origin toView: nil]; + frame.origin = [[fOutline window] convertBaseToScreen: frame.origin]; + frame.origin.y -= frame.size.height; + } + + return frame; +} + +- (int) visibleRowWithURL: (NSURL *) url +{ + NSString * fullPath = [url path]; + NSString * folder = [fTorrent downloadFolder]; + NSRange visibleRows = [fOutline rowsInRect: [fOutline bounds]]; + + int row; + for (row = visibleRows.location; row <= row + visibleRows.length; row++) + { + id rowItem = [fOutline itemAtRow: row]; + if ([[folder stringByAppendingPathComponent: [rowItem objectForKey: @"Path"]] isEqualToString: fullPath]) + return row; + } + return -1; +} + +- (void) userDidPressSpaceInOutlineView: (id) outlineView +{ + if (fQuickLookAvailable) + { + if ([[QLPreviewPanel sharedPreviewPanel] isOpen]) + [[QLPreviewPanel sharedPreviewPanel] closeWithEffect: 2]; + else + { + if ([self quickLookSelectedItems]) + { + [[QLPreviewPanel sharedPreviewPanel] makeKeyAndOrderFrontWithEffect: 2]; + // Restore the focus to our window to demo the selection changing, scrolling (left/right) + // and closing (space) functionality + [[fOutline window] makeKeyWindow]; + } + } + } +} + +- (void) userDidPressRightInOutlineView: (id) outlineView +{ + if (fQuickLookAvailable && [[QLPreviewPanel sharedPreviewPanel] isOpen]) + [[QLPreviewPanel sharedPreviewPanel] selectNextItem]; +} + +- (void) userDidPressLeftInOutlineView: (id) outlineView +{ + if (fQuickLookAvailable && [[QLPreviewPanel sharedPreviewPanel] isOpen]) + [[QLPreviewPanel sharedPreviewPanel] selectPreviousItem]; +} + +- (BOOL) quickLookSelectedItems +{ + if (fQuickLookAvailable) + { + NSString * folder = [fTorrent downloadFolder]; + NSIndexSet * indexes = [fOutline selectedRowIndexes]; + NSMutableArray * urlArray = [NSMutableArray arrayWithCapacity: [indexes count]]; + + int i; + for (i = [indexes firstIndex]; i != NSNotFound; i = [indexes indexGreaterThanIndex: i]) + { + id item = [fOutline itemAtRow: i]; + if ([[item objectForKey: @"IsFolder"] boolValue] + || [fTorrent fileProgress: [[item objectForKey: @"Indexes"] firstIndex]] == 1.0) + [urlArray addObject: [NSURL fileURLWithPath: [folder stringByAppendingPathComponent: [item objectForKey: @"Path"]]]]; + } + + if ([urlArray count]) + { + [[QLPreviewPanel sharedPreviewPanel] setURLs: urlArray currentIndex: 0 preservingDisplayState: YES]; + return YES; + } + else + return NO; + } +} + +- (void) outlineViewSelectionDidChange: (NSNotification *) notification +{ + if (fQuickLookAvailable) + { + // If the user changes the selection while the panel is open then update the current items + if ([[QLPreviewPanel sharedPreviewPanel] isOpen] && ![self quickLookSelectedItems]) + [[QLPreviewPanel sharedPreviewPanel] closeWithEffect: 1]; + } +} + - (void) setTorrent: (Torrent *) torrent { fTorrent = torrent; diff --git a/macosx/FileOutlineView.m b/macosx/FileOutlineView.m index 5f453248b..38edc5e16 100644 --- a/macosx/FileOutlineView.m +++ b/macosx/FileOutlineView.m @@ -23,6 +23,7 @@ *****************************************************************************/ #import "FileOutlineView.h" +#import "FileOutlineController.h" #import "FileNameCell.h" #import "FilePriorityCell.h" #import "Torrent.h" @@ -83,6 +84,20 @@ [super mouseDown: event]; } +- (void) keyDown: (NSEvent *) event +{ + unichar firstChar = [[event charactersIgnoringModifiers] characterAtIndex: 0]; + if (firstChar == ' ') + [(FileOutlineController *)[super delegate] userDidPressSpaceInOutlineView: self]; + else if (firstChar == NSRightArrowFunctionKey) + [(FileOutlineController *)[super delegate] userDidPressRightInOutlineView: self]; + else if (firstChar == NSLeftArrowFunctionKey) + [(FileOutlineController *)[super delegate] userDidPressLeftInOutlineView: self]; + else; + + [super keyDown: event]; +} + - (NSMenu *) menuForEvent: (NSEvent *) event { int row = [self rowAtPoint: [self convertPoint: [event locationInWindow] fromView: nil]]; diff --git a/macosx/InfoWindowController.m b/macosx/InfoWindowController.m index cd03567f8..9b00e1950 100644 --- a/macosx/InfoWindowController.m +++ b/macosx/InfoWindowController.m @@ -590,6 +590,11 @@ typedef enum return windowRect; } +- (void) windowWillClose: (NSNotification *) notification +{ + [fFileController fileTabClosed]; +} + - (void) setTab: (id) sender { int oldTabTag = fCurrentTabTag; @@ -619,6 +624,8 @@ typedef enum oldResizeSaveKey = @"InspectorContentHeightPeers"; break; case TAB_FILES_TAG: + [fFileController fileTabClosed]; + oldResizeSaveKey = @"InspectorContentHeightFiles"; break; } diff --git a/macosx/QuickLook.h b/macosx/QuickLook.h new file mode 100644 index 000000000..df1de9c4e --- /dev/null +++ b/macosx/QuickLook.h @@ -0,0 +1,85 @@ +@interface QLPreviewPanel : NSPanel ++ (id)sharedPreviewPanel; ++ (id)_previewPanel; ++ (BOOL)isSharedPreviewPanelLoaded; +- (id)initWithContentRect:(struct _NSRect)fp8 styleMask:(unsigned int)fp24 backing:(unsigned int)fp28 defer:(BOOL)fp32; +- (id)initWithCoder:(id)fp8; +- (void)dealloc; +- (BOOL)isOpaque; +- (BOOL)canBecomeKeyWindow; +- (BOOL)canBecomeMainWindow; +- (BOOL)shouldIgnorePanelFrameChanges; +- (BOOL)isOpen; +- (void)setFrame:(struct _NSRect)fp8 display:(BOOL)fp24 animate:(BOOL)fp28; +- (id)_subEffectsForWindow:(id)fp8 itemFrame:(struct _NSRect)fp12 transitionWindow:(id *)fp28; +- (id)_scaleEffectForItemFrame:(struct _NSRect)fp8 transitionWindow:(id *)fp24; +- (void)_invertCurrentEffect; +- (struct _NSRect)_currentItemFrame; +- (void)setAutosizesAndCenters:(BOOL)fp8; +- (BOOL)autosizesAndCenters; +- (void)makeKeyAndOrderFront:(id)fp8; +- (void)makeKeyAndOrderFrontWithEffect:(int)fp8; +- (void)makeKeyAndGoFullscreenWithEffect:(int)fp8; +- (void)makeKeyAndOrderFrontWithEffect:(int)fp8 canClose:(BOOL)fp12; +- (void)_makeKeyAndOrderFrontWithEffect:(int)fp8 canClose:(BOOL)fp12 willOpen:(BOOL)fp16 toFullscreen:(BOOL)fp20; +- (int)openingEffect; +- (void)closePanel; +- (void)close; +- (void)closeWithEffect:(int)fp8; +- (void)closeWithEffect:(int)fp8 canReopen:(BOOL)fp12; +- (void)_closeWithEffect:(int)fp8 canReopen:(BOOL)fp12; +- (void)windowEffectDidTerminate:(id)fp8; +- (void)_close:(id)fp8; +- (void)sendEvent:(id)fp8; +- (void)selectNextItem; +- (void)selectPreviousItem; +- (void)setURLs:(id)fp8 currentIndex:(unsigned int)fp12 preservingDisplayState:(BOOL)fp16; +- (void)setURLs:(id)fp8 preservingDisplayState:(BOOL)fp12; +- (void)setURLs:(id)fp8; +- (id)URLs; +- (unsigned int)indexOfCurrentURL; +- (void)setIndexOfCurrentURL:(unsigned int)fp8; +- (void)setDelegate:(id)fp8; +- (id)sharedPreviewView; +- (void)setSharedPreviewView:(id)fp8; +- (void)setCyclesSelection:(BOOL)fp8; +- (BOOL)cyclesSelection; +- (void)setShowsAddToiPhotoButton:(BOOL)fp8; +- (BOOL)showsAddToiPhotoButton; +- (void)setShowsiChatTheaterButton:(BOOL)fp8; +- (BOOL)showsiChatTheaterButton; +- (void)setShowsFullscreenButton:(BOOL)fp8; +- (BOOL)showsFullscreenButton; +- (void)setShowsIndexSheetButton:(BOOL)fp8; +- (BOOL)showsIndexSheetButton; +- (void)setAutostarts:(BOOL)fp8; +- (BOOL)autostarts; +- (void)setPlaysDuringPanelAnimation:(BOOL)fp8; +- (BOOL)playsDuringPanelAnimation; +- (void)setDeferredLoading:(BOOL)fp8; +- (BOOL)deferredLoading; +- (void)setEnableDragNDrop:(BOOL)fp8; +- (BOOL)enableDragNDrop; +- (void)start:(id)fp8; +- (void)stop:(id)fp8; +- (void)setShowsIndexSheet:(BOOL)fp8; +- (BOOL)showsIndexSheet; +- (void)setShareWithiChat:(BOOL)fp8; +- (BOOL)shareWithiChat; +- (void)setPlaysSlideShow:(BOOL)fp8; +- (BOOL)playsSlideShow; +- (void)setIsFullscreen:(BOOL)fp8; +- (BOOL)isFullscreen; +- (void)setMandatoryClient:(id)fp8; +- (id)mandatoryClient; +- (void)setForcedContentTypeUTI:(id)fp8; +- (id)forcedContentTypeUTI; +- (void)setDocumentURLs:(id)fp8; +- (void)setDocumentURLs:(id)fp8 preservingDisplayState:(BOOL)fp12; +- (void)setDocumentURLs:(id)fp8 itemFrame:(struct _NSRect)fp12; +- (void)setURLs:(id)fp8 itemFrame:(struct _NSRect)fp12; +- (void)setAutoSizeAndCenterOnScreen:(BOOL)fp8; +- (void)setShowsAddToiPhoto:(BOOL)fp8; +- (void)setShowsiChatTheater:(BOOL)fp8; +- (void)setShowsFullscreen:(BOOL)fp8; +@end \ No newline at end of file