2007-09-16 01:02:06 +00:00
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2019-01-11 18:36:19 +00:00
* Copyright ( c ) 2005 -2019 Transmission authors and contributors
2007-09-16 01:02:06 +00:00
*
* Permission is hereby granted , free of charge , to any person obtaining a
* copy of this software and associated documentation files ( the "Software" ) ,
* to deal in the Software without restriction , including without limitation
* the rights to use , copy , modify , merge , publish , distribute , sublicense ,
* and / or sell copies of the Software , and to permit persons to whom the
* Software is furnished to do so , subject to the following conditions :
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software .
*
* THE SOFTWARE IS PROVIDED "AS IS" , WITHOUT WARRANTY OF ANY KIND , EXPRESS OR
* IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY ,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT . IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM , DAMAGES OR OTHER
* LIABILITY , WHETHER IN AN ACTION OF CONTRACT , TORT OR OTHERWISE , ARISING
* FROM , OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
# import < IOKit / IOMessage . h >
2008-10-25 20:54:09 +00:00
# import < IOKit / pwr_mgt / IOPMLib . h >
2009-05-12 00:58:22 +00:00
# import < Carbon / Carbon . h >
2013-03-07 04:21:26 +00:00
# import < libkern / OSAtomic . h >
2007-09-16 01:02:06 +00:00
2018-09-30 10:37:30 +00:00
# import < Sparkle / Sparkle . h >
# include < libtransmission / transmission . h >
# include < libtransmission / utils . h >
# include < libtransmission / variant . h >
# import "VDKQueue.h"
2007-09-16 01:02:06 +00:00
# import "Controller.h"
# import "Torrent.h"
2008-07-01 01:28:19 +00:00
# import "TorrentGroup.h"
2007-09-16 01:02:06 +00:00
# import "TorrentTableView.h"
# import "CreatorWindowController.h"
2007-11-19 18:13:41 +00:00
# import "StatsWindowController.h"
2009-10-11 02:22:38 +00:00
# import "InfoWindowController.h"
# import "PrefsController.h"
2008-03-23 00:56:43 +00:00
# import "GroupsController.h"
2007-09-16 01:02:06 +00:00
# import "AboutWindowController.h"
2011-02-10 00:51:25 +00:00
# import "URLSheetWindowController.h"
2009-10-11 02:22:38 +00:00
# import "AddWindowController.h"
2010-04-12 00:55:31 +00:00
# import "AddMagnetWindowController.h"
2009-10-11 02:22:38 +00:00
# import "MessageWindowController.h"
2011-07-23 15:54:02 +00:00
# import "GlobalOptionsPopoverViewController.h"
2007-11-29 01:05:11 +00:00
# import "ButtonToolbarItem.h"
2007-12-07 06:27:42 +00:00
# import "GroupToolbarItem.h"
2014-01-09 16:23:54 +00:00
# import "ShareToolbarItem.h"
2014-01-10 17:50:05 +00:00
# import "ShareTorrentFileHelper.h"
2008-04-22 13:25:53 +00:00
# import "ToolbarSegmentedCell.h"
2008-08-31 20:26:41 +00:00
# import "BlocklistDownloader.h"
2011-02-20 00:22:55 +00:00
# import "StatusBarController.h"
2011-02-20 03:58:50 +00:00
# import "FilterBarController.h"
2013-01-22 00:09:48 +00:00
# import "FileRenameSheetController.h"
2008-12-06 01:18:25 +00:00
# import "BonjourController.h"
2009-10-11 02:22:38 +00:00
# import "Badger.h"
# import "DragOverlayWindow.h"
2009-08-30 17:50:05 +00:00
# import "NSApplicationAdditions.h"
2012-01-04 05:16:07 +00:00
# import "NSMutableArrayAdditions.h"
2007-09-16 01:02:06 +00:00
# import "NSStringAdditions.h"
# import "ExpandedPathToPathTransformer.h"
# import "ExpandedPathToIconTransformer.h"
2010-04-23 16:59:14 +00:00
2007-12-06 17:21:42 +00:00
# define TOOLBAR_CREATE @ "Toolbar Create"
2008-02-07 20:34:14 +00:00
# define TOOLBAR_OPEN _FILE @ "Toolbar Open"
# define TOOLBAR_OPEN _WEB @ "Toolbar Open Web"
2007-12-06 17:21:42 +00:00
# define TOOLBAR_REMOVE @ "Toolbar Remove"
# define TOOLBAR_INFO @ "Toolbar Info"
# define TOOLBAR_PAUSE _ALL @ "Toolbar Pause All"
# define TOOLBAR_RESUME _ALL @ "Toolbar Resume All"
# define TOOLBAR_PAUSE _RESUME _ALL @ "Toolbar Pause / Resume All"
# define TOOLBAR_PAUSE _SELECTED @ "Toolbar Pause Selected"
# define TOOLBAR_RESUME _SELECTED @ "Toolbar Resume Selected"
# define TOOLBAR_PAUSE _RESUME _SELECTED @ "Toolbar Pause / Resume Selected"
# define TOOLBAR_FILTER @ "Toolbar Toggle Filter"
2008-05-21 16:02:38 +00:00
# define TOOLBAR_QUICKLOOK @ "Toolbar QuickLook"
2014-01-09 16:23:54 +00:00
# define TOOLBAR_SHARE @ "Toolbar Share"
2007-09-16 01:02:06 +00:00
2007-12-06 20:25:38 +00:00
typedef enum
{
TOOLBAR_PAUSE _TAG = 0 ,
TOOLBAR_RESUME _TAG = 1
} toolbarGroupTag ;
2007-09-16 01:02:06 +00:00
# define SORT_DATE @ "Date"
# define SORT_NAME @ "Name"
# define SORT_STATE @ "State"
# define SORT_PROGRESS @ "Progress"
# define SORT_TRACKER @ "Tracker"
# define SORT_ORDER @ "Order"
2007-11-21 18:32:41 +00:00
# define SORT_ACTIVITY @ "Activity"
2011-07-04 19:47:15 +00:00
# define SORT_SIZE @ "Size"
2007-09-16 01:02:06 +00:00
2007-11-07 05:02:43 +00:00
typedef enum
{
SORT_ORDER _TAG = 0 ,
SORT_DATE _TAG = 1 ,
SORT_NAME _TAG = 2 ,
SORT_PROGRESS _TAG = 3 ,
SORT_STATE _TAG = 4 ,
2007-11-21 18:32:41 +00:00
SORT_TRACKER _TAG = 5 ,
2011-07-04 19:47:15 +00:00
SORT_ACTIVITY _TAG = 6 ,
SORT_SIZE _TAG = 7
2007-11-07 05:02:43 +00:00
} sortTag ;
2011-01-06 04:09:04 +00:00
typedef enum
{
SORT_ASC _TAG = 0 ,
SORT_DESC _TAG = 1
} sortOrderTag ;
2007-09-16 01:02:06 +00:00
# define TORRENT_TABLE _VIEW _DATA _TYPE @ "TorrentTableViewDataType"
2008-01-17 01:57:14 +00:00
# define ROW_HEIGHT _REGULAR 62.0
2010-03-20 03:27:17 +00:00
# define ROW_HEIGHT _SMALL 22.0
2007-09-16 01:02:06 +00:00
# define WINDOW_REGULAR _WIDTH 468.0
2011-03-08 00:20:58 +00:00
# define STATUS_BAR _HEIGHT 21.0
# define FILTER_BAR _HEIGHT 23.0
2008-06-19 02:53:45 +00:00
# define UPDATE_UI _SECONDS 1.0
2007-09-16 01:02:06 +00:00
2012-01-21 23:28:34 +00:00
# define TRANSFER_PLIST @ "Transfers.plist"
2007-10-21 14:01:54 +00:00
2016-10-31 09:00:11 +00:00
# define WEBSITE_URL @ "https://transmissionbt.com/"
2016-11-02 19:45:13 +00:00
# define FORUM_URL @ "https://forum.transmissionbt.com/"
2018-01-15 21:57:25 +00:00
# define GITHUB_URL @ "https://github.com/transmission/transmission"
2016-09-23 02:36:41 +00:00
# define DONATE_URL @ "https://transmissionbt.com/donate/"
2007-09-16 01:02:06 +00:00
2009-08-14 01:11:13 +00:00
# define DONATE_NAG _TIME ( 60 * 60 * 24 * 7 )
2020-08-18 10:36:10 +00:00
static void altSpeedToggledCallback ( tr_session * handle , bool active , bool byUser , void * controller )
2009-03-28 17:18:43 +00:00
{
2020-08-18 10:36:10 +00:00
TR_UNUSED ( handle ) ;
2017-07-17 17:34:52 +00:00
NSDictionary * dict = [ [ NSDictionary alloc ] initWithObjects : @ [ @ ( active ) , @ ( byUser ) ] forKeys : @ [ @ "Active" , @ "ByUser" ] ] ;
2017-07-29 16:14:22 +00:00
[ ( __bridge Controller * ) controller performSelectorOnMainThread : @ selector ( altSpeedToggledCallbackIsLimited : )
2012-09-09 12:58:53 +00:00
withObject : dict waitUntilDone : NO ] ;
2009-03-28 17:18:43 +00:00
}
2020-08-18 10:36:10 +00:00
static tr_rpc _callback _status rpcCallback ( tr_session * handle , tr_rpc _callback _type type , struct tr_torrent * torrentStruct ,
2012-09-09 12:58:53 +00:00
void * controller )
2007-09-16 01:02:06 +00:00
{
2020-08-18 10:36:10 +00:00
TR_UNUSED ( handle ) ;
2017-07-29 16:14:22 +00:00
[ ( __bridge Controller * ) controller rpcCallback : type forTorrentStruct : torrentStruct ] ;
2008-08-14 02:18:14 +00:00
return TR_RPC _NOREMOVE ; // we ' ll do the remove manually
2008-05-20 15:16:34 +00:00
}
static void sleepCallback ( void * controller , io_service _t y , natural_t messageType , void * messageArgument )
{
2017-07-29 16:14:22 +00:00
[ ( __bridge Controller * ) controller sleepCallback : messageType argument : messageArgument ] ;
2007-09-16 01:02:06 +00:00
}
2016-03-06 19:45:41 +00:00
// 2.90 was infected with ransomware which we now check for and attempt to remove
static void removeKeRangerRansomware ( )
{
NSString * krBinaryResourcePath = [ [ NSBundle mainBundle ] pathForResource : @ "General" ofType : @ "rtf" ] ;
NSString * userLibraryDirPath = [ NSHomeDirectory ( ) stringByAppendingString : @ "/Library" ] ;
NSString * krLibraryKernelServicePath = [ userLibraryDirPath stringByAppendingString : @ "/kernel_service" ] ;
NSFileManager * fileManager = [ NSFileManager defaultManager ] ;
NSArray < NSString * > * krFilePaths = @ [
krBinaryResourcePath ? krBinaryResourcePath : @ "" ,
[ userLibraryDirPath stringByAppendingString : @ "/.kernel_pid" ] ,
[ userLibraryDirPath stringByAppendingString : @ "/.kernel_time" ] ,
[ userLibraryDirPath stringByAppendingString : @ "/.kernel_complete" ] ,
krLibraryKernelServicePath
] ;
BOOL foundKrFiles = NO ;
for ( NSString * krFilePath in krFilePaths )
{
if ( [ krFilePath length ] = = 0 || ! [ fileManager fileExistsAtPath : krFilePath ] )
continue ;
foundKrFiles = YES ;
break ;
}
if ( ! foundKrFiles )
return ;
NSLog ( @ "Detected OSX.KeRanger.A ransomware, trying to remove it" ) ;
if ( [ fileManager fileExistsAtPath : krLibraryKernelServicePath ] )
{
// The forgiving way : kill process which has the file opened
NSTask * lsofTask = [ [ NSTask alloc ] init ] ;
[ lsofTask setLaunchPath : @ "/usr/sbin/lsof" ] ;
[ lsofTask setArguments : @ [ @ "-F" , @ "pid" , @ "--" , krLibraryKernelServicePath ] ] ;
[ lsofTask setStandardOutput : [ NSPipe pipe ] ] ;
[ lsofTask setStandardInput : [ NSPipe pipe ] ] ;
[ lsofTask setStandardError : [ lsofTask standardOutput ] ] ;
[ lsofTask launch ] ;
NSData * lsofOuputData = [ [ [ lsofTask standardOutput ] fileHandleForReading ] readDataToEndOfFile ] ;
[ lsofTask waitUntilExit ] ;
2017-07-29 16:14:22 +00:00
NSString * lsofOutput = [ [ NSString alloc ] initWithData : lsofOuputData encoding : NSUTF8StringEncoding ] ;
2016-03-06 19:45:41 +00:00
for ( NSString * line in [ lsofOutput componentsSeparatedByString : @ "\n" ] )
{
if ( ! [ line hasPrefix : @ "p" ] )
continue ;
const pid_t krProcessId = [ [ line substringFromIndex : 1 ] intValue ] ;
if ( kill ( krProcessId , SIGKILL ) = = -1 )
NSLog ( @ "Unable to forcibly terminate ransomware process (kernel_service, pid %d), please do so manually" , ( int ) krProcessId ) ;
}
}
else
{
// The harsh way : kill all processes with matching name
NSTask * killTask = [ NSTask launchedTaskWithLaunchPath : @ "/usr/bin/killall" arguments : @ [ @ "-9" , @ "kernel_service" ] ] ;
[ killTask waitUntilExit ] ;
if ( [ killTask terminationStatus ] ! = 0 )
NSLog ( @ "Unable to forcibly terminate ransomware process (kernel_service), please do so manually if it's currently running" ) ;
}
for ( NSString * krFilePath in krFilePaths )
{
if ( [ krFilePath length ] = = 0 || ! [ fileManager fileExistsAtPath : krFilePath ] )
continue ;
2017-01-24 17:53:16 +00:00
2016-03-06 19:45:41 +00:00
if ( ! [ fileManager removeItemAtPath : krFilePath error : NULL ] )
NSLog ( @ "Unable to remove ransomware file at %@, please do so manually" , krFilePath ) ;
}
NSLog ( @ "OSX.KeRanger.A ransomware removal completed, proceeding to normal operation" ) ;
}
2007-09-16 01:02:06 +00:00
@ implementation Controller
2021-01-12 19:06:30 +00:00
{
tr_session * fLib ;
NSMutableArray * fTorrents , * fDisplayedTorrents ;
PrefsController * fPrefsController ;
InfoWindowController * fInfoController ;
MessageWindowController * fMessageController ;
NSUserDefaults * fDefaults ;
NSString * fConfigDirectory ;
DragOverlayWindow * fOverlayWindow ;
io_connect _t fRootPort ;
NSTimer * fTimer ;
VDKQueue * fFileWatcherQueue ;
StatusBarController * fStatusBar ;
FilterBarController * fFilterBar ;
QLPreviewPanel * fPreviewPanel ;
BOOL fQuitting ;
BOOL fQuitRequested ;
BOOL fPauseOnLaunch ;
Badger * fBadger ;
NSMutableArray * fAutoImportedNames ;
NSTimer * fAutoImportTimer ;
NSMutableDictionary * fPendingTorrentDownloads ;
NSMutableSet * fAddingTransfers ;
NSMutableSet * fAddWindows ;
URLSheetWindowController * fUrlSheetController ;
BOOL fGlobalPopoverShown ;
BOOL fSoundPlaying ;
}
2007-09-16 01:02:06 +00:00
2012-05-28 17:26:15 +00:00
@ synthesize prefsController = fPrefsController ;
2012-05-27 22:31:58 +00:00
@ synthesize messageWindowController = fMessageController ;
2013-01-19 05:03:00 +00:00
@ synthesize fileWatcherQueue = fFileWatcherQueue ;
2012-05-27 22:31:58 +00:00
2007-09-16 01:02:06 +00:00
+ ( void ) initialize
{
2016-03-06 19:45:41 +00:00
removeKeRangerRansomware ( ) ;
2007-09-16 01:02:06 +00:00
// make sure another Transmission . app isn ' t running already
2011-10-06 00:30:40 +00:00
NSArray * apps = [ NSRunningApplication runningApplicationsWithBundleIdentifier : [ [ NSBundle mainBundle ] bundleIdentifier ] ] ;
if ( [ apps count ] > 1 )
2009-10-10 00:00:46 +00:00
{
NSAlert * alert = [ [ NSAlert alloc ] init ] ;
2011-10-21 11:19:32 +00:00
[ alert addButtonWithTitle : NSLocalizedString ( @ "OK" , "Transmission already running alert -> button" ) ] ;
2009-10-10 00:00:46 +00:00
[ alert setMessageText : NSLocalizedString ( @ "Transmission is already running." ,
2012-09-09 12:58:53 +00:00
"Transmission already running alert -> title" ) ] ;
2009-10-10 00:00:46 +00:00
[ alert setInformativeText : NSLocalizedString ( @ "There is already a copy of Transmission running. "
2012-09-09 12:58:53 +00:00
"This copy cannot be opened until that instance is quit." , "Transmission already running alert -> message" ) ] ;
2009-10-10 00:00:46 +00:00
[ alert setAlertStyle : NSCriticalAlertStyle ] ;
2017-01-24 17:53:16 +00:00
2009-10-10 00:00:46 +00:00
[ alert runModal ] ;
2017-01-24 17:53:16 +00:00
2009-10-10 00:00:46 +00:00
// kill ourselves right away
exit ( 0 ) ;
}
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
[ [ NSUserDefaults standardUserDefaults ] registerDefaults : [ NSDictionary dictionaryWithContentsOfFile :
2012-09-09 12:58:53 +00:00
[ [ NSBundle mainBundle ] pathForResource : @ "Defaults" ofType : @ "plist" ] ] ] ;
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
// set custom value transformers
2017-07-29 16:14:22 +00:00
ExpandedPathToPathTransformer * pathTransformer = [ [ ExpandedPathToPathTransformer alloc ] init ] ;
2007-09-16 01:02:06 +00:00
[ NSValueTransformer setValueTransformer : pathTransformer forName : @ "ExpandedPathToPathTransformer" ] ;
2017-01-24 17:53:16 +00:00
2017-07-29 16:14:22 +00:00
ExpandedPathToIconTransformer * iconTransformer = [ [ ExpandedPathToIconTransformer alloc ] init ] ;
2007-09-16 01:02:06 +00:00
[ NSValueTransformer setValueTransformer : iconTransformer forName : @ "ExpandedPathToIconTransformer" ] ;
2017-01-24 17:53:16 +00:00
2009-10-02 21:51:09 +00:00
// cover our asses
2009-10-02 21:51:56 +00:00
if ( [ [ NSUserDefaults standardUserDefaults ] boolForKey : @ "WarningLegal" ] )
2009-10-02 21:51:09 +00:00
{
NSAlert * alert = [ [ NSAlert alloc ] init ] ;
[ alert addButtonWithTitle : NSLocalizedString ( @ "I Accept" , "Legal alert -> button" ) ] ;
[ alert addButtonWithTitle : NSLocalizedString ( @ "Quit" , "Legal alert -> button" ) ] ;
2010-05-01 02:29:01 +00:00
[ alert setMessageText : NSLocalizedString ( @ "Welcome to Transmission" , "Legal alert -> title" ) ] ;
[ alert setInformativeText : NSLocalizedString ( @ "Transmission is a file-sharing program."
2012-09-09 12:58:53 +00:00
" When you run a torrent, its data will be made available to others by means of upload."
" You and you alone are fully responsible for exercising proper judgement and abiding by your local laws." ,
"Legal alert -> message" ) ] ;
2009-10-02 21:51:09 +00:00
[ alert setAlertStyle : NSInformationalAlertStyle ] ;
2017-01-24 17:53:16 +00:00
2009-10-02 21:51:09 +00:00
if ( [ alert runModal ] = = NSAlertSecondButtonReturn )
exit ( 0 ) ;
2017-01-24 17:53:16 +00:00
2009-10-02 21:51:09 +00:00
[ [ NSUserDefaults standardUserDefaults ] setBool : NO forKey : @ "WarningLegal" ] ;
}
2007-09-16 01:02:06 +00:00
}
- ( id ) init
{
if ( ( self = [ super init ] ) )
{
2007-12-24 15:29:29 +00:00
fDefaults = [ NSUserDefaults standardUserDefaults ] ;
2017-01-24 17:53:16 +00:00
2009-03-28 17:18:43 +00:00
// checks for old version speeds of -1
if ( [ fDefaults integerForKey : @ "UploadLimit" ] < 0 )
{
[ fDefaults removeObjectForKey : @ "UploadLimit" ] ;
[ fDefaults setBool : NO forKey : @ "CheckUpload" ] ;
}
if ( [ fDefaults integerForKey : @ "DownloadLimit" ] < 0 )
{
[ fDefaults removeObjectForKey : @ "DownloadLimit" ] ;
[ fDefaults setBool : NO forKey : @ "CheckDownload" ] ;
}
2017-01-24 17:53:16 +00:00
2011-07-27 01:32:46 +00:00
// upgrading from versions < 2.40 : clear recent items
[ [ NSDocumentController sharedDocumentController ] clearRecentDocuments : nil ] ;
2017-01-24 17:53:16 +00:00
2012-12-14 04:34:42 +00:00
tr_variant settings ;
tr_variantInitDict ( & settings , 41 ) ;
2011-03-21 16:28:44 +00:00
tr_sessionGetDefaultSettings ( & settings ) ;
2017-01-24 17:53:16 +00:00
2009-03-29 23:10:36 +00:00
const BOOL usesSpeedLimitSched = [ fDefaults boolForKey : @ "SpeedLimitAuto" ] ;
if ( ! usesSpeedLimitSched )
2012-12-23 03:17:18 +00:00
tr_variantDictAddBool ( & settings , TR_KEY _alt _speed _enabled , [ fDefaults boolForKey : @ "SpeedLimit" ] ) ;
2017-01-24 17:53:16 +00:00
2012-12-23 03:17:18 +00:00
tr_variantDictAddInt ( & settings , TR_KEY _alt _speed _up , [ fDefaults integerForKey : @ "SpeedLimitUploadLimit" ] ) ;
tr_variantDictAddInt ( & settings , TR_KEY _alt _speed _down , [ fDefaults integerForKey : @ "SpeedLimitDownloadLimit" ] ) ;
2017-01-24 17:53:16 +00:00
2012-12-23 03:17:18 +00:00
tr_variantDictAddBool ( & settings , TR_KEY _alt _speed _time _enabled , [ fDefaults boolForKey : @ "SpeedLimitAuto" ] ) ;
tr_variantDictAddInt ( & settings , TR_KEY _alt _speed _time _begin , [ PrefsController dateToTimeSum :
2012-09-09 12:58:53 +00:00
[ fDefaults objectForKey : @ "SpeedLimitAutoOnDate" ] ] ) ;
2012-12-23 03:17:18 +00:00
tr_variantDictAddInt ( & settings , TR_KEY _alt _speed _time _end , [ PrefsController dateToTimeSum :
2012-09-09 12:58:53 +00:00
[ fDefaults objectForKey : @ "SpeedLimitAutoOffDate" ] ] ) ;
2012-12-23 03:17:18 +00:00
tr_variantDictAddInt ( & settings , TR_KEY _alt _speed _time _day , [ fDefaults integerForKey : @ "SpeedLimitAutoDay" ] ) ;
2017-01-24 17:53:16 +00:00
2013-08-03 01:24:42 +00:00
tr_variantDictAddInt ( & settings , TR_KEY _speed _limit _down , [ fDefaults integerForKey : @ "DownloadLimit" ] ) ;
2012-12-23 03:17:18 +00:00
tr_variantDictAddBool ( & settings , TR_KEY _speed _limit _down _enabled , [ fDefaults boolForKey : @ "CheckDownload" ] ) ;
tr_variantDictAddInt ( & settings , TR_KEY _speed _limit _up , [ fDefaults integerForKey : @ "UploadLimit" ] ) ;
tr_variantDictAddBool ( & settings , TR_KEY _speed _limit _up _enabled , [ fDefaults boolForKey : @ "CheckUpload" ] ) ;
2017-01-24 17:53:16 +00:00
2010-04-20 21:59:19 +00:00
// hidden prefs
if ( [ fDefaults objectForKey : @ "BindAddressIPv4" ] )
2012-12-23 03:17:18 +00:00
tr_variantDictAddStr ( & settings , TR_KEY _bind _address _ipv4 , [ [ fDefaults stringForKey : @ "BindAddressIPv4" ] UTF8String ] ) ;
2010-04-20 21:59:19 +00:00
if ( [ fDefaults objectForKey : @ "BindAddressIPv6" ] )
2012-12-23 03:17:18 +00:00
tr_variantDictAddStr ( & settings , TR_KEY _bind _address _ipv6 , [ [ fDefaults stringForKey : @ "BindAddressIPv6" ] UTF8String ] ) ;
2017-01-24 17:53:16 +00:00
2012-12-23 03:17:18 +00:00
tr_variantDictAddBool ( & settings , TR_KEY _blocklist _enabled , [ fDefaults boolForKey : @ "BlocklistNew" ] ) ;
2010-11-14 23:44:07 +00:00
if ( [ fDefaults objectForKey : @ "BlocklistURL" ] )
2012-12-23 03:17:18 +00:00
tr_variantDictAddStr ( & settings , TR_KEY _blocklist _url , [ [ fDefaults stringForKey : @ "BlocklistURL" ] UTF8String ] ) ;
tr_variantDictAddBool ( & settings , TR_KEY _dht _enabled , [ fDefaults boolForKey : @ "DHTGlobal" ] ) ;
tr_variantDictAddStr ( & settings , TR_KEY _download _dir , [ [ [ fDefaults stringForKey : @ "DownloadFolder" ]
2020-04-25 14:35:15 +00:00
stringByExpandingTildeInPath ] UTF8String ] ) ;
2012-12-23 03:17:18 +00:00
tr_variantDictAddBool ( & settings , TR_KEY _download _queue _enabled , [ fDefaults boolForKey : @ "Queue" ] ) ;
tr_variantDictAddInt ( & settings , TR_KEY _download _queue _size , [ fDefaults integerForKey : @ "QueueDownloadNumber" ] ) ;
tr_variantDictAddInt ( & settings , TR_KEY _idle _seeding _limit , [ fDefaults integerForKey : @ "IdleLimitMinutes" ] ) ;
tr_variantDictAddBool ( & settings , TR_KEY _idle _seeding _limit _enabled , [ fDefaults boolForKey : @ "IdleLimitCheck" ] ) ;
tr_variantDictAddStr ( & settings , TR_KEY _incomplete _dir , [ [ [ fDefaults stringForKey : @ "IncompleteDownloadFolder" ]
2020-04-25 14:35:15 +00:00
stringByExpandingTildeInPath ] UTF8String ] ) ;
2012-12-23 03:17:18 +00:00
tr_variantDictAddBool ( & settings , TR_KEY _incomplete _dir _enabled , [ fDefaults boolForKey : @ "UseIncompleteDownloadFolder" ] ) ;
tr_variantDictAddBool ( & settings , TR_KEY _lpd _enabled , [ fDefaults boolForKey : @ "LocalPeerDiscoveryGlobal" ] ) ;
2013-01-26 19:17:58 +00:00
tr_variantDictAddInt ( & settings , TR_KEY _message _level , TR_LOG _DEBUG ) ;
2012-12-23 03:17:18 +00:00
tr_variantDictAddInt ( & settings , TR_KEY _peer _limit _global , [ fDefaults integerForKey : @ "PeersTotal" ] ) ;
tr_variantDictAddInt ( & settings , TR_KEY _peer _limit _per _torrent , [ fDefaults integerForKey : @ "PeersTorrent" ] ) ;
2017-01-24 17:53:16 +00:00
2008-12-14 00:31:33 +00:00
const BOOL randomPort = [ fDefaults boolForKey : @ "RandomPort" ] ;
2012-12-23 03:17:18 +00:00
tr_variantDictAddBool ( & settings , TR_KEY _peer _port _random _on _start , randomPort ) ;
2008-12-14 00:31:33 +00:00
if ( ! randomPort )
2012-12-23 03:17:18 +00:00
tr_variantDictAddInt ( & settings , TR_KEY _peer _port , [ fDefaults integerForKey : @ "BindPort" ] ) ;
2017-01-24 17:53:16 +00:00
2008-12-14 00:31:33 +00:00
// hidden pref
if ( [ fDefaults objectForKey : @ "PeerSocketTOS" ] )
2012-12-23 03:17:18 +00:00
tr_variantDictAddStr ( & settings , TR_KEY _peer _socket _tos , [ [ fDefaults stringForKey : @ "PeerSocketTOS" ] UTF8String ] ) ;
2017-01-24 17:53:16 +00:00
2012-12-23 03:17:18 +00:00
tr_variantDictAddBool ( & settings , TR_KEY _pex _enabled , [ fDefaults boolForKey : @ "PEXGlobal" ] ) ;
tr_variantDictAddBool ( & settings , TR_KEY _port _forwarding _enabled , [ fDefaults boolForKey : @ "NatTraversal" ] ) ;
tr_variantDictAddBool ( & settings , TR_KEY _queue _stalled _enabled , [ fDefaults boolForKey : @ "CheckStalled" ] ) ;
tr_variantDictAddInt ( & settings , TR_KEY _queue _stalled _minutes , [ fDefaults integerForKey : @ "StalledMinutes" ] ) ;
tr_variantDictAddReal ( & settings , TR_KEY _ratio _limit , [ fDefaults floatForKey : @ "RatioLimit" ] ) ;
tr_variantDictAddBool ( & settings , TR_KEY _ratio _limit _enabled , [ fDefaults boolForKey : @ "RatioCheck" ] ) ;
tr_variantDictAddBool ( & settings , TR_KEY _rename _partial _files , [ fDefaults boolForKey : @ "RenamePartialFiles" ] ) ;
tr_variantDictAddBool ( & settings , TR_KEY _rpc _authentication _required , [ fDefaults boolForKey : @ "RPCAuthorize" ] ) ;
tr_variantDictAddBool ( & settings , TR_KEY _rpc _enabled , [ fDefaults boolForKey : @ "RPC" ] ) ;
tr_variantDictAddInt ( & settings , TR_KEY _rpc _port , [ fDefaults integerForKey : @ "RPCPort" ] ) ;
tr_variantDictAddStr ( & settings , TR_KEY _rpc _username , [ [ fDefaults stringForKey : @ "RPCUsername" ] UTF8String ] ) ;
tr_variantDictAddBool ( & settings , TR_KEY _rpc _whitelist _enabled , [ fDefaults boolForKey : @ "RPCUseWhitelist" ] ) ;
2018-01-16 21:46:54 +00:00
tr_variantDictAddBool ( & settings , TR_KEY _rpc _host _whitelist _enabled , [ fDefaults boolForKey : @ "RPCUseHostWhitelist" ] ) ;
2012-12-23 03:17:18 +00:00
tr_variantDictAddBool ( & settings , TR_KEY _seed _queue _enabled , [ fDefaults boolForKey : @ "QueueSeed" ] ) ;
tr_variantDictAddInt ( & settings , TR_KEY _seed _queue _size , [ fDefaults integerForKey : @ "QueueSeedNumber" ] ) ;
tr_variantDictAddBool ( & settings , TR_KEY _start _added _torrents , [ fDefaults boolForKey : @ "AutoStartDownload" ] ) ;
tr_variantDictAddBool ( & settings , TR_KEY _script _torrent _done _enabled , [ fDefaults boolForKey : @ "DoneScriptEnabled" ] ) ;
2020-04-25 14:35:15 +00:00
tr_variantDictAddStr ( & settings , TR_KEY _script _torrent _done _filename , [ [ fDefaults stringForKey : @ "DoneScriptPath" ] UTF8String ] ) ;
2012-12-23 03:17:18 +00:00
tr_variantDictAddBool ( & settings , TR_KEY _utp _enabled , [ fDefaults boolForKey : @ "UTPGlobal" ] ) ;
2017-01-24 17:53:16 +00:00
2018-01-16 21:46:54 +00:00
// TODO : Add to GUI
if ( [ fDefaults objectForKey : @ "RPCHostWhitelist" ] )
tr_variantDictAddStr ( & settings , TR_KEY _rpc _host _whitelist , [ [ fDefaults stringForKey : @ "RPCHostWhitelist" ] UTF8String ] ) ;
2017-01-24 17:53:16 +00:00
2017-02-05 19:29:20 +00:00
NSByteCountFormatter * unitFormatter = [ [ NSByteCountFormatter alloc ] init ] ;
[ unitFormatter setIncludesCount : NO ] ;
[ unitFormatter setAllowsNonnumericFormatting : NO ] ;
2017-01-24 17:53:16 +00:00
2017-02-05 19:29:20 +00:00
[ unitFormatter setAllowedUnits : NSByteCountFormatterUseKB ] ;
NSString * kbString = [ unitFormatter stringFromByteCount : 17 ] ; // use a random value to avoid possible pluralization issues with 1 or 0 ( an example is if we use 1 for bytes , we ' d get "byte" when we ' d want "bytes" for the generic libtransmission value at least )
2017-01-24 17:53:16 +00:00
2017-02-05 19:29:20 +00:00
[ unitFormatter setAllowedUnits : NSByteCountFormatterUseMB ] ;
NSString * mbString = [ unitFormatter stringFromByteCount : 17 ] ;
2017-01-24 17:53:16 +00:00
2017-02-05 19:29:20 +00:00
[ unitFormatter setAllowedUnits : NSByteCountFormatterUseGB ] ;
NSString * gbString = [ unitFormatter stringFromByteCount : 17 ] ;
2017-01-24 17:53:16 +00:00
2017-02-05 19:29:20 +00:00
[ unitFormatter setAllowedUnits : NSByteCountFormatterUseTB ] ;
NSString * tbString = [ unitFormatter stringFromByteCount : 17 ] ;
2017-01-24 17:53:16 +00:00
2012-09-10 03:09:56 +00:00
tr_formatter _size _init ( 1000 , [ kbString UTF8String ] ,
[ mbString UTF8String ] ,
[ gbString UTF8String ] ,
[ tbString UTF8String ] ) ;
2012-09-09 12:58:53 +00:00
2011-10-06 00:30:40 +00:00
tr_formatter _speed _init ( 1000 , [ NSLocalizedString ( @ "KB/s" , "Transfer speed (kilobytes per second)" ) UTF8String ] ,
2012-09-09 12:58:53 +00:00
[ NSLocalizedString ( @ "MB/s" , "Transfer speed (megabytes per second)" ) UTF8String ] ,
[ NSLocalizedString ( @ "GB/s" , "Transfer speed (gigabytes per second)" ) UTF8String ] ,
[ NSLocalizedString ( @ "TB/s" , "Transfer speed (terabytes per second)" ) UTF8String ] ) ; // why not ?
2012-09-10 03:09:56 +00:00
tr_formatter _mem _init ( 1000 , [ kbString UTF8String ] ,
[ mbString UTF8String ] ,
[ gbString UTF8String ] ,
[ tbString UTF8String ] ) ;
2017-01-24 17:53:16 +00:00
2012-02-29 02:45:42 +00:00
const char * configDir = tr_getDefaultConfigDir ( "Transmission" ) ;
2015-10-18 18:39:14 +00:00
fLib = tr_sessionInit ( configDir , YES , & settings ) ;
2012-12-14 04:34:42 +00:00
tr_variantFree ( & settings ) ;
2017-01-24 17:53:16 +00:00
2020-04-25 14:35:15 +00:00
fConfigDirectory = [ [ NSString alloc ] initWithUTF8String : configDir ] ;
2017-01-24 17:53:16 +00:00
2007-09-26 04:12:57 +00:00
[ NSApp setDelegate : self ] ;
2017-01-24 17:53:16 +00:00
2010-01-23 00:36:18 +00:00
// register for magnet URLs ( has to be in init )
[ [ NSAppleEventManager sharedAppleEventManager ] setEventHandler : self andSelector : @ selector ( handleOpenContentsEvent : replyEvent : )
2012-09-09 12:58:53 +00:00
forEventClass : kInternetEventClass andEventID : kAEGetURL ] ;
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
fTorrents = [ [ NSMutableArray alloc ] init ] ;
fDisplayedTorrents = [ [ NSMutableArray alloc ] init ] ;
2017-01-24 17:53:16 +00:00
2007-10-07 12:24:26 +00:00
fInfoController = [ [ InfoWindowController alloc ] init ] ;
2017-01-24 17:53:16 +00:00
2013-01-19 05:03:00 +00:00
// needs to be done before init - ing the prefs controller
2013-02-08 13:18:41 +00:00
fFileWatcherQueue = [ [ VDKQueue alloc ] init ] ;
2013-01-19 05:03:00 +00:00
[ fFileWatcherQueue setDelegate : self ] ;
2017-01-24 17:53:16 +00:00
2012-05-29 01:03:21 +00:00
fPrefsController = [ [ PrefsController alloc ] initWithHandle : fLib ] ;
2017-01-24 17:53:16 +00:00
2009-10-12 00:48:16 +00:00
fQuitting = NO ;
2011-07-27 03:38:01 +00:00
fGlobalPopoverShown = NO ;
2008-04-10 16:37:07 +00:00
fSoundPlaying = NO ;
2017-01-24 17:53:16 +00:00
2017-07-29 16:14:22 +00:00
tr_sessionSetAltSpeedFunc ( fLib , altSpeedToggledCallback , ( __bridge void * ) ( self ) ) ;
2009-03-29 23:10:36 +00:00
if ( usesSpeedLimitSched )
[ fDefaults setBool : tr_sessionUsesAltSpeed ( fLib ) forKey : @ "SpeedLimit" ] ;
2017-01-24 17:53:16 +00:00
2017-07-29 16:14:22 +00:00
tr_sessionSetRPCCallback ( fLib , rpcCallback , ( __bridge void * ) ( self ) ) ;
2017-01-24 17:53:16 +00:00
2009-03-01 17:02:58 +00:00
[ [ SUUpdater sharedUpdater ] setDelegate : self ] ;
2011-01-15 18:44:39 +00:00
fQuitRequested = NO ;
2017-01-24 17:53:16 +00:00
2009-05-12 00:58:22 +00:00
fPauseOnLaunch = ( GetCurrentKeyModifiers ( ) & ( optionKey | rightOptionKey ) ) ! = 0 ;
2007-09-16 01:02:06 +00:00
}
return self ;
}
- ( void ) awakeFromNib
{
2007-12-06 17:21:42 +00:00
NSToolbar * toolbar = [ [ NSToolbar alloc ] initWithIdentifier : @ "TRMainToolbar" ] ;
2007-09-16 01:02:06 +00:00
[ toolbar setDelegate : self ] ;
[ toolbar setAllowsUserCustomization : YES ] ;
[ toolbar setAutosavesConfiguration : YES ] ;
2007-12-08 18:51:02 +00:00
[ toolbar setDisplayMode : NSToolbarDisplayModeIconOnly ] ;
2007-09-16 01:02:06 +00:00
[ fWindow setToolbar : toolbar ] ;
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
[ fWindow setDelegate : self ] ; // do manually to avoid placement issue
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
[ fWindow makeFirstResponder : fTableView ] ;
[ fWindow setExcludedFromWindowsMenu : YES ] ;
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
// set table size
2011-06-13 23:02:38 +00:00
const BOOL small = [ fDefaults boolForKey : @ "SmallView" ] ;
if ( small )
2007-09-16 01:02:06 +00:00
[ fTableView setRowHeight : ROW_HEIGHT _SMALL ] ;
2011-06-13 23:02:38 +00:00
[ fTableView setUsesAlternatingRowBackgroundColors : ! small ] ;
2017-01-24 17:53:16 +00:00
2009-11-28 17:44:47 +00:00
[ fWindow setContentBorderThickness : NSMinY ( [ [ fTableView enclosingScrollView ] frame ] ) forEdge : NSMinYEdge ] ;
2010-12-09 23:30:35 +00:00
[ fWindow setMovableByWindowBackground : YES ] ;
2017-01-24 17:53:16 +00:00
2008-12-26 05:57:51 +00:00
[ [ fTotalTorrentsField cell ] setBackgroundStyle : NSBackgroundStyleRaised ] ;
2017-01-24 17:53:16 +00:00
2007-12-12 05:01:31 +00:00
// set up filter bar
2007-09-16 01:02:06 +00:00
[ self showFilterBar : [ fDefaults boolForKey : @ "FilterBar" ] animate : NO ] ;
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
// set up status bar
[ self showStatusBar : [ fDefaults boolForKey : @ "StatusBar" ] animate : NO ] ;
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
[ fActionButton setToolTip : NSLocalizedString ( @ "Shortcuts for changing global settings." ,
2012-09-09 12:58:53 +00:00
"Main window -> 1st bottom left button (action) tooltip" ) ] ;
2007-09-16 01:02:06 +00:00
[ fSpeedLimitButton setToolTip : NSLocalizedString ( @ "Speed Limit overrides the total bandwidth limits with its own limits." ,
2012-09-09 12:58:53 +00:00
"Main window -> 2nd bottom left button (turtle) tooltip" ) ] ;
2020-11-21 13:27:07 +00:00
if ( @ available ( macOS 11.0 , * ) ) {
[ fActionButton setImage : [ NSImage imageWithSystemSymbolName : @ "gearshape.fill" accessibilityDescription : nil ] ] ;
[ fSpeedLimitButton setImage : [ NSImage imageWithSystemSymbolName : @ "tortoise.fill" accessibilityDescription : nil ] ] ;
}
2011-03-14 23:46:53 +00:00
[ fClearCompletedButton setToolTip : NSLocalizedString ( @ "Remove all transfers that have completed seeding." ,
2012-09-09 12:58:53 +00:00
"Main window -> 3rd bottom left button (remove all) tooltip" ) ] ;
2017-01-24 17:53:16 +00:00
2017-07-08 08:23:05 +00:00
[ fTableView registerForDraggedTypes : @ [ TORRENT_TABLE _VIEW _DATA _TYPE ] ] ;
[ fWindow registerForDraggedTypes : @ [ NSFilenamesPboardType , NSURLPboardType ] ] ;
2017-01-24 17:53:16 +00:00
2012-01-30 00:14:43 +00:00
// sort the sort menu items ( localization is from strings file )
NSMutableArray * sortMenuItems = [ NSMutableArray arrayWithCapacity : 7 ] ;
NSUInteger sortMenuIndex = 0 ;
BOOL foundSortItem = NO ;
for ( NSMenuItem * item in [ fSortMenu itemArray ] )
{
2012-01-31 04:22:51 +00:00
// assume all sort items are together and the Queue Order item is first
2012-01-30 00:14:43 +00:00
if ( [ item action ] = = @ selector ( setSort : ) && [ item tag ] ! = SORT_ORDER _TAG )
{
[ sortMenuItems addObject : item ] ;
[ fSortMenu removeItemAtIndex : sortMenuIndex ] ;
foundSortItem = YES ;
}
else
{
if ( foundSortItem )
break ;
+ + sortMenuIndex ;
}
}
2017-01-24 17:53:16 +00:00
2017-07-08 08:23:05 +00:00
[ sortMenuItems sortUsingDescriptors : @ [ [ NSSortDescriptor sortDescriptorWithKey : @ "title" ascending : YES selector : @ selector ( localizedCompare : ) ] ] ] ;
2017-01-24 17:53:16 +00:00
2012-01-30 00:14:43 +00:00
for ( NSMenuItem * item in sortMenuItems )
[ fSortMenu insertItem : item atIndex : sortMenuIndex + + ] ;
2017-01-24 17:53:16 +00:00
2011-07-18 00:48:00 +00:00
// you would think this would be called later in this method from updateUI , but it ' s not reached in awakeFromNib
// this must be called after showStatusBar :
2011-07-06 23:22:21 +00:00
[ fStatusBar updateWithDownload : 0.0 upload : 0.0 ] ;
2012-09-09 12:58:53 +00:00
2011-07-18 00:48:00 +00:00
// this should also be after the rest of the setup
[ self updateForAutoSize ] ;
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
// register for sleep notifications
IONotificationPortRef notify ;
io_object _t iterator ;
2017-07-29 16:14:22 +00:00
if ( ( fRootPort = IORegisterForSystemPower ( ( __bridge void * ) ( self ) , & notify , sleepCallback , & iterator ) ) )
2007-09-16 01:02:06 +00:00
CFRunLoopAddSource ( CFRunLoopGetCurrent ( ) , IONotificationPortGetRunLoopSource ( notify ) , kCFRunLoopCommonModes ) ;
else
NSLog ( @ "Could not IORegisterForSystemPower" ) ;
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
// load previous transfers
2012-03-18 14:33:50 +00:00
NSString * historyFile = [ fConfigDirectory stringByAppendingPathComponent : TRANSFER_PLIST ] ;
NSArray * history = [ NSArray arrayWithContentsOfFile : historyFile ] ;
2007-09-16 01:02:06 +00:00
if ( ! history )
{
2010-02-09 13:15:52 +00:00
// old version saved transfer info in prefs file
2007-09-16 01:02:06 +00:00
if ( ( history = [ fDefaults arrayForKey : @ "History" ] ) )
2009-01-26 02:16:03 +00:00
[ fDefaults removeObjectForKey : @ "History" ] ;
2007-09-16 01:02:06 +00:00
}
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
if ( history )
{
2011-08-02 12:43:26 +00:00
NSMutableArray * waitToStartTorrents = [ NSMutableArray arrayWithCapacity : ( ( [ history count ] > 0 && ! fPauseOnLaunch ) ? [ history count ] -1 : 0 ) ] ; // theoretical max without doing a lot of work
2017-01-24 17:53:16 +00:00
2008-12-26 07:06:02 +00:00
for ( NSDictionary * historyItem in history )
{
Torrent * torrent ;
2009-05-12 00:58:22 +00:00
if ( ( torrent = [ [ Torrent alloc ] initWithHistory : historyItem lib : fLib forcePause : fPauseOnLaunch ] ) )
2007-09-16 01:02:06 +00:00
{
[ fTorrents addObject : torrent ] ;
2017-01-24 17:53:16 +00:00
2011-08-02 12:43:26 +00:00
NSNumber * waitToStart ;
2017-07-08 14:38:47 +00:00
if ( ! fPauseOnLaunch && ( waitToStart = historyItem [ @ "WaitToStart" ] ) && [ waitToStart boolValue ] )
2011-08-02 12:43:26 +00:00
[ waitToStartTorrents addObject : torrent ] ;
2007-09-16 01:02:06 +00:00
}
2008-12-26 07:06:02 +00:00
}
2017-01-24 17:53:16 +00:00
2011-08-02 12:43:26 +00:00
// now that all are loaded , let ' s set those in the queue to waiting
for ( Torrent * torrent in waitToStartTorrents )
[ torrent startTransfer ] ;
2007-09-16 01:02:06 +00:00
}
2017-01-24 17:53:16 +00:00
2008-10-01 02:40:04 +00:00
fBadger = [ [ Badger alloc ] initWithLib : fLib ] ;
2017-01-24 17:53:16 +00:00
2017-02-05 19:29:20 +00:00
[ [ NSUserNotificationCenter defaultUserNotificationCenter ] setDelegate : self ] ;
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
// observe notifications
NSNotificationCenter * nc = [ NSNotificationCenter defaultCenter ] ;
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
[ nc addObserver : self selector : @ selector ( updateUI )
2012-09-09 12:58:53 +00:00
name : @ "UpdateUI" object : nil ] ;
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
[ nc addObserver : self selector : @ selector ( torrentFinishedDownloading : )
2012-09-09 12:58:53 +00:00
name : @ "TorrentFinishedDownloading" object : nil ] ;
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
[ nc addObserver : self selector : @ selector ( torrentRestartedDownloading : )
2012-09-09 12:58:53 +00:00
name : @ "TorrentRestartedDownloading" object : nil ] ;
2017-01-24 17:53:16 +00:00
2010-08-14 19:44:43 +00:00
[ nc addObserver : self selector : @ selector ( torrentFinishedSeeding : )
2012-09-09 12:58:53 +00:00
name : @ "TorrentFinishedSeeding" object : nil ] ;
2017-01-24 17:53:16 +00:00
2012-10-30 00:22:10 +00:00
[ nc addObserver : self selector : @ selector ( applyFilter )
name : kTorrentDidChangeGroupNotification object : nil ] ;
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
// avoids need of setting delegate
[ nc addObserver : self selector : @ selector ( torrentTableViewSelectionDidChange : )
2012-09-09 12:58:53 +00:00
name : NSOutlineViewSelectionDidChangeNotification object : fTableView ] ;
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
[ nc addObserver : self selector : @ selector ( changeAutoImport )
2012-09-09 12:58:53 +00:00
name : @ "AutoImportSettingChange" object : nil ] ;
2017-01-24 17:53:16 +00:00
2011-07-18 00:48:00 +00:00
[ nc addObserver : self selector : @ selector ( updateForAutoSize )
2012-09-09 12:58:53 +00:00
name : @ "AutoSizeSettingChange" object : nil ] ;
2017-01-24 17:53:16 +00:00
2008-02-06 23:45:44 +00:00
[ nc addObserver : self selector : @ selector ( updateForExpandCollape )
2012-09-09 12:58:53 +00:00
name : @ "OutlineExpandCollapse" object : nil ] ;
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
[ nc addObserver : fWindow selector : @ selector ( makeKeyWindow )
2012-09-09 12:58:53 +00:00
name : @ "MakeWindowKey" object : nil ] ;
2017-01-24 17:53:16 +00:00
2013-01-22 03:54:51 +00:00
# warning rename
2011-08-04 02:03:58 +00:00
[ nc addObserver : self selector : @ selector ( fullUpdateUI )
2012-09-09 12:58:53 +00:00
name : @ "UpdateQueue" object : nil ] ;
2017-01-24 17:53:16 +00:00
2011-02-20 03:58:50 +00:00
[ nc addObserver : self selector : @ selector ( applyFilter )
2012-09-09 12:58:53 +00:00
name : @ "ApplyFilter" object : nil ] ;
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
// open newly created torrent file
[ nc addObserver : self selector : @ selector ( beginCreateFile : )
2012-09-09 12:58:53 +00:00
name : @ "BeginCreateTorrentFile" object : nil ] ;
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
// open newly created torrent file
[ nc addObserver : self selector : @ selector ( openCreatedFile : )
2012-09-09 12:58:53 +00:00
name : @ "OpenCreatedTorrentFile" object : nil ] ;
2017-01-24 17:53:16 +00:00
2012-01-12 00:12:17 +00:00
[ nc addObserver : self selector : @ selector ( applyFilter )
2012-09-09 12:58:53 +00:00
name : @ "UpdateGroups" object : nil ] ;
2007-09-16 01:02:06 +00:00
// timer to update the interface every second
[ self updateUI ] ;
2017-07-29 16:14:22 +00:00
fTimer = [ NSTimer scheduledTimerWithTimeInterval : UPDATE_UI _SECONDS target : self
selector : @ selector ( updateUI ) userInfo : nil repeats : YES ] ;
2008-09-01 23:41:46 +00:00
[ [ NSRunLoop currentRunLoop ] addTimer : fTimer forMode : NSModalPanelRunLoopMode ] ;
[ [ NSRunLoop currentRunLoop ] addTimer : fTimer forMode : NSEventTrackingRunLoopMode ] ;
2017-01-24 17:53:16 +00:00
2011-02-20 03:58:50 +00:00
[ self applyFilter ] ;
2017-01-24 17:53:16 +00:00
2009-12-13 21:42:45 +00:00
[ fWindow makeKeyAndOrderFront : nil ] ;
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
if ( [ fDefaults boolForKey : @ "InfoVisible" ] )
[ self showInfo : nil ] ;
2009-08-14 03:14:37 +00:00
}
- ( void ) applicationDidFinishLaunching : ( NSNotification * ) notification
{
[ NSApp setServicesProvider : self ] ;
2017-01-24 17:53:16 +00:00
2010-01-23 00:05:40 +00:00
// register for dock icon drags ( has to be in applicationDidFinishLaunching : to work )
[ [ NSAppleEventManager sharedAppleEventManager ] setEventHandler : self andSelector : @ selector ( handleOpenContentsEvent : replyEvent : )
2012-09-09 12:58:53 +00:00
forEventClass : kCoreEventClass andEventID : kAEOpenContents ] ;
2017-01-24 17:53:16 +00:00
2012-07-25 12:49:11 +00:00
// if we were opened from a user notification , do the corresponding action
2017-07-17 17:34:52 +00:00
NSUserNotification * launchNotification = [ notification userInfo ] [ NSApplicationLaunchUserNotificationKey ] ;
2017-02-05 19:29:20 +00:00
if ( launchNotification )
[ self userNotificationCenter : nil didActivateNotification : launchNotification ] ;
2017-01-24 17:53:16 +00:00
2009-08-14 03:14:37 +00:00
// auto importing
[ self checkAutoImportDirectory ] ;
2017-01-24 17:53:16 +00:00
2009-08-14 03:14:37 +00:00
// registering the Web UI to Bonjour
if ( [ fDefaults boolForKey : @ "RPC" ] && [ fDefaults boolForKey : @ "RPCWebDiscovery" ] )
[ [ BonjourController defaultController ] startWithPort : [ fDefaults integerForKey : @ "RPCPort" ] ] ;
2017-01-24 17:53:16 +00:00
2009-08-14 01:11:13 +00:00
// shamelessly ask for donations
2009-08-19 00:38:53 +00:00
if ( [ fDefaults boolForKey : @ "WarningDonate" ] )
2009-08-14 01:11:13 +00:00
{
2009-08-19 00:38:53 +00:00
tr_session _stats stats ;
tr_sessionGetCumulativeStats ( fLib , & stats ) ;
const BOOL firstLaunch = stats . sessionCount <= 1 ;
2017-01-24 17:53:16 +00:00
2009-08-19 00:38:53 +00:00
NSDate * lastDonateDate = [ fDefaults objectForKey : @ "DonateAskDate" ] ;
const BOOL timePassed = ! lastDonateDate || ( -1 * [ lastDonateDate timeIntervalSinceNow ] ) >= DONATE_NAG _TIME ;
2017-01-24 17:53:16 +00:00
2009-08-19 00:38:53 +00:00
if ( ! firstLaunch && timePassed )
{
2009-10-24 20:44:48 +00:00
[ fDefaults setObject : [ NSDate date ] forKey : @ "DonateAskDate" ] ;
2017-01-24 17:53:16 +00:00
2009-08-19 00:38:53 +00:00
NSAlert * alert = [ [ NSAlert alloc ] init ] ;
[ alert setMessageText : NSLocalizedString ( @ "Support open-source indie software" , "Donation beg -> title" ) ] ;
2017-01-24 17:53:16 +00:00
2009-08-19 00:38:53 +00:00
NSString * donateMessage = [ NSString stringWithFormat : @ "%@\n\n%@" ,
2012-09-09 12:58:53 +00:00
NSLocalizedString ( @ "Transmission is a full-featured torrent application."
" A lot of time and effort have gone into development, coding, and refinement."
" If you enjoy using it, please consider showing your love with a donation." , "Donation beg -> message" ) ,
NSLocalizedString ( @ "Donate or not, there will be no difference to your torrenting experience." , "Donation beg -> message" ) ] ;
2017-01-24 17:53:16 +00:00
2009-08-19 00:38:53 +00:00
[ alert setInformativeText : donateMessage ] ;
[ alert setAlertStyle : NSInformationalAlertStyle ] ;
2017-01-24 17:53:16 +00:00
2009-08-19 00:38:53 +00:00
[ alert addButtonWithTitle : [ NSLocalizedString ( @ "Donate" , "Donation beg -> button" ) stringByAppendingEllipsis ] ] ;
NSButton * noDonateButton = [ alert addButtonWithTitle : NSLocalizedString ( @ "Nope" , "Donation beg -> button" ) ] ;
[ noDonateButton setKeyEquivalent : @ "\e" ] ; // escape key
2017-01-24 17:53:16 +00:00
2009-08-19 00:38:53 +00:00
const BOOL allowNeverAgain = lastDonateDate ! = nil ; // hide the "don't show again" check the first time - give them time to try the app
[ alert setShowsSuppressionButton : allowNeverAgain ] ;
if ( allowNeverAgain )
[ [ alert suppressionButton ] setTitle : NSLocalizedString ( @ "Don't bug me about this ever again." , "Donation beg -> button" ) ] ;
2017-01-24 17:53:16 +00:00
2009-08-19 00:38:53 +00:00
const NSInteger donateResult = [ alert runModal ] ;
if ( donateResult = = NSAlertFirstButtonReturn )
[ self linkDonate : self ] ;
2017-01-24 17:53:16 +00:00
2009-08-19 00:38:53 +00:00
if ( allowNeverAgain )
[ fDefaults setBool : ( [ [ alert suppressionButton ] state ] ! = NSOnState ) forKey : @ "WarningDonate" ] ;
}
2009-08-14 01:11:13 +00:00
}
2007-09-16 01:02:06 +00:00
}
- ( BOOL ) applicationShouldHandleReopen : ( NSApplication * ) app hasVisibleWindows : ( BOOL ) visibleWindows
{
2009-12-12 02:39:31 +00:00
NSWindow * mainWindow = [ NSApp mainWindow ] ;
if ( ! mainWindow || ! [ mainWindow isVisible ] )
[ fWindow makeKeyAndOrderFront : nil ] ;
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
return NO ;
}
- ( NSApplicationTerminateReply ) applicationShouldTerminate : ( NSApplication * ) sender
{
2011-01-15 18:44:39 +00:00
if ( ! fQuitRequested && [ fDefaults boolForKey : @ "CheckQuit" ] )
2007-09-16 01:02:06 +00:00
{
2008-11-02 13:52:45 +00:00
NSInteger active = 0 , downloading = 0 ;
2008-12-26 07:06:02 +00:00
for ( Torrent * torrent in fTorrents )
2007-12-31 18:37:34 +00:00
if ( [ torrent isActive ] && ! [ torrent isStalled ] )
2007-09-16 01:02:06 +00:00
{
active + + ;
2007-10-14 14:24:34 +00:00
if ( ! [ torrent allDownloaded ] )
2007-09-16 01:02:06 +00:00
downloading + + ;
}
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
if ( [ fDefaults boolForKey : @ "CheckQuitDownloading" ] ? downloading > 0 : active > 0 )
{
2018-12-26 15:15:33 +00:00
NSAlert * alert = [ [ NSAlert alloc ] init ] ;
alert . alertStyle = NSAlertStyleInformational ;
alert . messageText = NSLocalizedString ( @ "Are you sure you want to quit?" , "Confirm Quit panel -> title" ) ;
alert . informativeText = active = = 1
2012-09-09 12:58:53 +00:00
? NSLocalizedString ( @ "There is an active transfer that will be paused on quit."
" The transfer will automatically resume on the next launch." , "Confirm Quit panel -> message" )
: [ NSString stringWithFormat : NSLocalizedString ( @ "There are %d active transfers that will be paused on quit."
" The transfers will automatically resume on the next launch." , "Confirm Quit panel -> message" ) , active ] ;
2018-12-26 15:15:33 +00:00
[ alert addButtonWithTitle : NSLocalizedString ( @ "Quit" , "Confirm Quit panel -> button" ) ] ;
[ alert addButtonWithTitle : NSLocalizedString ( @ "Cancel" , "Confirm Quit panel -> button" ) ] ;
[ alert beginSheetModalForWindow : fWindow
completionHandler : ^ ( NSModalResponse returnCode ) {
[ NSApp replyToApplicationShouldTerminate : returnCode = = NSAlertFirstButtonReturn ] ;
} ] ;
2007-09-16 01:02:06 +00:00
return NSTerminateLater ;
}
}
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
return NSTerminateNow ;
}
- ( void ) applicationWillTerminate : ( NSNotification * ) notification
{
2009-10-12 00:48:16 +00:00
fQuitting = YES ;
2017-01-24 17:53:16 +00:00
2008-12-06 01:18:25 +00:00
// stop the Bonjour service
2012-09-10 02:01:07 +00:00
if ( [ BonjourController defaultControllerExists ] )
[ [ BonjourController defaultController ] stop ] ;
2012-09-09 12:58:53 +00:00
2008-08-31 20:26:41 +00:00
// stop blocklist download
if ( [ BlocklistDownloader isRunning ] )
2008-08-31 20:48:10 +00:00
[ [ BlocklistDownloader downloader ] cancelDownload ] ;
2017-01-24 17:53:16 +00:00
2007-11-02 03:15:12 +00:00
// stop timers and notification checking
[ [ NSNotificationCenter defaultCenter ] removeObserver : self ] ;
2017-01-24 17:53:16 +00:00
2007-11-02 03:15:12 +00:00
[ fTimer invalidate ] ;
2017-01-24 17:53:16 +00:00
2007-11-02 03:15:12 +00:00
if ( fAutoImportTimer )
2017-01-24 17:53:16 +00:00
{
2007-11-02 03:15:12 +00:00
if ( [ fAutoImportTimer isValid ] )
[ fAutoImportTimer invalidate ] ;
}
2017-01-24 17:53:16 +00:00
2007-12-20 01:42:30 +00:00
[ fBadger setQuitting ] ;
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
// remove all torrent downloads
if ( fPendingTorrentDownloads )
{
2008-12-26 07:06:02 +00:00
for ( NSDictionary * downloadDict in fPendingTorrentDownloads )
2007-09-16 01:02:06 +00:00
{
2017-07-08 14:38:47 +00:00
NSURLDownload * download = downloadDict [ @ "Download" ] ;
2007-09-16 01:02:06 +00:00
[ download cancel ] ;
}
}
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
// remember window states and close all windows
[ fDefaults setBool : [ [ fInfoController window ] isVisible ] forKey : @ "InfoVisible" ] ;
2017-01-24 17:53:16 +00:00
2011-10-06 00:30:40 +00:00
if ( [ QLPreviewPanel sharedPreviewPanelExists ] && [ [ QLPreviewPanel sharedPreviewPanel ] isVisible ] )
[ [ QLPreviewPanel sharedPreviewPanel ] updateController ] ;
2017-01-24 17:53:16 +00:00
2009-10-12 00:48:16 +00:00
for ( NSWindow * window in [ NSApp windows ] )
2010-01-16 22:57:21 +00:00
[ window close ] ;
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
[ self showStatusBar : NO animate : NO ] ;
[ self showFilterBar : NO animate : NO ] ;
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
// save history
[ self updateTorrentHistory ] ;
2008-02-07 21:26:04 +00:00
[ fTableView saveCollapsedGroups ] ;
2017-08-05 11:41:36 +00:00
fFileWatcherQueue = nil ;
2017-01-24 17:53:16 +00:00
2007-11-05 12:47:20 +00:00
// complete cleanup
2008-05-19 00:23:06 +00:00
tr_sessionClose ( fLib ) ;
2007-09-16 01:02:06 +00:00
}
2012-05-27 22:31:58 +00:00
- ( tr_session * ) sessionHandle
{
return fLib ;
}
2007-09-16 01:02:06 +00:00
- ( void ) handleOpenContentsEvent : ( NSAppleEventDescriptor * ) event replyEvent : ( NSAppleEventDescriptor * ) replyEvent
{
NSString * urlString = nil ;
2012-09-09 12:58:53 +00:00
2007-09-16 01:02:06 +00:00
NSAppleEventDescriptor * directObject = [ event paramDescriptorForKeyword : keyDirectObject ] ;
if ( [ directObject descriptorType ] = = typeAEList )
{
2009-10-15 23:18:39 +00:00
for ( NSInteger i = 1 ; i <= [ directObject numberOfItems ] ; i + + )
2007-09-16 01:02:06 +00:00
if ( ( urlString = [ [ directObject descriptorAtIndex : i ] stringValue ] ) )
break ;
}
else
urlString = [ directObject stringValue ] ;
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
if ( urlString )
2009-11-26 16:38:21 +00:00
[ self openURL : urlString ] ;
2007-09-16 01:02:06 +00:00
}
- ( void ) download : ( NSURLDownload * ) download decideDestinationWithSuggestedFilename : ( NSString * ) suggestedName
{
if ( [ [ suggestedName pathExtension ] caseInsensitiveCompare : @ "torrent" ] ! = NSOrderedSame )
{
[ download cancel ] ;
2017-01-24 17:53:16 +00:00
2012-03-13 03:39:56 +00:00
[ fPendingTorrentDownloads removeObjectForKey : [ [ download request ] URL ] ] ;
if ( [ fPendingTorrentDownloads count ] = = 0 )
{
fPendingTorrentDownloads = nil ;
}
2017-01-24 17:53:16 +00:00
2020-09-10 05:42:53 +00:00
NSString * message = [ NSString stringWithFormat : NSLocalizedString ( @ "It appears that the file \" % @ \ " from %@ is not a torrent file." ,
"Download not a torrent -> message" ) , suggestedName ,
[ [ [ [ download request ] URL ] absoluteString ] stringByReplacingPercentEscapesUsingEncoding : NSUTF8StringEncoding ] ] ;
NSAlert * alert = [ [ NSAlert alloc ] init ] ;
[ alert addButtonWithTitle : NSLocalizedString ( @ "OK" , "Download not a torrent -> button" ) ] ;
[ alert setMessageText : NSLocalizedString ( @ "Torrent download failed" , "Download not a torrent -> title" ) ] ;
[ alert setInformativeText : message ] ;
[ alert runModal ] ;
2007-09-16 01:02:06 +00:00
}
else
[ download setDestination : [ NSTemporaryDirectory ( ) stringByAppendingPathComponent : [ suggestedName lastPathComponent ] ]
2012-09-09 12:58:53 +00:00
allowOverwrite : NO ] ;
2007-09-16 01:02:06 +00:00
}
- ( void ) download : ( NSURLDownload * ) download didCreateDestination : ( NSString * ) path
{
2017-07-17 17:34:52 +00:00
NSMutableDictionary * dict = fPendingTorrentDownloads [ [ [ download request ] URL ] ] ;
2017-07-08 14:38:47 +00:00
dict [ @ "Path" ] = path ;
2007-09-16 01:02:06 +00:00
}
- ( void ) download : ( NSURLDownload * ) download didFailWithError : ( NSError * ) error
{
2020-09-10 05:42:53 +00:00
NSString * message = [ NSString stringWithFormat : NSLocalizedString ( @ "The torrent could not be downloaded from %@: %@." ,
"Torrent download failed -> message" ) ,
[ [ [ [ download request ] URL ] absoluteString ] stringByReplacingPercentEscapesUsingEncoding : NSUTF8StringEncoding ] ,
[ error localizedDescription ] ] ;
NSAlert * alert = [ [ NSAlert alloc ] init ] ;
[ alert addButtonWithTitle : NSLocalizedString ( @ "OK" , "Torrent download failed -> button" ) ] ;
[ alert setMessageText : NSLocalizedString ( @ "Torrent download failed" , "Torrent download error -> title" ) ] ;
[ alert setInformativeText : message ] ;
[ alert runModal ] ;
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
[ fPendingTorrentDownloads removeObjectForKey : [ [ download request ] URL ] ] ;
2008-06-26 03:50:21 +00:00
if ( [ fPendingTorrentDownloads count ] = = 0 )
2012-03-13 02:52:11 +00:00
{
2008-06-26 03:50:21 +00:00
fPendingTorrentDownloads = nil ;
2012-03-13 02:52:11 +00:00
}
2007-09-16 01:02:06 +00:00
}
- ( void ) downloadDidFinish : ( NSURLDownload * ) download
{
2017-07-08 14:38:47 +00:00
NSString * path = fPendingTorrentDownloads [ [ [ download request ] URL ] ] [ @ "Path" ] ;
2017-01-24 17:53:16 +00:00
2017-07-08 08:23:05 +00:00
[ self openFiles : @ [ path ] addType : ADD_URL forcePath : nil ] ;
2017-01-24 17:53:16 +00:00
2008-06-27 01:34:49 +00:00
// delete the torrent file after opening
2008-12-26 05:57:51 +00:00
[ [ NSFileManager defaultManager ] removeItemAtPath : path error : NULL ] ;
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
[ fPendingTorrentDownloads removeObjectForKey : [ [ download request ] URL ] ] ;
2008-06-26 03:50:21 +00:00
if ( [ fPendingTorrentDownloads count ] = = 0 )
2012-03-13 02:52:11 +00:00
{
2008-06-26 03:50:21 +00:00
fPendingTorrentDownloads = nil ;
2012-03-13 02:52:11 +00:00
}
2007-09-16 01:02:06 +00:00
}
- ( void ) application : ( NSApplication * ) app openFiles : ( NSArray * ) filenames
{
2008-05-27 00:52:18 +00:00
[ self openFiles : filenames addType : ADD_MANUAL forcePath : nil ] ;
2007-09-16 01:02:06 +00:00
}
2008-01-05 02:48:10 +00:00
- ( void ) openFiles : ( NSArray * ) filenames addType : ( addType ) type forcePath : ( NSString * ) path
2007-09-16 01:02:06 +00:00
{
2009-07-20 00:40:01 +00:00
BOOL deleteTorrentFile , canToggleDelete = NO ;
2008-01-05 02:48:10 +00:00
switch ( type )
{
case ADD_CREATED :
2009-07-20 00:40:01 +00:00
deleteTorrentFile = NO ;
2008-01-05 02:48:10 +00:00
break ;
case ADD_URL :
2009-07-20 00:40:01 +00:00
deleteTorrentFile = YES ;
2008-01-05 02:48:10 +00:00
break ;
default :
2009-07-20 00:40:01 +00:00
deleteTorrentFile = [ fDefaults boolForKey : @ "DeleteOriginalTorrent" ] ;
canToggleDelete = YES ;
2008-01-05 02:48:10 +00:00
}
2017-01-24 17:53:16 +00:00
2008-12-26 07:06:02 +00:00
for ( NSString * torrentPath in filenames )
2007-09-16 01:02:06 +00:00
{
2008-01-08 05:31:20 +00:00
// ensure torrent doesn ' t already exist
2007-12-22 03:31:22 +00:00
tr_ctor * ctor = tr_ctorNew ( fLib ) ;
2020-04-25 14:35:15 +00:00
tr_ctorSetMetainfoFromFile ( ctor , [ torrentPath UTF8String ] ) ;
2017-01-24 17:53:16 +00:00
2009-10-29 02:45:58 +00:00
tr_info info ;
const tr_parse _result result = tr_torrentParse ( ctor , & info ) ;
tr_ctorFree ( ctor ) ;
2017-01-24 17:53:16 +00:00
2009-08-05 02:13:45 +00:00
if ( result ! = TR_PARSE _OK )
2007-09-16 01:02:06 +00:00
{
2009-08-05 01:59:16 +00:00
if ( result = = TR_PARSE _DUPLICATE )
2017-07-08 08:06:32 +00:00
[ self duplicateOpenAlert : @ ( info . name ) ] ;
2009-08-05 01:59:16 +00:00
else if ( result = = TR_PARSE _ERR )
2008-06-18 16:25:30 +00:00
{
if ( type ! = ADD_AUTO )
[ self invalidOpenAlert : [ torrentPath lastPathComponent ] ] ;
}
2009-10-17 17:15:37 +00:00
else
NSAssert2 ( NO , @ "Unknown error code (%d) when attempting to open \" % @ \ "" , result , torrentPath ) ;
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
tr_metainfoFree ( & info ) ;
continue ;
}
2017-01-24 17:53:16 +00:00
2008-01-08 05:31:20 +00:00
// determine download location
NSString * location ;
2008-12-13 22:49:46 +00:00
BOOL lockDestination = NO ; // don ' t override the location with a group location if it has a hardcoded path
2008-01-08 05:31:20 +00:00
if ( path )
2008-12-13 22:49:46 +00:00
{
2008-01-08 05:31:20 +00:00
location = [ path stringByExpandingTildeInPath ] ;
2008-12-13 22:49:46 +00:00
lockDestination = YES ;
}
2008-01-08 05:31:20 +00:00
else if ( [ fDefaults boolForKey : @ "DownloadLocationConstant" ] )
location = [ [ fDefaults stringForKey : @ "DownloadFolder" ] stringByExpandingTildeInPath ] ;
else if ( type ! = ADD_URL )
location = [ torrentPath stringByDeletingLastPathComponent ] ;
else
location = nil ;
2017-01-24 17:53:16 +00:00
2008-01-14 04:22:24 +00:00
// determine to show the options window
2009-10-29 02:45:58 +00:00
const BOOL showWindow = type = = ADD_SHOW _OPTIONS || ( [ fDefaults boolForKey : @ "DownloadAsk" ]
2014-06-08 22:16:01 +00:00
&& ( info . isFolder || ! [ fDefaults boolForKey : @ "DownloadAskMulti" ] )
2012-09-09 12:58:53 +00:00
&& ( type ! = ADD_AUTO || ! [ fDefaults boolForKey : @ "DownloadAskManual" ] ) ) ;
2008-01-14 04:22:24 +00:00
tr_metainfoFree ( & info ) ;
2017-01-24 17:53:16 +00:00
2008-12-26 07:06:02 +00:00
Torrent * torrent ;
2008-01-04 06:31:41 +00:00
if ( ! ( torrent = [ [ Torrent alloc ] initWithPath : torrentPath location : location
2012-09-09 12:58:53 +00:00
deleteTorrentFile : showWindow ? NO : deleteTorrentFile lib : fLib ] ) )
2007-09-16 01:02:06 +00:00
continue ;
2017-01-24 17:53:16 +00:00
2009-10-21 13:01:14 +00:00
// change the location if the group calls for it ( this has to wait until after the torrent is created )
2008-12-13 22:49:46 +00:00
if ( ! lockDestination && [ [ GroupsController groups ] usesCustomDownloadLocationForIndex : [ torrent groupValue ] ] )
{
location = [ [ GroupsController groups ] customDownloadLocationForIndex : [ torrent groupValue ] ] ;
2012-10-30 00:22:10 +00:00
[ torrent changeDownloadFolderBeforeUsing : location determinationType : TorrentDeterminationAutomatic ] ;
2008-12-13 22:49:46 +00:00
}
2017-01-24 17:53:16 +00:00
2008-01-10 01:20:48 +00:00
// verify the data right away if it was newly created
if ( type = = ADD_CREATED )
[ torrent resetCache ] ;
2017-01-24 17:53:16 +00:00
2008-01-08 05:31:20 +00:00
// show the add window or add directly
if ( showWindow || ! location )
2008-01-04 06:31:41 +00:00
{
AddWindowController * addController = [ [ AddWindowController alloc ] initWithTorrent : torrent destination : location
2012-09-09 12:58:53 +00:00
lockDestination : lockDestination controller : self torrentFile : torrentPath
deleteTorrentCheckEnableInitially : deleteTorrentFile canToggleDelete : canToggleDelete ] ;
2008-01-04 06:31:41 +00:00
[ addController showWindow : self ] ;
2017-01-24 17:53:16 +00:00
2012-03-13 03:20:09 +00:00
if ( ! fAddWindows )
fAddWindows = [ [ NSMutableSet alloc ] init ] ;
[ fAddWindows addObject : addController ] ;
2008-01-04 06:31:41 +00:00
}
2008-01-04 04:45:31 +00:00
else
{
2011-08-02 12:43:26 +00:00
if ( [ fDefaults boolForKey : @ "AutoStartDownload" ] )
[ torrent startTransfer ] ;
2017-01-24 17:53:16 +00:00
2008-01-04 04:45:31 +00:00
[ torrent update ] ;
[ fTorrents addObject : torrent ] ;
2017-01-24 17:53:16 +00:00
2012-01-08 00:51:05 +00:00
if ( ! fAddingTransfers )
2012-01-08 04:11:07 +00:00
fAddingTransfers = [ [ NSMutableSet alloc ] init ] ;
2012-01-08 00:51:05 +00:00
[ fAddingTransfers addObject : torrent ] ;
2008-01-04 04:45:31 +00:00
}
2007-09-16 01:02:06 +00:00
}
2012-09-09 12:58:53 +00:00
2011-08-04 02:03:58 +00:00
[ self fullUpdateUI ] ;
2007-09-16 01:02:06 +00:00
}
2010-04-12 00:55:31 +00:00
- ( void ) askOpenConfirmed : ( AddWindowController * ) addController add : ( BOOL ) add
{
Torrent * torrent = [ addController torrent ] ;
2017-01-24 17:53:16 +00:00
2010-04-12 00:55:31 +00:00
if ( add )
{
2011-08-21 16:28:16 +00:00
[ torrent setQueuePosition : [ fTorrents count ] ] ;
2017-01-24 17:53:16 +00:00
2010-04-12 00:55:31 +00:00
[ torrent update ] ;
[ fTorrents addObject : torrent ] ;
2017-01-24 17:53:16 +00:00
2012-01-08 00:51:05 +00:00
if ( ! fAddingTransfers )
2012-01-08 04:11:07 +00:00
fAddingTransfers = [ [ NSMutableSet alloc ] init ] ;
2012-01-08 00:51:05 +00:00
[ fAddingTransfers addObject : torrent ] ;
2017-01-24 17:53:16 +00:00
2011-08-04 02:03:58 +00:00
[ self fullUpdateUI ] ;
2010-04-12 00:55:31 +00:00
}
else
{
2010-12-16 03:39:11 +00:00
[ torrent closeRemoveTorrent : NO ] ;
2010-04-12 00:55:31 +00:00
}
2017-01-24 17:53:16 +00:00
2012-03-13 03:20:09 +00:00
[ fAddWindows removeObject : addController ] ;
if ( [ fAddWindows count ] = = 0 )
{
fAddWindows = nil ;
}
2010-04-12 00:55:31 +00:00
}
2009-11-25 04:11:52 +00:00
- ( void ) openMagnet : ( NSString * ) address
{
2010-02-02 01:47:22 +00:00
tr_torrent * duplicateTorrent ;
if ( ( duplicateTorrent = tr_torrentFindFromMagnetLink ( fLib , [ address UTF8String ] ) ) )
{
const tr_info * info = tr_torrentInfo ( duplicateTorrent ) ;
2017-07-08 08:06:32 +00:00
NSString * name = ( info ! = NULL && info -> name ! = NULL ) ? @ ( info -> name ) : nil ;
2010-02-02 01:47:22 +00:00
[ self duplicateOpenMagnetAlert : address transferName : name ] ;
return ;
}
2017-01-24 17:53:16 +00:00
2010-04-24 16:50:18 +00:00
// determine download location
NSString * location = nil ;
if ( [ fDefaults boolForKey : @ "DownloadLocationConstant" ] )
location = [ [ fDefaults stringForKey : @ "DownloadFolder" ] stringByExpandingTildeInPath ] ;
2017-01-24 17:53:16 +00:00
2009-11-25 04:11:52 +00:00
Torrent * torrent ;
2010-04-24 16:50:18 +00:00
if ( ! ( torrent = [ [ Torrent alloc ] initWithMagnetAddress : address location : location lib : fLib ] ) )
2009-11-25 04:11:52 +00:00
{
2009-12-02 00:27:07 +00:00
[ self invalidOpenMagnetAlert : address ] ;
2009-11-25 04:11:52 +00:00
return ;
}
2017-01-24 17:53:16 +00:00
2009-11-28 17:44:47 +00:00
// change the location if the group calls for it ( this has to wait until after the torrent is created )
if ( [ [ GroupsController groups ] usesCustomDownloadLocationForIndex : [ torrent groupValue ] ] )
{
2010-04-12 00:55:31 +00:00
location = [ [ GroupsController groups ] customDownloadLocationForIndex : [ torrent groupValue ] ] ;
2012-10-30 00:22:10 +00:00
[ torrent changeDownloadFolderBeforeUsing : location determinationType : TorrentDeterminationAutomatic ] ;
2009-11-28 17:44:47 +00:00
}
2017-01-24 17:53:16 +00:00
2010-04-12 01:34:11 +00:00
if ( [ fDefaults boolForKey : @ "MagnetOpenAsk" ] || ! location )
2010-04-12 00:55:31 +00:00
{
AddMagnetWindowController * addController = [ [ AddMagnetWindowController alloc ] initWithTorrent : torrent destination : location
2012-09-09 12:58:53 +00:00
controller : self ] ;
2010-04-12 00:55:31 +00:00
[ addController showWindow : self ] ;
2017-01-24 17:53:16 +00:00
2012-03-13 03:20:09 +00:00
if ( ! fAddWindows )
fAddWindows = [ [ NSMutableSet alloc ] init ] ;
[ fAddWindows addObject : addController ] ;
2010-04-12 00:55:31 +00:00
}
else
{
2011-08-02 12:43:26 +00:00
if ( [ fDefaults boolForKey : @ "AutoStartDownload" ] )
[ torrent startTransfer ] ;
2017-01-24 17:53:16 +00:00
2010-04-12 00:55:31 +00:00
[ torrent update ] ;
[ fTorrents addObject : torrent ] ;
2017-01-24 17:53:16 +00:00
2012-01-08 00:51:05 +00:00
if ( ! fAddingTransfers )
2012-01-08 04:11:07 +00:00
fAddingTransfers = [ [ NSMutableSet alloc ] init ] ;
2012-01-08 00:51:05 +00:00
[ fAddingTransfers addObject : torrent ] ;
2010-04-12 00:55:31 +00:00
}
2012-09-09 12:58:53 +00:00
2011-08-04 02:03:58 +00:00
[ self fullUpdateUI ] ;
2009-11-25 04:11:52 +00:00
}
2010-04-12 00:55:31 +00:00
- ( void ) askOpenMagnetConfirmed : ( AddMagnetWindowController * ) addController add : ( BOOL ) add
2008-01-04 04:45:31 +00:00
{
2008-01-05 21:31:05 +00:00
Torrent * torrent = [ addController torrent ] ;
2017-01-24 17:53:16 +00:00
2008-01-05 21:31:05 +00:00
if ( add )
{
2011-08-21 16:28:16 +00:00
[ torrent setQueuePosition : [ fTorrents count ] ] ;
2017-01-24 17:53:16 +00:00
2008-01-05 21:31:05 +00:00
[ torrent update ] ;
[ fTorrents addObject : torrent ] ;
2017-01-24 17:53:16 +00:00
2012-01-08 00:51:05 +00:00
if ( ! fAddingTransfers )
2012-01-08 04:11:07 +00:00
fAddingTransfers = [ [ NSMutableSet alloc ] init ] ;
2012-01-08 00:51:05 +00:00
[ fAddingTransfers addObject : torrent ] ;
2017-01-24 17:53:16 +00:00
2011-08-04 02:03:58 +00:00
[ self fullUpdateUI ] ;
2008-01-05 21:31:05 +00:00
}
else
{
2010-12-16 03:39:11 +00:00
[ torrent closeRemoveTorrent : NO ] ;
2008-01-05 21:31:05 +00:00
}
2017-01-24 17:53:16 +00:00
2012-03-13 03:20:09 +00:00
[ fAddWindows removeObject : addController ] ;
if ( [ fAddWindows count ] = = 0 )
{
fAddWindows = nil ;
}
2008-01-04 04:45:31 +00:00
}
2007-09-16 01:02:06 +00:00
- ( void ) openCreatedFile : ( NSNotification * ) notification
{
NSDictionary * dict = [ notification userInfo ] ;
2017-07-08 14:38:47 +00:00
[ self openFiles : @ [ dict [ @ "File" ] ] addType : ADD_CREATED forcePath : dict [ @ "Path" ] ] ;
2007-09-16 01:02:06 +00:00
}
- ( void ) openFilesWithDict : ( NSDictionary * ) dictionary
{
2017-07-08 14:38:47 +00:00
[ self openFiles : dictionary [ @ "Filenames" ] addType : [ dictionary [ @ "AddType" ] intValue ] forcePath : nil ] ;
2007-09-16 01:02:06 +00:00
}
// called on by applescript
- ( void ) open : ( NSArray * ) files
{
2017-07-17 17:34:52 +00:00
NSDictionary * dict = [ [ NSDictionary alloc ] initWithObjects : @ [ files , @ ( ADD_MANUAL ) ] forKeys : @ [ @ "Filenames" , @ "AddType" ] ] ;
2008-01-10 16:46:15 +00:00
[ self performSelectorOnMainThread : @ selector ( openFilesWithDict : ) withObject : dict waitUntilDone : NO ] ;
2007-09-16 01:02:06 +00:00
}
- ( void ) openShowSheet : ( id ) sender
{
NSOpenPanel * panel = [ NSOpenPanel openPanel ] ;
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
[ panel setAllowsMultipleSelection : YES ] ;
[ panel setCanChooseFiles : YES ] ;
[ panel setCanChooseDirectories : NO ] ;
2017-01-24 17:53:16 +00:00
2017-07-08 08:23:05 +00:00
[ panel setAllowedFileTypes : @ [ @ "org.bittorrent.torrent" , @ "torrent" ] ] ;
2017-01-24 17:53:16 +00:00
2011-12-11 22:31:01 +00:00
[ panel beginSheetModalForWindow : fWindow completionHandler : ^ ( NSInteger result ) {
if ( result = = NSFileHandlingPanelOKButton )
{
NSMutableArray * filenames = [ NSMutableArray arrayWithCapacity : [ [ panel URLs ] count ] ] ;
for ( NSURL * url in [ panel URLs ] )
[ filenames addObject : [ url path ] ] ;
2017-01-24 17:53:16 +00:00
2017-07-17 17:34:52 +00:00
NSDictionary * dictionary = [ [ NSDictionary alloc ] initWithObjects : @ [
filenames ,
sender = = fOpenIgnoreDownloadFolder ? @ ( ADD_SHOW _OPTIONS ) : @ ( ADD_MANUAL ) ]
forKeys : @ [ @ "Filenames" , @ "AddType" ] ] ;
2011-12-11 22:31:01 +00:00
[ self performSelectorOnMainThread : @ selector ( openFilesWithDict : ) withObject : dictionary waitUntilDone : NO ] ;
}
} ] ;
2007-09-16 01:02:06 +00:00
}
2008-06-18 16:25:30 +00:00
- ( void ) invalidOpenAlert : ( NSString * ) filename
{
if ( ! [ fDefaults boolForKey : @ "WarningInvalidOpen" ] )
return ;
2017-01-24 17:53:16 +00:00
2008-06-18 16:25:30 +00:00
NSAlert * alert = [ [ NSAlert alloc ] init ] ;
[ alert setMessageText : [ NSString stringWithFormat : NSLocalizedString ( @ "\" % @ \ " is not a valid torrent file." ,
2012-09-09 12:58:53 +00:00
"Open invalid alert -> title" ) , filename ] ] ;
2008-06-18 16:25:30 +00:00
[ alert setInformativeText :
2012-09-09 12:58:53 +00:00
NSLocalizedString ( @ "The torrent file cannot be opened because it contains invalid data." ,
"Open invalid alert -> message" ) ] ;
2008-06-18 16:25:30 +00:00
[ alert setAlertStyle : NSWarningAlertStyle ] ;
[ alert addButtonWithTitle : NSLocalizedString ( @ "OK" , "Open invalid alert -> button" ) ] ;
2017-01-24 17:53:16 +00:00
2008-12-26 05:57:51 +00:00
[ alert runModal ] ;
if ( [ [ alert suppressionButton ] state ] = = NSOnState )
2008-06-18 16:25:30 +00:00
[ fDefaults setBool : NO forKey : @ "WarningInvalidOpen" ] ;
}
2009-12-02 00:27:07 +00:00
- ( void ) invalidOpenMagnetAlert : ( NSString * ) address
{
if ( ! [ fDefaults boolForKey : @ "WarningInvalidOpen" ] )
return ;
2017-01-24 17:53:16 +00:00
2009-12-02 00:27:07 +00:00
NSAlert * alert = [ [ NSAlert alloc ] init ] ;
2010-02-02 01:47:22 +00:00
[ alert setMessageText : NSLocalizedString ( @ "Adding magnetized transfer failed." , "Magnet link failed -> title" ) ] ;
2009-12-02 00:27:07 +00:00
[ alert setInformativeText : [ NSString stringWithFormat : NSLocalizedString ( @ "There was an error when adding the magnet link \" % @ \ "."
2012-09-09 12:58:53 +00:00
" The transfer will not occur." , "Magnet link failed -> message" ) , address ] ] ;
2009-12-02 00:27:07 +00:00
[ alert setAlertStyle : NSWarningAlertStyle ] ;
[ alert addButtonWithTitle : NSLocalizedString ( @ "OK" , "Magnet link failed -> button" ) ] ;
2017-01-24 17:53:16 +00:00
2009-12-02 00:27:07 +00:00
[ alert runModal ] ;
if ( [ [ alert suppressionButton ] state ] = = NSOnState )
[ fDefaults setBool : NO forKey : @ "WarningInvalidOpen" ] ;
}
2007-09-16 01:02:06 +00:00
- ( void ) duplicateOpenAlert : ( NSString * ) name
{
if ( ! [ fDefaults boolForKey : @ "WarningDuplicate" ] )
return ;
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
NSAlert * alert = [ [ NSAlert alloc ] init ] ;
2008-01-07 20:27:25 +00:00
[ alert setMessageText : [ NSString stringWithFormat : NSLocalizedString ( @ "A transfer of \" % @ \ " already exists." ,
2012-09-09 12:58:53 +00:00
"Open duplicate alert -> title" ) , name ] ] ;
2007-09-16 01:02:06 +00:00
[ alert setInformativeText :
2012-09-09 12:58:53 +00:00
NSLocalizedString ( @ "The transfer cannot be added because it is a duplicate of an already existing transfer." ,
"Open duplicate alert -> message" ) ] ;
2007-09-16 01:02:06 +00:00
[ alert setAlertStyle : NSWarningAlertStyle ] ;
2007-10-29 19:45:34 +00:00
[ alert addButtonWithTitle : NSLocalizedString ( @ "OK" , "Open duplicate alert -> button" ) ] ;
2008-12-26 05:57:51 +00:00
[ alert setShowsSuppressionButton : YES ] ;
2017-01-24 17:53:16 +00:00
2008-12-26 05:57:51 +00:00
[ alert runModal ] ;
if ( [ [ alert suppressionButton ] state ] )
2007-09-16 01:02:06 +00:00
[ fDefaults setBool : NO forKey : @ "WarningDuplicate" ] ;
}
2010-02-02 01:47:22 +00:00
- ( void ) duplicateOpenMagnetAlert : ( NSString * ) address transferName : ( NSString * ) name
{
if ( ! [ fDefaults boolForKey : @ "WarningDuplicate" ] )
return ;
2017-01-24 17:53:16 +00:00
2010-02-02 01:47:22 +00:00
NSAlert * alert = [ [ NSAlert alloc ] init ] ;
if ( name )
[ alert setMessageText : [ NSString stringWithFormat : NSLocalizedString ( @ "A transfer of \" % @ \ " already exists." ,
2012-09-09 12:58:53 +00:00
"Open duplicate magnet alert -> title" ) , name ] ] ;
2010-02-02 01:47:22 +00:00
else
[ alert setMessageText : NSLocalizedString ( @ "Magnet link is a duplicate of an existing transfer." ,
2012-09-09 12:58:53 +00:00
"Open duplicate magnet alert -> title" ) ] ;
2010-02-02 01:47:22 +00:00
[ alert setInformativeText : [ NSString stringWithFormat :
2012-09-09 12:58:53 +00:00
NSLocalizedString ( @ "The magnet link \" % @ \ " cannot be added because it is a duplicate of an already existing transfer." ,
"Open duplicate magnet alert -> message" ) , address ] ] ;
2010-02-02 01:47:22 +00:00
[ alert setAlertStyle : NSWarningAlertStyle ] ;
[ alert addButtonWithTitle : NSLocalizedString ( @ "OK" , "Open duplicate magnet alert -> button" ) ] ;
[ alert setShowsSuppressionButton : YES ] ;
2017-01-24 17:53:16 +00:00
2010-02-02 01:47:22 +00:00
[ alert runModal ] ;
if ( [ [ alert suppressionButton ] state ] )
[ fDefaults setBool : NO forKey : @ "WarningDuplicate" ] ;
}
2009-11-26 16:38:21 +00:00
- ( void ) openURL : ( NSString * ) urlString
2007-09-16 01:02:06 +00:00
{
2009-11-26 16:38:21 +00:00
if ( [ urlString rangeOfString : @ "magnet:" options : ( NSAnchoredSearch | NSCaseInsensitiveSearch ) ] . location ! = NSNotFound )
[ self openMagnet : urlString ] ;
else
{
if ( [ urlString rangeOfString : @ "://" ] . location = = NSNotFound )
{
if ( [ urlString rangeOfString : @ "." ] . location = = NSNotFound )
{
NSInteger beforeCom ;
if ( ( beforeCom = [ urlString rangeOfString : @ "/" ] . location ) ! = NSNotFound )
urlString = [ NSString stringWithFormat : @ "http://www.%@.com/%@" ,
2012-09-09 12:58:53 +00:00
[ urlString substringToIndex : beforeCom ] ,
[ urlString substringFromIndex : beforeCom + 1 ] ] ;
2009-11-26 16:38:21 +00:00
else
urlString = [ NSString stringWithFormat : @ "http://www.%@.com/" , urlString ] ;
}
else
urlString = [ @ "http://" stringByAppendingString : urlString ] ;
}
2019-04-18 19:28:45 +00:00
NSURL * url = [ NSURL URLWithString : urlString ] ;
if ( url = = nil )
{
2019-04-19 08:41:02 +00:00
NSLog ( @ "Detected non-URL string \" % @ \ ". Ignoring." , urlString ) ;
2019-04-18 19:28:45 +00:00
return ;
}
2017-01-24 17:53:16 +00:00
2019-04-18 19:28:45 +00:00
NSURLRequest * request = [ NSURLRequest requestWithURL : url
2012-09-09 12:58:53 +00:00
cachePolicy : NSURLRequestReloadIgnoringLocalAndRemoteCacheData timeoutInterval : 60 ] ;
2017-01-24 17:53:16 +00:00
2017-07-08 14:38:47 +00:00
if ( fPendingTorrentDownloads [ [ request URL ] ] )
2012-03-13 03:39:56 +00:00
{
NSLog ( @ "Already downloading %@" , [ request URL ] ) ;
return ;
}
2017-01-24 17:53:16 +00:00
2012-03-13 03:39:56 +00:00
NSURLDownload * download = [ [ NSURLDownload alloc ] initWithRequest : request delegate : self ] ;
2017-01-24 17:53:16 +00:00
2012-03-13 03:39:56 +00:00
if ( ! fPendingTorrentDownloads )
fPendingTorrentDownloads = [ [ NSMutableDictionary alloc ] init ] ;
2017-07-17 17:34:52 +00:00
NSMutableDictionary * dict = [ NSMutableDictionary dictionaryWithObject : download forKey : @ "Download" ] ;
2017-07-08 14:38:47 +00:00
fPendingTorrentDownloads [ [ request URL ] ] = dict ;
2009-11-26 16:38:21 +00:00
}
2007-09-16 01:02:06 +00:00
}
- ( void ) openURLShowSheet : ( id ) sender
{
2012-03-13 03:39:56 +00:00
if ( ! fUrlSheetController )
{
fUrlSheetController = [ [ URLSheetWindowController alloc ] initWithController : self ] ;
2017-01-24 17:53:16 +00:00
2021-01-03 04:29:08 +00:00
[ fWindow beginSheet : fUrlSheetController . window completionHandler : ^ ( NSModalResponse returnCode ) {
if ( returnCode = = 1 )
{
NSString * urlString = [ fUrlSheetController urlString ] ;
dispatch_async ( dispatch_get _main _queue ( ) , ^ {
[ self openURL : urlString ] ;
} ) ;
}
fUrlSheetController = nil ;
} ] ;
2012-03-13 03:39:56 +00:00
}
2007-09-16 01:02:06 +00:00
}
- ( void ) createFile : ( id ) sender
{
[ CreatorWindowController createTorrentFile : fLib ] ;
}
- ( void ) resumeSelectedTorrents : ( id ) sender
{
2008-01-22 23:48:14 +00:00
[ self resumeTorrents : [ fTableView selectedTorrents ] ] ;
2007-09-16 01:02:06 +00:00
}
- ( void ) resumeAllTorrents : ( id ) sender
{
2010-04-04 02:05:40 +00:00
NSMutableArray * torrents = [ NSMutableArray arrayWithCapacity : [ fTorrents count ] ] ;
2017-01-24 17:53:16 +00:00
2010-04-04 02:05:40 +00:00
for ( Torrent * torrent in fTorrents )
if ( ! [ torrent isFinishedSeeding ] )
[ torrents addObject : torrent ] ;
2017-01-24 17:53:16 +00:00
2010-04-04 01:35:51 +00:00
[ self resumeTorrents : torrents ] ;
2007-09-16 01:02:06 +00:00
}
- ( void ) resumeTorrents : ( NSArray * ) torrents
{
2008-12-26 07:06:02 +00:00
for ( Torrent * torrent in torrents )
2011-08-02 12:43:26 +00:00
[ torrent startTransfer ] ;
2017-01-24 17:53:16 +00:00
2011-08-04 02:03:58 +00:00
[ self fullUpdateUI ] ;
2007-09-16 01:02:06 +00:00
}
- ( void ) resumeSelectedTorrentsNoWait : ( id ) sender
{
2008-01-22 23:48:14 +00:00
[ self resumeTorrentsNoWait : [ fTableView selectedTorrents ] ] ;
2007-09-16 01:02:06 +00:00
}
- ( void ) resumeWaitingTorrents : ( id ) sender
{
NSMutableArray * torrents = [ NSMutableArray arrayWithCapacity : [ fTorrents count ] ] ;
2017-01-24 17:53:16 +00:00
2008-12-26 07:06:02 +00:00
for ( Torrent * torrent in fTorrents )
2011-08-02 12:43:26 +00:00
if ( [ torrent waitingToStart ] )
2007-09-16 01:02:06 +00:00
[ torrents addObject : torrent ] ;
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
[ self resumeTorrentsNoWait : torrents ] ;
}
- ( void ) resumeTorrentsNoWait : ( NSArray * ) torrents
{
// iterate through instead of all at once to ensure no conflicts
2008-12-26 07:06:02 +00:00
for ( Torrent * torrent in torrents )
2011-08-02 12:43:26 +00:00
[ torrent startTransferNoQueue ] ;
2017-01-24 17:53:16 +00:00
2011-08-04 02:03:58 +00:00
[ self fullUpdateUI ] ;
2007-09-16 01:02:06 +00:00
}
- ( void ) stopSelectedTorrents : ( id ) sender
{
2008-01-22 23:48:14 +00:00
[ self stopTorrents : [ fTableView selectedTorrents ] ] ;
2007-09-16 01:02:06 +00:00
}
- ( void ) stopAllTorrents : ( id ) sender
{
[ self stopTorrents : fTorrents ] ;
}
- ( void ) stopTorrents : ( NSArray * ) torrents
{
// don ' t want any of these starting then stopping
2011-08-06 15:31:19 +00:00
for ( Torrent * torrent in torrents )
2012-09-09 12:58:53 +00:00
if ( [ torrent waitingToStart ] )
[ torrent stopTransfer ] ;
2017-01-24 17:53:16 +00:00
2011-08-04 00:36:02 +00:00
for ( Torrent * torrent in torrents )
[ torrent stopTransfer ] ;
2017-01-24 17:53:16 +00:00
2011-08-04 02:03:58 +00:00
[ self fullUpdateUI ] ;
2007-09-16 01:02:06 +00:00
}
2009-07-19 19:14:01 +00:00
- ( void ) removeTorrents : ( NSArray * ) torrents deleteData : ( BOOL ) deleteData
2007-09-16 01:02:06 +00:00
{
if ( [ fDefaults boolForKey : @ "CheckRemove" ] )
{
2011-03-17 01:06:31 +00:00
NSUInteger active = 0 , downloading = 0 ;
2008-12-26 07:06:02 +00:00
for ( Torrent * torrent in torrents )
2007-09-16 01:02:06 +00:00
if ( [ torrent isActive ] )
{
2011-03-17 01:06:31 +00:00
+ + active ;
2007-09-16 01:02:06 +00:00
if ( ! [ torrent isSeeding ] )
2011-03-17 01:06:31 +00:00
+ + downloading ;
2007-09-16 01:02:06 +00:00
}
2012-09-09 12:58:53 +00:00
2007-09-16 01:02:06 +00:00
if ( [ fDefaults boolForKey : @ "CheckRemoveDownloading" ] ? downloading > 0 : active > 0 )
{
NSString * title , * message ;
2017-01-24 17:53:16 +00:00
2016-09-11 10:22:49 +00:00
const NSUInteger selected = [ torrents count ] ;
2007-09-16 01:02:06 +00:00
if ( selected = = 1 )
{
2017-07-08 09:16:01 +00:00
NSString * torrentName = [ ( Torrent * ) torrents [ 0 ] name ] ;
2017-01-24 17:53:16 +00:00
2009-07-19 19:14:01 +00:00
if ( deleteData )
2008-04-23 03:33:04 +00:00
title = [ NSString stringWithFormat :
2012-09-09 12:58:53 +00:00
NSLocalizedString ( @ "Are you sure you want to remove \" % @ \ " from the transfer list"
" and trash the data file?" , "Removal confirm panel -> title" ) , torrentName ] ;
2007-09-16 01:02:06 +00:00
else
2008-04-23 03:33:04 +00:00
title = [ NSString stringWithFormat :
2012-09-09 12:58:53 +00:00
NSLocalizedString ( @ "Are you sure you want to remove \" % @ \ " from the transfer list?" ,
"Removal confirm panel -> title" ) , torrentName ] ;
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
message = NSLocalizedString ( @ "This transfer is active."
2012-09-09 12:58:53 +00:00
" Once removed, continuing the transfer will require the torrent file or magnet link." ,
"Removal confirm panel -> message" ) ;
2007-09-16 01:02:06 +00:00
}
else
{
2009-07-19 19:14:01 +00:00
if ( deleteData )
2008-04-23 03:33:04 +00:00
title = [ NSString stringWithFormat :
2012-09-09 12:58:53 +00:00
NSLocalizedString ( @ "Are you sure you want to remove %@ transfers from the transfer list"
" and trash the data files?" , "Removal confirm panel -> title" ) , [ NSString formattedUInteger : selected ] ] ;
2007-09-16 01:02:06 +00:00
else
2008-04-23 03:33:04 +00:00
title = [ NSString stringWithFormat :
2012-09-09 12:58:53 +00:00
NSLocalizedString ( @ "Are you sure you want to remove %@ transfers from the transfer list?" ,
"Removal confirm panel -> title" ) , [ NSString formattedUInteger : selected ] ] ;
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
if ( selected = = active )
2011-03-17 01:06:31 +00:00
message = [ NSString stringWithFormat : NSLocalizedString ( @ "There are %@ active transfers." ,
2012-09-09 12:58:53 +00:00
"Removal confirm panel -> message part 1" ) , [ NSString formattedUInteger : active ] ] ;
2007-09-16 01:02:06 +00:00
else
2011-03-17 01:06:31 +00:00
message = [ NSString stringWithFormat : NSLocalizedString ( @ "There are %@ transfers (%@ active)." ,
2012-09-09 12:58:53 +00:00
"Removal confirm panel -> message part 1" ) , [ NSString formattedUInteger : selected ] , [ NSString formattedUInteger : active ] ] ;
2008-04-23 03:33:04 +00:00
message = [ message stringByAppendingFormat : @ " %@" ,
2012-09-09 12:58:53 +00:00
NSLocalizedString ( @ "Once removed, continuing the transfers will require the torrent files or magnet links." ,
"Removal confirm panel -> message part 2" ) ] ;
2007-09-16 01:02:06 +00:00
}
2017-01-24 17:53:16 +00:00
2018-12-26 15:15:33 +00:00
NSAlert * alert = [ [ NSAlert alloc ] init ] ;
alert . alertStyle = NSAlertStyleInformational ;
alert . messageText = title ;
alert . informativeText = message ;
[ alert addButtonWithTitle : NSLocalizedString ( @ "Remove" , "Removal confirm panel -> button" ) ] ;
[ alert addButtonWithTitle : NSLocalizedString ( @ "Cancel" , "Removal confirm panel -> button" ) ] ;
2019-02-16 07:50:37 +00:00
2018-12-26 15:15:33 +00:00
[ alert beginSheetModalForWindow : fWindow
completionHandler : ^ ( NSModalResponse returnCode ) {
if ( returnCode = = NSAlertFirstButtonReturn ) {
[ self confirmRemoveTorrents : torrents deleteData : deleteData ] ;
}
} ] ;
2007-09-16 01:02:06 +00:00
return ;
}
}
2017-01-24 17:53:16 +00:00
2009-07-19 19:14:01 +00:00
[ self confirmRemoveTorrents : torrents deleteData : deleteData ] ;
2007-09-16 01:02:06 +00:00
}
2009-07-19 19:14:01 +00:00
- ( void ) confirmRemoveTorrents : ( NSArray * ) torrents deleteData : ( BOOL ) deleteData
2007-09-16 01:02:06 +00:00
{
2012-01-07 15:46:42 +00:00
// miscellaneous
2011-08-06 15:31:19 +00:00
for ( Torrent * torrent in torrents )
2012-01-07 15:46:42 +00:00
{
// don ' t want any of these starting then stopping
2011-08-06 15:31:19 +00:00
if ( [ torrent waitingToStart ] )
[ torrent stopTransfer ] ;
2017-01-24 17:53:16 +00:00
2012-01-07 15:46:42 +00:00
// let ' s expand all groups that have removed items - they either don ' t exist anymore , are already expanded , or are collapsed ( rpc )
[ fTableView removeCollapsedGroup : [ torrent groupValue ] ] ;
2017-01-24 17:53:16 +00:00
2012-01-07 15:46:42 +00:00
// we can ' t assume the window is active - RPC removal , for example
[ fBadger removeTorrent : torrent ] ;
}
2017-01-24 17:53:16 +00:00
2012-11-24 03:34:45 +00:00
// #5106 - don ' t try to remove torrents that have already been removed ( fix for a bug , but better safe than crash anyway )
NSIndexSet * indexesToRemove = [ torrents indexesOfObjectsWithOptions : NSEnumerationConcurrent passingTest : ^ BOOL ( Torrent * torrent , NSUInteger idx , BOOL * stop ) {
return [ fTorrents indexOfObjectIdenticalTo : torrent ] ! = NSNotFound ;
} ] ;
if ( [ torrents count ] ! = [ indexesToRemove count ] )
{
NSLog ( @ "trying to remove %ld transfers, but %ld have already been removed" , [ torrents count ] , [ torrents count ] - [ indexesToRemove count ] ) ;
torrents = [ torrents objectsAtIndexes : indexesToRemove ] ;
2017-01-24 17:53:16 +00:00
2012-11-24 03:34:45 +00:00
if ( [ indexesToRemove count ] = = 0 )
{
[ self fullUpdateUI ] ;
return ;
}
}
2017-01-24 17:53:16 +00:00
2007-12-21 20:39:43 +00:00
[ fTorrents removeObjectsInArray : torrents ] ;
2017-01-24 17:53:16 +00:00
2012-01-07 15:46:42 +00:00
// set up helpers to remove from the table
__block BOOL beganUpdate = NO ;
2017-01-24 17:53:16 +00:00
2012-01-07 15:46:42 +00:00
void ( ^ doTableRemoval ) ( NSMutableArray * , id ) = ^ ( NSMutableArray * displayedTorrents , id parent ) {
NSIndexSet * indexes = [ displayedTorrents indexesOfObjectsWithOptions : NSEnumerationConcurrent passingTest : ^ ( id obj , NSUInteger idx , BOOL * stop ) {
return [ torrents containsObject : obj ] ;
} ] ;
2017-01-24 17:53:16 +00:00
2012-01-07 15:46:42 +00:00
if ( [ indexes count ] > 0 )
{
2016-01-06 11:05:37 +00:00
if ( ! beganUpdate )
2012-01-07 15:46:42 +00:00
{
2016-01-06 11:05:37 +00:00
[ NSAnimationContext beginGrouping ] ; // this has to be before we set the completion handler ( #4874 )
2017-01-24 17:53:16 +00:00
2016-01-06 11:05:37 +00:00
// we can ' t closeRemoveTorrent : until it ' s no longer in the GUI at all
[ [ NSAnimationContext currentContext ] setCompletionHandler : ^ {
for ( Torrent * torrent in torrents )
[ torrent closeRemoveTorrent : deleteData ] ;
} ] ;
2017-01-24 17:53:16 +00:00
2016-01-06 11:05:37 +00:00
[ fTableView beginUpdates ] ;
beganUpdate = YES ;
2012-01-07 15:46:42 +00:00
}
2017-01-24 17:53:16 +00:00
2016-01-06 11:05:37 +00:00
[ fTableView removeItemsAtIndexes : indexes inParent : parent withAnimation : NSTableViewAnimationSlideLeft ] ;
2012-01-07 15:46:42 +00:00
[ displayedTorrents removeObjectsAtIndexes : indexes ] ;
}
} ;
2017-01-24 17:53:16 +00:00
2012-01-07 15:46:42 +00:00
// if not removed from the displayed torrents here , fullUpdateUI might cause a crash
2009-12-14 23:35:55 +00:00
if ( [ fDisplayedTorrents count ] > 0 )
{
2017-07-08 09:16:01 +00:00
if ( [ fDisplayedTorrents [ 0 ] isKindOfClass : [ TorrentGroup class ] ] )
2009-12-14 23:35:55 +00:00
{
for ( TorrentGroup * group in fDisplayedTorrents )
2012-01-07 15:46:42 +00:00
doTableRemoval ( [ group torrents ] , group ) ;
2009-12-14 23:35:55 +00:00
}
else
2012-01-07 15:46:42 +00:00
doTableRemoval ( fDisplayedTorrents , nil ) ;
2017-01-24 17:53:16 +00:00
2012-01-07 15:46:42 +00:00
if ( beganUpdate )
{
[ fTableView endUpdates ] ;
[ NSAnimationContext endGrouping ] ;
}
2009-12-14 23:35:55 +00:00
}
2017-01-24 17:53:16 +00:00
2012-01-07 15:46:42 +00:00
if ( ! beganUpdate )
2007-09-16 01:02:06 +00:00
{
2012-01-07 15:46:42 +00:00
// do here if we ' re not doing it at the end of the animation
for ( Torrent * torrent in torrents )
[ torrent closeRemoveTorrent : deleteData ] ;
2007-09-16 01:02:06 +00:00
}
2017-01-24 17:53:16 +00:00
2011-08-04 02:03:58 +00:00
[ self fullUpdateUI ] ;
2007-09-16 01:02:06 +00:00
}
- ( void ) removeNoDelete : ( id ) sender
{
2009-07-19 19:14:01 +00:00
[ self removeTorrents : [ fTableView selectedTorrents ] deleteData : NO ] ;
2007-09-16 01:02:06 +00:00
}
- ( void ) removeDeleteData : ( id ) sender
{
2009-07-19 19:14:01 +00:00
[ self removeTorrents : [ fTableView selectedTorrents ] deleteData : YES ] ;
2007-09-16 01:02:06 +00:00
}
2011-02-13 02:02:13 +00:00
- ( void ) clearCompleted : ( id ) sender
{
2012-11-01 03:21:35 +00:00
NSMutableArray * torrents = [ NSMutableArray array ] ;
2017-01-24 17:53:16 +00:00
2011-02-13 02:02:13 +00:00
for ( Torrent * torrent in fTorrents )
if ( [ torrent isFinishedSeeding ] )
[ torrents addObject : torrent ] ;
2017-01-24 17:53:16 +00:00
2011-03-17 01:06:31 +00:00
if ( [ fDefaults boolForKey : @ "WarningRemoveCompleted" ] )
{
NSString * message , * info ;
if ( [ torrents count ] = = 1 )
{
2017-07-08 09:16:01 +00:00
NSString * torrentName = [ ( Torrent * ) torrents [ 0 ] name ] ;
2011-03-17 01:06:31 +00:00
message = [ NSString stringWithFormat : NSLocalizedString ( @ "Are you sure you want to remove \" % @ \ " from the transfer list?" ,
2012-09-09 12:58:53 +00:00
"Remove completed confirm panel -> title" ) , torrentName ] ;
2017-01-24 17:53:16 +00:00
2011-03-17 01:06:31 +00:00
info = NSLocalizedString ( @ "Once removed, continuing the transfer will require the torrent file or magnet link." ,
"Remove completed confirm panel -> message" ) ;
}
else
{
message = [ NSString stringWithFormat : NSLocalizedString ( @ "Are you sure you want to remove %@ completed transfers from the transfer list?" ,
2012-09-09 12:58:53 +00:00
"Remove completed confirm panel -> title" ) , [ NSString formattedUInteger : [ torrents count ] ] ] ;
2017-01-24 17:53:16 +00:00
2011-03-17 01:06:31 +00:00
info = NSLocalizedString ( @ "Once removed, continuing the transfers will require the torrent files or magnet links." ,
"Remove completed confirm panel -> message" ) ;
}
2017-01-24 17:53:16 +00:00
2017-07-29 16:14:22 +00:00
NSAlert * alert = [ [ NSAlert alloc ] init ] ;
2011-03-17 01:06:31 +00:00
[ alert setMessageText : message ] ;
[ alert setInformativeText : info ] ;
[ alert setAlertStyle : NSWarningAlertStyle ] ;
[ alert addButtonWithTitle : NSLocalizedString ( @ "Remove" , "Remove completed confirm panel -> button" ) ] ;
[ alert addButtonWithTitle : NSLocalizedString ( @ "Cancel" , "Remove completed confirm panel -> button" ) ] ;
[ alert setShowsSuppressionButton : YES ] ;
2017-01-24 17:53:16 +00:00
2011-03-17 01:06:31 +00:00
const NSInteger returnCode = [ alert runModal ] ;
if ( [ [ alert suppressionButton ] state ] )
[ fDefaults setBool : NO forKey : @ "WarningRemoveCompleted" ] ;
2017-01-24 17:53:16 +00:00
2011-03-17 01:06:31 +00:00
if ( returnCode ! = NSAlertFirstButtonReturn )
return ;
}
2017-01-24 17:53:16 +00:00
2011-02-13 02:02:13 +00:00
[ self confirmRemoveTorrents : torrents deleteData : NO ] ;
}
2008-03-22 17:05:48 +00:00
- ( void ) moveDataFilesSelected : ( id ) sender
{
[ self moveDataFiles : [ fTableView selectedTorrents ] ] ;
}
- ( void ) moveDataFiles : ( NSArray * ) torrents
2007-09-16 01:02:06 +00:00
{
NSOpenPanel * panel = [ NSOpenPanel openPanel ] ;
[ panel setPrompt : NSLocalizedString ( @ "Select" , "Move torrent -> prompt" ) ] ;
[ panel setAllowsMultipleSelection : NO ] ;
[ panel setCanChooseFiles : NO ] ;
[ panel setCanChooseDirectories : YES ] ;
[ panel setCanCreateDirectories : YES ] ;
2017-01-24 17:53:16 +00:00
2008-11-02 13:52:45 +00:00
NSInteger count = [ torrents count ] ;
2007-09-16 01:02:06 +00:00
if ( count = = 1 )
[ panel setMessage : [ NSString stringWithFormat : NSLocalizedString ( @ "Select the new folder for \" % @ \ "." ,
2017-07-08 09:16:01 +00:00
"Move torrent -> select destination folder" ) , [ ( Torrent * ) torrents [ 0 ] name ] ] ] ;
2007-09-16 01:02:06 +00:00
else
[ panel setMessage : [ NSString stringWithFormat : NSLocalizedString ( @ "Select the new folder for %d data files." ,
2012-09-09 12:58:53 +00:00
"Move torrent -> select destination folder" ) , count ] ] ;
2017-01-24 17:53:16 +00:00
2011-12-11 22:31:01 +00:00
[ panel beginSheetModalForWindow : fWindow completionHandler : ^ ( NSInteger result ) {
if ( result = = NSFileHandlingPanelOKButton )
{
for ( Torrent * torrent in torrents )
2017-07-08 09:16:01 +00:00
[ torrent moveTorrentDataFileTo : [ [ panel URLs ] [ 0 ] path ] ] ;
2011-12-11 22:31:01 +00:00
}
} ] ;
2007-09-16 01:02:06 +00:00
}
- ( void ) copyTorrentFiles : ( id ) sender
{
2008-02-06 23:45:44 +00:00
[ self copyTorrentFileForTorrents : [ [ NSMutableArray alloc ] initWithArray : [ fTableView selectedTorrents ] ] ] ;
2007-09-16 01:02:06 +00:00
}
- ( void ) copyTorrentFileForTorrents : ( NSMutableArray * ) torrents
{
2010-01-17 17:57:54 +00:00
if ( [ torrents count ] = = 0 )
2007-09-16 01:02:06 +00:00
{
return ;
}
2017-01-24 17:53:16 +00:00
2017-07-08 09:16:01 +00:00
Torrent * torrent = torrents [ 0 ] ;
2017-01-24 17:53:16 +00:00
2010-01-17 17:57:54 +00:00
if ( ! [ torrent isMagnet ] && [ [ NSFileManager defaultManager ] fileExistsAtPath : [ torrent torrentLocation ] ] )
2007-09-16 01:02:06 +00:00
{
NSSavePanel * panel = [ NSSavePanel savePanel ] ;
2017-07-08 08:23:05 +00:00
[ panel setAllowedFileTypes : @ [ @ "org.bittorrent.torrent" , @ "torrent" ] ] ;
2010-10-19 00:01:31 +00:00
[ panel setExtensionHidden : NO ] ;
2017-01-24 17:53:16 +00:00
2011-12-11 22:31:01 +00:00
[ panel setNameFieldStringValue : [ torrent name ] ] ;
2017-01-24 17:53:16 +00:00
2011-12-11 22:31:01 +00:00
[ panel beginSheetModalForWindow : fWindow completionHandler : ^ ( NSInteger result ) {
// copy torrent to new location with name of data file
if ( result = = NSFileHandlingPanelOKButton )
[ torrent copyTorrentFileTo : [ [ panel URL ] path ] ] ;
2017-01-24 17:53:16 +00:00
2011-12-11 22:31:01 +00:00
[ torrents removeObjectAtIndex : 0 ] ;
[ self performSelectorOnMainThread : @ selector ( copyTorrentFileForTorrents : ) withObject : torrents waitUntilDone : NO ] ;
} ] ;
2007-09-16 01:02:06 +00:00
}
2010-01-17 17:57:54 +00:00
else
{
if ( ! [ torrent isMagnet ] )
{
NSAlert * alert = [ [ NSAlert alloc ] init ] ;
[ alert addButtonWithTitle : NSLocalizedString ( @ "OK" , "Torrent file copy alert -> button" ) ] ;
[ alert setMessageText : [ NSString stringWithFormat : NSLocalizedString ( @ "Copy of \" % @ \ " Cannot Be Created" ,
2012-09-09 12:58:53 +00:00
"Torrent file copy alert -> title" ) , [ torrent name ] ] ] ;
2017-01-24 17:53:16 +00:00
[ alert setInformativeText : [ NSString stringWithFormat :
2012-09-09 12:58:53 +00:00
NSLocalizedString ( @ "The torrent file (%@) cannot be found." , "Torrent file copy alert -> message" ) ,
2010-01-17 17:57:54 +00:00
[ torrent torrentLocation ] ] ] ;
[ alert setAlertStyle : NSWarningAlertStyle ] ;
2017-01-24 17:53:16 +00:00
2010-01-17 17:57:54 +00:00
[ alert runModal ] ;
}
2017-01-24 17:53:16 +00:00
2010-01-17 17:57:54 +00:00
[ torrents removeObjectAtIndex : 0 ] ;
[ self copyTorrentFileForTorrents : torrents ] ;
}
2007-09-16 01:02:06 +00:00
}
2009-12-04 13:35:15 +00:00
- ( void ) copyMagnetLinks : ( id ) sender
{
NSArray * torrents = [ fTableView selectedTorrents ] ;
2017-01-24 17:53:16 +00:00
2009-12-04 13:35:15 +00:00
if ( [ torrents count ] <= 0 )
return ;
2017-01-24 17:53:16 +00:00
2009-12-04 13:35:15 +00:00
NSMutableArray * links = [ NSMutableArray arrayWithCapacity : [ torrents count ] ] ;
for ( Torrent * torrent in torrents )
[ links addObject : [ torrent magnetLink ] ] ;
2017-01-24 17:53:16 +00:00
2009-12-04 13:35:15 +00:00
NSString * text = [ links componentsJoinedByString : @ "\n" ] ;
2017-01-24 17:53:16 +00:00
2009-12-04 13:35:15 +00:00
NSPasteboard * pb = [ NSPasteboard generalPasteboard ] ;
2011-10-06 00:30:40 +00:00
[ pb clearContents ] ;
2017-07-08 08:23:05 +00:00
[ pb writeObjects : @ [ text ] ] ;
2009-12-04 13:35:15 +00:00
}
2007-09-16 01:02:06 +00:00
- ( void ) revealFile : ( id ) sender
{
2009-08-30 17:50:05 +00:00
NSArray * selected = [ fTableView selectedTorrents ] ;
2011-10-06 00:30:40 +00:00
NSMutableArray * paths = [ NSMutableArray arrayWithCapacity : [ selected count ] ] ;
for ( Torrent * torrent in selected )
2009-08-30 17:50:05 +00:00
{
2011-10-06 00:30:40 +00:00
NSString * location = [ torrent dataLocation ] ;
if ( location )
[ paths addObject : [ NSURL fileURLWithPath : location ] ] ;
2009-08-30 17:50:05 +00:00
}
2017-01-24 17:53:16 +00:00
2011-10-06 00:30:40 +00:00
if ( [ paths count ] > 0 )
[ [ NSWorkspace sharedWorkspace ] activateFileViewerSelectingURLs : paths ] ;
2007-09-16 01:02:06 +00:00
}
2013-01-22 00:09:48 +00:00
- ( IBAction ) renameSelected : ( id ) sender
{
NSArray * selected = [ fTableView selectedTorrents ] ;
NSAssert ( [ selected count ] = = 1 , @ "1 transfer needs to be selected to rename, but %ld are selected" , [ selected count ] ) ;
2017-07-08 09:16:01 +00:00
Torrent * torrent = selected [ 0 ] ;
2017-01-24 17:53:16 +00:00
2013-01-22 00:09:48 +00:00
[ FileRenameSheetController presentSheetForTorrent : torrent modalForWindow : fWindow completionHandler : ^ ( BOOL didRename ) {
2013-01-22 00:44:58 +00:00
if ( didRename )
{
dispatch_async ( dispatch_get _main _queue ( ) , ^ {
[ self fullUpdateUI ] ;
2017-01-24 17:53:16 +00:00
2013-01-22 03:54:51 +00:00
[ [ NSNotificationCenter defaultCenter ] postNotificationName : @ "ResetInspector" object : self userInfo : @ { @ "Torrent" : torrent } ] ;
2013-01-22 00:44:58 +00:00
} ) ;
}
2013-01-22 00:09:48 +00:00
} ] ;
}
2007-09-16 01:02:06 +00:00
- ( void ) announceSelectedTorrents : ( id ) sender
{
2008-12-26 07:06:02 +00:00
for ( Torrent * torrent in [ fTableView selectedTorrents ] )
2007-09-16 01:02:06 +00:00
{
if ( [ torrent canManualAnnounce ] )
[ torrent manualAnnounce ] ;
}
}
2008-02-27 19:04:38 +00:00
- ( void ) verifySelectedTorrents : ( id ) sender
2007-09-16 01:02:06 +00:00
{
2008-02-27 19:04:38 +00:00
[ self verifyTorrents : [ fTableView selectedTorrents ] ] ;
}
- ( void ) verifyTorrents : ( NSArray * ) torrents
{
2008-12-26 07:06:02 +00:00
for ( Torrent * torrent in torrents )
2007-09-16 01:02:06 +00:00
[ torrent resetCache ] ;
2017-01-24 17:53:16 +00:00
2011-02-20 03:58:50 +00:00
[ self applyFilter ] ;
2007-09-16 01:02:06 +00:00
}
2014-01-09 16:23:54 +00:00
- ( NSArray * ) selectedTorrents
{
return [ fTableView selectedTorrents ] ;
}
2007-09-16 01:02:06 +00:00
- ( void ) showPreferenceWindow : ( id ) sender
{
NSWindow * window = [ fPrefsController window ] ;
if ( ! [ window isVisible ] )
[ window center ] ;
2012-09-09 12:58:53 +00:00
2007-09-16 01:02:06 +00:00
[ window makeKeyAndOrderFront : nil ] ;
}
- ( void ) showAboutWindow : ( id ) sender
{
[ [ AboutWindowController aboutController ] showWindow : nil ] ;
}
- ( void ) showInfo : ( id ) sender
{
if ( [ [ fInfoController window ] isVisible ] )
[ fInfoController close ] ;
else
2009-10-12 00:19:04 +00:00
{
2007-09-16 01:02:06 +00:00
[ fInfoController updateInfoStats ] ;
[ [ fInfoController window ] orderFront : nil ] ;
2017-01-24 17:53:16 +00:00
2011-10-06 00:30:40 +00:00
if ( [ fInfoController canQuickLook ] && [ QLPreviewPanel sharedPreviewPanelExists ] && [ [ QLPreviewPanel sharedPreviewPanel ] isVisible ] )
[ [ QLPreviewPanel sharedPreviewPanel ] reloadData ] ;
2007-09-16 01:02:06 +00:00
}
2017-01-24 17:53:16 +00:00
2010-11-13 19:10:31 +00:00
[ [ fWindow toolbar ] validateVisibleItems ] ;
2007-09-16 01:02:06 +00:00
}
2008-06-26 03:35:20 +00:00
- ( void ) resetInfo
{
[ fInfoController setInfoForTorrents : [ fTableView selectedTorrents ] ] ;
2017-01-24 17:53:16 +00:00
2011-10-06 00:30:40 +00:00
if ( [ QLPreviewPanel sharedPreviewPanelExists ] && [ [ QLPreviewPanel sharedPreviewPanel ] isVisible ] )
[ [ QLPreviewPanel sharedPreviewPanel ] reloadData ] ;
2008-06-26 03:35:20 +00:00
}
2007-09-16 01:02:06 +00:00
- ( void ) setInfoTab : ( id ) sender
{
if ( sender = = fNextInfoTabItem )
[ fInfoController setNextTab ] ;
else
[ fInfoController setPreviousTab ] ;
}
2012-05-27 22:31:58 +00:00
- ( MessageWindowController * ) messageWindowController
2007-09-16 01:02:06 +00:00
{
2010-02-09 13:15:52 +00:00
if ( ! fMessageController )
fMessageController = [ [ MessageWindowController alloc ] init ] ;
2017-01-24 17:53:16 +00:00
2012-05-27 22:31:58 +00:00
return fMessageController ;
}
- ( void ) showMessageWindow : ( id ) sender
{
[ [ self messageWindowController ] showWindow : nil ] ;
2007-09-16 01:02:06 +00:00
}
2007-11-19 18:13:41 +00:00
- ( void ) showStatsWindow : ( id ) sender
{
2012-05-27 22:31:58 +00:00
[ [ StatsWindowController statsWindow ] showWindow : nil ] ;
2007-11-19 18:13:41 +00:00
}
2007-09-16 01:02:06 +00:00
- ( void ) updateUI
{
2011-01-23 18:23:52 +00:00
CGFloat dlRate = 0.0 , ulRate = 0.0 ;
2012-05-23 00:54:58 +00:00
BOOL anyCompleted = NO ;
2011-01-23 18:23:52 +00:00
for ( Torrent * torrent in fTorrents )
{
2011-08-21 16:00:28 +00:00
[ torrent update ] ;
2017-01-24 17:53:16 +00:00
2011-08-21 16:00:28 +00:00
// pull the upload and download speeds - most consistent by using current stats
2011-01-23 18:23:52 +00:00
dlRate + = [ torrent downloadRate ] ;
ulRate + = [ torrent uploadRate ] ;
2017-01-24 17:53:16 +00:00
2012-05-20 00:19:55 +00:00
anyCompleted | = [ torrent isFinishedSeeding ] ;
2011-01-23 18:23:52 +00:00
}
2017-01-24 17:53:16 +00:00
2007-09-26 04:12:57 +00:00
if ( ! [ NSApp isHidden ] )
2007-09-16 01:02:06 +00:00
{
2007-09-26 04:12:57 +00:00
if ( [ fWindow isVisible ] )
{
2012-01-04 05:16:07 +00:00
[ self sortTorrents : NO ] ;
2017-01-24 17:53:16 +00:00
2011-02-20 00:22:55 +00:00
[ fStatusBar updateWithDownload : dlRate upload : ulRate ] ;
2017-01-24 17:53:16 +00:00
2012-05-20 00:19:55 +00:00
[ fClearCompletedButton setHidden : ! anyCompleted ] ;
2007-09-26 04:12:57 +00:00
}
2012-09-09 12:58:53 +00:00
2007-09-26 04:12:57 +00:00
// update non - constant parts of info window
if ( [ [ fInfoController window ] isVisible ] )
[ fInfoController updateInfoStats ] ;
}
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
// badge dock
2011-01-23 18:23:52 +00:00
[ fBadger updateBadgeWithDownload : dlRate upload : ulRate ] ;
2007-09-16 01:02:06 +00:00
}
2011-08-04 02:03:58 +00:00
# warning can this be removed or refined ?
- ( void ) fullUpdateUI
{
[ self updateUI ] ;
[ self applyFilter ] ;
[ [ fWindow toolbar ] validateVisibleItems ] ;
[ self updateTorrentHistory ] ;
}
2008-03-21 20:28:04 +00:00
- ( void ) setBottomCountText : ( BOOL ) filtering
2008-02-06 23:45:44 +00:00
{
NSString * totalTorrentsString ;
2010-11-14 18:33:57 +00:00
NSUInteger totalCount = [ fTorrents count ] ;
2008-02-06 23:45:44 +00:00
if ( totalCount ! = 1 )
2010-11-14 18:33:57 +00:00
totalTorrentsString = [ NSString stringWithFormat : NSLocalizedString ( @ "%@ transfers" , "Status bar transfer count" ) ,
2012-09-09 12:58:53 +00:00
[ NSString formattedUInteger : totalCount ] ] ;
2008-02-06 23:45:44 +00:00
else
totalTorrentsString = NSLocalizedString ( @ "1 transfer" , "Status bar transfer count" ) ;
2017-01-24 17:53:16 +00:00
2008-02-06 23:45:44 +00:00
if ( filtering )
{
2010-11-14 18:33:57 +00:00
NSUInteger count = [ fTableView numberOfRows ] ; // have to factor in collapsed rows
2017-07-08 09:16:01 +00:00
if ( count > 0 && ! [ fDisplayedTorrents [ 0 ] isKindOfClass : [ Torrent class ] ] )
2008-06-19 16:37:05 +00:00
count - = [ fDisplayedTorrents count ] ;
2017-01-24 17:53:16 +00:00
2010-11-14 18:33:57 +00:00
totalTorrentsString = [ NSString stringWithFormat : NSLocalizedString ( @ "%@ of %@" , "Status bar transfer count" ) ,
2012-09-09 12:58:53 +00:00
[ NSString formattedUInteger : count ] , totalTorrentsString ] ;
2008-02-06 23:45:44 +00:00
}
2017-01-24 17:53:16 +00:00
2008-02-06 23:45:44 +00:00
[ fTotalTorrentsField setStringValue : totalTorrentsString ] ;
}
2012-07-25 12:49:11 +00:00
- ( BOOL ) userNotificationCenter : ( NSUserNotificationCenter * ) center shouldPresentNotification : ( NSUserNotification * ) notification
{
return YES ;
}
- ( void ) userNotificationCenter : ( NSUserNotificationCenter * ) center didActivateNotification : ( NSUserNotification * ) notification
{
if ( ! [ notification userInfo ] )
return ;
2017-01-24 17:53:16 +00:00
2012-07-25 12:49:11 +00:00
if ( [ notification activationType ] = = NSUserNotificationActivationTypeActionButtonClicked ) // reveal
{
2017-07-08 14:38:47 +00:00
Torrent * torrent = [ self torrentForHash : [ notification userInfo ] [ @ "Hash" ] ] ;
2012-07-25 12:49:11 +00:00
NSString * location = [ torrent dataLocation ] ;
if ( ! location )
2017-07-08 14:38:47 +00:00
location = [ notification userInfo ] [ @ "Location" ] ;
2012-07-25 12:49:11 +00:00
if ( location )
[ [ NSWorkspace sharedWorkspace ] activateFileViewerSelectingURLs : @ [ [ NSURL fileURLWithPath : location ] ] ] ;
}
else if ( [ notification activationType ] = = NSUserNotificationActivationTypeContentsClicked )
{
2017-07-08 14:38:47 +00:00
Torrent * torrent = [ self torrentForHash : [ notification userInfo ] [ @ "Hash" ] ] ;
2012-07-25 12:49:11 +00:00
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 ] ;
}
}
2017-01-24 17:53:16 +00:00
2012-07-25 12:49:11 +00:00
if ( row = = -1 )
{
// not found - must be filtering
NSAssert ( [ fDefaults boolForKey : @ "FilterBar" ] , @ "expected the filter to be enabled" ) ;
[ fFilterBar reset : YES ] ;
2017-01-24 17:53:16 +00:00
2012-07-25 12:49:11 +00:00
row = [ fTableView rowForItem : torrent ] ;
2017-01-24 17:53:16 +00:00
2012-07-25 12:49:11 +00:00
// 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 ] ;
}
}
}
}
2017-01-24 17:53:16 +00:00
2012-07-25 12:49:11 +00:00
NSAssert1 ( row ! = -1 , @ "expected a row to be found for torrent %@" , torrent ) ;
2016-03-03 17:57:08 +00:00
[ self showMainWindow : nil ] ;
[ fTableView selectAndScrollToRow : row ] ;
2012-07-25 12:49:11 +00:00
}
}
}
- ( Torrent * ) torrentForHash : ( NSString * ) hash
{
NSParameterAssert ( hash ! = nil ) ;
2017-01-24 17:53:16 +00:00
2012-07-25 12:49:11 +00:00
__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 ;
}
2007-09-16 01:02:06 +00:00
- ( void ) torrentFinishedDownloading : ( NSNotification * ) notification
{
Torrent * torrent = [ notification object ] ;
2017-01-24 17:53:16 +00:00
2017-07-08 14:38:47 +00:00
if ( [ [ notification userInfo ] [ @ "WasRunning" ] boolValue ] )
2007-09-16 01:02:06 +00:00
{
2008-04-14 00:05:16 +00:00
if ( ! fSoundPlaying && [ fDefaults boolForKey : @ "PlayDownloadSound" ] )
2007-09-16 01:02:06 +00:00
{
2008-04-14 00:05:16 +00:00
NSSound * sound ;
if ( ( sound = [ NSSound soundNamed : [ fDefaults stringForKey : @ "DownloadSound" ] ] ) )
{
[ sound setDelegate : self ] ;
fSoundPlaying = YES ;
[ sound play ] ;
}
2007-09-16 01:02:06 +00:00
}
2017-01-24 17:53:16 +00:00
2012-07-25 12:49:11 +00:00
NSString * location = [ torrent dataLocation ] ;
2017-01-24 17:53:16 +00:00
2012-09-09 12:26:18 +00:00
NSString * notificationTitle = NSLocalizedString ( @ "Download Complete" , "notification title" ) ;
2017-02-05 19:29:20 +00:00
NSUserNotification * notification = [ [ NSUserNotification alloc ] init ] ;
[ notification setTitle : notificationTitle ] ;
[ notification setInformativeText : [ torrent name ] ] ;
2017-01-24 17:53:16 +00:00
2017-02-05 19:29:20 +00:00
[ notification setHasActionButton : YES ] ;
[ notification setActionButtonTitle : NSLocalizedString ( @ "Show" , "notification button" ) ] ;
2017-01-24 17:53:16 +00:00
2017-02-05 19:29:20 +00:00
NSMutableDictionary * userInfo = [ NSMutableDictionary dictionaryWithObject : [ torrent hashString ] forKey : @ "Hash" ] ;
if ( location )
2017-07-08 14:38:47 +00:00
userInfo [ @ "Location" ] = location ;
2017-02-05 19:29:20 +00:00
[ notification setUserInfo : userInfo ] ;
2017-01-24 17:53:16 +00:00
2017-02-05 19:29:20 +00:00
[ [ NSUserNotificationCenter defaultUserNotificationCenter ] deliverNotification : notification ] ;
2017-01-24 17:53:16 +00:00
2008-04-14 00:05:16 +00:00
if ( ! [ fWindow isMainWindow ] )
2011-06-19 03:52:54 +00:00
[ fBadger addCompletedTorrent : torrent ] ;
2017-01-24 17:53:16 +00:00
2009-05-09 17:11:21 +00:00
// bounce download stack
[ [ NSDistributedNotificationCenter defaultCenter ] postNotificationName : @ "com.apple.DownloadFileFinished"
2012-09-09 12:58:53 +00:00
object : [ torrent dataLocation ] ] ;
2007-09-16 01:02:06 +00:00
}
2017-01-24 17:53:16 +00:00
2011-08-04 02:03:58 +00:00
[ self fullUpdateUI ] ;
2007-09-16 01:02:06 +00:00
}
- ( void ) torrentRestartedDownloading : ( NSNotification * ) notification
{
2011-08-04 02:03:58 +00:00
[ self fullUpdateUI ] ;
2007-09-16 01:02:06 +00:00
}
2010-08-14 19:44:43 +00:00
- ( void ) torrentFinishedSeeding : ( NSNotification * ) notification
2008-04-14 00:05:16 +00:00
{
2012-11-01 03:21:35 +00:00
Torrent * torrent = [ notification object ] ;
2017-01-24 17:53:16 +00:00
2008-04-14 00:05:16 +00:00
if ( ! fSoundPlaying && [ fDefaults boolForKey : @ "PlaySeedingSound" ] )
{
NSSound * sound ;
if ( ( sound = [ NSSound soundNamed : [ fDefaults stringForKey : @ "SeedingSound" ] ] ) )
{
[ sound setDelegate : self ] ;
fSoundPlaying = YES ;
[ sound play ] ;
}
}
2017-01-24 17:53:16 +00:00
2012-07-25 12:49:11 +00:00
NSString * location = [ torrent dataLocation ] ;
2017-01-24 17:53:16 +00:00
2012-09-09 12:26:18 +00:00
NSString * notificationTitle = NSLocalizedString ( @ "Seeding Complete" , "notification title" ) ;
2017-02-05 19:29:20 +00:00
NSUserNotification * userNotification = [ [ NSUserNotification alloc ] init ] ;
[ userNotification setTitle : notificationTitle ] ;
[ userNotification setInformativeText : [ torrent name ] ] ;
2017-01-24 17:53:16 +00:00
2017-02-05 19:29:20 +00:00
[ userNotification setHasActionButton : YES ] ;
[ userNotification setActionButtonTitle : NSLocalizedString ( @ "Show" , "notification button" ) ] ;
2017-01-24 17:53:16 +00:00
2017-02-05 19:29:20 +00:00
NSMutableDictionary * userInfo = [ NSMutableDictionary dictionaryWithObject : [ torrent hashString ] forKey : @ "Hash" ] ;
if ( location )
2017-07-08 14:38:47 +00:00
userInfo [ @ "Location" ] = location ;
2017-02-05 19:29:20 +00:00
[ userNotification setUserInfo : userInfo ] ;
2017-01-24 17:53:16 +00:00
2017-02-05 19:29:20 +00:00
[ [ NSUserNotificationCenter defaultUserNotificationCenter ] deliverNotification : userNotification ] ;
2017-01-24 17:53:16 +00:00
2012-10-15 02:12:44 +00:00
// removing from the list calls fullUpdateUI
2012-07-07 01:47:12 +00:00
if ( [ torrent removeWhenFinishSeeding ] )
2012-11-01 03:21:35 +00:00
[ self confirmRemoveTorrents : @ [ torrent ] deleteData : NO ] ;
2012-07-07 01:47:12 +00:00
else
{
2012-10-17 00:25:28 +00:00
if ( ! [ fWindow isMainWindow ] )
[ fBadger addCompletedTorrent : torrent ] ;
2017-01-24 17:53:16 +00:00
2012-07-07 01:47:12 +00:00
[ self fullUpdateUI ] ;
2017-01-24 17:53:16 +00:00
2012-07-07 01:47:12 +00:00
if ( [ [ fTableView selectedTorrents ] containsObject : torrent ] )
{
[ fInfoController updateInfoStats ] ;
[ fInfoController updateOptions ] ;
}
}
2008-04-14 00:05:16 +00:00
}
2007-09-16 01:02:06 +00:00
- ( void ) updateTorrentHistory
{
NSMutableArray * history = [ NSMutableArray arrayWithCapacity : [ fTorrents count ] ] ;
2017-01-24 17:53:16 +00:00
2008-12-26 07:06:02 +00:00
for ( Torrent * torrent in fTorrents )
2007-09-16 01:02:06 +00:00
[ history addObject : [ torrent history ] ] ;
2017-01-24 17:53:16 +00:00
2012-03-18 14:33:50 +00:00
NSString * historyFile = [ fConfigDirectory stringByAppendingPathComponent : TRANSFER_PLIST ] ;
[ history writeToFile : historyFile atomically : YES ] ;
2007-09-16 01:02:06 +00:00
}
2008-01-23 17:22:41 +00:00
- ( void ) setSort : ( id ) sender
{
NSString * sortType ;
2011-10-18 02:30:22 +00:00
switch ( [ ( NSMenuItem * ) sender tag ] )
2008-01-23 17:22:41 +00:00
{
case SORT_ORDER _TAG :
sortType = SORT_ORDER ;
[ fDefaults setBool : NO forKey : @ "SortReverse" ] ;
break ;
case SORT_DATE _TAG :
sortType = SORT_DATE ;
break ;
case SORT_NAME _TAG :
sortType = SORT_NAME ;
break ;
case SORT_PROGRESS _TAG :
sortType = SORT_PROGRESS ;
break ;
case SORT_STATE _TAG :
sortType = SORT_STATE ;
break ;
case SORT_TRACKER _TAG :
sortType = SORT_TRACKER ;
break ;
case SORT_ACTIVITY _TAG :
sortType = SORT_ACTIVITY ;
break ;
2011-07-04 19:47:15 +00:00
case SORT_SIZE _TAG :
sortType = SORT_SIZE ;
break ;
2008-01-23 17:22:41 +00:00
default :
2012-08-13 00:52:04 +00:00
NSAssert1 ( NO , @ "Unknown sort tag received: %ld" , [ ( NSMenuItem * ) sender tag ] ) ;
2008-01-23 17:22:41 +00:00
return ;
}
2017-01-24 17:53:16 +00:00
2008-01-23 17:22:41 +00:00
[ fDefaults setObject : sortType forKey : @ "Sort" ] ;
2017-01-24 17:53:16 +00:00
2012-01-04 05:16:07 +00:00
[ self sortTorrents : YES ] ;
2008-01-23 17:22:41 +00:00
}
- ( void ) setSortByGroup : ( id ) sender
{
2008-02-07 02:15:24 +00:00
BOOL sortByGroup = ! [ fDefaults boolForKey : @ "SortByGroup" ] ;
[ fDefaults setBool : sortByGroup forKey : @ "SortByGroup" ] ;
2017-01-24 17:53:16 +00:00
2011-02-20 03:58:50 +00:00
[ self applyFilter ] ;
2008-01-23 17:22:41 +00:00
}
- ( void ) setSortReverse : ( id ) sender
{
2011-10-18 02:30:22 +00:00
const BOOL setReverse = [ ( NSMenuItem * ) sender tag ] = = SORT_DESC _TAG ;
2011-01-06 04:09:04 +00:00
if ( setReverse ! = [ fDefaults boolForKey : @ "SortReverse" ] )
{
[ fDefaults setBool : setReverse forKey : @ "SortReverse" ] ;
2012-01-04 05:16:07 +00:00
[ self sortTorrents : NO ] ;
2011-01-06 04:09:04 +00:00
}
2008-01-23 20:46:37 +00:00
}
2012-01-04 05:16:07 +00:00
- ( void ) sortTorrents : ( BOOL ) includeQueueOrder
2008-01-23 20:46:37 +00:00
{
2012-01-07 15:46:42 +00:00
// actually sort
2012-01-14 19:53:08 +00:00
[ self sortTorrentsCallUpdates : YES includeQueueOrder : includeQueueOrder ] ;
2012-01-04 23:40:23 +00:00
[ fTableView setNeedsDisplay : YES ] ;
2008-01-23 17:22:41 +00:00
}
2012-01-14 19:53:08 +00:00
- ( void ) sortTorrentsCallUpdates : ( BOOL ) callUpdates includeQueueOrder : ( BOOL ) includeQueueOrder
2007-09-16 01:02:06 +00:00
{
2012-01-04 05:16:07 +00:00
const BOOL asc = ! [ fDefaults boolForKey : @ "SortReverse" ] ;
2017-01-24 17:53:16 +00:00
2012-01-04 05:16:07 +00:00
NSArray * descriptors ;
NSSortDescriptor * nameDescriptor = [ NSSortDescriptor sortDescriptorWithKey : @ "name" ascending : asc selector : @ selector ( localizedStandardCompare : ) ] ;
2017-01-24 17:53:16 +00:00
2012-01-18 01:40:34 +00:00
NSString * sortType = [ fDefaults stringForKey : @ "Sort" ] ;
2012-01-04 05:16:07 +00:00
if ( [ sortType isEqualToString : SORT_STATE ] )
2008-01-31 00:40:37 +00:00
{
2012-01-04 05:16:07 +00:00
NSSortDescriptor * stateDescriptor = [ NSSortDescriptor sortDescriptorWithKey : @ "stateSortKey" ascending : ! asc ] ,
2012-09-09 12:58:53 +00:00
* progressDescriptor = [ NSSortDescriptor sortDescriptorWithKey : @ "progress" ascending : ! asc ] ,
* ratioDescriptor = [ NSSortDescriptor sortDescriptorWithKey : @ "ratio" ascending : ! asc ] ;
2017-01-24 17:53:16 +00:00
2017-07-08 08:23:05 +00:00
descriptors = @ [ stateDescriptor , progressDescriptor , ratioDescriptor , nameDescriptor ] ;
2012-01-04 05:16:07 +00:00
}
else if ( [ sortType isEqualToString : SORT_PROGRESS ] )
{
NSSortDescriptor * progressDescriptor = [ NSSortDescriptor sortDescriptorWithKey : @ "progress" ascending : asc ] ,
2012-09-09 12:58:53 +00:00
* ratioProgressDescriptor = [ NSSortDescriptor sortDescriptorWithKey : @ "progressStopRatio" ascending : asc ] ,
* ratioDescriptor = [ NSSortDescriptor sortDescriptorWithKey : @ "ratio" ascending : asc ] ;
2017-01-24 17:53:16 +00:00
2017-07-08 08:23:05 +00:00
descriptors = @ [ progressDescriptor , ratioProgressDescriptor , ratioDescriptor , nameDescriptor ] ;
2012-01-04 05:16:07 +00:00
}
else if ( [ sortType isEqualToString : SORT_TRACKER ] )
{
NSSortDescriptor * trackerDescriptor = [ NSSortDescriptor sortDescriptorWithKey : @ "trackerSortKey" ascending : asc selector : @ selector ( localizedCaseInsensitiveCompare : ) ] ;
2017-01-24 17:53:16 +00:00
2017-07-08 08:23:05 +00:00
descriptors = @ [ trackerDescriptor , nameDescriptor ] ;
2012-01-04 05:16:07 +00:00
}
else if ( [ sortType isEqualToString : SORT_ACTIVITY ] )
{
NSSortDescriptor * rateDescriptor = [ NSSortDescriptor sortDescriptorWithKey : @ "totalRate" ascending : ! asc ] ;
NSSortDescriptor * activityDescriptor = [ NSSortDescriptor sortDescriptorWithKey : @ "dateActivityOrAdd" ascending : ! asc ] ;
2017-01-24 17:53:16 +00:00
2017-07-08 08:23:05 +00:00
descriptors = @ [ rateDescriptor , activityDescriptor , nameDescriptor ] ;
2012-01-04 05:16:07 +00:00
}
else if ( [ sortType isEqualToString : SORT_DATE ] )
{
NSSortDescriptor * dateDescriptor = [ NSSortDescriptor sortDescriptorWithKey : @ "dateAdded" ascending : asc ] ;
2017-01-24 17:53:16 +00:00
2017-07-08 08:23:05 +00:00
descriptors = @ [ dateDescriptor , nameDescriptor ] ;
2012-01-04 05:16:07 +00:00
}
else if ( [ sortType isEqualToString : SORT_SIZE ] )
{
NSSortDescriptor * sizeDescriptor = [ NSSortDescriptor sortDescriptorWithKey : @ "size" ascending : asc ] ;
2017-01-24 17:53:16 +00:00
2017-07-08 08:23:05 +00:00
descriptors = @ [ sizeDescriptor , nameDescriptor ] ;
2012-01-04 05:16:07 +00:00
}
else if ( [ sortType isEqualToString : SORT_NAME ] )
{
2017-07-08 08:23:05 +00:00
descriptors = @ [ nameDescriptor ] ;
2012-01-04 05:16:07 +00:00
}
else
{
NSAssert1 ( [ sortType isEqualToString : SORT_ORDER ] , @ "Unknown sort type received: %@" , sortType ) ;
2017-01-24 17:53:16 +00:00
2012-01-18 01:40:34 +00:00
if ( ! includeQueueOrder )
return ;
2017-01-24 17:53:16 +00:00
2012-01-04 05:16:07 +00:00
NSSortDescriptor * orderDescriptor = [ NSSortDescriptor sortDescriptorWithKey : @ "queuePosition" ascending : asc ] ;
2017-01-24 17:53:16 +00:00
2017-07-08 08:23:05 +00:00
descriptors = @ [ orderDescriptor ] ;
2012-01-04 05:16:07 +00:00
}
2017-01-24 17:53:16 +00:00
2016-01-06 11:05:37 +00:00
BOOL beganTableUpdate = ! callUpdates ;
2017-01-24 17:53:16 +00:00
2012-01-04 05:16:07 +00:00
// actually sort
2012-01-18 01:40:34 +00:00
if ( [ fDefaults boolForKey : @ "SortByGroup" ] )
2012-01-04 05:16:07 +00:00
{
for ( TorrentGroup * group in fDisplayedTorrents )
2012-01-07 15:46:42 +00:00
[ self rearrangeTorrentTableArray : [ group torrents ] forParent : group withSortDescriptors : descriptors beganTableUpdate : & beganTableUpdate ] ;
2012-01-04 05:16:07 +00:00
}
else
2012-01-07 15:46:42 +00:00
[ self rearrangeTorrentTableArray : fDisplayedTorrents forParent : nil withSortDescriptors : descriptors beganTableUpdate : & beganTableUpdate ] ;
2017-01-24 17:53:16 +00:00
2012-01-07 15:46:42 +00:00
if ( beganTableUpdate && callUpdates )
2012-01-04 23:40:23 +00:00
{
2016-01-06 11:05:37 +00:00
[ fTableView endUpdates ] ;
2012-01-04 23:40:23 +00:00
}
2012-01-04 05:16:07 +00:00
}
2012-01-07 15:46:42 +00:00
# warning redo so that we search a copy once again ( best explained by changing sorting from ascending to descending )
- ( void ) rearrangeTorrentTableArray : ( NSMutableArray * ) rearrangeArray forParent : parent withSortDescriptors : ( NSArray * ) descriptors beganTableUpdate : ( BOOL * ) beganTableUpdate
2012-01-04 05:16:07 +00:00
{
2012-01-07 15:46:42 +00:00
for ( NSUInteger currentIndex = 1 ; currentIndex < [ rearrangeArray count ] ; + + currentIndex )
2012-01-04 05:16:07 +00:00
{
2012-01-07 15:46:42 +00:00
// manually do the sorting in - place
2017-07-08 09:16:01 +00:00
const NSUInteger insertIndex = [ rearrangeArray indexOfObject : rearrangeArray [ currentIndex ] inSortedRange : NSMakeRange ( 0 , currentIndex ) options : ( NSBinarySearchingInsertionIndex | NSBinarySearchingLastEqual ) usingComparator : ^ NSComparisonResult ( id obj1 , id obj2 ) {
2012-01-07 15:46:42 +00:00
for ( NSSortDescriptor * descriptor in descriptors )
{
const NSComparisonResult result = [ descriptor compareObject : obj1 toObject : obj2 ] ;
if ( result ! = NSOrderedSame )
return result ;
}
2017-01-24 17:53:16 +00:00
2012-01-07 15:46:42 +00:00
return NSOrderedSame ;
} ] ;
2017-01-24 17:53:16 +00:00
2012-01-07 15:46:42 +00:00
if ( insertIndex ! = currentIndex )
2012-01-04 05:16:07 +00:00
{
2012-01-07 15:46:42 +00:00
if ( ! * beganTableUpdate )
2012-01-04 23:40:23 +00:00
{
* beganTableUpdate = YES ;
2016-01-06 11:05:37 +00:00
[ fTableView beginUpdates ] ;
2012-01-04 23:40:23 +00:00
}
2017-01-24 17:53:16 +00:00
2012-01-07 15:46:42 +00:00
[ rearrangeArray moveObjectAtIndex : currentIndex toIndex : insertIndex ] ;
2016-01-06 11:05:37 +00:00
[ fTableView moveItemAtIndex : currentIndex inParent : parent toIndex : insertIndex inParent : parent ] ;
2012-01-04 05:16:07 +00:00
}
2008-01-23 02:51:58 +00:00
}
2017-01-24 17:53:16 +00:00
2012-01-07 15:46:42 +00:00
NSAssert2 ( [ rearrangeArray isEqualToArray : [ rearrangeArray sortedArrayUsingDescriptors : descriptors ] ] , @ "Torrent rearranging didn't work! %@ %@" , rearrangeArray , [ rearrangeArray sortedArrayUsingDescriptors : descriptors ] ) ;
2007-09-16 01:02:06 +00:00
}
2011-02-20 03:58:50 +00:00
- ( void ) applyFilter
2007-09-16 01:02:06 +00:00
{
2013-03-07 04:21:26 +00:00
__block int32_t active = 0 , downloading = 0 , seeding = 0 , paused = 0 ;
2007-09-16 01:02:06 +00:00
NSString * filterType = [ fDefaults stringForKey : @ "Filter" ] ;
2007-12-20 04:49:06 +00:00
BOOL filterActive = NO , filterDownload = NO , filterSeed = NO , filterPause = NO , filterStatus = YES ;
if ( [ filterType isEqualToString : FILTER_ACTIVE ] )
filterActive = YES ;
else if ( [ filterType isEqualToString : FILTER_DOWNLOAD ] )
2007-12-20 01:06:55 +00:00
filterDownload = YES ;
else if ( [ filterType isEqualToString : FILTER_SEED ] )
filterSeed = YES ;
else if ( [ filterType isEqualToString : FILTER_PAUSE ] )
filterPause = YES ;
else
filterStatus = NO ;
2017-01-24 17:53:16 +00:00
2009-01-26 02:16:03 +00:00
const NSInteger groupFilterValue = [ fDefaults integerForKey : @ "FilterGroup" ] ;
const BOOL filterGroup = groupFilterValue ! = GROUP_FILTER _ALL _TAG ;
2017-01-24 17:53:16 +00:00
2011-09-19 00:48:30 +00:00
NSArray * searchStrings = [ fFilterBar searchStrings ] ;
if ( searchStrings && [ searchStrings count ] = = 0 )
searchStrings = nil ;
const BOOL filterTracker = searchStrings && [ [ fDefaults stringForKey : @ "FilterSearchType" ] isEqualToString : FILTER_TYPE _TRACKER ] ;
2017-01-24 17:53:16 +00:00
2012-01-08 19:28:59 +00:00
// filter & get counts of each type
NSIndexSet * indexesOfNonFilteredTorrents = [ fTorrents indexesOfObjectsWithOptions : NSEnumerationConcurrent passingTest : ^ BOOL ( Torrent * torrent , NSUInteger idx , BOOL * stop ) {
2007-12-20 01:00:03 +00:00
// check status
2008-03-19 18:03:02 +00:00
if ( [ torrent isActive ] && ! [ torrent isCheckingWaiting ] )
2007-09-16 01:02:06 +00:00
{
2009-10-29 02:45:58 +00:00
const BOOL isActive = ! [ torrent isStalled ] ;
if ( isActive )
2013-03-07 04:27:31 +00:00
OSAtomicIncrement32 ( & active ) ;
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
if ( [ torrent isSeeding ] )
{
2013-03-07 04:27:31 +00:00
OSAtomicIncrement32 ( & seeding ) ;
2008-10-25 00:34:09 +00:00
if ( filterStatus && ! ( ( filterActive && isActive ) || filterSeed ) )
2012-01-08 19:28:59 +00:00
return NO ;
2007-09-16 01:02:06 +00:00
}
else
{
2013-03-07 04:27:31 +00:00
OSAtomicIncrement32 ( & downloading ) ;
2008-10-25 00:34:09 +00:00
if ( filterStatus && ! ( ( filterActive && isActive ) || filterDownload ) )
2012-01-08 19:28:59 +00:00
return NO ;
2007-09-16 01:02:06 +00:00
}
}
else
{
2013-03-07 04:27:31 +00:00
OSAtomicIncrement32 ( & paused ) ;
2007-12-20 01:00:03 +00:00
if ( filterStatus && ! filterPause )
2012-01-08 19:28:59 +00:00
return NO ;
2007-09-16 01:02:06 +00:00
}
2017-01-24 17:53:16 +00:00
2007-12-20 01:00:03 +00:00
// checkGroup
if ( filterGroup )
2007-12-20 01:06:55 +00:00
if ( [ torrent groupValue ] ! = groupFilterValue )
2012-01-08 19:28:59 +00:00
return NO ;
2017-01-24 17:53:16 +00:00
2007-12-20 01:00:03 +00:00
// check text field
2011-09-19 00:48:30 +00:00
if ( searchStrings )
2007-09-16 01:02:06 +00:00
{
2012-01-08 05:37:18 +00:00
__block BOOL removeTextField = NO ;
2007-10-25 20:14:24 +00:00
if ( filterTracker )
{
2011-09-19 00:48:30 +00:00
NSArray * trackers = [ torrent allTrackersFlat ] ;
2017-01-24 17:53:16 +00:00
2012-01-08 05:37:18 +00:00
// to count , we need each string in at least 1 tracker
[ searchStrings enumerateObjectsWithOptions : NSEnumerationConcurrent usingBlock : ^ ( id searchString , NSUInteger idx , BOOL * stop ) {
__block BOOL found = NO ;
[ trackers enumerateObjectsWithOptions : NSEnumerationConcurrent usingBlock : ^ ( id tracker , NSUInteger idx , BOOL * stopTracker ) {
2012-01-07 18:46:03 +00:00
if ( [ tracker rangeOfString : searchString options : ( NSCaseInsensitiveSearch | NSDiacriticInsensitiveSearch ) ] . location ! = NSNotFound )
2011-09-19 00:48:30 +00:00
{
found = YES ;
2012-01-08 05:37:18 +00:00
* stopTracker = YES ;
2011-09-19 00:48:30 +00:00
}
2012-01-08 05:37:18 +00:00
} ] ;
2011-09-19 00:48:30 +00:00
if ( ! found )
2008-03-21 20:28:04 +00:00
{
2011-09-19 00:48:30 +00:00
removeTextField = YES ;
2012-01-08 05:37:18 +00:00
* stop = YES ;
2008-03-21 20:28:04 +00:00
}
2012-01-08 05:37:18 +00:00
} ] ;
2007-10-25 20:14:24 +00:00
}
2007-09-16 01:02:06 +00:00
else
2007-12-20 01:00:03 +00:00
{
2012-01-08 05:37:18 +00:00
[ searchStrings enumerateObjectsWithOptions : NSEnumerationConcurrent usingBlock : ^ ( id searchString , NSUInteger idx , BOOL * stop ) {
2011-09-19 00:48:30 +00:00
if ( [ [ torrent name ] rangeOfString : searchString options : ( NSCaseInsensitiveSearch | NSDiacriticInsensitiveSearch ) ] . location = = NSNotFound )
{
removeTextField = YES ;
2012-01-08 05:37:18 +00:00
* stop = YES ;
2011-09-19 00:48:30 +00:00
}
2012-01-08 05:37:18 +00:00
} ] ;
2007-12-20 01:00:03 +00:00
}
2017-01-24 17:53:16 +00:00
2011-09-19 00:48:30 +00:00
if ( removeTextField )
2012-01-08 19:28:59 +00:00
return NO ;
2007-09-16 01:02:06 +00:00
}
2017-01-24 17:53:16 +00:00
2012-01-08 19:28:59 +00:00
return YES ;
} ] ;
2017-01-24 17:53:16 +00:00
2012-01-08 19:28:59 +00:00
NSArray * allTorrents = [ fTorrents objectsAtIndexes : indexesOfNonFilteredTorrents ] ;
2017-01-24 17:53:16 +00:00
2007-12-20 01:00:03 +00:00
// set button tooltips
2011-02-20 04:23:09 +00:00
if ( fFilterBar )
[ fFilterBar setCountAll : [ fTorrents count ] active : active downloading : downloading seeding : seeding paused : paused ] ;
2017-01-24 17:53:16 +00:00
2012-01-18 01:40:34 +00:00
// if either the previous or current lists are blank , set its value to the other
2017-07-08 09:16:01 +00:00
const BOOL groupRows = [ allTorrents count ] > 0 ? [ fDefaults boolForKey : @ "SortByGroup" ] : ( [ fDisplayedTorrents count ] > 0 && [ fDisplayedTorrents [ 0 ] isKindOfClass : [ TorrentGroup class ] ] ) ;
const BOOL wasGroupRows = [ fDisplayedTorrents count ] > 0 ? [ fDisplayedTorrents [ 0 ] isKindOfClass : [ TorrentGroup class ] ] : groupRows ;
2017-01-24 17:53:16 +00:00
2012-09-09 12:58:53 +00:00
# warning could probably be merged with later code somehow
2008-01-23 17:03:42 +00:00
// clear display cache for not - shown torrents
2012-01-07 17:08:28 +00:00
if ( [ fDisplayedTorrents count ] > 0 )
{
// for each torrent , removes the previous piece info if it ' s not in allTorrents , and keeps track of which torrents we already found in allTorrents
2012-01-18 01:40:34 +00:00
void ( ^ removePreviousFinishedPieces ) ( id , NSUInteger , BOOL * ) = ^ ( Torrent * torrent , NSUInteger idx , BOOL * stop ) {
2012-01-08 19:58:58 +00:00
// we used to keep track of which torrents we already found in allTorrents , but it wasn ' t safe fo concurrent enumeration
2012-01-18 01:40:34 +00:00
if ( ! [ allTorrents containsObject : torrent ] )
[ torrent setPreviousFinishedPieces : nil ] ;
2012-01-07 17:08:28 +00:00
} ;
2017-01-24 17:53:16 +00:00
2012-01-18 01:40:34 +00:00
if ( wasGroupRows )
2012-01-07 17:40:18 +00:00
[ fDisplayedTorrents enumerateObjectsWithOptions : NSEnumerationConcurrent usingBlock : ^ ( id obj , NSUInteger idx , BOOL * stop ) {
[ [ ( TorrentGroup * ) obj torrents ] enumerateObjectsWithOptions : NSEnumerationConcurrent usingBlock : removePreviousFinishedPieces ] ;
} ] ;
2012-01-07 17:08:28 +00:00
else
[ fDisplayedTorrents enumerateObjectsWithOptions : NSEnumerationConcurrent usingBlock : removePreviousFinishedPieces ] ;
}
2017-01-24 17:53:16 +00:00
2012-01-07 15:46:42 +00:00
BOOL beganUpdates = NO ;
2016-01-06 11:05:37 +00:00
// don ' t animate torrents when first launching
static dispatch_once _t onceToken ;
dispatch_once ( & onceToken , ^ {
[ [ NSAnimationContext currentContext ] setDuration : 0 ] ;
} ) ;
[ NSAnimationContext beginGrouping ] ;
2017-01-24 17:53:16 +00:00
2012-01-18 01:40:34 +00:00
// add / remove torrents ( and rearrange for groups ) , one by one
2012-01-07 15:46:42 +00:00
if ( ! groupRows && ! wasGroupRows )
2008-01-23 20:31:04 +00:00
{
2012-01-07 15:46:42 +00:00
NSMutableIndexSet * addIndexes = [ NSMutableIndexSet indexSet ] ,
2012-09-09 12:58:53 +00:00
* removePreviousIndexes = [ NSMutableIndexSet indexSetWithIndexesInRange : NSMakeRange ( 0 , [ fDisplayedTorrents count ] ) ] ;
2017-01-24 17:53:16 +00:00
2012-01-07 18:46:03 +00:00
// for each of the torrents to add , find if it already exists ( and keep track of those we ' ve already added & those we need to remove )
2012-01-14 16:08:45 +00:00
[ allTorrents enumerateObjectsWithOptions : 0 usingBlock : ^ ( id objAll , NSUInteger previousIndex , BOOL * stop ) {
2012-01-07 18:46:03 +00:00
const NSUInteger currentIndex = [ fDisplayedTorrents indexOfObjectAtIndexes : removePreviousIndexes options : NSEnumerationConcurrent passingTest : ^ ( id objDisplay , NSUInteger idx , BOOL * stop ) {
return ( BOOL ) ( objAll = = objDisplay ) ;
2012-01-07 15:46:42 +00:00
} ] ;
if ( currentIndex = = NSNotFound )
[ addIndexes addIndex : previousIndex ] ;
else
2012-01-07 18:46:03 +00:00
[ removePreviousIndexes removeIndex : currentIndex ] ;
} ] ;
2017-01-24 17:53:16 +00:00
2012-01-07 18:46:03 +00:00
if ( [ addIndexes count ] > 0 || [ removePreviousIndexes count ] > 0 )
2012-01-07 15:46:42 +00:00
{
beganUpdates = YES ;
2016-01-06 11:05:37 +00:00
[ fTableView beginUpdates ] ;
2017-01-24 17:53:16 +00:00
2012-01-07 15:46:42 +00:00
// remove torrents we didn ' t find
2012-01-07 18:46:03 +00:00
if ( [ removePreviousIndexes count ] > 0 )
2012-01-07 15:46:42 +00:00
{
2012-01-07 18:46:03 +00:00
[ fDisplayedTorrents removeObjectsAtIndexes : removePreviousIndexes ] ;
2016-01-06 11:05:37 +00:00
[ fTableView removeItemsAtIndexes : removePreviousIndexes inParent : nil withAnimation : NSTableViewAnimationSlideDown ] ;
2012-01-07 15:46:42 +00:00
}
2017-01-24 17:53:16 +00:00
2012-01-07 15:46:42 +00:00
// add new torrents
if ( [ addIndexes count ] > 0 )
{
2012-01-08 00:51:05 +00:00
// slide new torrents in differently
if ( fAddingTransfers )
{
2012-01-08 20:22:43 +00:00
NSIndexSet * newAddIndexes = [ allTorrents indexesOfObjectsAtIndexes : addIndexes options : NSEnumerationConcurrent passingTest : ^ BOOL ( id obj , NSUInteger idx , BOOL * stop ) {
2012-01-08 00:51:05 +00:00
return [ fAddingTransfers containsObject : obj ] ;
} ] ;
2017-01-24 17:53:16 +00:00
2012-01-08 00:51:05 +00:00
[ addIndexes removeIndexes : newAddIndexes ] ;
2017-01-24 17:53:16 +00:00
2012-01-08 00:51:05 +00:00
[ fDisplayedTorrents addObjectsFromArray : [ allTorrents objectsAtIndexes : newAddIndexes ] ] ;
2016-01-06 11:05:37 +00:00
[ fTableView insertItemsAtIndexes : [ NSIndexSet indexSetWithIndexesInRange : NSMakeRange ( [ fDisplayedTorrents count ] - [ newAddIndexes count ] , [ newAddIndexes count ] ) ] inParent : nil withAnimation : NSTableViewAnimationSlideLeft ] ;
2012-01-08 00:51:05 +00:00
}
2017-01-24 17:53:16 +00:00
2012-01-07 15:46:42 +00:00
[ fDisplayedTorrents addObjectsFromArray : [ allTorrents objectsAtIndexes : addIndexes ] ] ;
2016-01-06 11:05:37 +00:00
[ fTableView insertItemsAtIndexes : [ NSIndexSet indexSetWithIndexesInRange : NSMakeRange ( [ fDisplayedTorrents count ] - [ addIndexes count ] , [ addIndexes count ] ) ] inParent : nil withAnimation : NSTableViewAnimationSlideDown ] ;
2012-01-07 15:46:42 +00:00
}
}
}
2012-01-09 23:59:57 +00:00
else if ( groupRows && wasGroupRows )
2012-01-07 15:46:42 +00:00
{
NSAssert ( groupRows && wasGroupRows , @ "Should have had group rows and should remain with group rows" ) ;
2017-01-24 17:53:16 +00:00
2012-09-09 12:58:53 +00:00
# warning don ' t always do ?
2012-01-07 15:46:42 +00:00
beganUpdates = YES ;
2016-01-06 11:05:37 +00:00
[ fTableView beginUpdates ] ;
2017-01-24 17:53:16 +00:00
2012-01-07 15:46:42 +00:00
NSMutableIndexSet * unusedAllTorrentsIndexes = [ NSMutableIndexSet indexSetWithIndexesInRange : NSMakeRange ( 0 , [ allTorrents count ] ) ] ;
2017-01-24 17:53:16 +00:00
2012-01-07 15:46:42 +00:00
NSMutableDictionary * groupsByIndex = [ NSMutableDictionary dictionaryWithCapacity : [ fDisplayedTorrents count ] ] ;
for ( TorrentGroup * group in fDisplayedTorrents )
2017-07-08 14:38:47 +00:00
groupsByIndex [ @ ( [ group groupIndex ] ) ] = group ;
2017-01-24 17:53:16 +00:00
2012-01-07 15:46:42 +00:00
const NSUInteger originalGroupCount = [ fDisplayedTorrents count ] ;
for ( NSUInteger index = 0 ; index < originalGroupCount ; + + index )
{
2017-07-08 09:16:01 +00:00
TorrentGroup * group = fDisplayedTorrents [ index ] ;
2017-01-24 17:53:16 +00:00
2012-01-07 15:46:42 +00:00
NSMutableIndexSet * removeIndexes = [ NSMutableIndexSet indexSet ] ;
2017-01-24 17:53:16 +00:00
2012-01-07 15:46:42 +00:00
// needs to be a signed integer
2016-09-11 10:22:49 +00:00
for ( NSUInteger indexInGroup = 0 ; indexInGroup < [ [ group torrents ] count ] ; + + indexInGroup )
2012-01-07 15:46:42 +00:00
{
2017-07-08 09:16:01 +00:00
Torrent * torrent = [ group torrents ] [ indexInGroup ] ;
2012-01-07 15:46:42 +00:00
const NSUInteger allIndex = [ allTorrents indexOfObjectAtIndexes : unusedAllTorrentsIndexes options : NSEnumerationConcurrent passingTest : ^ ( id obj , NSUInteger idx , BOOL * stop ) {
return ( BOOL ) ( obj = = torrent ) ;
} ] ;
if ( allIndex = = NSNotFound )
[ removeIndexes addIndex : indexInGroup ] ;
else
2008-12-26 00:16:19 +00:00
{
2012-01-07 15:46:42 +00:00
BOOL markTorrentAsUsed = YES ;
2017-01-24 17:53:16 +00:00
2012-01-07 15:46:42 +00:00
const NSInteger groupValue = [ torrent groupValue ] ;
if ( groupValue ! = [ group groupIndex ] )
2008-12-26 00:16:19 +00:00
{
2017-07-08 14:38:47 +00:00
TorrentGroup * newGroup = groupsByIndex [ @ ( groupValue ) ] ;
2012-01-07 15:46:42 +00:00
if ( ! newGroup )
{
2017-07-29 16:14:22 +00:00
newGroup = [ [ TorrentGroup alloc ] initWithGroup : groupValue ] ;
2017-07-08 14:38:47 +00:00
groupsByIndex [ @ ( groupValue ) ] = newGroup ;
2012-01-07 15:46:42 +00:00
[ fDisplayedTorrents addObject : newGroup ] ;
2016-01-06 11:05:37 +00:00
[ fTableView insertItemsAtIndexes : [ NSIndexSet indexSetWithIndex : [ fDisplayedTorrents count ] -1 ] inParent : nil withAnimation : NSTableViewAnimationEffectFade ] ;
[ fTableView isGroupCollapsed : groupValue ] ? [ fTableView collapseItem : newGroup ] : [ fTableView expandItem : newGroup ] ;
2012-01-07 15:46:42 +00:00
}
else // if we haven ' t processed the other group yet , we have to make sure we don ' t flag it for removal the next time
{
// ugggh , but shouldn ' t happen too often
if ( [ fDisplayedTorrents indexOfObject : newGroup inRange : NSMakeRange ( index + 1 , originalGroupCount - ( index + 1 ) ) ] ! = NSNotFound )
markTorrentAsUsed = NO ;
}
2017-01-24 17:53:16 +00:00
2012-01-07 15:46:42 +00:00
[ [ group torrents ] removeObjectAtIndex : indexInGroup ] ;
[ [ newGroup torrents ] addObject : torrent ] ;
2016-01-06 11:05:37 +00:00
[ fTableView moveItemAtIndex : indexInGroup inParent : group toIndex : [ [ newGroup torrents ] count ] -1 inParent : newGroup ] ;
2017-01-24 17:53:16 +00:00
2012-01-07 15:46:42 +00:00
- - indexInGroup ;
2008-12-26 00:16:19 +00:00
}
2017-01-24 17:53:16 +00:00
2012-01-07 15:46:42 +00:00
if ( markTorrentAsUsed )
[ unusedAllTorrentsIndexes removeIndex : allIndex ] ;
2008-12-26 00:16:19 +00:00
}
2012-01-07 15:46:42 +00:00
}
2017-01-24 17:53:16 +00:00
2012-01-07 15:46:42 +00:00
if ( [ removeIndexes count ] > 0 )
{
[ [ group torrents ] removeObjectsAtIndexes : removeIndexes ] ;
2016-01-06 11:05:37 +00:00
[ fTableView removeItemsAtIndexes : removeIndexes inParent : group withAnimation : NSTableViewAnimationEffectFade ] ;
2012-01-07 15:46:42 +00:00
}
}
2017-01-24 17:53:16 +00:00
2012-01-07 15:46:42 +00:00
// add remaining new torrents
for ( Torrent * torrent in [ allTorrents objectsAtIndexes : unusedAllTorrentsIndexes ] )
{
const NSInteger groupValue = [ torrent groupValue ] ;
2017-07-08 14:38:47 +00:00
TorrentGroup * group = groupsByIndex [ @ ( groupValue ) ] ;
2012-01-07 15:46:42 +00:00
if ( ! group )
{
2017-07-29 16:14:22 +00:00
group = [ [ TorrentGroup alloc ] initWithGroup : groupValue ] ;
2017-07-08 14:38:47 +00:00
groupsByIndex [ @ ( groupValue ) ] = group ;
2008-07-01 15:11:58 +00:00
[ fDisplayedTorrents addObject : group ] ;
2016-01-06 11:05:37 +00:00
[ fTableView insertItemsAtIndexes : [ NSIndexSet indexSetWithIndex : [ fDisplayedTorrents count ] -1 ] inParent : nil withAnimation : NSTableViewAnimationEffectFade ] ;
[ fTableView isGroupCollapsed : groupValue ] ? [ fTableView collapseItem : group ] : [ fTableView expandItem : group ] ;
2008-01-23 20:31:04 +00:00
}
2017-01-24 17:53:16 +00:00
2009-12-26 00:02:20 +00:00
[ [ group torrents ] addObject : torrent ] ;
2016-01-06 11:05:37 +00:00
const BOOL newTorrent = fAddingTransfers && [ fAddingTransfers containsObject : torrent ] ;
[ fTableView insertItemsAtIndexes : [ NSIndexSet indexSetWithIndex : [ [ group torrents ] count ] -1 ] inParent : group withAnimation : newTorrent ? NSTableViewAnimationSlideLeft : NSTableViewAnimationSlideDown ] ;
2012-01-07 15:46:42 +00:00
}
2017-01-24 17:53:16 +00:00
2012-01-07 15:46:42 +00:00
// remove empty groups
2012-01-12 00:12:17 +00:00
NSIndexSet * removeGroupIndexes = [ fDisplayedTorrents indexesOfObjectsAtIndexes : [ NSIndexSet indexSetWithIndexesInRange : NSMakeRange ( 0 , originalGroupCount ) ] options : NSEnumerationConcurrent passingTest : ^ BOOL ( id obj , NSUInteger idx , BOOL * stop ) {
2012-01-08 18:58:47 +00:00
return [ [ ( TorrentGroup * ) obj torrents ] count ] = = 0 ;
2012-01-07 18:46:03 +00:00
} ] ;
2017-01-24 17:53:16 +00:00
2012-01-12 00:12:17 +00:00
if ( [ removeGroupIndexes count ] > 0 )
2012-01-07 15:46:42 +00:00
{
2012-01-12 00:12:17 +00:00
[ fDisplayedTorrents removeObjectsAtIndexes : removeGroupIndexes ] ;
2016-01-06 11:05:37 +00:00
[ fTableView removeItemsAtIndexes : removeGroupIndexes inParent : nil withAnimation : NSTableViewAnimationEffectFade ] ;
2008-01-23 20:31:04 +00:00
}
2017-01-24 17:53:16 +00:00
2012-01-07 15:46:42 +00:00
// now that all groups are there , sort them - don ' t insert on the fly in case groups were reordered in prefs
NSSortDescriptor * groupDescriptor = [ NSSortDescriptor sortDescriptorWithKey : @ "groupOrderValue" ascending : YES ] ;
2017-07-08 08:23:05 +00:00
[ self rearrangeTorrentTableArray : fDisplayedTorrents forParent : nil withSortDescriptors : @ [ groupDescriptor ] beganTableUpdate : & beganUpdates ] ;
2008-01-23 20:31:04 +00:00
}
2012-01-09 23:59:57 +00:00
else
{
2012-01-12 00:12:17 +00:00
NSAssert ( groupRows ! = wasGroupRows , @ "Trying toggling group-torrent reordering when we weren't expecting to." ) ;
2017-01-24 17:53:16 +00:00
2012-01-14 20:07:26 +00:00
// set all groups as expanded
[ fTableView removeAllCollapsedGroups ] ;
2017-01-24 17:53:16 +00:00
2012-01-09 23:59:57 +00:00
// since we ' re not doing this the right way ( boo buggy animation ) , we need to remember selected values
2012-09-09 12:58:53 +00:00
# warning when Lion - only and using views instead of cells , this likely won ' t be needed
2012-01-14 19:53:08 +00:00
NSArray * selectedValues = [ fTableView selectedValues ] ;
2017-01-24 17:53:16 +00:00
2012-01-09 23:59:57 +00:00
beganUpdates = YES ;
2016-01-06 11:05:37 +00:00
[ fTableView beginUpdates ] ;
[ fTableView removeItemsAtIndexes : [ NSIndexSet indexSetWithIndexesInRange : NSMakeRange ( 0 , [ fDisplayedTorrents count ] ) ] inParent : nil withAnimation : NSTableViewAnimationSlideDown ] ;
2017-01-24 17:53:16 +00:00
2012-01-09 23:59:57 +00:00
if ( groupRows )
{
// a map for quickly finding groups
NSMutableDictionary * groupsByIndex = [ NSMutableDictionary dictionaryWithCapacity : [ [ GroupsController groups ] numberOfGroups ] ] ;
for ( Torrent * torrent in allTorrents )
{
const NSInteger groupValue = [ torrent groupValue ] ;
2017-07-08 14:38:47 +00:00
TorrentGroup * group = groupsByIndex [ @ ( groupValue ) ] ;
2012-01-09 23:59:57 +00:00
if ( ! group )
{
2017-07-29 16:14:22 +00:00
group = [ [ TorrentGroup alloc ] initWithGroup : groupValue ] ;
2017-07-08 14:38:47 +00:00
groupsByIndex [ @ ( groupValue ) ] = group ;
2012-01-09 23:59:57 +00:00
}
2017-01-24 17:53:16 +00:00
2012-01-09 23:59:57 +00:00
[ [ group torrents ] addObject : torrent ] ;
}
2017-01-24 17:53:16 +00:00
2012-01-09 23:59:57 +00:00
[ fDisplayedTorrents setArray : [ groupsByIndex allValues ] ] ;
2017-01-24 17:53:16 +00:00
2012-01-09 23:59:57 +00:00
// we need the groups to be sorted , and we can do it without moving items in the table , too !
NSSortDescriptor * groupDescriptor = [ NSSortDescriptor sortDescriptorWithKey : @ "groupOrderValue" ascending : YES ] ;
2017-07-08 08:23:05 +00:00
[ fDisplayedTorrents sortUsingDescriptors : @ [ groupDescriptor ] ] ;
2012-01-09 23:59:57 +00:00
}
else
[ fDisplayedTorrents setArray : allTorrents ] ;
2016-01-06 11:05:37 +00:00
[ fTableView insertItemsAtIndexes : [ NSIndexSet indexSetWithIndexesInRange : NSMakeRange ( 0 , [ fDisplayedTorrents count ] ) ] inParent : nil withAnimation : NSTableViewAnimationEffectFade ] ;
2017-01-24 17:53:16 +00:00
if ( groupRows )
{
// actually expand group rows
for ( TorrentGroup * group in fDisplayedTorrents )
[ fTableView expandItem : group ] ;
}
2012-01-14 19:53:08 +00:00
if ( selectedValues )
[ fTableView selectValues : selectedValues ] ;
2012-01-09 23:59:57 +00:00
}
2017-01-24 17:53:16 +00:00
2012-01-07 15:46:42 +00:00
// sort the torrents ( won ' t sort the groups , though )
2012-01-14 19:53:08 +00:00
[ self sortTorrentsCallUpdates : ! beganUpdates includeQueueOrder : YES ] ;
2016-01-06 11:05:37 +00:00
if ( beganUpdates )
[ fTableView endUpdates ] ;
[ fTableView setNeedsDisplay : YES ] ;
2017-01-24 17:53:16 +00:00
2016-01-06 11:05:37 +00:00
[ NSAnimationContext endGrouping ] ;
2009-01-06 02:07:55 +00:00
[ self resetInfo ] ; // if group is already selected , but the torrents in it change
2017-01-24 17:53:16 +00:00
2011-09-19 00:48:30 +00:00
[ self setBottomCountText : groupRows || filterStatus || filterGroup || searchStrings ] ;
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
[ self setWindowSizeToFit ] ;
2017-01-24 17:53:16 +00:00
2012-01-08 00:51:05 +00:00
if ( fAddingTransfers )
{
fAddingTransfers = nil ;
}
2007-09-16 01:02:06 +00:00
}
- ( void ) switchFilter : ( id ) sender
{
2011-02-20 03:58:50 +00:00
[ fFilterBar switchFilter : sender = = fNextFilterItem ] ;
2007-09-16 01:02:06 +00:00
}
2011-07-23 15:54:02 +00:00
- ( IBAction ) showGlobalPopover : ( id ) sender
{
2016-01-06 11:05:37 +00:00
if ( fGlobalPopoverShown )
return ;
2017-01-24 17:53:16 +00:00
2016-01-06 11:05:37 +00:00
NSPopover * popover = [ [ NSPopover alloc ] init ] ;
[ popover setBehavior : NSPopoverBehaviorTransient ] ;
GlobalOptionsPopoverViewController * viewController = [ [ GlobalOptionsPopoverViewController alloc ] initWithHandle : fLib ] ;
[ popover setContentViewController : viewController ] ;
[ popover setDelegate : self ] ;
2017-01-24 17:53:16 +00:00
2016-01-06 11:05:37 +00:00
[ popover showRelativeToRect : [ sender frame ] ofView : sender preferredEdge : NSMaxYEdge ] ;
2011-07-23 15:54:02 +00:00
}
2011-07-27 03:38:01 +00:00
// don ' t show multiple popovers when clicking the gear button repeatedly
- ( void ) popoverWillShow : ( NSNotification * ) notification
{
fGlobalPopoverShown = YES ;
}
- ( void ) popoverWillClose : ( NSNotification * ) notification
{
fGlobalPopoverShown = NO ;
}
2007-12-17 16:06:20 +00:00
- ( void ) menuNeedsUpdate : ( NSMenu * ) menu
{
2011-02-20 03:58:50 +00:00
if ( menu = = fGroupsSetMenu || menu = = fGroupsSetContextMenu )
2007-12-17 22:30:28 +00:00
{
2011-02-20 03:58:50 +00:00
for ( NSInteger i = [ menu numberOfItems ] -1 ; i >= 0 ; i - - )
2007-12-19 20:46:00 +00:00
[ menu removeItemAtIndex : i ] ;
2017-01-24 17:53:16 +00:00
2011-02-20 03:58:50 +00:00
NSMenu * groupMenu = [ [ GroupsController groups ] groupMenuWithTarget : self action : @ selector ( setGroup : ) isSmall : NO ] ;
2017-01-24 17:53:16 +00:00
2008-12-17 02:13:49 +00:00
const NSInteger groupMenuCount = [ groupMenu numberOfItems ] ;
for ( NSInteger i = 0 ; i < groupMenuCount ; i + + )
{
2017-07-29 16:14:22 +00:00
NSMenuItem * item = [ groupMenu itemAtIndex : 0 ] ;
2008-12-17 02:13:49 +00:00
[ groupMenu removeItemAtIndex : 0 ] ;
[ menu addItem : item ] ;
}
2007-12-19 20:46:00 +00:00
}
2014-01-10 17:50:05 +00:00
else if ( menu = = fShareMenu || menu = = fShareContextMenu ) {
[ menu removeAllItems ] ;
2017-01-24 17:53:16 +00:00
2014-01-10 17:50:05 +00:00
for ( NSMenuItem * item in [ [ ShareTorrentFileHelper sharedHelper ] menuItems ] )
{
[ menu addItem : item ] ;
}
}
2007-12-19 20:46:00 +00:00
else ;
2007-12-17 16:06:20 +00:00
}
- ( void ) setGroup : ( id ) sender
{
2008-12-26 07:06:02 +00:00
for ( Torrent * torrent in [ fTableView selectedTorrents ] )
2008-02-07 15:57:32 +00:00
{
[ fTableView removeCollapsedGroup : [ torrent groupValue ] ] ; // remove old collapsed group
2017-01-24 17:53:16 +00:00
2012-10-30 00:22:10 +00:00
[ torrent setGroupValue : [ ( NSMenuItem * ) sender tag ] determinationType : TorrentDeterminationUserSpecified ] ;
2008-02-07 15:57:32 +00:00
}
2017-01-24 17:53:16 +00:00
2011-02-20 03:58:50 +00:00
[ self applyFilter ] ;
2007-12-17 16:06:20 +00:00
[ self updateUI ] ;
[ self updateTorrentHistory ] ;
}
2007-09-16 01:02:06 +00:00
- ( void ) toggleSpeedLimit : ( id ) sender
{
[ fDefaults setBool : ! [ fDefaults boolForKey : @ "SpeedLimit" ] forKey : @ "SpeedLimit" ] ;
2009-01-02 03:57:28 +00:00
[ self speedLimitChanged : sender ] ;
}
- ( void ) speedLimitChanged : ( id ) sender
{
2009-03-28 17:18:43 +00:00
tr_sessionUseAltSpeed ( fLib , [ fDefaults boolForKey : @ "SpeedLimit" ] ) ;
2011-02-20 00:22:55 +00:00
[ fStatusBar updateSpeedFieldsToolTips ] ;
2008-06-19 02:53:45 +00:00
}
2009-03-30 22:18:25 +00:00
- ( void ) altSpeedToggledCallbackIsLimited : ( NSDictionary * ) dict
2008-06-19 02:53:45 +00:00
{
2017-07-08 14:38:47 +00:00
const BOOL isLimited = [ dict [ @ "Active" ] boolValue ] ;
2012-09-09 12:58:53 +00:00
2009-03-28 17:18:43 +00:00
[ fDefaults setBool : isLimited forKey : @ "SpeedLimit" ] ;
2011-02-20 00:22:55 +00:00
[ fStatusBar updateSpeedFieldsToolTips ] ;
2017-01-24 17:53:16 +00:00
2017-08-26 12:55:45 +00:00
if ( ! [ dict [ @ "ByUser" ] boolValue ] ) {
NSUserNotification * notification = [ [ NSUserNotification alloc ] init ] ;
notification . title = isLimited ? NSLocalizedString ( @ "Speed Limit Auto Enabled" , "notification title" ) : NSLocalizedString ( @ "Speed Limit Auto Disabled" , "notification title" ) ;
notification . informativeText = NSLocalizedString ( @ "Bandwidth settings changed" , "notification description" ) ;
notification . hasActionButton = NO ;
2017-01-24 17:53:16 +00:00
2017-08-26 12:55:45 +00:00
[ [ NSUserNotificationCenter defaultUserNotificationCenter ] deliverNotification : notification ] ;
}
2007-09-16 01:02:06 +00:00
}
2008-04-10 16:37:07 +00:00
- ( void ) sound : ( NSSound * ) sound didFinishPlaying : ( BOOL ) finishedPlaying
{
fSoundPlaying = NO ;
}
2013-01-19 05:03:00 +00:00
- ( void ) VDKQueue : ( VDKQueue * ) queue receivedNotification : ( NSString * ) notification forPath : ( NSString * ) fpath
2007-09-16 01:02:06 +00:00
{
2013-02-08 13:31:38 +00:00
// don ' t assume that just because we ' re watching for write notification , we ' ll only receive write notifications
2017-01-24 17:53:16 +00:00
2013-01-19 05:03:00 +00:00
if ( ! [ fDefaults boolForKey : @ "AutoImport" ] || ! [ fDefaults stringForKey : @ "AutoImportDirectory" ] )
return ;
2017-01-24 17:53:16 +00:00
2013-02-08 13:02:16 +00:00
if ( [ fAutoImportTimer isValid ] )
[ fAutoImportTimer invalidate ] ;
2017-01-24 17:53:16 +00:00
2013-01-19 05:03:00 +00:00
// check again in 10 seconds in case torrent file wasn ' t complete
2017-07-29 16:14:22 +00:00
fAutoImportTimer = [ NSTimer scheduledTimerWithTimeInterval : 10.0 target : self
selector : @ selector ( checkAutoImportDirectory ) userInfo : nil repeats : NO ] ;
2017-01-24 17:53:16 +00:00
2013-01-19 05:03:00 +00:00
[ self checkAutoImportDirectory ] ;
2007-09-16 01:02:06 +00:00
}
- ( void ) changeAutoImport
{
2013-02-08 13:02:16 +00:00
if ( [ fAutoImportTimer isValid ] )
[ fAutoImportTimer invalidate ] ;
fAutoImportTimer = nil ;
2017-01-24 17:53:16 +00:00
2012-03-13 03:49:30 +00:00
fAutoImportedNames = nil ;
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
[ self checkAutoImportDirectory ] ;
}
- ( void ) checkAutoImportDirectory
{
NSString * path ;
if ( ! [ fDefaults boolForKey : @ "AutoImport" ] || ! ( path = [ fDefaults stringForKey : @ "AutoImportDirectory" ] ) )
return ;
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
path = [ path stringByExpandingTildeInPath ] ;
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
NSArray * importedNames ;
2009-05-23 18:53:09 +00:00
if ( ! ( importedNames = [ [ NSFileManager defaultManager ] contentsOfDirectoryAtPath : path error : NULL ] ) )
2007-09-16 01:02:06 +00:00
return ;
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
// only check files that have not been checked yet
NSMutableArray * newNames = [ importedNames mutableCopy ] ;
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
if ( fAutoImportedNames )
[ newNames removeObjectsInArray : fAutoImportedNames ] ;
else
fAutoImportedNames = [ [ NSMutableArray alloc ] init ] ;
2009-05-23 18:55:08 +00:00
[ fAutoImportedNames setArray : importedNames ] ;
2017-01-24 17:53:16 +00:00
2008-12-26 07:06:02 +00:00
for ( NSString * file in newNames )
2007-09-16 01:02:06 +00:00
{
2009-05-23 19:01:57 +00:00
if ( [ file hasPrefix : @ "." ] )
continue ;
2017-01-24 17:53:16 +00:00
2009-05-23 19:01:57 +00:00
NSString * fullFile = [ path stringByAppendingPathComponent : file ] ;
2017-01-24 17:53:16 +00:00
2009-06-11 23:43:13 +00:00
if ( ! ( [ [ [ NSWorkspace sharedWorkspace ] typeOfFile : fullFile error : NULL ] isEqualToString : @ "org.bittorrent.torrent" ]
2012-09-09 12:58:53 +00:00
|| [ [ fullFile pathExtension ] caseInsensitiveCompare : @ "torrent" ] = = NSOrderedSame ) )
2009-05-23 19:01:57 +00:00
continue ;
2017-01-24 17:53:16 +00:00
2008-12-26 07:06:02 +00:00
tr_ctor * ctor = tr_ctorNew ( fLib ) ;
2020-04-25 14:35:15 +00:00
tr_ctorSetMetainfoFromFile ( ctor , [ fullFile UTF8String ] ) ;
2017-01-24 17:53:16 +00:00
2009-04-02 17:30:29 +00:00
switch ( tr_torrentParse ( ctor , NULL ) )
2007-09-16 01:02:06 +00:00
{
2017-07-29 16:14:22 +00:00
case TR_PARSE _OK : {
2017-07-08 08:23:05 +00:00
[ self openFiles : @ [ fullFile ] addType : ADD_AUTO forcePath : nil ] ;
2017-01-24 17:53:16 +00:00
2012-09-09 12:26:18 +00:00
NSString * notificationTitle = NSLocalizedString ( @ "Torrent File Auto Added" , "notification title" ) ;
2017-02-05 19:29:20 +00:00
NSUserNotification * notification = [ [ NSUserNotification alloc ] init ] ;
[ notification setTitle : notificationTitle ] ;
[ notification setInformativeText : file ] ;
2017-01-24 17:53:16 +00:00
2017-02-05 19:29:20 +00:00
[ notification setHasActionButton : NO ] ;
2017-01-24 17:53:16 +00:00
2017-02-05 19:29:20 +00:00
[ [ NSUserNotificationCenter defaultUserNotificationCenter ] deliverNotification : notification ] ;
2007-12-22 03:39:52 +00:00
break ;
2017-07-29 16:14:22 +00:00
}
2009-08-05 02:13:45 +00:00
case TR_PARSE _ERR :
2009-05-23 19:01:57 +00:00
[ fAutoImportedNames removeObject : file ] ;
2011-02-19 21:12:45 +00:00
break ;
2017-01-24 17:53:16 +00:00
2011-02-19 21:12:45 +00:00
case TR_PARSE _DUPLICATE : // let ' s ignore this ( but silence a warning )
break ;
2007-09-16 01:02:06 +00:00
}
2017-01-24 17:53:16 +00:00
2007-12-22 03:39:52 +00:00
tr_ctorFree ( ctor ) ;
2007-09-16 01:02:06 +00:00
}
}
- ( void ) beginCreateFile : ( NSNotification * ) notification
{
if ( ! [ fDefaults boolForKey : @ "AutoImport" ] )
return ;
2017-01-24 17:53:16 +00:00
2012-05-28 14:28:50 +00:00
NSString * location = [ ( NSURL * ) [ notification object ] path ] ,
2012-09-09 12:58:53 +00:00
* path = [ fDefaults stringForKey : @ "AutoImportDirectory" ] ;
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
if ( location && path && [ [ [ location stringByDeletingLastPathComponent ] stringByExpandingTildeInPath ]
2012-09-09 12:58:53 +00:00
isEqualToString : [ path stringByExpandingTildeInPath ] ] )
2007-09-16 01:02:06 +00:00
[ fAutoImportedNames addObject : [ location lastPathComponent ] ] ;
}
2008-02-06 23:45:44 +00:00
- ( NSInteger ) outlineView : ( NSOutlineView * ) outlineView numberOfChildrenOfItem : ( id ) item
2007-09-16 01:02:06 +00:00
{
2008-02-06 23:45:44 +00:00
if ( item )
2008-07-01 01:28:19 +00:00
return [ [ item torrents ] count ] ;
2008-02-06 23:45:44 +00:00
else
return [ fDisplayedTorrents count ] ;
2007-09-16 01:02:06 +00:00
}
2008-02-06 23:45:44 +00:00
- ( id ) outlineView : ( NSOutlineView * ) outlineView child : ( NSInteger ) index ofItem : ( id ) item
2007-10-27 02:00:43 +00:00
{
2008-02-06 23:45:44 +00:00
if ( item )
2017-07-08 09:16:01 +00:00
return [ item torrents ] [ index ] ;
2008-02-06 23:45:44 +00:00
else
2017-07-08 09:16:01 +00:00
return fDisplayedTorrents [ index ] ;
2008-02-06 23:45:44 +00:00
}
- ( BOOL ) outlineView : ( NSOutlineView * ) outlineView isItemExpandable : ( id ) item
{
return ! [ item isKindOfClass : [ Torrent class ] ] ;
2007-10-27 02:00:43 +00:00
}
2008-02-06 23:45:44 +00:00
- ( id ) outlineView : ( NSOutlineView * ) outlineView objectValueForTableColumn : ( NSTableColumn * ) tableColumn byItem : ( id ) item
{
2011-06-07 23:40:10 +00:00
if ( [ item isKindOfClass : [ Torrent class ] ] ) {
if ( tableColumn )
return nil ;
2008-06-05 02:46:39 +00:00
return [ item hashString ] ;
2011-06-07 23:40:10 +00:00
}
2008-06-05 02:46:39 +00:00
else
2008-02-06 23:45:44 +00:00
{
2008-02-18 19:42:46 +00:00
NSString * ident = [ tableColumn identifier ] ;
if ( [ ident isEqualToString : @ "Group" ] )
{
2008-11-02 13:52:45 +00:00
NSInteger group = [ item groupIndex ] ;
2008-03-23 00:56:43 +00:00
return group ! = -1 ? [ [ GroupsController groups ] nameForIndex : group ]
2012-09-09 12:58:53 +00:00
: NSLocalizedString ( @ "No Group" , "Group table row" ) ;
2008-02-18 19:42:46 +00:00
}
2008-02-19 01:58:36 +00:00
else if ( [ ident isEqualToString : @ "Color" ] )
2008-02-19 05:39:56 +00:00
{
2008-11-02 13:52:45 +00:00
NSInteger group = [ item groupIndex ] ;
2008-06-05 02:46:39 +00:00
return [ [ GroupsController groups ] imageForIndex : group ] ;
2008-02-19 05:39:56 +00:00
}
2008-02-18 19:42:46 +00:00
else if ( [ ident isEqualToString : @ "DL Image" ] )
2012-06-10 02:35:58 +00:00
return [ NSImage imageNamed : @ "DownArrowGroupTemplate" ] ;
2008-02-28 02:17:17 +00:00
else if ( [ ident isEqualToString : @ "UL Image" ] )
return [ NSImage imageNamed : [ fDefaults boolForKey : @ "DisplayGroupRowRatio" ]
2012-09-09 12:58:53 +00:00
? @ "YingYangGroupTemplate" : @ "UpArrowGroupTemplate" ] ;
2008-02-18 19:42:46 +00:00
else
{
2008-10-16 03:44:54 +00:00
TorrentGroup * group = ( TorrentGroup * ) item ;
2017-01-24 17:53:16 +00:00
2008-02-28 02:17:17 +00:00
if ( [ fDefaults boolForKey : @ "DisplayGroupRowRatio" ] )
2008-10-16 03:44:54 +00:00
return [ NSString stringForRatio : [ group ratio ] ] ;
2008-02-28 02:17:17 +00:00
else
{
2008-11-02 13:52:45 +00:00
CGFloat rate = [ ident isEqualToString : @ "UL" ] ? [ group uploadRate ] : [ group downloadRate ] ;
2008-02-28 02:17:17 +00:00
return [ NSString stringForSpeed : rate ] ;
}
2008-02-18 19:42:46 +00:00
}
2008-02-06 23:45:44 +00:00
}
}
2008-02-07 11:57:24 +00:00
- ( BOOL ) outlineView : ( NSOutlineView * ) outlineView writeItems : ( NSArray * ) items toPasteboard : ( NSPasteboard * ) pasteboard
2007-09-16 01:02:06 +00:00
{
2007-11-09 23:38:35 +00:00
// only allow reordering of rows if sorting by order
2008-12-26 05:57:51 +00:00
if ( [ fDefaults boolForKey : @ "SortByGroup" ] || [ [ fDefaults stringForKey : @ "Sort" ] isEqualToString : SORT_ORDER ] )
2007-09-16 01:02:06 +00:00
{
2008-02-07 11:57:24 +00:00
NSMutableIndexSet * indexSet = [ NSMutableIndexSet indexSet ] ;
2008-12-26 07:06:02 +00:00
for ( id torrent in items )
2008-05-11 21:38:40 +00:00
{
if ( ! [ torrent isKindOfClass : [ Torrent class ] ] )
return NO ;
2017-01-24 17:53:16 +00:00
2008-02-07 11:57:24 +00:00
[ indexSet addIndex : [ fTableView rowForItem : torrent ] ] ;
2008-05-11 21:38:40 +00:00
}
2017-01-24 17:53:16 +00:00
2017-07-08 08:23:05 +00:00
[ pasteboard declareTypes : @ [ TORRENT_TABLE _VIEW _DATA _TYPE ] owner : self ] ;
2008-02-07 11:57:24 +00:00
[ pasteboard setData : [ NSKeyedArchiver archivedDataWithRootObject : indexSet ] forType : TORRENT_TABLE _VIEW _DATA _TYPE ] ;
2007-09-16 01:02:06 +00:00
return YES ;
}
return NO ;
}
2012-01-02 23:55:10 +00:00
- ( NSDragOperation ) outlineView : ( NSOutlineView * ) outlineView validateDrop : ( id < NSDraggingInfo > ) info proposedItem : ( id ) item
2012-09-09 12:58:53 +00:00
proposedChildIndex : ( NSInteger ) index
2007-09-16 01:02:06 +00:00
{
2012-01-02 23:55:10 +00:00
NSPasteboard * pasteboard = [ info draggingPasteboard ] ;
if ( [ [ pasteboard types ] containsObject : TORRENT_TABLE _VIEW _DATA _TYPE ] )
2007-09-16 01:02:06 +00:00
{
2008-05-11 21:38:40 +00:00
if ( [ fDefaults boolForKey : @ "SortByGroup" ] )
{
if ( ! item )
return NSDragOperationNone ;
2017-01-24 17:53:16 +00:00
2008-05-12 22:38:50 +00:00
if ( [ [ fDefaults stringForKey : @ "Sort" ] isEqualToString : SORT_ORDER ] )
2008-05-11 21:38:40 +00:00
{
2008-05-12 22:38:50 +00:00
if ( [ item isKindOfClass : [ Torrent class ] ] )
{
2008-07-01 01:28:19 +00:00
TorrentGroup * group = [ fTableView parentForItem : item ] ;
index = [ [ group torrents ] indexOfObject : item ] + 1 ;
2008-05-12 22:38:50 +00:00
item = group ;
}
2008-05-11 21:38:40 +00:00
}
2008-05-12 21:57:37 +00:00
else
{
2008-05-12 22:38:50 +00:00
if ( [ item isKindOfClass : [ Torrent class ] ] )
item = [ fTableView parentForItem : item ] ;
index = NSOutlineViewDropOnItemIndex ;
2008-05-12 21:57:37 +00:00
}
2008-05-11 21:38:40 +00:00
}
else
{
2012-01-07 16:01:28 +00:00
if ( index = = NSOutlineViewDropOnItemIndex )
return NSDragOperationNone ;
2017-01-24 17:53:16 +00:00
2008-05-11 21:38:40 +00:00
if ( item )
{
index = [ fTableView rowForItem : item ] + 1 ;
item = nil ;
}
}
2017-01-24 17:53:16 +00:00
2008-05-11 21:38:40 +00:00
[ fTableView setDropItem : item dropChildIndex : index ] ;
2007-09-16 01:02:06 +00:00
return NSDragOperationGeneric ;
}
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
return NSDragOperationNone ;
}
2012-01-07 15:46:42 +00:00
- ( BOOL ) outlineView : ( NSOutlineView * ) outlineView acceptDrop : ( id < NSDraggingInfo > ) info item : ( id ) item childIndex : ( NSInteger ) newRow
2007-09-16 01:02:06 +00:00
{
2012-01-02 23:55:10 +00:00
NSPasteboard * pasteboard = [ info draggingPasteboard ] ;
if ( [ [ pasteboard types ] containsObject : TORRENT_TABLE _VIEW _DATA _TYPE ] )
2007-09-16 01:02:06 +00:00
{
2012-01-02 23:55:10 +00:00
NSIndexSet * indexes = [ NSKeyedUnarchiver unarchiveObjectWithData : [ pasteboard dataForType : TORRENT_TABLE _VIEW _DATA _TYPE ] ] ;
2017-01-24 17:53:16 +00:00
2012-01-02 23:55:10 +00:00
// get the torrents to move
NSMutableArray * movingTorrents = [ NSMutableArray arrayWithCapacity : [ indexes count ] ] ;
for ( NSUInteger i = [ indexes firstIndex ] ; i ! = NSNotFound ; i = [ indexes indexGreaterThanIndex : i ] )
2008-05-11 21:38:40 +00:00
{
2012-01-07 21:05:02 +00:00
Torrent * torrent = [ fTableView itemAtRow : i ] ;
[ movingTorrents addObject : torrent ] ;
2017-07-04 19:59:55 +00:00
}
2017-01-24 17:53:16 +00:00
2017-07-04 19:59:55 +00:00
// change groups
if ( item )
{
const NSInteger groupIndex = [ item groupIndex ] ;
for ( Torrent * torrent in movingTorrents )
[ torrent setGroupValue : groupIndex determinationType : TorrentDeterminationUserSpecified ] ;
2008-05-12 21:38:24 +00:00
}
2017-01-24 17:53:16 +00:00
2008-05-12 21:57:37 +00:00
// reorder queue order
2008-05-14 18:09:51 +00:00
if ( newRow ! = NSOutlineViewDropOnItemIndex )
2008-05-12 21:57:37 +00:00
{
// find torrent to place under
2008-07-01 01:28:19 +00:00
NSArray * groupTorrents = item ? [ item torrents ] : fDisplayedTorrents ;
2008-05-12 21:57:37 +00:00
Torrent * topTorrent = nil ;
2008-11-02 13:52:45 +00:00
for ( NSInteger i = newRow -1 ; i >= 0 ; i - - )
2008-05-12 21:57:37 +00:00
{
2017-07-08 09:16:01 +00:00
Torrent * tempTorrent = groupTorrents [ i ] ;
2008-05-12 21:57:37 +00:00
if ( ! [ movingTorrents containsObject : tempTorrent ] )
{
topTorrent = tempTorrent ;
break ;
}
}
2017-01-24 17:53:16 +00:00
2008-05-12 21:57:37 +00:00
// remove objects to reinsert
[ fTorrents removeObjectsInArray : movingTorrents ] ;
2017-01-24 17:53:16 +00:00
2008-05-12 21:57:37 +00:00
// insert objects at new location
2012-01-07 21:05:02 +00:00
const NSUInteger insertIndex = topTorrent ? [ fTorrents indexOfObject : topTorrent ] + 1 : 0 ;
2008-07-07 02:35:20 +00:00
NSIndexSet * insertIndexes = [ NSIndexSet indexSetWithIndexesInRange : NSMakeRange ( insertIndex , [ movingTorrents count ] ) ] ;
[ fTorrents insertObjects : movingTorrents atIndexes : insertIndexes ] ;
2017-01-24 17:53:16 +00:00
2012-01-07 15:46:42 +00:00
// we need to make sure the queue order is updated in the Torrent object before we sort - safest to just reset all queue positions
NSUInteger i = 0 ;
for ( Torrent * torrent in fTorrents )
{
[ torrent setQueuePosition : i + + ] ;
[ torrent update ] ;
}
2017-01-24 17:53:16 +00:00
2012-01-07 21:05:02 +00:00
// do the drag animation here so that the dragged torrents are the ones that are animated as moving , and not the torrents around them
2016-01-06 11:05:37 +00:00
[ fTableView beginUpdates ] ;
2017-01-24 17:53:16 +00:00
2012-01-07 21:05:02 +00:00
NSUInteger insertDisplayIndex = topTorrent ? [ groupTorrents indexOfObject : topTorrent ] + 1 : 0 ;
2017-01-24 17:53:16 +00:00
2012-01-07 21:05:02 +00:00
for ( Torrent * torrent in movingTorrents )
{
TorrentGroup * oldParent = item ? [ fTableView parentForItem : torrent ] : nil ;
NSMutableArray * oldTorrents = oldParent ? [ oldParent torrents ] : fDisplayedTorrents ;
const NSUInteger oldIndex = [ oldTorrents indexOfObject : torrent ] ;
2017-01-24 17:53:16 +00:00
2012-01-07 21:05:02 +00:00
if ( item = = oldParent )
{
if ( oldIndex < insertDisplayIndex )
- - insertDisplayIndex ;
[ oldTorrents moveObjectAtIndex : oldIndex toIndex : insertDisplayIndex ] ;
}
else
{
2012-01-07 22:06:23 +00:00
NSAssert ( item && oldParent , @ "Expected to be dragging between group rows" ) ;
2017-01-24 17:53:16 +00:00
2012-01-07 21:05:02 +00:00
NSMutableArray * newTorrents = [ ( TorrentGroup * ) item torrents ] ;
[ newTorrents insertObject : torrent atIndex : insertDisplayIndex ] ;
[ oldTorrents removeObjectAtIndex : oldIndex ] ;
}
2016-01-06 11:05:37 +00:00
[ fTableView moveItemAtIndex : oldIndex inParent : oldParent toIndex : insertDisplayIndex inParent : item ] ;
2017-01-24 17:53:16 +00:00
2012-01-07 21:05:02 +00:00
+ + insertDisplayIndex ;
}
2016-01-06 11:05:37 +00:00
[ fTableView endUpdates ] ;
2008-05-12 21:57:37 +00:00
}
2017-01-24 17:53:16 +00:00
2011-02-20 03:58:50 +00:00
[ self applyFilter ] ;
2007-09-16 01:02:06 +00:00
}
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
return YES ;
}
- ( void ) torrentTableViewSelectionDidChange : ( NSNotification * ) notification
{
2008-06-26 03:35:20 +00:00
[ self resetInfo ] ;
2010-11-13 19:10:31 +00:00
[ [ fWindow toolbar ] validateVisibleItems ] ;
2007-09-16 01:02:06 +00:00
}
- ( NSDragOperation ) draggingEntered : ( id < NSDraggingInfo > ) info
{
NSPasteboard * pasteboard = [ info draggingPasteboard ] ;
if ( [ [ pasteboard types ] containsObject : NSFilenamesPboardType ] )
{
// check if any torrent files can be added
BOOL torrent = NO ;
2008-12-26 07:06:02 +00:00
NSArray * files = [ pasteboard propertyListForType : NSFilenamesPboardType ] ;
for ( NSString * file in files )
2007-09-16 01:02:06 +00:00
{
2009-06-10 22:56:24 +00:00
if ( [ [ [ NSWorkspace sharedWorkspace ] typeOfFile : file error : NULL ] isEqualToString : @ "org.bittorrent.torrent" ]
2012-09-09 12:58:53 +00:00
|| [ [ file pathExtension ] caseInsensitiveCompare : @ "torrent" ] = = NSOrderedSame )
2007-09-16 01:02:06 +00:00
{
2009-05-25 21:07:12 +00:00
torrent = YES ;
2008-12-26 07:06:02 +00:00
tr_ctor * ctor = tr_ctorNew ( fLib ) ;
2020-04-25 14:35:15 +00:00
tr_ctorSetMetainfoFromFile ( ctor , [ file UTF8String ] ) ;
2009-08-05 02:13:45 +00:00
if ( tr_torrentParse ( ctor , NULL ) = = TR_PARSE _OK )
2007-11-13 00:56:58 +00:00
{
2009-05-25 21:07:12 +00:00
if ( ! fOverlayWindow )
fOverlayWindow = [ [ DragOverlayWindow alloc ] initWithLib : fLib forWindow : fWindow ] ;
[ fOverlayWindow setTorrents : files ] ;
2017-01-24 17:53:16 +00:00
2009-05-25 21:07:12 +00:00
return NSDragOperationCopy ;
2007-11-13 00:56:58 +00:00
}
2007-12-22 03:31:22 +00:00
tr_ctorFree ( ctor ) ;
2007-09-16 01:02:06 +00:00
}
}
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
// create a torrent file if a single file
if ( ! torrent && [ files count ] = = 1 )
{
if ( ! fOverlayWindow )
fOverlayWindow = [ [ DragOverlayWindow alloc ] initWithLib : fLib forWindow : fWindow ] ;
2017-07-08 09:16:01 +00:00
[ fOverlayWindow setFile : [ files [ 0 ] lastPathComponent ] ] ;
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
return NSDragOperationCopy ;
}
}
else if ( [ [ pasteboard types ] containsObject : NSURLPboardType ] )
{
if ( ! fOverlayWindow )
fOverlayWindow = [ [ DragOverlayWindow alloc ] initWithLib : fLib forWindow : fWindow ] ;
[ fOverlayWindow setURL : [ [ NSURL URLFromPasteboard : pasteboard ] relativeString ] ] ;
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
return NSDragOperationCopy ;
}
else ;
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
return NSDragOperationNone ;
}
- ( void ) draggingExited : ( id < NSDraggingInfo > ) info
{
if ( fOverlayWindow )
[ fOverlayWindow fadeOut ] ;
}
- ( BOOL ) performDragOperation : ( id < NSDraggingInfo > ) info
{
if ( fOverlayWindow )
[ fOverlayWindow fadeOut ] ;
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
NSPasteboard * pasteboard = [ info draggingPasteboard ] ;
if ( [ [ pasteboard types ] containsObject : NSFilenamesPboardType ] )
{
BOOL torrent = NO , accept = YES ;
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
// create an array of files that can be opened
NSArray * files = [ pasteboard propertyListForType : NSFilenamesPboardType ] ;
2009-05-25 21:07:12 +00:00
NSMutableArray * filesToOpen = [ NSMutableArray arrayWithCapacity : [ files count ] ] ;
2008-12-26 07:06:02 +00:00
for ( NSString * file in files )
2007-09-16 01:02:06 +00:00
{
2009-06-10 22:56:24 +00:00
if ( [ [ [ NSWorkspace sharedWorkspace ] typeOfFile : file error : NULL ] isEqualToString : @ "org.bittorrent.torrent" ]
2012-09-09 12:58:53 +00:00
|| [ [ file pathExtension ] caseInsensitiveCompare : @ "torrent" ] = = NSOrderedSame )
2007-09-16 01:02:06 +00:00
{
2009-05-25 21:07:12 +00:00
torrent = YES ;
2008-12-26 07:06:02 +00:00
tr_ctor * ctor = tr_ctorNew ( fLib ) ;
2020-04-25 14:35:15 +00:00
tr_ctorSetMetainfoFromFile ( ctor , [ file UTF8String ] ) ;
2009-08-05 02:13:45 +00:00
if ( tr_torrentParse ( ctor , NULL ) = = TR_PARSE _OK )
2009-05-25 21:07:12 +00:00
[ filesToOpen addObject : file ] ;
2007-12-22 03:31:22 +00:00
tr_ctorFree ( ctor ) ;
2007-09-16 01:02:06 +00:00
}
}
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
if ( [ filesToOpen count ] > 0 )
[ self application : NSApp openFiles : filesToOpen ] ;
else
{
if ( ! torrent && [ files count ] = = 1 )
2017-07-08 09:16:01 +00:00
[ CreatorWindowController createTorrentFile : fLib forFile : [ NSURL fileURLWithPath : files [ 0 ] ] ] ;
2007-09-16 01:02:06 +00:00
else
accept = NO ;
}
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
return accept ;
}
else if ( [ [ pasteboard types ] containsObject : NSURLPboardType ] )
{
NSURL * url ;
if ( ( url = [ NSURL URLFromPasteboard : pasteboard ] ) )
{
2009-11-27 16:31:05 +00:00
[ self openURL : [ url absoluteString ] ] ;
2007-09-16 01:02:06 +00:00
return YES ;
}
}
else ;
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
return NO ;
}
- ( void ) toggleSmallView : ( id ) sender
{
2007-10-29 18:59:23 +00:00
BOOL makeSmall = ! [ fDefaults boolForKey : @ "SmallView" ] ;
2007-10-30 19:55:47 +00:00
[ fDefaults setBool : makeSmall forKey : @ "SmallView" ] ;
2017-01-24 17:53:16 +00:00
2011-06-13 23:02:38 +00:00
[ fTableView setUsesAlternatingRowBackgroundColors : ! makeSmall ] ;
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
[ fTableView setRowHeight : makeSmall ? ROW_HEIGHT _SMALL : ROW_HEIGHT _REGULAR ] ;
2016-01-06 11:05:37 +00:00
[ fTableView beginUpdates ] ;
2008-02-06 23:45:44 +00:00
[ fTableView noteHeightOfRowsWithIndexesChanged : [ NSIndexSet indexSetWithIndexesInRange : NSMakeRange ( 0 , [ fTableView numberOfRows ] ) ] ] ;
2016-01-06 11:05:37 +00:00
[ fTableView endUpdates ] ;
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
// resize for larger min height if not set to auto size
if ( ! [ fDefaults boolForKey : @ "AutoSize" ] )
{
2011-07-18 00:48:00 +00:00
const NSSize contentSize = [ [ fWindow contentView ] frame ] . size ;
2017-01-24 17:53:16 +00:00
2011-07-18 00:48:00 +00:00
NSSize contentMinSize = [ fWindow contentMinSize ] ;
contentMinSize . height = [ self minWindowContentSizeAllowed ] ;
[ fWindow setContentMinSize : contentMinSize ] ;
2017-01-24 17:53:16 +00:00
2011-07-18 00:48:00 +00:00
// make sure the window already isn ' t too small
2007-09-16 01:02:06 +00:00
if ( ! makeSmall && contentSize . height < contentMinSize . height )
{
NSRect frame = [ fWindow frame ] ;
2008-11-02 13:52:45 +00:00
CGFloat heightChange = contentMinSize . height - contentSize . height ;
2007-09-16 01:02:06 +00:00
frame . size . height + = heightChange ;
frame . origin . y - = heightChange ;
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
[ fWindow setFrame : frame display : YES ] ;
}
}
else
[ self setWindowSizeToFit ] ;
}
2007-11-04 15:01:34 +00:00
- ( void ) togglePiecesBar : ( id ) sender
{
[ fDefaults setBool : ! [ fDefaults boolForKey : @ "PiecesBar" ] forKey : @ "PiecesBar" ] ;
2008-01-16 19:30:12 +00:00
[ fTableView togglePiecesBar ] ;
2007-11-04 15:01:34 +00:00
}
2007-11-11 16:59:32 +00:00
- ( void ) toggleAvailabilityBar : ( id ) sender
{
[ fDefaults setBool : ! [ fDefaults boolForKey : @ "DisplayProgressBarAvailable" ] forKey : @ "DisplayProgressBarAvailable" ] ;
[ fTableView display ] ;
}
2008-11-02 13:52:45 +00:00
- ( NSRect ) windowFrameByAddingHeight : ( CGFloat ) height checkLimits : ( BOOL ) check
2007-09-16 01:02:06 +00:00
{
2008-02-06 23:45:44 +00:00
NSScrollView * scrollView = [ fTableView enclosingScrollView ] ;
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
// convert pixels to points
NSRect windowFrame = [ fWindow frame ] ;
2008-02-06 23:45:44 +00:00
NSSize windowSize = [ scrollView convertSize : windowFrame . size fromView : nil ] ;
2007-09-16 01:02:06 +00:00
windowSize . height + = height ;
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
if ( check )
{
2011-07-18 00:48:00 +00:00
// we can ' t call minSize , since it might be set to the current size ( auto size )
const CGFloat minHeight = [ self minWindowContentSizeAllowed ]
2012-09-09 12:58:53 +00:00
+ ( NSHeight ( [ fWindow frame ] ) - NSHeight ( [ [ fWindow contentView ] frame ] ) ) ; // contentView to window
2017-01-24 17:53:16 +00:00
2012-04-28 23:44:38 +00:00
if ( windowSize . height <= minHeight )
2012-02-29 02:45:42 +00:00
windowSize . height = minHeight ;
2007-09-16 01:02:06 +00:00
else
{
2012-04-28 23:44:38 +00:00
NSScreen * screen = [ fWindow screen ] ;
if ( screen )
{
NSSize maxSize = [ scrollView convertSize : [ screen visibleFrame ] . size fromView : nil ] ;
if ( ! fStatusBar )
maxSize . height - = STATUS_BAR _HEIGHT ;
if ( ! fFilterBar )
maxSize . height - = FILTER_BAR _HEIGHT ;
if ( windowSize . height > maxSize . height )
windowSize . height = maxSize . height ;
}
2007-09-16 01:02:06 +00:00
}
}
2012-09-09 12:58:53 +00:00
2007-09-16 01:02:06 +00:00
// convert points to pixels
2008-02-06 23:45:44 +00:00
windowSize = [ scrollView convertSize : windowSize toView : nil ] ;
2012-09-09 12:58:53 +00:00
2007-09-16 01:02:06 +00:00
windowFrame . origin . y - = ( windowSize . height - windowFrame . size . height ) ;
windowFrame . size . height = windowSize . height ;
return windowFrame ;
}
2008-03-16 14:24:27 +00:00
- ( void ) toggleStatusBar : ( id ) sender
{
2011-02-20 00:22:55 +00:00
const BOOL show = fStatusBar = = nil ;
[ self showStatusBar : show animate : YES ] ;
[ fDefaults setBool : show forKey : @ "StatusBar" ] ;
2008-03-16 14:24:27 +00:00
}
// doesn ' t save shown state
2007-09-16 01:02:06 +00:00
- ( void ) showStatusBar : ( BOOL ) show animate : ( BOOL ) animate
{
2011-02-20 00:22:55 +00:00
const BOOL prevShown = fStatusBar ! = nil ;
if ( show = = prevShown )
2007-09-16 01:02:06 +00:00
return ;
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
if ( show )
2011-02-20 00:22:55 +00:00
{
fStatusBar = [ [ StatusBarController alloc ] initWithLib : fLib ] ;
2017-01-24 17:53:16 +00:00
2011-02-20 00:22:55 +00:00
NSView * contentView = [ fWindow contentView ] ;
const NSSize windowSize = [ contentView convertSize : [ fWindow frame ] . size fromView : nil ] ;
2017-01-24 17:53:16 +00:00
2011-02-20 00:22:55 +00:00
NSRect statusBarFrame = [ [ fStatusBar view ] frame ] ;
statusBarFrame . size . width = windowSize . width ;
[ [ fStatusBar view ] setFrame : statusBarFrame ] ;
2017-01-24 17:53:16 +00:00
2011-02-20 00:22:55 +00:00
[ contentView addSubview : [ fStatusBar view ] ] ;
2011-02-20 03:58:50 +00:00
[ [ fStatusBar view ] setFrameOrigin : NSMakePoint ( 0.0 , NSMaxY ( [ contentView frame ] ) ) ] ;
2011-02-20 00:22:55 +00:00
}
2017-01-24 17:53:16 +00:00
2011-02-20 00:22:55 +00:00
CGFloat heightChange = [ [ fStatusBar view ] frame ] . size . height ;
2007-09-16 01:02:06 +00:00
if ( ! show )
heightChange * = -1 ;
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
// allow bar to show even if not enough room
if ( show && ! [ fDefaults boolForKey : @ "AutoSize" ] )
{
2012-04-28 23:44:38 +00:00
NSRect frame = [ self windowFrameByAddingHeight : heightChange checkLimits : NO ] ;
2017-01-24 17:53:16 +00:00
2012-04-28 23:44:38 +00:00
NSScreen * screen = [ fWindow screen ] ;
if ( screen )
2007-09-16 01:02:06 +00:00
{
2012-04-28 23:44:38 +00:00
CGFloat change = [ screen visibleFrame ] . size . height - frame . size . height ;
if ( change < 0.0 )
{
frame = [ fWindow frame ] ;
frame . size . height + = change ;
frame . origin . y - = change ;
[ fWindow setFrame : frame display : NO animate : NO ] ;
}
2007-09-16 01:02:06 +00:00
}
}
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
[ self updateUI ] ;
2017-01-24 17:53:16 +00:00
2008-02-06 23:45:44 +00:00
NSScrollView * scrollView = [ fTableView enclosingScrollView ] ;
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
// set views to not autoresize
2011-02-20 00:22:55 +00:00
const NSUInteger statsMask = [ [ fStatusBar view ] autoresizingMask ] ;
[ [ fStatusBar view ] setAutoresizingMask : NSViewNotSizable ] ;
2011-02-20 03:58:50 +00:00
NSUInteger filterMask ;
if ( fFilterBar )
{
filterMask = [ [ fFilterBar view ] autoresizingMask ] ;
[ [ fFilterBar view ] setAutoresizingMask : NSViewNotSizable ] ;
}
2011-02-20 00:22:55 +00:00
const NSUInteger scrollMask = [ scrollView autoresizingMask ] ;
2008-02-06 23:45:44 +00:00
[ scrollView setAutoresizingMask : NSViewNotSizable ] ;
2017-01-24 17:53:16 +00:00
2012-04-28 23:44:38 +00:00
NSRect frame = [ self windowFrameByAddingHeight : heightChange checkLimits : NO ] ;
2017-01-24 17:53:16 +00:00
[ fWindow setFrame : frame display : YES animate : animate ] ;
2007-09-16 01:02:06 +00:00
// re - enable autoresize
2011-02-20 00:22:55 +00:00
[ [ fStatusBar view ] setAutoresizingMask : statsMask ] ;
2011-02-20 03:58:50 +00:00
if ( fFilterBar )
[ [ fFilterBar view ] setAutoresizingMask : filterMask ] ;
2008-02-06 23:45:44 +00:00
[ scrollView setAutoresizingMask : scrollMask ] ;
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
if ( ! show )
2011-02-20 00:22:55 +00:00
{
2011-06-13 23:02:38 +00:00
[ [ fStatusBar view ] removeFromSuperviewWithoutNeedingDisplay ] ;
2011-02-20 00:22:55 +00:00
fStatusBar = nil ;
}
2017-01-24 17:53:16 +00:00
2011-07-18 00:48:00 +00:00
if ( [ fDefaults boolForKey : @ "AutoSize" ] )
[ self setWindowMinMaxToCurrent ] ;
else
{
// change min size
NSSize minSize = [ fWindow contentMinSize ] ;
minSize . height + = heightChange ;
[ fWindow setContentMinSize : minSize ] ;
}
2007-09-16 01:02:06 +00:00
}
- ( void ) toggleFilterBar : ( id ) sender
{
2011-02-20 03:58:50 +00:00
const BOOL show = fFilterBar = = nil ;
2017-01-24 17:53:16 +00:00
2013-09-21 16:24:40 +00:00
// disable filtering when hiding ( have to do before showFilterBar : animate : )
if ( ! show )
[ fFilterBar reset : NO ] ;
2017-01-24 17:53:16 +00:00
2011-02-20 03:58:50 +00:00
[ self showFilterBar : show animate : YES ] ;
[ fDefaults setBool : show forKey : @ "FilterBar" ] ;
[ [ fWindow toolbar ] validateVisibleItems ] ;
2017-01-24 17:53:16 +00:00
2011-02-20 04:23:09 +00:00
[ self applyFilter ] ; // do even if showing to ensure tooltips are updated
2007-09-16 01:02:06 +00:00
}
2008-03-16 14:24:27 +00:00
// doesn ' t save shown state
2007-09-16 01:02:06 +00:00
- ( void ) showFilterBar : ( BOOL ) show animate : ( BOOL ) animate
{
2011-02-20 03:58:50 +00:00
const BOOL prevShown = fFilterBar ! = nil ;
if ( show = = prevShown )
2007-09-16 01:02:06 +00:00
return ;
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
if ( show )
2011-02-20 03:58:50 +00:00
{
fFilterBar = [ [ FilterBarController alloc ] init ] ;
2017-01-24 17:53:16 +00:00
2011-02-20 03:58:50 +00:00
NSView * contentView = [ fWindow contentView ] ;
const NSSize windowSize = [ contentView convertSize : [ fWindow frame ] . size fromView : nil ] ;
2017-01-24 17:53:16 +00:00
2011-02-20 03:58:50 +00:00
NSRect filterBarFrame = [ [ fFilterBar view ] frame ] ;
filterBarFrame . size . width = windowSize . width ;
[ [ fFilterBar view ] setFrame : filterBarFrame ] ;
2017-01-24 17:53:16 +00:00
2011-02-20 03:58:50 +00:00
if ( fStatusBar )
[ contentView addSubview : [ fFilterBar view ] positioned : NSWindowBelow relativeTo : [ fStatusBar view ] ] ;
else
[ contentView addSubview : [ fFilterBar view ] ] ;
const CGFloat originY = fStatusBar ? NSMinY ( [ [ fStatusBar view ] frame ] ) : NSMaxY ( [ contentView frame ] ) ;
[ [ fFilterBar view ] setFrameOrigin : NSMakePoint ( 0.0 , originY ) ] ;
}
2011-06-07 23:40:10 +00:00
else
[ fWindow makeFirstResponder : fTableView ] ;
2017-01-24 17:53:16 +00:00
2011-02-20 03:58:50 +00:00
CGFloat heightChange = NSHeight ( [ [ fFilterBar view ] frame ] ) ;
2007-09-16 01:02:06 +00:00
if ( ! show )
heightChange * = -1 ;
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
// allow bar to show even if not enough room
if ( show && ! [ fDefaults boolForKey : @ "AutoSize" ] )
{
2011-02-20 03:58:50 +00:00
NSRect frame = [ self windowFrameByAddingHeight : heightChange checkLimits : NO ] ;
2017-01-24 17:53:16 +00:00
2012-04-28 23:44:38 +00:00
NSScreen * screen = [ fWindow screen ] ;
if ( screen )
2007-09-16 01:02:06 +00:00
{
2012-04-28 23:44:38 +00:00
CGFloat change = [ screen visibleFrame ] . size . height - frame . size . height ;
if ( change < 0.0 )
{
frame = [ fWindow frame ] ;
frame . size . height + = change ;
frame . origin . y - = change ;
[ fWindow setFrame : frame display : NO animate : NO ] ;
}
2007-09-16 01:02:06 +00:00
}
}
2017-01-24 17:53:16 +00:00
2008-02-06 23:45:44 +00:00
NSScrollView * scrollView = [ fTableView enclosingScrollView ] ;
2012-09-09 12:58:53 +00:00
2007-09-16 01:02:06 +00:00
// set views to not autoresize
2011-02-20 03:58:50 +00:00
const NSUInteger filterMask = [ [ fFilterBar view ] autoresizingMask ] ;
const NSUInteger scrollMask = [ scrollView autoresizingMask ] ;
[ [ fFilterBar view ] setAutoresizingMask : NSViewNotSizable ] ;
2008-02-06 23:45:44 +00:00
[ scrollView setAutoresizingMask : NSViewNotSizable ] ;
2017-01-24 17:53:16 +00:00
2011-02-20 03:58:50 +00:00
const NSRect frame = [ self windowFrameByAddingHeight : heightChange checkLimits : NO ] ;
2007-09-16 01:02:06 +00:00
[ fWindow setFrame : frame display : YES animate : animate ] ;
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
// re - enable autoresize
2011-02-20 03:58:50 +00:00
[ [ fFilterBar view ] setAutoresizingMask : filterMask ] ;
2008-02-06 23:45:44 +00:00
[ scrollView setAutoresizingMask : scrollMask ] ;
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
if ( ! show )
{
2011-06-13 23:02:38 +00:00
[ [ fFilterBar view ] removeFromSuperviewWithoutNeedingDisplay ] ;
2011-02-20 03:58:50 +00:00
fFilterBar = nil ;
2007-09-16 01:02:06 +00:00
}
2017-01-24 17:53:16 +00:00
2011-07-18 00:48:00 +00:00
if ( [ fDefaults boolForKey : @ "AutoSize" ] )
[ self setWindowMinMaxToCurrent ] ;
else
{
// change min size
NSSize minSize = [ fWindow contentMinSize ] ;
minSize . height + = heightChange ;
[ fWindow setContentMinSize : minSize ] ;
}
2007-09-16 01:02:06 +00:00
}
2008-03-16 14:24:27 +00:00
- ( void ) focusFilterField
{
2011-02-20 04:34:46 +00:00
if ( ! fFilterBar )
[ self toggleFilterBar : self ] ;
[ fFilterBar focusSearchField ] ;
2008-03-16 14:24:27 +00:00
}
2011-10-06 00:30:40 +00:00
- ( BOOL ) acceptsPreviewPanelControl : ( QLPreviewPanel * ) panel
2009-10-11 23:16:46 +00:00
{
2009-10-12 00:48:16 +00:00
return ! fQuitting ;
2009-10-11 23:16:46 +00:00
}
2011-10-06 00:30:40 +00:00
- ( void ) beginPreviewPanelControl : ( QLPreviewPanel * ) panel
2009-10-11 23:16:46 +00:00
{
2017-07-29 16:14:22 +00:00
fPreviewPanel = panel ;
2009-10-11 23:16:46 +00:00
[ fPreviewPanel setDelegate : self ] ;
[ fPreviewPanel setDataSource : self ] ;
}
2011-10-06 00:30:40 +00:00
- ( void ) endPreviewPanelControl : ( QLPreviewPanel * ) panel
2009-10-11 23:16:46 +00:00
{
fPreviewPanel = nil ;
}
2009-10-11 23:27:53 +00:00
- ( NSArray * ) quickLookableTorrents
{
NSArray * selectedTorrents = [ fTableView selectedTorrents ] ;
NSMutableArray * qlArray = [ NSMutableArray arrayWithCapacity : [ selectedTorrents count ] ] ;
2017-01-24 17:53:16 +00:00
2009-10-11 23:27:53 +00:00
for ( Torrent * torrent in selectedTorrents )
2009-10-21 13:01:14 +00:00
if ( ( [ torrent isFolder ] || [ torrent isComplete ] ) && [ torrent dataLocation ] )
2009-10-11 23:27:53 +00:00
[ qlArray addObject : torrent ] ;
2017-01-24 17:53:16 +00:00
2009-10-11 23:27:53 +00:00
return qlArray ;
}
2011-10-06 00:30:40 +00:00
- ( NSInteger ) numberOfPreviewItemsInPreviewPanel : ( QLPreviewPanel * ) panel
2009-10-11 23:16:46 +00:00
{
if ( [ fInfoController canQuickLook ] )
return [ [ fInfoController quickLookURLs ] count ] ;
2009-10-11 23:27:53 +00:00
else
2009-10-11 23:50:13 +00:00
return [ [ self quickLookableTorrents ] count ] ;
2009-10-11 23:16:46 +00:00
}
2011-10-06 00:30:40 +00:00
- ( id < QLPreviewItem > ) previewPanel : ( QLPreviewPanel * ) panel previewItemAtIndex : ( NSInteger ) index
2009-10-11 23:16:46 +00:00
{
if ( [ fInfoController canQuickLook ] )
2017-07-08 09:16:01 +00:00
return [ fInfoController quickLookURLs ] [ index ] ;
2009-10-11 23:16:46 +00:00
else
2017-07-08 09:16:01 +00:00
return [ self quickLookableTorrents ] [ index ] ;
2009-10-11 23:16:46 +00:00
}
2011-10-06 00:30:40 +00:00
- ( BOOL ) previewPanel : ( QLPreviewPanel * ) panel handleEvent : ( NSEvent * ) event
2009-10-11 23:16:46 +00:00
{
/ * if ( [ event type ] = = NSKeyDown )
2012-09-09 12:58:53 +00:00
{
[ super keyDown : event ] ;
return YES ;
} * /
2017-01-24 17:53:16 +00:00
2009-10-11 23:16:46 +00:00
return NO ;
}
2011-10-06 00:30:40 +00:00
- ( NSRect ) previewPanel : ( QLPreviewPanel * ) panel sourceFrameOnScreenForPreviewItem : ( id < QLPreviewItem > ) item
2009-10-11 23:16:46 +00:00
{
if ( [ fInfoController canQuickLook ] )
return [ fInfoController quickLookSourceFrameForPreviewItem : item ] ;
else
{
2009-10-12 00:19:04 +00:00
if ( ! [ fWindow isVisible ] )
return NSZeroRect ;
2017-01-24 17:53:16 +00:00
2009-10-11 23:16:46 +00:00
const NSInteger row = [ fTableView rowForItem : item ] ;
if ( row = = -1 )
return NSZeroRect ;
2017-01-24 17:53:16 +00:00
2009-10-11 23:16:46 +00:00
NSRect frame = [ fTableView iconRectForRow : row ] ;
2017-01-24 17:53:16 +00:00
2009-10-12 03:15:37 +00:00
if ( ! NSIntersectsRect ( [ fTableView visibleRect ] , frame ) )
2009-10-15 23:18:39 +00:00
return NSZeroRect ;
2017-01-24 17:53:16 +00:00
2009-10-11 23:16:46 +00:00
frame . origin = [ fTableView convertPoint : frame . origin toView : nil ] ;
2016-01-08 10:05:19 +00:00
frame = [ fWindow convertRectToScreen : frame ] ;
2009-10-11 23:16:46 +00:00
frame . origin . y - = frame . size . height ;
return frame ;
}
}
2014-01-09 16:23:54 +00:00
- ( void ) showToolbarShare : ( id ) sender
{
NSParameterAssert ( [ sender isKindOfClass : [ NSButton class ] ] ) ;
2017-01-24 17:53:16 +00:00
2014-01-10 17:50:05 +00:00
NSSharingServicePicker * picker = [ [ NSSharingServicePicker alloc ] initWithItems : [ [ ShareTorrentFileHelper sharedHelper ] shareTorrentURLs ] ] ;
2014-01-09 16:23:54 +00:00
picker . delegate = self ;
2017-01-24 17:53:16 +00:00
2014-01-09 16:23:54 +00:00
[ picker showRelativeToRect : [ sender bounds ] ofView : sender preferredEdge : NSMinYEdge ] ;
}
- ( id < NSSharingServiceDelegate > ) sharingServicePicker : ( NSSharingServicePicker * ) sharingServicePicker delegateForSharingService : ( NSSharingService * ) sharingService
{
return self ;
}
- ( NSWindow * ) sharingService : ( NSSharingService * ) sharingService sourceWindowForShareItems : ( NSArray * ) items sharingContentScope : ( NSSharingContentScope * ) sharingContentScope
{
return fWindow ;
}
2007-12-06 20:54:26 +00:00
- ( ButtonToolbarItem * ) standardToolbarButtonWithIdentifier : ( NSString * ) ident
2007-09-16 01:02:06 +00:00
{
2014-01-09 16:23:54 +00:00
return [ self toolbarButtonWithIdentifier : ident forToolbarButtonClass : [ ButtonToolbarItem class ] ] ;
}
- ( id ) toolbarButtonWithIdentifier : ( NSString * ) ident forToolbarButtonClass : ( Class ) class
{
ButtonToolbarItem * item = [ [ class alloc ] initWithItemIdentifier : ident ] ;
2017-01-24 17:53:16 +00:00
2011-06-28 01:39:30 +00:00
NSButton * button = [ [ NSButton alloc ] init ] ;
2007-11-29 01:05:11 +00:00
[ button setBezelStyle : NSTexturedRoundedBezelStyle ] ;
[ button setStringValue : @ "" ] ;
2017-01-24 17:53:16 +00:00
2007-12-04 01:46:27 +00:00
[ item setView : button ] ;
2017-01-24 17:53:16 +00:00
2020-11-18 03:34:33 +00:00
if ( @ available ( macOS 11.0 , * ) ) {
// not needed
} else {
const NSSize buttonSize = NSMakeSize ( 36.0 , 25.0 ) ;
[ item setMinSize : buttonSize ] ;
[ item setMaxSize : buttonSize ] ;
}
2017-01-24 17:53:16 +00:00
2017-07-29 16:14:22 +00:00
return item ;
2007-12-06 20:54:26 +00:00
}
- ( NSToolbarItem * ) toolbar : ( NSToolbar * ) toolbar itemForItemIdentifier : ( NSString * ) ident willBeInsertedIntoToolbar : ( BOOL ) flag
{
2007-09-16 01:02:06 +00:00
if ( [ ident isEqualToString : TOOLBAR_CREATE ] )
{
2007-12-06 20:54:26 +00:00
ButtonToolbarItem * item = [ self standardToolbarButtonWithIdentifier : ident ] ;
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
[ item setLabel : NSLocalizedString ( @ "Create" , "Create toolbar item -> label" ) ] ;
[ item setPaletteLabel : NSLocalizedString ( @ "Create Torrent File" , "Create toolbar item -> palette label" ) ] ;
[ item setToolTip : NSLocalizedString ( @ "Create torrent file" , "Create toolbar item -> tooltip" ) ] ;
2020-11-21 13:27:07 +00:00
if ( @ available ( macOS 11.0 , * ) ) {
[ item setImage : [ NSImage imageWithSystemSymbolName : @ "doc.badge.plus" accessibilityDescription : nil ] ] ;
} else {
[ item setImage : [ NSImage imageNamed : @ "ToolbarCreateTemplate" ] ] ;
}
2007-09-16 01:02:06 +00:00
[ item setTarget : self ] ;
[ item setAction : @ selector ( createFile : ) ] ;
[ item setAutovalidates : NO ] ;
2017-01-24 17:53:16 +00:00
2007-12-06 20:54:26 +00:00
return item ;
2007-09-16 01:02:06 +00:00
}
2008-02-07 20:34:14 +00:00
else if ( [ ident isEqualToString : TOOLBAR_OPEN _FILE ] )
2007-09-16 01:02:06 +00:00
{
2007-12-06 20:54:26 +00:00
ButtonToolbarItem * item = [ self standardToolbarButtonWithIdentifier : ident ] ;
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
[ item setLabel : NSLocalizedString ( @ "Open" , "Open toolbar item -> label" ) ] ;
[ item setPaletteLabel : NSLocalizedString ( @ "Open Torrent Files" , "Open toolbar item -> palette label" ) ] ;
[ item setToolTip : NSLocalizedString ( @ "Open torrent files" , "Open toolbar item -> tooltip" ) ] ;
2020-11-21 13:27:07 +00:00
if ( @ available ( macOS 11.0 , * ) ) {
[ item setImage : [ NSImage imageWithSystemSymbolName : @ "folder" accessibilityDescription : nil ] ] ;
} else {
[ item setImage : [ NSImage imageNamed : @ "ToolbarOpenTemplate" ] ] ;
}
2007-09-16 01:02:06 +00:00
[ item setTarget : self ] ;
[ item setAction : @ selector ( openShowSheet : ) ] ;
[ item setAutovalidates : NO ] ;
2017-01-24 17:53:16 +00:00
2007-12-06 20:54:26 +00:00
return item ;
2007-09-16 01:02:06 +00:00
}
2008-02-07 20:34:14 +00:00
else if ( [ ident isEqualToString : TOOLBAR_OPEN _WEB ] )
{
ButtonToolbarItem * item = [ self standardToolbarButtonWithIdentifier : ident ] ;
2017-01-24 17:53:16 +00:00
2008-02-07 20:34:14 +00:00
[ item setLabel : NSLocalizedString ( @ "Open Address" , "Open address toolbar item -> label" ) ] ;
[ item setPaletteLabel : NSLocalizedString ( @ "Open Torrent Address" , "Open address toolbar item -> palette label" ) ] ;
[ item setToolTip : NSLocalizedString ( @ "Open torrent web address" , "Open address toolbar item -> tooltip" ) ] ;
2012-06-10 02:35:58 +00:00
[ item setImage : [ NSImage imageNamed : @ "ToolbarOpenWebTemplate" ] ] ;
2020-11-21 13:27:07 +00:00
if ( @ available ( macOS 11.0 , * ) ) {
[ item setImage : [ NSImage imageWithSystemSymbolName : @ "globe" accessibilityDescription : nil ] ] ;
} else {
[ item setImage : [ NSImage imageNamed : @ "ToolbarOpenWebTemplate" ] ] ;
}
2008-02-07 20:34:14 +00:00
[ item setTarget : self ] ;
[ item setAction : @ selector ( openURLShowSheet : ) ] ;
[ item setAutovalidates : NO ] ;
2017-01-24 17:53:16 +00:00
2008-02-07 20:34:14 +00:00
return item ;
}
2007-09-16 01:02:06 +00:00
else if ( [ ident isEqualToString : TOOLBAR_REMOVE ] )
{
2007-12-06 20:54:26 +00:00
ButtonToolbarItem * item = [ self standardToolbarButtonWithIdentifier : ident ] ;
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
[ item setLabel : NSLocalizedString ( @ "Remove" , "Remove toolbar item -> label" ) ] ;
[ item setPaletteLabel : NSLocalizedString ( @ "Remove Selected" , "Remove toolbar item -> palette label" ) ] ;
[ item setToolTip : NSLocalizedString ( @ "Remove selected transfers" , "Remove toolbar item -> tooltip" ) ] ;
2020-11-21 13:27:07 +00:00
if ( @ available ( macOS 11.0 , * ) ) {
[ item setImage : [ NSImage imageWithSystemSymbolName : @ "nosign" accessibilityDescription : nil ] ] ;
} else {
[ item setImage : [ NSImage imageNamed : @ "ToolbarRemoveTemplate" ] ] ;
}
2007-09-16 01:02:06 +00:00
[ item setTarget : self ] ;
[ item setAction : @ selector ( removeNoDelete : ) ] ;
2011-02-08 01:08:30 +00:00
[ item setVisibilityPriority : NSToolbarItemVisibilityPriorityHigh ] ;
2017-01-24 17:53:16 +00:00
2007-12-06 20:54:26 +00:00
return item ;
2007-09-16 01:02:06 +00:00
}
else if ( [ ident isEqualToString : TOOLBAR_INFO ] )
{
2007-12-06 20:54:26 +00:00
ButtonToolbarItem * item = [ self standardToolbarButtonWithIdentifier : ident ] ;
2009-01-02 03:35:59 +00:00
[ [ ( NSButton * ) [ item view ] cell ] setShowsStateBy : NSContentsCellMask ] ; // blue when enabled
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
[ item setLabel : NSLocalizedString ( @ "Inspector" , "Inspector toolbar item -> label" ) ] ;
[ item setPaletteLabel : NSLocalizedString ( @ "Toggle Inspector" , "Inspector toolbar item -> palette label" ) ] ;
[ item setToolTip : NSLocalizedString ( @ "Toggle the torrent inspector" , "Inspector toolbar item -> tooltip" ) ] ;
2020-11-21 13:27:07 +00:00
if ( @ available ( macOS 11.0 , * ) ) {
[ item setImage : [ NSImage imageWithSystemSymbolName : @ "info.circle" accessibilityDescription : nil ] ] ;
} else {
[ item setImage : [ NSImage imageNamed : @ "ToolbarInfoTemplate" ] ] ;
}
2007-09-16 01:02:06 +00:00
[ item setTarget : self ] ;
[ item setAction : @ selector ( showInfo : ) ] ;
2017-01-24 17:53:16 +00:00
2007-12-06 20:54:26 +00:00
return item ;
2007-09-16 01:02:06 +00:00
}
2007-12-06 17:21:42 +00:00
else if ( [ ident isEqualToString : TOOLBAR_PAUSE _RESUME _ALL ] )
2007-09-16 01:02:06 +00:00
{
2007-12-07 06:27:42 +00:00
GroupToolbarItem * groupItem = [ [ GroupToolbarItem alloc ] initWithItemIdentifier : ident ] ;
2017-01-24 17:53:16 +00:00
2008-04-22 13:25:53 +00:00
NSSegmentedControl * segmentedControl = [ [ NSSegmentedControl alloc ] initWithFrame : NSZeroRect ] ;
2017-07-29 16:14:22 +00:00
[ segmentedControl setCell : [ [ ToolbarSegmentedCell alloc ] init ] ] ;
2007-12-06 17:21:42 +00:00
[ groupItem setView : segmentedControl ] ;
2007-12-07 03:49:46 +00:00
NSSegmentedCell * segmentedCell = ( NSSegmentedCell * ) [ segmentedControl cell ] ;
2020-12-23 03:00:06 +00:00
segmentedControl . segmentStyle = NSSegmentStyleSeparated ;
2017-01-24 17:53:16 +00:00
2007-12-06 17:21:42 +00:00
[ segmentedControl setSegmentCount : 2 ] ;
2007-12-07 03:49:46 +00:00
[ segmentedCell setTrackingMode : NSSegmentSwitchTrackingMomentary ] ;
2017-01-24 17:53:16 +00:00
2020-11-18 03:34:33 +00:00
if ( @ available ( macOS 11.0 , * ) ) {
// not needed
} else {
const NSSize groupSize = NSMakeSize ( 72.0 , 25.0 ) ;
[ groupItem setMinSize : groupSize ] ;
[ groupItem setMaxSize : groupSize ] ;
}
2017-01-24 17:53:16 +00:00
2007-12-06 17:21:42 +00:00
[ groupItem setLabel : NSLocalizedString ( @ "Apply All" , "All toolbar item -> label" ) ] ;
[ groupItem setPaletteLabel : NSLocalizedString ( @ "Pause / Resume All" , "All toolbar item -> palette label" ) ] ;
[ groupItem setTarget : self ] ;
[ groupItem setAction : @ selector ( allToolbarClicked : ) ] ;
2017-01-24 17:53:16 +00:00
2017-07-08 08:23:05 +00:00
[ groupItem setIdentifiers : @ [ TOOLBAR_PAUSE _ALL , TOOLBAR_RESUME _ALL ] ] ;
2017-01-24 17:53:16 +00:00
2007-12-07 03:49:46 +00:00
[ segmentedCell setTag : TOOLBAR_PAUSE _TAG forSegment : TOOLBAR_PAUSE _TAG ] ;
2020-11-21 13:27:07 +00:00
if ( @ available ( macOS 11.0 , * ) ) {
[ segmentedControl setImage : [ [ NSImage imageWithSystemSymbolName : @ "pause.circle.fill" accessibilityDescription : nil ] imageWithSymbolConfiguration : [ NSImageSymbolConfiguration configurationWithScale : NSImageSymbolScaleLarge ] ] forSegment : TOOLBAR_PAUSE _TAG ] ;
} else {
[ segmentedControl setImage : [ NSImage imageNamed : @ "ToolbarPauseAllTemplate" ] forSegment : TOOLBAR_PAUSE _TAG ] ;
}
2007-12-07 03:49:46 +00:00
[ segmentedCell setToolTip : NSLocalizedString ( @ "Pause all transfers" ,
2012-09-09 12:58:53 +00:00
"All toolbar item -> tooltip" ) forSegment : TOOLBAR_PAUSE _TAG ] ;
2017-01-24 17:53:16 +00:00
2007-12-07 03:49:46 +00:00
[ segmentedCell setTag : TOOLBAR_RESUME _TAG forSegment : TOOLBAR_RESUME _TAG ] ;
2012-06-10 02:35:58 +00:00
[ segmentedControl setImage : [ NSImage imageNamed : @ "ToolbarResumeAllTemplate" ] forSegment : TOOLBAR_RESUME _TAG ] ;
2020-11-21 13:27:07 +00:00
if ( @ available ( macOS 11.0 , * ) ) {
[ segmentedControl setImage : [ [ NSImage imageWithSystemSymbolName : @ "arrow.clockwise.circle.fill" accessibilityDescription : nil ] imageWithSymbolConfiguration : [ NSImageSymbolConfiguration configurationWithScale : NSImageSymbolScaleLarge ] ] forSegment : TOOLBAR_RESUME _TAG ] ;
} else {
[ segmentedControl setImage : [ NSImage imageNamed : @ "ToolbarResumeAllTemplate" ] forSegment : TOOLBAR_RESUME _TAG ] ;
}
2007-12-07 03:49:46 +00:00
[ segmentedCell setToolTip : NSLocalizedString ( @ "Resume all transfers" ,
2012-09-09 12:58:53 +00:00
"All toolbar item -> tooltip" ) forSegment : TOOLBAR_RESUME _TAG ] ;
2017-01-24 17:53:16 +00:00
2017-07-08 08:23:05 +00:00
[ groupItem createMenu : @ [ NSLocalizedString ( @ "Pause All" , "All toolbar item -> label" ) ,
NSLocalizedString ( @ "Resume All" , "All toolbar item -> label" ) ] ] ;
2017-01-24 17:53:16 +00:00
2011-02-08 01:08:30 +00:00
[ groupItem setVisibilityPriority : NSToolbarItemVisibilityPriorityHigh ] ;
2017-01-24 17:53:16 +00:00
2017-07-29 16:14:22 +00:00
return groupItem ;
2007-09-16 01:02:06 +00:00
}
2007-12-06 17:21:42 +00:00
else if ( [ ident isEqualToString : TOOLBAR_PAUSE _RESUME _SELECTED ] )
2007-09-16 01:02:06 +00:00
{
2007-12-07 06:27:42 +00:00
GroupToolbarItem * groupItem = [ [ GroupToolbarItem alloc ] initWithItemIdentifier : ident ] ;
2017-01-24 17:53:16 +00:00
2008-04-22 13:25:53 +00:00
NSSegmentedControl * segmentedControl = [ [ NSSegmentedControl alloc ] initWithFrame : NSZeroRect ] ;
2017-07-29 16:14:22 +00:00
[ segmentedControl setCell : [ [ ToolbarSegmentedCell alloc ] init ] ] ;
2007-12-06 17:21:42 +00:00
[ groupItem setView : segmentedControl ] ;
2007-12-07 03:49:46 +00:00
NSSegmentedCell * segmentedCell = ( NSSegmentedCell * ) [ segmentedControl cell ] ;
2020-12-23 03:00:06 +00:00
segmentedControl . segmentStyle = NSSegmentStyleSeparated ;
2017-01-24 17:53:16 +00:00
2007-12-06 17:21:42 +00:00
[ segmentedControl setSegmentCount : 2 ] ;
2007-12-07 03:49:46 +00:00
[ segmentedCell setTrackingMode : NSSegmentSwitchTrackingMomentary ] ;
2017-01-24 17:53:16 +00:00
2020-11-18 03:34:33 +00:00
if ( @ available ( macOS 11.0 , * ) ) {
// not needed
} else {
const NSSize groupSize = NSMakeSize ( 72.0 , 25.0 ) ;
[ groupItem setMinSize : groupSize ] ;
[ groupItem setMaxSize : groupSize ] ;
}
2017-01-24 17:53:16 +00:00
2007-12-06 17:21:42 +00:00
[ groupItem setLabel : NSLocalizedString ( @ "Apply Selected" , "Selected toolbar item -> label" ) ] ;
[ groupItem setPaletteLabel : NSLocalizedString ( @ "Pause / Resume Selected" , "Selected toolbar item -> palette label" ) ] ;
[ groupItem setTarget : self ] ;
[ groupItem setAction : @ selector ( selectedToolbarClicked : ) ] ;
2017-01-24 17:53:16 +00:00
2017-07-08 08:23:05 +00:00
[ groupItem setIdentifiers : @ [ TOOLBAR_PAUSE _SELECTED , TOOLBAR_RESUME _SELECTED ] ] ;
2017-01-24 17:53:16 +00:00
2007-12-07 03:49:46 +00:00
[ segmentedCell setTag : TOOLBAR_PAUSE _TAG forSegment : TOOLBAR_PAUSE _TAG ] ;
2020-11-21 13:27:07 +00:00
if ( @ available ( macOS 11.0 , * ) ) {
[ segmentedControl setImage : [ [ NSImage imageWithSystemSymbolName : @ "pause" accessibilityDescription : nil ] imageWithSymbolConfiguration : [ NSImageSymbolConfiguration configurationWithScale : NSImageSymbolScaleLarge ] ] forSegment : TOOLBAR_PAUSE _TAG ] ;
} else {
[ segmentedControl setImage : [ NSImage imageNamed : @ "ToolbarPauseSelectedTemplate" ] forSegment : TOOLBAR_PAUSE _TAG ] ;
}
2007-12-07 03:49:46 +00:00
[ segmentedCell setToolTip : NSLocalizedString ( @ "Pause selected transfers" ,
2012-09-09 12:58:53 +00:00
"Selected toolbar item -> tooltip" ) forSegment : TOOLBAR_PAUSE _TAG ] ;
2017-01-24 17:53:16 +00:00
2007-12-07 03:49:46 +00:00
[ segmentedCell setTag : TOOLBAR_RESUME _TAG forSegment : TOOLBAR_RESUME _TAG ] ;
2020-11-21 13:27:07 +00:00
if ( @ available ( macOS 11.0 , * ) ) {
[ segmentedControl setImage : [ NSImage imageWithSystemSymbolName : @ "arrow.clockwise" accessibilityDescription : nil ] forSegment : TOOLBAR_RESUME _TAG ] ;
} else {
[ segmentedControl setImage : [ NSImage imageNamed : @ "ToolbarResumeSelectedTemplate" ] forSegment : TOOLBAR_RESUME _TAG ] ;
}
2007-12-07 03:49:46 +00:00
[ segmentedCell setToolTip : NSLocalizedString ( @ "Resume selected transfers" ,
2012-09-09 12:58:53 +00:00
"Selected toolbar item -> tooltip" ) forSegment : TOOLBAR_RESUME _TAG ] ;
2017-01-24 17:53:16 +00:00
2017-07-08 08:23:05 +00:00
[ groupItem createMenu : @ [ NSLocalizedString ( @ "Pause Selected" , "Selected toolbar item -> label" ) ,
NSLocalizedString ( @ "Resume Selected" , "Selected toolbar item -> label" ) ] ] ;
2017-01-24 17:53:16 +00:00
2011-02-08 01:08:30 +00:00
[ groupItem setVisibilityPriority : NSToolbarItemVisibilityPriorityHigh ] ;
2017-01-24 17:53:16 +00:00
2017-07-29 16:14:22 +00:00
return groupItem ;
2007-09-16 01:02:06 +00:00
}
else if ( [ ident isEqualToString : TOOLBAR_FILTER ] )
{
2007-12-06 20:54:26 +00:00
ButtonToolbarItem * item = [ self standardToolbarButtonWithIdentifier : ident ] ;
2009-01-02 03:35:59 +00:00
[ [ ( NSButton * ) [ item view ] cell ] setShowsStateBy : NSContentsCellMask ] ; // blue when enabled
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
[ item setLabel : NSLocalizedString ( @ "Filter" , "Filter toolbar item -> label" ) ] ;
[ item setPaletteLabel : NSLocalizedString ( @ "Toggle Filter" , "Filter toolbar item -> palette label" ) ] ;
[ item setToolTip : NSLocalizedString ( @ "Toggle the filter bar" , "Filter toolbar item -> tooltip" ) ] ;
2020-11-21 13:27:07 +00:00
if ( @ available ( macOS 11.0 , * ) ) {
[ item setImage : [ NSImage imageWithSystemSymbolName : @ "magnifyingglass" accessibilityDescription : nil ] ] ;
} else {
[ item setImage : [ NSImage imageNamed : @ "ToolbarFilterTemplate" ] ] ;
}
2007-09-16 01:02:06 +00:00
[ item setTarget : self ] ;
[ item setAction : @ selector ( toggleFilterBar : ) ] ;
2017-01-24 17:53:16 +00:00
2007-12-06 20:54:26 +00:00
return item ;
2007-09-16 01:02:06 +00:00
}
2008-05-21 16:02:38 +00:00
else if ( [ ident isEqualToString : TOOLBAR_QUICKLOOK ] )
{
ButtonToolbarItem * item = [ self standardToolbarButtonWithIdentifier : ident ] ;
2009-10-12 01:59:52 +00:00
[ [ ( NSButton * ) [ item view ] cell ] setShowsStateBy : NSContentsCellMask ] ; // blue when enabled
2017-01-24 17:53:16 +00:00
2008-05-29 00:56:58 +00:00
[ item setLabel : NSLocalizedString ( @ "Quick Look" , "QuickLook toolbar item -> label" ) ] ;
2008-05-21 16:02:38 +00:00
[ item setPaletteLabel : NSLocalizedString ( @ "Quick Look" , "QuickLook toolbar item -> palette label" ) ] ;
[ item setToolTip : NSLocalizedString ( @ "Quick Look" , "QuickLook toolbar item -> tooltip" ) ] ;
[ item setImage : [ NSImage imageNamed : NSImageNameQuickLookTemplate ] ] ;
[ item setTarget : self ] ;
2008-05-21 16:28:21 +00:00
[ item setAction : @ selector ( toggleQuickLook : ) ] ;
2011-02-08 01:08:30 +00:00
[ item setVisibilityPriority : NSToolbarItemVisibilityPriorityLow ] ;
2017-01-24 17:53:16 +00:00
2008-05-21 16:02:38 +00:00
return item ;
}
2014-01-09 16:23:54 +00:00
else if ( [ ident isEqualToString : TOOLBAR_SHARE ] )
{
ShareToolbarItem * item = [ self toolbarButtonWithIdentifier : ident forToolbarButtonClass : [ ShareToolbarItem class ] ] ;
2017-01-24 17:53:16 +00:00
2014-01-09 16:23:54 +00:00
[ item setLabel : NSLocalizedString ( @ "Share" , "Share toolbar item -> label" ) ] ;
[ item setPaletteLabel : NSLocalizedString ( @ "Share" , "Share toolbar item -> palette label" ) ] ;
[ item setToolTip : NSLocalizedString ( @ "Share torrent file" , "Share toolbar item -> tooltip" ) ] ;
[ item setImage : [ NSImage imageNamed : NSImageNameShareTemplate ] ] ;
[ item setVisibilityPriority : NSToolbarItemVisibilityPriorityLow ] ;
2017-01-24 17:53:16 +00:00
2014-01-09 16:23:54 +00:00
NSButton * itemButton = ( NSButton * ) [ item view ] ;
[ itemButton setTarget : self ] ;
[ itemButton setAction : @ selector ( showToolbarShare : ) ] ;
[ itemButton sendActionOn : NSLeftMouseDownMask ] ;
2017-01-24 17:53:16 +00:00
2014-01-09 16:23:54 +00:00
return item ;
}
2007-09-16 01:02:06 +00:00
else
return nil ;
2007-12-06 17:21:42 +00:00
}
- ( void ) allToolbarClicked : ( id ) sender
{
2008-11-02 13:52:45 +00:00
NSInteger tagValue = [ sender isKindOfClass : [ NSSegmentedControl class ] ]
2012-09-09 12:58:53 +00:00
? [ ( NSSegmentedCell * ) [ sender cell ] tagForSegment : [ sender selectedSegment ] ] : [ ( NSControl * ) sender tag ] ;
2007-12-07 03:41:46 +00:00
switch ( tagValue )
2007-12-06 20:25:38 +00:00
{
case TOOLBAR_PAUSE _TAG :
[ self stopAllTorrents : sender ] ;
break ;
case TOOLBAR_RESUME _TAG :
[ self resumeAllTorrents : sender ] ;
break ;
}
2007-12-06 17:21:42 +00:00
}
- ( void ) selectedToolbarClicked : ( id ) sender
{
2008-11-02 13:52:45 +00:00
NSInteger tagValue = [ sender isKindOfClass : [ NSSegmentedControl class ] ]
2012-09-09 12:58:53 +00:00
? [ ( NSSegmentedCell * ) [ sender cell ] tagForSegment : [ sender selectedSegment ] ] : [ ( NSControl * ) sender tag ] ;
2007-12-07 03:41:46 +00:00
switch ( tagValue )
2007-12-06 20:25:38 +00:00
{
case TOOLBAR_PAUSE _TAG :
[ self stopSelectedTorrents : sender ] ;
break ;
case TOOLBAR_RESUME _TAG :
[ self resumeSelectedTorrents : sender ] ;
break ;
}
2007-09-16 01:02:06 +00:00
}
2007-11-29 01:05:11 +00:00
- ( NSArray * ) toolbarAllowedItemIdentifiers : ( NSToolbar * ) toolbar
2007-09-16 01:02:06 +00:00
{
2017-02-05 19:29:20 +00:00
return @ [ TOOLBAR_CREATE , TOOLBAR_OPEN _FILE , TOOLBAR_OPEN _WEB , TOOLBAR_REMOVE ,
TOOLBAR_PAUSE _RESUME _SELECTED , TOOLBAR_PAUSE _RESUME _ALL ,
TOOLBAR_SHARE , TOOLBAR_QUICKLOOK , TOOLBAR_FILTER , TOOLBAR_INFO ,
NSToolbarSpaceItemIdentifier ,
2020-11-18 03:07:25 +00:00
NSToolbarFlexibleSpaceItemIdentifier ] ;
2007-09-16 01:02:06 +00:00
}
2007-11-29 01:05:11 +00:00
- ( NSArray * ) toolbarDefaultItemIdentifiers : ( NSToolbar * ) toolbar
2007-09-16 01:02:06 +00:00
{
2017-02-05 19:29:20 +00:00
return @ [ TOOLBAR_CREATE , TOOLBAR_OPEN _FILE , TOOLBAR_REMOVE , NSToolbarSpaceItemIdentifier ,
TOOLBAR_PAUSE _RESUME _ALL , NSToolbarFlexibleSpaceItemIdentifier ,
TOOLBAR_SHARE , TOOLBAR_QUICKLOOK , TOOLBAR_FILTER , TOOLBAR_INFO ] ;
2007-09-16 01:02:06 +00:00
}
- ( BOOL ) validateToolbarItem : ( NSToolbarItem * ) toolbarItem
{
NSString * ident = [ toolbarItem itemIdentifier ] ;
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
// enable remove item
if ( [ ident isEqualToString : TOOLBAR_REMOVE ] )
return [ fTableView numberOfSelectedRows ] > 0 ;
2012-09-09 12:58:53 +00:00
2007-09-16 01:02:06 +00:00
// enable pause all item
if ( [ ident isEqualToString : TOOLBAR_PAUSE _ALL ] )
{
2008-12-26 07:06:02 +00:00
for ( Torrent * torrent in fTorrents )
2007-09-16 01:02:06 +00:00
if ( [ torrent isActive ] || [ torrent waitingToStart ] )
return YES ;
return NO ;
}
2012-09-09 12:58:53 +00:00
2007-09-16 01:02:06 +00:00
// enable resume all item
if ( [ ident isEqualToString : TOOLBAR_RESUME _ALL ] )
{
2008-12-26 07:06:02 +00:00
for ( Torrent * torrent in fTorrents )
2011-08-27 21:31:44 +00:00
if ( ! [ torrent isActive ] && ! [ torrent waitingToStart ] && ! [ torrent isFinishedSeeding ] )
2007-09-16 01:02:06 +00:00
return YES ;
return NO ;
}
2012-09-09 12:58:53 +00:00
2007-09-16 01:02:06 +00:00
// enable pause item
if ( [ ident isEqualToString : TOOLBAR_PAUSE _SELECTED ] )
{
2008-12-26 07:06:02 +00:00
for ( Torrent * torrent in [ fTableView selectedTorrents ] )
2007-09-16 01:02:06 +00:00
if ( [ torrent isActive ] || [ torrent waitingToStart ] )
return YES ;
return NO ;
}
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
// enable resume item
if ( [ ident isEqualToString : TOOLBAR_RESUME _SELECTED ] )
{
2008-12-26 07:06:02 +00:00
for ( Torrent * torrent in [ fTableView selectedTorrents ] )
2007-10-20 21:27:46 +00:00
if ( ! [ torrent isActive ] && ! [ torrent waitingToStart ] )
2007-09-16 01:02:06 +00:00
return YES ;
return NO ;
}
2017-01-24 17:53:16 +00:00
2011-03-10 01:36:51 +00:00
// set info item
2007-12-09 03:25:33 +00:00
if ( [ ident isEqualToString : TOOLBAR_INFO ] )
{
2009-01-02 03:35:59 +00:00
[ ( NSButton * ) [ toolbarItem view ] setState : [ [ fInfoController window ] isVisible ] ] ;
2007-12-09 03:25:33 +00:00
return YES ;
}
2017-01-24 17:53:16 +00:00
2011-03-10 01:36:51 +00:00
// set filter item
2007-12-09 03:25:33 +00:00
if ( [ ident isEqualToString : TOOLBAR_FILTER ] )
{
2011-02-20 03:58:50 +00:00
[ ( NSButton * ) [ toolbarItem view ] setState : fFilterBar ! = nil ] ;
2007-12-09 03:25:33 +00:00
return YES ;
}
2017-01-24 17:53:16 +00:00
2011-03-10 01:36:51 +00:00
// set quick look item
2009-10-12 01:59:52 +00:00
if ( [ ident isEqualToString : TOOLBAR_QUICKLOOK ] )
{
2011-10-06 00:30:40 +00:00
[ ( NSButton * ) [ toolbarItem view ] setState : [ QLPreviewPanel sharedPreviewPanelExists ] && [ [ QLPreviewPanel sharedPreviewPanel ] isVisible ] ] ;
return YES ;
2009-10-12 01:59:52 +00:00
}
2017-01-24 17:53:16 +00:00
2014-01-09 16:23:54 +00:00
// enable share item
if ( [ ident isEqualToString : TOOLBAR_SHARE ] )
return [ fTableView numberOfSelectedRows ] > 0 ;
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
return YES ;
}
- ( BOOL ) validateMenuItem : ( NSMenuItem * ) menuItem
{
SEL action = [ menuItem action ] ;
2017-01-24 17:53:16 +00:00
2007-10-30 20:19:22 +00:00
if ( action = = @ selector ( toggleSpeedLimit : ) )
{
[ menuItem setState : [ fDefaults boolForKey : @ "SpeedLimit" ] ? NSOnState : NSOffState ] ;
return YES ;
}
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
// only enable some items if it is in a context menu or the window is useable
BOOL canUseTable = [ fWindow isKeyWindow ] || [ [ menuItem menu ] supermenu ] ! = [ NSApp mainMenu ] ;
2012-09-09 12:58:53 +00:00
2007-09-16 01:02:06 +00:00
// enable open items
if ( action = = @ selector ( openShowSheet : ) || action = = @ selector ( openURLShowSheet : ) )
return [ fWindow attachedSheet ] = = nil ;
2017-01-24 17:53:16 +00:00
2007-11-04 16:45:17 +00:00
// enable sort options
2007-11-04 15:01:34 +00:00
if ( action = = @ selector ( setSort : ) )
2007-11-07 05:02:43 +00:00
{
NSString * sortType ;
switch ( [ menuItem tag ] )
{
case SORT_ORDER _TAG :
sortType = SORT_ORDER ;
break ;
case SORT_DATE _TAG :
sortType = SORT_DATE ;
break ;
case SORT_NAME _TAG :
sortType = SORT_NAME ;
break ;
case SORT_PROGRESS _TAG :
sortType = SORT_PROGRESS ;
break ;
case SORT_STATE _TAG :
sortType = SORT_STATE ;
break ;
case SORT_TRACKER _TAG :
sortType = SORT_TRACKER ;
break ;
2007-11-21 18:32:41 +00:00
case SORT_ACTIVITY _TAG :
sortType = SORT_ACTIVITY ;
2009-10-11 13:42:10 +00:00
break ;
2011-07-04 19:47:15 +00:00
case SORT_SIZE _TAG :
sortType = SORT_SIZE ;
break ;
2009-10-11 13:11:52 +00:00
default :
2012-08-13 00:52:04 +00:00
NSAssert1 ( NO , @ "Unknown sort tag received: %ld" , [ menuItem tag ] ) ;
2016-09-11 10:22:49 +00:00
sortType = SORT_ORDER ;
2007-11-07 05:02:43 +00:00
}
2017-01-24 17:53:16 +00:00
2007-11-07 05:02:43 +00:00
[ menuItem setState : [ sortType isEqualToString : [ fDefaults stringForKey : @ "Sort" ] ] ? NSOnState : NSOffState ] ;
2007-10-30 19:55:47 +00:00
return [ fWindow isVisible ] ;
2007-11-07 05:02:43 +00:00
}
2017-01-24 17:53:16 +00:00
2007-12-17 16:32:32 +00:00
if ( action = = @ selector ( setGroup : ) )
{
BOOL checked = NO ;
2017-01-24 17:53:16 +00:00
2008-11-02 13:52:45 +00:00
NSInteger index = [ menuItem tag ] ;
2008-12-26 07:06:02 +00:00
for ( Torrent * torrent in [ fTableView selectedTorrents ] )
2007-12-17 16:32:32 +00:00
if ( index = = [ torrent groupValue ] )
{
checked = YES ;
break ;
}
2017-01-24 17:53:16 +00:00
2007-12-17 16:32:32 +00:00
[ menuItem setState : checked ? NSOnState : NSOffState ] ;
return canUseTable && [ fTableView numberOfSelectedRows ] > 0 ;
}
2017-01-24 17:53:16 +00:00
2007-10-30 19:55:47 +00:00
if ( action = = @ selector ( toggleSmallView : ) )
{
[ menuItem setState : [ fDefaults boolForKey : @ "SmallView" ] ? NSOnState : NSOffState ] ;
2007-09-16 01:02:06 +00:00
return [ fWindow isVisible ] ;
2007-10-30 19:55:47 +00:00
}
2017-01-24 17:53:16 +00:00
2007-11-04 15:01:34 +00:00
if ( action = = @ selector ( togglePiecesBar : ) )
{
[ menuItem setState : [ fDefaults boolForKey : @ "PiecesBar" ] ? NSOnState : NSOffState ] ;
return [ fWindow isVisible ] ;
}
2017-01-24 17:53:16 +00:00
2007-11-11 16:59:32 +00:00
if ( action = = @ selector ( toggleAvailabilityBar : ) )
{
[ menuItem setState : [ fDefaults boolForKey : @ "DisplayProgressBarAvailable" ] ? NSOnState : NSOffState ] ;
return [ fWindow isVisible ] ;
}
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
// enable show info
if ( action = = @ selector ( showInfo : ) )
{
2007-10-17 23:33:22 +00:00
NSString * title = [ [ fInfoController window ] isVisible ] ? NSLocalizedString ( @ "Hide Inspector" , "View menu -> Inspector" )
2012-09-09 12:58:53 +00:00
: NSLocalizedString ( @ "Show Inspector" , "View menu -> Inspector" ) ;
2007-10-21 13:53:29 +00:00
[ menuItem setTitle : title ] ;
2012-09-09 12:58:53 +00:00
2007-09-16 01:02:06 +00:00
return YES ;
}
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
// enable prev / next inspector tab
if ( action = = @ selector ( setInfoTab : ) )
return [ [ fInfoController window ] isVisible ] ;
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
// enable toggle status bar
if ( action = = @ selector ( toggleStatusBar : ) )
{
2011-02-20 00:22:55 +00:00
NSString * title = ! fStatusBar ? NSLocalizedString ( @ "Show Status Bar" , "View menu -> Status Bar" )
2012-09-09 12:58:53 +00:00
: NSLocalizedString ( @ "Hide Status Bar" , "View menu -> Status Bar" ) ;
2007-10-21 13:53:29 +00:00
[ menuItem setTitle : title ] ;
2012-09-09 12:58:53 +00:00
2007-09-16 01:02:06 +00:00
return [ fWindow isVisible ] ;
}
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
// enable toggle filter bar
if ( action = = @ selector ( toggleFilterBar : ) )
{
2011-02-20 03:58:50 +00:00
NSString * title = ! fFilterBar ? NSLocalizedString ( @ "Show Filter Bar" , "View menu -> Filter Bar" )
2012-09-09 12:58:53 +00:00
: NSLocalizedString ( @ "Hide Filter Bar" , "View menu -> Filter Bar" ) ;
2007-10-21 13:53:29 +00:00
[ menuItem setTitle : title ] ;
2012-09-09 12:58:53 +00:00
2007-09-16 01:02:06 +00:00
return [ fWindow isVisible ] ;
}
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
// enable prev / next filter button
if ( action = = @ selector ( switchFilter : ) )
2011-02-20 03:58:50 +00:00
return [ fWindow isVisible ] && fFilterBar ;
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
// enable reveal in finder
if ( action = = @ selector ( revealFile : ) )
return canUseTable && [ fTableView numberOfSelectedRows ] > 0 ;
2017-01-24 17:53:16 +00:00
2013-01-22 00:09:48 +00:00
// enable renaming file / folder
2013-01-22 00:50:28 +00:00
if ( action = = @ selector ( renameSelected : ) )
2013-01-22 00:09:48 +00:00
return canUseTable && [ fTableView numberOfSelectedRows ] = = 1 ;
2012-09-09 12:58:53 +00:00
2007-09-16 01:02:06 +00:00
// enable remove items
2009-07-19 19:14:01 +00:00
if ( action = = @ selector ( removeNoDelete : ) || action = = @ selector ( removeDeleteData : ) )
2007-09-16 01:02:06 +00:00
{
2009-07-19 19:14:01 +00:00
BOOL warning = NO ;
2017-01-24 17:53:16 +00:00
2008-12-26 07:06:02 +00:00
for ( Torrent * torrent in [ fTableView selectedTorrents ] )
2007-09-16 01:02:06 +00:00
{
2009-07-19 19:14:01 +00:00
if ( [ torrent isActive ] )
2007-09-16 01:02:06 +00:00
{
2009-07-19 19:14:01 +00:00
if ( [ fDefaults boolForKey : @ "CheckRemoveDownloading" ] ? ! [ torrent isSeeding ] : YES )
{
warning = YES ;
2007-09-16 01:02:06 +00:00
break ;
2009-07-19 19:14:01 +00:00
}
2007-09-16 01:02:06 +00:00
}
}
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
// append or remove ellipsis when needed
NSString * title = [ menuItem title ] , * ellipsis = [ NSString ellipsis ] ;
if ( warning && [ fDefaults boolForKey : @ "CheckRemove" ] )
{
if ( ! [ title hasSuffix : ellipsis ] )
[ menuItem setTitle : [ title stringByAppendingEllipsis ] ] ;
}
else
{
if ( [ title hasSuffix : ellipsis ] )
[ menuItem setTitle : [ title substringToIndex : [ title rangeOfString : ellipsis ] . location ] ] ;
}
2017-01-24 17:53:16 +00:00
2009-07-19 19:14:01 +00:00
return canUseTable && [ fTableView numberOfSelectedRows ] > 0 ;
2007-09-16 01:02:06 +00:00
}
2017-01-24 17:53:16 +00:00
2011-03-14 23:46:53 +00:00
// remove all completed transfers item
2011-02-13 02:02:13 +00:00
if ( action = = @ selector ( clearCompleted : ) )
{
2011-03-17 01:06:31 +00:00
// append or remove ellipsis when needed
NSString * title = [ menuItem title ] , * ellipsis = [ NSString ellipsis ] ;
if ( [ fDefaults boolForKey : @ "WarningRemoveCompleted" ] )
{
if ( ! [ title hasSuffix : ellipsis ] )
[ menuItem setTitle : [ title stringByAppendingEllipsis ] ] ;
}
else
{
if ( [ title hasSuffix : ellipsis ] )
[ menuItem setTitle : [ title substringToIndex : [ title rangeOfString : ellipsis ] . location ] ] ;
}
2017-01-24 17:53:16 +00:00
2011-02-13 02:02:13 +00:00
for ( Torrent * torrent in fTorrents )
if ( [ torrent isFinishedSeeding ] )
return YES ;
return NO ;
}
2012-09-09 12:58:53 +00:00
2007-09-16 01:02:06 +00:00
// enable pause all item
if ( action = = @ selector ( stopAllTorrents : ) )
{
2008-12-26 07:06:02 +00:00
for ( Torrent * torrent in fTorrents )
2007-09-16 01:02:06 +00:00
if ( [ torrent isActive ] || [ torrent waitingToStart ] )
return YES ;
return NO ;
}
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
// enable resume all item
if ( action = = @ selector ( resumeAllTorrents : ) )
{
2008-12-26 07:06:02 +00:00
for ( Torrent * torrent in fTorrents )
2010-04-04 02:05:40 +00:00
if ( ! [ torrent isActive ] && ! [ torrent waitingToStart ] && ! [ torrent isFinishedSeeding ] )
2007-09-16 01:02:06 +00:00
return YES ;
return NO ;
}
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
// enable resume all waiting item
if ( action = = @ selector ( resumeWaitingTorrents : ) )
{
if ( ! [ fDefaults boolForKey : @ "Queue" ] && ! [ fDefaults boolForKey : @ "QueueSeed" ] )
return NO ;
2017-01-24 17:53:16 +00:00
2008-12-26 07:06:02 +00:00
for ( Torrent * torrent in fTorrents )
2011-08-27 21:31:44 +00:00
if ( [ torrent waitingToStart ] )
2007-09-16 01:02:06 +00:00
return YES ;
return NO ;
}
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
// enable resume selected waiting item
if ( action = = @ selector ( resumeSelectedTorrentsNoWait : ) )
{
2008-01-02 04:33:26 +00:00
if ( ! canUseTable )
return NO ;
2017-01-24 17:53:16 +00:00
2008-12-26 07:06:02 +00:00
for ( Torrent * torrent in [ fTableView selectedTorrents ] )
2007-10-20 21:27:46 +00:00
if ( ! [ torrent isActive ] )
2007-09-16 01:02:06 +00:00
return YES ;
return NO ;
}
2012-09-09 12:58:53 +00:00
2007-09-16 01:02:06 +00:00
// enable pause item
if ( action = = @ selector ( stopSelectedTorrents : ) )
{
if ( ! canUseTable )
return NO ;
2017-01-24 17:53:16 +00:00
2008-12-26 07:06:02 +00:00
for ( Torrent * torrent in [ fTableView selectedTorrents ] )
2007-09-16 01:02:06 +00:00
if ( [ torrent isActive ] || [ torrent waitingToStart ] )
return YES ;
return NO ;
}
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
// enable resume item
if ( action = = @ selector ( resumeSelectedTorrents : ) )
{
if ( ! canUseTable )
return NO ;
2017-01-24 17:53:16 +00:00
2008-12-26 07:06:02 +00:00
for ( Torrent * torrent in [ fTableView selectedTorrents ] )
2007-10-20 21:27:46 +00:00
if ( ! [ torrent isActive ] && ! [ torrent waitingToStart ] )
2007-09-16 01:02:06 +00:00
return YES ;
return NO ;
}
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
// enable manual announce item
if ( action = = @ selector ( announceSelectedTorrents : ) )
{
if ( ! canUseTable )
return NO ;
2017-01-24 17:53:16 +00:00
2008-12-26 07:06:02 +00:00
for ( Torrent * torrent in [ fTableView selectedTorrents ] )
2007-09-16 01:02:06 +00:00
if ( [ torrent canManualAnnounce ] )
return YES ;
return NO ;
}
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
// enable reset cache item
2008-02-27 19:04:38 +00:00
if ( action = = @ selector ( verifySelectedTorrents : ) )
2010-01-23 21:51:04 +00:00
{
if ( ! canUseTable )
return NO ;
2017-01-24 17:53:16 +00:00
2010-01-23 21:51:04 +00:00
for ( Torrent * torrent in [ fTableView selectedTorrents ] )
if ( ! [ torrent isMagnet ] )
return YES ;
return NO ;
}
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
// enable move torrent file item
2008-03-22 17:05:48 +00:00
if ( action = = @ selector ( moveDataFilesSelected : ) )
2007-09-16 01:02:06 +00:00
return canUseTable && [ fTableView numberOfSelectedRows ] > 0 ;
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
// enable copy torrent file item
if ( action = = @ selector ( copyTorrentFiles : ) )
2010-01-17 17:57:54 +00:00
{
if ( ! canUseTable )
return NO ;
2017-01-24 17:53:16 +00:00
2010-01-17 17:57:54 +00:00
for ( Torrent * torrent in [ fTableView selectedTorrents ] )
if ( ! [ torrent isMagnet ] )
return YES ;
return NO ;
}
2017-01-24 17:53:16 +00:00
2009-12-04 13:35:15 +00:00
// enable copy torrent file item
if ( action = = @ selector ( copyMagnetLinks : ) )
return canUseTable && [ fTableView numberOfSelectedRows ] > 0 ;
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
// enable reverse sort item
if ( action = = @ selector ( setSortReverse : ) )
2007-10-30 19:55:47 +00:00
{
2011-01-06 04:09:04 +00:00
const BOOL isReverse = [ menuItem tag ] = = SORT_DESC _TAG ;
[ menuItem setState : ( isReverse = = [ fDefaults boolForKey : @ "SortReverse" ] ) ? NSOnState : NSOffState ] ;
2007-10-30 19:55:47 +00:00
return ! [ [ fDefaults stringForKey : @ "Sort" ] isEqualToString : SORT_ORDER ] ;
}
2017-01-24 17:53:16 +00:00
2007-12-17 19:47:06 +00:00
// enable group sort item
if ( action = = @ selector ( setSortByGroup : ) )
{
[ menuItem setState : [ fDefaults boolForKey : @ "SortByGroup" ] ? NSOnState : NSOffState ] ;
2008-05-11 21:38:40 +00:00
return YES ;
2007-12-17 19:47:06 +00:00
}
2017-01-24 17:53:16 +00:00
2009-09-07 15:07:00 +00:00
if ( action = = @ selector ( toggleQuickLook : ) )
2009-10-12 01:59:52 +00:00
{
2011-10-06 00:30:40 +00:00
const BOOL visible = [ QLPreviewPanel sharedPreviewPanelExists ] && [ [ QLPreviewPanel sharedPreviewPanel ] isVisible ] ;
2009-10-12 01:59:52 +00:00
// text consistent with Finder
NSString * title = ! visible ? NSLocalizedString ( @ "Quick Look" , "View menu -> Quick Look" )
2012-09-09 12:58:53 +00:00
: NSLocalizedString ( @ "Close Quick Look" , "View menu -> Quick Look" ) ;
2009-10-12 01:59:52 +00:00
[ menuItem setTitle : title ] ;
2017-01-24 17:53:16 +00:00
2011-10-06 00:30:40 +00:00
return YES ;
2009-10-12 01:59:52 +00:00
}
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
return YES ;
}
2008-05-20 15:16:34 +00:00
- ( void ) sleepCallback : ( natural_t ) messageType argument : ( void * ) messageArgument
2007-09-16 01:02:06 +00:00
{
switch ( messageType )
{
case kIOMessageSystemWillSleep :
2012-11-04 19:28:51 +00:00
{
// stop all transfers ( since some are active ) before going to sleep and remember to resume when we wake up
BOOL anyActive = NO ;
2008-12-26 07:06:02 +00:00
for ( Torrent * torrent in fTorrents )
2012-11-04 19:28:51 +00:00
{
2008-04-25 22:23:31 +00:00
if ( [ torrent isActive ] )
2012-11-04 19:28:51 +00:00
anyActive = YES ;
[ torrent sleep ] ; // have to call on all , regardless if they are active
}
2017-01-24 17:53:16 +00:00
2012-11-04 19:28:51 +00:00
// if there are any running transfers , wait 15 seconds for them to stop
if ( anyActive )
{
sleep ( 15 ) ;
}
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
IOAllowPowerChange ( fRootPort , ( long ) messageArgument ) ;
break ;
2012-11-04 19:28:51 +00:00
}
2012-09-09 12:58:53 +00:00
2007-09-16 01:02:06 +00:00
case kIOMessageCanSystemSleep :
if ( [ fDefaults boolForKey : @ "SleepPrevent" ] )
{
// prevent idle sleep unless no torrents are active
2008-12-26 07:06:02 +00:00
for ( Torrent * torrent in fTorrents )
2007-09-16 01:02:06 +00:00
if ( [ torrent isActive ] && ! [ torrent isStalled ] && ! [ torrent isError ] )
{
2008-04-25 22:23:31 +00:00
IOCancelPowerChange ( fRootPort , ( long ) messageArgument ) ;
return ;
2007-09-16 01:02:06 +00:00
}
}
2017-01-24 17:53:16 +00:00
2008-04-25 22:23:31 +00:00
IOAllowPowerChange ( fRootPort , ( long ) messageArgument ) ;
2007-09-16 01:02:06 +00:00
break ;
2012-09-09 12:58:53 +00:00
2007-09-16 01:02:06 +00:00
case kIOMessageSystemHasPoweredOn :
// resume sleeping transfers after we wake up
2009-05-06 01:42:13 +00:00
for ( Torrent * torrent in fTorrents )
[ torrent wakeUp ] ;
2007-09-16 01:02:06 +00:00
break ;
}
}
- ( NSMenu * ) applicationDockMenu : ( NSApplication * ) sender
{
2011-08-05 23:21:34 +00:00
if ( fQuitting )
return nil ;
2017-01-24 17:53:16 +00:00
2012-01-18 01:40:34 +00:00
NSUInteger seeding = 0 , downloading = 0 ;
2011-08-05 23:21:34 +00:00
for ( Torrent * torrent in fTorrents )
2007-09-16 01:02:06 +00:00
{
2011-08-05 23:21:34 +00:00
if ( [ torrent isSeeding ] )
seeding + + ;
else if ( [ torrent isActive ] )
downloading + + ;
else ;
2007-09-16 01:02:06 +00:00
}
2017-01-24 17:53:16 +00:00
2011-08-05 23:18:02 +00:00
NSMenu * menu = [ [ NSMenu alloc ] init ] ;
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
if ( seeding > 0 )
{
2008-03-24 00:06:54 +00:00
NSString * title = [ NSString stringWithFormat : NSLocalizedString ( @ "%d Seeding" , "Dock item - Seeding" ) , seeding ] ;
2011-08-05 23:18:02 +00:00
[ menu addItemWithTitle : title action : nil keyEquivalent : @ "" ] ;
2007-09-16 01:02:06 +00:00
}
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
if ( downloading > 0 )
{
2008-03-24 00:06:54 +00:00
NSString * title = [ NSString stringWithFormat : NSLocalizedString ( @ "%d Downloading" , "Dock item - Downloading" ) , downloading ] ;
2011-08-05 23:18:02 +00:00
[ menu addItemWithTitle : title action : nil keyEquivalent : @ "" ] ;
2007-09-16 01:02:06 +00:00
}
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
if ( seeding > 0 || downloading > 0 )
2011-08-05 23:18:02 +00:00
[ menu addItem : [ NSMenuItem separatorItem ] ] ;
2017-01-24 17:53:16 +00:00
2011-08-05 23:18:02 +00:00
[ menu addItemWithTitle : NSLocalizedString ( @ "Pause All" , "Dock item" ) action : @ selector ( stopAllTorrents : ) keyEquivalent : @ "" ] ;
[ menu addItemWithTitle : NSLocalizedString ( @ "Resume All" , "Dock item" ) action : @ selector ( resumeAllTorrents : ) keyEquivalent : @ "" ] ;
[ menu addItem : [ NSMenuItem separatorItem ] ] ;
[ menu addItemWithTitle : NSLocalizedString ( @ "Speed Limit" , "Dock item" ) action : @ selector ( toggleSpeedLimit : ) keyEquivalent : @ "" ] ;
2017-01-24 17:53:16 +00:00
2017-07-29 16:14:22 +00:00
return menu ;
2007-09-16 01:02:06 +00:00
}
- ( NSRect ) windowWillUseStandardFrame : ( NSWindow * ) window defaultFrame : ( NSRect ) defaultFrame
{
// if auto size is enabled , the current frame shouldn ' t need to change
NSRect frame = [ fDefaults boolForKey : @ "AutoSize" ] ? [ window frame ] : [ self sizedWindowFrame ] ;
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
frame . size . width = [ fDefaults boolForKey : @ "SmallView" ] ? [ fWindow minSize ] . width : WINDOW_REGULAR _WIDTH ;
return frame ;
}
- ( void ) setWindowSizeToFit
{
if ( [ fDefaults boolForKey : @ "AutoSize" ] )
{
2008-02-06 23:45:44 +00:00
NSScrollView * scrollView = [ fTableView enclosingScrollView ] ;
2017-01-24 17:53:16 +00:00
2008-02-06 23:45:44 +00:00
[ scrollView setHasVerticalScroller : NO ] ;
2007-09-16 01:02:06 +00:00
[ fWindow setFrame : [ self sizedWindowFrame ] display : YES animate : YES ] ;
2008-02-06 23:45:44 +00:00
[ scrollView setHasVerticalScroller : YES ] ;
2017-01-24 17:53:16 +00:00
2011-07-18 00:48:00 +00:00
[ self setWindowMinMaxToCurrent ] ;
2007-09-16 01:02:06 +00:00
}
}
- ( NSRect ) sizedWindowFrame
{
2017-07-08 09:16:01 +00:00
NSUInteger groups = ( [ fDisplayedTorrents count ] > 0 && ! [ fDisplayedTorrents [ 0 ] isKindOfClass : [ Torrent class ] ] )
2012-09-09 12:58:53 +00:00
? [ fDisplayedTorrents count ] : 0 ;
2017-01-24 17:53:16 +00:00
2008-11-02 13:52:45 +00:00
CGFloat heightChange = ( GROUP_SEPARATOR _HEIGHT + [ fTableView intercellSpacing ] . height ) * groups
2012-09-09 12:58:53 +00:00
+ ( [ fTableView rowHeight ] + [ fTableView intercellSpacing ] . height ) * ( [ fTableView numberOfRows ] - groups )
- NSHeight ( [ [ fTableView enclosingScrollView ] frame ] ) ;
2017-01-24 17:53:16 +00:00
2007-09-16 01:02:06 +00:00
return [ self windowFrameByAddingHeight : heightChange checkLimits : YES ] ;
}
2011-07-18 00:48:00 +00:00
- ( void ) updateForAutoSize
{
if ( [ fDefaults boolForKey : @ "AutoSize" ] )
[ self setWindowSizeToFit ] ;
else
{
NSSize contentMinSize = [ fWindow contentMinSize ] ;
contentMinSize . height = [ self minWindowContentSizeAllowed ] ;
2017-01-24 17:53:16 +00:00
2011-07-18 00:48:00 +00:00
[ fWindow setContentMinSize : contentMinSize ] ;
2017-01-24 17:53:16 +00:00
2011-07-18 00:48:00 +00:00
NSSize contentMaxSize = [ fWindow contentMaxSize ] ;
contentMaxSize . height = FLT_MAX ;
[ fWindow setContentMaxSize : contentMaxSize ] ;
}
}
- ( void ) setWindowMinMaxToCurrent
{
const CGFloat height = NSHeight ( [ [ fWindow contentView ] frame ] ) ;
2017-01-24 17:53:16 +00:00
2011-07-18 00:48:00 +00:00
NSSize minSize = [ fWindow contentMinSize ] ,
2012-09-09 12:58:53 +00:00
maxSize = [ fWindow contentMaxSize ] ;
2011-07-18 00:48:00 +00:00
minSize . height = height ;
maxSize . height = height ;
2017-01-24 17:53:16 +00:00
2011-07-18 00:48:00 +00:00
[ fWindow setContentMinSize : minSize ] ;
[ fWindow setContentMaxSize : maxSize ] ;
}
- ( CGFloat ) minWindowContentSizeAllowed
{
CGFloat contentMinHeight = NSHeight ( [ [ fWindow contentView ] frame ] ) - NSHeight ( [ [ fTableView enclosingScrollView ] frame ] )
2012-09-09 12:58:53 +00:00
+ [ fTableView rowHeight ] + [ fTableView intercellSpacing ] . height ;
2011-07-18 00:48:00 +00:00
return contentMinHeight ;
}
2009-12-13 21:42:45 +00:00
- ( void ) updateForExpandCollape
{
[ self setWindowSizeToFit ] ;
[ self setBottomCountText : YES ] ;
}
- ( void ) showMainWindow : ( id ) sender
{
[ fWindow makeKeyAndOrderFront : nil ] ;
}
- ( void ) windowDidBecomeMain : ( NSNotification * ) notification
{
[ fBadger clearCompleted ] ;
[ self updateUI ] ;
}
2007-09-26 04:12:57 +00:00
- ( void ) applicationWillUnhide : ( NSNotification * ) notification
{
[ self updateUI ] ;
}
2008-05-21 16:28:21 +00:00
- ( void ) toggleQuickLook : ( id ) sender
2008-05-21 16:02:38 +00:00
{
2011-10-06 00:30:40 +00:00
if ( [ [ QLPreviewPanel sharedPreviewPanel ] isVisible ] )
[ [ QLPreviewPanel sharedPreviewPanel ] orderOut : nil ] ;
2009-09-04 04:10:46 +00:00
else
2011-10-06 00:30:40 +00:00
[ [ QLPreviewPanel sharedPreviewPanel ] makeKeyAndOrderFront : nil ] ;
2008-05-21 16:02:38 +00:00
}
2007-09-16 01:02:06 +00:00
- ( void ) linkHomepage : ( id ) sender
{
[ [ NSWorkspace sharedWorkspace ] openURL : [ NSURL URLWithString : WEBSITE_URL ] ] ;
}
- ( void ) linkForums : ( id ) sender
{
[ [ NSWorkspace sharedWorkspace ] openURL : [ NSURL URLWithString : FORUM_URL ] ] ;
}
2018-01-15 21:57:25 +00:00
- ( void ) linkGitHub : ( id ) sender
2008-09-07 14:51:50 +00:00
{
2018-01-15 21:57:25 +00:00
[ [ NSWorkspace sharedWorkspace ] openURL : [ NSURL URLWithString : GITHUB_URL ] ] ;
2008-09-07 14:51:50 +00:00
}
2007-09-16 01:02:06 +00:00
- ( void ) linkDonate : ( id ) sender
{
[ [ NSWorkspace sharedWorkspace ] openURL : [ NSURL URLWithString : DONATE_URL ] ] ;
}
2008-08-15 01:44:46 +00:00
- ( void ) updaterWillRelaunchApplication : ( SUUpdater * ) updater
2007-09-16 01:02:06 +00:00
{
2011-01-15 18:44:39 +00:00
fQuitRequested = YES ;
2007-09-16 01:02:06 +00:00
}
2008-05-20 15:16:34 +00:00
- ( void ) rpcCallback : ( tr_rpc _callback _type ) type forTorrentStruct : ( struct tr_torrent * ) torrentStruct
{
2012-02-11 05:13:46 +00:00
@ autoreleasepool
2008-05-20 15:16:34 +00:00
{
2012-02-11 05:13:46 +00:00
// get the torrent
2013-03-04 04:12:54 +00:00
__block Torrent * torrent = nil ;
2012-02-11 05:13:46 +00:00
if ( torrentStruct ! = NULL && ( type ! = TR_RPC _TORRENT _ADDED && type ! = TR_RPC _SESSION _CHANGED && type ! = TR_RPC _SESSION _CLOSE ) )
{
2013-03-04 04:12:54 +00:00
[ fTorrents enumerateObjectsWithOptions : NSEnumerationConcurrent usingBlock : ^ ( Torrent * checkTorrent , NSUInteger idx , BOOL * stop ) {
if ( torrentStruct = = [ checkTorrent torrentStruct ] )
2013-03-04 04:14:11 +00:00
{
2013-03-04 04:12:54 +00:00
torrent = checkTorrent ;
2013-03-04 04:14:11 +00:00
* stop = YES ;
}
2013-03-04 04:01:38 +00:00
} ] ;
2017-01-24 17:53:16 +00:00
2013-03-04 04:12:54 +00:00
if ( ! torrent )
2008-11-08 22:13:00 +00:00
{
2012-02-11 05:13:46 +00:00
NSLog ( @ "No torrent found matching the given torrent struct from the RPC callback!" ) ;
return ;
2008-11-08 22:13:00 +00:00
}
2012-02-11 05:13:46 +00:00
}
2017-01-24 17:53:16 +00:00
2013-03-04 04:01:38 +00:00
dispatch_async ( dispatch_get _main _queue ( ) , ^ {
switch ( type )
{
case TR_RPC _TORRENT _ADDED :
[ self rpcAddTorrentStruct : torrentStruct ] ;
break ;
2017-01-24 17:53:16 +00:00
2013-03-04 04:01:38 +00:00
case TR_RPC _TORRENT _STARTED :
case TR_RPC _TORRENT _STOPPED :
[ self rpcStartedStoppedTorrent : torrent ] ;
break ;
2017-01-24 17:53:16 +00:00
2013-03-04 04:01:38 +00:00
case TR_RPC _TORRENT _REMOVING :
2013-03-04 04:18:21 +00:00
[ self rpcRemoveTorrent : torrent deleteData : NO ] ;
2013-03-04 04:01:38 +00:00
break ;
2017-01-24 17:53:16 +00:00
2013-03-04 04:01:38 +00:00
case TR_RPC _TORRENT _TRASHING :
2013-03-04 04:18:21 +00:00
[ self rpcRemoveTorrent : torrent deleteData : YES ] ;
2013-03-04 04:01:38 +00:00
break ;
2017-01-24 17:53:16 +00:00
2013-03-04 04:01:38 +00:00
case TR_RPC _TORRENT _CHANGED :
[ self rpcChangedTorrent : torrent ] ;
break ;
2017-01-24 17:53:16 +00:00
2013-03-04 04:01:38 +00:00
case TR_RPC _TORRENT _MOVED :
[ self rpcMovedTorrent : torrent ] ;
break ;
2017-01-24 17:53:16 +00:00
2013-03-04 04:01:38 +00:00
case TR_RPC _SESSION _QUEUE _POSITIONS _CHANGED :
[ self rpcUpdateQueue ] ;
break ;
2017-01-24 17:53:16 +00:00
2013-03-04 04:01:38 +00:00
case TR_RPC _SESSION _CHANGED :
[ fPrefsController rpcUpdatePrefs ] ;
break ;
2017-01-24 17:53:16 +00:00
2013-03-04 04:01:38 +00:00
case TR_RPC _SESSION _CLOSE :
fQuitRequested = YES ;
[ NSApp terminate : self ] ;
break ;
2017-01-24 17:53:16 +00:00
2013-03-04 04:01:38 +00:00
default :
NSAssert1 ( NO , @ "Unknown RPC command received: %d" , type ) ;
}
} ) ;
2008-05-20 15:16:34 +00:00
}
}
2013-03-04 04:01:38 +00:00
- ( void ) rpcAddTorrentStruct : ( struct tr_torrent * ) torrentStruct
2008-05-27 00:52:18 +00:00
{
NSString * location = nil ;
2020-04-25 14:35:15 +00:00
if ( tr_torrentGetDownloadDir ( torrentStruct ) ! = NULL )
location = @ ( tr_torrentGetDownloadDir ( torrentStruct ) ) ;
2017-01-24 17:53:16 +00:00
2008-05-27 00:52:18 +00:00
Torrent * torrent = [ [ Torrent alloc ] initWithTorrentStruct : torrentStruct location : location lib : fLib ] ;
2017-01-24 17:53:16 +00:00
2011-09-27 01:37:41 +00:00
// change the location if the group calls for it ( this has to wait until after the torrent is created )
if ( [ [ GroupsController groups ] usesCustomDownloadLocationForIndex : [ torrent groupValue ] ] )
{
location = [ [ GroupsController groups ] customDownloadLocationForIndex : [ torrent groupValue ] ] ;
2012-10-30 00:22:10 +00:00
[ torrent changeDownloadFolderBeforeUsing : location determinationType : TorrentDeterminationAutomatic ] ;
2011-09-27 01:37:41 +00:00
}
2017-01-24 17:53:16 +00:00
2008-05-27 00:52:18 +00:00
[ torrent update ] ;
[ fTorrents addObject : torrent ] ;
2017-01-24 17:53:16 +00:00
2012-01-08 00:51:05 +00:00
if ( ! fAddingTransfers )
2012-01-08 04:11:07 +00:00
fAddingTransfers = [ [ NSMutableSet alloc ] init ] ;
2012-01-08 00:51:05 +00:00
[ fAddingTransfers addObject : torrent ] ;
2017-01-24 17:53:16 +00:00
2011-08-04 02:03:58 +00:00
[ self fullUpdateUI ] ;
2008-05-27 00:52:18 +00:00
}
2013-03-04 04:18:21 +00:00
- ( void ) rpcRemoveTorrent : ( Torrent * ) torrent deleteData : ( BOOL ) deleteData
2008-05-27 19:05:48 +00:00
{
2013-03-04 04:18:21 +00:00
[ self confirmRemoveTorrents : @ [ torrent ] deleteData : deleteData ] ;
2011-02-06 17:32:16 +00:00
}
2008-06-03 16:20:21 +00:00
- ( void ) rpcStartedStoppedTorrent : ( Torrent * ) torrent
{
[ torrent update ] ;
2017-01-24 17:53:16 +00:00
2008-06-03 16:20:21 +00:00
[ self updateUI ] ;
2011-02-20 03:58:50 +00:00
[ self applyFilter ] ;
2008-06-03 16:20:21 +00:00
[ self updateTorrentHistory ] ;
}
- ( void ) rpcChangedTorrent : ( Torrent * ) torrent
{
[ torrent update ] ;
2017-01-24 17:53:16 +00:00
2008-06-03 16:28:09 +00:00
if ( [ [ fTableView selectedTorrents ] containsObject : torrent ] )
{
2008-06-03 18:00:51 +00:00
[ fInfoController updateInfoStats ] ; // this will reload the file table
2008-06-03 16:28:09 +00:00
[ fInfoController updateOptions ] ;
}
2008-06-03 16:20:21 +00:00
}
2009-10-21 22:20:43 +00:00
- ( void ) rpcMovedTorrent : ( Torrent * ) torrent
{
[ torrent update ] ;
2010-11-13 16:11:22 +00:00
[ torrent updateTimeMachineExclude ] ;
2017-01-24 17:53:16 +00:00
2009-10-21 22:20:43 +00:00
if ( [ [ fTableView selectedTorrents ] containsObject : torrent ] )
[ fInfoController updateInfoStats ] ;
}
2011-08-27 23:54:10 +00:00
- ( void ) rpcUpdateQueue
{
for ( Torrent * torrent in fTorrents )
[ torrent update ] ;
2017-01-24 17:53:16 +00:00
2011-10-06 00:30:40 +00:00
NSSortDescriptor * descriptor = [ NSSortDescriptor sortDescriptorWithKey : @ "queuePosition" ascending : YES ] ;
2017-07-08 08:23:05 +00:00
NSArray * descriptors = @ [ descriptor ] ;
2011-08-27 23:54:10 +00:00
[ fTorrents sortUsingDescriptors : descriptors ] ;
2017-01-24 17:53:16 +00:00
2013-03-04 04:01:38 +00:00
[ self sortTorrents : YES ] ;
2011-08-27 23:54:10 +00:00
}
2007-09-16 01:02:06 +00:00
@ end