]> granicus.if.org Git - transmission/commitdiff
#4963 Support Notification Center on 10.8
authorMitchell Livingston <livings124@transmissionbt.com>
Wed, 25 Jul 2012 12:49:11 +0000 (12:49 +0000)
committerMitchell Livingston <livings124@transmissionbt.com>
Wed, 25 Jul 2012 12:49:11 +0000 (12:49 +0000)
macosx/Controller.h
macosx/Controller.m
macosx/FilterBarController.h
macosx/FilterBarController.m

index a83f2386eb6be5523f566796d011feb98b55f3d5..f08050c6ee0f0285c34f91b45fc70f91637548a6 100644 (file)
@@ -49,7 +49,7 @@ typedef enum
     ADD_CREATED
 } addType;
 
-@interface Controller : NSObject <GrowlApplicationBridgeDelegate, NSURLDownloadDelegate, NSPopoverDelegate, NSSoundDelegate, NSToolbarDelegate, NSWindowDelegate, QLPreviewPanelDataSource, QLPreviewPanelDelegate>
+@interface Controller : NSObject <GrowlApplicationBridgeDelegate, NSURLDownloadDelegate, NSUserNotificationCenterDelegate, NSPopoverDelegate, NSSoundDelegate, NSToolbarDelegate, NSWindowDelegate, QLPreviewPanelDataSource, QLPreviewPanelDelegate>
 {
     tr_session                      * fLib;
     
@@ -193,6 +193,8 @@ typedef enum
 
 - (void) setBottomCountText: (BOOL) filtering;
 
+- (Torrent *) torrentForHash: (NSString *) hash;
+
 - (void) torrentFinishedDownloading: (NSNotification *) notification;
 - (void) torrentRestartedDownloading: (NSNotification *) notification;
 - (void) torrentFinishedSeeding: (NSNotification *) notification;
index 98502c771725e6bdd74701620deb6c453fcf3858..18ea83d0d2c1df1fd30a997b86bf2cd30dbe7576 100644 (file)
@@ -484,6 +484,9 @@ static void sleepCallback(void * controller, io_service_t y, natural_t messageTy
     
     fBadger = [[Badger alloc] initWithLib: fLib];
     
+    if ([NSApp isOnMountainLionOrBetter])
+        [[NSUserNotificationCenterMtLion defaultUserNotificationCenter] setDelegate: self];
+    
     //observe notifications
     NSNotificationCenter * nc = [NSNotificationCenter defaultCenter];
     
@@ -555,6 +558,14 @@ static void sleepCallback(void * controller, io_service_t y, natural_t messageTy
     [[NSAppleEventManager sharedAppleEventManager] setEventHandler: self andSelector: @selector(handleOpenContentsEvent:replyEvent:)
         forEventClass: kCoreEventClass andEventID: kAEOpenContents];
     
+    //if we were opened from a user notification, do the corresponding action
+    if ([NSApp isOnMountainLionOrBetter])
+    {
+        NSUserNotification * launchNotification = [[notification userInfo] objectForKey: NSApplicationLaunchUserNotificationKey];
+        if (launchNotification)
+            [self userNotificationCenter: nil didActivateNotification: launchNotification];
+    }
+    
     //auto importing
     [self checkAutoImportDirectory];
     
@@ -1836,6 +1847,101 @@ static void sleepCallback(void * controller, io_service_t y, natural_t messageTy
     [fTotalTorrentsField setStringValue: totalTorrentsString];
 }
 
+- (BOOL) userNotificationCenter: (NSUserNotificationCenter *) center shouldPresentNotification:(NSUserNotification *) notification
+{
+    return YES;
+}
+
+- (void) userNotificationCenter: (NSUserNotificationCenter *) center didActivateNotification: (NSUserNotification *) notification
+{
+    if (![notification userInfo])
+        return;
+    
+    if ([notification activationType] == NSUserNotificationActivationTypeActionButtonClicked) //reveal
+    {
+        Torrent * torrent = [self torrentForHash: [[notification userInfo] objectForKey: @"Hash"]];
+        NSString * location = [torrent dataLocation];
+        if (!location)
+            location = [[notification userInfo] objectForKey: @"Location"];
+        if (location)
+            [[NSWorkspace sharedWorkspace] activateFileViewerSelectingURLs: @[[NSURL fileURLWithPath: location]]];
+    }
+    else if ([notification activationType] == NSUserNotificationActivationTypeContentsClicked)
+    {
+        Torrent * torrent = [self torrentForHash: [[notification userInfo] objectForKey: @"Hash"]];
+        if (torrent)
+        {
+            //select in the table - first see if it's already shown
+            NSInteger row = [fTableView rowForItem: torrent];
+            if (row == -1)
+            {
+                //if it's not shown, see if it's in a collapsed row
+                if ([fDefaults boolForKey: @"SortByGroup"])
+                {
+                    __block TorrentGroup * parent = nil;
+                    [fDisplayedTorrents enumerateObjectsWithOptions: NSEnumerationConcurrent usingBlock: ^(TorrentGroup * group, NSUInteger idx, BOOL *stop) {
+                        if ([[group torrents] containsObject: torrent])
+                        {
+                            parent = group;
+                            *stop = YES;
+                        }
+                    }];
+                    if (parent)
+                    {
+                        [[fTableView animator] expandItem: parent];
+                        row = [fTableView rowForItem: torrent];
+                    }
+                }
+                
+                if (row == -1)
+                {
+                    //not found - must be filtering
+                    NSAssert([fDefaults boolForKey: @"FilterBar"], @"expected the filter to be enabled");
+                    [fFilterBar reset: YES];
+                    
+                    row = [fTableView rowForItem: torrent];
+                    
+                    //if it's not shown, it has to be in a collapsed row...again
+                    if ([fDefaults boolForKey: @"SortByGroup"])
+                    {
+                        __block TorrentGroup * parent = nil;
+                        [fDisplayedTorrents enumerateObjectsWithOptions: NSEnumerationConcurrent usingBlock: ^(TorrentGroup * group, NSUInteger idx, BOOL *stop) {
+                            if ([[group torrents] containsObject: torrent])
+                            {
+                                parent = group;
+                                *stop = YES;
+                            }
+                        }];
+                        if (parent)
+                        {
+                            [[fTableView animator] expandItem: parent];
+                            row = [fTableView rowForItem: torrent];
+                        }
+                    }
+                }
+            }
+            
+            NSAssert1(row != -1, @"expected a row to be found for torrent %@", torrent);
+            [fTableView selectRowIndexes: [NSIndexSet indexSetWithIndex: row] byExtendingSelection:NO];
+        }
+    }
+}
+
+- (Torrent *) torrentForHash: (NSString *) hash
+{
+    NSParameterAssert(hash != nil);
+    
+    __block Torrent * torrent = nil;
+    [fTorrents enumerateObjectsWithOptions: NSEnumerationConcurrent usingBlock: ^(id obj, NSUInteger idx, BOOL * stop) {
+        if ([[(Torrent *)obj hashString] isEqualToString: hash])
+        {
+            torrent = obj;
+            *stop = YES;
+        }
+    }];
+    return torrent;
+}
+
 - (void) torrentFinishedDownloading: (NSNotification *) notification
 {
     Torrent * torrent = [notification object];
@@ -1853,9 +1959,28 @@ static void sleepCallback(void * controller, io_service_t y, natural_t messageTy
             }
         }
         
+        NSString * location = [torrent dataLocation];
+        
+        if ([NSApp isOnMountainLionOrBetter])
+        {
+            NSUserNotification * notification = [[NSUserNotificationMtLion alloc] init];
+            [notification setTitle: NSLocalizedString(@"Download Complete", "notification title")];
+            [notification setSubtitle: [torrent name]];
+            
+            [notification setHasActionButton: YES];
+            [notification setActionButtonTitle: NSLocalizedString(@"Reveal", "notification button")];
+            
+            NSMutableDictionary * userInfo = [NSMutableDictionary dictionaryWithObject: [torrent hashString] forKey: @"Hash"];
+            if (location)
+                [userInfo setObject: location forKey: @"Location"];
+            [notification setUserInfo: userInfo];
+            
+            [[NSUserNotificationCenterMtLion defaultUserNotificationCenter] deliverNotification: notification];
+            [notification release];
+        }
+        
         NSMutableDictionary * clickContext = [NSMutableDictionary dictionaryWithObject: GROWL_DOWNLOAD_COMPLETE forKey: @"Type"];
         
-        NSString * location = [torrent dataLocation];
         if (location)
             [clickContext setObject: location forKey: @"Location"];
         
@@ -1894,9 +2019,28 @@ static void sleepCallback(void * controller, io_service_t y, natural_t messageTy
         }
     }
     
+    NSString * location = [torrent dataLocation];
+    
+    if ([NSApp isOnMountainLionOrBetter])
+    {
+        NSUserNotification * notification = [[NSUserNotificationMtLion alloc] init];
+        [notification setTitle: NSLocalizedString(@"Seeding Complete", "notification title")];
+        [notification setSubtitle: [torrent name]];
+        
+        [notification setHasActionButton: YES];
+        [notification setActionButtonTitle: NSLocalizedString(@"Reveal", "notification button")];
+        
+        NSMutableDictionary * userInfo = [NSMutableDictionary dictionaryWithObject: [torrent hashString] forKey: @"Hash"];
+        if (location)
+            [userInfo setObject: location forKey: @"Location"];
+        [notification setUserInfo: userInfo];
+        
+        [[NSUserNotificationCenterMtLion defaultUserNotificationCenter] deliverNotification: notification];
+        [notification release];
+    }
+    
     NSMutableDictionary * clickContext = [NSMutableDictionary dictionaryWithObject: GROWL_SEEDING_COMPLETE forKey: @"Type"];
     
-    NSString * location = [torrent dataLocation];
     if (location)
         [clickContext setObject: location forKey: @"Location"];
     
@@ -2815,6 +2959,18 @@ static void sleepCallback(void * controller, io_service_t y, natural_t messageTy
             case TR_PARSE_OK:
                 [self openFiles: [NSArray arrayWithObject: fullFile] addType: ADD_AUTO forcePath: nil];
                 
+                if ([NSApp isOnMountainLionOrBetter])
+                {
+                    NSUserNotification* notification = [[NSUserNotificationMtLion alloc] init];
+                    [notification setTitle: NSLocalizedString(@"Torrent File Auto Added", "notification title")];
+                    [notification setSubtitle: file];
+                    
+                    [notification setHasActionButton: NO];
+                    
+                    [[NSUserNotificationCenterMtLion defaultUserNotificationCenter] deliverNotification: notification];
+                    [notification release];
+                }
+                
                 [GrowlApplicationBridge notifyWithTitle: NSLocalizedString(@"Torrent File Auto Added", "Growl notification title")
                     description: file notificationName: GROWL_AUTO_ADD iconData: nil priority: 0 isSticky: NO
                     clickContext: nil];
@@ -3402,11 +3558,7 @@ static void sleepCallback(void * controller, io_service_t y, natural_t messageTy
     
     //disable filtering when hiding
     if (!show)
-    {
-        [[NSUserDefaults standardUserDefaults] setObject: FILTER_NONE forKey: @"Filter"];
-        [[NSUserDefaults standardUserDefaults] setInteger: GROUP_FILTER_ALL_TAG forKey: @"FilterGroup"];
-        [[NSUserDefaults standardUserDefaults] removeObjectForKey: @"FilterSearchString"];
-    }
+        [fFilterBar reset: NO];
     
     [self applyFilter]; //do even if showing to ensure tooltips are updated
 }
@@ -4494,7 +4646,7 @@ static void sleepCallback(void * controller, io_service_t y, natural_t messageTy
 
 - (void) growlNotificationWasClicked: (id) clickContext
 {
-    if (!clickContext || ![clickContext isKindOfClass: [NSDictionary class]])
+    if (![clickContext isKindOfClass: [NSDictionary class]])
         return;
     
     NSString * type = [clickContext objectForKey: @"Type"], * location;
index eeef1207fc22435530a95dca0023aac63d6a2458..45d57a329ba57920346d8bc2f286860d2e2c45e5 100644 (file)
@@ -54,6 +54,7 @@
 - (void) setSearchText: (id) sender;
 - (void) setSearchType: (id) sender;
 - (void) setGroupFilter: (id) sender;
+- (void) reset: (BOOL) updateUI;
 
 - (NSArray *) searchStrings;
 - (void) focusSearchField;
@@ -61,4 +62,5 @@
 - (void) setCountAll: (NSUInteger) all active: (NSUInteger) active downloading: (NSUInteger) downloading
         seeding: (NSUInteger) seeding paused: (NSUInteger) paused;
 
+
 @end
index 82fd0ae3f99f5666433a1bcfd3d97faea27034a0..2297699964a88dd5a8b6ba9be4869e8d48b9a5be 100644 (file)
     [[NSNotificationCenter defaultCenter] postNotificationName: @"ApplyFilter" object: nil];
 }
 
+- (void) reset: (BOOL) updateUI
+{
+    [[NSUserDefaults standardUserDefaults] setInteger: GROUP_FILTER_ALL_TAG forKey: @"FilterGroup"];
+    
+    if (updateUI)
+    {   
+        [self updateGroupsButton];
+        
+        [self setFilter: fNoFilterButton];
+        
+        [fSearchField setStringValue: @""];
+        [self setSearchText: fSearchField];
+    }
+    else
+    {
+        [[NSUserDefaults standardUserDefaults] setObject: FILTER_NONE forKey: @"Filter"];
+        [[NSUserDefaults standardUserDefaults] removeObjectForKey: @"FilterSearchString"];
+    }
+}
+
 - (NSArray *) searchStrings
 {
     return [[fSearchField stringValue] betterComponentsSeparatedByCharactersInSet: [NSCharacterSet whitespaceAndNewlineCharacterSet]];