Use properties instead of ivars (#2453)
This commit is contained in:
parent
95e30768c4
commit
54d1a02e92
|
@ -3473,6 +3473,7 @@
|
|||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
|
@ -3630,6 +3631,7 @@
|
|||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
|
@ -3712,6 +3714,7 @@
|
|||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
|
|
|
@ -5,15 +5,6 @@
|
|||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
@interface AboutWindowController : NSWindowController
|
||||
{
|
||||
IBOutlet NSTextView* fTextView;
|
||||
IBOutlet NSTextView* fLicenseView;
|
||||
IBOutlet NSTextField* fVersionField;
|
||||
IBOutlet NSTextField* fCopyrightField;
|
||||
IBOutlet NSButton* fLicenseButton;
|
||||
IBOutlet NSButton* fLicenseCloseButton;
|
||||
IBOutlet NSPanel* fLicenseSheet;
|
||||
}
|
||||
|
||||
@property(nonatomic, class, readonly) AboutWindowController* aboutController;
|
||||
|
||||
|
|
|
@ -6,6 +6,18 @@
|
|||
|
||||
#import "AboutWindowController.h"
|
||||
|
||||
@interface AboutWindowController ()
|
||||
|
||||
@property(nonatomic) IBOutlet NSTextView* fTextView;
|
||||
@property(nonatomic) IBOutlet NSTextView* fLicenseView;
|
||||
@property(nonatomic) IBOutlet NSTextField* fVersionField;
|
||||
@property(nonatomic) IBOutlet NSTextField* fCopyrightField;
|
||||
@property(nonatomic) IBOutlet NSButton* fLicenseButton;
|
||||
@property(nonatomic) IBOutlet NSButton* fLicenseCloseButton;
|
||||
@property(nonatomic) IBOutlet NSPanel* fLicenseSheet;
|
||||
|
||||
@end
|
||||
|
||||
@implementation AboutWindowController
|
||||
|
||||
AboutWindowController* fAboutBoxInstance = nil;
|
||||
|
@ -21,25 +33,25 @@ AboutWindowController* fAboutBoxInstance = nil;
|
|||
|
||||
- (void)awakeFromNib
|
||||
{
|
||||
fVersionField.stringValue = @(LONG_VERSION_STRING);
|
||||
self.fVersionField.stringValue = @(LONG_VERSION_STRING);
|
||||
|
||||
fCopyrightField.stringValue = [NSBundle.mainBundle localizedStringForKey:@"NSHumanReadableCopyright" value:nil
|
||||
self.fCopyrightField.stringValue = [NSBundle.mainBundle localizedStringForKey:@"NSHumanReadableCopyright" value:nil
|
||||
table:@"InfoPlist"];
|
||||
|
||||
[fTextView.textStorage setAttributedString:[[NSAttributedString alloc] initWithPath:[NSBundle.mainBundle pathForResource:@"Credits"
|
||||
[self.fTextView.textStorage setAttributedString:[[NSAttributedString alloc] initWithPath:[NSBundle.mainBundle pathForResource:@"Credits"
|
||||
ofType:@"rtf"]
|
||||
documentAttributes:nil]];
|
||||
|
||||
//size license button
|
||||
CGFloat const oldButtonWidth = NSWidth(fLicenseButton.frame);
|
||||
CGFloat const oldButtonWidth = NSWidth(self.fLicenseButton.frame);
|
||||
|
||||
fLicenseButton.title = NSLocalizedString(@"License", "About window -> license button");
|
||||
[fLicenseButton sizeToFit];
|
||||
self.fLicenseButton.title = NSLocalizedString(@"License", "About window -> license button");
|
||||
[self.fLicenseButton sizeToFit];
|
||||
|
||||
NSRect buttonFrame = fLicenseButton.frame;
|
||||
NSRect buttonFrame = self.fLicenseButton.frame;
|
||||
buttonFrame.size.width += 10.0;
|
||||
buttonFrame.origin.x -= NSWidth(buttonFrame) - oldButtonWidth;
|
||||
fLicenseButton.frame = buttonFrame;
|
||||
self.fLicenseButton.frame = buttonFrame;
|
||||
}
|
||||
|
||||
- (void)windowDidLoad
|
||||
|
@ -57,16 +69,16 @@ AboutWindowController* fAboutBoxInstance = nil;
|
|||
NSString* licenseText = [NSString stringWithContentsOfFile:[NSBundle.mainBundle pathForResource:@"COPYING" ofType:nil]
|
||||
usedEncoding:nil
|
||||
error:NULL];
|
||||
fLicenseView.string = licenseText;
|
||||
fLicenseCloseButton.title = NSLocalizedString(@"OK", "About window -> license close button");
|
||||
self.fLicenseView.string = licenseText;
|
||||
self.fLicenseCloseButton.title = NSLocalizedString(@"OK", "About window -> license close button");
|
||||
|
||||
[self.window beginSheet:fLicenseSheet completionHandler:nil];
|
||||
[self.window beginSheet:self.fLicenseSheet completionHandler:nil];
|
||||
}
|
||||
|
||||
- (IBAction)hideLicense:(id)sender
|
||||
{
|
||||
[fLicenseSheet orderOut:nil];
|
||||
[NSApp endSheet:fLicenseSheet];
|
||||
[self.fLicenseSheet orderOut:nil];
|
||||
[NSApp endSheet:self.fLicenseSheet];
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -4,43 +4,15 @@
|
|||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
#import "Torrent.h"
|
||||
|
||||
@class Controller;
|
||||
@class Torrent;
|
||||
|
||||
@interface AddMagnetWindowController : NSWindowController
|
||||
{
|
||||
IBOutlet NSImageView* fLocationImageView;
|
||||
IBOutlet NSTextField* fNameField;
|
||||
IBOutlet NSTextField* fLocationField;
|
||||
IBOutlet NSButton* fStartCheck;
|
||||
IBOutlet NSPopUpButton* fGroupPopUp;
|
||||
IBOutlet NSPopUpButton* fPriorityPopUp;
|
||||
|
||||
//remove these when switching to auto layout
|
||||
IBOutlet NSTextField* fMagnetLinkLabel;
|
||||
IBOutlet NSTextField* fDownloadToLabel;
|
||||
IBOutlet NSTextField* fGroupLabel;
|
||||
IBOutlet NSTextField* fPriorityLabel;
|
||||
IBOutlet NSButton* fChangeDestinationButton;
|
||||
IBOutlet NSBox* fDownloadToBox;
|
||||
IBOutlet NSButton* fAddButton;
|
||||
IBOutlet NSButton* fCancelButton;
|
||||
|
||||
Controller* fController;
|
||||
|
||||
Torrent* fTorrent;
|
||||
NSString* fDestination;
|
||||
|
||||
NSInteger fGroupValue;
|
||||
TorrentDeterminationType fGroupDeterminationType;
|
||||
}
|
||||
|
||||
- (instancetype)initWithTorrent:(Torrent*)torrent destination:(NSString*)path controller:(Controller*)controller;
|
||||
|
||||
@property(nonatomic, readonly) Torrent* torrent;
|
||||
|
||||
- (instancetype)initWithTorrent:(Torrent*)torrent destination:(NSString*)path controller:(Controller*)controller;
|
||||
|
||||
- (void)setDestination:(id)sender;
|
||||
|
||||
- (void)add:(id)sender;
|
||||
|
|
|
@ -15,6 +15,30 @@
|
|||
|
||||
@interface AddMagnetWindowController ()
|
||||
|
||||
@property(nonatomic) IBOutlet NSImageView* fLocationImageView;
|
||||
@property(nonatomic) IBOutlet NSTextField* fNameField;
|
||||
@property(nonatomic) IBOutlet NSTextField* fLocationField;
|
||||
@property(nonatomic) IBOutlet NSButton* fStartCheck;
|
||||
@property(nonatomic) IBOutlet NSPopUpButton* fGroupPopUp;
|
||||
@property(nonatomic) IBOutlet NSPopUpButton* fPriorityPopUp;
|
||||
|
||||
//remove these when switching to auto layout
|
||||
@property(nonatomic) IBOutlet NSTextField* fMagnetLinkLabel;
|
||||
@property(nonatomic) IBOutlet NSTextField* fDownloadToLabel;
|
||||
@property(nonatomic) IBOutlet NSTextField* fGroupLabel;
|
||||
@property(nonatomic) IBOutlet NSTextField* fPriorityLabel;
|
||||
@property(nonatomic) IBOutlet NSButton* fChangeDestinationButton;
|
||||
@property(nonatomic) IBOutlet NSBox* fDownloadToBox;
|
||||
@property(nonatomic) IBOutlet NSButton* fAddButton;
|
||||
@property(nonatomic) IBOutlet NSButton* fCancelButton;
|
||||
|
||||
@property(nonatomic, readonly) Controller* fController;
|
||||
|
||||
@property(nonatomic) NSString* fDestination;
|
||||
|
||||
@property(nonatomic) NSInteger fGroupValue;
|
||||
@property(nonatomic) TorrentDeterminationType fGroupDeterminationType;
|
||||
|
||||
- (void)confirmAdd;
|
||||
|
||||
- (void)setDestinationPath:(NSString*)destination determinationType:(TorrentDeterminationType)determinationType;
|
||||
|
@ -30,13 +54,13 @@
|
|||
{
|
||||
if ((self = [super initWithWindowNibName:@"AddMagnetWindow"]))
|
||||
{
|
||||
fTorrent = torrent;
|
||||
fDestination = path.stringByExpandingTildeInPath;
|
||||
_torrent = torrent;
|
||||
_fDestination = path.stringByExpandingTildeInPath;
|
||||
|
||||
fController = controller;
|
||||
_fController = controller;
|
||||
|
||||
fGroupValue = torrent.groupValue;
|
||||
fGroupDeterminationType = TorrentDeterminationAutomatic;
|
||||
_fGroupValue = torrent.groupValue;
|
||||
_fGroupDeterminationType = TorrentDeterminationAutomatic;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
@ -45,16 +69,16 @@
|
|||
{
|
||||
[NSNotificationCenter.defaultCenter addObserver:self selector:@selector(updateGroupMenu:) name:@"UpdateGroups" object:nil];
|
||||
|
||||
NSString* name = fTorrent.name;
|
||||
NSString* name = self.torrent.name;
|
||||
self.window.title = name;
|
||||
fNameField.stringValue = name;
|
||||
fNameField.toolTip = name;
|
||||
self.fNameField.stringValue = name;
|
||||
self.fNameField.toolTip = name;
|
||||
|
||||
[self setGroupsMenu];
|
||||
[fGroupPopUp selectItemWithTag:fGroupValue];
|
||||
[self.fGroupPopUp selectItemWithTag:self.fGroupValue];
|
||||
|
||||
NSInteger priorityIndex;
|
||||
switch (fTorrent.priority)
|
||||
switch (self.torrent.priority)
|
||||
{
|
||||
case TR_PRI_HIGH:
|
||||
priorityIndex = POPUP_PRIORITY_HIGH;
|
||||
|
@ -66,49 +90,49 @@
|
|||
priorityIndex = POPUP_PRIORITY_LOW;
|
||||
break;
|
||||
default:
|
||||
NSAssert1(NO, @"Unknown priority for adding torrent: %d", fTorrent.priority);
|
||||
NSAssert1(NO, @"Unknown priority for adding torrent: %d", self.torrent.priority);
|
||||
priorityIndex = POPUP_PRIORITY_NORMAL;
|
||||
}
|
||||
[fPriorityPopUp selectItemAtIndex:priorityIndex];
|
||||
[self.fPriorityPopUp selectItemAtIndex:priorityIndex];
|
||||
|
||||
fStartCheck.state = [NSUserDefaults.standardUserDefaults boolForKey:@"AutoStartDownload"] ? NSControlStateValueOn
|
||||
self.fStartCheck.state = [NSUserDefaults.standardUserDefaults boolForKey:@"AutoStartDownload"] ? NSControlStateValueOn
|
||||
: NSControlStateValueOff;
|
||||
|
||||
if (fDestination)
|
||||
if (self.fDestination)
|
||||
{
|
||||
[self setDestinationPath:fDestination determinationType:TorrentDeterminationAutomatic];
|
||||
[self setDestinationPath:self.fDestination determinationType:TorrentDeterminationAutomatic];
|
||||
}
|
||||
else
|
||||
{
|
||||
fLocationField.stringValue = @"";
|
||||
fLocationImageView.image = nil;
|
||||
self.fLocationField.stringValue = @"";
|
||||
self.fLocationImageView.image = nil;
|
||||
}
|
||||
|
||||
#warning when 10.7-only, switch to auto layout
|
||||
[fMagnetLinkLabel sizeToFit];
|
||||
[self.fMagnetLinkLabel sizeToFit];
|
||||
|
||||
CGFloat const downloadToLabelOldWidth = fDownloadToLabel.frame.size.width;
|
||||
[fDownloadToLabel sizeToFit];
|
||||
CGFloat const changeDestOldWidth = fChangeDestinationButton.frame.size.width;
|
||||
[fChangeDestinationButton sizeToFit];
|
||||
NSRect changeDestFrame = fChangeDestinationButton.frame;
|
||||
CGFloat const downloadToLabelOldWidth = self.fDownloadToLabel.frame.size.width;
|
||||
[self.fDownloadToLabel sizeToFit];
|
||||
CGFloat const changeDestOldWidth = self.fChangeDestinationButton.frame.size.width;
|
||||
[self.fChangeDestinationButton sizeToFit];
|
||||
NSRect changeDestFrame = self.fChangeDestinationButton.frame;
|
||||
changeDestFrame.origin.x -= changeDestFrame.size.width - changeDestOldWidth;
|
||||
fChangeDestinationButton.frame = changeDestFrame;
|
||||
self.fChangeDestinationButton.frame = changeDestFrame;
|
||||
|
||||
NSRect downloadToBoxFrame = fDownloadToBox.frame;
|
||||
CGFloat const downloadToBoxSizeDiff = (fDownloadToLabel.frame.size.width - downloadToLabelOldWidth) +
|
||||
NSRect downloadToBoxFrame = self.fDownloadToBox.frame;
|
||||
CGFloat const downloadToBoxSizeDiff = (self.fDownloadToLabel.frame.size.width - downloadToLabelOldWidth) +
|
||||
(changeDestFrame.size.width - changeDestOldWidth);
|
||||
downloadToBoxFrame.size.width -= downloadToBoxSizeDiff;
|
||||
downloadToBoxFrame.origin.x -= downloadToLabelOldWidth - fDownloadToLabel.frame.size.width;
|
||||
fDownloadToBox.frame = downloadToBoxFrame;
|
||||
downloadToBoxFrame.origin.x -= downloadToLabelOldWidth - self.fDownloadToLabel.frame.size.width;
|
||||
self.fDownloadToBox.frame = downloadToBoxFrame;
|
||||
|
||||
NSRect groupPopUpFrame = fGroupPopUp.frame;
|
||||
NSRect priorityPopUpFrame = fPriorityPopUp.frame;
|
||||
CGFloat const popUpOffset = groupPopUpFrame.origin.x - NSMaxX(fGroupLabel.frame);
|
||||
[fGroupLabel sizeToFit];
|
||||
[fPriorityLabel sizeToFit];
|
||||
NSRect groupLabelFrame = fGroupLabel.frame;
|
||||
NSRect priorityLabelFrame = fPriorityLabel.frame;
|
||||
NSRect groupPopUpFrame = self.fGroupPopUp.frame;
|
||||
NSRect priorityPopUpFrame = self.fPriorityPopUp.frame;
|
||||
CGFloat const popUpOffset = groupPopUpFrame.origin.x - NSMaxX(self.fGroupLabel.frame);
|
||||
[self.fGroupLabel sizeToFit];
|
||||
[self.fPriorityLabel sizeToFit];
|
||||
NSRect groupLabelFrame = self.fGroupLabel.frame;
|
||||
NSRect priorityLabelFrame = self.fPriorityLabel.frame;
|
||||
//first bring them both to the left edge
|
||||
groupLabelFrame.origin.x = MIN(groupLabelFrame.origin.x, priorityLabelFrame.origin.x);
|
||||
priorityLabelFrame.origin.x = MIN(groupLabelFrame.origin.x, priorityLabelFrame.origin.x);
|
||||
|
@ -118,18 +142,18 @@
|
|||
priorityLabelFrame.origin.x += labelWidth - priorityLabelFrame.size.width;
|
||||
groupPopUpFrame.origin.x = NSMaxX(groupLabelFrame) + popUpOffset;
|
||||
priorityPopUpFrame.origin.x = NSMaxX(priorityLabelFrame) + popUpOffset;
|
||||
fGroupLabel.frame = groupLabelFrame;
|
||||
fGroupPopUp.frame = groupPopUpFrame;
|
||||
fPriorityLabel.frame = priorityLabelFrame;
|
||||
fPriorityPopUp.frame = priorityPopUpFrame;
|
||||
self.fGroupLabel.frame = groupLabelFrame;
|
||||
self.fGroupPopUp.frame = groupPopUpFrame;
|
||||
self.fPriorityLabel.frame = priorityLabelFrame;
|
||||
self.fPriorityPopUp.frame = priorityPopUpFrame;
|
||||
|
||||
CGFloat const minButtonWidth = 82.0;
|
||||
CGFloat const oldAddButtonWidth = fAddButton.bounds.size.width;
|
||||
CGFloat const oldCancelButtonWidth = fCancelButton.bounds.size.width;
|
||||
[fAddButton sizeToFit];
|
||||
[fCancelButton sizeToFit];
|
||||
NSRect addButtonFrame = fAddButton.frame;
|
||||
NSRect cancelButtonFrame = fCancelButton.frame;
|
||||
CGFloat const oldAddButtonWidth = self.fAddButton.bounds.size.width;
|
||||
CGFloat const oldCancelButtonWidth = self.fCancelButton.bounds.size.width;
|
||||
[self.fAddButton sizeToFit];
|
||||
[self.fCancelButton sizeToFit];
|
||||
NSRect addButtonFrame = self.fAddButton.frame;
|
||||
NSRect cancelButtonFrame = self.fCancelButton.frame;
|
||||
CGFloat buttonWidth = MAX(addButtonFrame.size.width, cancelButtonFrame.size.width);
|
||||
buttonWidth = MAX(buttonWidth, minButtonWidth);
|
||||
addButtonFrame.size.width = buttonWidth;
|
||||
|
@ -137,16 +161,16 @@
|
|||
CGFloat const addButtonWidthIncrease = buttonWidth - oldAddButtonWidth;
|
||||
addButtonFrame.origin.x -= addButtonWidthIncrease;
|
||||
cancelButtonFrame.origin.x -= addButtonWidthIncrease + (buttonWidth - oldCancelButtonWidth);
|
||||
fAddButton.frame = addButtonFrame;
|
||||
fCancelButton.frame = cancelButtonFrame;
|
||||
self.fAddButton.frame = addButtonFrame;
|
||||
self.fCancelButton.frame = cancelButtonFrame;
|
||||
|
||||
[fStartCheck sizeToFit];
|
||||
[self.fStartCheck sizeToFit];
|
||||
}
|
||||
|
||||
- (void)windowDidLoad
|
||||
{
|
||||
//if there is no destination, prompt for one right away
|
||||
if (!fDestination)
|
||||
if (!self.fDestination)
|
||||
{
|
||||
[self setDestination:nil];
|
||||
}
|
||||
|
@ -157,11 +181,6 @@
|
|||
[NSNotificationCenter.defaultCenter removeObserver:self];
|
||||
}
|
||||
|
||||
- (Torrent*)torrent
|
||||
{
|
||||
return fTorrent;
|
||||
}
|
||||
|
||||
- (void)setDestination:(id)sender
|
||||
{
|
||||
NSOpenPanel* panel = [NSOpenPanel openPanel];
|
||||
|
@ -173,7 +192,7 @@
|
|||
panel.canCreateDirectories = YES;
|
||||
|
||||
panel.message = [NSString stringWithFormat:NSLocalizedString(@"Select the download folder for \"%@\"", "Add -> select destination folder"),
|
||||
fTorrent.name];
|
||||
self.torrent.name];
|
||||
|
||||
[panel beginSheetModalForWindow:self.window completionHandler:^(NSInteger result) {
|
||||
if (result == NSModalResponseOK)
|
||||
|
@ -182,7 +201,7 @@
|
|||
}
|
||||
else
|
||||
{
|
||||
if (!fDestination)
|
||||
if (!self.fDestination)
|
||||
{
|
||||
[self performSelectorOnMainThread:@selector(cancelAdd:) withObject:nil waitUntilDone:NO];
|
||||
}
|
||||
|
@ -192,7 +211,7 @@
|
|||
|
||||
- (void)add:(id)sender
|
||||
{
|
||||
if ([fDestination.lastPathComponent isEqualToString:fTorrent.name] &&
|
||||
if ([self.fDestination.lastPathComponent isEqualToString:self.torrent.name] &&
|
||||
[NSUserDefaults.standardUserDefaults boolForKey:@"WarningFolderDataSameName"])
|
||||
{
|
||||
NSAlert* alert = [[NSAlert alloc] init];
|
||||
|
@ -232,7 +251,7 @@
|
|||
//only called on cancel
|
||||
- (BOOL)windowShouldClose:(id)window
|
||||
{
|
||||
[fController askOpenMagnetConfirmed:self add:NO];
|
||||
[self.fController askOpenMagnetConfirmed:self add:NO];
|
||||
return YES;
|
||||
}
|
||||
|
||||
|
@ -254,68 +273,70 @@
|
|||
NSAssert1(NO, @"Unknown priority tag for adding torrent: %ld", [sender tag]);
|
||||
priority = TR_PRI_NORMAL;
|
||||
}
|
||||
fTorrent.priority = priority;
|
||||
self.torrent.priority = priority;
|
||||
}
|
||||
|
||||
- (void)updateGroupMenu:(NSNotification*)notification
|
||||
{
|
||||
[self setGroupsMenu];
|
||||
if (![fGroupPopUp selectItemWithTag:fGroupValue])
|
||||
if (![self.fGroupPopUp selectItemWithTag:self.fGroupValue])
|
||||
{
|
||||
fGroupValue = -1;
|
||||
fGroupDeterminationType = TorrentDeterminationAutomatic;
|
||||
[fGroupPopUp selectItemWithTag:fGroupValue];
|
||||
self.fGroupValue = -1;
|
||||
self.fGroupDeterminationType = TorrentDeterminationAutomatic;
|
||||
[self.fGroupPopUp selectItemWithTag:self.fGroupValue];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
- (void)confirmAdd
|
||||
{
|
||||
[fTorrent setGroupValue:fGroupValue determinationType:fGroupDeterminationType];
|
||||
[self.torrent setGroupValue:self.fGroupValue determinationType:self.fGroupDeterminationType];
|
||||
|
||||
if (fStartCheck.state == NSControlStateValueOn)
|
||||
if (self.fStartCheck.state == NSControlStateValueOn)
|
||||
{
|
||||
[fTorrent startTransfer];
|
||||
[self.torrent startTransfer];
|
||||
}
|
||||
|
||||
[self close];
|
||||
[fController askOpenMagnetConfirmed:self add:YES];
|
||||
[self.fController askOpenMagnetConfirmed:self add:YES];
|
||||
}
|
||||
|
||||
- (void)setDestinationPath:(NSString*)destination determinationType:(TorrentDeterminationType)determinationType
|
||||
{
|
||||
destination = destination.stringByExpandingTildeInPath;
|
||||
if (!fDestination || ![fDestination isEqualToString:destination])
|
||||
if (!self.fDestination || ![self.fDestination isEqualToString:destination])
|
||||
{
|
||||
fDestination = destination;
|
||||
self.fDestination = destination;
|
||||
|
||||
[fTorrent changeDownloadFolderBeforeUsing:fDestination determinationType:determinationType];
|
||||
[self.torrent changeDownloadFolderBeforeUsing:self.fDestination determinationType:determinationType];
|
||||
}
|
||||
|
||||
fLocationField.stringValue = fDestination.stringByAbbreviatingWithTildeInPath;
|
||||
fLocationField.toolTip = fDestination;
|
||||
self.fLocationField.stringValue = self.fDestination.stringByAbbreviatingWithTildeInPath;
|
||||
self.fLocationField.toolTip = self.fDestination;
|
||||
|
||||
ExpandedPathToIconTransformer* iconTransformer = [[ExpandedPathToIconTransformer alloc] init];
|
||||
fLocationImageView.image = [iconTransformer transformedValue:fDestination];
|
||||
self.fLocationImageView.image = [iconTransformer transformedValue:self.fDestination];
|
||||
}
|
||||
|
||||
- (void)setGroupsMenu
|
||||
{
|
||||
NSMenu* groupMenu = [GroupsController.groups groupMenuWithTarget:self action:@selector(changeGroupValue:) isSmall:NO];
|
||||
fGroupPopUp.menu = groupMenu;
|
||||
self.fGroupPopUp.menu = groupMenu;
|
||||
}
|
||||
|
||||
- (void)changeGroupValue:(id)sender
|
||||
{
|
||||
NSInteger previousGroup = fGroupValue;
|
||||
fGroupValue = [sender tag];
|
||||
fGroupDeterminationType = TorrentDeterminationUserSpecified;
|
||||
NSInteger previousGroup = self.fGroupValue;
|
||||
self.fGroupValue = [sender tag];
|
||||
self.fGroupDeterminationType = TorrentDeterminationUserSpecified;
|
||||
|
||||
if ([GroupsController.groups usesCustomDownloadLocationForIndex:fGroupValue])
|
||||
if ([GroupsController.groups usesCustomDownloadLocationForIndex:self.fGroupValue])
|
||||
{
|
||||
[self setDestinationPath:[GroupsController.groups customDownloadLocationForIndex:fGroupValue]
|
||||
[self setDestinationPath:[GroupsController.groups customDownloadLocationForIndex:self.fGroupValue]
|
||||
determinationType:TorrentDeterminationAutomatic];
|
||||
}
|
||||
else if ([fDestination isEqualToString:[GroupsController.groups customDownloadLocationForIndex:previousGroup]])
|
||||
else if ([self.fDestination isEqualToString:[GroupsController.groups customDownloadLocationForIndex:previousGroup]])
|
||||
{
|
||||
[self setDestinationPath:[NSUserDefaults.standardUserDefaults stringForKey:@"DownloadFolder"]
|
||||
determinationType:TorrentDeterminationAutomatic];
|
||||
|
|
|
@ -4,47 +4,12 @@
|
|||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
#import "Torrent.h"
|
||||
|
||||
@class Controller;
|
||||
@class FileOutlineController;
|
||||
@class Torrent;
|
||||
|
||||
@interface AddWindowController : NSWindowController
|
||||
{
|
||||
IBOutlet NSImageView* fIconView;
|
||||
IBOutlet NSImageView* fLocationImageView;
|
||||
IBOutlet NSTextField* fNameField;
|
||||
IBOutlet NSTextField* fStatusField;
|
||||
IBOutlet NSTextField* fLocationField;
|
||||
IBOutlet NSButton* fStartCheck;
|
||||
IBOutlet NSButton* fDeleteCheck;
|
||||
IBOutlet NSPopUpButton* fGroupPopUp;
|
||||
IBOutlet NSPopUpButton* fPriorityPopUp;
|
||||
IBOutlet NSProgressIndicator* fVerifyIndicator;
|
||||
|
||||
IBOutlet NSTextField* fFileFilterField;
|
||||
IBOutlet NSButton* fCheckAllButton;
|
||||
IBOutlet NSButton* fUncheckAllButton;
|
||||
|
||||
IBOutlet FileOutlineController* fFileController;
|
||||
IBOutlet NSScrollView* fFileScrollView;
|
||||
|
||||
Controller* fController;
|
||||
|
||||
Torrent* fTorrent;
|
||||
NSString* fDestination;
|
||||
NSString* fTorrentFile;
|
||||
BOOL fLockDestination;
|
||||
|
||||
BOOL fDeleteTorrentEnableInitially;
|
||||
BOOL fCanToggleDelete;
|
||||
NSInteger fGroupValue;
|
||||
|
||||
NSTimer* fTimer;
|
||||
|
||||
TorrentDeterminationType fGroupValueDetermination;
|
||||
}
|
||||
@property(nonatomic, readonly) Torrent* torrent;
|
||||
|
||||
// if canToggleDelete is NO, we will also not delete the file regardless of the delete check's state
|
||||
// (this is so it can be disabled and checked for a downloaded torrent, where the file's already deleted)
|
||||
|
@ -56,8 +21,6 @@
|
|||
deleteTorrentCheckEnableInitially:(BOOL)deleteTorrent
|
||||
canToggleDelete:(BOOL)canToggleDelete;
|
||||
|
||||
@property(nonatomic, readonly) Torrent* torrent;
|
||||
|
||||
- (void)setDestination:(id)sender;
|
||||
|
||||
- (void)add:(id)sender;
|
||||
|
|
|
@ -18,6 +18,38 @@
|
|||
|
||||
@interface AddWindowController ()
|
||||
|
||||
@property(nonatomic) IBOutlet NSImageView* fIconView;
|
||||
@property(nonatomic) IBOutlet NSImageView* fLocationImageView;
|
||||
@property(nonatomic) IBOutlet NSTextField* fNameField;
|
||||
@property(nonatomic) IBOutlet NSTextField* fStatusField;
|
||||
@property(nonatomic) IBOutlet NSTextField* fLocationField;
|
||||
@property(nonatomic) IBOutlet NSButton* fStartCheck;
|
||||
@property(nonatomic) IBOutlet NSButton* fDeleteCheck;
|
||||
@property(nonatomic) IBOutlet NSPopUpButton* fGroupPopUp;
|
||||
@property(nonatomic) IBOutlet NSPopUpButton* fPriorityPopUp;
|
||||
@property(nonatomic) IBOutlet NSProgressIndicator* fVerifyIndicator;
|
||||
|
||||
@property(nonatomic) IBOutlet NSTextField* fFileFilterField;
|
||||
@property(nonatomic) IBOutlet NSButton* fCheckAllButton;
|
||||
@property(nonatomic) IBOutlet NSButton* fUncheckAllButton;
|
||||
|
||||
@property(nonatomic) IBOutlet FileOutlineController* fFileController;
|
||||
@property(nonatomic) IBOutlet NSScrollView* fFileScrollView;
|
||||
|
||||
@property(nonatomic, readonly) Controller* fController;
|
||||
|
||||
@property(nonatomic, copy) NSString* fDestination;
|
||||
@property(nonatomic, readonly) NSString* fTorrentFile;
|
||||
@property(nonatomic) BOOL fLockDestination;
|
||||
|
||||
@property(nonatomic, readonly) BOOL fDeleteTorrentEnableInitially;
|
||||
@property(nonatomic, readonly) BOOL fCanToggleDelete;
|
||||
@property(nonatomic) NSInteger fGroupValue;
|
||||
|
||||
@property(nonatomic, weak) NSTimer* fTimer;
|
||||
|
||||
@property(nonatomic) TorrentDeterminationType fGroupValueDetermination;
|
||||
|
||||
- (void)updateFiles;
|
||||
|
||||
- (void)confirmAdd;
|
||||
|
@ -41,21 +73,21 @@
|
|||
{
|
||||
if ((self = [super initWithWindowNibName:@"AddWindow"]))
|
||||
{
|
||||
fTorrent = torrent;
|
||||
fDestination = path.stringByExpandingTildeInPath;
|
||||
fLockDestination = lockDestination;
|
||||
_torrent = torrent;
|
||||
_fDestination = path.stringByExpandingTildeInPath;
|
||||
_fLockDestination = lockDestination;
|
||||
|
||||
fController = controller;
|
||||
_fController = controller;
|
||||
|
||||
fTorrentFile = torrentFile.stringByExpandingTildeInPath;
|
||||
_fTorrentFile = torrentFile.stringByExpandingTildeInPath;
|
||||
|
||||
fDeleteTorrentEnableInitially = deleteTorrent;
|
||||
fCanToggleDelete = canToggleDelete;
|
||||
_fDeleteTorrentEnableInitially = deleteTorrent;
|
||||
_fCanToggleDelete = canToggleDelete;
|
||||
|
||||
fGroupValue = torrent.groupValue;
|
||||
fGroupValueDetermination = TorrentDeterminationAutomatic;
|
||||
_fGroupValue = torrent.groupValue;
|
||||
_fGroupValueDetermination = TorrentDeterminationAutomatic;
|
||||
|
||||
fVerifyIndicator.usesThreadedAnimation = YES;
|
||||
_fVerifyIndicator.usesThreadedAnimation = YES;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
@ -63,30 +95,30 @@
|
|||
- (void)awakeFromNib
|
||||
{
|
||||
[NSNotificationCenter.defaultCenter addObserver:self selector:@selector(updateCheckButtons:) name:@"TorrentFileCheckChange"
|
||||
object:fTorrent];
|
||||
object:self.torrent];
|
||||
|
||||
[NSNotificationCenter.defaultCenter addObserver:self selector:@selector(updateGroupMenu:) name:@"UpdateGroups" object:nil];
|
||||
|
||||
[fFileController setTorrent:fTorrent];
|
||||
self.fFileController.torrent = self.torrent;
|
||||
|
||||
NSString* name = fTorrent.name;
|
||||
NSString* name = self.torrent.name;
|
||||
self.window.title = name;
|
||||
fNameField.stringValue = name;
|
||||
fNameField.toolTip = name;
|
||||
self.fNameField.stringValue = name;
|
||||
self.fNameField.toolTip = name;
|
||||
|
||||
fIconView.image = fTorrent.icon;
|
||||
self.fIconView.image = self.torrent.icon;
|
||||
|
||||
if (!fTorrent.folder)
|
||||
if (!self.torrent.folder)
|
||||
{
|
||||
fFileFilterField.hidden = YES;
|
||||
fCheckAllButton.hidden = YES;
|
||||
fUncheckAllButton.hidden = YES;
|
||||
self.fFileFilterField.hidden = YES;
|
||||
self.fCheckAllButton.hidden = YES;
|
||||
self.fUncheckAllButton.hidden = YES;
|
||||
|
||||
NSRect scrollFrame = fFileScrollView.frame;
|
||||
CGFloat const diff = NSMinY(fFileScrollView.frame) - NSMinY(fFileFilterField.frame);
|
||||
NSRect scrollFrame = self.fFileScrollView.frame;
|
||||
CGFloat const diff = NSMinY(self.fFileScrollView.frame) - NSMinY(self.fFileFilterField.frame);
|
||||
scrollFrame.origin.y -= diff;
|
||||
scrollFrame.size.height += diff;
|
||||
fFileScrollView.frame = scrollFrame;
|
||||
self.fFileScrollView.frame = scrollFrame;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -94,10 +126,10 @@
|
|||
}
|
||||
|
||||
[self setGroupsMenu];
|
||||
[fGroupPopUp selectItemWithTag:fGroupValue];
|
||||
[self.fGroupPopUp selectItemWithTag:self.fGroupValue];
|
||||
|
||||
NSInteger priorityIndex;
|
||||
switch (fTorrent.priority)
|
||||
switch (self.torrent.priority)
|
||||
{
|
||||
case TR_PRI_HIGH:
|
||||
priorityIndex = POPUP_PRIORITY_HIGH;
|
||||
|
@ -109,29 +141,29 @@
|
|||
priorityIndex = POPUP_PRIORITY_LOW;
|
||||
break;
|
||||
default:
|
||||
NSAssert1(NO, @"Unknown priority for adding torrent: %d", fTorrent.priority);
|
||||
NSAssert1(NO, @"Unknown priority for adding torrent: %d", self.torrent.priority);
|
||||
priorityIndex = POPUP_PRIORITY_NORMAL;
|
||||
}
|
||||
[fPriorityPopUp selectItemAtIndex:priorityIndex];
|
||||
[self.fPriorityPopUp selectItemAtIndex:priorityIndex];
|
||||
|
||||
fStartCheck.state = [NSUserDefaults.standardUserDefaults boolForKey:@"AutoStartDownload"] ? NSControlStateValueOn
|
||||
self.fStartCheck.state = [NSUserDefaults.standardUserDefaults boolForKey:@"AutoStartDownload"] ? NSControlStateValueOn
|
||||
: NSControlStateValueOff;
|
||||
|
||||
fDeleteCheck.state = fDeleteTorrentEnableInitially ? NSControlStateValueOn : NSControlStateValueOff;
|
||||
fDeleteCheck.enabled = fCanToggleDelete;
|
||||
self.fDeleteCheck.state = self.fDeleteTorrentEnableInitially ? NSControlStateValueOn : NSControlStateValueOff;
|
||||
self.fDeleteCheck.enabled = self.fCanToggleDelete;
|
||||
|
||||
if (fDestination)
|
||||
if (self.fDestination)
|
||||
{
|
||||
[self setDestinationPath:fDestination
|
||||
determinationType:(fLockDestination ? TorrentDeterminationUserSpecified : TorrentDeterminationAutomatic)];
|
||||
[self setDestinationPath:self.fDestination
|
||||
determinationType:(self.fLockDestination ? TorrentDeterminationUserSpecified : TorrentDeterminationAutomatic)];
|
||||
}
|
||||
else
|
||||
{
|
||||
fLocationField.stringValue = @"";
|
||||
fLocationImageView.image = nil;
|
||||
self.fLocationField.stringValue = @"";
|
||||
self.fLocationImageView.image = nil;
|
||||
}
|
||||
|
||||
fTimer = [NSTimer scheduledTimerWithTimeInterval:UPDATE_SECONDS target:self selector:@selector(updateFiles) userInfo:nil
|
||||
self.fTimer = [NSTimer scheduledTimerWithTimeInterval:UPDATE_SECONDS target:self selector:@selector(updateFiles) userInfo:nil
|
||||
repeats:YES];
|
||||
[self updateFiles];
|
||||
}
|
||||
|
@ -139,7 +171,7 @@
|
|||
- (void)windowDidLoad
|
||||
{
|
||||
//if there is no destination, prompt for one right away
|
||||
if (!fDestination)
|
||||
if (!self.fDestination)
|
||||
{
|
||||
[self setDestination:nil];
|
||||
}
|
||||
|
@ -149,12 +181,7 @@
|
|||
{
|
||||
[NSNotificationCenter.defaultCenter removeObserver:self];
|
||||
|
||||
[fTimer invalidate];
|
||||
}
|
||||
|
||||
- (Torrent*)torrent
|
||||
{
|
||||
return fTorrent;
|
||||
[_fTimer invalidate];
|
||||
}
|
||||
|
||||
- (void)setDestination:(id)sender
|
||||
|
@ -168,17 +195,17 @@
|
|||
panel.canCreateDirectories = YES;
|
||||
|
||||
panel.message = [NSString stringWithFormat:NSLocalizedString(@"Select the download folder for \"%@\"", "Add -> select destination folder"),
|
||||
fTorrent.name];
|
||||
self.torrent.name];
|
||||
|
||||
[panel beginSheetModalForWindow:self.window completionHandler:^(NSInteger result) {
|
||||
if (result == NSModalResponseOK)
|
||||
{
|
||||
fLockDestination = YES;
|
||||
self.fLockDestination = YES;
|
||||
[self setDestinationPath:panel.URLs[0].path determinationType:TorrentDeterminationUserSpecified];
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!fDestination)
|
||||
if (!self.fDestination)
|
||||
{
|
||||
[self performSelectorOnMainThread:@selector(cancelAdd:) withObject:nil waitUntilDone:NO];
|
||||
}
|
||||
|
@ -188,7 +215,7 @@
|
|||
|
||||
- (void)add:(id)sender
|
||||
{
|
||||
if ([fDestination.lastPathComponent isEqualToString:fTorrent.name] &&
|
||||
if ([self.fDestination.lastPathComponent isEqualToString:self.torrent.name] &&
|
||||
[NSUserDefaults.standardUserDefaults boolForKey:@"WarningFolderDataSameName"])
|
||||
{
|
||||
NSAlert* alert = [[NSAlert alloc] init];
|
||||
|
@ -228,33 +255,33 @@
|
|||
//only called on cancel
|
||||
- (BOOL)windowShouldClose:(id)window
|
||||
{
|
||||
[fTimer invalidate];
|
||||
fTimer = nil;
|
||||
[self.fTimer invalidate];
|
||||
self.fTimer = nil;
|
||||
|
||||
[fFileController setTorrent:nil]; //avoid a crash when window tries to update
|
||||
self.fFileController.torrent = nil; //avoid a crash when window tries to update
|
||||
|
||||
[fController askOpenConfirmed:self add:NO];
|
||||
[self.fController askOpenConfirmed:self add:NO];
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)setFileFilterText:(id)sender
|
||||
{
|
||||
[fFileController setFilterText:[sender stringValue]];
|
||||
self.fFileController.filterText = [sender stringValue];
|
||||
}
|
||||
|
||||
- (IBAction)checkAll:(id)sender
|
||||
{
|
||||
[fFileController checkAll];
|
||||
[self.fFileController checkAll];
|
||||
}
|
||||
|
||||
- (IBAction)uncheckAll:(id)sender
|
||||
{
|
||||
[fFileController uncheckAll];
|
||||
[self.fFileController uncheckAll];
|
||||
}
|
||||
|
||||
- (void)verifyLocalData:(id)sender
|
||||
{
|
||||
[fTorrent resetCache];
|
||||
[self.torrent resetCache];
|
||||
[self updateFiles];
|
||||
}
|
||||
|
||||
|
@ -276,24 +303,24 @@
|
|||
NSAssert1(NO, @"Unknown priority tag for adding torrent: %ld", [sender tag]);
|
||||
priority = TR_PRI_NORMAL;
|
||||
}
|
||||
fTorrent.priority = priority;
|
||||
self.torrent.priority = priority;
|
||||
}
|
||||
|
||||
- (void)updateCheckButtons:(NSNotification*)notification
|
||||
{
|
||||
NSString* statusString = [NSString stringForFileSize:fTorrent.size];
|
||||
if (fTorrent.folder)
|
||||
NSString* statusString = [NSString stringForFileSize:self.torrent.size];
|
||||
if (self.torrent.folder)
|
||||
{
|
||||
//check buttons
|
||||
//keep synced with identical code in InfoFileViewController.m
|
||||
NSInteger const filesCheckState = [fTorrent
|
||||
checkForFiles:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, fTorrent.fileCount)]];
|
||||
fCheckAllButton.enabled = filesCheckState != NSControlStateValueOn; //if anything is unchecked
|
||||
fUncheckAllButton.enabled = !fTorrent.allDownloaded; //if there are any checked files that aren't finished
|
||||
NSInteger const filesCheckState = [self.torrent
|
||||
checkForFiles:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, self.torrent.fileCount)]];
|
||||
self.fCheckAllButton.enabled = filesCheckState != NSControlStateValueOn; //if anything is unchecked
|
||||
self.fUncheckAllButton.enabled = !self.torrent.allDownloaded; //if there are any checked files that aren't finished
|
||||
|
||||
//status field
|
||||
NSString* fileString;
|
||||
NSInteger count = fTorrent.fileCount;
|
||||
NSInteger count = self.torrent.fileCount;
|
||||
if (count != 1)
|
||||
{
|
||||
fileString = [NSString
|
||||
|
@ -305,112 +332,114 @@
|
|||
}
|
||||
|
||||
NSString* selectedString = [NSString stringWithFormat:NSLocalizedString(@"%@ selected", "Add torrent -> info"),
|
||||
[NSString stringForFileSize:fTorrent.totalSizeSelected]];
|
||||
[NSString stringForFileSize:self.torrent.totalSizeSelected]];
|
||||
|
||||
statusString = [NSString stringWithFormat:@"%@, %@ (%@)", fileString, statusString, selectedString];
|
||||
}
|
||||
|
||||
fStatusField.stringValue = statusString;
|
||||
self.fStatusField.stringValue = statusString;
|
||||
}
|
||||
|
||||
- (void)updateGroupMenu:(NSNotification*)notification
|
||||
{
|
||||
[self setGroupsMenu];
|
||||
if (![fGroupPopUp selectItemWithTag:fGroupValue])
|
||||
if (![self.fGroupPopUp selectItemWithTag:self.fGroupValue])
|
||||
{
|
||||
fGroupValue = -1;
|
||||
fGroupValueDetermination = TorrentDeterminationAutomatic;
|
||||
[fGroupPopUp selectItemWithTag:fGroupValue];
|
||||
self.fGroupValue = -1;
|
||||
self.fGroupValueDetermination = TorrentDeterminationAutomatic;
|
||||
[self.fGroupPopUp selectItemWithTag:self.fGroupValue];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
- (void)updateFiles
|
||||
{
|
||||
[fTorrent update];
|
||||
[self.torrent update];
|
||||
|
||||
[fFileController refresh];
|
||||
[self.fFileController refresh];
|
||||
|
||||
[self updateCheckButtons:nil]; //call in case button state changed by checking
|
||||
|
||||
if (fTorrent.checking)
|
||||
if (self.torrent.checking)
|
||||
{
|
||||
BOOL const waiting = fTorrent.checkingWaiting;
|
||||
fVerifyIndicator.indeterminate = waiting;
|
||||
BOOL const waiting = self.torrent.checkingWaiting;
|
||||
self.fVerifyIndicator.indeterminate = waiting;
|
||||
if (waiting)
|
||||
{
|
||||
[fVerifyIndicator startAnimation:self];
|
||||
[self.fVerifyIndicator startAnimation:self];
|
||||
}
|
||||
else
|
||||
{
|
||||
fVerifyIndicator.doubleValue = fTorrent.checkingProgress;
|
||||
self.fVerifyIndicator.doubleValue = self.torrent.checkingProgress;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fVerifyIndicator.indeterminate = YES; //we want to hide when stopped, which only applies when indeterminate
|
||||
[fVerifyIndicator stopAnimation:self];
|
||||
self.fVerifyIndicator.indeterminate = YES; //we want to hide when stopped, which only applies when indeterminate
|
||||
[self.fVerifyIndicator stopAnimation:self];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)confirmAdd
|
||||
{
|
||||
[fTimer invalidate];
|
||||
fTimer = nil;
|
||||
[fTorrent setGroupValue:fGroupValue determinationType:fGroupValueDetermination];
|
||||
[self.fTimer invalidate];
|
||||
self.fTimer = nil;
|
||||
[self.torrent setGroupValue:self.fGroupValue determinationType:self.fGroupValueDetermination];
|
||||
|
||||
if (fTorrentFile && fCanToggleDelete && fDeleteCheck.state == NSControlStateValueOn)
|
||||
if (self.fTorrentFile && self.fCanToggleDelete && self.fDeleteCheck.state == NSControlStateValueOn)
|
||||
{
|
||||
[Torrent trashFile:fTorrentFile error:nil];
|
||||
[Torrent trashFile:self.fTorrentFile error:nil];
|
||||
}
|
||||
|
||||
if (fStartCheck.state == NSControlStateValueOn)
|
||||
if (self.fStartCheck.state == NSControlStateValueOn)
|
||||
{
|
||||
[fTorrent startTransfer];
|
||||
[self.torrent startTransfer];
|
||||
}
|
||||
|
||||
[fFileController setTorrent:nil]; //avoid a crash when window tries to update
|
||||
self.fFileController.torrent = nil; //avoid a crash when window tries to update
|
||||
|
||||
[self close];
|
||||
[fController askOpenConfirmed:self add:YES];
|
||||
[self.fController askOpenConfirmed:self add:YES];
|
||||
}
|
||||
|
||||
- (void)setDestinationPath:(NSString*)destination determinationType:(TorrentDeterminationType)determinationType
|
||||
{
|
||||
destination = destination.stringByExpandingTildeInPath;
|
||||
if (!fDestination || ![fDestination isEqualToString:destination])
|
||||
if (!self.fDestination || ![self.fDestination isEqualToString:destination])
|
||||
{
|
||||
fDestination = destination;
|
||||
self.fDestination = destination;
|
||||
|
||||
[fTorrent changeDownloadFolderBeforeUsing:fDestination determinationType:determinationType];
|
||||
[self.torrent changeDownloadFolderBeforeUsing:self.fDestination determinationType:determinationType];
|
||||
}
|
||||
|
||||
fLocationField.stringValue = fDestination.stringByAbbreviatingWithTildeInPath;
|
||||
fLocationField.toolTip = fDestination;
|
||||
self.fLocationField.stringValue = self.fDestination.stringByAbbreviatingWithTildeInPath;
|
||||
self.fLocationField.toolTip = self.fDestination;
|
||||
|
||||
ExpandedPathToIconTransformer* iconTransformer = [[ExpandedPathToIconTransformer alloc] init];
|
||||
fLocationImageView.image = [iconTransformer transformedValue:fDestination];
|
||||
self.fLocationImageView.image = [iconTransformer transformedValue:self.fDestination];
|
||||
}
|
||||
|
||||
- (void)setGroupsMenu
|
||||
{
|
||||
NSMenu* groupMenu = [GroupsController.groups groupMenuWithTarget:self action:@selector(changeGroupValue:) isSmall:NO];
|
||||
fGroupPopUp.menu = groupMenu;
|
||||
self.fGroupPopUp.menu = groupMenu;
|
||||
}
|
||||
|
||||
- (void)changeGroupValue:(id)sender
|
||||
{
|
||||
NSInteger previousGroup = fGroupValue;
|
||||
fGroupValue = [sender tag];
|
||||
fGroupValueDetermination = TorrentDeterminationUserSpecified;
|
||||
NSInteger previousGroup = self.fGroupValue;
|
||||
self.fGroupValue = [sender tag];
|
||||
self.fGroupValueDetermination = TorrentDeterminationUserSpecified;
|
||||
|
||||
if (!fLockDestination)
|
||||
if (!self.fLockDestination)
|
||||
{
|
||||
if ([GroupsController.groups usesCustomDownloadLocationForIndex:fGroupValue])
|
||||
if ([GroupsController.groups usesCustomDownloadLocationForIndex:self.fGroupValue])
|
||||
{
|
||||
[self setDestinationPath:[GroupsController.groups customDownloadLocationForIndex:fGroupValue]
|
||||
[self setDestinationPath:[GroupsController.groups customDownloadLocationForIndex:self.fGroupValue]
|
||||
determinationType:TorrentDeterminationAutomatic];
|
||||
}
|
||||
else if ([fDestination isEqualToString:[GroupsController.groups customDownloadLocationForIndex:previousGroup]])
|
||||
else if ([self.fDestination isEqualToString:[GroupsController.groups customDownloadLocationForIndex:previousGroup]])
|
||||
{
|
||||
[self setDestinationPath:[NSUserDefaults.standardUserDefaults stringForKey:@"DownloadFolder"]
|
||||
determinationType:TorrentDeterminationAutomatic];
|
||||
|
|
|
@ -7,14 +7,6 @@
|
|||
#include <libtransmission/transmission.h>
|
||||
|
||||
@interface BadgeView : NSView
|
||||
{
|
||||
tr_session* fLib;
|
||||
|
||||
NSMutableDictionary* fAttributes;
|
||||
|
||||
CGFloat fDownloadRate;
|
||||
CGFloat fUploadRate;
|
||||
}
|
||||
|
||||
- (instancetype)initWithLib:(tr_session*)lib;
|
||||
|
||||
|
|
|
@ -9,6 +9,13 @@
|
|||
|
||||
@interface BadgeView ()
|
||||
|
||||
@property(nonatomic, readonly) tr_session* fLib;
|
||||
|
||||
@property(nonatomic) NSMutableDictionary* fAttributes;
|
||||
|
||||
@property(nonatomic) CGFloat fDownloadRate;
|
||||
@property(nonatomic) CGFloat fUploadRate;
|
||||
|
||||
- (void)badge:(NSImage*)badge string:(NSString*)string atHeight:(CGFloat)height;
|
||||
|
||||
@end
|
||||
|
@ -19,10 +26,10 @@
|
|||
{
|
||||
if ((self = [super init]))
|
||||
{
|
||||
fLib = lib;
|
||||
_fLib = lib;
|
||||
|
||||
fDownloadRate = 0.0;
|
||||
fUploadRate = 0.0;
|
||||
_fDownloadRate = 0.0;
|
||||
_fUploadRate = 0.0;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
@ -30,13 +37,13 @@
|
|||
- (BOOL)setRatesWithDownload:(CGFloat)downloadRate upload:(CGFloat)uploadRate
|
||||
{
|
||||
//only needs update if the badges were displayed or are displayed now
|
||||
if (fDownloadRate == downloadRate && fUploadRate == uploadRate)
|
||||
if (self.fDownloadRate == downloadRate && self.fUploadRate == uploadRate)
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
fDownloadRate = downloadRate;
|
||||
fUploadRate = uploadRate;
|
||||
self.fDownloadRate = downloadRate;
|
||||
self.fUploadRate = uploadRate;
|
||||
return YES;
|
||||
}
|
||||
|
||||
|
@ -44,13 +51,14 @@
|
|||
{
|
||||
[NSApp.applicationIconImage drawInRect:rect fromRect:NSZeroRect operation:NSCompositingOperationSourceOver fraction:1.0];
|
||||
|
||||
BOOL const upload = fUploadRate >= 0.1;
|
||||
BOOL const download = fDownloadRate >= 0.1;
|
||||
BOOL const upload = self.fUploadRate >= 0.1;
|
||||
BOOL const download = self.fDownloadRate >= 0.1;
|
||||
CGFloat bottom = 0.0;
|
||||
if (upload)
|
||||
{
|
||||
NSImage* uploadBadge = [NSImage imageNamed:@"UploadBadge"];
|
||||
[self badge:uploadBadge string:[NSString stringForSpeedAbbrev:fUploadRate] atHeight:bottom];
|
||||
[self badge:uploadBadge string:[NSString stringForSpeedAbbrev:self.fUploadRate] atHeight:bottom];
|
||||
|
||||
if (download)
|
||||
{
|
||||
bottom += uploadBadge.size.height + BETWEEN_PADDING; //download rate above upload rate
|
||||
|
@ -58,21 +66,21 @@
|
|||
}
|
||||
if (download)
|
||||
{
|
||||
[self badge:[NSImage imageNamed:@"DownloadBadge"] string:[NSString stringForSpeedAbbrev:fDownloadRate] atHeight:bottom];
|
||||
[self badge:[NSImage imageNamed:@"DownloadBadge"] string:[NSString stringForSpeedAbbrev:self.fDownloadRate] atHeight:bottom];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)badge:(NSImage*)badge string:(NSString*)string atHeight:(CGFloat)height
|
||||
{
|
||||
if (!fAttributes)
|
||||
if (!self.fAttributes)
|
||||
{
|
||||
NSShadow* stringShadow = [[NSShadow alloc] init];
|
||||
stringShadow.shadowOffset = NSMakeSize(2.0, -2.0);
|
||||
stringShadow.shadowBlurRadius = 4.0;
|
||||
|
||||
fAttributes = [[NSMutableDictionary alloc] initWithCapacity:3];
|
||||
fAttributes[NSForegroundColorAttributeName] = NSColor.whiteColor;
|
||||
fAttributes[NSShadowAttributeName] = stringShadow;
|
||||
self.fAttributes = [[NSMutableDictionary alloc] initWithCapacity:3];
|
||||
self.fAttributes[NSForegroundColorAttributeName] = NSColor.whiteColor;
|
||||
self.fAttributes[NSShadowAttributeName] = stringShadow;
|
||||
}
|
||||
|
||||
NSRect badgeRect;
|
||||
|
@ -87,8 +95,8 @@
|
|||
NSSize stringSize;
|
||||
do
|
||||
{
|
||||
fAttributes[NSFontAttributeName] = [NSFont boldSystemFontOfSize:fontSize];
|
||||
stringSize = [string sizeWithAttributes:fAttributes];
|
||||
self.fAttributes[NSFontAttributeName] = [NSFont boldSystemFontOfSize:fontSize];
|
||||
stringSize = [string sizeWithAttributes:self.fAttributes];
|
||||
fontSize -= 1.0;
|
||||
} while (NSWidth(badgeRect) < stringSize.width);
|
||||
|
||||
|
@ -98,7 +106,7 @@
|
|||
stringRect.origin.y = NSMidY(badgeRect) - stringSize.height * 0.5 + 1.0; //adjust for shadow
|
||||
stringRect.size = stringSize;
|
||||
|
||||
[string drawInRect:stringRect withAttributes:fAttributes];
|
||||
[string drawInRect:stringRect withAttributes:self.fAttributes];
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -9,11 +9,6 @@
|
|||
@class Torrent;
|
||||
|
||||
@interface Badger : NSObject
|
||||
{
|
||||
tr_session* fLib;
|
||||
|
||||
NSMutableSet* fHashes;
|
||||
}
|
||||
|
||||
- (instancetype)initWithLib:(tr_session*)lib;
|
||||
|
||||
|
|
|
@ -7,18 +7,26 @@
|
|||
#import "NSStringAdditions.h"
|
||||
#import "Torrent.h"
|
||||
|
||||
@interface Badger ()
|
||||
|
||||
@property(nonatomic, readonly) tr_session* fLib;
|
||||
|
||||
@property(nonatomic, readonly) NSMutableSet* fHashes;
|
||||
|
||||
@end
|
||||
|
||||
@implementation Badger
|
||||
|
||||
- (instancetype)initWithLib:(tr_session*)lib
|
||||
{
|
||||
if ((self = [super init]))
|
||||
{
|
||||
fLib = lib;
|
||||
_fLib = lib;
|
||||
|
||||
BadgeView* view = [[BadgeView alloc] initWithLib:lib];
|
||||
NSApp.dockTile.contentView = view;
|
||||
|
||||
fHashes = [[NSMutableSet alloc] init];
|
||||
_fHashes = [[NSMutableSet alloc] init];
|
||||
}
|
||||
|
||||
return self;
|
||||
|
@ -40,18 +48,18 @@
|
|||
{
|
||||
NSParameterAssert(torrent != nil);
|
||||
|
||||
[fHashes addObject:torrent.hashString];
|
||||
NSApp.dockTile.badgeLabel = [NSString formattedUInteger:fHashes.count];
|
||||
[self.fHashes addObject:torrent.hashString];
|
||||
NSApp.dockTile.badgeLabel = [NSString formattedUInteger:self.fHashes.count];
|
||||
}
|
||||
|
||||
- (void)removeTorrent:(Torrent*)torrent
|
||||
{
|
||||
if ([fHashes member:torrent.hashString])
|
||||
if ([self.fHashes member:torrent.hashString])
|
||||
{
|
||||
[fHashes removeObject:torrent.hashString];
|
||||
if (fHashes.count > 0)
|
||||
[self.fHashes removeObject:torrent.hashString];
|
||||
if (self.fHashes.count > 0)
|
||||
{
|
||||
NSApp.dockTile.badgeLabel = [NSString formattedUInteger:fHashes.count];
|
||||
NSApp.dockTile.badgeLabel = [NSString formattedUInteger:self.fHashes.count];
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -62,9 +70,9 @@
|
|||
|
||||
- (void)clearCompleted
|
||||
{
|
||||
if (fHashes.count > 0)
|
||||
if (self.fHashes.count > 0)
|
||||
{
|
||||
[fHashes removeAllObjects];
|
||||
[self.fHashes removeAllObjects];
|
||||
NSApp.dockTile.badgeLabel = @"";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,21 +13,11 @@ typedef NS_ENUM(unsigned int, blocklistDownloadState) { //
|
|||
};
|
||||
|
||||
@interface BlocklistDownloader : NSObject<NSURLSessionDownloadDelegate>
|
||||
{
|
||||
NSURLSession* fSession;
|
||||
|
||||
BlocklistDownloaderViewController* fViewController;
|
||||
|
||||
NSUInteger fCurrentSize;
|
||||
long long fExpectedSize;
|
||||
|
||||
blocklistDownloadState fState;
|
||||
}
|
||||
|
||||
+ (BlocklistDownloader*)downloader; //starts download if not already occuring
|
||||
@property(nonatomic) BlocklistDownloaderViewController* viewController;
|
||||
@property(nonatomic, class, readonly) BOOL isRunning;
|
||||
|
||||
- (void)setViewController:(BlocklistDownloaderViewController*)viewController;
|
||||
+ (BlocklistDownloader*)downloader; //starts download if not already occuring
|
||||
|
||||
- (void)cancelDownload;
|
||||
|
||||
|
|
|
@ -9,6 +9,11 @@
|
|||
|
||||
@interface BlocklistDownloader ()
|
||||
|
||||
@property(nonatomic) NSURLSession* fSession;
|
||||
@property(nonatomic) NSUInteger fCurrentSize;
|
||||
@property(nonatomic) long long fExpectedSize;
|
||||
@property(nonatomic) blocklistDownloadState fState;
|
||||
|
||||
- (void)startDownload;
|
||||
- (void)decompressFrom:(NSURL*)file to:(NSURL*)destination error:(NSError**)error;
|
||||
|
||||
|
@ -36,19 +41,19 @@ BlocklistDownloader* fBLDownloader = nil;
|
|||
|
||||
- (void)setViewController:(BlocklistDownloaderViewController*)viewController
|
||||
{
|
||||
fViewController = viewController;
|
||||
if (fViewController)
|
||||
_viewController = viewController;
|
||||
if (_viewController)
|
||||
{
|
||||
switch (fState)
|
||||
switch (self.fState)
|
||||
{
|
||||
case BLOCKLIST_DL_START:
|
||||
[fViewController setStatusStarting];
|
||||
[_viewController setStatusStarting];
|
||||
break;
|
||||
case BLOCKLIST_DL_DOWNLOADING:
|
||||
[fViewController setStatusProgressForCurrentSize:fCurrentSize expectedSize:fExpectedSize];
|
||||
[_viewController setStatusProgressForCurrentSize:self.fCurrentSize expectedSize:self.fExpectedSize];
|
||||
break;
|
||||
case BLOCKLIST_DL_PROCESSING:
|
||||
[fViewController setStatusProcessing];
|
||||
[_viewController setStatusProcessing];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -56,9 +61,9 @@ BlocklistDownloader* fBLDownloader = nil;
|
|||
|
||||
- (void)cancelDownload
|
||||
{
|
||||
[fViewController setFinished];
|
||||
[_viewController setFinished];
|
||||
|
||||
[fSession invalidateAndCancel];
|
||||
[self.fSession invalidateAndCancel];
|
||||
|
||||
[BlocklistScheduler.scheduler updateSchedule];
|
||||
|
||||
|
@ -72,12 +77,12 @@ BlocklistDownloader* fBLDownloader = nil;
|
|||
totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
|
||||
{
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
fState = BLOCKLIST_DL_DOWNLOADING;
|
||||
self.fState = BLOCKLIST_DL_DOWNLOADING;
|
||||
|
||||
fCurrentSize = totalBytesWritten;
|
||||
fExpectedSize = totalBytesExpectedToWrite;
|
||||
self.fCurrentSize = totalBytesWritten;
|
||||
self.fExpectedSize = totalBytesExpectedToWrite;
|
||||
|
||||
[fViewController setStatusProgressForCurrentSize:fCurrentSize expectedSize:fExpectedSize];
|
||||
[self.viewController setStatusProgressForCurrentSize:self.fCurrentSize expectedSize:self.fExpectedSize];
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -88,7 +93,7 @@ didCompleteWithError:(NSError *)error
|
|||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if (error)
|
||||
{
|
||||
[fViewController setFailed:error.localizedDescription];
|
||||
[self.viewController setFailed:error.localizedDescription];
|
||||
}
|
||||
|
||||
[NSUserDefaults.standardUserDefaults setObject:[NSDate date] forKey:@"BlocklistNewLastUpdate"];
|
||||
|
@ -102,10 +107,10 @@ didCompleteWithError:(NSError *)error
|
|||
downloadTask:(NSURLSessionDownloadTask *)downloadTask
|
||||
didFinishDownloadingToURL:(NSURL *)location
|
||||
{
|
||||
fState = BLOCKLIST_DL_PROCESSING;
|
||||
self.fState = BLOCKLIST_DL_PROCESSING;
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[fViewController setStatusProcessing];
|
||||
[self.viewController setStatusProcessing];
|
||||
});
|
||||
|
||||
NSString* filename = downloadTask.response.suggestedFilename;
|
||||
|
@ -139,11 +144,11 @@ didFinishDownloadingToURL:(NSURL *)location
|
|||
|
||||
if (count > 0)
|
||||
{
|
||||
[fViewController setFinished];
|
||||
[self.viewController setFinished];
|
||||
}
|
||||
else
|
||||
{
|
||||
[fViewController setFailed:NSLocalizedString(@"The specified blocklist file did not contain any valid rules.", "blocklist fail message")];
|
||||
[self.viewController setFailed:NSLocalizedString(@"The specified blocklist file did not contain any valid rules.", "blocklist fail message")];
|
||||
}
|
||||
|
||||
//update last updated date for schedule
|
||||
|
@ -158,11 +163,13 @@ didFinishDownloadingToURL:(NSURL *)location
|
|||
});
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
- (void)startDownload
|
||||
{
|
||||
fState = BLOCKLIST_DL_START;
|
||||
self.fState = BLOCKLIST_DL_START;
|
||||
|
||||
fSession = [NSURLSession sessionWithConfiguration:NSURLSessionConfiguration.ephemeralSessionConfiguration
|
||||
self.fSession = [NSURLSession sessionWithConfiguration:NSURLSessionConfiguration.ephemeralSessionConfiguration
|
||||
delegate:self
|
||||
delegateQueue:nil];
|
||||
|
||||
|
@ -178,7 +185,7 @@ didFinishDownloadingToURL:(NSURL *)location
|
|||
urlString = [@"https://" stringByAppendingString:urlString];
|
||||
}
|
||||
|
||||
NSURLSessionDownloadTask* task = [fSession downloadTaskWithURL:[NSURL URLWithString:urlString]];
|
||||
NSURLSessionDownloadTask* task = [self.fSession downloadTaskWithURL:[NSURL URLWithString:urlString]];
|
||||
[task resume];
|
||||
}
|
||||
|
||||
|
|
|
@ -9,14 +9,6 @@
|
|||
@class PrefsController;
|
||||
|
||||
@interface BlocklistDownloaderViewController : NSObject
|
||||
{
|
||||
PrefsController* fPrefsController;
|
||||
|
||||
IBOutlet NSWindow* fStatusWindow;
|
||||
IBOutlet NSProgressIndicator* fProgressBar;
|
||||
IBOutlet NSTextField* fTextField;
|
||||
IBOutlet NSButton* fButton;
|
||||
}
|
||||
|
||||
+ (void)downloadWithPrefsController:(PrefsController*)prefsController;
|
||||
|
||||
|
|
|
@ -9,6 +9,13 @@
|
|||
|
||||
@interface BlocklistDownloaderViewController ()
|
||||
|
||||
@property(nonatomic) IBOutlet NSWindow* fStatusWindow;
|
||||
@property(nonatomic) IBOutlet NSProgressIndicator* fProgressBar;
|
||||
@property(nonatomic) IBOutlet NSTextField* fTextField;
|
||||
@property(nonatomic) IBOutlet NSButton* fButton;
|
||||
|
||||
@property(nonatomic, readonly) PrefsController* fPrefsController;
|
||||
|
||||
- (instancetype)initWithPrefsController:(PrefsController*)prefsController;
|
||||
- (void)startDownload;
|
||||
|
||||
|
@ -28,17 +35,17 @@ BlocklistDownloaderViewController* fBLViewController = nil;
|
|||
|
||||
- (void)awakeFromNib
|
||||
{
|
||||
fButton.title = NSLocalizedString(@"Cancel", "Blocklist -> cancel button");
|
||||
self.fButton.title = NSLocalizedString(@"Cancel", "Blocklist -> cancel button");
|
||||
|
||||
CGFloat const oldWidth = NSWidth(fButton.frame);
|
||||
[fButton sizeToFit];
|
||||
NSRect buttonFrame = fButton.frame;
|
||||
CGFloat const oldWidth = NSWidth(self.fButton.frame);
|
||||
[self.fButton sizeToFit];
|
||||
NSRect buttonFrame = self.fButton.frame;
|
||||
buttonFrame.size.width += 12.0; //sizeToFit sizes a bit too small
|
||||
buttonFrame.origin.x -= NSWidth(buttonFrame) - oldWidth;
|
||||
fButton.frame = buttonFrame;
|
||||
self.fButton.frame = buttonFrame;
|
||||
|
||||
fProgressBar.usesThreadedAnimation = YES;
|
||||
[fProgressBar startAnimation:self];
|
||||
self.fProgressBar.usesThreadedAnimation = YES;
|
||||
[self.fProgressBar startAnimation:self];
|
||||
}
|
||||
|
||||
- (void)cancelDownload:(id)sender
|
||||
|
@ -48,8 +55,8 @@ BlocklistDownloaderViewController* fBLViewController = nil;
|
|||
|
||||
- (void)setStatusStarting
|
||||
{
|
||||
fTextField.stringValue = [NSLocalizedString(@"Connecting to site", "Blocklist -> message") stringByAppendingEllipsis];
|
||||
fProgressBar.indeterminate = YES;
|
||||
self.fTextField.stringValue = [NSLocalizedString(@"Connecting to site", "Blocklist -> message") stringByAppendingEllipsis];
|
||||
self.fProgressBar.indeterminate = YES;
|
||||
}
|
||||
|
||||
- (void)setStatusProgressForCurrentSize:(NSUInteger)currentSize expectedSize:(long long)expectedSize
|
||||
|
@ -57,42 +64,42 @@ BlocklistDownloaderViewController* fBLViewController = nil;
|
|||
NSString* string = NSLocalizedString(@"Downloading blocklist", "Blocklist -> message");
|
||||
if (expectedSize != NSURLResponseUnknownLength)
|
||||
{
|
||||
fProgressBar.indeterminate = NO;
|
||||
self.fProgressBar.indeterminate = NO;
|
||||
|
||||
NSString* substring = [NSString stringForFilePartialSize:currentSize fullSize:expectedSize];
|
||||
string = [string stringByAppendingFormat:@" (%@)", substring];
|
||||
fProgressBar.doubleValue = (double)currentSize / expectedSize;
|
||||
self.fProgressBar.doubleValue = (double)currentSize / expectedSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
string = [string stringByAppendingFormat:@" (%@)", [NSString stringForFileSize:currentSize]];
|
||||
}
|
||||
|
||||
fTextField.stringValue = string;
|
||||
self.fTextField.stringValue = string;
|
||||
}
|
||||
|
||||
- (void)setStatusProcessing
|
||||
{
|
||||
//change to indeterminate while processing
|
||||
fProgressBar.indeterminate = YES;
|
||||
[fProgressBar startAnimation:self];
|
||||
self.fProgressBar.indeterminate = YES;
|
||||
[self.fProgressBar startAnimation:self];
|
||||
|
||||
fTextField.stringValue = [NSLocalizedString(@"Processing blocklist", "Blocklist -> message") stringByAppendingEllipsis];
|
||||
fButton.enabled = NO;
|
||||
self.fTextField.stringValue = [NSLocalizedString(@"Processing blocklist", "Blocklist -> message") stringByAppendingEllipsis];
|
||||
self.fButton.enabled = NO;
|
||||
}
|
||||
|
||||
- (void)setFinished
|
||||
{
|
||||
[NSApp endSheet:fStatusWindow];
|
||||
[fStatusWindow orderOut:self];
|
||||
[NSApp endSheet:self.fStatusWindow];
|
||||
[self.fStatusWindow orderOut:self];
|
||||
|
||||
fBLViewController = nil;
|
||||
}
|
||||
|
||||
- (void)setFailed:(NSString*)error
|
||||
{
|
||||
[NSApp endSheet:fStatusWindow];
|
||||
[fStatusWindow orderOut:self];
|
||||
[NSApp endSheet:self.fStatusWindow];
|
||||
[self.fStatusWindow orderOut:self];
|
||||
|
||||
NSAlert* alert = [[NSAlert alloc] init];
|
||||
[alert addButtonWithTitle:NSLocalizedString(@"OK", "Blocklist -> button")];
|
||||
|
@ -101,18 +108,20 @@ BlocklistDownloaderViewController* fBLViewController = nil;
|
|||
|
||||
alert.informativeText = error;
|
||||
|
||||
[alert beginSheetModalForWindow:fPrefsController.window completionHandler:^(NSModalResponse returnCode) {
|
||||
[alert beginSheetModalForWindow:self.fPrefsController.window completionHandler:^(NSModalResponse returnCode) {
|
||||
[alert.window orderOut:self];
|
||||
|
||||
fBLViewController = nil;
|
||||
}];
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
- (instancetype)initWithPrefsController:(PrefsController*)prefsController
|
||||
{
|
||||
if ((self = [super init]))
|
||||
{
|
||||
fPrefsController = prefsController;
|
||||
_fPrefsController = prefsController;
|
||||
}
|
||||
|
||||
return self;
|
||||
|
@ -126,7 +135,7 @@ BlocklistDownloaderViewController* fBLViewController = nil;
|
|||
BlocklistDownloader* downloader = [BlocklistDownloader downloader];
|
||||
[downloader setViewController:self]; //do before showing the sheet to ensure it doesn't slide out with placeholder text
|
||||
|
||||
[fPrefsController.window beginSheet:fStatusWindow completionHandler:nil];
|
||||
[self.fPrefsController.window beginSheet:self.fStatusWindow completionHandler:nil];
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -5,9 +5,6 @@
|
|||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
@interface BlocklistScheduler : NSObject
|
||||
{
|
||||
NSTimer* fTimer;
|
||||
}
|
||||
|
||||
@property(nonatomic, class, readonly) BlocklistScheduler* scheduler;
|
||||
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
|
||||
@interface BlocklistScheduler ()
|
||||
|
||||
@property (nonatomic) NSTimer* fTimer;
|
||||
|
||||
- (void)runUpdater;
|
||||
|
||||
@end
|
||||
|
@ -55,25 +57,27 @@ BlocklistScheduler* fScheduler = nil;
|
|||
|
||||
NSDate* useDate = lastUpdateDate ? [lastUpdateDate laterDate:closeDate] : closeDate;
|
||||
|
||||
fTimer = [[NSTimer alloc] initWithFireDate:useDate interval:0 target:self selector:@selector(runUpdater) userInfo:nil
|
||||
self.fTimer = [[NSTimer alloc] initWithFireDate:useDate interval:0 target:self selector:@selector(runUpdater) userInfo:nil
|
||||
repeats:NO];
|
||||
|
||||
//current run loop usually means a second update won't work
|
||||
NSRunLoop* loop = NSRunLoop.mainRunLoop;
|
||||
[loop addTimer:fTimer forMode:NSDefaultRunLoopMode];
|
||||
[loop addTimer:fTimer forMode:NSModalPanelRunLoopMode];
|
||||
[loop addTimer:fTimer forMode:NSEventTrackingRunLoopMode];
|
||||
[loop addTimer:self.fTimer forMode:NSDefaultRunLoopMode];
|
||||
[loop addTimer:self.fTimer forMode:NSModalPanelRunLoopMode];
|
||||
[loop addTimer:self.fTimer forMode:NSEventTrackingRunLoopMode];
|
||||
}
|
||||
|
||||
- (void)cancelSchedule
|
||||
{
|
||||
[fTimer invalidate];
|
||||
fTimer = nil;
|
||||
[self.fTimer invalidate];
|
||||
self.fTimer = nil;
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
- (void)runUpdater
|
||||
{
|
||||
fTimer = nil;
|
||||
self.fTimer = nil;
|
||||
[BlocklistDownloader downloader];
|
||||
}
|
||||
|
||||
|
|
|
@ -5,9 +5,6 @@
|
|||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
@interface BonjourController : NSObject<NSNetServiceDelegate>
|
||||
{
|
||||
NSNetService* fService;
|
||||
}
|
||||
|
||||
@property(nonatomic, class, readonly) BonjourController* defaultController;
|
||||
@property(nonatomic, class, readonly) BOOL defaultControllerExists;
|
||||
|
|
|
@ -6,6 +6,12 @@
|
|||
|
||||
#define BONJOUR_SERVICE_NAME_MAX_LENGTH 63
|
||||
|
||||
@interface BonjourController ()
|
||||
|
||||
@property(nonatomic) NSNetService* fService;
|
||||
|
||||
@end
|
||||
|
||||
@implementation BonjourController
|
||||
|
||||
BonjourController* fDefaultController = nil;
|
||||
|
@ -36,16 +42,16 @@ BonjourController* fDefaultController = nil;
|
|||
[serviceName deleteCharactersInRange:NSMakeRange(BONJOUR_SERVICE_NAME_MAX_LENGTH, serviceName.length - BONJOUR_SERVICE_NAME_MAX_LENGTH)];
|
||||
}
|
||||
|
||||
fService = [[NSNetService alloc] initWithDomain:@"" type:@"_http._tcp." name:serviceName port:port];
|
||||
fService.delegate = self;
|
||||
self.fService = [[NSNetService alloc] initWithDomain:@"" type:@"_http._tcp." name:serviceName port:port];
|
||||
self.fService.delegate = self;
|
||||
|
||||
[fService publish];
|
||||
[self.fService publish];
|
||||
}
|
||||
|
||||
- (void)stop
|
||||
{
|
||||
[fService stop];
|
||||
fService = nil;
|
||||
[self.fService stop];
|
||||
self.fService = nil;
|
||||
}
|
||||
|
||||
- (void)netService:(NSNetService*)sender didNotPublish:(NSDictionary*)errorDict
|
||||
|
|
|
@ -5,7 +5,5 @@
|
|||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
@interface ButtonToolbarItem : NSToolbarItem
|
||||
{
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
@class PrefsController;
|
||||
@class StatusBarController;
|
||||
@class Torrent;
|
||||
@class TorrentTableView;
|
||||
@class URLSheetWindowController;
|
||||
|
||||
typedef NS_ENUM(unsigned int, addType) { //
|
||||
|
@ -34,30 +33,6 @@ typedef NS_ENUM(unsigned int, addType) { //
|
|||
|
||||
@interface Controller
|
||||
: NSObject<NSApplicationDelegate, NSURLDownloadDelegate, NSUserNotificationCenterDelegate, NSPopoverDelegate, NSSharingServiceDelegate, NSSharingServicePickerDelegate, NSSoundDelegate, NSToolbarDelegate, NSWindowDelegate, QLPreviewPanelDataSource, QLPreviewPanelDelegate, VDKQueueDelegate, SUUpdaterDelegate>
|
||||
{
|
||||
IBOutlet NSWindow* fWindow;
|
||||
IBOutlet TorrentTableView* fTableView;
|
||||
|
||||
IBOutlet NSMenuItem* fOpenIgnoreDownloadFolder;
|
||||
IBOutlet NSButton* fActionButton;
|
||||
IBOutlet NSButton* fSpeedLimitButton;
|
||||
IBOutlet NSButton* fClearCompletedButton;
|
||||
IBOutlet NSTextField* fTotalTorrentsField;
|
||||
IBOutlet NSMenuItem* fNextFilterItem;
|
||||
|
||||
IBOutlet NSMenuItem* fNextInfoTabItem;
|
||||
IBOutlet NSMenuItem* fPrevInfoTabItem;
|
||||
|
||||
IBOutlet NSMenu* fSortMenu;
|
||||
|
||||
IBOutlet NSMenu* fGroupsSetMenu;
|
||||
IBOutlet NSMenu* fGroupsSetContextMenu;
|
||||
|
||||
IBOutlet NSMenu* fShareMenu;
|
||||
IBOutlet NSMenu* fShareContextMenu;
|
||||
IBOutlet NSMenuItem* fShareMenuItem; // remove when dropping 10.6
|
||||
IBOutlet NSMenuItem* fShareContextMenuItem; // remove when dropping 10.6
|
||||
}
|
||||
|
||||
- (void)openFiles:(NSArray*)filenames addType:(addType)type forcePath:(NSString*)path;
|
||||
|
||||
|
|
1440
macosx/Controller.mm
1440
macosx/Controller.mm
File diff suppressed because it is too large
Load Diff
|
@ -5,36 +5,8 @@
|
|||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
#include <libtransmission/transmission.h>
|
||||
#include <libtransmission/makemeta.h>
|
||||
|
||||
@interface CreatorWindowController : NSWindowController
|
||||
{
|
||||
IBOutlet NSImageView* fIconView;
|
||||
IBOutlet NSTextField* fNameField;
|
||||
IBOutlet NSTextField* fStatusField;
|
||||
IBOutlet NSTextField* fPiecesField;
|
||||
IBOutlet NSTextField* fLocationField;
|
||||
IBOutlet NSTableView* fTrackerTable;
|
||||
IBOutlet NSSegmentedControl* fTrackerAddRemoveControl;
|
||||
IBOutlet NSTextView* fCommentView;
|
||||
IBOutlet NSButton* fPrivateCheck;
|
||||
IBOutlet NSButton* fOpenCheck;
|
||||
IBOutlet NSTextField* fSource;
|
||||
|
||||
IBOutlet NSView* fProgressView;
|
||||
IBOutlet NSProgressIndicator* fProgressIndicator;
|
||||
|
||||
tr_metainfo_builder* fInfo;
|
||||
NSURL* fPath;
|
||||
NSURL* fLocation;
|
||||
NSMutableArray* fTrackers;
|
||||
|
||||
NSTimer* fTimer;
|
||||
BOOL fStarted;
|
||||
BOOL fOpenWhenCreated;
|
||||
|
||||
NSUserDefaults* fDefaults;
|
||||
}
|
||||
|
||||
+ (CreatorWindowController*)createTorrentFile:(tr_session*)handle;
|
||||
+ (CreatorWindowController*)createTorrentFile:(tr_session*)handle forFile:(NSURL*)file;
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
// License text can be found in the licenses/ folder.
|
||||
|
||||
#include <libtransmission/transmission.h>
|
||||
#include <libtransmission/makemeta.h>
|
||||
#include <libtransmission/utils.h>
|
||||
#include <libtransmission/web-utils.h> // tr_urlIsValidTracker()
|
||||
|
||||
|
@ -16,6 +17,32 @@
|
|||
|
||||
@interface CreatorWindowController ()
|
||||
|
||||
@property(nonatomic) IBOutlet NSImageView* fIconView;
|
||||
@property(nonatomic) IBOutlet NSTextField* fNameField;
|
||||
@property(nonatomic) IBOutlet NSTextField* fStatusField;
|
||||
@property(nonatomic) IBOutlet NSTextField* fPiecesField;
|
||||
@property(nonatomic) IBOutlet NSTextField* fLocationField;
|
||||
@property(nonatomic) IBOutlet NSTableView* fTrackerTable;
|
||||
@property(nonatomic) IBOutlet NSSegmentedControl* fTrackerAddRemoveControl;
|
||||
@property(nonatomic) IBOutlet NSTextView* fCommentView;
|
||||
@property(nonatomic) IBOutlet NSButton* fPrivateCheck;
|
||||
@property(nonatomic) IBOutlet NSButton* fOpenCheck;
|
||||
@property(nonatomic) IBOutlet NSTextField* fSource;
|
||||
|
||||
@property(nonatomic) IBOutlet NSView* fProgressView;
|
||||
@property(nonatomic) IBOutlet NSProgressIndicator* fProgressIndicator;
|
||||
|
||||
@property(nonatomic, readonly) tr_metainfo_builder* fInfo;
|
||||
@property(nonatomic, readonly) NSURL* fPath;
|
||||
@property(nonatomic) NSURL* fLocation;
|
||||
@property(nonatomic) NSMutableArray* fTrackers;
|
||||
|
||||
@property(nonatomic) NSTimer* fTimer;
|
||||
@property(nonatomic) BOOL fStarted;
|
||||
@property(nonatomic) BOOL fOpenWhenCreated;
|
||||
|
||||
@property(nonatomic, readonly) NSUserDefaults* fDefaults;
|
||||
|
||||
+ (NSURL*)chooseFile;
|
||||
|
||||
- (void)updateLocationField;
|
||||
|
@ -58,12 +85,12 @@ NSMutableSet* creatorWindowControllerSet = nil;
|
|||
creatorWindowControllerSet = [NSMutableSet set];
|
||||
}
|
||||
|
||||
fStarted = NO;
|
||||
_fStarted = NO;
|
||||
|
||||
fPath = path;
|
||||
fInfo = tr_metaInfoBuilderCreate(fPath.path.UTF8String);
|
||||
_fPath = path;
|
||||
_fInfo = tr_metaInfoBuilderCreate(_fPath.path.UTF8String);
|
||||
|
||||
if (fInfo->fileCount == 0)
|
||||
if (_fInfo->fileCount == 0)
|
||||
{
|
||||
NSAlert* alert = [[NSAlert alloc] init];
|
||||
[alert addButtonWithTitle:NSLocalizedString(@"OK", "Create torrent -> no files -> button")];
|
||||
|
@ -77,7 +104,7 @@ NSMutableSet* creatorWindowControllerSet = nil;
|
|||
|
||||
return nil;
|
||||
}
|
||||
if (fInfo->totalSize == 0)
|
||||
if (_fInfo->totalSize == 0)
|
||||
{
|
||||
NSAlert* alert = [[NSAlert alloc] init];
|
||||
[alert addButtonWithTitle:NSLocalizedString(@"OK", "Create torrent -> zero size -> button")];
|
||||
|
@ -90,32 +117,32 @@ NSMutableSet* creatorWindowControllerSet = nil;
|
|||
return nil;
|
||||
}
|
||||
|
||||
fDefaults = NSUserDefaults.standardUserDefaults;
|
||||
_fDefaults = NSUserDefaults.standardUserDefaults;
|
||||
|
||||
//get list of trackers
|
||||
if (!(fTrackers = [[fDefaults arrayForKey:@"CreatorTrackers"] mutableCopy]))
|
||||
if (!(_fTrackers = [[_fDefaults arrayForKey:@"CreatorTrackers"] mutableCopy]))
|
||||
{
|
||||
fTrackers = [[NSMutableArray alloc] init];
|
||||
_fTrackers = [[NSMutableArray alloc] init];
|
||||
|
||||
//check for single tracker from versions before 1.3
|
||||
NSString* tracker;
|
||||
if ((tracker = [fDefaults stringForKey:@"CreatorTracker"]))
|
||||
if ((tracker = [_fDefaults stringForKey:@"CreatorTracker"]))
|
||||
{
|
||||
[fDefaults removeObjectForKey:@"CreatorTracker"];
|
||||
[_fDefaults removeObjectForKey:@"CreatorTracker"];
|
||||
if (![tracker isEqualToString:@""])
|
||||
{
|
||||
[fTrackers addObject:tracker];
|
||||
[fDefaults setObject:fTrackers forKey:@"CreatorTrackers"];
|
||||
[_fTrackers addObject:tracker];
|
||||
[_fDefaults setObject:_fTrackers forKey:@"CreatorTrackers"];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//remove potentially invalid addresses
|
||||
for (NSInteger i = fTrackers.count - 1; i >= 0; i--)
|
||||
for (NSInteger i = _fTrackers.count - 1; i >= 0; i--)
|
||||
{
|
||||
if (!tr_urlIsValidTracker([fTrackers[i] UTF8String]))
|
||||
if (!tr_urlIsValidTracker([_fTrackers[i] UTF8String]))
|
||||
{
|
||||
[fTrackers removeObjectAtIndex:i];
|
||||
[_fTrackers removeObjectAtIndex:i];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -128,25 +155,25 @@ NSMutableSet* creatorWindowControllerSet = nil;
|
|||
{
|
||||
self.window.restorationClass = [self class];
|
||||
|
||||
NSString* name = fPath.lastPathComponent;
|
||||
NSString* name = self.fPath.lastPathComponent;
|
||||
|
||||
self.window.title = name;
|
||||
|
||||
fNameField.stringValue = name;
|
||||
fNameField.toolTip = fPath.path;
|
||||
self.fNameField.stringValue = name;
|
||||
self.fNameField.toolTip = self.fPath.path;
|
||||
|
||||
BOOL const multifile = fInfo->isFolder;
|
||||
BOOL const multifile = self.fInfo->isFolder;
|
||||
|
||||
NSImage* icon = [NSWorkspace.sharedWorkspace
|
||||
iconForFileType:multifile ? NSFileTypeForHFSTypeCode(kGenericFolderIcon) : fPath.pathExtension];
|
||||
icon.size = fIconView.frame.size;
|
||||
fIconView.image = icon;
|
||||
iconForFileType:multifile ? NSFileTypeForHFSTypeCode(kGenericFolderIcon) : self.fPath.pathExtension];
|
||||
icon.size = self.fIconView.frame.size;
|
||||
self.fIconView.image = icon;
|
||||
|
||||
NSString* statusString = [NSString stringForFileSize:fInfo->totalSize];
|
||||
NSString* statusString = [NSString stringForFileSize:self.fInfo->totalSize];
|
||||
if (multifile)
|
||||
{
|
||||
NSString* fileString;
|
||||
NSInteger count = fInfo->fileCount;
|
||||
NSInteger count = self.fInfo->fileCount;
|
||||
if (count != 1)
|
||||
{
|
||||
fileString = [NSString
|
||||
|
@ -158,53 +185,53 @@ NSMutableSet* creatorWindowControllerSet = nil;
|
|||
}
|
||||
statusString = [NSString stringWithFormat:@"%@, %@", fileString, statusString];
|
||||
}
|
||||
fStatusField.stringValue = statusString;
|
||||
self.fStatusField.stringValue = statusString;
|
||||
|
||||
if (fInfo->pieceCount == 1)
|
||||
if (self.fInfo->pieceCount == 1)
|
||||
{
|
||||
fPiecesField.stringValue = [NSString stringWithFormat:NSLocalizedString(@"1 piece, %@", "Create torrent -> info"),
|
||||
[NSString stringForFileSize:fInfo->pieceSize]];
|
||||
self.fPiecesField.stringValue = [NSString stringWithFormat:NSLocalizedString(@"1 piece, %@", "Create torrent -> info"),
|
||||
[NSString stringForFileSize:self.fInfo->pieceSize]];
|
||||
}
|
||||
else
|
||||
{
|
||||
fPiecesField.stringValue = [NSString stringWithFormat:NSLocalizedString(@"%d pieces, %@ each", "Create torrent -> info"),
|
||||
fInfo->pieceCount,
|
||||
[NSString stringForFileSize:fInfo->pieceSize]];
|
||||
self.fPiecesField.stringValue = [NSString stringWithFormat:NSLocalizedString(@"%d pieces, %@ each", "Create torrent -> info"),
|
||||
self.fInfo->pieceCount,
|
||||
[NSString stringForFileSize:self.fInfo->pieceSize]];
|
||||
}
|
||||
|
||||
fLocation = [[fDefaults URLForKey:@"CreatorLocationURL"] URLByAppendingPathComponent:[name stringByAppendingPathExtension:@"torrent"]];
|
||||
if (!fLocation)
|
||||
self.fLocation = [[self.fDefaults URLForKey:@"CreatorLocationURL"] URLByAppendingPathComponent:[name stringByAppendingPathExtension:@"torrent"]];
|
||||
if (!self.fLocation)
|
||||
{
|
||||
//for 2.5 and earlier
|
||||
#warning we still store "CreatorLocation" in Defaults.plist, and not "CreatorLocationURL"
|
||||
NSString* location = [fDefaults stringForKey:@"CreatorLocation"];
|
||||
fLocation = [[NSURL alloc] initFileURLWithPath:[location.stringByExpandingTildeInPath
|
||||
NSString* location = [self.fDefaults stringForKey:@"CreatorLocation"];
|
||||
self.fLocation = [[NSURL alloc] initFileURLWithPath:[location.stringByExpandingTildeInPath
|
||||
stringByAppendingPathComponent:[name stringByAppendingPathExtension:@"torrent"]]];
|
||||
}
|
||||
[self updateLocationField];
|
||||
|
||||
//set previously saved values
|
||||
if ([fDefaults objectForKey:@"CreatorPrivate"])
|
||||
if ([self.fDefaults objectForKey:@"CreatorPrivate"])
|
||||
{
|
||||
fPrivateCheck.state = [fDefaults boolForKey:@"CreatorPrivate"] ? NSControlStateValueOn : NSControlStateValueOff;
|
||||
self.fPrivateCheck.state = [self.fDefaults boolForKey:@"CreatorPrivate"] ? NSControlStateValueOn : NSControlStateValueOff;
|
||||
}
|
||||
|
||||
if ([fDefaults objectForKey:@"CreatorSource"])
|
||||
if ([self.fDefaults objectForKey:@"CreatorSource"])
|
||||
{
|
||||
fSource.stringValue = [fDefaults stringForKey:@"CreatorSource"];
|
||||
self.fSource.stringValue = [self.fDefaults stringForKey:@"CreatorSource"];
|
||||
}
|
||||
|
||||
fOpenCheck.state = [fDefaults boolForKey:@"CreatorOpen"] ? NSControlStateValueOn : NSControlStateValueOff;
|
||||
self.fOpenCheck.state = [self.fDefaults boolForKey:@"CreatorOpen"] ? NSControlStateValueOn : NSControlStateValueOff;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
if (fInfo)
|
||||
if (_fInfo)
|
||||
{
|
||||
tr_metaInfoBuilderFree(fInfo);
|
||||
tr_metaInfoBuilderFree(_fInfo);
|
||||
}
|
||||
|
||||
[fTimer invalidate];
|
||||
[_fTimer invalidate];
|
||||
}
|
||||
|
||||
+ (void)restoreWindowWithIdentifier:(NSString*)identifier
|
||||
|
@ -224,27 +251,27 @@ NSMutableSet* creatorWindowControllerSet = nil;
|
|||
|
||||
- (void)window:(NSWindow*)window willEncodeRestorableState:(NSCoder*)state
|
||||
{
|
||||
[state encodeObject:fPath forKey:@"TRCreatorPath"];
|
||||
[state encodeObject:fLocation forKey:@"TRCreatorLocation"];
|
||||
[state encodeObject:fTrackers forKey:@"TRCreatorTrackers"];
|
||||
[state encodeInteger:fOpenCheck.state forKey:@"TRCreatorOpenCheck"];
|
||||
[state encodeInteger:fPrivateCheck.state forKey:@"TRCreatorPrivateCheck"];
|
||||
[state encodeObject:fSource.stringValue forKey:@"TRCreatorSource"];
|
||||
[state encodeObject:fCommentView.string forKey:@"TRCreatorPrivateComment"];
|
||||
[state encodeObject:self.fPath forKey:@"TRCreatorPath"];
|
||||
[state encodeObject:self.fLocation forKey:@"TRCreatorLocation"];
|
||||
[state encodeObject:self.fTrackers forKey:@"TRCreatorTrackers"];
|
||||
[state encodeInteger:self.fOpenCheck.state forKey:@"TRCreatorOpenCheck"];
|
||||
[state encodeInteger:self.fPrivateCheck.state forKey:@"TRCreatorPrivateCheck"];
|
||||
[state encodeObject:self.fSource.stringValue forKey:@"TRCreatorSource"];
|
||||
[state encodeObject:self.fCommentView.string forKey:@"TRCreatorPrivateComment"];
|
||||
}
|
||||
|
||||
- (void)window:(NSWindow*)window didDecodeRestorableState:(NSCoder*)coder
|
||||
{
|
||||
fLocation = [coder decodeObjectForKey:@"TRCreatorLocation"];
|
||||
self.fLocation = [coder decodeObjectForKey:@"TRCreatorLocation"];
|
||||
[self updateLocationField];
|
||||
|
||||
fTrackers = [coder decodeObjectForKey:@"TRCreatorTrackers"];
|
||||
[fTrackerTable reloadData];
|
||||
self.fTrackers = [coder decodeObjectForKey:@"TRCreatorTrackers"];
|
||||
[self.fTrackerTable reloadData];
|
||||
|
||||
fOpenCheck.state = [coder decodeIntegerForKey:@"TRCreatorOpenCheck"];
|
||||
fPrivateCheck.state = [coder decodeIntegerForKey:@"TRCreatorPrivateCheck"];
|
||||
fSource.stringValue = [coder decodeObjectForKey:@"TRCreatorSource"];
|
||||
fCommentView.string = [coder decodeObjectForKey:@"TRCreatorPrivateComment"];
|
||||
self.fOpenCheck.state = [coder decodeIntegerForKey:@"TRCreatorOpenCheck"];
|
||||
self.fPrivateCheck.state = [coder decodeIntegerForKey:@"TRCreatorPrivateCheck"];
|
||||
self.fSource.stringValue = [coder decodeObjectForKey:@"TRCreatorSource"];
|
||||
self.fCommentView.string = [coder decodeObjectForKey:@"TRCreatorPrivateComment"];
|
||||
}
|
||||
|
||||
- (IBAction)setLocation:(id)sender
|
||||
|
@ -257,13 +284,13 @@ NSMutableSet* creatorWindowControllerSet = nil;
|
|||
panel.allowedFileTypes = @[ @"org.bittorrent.torrent", @"torrent" ];
|
||||
panel.canSelectHiddenExtension = YES;
|
||||
|
||||
panel.directoryURL = fLocation.URLByDeletingLastPathComponent;
|
||||
panel.nameFieldStringValue = fLocation.lastPathComponent;
|
||||
panel.directoryURL = self.fLocation.URLByDeletingLastPathComponent;
|
||||
panel.nameFieldStringValue = self.fLocation.lastPathComponent;
|
||||
|
||||
[panel beginSheetModalForWindow:self.window completionHandler:^(NSInteger result) {
|
||||
if (result == NSModalResponseOK)
|
||||
{
|
||||
fLocation = panel.URL;
|
||||
self.fLocation = panel.URL;
|
||||
[self updateLocationField];
|
||||
}
|
||||
}];
|
||||
|
@ -272,13 +299,13 @@ NSMutableSet* creatorWindowControllerSet = nil;
|
|||
- (IBAction)create:(id)sender
|
||||
{
|
||||
//make sure the trackers are no longer being verified
|
||||
if (fTrackerTable.editedRow != -1)
|
||||
if (self.fTrackerTable.editedRow != -1)
|
||||
{
|
||||
[self.window endEditingFor:fTrackerTable];
|
||||
[self.window endEditingFor:self.fTrackerTable];
|
||||
}
|
||||
|
||||
BOOL const isPrivate = fPrivateCheck.state == NSControlStateValueOn;
|
||||
if (fTrackers.count == 0 && [fDefaults boolForKey:isPrivate ? @"WarningCreatorPrivateBlankAddress" : @"WarningCreatorBlankAddress"])
|
||||
BOOL const isPrivate = self.fPrivateCheck.state == NSControlStateValueOn;
|
||||
if (self.fTrackers.count == 0 && [self.fDefaults boolForKey:isPrivate ? @"WarningCreatorPrivateBlankAddress" : @"WarningCreatorBlankAddress"])
|
||||
{
|
||||
NSAlert* alert = [[NSAlert alloc] init];
|
||||
alert.messageText = NSLocalizedString(@"There are no tracker addresses.", "Create torrent -> blank address -> title");
|
||||
|
@ -303,7 +330,7 @@ NSMutableSet* creatorWindowControllerSet = nil;
|
|||
if (alert.suppressionButton.state == NSControlStateValueOn)
|
||||
{
|
||||
[NSUserDefaults.standardUserDefaults setBool:NO forKey:@"WarningCreatorBlankAddress"]; //set regardless of private/public
|
||||
if (fPrivateCheck.state == NSControlStateValueOn)
|
||||
if (self.fPrivateCheck.state == NSControlStateValueOn)
|
||||
{
|
||||
[NSUserDefaults.standardUserDefaults setBool:NO forKey:@"WarningCreatorPrivateBlankAddress"];
|
||||
}
|
||||
|
@ -333,43 +360,43 @@ NSMutableSet* creatorWindowControllerSet = nil;
|
|||
|
||||
- (IBAction)cancelCreateProgress:(id)sender
|
||||
{
|
||||
fInfo->abortFlag = 1;
|
||||
[fTimer fire];
|
||||
self.fInfo->abortFlag = 1;
|
||||
[self.fTimer fire];
|
||||
}
|
||||
|
||||
- (NSInteger)numberOfRowsInTableView:(NSTableView*)tableView
|
||||
{
|
||||
return fTrackers.count;
|
||||
return self.fTrackers.count;
|
||||
}
|
||||
|
||||
- (id)tableView:(NSTableView*)tableView objectValueForTableColumn:(NSTableColumn*)tableColumn row:(NSInteger)row
|
||||
{
|
||||
return fTrackers[row];
|
||||
return self.fTrackers[row];
|
||||
}
|
||||
|
||||
- (IBAction)addRemoveTracker:(id)sender
|
||||
{
|
||||
//don't allow add/remove when currently adding - it leads to weird results
|
||||
if (fTrackerTable.editedRow != -1)
|
||||
if (self.fTrackerTable.editedRow != -1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ([[sender cell] tagForSegment:[sender selectedSegment]] == TRACKER_REMOVE_TAG)
|
||||
{
|
||||
[fTrackers removeObjectsAtIndexes:fTrackerTable.selectedRowIndexes];
|
||||
[self.fTrackers removeObjectsAtIndexes:self.fTrackerTable.selectedRowIndexes];
|
||||
|
||||
[fTrackerTable deselectAll:self];
|
||||
[fTrackerTable reloadData];
|
||||
[self.fTrackerTable deselectAll:self];
|
||||
[self.fTrackerTable reloadData];
|
||||
}
|
||||
else
|
||||
{
|
||||
[fTrackers addObject:@""];
|
||||
[fTrackerTable reloadData];
|
||||
[self.fTrackers addObject:@""];
|
||||
[self.fTrackerTable reloadData];
|
||||
|
||||
NSInteger const row = fTrackers.count - 1;
|
||||
[fTrackerTable selectRowIndexes:[NSIndexSet indexSetWithIndex:row] byExtendingSelection:NO];
|
||||
[fTrackerTable editColumn:0 row:row withEvent:nil select:YES];
|
||||
NSInteger const row = self.fTrackers.count - 1;
|
||||
[self.fTrackerTable selectRowIndexes:[NSIndexSet indexSetWithIndex:row] byExtendingSelection:NO];
|
||||
[self.fTrackerTable editColumn:0 row:row withEvent:nil select:YES];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -390,25 +417,25 @@ NSMutableSet* creatorWindowControllerSet = nil;
|
|||
if (!tr_urlIsValidTracker(tracker.UTF8String))
|
||||
{
|
||||
NSBeep();
|
||||
[fTrackers removeObjectAtIndex:row];
|
||||
[self.fTrackers removeObjectAtIndex:row];
|
||||
}
|
||||
else
|
||||
{
|
||||
fTrackers[row] = tracker;
|
||||
self.fTrackers[row] = tracker;
|
||||
}
|
||||
|
||||
[fTrackerTable deselectAll:self];
|
||||
[fTrackerTable reloadData];
|
||||
[self.fTrackerTable deselectAll:self];
|
||||
[self.fTrackerTable reloadData];
|
||||
}
|
||||
|
||||
- (void)tableViewSelectionDidChange:(NSNotification*)notification
|
||||
{
|
||||
[fTrackerAddRemoveControl setEnabled:fTrackerTable.numberOfSelectedRows > 0 forSegment:TRACKER_REMOVE_TAG];
|
||||
[self.fTrackerAddRemoveControl setEnabled:self.fTrackerTable.numberOfSelectedRows > 0 forSegment:TRACKER_REMOVE_TAG];
|
||||
}
|
||||
|
||||
- (void)copy:(id)sender
|
||||
{
|
||||
NSArray* addresses = [fTrackers objectsAtIndexes:fTrackerTable.selectedRowIndexes];
|
||||
NSArray* addresses = [self.fTrackers objectsAtIndexes:self.fTrackerTable.selectedRowIndexes];
|
||||
NSString* text = [addresses componentsJoinedByString:@"\n"];
|
||||
|
||||
NSPasteboard* pb = NSPasteboard.generalPasteboard;
|
||||
|
@ -422,12 +449,12 @@ NSMutableSet* creatorWindowControllerSet = nil;
|
|||
|
||||
if (action == @selector(copy:))
|
||||
{
|
||||
return self.window.firstResponder == fTrackerTable && fTrackerTable.numberOfSelectedRows > 0;
|
||||
return self.window.firstResponder == self.fTrackerTable && self.fTrackerTable.numberOfSelectedRows > 0;
|
||||
}
|
||||
|
||||
if (action == @selector(paste:))
|
||||
{
|
||||
return self.window.firstResponder == fTrackerTable &&
|
||||
return self.window.firstResponder == self.fTrackerTable &&
|
||||
[NSPasteboard.generalPasteboard canReadObjectForClasses:@[ [NSString class] ] options:nil];
|
||||
}
|
||||
|
||||
|
@ -462,15 +489,15 @@ NSMutableSet* creatorWindowControllerSet = nil;
|
|||
|
||||
if (tr_urlIsValidTracker(tracker.UTF8String))
|
||||
{
|
||||
[fTrackers addObject:tracker];
|
||||
[self.fTrackers addObject:tracker];
|
||||
added = YES;
|
||||
}
|
||||
}
|
||||
|
||||
if (added)
|
||||
{
|
||||
[fTrackerTable deselectAll:self];
|
||||
[fTrackerTable reloadData];
|
||||
[self.fTrackerTable deselectAll:self];
|
||||
[self.fTrackerTable reloadData];
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -478,11 +505,13 @@ NSMutableSet* creatorWindowControllerSet = nil;
|
|||
}
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
- (void)updateLocationField
|
||||
{
|
||||
NSString* pathString = fLocation.path;
|
||||
fLocationField.stringValue = pathString.stringByAbbreviatingWithTildeInPath;
|
||||
fLocationField.toolTip = pathString;
|
||||
NSString* pathString = self.fLocation.path;
|
||||
self.fLocationField.stringValue = pathString.stringByAbbreviatingWithTildeInPath;
|
||||
self.fLocationField.toolTip = pathString;
|
||||
}
|
||||
|
||||
+ (NSURL*)chooseFile
|
||||
|
@ -505,7 +534,7 @@ NSMutableSet* creatorWindowControllerSet = nil;
|
|||
- (void)createReal
|
||||
{
|
||||
//check if the location currently exists
|
||||
if (![fLocation.URLByDeletingLastPathComponent checkResourceIsReachableAndReturnError:NULL])
|
||||
if (![self.fLocation.URLByDeletingLastPathComponent checkResourceIsReachableAndReturnError:NULL])
|
||||
{
|
||||
NSAlert* alert = [[NSAlert alloc] init];
|
||||
[alert addButtonWithTitle:NSLocalizedString(@"OK", "Create torrent -> directory doesn't exist warning -> button")];
|
||||
|
@ -514,7 +543,7 @@ NSMutableSet* creatorWindowControllerSet = nil;
|
|||
@"The directory \"%@\" does not currently exist. "
|
||||
"Create this directory or choose a different one to create the torrent file.",
|
||||
"Create torrent -> directory doesn't exist warning -> warning"),
|
||||
fLocation.URLByDeletingLastPathComponent.path];
|
||||
self.fLocation.URLByDeletingLastPathComponent.path];
|
||||
alert.alertStyle = NSAlertStyleWarning;
|
||||
|
||||
[alert beginSheetModalForWindow:self.window completionHandler:nil];
|
||||
|
@ -522,9 +551,9 @@ NSMutableSet* creatorWindowControllerSet = nil;
|
|||
}
|
||||
|
||||
//check if a file with the same name and location already exists
|
||||
if ([fLocation checkResourceIsReachableAndReturnError:NULL])
|
||||
if ([self.fLocation checkResourceIsReachableAndReturnError:NULL])
|
||||
{
|
||||
NSArray* pathComponents = fLocation.pathComponents;
|
||||
NSArray* pathComponents = self.fLocation.pathComponents;
|
||||
NSInteger count = pathComponents.count;
|
||||
|
||||
NSAlert* alert = [[NSAlert alloc] init];
|
||||
|
@ -545,54 +574,54 @@ NSMutableSet* creatorWindowControllerSet = nil;
|
|||
}
|
||||
|
||||
//parse non-empty tracker strings
|
||||
tr_tracker_info* trackerInfo = tr_new0(tr_tracker_info, fTrackers.count);
|
||||
tr_tracker_info* trackerInfo = tr_new0(tr_tracker_info, self.fTrackers.count);
|
||||
|
||||
for (NSUInteger i = 0; i < fTrackers.count; i++)
|
||||
for (NSUInteger i = 0; i < self.fTrackers.count; i++)
|
||||
{
|
||||
trackerInfo[i].announce = (char*)[fTrackers[i] UTF8String];
|
||||
trackerInfo[i].announce = (char*)[self.fTrackers[i] UTF8String];
|
||||
trackerInfo[i].tier = i;
|
||||
}
|
||||
|
||||
//store values
|
||||
[fDefaults setObject:fTrackers forKey:@"CreatorTrackers"];
|
||||
[fDefaults setBool:fPrivateCheck.state == NSControlStateValueOn forKey:@"CreatorPrivate"];
|
||||
[fDefaults setObject: [fSource stringValue] forKey: @"CreatorSource"];
|
||||
[fDefaults setBool:fOpenCheck.state == NSControlStateValueOn forKey:@"CreatorOpen"];
|
||||
fOpenWhenCreated = fOpenCheck.state == NSControlStateValueOn; //need this since the check box might not exist, and value in prefs might have changed from another creator window
|
||||
[fDefaults setURL:fLocation.URLByDeletingLastPathComponent forKey:@"CreatorLocationURL"];
|
||||
[self.fDefaults setObject:self.fTrackers forKey:@"CreatorTrackers"];
|
||||
[self.fDefaults setBool:self.fPrivateCheck.state == NSControlStateValueOn forKey:@"CreatorPrivate"];
|
||||
[self.fDefaults setObject: [self.fSource stringValue] forKey: @"CreatorSource"];
|
||||
[self.fDefaults setBool:self.fOpenCheck.state == NSControlStateValueOn forKey:@"CreatorOpen"];
|
||||
self.fOpenWhenCreated = self.fOpenCheck.state == NSControlStateValueOn; //need this since the check box might not exist, and value in prefs might have changed from another creator window
|
||||
[self.fDefaults setURL:self.fLocation.URLByDeletingLastPathComponent forKey:@"CreatorLocationURL"];
|
||||
|
||||
self.window.restorable = NO;
|
||||
|
||||
[NSNotificationCenter.defaultCenter postNotificationName:@"BeginCreateTorrentFile" object:fLocation userInfo:nil];
|
||||
[NSNotificationCenter.defaultCenter postNotificationName:@"BeginCreateTorrentFile" object:self.fLocation userInfo:nil];
|
||||
tr_makeMetaInfo(
|
||||
fInfo,
|
||||
fLocation.path.UTF8String,
|
||||
self.fInfo,
|
||||
self.fLocation.path.UTF8String,
|
||||
trackerInfo,
|
||||
fTrackers.count,
|
||||
self.fTrackers.count,
|
||||
nullptr,
|
||||
0,
|
||||
fCommentView.string.UTF8String,
|
||||
fPrivateCheck.state == NSControlStateValueOn,
|
||||
fSource.stringValue.UTF8String);
|
||||
self.fCommentView.string.UTF8String,
|
||||
self.fPrivateCheck.state == NSControlStateValueOn,
|
||||
self.fSource.stringValue.UTF8String);
|
||||
tr_free(trackerInfo);
|
||||
|
||||
fTimer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(checkProgress) userInfo:nil repeats:YES];
|
||||
self.fTimer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(checkProgress) userInfo:nil repeats:YES];
|
||||
}
|
||||
|
||||
- (void)checkProgress
|
||||
{
|
||||
if (fInfo->isDone)
|
||||
if (self.fInfo->isDone)
|
||||
{
|
||||
[fTimer invalidate];
|
||||
fTimer = nil;
|
||||
[self.fTimer invalidate];
|
||||
self.fTimer = nil;
|
||||
|
||||
NSAlert* alert;
|
||||
switch (fInfo->result)
|
||||
switch (self.fInfo->result)
|
||||
{
|
||||
case TrMakemetaResult::OK:
|
||||
if (fOpenWhenCreated)
|
||||
if (self.fOpenWhenCreated)
|
||||
{
|
||||
NSDictionary* dict = @{ @"File" : fLocation.path, @"Path" : fPath.URLByDeletingLastPathComponent.path };
|
||||
NSDictionary* dict = @{ @"File" : self.fLocation.path, @"Path" : self.fPath.URLByDeletingLastPathComponent.path };
|
||||
[NSNotificationCenter.defaultCenter postNotificationName:@"OpenCreatedTorrentFile" object:self userInfo:dict];
|
||||
}
|
||||
|
||||
|
@ -607,29 +636,29 @@ NSMutableSet* creatorWindowControllerSet = nil;
|
|||
alert = [[NSAlert alloc] init];
|
||||
[alert addButtonWithTitle:NSLocalizedString(@"OK", "Create torrent -> failed -> button")];
|
||||
alert.messageText = [NSString stringWithFormat:NSLocalizedString(@"Creation of \"%@\" failed.", "Create torrent -> failed -> title"),
|
||||
fLocation.lastPathComponent];
|
||||
self.fLocation.lastPathComponent];
|
||||
alert.alertStyle = NSAlertStyleWarning;
|
||||
|
||||
if (fInfo->result == TrMakemetaResult::ERR_IO_READ)
|
||||
if (self.fInfo->result == TrMakemetaResult::ERR_IO_READ)
|
||||
{
|
||||
alert.informativeText = [NSString
|
||||
stringWithFormat:NSLocalizedString(@"Could not read \"%s\": %s.", "Create torrent -> failed -> warning"),
|
||||
fInfo->errfile,
|
||||
strerror(fInfo->my_errno)];
|
||||
self.fInfo->errfile,
|
||||
strerror(self.fInfo->my_errno)];
|
||||
}
|
||||
else if (fInfo->result == TrMakemetaResult::ERR_IO_WRITE)
|
||||
else if (self.fInfo->result == TrMakemetaResult::ERR_IO_WRITE)
|
||||
{
|
||||
alert.informativeText = [NSString
|
||||
stringWithFormat:NSLocalizedString(@"Could not write \"%s\": %s.", "Create torrent -> failed -> warning"),
|
||||
fInfo->errfile,
|
||||
strerror(fInfo->my_errno)];
|
||||
self.fInfo->errfile,
|
||||
strerror(self.fInfo->my_errno)];
|
||||
}
|
||||
else //invalid url should have been caught before creating
|
||||
{
|
||||
alert.informativeText = [NSString
|
||||
stringWithFormat:@"%@ (%d)",
|
||||
NSLocalizedString(@"An unknown error has occurred.", "Create torrent -> failed -> warning"),
|
||||
fInfo->result];
|
||||
self.fInfo->result];
|
||||
}
|
||||
|
||||
[alert beginSheetModalForWindow:self.window completionHandler:^(NSModalResponse returnCode) {
|
||||
|
@ -640,19 +669,19 @@ NSMutableSet* creatorWindowControllerSet = nil;
|
|||
}
|
||||
else
|
||||
{
|
||||
fProgressIndicator.doubleValue = (double)fInfo->pieceIndex / fInfo->pieceCount;
|
||||
self.fProgressIndicator.doubleValue = (double)self.fInfo->pieceIndex / self.fInfo->pieceCount;
|
||||
|
||||
if (!fStarted)
|
||||
if (!self.fStarted)
|
||||
{
|
||||
fStarted = YES;
|
||||
self.fStarted = YES;
|
||||
|
||||
fProgressView.hidden = YES;
|
||||
self.fProgressView.hidden = YES;
|
||||
|
||||
NSWindow* window = self.window;
|
||||
window.frameAutosaveName = @"";
|
||||
|
||||
NSRect windowRect = window.frame;
|
||||
CGFloat difference = fProgressView.frame.size.height - window.contentView.frame.size.height;
|
||||
CGFloat difference = self.fProgressView.frame.size.height - window.contentView.frame.size.height;
|
||||
windowRect.origin.y -= difference;
|
||||
windowRect.size.height += difference;
|
||||
|
||||
|
@ -661,9 +690,9 @@ NSMutableSet* creatorWindowControllerSet = nil;
|
|||
window.minSize = NSMakeSize(window.minSize.width, height);
|
||||
window.maxSize = NSMakeSize(window.maxSize.width, height);
|
||||
|
||||
window.contentView = fProgressView;
|
||||
window.contentView = self.fProgressView;
|
||||
[window setFrame:windowRect display:YES animate:YES];
|
||||
fProgressView.hidden = NO;
|
||||
self.fProgressView.hidden = NO;
|
||||
|
||||
[window standardWindowButton:NSWindowCloseButton].enabled = NO;
|
||||
}
|
||||
|
|
|
@ -5,12 +5,6 @@
|
|||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
@interface DragOverlayView : NSView
|
||||
{
|
||||
NSImage* fBadge;
|
||||
|
||||
NSDictionary* fMainLineAttributes;
|
||||
NSDictionary* fSubLineAttributes;
|
||||
}
|
||||
|
||||
- (void)setOverlay:(NSImage*)icon mainLine:(NSString*)mainLine subLine:(NSString*)subLine;
|
||||
|
||||
|
|
|
@ -7,6 +7,15 @@
|
|||
#define PADDING 10.0
|
||||
#define ICON_WIDTH 64.0
|
||||
|
||||
@interface DragOverlayView ()
|
||||
|
||||
@property(nonatomic) NSImage* fBadge;
|
||||
|
||||
@property(nonatomic, readonly) NSDictionary* fMainLineAttributes;
|
||||
@property(nonatomic, readonly) NSDictionary* fSubLineAttributes;
|
||||
|
||||
@end
|
||||
|
||||
@implementation DragOverlayView
|
||||
|
||||
- (instancetype)initWithFrame:(NSRect)frame
|
||||
|
@ -23,14 +32,14 @@
|
|||
NSMutableParagraphStyle* paragraphStyle = [NSParagraphStyle.defaultParagraphStyle mutableCopy];
|
||||
paragraphStyle.lineBreakMode = NSLineBreakByTruncatingMiddle;
|
||||
|
||||
fMainLineAttributes = @{
|
||||
_fMainLineAttributes = @{
|
||||
NSForegroundColorAttributeName : NSColor.whiteColor,
|
||||
NSFontAttributeName : bigFont,
|
||||
NSShadowAttributeName : stringShadow,
|
||||
NSParagraphStyleAttributeName : paragraphStyle
|
||||
};
|
||||
|
||||
fSubLineAttributes = @{
|
||||
_fSubLineAttributes = @{
|
||||
NSForegroundColorAttributeName : NSColor.whiteColor,
|
||||
NSFontAttributeName : smallFont,
|
||||
NSShadowAttributeName : stringShadow,
|
||||
|
@ -45,8 +54,8 @@
|
|||
//create badge
|
||||
NSRect const badgeRect = NSMakeRect(0.0, 0.0, 325.0, 84.0);
|
||||
|
||||
fBadge = [[NSImage alloc] initWithSize:badgeRect.size];
|
||||
[fBadge lockFocus];
|
||||
self.fBadge = [[NSImage alloc] initWithSize:badgeRect.size];
|
||||
[self.fBadge lockFocus];
|
||||
|
||||
NSBezierPath* bp = [NSBezierPath bezierPathWithRoundedRect:badgeRect xRadius:15.0 yRadius:15.0];
|
||||
[[NSColor colorWithCalibratedWhite:0.0 alpha:0.75] set];
|
||||
|
@ -58,33 +67,33 @@
|
|||
fraction:1.0];
|
||||
|
||||
//place main text
|
||||
NSSize const mainLineSize = [mainLine sizeWithAttributes:fMainLineAttributes];
|
||||
NSSize const subLineSize = [subLine sizeWithAttributes:fSubLineAttributes];
|
||||
NSSize const mainLineSize = [mainLine sizeWithAttributes:self.fMainLineAttributes];
|
||||
NSSize const subLineSize = [subLine sizeWithAttributes:self.fSubLineAttributes];
|
||||
|
||||
NSRect lineRect = NSMakeRect(
|
||||
PADDING + ICON_WIDTH + 5.0,
|
||||
(NSHeight(badgeRect) + (subLineSize.height + 2.0 - mainLineSize.height)) * 0.5,
|
||||
NSWidth(badgeRect) - (PADDING + ICON_WIDTH + 2.0) - PADDING,
|
||||
mainLineSize.height);
|
||||
[mainLine drawInRect:lineRect withAttributes:fMainLineAttributes];
|
||||
[mainLine drawInRect:lineRect withAttributes:self.fMainLineAttributes];
|
||||
|
||||
//place sub text
|
||||
lineRect.origin.y -= subLineSize.height + 2.0;
|
||||
lineRect.size.height = subLineSize.height;
|
||||
[subLine drawInRect:lineRect withAttributes:fSubLineAttributes];
|
||||
[subLine drawInRect:lineRect withAttributes:self.fSubLineAttributes];
|
||||
|
||||
[fBadge unlockFocus];
|
||||
[self.fBadge unlockFocus];
|
||||
|
||||
self.needsDisplay = YES;
|
||||
}
|
||||
|
||||
- (void)drawRect:(NSRect)rect
|
||||
{
|
||||
if (fBadge)
|
||||
if (self.fBadge)
|
||||
{
|
||||
NSRect const frame = self.frame;
|
||||
NSSize const imageSize = fBadge.size;
|
||||
[fBadge drawAtPoint:NSMakePoint((NSWidth(frame) - imageSize.width) * 0.5, (NSHeight(frame) - imageSize.height) * 0.5)
|
||||
NSSize const imageSize = self.fBadge.size;
|
||||
[self.fBadge drawAtPoint:NSMakePoint((NSWidth(frame) - imageSize.width) * 0.5, (NSHeight(frame) - imageSize.height) * 0.5)
|
||||
fromRect:NSZeroRect
|
||||
operation:NSCompositingOperationSourceOver
|
||||
fraction:1.0];
|
||||
|
|
|
@ -7,12 +7,6 @@
|
|||
#include <libtransmission/transmission.h>
|
||||
|
||||
@interface DragOverlayWindow : NSWindow
|
||||
{
|
||||
tr_session* fLib;
|
||||
|
||||
NSViewAnimation* fFadeInAnimation;
|
||||
NSViewAnimation* fFadeOutAnimation;
|
||||
}
|
||||
|
||||
- (instancetype)initWithLib:(tr_session*)lib forWindow:(NSWindow*)window;
|
||||
|
||||
|
|
|
@ -11,6 +11,11 @@
|
|||
|
||||
@interface DragOverlayWindow ()
|
||||
|
||||
@property(nonatomic, readonly) tr_session* fLib;
|
||||
|
||||
@property(nonatomic, readonly) NSViewAnimation* fFadeInAnimation;
|
||||
@property(nonatomic, readonly) NSViewAnimation* fFadeOutAnimation;
|
||||
|
||||
- (void)resizeWindow;
|
||||
|
||||
@end
|
||||
|
@ -24,7 +29,7 @@
|
|||
backing:NSBackingStoreBuffered
|
||||
defer:NO])))
|
||||
{
|
||||
fLib = lib;
|
||||
_fLib = lib;
|
||||
|
||||
self.backgroundColor = [NSColor colorWithCalibratedWhite:0.0 alpha:0.5];
|
||||
self.alphaValue = 0.0;
|
||||
|
@ -37,17 +42,17 @@
|
|||
self.releasedWhenClosed = NO;
|
||||
self.ignoresMouseEvents = YES;
|
||||
|
||||
fFadeInAnimation = [[NSViewAnimation alloc] initWithViewAnimations:@[
|
||||
_fFadeInAnimation = [[NSViewAnimation alloc] initWithViewAnimations:@[
|
||||
@{ NSViewAnimationTargetKey : self, NSViewAnimationEffectKey : NSViewAnimationFadeInEffect }
|
||||
]];
|
||||
fFadeInAnimation.duration = 0.15;
|
||||
fFadeInAnimation.animationBlockingMode = NSAnimationNonblockingThreaded;
|
||||
_fFadeInAnimation.duration = 0.15;
|
||||
_fFadeInAnimation.animationBlockingMode = NSAnimationNonblockingThreaded;
|
||||
|
||||
fFadeOutAnimation = [[NSViewAnimation alloc] initWithViewAnimations:@[
|
||||
_fFadeOutAnimation = [[NSViewAnimation alloc] initWithViewAnimations:@[
|
||||
@{ NSViewAnimationTargetKey : self, NSViewAnimationEffectKey : NSViewAnimationFadeOutEffect }
|
||||
]];
|
||||
fFadeOutAnimation.duration = 0.5;
|
||||
fFadeOutAnimation.animationBlockingMode = NSAnimationNonblockingThreaded;
|
||||
_fFadeOutAnimation.duration = 0.5;
|
||||
_fFadeOutAnimation.animationBlockingMode = NSAnimationNonblockingThreaded;
|
||||
|
||||
[window addChildWindow:self ordered:NSWindowAbove];
|
||||
|
||||
|
@ -149,28 +154,30 @@
|
|||
- (void)fadeIn
|
||||
{
|
||||
//stop other animation and set to same progress
|
||||
if (fFadeOutAnimation.animating)
|
||||
if (self.fFadeOutAnimation.animating)
|
||||
{
|
||||
[fFadeOutAnimation stopAnimation];
|
||||
fFadeInAnimation.currentProgress = 1.0 - fFadeOutAnimation.currentProgress;
|
||||
[self.fFadeOutAnimation stopAnimation];
|
||||
self.fFadeInAnimation.currentProgress = 1.0 - self.fFadeOutAnimation.currentProgress;
|
||||
}
|
||||
[fFadeInAnimation startAnimation];
|
||||
[self.fFadeInAnimation startAnimation];
|
||||
}
|
||||
|
||||
- (void)fadeOut
|
||||
{
|
||||
//stop other animation and set to same progress
|
||||
if (fFadeInAnimation.animating)
|
||||
if (self.fFadeInAnimation.animating)
|
||||
{
|
||||
[fFadeInAnimation stopAnimation];
|
||||
fFadeOutAnimation.currentProgress = 1.0 - fFadeInAnimation.currentProgress;
|
||||
[self.fFadeInAnimation stopAnimation];
|
||||
self.fFadeOutAnimation.currentProgress = 1.0 - self.fFadeInAnimation.currentProgress;
|
||||
}
|
||||
if (self.alphaValue > 0.0)
|
||||
{
|
||||
[fFadeOutAnimation startAnimation];
|
||||
[self.fFadeOutAnimation startAnimation];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
- (void)resizeWindow
|
||||
{
|
||||
[self setFrame:self.parentWindow.frame display:NO];
|
||||
|
|
|
@ -5,7 +5,5 @@
|
|||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface ExpandedPathToIconTransformer : NSValueTransformer
|
||||
{
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -5,7 +5,5 @@
|
|||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface ExpandedPathToPathTransformer : NSValueTransformer
|
||||
{
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -6,16 +6,14 @@
|
|||
|
||||
@interface FileListNode ()
|
||||
|
||||
@property(nonatomic, readonly) NSMutableIndexSet* indexesInternal;
|
||||
@property(nonatomic) NSImage* iconInternal;
|
||||
|
||||
- (instancetype)initWithFolder:(BOOL)isFolder name:(NSString*)name path:(NSString*)path torrent:(Torrent*)torrent;
|
||||
|
||||
@end
|
||||
|
||||
@implementation FileListNode
|
||||
{
|
||||
NSMutableIndexSet* _indexes;
|
||||
NSImage* _icon;
|
||||
NSMutableArray* _children;
|
||||
}
|
||||
|
||||
- (instancetype)initWithFolderName:(NSString*)name path:(NSString*)path torrent:(Torrent*)torrent
|
||||
{
|
||||
|
@ -37,7 +35,7 @@
|
|||
if ((self = [self initWithFolder:NO name:name path:path torrent:torrent]))
|
||||
{
|
||||
_size = size;
|
||||
[_indexes addIndex:index];
|
||||
[_indexesInternal addIndex:index];
|
||||
}
|
||||
|
||||
return self;
|
||||
|
@ -54,7 +52,7 @@
|
|||
{
|
||||
NSAssert(_isFolder, @"method can only be invoked on folders");
|
||||
|
||||
[_indexes addIndex:index];
|
||||
[self.indexesInternal addIndex:index];
|
||||
_size += size;
|
||||
}
|
||||
|
||||
|
@ -68,33 +66,26 @@
|
|||
{
|
||||
if (!_isFolder)
|
||||
{
|
||||
return [NSString stringWithFormat:@"%@ (%ld)", _name, _indexes.firstIndex];
|
||||
return [NSString stringWithFormat:@"%@ (%ld)", _name, _indexesInternal.firstIndex];
|
||||
}
|
||||
else
|
||||
{
|
||||
return [NSString stringWithFormat:@"%@ (folder: %@)", _name, _indexes];
|
||||
return [NSString stringWithFormat:@"%@ (folder: %@)", _name, _indexesInternal];
|
||||
}
|
||||
}
|
||||
|
||||
- (NSImage*)icon
|
||||
{
|
||||
if (!_icon)
|
||||
if (!_iconInternal)
|
||||
{
|
||||
_icon = [NSWorkspace.sharedWorkspace iconForFileType:_isFolder ? NSFileTypeForHFSTypeCode(kGenericFolderIcon) : _name.pathExtension];
|
||||
_iconInternal = [NSWorkspace.sharedWorkspace iconForFileType:_isFolder ? NSFileTypeForHFSTypeCode(kGenericFolderIcon) : _name.pathExtension];
|
||||
}
|
||||
return _icon;
|
||||
}
|
||||
|
||||
- (NSMutableArray*)children
|
||||
{
|
||||
NSAssert(_isFolder, @"method can only be invoked on folders");
|
||||
|
||||
return _children;
|
||||
return _iconInternal;
|
||||
}
|
||||
|
||||
- (NSIndexSet*)indexes
|
||||
{
|
||||
return _indexes;
|
||||
return _indexesInternal;
|
||||
}
|
||||
|
||||
- (BOOL)updateFromOldName:(NSString*)oldName toNewName:(NSString*)newName inPath:(NSString*)path
|
||||
|
@ -111,7 +102,7 @@
|
|||
if ([oldName isEqualToString:self.name])
|
||||
{
|
||||
_name = [newName copy];
|
||||
_icon = nil;
|
||||
_iconInternal = nil;
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
|
@ -137,6 +128,8 @@
|
|||
return NO;
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
- (instancetype)initWithFolder:(BOOL)isFolder name:(NSString*)name path:(NSString*)path torrent:(Torrent*)torrent
|
||||
{
|
||||
if ((self = [super init]))
|
||||
|
@ -145,7 +138,7 @@
|
|||
_name = [name copy];
|
||||
_path = [path copy];
|
||||
|
||||
_indexes = [[NSMutableIndexSet alloc] init];
|
||||
_indexesInternal = [[NSMutableIndexSet alloc] init];
|
||||
|
||||
_torrent = torrent;
|
||||
}
|
||||
|
|
|
@ -5,10 +5,6 @@
|
|||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
@interface FileNameCell : NSActionCell
|
||||
{
|
||||
NSMutableDictionary* fTitleAttributes;
|
||||
NSMutableDictionary* fStatusAttributes;
|
||||
}
|
||||
|
||||
- (NSRect)imageRectForBounds:(NSRect)bounds;
|
||||
|
||||
|
|
|
@ -22,11 +22,13 @@
|
|||
|
||||
@interface FileNameCell ()
|
||||
|
||||
- (NSRect)rectForTitleWithString:(NSAttributedString*)string inBounds:(NSRect)bounds;
|
||||
- (NSRect)rectForStatusWithString:(NSAttributedString*)string withTitleRect:(NSRect)titleRect inBounds:(NSRect)bounds;
|
||||
|
||||
@property(nonatomic, readonly) NSAttributedString* attributedTitle;
|
||||
@property(nonatomic, readonly) NSAttributedString* attributedStatus;
|
||||
@property(nonatomic, readonly) NSMutableDictionary* fTitleAttributes;
|
||||
@property(nonatomic, readonly) NSMutableDictionary* fStatusAttributes;
|
||||
|
||||
- (NSRect)rectForTitleWithString:(NSAttributedString*)string inBounds:(NSRect)bounds;
|
||||
- (NSRect)rectForStatusWithString:(NSAttributedString*)string withTitleRect:(NSRect)titleRect inBounds:(NSRect)bounds;
|
||||
|
||||
@end
|
||||
|
||||
|
@ -39,13 +41,13 @@
|
|||
NSMutableParagraphStyle* paragraphStyle = [NSParagraphStyle.defaultParagraphStyle mutableCopy];
|
||||
paragraphStyle.lineBreakMode = NSLineBreakByTruncatingMiddle;
|
||||
|
||||
fTitleAttributes = [[NSMutableDictionary alloc]
|
||||
_fTitleAttributes = [[NSMutableDictionary alloc]
|
||||
initWithObjectsAndKeys:[NSFont messageFontOfSize:12.0], NSFontAttributeName, paragraphStyle, NSParagraphStyleAttributeName, nil];
|
||||
|
||||
NSMutableParagraphStyle* statusParagraphStyle = [NSParagraphStyle.defaultParagraphStyle mutableCopy];
|
||||
statusParagraphStyle.lineBreakMode = NSLineBreakByTruncatingTail;
|
||||
|
||||
fStatusAttributes = [[NSMutableDictionary alloc]
|
||||
_fStatusAttributes = [[NSMutableDictionary alloc]
|
||||
initWithObjectsAndKeys:[NSFont messageFontOfSize:9.0], NSFontAttributeName, statusParagraphStyle, NSParagraphStyleAttributeName, nil];
|
||||
}
|
||||
return self;
|
||||
|
@ -55,8 +57,8 @@
|
|||
{
|
||||
FileNameCell* copy = [super copyWithZone:zone];
|
||||
|
||||
copy->fTitleAttributes = fTitleAttributes;
|
||||
copy->fStatusAttributes = fStatusAttributes;
|
||||
copy->_fTitleAttributes = _fTitleAttributes;
|
||||
copy->_fStatusAttributes = _fStatusAttributes;
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
@ -103,8 +105,8 @@
|
|||
statusColor = NSColor.secondaryLabelColor;
|
||||
}
|
||||
|
||||
fTitleAttributes[NSForegroundColorAttributeName] = titleColor;
|
||||
fStatusAttributes[NSForegroundColorAttributeName] = statusColor;
|
||||
self.fTitleAttributes[NSForegroundColorAttributeName] = titleColor;
|
||||
self.fStatusAttributes[NSForegroundColorAttributeName] = statusColor;
|
||||
|
||||
//title
|
||||
NSAttributedString* titleString = self.attributedTitle;
|
||||
|
@ -137,11 +139,13 @@
|
|||
cellFrame.origin.x += PADDING_EXPANSION_FRAME;
|
||||
cellFrame.origin.y += PADDING_EXPANSION_FRAME;
|
||||
|
||||
fTitleAttributes[NSForegroundColorAttributeName] = NSColor.controlTextColor;
|
||||
self.fTitleAttributes[NSForegroundColorAttributeName] = NSColor.controlTextColor;
|
||||
NSAttributedString* titleString = self.attributedTitle;
|
||||
[titleString drawInRect:cellFrame];
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
- (NSRect)rectForTitleWithString:(NSAttributedString*)string inBounds:(NSRect)bounds
|
||||
{
|
||||
NSSize const titleSize = [string size];
|
||||
|
@ -190,7 +194,7 @@
|
|||
- (NSAttributedString*)attributedTitle
|
||||
{
|
||||
NSString* title = ((FileListNode*)self.objectValue).name;
|
||||
return [[NSAttributedString alloc] initWithString:title attributes:fTitleAttributes];
|
||||
return [[NSAttributedString alloc] initWithString:title attributes:self.fTitleAttributes];
|
||||
}
|
||||
|
||||
- (NSAttributedString*)attributedStatus
|
||||
|
@ -205,7 +209,7 @@
|
|||
percentString,
|
||||
[NSString stringForFileSize:node.size]];
|
||||
|
||||
return [[NSAttributedString alloc] initWithString:status attributes:fStatusAttributes];
|
||||
return [[NSAttributedString alloc] initWithString:status attributes:self.fStatusAttributes];
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -8,20 +8,10 @@
|
|||
@class FileOutlineView;
|
||||
|
||||
@interface FileOutlineController : NSObject
|
||||
{
|
||||
Torrent* fTorrent;
|
||||
NSMutableArray* fFileList;
|
||||
|
||||
IBOutlet FileOutlineView* fOutline;
|
||||
|
||||
NSString* fFilterText;
|
||||
}
|
||||
|
||||
@property(nonatomic, readonly) FileOutlineView* outlineView;
|
||||
|
||||
- (void)setTorrent:(Torrent*)torrent;
|
||||
|
||||
- (void)setFilterText:(NSString*)text;
|
||||
@property(nonatomic) Torrent* torrent;
|
||||
@property(nonatomic) NSString* filterText;
|
||||
|
||||
- (void)refresh;
|
||||
|
||||
|
|
|
@ -29,6 +29,10 @@ typedef NS_ENUM(unsigned int, filePriorityMenuTag) { //
|
|||
|
||||
@interface FileOutlineController ()
|
||||
|
||||
@property(nonatomic) NSMutableArray* fFileList;
|
||||
|
||||
@property(nonatomic) IBOutlet FileOutlineView* fOutline;
|
||||
|
||||
@property(nonatomic, readonly) NSMenu* menu;
|
||||
|
||||
- (NSUInteger)findFileNode:(FileListNode*)node
|
||||
|
@ -43,35 +47,35 @@ typedef NS_ENUM(unsigned int, filePriorityMenuTag) { //
|
|||
|
||||
- (void)awakeFromNib
|
||||
{
|
||||
fFileList = [[NSMutableArray alloc] init];
|
||||
self.fFileList = [[NSMutableArray alloc] init];
|
||||
|
||||
fOutline.doubleAction = @selector(revealFile:);
|
||||
fOutline.target = self;
|
||||
self.fOutline.doubleAction = @selector(revealFile:);
|
||||
self.fOutline.target = self;
|
||||
|
||||
//set table header tool tips
|
||||
[fOutline tableColumnWithIdentifier:@"Check"].headerToolTip = NSLocalizedString(@"Download", "file table -> header tool tip");
|
||||
[fOutline tableColumnWithIdentifier:@"Priority"].headerToolTip = NSLocalizedString(@"Priority", "file table -> header tool tip");
|
||||
[self.fOutline tableColumnWithIdentifier:@"Check"].headerToolTip = NSLocalizedString(@"Download", "file table -> header tool tip");
|
||||
[self.fOutline tableColumnWithIdentifier:@"Priority"].headerToolTip = NSLocalizedString(@"Priority", "file table -> header tool tip");
|
||||
|
||||
fOutline.menu = self.menu;
|
||||
self.fOutline.menu = self.menu;
|
||||
|
||||
[self setTorrent:nil];
|
||||
self.torrent = nil;
|
||||
}
|
||||
|
||||
- (FileOutlineView*)outlineView
|
||||
{
|
||||
return fOutline;
|
||||
return _fOutline;
|
||||
}
|
||||
|
||||
- (void)setTorrent:(Torrent*)torrent
|
||||
{
|
||||
fTorrent = torrent;
|
||||
_torrent = torrent;
|
||||
|
||||
[fFileList setArray:fTorrent.fileList];
|
||||
[self.fFileList setArray:_torrent.fileList];
|
||||
|
||||
fFilterText = nil;
|
||||
self.filterText = nil;
|
||||
|
||||
[fOutline reloadData];
|
||||
[fOutline deselectAll:nil]; //do this after reloading the data #4575
|
||||
[self.fOutline reloadData];
|
||||
[self.fOutline deselectAll:nil]; //do this after reloading the data #4575
|
||||
}
|
||||
|
||||
- (void)setFilterText:(NSString*)text
|
||||
|
@ -83,12 +87,12 @@ typedef NS_ENUM(unsigned int, filePriorityMenuTag) { //
|
|||
components = nil;
|
||||
}
|
||||
|
||||
if ((!text && !fFilterText) || (text && fFilterText && [text isEqualToString:fFilterText]))
|
||||
if ((!text && !_filterText) || (text && _filterText && [text isEqualToString:_filterText]))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
[fOutline beginUpdates];
|
||||
[self.fOutline beginUpdates];
|
||||
|
||||
NSUInteger currentIndex = 0, totalCount = 0;
|
||||
NSMutableArray* itemsToAdd = [NSMutableArray array];
|
||||
|
@ -96,7 +100,7 @@ typedef NS_ENUM(unsigned int, filePriorityMenuTag) { //
|
|||
|
||||
NSMutableDictionary* removedIndexesForParents = nil; //ugly, but we can't modify the actual file nodes
|
||||
|
||||
NSArray* tempList = !text ? fTorrent.fileList : fTorrent.flatFileList;
|
||||
NSArray* tempList = !text ? self.torrent.fileList : self.torrent.flatFileList;
|
||||
for (FileListNode* item in tempList)
|
||||
{
|
||||
__block BOOL filter = NO;
|
||||
|
@ -115,8 +119,8 @@ typedef NS_ENUM(unsigned int, filePriorityMenuTag) { //
|
|||
{
|
||||
FileListNode* parent = nil;
|
||||
NSUInteger previousIndex = !item.isFolder ?
|
||||
[self findFileNode:item inList:fFileList
|
||||
atIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(currentIndex, fFileList.count - currentIndex)]
|
||||
[self findFileNode:item inList:self.fFileList
|
||||
atIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(currentIndex, self.fFileList.count - currentIndex)]
|
||||
currentParent:nil
|
||||
finalParent:&parent] :
|
||||
NSNotFound;
|
||||
|
@ -133,7 +137,7 @@ typedef NS_ENUM(unsigned int, filePriorityMenuTag) { //
|
|||
{
|
||||
if (previousIndex != currentIndex)
|
||||
{
|
||||
[fFileList moveObjectAtIndex:previousIndex toIndex:currentIndex];
|
||||
[self.fFileList moveObjectAtIndex:previousIndex toIndex:currentIndex];
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -142,7 +146,7 @@ typedef NS_ENUM(unsigned int, filePriorityMenuTag) { //
|
|||
}
|
||||
else
|
||||
{
|
||||
[fFileList insertObject:item atIndex:currentIndex];
|
||||
[self.fFileList insertObject:item atIndex:currentIndex];
|
||||
|
||||
//figure out the index within the semi-edited table - UGLY
|
||||
if (!removedIndexesForParents)
|
||||
|
@ -165,7 +169,7 @@ typedef NS_ENUM(unsigned int, filePriorityMenuTag) { //
|
|||
|
||||
if (move)
|
||||
{
|
||||
[fOutline moveItemAtIndex:previousIndex inParent:parent toIndex:currentIndex inParent:nil];
|
||||
[self.fOutline moveItemAtIndex:previousIndex inParent:parent toIndex:currentIndex inParent:nil];
|
||||
}
|
||||
|
||||
++currentIndex;
|
||||
|
@ -176,26 +180,26 @@ typedef NS_ENUM(unsigned int, filePriorityMenuTag) { //
|
|||
}
|
||||
|
||||
//remove trailing items - those are the unused
|
||||
if (currentIndex < fFileList.count)
|
||||
if (currentIndex < self.fFileList.count)
|
||||
{
|
||||
NSRange const removeRange = NSMakeRange(currentIndex, fFileList.count - currentIndex);
|
||||
[fFileList removeObjectsInRange:removeRange];
|
||||
[fOutline removeItemsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:removeRange] inParent:nil
|
||||
NSRange const removeRange = NSMakeRange(currentIndex, self.fFileList.count - currentIndex);
|
||||
[self.fFileList removeObjectsInRange:removeRange];
|
||||
[self.fOutline removeItemsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:removeRange] inParent:nil
|
||||
withAnimation:NSTableViewAnimationSlideDown];
|
||||
}
|
||||
|
||||
//add new items
|
||||
[fFileList insertObjects:itemsToAdd atIndexes:itemsToAddIndexes];
|
||||
[fOutline insertItemsAtIndexes:itemsToAddIndexes inParent:nil withAnimation:NSTableViewAnimationSlideUp];
|
||||
[self.fFileList insertObjects:itemsToAdd atIndexes:itemsToAddIndexes];
|
||||
[self.fOutline insertItemsAtIndexes:itemsToAddIndexes inParent:nil withAnimation:NSTableViewAnimationSlideUp];
|
||||
|
||||
[fOutline endUpdates];
|
||||
[self.fOutline endUpdates];
|
||||
|
||||
fFilterText = text;
|
||||
_filterText = text;
|
||||
}
|
||||
|
||||
- (void)refresh
|
||||
{
|
||||
fOutline.needsDisplay = YES;
|
||||
self.fOutline.needsDisplay = YES;
|
||||
}
|
||||
|
||||
- (void)outlineViewSelectionDidChange:(NSNotification*)notification
|
||||
|
@ -210,7 +214,7 @@ typedef NS_ENUM(unsigned int, filePriorityMenuTag) { //
|
|||
{
|
||||
if (!item)
|
||||
{
|
||||
return fFileList ? fFileList.count : 0;
|
||||
return self.fFileList ? self.fFileList.count : 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -226,14 +230,14 @@ typedef NS_ENUM(unsigned int, filePriorityMenuTag) { //
|
|||
|
||||
- (id)outlineView:(NSOutlineView*)outlineView child:(NSInteger)index ofItem:(id)item
|
||||
{
|
||||
return (item ? ((FileListNode*)item).children : fFileList)[index];
|
||||
return (item ? ((FileListNode*)item).children : self.fFileList)[index];
|
||||
}
|
||||
|
||||
- (id)outlineView:(NSOutlineView*)outlineView objectValueForTableColumn:(NSTableColumn*)tableColumn byItem:(id)item
|
||||
{
|
||||
if ([tableColumn.identifier isEqualToString:@"Check"])
|
||||
{
|
||||
return @([fTorrent checkForFiles:((FileListNode*)item).indexes]);
|
||||
return @([self.torrent checkForFiles:((FileListNode*)item).indexes]);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -249,14 +253,14 @@ typedef NS_ENUM(unsigned int, filePriorityMenuTag) { //
|
|||
NSString* identifier = tableColumn.identifier;
|
||||
if ([identifier isEqualToString:@"Check"])
|
||||
{
|
||||
[cell setEnabled:[fTorrent canChangeDownloadCheckForFiles:((FileListNode*)item).indexes]];
|
||||
[cell setEnabled:[self.torrent canChangeDownloadCheckForFiles:((FileListNode*)item).indexes]];
|
||||
}
|
||||
else if ([identifier isEqualToString:@"Priority"])
|
||||
{
|
||||
[cell setRepresentedObject:item];
|
||||
|
||||
NSInteger hoveredRow = fOutline.hoveredRow;
|
||||
[(FilePriorityCell*)cell setHovered:hoveredRow != -1 && hoveredRow == [fOutline rowForItem:item]];
|
||||
NSInteger hoveredRow = self.fOutline.hoveredRow;
|
||||
((FilePriorityCell*)cell).hovered = hoveredRow != -1 && hoveredRow == [self.fOutline rowForItem:item];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -271,17 +275,17 @@ typedef NS_ENUM(unsigned int, filePriorityMenuTag) { //
|
|||
NSIndexSet* indexSet;
|
||||
if (NSEvent.modifierFlags & NSEventModifierFlagOption)
|
||||
{
|
||||
indexSet = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, fTorrent.fileCount)];
|
||||
indexSet = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, self.torrent.fileCount)];
|
||||
}
|
||||
else
|
||||
{
|
||||
indexSet = ((FileListNode*)item).indexes;
|
||||
}
|
||||
|
||||
[fTorrent setFileCheckState:[object intValue] != NSControlStateValueOff ? NSControlStateValueOn
|
||||
[self.torrent setFileCheckState:[object intValue] != NSControlStateValueOff ? NSControlStateValueOn
|
||||
: NSControlStateValueOff
|
||||
forIndexes:indexSet];
|
||||
fOutline.needsDisplay = YES;
|
||||
self.fOutline.needsDisplay = YES;
|
||||
|
||||
[NSNotificationCenter.defaultCenter postNotificationName:@"UpdateUI" object:nil];
|
||||
}
|
||||
|
@ -302,7 +306,7 @@ typedef NS_ENUM(unsigned int, filePriorityMenuTag) { //
|
|||
NSString* ident = tableColumn.identifier;
|
||||
if ([ident isEqualToString:@"Name"])
|
||||
{
|
||||
NSString* path = [fTorrent fileLocation:item];
|
||||
NSString* path = [self.torrent fileLocation:item];
|
||||
if (!path)
|
||||
{
|
||||
FileListNode* node = (FileListNode*)item;
|
||||
|
@ -324,7 +328,7 @@ typedef NS_ENUM(unsigned int, filePriorityMenuTag) { //
|
|||
}
|
||||
else if ([ident isEqualToString:@"Priority"])
|
||||
{
|
||||
NSSet* priorities = [fTorrent filePrioritiesForIndexes:((FileListNode*)item).indexes];
|
||||
NSSet* priorities = [self.torrent filePrioritiesForIndexes:((FileListNode*)item).indexes];
|
||||
switch (priorities.count)
|
||||
{
|
||||
case 0:
|
||||
|
@ -364,49 +368,49 @@ typedef NS_ENUM(unsigned int, filePriorityMenuTag) { //
|
|||
{
|
||||
NSInteger state = [sender tag] == FILE_UNCHECK_TAG ? NSControlStateValueOff : NSControlStateValueOn;
|
||||
|
||||
NSIndexSet* indexSet = fOutline.selectedRowIndexes;
|
||||
NSIndexSet* indexSet = self.fOutline.selectedRowIndexes;
|
||||
NSMutableIndexSet* itemIndexes = [NSMutableIndexSet indexSet];
|
||||
for (NSInteger i = indexSet.firstIndex; i != NSNotFound; i = [indexSet indexGreaterThanIndex:i])
|
||||
{
|
||||
FileListNode* item = [fOutline itemAtRow:i];
|
||||
FileListNode* item = [self.fOutline itemAtRow:i];
|
||||
[itemIndexes addIndexes:item.indexes];
|
||||
}
|
||||
|
||||
[fTorrent setFileCheckState:state forIndexes:itemIndexes];
|
||||
fOutline.needsDisplay = YES;
|
||||
[self.torrent setFileCheckState:state forIndexes:itemIndexes];
|
||||
self.fOutline.needsDisplay = YES;
|
||||
}
|
||||
|
||||
- (void)setOnlySelectedCheck:(id)sender
|
||||
{
|
||||
NSIndexSet* indexSet = fOutline.selectedRowIndexes;
|
||||
NSIndexSet* indexSet = self.fOutline.selectedRowIndexes;
|
||||
NSMutableIndexSet* itemIndexes = [NSMutableIndexSet indexSet];
|
||||
for (NSInteger i = indexSet.firstIndex; i != NSNotFound; i = [indexSet indexGreaterThanIndex:i])
|
||||
{
|
||||
FileListNode* item = [fOutline itemAtRow:i];
|
||||
FileListNode* item = [self.fOutline itemAtRow:i];
|
||||
[itemIndexes addIndexes:item.indexes];
|
||||
}
|
||||
|
||||
[fTorrent setFileCheckState:NSControlStateValueOn forIndexes:itemIndexes];
|
||||
[self.torrent setFileCheckState:NSControlStateValueOn forIndexes:itemIndexes];
|
||||
|
||||
NSMutableIndexSet* remainingItemIndexes = [NSMutableIndexSet indexSetWithIndexesInRange:NSMakeRange(0, fTorrent.fileCount)];
|
||||
NSMutableIndexSet* remainingItemIndexes = [NSMutableIndexSet indexSetWithIndexesInRange:NSMakeRange(0, self.torrent.fileCount)];
|
||||
[remainingItemIndexes removeIndexes:itemIndexes];
|
||||
[fTorrent setFileCheckState:NSControlStateValueOff forIndexes:remainingItemIndexes];
|
||||
[self.torrent setFileCheckState:NSControlStateValueOff forIndexes:remainingItemIndexes];
|
||||
|
||||
fOutline.needsDisplay = YES;
|
||||
self.fOutline.needsDisplay = YES;
|
||||
}
|
||||
|
||||
- (void)checkAll
|
||||
{
|
||||
NSIndexSet* indexSet = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, fTorrent.fileCount)];
|
||||
[fTorrent setFileCheckState:NSControlStateValueOn forIndexes:indexSet];
|
||||
fOutline.needsDisplay = YES;
|
||||
NSIndexSet* indexSet = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, self.torrent.fileCount)];
|
||||
[self.torrent setFileCheckState:NSControlStateValueOn forIndexes:indexSet];
|
||||
self.fOutline.needsDisplay = YES;
|
||||
}
|
||||
|
||||
- (void)uncheckAll
|
||||
{
|
||||
NSIndexSet* indexSet = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, fTorrent.fileCount)];
|
||||
[fTorrent setFileCheckState:NSControlStateValueOff forIndexes:indexSet];
|
||||
fOutline.needsDisplay = YES;
|
||||
NSIndexSet* indexSet = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, self.torrent.fileCount)];
|
||||
[self.torrent setFileCheckState:NSControlStateValueOff forIndexes:indexSet];
|
||||
self.fOutline.needsDisplay = YES;
|
||||
}
|
||||
|
||||
- (void)setPriority:(id)sender
|
||||
|
@ -424,25 +428,25 @@ typedef NS_ENUM(unsigned int, filePriorityMenuTag) { //
|
|||
priority = TR_PRI_LOW;
|
||||
}
|
||||
|
||||
NSIndexSet* indexSet = fOutline.selectedRowIndexes;
|
||||
NSIndexSet* indexSet = self.fOutline.selectedRowIndexes;
|
||||
NSMutableIndexSet* itemIndexes = [NSMutableIndexSet indexSet];
|
||||
for (NSInteger i = indexSet.firstIndex; i != NSNotFound; i = [indexSet indexGreaterThanIndex:i])
|
||||
{
|
||||
FileListNode* item = [fOutline itemAtRow:i];
|
||||
FileListNode* item = [self.fOutline itemAtRow:i];
|
||||
[itemIndexes addIndexes:item.indexes];
|
||||
}
|
||||
|
||||
[fTorrent setFilePriority:priority forIndexes:itemIndexes];
|
||||
fOutline.needsDisplay = YES;
|
||||
[self.torrent setFilePriority:priority forIndexes:itemIndexes];
|
||||
self.fOutline.needsDisplay = YES;
|
||||
}
|
||||
|
||||
- (void)revealFile:(id)sender
|
||||
{
|
||||
NSIndexSet* indexes = fOutline.selectedRowIndexes;
|
||||
NSIndexSet* indexes = self.fOutline.selectedRowIndexes;
|
||||
NSMutableArray* paths = [NSMutableArray arrayWithCapacity:indexes.count];
|
||||
for (NSUInteger i = indexes.firstIndex; i != NSNotFound; i = [indexes indexGreaterThanIndex:i])
|
||||
{
|
||||
NSString* path = [fTorrent fileLocation:[fOutline itemAtRow:i]];
|
||||
NSString* path = [self.torrent fileLocation:[self.fOutline itemAtRow:i]];
|
||||
if (path)
|
||||
{
|
||||
[paths addObject:[NSURL fileURLWithPath:path]];
|
||||
|
@ -457,14 +461,14 @@ typedef NS_ENUM(unsigned int, filePriorityMenuTag) { //
|
|||
|
||||
- (void)renameSelected:(id)sender
|
||||
{
|
||||
NSIndexSet* indexes = fOutline.selectedRowIndexes;
|
||||
NSIndexSet* indexes = self.fOutline.selectedRowIndexes;
|
||||
NSAssert(indexes.count == 1, @"1 file needs to be selected to rename, but %ld are selected", indexes.count);
|
||||
|
||||
FileListNode* node = [fOutline itemAtRow:indexes.firstIndex];
|
||||
FileListNode* node = [self.fOutline itemAtRow:indexes.firstIndex];
|
||||
Torrent* torrent = node.torrent;
|
||||
if (!torrent.folder)
|
||||
{
|
||||
[FileRenameSheetController presentSheetForTorrent:torrent modalForWindow:fOutline.window completionHandler:^(BOOL didRename) {
|
||||
[FileRenameSheetController presentSheetForTorrent:torrent modalForWindow:self.fOutline.window completionHandler:^(BOOL didRename) {
|
||||
if (didRename)
|
||||
{
|
||||
[NSNotificationCenter.defaultCenter postNotificationName:@"UpdateQueue" object:self];
|
||||
|
@ -475,7 +479,7 @@ typedef NS_ENUM(unsigned int, filePriorityMenuTag) { //
|
|||
}
|
||||
else
|
||||
{
|
||||
[FileRenameSheetController presentSheetForFileListNode:node modalForWindow:fOutline.window completionHandler:^(BOOL didRename) {
|
||||
[FileRenameSheetController presentSheetForFileListNode:node modalForWindow:self.fOutline.window completionHandler:^(BOOL didRename) {
|
||||
#warning instead of calling reset inspector, just resort?
|
||||
if (didRename)
|
||||
[NSNotificationCenter.defaultCenter postNotificationName:@"ResetInspector" object:self
|
||||
|
@ -487,7 +491,7 @@ typedef NS_ENUM(unsigned int, filePriorityMenuTag) { //
|
|||
#warning make real view controller (Leopard-only) so that Command-R will work
|
||||
- (BOOL)validateMenuItem:(NSMenuItem*)menuItem
|
||||
{
|
||||
if (!fTorrent)
|
||||
if (!self.torrent)
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
@ -496,10 +500,10 @@ typedef NS_ENUM(unsigned int, filePriorityMenuTag) { //
|
|||
|
||||
if (action == @selector(revealFile:))
|
||||
{
|
||||
NSIndexSet* indexSet = fOutline.selectedRowIndexes;
|
||||
NSIndexSet* indexSet = self.fOutline.selectedRowIndexes;
|
||||
for (NSInteger i = indexSet.firstIndex; i != NSNotFound; i = [indexSet indexGreaterThanIndex:i])
|
||||
{
|
||||
if ([fTorrent fileLocation:[fOutline itemAtRow:i]] != nil)
|
||||
if ([self.torrent fileLocation:[self.fOutline itemAtRow:i]] != nil)
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
@ -509,51 +513,51 @@ typedef NS_ENUM(unsigned int, filePriorityMenuTag) { //
|
|||
|
||||
if (action == @selector(setCheck:))
|
||||
{
|
||||
if (fOutline.numberOfSelectedRows == 0)
|
||||
if (self.fOutline.numberOfSelectedRows == 0)
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
NSIndexSet* indexSet = fOutline.selectedRowIndexes;
|
||||
NSIndexSet* indexSet = self.fOutline.selectedRowIndexes;
|
||||
NSMutableIndexSet* itemIndexes = [NSMutableIndexSet indexSet];
|
||||
for (NSInteger i = indexSet.firstIndex; i != NSNotFound; i = [indexSet indexGreaterThanIndex:i])
|
||||
{
|
||||
FileListNode* node = [fOutline itemAtRow:i];
|
||||
FileListNode* node = [self.fOutline itemAtRow:i];
|
||||
[itemIndexes addIndexes:node.indexes];
|
||||
}
|
||||
|
||||
NSInteger state = (menuItem.tag == FILE_CHECK_TAG) ? NSControlStateValueOn : NSControlStateValueOff;
|
||||
return [fTorrent checkForFiles:itemIndexes] != state && [fTorrent canChangeDownloadCheckForFiles:itemIndexes];
|
||||
return [self.torrent checkForFiles:itemIndexes] != state && [self.torrent canChangeDownloadCheckForFiles:itemIndexes];
|
||||
}
|
||||
|
||||
if (action == @selector(setOnlySelectedCheck:))
|
||||
{
|
||||
if (fOutline.numberOfSelectedRows == 0)
|
||||
if (self.fOutline.numberOfSelectedRows == 0)
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
NSIndexSet* indexSet = fOutline.selectedRowIndexes;
|
||||
NSIndexSet* indexSet = self.fOutline.selectedRowIndexes;
|
||||
NSMutableIndexSet* itemIndexes = [NSMutableIndexSet indexSet];
|
||||
for (NSInteger i = indexSet.firstIndex; i != NSNotFound; i = [indexSet indexGreaterThanIndex:i])
|
||||
{
|
||||
FileListNode* node = [fOutline itemAtRow:i];
|
||||
FileListNode* node = [self.fOutline itemAtRow:i];
|
||||
[itemIndexes addIndexes:node.indexes];
|
||||
}
|
||||
|
||||
return [fTorrent canChangeDownloadCheckForFiles:itemIndexes];
|
||||
return [self.torrent canChangeDownloadCheckForFiles:itemIndexes];
|
||||
}
|
||||
|
||||
if (action == @selector(setPriority:))
|
||||
{
|
||||
if (fOutline.numberOfSelectedRows == 0)
|
||||
if (self.fOutline.numberOfSelectedRows == 0)
|
||||
{
|
||||
menuItem.state = NSControlStateValueOff;
|
||||
return NO;
|
||||
}
|
||||
|
||||
//determine which priorities are checked
|
||||
NSIndexSet* indexSet = fOutline.selectedRowIndexes;
|
||||
NSIndexSet* indexSet = self.fOutline.selectedRowIndexes;
|
||||
tr_priority_t priority;
|
||||
switch (menuItem.tag)
|
||||
{
|
||||
|
@ -571,15 +575,15 @@ typedef NS_ENUM(unsigned int, filePriorityMenuTag) { //
|
|||
BOOL current = NO, canChange = NO;
|
||||
for (NSInteger i = indexSet.firstIndex; i != NSNotFound; i = [indexSet indexGreaterThanIndex:i])
|
||||
{
|
||||
FileListNode* node = [fOutline itemAtRow:i];
|
||||
FileListNode* node = [self.fOutline itemAtRow:i];
|
||||
NSIndexSet* fileIndexSet = node.indexes;
|
||||
if (![fTorrent canChangeDownloadCheckForFiles:fileIndexSet])
|
||||
if (![self.torrent canChangeDownloadCheckForFiles:fileIndexSet])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
canChange = YES;
|
||||
if ([fTorrent hasFilePriority:priority forIndexes:fileIndexSet])
|
||||
if ([self.torrent hasFilePriority:priority forIndexes:fileIndexSet])
|
||||
{
|
||||
current = YES;
|
||||
break;
|
||||
|
@ -592,12 +596,14 @@ typedef NS_ENUM(unsigned int, filePriorityMenuTag) { //
|
|||
|
||||
if (action == @selector(renameSelected:))
|
||||
{
|
||||
return fOutline.numberOfSelectedRows == 1;
|
||||
return self.fOutline.numberOfSelectedRows == 1;
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
- (NSMenu*)menu
|
||||
{
|
||||
NSMenu* menu = [[NSMenu alloc] initWithTitle:@"File Outline Menu"];
|
||||
|
|
|
@ -4,15 +4,10 @@
|
|||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
@class Torrent;
|
||||
|
||||
@interface FileOutlineView : NSOutlineView
|
||||
{
|
||||
NSInteger fMouseRow;
|
||||
}
|
||||
|
||||
- (NSRect)iconRectForRow:(int)row;
|
||||
|
||||
@property(nonatomic, readonly) NSInteger hoveredRow;
|
||||
|
||||
- (NSRect)iconRectForRow:(int)row;
|
||||
|
||||
@end
|
||||
|
|
|
@ -9,6 +9,12 @@
|
|||
#import "FilePriorityCell.h"
|
||||
#import "Torrent.h"
|
||||
|
||||
@interface FileOutlineView ()
|
||||
|
||||
@property(nonatomic) NSInteger hoveredRow;
|
||||
|
||||
@end
|
||||
|
||||
@implementation FileOutlineView
|
||||
|
||||
- (void)awakeFromNib
|
||||
|
@ -22,7 +28,7 @@
|
|||
self.autoresizesOutlineColumn = NO;
|
||||
self.indentationPerLevel = 14.0;
|
||||
|
||||
fMouseRow = -1;
|
||||
self.hoveredRow = -1;
|
||||
}
|
||||
|
||||
- (void)mouseDown:(NSEvent*)event
|
||||
|
@ -89,18 +95,13 @@
|
|||
}
|
||||
}
|
||||
|
||||
- (NSInteger)hoveredRow
|
||||
{
|
||||
return fMouseRow;
|
||||
}
|
||||
|
||||
- (void)mouseEntered:(NSEvent*)event
|
||||
{
|
||||
NSNumber* row;
|
||||
if ((row = ((NSDictionary*)event.userData)[@"Row"]))
|
||||
{
|
||||
fMouseRow = row.intValue;
|
||||
[self setNeedsDisplayInRect:[self frameOfCellAtColumn:[self columnWithIdentifier:@"Priority"] row:fMouseRow]];
|
||||
self.hoveredRow = row.intValue;
|
||||
[self setNeedsDisplayInRect:[self frameOfCellAtColumn:[self columnWithIdentifier:@"Priority"] row:self.hoveredRow]];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -110,7 +111,7 @@
|
|||
if ((row = ((NSDictionary*)event.userData)[@"Row"]))
|
||||
{
|
||||
[self setNeedsDisplayInRect:[self frameOfCellAtColumn:[self columnWithIdentifier:@"Priority"] row:row.intValue]];
|
||||
fMouseRow = -1;
|
||||
self.hoveredRow = -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,18 +4,13 @@
|
|||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
#import "FileOutlineView.h"
|
||||
|
||||
@interface FilePriorityCell : NSSegmentedCell
|
||||
{
|
||||
BOOL fHoverRow;
|
||||
}
|
||||
|
||||
@property(nonatomic) BOOL hovered;
|
||||
|
||||
- (void)addTrackingAreasForView:(NSView*)controlView
|
||||
inRect:(NSRect)cellFrame
|
||||
withUserInfo:(NSDictionary*)userInfo
|
||||
mouseLocation:(NSPoint)mouseLocation;
|
||||
|
||||
- (void)setHovered:(BOOL)hovered;
|
||||
|
||||
@end
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
[self setImage:[NSImage imageNamed:@"PriorityControlNormal"] forSegment:1];
|
||||
[self setImage:[NSImage imageNamed:@"PriorityControlHigh"] forSegment:2];
|
||||
|
||||
fHoverRow = NO;
|
||||
_hovered = NO;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
@ -86,11 +86,6 @@
|
|||
[controlView addTrackingArea:area];
|
||||
}
|
||||
|
||||
- (void)setHovered:(BOOL)hovered
|
||||
{
|
||||
fHoverRow = hovered;
|
||||
}
|
||||
|
||||
- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView*)controlView
|
||||
{
|
||||
FileListNode* node = self.representedObject;
|
||||
|
@ -98,7 +93,7 @@
|
|||
NSSet* priorities = [torrent filePrioritiesForIndexes:node.indexes];
|
||||
|
||||
NSUInteger const count = priorities.count;
|
||||
if (fHoverRow && count > 0)
|
||||
if (self.hovered && count > 0)
|
||||
{
|
||||
[super setSelected:[priorities containsObject:@(TR_PRI_LOW)] forSegment:0];
|
||||
[super setSelected:[priorities containsObject:@(TR_PRI_NORMAL)] forSegment:1];
|
||||
|
|
|
@ -17,11 +17,6 @@
|
|||
modalForWindow:(NSWindow*)window
|
||||
completionHandler:(void (^)(BOOL didRename))completionHandler;
|
||||
|
||||
@property(weak) IBOutlet NSTextField* labelField;
|
||||
@property(weak) IBOutlet NSTextField* inputField;
|
||||
@property(weak) IBOutlet NSButton* renameButton;
|
||||
@property(weak) IBOutlet NSButton* cancelButton;
|
||||
|
||||
- (IBAction)rename:(id)sender;
|
||||
- (IBAction)cancelRename:(id)sender;
|
||||
|
||||
|
|
|
@ -11,6 +11,11 @@ typedef void (^CompletionBlock)(BOOL);
|
|||
|
||||
@interface FileRenameSheetController ()
|
||||
|
||||
@property(nonatomic, weak) IBOutlet NSTextField* labelField;
|
||||
@property(nonatomic, weak) IBOutlet NSTextField* inputField;
|
||||
@property(nonatomic, weak) IBOutlet NSButton* renameButton;
|
||||
@property(nonatomic, weak) IBOutlet NSButton* cancelButton;
|
||||
|
||||
@property(nonatomic) Torrent* torrent;
|
||||
@property(nonatomic) FileListNode* node;
|
||||
@property(nonatomic, copy) CompletionBlock completionHandler;
|
||||
|
|
|
@ -4,8 +4,6 @@
|
|||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
@class FilterButton;
|
||||
|
||||
#define FILTER_NONE @"None"
|
||||
#define FILTER_ACTIVE @"Active"
|
||||
#define FILTER_DOWNLOAD @"Download"
|
||||
|
@ -18,17 +16,8 @@
|
|||
#define GROUP_FILTER_ALL_TAG -2
|
||||
|
||||
@interface FilterBarController : NSViewController
|
||||
{
|
||||
IBOutlet FilterButton* fNoFilterButton;
|
||||
IBOutlet FilterButton* fActiveFilterButton;
|
||||
IBOutlet FilterButton* fDownloadFilterButton;
|
||||
IBOutlet FilterButton* fSeedFilterButton;
|
||||
IBOutlet FilterButton* fPauseFilterButton;
|
||||
|
||||
IBOutlet NSSearchField* fSearchField;
|
||||
|
||||
IBOutlet NSPopUpButton* fGroupsButton;
|
||||
}
|
||||
@property(nonatomic, readonly) NSArray* searchStrings;
|
||||
|
||||
- (instancetype)init;
|
||||
|
||||
|
@ -38,8 +27,6 @@
|
|||
- (void)setSearchType:(id)sender;
|
||||
- (void)setGroupFilter:(id)sender;
|
||||
- (void)reset:(BOOL)updateUI;
|
||||
|
||||
@property(nonatomic, readonly) NSArray* searchStrings;
|
||||
- (void)focusSearchField;
|
||||
|
||||
- (void)setCountAll:(NSUInteger)all
|
||||
|
|
|
@ -15,6 +15,16 @@
|
|||
|
||||
@interface FilterBarController ()
|
||||
|
||||
@property(nonatomic) IBOutlet FilterButton* fNoFilterButton;
|
||||
@property(nonatomic) IBOutlet FilterButton* fActiveFilterButton;
|
||||
@property(nonatomic) IBOutlet FilterButton* fDownloadFilterButton;
|
||||
@property(nonatomic) IBOutlet FilterButton* fSeedFilterButton;
|
||||
@property(nonatomic) IBOutlet FilterButton* fPauseFilterButton;
|
||||
|
||||
@property(nonatomic) IBOutlet NSSearchField* fSearchField;
|
||||
|
||||
@property(nonatomic) IBOutlet NSPopUpButton* fGroupsButton;
|
||||
|
||||
- (void)resizeBar;
|
||||
- (void)updateGroupsButton;
|
||||
- (void)updateGroups:(NSNotification*)notification;
|
||||
|
@ -31,22 +41,22 @@
|
|||
- (void)awakeFromNib
|
||||
{
|
||||
//localizations
|
||||
fNoFilterButton.title = NSLocalizedString(@"All", "Filter Bar -> filter button");
|
||||
fActiveFilterButton.title = NSLocalizedString(@"Active", "Filter Bar -> filter button");
|
||||
fDownloadFilterButton.title = NSLocalizedString(@"Downloading", "Filter Bar -> filter button");
|
||||
fSeedFilterButton.title = NSLocalizedString(@"Seeding", "Filter Bar -> filter button");
|
||||
fPauseFilterButton.title = NSLocalizedString(@"Paused", "Filter Bar -> filter button");
|
||||
self.fNoFilterButton.title = NSLocalizedString(@"All", "Filter Bar -> filter button");
|
||||
self.fActiveFilterButton.title = NSLocalizedString(@"Active", "Filter Bar -> filter button");
|
||||
self.fDownloadFilterButton.title = NSLocalizedString(@"Downloading", "Filter Bar -> filter button");
|
||||
self.fSeedFilterButton.title = NSLocalizedString(@"Seeding", "Filter Bar -> filter button");
|
||||
self.fPauseFilterButton.title = NSLocalizedString(@"Paused", "Filter Bar -> filter button");
|
||||
|
||||
fNoFilterButton.cell.backgroundStyle = NSBackgroundStyleRaised;
|
||||
fActiveFilterButton.cell.backgroundStyle = NSBackgroundStyleRaised;
|
||||
fDownloadFilterButton.cell.backgroundStyle = NSBackgroundStyleRaised;
|
||||
fSeedFilterButton.cell.backgroundStyle = NSBackgroundStyleRaised;
|
||||
fPauseFilterButton.cell.backgroundStyle = NSBackgroundStyleRaised;
|
||||
self.fNoFilterButton.cell.backgroundStyle = NSBackgroundStyleRaised;
|
||||
self.fActiveFilterButton.cell.backgroundStyle = NSBackgroundStyleRaised;
|
||||
self.fDownloadFilterButton.cell.backgroundStyle = NSBackgroundStyleRaised;
|
||||
self.fSeedFilterButton.cell.backgroundStyle = NSBackgroundStyleRaised;
|
||||
self.fPauseFilterButton.cell.backgroundStyle = NSBackgroundStyleRaised;
|
||||
|
||||
[fSearchField.searchMenuTemplate itemWithTag:FILTER_TYPE_TAG_NAME].title = NSLocalizedString(@"Name", "Filter Bar -> filter menu");
|
||||
[fSearchField.searchMenuTemplate itemWithTag:FILTER_TYPE_TAG_TRACKER].title = NSLocalizedString(@"Tracker", "Filter Bar -> filter menu");
|
||||
[self.fSearchField.searchMenuTemplate itemWithTag:FILTER_TYPE_TAG_NAME].title = NSLocalizedString(@"Name", "Filter Bar -> filter menu");
|
||||
[self.fSearchField.searchMenuTemplate itemWithTag:FILTER_TYPE_TAG_TRACKER].title = NSLocalizedString(@"Tracker", "Filter Bar -> filter menu");
|
||||
|
||||
[fGroupsButton.menu itemWithTag:GROUP_FILTER_ALL_TAG].title = NSLocalizedString(@"All Groups", "Filter Bar -> group filter menu");
|
||||
[self.fGroupsButton.menu itemWithTag:GROUP_FILTER_ALL_TAG].title = NSLocalizedString(@"All Groups", "Filter Bar -> group filter menu");
|
||||
|
||||
[self resizeBar];
|
||||
|
||||
|
@ -56,19 +66,19 @@
|
|||
NSButton* currentFilterButton;
|
||||
if ([filterType isEqualToString:FILTER_ACTIVE])
|
||||
{
|
||||
currentFilterButton = fActiveFilterButton;
|
||||
currentFilterButton = self.fActiveFilterButton;
|
||||
}
|
||||
else if ([filterType isEqualToString:FILTER_PAUSE])
|
||||
{
|
||||
currentFilterButton = fPauseFilterButton;
|
||||
currentFilterButton = self.fPauseFilterButton;
|
||||
}
|
||||
else if ([filterType isEqualToString:FILTER_SEED])
|
||||
{
|
||||
currentFilterButton = fSeedFilterButton;
|
||||
currentFilterButton = self.fSeedFilterButton;
|
||||
}
|
||||
else if ([filterType isEqualToString:FILTER_DOWNLOAD])
|
||||
{
|
||||
currentFilterButton = fDownloadFilterButton;
|
||||
currentFilterButton = self.fDownloadFilterButton;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -77,14 +87,14 @@
|
|||
{
|
||||
[NSUserDefaults.standardUserDefaults setObject:FILTER_NONE forKey:@"Filter"];
|
||||
}
|
||||
currentFilterButton = fNoFilterButton;
|
||||
currentFilterButton = self.fNoFilterButton;
|
||||
}
|
||||
currentFilterButton.state = NSControlStateValueOn;
|
||||
|
||||
//set filter search type
|
||||
NSString* filterSearchType = [NSUserDefaults.standardUserDefaults stringForKey:@"FilterSearchType"];
|
||||
|
||||
NSMenu* filterSearchMenu = fSearchField.searchMenuTemplate;
|
||||
NSMenu* filterSearchMenu = self.fSearchField.searchMenuTemplate;
|
||||
NSString* filterSearchTypeTitle;
|
||||
if ([filterSearchType isEqualToString:FILTER_TYPE_TRACKER])
|
||||
{
|
||||
|
@ -99,12 +109,12 @@
|
|||
}
|
||||
filterSearchTypeTitle = [filterSearchMenu itemWithTag:FILTER_TYPE_TAG_NAME].title;
|
||||
}
|
||||
fSearchField.placeholderString = filterSearchTypeTitle;
|
||||
self.fSearchField.placeholderString = filterSearchTypeTitle;
|
||||
|
||||
NSString* searchString;
|
||||
if ((searchString = [NSUserDefaults.standardUserDefaults stringForKey:@"FilterSearchString"]))
|
||||
{
|
||||
fSearchField.stringValue = searchString;
|
||||
self.fSearchField.stringValue = searchString;
|
||||
}
|
||||
|
||||
[self updateGroupsButton];
|
||||
|
@ -128,23 +138,23 @@
|
|||
NSButton* prevFilterButton;
|
||||
if ([oldFilterType isEqualToString:FILTER_PAUSE])
|
||||
{
|
||||
prevFilterButton = fPauseFilterButton;
|
||||
prevFilterButton = self.fPauseFilterButton;
|
||||
}
|
||||
else if ([oldFilterType isEqualToString:FILTER_ACTIVE])
|
||||
{
|
||||
prevFilterButton = fActiveFilterButton;
|
||||
prevFilterButton = self.fActiveFilterButton;
|
||||
}
|
||||
else if ([oldFilterType isEqualToString:FILTER_SEED])
|
||||
{
|
||||
prevFilterButton = fSeedFilterButton;
|
||||
prevFilterButton = self.fSeedFilterButton;
|
||||
}
|
||||
else if ([oldFilterType isEqualToString:FILTER_DOWNLOAD])
|
||||
{
|
||||
prevFilterButton = fDownloadFilterButton;
|
||||
prevFilterButton = self.fDownloadFilterButton;
|
||||
}
|
||||
else
|
||||
{
|
||||
prevFilterButton = fNoFilterButton;
|
||||
prevFilterButton = self.fNoFilterButton;
|
||||
}
|
||||
|
||||
if (sender != prevFilterButton)
|
||||
|
@ -153,19 +163,19 @@
|
|||
[sender setState:NSControlStateValueOn];
|
||||
|
||||
NSString* filterType;
|
||||
if (sender == fActiveFilterButton)
|
||||
if (sender == self.fActiveFilterButton)
|
||||
{
|
||||
filterType = FILTER_ACTIVE;
|
||||
}
|
||||
else if (sender == fDownloadFilterButton)
|
||||
else if (sender == self.fDownloadFilterButton)
|
||||
{
|
||||
filterType = FILTER_DOWNLOAD;
|
||||
}
|
||||
else if (sender == fPauseFilterButton)
|
||||
else if (sender == self.fPauseFilterButton)
|
||||
{
|
||||
filterType = FILTER_PAUSE;
|
||||
}
|
||||
else if (sender == fSeedFilterButton)
|
||||
else if (sender == self.fSeedFilterButton)
|
||||
{
|
||||
filterType = FILTER_SEED;
|
||||
}
|
||||
|
@ -191,27 +201,27 @@
|
|||
NSButton* button;
|
||||
if ([filterType isEqualToString:FILTER_NONE])
|
||||
{
|
||||
button = right ? fActiveFilterButton : fPauseFilterButton;
|
||||
button = right ? self.fActiveFilterButton : self.fPauseFilterButton;
|
||||
}
|
||||
else if ([filterType isEqualToString:FILTER_ACTIVE])
|
||||
{
|
||||
button = right ? fDownloadFilterButton : fNoFilterButton;
|
||||
button = right ? self.fDownloadFilterButton : self.fNoFilterButton;
|
||||
}
|
||||
else if ([filterType isEqualToString:FILTER_DOWNLOAD])
|
||||
{
|
||||
button = right ? fSeedFilterButton : fActiveFilterButton;
|
||||
button = right ? self.fSeedFilterButton : self.fActiveFilterButton;
|
||||
}
|
||||
else if ([filterType isEqualToString:FILTER_SEED])
|
||||
{
|
||||
button = right ? fPauseFilterButton : fDownloadFilterButton;
|
||||
button = right ? self.fPauseFilterButton : self.fDownloadFilterButton;
|
||||
}
|
||||
else if ([filterType isEqualToString:FILTER_PAUSE])
|
||||
{
|
||||
button = right ? fNoFilterButton : fSeedFilterButton;
|
||||
button = right ? self.fNoFilterButton : self.fSeedFilterButton;
|
||||
}
|
||||
else
|
||||
{
|
||||
button = fNoFilterButton;
|
||||
button = self.fNoFilterButton;
|
||||
}
|
||||
|
||||
[self setFilter:button];
|
||||
|
@ -219,13 +229,13 @@
|
|||
|
||||
- (void)setSearchText:(id)sender
|
||||
{
|
||||
[NSUserDefaults.standardUserDefaults setObject:fSearchField.stringValue forKey:@"FilterSearchString"];
|
||||
[NSUserDefaults.standardUserDefaults setObject:self.fSearchField.stringValue forKey:@"FilterSearchString"];
|
||||
[NSNotificationCenter.defaultCenter postNotificationName:@"ApplyFilter" object:nil];
|
||||
}
|
||||
|
||||
- (void)focusSearchField
|
||||
{
|
||||
[self.view.window makeFirstResponder:fSearchField];
|
||||
[self.view.window makeFirstResponder:self.fSearchField];
|
||||
}
|
||||
|
||||
- (void)setSearchType:(id)sender
|
||||
|
@ -256,7 +266,7 @@
|
|||
|
||||
[NSUserDefaults.standardUserDefaults setObject:filterType forKey:@"FilterSearchType"];
|
||||
|
||||
fSearchField.placeholderString = [sender title];
|
||||
self.fSearchField.placeholderString = [sender title];
|
||||
}
|
||||
|
||||
[NSNotificationCenter.defaultCenter postNotificationName:@"ApplyFilter" object:nil];
|
||||
|
@ -278,10 +288,10 @@
|
|||
{
|
||||
[self updateGroupsButton];
|
||||
|
||||
[self setFilter:fNoFilterButton];
|
||||
[self setFilter:self.fNoFilterButton];
|
||||
|
||||
fSearchField.stringValue = @"";
|
||||
[self setSearchText:fSearchField];
|
||||
self.fSearchField.stringValue = @"";
|
||||
[self setSearchText:self.fSearchField];
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -292,7 +302,7 @@
|
|||
|
||||
- (NSArray*)searchStrings
|
||||
{
|
||||
return [fSearchField.stringValue betterComponentsSeparatedByCharactersInSet:NSCharacterSet.whitespaceAndNewlineCharacterSet];
|
||||
return [self.fSearchField.stringValue betterComponentsSeparatedByCharactersInSet:NSCharacterSet.whitespaceAndNewlineCharacterSet];
|
||||
}
|
||||
|
||||
- (void)setCountAll:(NSUInteger)all
|
||||
|
@ -301,16 +311,16 @@
|
|||
seeding:(NSUInteger)seeding
|
||||
paused:(NSUInteger)paused
|
||||
{
|
||||
[fNoFilterButton setCount:all];
|
||||
[fActiveFilterButton setCount:active];
|
||||
[fDownloadFilterButton setCount:downloading];
|
||||
[fSeedFilterButton setCount:seeding];
|
||||
[fPauseFilterButton setCount:paused];
|
||||
self.fNoFilterButton.count = all;
|
||||
self.fActiveFilterButton.count = active;
|
||||
self.fDownloadFilterButton.count = downloading;
|
||||
self.fSeedFilterButton.count = seeding;
|
||||
self.fPauseFilterButton.count = paused;
|
||||
}
|
||||
|
||||
- (void)menuNeedsUpdate:(NSMenu*)menu
|
||||
{
|
||||
if (menu == fGroupsButton.menu)
|
||||
if (menu == self.fGroupsButton.menu)
|
||||
{
|
||||
for (NSInteger i = menu.numberOfItems - 1; i >= 3; i--)
|
||||
{
|
||||
|
@ -363,23 +373,25 @@
|
|||
return YES;
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
- (void)resizeBar
|
||||
{
|
||||
//replace all buttons
|
||||
[fNoFilterButton sizeToFit];
|
||||
[fActiveFilterButton sizeToFit];
|
||||
[fDownloadFilterButton sizeToFit];
|
||||
[fSeedFilterButton sizeToFit];
|
||||
[fPauseFilterButton sizeToFit];
|
||||
[self.fNoFilterButton sizeToFit];
|
||||
[self.fActiveFilterButton sizeToFit];
|
||||
[self.fDownloadFilterButton sizeToFit];
|
||||
[self.fSeedFilterButton sizeToFit];
|
||||
[self.fPauseFilterButton sizeToFit];
|
||||
|
||||
NSRect allRect = fNoFilterButton.frame;
|
||||
NSRect activeRect = fActiveFilterButton.frame;
|
||||
NSRect downloadRect = fDownloadFilterButton.frame;
|
||||
NSRect seedRect = fSeedFilterButton.frame;
|
||||
NSRect pauseRect = fPauseFilterButton.frame;
|
||||
NSRect allRect = self.fNoFilterButton.frame;
|
||||
NSRect activeRect = self.fActiveFilterButton.frame;
|
||||
NSRect downloadRect = self.fDownloadFilterButton.frame;
|
||||
NSRect seedRect = self.fSeedFilterButton.frame;
|
||||
NSRect pauseRect = self.fPauseFilterButton.frame;
|
||||
|
||||
//size search filter to not overlap buttons
|
||||
NSRect searchFrame = fSearchField.frame;
|
||||
NSRect searchFrame = self.fSearchField.frame;
|
||||
searchFrame.origin.x = NSMaxX(pauseRect) + 5.0;
|
||||
searchFrame.size.width = NSWidth(self.view.frame) - searchFrame.origin.x - 5.0;
|
||||
|
||||
|
@ -413,13 +425,13 @@
|
|||
seedRect.origin.x = NSMaxX(downloadRect) + 1.0;
|
||||
pauseRect.origin.x = NSMaxX(seedRect) + 1.0;
|
||||
|
||||
fNoFilterButton.frame = allRect;
|
||||
fActiveFilterButton.frame = activeRect;
|
||||
fDownloadFilterButton.frame = downloadRect;
|
||||
fSeedFilterButton.frame = seedRect;
|
||||
fPauseFilterButton.frame = pauseRect;
|
||||
self.fNoFilterButton.frame = allRect;
|
||||
self.fActiveFilterButton.frame = activeRect;
|
||||
self.fDownloadFilterButton.frame = downloadRect;
|
||||
self.fSeedFilterButton.frame = seedRect;
|
||||
self.fPauseFilterButton.frame = pauseRect;
|
||||
|
||||
fSearchField.frame = searchFrame;
|
||||
self.fSearchField.frame = searchFrame;
|
||||
}
|
||||
|
||||
- (void)updateGroupsButton
|
||||
|
@ -441,8 +453,8 @@
|
|||
toolTip = [NSLocalizedString(@"Group", "Groups -> Button") stringByAppendingFormat:@": %@", groupName];
|
||||
}
|
||||
|
||||
[fGroupsButton.menu itemAtIndex:0].image = icon;
|
||||
fGroupsButton.toolTip = toolTip;
|
||||
[self.fGroupsButton.menu itemAtIndex:0].image = icon;
|
||||
self.fGroupsButton.toolTip = toolTip;
|
||||
}
|
||||
|
||||
- (void)updateGroups:(NSNotification*)notification
|
||||
|
|
|
@ -5,7 +5,5 @@
|
|||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
@interface FilterBarView : NSView
|
||||
{
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -5,10 +5,7 @@
|
|||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
@interface FilterButton : NSButton
|
||||
{
|
||||
NSUInteger fCount;
|
||||
}
|
||||
|
||||
- (void)setCount:(NSUInteger)count;
|
||||
@property(nonatomic) NSUInteger count;
|
||||
|
||||
@end
|
||||
|
|
|
@ -11,23 +11,23 @@
|
|||
{
|
||||
if ((self = [super initWithCoder:coder]))
|
||||
{
|
||||
fCount = NSNotFound;
|
||||
_count = NSNotFound;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)setCount:(NSUInteger)count
|
||||
{
|
||||
if (count == fCount)
|
||||
if (count == _count)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
fCount = count;
|
||||
_count = count;
|
||||
|
||||
self.toolTip = fCount == 1 ? NSLocalizedString(@"1 transfer", "Filter Button -> tool tip") :
|
||||
self.toolTip = _count == 1 ? NSLocalizedString(@"1 transfer", "Filter Button -> tool tip") :
|
||||
[NSString stringWithFormat:NSLocalizedString(@"%@ transfers", "Filter Bar Button -> tool tip"),
|
||||
[NSString formattedUInteger:fCount]];
|
||||
[NSString formattedUInteger:_count]];
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -7,18 +7,6 @@
|
|||
#include <libtransmission/transmission.h>
|
||||
|
||||
@interface GlobalOptionsPopoverViewController : NSViewController
|
||||
{
|
||||
tr_session* fHandle;
|
||||
NSUserDefaults* fDefaults;
|
||||
|
||||
IBOutlet NSTextField* fUploadLimitField;
|
||||
IBOutlet NSTextField* fDownloadLimitField;
|
||||
|
||||
IBOutlet NSTextField* fRatioStopField;
|
||||
IBOutlet NSTextField* fIdleStopField;
|
||||
|
||||
NSString* fInitialString;
|
||||
}
|
||||
|
||||
- (instancetype)initWithHandle:(tr_session*)handle;
|
||||
|
||||
|
|
|
@ -4,15 +4,30 @@
|
|||
|
||||
#import "GlobalOptionsPopoverViewController.h"
|
||||
|
||||
@interface GlobalOptionsPopoverViewController ()
|
||||
|
||||
@property(nonatomic, readonly) tr_session* fHandle;
|
||||
@property(nonatomic, readonly) NSUserDefaults* fDefaults;
|
||||
|
||||
@property(nonatomic) IBOutlet NSTextField* fUploadLimitField;
|
||||
@property(nonatomic) IBOutlet NSTextField* fDownloadLimitField;
|
||||
|
||||
@property(nonatomic) IBOutlet NSTextField* fRatioStopField;
|
||||
@property(nonatomic) IBOutlet NSTextField* fIdleStopField;
|
||||
|
||||
@property(nonatomic, copy) NSString* fInitialString;
|
||||
|
||||
@end
|
||||
|
||||
@implementation GlobalOptionsPopoverViewController
|
||||
|
||||
- (instancetype)initWithHandle:(tr_session*)handle
|
||||
{
|
||||
if ((self = [super initWithNibName:@"GlobalOptionsPopover" bundle:nil]))
|
||||
{
|
||||
fHandle = handle;
|
||||
_fHandle = handle;
|
||||
|
||||
fDefaults = NSUserDefaults.standardUserDefaults;
|
||||
_fDefaults = NSUserDefaults.standardUserDefaults;
|
||||
}
|
||||
|
||||
return self;
|
||||
|
@ -20,11 +35,11 @@
|
|||
|
||||
- (void)awakeFromNib
|
||||
{
|
||||
fUploadLimitField.intValue = [fDefaults integerForKey:@"UploadLimit"];
|
||||
fDownloadLimitField.intValue = [fDefaults integerForKey:@"DownloadLimit"];
|
||||
self.fUploadLimitField.intValue = [self.fDefaults integerForKey:@"UploadLimit"];
|
||||
self.fDownloadLimitField.intValue = [self.fDefaults integerForKey:@"DownloadLimit"];
|
||||
|
||||
fRatioStopField.floatValue = [fDefaults floatForKey:@"RatioLimit"];
|
||||
fIdleStopField.integerValue = [fDefaults integerForKey:@"IdleLimitMinutes"];
|
||||
self.fRatioStopField.floatValue = [self.fDefaults floatForKey:@"RatioLimit"];
|
||||
self.fIdleStopField.integerValue = [self.fDefaults integerForKey:@"IdleLimitMinutes"];
|
||||
|
||||
[self.view setFrameSize:self.view.fittingSize];
|
||||
}
|
||||
|
@ -36,7 +51,7 @@
|
|||
|
||||
- (IBAction)setDownSpeedSetting:(id)sender
|
||||
{
|
||||
tr_sessionLimitSpeed(fHandle, TR_DOWN, [fDefaults boolForKey:@"CheckDownload"]);
|
||||
tr_sessionLimitSpeed(self.fHandle, TR_DOWN, [self.fDefaults boolForKey:@"CheckDownload"]);
|
||||
|
||||
[NSNotificationCenter.defaultCenter postNotificationName:@"SpeedLimitUpdate" object:nil];
|
||||
}
|
||||
|
@ -44,8 +59,8 @@
|
|||
- (IBAction)setDownSpeedLimit:(id)sender
|
||||
{
|
||||
NSInteger const limit = [sender integerValue];
|
||||
[fDefaults setInteger:limit forKey:@"DownloadLimit"];
|
||||
tr_sessionSetSpeedLimit_KBps(fHandle, TR_DOWN, limit);
|
||||
[self.fDefaults setInteger:limit forKey:@"DownloadLimit"];
|
||||
tr_sessionSetSpeedLimit_KBps(self.fHandle, TR_DOWN, limit);
|
||||
|
||||
[NSNotificationCenter.defaultCenter postNotificationName:@"UpdateSpeedLimitValuesOutsidePrefs" object:nil];
|
||||
[NSNotificationCenter.defaultCenter postNotificationName:@"SpeedLimitUpdate" object:nil];
|
||||
|
@ -53,7 +68,7 @@
|
|||
|
||||
- (IBAction)setUpSpeedSetting:(id)sender
|
||||
{
|
||||
tr_sessionLimitSpeed(fHandle, TR_UP, [fDefaults boolForKey:@"CheckUpload"]);
|
||||
tr_sessionLimitSpeed(self.fHandle, TR_UP, [self.fDefaults boolForKey:@"CheckUpload"]);
|
||||
|
||||
[NSNotificationCenter.defaultCenter postNotificationName:@"UpdateSpeedLimitValuesOutsidePrefs" object:nil];
|
||||
[NSNotificationCenter.defaultCenter postNotificationName:@"SpeedLimitUpdate" object:nil];
|
||||
|
@ -62,15 +77,15 @@
|
|||
- (IBAction)setUpSpeedLimit:(id)sender
|
||||
{
|
||||
NSInteger const limit = [sender integerValue];
|
||||
[fDefaults setInteger:limit forKey:@"UploadLimit"];
|
||||
tr_sessionSetSpeedLimit_KBps(fHandle, TR_UP, limit);
|
||||
[self.fDefaults setInteger:limit forKey:@"UploadLimit"];
|
||||
tr_sessionSetSpeedLimit_KBps(self.fHandle, TR_UP, limit);
|
||||
|
||||
[NSNotificationCenter.defaultCenter postNotificationName:@"SpeedLimitUpdate" object:nil];
|
||||
}
|
||||
|
||||
- (IBAction)setRatioStopSetting:(id)sender
|
||||
{
|
||||
tr_sessionSetRatioLimited(fHandle, [fDefaults boolForKey:@"RatioCheck"]);
|
||||
tr_sessionSetRatioLimited(self.fHandle, [self.fDefaults boolForKey:@"RatioCheck"]);
|
||||
|
||||
//reload main table for seeding progress
|
||||
[NSNotificationCenter.defaultCenter postNotificationName:@"UpdateUI" object:nil];
|
||||
|
@ -82,8 +97,8 @@
|
|||
- (IBAction)setRatioStopLimit:(id)sender
|
||||
{
|
||||
CGFloat const value = [sender floatValue];
|
||||
[fDefaults setFloat:value forKey:@"RatioLimit"];
|
||||
tr_sessionSetRatioLimit(fHandle, value);
|
||||
[self.fDefaults setFloat:value forKey:@"RatioLimit"];
|
||||
tr_sessionSetRatioLimit(self.fHandle, value);
|
||||
|
||||
[NSNotificationCenter.defaultCenter postNotificationName:@"UpdateRatioStopValueOutsidePrefs" object:nil];
|
||||
|
||||
|
@ -96,7 +111,7 @@
|
|||
|
||||
- (IBAction)setIdleStopSetting:(id)sender
|
||||
{
|
||||
tr_sessionSetIdleLimited(fHandle, [fDefaults boolForKey:@"IdleLimitCheck"]);
|
||||
tr_sessionSetIdleLimited(self.fHandle, [self.fDefaults boolForKey:@"IdleLimitCheck"]);
|
||||
|
||||
//reload main table for remaining seeding time
|
||||
[NSNotificationCenter.defaultCenter postNotificationName:@"UpdateUI" object:nil];
|
||||
|
@ -108,8 +123,8 @@
|
|||
- (IBAction)setIdleStopLimit:(id)sender
|
||||
{
|
||||
NSInteger const value = [sender integerValue];
|
||||
[fDefaults setInteger:value forKey:@"IdleLimitMinutes"];
|
||||
tr_sessionSetIdleLimit(fHandle, value);
|
||||
[self.fDefaults setInteger:value forKey:@"IdleLimitMinutes"];
|
||||
tr_sessionSetIdleLimit(self.fHandle, value);
|
||||
|
||||
[NSNotificationCenter.defaultCenter postNotificationName:@"UpdateIdleStopValueOutsidePrefs" object:nil];
|
||||
|
||||
|
@ -122,7 +137,7 @@
|
|||
|
||||
- (BOOL)control:(NSControl*)control textShouldBeginEditing:(NSText*)fieldEditor
|
||||
{
|
||||
fInitialString = control.stringValue;
|
||||
self.fInitialString = control.stringValue;
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
@ -130,10 +145,10 @@
|
|||
- (BOOL)control:(NSControl*)control didFailToFormatString:(NSString*)string errorDescription:(NSString*)error
|
||||
{
|
||||
NSBeep();
|
||||
if (fInitialString)
|
||||
if (self.fInitialString)
|
||||
{
|
||||
control.stringValue = fInitialString;
|
||||
fInitialString = nil;
|
||||
control.stringValue = self.fInitialString;
|
||||
self.fInitialString = nil;
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
|
|
@ -5,11 +5,8 @@
|
|||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
@interface GroupToolbarItem : NSToolbarItem
|
||||
{
|
||||
NSArray* fIdentifiers;
|
||||
}
|
||||
|
||||
- (void)setIdentifiers:(NSArray*)identifiers;
|
||||
@property(nonatomic, copy) NSArray* identifiers;
|
||||
|
||||
- (void)createMenu:(NSArray*)labels;
|
||||
|
||||
|
|
|
@ -6,18 +6,13 @@
|
|||
|
||||
@implementation GroupToolbarItem
|
||||
|
||||
- (void)setIdentifiers:(NSArray*)identifiers
|
||||
{
|
||||
fIdentifiers = identifiers;
|
||||
}
|
||||
|
||||
- (void)validate
|
||||
{
|
||||
NSSegmentedControl* control = (NSSegmentedControl*)self.view;
|
||||
|
||||
for (NSInteger i = 0; i < control.segmentCount; i++)
|
||||
{
|
||||
[control setEnabled:[self.target validateToolbarItem:[[NSToolbarItem alloc] initWithItemIdentifier:fIdentifiers[i]]]
|
||||
[control setEnabled:[self.target validateToolbarItem:[[NSToolbarItem alloc] initWithItemIdentifier:self.identifiers[i]]]
|
||||
forSegment:i];
|
||||
}
|
||||
}
|
||||
|
@ -51,7 +46,7 @@
|
|||
for (NSInteger i = 0; i < count; i++)
|
||||
{
|
||||
[menuItem.submenu itemAtIndex:i].enabled = [self.target
|
||||
validateToolbarItem:[[NSToolbarItem alloc] initWithItemIdentifier:fIdentifiers[i]]];
|
||||
validateToolbarItem:[[NSToolbarItem alloc] initWithItemIdentifier:self.identifiers[i]]];
|
||||
}
|
||||
|
||||
return menuItem;
|
||||
|
|
|
@ -7,9 +7,6 @@
|
|||
@class Torrent;
|
||||
|
||||
@interface GroupsController : NSObject
|
||||
{
|
||||
NSMutableArray* fGroups;
|
||||
}
|
||||
|
||||
@property(nonatomic, class, readonly) GroupsController* groups;
|
||||
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
|
||||
@interface GroupsController ()
|
||||
|
||||
@property(nonatomic, readonly) NSMutableArray* fGroups;
|
||||
|
||||
- (void)saveGroups;
|
||||
|
||||
- (NSImage*)imageForGroup:(NSMutableDictionary*)dict;
|
||||
|
@ -38,11 +40,11 @@ GroupsController* fGroupsInstance = nil;
|
|||
NSData* data;
|
||||
if ((data = [NSUserDefaults.standardUserDefaults dataForKey:@"GroupDicts"]))
|
||||
{
|
||||
fGroups = [NSKeyedUnarchiver unarchiveObjectWithData:data];
|
||||
_fGroups = [NSKeyedUnarchiver unarchiveObjectWithData:data];
|
||||
}
|
||||
else if ((data = [NSUserDefaults.standardUserDefaults dataForKey:@"Groups"])) //handle old groups
|
||||
{
|
||||
fGroups = [NSUnarchiver unarchiveObjectWithData:data];
|
||||
_fGroups = [NSUnarchiver unarchiveObjectWithData:data];
|
||||
[NSUserDefaults.standardUserDefaults removeObjectForKey:@"Groups"];
|
||||
[self saveGroups];
|
||||
}
|
||||
|
@ -70,7 +72,7 @@ GroupsController* fGroupsInstance = nil;
|
|||
NSMutableDictionary* gray = [NSMutableDictionary
|
||||
dictionaryWithObjectsAndKeys:NSColor.grayColor, @"Color", NSLocalizedString(@"Gray", "Groups -> Name"), @"Name", @6, @"Index", nil];
|
||||
|
||||
fGroups = [[NSMutableArray alloc] initWithObjects:red, orange, yellow, green, blue, purple, gray, nil];
|
||||
_fGroups = [[NSMutableArray alloc] initWithObjects:red, orange, yellow, green, blue, purple, gray, nil];
|
||||
[self saveGroups]; //make sure this is saved right away
|
||||
}
|
||||
}
|
||||
|
@ -80,16 +82,16 @@ GroupsController* fGroupsInstance = nil;
|
|||
|
||||
- (NSInteger)numberOfGroups
|
||||
{
|
||||
return fGroups.count;
|
||||
return self.fGroups.count;
|
||||
}
|
||||
|
||||
- (NSInteger)rowValueForIndex:(NSInteger)index
|
||||
{
|
||||
if (index != -1)
|
||||
{
|
||||
for (NSUInteger i = 0; i < fGroups.count; i++)
|
||||
for (NSUInteger i = 0; i < self.fGroups.count; i++)
|
||||
{
|
||||
if (index == [fGroups[i][@"Index"] integerValue])
|
||||
if (index == [self.fGroups[i][@"Index"] integerValue])
|
||||
{
|
||||
return i;
|
||||
}
|
||||
|
@ -100,19 +102,19 @@ GroupsController* fGroupsInstance = nil;
|
|||
|
||||
- (NSInteger)indexForRow:(NSInteger)row
|
||||
{
|
||||
return [fGroups[row][@"Index"] integerValue];
|
||||
return [self.fGroups[row][@"Index"] integerValue];
|
||||
}
|
||||
|
||||
- (NSString*)nameForIndex:(NSInteger)index
|
||||
{
|
||||
NSInteger orderIndex = [self rowValueForIndex:index];
|
||||
return orderIndex != -1 ? fGroups[orderIndex][@"Name"] : nil;
|
||||
return orderIndex != -1 ? self.fGroups[orderIndex][@"Name"] : nil;
|
||||
}
|
||||
|
||||
- (void)setName:(NSString*)name forIndex:(NSInteger)index
|
||||
{
|
||||
NSInteger orderIndex = [self rowValueForIndex:index];
|
||||
fGroups[orderIndex][@"Name"] = name;
|
||||
self.fGroups[orderIndex][@"Name"] = name;
|
||||
[self saveGroups];
|
||||
|
||||
[NSNotificationCenter.defaultCenter postNotificationName:@"UpdateGroups" object:self];
|
||||
|
@ -121,18 +123,18 @@ GroupsController* fGroupsInstance = nil;
|
|||
- (NSImage*)imageForIndex:(NSInteger)index
|
||||
{
|
||||
NSInteger orderIndex = [self rowValueForIndex:index];
|
||||
return orderIndex != -1 ? [self imageForGroup:fGroups[orderIndex]] : [NSImage imageNamed:@"GroupsNoneTemplate"];
|
||||
return orderIndex != -1 ? [self imageForGroup:self.fGroups[orderIndex]] : [NSImage imageNamed:@"GroupsNoneTemplate"];
|
||||
}
|
||||
|
||||
- (NSColor*)colorForIndex:(NSInteger)index
|
||||
{
|
||||
NSInteger orderIndex = [self rowValueForIndex:index];
|
||||
return orderIndex != -1 ? fGroups[orderIndex][@"Color"] : nil;
|
||||
return orderIndex != -1 ? self.fGroups[orderIndex][@"Color"] : nil;
|
||||
}
|
||||
|
||||
- (void)setColor:(NSColor*)color forIndex:(NSInteger)index
|
||||
{
|
||||
NSMutableDictionary* dict = fGroups[[self rowValueForIndex:index]];
|
||||
NSMutableDictionary* dict = self.fGroups[[self rowValueForIndex:index]];
|
||||
[dict removeObjectForKey:@"Icon"];
|
||||
|
||||
dict[@"Color"] = color;
|
||||
|
@ -149,12 +151,12 @@ GroupsController* fGroupsInstance = nil;
|
|||
}
|
||||
|
||||
NSInteger orderIndex = [self rowValueForIndex:index];
|
||||
return [fGroups[orderIndex][@"UsesCustomDownloadLocation"] boolValue];
|
||||
return [self.fGroups[orderIndex][@"UsesCustomDownloadLocation"] boolValue];
|
||||
}
|
||||
|
||||
- (void)setUsesCustomDownloadLocation:(BOOL)useCustomLocation forIndex:(NSInteger)index
|
||||
{
|
||||
NSMutableDictionary* dict = fGroups[[self rowValueForIndex:index]];
|
||||
NSMutableDictionary* dict = self.fGroups[[self rowValueForIndex:index]];
|
||||
|
||||
dict[@"UsesCustomDownloadLocation"] = @(useCustomLocation);
|
||||
|
||||
|
@ -164,12 +166,12 @@ GroupsController* fGroupsInstance = nil;
|
|||
- (NSString*)customDownloadLocationForIndex:(NSInteger)index
|
||||
{
|
||||
NSInteger orderIndex = [self rowValueForIndex:index];
|
||||
return orderIndex != -1 ? fGroups[orderIndex][@"CustomDownloadLocation"] : nil;
|
||||
return orderIndex != -1 ? self.fGroups[orderIndex][@"CustomDownloadLocation"] : nil;
|
||||
}
|
||||
|
||||
- (void)setCustomDownloadLocation:(NSString*)location forIndex:(NSInteger)index
|
||||
{
|
||||
NSMutableDictionary* dict = fGroups[[self rowValueForIndex:index]];
|
||||
NSMutableDictionary* dict = self.fGroups[[self rowValueForIndex:index]];
|
||||
dict[@"CustomDownloadLocation"] = location;
|
||||
|
||||
[GroupsController.groups saveGroups];
|
||||
|
@ -183,13 +185,13 @@ GroupsController* fGroupsInstance = nil;
|
|||
return NO;
|
||||
}
|
||||
|
||||
NSNumber* assignRules = fGroups[orderIndex][@"UsesAutoGroupRules"];
|
||||
NSNumber* assignRules = self.fGroups[orderIndex][@"UsesAutoGroupRules"];
|
||||
return assignRules && assignRules.boolValue;
|
||||
}
|
||||
|
||||
- (void)setUsesAutoAssignRules:(BOOL)useAutoAssignRules forIndex:(NSInteger)index
|
||||
{
|
||||
NSMutableDictionary* dict = fGroups[[self rowValueForIndex:index]];
|
||||
NSMutableDictionary* dict = self.fGroups[[self rowValueForIndex:index]];
|
||||
|
||||
dict[@"UsesAutoGroupRules"] = @(useAutoAssignRules);
|
||||
|
||||
|
@ -204,12 +206,12 @@ GroupsController* fGroupsInstance = nil;
|
|||
return nil;
|
||||
}
|
||||
|
||||
return fGroups[orderIndex][@"AutoGroupRules"];
|
||||
return self.fGroups[orderIndex][@"AutoGroupRules"];
|
||||
}
|
||||
|
||||
- (void)setAutoAssignRules:(NSPredicate*)predicate forIndex:(NSInteger)index
|
||||
{
|
||||
NSMutableDictionary* dict = fGroups[[self rowValueForIndex:index]];
|
||||
NSMutableDictionary* dict = self.fGroups[[self rowValueForIndex:index]];
|
||||
|
||||
if (predicate)
|
||||
{
|
||||
|
@ -226,15 +228,15 @@ GroupsController* fGroupsInstance = nil;
|
|||
- (void)addNewGroup
|
||||
{
|
||||
//find the lowest index
|
||||
NSMutableIndexSet* candidates = [NSMutableIndexSet indexSetWithIndexesInRange:NSMakeRange(0, fGroups.count + 1)];
|
||||
for (NSDictionary* dict in fGroups)
|
||||
NSMutableIndexSet* candidates = [NSMutableIndexSet indexSetWithIndexesInRange:NSMakeRange(0, self.fGroups.count + 1)];
|
||||
for (NSDictionary* dict in self.fGroups)
|
||||
{
|
||||
[candidates removeIndex:[dict[@"Index"] integerValue]];
|
||||
}
|
||||
|
||||
NSInteger const index = candidates.firstIndex;
|
||||
|
||||
[fGroups addObject:[NSMutableDictionary dictionaryWithObjectsAndKeys:@(index),
|
||||
[self.fGroups addObject:[NSMutableDictionary dictionaryWithObjectsAndKeys:@(index),
|
||||
@"Index",
|
||||
[NSColor colorWithCalibratedRed:0.0 green:0.65 blue:1.0
|
||||
alpha:1.0],
|
||||
|
@ -249,8 +251,8 @@ GroupsController* fGroupsInstance = nil;
|
|||
|
||||
- (void)removeGroupWithRowIndex:(NSInteger)row
|
||||
{
|
||||
NSInteger index = [fGroups[row][@"Index"] integerValue];
|
||||
[fGroups removeObjectAtIndex:row];
|
||||
NSInteger index = [self.fGroups[row][@"Index"] integerValue];
|
||||
[self.fGroups removeObjectAtIndex:row];
|
||||
|
||||
[NSNotificationCenter.defaultCenter postNotificationName:@"GroupValueRemoved" object:self
|
||||
userInfo:@{ @"Index" : @(index) }];
|
||||
|
@ -266,7 +268,7 @@ GroupsController* fGroupsInstance = nil;
|
|||
|
||||
- (void)moveGroupAtRow:(NSInteger)oldRow toRow:(NSInteger)newRow
|
||||
{
|
||||
[fGroups moveObjectAtIndex:oldRow toIndex:newRow];
|
||||
[self.fGroups moveObjectAtIndex:oldRow toIndex:newRow];
|
||||
|
||||
[self saveGroups];
|
||||
[NSNotificationCenter.defaultCenter postNotificationName:@"UpdateGroups" object:self];
|
||||
|
@ -296,7 +298,7 @@ GroupsController* fGroupsInstance = nil;
|
|||
|
||||
[menu addItem:item];
|
||||
|
||||
for (NSMutableDictionary* dict in fGroups)
|
||||
for (NSMutableDictionary* dict in self.fGroups)
|
||||
{
|
||||
item = [[NSMenuItem alloc] initWithTitle:dict[@"Name"] action:action keyEquivalent:@""];
|
||||
item.target = target;
|
||||
|
@ -324,7 +326,7 @@ GroupsController* fGroupsInstance = nil;
|
|||
|
||||
- (NSInteger)groupIndexForTorrent:(Torrent*)torrent
|
||||
{
|
||||
for (NSDictionary* group in fGroups)
|
||||
for (NSDictionary* group in self.fGroups)
|
||||
{
|
||||
NSInteger row = [group[@"Index"] integerValue];
|
||||
if ([self torrent:torrent doesMatchRulesForGroupAtIndex:row])
|
||||
|
@ -335,11 +337,13 @@ GroupsController* fGroupsInstance = nil;
|
|||
return -1;
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
- (void)saveGroups
|
||||
{
|
||||
//don't archive the icon
|
||||
NSMutableArray* groups = [NSMutableArray arrayWithCapacity:fGroups.count];
|
||||
for (NSDictionary* dict in fGroups)
|
||||
NSMutableArray* groups = [NSMutableArray arrayWithCapacity:self.fGroups.count];
|
||||
for (NSDictionary* dict in self.fGroups)
|
||||
{
|
||||
NSMutableDictionary* tempDict = [dict mutableCopy];
|
||||
[tempDict removeObjectForKey:@"Icon"];
|
||||
|
|
|
@ -5,26 +5,10 @@
|
|||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
@interface GroupsPrefsController : NSObject
|
||||
{
|
||||
IBOutlet NSTableView* fTableView;
|
||||
IBOutlet NSSegmentedControl* fAddRemoveControl;
|
||||
|
||||
IBOutlet NSColorWell* fSelectedColorView;
|
||||
IBOutlet NSTextField* fSelectedColorNameField;
|
||||
IBOutlet NSButton* fCustomLocationEnableCheck;
|
||||
IBOutlet NSPopUpButton* fCustomLocationPopUp;
|
||||
|
||||
IBOutlet NSButton* fAutoAssignRulesEnableCheck;
|
||||
IBOutlet NSButton* fAutoAssignRulesEditButton;
|
||||
}
|
||||
|
||||
- (void)addRemoveGroup:(id)sender;
|
||||
|
||||
- (IBAction)toggleUseCustomDownloadLocation:(id)sender;
|
||||
- (IBAction)customDownloadLocationSheetShow:(id)sender;
|
||||
|
||||
- (IBAction)toggleUseAutoAssignRules:(id)sender;
|
||||
- (IBAction)orderFrontRulesSheet:(id)sender;
|
||||
- (IBAction)cancelRules:(id)sender;
|
||||
- (IBAction)saveRules:(id)sender;
|
||||
|
||||
@end
|
||||
|
|
|
@ -15,14 +15,21 @@
|
|||
|
||||
@interface GroupsPrefsController ()
|
||||
|
||||
@property(nonatomic) IBOutlet NSTableView* fTableView;
|
||||
@property(nonatomic) IBOutlet NSSegmentedControl* fAddRemoveControl;
|
||||
|
||||
@property(nonatomic) IBOutlet NSColorWell* fSelectedColorView;
|
||||
@property(nonatomic) IBOutlet NSTextField* fSelectedColorNameField;
|
||||
@property(nonatomic) IBOutlet NSButton* fCustomLocationEnableCheck;
|
||||
@property(nonatomic) IBOutlet NSPopUpButton* fCustomLocationPopUp;
|
||||
|
||||
@property(nonatomic) IBOutlet NSButton* fAutoAssignRulesEnableCheck;
|
||||
@property(nonatomic) IBOutlet NSButton* fAutoAssignRulesEditButton;
|
||||
|
||||
@property(nonatomic) IBOutlet NSWindow* groupRulesSheetWindow;
|
||||
@property(nonatomic, weak) IBOutlet NSPredicateEditor* ruleEditor;
|
||||
@property(nonatomic, weak) IBOutlet NSLayoutConstraint* ruleEditorHeightConstraint;
|
||||
|
||||
@end
|
||||
|
||||
@interface GroupsPrefsController ()
|
||||
|
||||
- (void)updateSelectedGroup;
|
||||
- (void)refreshCustomLocationWithSingleGroup;
|
||||
|
||||
|
@ -30,15 +37,11 @@
|
|||
|
||||
@implementation GroupsPrefsController
|
||||
|
||||
@synthesize groupRulesSheetWindow;
|
||||
@synthesize ruleEditor;
|
||||
@synthesize ruleEditorHeightConstraint;
|
||||
|
||||
- (void)awakeFromNib
|
||||
{
|
||||
[fTableView registerForDraggedTypes:@[ GROUP_TABLE_VIEW_DATA_TYPE ]];
|
||||
[self.fTableView registerForDraggedTypes:@[ GROUP_TABLE_VIEW_DATA_TYPE ]];
|
||||
|
||||
[fSelectedColorView addObserver:self forKeyPath:@"color" options:0 context:NULL];
|
||||
[self.fSelectedColorView addObserver:self forKeyPath:@"color" options:0 context:NULL];
|
||||
|
||||
[self updateSelectedGroup];
|
||||
}
|
||||
|
@ -71,21 +74,21 @@
|
|||
|
||||
- (void)observeValueForKeyPath:(NSString*)keyPath ofObject:(id)object change:(NSDictionary*)change context:(void*)context
|
||||
{
|
||||
if (object == fSelectedColorView && fTableView.numberOfSelectedRows == 1)
|
||||
if (object == self.fSelectedColorView && self.fTableView.numberOfSelectedRows == 1)
|
||||
{
|
||||
NSInteger index = [GroupsController.groups indexForRow:fTableView.selectedRow];
|
||||
[GroupsController.groups setColor:fSelectedColorView.color forIndex:index];
|
||||
fTableView.needsDisplay = YES;
|
||||
NSInteger index = [GroupsController.groups indexForRow:self.fTableView.selectedRow];
|
||||
[GroupsController.groups setColor:self.fSelectedColorView.color forIndex:index];
|
||||
self.fTableView.needsDisplay = YES;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)controlTextDidEndEditing:(NSNotification*)notification
|
||||
{
|
||||
if (notification.object == fSelectedColorNameField)
|
||||
if (notification.object == self.fSelectedColorNameField)
|
||||
{
|
||||
NSInteger index = [GroupsController.groups indexForRow:fTableView.selectedRow];
|
||||
[GroupsController.groups setName:fSelectedColorNameField.stringValue forIndex:index];
|
||||
fTableView.needsDisplay = YES;
|
||||
NSInteger index = [GroupsController.groups indexForRow:self.fTableView.selectedRow];
|
||||
[GroupsController.groups setName:self.fSelectedColorNameField.stringValue forIndex:index];
|
||||
self.fTableView.needsDisplay = YES;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -104,7 +107,7 @@
|
|||
NSPasteboard* pasteboard = info.draggingPasteboard;
|
||||
if ([pasteboard.types containsObject:GROUP_TABLE_VIEW_DATA_TYPE])
|
||||
{
|
||||
[fTableView setDropRow:row dropOperation:NSTableViewDropAbove];
|
||||
[self.fTableView setDropRow:row dropOperation:NSTableViewDropAbove];
|
||||
return NSDragOperationGeneric;
|
||||
}
|
||||
|
||||
|
@ -127,12 +130,12 @@
|
|||
newRow--;
|
||||
}
|
||||
|
||||
[fTableView beginUpdates];
|
||||
[self.fTableView beginUpdates];
|
||||
|
||||
[GroupsController.groups moveGroupAtRow:oldRow toRow:newRow];
|
||||
|
||||
[fTableView moveRowAtIndex:oldRow toIndex:newRow];
|
||||
[fTableView endUpdates];
|
||||
[self.fTableView moveRowAtIndex:oldRow toIndex:newRow];
|
||||
[self.fTableView endUpdates];
|
||||
}
|
||||
|
||||
return YES;
|
||||
|
@ -150,40 +153,40 @@
|
|||
switch ([[sender cell] tagForSegment:[sender selectedSegment]])
|
||||
{
|
||||
case ADD_TAG:
|
||||
[fTableView beginUpdates];
|
||||
[self.fTableView beginUpdates];
|
||||
|
||||
[GroupsController.groups addNewGroup];
|
||||
|
||||
row = fTableView.numberOfRows;
|
||||
row = self.fTableView.numberOfRows;
|
||||
|
||||
[fTableView insertRowsAtIndexes:[NSIndexSet indexSetWithIndex:row] withAnimation:NSTableViewAnimationSlideUp];
|
||||
[fTableView endUpdates];
|
||||
[self.fTableView insertRowsAtIndexes:[NSIndexSet indexSetWithIndex:row] withAnimation:NSTableViewAnimationSlideUp];
|
||||
[self.fTableView endUpdates];
|
||||
|
||||
[fTableView selectRowIndexes:[NSIndexSet indexSetWithIndex:row] byExtendingSelection:NO];
|
||||
[fTableView scrollRowToVisible:row];
|
||||
[self.fTableView selectRowIndexes:[NSIndexSet indexSetWithIndex:row] byExtendingSelection:NO];
|
||||
[self.fTableView scrollRowToVisible:row];
|
||||
|
||||
[fSelectedColorNameField.window makeFirstResponder:fSelectedColorNameField];
|
||||
[self.fSelectedColorNameField.window makeFirstResponder:self.fSelectedColorNameField];
|
||||
|
||||
break;
|
||||
|
||||
case REMOVE_TAG:
|
||||
row = fTableView.selectedRow;
|
||||
row = self.fTableView.selectedRow;
|
||||
|
||||
[fTableView beginUpdates];
|
||||
[self.fTableView beginUpdates];
|
||||
|
||||
[GroupsController.groups removeGroupWithRowIndex:row];
|
||||
|
||||
[fTableView removeRowsAtIndexes:[NSIndexSet indexSetWithIndex:row] withAnimation:NSTableViewAnimationSlideUp];
|
||||
[fTableView endUpdates];
|
||||
[self.fTableView removeRowsAtIndexes:[NSIndexSet indexSetWithIndex:row] withAnimation:NSTableViewAnimationSlideUp];
|
||||
[self.fTableView endUpdates];
|
||||
|
||||
if (fTableView.numberOfRows > 0)
|
||||
if (self.fTableView.numberOfRows > 0)
|
||||
{
|
||||
if (row == fTableView.numberOfRows)
|
||||
if (row == self.fTableView.numberOfRows)
|
||||
{
|
||||
--row;
|
||||
}
|
||||
[fTableView selectRowIndexes:[NSIndexSet indexSetWithIndex:row] byExtendingSelection:NO];
|
||||
[fTableView scrollRowToVisible:row];
|
||||
[self.fTableView selectRowIndexes:[NSIndexSet indexSetWithIndex:row] byExtendingSelection:NO];
|
||||
[self.fTableView scrollRowToVisible:row];
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -202,8 +205,8 @@
|
|||
panel.canChooseDirectories = YES;
|
||||
panel.canCreateDirectories = YES;
|
||||
|
||||
[panel beginSheetModalForWindow:fCustomLocationPopUp.window completionHandler:^(NSInteger result) {
|
||||
NSInteger const index = [GroupsController.groups indexForRow:fTableView.selectedRow];
|
||||
[panel beginSheetModalForWindow:self.fCustomLocationPopUp.window completionHandler:^(NSInteger result) {
|
||||
NSInteger const index = [GroupsController.groups indexForRow:self.fTableView.selectedRow];
|
||||
if (result == NSModalResponseOK)
|
||||
{
|
||||
NSString* path = panel.URLs[0].path;
|
||||
|
@ -220,14 +223,14 @@
|
|||
|
||||
[self refreshCustomLocationWithSingleGroup];
|
||||
|
||||
[fCustomLocationPopUp selectItemAtIndex:0];
|
||||
[self.fCustomLocationPopUp selectItemAtIndex:0];
|
||||
}];
|
||||
}
|
||||
|
||||
- (IBAction)toggleUseCustomDownloadLocation:(id)sender
|
||||
{
|
||||
NSInteger index = [GroupsController.groups indexForRow:fTableView.selectedRow];
|
||||
if (fCustomLocationEnableCheck.state == NSControlStateValueOn)
|
||||
NSInteger index = [GroupsController.groups indexForRow:self.fTableView.selectedRow];
|
||||
if (self.fCustomLocationEnableCheck.state == NSControlStateValueOn)
|
||||
{
|
||||
if ([GroupsController.groups customDownloadLocationForIndex:index])
|
||||
{
|
||||
|
@ -243,7 +246,7 @@
|
|||
[GroupsController.groups setUsesCustomDownloadLocation:NO forIndex:index];
|
||||
}
|
||||
|
||||
fCustomLocationPopUp.enabled = (fCustomLocationEnableCheck.state == NSControlStateValueOn);
|
||||
self.fCustomLocationPopUp.enabled = (self.fCustomLocationEnableCheck.state == NSControlStateValueOn);
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
@ -251,8 +254,8 @@
|
|||
|
||||
- (IBAction)toggleUseAutoAssignRules:(id)sender
|
||||
{
|
||||
NSInteger index = [GroupsController.groups indexForRow:fTableView.selectedRow];
|
||||
if (fAutoAssignRulesEnableCheck.state == NSControlStateValueOn)
|
||||
NSInteger index = [GroupsController.groups indexForRow:self.fTableView.selectedRow];
|
||||
if (self.fAutoAssignRulesEnableCheck.state == NSControlStateValueOn)
|
||||
{
|
||||
if ([GroupsController.groups autoAssignRulesForIndex:index])
|
||||
{
|
||||
|
@ -268,7 +271,7 @@
|
|||
[GroupsController.groups setUsesAutoAssignRules:NO forIndex:index];
|
||||
}
|
||||
|
||||
fAutoAssignRulesEditButton.enabled = fAutoAssignRulesEnableCheck.state == NSControlStateValueOn;
|
||||
self.fAutoAssignRulesEditButton.enabled = self.fAutoAssignRulesEnableCheck.state == NSControlStateValueOn;
|
||||
}
|
||||
|
||||
- (IBAction)orderFrontRulesSheet:(id)sender
|
||||
|
@ -278,7 +281,7 @@
|
|||
[NSBundle.mainBundle loadNibNamed:@"GroupRules" owner:self topLevelObjects:NULL];
|
||||
}
|
||||
|
||||
NSInteger index = [GroupsController.groups indexForRow:fTableView.selectedRow];
|
||||
NSInteger index = [GroupsController.groups indexForRow:self.fTableView.selectedRow];
|
||||
NSPredicate* predicate = [GroupsController.groups autoAssignRulesForIndex:index];
|
||||
self.ruleEditor.objectValue = predicate;
|
||||
|
||||
|
@ -287,7 +290,7 @@
|
|||
[self.ruleEditor addRow:nil];
|
||||
}
|
||||
|
||||
[fTableView.window beginSheet:self.groupRulesSheetWindow completionHandler:nil];
|
||||
[self.fTableView.window beginSheet:self.groupRulesSheetWindow completionHandler:nil];
|
||||
}
|
||||
|
||||
- (IBAction)cancelRules:(id)sender
|
||||
|
@ -295,12 +298,12 @@
|
|||
[self.groupRulesSheetWindow orderOut:nil];
|
||||
[NSApp endSheet:self.groupRulesSheetWindow];
|
||||
|
||||
NSInteger index = [GroupsController.groups indexForRow:fTableView.selectedRow];
|
||||
NSInteger index = [GroupsController.groups indexForRow:self.fTableView.selectedRow];
|
||||
if (![GroupsController.groups autoAssignRulesForIndex:index])
|
||||
{
|
||||
[GroupsController.groups setUsesAutoAssignRules:NO forIndex:index];
|
||||
fAutoAssignRulesEnableCheck.state = NO;
|
||||
fAutoAssignRulesEditButton.enabled = NO;
|
||||
self.fAutoAssignRulesEnableCheck.state = NO;
|
||||
self.fAutoAssignRulesEditButton.enabled = NO;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -309,14 +312,14 @@
|
|||
[self.groupRulesSheetWindow orderOut:nil];
|
||||
[NSApp endSheet:self.groupRulesSheetWindow];
|
||||
|
||||
NSInteger index = [GroupsController.groups indexForRow:fTableView.selectedRow];
|
||||
NSInteger index = [GroupsController.groups indexForRow:self.fTableView.selectedRow];
|
||||
[GroupsController.groups setUsesAutoAssignRules:YES forIndex:index];
|
||||
|
||||
NSPredicate* predicate = self.ruleEditor.objectValue;
|
||||
[GroupsController.groups setAutoAssignRules:predicate forIndex:index];
|
||||
|
||||
fAutoAssignRulesEnableCheck.state = [GroupsController.groups usesAutoAssignRulesForIndex:index];
|
||||
fAutoAssignRulesEditButton.enabled = fAutoAssignRulesEnableCheck.state == NSControlStateValueOn;
|
||||
self.fAutoAssignRulesEnableCheck.state = [GroupsController.groups usesAutoAssignRulesForIndex:index];
|
||||
self.fAutoAssignRulesEditButton.enabled = self.fAutoAssignRulesEnableCheck.state == NSControlStateValueOn;
|
||||
}
|
||||
|
||||
- (void)ruleEditorRowsDidChange:(NSNotification*)notification
|
||||
|
@ -333,57 +336,59 @@
|
|||
ruleEditorScrollView.hasVerticalScroller = requiredRowCount > maxVisibleRowCount;
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
- (void)updateSelectedGroup
|
||||
{
|
||||
[fAddRemoveControl setEnabled:fTableView.numberOfSelectedRows > 0 forSegment:REMOVE_TAG];
|
||||
if (fTableView.numberOfSelectedRows == 1)
|
||||
[self.fAddRemoveControl setEnabled:self.fTableView.numberOfSelectedRows > 0 forSegment:REMOVE_TAG];
|
||||
if (self.fTableView.numberOfSelectedRows == 1)
|
||||
{
|
||||
NSInteger const index = [GroupsController.groups indexForRow:fTableView.selectedRow];
|
||||
fSelectedColorView.color = [GroupsController.groups colorForIndex:index];
|
||||
fSelectedColorView.enabled = YES;
|
||||
fSelectedColorNameField.stringValue = [GroupsController.groups nameForIndex:index];
|
||||
fSelectedColorNameField.enabled = YES;
|
||||
NSInteger const index = [GroupsController.groups indexForRow:self.fTableView.selectedRow];
|
||||
self.fSelectedColorView.color = [GroupsController.groups colorForIndex:index];
|
||||
self.fSelectedColorView.enabled = YES;
|
||||
self.fSelectedColorNameField.stringValue = [GroupsController.groups nameForIndex:index];
|
||||
self.fSelectedColorNameField.enabled = YES;
|
||||
|
||||
[self refreshCustomLocationWithSingleGroup];
|
||||
|
||||
fAutoAssignRulesEnableCheck.state = [GroupsController.groups usesAutoAssignRulesForIndex:index];
|
||||
fAutoAssignRulesEnableCheck.enabled = YES;
|
||||
fAutoAssignRulesEditButton.enabled = (fAutoAssignRulesEnableCheck.state == NSControlStateValueOn);
|
||||
self.fAutoAssignRulesEnableCheck.state = [GroupsController.groups usesAutoAssignRulesForIndex:index];
|
||||
self.fAutoAssignRulesEnableCheck.enabled = YES;
|
||||
self.fAutoAssignRulesEditButton.enabled = (self.fAutoAssignRulesEnableCheck.state == NSControlStateValueOn);
|
||||
}
|
||||
else
|
||||
{
|
||||
fSelectedColorView.color = NSColor.whiteColor;
|
||||
fSelectedColorView.enabled = NO;
|
||||
fSelectedColorNameField.stringValue = @"";
|
||||
fSelectedColorNameField.enabled = NO;
|
||||
fCustomLocationEnableCheck.enabled = NO;
|
||||
fCustomLocationPopUp.enabled = NO;
|
||||
fAutoAssignRulesEnableCheck.enabled = NO;
|
||||
fAutoAssignRulesEditButton.enabled = NO;
|
||||
self.fSelectedColorView.color = NSColor.whiteColor;
|
||||
self.fSelectedColorView.enabled = NO;
|
||||
self.fSelectedColorNameField.stringValue = @"";
|
||||
self.fSelectedColorNameField.enabled = NO;
|
||||
self.fCustomLocationEnableCheck.enabled = NO;
|
||||
self.fCustomLocationPopUp.enabled = NO;
|
||||
self.fAutoAssignRulesEnableCheck.enabled = NO;
|
||||
self.fAutoAssignRulesEditButton.enabled = NO;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)refreshCustomLocationWithSingleGroup
|
||||
{
|
||||
NSInteger const index = [GroupsController.groups indexForRow:fTableView.selectedRow];
|
||||
NSInteger const index = [GroupsController.groups indexForRow:self.fTableView.selectedRow];
|
||||
|
||||
BOOL const hasCustomLocation = [GroupsController.groups usesCustomDownloadLocationForIndex:index];
|
||||
fCustomLocationEnableCheck.state = hasCustomLocation;
|
||||
fCustomLocationEnableCheck.enabled = YES;
|
||||
fCustomLocationPopUp.enabled = hasCustomLocation;
|
||||
self.fCustomLocationEnableCheck.state = hasCustomLocation;
|
||||
self.fCustomLocationEnableCheck.enabled = YES;
|
||||
self.fCustomLocationPopUp.enabled = hasCustomLocation;
|
||||
|
||||
NSString* location = [GroupsController.groups customDownloadLocationForIndex:index];
|
||||
if (location)
|
||||
{
|
||||
ExpandedPathToPathTransformer* pathTransformer = [[ExpandedPathToPathTransformer alloc] init];
|
||||
[fCustomLocationPopUp itemAtIndex:0].title = [pathTransformer transformedValue:location];
|
||||
[self.fCustomLocationPopUp itemAtIndex:0].title = [pathTransformer transformedValue:location];
|
||||
ExpandedPathToIconTransformer* iconTransformer = [[ExpandedPathToIconTransformer alloc] init];
|
||||
[fCustomLocationPopUp itemAtIndex:0].image = [iconTransformer transformedValue:location];
|
||||
[self.fCustomLocationPopUp itemAtIndex:0].image = [iconTransformer transformedValue:location];
|
||||
}
|
||||
else
|
||||
{
|
||||
[fCustomLocationPopUp itemAtIndex:0].title = @"";
|
||||
[fCustomLocationPopUp itemAtIndex:0].image = nil;
|
||||
[self.fCustomLocationPopUp itemAtIndex:0].title = @"";
|
||||
[self.fCustomLocationPopUp itemAtIndex:0].image = nil;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,51 +6,7 @@
|
|||
|
||||
#import "InfoViewController.h"
|
||||
|
||||
@class PiecesView;
|
||||
@class Torrent;
|
||||
|
||||
@interface InfoActivityViewController : NSViewController<InfoViewController>
|
||||
{
|
||||
NSArray* fTorrents;
|
||||
|
||||
BOOL fSet;
|
||||
|
||||
IBOutlet NSTextField* fDateAddedField;
|
||||
IBOutlet NSTextField* fDateCompletedField;
|
||||
IBOutlet NSTextField* fDateActivityField;
|
||||
IBOutlet NSTextField* fStateField;
|
||||
IBOutlet NSTextField* fProgressField;
|
||||
IBOutlet NSTextField* fHaveField;
|
||||
IBOutlet NSTextField* fDownloadedTotalField;
|
||||
IBOutlet NSTextField* fUploadedTotalField;
|
||||
IBOutlet NSTextField* fFailedHashField;
|
||||
IBOutlet NSTextField* fRatioField;
|
||||
IBOutlet NSTextField* fDownloadTimeField;
|
||||
IBOutlet NSTextField* fSeedTimeField;
|
||||
IBOutlet NSTextView* fErrorMessageView;
|
||||
|
||||
IBOutlet PiecesView* fPiecesView;
|
||||
IBOutlet NSSegmentedControl* fPiecesControl;
|
||||
|
||||
//remove when we switch to auto layout on 10.7
|
||||
IBOutlet NSTextField* fTransferSectionLabel;
|
||||
IBOutlet NSTextField* fDatesSectionLabel;
|
||||
IBOutlet NSTextField* fTimeSectionLabel;
|
||||
IBOutlet NSTextField* fStateLabel;
|
||||
IBOutlet NSTextField* fProgressLabel;
|
||||
IBOutlet NSTextField* fHaveLabel;
|
||||
IBOutlet NSTextField* fDownloadedLabel;
|
||||
IBOutlet NSTextField* fUploadedLabel;
|
||||
IBOutlet NSTextField* fFailedDLLabel;
|
||||
IBOutlet NSTextField* fRatioLabel;
|
||||
IBOutlet NSTextField* fErrorLabel;
|
||||
IBOutlet NSTextField* fDateAddedLabel;
|
||||
IBOutlet NSTextField* fDateCompletedLabel;
|
||||
IBOutlet NSTextField* fDateActivityLabel;
|
||||
IBOutlet NSTextField* fDownloadTimeLabel;
|
||||
IBOutlet NSTextField* fSeedTimeLabel;
|
||||
IBOutlet NSScrollView* fErrorScrollView;
|
||||
}
|
||||
|
||||
- (void)setInfoForTorrents:(NSArray*)torrents;
|
||||
- (void)updateInfo;
|
||||
|
|
|
@ -16,6 +16,46 @@
|
|||
|
||||
@interface InfoActivityViewController ()
|
||||
|
||||
@property(nonatomic, copy) NSArray* fTorrents;
|
||||
|
||||
@property(nonatomic) BOOL fSet;
|
||||
|
||||
@property(nonatomic) IBOutlet NSTextField* fDateAddedField;
|
||||
@property(nonatomic) IBOutlet NSTextField* fDateCompletedField;
|
||||
@property(nonatomic) IBOutlet NSTextField* fDateActivityField;
|
||||
@property(nonatomic) IBOutlet NSTextField* fStateField;
|
||||
@property(nonatomic) IBOutlet NSTextField* fProgressField;
|
||||
@property(nonatomic) IBOutlet NSTextField* fHaveField;
|
||||
@property(nonatomic) IBOutlet NSTextField* fDownloadedTotalField;
|
||||
@property(nonatomic) IBOutlet NSTextField* fUploadedTotalField;
|
||||
@property(nonatomic) IBOutlet NSTextField* fFailedHashField;
|
||||
@property(nonatomic) IBOutlet NSTextField* fRatioField;
|
||||
@property(nonatomic) IBOutlet NSTextField* fDownloadTimeField;
|
||||
@property(nonatomic) IBOutlet NSTextField* fSeedTimeField;
|
||||
@property(nonatomic) IBOutlet NSTextView* fErrorMessageView;
|
||||
|
||||
@property(nonatomic) IBOutlet PiecesView* fPiecesView;
|
||||
@property(nonatomic) IBOutlet NSSegmentedControl* fPiecesControl;
|
||||
|
||||
//remove when we switch to auto layout
|
||||
@property(nonatomic) IBOutlet NSTextField* fTransferSectionLabel;
|
||||
@property(nonatomic) IBOutlet NSTextField* fDatesSectionLabel;
|
||||
@property(nonatomic) IBOutlet NSTextField* fTimeSectionLabel;
|
||||
@property(nonatomic) IBOutlet NSTextField* fStateLabel;
|
||||
@property(nonatomic) IBOutlet NSTextField* fProgressLabel;
|
||||
@property(nonatomic) IBOutlet NSTextField* fHaveLabel;
|
||||
@property(nonatomic) IBOutlet NSTextField* fDownloadedLabel;
|
||||
@property(nonatomic) IBOutlet NSTextField* fUploadedLabel;
|
||||
@property(nonatomic) IBOutlet NSTextField* fFailedDLLabel;
|
||||
@property(nonatomic) IBOutlet NSTextField* fRatioLabel;
|
||||
@property(nonatomic) IBOutlet NSTextField* fErrorLabel;
|
||||
@property(nonatomic) IBOutlet NSTextField* fDateAddedLabel;
|
||||
@property(nonatomic) IBOutlet NSTextField* fDateCompletedLabel;
|
||||
@property(nonatomic) IBOutlet NSTextField* fDateActivityLabel;
|
||||
@property(nonatomic) IBOutlet NSTextField* fDownloadTimeLabel;
|
||||
@property(nonatomic) IBOutlet NSTextField* fSeedTimeLabel;
|
||||
@property(nonatomic) IBOutlet NSScrollView* fErrorScrollView;
|
||||
|
||||
- (void)setupInfo;
|
||||
|
||||
@end
|
||||
|
@ -34,24 +74,24 @@
|
|||
|
||||
- (void)awakeFromNib
|
||||
{
|
||||
[fTransferSectionLabel sizeToFit];
|
||||
[fDatesSectionLabel sizeToFit];
|
||||
[fTimeSectionLabel sizeToFit];
|
||||
[self.fTransferSectionLabel sizeToFit];
|
||||
[self.fDatesSectionLabel sizeToFit];
|
||||
[self.fTimeSectionLabel sizeToFit];
|
||||
|
||||
NSArray* labels = @[
|
||||
fStateLabel,
|
||||
fProgressLabel,
|
||||
fHaveLabel,
|
||||
fDownloadedLabel,
|
||||
fUploadedLabel,
|
||||
fFailedDLLabel,
|
||||
fRatioLabel,
|
||||
fErrorLabel,
|
||||
fDateAddedLabel,
|
||||
fDateCompletedLabel,
|
||||
fDateActivityLabel,
|
||||
fDownloadTimeLabel,
|
||||
fSeedTimeLabel
|
||||
self.fStateLabel,
|
||||
self.fProgressLabel,
|
||||
self.fHaveLabel,
|
||||
self.fDownloadedLabel,
|
||||
self.fUploadedLabel,
|
||||
self.fFailedDLLabel,
|
||||
self.fRatioLabel,
|
||||
self.fErrorLabel,
|
||||
self.fDateAddedLabel,
|
||||
self.fDateCompletedLabel,
|
||||
self.fDateActivityLabel,
|
||||
self.fDownloadTimeLabel,
|
||||
self.fSeedTimeLabel
|
||||
];
|
||||
|
||||
CGFloat oldMaxWidth = 0.0, originX, newMaxWidth = 0.0;
|
||||
|
@ -80,19 +120,19 @@
|
|||
}
|
||||
|
||||
NSArray* fields = @[
|
||||
fDateAddedField,
|
||||
fDateCompletedField,
|
||||
fDateActivityField,
|
||||
fStateField,
|
||||
fProgressField,
|
||||
fHaveField,
|
||||
fDownloadedTotalField,
|
||||
fUploadedTotalField,
|
||||
fFailedHashField,
|
||||
fRatioField,
|
||||
fDownloadTimeField,
|
||||
fSeedTimeField,
|
||||
fErrorScrollView
|
||||
self.fDateAddedField,
|
||||
self.fDateCompletedField,
|
||||
self.fDateActivityField,
|
||||
self.fStateField,
|
||||
self.fProgressField,
|
||||
self.fHaveField,
|
||||
self.fDownloadedTotalField,
|
||||
self.fUploadedTotalField,
|
||||
self.fFailedHashField,
|
||||
self.fRatioField,
|
||||
self.fDownloadTimeField,
|
||||
self.fSeedTimeField,
|
||||
self.fErrorScrollView
|
||||
];
|
||||
|
||||
CGFloat const widthIncrease = newMaxWidth - oldMaxWidth;
|
||||
|
@ -106,8 +146,8 @@
|
|||
|
||||
//set the click action of the pieces view
|
||||
#warning after 2.8 just hook this up in the xib
|
||||
fPiecesView.action = @selector(updatePiecesView:);
|
||||
fPiecesView.target = self;
|
||||
self.fPiecesView.action = @selector(updatePiecesView:);
|
||||
self.fPiecesView.target = self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
|
@ -118,19 +158,19 @@
|
|||
- (void)setInfoForTorrents:(NSArray*)torrents
|
||||
{
|
||||
//don't check if it's the same in case the metadata changed
|
||||
fTorrents = torrents;
|
||||
self.fTorrents = torrents;
|
||||
|
||||
fSet = NO;
|
||||
self.fSet = NO;
|
||||
}
|
||||
|
||||
- (void)updateInfo
|
||||
{
|
||||
if (!fSet)
|
||||
if (!self.fSet)
|
||||
{
|
||||
[self setupInfo];
|
||||
}
|
||||
|
||||
NSInteger const numberSelected = fTorrents.count;
|
||||
NSInteger const numberSelected = self.fTorrents.count;
|
||||
if (numberSelected == 0)
|
||||
{
|
||||
return;
|
||||
|
@ -138,7 +178,7 @@
|
|||
|
||||
uint64_t have = 0, haveVerified = 0, downloadedTotal = 0, uploadedTotal = 0, failedHash = 0;
|
||||
NSDate* lastActivity = nil;
|
||||
for (Torrent* torrent in fTorrents)
|
||||
for (Torrent* torrent in self.fTorrents)
|
||||
{
|
||||
have += torrent.haveTotal;
|
||||
haveVerified += torrent.haveVerified;
|
||||
|
@ -155,7 +195,7 @@
|
|||
|
||||
if (have == 0)
|
||||
{
|
||||
fHaveField.stringValue = [NSString stringForFileSize:0];
|
||||
self.fHaveField.stringValue = [NSString stringForFileSize:0];
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -163,25 +203,25 @@
|
|||
[NSString stringForFileSize:haveVerified]];
|
||||
if (have == haveVerified)
|
||||
{
|
||||
fHaveField.stringValue = verifiedString;
|
||||
self.fHaveField.stringValue = verifiedString;
|
||||
}
|
||||
else
|
||||
{
|
||||
fHaveField.stringValue = [NSString stringWithFormat:@"%@ (%@)", [NSString stringForFileSize:have], verifiedString];
|
||||
self.fHaveField.stringValue = [NSString stringWithFormat:@"%@ (%@)", [NSString stringForFileSize:have], verifiedString];
|
||||
}
|
||||
}
|
||||
|
||||
fDownloadedTotalField.stringValue = [NSString stringForFileSize:downloadedTotal];
|
||||
fUploadedTotalField.stringValue = [NSString stringForFileSize:uploadedTotal];
|
||||
fFailedHashField.stringValue = [NSString stringForFileSize:failedHash];
|
||||
self.fDownloadedTotalField.stringValue = [NSString stringForFileSize:downloadedTotal];
|
||||
self.fUploadedTotalField.stringValue = [NSString stringForFileSize:uploadedTotal];
|
||||
self.fFailedHashField.stringValue = [NSString stringForFileSize:failedHash];
|
||||
|
||||
fDateActivityField.objectValue = lastActivity;
|
||||
self.fDateActivityField.objectValue = lastActivity;
|
||||
|
||||
if (numberSelected == 1)
|
||||
{
|
||||
Torrent* torrent = fTorrents[0];
|
||||
Torrent* torrent = self.fTorrents[0];
|
||||
|
||||
fStateField.stringValue = torrent.stateString;
|
||||
self.fStateField.stringValue = torrent.stateString;
|
||||
|
||||
NSString* progressString = [NSString percentString:torrent.progress longDecimals:YES];
|
||||
if (torrent.folder)
|
||||
|
@ -191,18 +231,18 @@
|
|||
[NSString percentString:torrent.progressDone longDecimals:YES]];
|
||||
progressString = [progressString stringByAppendingFormat:@" (%@)", progressSelectedString];
|
||||
}
|
||||
fProgressField.stringValue = progressString;
|
||||
self.fProgressField.stringValue = progressString;
|
||||
|
||||
fRatioField.stringValue = [NSString stringForRatio:torrent.ratio];
|
||||
self.fRatioField.stringValue = [NSString stringForRatio:torrent.ratio];
|
||||
|
||||
NSString* errorMessage = torrent.errorMessage;
|
||||
if (![errorMessage isEqualToString:fErrorMessageView.string])
|
||||
fErrorMessageView.string = errorMessage;
|
||||
if (![errorMessage isEqualToString:self.fErrorMessageView.string])
|
||||
self.fErrorMessageView.string = errorMessage;
|
||||
|
||||
fDateCompletedField.objectValue = torrent.dateCompleted;
|
||||
self.fDateCompletedField.objectValue = torrent.dateCompleted;
|
||||
|
||||
//uses a relative date, so can't be set once
|
||||
fDateAddedField.objectValue = torrent.dateAdded;
|
||||
self.fDateAddedField.objectValue = torrent.dateAdded;
|
||||
|
||||
static NSDateComponentsFormatter* timeFormatter;
|
||||
static dispatch_once_t onceToken;
|
||||
|
@ -213,14 +253,14 @@
|
|||
timeFormatter.zeroFormattingBehavior = NSDateComponentsFormatterZeroFormattingBehaviorDropLeading;
|
||||
});
|
||||
|
||||
fDownloadTimeField.stringValue = [timeFormatter stringFromTimeInterval:torrent.secondsDownloading];
|
||||
fSeedTimeField.stringValue = [timeFormatter stringFromTimeInterval:torrent.secondsSeeding];
|
||||
self.fDownloadTimeField.stringValue = [timeFormatter stringFromTimeInterval:torrent.secondsDownloading];
|
||||
self.fSeedTimeField.stringValue = [timeFormatter stringFromTimeInterval:torrent.secondsSeeding];
|
||||
|
||||
[fPiecesView updateView];
|
||||
[self.fPiecesView updateView];
|
||||
}
|
||||
else if (numberSelected > 1)
|
||||
{
|
||||
fRatioField.stringValue = [NSString stringForRatio:tr_getRatio(uploadedTotal, downloadedTotal)];
|
||||
self.fRatioField.stringValue = [NSString stringForRatio:tr_getRatio(uploadedTotal, downloadedTotal)];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -235,62 +275,64 @@
|
|||
{
|
||||
BOOL const piecesAvailableSegment = [NSUserDefaults.standardUserDefaults boolForKey:@"PiecesViewShowAvailability"];
|
||||
|
||||
[fPiecesControl setSelected:piecesAvailableSegment forSegment:PIECES_CONTROL_AVAILABLE];
|
||||
[fPiecesControl setSelected:!piecesAvailableSegment forSegment:PIECES_CONTROL_PROGRESS];
|
||||
[self.fPiecesControl setSelected:piecesAvailableSegment forSegment:PIECES_CONTROL_AVAILABLE];
|
||||
[self.fPiecesControl setSelected:!piecesAvailableSegment forSegment:PIECES_CONTROL_PROGRESS];
|
||||
|
||||
[fPiecesView updateView];
|
||||
[self.fPiecesView updateView];
|
||||
}
|
||||
|
||||
- (void)clearView
|
||||
{
|
||||
[fPiecesView clearView];
|
||||
[self.fPiecesView clearView];
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
- (void)setupInfo
|
||||
{
|
||||
NSUInteger const count = fTorrents.count;
|
||||
NSUInteger const count = self.fTorrents.count;
|
||||
if (count != 1)
|
||||
{
|
||||
if (count == 0)
|
||||
{
|
||||
fHaveField.stringValue = @"";
|
||||
fDownloadedTotalField.stringValue = @"";
|
||||
fUploadedTotalField.stringValue = @"";
|
||||
fFailedHashField.stringValue = @"";
|
||||
fDateActivityField.objectValue = @""; //using [field setStringValue: @""] causes "December 31, 1969 7:00 PM" to be displayed, at least on 10.7.3
|
||||
fRatioField.stringValue = @"";
|
||||
self.fHaveField.stringValue = @"";
|
||||
self.fDownloadedTotalField.stringValue = @"";
|
||||
self.fUploadedTotalField.stringValue = @"";
|
||||
self.fFailedHashField.stringValue = @"";
|
||||
self.fDateActivityField.objectValue = @""; //using [field setStringValue: @""] causes "December 31, 1969 7:00 PM" to be displayed, at least on 10.7.3
|
||||
self.fRatioField.stringValue = @"";
|
||||
}
|
||||
|
||||
fStateField.stringValue = @"";
|
||||
fProgressField.stringValue = @"";
|
||||
self.fStateField.stringValue = @"";
|
||||
self.fProgressField.stringValue = @"";
|
||||
|
||||
fErrorMessageView.string = @"";
|
||||
self.fErrorMessageView.string = @"";
|
||||
|
||||
//using [field setStringValue: @""] causes "December 31, 1969 7:00 PM" to be displayed, at least on 10.7.3
|
||||
fDateAddedField.objectValue = @"";
|
||||
fDateCompletedField.objectValue = @"";
|
||||
self.fDateAddedField.objectValue = @"";
|
||||
self.fDateCompletedField.objectValue = @"";
|
||||
|
||||
fDownloadTimeField.stringValue = @"";
|
||||
fSeedTimeField.stringValue = @"";
|
||||
self.fDownloadTimeField.stringValue = @"";
|
||||
self.fSeedTimeField.stringValue = @"";
|
||||
|
||||
[fPiecesControl setSelected:NO forSegment:PIECES_CONTROL_AVAILABLE];
|
||||
[fPiecesControl setSelected:NO forSegment:PIECES_CONTROL_PROGRESS];
|
||||
fPiecesControl.enabled = NO;
|
||||
[fPiecesView setTorrent:nil];
|
||||
[self.fPiecesControl setSelected:NO forSegment:PIECES_CONTROL_AVAILABLE];
|
||||
[self.fPiecesControl setSelected:NO forSegment:PIECES_CONTROL_PROGRESS];
|
||||
self.fPiecesControl.enabled = NO;
|
||||
self.fPiecesView.torrent = nil;
|
||||
}
|
||||
else
|
||||
{
|
||||
Torrent* torrent = fTorrents[0];
|
||||
Torrent* torrent = self.fTorrents[0];
|
||||
|
||||
BOOL const piecesAvailableSegment = [NSUserDefaults.standardUserDefaults boolForKey:@"PiecesViewShowAvailability"];
|
||||
[fPiecesControl setSelected:piecesAvailableSegment forSegment:PIECES_CONTROL_AVAILABLE];
|
||||
[fPiecesControl setSelected:!piecesAvailableSegment forSegment:PIECES_CONTROL_PROGRESS];
|
||||
fPiecesControl.enabled = YES;
|
||||
[self.fPiecesControl setSelected:piecesAvailableSegment forSegment:PIECES_CONTROL_AVAILABLE];
|
||||
[self.fPiecesControl setSelected:!piecesAvailableSegment forSegment:PIECES_CONTROL_PROGRESS];
|
||||
self.fPiecesControl.enabled = YES;
|
||||
|
||||
[fPiecesView setTorrent:torrent];
|
||||
self.fPiecesView.torrent = torrent;
|
||||
}
|
||||
|
||||
fSet = YES;
|
||||
self.fSet = YES;
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -7,20 +7,10 @@
|
|||
|
||||
#import "InfoViewController.h"
|
||||
|
||||
@class FileOutlineController;
|
||||
|
||||
@interface InfoFileViewController : NSViewController<InfoViewController>
|
||||
{
|
||||
NSArray* fTorrents;
|
||||
|
||||
BOOL fSet;
|
||||
|
||||
IBOutlet FileOutlineController* fFileController;
|
||||
|
||||
IBOutlet NSSearchField* fFileFilterField;
|
||||
IBOutlet NSButton* fCheckAllButton;
|
||||
IBOutlet NSButton* fUncheckAllButton;
|
||||
}
|
||||
@property(nonatomic, readonly) NSArray* quickLookURLs;
|
||||
@property(nonatomic, readonly) BOOL canQuickLook;
|
||||
|
||||
- (void)setInfoForTorrents:(NSArray*)torrents;
|
||||
- (void)updateInfo;
|
||||
|
@ -31,8 +21,6 @@
|
|||
- (IBAction)checkAll:(id)sender;
|
||||
- (IBAction)uncheckAll:(id)sender;
|
||||
|
||||
@property(nonatomic, readonly) NSArray* quickLookURLs;
|
||||
@property(nonatomic, readonly) BOOL canQuickLook;
|
||||
- (NSRect)quickLookSourceFrameForPreviewItem:(id<QLPreviewItem>)item;
|
||||
|
||||
@end
|
||||
|
|
|
@ -10,6 +10,16 @@
|
|||
|
||||
@interface InfoFileViewController ()
|
||||
|
||||
@property(nonatomic, copy) NSArray* fTorrents;
|
||||
|
||||
@property(nonatomic) BOOL fSet;
|
||||
|
||||
@property(nonatomic) IBOutlet FileOutlineController* fFileController;
|
||||
|
||||
@property(nonatomic) IBOutlet NSSearchField* fFileFilterField;
|
||||
@property(nonatomic) IBOutlet NSButton* fCheckAllButton;
|
||||
@property(nonatomic) IBOutlet NSButton* fUncheckAllButton;
|
||||
|
||||
- (void)setupInfo;
|
||||
|
||||
- (BOOL)canQuickLookFile:(FileListNode*)item;
|
||||
|
@ -38,59 +48,59 @@
|
|||
self.view.frame = viewRect;
|
||||
}
|
||||
|
||||
[fFileFilterField.cell setPlaceholderString:NSLocalizedString(@"Filter", "inspector -> file filter")];
|
||||
[self.fFileFilterField.cell setPlaceholderString:NSLocalizedString(@"Filter", "inspector -> file filter")];
|
||||
|
||||
//localize and place all and none buttons
|
||||
fCheckAllButton.title = NSLocalizedString(@"All", "inspector -> check all");
|
||||
fUncheckAllButton.title = NSLocalizedString(@"None", "inspector -> check all");
|
||||
self.fCheckAllButton.title = NSLocalizedString(@"All", "inspector -> check all");
|
||||
self.fUncheckAllButton.title = NSLocalizedString(@"None", "inspector -> check all");
|
||||
|
||||
NSRect checkAllFrame = fCheckAllButton.frame;
|
||||
NSRect uncheckAllFrame = fUncheckAllButton.frame;
|
||||
NSRect checkAllFrame = self.fCheckAllButton.frame;
|
||||
NSRect uncheckAllFrame = self.fUncheckAllButton.frame;
|
||||
CGFloat const oldAllWidth = checkAllFrame.size.width;
|
||||
CGFloat const oldNoneWidth = uncheckAllFrame.size.width;
|
||||
|
||||
[fCheckAllButton sizeToFit];
|
||||
[fUncheckAllButton sizeToFit];
|
||||
CGFloat const newWidth = MAX(fCheckAllButton.bounds.size.width, fUncheckAllButton.bounds.size.width);
|
||||
[self.fCheckAllButton sizeToFit];
|
||||
[self.fUncheckAllButton sizeToFit];
|
||||
CGFloat const newWidth = MAX(self.fCheckAllButton.bounds.size.width, self.fUncheckAllButton.bounds.size.width);
|
||||
|
||||
CGFloat const uncheckAllChange = newWidth - oldNoneWidth;
|
||||
uncheckAllFrame.size.width = newWidth;
|
||||
uncheckAllFrame.origin.x -= uncheckAllChange;
|
||||
fUncheckAllButton.frame = uncheckAllFrame;
|
||||
self.fUncheckAllButton.frame = uncheckAllFrame;
|
||||
|
||||
CGFloat const checkAllChange = newWidth - oldAllWidth;
|
||||
checkAllFrame.size.width = newWidth;
|
||||
checkAllFrame.origin.x -= (checkAllChange + uncheckAllChange);
|
||||
fCheckAllButton.frame = checkAllFrame;
|
||||
self.fCheckAllButton.frame = checkAllFrame;
|
||||
}
|
||||
|
||||
- (void)setInfoForTorrents:(NSArray*)torrents
|
||||
{
|
||||
//don't check if it's the same in case the metadata changed
|
||||
fTorrents = torrents;
|
||||
self.fTorrents = torrents;
|
||||
|
||||
fSet = NO;
|
||||
self.fSet = NO;
|
||||
}
|
||||
|
||||
- (void)updateInfo
|
||||
{
|
||||
if (!fSet)
|
||||
if (!self.fSet)
|
||||
{
|
||||
[self setupInfo];
|
||||
}
|
||||
|
||||
if (fTorrents.count == 1)
|
||||
if (self.fTorrents.count == 1)
|
||||
{
|
||||
[fFileController refresh];
|
||||
[self.fFileController refresh];
|
||||
|
||||
#warning use TorrentFileCheckChange notification as well
|
||||
Torrent* torrent = fTorrents[0];
|
||||
Torrent* torrent = self.fTorrents[0];
|
||||
if (torrent.folder)
|
||||
{
|
||||
NSInteger const filesCheckState = [torrent
|
||||
checkForFiles:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, torrent.fileCount)]];
|
||||
fCheckAllButton.enabled = filesCheckState != NSControlStateValueOn; //if anything is unchecked
|
||||
fUncheckAllButton.enabled = !torrent.allDownloaded; //if there are any checked files that aren't finished
|
||||
self.fCheckAllButton.enabled = filesCheckState != NSControlStateValueOn; //if anything is unchecked
|
||||
self.fUncheckAllButton.enabled = !torrent.allDownloaded; //if there are any checked files that aren't finished
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -102,23 +112,23 @@
|
|||
|
||||
- (void)setFileFilterText:(id)sender
|
||||
{
|
||||
[fFileController setFilterText:[sender stringValue]];
|
||||
self.fFileController.filterText = [sender stringValue];
|
||||
}
|
||||
|
||||
- (IBAction)checkAll:(id)sender
|
||||
{
|
||||
[fFileController checkAll];
|
||||
[self.fFileController checkAll];
|
||||
}
|
||||
|
||||
- (IBAction)uncheckAll:(id)sender
|
||||
{
|
||||
[fFileController uncheckAll];
|
||||
[self.fFileController uncheckAll];
|
||||
}
|
||||
|
||||
- (NSArray*)quickLookURLs
|
||||
{
|
||||
FileOutlineView* fileOutlineView = fFileController.outlineView;
|
||||
Torrent* torrent = fTorrents[0];
|
||||
FileOutlineView* fileOutlineView = self.fFileController.outlineView;
|
||||
Torrent* torrent = self.fTorrents[0];
|
||||
NSIndexSet* indexes = fileOutlineView.selectedRowIndexes;
|
||||
NSMutableArray* urlArray = [NSMutableArray arrayWithCapacity:indexes.count];
|
||||
|
||||
|
@ -136,18 +146,18 @@
|
|||
|
||||
- (BOOL)canQuickLook
|
||||
{
|
||||
if (fTorrents.count != 1)
|
||||
if (self.fTorrents.count != 1)
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
Torrent* torrent = fTorrents[0];
|
||||
Torrent* torrent = self.fTorrents[0];
|
||||
if (!torrent.folder)
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
FileOutlineView* fileOutlineView = fFileController.outlineView;
|
||||
FileOutlineView* fileOutlineView = self.fFileController.outlineView;
|
||||
NSIndexSet* indexes = fileOutlineView.selectedRowIndexes;
|
||||
|
||||
for (NSUInteger i = indexes.firstIndex; i != NSNotFound; i = [indexes indexGreaterThanIndex:i])
|
||||
|
@ -163,10 +173,10 @@
|
|||
|
||||
- (NSRect)quickLookSourceFrameForPreviewItem:(id<QLPreviewItem>)item
|
||||
{
|
||||
FileOutlineView* fileOutlineView = fFileController.outlineView;
|
||||
FileOutlineView* fileOutlineView = self.fFileController.outlineView;
|
||||
|
||||
NSString* fullPath = ((NSURL*)item).path;
|
||||
Torrent* torrent = fTorrents[0];
|
||||
Torrent* torrent = self.fTorrents[0];
|
||||
NSRange visibleRows = [fileOutlineView rowsInRect:fileOutlineView.bounds];
|
||||
|
||||
for (NSUInteger row = visibleRows.location; row < NSMaxRange(visibleRows); row++)
|
||||
|
@ -191,41 +201,43 @@
|
|||
return NSZeroRect;
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
- (void)setupInfo
|
||||
{
|
||||
fFileFilterField.stringValue = @"";
|
||||
self.fFileFilterField.stringValue = @"";
|
||||
|
||||
if (fTorrents.count == 1)
|
||||
if (self.fTorrents.count == 1)
|
||||
{
|
||||
Torrent* torrent = fTorrents[0];
|
||||
Torrent* torrent = self.fTorrents[0];
|
||||
|
||||
[fFileController setTorrent:torrent];
|
||||
self.fFileController.torrent = torrent;
|
||||
|
||||
BOOL const isFolder = torrent.folder;
|
||||
fFileFilterField.enabled = isFolder;
|
||||
self.fFileFilterField.enabled = isFolder;
|
||||
|
||||
if (!isFolder)
|
||||
{
|
||||
fCheckAllButton.enabled = NO;
|
||||
fUncheckAllButton.enabled = NO;
|
||||
self.fCheckAllButton.enabled = NO;
|
||||
self.fUncheckAllButton.enabled = NO;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
[fFileController setTorrent:nil];
|
||||
self.fFileController.torrent = nil;
|
||||
|
||||
fFileFilterField.enabled = NO;
|
||||
self.fFileFilterField.enabled = NO;
|
||||
|
||||
fCheckAllButton.enabled = NO;
|
||||
fUncheckAllButton.enabled = NO;
|
||||
self.fCheckAllButton.enabled = NO;
|
||||
self.fUncheckAllButton.enabled = NO;
|
||||
}
|
||||
|
||||
fSet = YES;
|
||||
self.fSet = YES;
|
||||
}
|
||||
|
||||
- (BOOL)canQuickLookFile:(FileListNode*)item
|
||||
{
|
||||
Torrent* torrent = fTorrents[0];
|
||||
Torrent* torrent = self.fTorrents[0];
|
||||
return (item.isFolder || [torrent fileProgress:item] >= 1.0) && [torrent fileLocation:item];
|
||||
}
|
||||
|
||||
|
|
|
@ -7,34 +7,6 @@
|
|||
#import "InfoViewController.h"
|
||||
|
||||
@interface InfoGeneralViewController : NSViewController<InfoViewController>
|
||||
{
|
||||
NSArray* fTorrents;
|
||||
|
||||
BOOL fSet;
|
||||
|
||||
IBOutlet NSTextField* fPiecesField;
|
||||
IBOutlet NSTextField* fHashField;
|
||||
IBOutlet NSTextField* fSecureField;
|
||||
IBOutlet NSTextField* fDataLocationField;
|
||||
IBOutlet NSTextField* fCreatorField;
|
||||
IBOutlet NSTextField* fDateCreatedField;
|
||||
|
||||
IBOutlet NSTextView* fCommentView;
|
||||
|
||||
IBOutlet NSButton* fRevealDataButton;
|
||||
|
||||
//remove when we switch to auto layout on 10.7
|
||||
IBOutlet NSTextField* fPiecesLabel;
|
||||
IBOutlet NSTextField* fHashLabel;
|
||||
IBOutlet NSTextField* fSecureLabel;
|
||||
IBOutlet NSTextField* fCreatorLabel;
|
||||
IBOutlet NSTextField* fDateCreatedLabel;
|
||||
IBOutlet NSTextField* fCommentLabel;
|
||||
IBOutlet NSTextField* fDataLocationLabel;
|
||||
IBOutlet NSTextField* fInfoSectionLabel;
|
||||
IBOutlet NSTextField* fWhereSectionLabel;
|
||||
IBOutlet NSScrollView* fCommentScrollView;
|
||||
}
|
||||
|
||||
- (void)setInfoForTorrents:(NSArray*)torrents;
|
||||
- (void)updateInfo;
|
||||
|
|
|
@ -8,6 +8,33 @@
|
|||
|
||||
@interface InfoGeneralViewController ()
|
||||
|
||||
@property(nonatomic, copy) NSArray* fTorrents;
|
||||
|
||||
@property(nonatomic) BOOL fSet;
|
||||
|
||||
@property(nonatomic) IBOutlet NSTextField* fPiecesField;
|
||||
@property(nonatomic) IBOutlet NSTextField* fHashField;
|
||||
@property(nonatomic) IBOutlet NSTextField* fSecureField;
|
||||
@property(nonatomic) IBOutlet NSTextField* fDataLocationField;
|
||||
@property(nonatomic) IBOutlet NSTextField* fCreatorField;
|
||||
@property(nonatomic) IBOutlet NSTextField* fDateCreatedField;
|
||||
|
||||
@property(nonatomic) IBOutlet NSTextView* fCommentView;
|
||||
|
||||
@property(nonatomic) IBOutlet NSButton* fRevealDataButton;
|
||||
|
||||
//remove when we switch to auto layout
|
||||
@property(nonatomic) IBOutlet NSTextField* fPiecesLabel;
|
||||
@property(nonatomic) IBOutlet NSTextField* fHashLabel;
|
||||
@property(nonatomic) IBOutlet NSTextField* fSecureLabel;
|
||||
@property(nonatomic) IBOutlet NSTextField* fCreatorLabel;
|
||||
@property(nonatomic) IBOutlet NSTextField* fDateCreatedLabel;
|
||||
@property(nonatomic) IBOutlet NSTextField* fCommentLabel;
|
||||
@property(nonatomic) IBOutlet NSTextField* fDataLocationLabel;
|
||||
@property(nonatomic) IBOutlet NSTextField* fInfoSectionLabel;
|
||||
@property(nonatomic) IBOutlet NSTextField* fWhereSectionLabel;
|
||||
@property(nonatomic) IBOutlet NSScrollView* fCommentScrollView;
|
||||
|
||||
- (void)setupInfo;
|
||||
|
||||
@end
|
||||
|
@ -26,18 +53,18 @@
|
|||
|
||||
- (void)awakeFromNib
|
||||
{
|
||||
#warning remove when 10.7-only with auto layout
|
||||
[fInfoSectionLabel sizeToFit];
|
||||
[fWhereSectionLabel sizeToFit];
|
||||
#warning remove when switching to auto layout
|
||||
[self.fInfoSectionLabel sizeToFit];
|
||||
[self.fWhereSectionLabel sizeToFit];
|
||||
|
||||
NSArray* labels = @[
|
||||
fPiecesLabel,
|
||||
fHashLabel,
|
||||
fSecureLabel,
|
||||
fCreatorLabel,
|
||||
fDateCreatedLabel,
|
||||
fCommentLabel,
|
||||
fDataLocationLabel,
|
||||
self.fPiecesLabel,
|
||||
self.fHashLabel,
|
||||
self.fSecureLabel,
|
||||
self.fCreatorLabel,
|
||||
self.fDateCreatedLabel,
|
||||
self.fCommentLabel,
|
||||
self.fDataLocationLabel,
|
||||
];
|
||||
|
||||
CGFloat oldMaxWidth = 0.0, originX, newMaxWidth = 0.0;
|
||||
|
@ -66,13 +93,13 @@
|
|||
}
|
||||
|
||||
NSArray* fields = @[
|
||||
fPiecesField,
|
||||
fHashField,
|
||||
fSecureField,
|
||||
fCreatorField,
|
||||
fDateCreatedField,
|
||||
fCommentScrollView,
|
||||
fDataLocationField,
|
||||
self.fPiecesField,
|
||||
self.fHashField,
|
||||
self.fSecureField,
|
||||
self.fCreatorField,
|
||||
self.fDateCreatedField,
|
||||
self.fCommentScrollView,
|
||||
self.fDataLocationField,
|
||||
];
|
||||
|
||||
CGFloat const widthIncrease = newMaxWidth - oldMaxWidth;
|
||||
|
@ -88,35 +115,35 @@
|
|||
- (void)setInfoForTorrents:(NSArray*)torrents
|
||||
{
|
||||
//don't check if it's the same in case the metadata changed
|
||||
fTorrents = torrents;
|
||||
self.fTorrents = torrents;
|
||||
|
||||
fSet = NO;
|
||||
self.fSet = NO;
|
||||
}
|
||||
|
||||
- (void)updateInfo
|
||||
{
|
||||
if (!fSet)
|
||||
if (!self.fSet)
|
||||
{
|
||||
[self setupInfo];
|
||||
}
|
||||
|
||||
if (fTorrents.count != 1)
|
||||
if (self.fTorrents.count != 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Torrent* torrent = fTorrents[0];
|
||||
Torrent* torrent = self.fTorrents[0];
|
||||
|
||||
NSString* location = torrent.dataLocation;
|
||||
fDataLocationField.stringValue = location ? location.stringByAbbreviatingWithTildeInPath : @"";
|
||||
fDataLocationField.toolTip = location ? location : @"";
|
||||
self.fDataLocationField.stringValue = location ? location.stringByAbbreviatingWithTildeInPath : @"";
|
||||
self.fDataLocationField.toolTip = location ? location : @"";
|
||||
|
||||
fRevealDataButton.hidden = !location;
|
||||
self.fRevealDataButton.hidden = !location;
|
||||
}
|
||||
|
||||
- (void)revealDataFile:(id)sender
|
||||
{
|
||||
Torrent* torrent = fTorrents[0];
|
||||
Torrent* torrent = self.fTorrents[0];
|
||||
NSString* location = torrent.dataLocation;
|
||||
if (!location)
|
||||
{
|
||||
|
@ -127,50 +154,52 @@
|
|||
[NSWorkspace.sharedWorkspace activateFileViewerSelectingURLs:@[ file ]];
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
- (void)setupInfo
|
||||
{
|
||||
if (fTorrents.count == 1)
|
||||
if (self.fTorrents.count == 1)
|
||||
{
|
||||
Torrent* torrent = fTorrents[0];
|
||||
Torrent* torrent = self.fTorrents[0];
|
||||
|
||||
#warning candidate for localizedStringWithFormat (although then we'll get two commas)
|
||||
NSString* piecesString = !torrent.magnet ?
|
||||
[NSString stringWithFormat:@"%ld, %@", torrent.pieceCount, [NSString stringForFileSize:torrent.pieceSize]] :
|
||||
@"";
|
||||
fPiecesField.stringValue = piecesString;
|
||||
self.fPiecesField.stringValue = piecesString;
|
||||
|
||||
NSString* hashString = torrent.hashString;
|
||||
fHashField.stringValue = hashString;
|
||||
fHashField.toolTip = hashString;
|
||||
fSecureField.stringValue = torrent.privateTorrent ?
|
||||
self.fHashField.stringValue = hashString;
|
||||
self.fHashField.toolTip = hashString;
|
||||
self.fSecureField.stringValue = torrent.privateTorrent ?
|
||||
NSLocalizedString(@"Private Torrent, non-tracker peer discovery disabled", "Inspector -> private torrent") :
|
||||
NSLocalizedString(@"Public Torrent", "Inspector -> private torrent");
|
||||
|
||||
NSString* commentString = torrent.comment;
|
||||
fCommentView.string = commentString;
|
||||
self.fCommentView.string = commentString;
|
||||
|
||||
NSString* creatorString = torrent.creator;
|
||||
fCreatorField.stringValue = creatorString;
|
||||
fDateCreatedField.objectValue = torrent.dateCreated;
|
||||
self.fCreatorField.stringValue = creatorString;
|
||||
self.fDateCreatedField.objectValue = torrent.dateCreated;
|
||||
}
|
||||
else
|
||||
{
|
||||
fPiecesField.stringValue = @"";
|
||||
fHashField.stringValue = @"";
|
||||
fHashField.toolTip = nil;
|
||||
fSecureField.stringValue = @"";
|
||||
fCommentView.string = @"";
|
||||
self.fPiecesField.stringValue = @"";
|
||||
self.fHashField.stringValue = @"";
|
||||
self.fHashField.toolTip = nil;
|
||||
self.fSecureField.stringValue = @"";
|
||||
self.fCommentView.string = @"";
|
||||
|
||||
fCreatorField.stringValue = @"";
|
||||
fDateCreatedField.stringValue = @"";
|
||||
self.fCreatorField.stringValue = @"";
|
||||
self.fDateCreatedField.stringValue = @"";
|
||||
|
||||
fDataLocationField.stringValue = @"";
|
||||
fDataLocationField.toolTip = nil;
|
||||
self.fDataLocationField.stringValue = @"";
|
||||
self.fDataLocationField.toolTip = nil;
|
||||
|
||||
fRevealDataButton.hidden = YES;
|
||||
self.fRevealDataButton.hidden = YES;
|
||||
}
|
||||
|
||||
fSet = YES;
|
||||
self.fSet = YES;
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -7,42 +7,6 @@
|
|||
#import "InfoViewController.h"
|
||||
|
||||
@interface InfoOptionsViewController : NSViewController<InfoViewController>
|
||||
{
|
||||
NSArray* fTorrents;
|
||||
|
||||
BOOL fSet;
|
||||
|
||||
IBOutlet NSPopUpButton* fPriorityPopUp;
|
||||
IBOutlet NSPopUpButton* fRatioPopUp;
|
||||
IBOutlet NSPopUpButton* fIdlePopUp;
|
||||
IBOutlet NSButton* fUploadLimitCheck;
|
||||
IBOutlet NSButton* fDownloadLimitCheck;
|
||||
IBOutlet NSButton* fGlobalLimitCheck;
|
||||
IBOutlet NSButton* fRemoveSeedingCompleteCheck;
|
||||
IBOutlet NSTextField* fUploadLimitField;
|
||||
IBOutlet NSTextField* fDownloadLimitField;
|
||||
IBOutlet NSTextField* fRatioLimitField;
|
||||
IBOutlet NSTextField* fIdleLimitField;
|
||||
IBOutlet NSTextField* fUploadLimitLabel;
|
||||
IBOutlet NSTextField* fDownloadLimitLabel;
|
||||
IBOutlet NSTextField* fIdleLimitLabel;
|
||||
IBOutlet NSTextField* fRatioLimitGlobalLabel;
|
||||
IBOutlet NSTextField* fIdleLimitGlobalLabel;
|
||||
IBOutlet NSTextField* fPeersConnectLabel;
|
||||
IBOutlet NSTextField* fPeersConnectField;
|
||||
|
||||
//remove when we switch to auto layout on 10.7
|
||||
IBOutlet NSTextField* fTransferBandwidthSectionLabel;
|
||||
IBOutlet NSTextField* fPrioritySectionLabel;
|
||||
IBOutlet NSTextField* fPriorityLabel;
|
||||
IBOutlet NSTextField* fSeedingLimitsSectionLabel;
|
||||
IBOutlet NSTextField* fRatioLabel;
|
||||
IBOutlet NSTextField* fInactivityLabel;
|
||||
IBOutlet NSTextField* fAdvancedSectionLabel;
|
||||
IBOutlet NSTextField* fMaxConnectionsLabel;
|
||||
|
||||
NSString* fInitialString;
|
||||
}
|
||||
|
||||
- (void)setInfoForTorrents:(NSArray*)torrents;
|
||||
- (void)updateInfo;
|
||||
|
|
|
@ -16,7 +16,42 @@
|
|||
|
||||
#define INVALID -99
|
||||
|
||||
@interface InfoOptionsViewController (Private)
|
||||
@interface InfoOptionsViewController ()
|
||||
|
||||
@property(nonatomic, copy) NSArray* fTorrents;
|
||||
|
||||
@property(nonatomic) BOOL fSet;
|
||||
|
||||
@property(nonatomic) IBOutlet NSPopUpButton* fPriorityPopUp;
|
||||
@property(nonatomic) IBOutlet NSPopUpButton* fRatioPopUp;
|
||||
@property(nonatomic) IBOutlet NSPopUpButton* fIdlePopUp;
|
||||
@property(nonatomic) IBOutlet NSButton* fUploadLimitCheck;
|
||||
@property(nonatomic) IBOutlet NSButton* fDownloadLimitCheck;
|
||||
@property(nonatomic) IBOutlet NSButton* fGlobalLimitCheck;
|
||||
@property(nonatomic) IBOutlet NSButton* fRemoveSeedingCompleteCheck;
|
||||
@property(nonatomic) IBOutlet NSTextField* fUploadLimitField;
|
||||
@property(nonatomic) IBOutlet NSTextField* fDownloadLimitField;
|
||||
@property(nonatomic) IBOutlet NSTextField* fRatioLimitField;
|
||||
@property(nonatomic) IBOutlet NSTextField* fIdleLimitField;
|
||||
@property(nonatomic) IBOutlet NSTextField* fUploadLimitLabel;
|
||||
@property(nonatomic) IBOutlet NSTextField* fDownloadLimitLabel;
|
||||
@property(nonatomic) IBOutlet NSTextField* fIdleLimitLabel;
|
||||
@property(nonatomic) IBOutlet NSTextField* fRatioLimitGlobalLabel;
|
||||
@property(nonatomic) IBOutlet NSTextField* fIdleLimitGlobalLabel;
|
||||
@property(nonatomic) IBOutlet NSTextField* fPeersConnectLabel;
|
||||
@property(nonatomic) IBOutlet NSTextField* fPeersConnectField;
|
||||
|
||||
//remove when we switch to auto layout
|
||||
@property(nonatomic) IBOutlet NSTextField* fTransferBandwidthSectionLabel;
|
||||
@property(nonatomic) IBOutlet NSTextField* fPrioritySectionLabel;
|
||||
@property(nonatomic) IBOutlet NSTextField* fPriorityLabel;
|
||||
@property(nonatomic) IBOutlet NSTextField* fSeedingLimitsSectionLabel;
|
||||
@property(nonatomic) IBOutlet NSTextField* fRatioLabel;
|
||||
@property(nonatomic) IBOutlet NSTextField* fInactivityLabel;
|
||||
@property(nonatomic) IBOutlet NSTextField* fAdvancedSectionLabel;
|
||||
@property(nonatomic) IBOutlet NSTextField* fMaxConnectionsLabel;
|
||||
|
||||
@property(nonatomic, copy) NSString* fInitialString;
|
||||
|
||||
- (void)setupInfo;
|
||||
- (void)setGlobalLabels;
|
||||
|
@ -54,30 +89,30 @@
|
|||
- (void)setInfoForTorrents:(NSArray*)torrents
|
||||
{
|
||||
//don't check if it's the same in case the metadata changed
|
||||
fTorrents = torrents;
|
||||
self.fTorrents = torrents;
|
||||
|
||||
fSet = NO;
|
||||
self.fSet = NO;
|
||||
}
|
||||
|
||||
- (void)updateInfo
|
||||
{
|
||||
if (!fSet)
|
||||
if (!self.fSet)
|
||||
{
|
||||
[self setupInfo];
|
||||
}
|
||||
|
||||
fSet = YES;
|
||||
self.fSet = YES;
|
||||
}
|
||||
|
||||
- (void)updateOptions
|
||||
{
|
||||
if (fTorrents.count == 0)
|
||||
if (self.fTorrents.count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//get bandwidth info
|
||||
NSEnumerator* enumerator = [fTorrents objectEnumerator];
|
||||
NSEnumerator* enumerator = [self.fTorrents objectEnumerator];
|
||||
Torrent* torrent = [enumerator nextObject]; //first torrent
|
||||
|
||||
NSInteger uploadUseSpeedLimit = [torrent usesSpeedLimit:YES] ? NSControlStateValueOn : NSControlStateValueOff;
|
||||
|
@ -121,41 +156,41 @@
|
|||
}
|
||||
|
||||
//set upload view
|
||||
fUploadLimitCheck.state = uploadUseSpeedLimit;
|
||||
fUploadLimitCheck.enabled = YES;
|
||||
self.fUploadLimitCheck.state = uploadUseSpeedLimit;
|
||||
self.fUploadLimitCheck.enabled = YES;
|
||||
|
||||
fUploadLimitLabel.enabled = uploadUseSpeedLimit == NSControlStateValueOn;
|
||||
fUploadLimitField.enabled = uploadUseSpeedLimit == NSControlStateValueOn;
|
||||
self.fUploadLimitLabel.enabled = uploadUseSpeedLimit == NSControlStateValueOn;
|
||||
self.fUploadLimitField.enabled = uploadUseSpeedLimit == NSControlStateValueOn;
|
||||
if (uploadSpeedLimit != INVALID)
|
||||
{
|
||||
fUploadLimitField.intValue = uploadSpeedLimit;
|
||||
self.fUploadLimitField.intValue = uploadSpeedLimit;
|
||||
}
|
||||
else
|
||||
{
|
||||
fUploadLimitField.stringValue = @"";
|
||||
self.fUploadLimitField.stringValue = @"";
|
||||
}
|
||||
|
||||
//set download view
|
||||
fDownloadLimitCheck.state = downloadUseSpeedLimit;
|
||||
fDownloadLimitCheck.enabled = YES;
|
||||
self.fDownloadLimitCheck.state = downloadUseSpeedLimit;
|
||||
self.fDownloadLimitCheck.enabled = YES;
|
||||
|
||||
fDownloadLimitLabel.enabled = downloadUseSpeedLimit == NSControlStateValueOn;
|
||||
fDownloadLimitField.enabled = downloadUseSpeedLimit == NSControlStateValueOn;
|
||||
self.fDownloadLimitLabel.enabled = downloadUseSpeedLimit == NSControlStateValueOn;
|
||||
self.fDownloadLimitField.enabled = downloadUseSpeedLimit == NSControlStateValueOn;
|
||||
if (downloadSpeedLimit != INVALID)
|
||||
{
|
||||
fDownloadLimitField.intValue = downloadSpeedLimit;
|
||||
self.fDownloadLimitField.intValue = downloadSpeedLimit;
|
||||
}
|
||||
else
|
||||
{
|
||||
fDownloadLimitField.stringValue = @"";
|
||||
self.fDownloadLimitField.stringValue = @"";
|
||||
}
|
||||
|
||||
//set global check
|
||||
fGlobalLimitCheck.state = globalUseSpeedLimit;
|
||||
fGlobalLimitCheck.enabled = YES;
|
||||
self.fGlobalLimitCheck.state = globalUseSpeedLimit;
|
||||
self.fGlobalLimitCheck.enabled = YES;
|
||||
|
||||
//get ratio and idle info
|
||||
enumerator = [fTorrents objectEnumerator];
|
||||
enumerator = [self.fTorrents objectEnumerator];
|
||||
torrent = [enumerator nextObject]; //first torrent
|
||||
|
||||
NSInteger checkRatio = torrent.ratioSetting;
|
||||
|
@ -214,20 +249,20 @@
|
|||
{
|
||||
index = -1;
|
||||
}
|
||||
[fRatioPopUp selectItemAtIndex:index];
|
||||
fRatioPopUp.enabled = YES;
|
||||
[self.fRatioPopUp selectItemAtIndex:index];
|
||||
self.fRatioPopUp.enabled = YES;
|
||||
|
||||
fRatioLimitField.hidden = checkRatio != TR_RATIOLIMIT_SINGLE;
|
||||
self.fRatioLimitField.hidden = checkRatio != TR_RATIOLIMIT_SINGLE;
|
||||
if (ratioLimit != INVALID)
|
||||
{
|
||||
fRatioLimitField.floatValue = ratioLimit;
|
||||
self.fRatioLimitField.floatValue = ratioLimit;
|
||||
}
|
||||
else
|
||||
{
|
||||
fRatioLimitField.stringValue = @"";
|
||||
self.fRatioLimitField.stringValue = @"";
|
||||
}
|
||||
|
||||
fRatioLimitGlobalLabel.hidden = checkRatio != TR_RATIOLIMIT_GLOBAL;
|
||||
self.fRatioLimitGlobalLabel.hidden = checkRatio != TR_RATIOLIMIT_GLOBAL;
|
||||
|
||||
//set idle view
|
||||
if (checkIdle == TR_IDLELIMIT_SINGLE)
|
||||
|
@ -246,28 +281,28 @@
|
|||
{
|
||||
index = -1;
|
||||
}
|
||||
[fIdlePopUp selectItemAtIndex:index];
|
||||
fIdlePopUp.enabled = YES;
|
||||
[self.fIdlePopUp selectItemAtIndex:index];
|
||||
self.fIdlePopUp.enabled = YES;
|
||||
|
||||
fIdleLimitField.hidden = checkIdle != TR_IDLELIMIT_SINGLE;
|
||||
self.fIdleLimitField.hidden = checkIdle != TR_IDLELIMIT_SINGLE;
|
||||
if (idleLimit != INVALID)
|
||||
{
|
||||
fIdleLimitField.integerValue = idleLimit;
|
||||
self.fIdleLimitField.integerValue = idleLimit;
|
||||
}
|
||||
else
|
||||
{
|
||||
fIdleLimitField.stringValue = @"";
|
||||
self.fIdleLimitField.stringValue = @"";
|
||||
}
|
||||
fIdleLimitLabel.hidden = checkIdle != TR_IDLELIMIT_SINGLE;
|
||||
self.fIdleLimitLabel.hidden = checkIdle != TR_IDLELIMIT_SINGLE;
|
||||
|
||||
fIdleLimitGlobalLabel.hidden = checkIdle != TR_IDLELIMIT_GLOBAL;
|
||||
self.fIdleLimitGlobalLabel.hidden = checkIdle != TR_IDLELIMIT_GLOBAL;
|
||||
|
||||
//set remove transfer when seeding finishes
|
||||
fRemoveSeedingCompleteCheck.state = removeWhenFinishSeeding;
|
||||
fRemoveSeedingCompleteCheck.enabled = YES;
|
||||
self.fRemoveSeedingCompleteCheck.state = removeWhenFinishSeeding;
|
||||
self.fRemoveSeedingCompleteCheck.enabled = YES;
|
||||
|
||||
//get priority info
|
||||
enumerator = [fTorrents objectEnumerator];
|
||||
enumerator = [self.fTorrents objectEnumerator];
|
||||
torrent = [enumerator nextObject]; //first torrent
|
||||
|
||||
NSInteger priority = torrent.priority;
|
||||
|
@ -297,11 +332,11 @@
|
|||
{
|
||||
index = -1;
|
||||
}
|
||||
[fPriorityPopUp selectItemAtIndex:index];
|
||||
fPriorityPopUp.enabled = YES;
|
||||
[self.fPriorityPopUp selectItemAtIndex:index];
|
||||
self.fPriorityPopUp.enabled = YES;
|
||||
|
||||
//get peer info
|
||||
enumerator = [fTorrents objectEnumerator];
|
||||
enumerator = [self.fTorrents objectEnumerator];
|
||||
torrent = [enumerator nextObject]; //first torrent
|
||||
|
||||
NSInteger maxPeers = torrent.maxPeerConnect;
|
||||
|
@ -316,21 +351,21 @@
|
|||
}
|
||||
|
||||
//set peer view
|
||||
fPeersConnectField.enabled = YES;
|
||||
fPeersConnectLabel.enabled = YES;
|
||||
self.fPeersConnectField.enabled = YES;
|
||||
self.fPeersConnectLabel.enabled = YES;
|
||||
if (maxPeers != INVALID)
|
||||
{
|
||||
fPeersConnectField.intValue = maxPeers;
|
||||
self.fPeersConnectField.intValue = maxPeers;
|
||||
}
|
||||
else
|
||||
{
|
||||
fPeersConnectField.stringValue = @"";
|
||||
self.fPeersConnectField.stringValue = @"";
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setUseSpeedLimit:(id)sender
|
||||
{
|
||||
BOOL const upload = sender == fUploadLimitCheck;
|
||||
BOOL const upload = sender == self.fUploadLimitCheck;
|
||||
|
||||
if (((NSButton*)sender).state == NSControlStateValueMixed)
|
||||
{
|
||||
|
@ -338,12 +373,12 @@
|
|||
}
|
||||
BOOL const limit = ((NSButton*)sender).state == NSControlStateValueOn;
|
||||
|
||||
for (Torrent* torrent in fTorrents)
|
||||
for (Torrent* torrent in self.fTorrents)
|
||||
{
|
||||
[torrent setUseSpeedLimit:limit upload:upload];
|
||||
}
|
||||
|
||||
NSTextField* field = upload ? fUploadLimitField : fDownloadLimitField;
|
||||
NSTextField* field = upload ? self.fUploadLimitField : self.fDownloadLimitField;
|
||||
field.enabled = limit;
|
||||
if (limit)
|
||||
{
|
||||
|
@ -351,7 +386,7 @@
|
|||
[self.view.window makeKeyAndOrderFront:self];
|
||||
}
|
||||
|
||||
NSTextField* label = upload ? fUploadLimitLabel : fDownloadLimitLabel;
|
||||
NSTextField* label = upload ? self.fUploadLimitLabel : self.fDownloadLimitLabel;
|
||||
label.enabled = limit;
|
||||
|
||||
[NSNotificationCenter.defaultCenter postNotificationName:@"UpdateOptionsNotification" object:self];
|
||||
|
@ -365,7 +400,7 @@
|
|||
}
|
||||
BOOL const limit = ((NSButton*)sender).state == NSControlStateValueOn;
|
||||
|
||||
for (Torrent* torrent in fTorrents)
|
||||
for (Torrent* torrent in self.fTorrents)
|
||||
{
|
||||
torrent.usesGlobalSpeedLimit = limit;
|
||||
}
|
||||
|
@ -375,10 +410,10 @@
|
|||
|
||||
- (void)setSpeedLimit:(id)sender
|
||||
{
|
||||
BOOL const upload = sender == fUploadLimitField;
|
||||
BOOL const upload = sender == self.fUploadLimitField;
|
||||
NSInteger const limit = [sender intValue];
|
||||
|
||||
for (Torrent* torrent in fTorrents)
|
||||
for (Torrent* torrent in self.fTorrents)
|
||||
{
|
||||
[torrent setSpeedLimit:limit upload:upload];
|
||||
}
|
||||
|
@ -407,19 +442,19 @@
|
|||
return;
|
||||
}
|
||||
|
||||
for (Torrent* torrent in fTorrents)
|
||||
for (Torrent* torrent in self.fTorrents)
|
||||
{
|
||||
torrent.ratioSetting = static_cast<tr_ratiolimit>(setting);
|
||||
}
|
||||
|
||||
fRatioLimitField.hidden = !single;
|
||||
self.fRatioLimitField.hidden = !single;
|
||||
if (single)
|
||||
{
|
||||
[fRatioLimitField selectText:self];
|
||||
[self.fRatioLimitField selectText:self];
|
||||
[self.view.window makeKeyAndOrderFront:self];
|
||||
}
|
||||
|
||||
fRatioLimitGlobalLabel.hidden = setting != TR_RATIOLIMIT_GLOBAL;
|
||||
self.fRatioLimitGlobalLabel.hidden = setting != TR_RATIOLIMIT_GLOBAL;
|
||||
|
||||
[NSNotificationCenter.defaultCenter postNotificationName:@"UpdateOptionsNotification" object:self];
|
||||
}
|
||||
|
@ -428,7 +463,7 @@
|
|||
{
|
||||
CGFloat const limit = [sender floatValue];
|
||||
|
||||
for (Torrent* torrent in fTorrents)
|
||||
for (Torrent* torrent in self.fTorrents)
|
||||
{
|
||||
torrent.ratioLimit = limit;
|
||||
}
|
||||
|
@ -457,20 +492,20 @@
|
|||
return;
|
||||
}
|
||||
|
||||
for (Torrent* torrent in fTorrents)
|
||||
for (Torrent* torrent in self.fTorrents)
|
||||
{
|
||||
torrent.idleSetting = static_cast<tr_idlelimit>(setting);
|
||||
}
|
||||
|
||||
fIdleLimitField.hidden = !single;
|
||||
fIdleLimitLabel.hidden = !single;
|
||||
self.fIdleLimitField.hidden = !single;
|
||||
self.fIdleLimitLabel.hidden = !single;
|
||||
if (single)
|
||||
{
|
||||
[fIdleLimitField selectText:self];
|
||||
[self.fIdleLimitField selectText:self];
|
||||
[self.view.window makeKeyAndOrderFront:self];
|
||||
}
|
||||
|
||||
fIdleLimitGlobalLabel.hidden = setting != TR_IDLELIMIT_GLOBAL;
|
||||
self.fIdleLimitGlobalLabel.hidden = setting != TR_IDLELIMIT_GLOBAL;
|
||||
|
||||
[NSNotificationCenter.defaultCenter postNotificationName:@"UpdateOptionsNotification" object:self];
|
||||
}
|
||||
|
@ -479,7 +514,7 @@
|
|||
{
|
||||
NSUInteger const limit = [sender integerValue];
|
||||
|
||||
for (Torrent* torrent in fTorrents)
|
||||
for (Torrent* torrent in self.fTorrents)
|
||||
{
|
||||
torrent.idleLimitMinutes = limit;
|
||||
}
|
||||
|
@ -495,7 +530,7 @@
|
|||
}
|
||||
BOOL const enable = ((NSButton*)sender).state == NSControlStateValueOn;
|
||||
|
||||
for (Torrent* torrent in fTorrents)
|
||||
for (Torrent* torrent in self.fTorrents)
|
||||
{
|
||||
torrent.removeWhenFinishSeeding = enable;
|
||||
}
|
||||
|
@ -522,7 +557,7 @@
|
|||
return;
|
||||
}
|
||||
|
||||
for (Torrent* torrent in fTorrents)
|
||||
for (Torrent* torrent in self.fTorrents)
|
||||
{
|
||||
torrent.priority = priority;
|
||||
}
|
||||
|
@ -536,7 +571,7 @@
|
|||
{
|
||||
NSInteger limit = [sender intValue];
|
||||
|
||||
for (Torrent* torrent in fTorrents)
|
||||
for (Torrent* torrent in self.fTorrents)
|
||||
{
|
||||
torrent.maxPeerConnect = limit;
|
||||
}
|
||||
|
@ -546,7 +581,7 @@
|
|||
|
||||
- (BOOL)control:(NSControl*)control textShouldBeginEditing:(NSText*)fieldEditor
|
||||
{
|
||||
fInitialString = control.stringValue;
|
||||
self.fInitialString = control.stringValue;
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
@ -554,59 +589,57 @@
|
|||
- (BOOL)control:(NSControl*)control didFailToFormatString:(NSString*)string errorDescription:(NSString*)error
|
||||
{
|
||||
NSBeep();
|
||||
if (fInitialString)
|
||||
if (self.fInitialString)
|
||||
{
|
||||
control.stringValue = fInitialString;
|
||||
fInitialString = nil;
|
||||
control.stringValue = self.fInitialString;
|
||||
self.fInitialString = nil;
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation InfoOptionsViewController (Private)
|
||||
#pragma mark - Private
|
||||
|
||||
- (void)setupInfo
|
||||
{
|
||||
if (fTorrents.count == 0)
|
||||
if (self.fTorrents.count == 0)
|
||||
{
|
||||
fUploadLimitCheck.enabled = NO;
|
||||
fUploadLimitCheck.state = NSControlStateValueOff;
|
||||
fUploadLimitField.enabled = NO;
|
||||
fUploadLimitLabel.enabled = NO;
|
||||
fUploadLimitField.stringValue = @"";
|
||||
self.fUploadLimitCheck.enabled = NO;
|
||||
self.fUploadLimitCheck.state = NSControlStateValueOff;
|
||||
self.fUploadLimitField.enabled = NO;
|
||||
self.fUploadLimitLabel.enabled = NO;
|
||||
self.fUploadLimitField.stringValue = @"";
|
||||
|
||||
fDownloadLimitCheck.enabled = NO;
|
||||
fDownloadLimitCheck.state = NSControlStateValueOff;
|
||||
fDownloadLimitField.enabled = NO;
|
||||
fDownloadLimitLabel.enabled = NO;
|
||||
fDownloadLimitField.stringValue = @"";
|
||||
self.fDownloadLimitCheck.enabled = NO;
|
||||
self.fDownloadLimitCheck.state = NSControlStateValueOff;
|
||||
self.fDownloadLimitField.enabled = NO;
|
||||
self.fDownloadLimitLabel.enabled = NO;
|
||||
self.fDownloadLimitField.stringValue = @"";
|
||||
|
||||
fGlobalLimitCheck.enabled = NO;
|
||||
fGlobalLimitCheck.state = NSControlStateValueOff;
|
||||
self.fGlobalLimitCheck.enabled = NO;
|
||||
self.fGlobalLimitCheck.state = NSControlStateValueOff;
|
||||
|
||||
fPriorityPopUp.enabled = NO;
|
||||
[fPriorityPopUp selectItemAtIndex:-1];
|
||||
self.fPriorityPopUp.enabled = NO;
|
||||
[self.fPriorityPopUp selectItemAtIndex:-1];
|
||||
|
||||
fRatioPopUp.enabled = NO;
|
||||
[fRatioPopUp selectItemAtIndex:-1];
|
||||
fRatioLimitField.hidden = YES;
|
||||
fRatioLimitField.stringValue = @"";
|
||||
fRatioLimitGlobalLabel.hidden = YES;
|
||||
self.fRatioPopUp.enabled = NO;
|
||||
[self.fRatioPopUp selectItemAtIndex:-1];
|
||||
self.fRatioLimitField.hidden = YES;
|
||||
self.fRatioLimitField.stringValue = @"";
|
||||
self.fRatioLimitGlobalLabel.hidden = YES;
|
||||
|
||||
fIdlePopUp.enabled = NO;
|
||||
[fIdlePopUp selectItemAtIndex:-1];
|
||||
fIdleLimitField.hidden = YES;
|
||||
fIdleLimitField.stringValue = @"";
|
||||
fIdleLimitLabel.hidden = YES;
|
||||
fIdleLimitGlobalLabel.hidden = YES;
|
||||
self.fIdlePopUp.enabled = NO;
|
||||
[self.fIdlePopUp selectItemAtIndex:-1];
|
||||
self.fIdleLimitField.hidden = YES;
|
||||
self.fIdleLimitField.stringValue = @"";
|
||||
self.fIdleLimitLabel.hidden = YES;
|
||||
self.fIdleLimitGlobalLabel.hidden = YES;
|
||||
|
||||
fRemoveSeedingCompleteCheck.enabled = NO;
|
||||
fRemoveSeedingCompleteCheck.state = NSControlStateValueOff;
|
||||
self.fRemoveSeedingCompleteCheck.enabled = NO;
|
||||
self.fRemoveSeedingCompleteCheck.state = NSControlStateValueOff;
|
||||
|
||||
fPeersConnectField.enabled = NO;
|
||||
fPeersConnectField.stringValue = @"";
|
||||
fPeersConnectLabel.enabled = NO;
|
||||
self.fPeersConnectField.enabled = NO;
|
||||
self.fPeersConnectField.stringValue = @"";
|
||||
self.fPeersConnectLabel.enabled = NO;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -619,7 +652,7 @@
|
|||
NSString* global = [NSUserDefaults.standardUserDefaults boolForKey:@"RatioCheck"] ?
|
||||
[NSString stringForRatio:[NSUserDefaults.standardUserDefaults floatForKey:@"RatioLimit"]] :
|
||||
NSLocalizedString(@"disabled", "Info options -> global setting");
|
||||
fRatioLimitGlobalLabel.stringValue = global;
|
||||
self.fRatioLimitGlobalLabel.stringValue = global;
|
||||
|
||||
//idle field
|
||||
NSString* globalIdle;
|
||||
|
@ -634,7 +667,7 @@
|
|||
{
|
||||
globalIdle = NSLocalizedString(@"disabled", "Info options -> global setting");
|
||||
}
|
||||
fIdleLimitGlobalLabel.stringValue = globalIdle;
|
||||
self.fIdleLimitGlobalLabel.stringValue = globalIdle;
|
||||
}
|
||||
|
||||
- (void)updateOptionsNotification:(NSNotification*)notification
|
||||
|
|
|
@ -6,25 +6,7 @@
|
|||
|
||||
#import "InfoViewController.h"
|
||||
|
||||
@class WebSeedTableView;
|
||||
|
||||
@interface InfoPeersViewController : NSViewController<InfoViewController>
|
||||
{
|
||||
NSArray* fTorrents;
|
||||
|
||||
BOOL fSet;
|
||||
|
||||
NSMutableArray* fPeers;
|
||||
NSMutableArray* fWebSeeds;
|
||||
|
||||
IBOutlet NSTableView* fPeerTable;
|
||||
IBOutlet WebSeedTableView* fWebSeedTable;
|
||||
|
||||
IBOutlet NSTextField* fConnectedPeersField;
|
||||
|
||||
CGFloat fViewTopMargin;
|
||||
IBOutlet NSLayoutConstraint* fWebSeedTableTopConstraint;
|
||||
}
|
||||
|
||||
- (void)setInfoForTorrents:(NSArray*)torrents;
|
||||
- (void)updateInfo;
|
||||
|
|
|
@ -15,12 +15,27 @@
|
|||
#define ANIMATION_ID_KEY @"animationId"
|
||||
#define WEB_SEED_ANIMATION_ID @"webSeed"
|
||||
|
||||
@interface InfoPeersViewController ()<CAAnimationDelegate>
|
||||
@interface InfoPeersViewController () <CAAnimationDelegate>
|
||||
|
||||
@property(nonatomic, copy) NSArray* fTorrents;
|
||||
|
||||
@property(nonatomic) BOOL fSet;
|
||||
|
||||
@property(nonatomic) NSMutableArray* fPeers;
|
||||
@property(nonatomic) NSMutableArray* fWebSeeds;
|
||||
|
||||
@property(nonatomic) IBOutlet NSTableView* fPeerTable;
|
||||
@property(nonatomic) IBOutlet WebSeedTableView* fWebSeedTable;
|
||||
|
||||
@property(nonatomic) IBOutlet NSTextField* fConnectedPeersField;
|
||||
|
||||
@property(nonatomic) CGFloat fViewTopMargin;
|
||||
@property(nonatomic) IBOutlet NSLayoutConstraint* fWebSeedTableTopConstraint;
|
||||
@property(nonatomic, readonly) NSArray* peerSortDescriptors;
|
||||
|
||||
- (void)setupInfo;
|
||||
|
||||
- (void)setWebSeedTableHidden:(BOOL)hide animate:(BOOL)animate;
|
||||
@property(nonatomic, readonly) NSArray* peerSortDescriptors;
|
||||
|
||||
@end
|
||||
|
||||
|
@ -47,33 +62,33 @@
|
|||
}
|
||||
|
||||
//set table header text
|
||||
[fPeerTable tableColumnWithIdentifier:@"IP"].headerCell.stringValue = NSLocalizedString(@"IP Address", "inspector -> peer table -> header");
|
||||
[fPeerTable tableColumnWithIdentifier:@"Client"].headerCell.stringValue = NSLocalizedString(@"Client", "inspector -> peer table -> header");
|
||||
[fPeerTable tableColumnWithIdentifier:@"DL From"].headerCell.stringValue = NSLocalizedString(@"DL", "inspector -> peer table -> header");
|
||||
[fPeerTable tableColumnWithIdentifier:@"UL To"].headerCell.stringValue = NSLocalizedString(@"UL", "inspector -> peer table -> header");
|
||||
[self.fPeerTable tableColumnWithIdentifier:@"IP"].headerCell.stringValue = NSLocalizedString(@"IP Address", "inspector -> peer table -> header");
|
||||
[self.fPeerTable tableColumnWithIdentifier:@"Client"].headerCell.stringValue = NSLocalizedString(@"Client", "inspector -> peer table -> header");
|
||||
[self.fPeerTable tableColumnWithIdentifier:@"DL From"].headerCell.stringValue = NSLocalizedString(@"DL", "inspector -> peer table -> header");
|
||||
[self.fPeerTable tableColumnWithIdentifier:@"UL To"].headerCell.stringValue = NSLocalizedString(@"UL", "inspector -> peer table -> header");
|
||||
|
||||
[fWebSeedTable tableColumnWithIdentifier:@"Address"].headerCell.stringValue = NSLocalizedString(@"Web Seeds", "inspector -> web seed table -> header");
|
||||
[fWebSeedTable tableColumnWithIdentifier:@"DL From"].headerCell.stringValue = NSLocalizedString(@"DL", "inspector -> web seed table -> header");
|
||||
[self.fWebSeedTable tableColumnWithIdentifier:@"Address"].headerCell.stringValue = NSLocalizedString(@"Web Seeds", "inspector -> web seed table -> header");
|
||||
[self.fWebSeedTable tableColumnWithIdentifier:@"DL From"].headerCell.stringValue = NSLocalizedString(@"DL", "inspector -> web seed table -> header");
|
||||
|
||||
//set table header tool tips
|
||||
[fPeerTable tableColumnWithIdentifier:@"Encryption"].headerToolTip = NSLocalizedString(@"Encrypted Connection", "inspector -> peer table -> header tool tip");
|
||||
[fPeerTable tableColumnWithIdentifier:@"Progress"].headerToolTip = NSLocalizedString(@"Available", "inspector -> peer table -> header tool tip");
|
||||
[fPeerTable tableColumnWithIdentifier:@"DL From"].headerToolTip = NSLocalizedString(@"Downloading From Peer", "inspector -> peer table -> header tool tip");
|
||||
[fPeerTable tableColumnWithIdentifier:@"UL To"].headerToolTip = NSLocalizedString(@"Uploading To Peer", "inspector -> peer table -> header tool tip");
|
||||
[self.fPeerTable tableColumnWithIdentifier:@"Encryption"].headerToolTip = NSLocalizedString(@"Encrypted Connection", "inspector -> peer table -> header tool tip");
|
||||
[self.fPeerTable tableColumnWithIdentifier:@"Progress"].headerToolTip = NSLocalizedString(@"Available", "inspector -> peer table -> header tool tip");
|
||||
[self.fPeerTable tableColumnWithIdentifier:@"DL From"].headerToolTip = NSLocalizedString(@"Downloading From Peer", "inspector -> peer table -> header tool tip");
|
||||
[self.fPeerTable tableColumnWithIdentifier:@"UL To"].headerToolTip = NSLocalizedString(@"Uploading To Peer", "inspector -> peer table -> header tool tip");
|
||||
|
||||
[fWebSeedTable tableColumnWithIdentifier:@"DL From"].headerToolTip = NSLocalizedString(
|
||||
[self.fWebSeedTable tableColumnWithIdentifier:@"DL From"].headerToolTip = NSLocalizedString(
|
||||
@"Downloading From Web Seed",
|
||||
"inspector -> web seed table -> header tool tip");
|
||||
|
||||
//prepare for animating peer table and web seed table
|
||||
fViewTopMargin = fWebSeedTableTopConstraint.constant;
|
||||
self.fViewTopMargin = self.fWebSeedTableTopConstraint.constant;
|
||||
|
||||
CABasicAnimation* webSeedTableAnimation = [CABasicAnimation animation];
|
||||
webSeedTableAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
|
||||
webSeedTableAnimation.duration = 0.125;
|
||||
webSeedTableAnimation.delegate = self;
|
||||
[webSeedTableAnimation setValue:WEB_SEED_ANIMATION_ID forKey:ANIMATION_ID_KEY];
|
||||
fWebSeedTableTopConstraint.animations = @{ @"constant" : webSeedTableAnimation };
|
||||
self.fWebSeedTableTopConstraint.animations = @{ @"constant" : webSeedTableAnimation };
|
||||
|
||||
[self setWebSeedTableHidden:YES animate:NO];
|
||||
}
|
||||
|
@ -82,39 +97,39 @@
|
|||
- (void)setInfoForTorrents:(NSArray*)torrents
|
||||
{
|
||||
//don't check if it's the same in case the metadata changed
|
||||
fTorrents = torrents;
|
||||
self.fTorrents = torrents;
|
||||
|
||||
fSet = NO;
|
||||
self.fSet = NO;
|
||||
}
|
||||
|
||||
- (void)updateInfo
|
||||
{
|
||||
if (!fSet)
|
||||
if (!self.fSet)
|
||||
{
|
||||
[self setupInfo];
|
||||
}
|
||||
|
||||
if (fTorrents.count == 0)
|
||||
if (self.fTorrents.count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!fPeers)
|
||||
if (!self.fPeers)
|
||||
{
|
||||
fPeers = [[NSMutableArray alloc] init];
|
||||
self.fPeers = [[NSMutableArray alloc] init];
|
||||
}
|
||||
else
|
||||
{
|
||||
[fPeers removeAllObjects];
|
||||
[self.fPeers removeAllObjects];
|
||||
}
|
||||
|
||||
if (!fWebSeeds)
|
||||
if (!self.fWebSeeds)
|
||||
{
|
||||
fWebSeeds = [[NSMutableArray alloc] init];
|
||||
self.fWebSeeds = [[NSMutableArray alloc] init];
|
||||
}
|
||||
else
|
||||
{
|
||||
[fWebSeeds removeAllObjects];
|
||||
[self.fWebSeeds removeAllObjects];
|
||||
}
|
||||
|
||||
NSUInteger connected = 0;
|
||||
|
@ -128,17 +143,17 @@
|
|||
NSUInteger toUs = 0;
|
||||
NSUInteger fromUs = 0;
|
||||
BOOL anyActive = false;
|
||||
for (Torrent* torrent in fTorrents)
|
||||
for (Torrent* torrent in self.fTorrents)
|
||||
{
|
||||
if (torrent.webSeedCount > 0)
|
||||
{
|
||||
[fWebSeeds addObjectsFromArray:torrent.webSeeds];
|
||||
[self.fWebSeeds addObjectsFromArray:torrent.webSeeds];
|
||||
}
|
||||
|
||||
if (torrent.active)
|
||||
{
|
||||
anyActive = YES;
|
||||
[fPeers addObjectsFromArray:torrent.peers];
|
||||
[self.fPeers addObjectsFromArray:torrent.peers];
|
||||
|
||||
NSUInteger const connectedThis = torrent.totalPeersConnected;
|
||||
if (connectedThis > 0)
|
||||
|
@ -158,12 +173,12 @@
|
|||
}
|
||||
}
|
||||
|
||||
[fPeers sortUsingDescriptors:self.peerSortDescriptors];
|
||||
[fPeerTable reloadData];
|
||||
[self.fPeers sortUsingDescriptors:self.peerSortDescriptors];
|
||||
[self.fPeerTable reloadData];
|
||||
|
||||
[fWebSeeds sortUsingDescriptors:fWebSeedTable.sortDescriptors];
|
||||
[fWebSeedTable reloadData];
|
||||
[fWebSeedTable setWebSeeds:fWebSeeds];
|
||||
[self.fWebSeeds sortUsingDescriptors:self.fWebSeedTable.sortDescriptors];
|
||||
[self.fWebSeedTable reloadData];
|
||||
self.fWebSeedTable.webSeeds = self.fWebSeeds;
|
||||
|
||||
if (anyActive)
|
||||
{
|
||||
|
@ -225,12 +240,12 @@
|
|||
connectedText = [connectedText stringByAppendingFormat:@"\n%@", [fromComponents componentsJoinedByString:@", "]];
|
||||
}
|
||||
|
||||
fConnectedPeersField.stringValue = connectedText;
|
||||
self.fConnectedPeersField.stringValue = connectedText;
|
||||
}
|
||||
else
|
||||
{
|
||||
NSString* notActiveString;
|
||||
if (fTorrents.count == 1)
|
||||
if (self.fTorrents.count == 1)
|
||||
{
|
||||
notActiveString = NSLocalizedString(@"Transfer Not Active", "Inspector -> Peers tab -> peers");
|
||||
}
|
||||
|
@ -239,7 +254,7 @@
|
|||
notActiveString = NSLocalizedString(@"Transfers Not Active", "Inspector -> Peers tab -> peers");
|
||||
}
|
||||
|
||||
fConnectedPeersField.stringValue = notActiveString;
|
||||
self.fConnectedPeersField.stringValue = notActiveString;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -250,28 +265,28 @@
|
|||
|
||||
- (void)clearView
|
||||
{
|
||||
fPeers = nil;
|
||||
fWebSeeds = nil;
|
||||
self.fPeers = nil;
|
||||
self.fWebSeeds = nil;
|
||||
}
|
||||
|
||||
- (NSInteger)numberOfRowsInTableView:(NSTableView*)tableView
|
||||
{
|
||||
if (tableView == fWebSeedTable)
|
||||
if (tableView == self.fWebSeedTable)
|
||||
{
|
||||
return fWebSeeds ? fWebSeeds.count : 0;
|
||||
return self.fWebSeeds ? self.fWebSeeds.count : 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return fPeers ? fPeers.count : 0;
|
||||
return self.fPeers ? self.fPeers.count : 0;
|
||||
}
|
||||
}
|
||||
|
||||
- (id)tableView:(NSTableView*)tableView objectValueForTableColumn:(NSTableColumn*)column row:(NSInteger)row
|
||||
{
|
||||
if (tableView == fWebSeedTable)
|
||||
if (tableView == self.fWebSeedTable)
|
||||
{
|
||||
NSString* ident = column.identifier;
|
||||
NSDictionary* webSeed = fWebSeeds[row];
|
||||
NSDictionary* webSeed = self.fWebSeeds[row];
|
||||
|
||||
if ([ident isEqualToString:@"DL From"])
|
||||
{
|
||||
|
@ -286,7 +301,7 @@
|
|||
else
|
||||
{
|
||||
NSString* ident = column.identifier;
|
||||
NSDictionary* peer = fPeers[row];
|
||||
NSDictionary* peer = self.fPeers[row];
|
||||
|
||||
if ([ident isEqualToString:@"Encryption"])
|
||||
{
|
||||
|
@ -319,33 +334,33 @@
|
|||
|
||||
- (void)tableView:(NSTableView*)tableView willDisplayCell:(id)cell forTableColumn:(NSTableColumn*)tableColumn row:(NSInteger)row
|
||||
{
|
||||
if (tableView == fPeerTable)
|
||||
if (tableView == self.fPeerTable)
|
||||
{
|
||||
NSString* ident = tableColumn.identifier;
|
||||
|
||||
if ([ident isEqualToString:@"Progress"])
|
||||
{
|
||||
NSDictionary* peer = fPeers[row];
|
||||
[(PeerProgressIndicatorCell*)cell setSeed:[peer[@"Seed"] boolValue]];
|
||||
NSDictionary* peer = self.fPeers[row];
|
||||
((PeerProgressIndicatorCell*)cell).seed = [peer[@"Seed"] boolValue];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)tableView:(NSTableView*)tableView didClickTableColumn:(NSTableColumn*)tableColumn
|
||||
{
|
||||
if (tableView == fWebSeedTable)
|
||||
if (tableView == self.fWebSeedTable)
|
||||
{
|
||||
if (fWebSeeds)
|
||||
if (self.fWebSeeds)
|
||||
{
|
||||
[fWebSeeds sortUsingDescriptors:fWebSeedTable.sortDescriptors];
|
||||
[self.fWebSeeds sortUsingDescriptors:self.fWebSeedTable.sortDescriptors];
|
||||
[tableView reloadData];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fPeers)
|
||||
if (self.fPeers)
|
||||
{
|
||||
[fPeers sortUsingDescriptors:self.peerSortDescriptors];
|
||||
[self.fPeers sortUsingDescriptors:self.peerSortDescriptors];
|
||||
[tableView reloadData];
|
||||
}
|
||||
}
|
||||
|
@ -353,7 +368,7 @@
|
|||
|
||||
- (BOOL)tableView:(NSTableView*)tableView shouldSelectRow:(NSInteger)row
|
||||
{
|
||||
return tableView != fPeerTable;
|
||||
return tableView != self.fPeerTable;
|
||||
}
|
||||
|
||||
- (NSString*)tableView:(NSTableView*)tableView
|
||||
|
@ -363,11 +378,11 @@
|
|||
row:(NSInteger)row
|
||||
mouseLocation:(NSPoint)mouseLocation
|
||||
{
|
||||
if (tableView == fPeerTable)
|
||||
if (tableView == self.fPeerTable)
|
||||
{
|
||||
BOOL const multiple = fTorrents.count > 1;
|
||||
BOOL const multiple = self.fTorrents.count > 1;
|
||||
|
||||
NSDictionary* peer = fPeers[row];
|
||||
NSDictionary* peer = self.fPeers[row];
|
||||
NSMutableArray* components = [NSMutableArray arrayWithCapacity:multiple ? 6 : 5];
|
||||
|
||||
if (multiple)
|
||||
|
@ -477,9 +492,9 @@
|
|||
}
|
||||
else
|
||||
{
|
||||
if (fTorrents.count > 1)
|
||||
if (self.fTorrents.count > 1)
|
||||
{
|
||||
return fWebSeeds[row][@"Name"];
|
||||
return self.fWebSeeds[row][@"Name"];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -493,7 +508,7 @@
|
|||
return;
|
||||
}
|
||||
|
||||
fWebSeedTable.enclosingScrollView.hidden = NO;
|
||||
self.fWebSeedTable.enclosingScrollView.hidden = NO;
|
||||
}
|
||||
|
||||
- (void)animationDidStop:(CAAnimation*)animation finished:(BOOL)finished
|
||||
|
@ -503,23 +518,25 @@
|
|||
return;
|
||||
}
|
||||
|
||||
fWebSeedTable.enclosingScrollView.hidden = finished && fWebSeedTableTopConstraint.constant < 0;
|
||||
self.fWebSeedTable.enclosingScrollView.hidden = finished && self.fWebSeedTableTopConstraint.constant < 0;
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
- (void)setupInfo
|
||||
{
|
||||
__block BOOL hasWebSeeds = NO;
|
||||
|
||||
if (fTorrents.count == 0)
|
||||
if (self.fTorrents.count == 0)
|
||||
{
|
||||
fPeers = nil;
|
||||
[fPeerTable reloadData];
|
||||
self.fPeers = nil;
|
||||
[self.fPeerTable reloadData];
|
||||
|
||||
fConnectedPeersField.stringValue = @"";
|
||||
self.fConnectedPeersField.stringValue = @"";
|
||||
}
|
||||
else
|
||||
{
|
||||
[fTorrents enumerateObjectsWithOptions:NSEnumerationConcurrent usingBlock:^(Torrent* torrent, NSUInteger idx, BOOL* stop) {
|
||||
[self.fTorrents enumerateObjectsWithOptions:NSEnumerationConcurrent usingBlock:^(Torrent* torrent, NSUInteger idx, BOOL* stop) {
|
||||
if (torrent.webSeedCount > 0)
|
||||
{
|
||||
hasWebSeeds = YES;
|
||||
|
@ -530,16 +547,16 @@
|
|||
|
||||
if (!hasWebSeeds)
|
||||
{
|
||||
fWebSeeds = nil;
|
||||
[fWebSeedTable reloadData];
|
||||
self.fWebSeeds = nil;
|
||||
[self.fWebSeedTable reloadData];
|
||||
}
|
||||
else
|
||||
{
|
||||
[fWebSeedTable deselectAll:self];
|
||||
[self.fWebSeedTable deselectAll:self];
|
||||
}
|
||||
[self setWebSeedTableHidden:!hasWebSeeds animate:YES];
|
||||
|
||||
fSet = YES;
|
||||
self.fSet = YES;
|
||||
}
|
||||
|
||||
- (void)setWebSeedTableHidden:(BOOL)hide animate:(BOOL)animate
|
||||
|
@ -549,16 +566,16 @@
|
|||
animate = NO;
|
||||
}
|
||||
|
||||
CGFloat const webSeedTableTopMargin = hide ? -NSHeight(fWebSeedTable.enclosingScrollView.frame) : fViewTopMargin;
|
||||
CGFloat const webSeedTableTopMargin = hide ? -NSHeight(self.fWebSeedTable.enclosingScrollView.frame) : self.fViewTopMargin;
|
||||
|
||||
(animate ? [fWebSeedTableTopConstraint animator] : fWebSeedTableTopConstraint).constant = webSeedTableTopMargin;
|
||||
(animate ? [self.fWebSeedTableTopConstraint animator] : self.fWebSeedTableTopConstraint).constant = webSeedTableTopMargin;
|
||||
}
|
||||
|
||||
- (NSArray*)peerSortDescriptors
|
||||
{
|
||||
NSMutableArray* descriptors = [NSMutableArray arrayWithCapacity:2];
|
||||
|
||||
NSArray* oldDescriptors = fPeerTable.sortDescriptors;
|
||||
NSArray* oldDescriptors = self.fPeerTable.sortDescriptors;
|
||||
BOOL useSecond = YES, asc = YES;
|
||||
if (oldDescriptors.count > 0)
|
||||
{
|
||||
|
|
|
@ -6,23 +6,7 @@
|
|||
|
||||
#import "InfoViewController.h"
|
||||
|
||||
@class Torrent;
|
||||
@class TrackerTableView;
|
||||
@class TrackerCell;
|
||||
|
||||
@interface InfoTrackersViewController : NSViewController<InfoViewController>
|
||||
{
|
||||
NSArray* fTorrents;
|
||||
|
||||
BOOL fSet;
|
||||
|
||||
NSMutableArray* fTrackers;
|
||||
|
||||
IBOutlet TrackerTableView* fTrackerTable;
|
||||
TrackerCell* fTrackerCell;
|
||||
|
||||
IBOutlet NSSegmentedControl* fTrackerAddRemoveControl;
|
||||
}
|
||||
|
||||
- (void)setInfoForTorrents:(NSArray*)torrents;
|
||||
- (void)updateInfo;
|
||||
|
|
|
@ -16,6 +16,17 @@
|
|||
|
||||
@interface InfoTrackersViewController ()
|
||||
|
||||
@property(nonatomic, copy) NSArray* fTorrents;
|
||||
|
||||
@property(nonatomic) BOOL fSet;
|
||||
|
||||
@property(nonatomic) NSMutableArray* fTrackers;
|
||||
|
||||
@property(nonatomic) IBOutlet TrackerTableView* fTrackerTable;
|
||||
@property(nonatomic, readonly) TrackerCell* fTrackerCell;
|
||||
|
||||
@property(nonatomic) IBOutlet NSSegmentedControl* fTrackerAddRemoveControl;
|
||||
|
||||
- (void)setupInfo;
|
||||
|
||||
- (void)addTrackers;
|
||||
|
@ -31,7 +42,7 @@
|
|||
{
|
||||
self.title = NSLocalizedString(@"Trackers", "Inspector view -> title");
|
||||
|
||||
fTrackerCell = [[TrackerCell alloc] init];
|
||||
_fTrackerCell = [[TrackerCell alloc] init];
|
||||
}
|
||||
|
||||
return self;
|
||||
|
@ -39,9 +50,9 @@
|
|||
|
||||
- (void)awakeFromNib
|
||||
{
|
||||
[fTrackerAddRemoveControl.cell setToolTip:NSLocalizedString(@"Add a tracker", "Inspector view -> tracker buttons")
|
||||
[self.fTrackerAddRemoveControl.cell setToolTip:NSLocalizedString(@"Add a tracker", "Inspector view -> tracker buttons")
|
||||
forSegment:TRACKER_ADD_TAG];
|
||||
[fTrackerAddRemoveControl.cell setToolTip:NSLocalizedString(@"Remove selected trackers", "Inspector view -> tracker buttons")
|
||||
[self.fTrackerAddRemoveControl.cell setToolTip:NSLocalizedString(@"Remove selected trackers", "Inspector view -> tracker buttons")
|
||||
forSegment:TRACKER_REMOVE_TAG];
|
||||
|
||||
CGFloat const height = [NSUserDefaults.standardUserDefaults floatForKey:@"InspectorContentHeightTracker"];
|
||||
|
@ -56,67 +67,67 @@
|
|||
- (void)setInfoForTorrents:(NSArray*)torrents
|
||||
{
|
||||
//don't check if it's the same in case the metadata changed
|
||||
fTorrents = torrents;
|
||||
self.fTorrents = torrents;
|
||||
|
||||
fSet = NO;
|
||||
self.fSet = NO;
|
||||
}
|
||||
|
||||
- (void)updateInfo
|
||||
{
|
||||
if (!fSet)
|
||||
if (!self.fSet)
|
||||
{
|
||||
[self setupInfo];
|
||||
}
|
||||
|
||||
if (fTorrents.count == 0)
|
||||
if (self.fTorrents.count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//get updated tracker stats
|
||||
if (fTrackerTable.editedRow == -1)
|
||||
if (self.fTrackerTable.editedRow == -1)
|
||||
{
|
||||
NSArray* oldTrackers = fTrackers;
|
||||
NSArray* oldTrackers = self.fTrackers;
|
||||
|
||||
if (fTorrents.count == 1)
|
||||
if (self.fTorrents.count == 1)
|
||||
{
|
||||
fTrackers = ((Torrent*)fTorrents[0]).allTrackerStats;
|
||||
self.fTrackers = ((Torrent*)self.fTorrents[0]).allTrackerStats;
|
||||
}
|
||||
else
|
||||
{
|
||||
fTrackers = [[NSMutableArray alloc] init];
|
||||
for (Torrent* torrent in fTorrents)
|
||||
self.fTrackers = [[NSMutableArray alloc] init];
|
||||
for (Torrent* torrent in self.fTorrents)
|
||||
{
|
||||
[fTrackers addObjectsFromArray:torrent.allTrackerStats];
|
||||
[self.fTrackers addObjectsFromArray:torrent.allTrackerStats];
|
||||
}
|
||||
}
|
||||
|
||||
[fTrackerTable setTrackers:fTrackers];
|
||||
self.fTrackerTable.trackers = self.fTrackers;
|
||||
|
||||
if (oldTrackers && [fTrackers isEqualToArray:oldTrackers])
|
||||
if (oldTrackers && [self.fTrackers isEqualToArray:oldTrackers])
|
||||
{
|
||||
fTrackerTable.needsDisplay = YES;
|
||||
self.fTrackerTable.needsDisplay = YES;
|
||||
}
|
||||
else
|
||||
{
|
||||
[fTrackerTable reloadData];
|
||||
[self.fTrackerTable reloadData];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NSAssert1(fTorrents.count == 1, @"Attempting to add tracker with %ld transfers selected", fTorrents.count);
|
||||
NSAssert1(self.fTorrents.count == 1, @"Attempting to add tracker with %ld transfers selected", self.fTorrents.count);
|
||||
|
||||
NSIndexSet* addedIndexes = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(fTrackers.count - 2, 2)];
|
||||
NSArray* tierAndTrackerBeingAdded = [fTrackers objectsAtIndexes:addedIndexes];
|
||||
NSIndexSet* addedIndexes = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(self.fTrackers.count - 2, 2)];
|
||||
NSArray* tierAndTrackerBeingAdded = [self.fTrackers objectsAtIndexes:addedIndexes];
|
||||
|
||||
fTrackers = ((Torrent*)fTorrents[0]).allTrackerStats;
|
||||
[fTrackers addObjectsFromArray:tierAndTrackerBeingAdded];
|
||||
self.fTrackers = ((Torrent*)self.fTorrents[0]).allTrackerStats;
|
||||
[self.fTrackers addObjectsFromArray:tierAndTrackerBeingAdded];
|
||||
|
||||
[fTrackerTable setTrackers:fTrackers];
|
||||
self.fTrackerTable.trackers = self.fTrackers;
|
||||
|
||||
NSIndexSet *updateIndexes = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, fTrackers.count - 2)],
|
||||
*columnIndexes = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, fTrackerTable.tableColumns.count)];
|
||||
[fTrackerTable reloadDataForRowIndexes:updateIndexes columnIndexes:columnIndexes];
|
||||
NSIndexSet *updateIndexes = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, self.fTrackers.count - 2)],
|
||||
*columnIndexes = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, self.fTrackerTable.tableColumns.count)];
|
||||
[self.fTrackerTable reloadDataForRowIndexes:updateIndexes columnIndexes:columnIndexes];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -127,17 +138,17 @@
|
|||
|
||||
- (void)clearView
|
||||
{
|
||||
fTrackers = nil;
|
||||
self.fTrackers = nil;
|
||||
}
|
||||
|
||||
- (NSInteger)numberOfRowsInTableView:(NSTableView*)tableView
|
||||
{
|
||||
return fTrackers ? fTrackers.count : 0;
|
||||
return self.fTrackers ? self.fTrackers.count : 0;
|
||||
}
|
||||
|
||||
- (id)tableView:(NSTableView*)tableView objectValueForTableColumn:(NSTableColumn*)column row:(NSInteger)row
|
||||
{
|
||||
id item = fTrackers[row];
|
||||
id item = self.fTrackers[row];
|
||||
|
||||
if ([item isKindOfClass:[NSDictionary class]])
|
||||
{
|
||||
|
@ -146,7 +157,7 @@
|
|||
NSLocalizedString(@"New Tier", "Inspector -> tracker table") :
|
||||
[NSString stringWithFormat:NSLocalizedString(@"Tier %d", "Inspector -> tracker table"), tier];
|
||||
|
||||
if (fTorrents.count > 1)
|
||||
if (self.fTorrents.count > 1)
|
||||
{
|
||||
tierString = [tierString stringByAppendingFormat:@" - %@", item[@"Name"]];
|
||||
}
|
||||
|
@ -160,14 +171,14 @@
|
|||
|
||||
- (NSCell*)tableView:(NSTableView*)tableView dataCellForTableColumn:(NSTableColumn*)tableColumn row:(NSInteger)row
|
||||
{
|
||||
BOOL const tracker = [fTrackers[row] isKindOfClass:[TrackerNode class]];
|
||||
return tracker ? fTrackerCell : [tableColumn dataCellForRow:row];
|
||||
BOOL const tracker = [self.fTrackers[row] isKindOfClass:[TrackerNode class]];
|
||||
return tracker ? self.fTrackerCell : [tableColumn dataCellForRow:row];
|
||||
}
|
||||
|
||||
- (CGFloat)tableView:(NSTableView*)tableView heightOfRow:(NSInteger)row
|
||||
{
|
||||
//check for NSDictionay instead of TrackerNode because of display issue when adding a row
|
||||
if ([fTrackers[row] isKindOfClass:[NSDictionary class]])
|
||||
if ([self.fTrackers[row] isKindOfClass:[NSDictionary class]])
|
||||
{
|
||||
return TRACKER_GROUP_SEPARATOR_HEIGHT;
|
||||
}
|
||||
|
@ -185,12 +196,12 @@
|
|||
|
||||
- (void)tableViewSelectionDidChange:(NSNotification*)notification
|
||||
{
|
||||
[fTrackerAddRemoveControl setEnabled:fTrackerTable.numberOfSelectedRows > 0 forSegment:TRACKER_REMOVE_TAG];
|
||||
[self.fTrackerAddRemoveControl setEnabled:self.fTrackerTable.numberOfSelectedRows > 0 forSegment:TRACKER_REMOVE_TAG];
|
||||
}
|
||||
|
||||
- (BOOL)tableView:(NSTableView*)tableView isGroupRow:(NSInteger)row
|
||||
{
|
||||
return ![fTrackers[row] isKindOfClass:[TrackerNode class]] && tableView.editedRow != row;
|
||||
return ![self.fTrackers[row] isKindOfClass:[TrackerNode class]] && tableView.editedRow != row;
|
||||
}
|
||||
|
||||
- (NSString*)tableView:(NSTableView*)tableView
|
||||
|
@ -200,7 +211,7 @@
|
|||
row:(NSInteger)row
|
||||
mouseLocation:(NSPoint)mouseLocation
|
||||
{
|
||||
id node = fTrackers[row];
|
||||
id node = self.fTrackers[row];
|
||||
if ([node isKindOfClass:[TrackerNode class]])
|
||||
{
|
||||
return ((TrackerNode*)node).fullAnnounceAddress;
|
||||
|
@ -216,7 +227,7 @@
|
|||
forTableColumn:(NSTableColumn*)tableColumn
|
||||
row:(NSInteger)row
|
||||
{
|
||||
Torrent* torrent = fTorrents[0];
|
||||
Torrent* torrent = self.fTorrents[0];
|
||||
|
||||
BOOL added = NO;
|
||||
for (NSString* tracker in [object componentsSeparatedByString:@"\n"])
|
||||
|
@ -233,11 +244,11 @@
|
|||
}
|
||||
|
||||
//reset table with either new or old value
|
||||
fTrackers = torrent.allTrackerStats;
|
||||
self.fTrackers = torrent.allTrackerStats;
|
||||
|
||||
[fTrackerTable setTrackers:fTrackers];
|
||||
[fTrackerTable reloadData];
|
||||
[fTrackerTable deselectAll:self];
|
||||
self.fTrackerTable.trackers = self.fTrackers;
|
||||
[self.fTrackerTable reloadData];
|
||||
[self.fTrackerTable deselectAll:self];
|
||||
|
||||
[NSNotificationCenter.defaultCenter postNotificationName:@"UpdateUI" object:nil]; //incase sort by tracker
|
||||
}
|
||||
|
@ -245,7 +256,7 @@
|
|||
- (void)addRemoveTracker:(id)sender
|
||||
{
|
||||
//don't allow add/remove when currently adding - it leads to weird results
|
||||
if (fTrackerTable.editedRow != -1)
|
||||
if (self.fTrackerTable.editedRow != -1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -262,35 +273,37 @@
|
|||
}
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
- (void)setupInfo
|
||||
{
|
||||
NSUInteger const numberSelected = fTorrents.count;
|
||||
NSUInteger const numberSelected = self.fTorrents.count;
|
||||
if (numberSelected != 1)
|
||||
{
|
||||
if (numberSelected == 0)
|
||||
{
|
||||
fTrackers = nil;
|
||||
self.fTrackers = nil;
|
||||
|
||||
[fTrackerTable setTrackers:nil];
|
||||
[fTrackerTable reloadData];
|
||||
self.fTrackerTable.trackers = nil;
|
||||
[self.fTrackerTable reloadData];
|
||||
}
|
||||
|
||||
[fTrackerTable setTorrent:nil];
|
||||
self.fTrackerTable.torrent = nil;
|
||||
|
||||
[fTrackerAddRemoveControl setEnabled:NO forSegment:TRACKER_ADD_TAG];
|
||||
[fTrackerAddRemoveControl setEnabled:NO forSegment:TRACKER_REMOVE_TAG];
|
||||
[self.fTrackerAddRemoveControl setEnabled:NO forSegment:TRACKER_ADD_TAG];
|
||||
[self.fTrackerAddRemoveControl setEnabled:NO forSegment:TRACKER_REMOVE_TAG];
|
||||
}
|
||||
else
|
||||
{
|
||||
[fTrackerTable setTorrent:fTorrents[0]];
|
||||
self.fTrackerTable.torrent = self.fTorrents[0];
|
||||
|
||||
[fTrackerAddRemoveControl setEnabled:YES forSegment:TRACKER_ADD_TAG];
|
||||
[fTrackerAddRemoveControl setEnabled:NO forSegment:TRACKER_REMOVE_TAG];
|
||||
[self.fTrackerAddRemoveControl setEnabled:YES forSegment:TRACKER_ADD_TAG];
|
||||
[self.fTrackerAddRemoveControl setEnabled:NO forSegment:TRACKER_REMOVE_TAG];
|
||||
}
|
||||
|
||||
[fTrackerTable deselectAll:self];
|
||||
[self.fTrackerTable deselectAll:self];
|
||||
|
||||
fSet = YES;
|
||||
self.fSet = YES;
|
||||
}
|
||||
|
||||
#warning doesn't like blank addresses
|
||||
|
@ -298,29 +311,29 @@
|
|||
{
|
||||
[self.view.window makeKeyWindow];
|
||||
|
||||
NSAssert1(fTorrents.count == 1, @"Attempting to add tracker with %ld transfers selected", fTorrents.count);
|
||||
NSAssert1(self.fTorrents.count == 1, @"Attempting to add tracker with %ld transfers selected", self.fTorrents.count);
|
||||
|
||||
[fTrackers addObject:@{ @"Tier" : @-1 }];
|
||||
[fTrackers addObject:@""];
|
||||
[self.fTrackers addObject:@{ @"Tier" : @-1 }];
|
||||
[self.fTrackers addObject:@""];
|
||||
|
||||
[fTrackerTable setTrackers:fTrackers];
|
||||
[fTrackerTable reloadData];
|
||||
[fTrackerTable selectRowIndexes:[NSIndexSet indexSetWithIndex:fTrackers.count - 1] byExtendingSelection:NO];
|
||||
[fTrackerTable editColumn:[fTrackerTable columnWithIdentifier:@"Tracker"] row:fTrackers.count - 1 withEvent:nil select:YES];
|
||||
self.fTrackerTable.trackers = self.fTrackers;
|
||||
[self.fTrackerTable reloadData];
|
||||
[self.fTrackerTable selectRowIndexes:[NSIndexSet indexSetWithIndex:self.fTrackers.count - 1] byExtendingSelection:NO];
|
||||
[self.fTrackerTable editColumn:[self.fTrackerTable columnWithIdentifier:@"Tracker"] row:self.fTrackers.count - 1 withEvent:nil select:YES];
|
||||
}
|
||||
|
||||
- (void)removeTrackers
|
||||
{
|
||||
NSMutableDictionary* removeIdentifiers = [NSMutableDictionary dictionaryWithCapacity:fTorrents.count];
|
||||
NSMutableDictionary* removeIdentifiers = [NSMutableDictionary dictionaryWithCapacity:self.fTorrents.count];
|
||||
NSUInteger removeTrackerCount = 0;
|
||||
|
||||
NSIndexSet* selectedIndexes = fTrackerTable.selectedRowIndexes;
|
||||
NSIndexSet* selectedIndexes = self.fTrackerTable.selectedRowIndexes;
|
||||
BOOL groupSelected = NO;
|
||||
NSUInteger groupRowIndex = NSNotFound;
|
||||
NSMutableIndexSet* removeIndexes = [NSMutableIndexSet indexSet];
|
||||
for (NSUInteger i = 0; i < fTrackers.count; ++i)
|
||||
for (NSUInteger i = 0; i < self.fTrackers.count; ++i)
|
||||
{
|
||||
id object = fTrackers[i];
|
||||
id object = self.fTrackers[i];
|
||||
if ([object isKindOfClass:[TrackerNode class]])
|
||||
{
|
||||
TrackerNode* node = (TrackerNode*)object;
|
||||
|
@ -422,7 +435,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
[fTrackerTable beginUpdates];
|
||||
[self.fTrackerTable beginUpdates];
|
||||
|
||||
for (Torrent* torrent in removeIdentifiers)
|
||||
{
|
||||
|
@ -430,17 +443,17 @@
|
|||
}
|
||||
|
||||
//reset table with either new or old value
|
||||
fTrackers = [[NSMutableArray alloc] init];
|
||||
for (Torrent* torrent in fTorrents)
|
||||
self.fTrackers = [[NSMutableArray alloc] init];
|
||||
for (Torrent* torrent in self.fTorrents)
|
||||
{
|
||||
[fTrackers addObjectsFromArray:torrent.allTrackerStats];
|
||||
[self.fTrackers addObjectsFromArray:torrent.allTrackerStats];
|
||||
}
|
||||
|
||||
[fTrackerTable removeRowsAtIndexes:removeIndexes withAnimation:NSTableViewAnimationSlideLeft];
|
||||
[self.fTrackerTable removeRowsAtIndexes:removeIndexes withAnimation:NSTableViewAnimationSlideLeft];
|
||||
|
||||
[fTrackerTable setTrackers:fTrackers];
|
||||
self.fTrackerTable.trackers = self.fTrackers;
|
||||
|
||||
[fTrackerTable endUpdates];
|
||||
[self.fTrackerTable endUpdates];
|
||||
|
||||
[NSNotificationCenter.defaultCenter postNotificationName:@"UpdateUI" object:nil]; //incase sort by tracker
|
||||
}
|
||||
|
|
|
@ -5,36 +5,10 @@
|
|||
#import <Cocoa/Cocoa.h>
|
||||
#import <Quartz/Quartz.h>
|
||||
|
||||
@protocol InfoViewController;
|
||||
@class InfoGeneralViewController;
|
||||
@class InfoActivityViewController;
|
||||
@class InfoTrackersViewController;
|
||||
@class InfoPeersViewController;
|
||||
@class InfoFileViewController;
|
||||
@class InfoOptionsViewController;
|
||||
|
||||
@interface InfoWindowController : NSWindowController
|
||||
{
|
||||
NSArray* fTorrents;
|
||||
|
||||
CGFloat fMinWindowWidth;
|
||||
|
||||
NSViewController<InfoViewController>* fViewController;
|
||||
NSInteger fCurrentTabTag;
|
||||
IBOutlet NSSegmentedControl* fTabs;
|
||||
|
||||
InfoGeneralViewController* fGeneralViewController;
|
||||
InfoActivityViewController* fActivityViewController;
|
||||
InfoTrackersViewController* fTrackersViewController;
|
||||
InfoPeersViewController* fPeersViewController;
|
||||
InfoFileViewController* fFileViewController;
|
||||
InfoOptionsViewController* fOptionsViewController;
|
||||
|
||||
IBOutlet NSImageView* fImageView;
|
||||
IBOutlet NSTextField* fNameField;
|
||||
IBOutlet NSTextField* fBasicInfoField;
|
||||
IBOutlet NSTextField* fNoneSelectedField;
|
||||
}
|
||||
@property(nonatomic, readonly) NSArray* quickLookURLs;
|
||||
@property(nonatomic, readonly) BOOL canQuickLook;
|
||||
|
||||
- (void)setInfoForTorrents:(NSArray*)torrents;
|
||||
- (void)updateInfoStats;
|
||||
|
@ -45,8 +19,6 @@
|
|||
- (void)setNextTab;
|
||||
- (void)setPreviousTab;
|
||||
|
||||
@property(nonatomic, readonly) NSArray* quickLookURLs;
|
||||
@property(nonatomic, readonly) BOOL canQuickLook;
|
||||
- (NSRect)quickLookSourceFrameForPreviewItem:(id<QLPreviewItem>)item;
|
||||
|
||||
@end
|
||||
|
|
|
@ -35,7 +35,27 @@ typedef NS_ENUM(unsigned int, tabTag) {
|
|||
TAB_OPTIONS_TAG = 5
|
||||
};
|
||||
|
||||
@interface InfoWindowController (Private)
|
||||
@interface InfoWindowController ()
|
||||
|
||||
@property(nonatomic, copy) NSArray* fTorrents;
|
||||
|
||||
@property(nonatomic) CGFloat fMinWindowWidth;
|
||||
|
||||
@property(nonatomic) NSViewController<InfoViewController>* fViewController;
|
||||
@property(nonatomic) NSInteger fCurrentTabTag;
|
||||
@property(nonatomic) IBOutlet NSSegmentedControl* fTabs;
|
||||
|
||||
@property(nonatomic) InfoGeneralViewController* fGeneralViewController;
|
||||
@property(nonatomic) InfoActivityViewController* fActivityViewController;
|
||||
@property(nonatomic) InfoTrackersViewController* fTrackersViewController;
|
||||
@property(nonatomic) InfoPeersViewController* fPeersViewController;
|
||||
@property(nonatomic) InfoFileViewController* fFileViewController;
|
||||
@property(nonatomic) InfoOptionsViewController* fOptionsViewController;
|
||||
|
||||
@property(nonatomic) IBOutlet NSImageView* fImageView;
|
||||
@property(nonatomic) IBOutlet NSTextField* fNameField;
|
||||
@property(nonatomic) IBOutlet NSTextField* fBasicInfoField;
|
||||
@property(nonatomic) IBOutlet NSTextField* fNoneSelectedField;
|
||||
|
||||
- (void)resetInfo;
|
||||
- (void)resetInfoForTorrent:(NSNotification*)notification;
|
||||
|
@ -52,7 +72,7 @@ typedef NS_ENUM(unsigned int, tabTag) {
|
|||
|
||||
- (void)awakeFromNib
|
||||
{
|
||||
fNoneSelectedField.stringValue = NSLocalizedString(@"No Torrents Selected", "Inspector -> selected torrents");
|
||||
self.fNoneSelectedField.stringValue = NSLocalizedString(@"No Torrents Selected", "Inspector -> selected torrents");
|
||||
|
||||
//window location and size
|
||||
NSPanel* window = (NSPanel*)self.window;
|
||||
|
@ -60,7 +80,7 @@ typedef NS_ENUM(unsigned int, tabTag) {
|
|||
window.floatingPanel = NO;
|
||||
|
||||
CGFloat const windowHeight = NSHeight(window.frame);
|
||||
fMinWindowWidth = window.minSize.width;
|
||||
self.fMinWindowWidth = window.minSize.width;
|
||||
|
||||
[window setFrameAutosaveName:@"InspectorWindow"];
|
||||
[window setFrameUsingName:@"InspectorWindow"];
|
||||
|
@ -73,34 +93,34 @@ typedef NS_ENUM(unsigned int, tabTag) {
|
|||
window.becomesKeyOnlyIfNeeded = YES;
|
||||
|
||||
//set tab tooltips
|
||||
[fTabs.cell setToolTip:NSLocalizedString(@"General Info", "Inspector -> tab") forSegment:TAB_GENERAL_TAG];
|
||||
[fTabs.cell setToolTip:NSLocalizedString(@"Activity", "Inspector -> tab") forSegment:TAB_ACTIVITY_TAG];
|
||||
[fTabs.cell setToolTip:NSLocalizedString(@"Trackers", "Inspector -> tab") forSegment:TAB_TRACKERS_TAG];
|
||||
[fTabs.cell setToolTip:NSLocalizedString(@"Peers", "Inspector -> tab") forSegment:TAB_PEERS_TAG];
|
||||
[fTabs.cell setToolTip:NSLocalizedString(@"Files", "Inspector -> tab") forSegment:TAB_FILE_TAG];
|
||||
[fTabs.cell setToolTip:NSLocalizedString(@"Options", "Inspector -> tab") forSegment:TAB_OPTIONS_TAG];
|
||||
[self.fTabs.cell setToolTip:NSLocalizedString(@"General Info", "Inspector -> tab") forSegment:TAB_GENERAL_TAG];
|
||||
[self.fTabs.cell setToolTip:NSLocalizedString(@"Activity", "Inspector -> tab") forSegment:TAB_ACTIVITY_TAG];
|
||||
[self.fTabs.cell setToolTip:NSLocalizedString(@"Trackers", "Inspector -> tab") forSegment:TAB_TRACKERS_TAG];
|
||||
[self.fTabs.cell setToolTip:NSLocalizedString(@"Peers", "Inspector -> tab") forSegment:TAB_PEERS_TAG];
|
||||
[self.fTabs.cell setToolTip:NSLocalizedString(@"Files", "Inspector -> tab") forSegment:TAB_FILE_TAG];
|
||||
[self.fTabs.cell setToolTip:NSLocalizedString(@"Options", "Inspector -> tab") forSegment:TAB_OPTIONS_TAG];
|
||||
|
||||
[fTabs setImage:[NSImage systemSymbol:@"info.circle"
|
||||
[self.fTabs setImage:[NSImage systemSymbol:@"info.circle"
|
||||
withFallback:@"InfoGeneral"]
|
||||
forSegment:TAB_GENERAL_TAG];
|
||||
[fTabs setImage:[NSImage systemSymbol:@"square.grid.3x3.fill.square"
|
||||
[self.fTabs setImage:[NSImage systemSymbol:@"square.grid.3x3.fill.square"
|
||||
withFallback:@"InfoActivity"]
|
||||
forSegment:TAB_ACTIVITY_TAG];
|
||||
[fTabs setImage:[NSImage systemSymbol:@"antenna.radiowaves.left.and.right"
|
||||
[self.fTabs setImage:[NSImage systemSymbol:@"antenna.radiowaves.left.and.right"
|
||||
withFallback:@"InfoTracker"]
|
||||
forSegment:TAB_TRACKERS_TAG];
|
||||
[fTabs setImage:[NSImage systemSymbol:@"person.2"
|
||||
[self.fTabs setImage:[NSImage systemSymbol:@"person.2"
|
||||
withFallback:@"InfoPeers"]
|
||||
forSegment:TAB_PEERS_TAG];
|
||||
[fTabs setImage:[NSImage systemSymbol:@"doc.on.doc"
|
||||
[self.fTabs setImage:[NSImage systemSymbol:@"doc.on.doc"
|
||||
withFallback:@"InfoFiles"]
|
||||
forSegment:TAB_FILE_TAG];
|
||||
[fTabs setImage:[NSImage systemSymbol:@"gearshape"
|
||||
[self.fTabs setImage:[NSImage systemSymbol:@"gearshape"
|
||||
withFallback:@"InfoOptions"]
|
||||
forSegment:TAB_OPTIONS_TAG];
|
||||
|
||||
//set selected tab
|
||||
fCurrentTabTag = INVALID;
|
||||
self.fCurrentTabTag = INVALID;
|
||||
NSString* identifier = [NSUserDefaults.standardUserDefaults stringForKey:@"InspectorSelected"];
|
||||
NSInteger tag;
|
||||
if ([identifier isEqualToString:TAB_INFO_IDENT])
|
||||
|
@ -133,10 +153,10 @@ typedef NS_ENUM(unsigned int, tabTag) {
|
|||
tag = TAB_GENERAL_TAG;
|
||||
}
|
||||
|
||||
fTabs.target = self;
|
||||
fTabs.action = @selector(setTab:);
|
||||
self.fTabs.target = self;
|
||||
self.fTabs.action = @selector(setTab:);
|
||||
|
||||
fTabs.selectedSegment = tag;
|
||||
self.fTabs.selectedSegment = tag;
|
||||
[self setTab:nil];
|
||||
|
||||
//set blank inspector
|
||||
|
@ -153,20 +173,20 @@ typedef NS_ENUM(unsigned int, tabTag) {
|
|||
{
|
||||
[NSNotificationCenter.defaultCenter removeObserver:self];
|
||||
|
||||
if ([fViewController respondsToSelector:@selector(saveViewSize)])
|
||||
if ([_fViewController respondsToSelector:@selector(saveViewSize)])
|
||||
{
|
||||
[fViewController saveViewSize];
|
||||
[_fViewController saveViewSize];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setInfoForTorrents:(NSArray*)torrents
|
||||
{
|
||||
if (fTorrents && [fTorrents isEqualToArray:torrents])
|
||||
if (self.fTorrents && [self.fTorrents isEqualToArray:torrents])
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
fTorrents = torrents;
|
||||
self.fTorrents = torrents;
|
||||
|
||||
[self resetInfo];
|
||||
}
|
||||
|
@ -180,7 +200,7 @@ typedef NS_ENUM(unsigned int, tabTag) {
|
|||
|
||||
- (void)windowWillClose:(NSNotification*)notification
|
||||
{
|
||||
if (fCurrentTabTag == TAB_FILE_TAG && ([QLPreviewPanel sharedPreviewPanelExists] && [QLPreviewPanel sharedPreviewPanel].visible))
|
||||
if (self.fCurrentTabTag == TAB_FILE_TAG && ([QLPreviewPanel sharedPreviewPanelExists] && [QLPreviewPanel sharedPreviewPanel].visible))
|
||||
{
|
||||
[[QLPreviewPanel sharedPreviewPanel] reloadData];
|
||||
}
|
||||
|
@ -188,9 +208,9 @@ typedef NS_ENUM(unsigned int, tabTag) {
|
|||
|
||||
- (void)setTab:(id)sender
|
||||
{
|
||||
NSInteger const oldTabTag = fCurrentTabTag;
|
||||
fCurrentTabTag = fTabs.selectedTag;
|
||||
if (fCurrentTabTag == oldTabTag)
|
||||
NSInteger const oldTabTag = self.fCurrentTabTag;
|
||||
self.fCurrentTabTag = self.fTabs.selectedTag;
|
||||
if (self.fCurrentTabTag == oldTabTag)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -199,17 +219,17 @@ typedef NS_ENUM(unsigned int, tabTag) {
|
|||
CGFloat oldHeight = 0;
|
||||
if (oldTabTag != INVALID)
|
||||
{
|
||||
if ([fViewController respondsToSelector:@selector(saveViewSize)])
|
||||
if ([self.fViewController respondsToSelector:@selector(saveViewSize)])
|
||||
{
|
||||
[fViewController saveViewSize];
|
||||
[self.fViewController saveViewSize];
|
||||
}
|
||||
|
||||
if ([fViewController respondsToSelector:@selector(clearView)])
|
||||
if ([self.fViewController respondsToSelector:@selector(clearView)])
|
||||
{
|
||||
[fViewController clearView];
|
||||
[self.fViewController clearView];
|
||||
}
|
||||
|
||||
NSView* oldView = fViewController.view;
|
||||
NSView* oldView = self.fViewController.view;
|
||||
oldHeight = NSHeight(oldView.frame);
|
||||
|
||||
//remove old view
|
||||
|
@ -218,70 +238,70 @@ typedef NS_ENUM(unsigned int, tabTag) {
|
|||
|
||||
//set new tab item
|
||||
NSString* identifier;
|
||||
switch (fCurrentTabTag)
|
||||
switch (self.fCurrentTabTag)
|
||||
{
|
||||
case TAB_GENERAL_TAG:
|
||||
if (!fGeneralViewController)
|
||||
if (!self.fGeneralViewController)
|
||||
{
|
||||
fGeneralViewController = [[InfoGeneralViewController alloc] init];
|
||||
[fGeneralViewController setInfoForTorrents:fTorrents];
|
||||
self.fGeneralViewController = [[InfoGeneralViewController alloc] init];
|
||||
[self.fGeneralViewController setInfoForTorrents:self.fTorrents];
|
||||
}
|
||||
|
||||
fViewController = fGeneralViewController;
|
||||
self.fViewController = self.fGeneralViewController;
|
||||
identifier = TAB_INFO_IDENT;
|
||||
break;
|
||||
case TAB_ACTIVITY_TAG:
|
||||
if (!fActivityViewController)
|
||||
if (!self.fActivityViewController)
|
||||
{
|
||||
fActivityViewController = [[InfoActivityViewController alloc] init];
|
||||
[fActivityViewController setInfoForTorrents:fTorrents];
|
||||
self.fActivityViewController = [[InfoActivityViewController alloc] init];
|
||||
[self.fActivityViewController setInfoForTorrents:self.fTorrents];
|
||||
}
|
||||
|
||||
fViewController = fActivityViewController;
|
||||
self.fViewController = self.fActivityViewController;
|
||||
identifier = TAB_ACTIVITY_IDENT;
|
||||
break;
|
||||
case TAB_TRACKERS_TAG:
|
||||
if (!fTrackersViewController)
|
||||
if (!self.fTrackersViewController)
|
||||
{
|
||||
fTrackersViewController = [[InfoTrackersViewController alloc] init];
|
||||
[fTrackersViewController setInfoForTorrents:fTorrents];
|
||||
self.fTrackersViewController = [[InfoTrackersViewController alloc] init];
|
||||
[self.fTrackersViewController setInfoForTorrents:self.fTorrents];
|
||||
}
|
||||
|
||||
fViewController = fTrackersViewController;
|
||||
self.fViewController = self.fTrackersViewController;
|
||||
identifier = TAB_TRACKER_IDENT;
|
||||
break;
|
||||
case TAB_PEERS_TAG:
|
||||
if (!fPeersViewController)
|
||||
if (!self.fPeersViewController)
|
||||
{
|
||||
fPeersViewController = [[InfoPeersViewController alloc] init];
|
||||
[fPeersViewController setInfoForTorrents:fTorrents];
|
||||
self.fPeersViewController = [[InfoPeersViewController alloc] init];
|
||||
[self.fPeersViewController setInfoForTorrents:self.fTorrents];
|
||||
}
|
||||
|
||||
fViewController = fPeersViewController;
|
||||
self.fViewController = self.fPeersViewController;
|
||||
identifier = TAB_PEERS_IDENT;
|
||||
break;
|
||||
case TAB_FILE_TAG:
|
||||
if (!fFileViewController)
|
||||
if (!self.fFileViewController)
|
||||
{
|
||||
fFileViewController = [[InfoFileViewController alloc] init];
|
||||
[fFileViewController setInfoForTorrents:fTorrents];
|
||||
self.fFileViewController = [[InfoFileViewController alloc] init];
|
||||
[self.fFileViewController setInfoForTorrents:self.fTorrents];
|
||||
}
|
||||
|
||||
fViewController = fFileViewController;
|
||||
self.fViewController = self.fFileViewController;
|
||||
identifier = TAB_FILES_IDENT;
|
||||
break;
|
||||
case TAB_OPTIONS_TAG:
|
||||
if (!fOptionsViewController)
|
||||
if (!self.fOptionsViewController)
|
||||
{
|
||||
fOptionsViewController = [[InfoOptionsViewController alloc] init];
|
||||
[fOptionsViewController setInfoForTorrents:fTorrents];
|
||||
self.fOptionsViewController = [[InfoOptionsViewController alloc] init];
|
||||
[self.fOptionsViewController setInfoForTorrents:self.fTorrents];
|
||||
}
|
||||
|
||||
fViewController = fOptionsViewController;
|
||||
self.fViewController = self.fOptionsViewController;
|
||||
identifier = TAB_OPTIONS_IDENT;
|
||||
break;
|
||||
default:
|
||||
NSAssert1(NO, @"Unknown info tab selected: %ld", fCurrentTabTag);
|
||||
NSAssert1(NO, @"Unknown info tab selected: %ld", self.fCurrentTabTag);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -290,11 +310,11 @@ typedef NS_ENUM(unsigned int, tabTag) {
|
|||
NSWindow* window = self.window;
|
||||
|
||||
window.title = [NSString
|
||||
stringWithFormat:@"%@ - %@", fViewController.title, NSLocalizedString(@"Torrent Inspector", "Inspector -> title")];
|
||||
stringWithFormat:@"%@ - %@", self.fViewController.title, NSLocalizedString(@"Torrent Inspector", "Inspector -> title")];
|
||||
|
||||
NSView* view = fViewController.view;
|
||||
NSView* view = self.fViewController.view;
|
||||
|
||||
[fViewController updateInfo];
|
||||
[self.fViewController updateInfo];
|
||||
|
||||
NSRect windowRect = window.frame, viewRect = view.frame;
|
||||
|
||||
|
@ -302,10 +322,10 @@ typedef NS_ENUM(unsigned int, tabTag) {
|
|||
windowRect.origin.y -= difference;
|
||||
windowRect.size.height += difference;
|
||||
|
||||
CGFloat const minWindowWidth = MAX(fMinWindowWidth, view.fittingSize.width);
|
||||
CGFloat const minWindowWidth = MAX(self.fMinWindowWidth, view.fittingSize.width);
|
||||
windowRect.size.width = MAX(NSWidth(windowRect), minWindowWidth);
|
||||
|
||||
if ([fViewController respondsToSelector:@selector(saveViewSize)]) //a little bit hacky, but avoids requiring an extra method
|
||||
if ([self.fViewController respondsToSelector:@selector(saveViewSize)]) //a little bit hacky, but avoids requiring an extra method
|
||||
{
|
||||
if (window.screen)
|
||||
{
|
||||
|
@ -339,9 +359,9 @@ typedef NS_ENUM(unsigned int, tabTag) {
|
|||
views:@{ @"view" : view }]];
|
||||
[window.contentView
|
||||
addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[tabs]-0-[view]-0-|" options:0 metrics:nil
|
||||
views:@{ @"tabs" : fTabs, @"view" : view }]];
|
||||
views:@{ @"tabs" : self.fTabs, @"view" : view }]];
|
||||
|
||||
if ((fCurrentTabTag == TAB_FILE_TAG || oldTabTag == TAB_FILE_TAG) &&
|
||||
if ((self.fCurrentTabTag == TAB_FILE_TAG || oldTabTag == TAB_FILE_TAG) &&
|
||||
([QLPreviewPanel sharedPreviewPanelExists] && [QLPreviewPanel sharedPreviewPanel].visible))
|
||||
{
|
||||
[[QLPreviewPanel sharedPreviewPanel] reloadData];
|
||||
|
@ -350,25 +370,25 @@ typedef NS_ENUM(unsigned int, tabTag) {
|
|||
|
||||
- (void)setNextTab
|
||||
{
|
||||
NSInteger tag = fTabs.selectedSegment + 1;
|
||||
if (tag >= fTabs.segmentCount)
|
||||
NSInteger tag = self.fTabs.selectedSegment + 1;
|
||||
if (tag >= self.fTabs.segmentCount)
|
||||
{
|
||||
tag = 0;
|
||||
}
|
||||
|
||||
fTabs.selectedSegment = tag;
|
||||
self.fTabs.selectedSegment = tag;
|
||||
[self setTab:nil];
|
||||
}
|
||||
|
||||
- (void)setPreviousTab
|
||||
{
|
||||
NSInteger tag = fTabs.selectedSegment - 1;
|
||||
NSInteger tag = self.fTabs.selectedSegment - 1;
|
||||
if (tag < 0)
|
||||
{
|
||||
tag = fTabs.segmentCount - 1;
|
||||
tag = self.fTabs.segmentCount - 1;
|
||||
}
|
||||
|
||||
fTabs.selectedSegment = tag;
|
||||
self.fTabs.selectedSegment = tag;
|
||||
[self setTab:nil];
|
||||
}
|
||||
|
||||
|
@ -386,54 +406,52 @@ typedef NS_ENUM(unsigned int, tabTag) {
|
|||
|
||||
- (void)updateInfoStats
|
||||
{
|
||||
[fViewController updateInfo];
|
||||
[self.fViewController updateInfo];
|
||||
}
|
||||
|
||||
- (void)updateOptions
|
||||
{
|
||||
[fOptionsViewController updateOptions];
|
||||
[self.fOptionsViewController updateOptions];
|
||||
}
|
||||
|
||||
- (NSArray*)quickLookURLs
|
||||
{
|
||||
return fFileViewController.quickLookURLs;
|
||||
return self.fFileViewController.quickLookURLs;
|
||||
}
|
||||
|
||||
- (BOOL)canQuickLook
|
||||
{
|
||||
if (fCurrentTabTag != TAB_FILE_TAG || !self.window.visible)
|
||||
if (self.fCurrentTabTag != TAB_FILE_TAG || !self.window.visible)
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
return fFileViewController.canQuickLook;
|
||||
return self.fFileViewController.canQuickLook;
|
||||
}
|
||||
|
||||
- (NSRect)quickLookSourceFrameForPreviewItem:(id<QLPreviewItem>)item
|
||||
{
|
||||
return [fFileViewController quickLookSourceFrameForPreviewItem:item];
|
||||
return [self.fFileViewController quickLookSourceFrameForPreviewItem:item];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation InfoWindowController (Private)
|
||||
#pragma mark - Private
|
||||
|
||||
- (void)resetInfo
|
||||
{
|
||||
NSUInteger const numberSelected = fTorrents.count;
|
||||
NSUInteger const numberSelected = self.fTorrents.count;
|
||||
if (numberSelected != 1)
|
||||
{
|
||||
if (numberSelected > 0)
|
||||
{
|
||||
fImageView.image = [NSImage imageNamed:NSImageNameMultipleDocuments];
|
||||
self.fImageView.image = [NSImage imageNamed:NSImageNameMultipleDocuments];
|
||||
|
||||
fNameField.stringValue = [NSString stringWithFormat:NSLocalizedString(@"%@ Torrents Selected", "Inspector -> selected torrents"),
|
||||
self.fNameField.stringValue = [NSString stringWithFormat:NSLocalizedString(@"%@ Torrents Selected", "Inspector -> selected torrents"),
|
||||
[NSString formattedUInteger:numberSelected]];
|
||||
fNameField.hidden = NO;
|
||||
self.fNameField.hidden = NO;
|
||||
|
||||
uint64_t size = 0;
|
||||
NSUInteger fileCount = 0, magnetCount = 0;
|
||||
for (Torrent* torrent in fTorrents)
|
||||
for (Torrent* torrent in self.fTorrents)
|
||||
{
|
||||
size += torrent.size;
|
||||
fileCount += torrent.fileCount;
|
||||
|
@ -477,7 +495,7 @@ typedef NS_ENUM(unsigned int, tabTag) {
|
|||
|
||||
if (magnetCount < numberSelected)
|
||||
{
|
||||
fBasicInfoField.stringValue = [NSString
|
||||
self.fBasicInfoField.stringValue = [NSString
|
||||
stringWithFormat:@"%@, %@",
|
||||
fileString,
|
||||
[NSString stringWithFormat:NSLocalizedString(@"%@ total", "Inspector -> selected torrents"),
|
||||
|
@ -485,38 +503,38 @@ typedef NS_ENUM(unsigned int, tabTag) {
|
|||
|
||||
NSByteCountFormatter* formatter = [[NSByteCountFormatter alloc] init];
|
||||
formatter.allowedUnits = NSByteCountFormatterUseBytes;
|
||||
fBasicInfoField.toolTip = [formatter stringFromByteCount:size];
|
||||
self.fBasicInfoField.toolTip = [formatter stringFromByteCount:size];
|
||||
}
|
||||
else
|
||||
{
|
||||
fBasicInfoField.stringValue = fileString;
|
||||
fBasicInfoField.toolTip = nil;
|
||||
self.fBasicInfoField.stringValue = fileString;
|
||||
self.fBasicInfoField.toolTip = nil;
|
||||
}
|
||||
fBasicInfoField.hidden = NO;
|
||||
self.fBasicInfoField.hidden = NO;
|
||||
|
||||
fNoneSelectedField.hidden = YES;
|
||||
self.fNoneSelectedField.hidden = YES;
|
||||
}
|
||||
else
|
||||
{
|
||||
fImageView.image = [NSImage imageNamed:NSImageNameApplicationIcon];
|
||||
fNoneSelectedField.hidden = NO;
|
||||
self.fImageView.image = [NSImage imageNamed:NSImageNameApplicationIcon];
|
||||
self.fNoneSelectedField.hidden = NO;
|
||||
|
||||
fNameField.hidden = YES;
|
||||
fBasicInfoField.hidden = YES;
|
||||
self.fNameField.hidden = YES;
|
||||
self.fBasicInfoField.hidden = YES;
|
||||
}
|
||||
|
||||
fNameField.toolTip = nil;
|
||||
self.fNameField.toolTip = nil;
|
||||
}
|
||||
else
|
||||
{
|
||||
Torrent* torrent = fTorrents[0];
|
||||
Torrent* torrent = self.fTorrents[0];
|
||||
|
||||
fImageView.image = torrent.icon;
|
||||
self.fImageView.image = torrent.icon;
|
||||
|
||||
NSString* name = torrent.name;
|
||||
fNameField.stringValue = name;
|
||||
fNameField.toolTip = name;
|
||||
fNameField.hidden = NO;
|
||||
self.fNameField.stringValue = name;
|
||||
self.fNameField.toolTip = name;
|
||||
self.fNameField.hidden = NO;
|
||||
|
||||
if (!torrent.magnet)
|
||||
{
|
||||
|
@ -536,36 +554,36 @@ typedef NS_ENUM(unsigned int, tabTag) {
|
|||
}
|
||||
basicString = [NSString stringWithFormat:@"%@, %@", fileString, basicString];
|
||||
}
|
||||
fBasicInfoField.stringValue = basicString;
|
||||
self.fBasicInfoField.stringValue = basicString;
|
||||
|
||||
NSByteCountFormatter* formatter = [[NSByteCountFormatter alloc] init];
|
||||
formatter.allowedUnits = NSByteCountFormatterUseBytes;
|
||||
fBasicInfoField.toolTip = [formatter stringFromByteCount:torrent.size];
|
||||
self.fBasicInfoField.toolTip = [formatter stringFromByteCount:torrent.size];
|
||||
}
|
||||
else
|
||||
{
|
||||
fBasicInfoField.stringValue = NSLocalizedString(@"Magnetized transfer", "Inspector -> selected torrents");
|
||||
fBasicInfoField.toolTip = nil;
|
||||
self.fBasicInfoField.stringValue = NSLocalizedString(@"Magnetized transfer", "Inspector -> selected torrents");
|
||||
self.fBasicInfoField.toolTip = nil;
|
||||
}
|
||||
fBasicInfoField.hidden = NO;
|
||||
self.fBasicInfoField.hidden = NO;
|
||||
|
||||
fNoneSelectedField.hidden = YES;
|
||||
self.fNoneSelectedField.hidden = YES;
|
||||
}
|
||||
|
||||
[fGeneralViewController setInfoForTorrents:fTorrents];
|
||||
[fActivityViewController setInfoForTorrents:fTorrents];
|
||||
[fTrackersViewController setInfoForTorrents:fTorrents];
|
||||
[fPeersViewController setInfoForTorrents:fTorrents];
|
||||
[fFileViewController setInfoForTorrents:fTorrents];
|
||||
[fOptionsViewController setInfoForTorrents:fTorrents];
|
||||
[self.fGeneralViewController setInfoForTorrents:self.fTorrents];
|
||||
[self.fActivityViewController setInfoForTorrents:self.fTorrents];
|
||||
[self.fTrackersViewController setInfoForTorrents:self.fTorrents];
|
||||
[self.fPeersViewController setInfoForTorrents:self.fTorrents];
|
||||
[self.fFileViewController setInfoForTorrents:self.fTorrents];
|
||||
[self.fOptionsViewController setInfoForTorrents:self.fTorrents];
|
||||
|
||||
[fViewController updateInfo];
|
||||
[self.fViewController updateInfo];
|
||||
}
|
||||
|
||||
- (void)resetInfoForTorrent:(NSNotification*)notification
|
||||
{
|
||||
Torrent* torrent = notification.userInfo[@"Torrent"];
|
||||
if (fTorrents && (!torrent || [fTorrents containsObject:torrent]))
|
||||
if (self.fTorrents && (!torrent || [self.fTorrents containsObject:torrent]))
|
||||
{
|
||||
[self resetInfo];
|
||||
}
|
||||
|
|
|
@ -5,23 +5,6 @@
|
|||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
@interface MessageWindowController : NSWindowController
|
||||
{
|
||||
IBOutlet NSTableView* fMessageTable;
|
||||
|
||||
IBOutlet NSPopUpButton* fLevelButton;
|
||||
IBOutlet NSButton* fSaveButton;
|
||||
IBOutlet NSButton* fClearButton;
|
||||
IBOutlet NSSearchField* fFilterField;
|
||||
|
||||
NSMutableArray* fMessages;
|
||||
NSMutableArray* fDisplayedMessages;
|
||||
|
||||
NSDictionary* fAttributes;
|
||||
|
||||
NSTimer* fTimer;
|
||||
|
||||
NSLock* fLock;
|
||||
}
|
||||
|
||||
- (void)updateLog:(NSTimer*)timer;
|
||||
|
||||
|
|
|
@ -19,6 +19,22 @@
|
|||
|
||||
@interface MessageWindowController ()
|
||||
|
||||
@property(nonatomic) IBOutlet NSTableView* fMessageTable;
|
||||
|
||||
@property(nonatomic) IBOutlet NSPopUpButton* fLevelButton;
|
||||
@property(nonatomic) IBOutlet NSButton* fSaveButton;
|
||||
@property(nonatomic) IBOutlet NSButton* fClearButton;
|
||||
@property(nonatomic) IBOutlet NSSearchField* fFilterField;
|
||||
|
||||
@property(nonatomic) NSMutableArray* fMessages;
|
||||
@property(nonatomic) NSMutableArray* fDisplayedMessages;
|
||||
|
||||
@property(nonatomic, copy) NSDictionary* fAttributes;
|
||||
|
||||
@property(nonatomic) NSTimer* fTimer;
|
||||
|
||||
@property(nonatomic) NSLock* fLock;
|
||||
|
||||
- (void)resizeColumn;
|
||||
- (BOOL)shouldIncludeMessageForFilter:(NSString*)filterString message:(NSDictionary*)message;
|
||||
- (void)updateListForFilter;
|
||||
|
@ -42,86 +58,86 @@
|
|||
|
||||
[NSNotificationCenter.defaultCenter addObserver:self selector:@selector(resizeColumn)
|
||||
name:NSTableViewColumnDidResizeNotification
|
||||
object:fMessageTable];
|
||||
object:self.fMessageTable];
|
||||
|
||||
[window setContentBorderThickness:NSMinY(fMessageTable.enclosingScrollView.frame) forEdge:NSMinYEdge];
|
||||
[window setContentBorderThickness:NSMinY(self.fMessageTable.enclosingScrollView.frame) forEdge:NSMinYEdge];
|
||||
|
||||
self.window.title = NSLocalizedString(@"Message Log", "Message window -> title");
|
||||
|
||||
//set images and text for popup button items
|
||||
[fLevelButton itemAtIndex:LEVEL_ERROR].title = NSLocalizedString(@"Error", "Message window -> level string");
|
||||
[fLevelButton itemAtIndex:LEVEL_INFO].title = NSLocalizedString(@"Info", "Message window -> level string");
|
||||
[fLevelButton itemAtIndex:LEVEL_DEBUG].title = NSLocalizedString(@"Debug", "Message window -> level string");
|
||||
[self.fLevelButton itemAtIndex:LEVEL_ERROR].title = NSLocalizedString(@"Error", "Message window -> level string");
|
||||
[self.fLevelButton itemAtIndex:LEVEL_INFO].title = NSLocalizedString(@"Info", "Message window -> level string");
|
||||
[self.fLevelButton itemAtIndex:LEVEL_DEBUG].title = NSLocalizedString(@"Debug", "Message window -> level string");
|
||||
|
||||
CGFloat const levelButtonOldWidth = NSWidth(fLevelButton.frame);
|
||||
[fLevelButton sizeToFit];
|
||||
CGFloat const levelButtonOldWidth = NSWidth(self.fLevelButton.frame);
|
||||
[self.fLevelButton sizeToFit];
|
||||
|
||||
//set table column text
|
||||
[fMessageTable tableColumnWithIdentifier:@"Date"].headerCell.title = NSLocalizedString(@"Date", "Message window -> table column");
|
||||
[fMessageTable tableColumnWithIdentifier:@"Name"].headerCell.title = NSLocalizedString(@"Process", "Message window -> table column");
|
||||
[fMessageTable tableColumnWithIdentifier:@"Message"].headerCell.title = NSLocalizedString(@"Message", "Message window -> table column");
|
||||
[self.fMessageTable tableColumnWithIdentifier:@"Date"].headerCell.title = NSLocalizedString(@"Date", "Message window -> table column");
|
||||
[self.fMessageTable tableColumnWithIdentifier:@"Name"].headerCell.title = NSLocalizedString(@"Process", "Message window -> table column");
|
||||
[self.fMessageTable tableColumnWithIdentifier:@"Message"].headerCell.title = NSLocalizedString(@"Message", "Message window -> table column");
|
||||
|
||||
//set and size buttons
|
||||
fSaveButton.title = [NSLocalizedString(@"Save", "Message window -> save button") stringByAppendingEllipsis];
|
||||
[fSaveButton sizeToFit];
|
||||
self.fSaveButton.title = [NSLocalizedString(@"Save", "Message window -> save button") stringByAppendingEllipsis];
|
||||
[self.fSaveButton sizeToFit];
|
||||
|
||||
NSRect saveButtonFrame = fSaveButton.frame;
|
||||
NSRect saveButtonFrame = self.fSaveButton.frame;
|
||||
saveButtonFrame.size.width += 10.0;
|
||||
saveButtonFrame.origin.x += NSWidth(fLevelButton.frame) - levelButtonOldWidth;
|
||||
fSaveButton.frame = saveButtonFrame;
|
||||
saveButtonFrame.origin.x += NSWidth(self.fLevelButton.frame) - levelButtonOldWidth;
|
||||
self.fSaveButton.frame = saveButtonFrame;
|
||||
|
||||
CGFloat const oldClearButtonWidth = fClearButton.frame.size.width;
|
||||
CGFloat const oldClearButtonWidth = self.fClearButton.frame.size.width;
|
||||
|
||||
fClearButton.title = NSLocalizedString(@"Clear", "Message window -> save button");
|
||||
[fClearButton sizeToFit];
|
||||
self.fClearButton.title = NSLocalizedString(@"Clear", "Message window -> save button");
|
||||
[self.fClearButton sizeToFit];
|
||||
|
||||
NSRect clearButtonFrame = fClearButton.frame;
|
||||
NSRect clearButtonFrame = self.fClearButton.frame;
|
||||
clearButtonFrame.size.width = MAX(clearButtonFrame.size.width + 10.0, saveButtonFrame.size.width);
|
||||
clearButtonFrame.origin.x -= NSWidth(clearButtonFrame) - oldClearButtonWidth;
|
||||
fClearButton.frame = clearButtonFrame;
|
||||
self.fClearButton.frame = clearButtonFrame;
|
||||
|
||||
[fFilterField.cell setPlaceholderString:NSLocalizedString(@"Filter", "Message window -> filter field")];
|
||||
NSRect filterButtonFrame = fFilterField.frame;
|
||||
[self.fFilterField.cell setPlaceholderString:NSLocalizedString(@"Filter", "Message window -> filter field")];
|
||||
NSRect filterButtonFrame = self.fFilterField.frame;
|
||||
filterButtonFrame.origin.x -= NSWidth(clearButtonFrame) - oldClearButtonWidth;
|
||||
fFilterField.frame = filterButtonFrame;
|
||||
self.fFilterField.frame = filterButtonFrame;
|
||||
|
||||
fAttributes = [[[fMessageTable tableColumnWithIdentifier:@"Message"].dataCell attributedStringValue] attributesAtIndex:0
|
||||
self.fAttributes = [[[self.fMessageTable tableColumnWithIdentifier:@"Message"].dataCell attributedStringValue] attributesAtIndex:0
|
||||
effectiveRange:NULL];
|
||||
|
||||
//select proper level in popup button
|
||||
switch ([NSUserDefaults.standardUserDefaults integerForKey:@"MessageLevel"])
|
||||
{
|
||||
case TR_LOG_ERROR:
|
||||
[fLevelButton selectItemAtIndex:LEVEL_ERROR];
|
||||
[self.fLevelButton selectItemAtIndex:LEVEL_ERROR];
|
||||
break;
|
||||
case TR_LOG_INFO:
|
||||
[fLevelButton selectItemAtIndex:LEVEL_INFO];
|
||||
[self.fLevelButton selectItemAtIndex:LEVEL_INFO];
|
||||
break;
|
||||
case TR_LOG_DEBUG:
|
||||
[fLevelButton selectItemAtIndex:LEVEL_DEBUG];
|
||||
[self.fLevelButton selectItemAtIndex:LEVEL_DEBUG];
|
||||
break;
|
||||
default: //safety
|
||||
[NSUserDefaults.standardUserDefaults setInteger:TR_LOG_ERROR forKey:@"MessageLevel"];
|
||||
[fLevelButton selectItemAtIndex:LEVEL_ERROR];
|
||||
[self.fLevelButton selectItemAtIndex:LEVEL_ERROR];
|
||||
}
|
||||
|
||||
fMessages = [[NSMutableArray alloc] init];
|
||||
fDisplayedMessages = [[NSMutableArray alloc] init];
|
||||
self.fMessages = [[NSMutableArray alloc] init];
|
||||
self.fDisplayedMessages = [[NSMutableArray alloc] init];
|
||||
|
||||
fLock = [[NSLock alloc] init];
|
||||
self.fLock = [[NSLock alloc] init];
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[NSNotificationCenter.defaultCenter removeObserver:self];
|
||||
[fTimer invalidate];
|
||||
[_fTimer invalidate];
|
||||
}
|
||||
|
||||
- (void)windowDidBecomeKey:(NSNotification*)notification
|
||||
{
|
||||
if (!fTimer)
|
||||
if (!self.fTimer)
|
||||
{
|
||||
fTimer = [NSTimer scheduledTimerWithTimeInterval:UPDATE_SECONDS target:self selector:@selector(updateLog:) userInfo:nil
|
||||
self.fTimer = [NSTimer scheduledTimerWithTimeInterval:UPDATE_SECONDS target:self selector:@selector(updateLog:) userInfo:nil
|
||||
repeats:YES];
|
||||
[self updateLog:nil];
|
||||
}
|
||||
|
@ -129,8 +145,8 @@
|
|||
|
||||
- (void)windowWillClose:(id)sender
|
||||
{
|
||||
[fTimer invalidate];
|
||||
fTimer = nil;
|
||||
[self.fTimer invalidate];
|
||||
self.fTimer = nil;
|
||||
}
|
||||
|
||||
+ (void)restoreWindowWithIdentifier:(NSString*)identifier
|
||||
|
@ -145,8 +161,8 @@
|
|||
|
||||
- (void)window:(NSWindow*)window didDecodeRestorableState:(NSCoder*)coder
|
||||
{
|
||||
[fTimer invalidate];
|
||||
fTimer = [NSTimer scheduledTimerWithTimeInterval:UPDATE_SECONDS target:self selector:@selector(updateLog:) userInfo:nil
|
||||
[self.fTimer invalidate];
|
||||
self.fTimer = [NSTimer scheduledTimerWithTimeInterval:UPDATE_SECONDS target:self selector:@selector(updateLog:) userInfo:nil
|
||||
repeats:YES];
|
||||
[self updateLog:nil];
|
||||
}
|
||||
|
@ -159,15 +175,15 @@
|
|||
return;
|
||||
}
|
||||
|
||||
[fLock lock];
|
||||
[self.fLock lock];
|
||||
|
||||
static NSUInteger currentIndex = 0;
|
||||
|
||||
NSScroller* scroller = fMessageTable.enclosingScrollView.verticalScroller;
|
||||
NSScroller* scroller = self.fMessageTable.enclosingScrollView.verticalScroller;
|
||||
BOOL const shouldScroll = currentIndex == 0 || scroller.floatValue == 1.0 || scroller.hidden || scroller.knobProportion == 1.0;
|
||||
|
||||
NSInteger const maxLevel = [NSUserDefaults.standardUserDefaults integerForKey:@"MessageLevel"];
|
||||
NSString* filterString = fFilterField.stringValue;
|
||||
NSString* filterString = self.fFilterField.stringValue;
|
||||
|
||||
BOOL changed = NO;
|
||||
|
||||
|
@ -185,51 +201,51 @@
|
|||
@"Name" : name,
|
||||
@"File" : file
|
||||
};
|
||||
[fMessages addObject:message];
|
||||
[self.fMessages addObject:message];
|
||||
|
||||
if (currentMessage->level <= maxLevel && [self shouldIncludeMessageForFilter:filterString message:message])
|
||||
{
|
||||
[fDisplayedMessages addObject:message];
|
||||
[self.fDisplayedMessages addObject:message];
|
||||
changed = YES;
|
||||
}
|
||||
}
|
||||
|
||||
if (fMessages.count > TR_LOG_MAX_QUEUE_LENGTH)
|
||||
if (self.fMessages.count > TR_LOG_MAX_QUEUE_LENGTH)
|
||||
{
|
||||
NSUInteger const oldCount = fDisplayedMessages.count;
|
||||
NSUInteger const oldCount = self.fDisplayedMessages.count;
|
||||
|
||||
NSIndexSet* removeIndexes = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, fMessages.count - TR_LOG_MAX_QUEUE_LENGTH)];
|
||||
NSArray* itemsToRemove = [fMessages objectsAtIndexes:removeIndexes];
|
||||
NSIndexSet* removeIndexes = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, self.fMessages.count - TR_LOG_MAX_QUEUE_LENGTH)];
|
||||
NSArray* itemsToRemove = [self.fMessages objectsAtIndexes:removeIndexes];
|
||||
|
||||
[fMessages removeObjectsAtIndexes:removeIndexes];
|
||||
[fDisplayedMessages removeObjectsInArray:itemsToRemove];
|
||||
[self.fMessages removeObjectsAtIndexes:removeIndexes];
|
||||
[self.fDisplayedMessages removeObjectsInArray:itemsToRemove];
|
||||
|
||||
changed |= oldCount > fDisplayedMessages.count;
|
||||
changed |= oldCount > self.fDisplayedMessages.count;
|
||||
}
|
||||
|
||||
if (changed)
|
||||
{
|
||||
[fDisplayedMessages sortUsingDescriptors:fMessageTable.sortDescriptors];
|
||||
[self.fDisplayedMessages sortUsingDescriptors:self.fMessageTable.sortDescriptors];
|
||||
|
||||
[fMessageTable reloadData];
|
||||
[self.fMessageTable reloadData];
|
||||
if (shouldScroll)
|
||||
[fMessageTable scrollRowToVisible:fMessageTable.numberOfRows - 1];
|
||||
[self.fMessageTable scrollRowToVisible:self.fMessageTable.numberOfRows - 1];
|
||||
}
|
||||
|
||||
[fLock unlock];
|
||||
[self.fLock unlock];
|
||||
|
||||
tr_logFreeQueue(messages);
|
||||
}
|
||||
|
||||
- (NSInteger)numberOfRowsInTableView:(NSTableView*)tableView
|
||||
{
|
||||
return fDisplayedMessages.count;
|
||||
return self.fDisplayedMessages.count;
|
||||
}
|
||||
|
||||
- (id)tableView:(NSTableView*)tableView objectValueForTableColumn:(NSTableColumn*)column row:(NSInteger)row
|
||||
{
|
||||
NSString* ident = column.identifier;
|
||||
NSDictionary* message = fDisplayedMessages[row];
|
||||
NSDictionary* message = self.fDisplayedMessages[row];
|
||||
|
||||
if ([ident isEqualToString:@"Date"])
|
||||
{
|
||||
|
@ -264,18 +280,18 @@
|
|||
#warning don't cut off end
|
||||
- (CGFloat)tableView:(NSTableView*)tableView heightOfRow:(NSInteger)row
|
||||
{
|
||||
NSString* message = fDisplayedMessages[row][@"Message"];
|
||||
NSString* message = self.fDisplayedMessages[row][@"Message"];
|
||||
|
||||
NSTableColumn* column = [tableView tableColumnWithIdentifier:@"Message"];
|
||||
CGFloat const count = floorf([message sizeWithAttributes:fAttributes].width / column.width);
|
||||
CGFloat const count = floorf([message sizeWithAttributes:self.fAttributes].width / column.width);
|
||||
|
||||
return tableView.rowHeight * (count + 1.0);
|
||||
}
|
||||
|
||||
- (void)tableView:(NSTableView*)tableView sortDescriptorsDidChange:(NSArray*)oldDescriptors
|
||||
{
|
||||
[fDisplayedMessages sortUsingDescriptors:fMessageTable.sortDescriptors];
|
||||
[fMessageTable reloadData];
|
||||
[self.fDisplayedMessages sortUsingDescriptors:self.fMessageTable.sortDescriptors];
|
||||
[self.fMessageTable reloadData];
|
||||
}
|
||||
|
||||
- (NSString*)tableView:(NSTableView*)tableView
|
||||
|
@ -285,16 +301,16 @@
|
|||
row:(NSInteger)row
|
||||
mouseLocation:(NSPoint)mouseLocation
|
||||
{
|
||||
NSDictionary* message = fDisplayedMessages[row];
|
||||
NSDictionary* message = self.fDisplayedMessages[row];
|
||||
return message[@"File"];
|
||||
}
|
||||
|
||||
- (void)copy:(id)sender
|
||||
{
|
||||
NSIndexSet* indexes = fMessageTable.selectedRowIndexes;
|
||||
NSIndexSet* indexes = self.fMessageTable.selectedRowIndexes;
|
||||
NSMutableArray* messageStrings = [NSMutableArray arrayWithCapacity:indexes.count];
|
||||
|
||||
for (NSDictionary* message in [fDisplayedMessages objectsAtIndexes:indexes])
|
||||
for (NSDictionary* message in [self.fDisplayedMessages objectsAtIndexes:indexes])
|
||||
{
|
||||
[messageStrings addObject:[self stringForMessage:message]];
|
||||
}
|
||||
|
@ -312,7 +328,7 @@
|
|||
|
||||
if (action == @selector(copy:))
|
||||
{
|
||||
return fMessageTable.numberOfSelectedRows > 0;
|
||||
return self.fMessageTable.numberOfSelectedRows > 0;
|
||||
}
|
||||
|
||||
return YES;
|
||||
|
@ -321,7 +337,7 @@
|
|||
- (void)changeLevel:(id)sender
|
||||
{
|
||||
NSInteger level;
|
||||
switch (fLevelButton.indexOfSelectedItem)
|
||||
switch (self.fLevelButton.indexOfSelectedItem)
|
||||
{
|
||||
case LEVEL_ERROR:
|
||||
level = TR_LOG_ERROR;
|
||||
|
@ -333,7 +349,7 @@
|
|||
level = TR_LOG_DEBUG;
|
||||
break;
|
||||
default:
|
||||
NSAssert1(NO, @"Unknown message log level: %ld", [fLevelButton indexOfSelectedItem]);
|
||||
NSAssert1(NO, @"Unknown message log level: %ld", [self.fLevelButton indexOfSelectedItem]);
|
||||
level = TR_LOG_INFO;
|
||||
}
|
||||
|
||||
|
@ -344,37 +360,37 @@
|
|||
|
||||
[NSUserDefaults.standardUserDefaults setInteger:level forKey:@"MessageLevel"];
|
||||
|
||||
[fLock lock];
|
||||
[self.fLock lock];
|
||||
|
||||
[self updateListForFilter];
|
||||
|
||||
[fLock unlock];
|
||||
[self.fLock unlock];
|
||||
}
|
||||
|
||||
- (void)changeFilter:(id)sender
|
||||
{
|
||||
[fLock lock];
|
||||
[self.fLock lock];
|
||||
|
||||
[self updateListForFilter];
|
||||
|
||||
[fLock unlock];
|
||||
[self.fLock unlock];
|
||||
}
|
||||
|
||||
- (void)clearLog:(id)sender
|
||||
{
|
||||
[fLock lock];
|
||||
[self.fLock lock];
|
||||
|
||||
[fMessages removeAllObjects];
|
||||
[self.fMessages removeAllObjects];
|
||||
|
||||
[fMessageTable beginUpdates];
|
||||
[fMessageTable removeRowsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, fDisplayedMessages.count)]
|
||||
[self.fMessageTable beginUpdates];
|
||||
[self.fMessageTable removeRowsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, self.fDisplayedMessages.count)]
|
||||
withAnimation:NSTableViewAnimationSlideLeft];
|
||||
|
||||
[fDisplayedMessages removeAllObjects];
|
||||
[self.fDisplayedMessages removeAllObjects];
|
||||
|
||||
[fMessageTable endUpdates];
|
||||
[self.fMessageTable endUpdates];
|
||||
|
||||
[fLock unlock];
|
||||
[self.fLock unlock];
|
||||
}
|
||||
|
||||
- (void)writeToFile:(id)sender
|
||||
|
@ -391,7 +407,7 @@
|
|||
//make the array sorted by date
|
||||
NSSortDescriptor* descriptor = [NSSortDescriptor sortDescriptorWithKey:@"Index" ascending:YES];
|
||||
NSArray* descriptors = @[ descriptor ];
|
||||
NSArray* sortedMessages = [fDisplayedMessages sortedArrayUsingDescriptors:descriptors];
|
||||
NSArray* sortedMessages = [self.fDisplayedMessages sortedArrayUsingDescriptors:descriptors];
|
||||
|
||||
//create the text to output
|
||||
NSMutableArray* messageStrings = [NSMutableArray arrayWithCapacity:sortedMessages.count];
|
||||
|
@ -418,9 +434,11 @@
|
|||
}];
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
- (void)resizeColumn
|
||||
{
|
||||
[fMessageTable noteHeightOfRowsWithIndexesChanged:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, fMessageTable.numberOfRows)]];
|
||||
[self.fMessageTable noteHeightOfRowsWithIndexesChanged:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, self.fMessageTable.numberOfRows)]];
|
||||
}
|
||||
|
||||
- (BOOL)shouldIncludeMessageForFilter:(NSString*)filterString message:(NSDictionary*)message
|
||||
|
@ -438,17 +456,17 @@
|
|||
- (void)updateListForFilter
|
||||
{
|
||||
NSInteger const level = [NSUserDefaults.standardUserDefaults integerForKey:@"MessageLevel"];
|
||||
NSString* filterString = fFilterField.stringValue;
|
||||
NSString* filterString = self.fFilterField.stringValue;
|
||||
|
||||
NSIndexSet* indexes = [fMessages indexesOfObjectsWithOptions:NSEnumerationConcurrent
|
||||
NSIndexSet* indexes = [self.fMessages indexesOfObjectsWithOptions:NSEnumerationConcurrent
|
||||
passingTest:^BOOL(id message, NSUInteger idx, BOOL* stop) {
|
||||
return [((NSDictionary*)message)[@"Level"] integerValue] <= level &&
|
||||
[self shouldIncludeMessageForFilter:filterString message:message];
|
||||
}];
|
||||
|
||||
NSArray* tempMessages = [[fMessages objectsAtIndexes:indexes] sortedArrayUsingDescriptors:fMessageTable.sortDescriptors];
|
||||
NSArray* tempMessages = [[self.fMessages objectsAtIndexes:indexes] sortedArrayUsingDescriptors:self.fMessageTable.sortDescriptors];
|
||||
|
||||
[fMessageTable beginUpdates];
|
||||
[self.fMessageTable beginUpdates];
|
||||
|
||||
//figure out which rows were added/moved
|
||||
NSUInteger currentIndex = 0, totalCount = 0;
|
||||
|
@ -457,9 +475,9 @@
|
|||
|
||||
for (NSDictionary* message in tempMessages)
|
||||
{
|
||||
NSUInteger const previousIndex = [fDisplayedMessages
|
||||
NSUInteger const previousIndex = [self.fDisplayedMessages
|
||||
indexOfObject:message
|
||||
inRange:NSMakeRange(currentIndex, fDisplayedMessages.count - currentIndex)];
|
||||
inRange:NSMakeRange(currentIndex, self.fDisplayedMessages.count - currentIndex)];
|
||||
if (previousIndex == NSNotFound)
|
||||
{
|
||||
[itemsToAdd addObject:message];
|
||||
|
@ -469,8 +487,8 @@
|
|||
{
|
||||
if (previousIndex != currentIndex)
|
||||
{
|
||||
[fDisplayedMessages moveObjectAtIndex:previousIndex toIndex:currentIndex];
|
||||
[fMessageTable moveRowAtIndex:previousIndex toIndex:currentIndex];
|
||||
[self.fDisplayedMessages moveObjectAtIndex:previousIndex toIndex:currentIndex];
|
||||
[self.fMessageTable moveRowAtIndex:previousIndex toIndex:currentIndex];
|
||||
}
|
||||
++currentIndex;
|
||||
}
|
||||
|
@ -479,21 +497,21 @@
|
|||
}
|
||||
|
||||
//remove trailing items - those are the unused
|
||||
if (currentIndex < fDisplayedMessages.count)
|
||||
if (currentIndex < self.fDisplayedMessages.count)
|
||||
{
|
||||
NSRange const removeRange = NSMakeRange(currentIndex, fDisplayedMessages.count - currentIndex);
|
||||
[fDisplayedMessages removeObjectsInRange:removeRange];
|
||||
[fMessageTable removeRowsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:removeRange]
|
||||
NSRange const removeRange = NSMakeRange(currentIndex, self.fDisplayedMessages.count - currentIndex);
|
||||
[self.fDisplayedMessages removeObjectsInRange:removeRange];
|
||||
[self.fMessageTable removeRowsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:removeRange]
|
||||
withAnimation:NSTableViewAnimationSlideDown];
|
||||
}
|
||||
|
||||
//add new items
|
||||
[fDisplayedMessages insertObjects:itemsToAdd atIndexes:itemsToAddIndexes];
|
||||
[fMessageTable insertRowsAtIndexes:itemsToAddIndexes withAnimation:NSTableViewAnimationSlideUp];
|
||||
[self.fDisplayedMessages insertObjects:itemsToAdd atIndexes:itemsToAddIndexes];
|
||||
[self.fMessageTable insertRowsAtIndexes:itemsToAddIndexes withAnimation:NSTableViewAnimationSlideUp];
|
||||
|
||||
[fMessageTable endUpdates];
|
||||
[self.fMessageTable endUpdates];
|
||||
|
||||
NSAssert2([fDisplayedMessages isEqualToArray:tempMessages], @"Inconsistency between message arrays! %@ %@", fDisplayedMessages, tempMessages);
|
||||
NSAssert2([self.fDisplayedMessages isEqualToArray:tempMessages], @"Inconsistency between message arrays! %@ %@", self.fDisplayedMessages, tempMessages);
|
||||
}
|
||||
|
||||
- (NSString*)stringForMessage:(NSDictionary*)message
|
||||
|
|
|
@ -5,11 +5,7 @@
|
|||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
@interface PeerProgressIndicatorCell : NSLevelIndicatorCell
|
||||
{
|
||||
NSDictionary* fAttributes;
|
||||
BOOL fSeed;
|
||||
}
|
||||
|
||||
- (void)setSeed:(BOOL)seed;
|
||||
@property(nonatomic) BOOL seed;
|
||||
|
||||
@end
|
||||
|
|
|
@ -5,49 +5,50 @@
|
|||
#import "PeerProgressIndicatorCell.h"
|
||||
#import "NSStringAdditions.h"
|
||||
|
||||
@interface PeerProgressIndicatorCell ()
|
||||
|
||||
@property(nonatomic, copy) NSDictionary* fAttributes;
|
||||
|
||||
@end
|
||||
|
||||
@implementation PeerProgressIndicatorCell
|
||||
|
||||
- (id)copyWithZone:(NSZone*)zone
|
||||
{
|
||||
PeerProgressIndicatorCell* copy = [super copyWithZone:zone];
|
||||
copy->fAttributes = fAttributes;
|
||||
copy->_fAttributes = _fAttributes;
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
- (void)setSeed:(BOOL)seed
|
||||
{
|
||||
fSeed = seed;
|
||||
}
|
||||
|
||||
- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView*)controlView
|
||||
{
|
||||
if ([NSUserDefaults.standardUserDefaults boolForKey:@"DisplayPeerProgressBarNumber"])
|
||||
{
|
||||
if (!fAttributes)
|
||||
if (!self.fAttributes)
|
||||
{
|
||||
NSMutableParagraphStyle* paragraphStyle = [NSParagraphStyle.defaultParagraphStyle mutableCopy];
|
||||
paragraphStyle.alignment = NSTextAlignmentRight;
|
||||
|
||||
fAttributes = @{
|
||||
self.fAttributes = @{
|
||||
NSFontAttributeName : [NSFont systemFontOfSize:11.0],
|
||||
NSForegroundColorAttributeName : NSColor.labelColor,
|
||||
NSParagraphStyleAttributeName : paragraphStyle
|
||||
};
|
||||
}
|
||||
|
||||
[[NSString percentString:self.floatValue longDecimals:NO] drawInRect:cellFrame withAttributes:fAttributes];
|
||||
[[NSString percentString:self.floatValue longDecimals:NO] drawInRect:cellFrame withAttributes:self.fAttributes];
|
||||
}
|
||||
else
|
||||
{
|
||||
//attributes not needed anymore
|
||||
if (fAttributes)
|
||||
if (self.fAttributes)
|
||||
{
|
||||
fAttributes = nil;
|
||||
self.fAttributes = nil;
|
||||
}
|
||||
|
||||
[super drawWithFrame:cellFrame inView:controlView];
|
||||
if (fSeed)
|
||||
if (self.seed)
|
||||
{
|
||||
NSImage* checkImage = [NSImage imageNamed:@"CompleteCheck"];
|
||||
|
||||
|
|
|
@ -7,20 +7,8 @@
|
|||
@class Torrent;
|
||||
|
||||
@interface PiecesView : NSImageView
|
||||
{
|
||||
int8_t* fPieces;
|
||||
|
||||
NSColor* fGreenAvailabilityColor;
|
||||
NSColor* fBluePieceColor;
|
||||
|
||||
Torrent* fTorrent;
|
||||
NSInteger fNumPieces;
|
||||
NSInteger fAcross;
|
||||
NSInteger fWidth;
|
||||
NSInteger fExtraBorder;
|
||||
}
|
||||
|
||||
- (void)setTorrent:(Torrent*)torrent;
|
||||
@property(nonatomic) Torrent* torrent;
|
||||
|
||||
- (void)clearView;
|
||||
- (void)updateView;
|
||||
|
|
|
@ -23,37 +23,51 @@ enum
|
|||
PIECE_FLASHING
|
||||
};
|
||||
|
||||
@interface PiecesView ()
|
||||
|
||||
@property(nonatomic) int8_t* fPieces;
|
||||
|
||||
@property(nonatomic) NSColor* fGreenAvailabilityColor;
|
||||
@property(nonatomic) NSColor* fBluePieceColor;
|
||||
|
||||
@property(nonatomic) NSInteger fNumPieces;
|
||||
@property(nonatomic) NSInteger fAcross;
|
||||
@property(nonatomic) NSInteger fWidth;
|
||||
@property(nonatomic) NSInteger fExtraBorder;
|
||||
|
||||
@end
|
||||
|
||||
@implementation PiecesView
|
||||
|
||||
- (void)awakeFromNib
|
||||
{
|
||||
//store box colors
|
||||
fGreenAvailabilityColor = [NSColor colorWithCalibratedRed:0.0 green:1.0 blue:0.4 alpha:1.0];
|
||||
fBluePieceColor = [NSColor colorWithCalibratedRed:0.0 green:0.4 blue:0.8 alpha:1.0];
|
||||
self.fGreenAvailabilityColor = [NSColor colorWithCalibratedRed:0.0 green:1.0 blue:0.4 alpha:1.0];
|
||||
self.fBluePieceColor = [NSColor colorWithCalibratedRed:0.0 green:0.4 blue:0.8 alpha:1.0];
|
||||
|
||||
//actually draw the box
|
||||
[self setTorrent:nil];
|
||||
self.torrent = nil;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
tr_free(fPieces);
|
||||
tr_free(_fPieces);
|
||||
}
|
||||
|
||||
- (void)setTorrent:(Torrent*)torrent
|
||||
{
|
||||
[self clearView];
|
||||
|
||||
fTorrent = (torrent && !torrent.magnet) ? torrent : nil;
|
||||
if (fTorrent)
|
||||
_torrent = (torrent && !torrent.magnet) ? torrent : nil;
|
||||
if (_torrent)
|
||||
{
|
||||
//determine relevant values
|
||||
fNumPieces = MIN(fTorrent.pieceCount, MAX_ACROSS * MAX_ACROSS);
|
||||
fAcross = ceil(sqrt(fNumPieces));
|
||||
_fNumPieces = MIN(_torrent.pieceCount, MAX_ACROSS * MAX_ACROSS);
|
||||
_fAcross = ceil(sqrt(_fNumPieces));
|
||||
|
||||
CGFloat const width = self.bounds.size.width;
|
||||
fWidth = (width - (fAcross + 1) * BETWEEN) / fAcross;
|
||||
fExtraBorder = (width - ((fWidth + BETWEEN) * fAcross + BETWEEN)) / 2;
|
||||
_fWidth = (width - (_fAcross + 1) * BETWEEN) / _fAcross;
|
||||
_fExtraBorder = (width - ((_fWidth + BETWEEN) * _fAcross + BETWEEN)) / 2;
|
||||
}
|
||||
|
||||
NSImage* back = [[NSImage alloc] initWithSize:self.bounds.size];
|
||||
|
@ -71,22 +85,22 @@ enum
|
|||
|
||||
- (void)clearView
|
||||
{
|
||||
tr_free(fPieces);
|
||||
fPieces = NULL;
|
||||
tr_free(self.fPieces);
|
||||
self.fPieces = NULL;
|
||||
}
|
||||
|
||||
- (void)updateView
|
||||
{
|
||||
if (!fTorrent)
|
||||
if (!self.torrent)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//determine if first time
|
||||
BOOL const first = fPieces == NULL;
|
||||
BOOL const first = self.fPieces == NULL;
|
||||
if (first)
|
||||
{
|
||||
fPieces = (int8_t*)tr_malloc(fNumPieces * sizeof(int8_t));
|
||||
self.fPieces = (int8_t*)tr_malloc(self.fNumPieces * sizeof(int8_t));
|
||||
}
|
||||
|
||||
int8_t* pieces = NULL;
|
||||
|
@ -95,76 +109,76 @@ enum
|
|||
BOOL const showAvailablity = [NSUserDefaults.standardUserDefaults boolForKey:@"PiecesViewShowAvailability"];
|
||||
if (showAvailablity)
|
||||
{
|
||||
pieces = (int8_t*)tr_malloc(fNumPieces * sizeof(int8_t));
|
||||
[fTorrent getAvailability:pieces size:fNumPieces];
|
||||
pieces = (int8_t*)tr_malloc(self.fNumPieces * sizeof(int8_t));
|
||||
[self.torrent getAvailability:pieces size:self.fNumPieces];
|
||||
}
|
||||
else
|
||||
{
|
||||
piecesPercent = (float*)tr_malloc(fNumPieces * sizeof(float));
|
||||
[fTorrent getAmountFinished:piecesPercent size:fNumPieces];
|
||||
piecesPercent = (float*)tr_malloc(self.fNumPieces * sizeof(float));
|
||||
[self.torrent getAmountFinished:piecesPercent size:self.fNumPieces];
|
||||
}
|
||||
|
||||
NSImage* image = self.image;
|
||||
|
||||
NSRect fillRects[fNumPieces];
|
||||
NSColor* fillColors[fNumPieces];
|
||||
NSRect fillRects[self.fNumPieces];
|
||||
NSColor* fillColors[self.fNumPieces];
|
||||
|
||||
NSInteger usedCount = 0;
|
||||
|
||||
for (NSInteger index = 0; index < fNumPieces; index++)
|
||||
for (NSInteger index = 0; index < self.fNumPieces; index++)
|
||||
{
|
||||
NSColor* pieceColor = nil;
|
||||
|
||||
if (showAvailablity ? pieces[index] == -1 : piecesPercent[index] == 1.0)
|
||||
{
|
||||
if (first || fPieces[index] != PIECE_FINISHED)
|
||||
if (first || self.fPieces[index] != PIECE_FINISHED)
|
||||
{
|
||||
if (!first && fPieces[index] != PIECE_FLASHING)
|
||||
if (!first && self.fPieces[index] != PIECE_FLASHING)
|
||||
{
|
||||
pieceColor = NSColor.orangeColor;
|
||||
fPieces[index] = PIECE_FLASHING;
|
||||
self.fPieces[index] = PIECE_FLASHING;
|
||||
}
|
||||
else
|
||||
{
|
||||
pieceColor = fBluePieceColor;
|
||||
fPieces[index] = PIECE_FINISHED;
|
||||
pieceColor = self.fBluePieceColor;
|
||||
self.fPieces[index] = PIECE_FINISHED;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (showAvailablity ? pieces[index] == 0 : piecesPercent[index] == 0.0)
|
||||
{
|
||||
if (first || fPieces[index] != PIECE_NONE)
|
||||
if (first || self.fPieces[index] != PIECE_NONE)
|
||||
{
|
||||
pieceColor = NSColor.whiteColor;
|
||||
fPieces[index] = PIECE_NONE;
|
||||
self.fPieces[index] = PIECE_NONE;
|
||||
}
|
||||
}
|
||||
else if (showAvailablity && pieces[index] >= HIGH_PEERS)
|
||||
{
|
||||
if (first || fPieces[index] != PIECE_HIGH_PEERS)
|
||||
if (first || self.fPieces[index] != PIECE_HIGH_PEERS)
|
||||
{
|
||||
pieceColor = fGreenAvailabilityColor;
|
||||
fPieces[index] = PIECE_HIGH_PEERS;
|
||||
pieceColor = self.fGreenAvailabilityColor;
|
||||
self.fPieces[index] = PIECE_HIGH_PEERS;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//always redraw "mixed"
|
||||
CGFloat percent = showAvailablity ? (CGFloat)pieces[index] / HIGH_PEERS : piecesPercent[index];
|
||||
NSColor* fullColor = showAvailablity ? fGreenAvailabilityColor : fBluePieceColor;
|
||||
NSColor* fullColor = showAvailablity ? self.fGreenAvailabilityColor : self.fBluePieceColor;
|
||||
pieceColor = [NSColor.whiteColor blendedColorWithFraction:percent ofColor:fullColor];
|
||||
fPieces[index] = PIECE_SOME;
|
||||
self.fPieces[index] = PIECE_SOME;
|
||||
}
|
||||
|
||||
if (pieceColor)
|
||||
{
|
||||
NSInteger const across = index % fAcross;
|
||||
NSInteger const down = index / fAcross;
|
||||
NSInteger const across = index % self.fAcross;
|
||||
NSInteger const down = index / self.fAcross;
|
||||
fillRects[usedCount] = NSMakeRect(
|
||||
across * (fWidth + BETWEEN) + BETWEEN + fExtraBorder,
|
||||
image.size.width - (down + 1) * (fWidth + BETWEEN) - fExtraBorder,
|
||||
fWidth,
|
||||
fWidth);
|
||||
across * (self.fWidth + BETWEEN) + BETWEEN + self.fExtraBorder,
|
||||
image.size.width - (down + 1) * (self.fWidth + BETWEEN) - self.fExtraBorder,
|
||||
self.fWidth,
|
||||
self.fWidth);
|
||||
fillColors[usedCount] = pieceColor;
|
||||
|
||||
usedCount++;
|
||||
|
@ -190,7 +204,7 @@ enum
|
|||
|
||||
- (void)mouseDown:(NSEvent*)event
|
||||
{
|
||||
if (fTorrent)
|
||||
if (self.torrent)
|
||||
{
|
||||
BOOL const availability = ![NSUserDefaults.standardUserDefaults boolForKey:@"PiecesViewShowAvailability"];
|
||||
[NSUserDefaults.standardUserDefaults setBool:availability forKey:@"PiecesViewShowAvailability"];
|
||||
|
|
|
@ -12,19 +12,10 @@ typedef NS_ENUM(unsigned int, port_status_t) { //
|
|||
};
|
||||
|
||||
@interface PortChecker : NSObject
|
||||
{
|
||||
id fDelegate;
|
||||
port_status_t fStatus;
|
||||
|
||||
NSURLConnection* fConnection;
|
||||
NSMutableData* fPortProbeData;
|
||||
|
||||
NSTimer* fTimer;
|
||||
}
|
||||
@property(nonatomic, readonly) port_status_t status;
|
||||
|
||||
- (instancetype)initForPort:(NSInteger)portNumber delay:(BOOL)delay withDelegate:(id)delegate;
|
||||
- (void)cancelProbe;
|
||||
|
||||
@property(nonatomic, readonly) port_status_t status;
|
||||
|
||||
@end
|
||||
|
|
|
@ -9,6 +9,14 @@
|
|||
|
||||
@interface PortChecker ()
|
||||
|
||||
@property(nonatomic, weak) id fDelegate;
|
||||
@property(nonatomic) port_status_t fStatus;
|
||||
|
||||
@property(nonatomic) NSURLConnection* fConnection;
|
||||
@property(nonatomic) NSMutableData* fPortProbeData;
|
||||
|
||||
@property(nonatomic) NSTimer* fTimer;
|
||||
|
||||
- (void)startProbe:(NSTimer*)timer;
|
||||
|
||||
- (void)callBackWithStatus:(port_status_t)status;
|
||||
|
@ -21,16 +29,16 @@
|
|||
{
|
||||
if ((self = [super init]))
|
||||
{
|
||||
fDelegate = delegate;
|
||||
_fDelegate = delegate;
|
||||
|
||||
fStatus = PORT_STATUS_CHECKING;
|
||||
_fStatus = PORT_STATUS_CHECKING;
|
||||
|
||||
fTimer = [NSTimer scheduledTimerWithTimeInterval:CHECK_FIRE target:self selector:@selector(startProbe:)
|
||||
_fTimer = [NSTimer scheduledTimerWithTimeInterval:CHECK_FIRE target:self selector:@selector(startProbe:)
|
||||
userInfo:@(portNumber)
|
||||
repeats:NO];
|
||||
if (!delay)
|
||||
{
|
||||
[fTimer fire];
|
||||
[_fTimer fire];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -39,30 +47,30 @@
|
|||
|
||||
- (void)dealloc
|
||||
{
|
||||
[fTimer invalidate];
|
||||
[_fTimer invalidate];
|
||||
}
|
||||
|
||||
- (port_status_t)status
|
||||
{
|
||||
return fStatus;
|
||||
return self.fStatus;
|
||||
}
|
||||
|
||||
- (void)cancelProbe
|
||||
{
|
||||
[fTimer invalidate];
|
||||
fTimer = nil;
|
||||
[self.fTimer invalidate];
|
||||
self.fTimer = nil;
|
||||
|
||||
[fConnection cancel];
|
||||
[self.fConnection cancel];
|
||||
}
|
||||
|
||||
- (void)connection:(NSURLConnection*)connection didReceiveResponse:(NSURLResponse*)response
|
||||
{
|
||||
fPortProbeData.length = 0;
|
||||
self.fPortProbeData.length = 0;
|
||||
}
|
||||
|
||||
- (void)connection:(NSURLConnection*)connection didReceiveData:(NSData*)data
|
||||
{
|
||||
[fPortProbeData appendData:data];
|
||||
[self.fPortProbeData appendData:data];
|
||||
}
|
||||
|
||||
- (void)connection:(NSURLConnection*)connection didFailWithError:(NSError*)error
|
||||
|
@ -73,8 +81,8 @@
|
|||
|
||||
- (void)connectionDidFinishLoading:(NSURLConnection*)connection
|
||||
{
|
||||
NSString* probeString = [[NSString alloc] initWithData:fPortProbeData encoding:NSUTF8StringEncoding];
|
||||
fPortProbeData = nil;
|
||||
NSString* probeString = [[NSString alloc] initWithData:self.fPortProbeData encoding:NSUTF8StringEncoding];
|
||||
self.fPortProbeData = nil;
|
||||
|
||||
if (probeString)
|
||||
{
|
||||
|
@ -99,17 +107,19 @@
|
|||
}
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
- (void)startProbe:(NSTimer*)timer
|
||||
{
|
||||
fTimer = nil;
|
||||
self.fTimer = nil;
|
||||
|
||||
NSURLRequest* portProbeRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:CHECKER_URL([[timer userInfo] integerValue])]
|
||||
cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData
|
||||
timeoutInterval:15.0];
|
||||
|
||||
if ((fConnection = [[NSURLConnection alloc] initWithRequest:portProbeRequest delegate:self]))
|
||||
if ((self.fConnection = [[NSURLConnection alloc] initWithRequest:portProbeRequest delegate:self]))
|
||||
{
|
||||
fPortProbeData = [[NSMutableData alloc] init];
|
||||
self.fPortProbeData = [[NSMutableData alloc] init];
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -120,11 +130,11 @@
|
|||
|
||||
- (void)callBackWithStatus:(port_status_t)status
|
||||
{
|
||||
fStatus = status;
|
||||
self.fStatus = status;
|
||||
|
||||
if (fDelegate && [fDelegate respondsToSelector:@selector(portCheckerDidFinishProbing:)])
|
||||
if (self.fDelegate && [self.fDelegate respondsToSelector:@selector(portCheckerDidFinishProbing:)])
|
||||
{
|
||||
[fDelegate performSelectorOnMainThread:@selector(portCheckerDidFinishProbing:) withObject:self waitUntilDone:NO];
|
||||
[self.fDelegate performSelectorOnMainThread:@selector(portCheckerDidFinishProbing:) withObject:self waitUntilDone:NO];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,5 @@
|
|||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
@interface PredicateEditorRowTemplateAny : NSPredicateEditorRowTemplate
|
||||
{
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -6,174 +6,13 @@
|
|||
|
||||
#include <libtransmission/transmission.h>
|
||||
|
||||
@class PortChecker;
|
||||
|
||||
@interface PrefsController : NSWindowController<NSToolbarDelegate>
|
||||
{
|
||||
tr_session* fHandle;
|
||||
NSUserDefaults* fDefaults;
|
||||
BOOL fHasLoaded;
|
||||
|
||||
IBOutlet NSView* fGeneralView;
|
||||
IBOutlet NSView* fTransfersView;
|
||||
IBOutlet NSView* fBandwidthView;
|
||||
IBOutlet NSView* fPeersView;
|
||||
IBOutlet NSView* fNetworkView;
|
||||
IBOutlet NSView* fRemoteView;
|
||||
IBOutlet NSView* fGroupsView;
|
||||
|
||||
NSString* fInitialString;
|
||||
|
||||
IBOutlet NSButton* fSystemPreferencesButton;
|
||||
IBOutlet NSTextField* fCheckForUpdatesLabel;
|
||||
IBOutlet NSButton* fCheckForUpdatesButton;
|
||||
IBOutlet NSButton* fCheckForUpdatesBetaButton;
|
||||
|
||||
IBOutlet NSPopUpButton* fFolderPopUp;
|
||||
IBOutlet NSPopUpButton* fIncompleteFolderPopUp;
|
||||
IBOutlet NSPopUpButton* fImportFolderPopUp;
|
||||
IBOutlet NSPopUpButton* fDoneScriptPopUp;
|
||||
IBOutlet NSButton* fShowMagnetAddWindowCheck;
|
||||
IBOutlet NSTextField* fRatioStopField;
|
||||
IBOutlet NSTextField* fIdleStopField;
|
||||
IBOutlet NSTextField* fQueueDownloadField;
|
||||
IBOutlet NSTextField* fQueueSeedField;
|
||||
IBOutlet NSTextField* fStalledField;
|
||||
|
||||
IBOutlet NSTextField* fUploadField;
|
||||
IBOutlet NSTextField* fDownloadField;
|
||||
IBOutlet NSTextField* fSpeedLimitUploadField;
|
||||
IBOutlet NSTextField* fSpeedLimitDownloadField;
|
||||
IBOutlet NSPopUpButton* fAutoSpeedDayTypePopUp;
|
||||
|
||||
IBOutlet NSTextField* fPeersGlobalField;
|
||||
IBOutlet NSTextField* fPeersTorrentField;
|
||||
IBOutlet NSTextField* fBlocklistURLField;
|
||||
IBOutlet NSTextField* fBlocklistMessageField;
|
||||
IBOutlet NSTextField* fBlocklistDateField;
|
||||
IBOutlet NSButton* fBlocklistButton;
|
||||
|
||||
PortChecker* fPortChecker;
|
||||
IBOutlet NSTextField* fPortField;
|
||||
IBOutlet NSTextField* fPortStatusField;
|
||||
IBOutlet NSButton* fNatCheck;
|
||||
IBOutlet NSImageView* fPortStatusImage;
|
||||
IBOutlet NSProgressIndicator* fPortStatusProgress;
|
||||
NSTimer* fPortStatusTimer;
|
||||
int fPeerPort, fNatStatus;
|
||||
|
||||
IBOutlet NSTextField* fRPCPortField;
|
||||
IBOutlet NSTextField* fRPCPasswordField;
|
||||
IBOutlet NSTableView* fRPCWhitelistTable;
|
||||
NSMutableArray* fRPCWhitelistArray;
|
||||
IBOutlet NSSegmentedControl* fRPCAddRemoveControl;
|
||||
NSString* fRPCPassword;
|
||||
}
|
||||
|
||||
- (instancetype)initWithHandle:(tr_session*)handle;
|
||||
|
||||
- (void)setAutoUpdateToBeta:(id)sender;
|
||||
|
||||
- (void)setPort:(id)sender;
|
||||
- (void)randomPort:(id)sender;
|
||||
- (void)setRandomPortOnStart:(id)sender;
|
||||
- (void)setNat:(id)sender;
|
||||
- (void)updatePortStatus;
|
||||
- (void)portCheckerDidFinishProbing:(PortChecker*)portChecker;
|
||||
|
||||
@property(nonatomic, readonly) NSArray* sounds;
|
||||
- (void)setSound:(id)sender;
|
||||
|
||||
- (void)setUTP:(id)sender;
|
||||
|
||||
- (void)setPeersGlobal:(id)sender;
|
||||
- (void)setPeersTorrent:(id)sender;
|
||||
|
||||
- (void)setPEX:(id)sender;
|
||||
- (void)setDHT:(id)sender;
|
||||
- (void)setLPD:(id)sender;
|
||||
|
||||
- (void)setEncryptionMode:(id)sender;
|
||||
|
||||
- (void)setBlocklistEnabled:(id)sender;
|
||||
- (void)updateBlocklist:(id)sender;
|
||||
- (void)setBlocklistAutoUpdate:(id)sender;
|
||||
- (void)updateBlocklistFields;
|
||||
- (void)updateBlocklistURLField;
|
||||
- (void)updateBlocklistButton;
|
||||
|
||||
- (void)setAutoStartDownloads:(id)sender;
|
||||
|
||||
- (void)setBadge:(id)sender;
|
||||
|
||||
- (IBAction)openNotificationSystemPrefs:(NSButton*)sender;
|
||||
|
||||
- (void)resetWarnings:(id)sender;
|
||||
|
||||
- (void)setDefaultForMagnets:(id)sender;
|
||||
|
||||
- (void)setQueue:(id)sender;
|
||||
- (void)setQueueNumber:(id)sender;
|
||||
|
||||
- (void)setStalled:(id)sender;
|
||||
- (void)setStalledMinutes:(id)sender;
|
||||
|
||||
- (void)setDownloadLocation:(id)sender;
|
||||
- (void)folderSheetShow:(id)sender;
|
||||
- (void)incompleteFolderSheetShow:(id)sender;
|
||||
- (void)setUseIncompleteFolder:(id)sender;
|
||||
|
||||
- (void)setRenamePartialFiles:(id)sender;
|
||||
|
||||
- (IBAction)setShowAddMagnetWindow:(id)sender;
|
||||
- (void)updateShowAddMagnetWindowField;
|
||||
|
||||
- (void)setDoneScriptEnabled:(id)sender;
|
||||
- (void)doneScriptSheetShow:(id)sender;
|
||||
|
||||
- (void)applyRatioSetting:(id)sender;
|
||||
- (void)setRatioStop:(id)sender;
|
||||
- (void)updateRatioStopField;
|
||||
- (void)updateRatioStopFieldOld;
|
||||
|
||||
- (void)applyIdleStopSetting:(id)sender;
|
||||
- (void)setIdleStop:(id)sender;
|
||||
- (void)updateLimitStopField;
|
||||
|
||||
- (void)applySpeedSettings:(id)sender;
|
||||
- (void)applyAltSpeedSettings;
|
||||
|
||||
- (void)updateLimitFields;
|
||||
- (void)setGlobalLimit:(id)sender;
|
||||
|
||||
- (void)setSpeedLimit:(id)sender;
|
||||
- (void)setAutoSpeedLimit:(id)sender;
|
||||
- (void)setAutoSpeedLimitTime:(id)sender;
|
||||
- (void)setAutoSpeedLimitDay:(id)sender;
|
||||
+ (NSInteger)dateToTimeSum:(NSDate*)date;
|
||||
+ (NSDate*)timeSumToDate:(NSInteger)sum;
|
||||
|
||||
- (void)setAutoImport:(id)sender;
|
||||
- (void)importFolderSheetShow:(id)sender;
|
||||
|
||||
- (void)setAutoSize:(id)sender;
|
||||
|
||||
- (void)setRPCEnabled:(id)sender;
|
||||
- (void)linkWebUI:(id)sender;
|
||||
- (void)setRPCAuthorize:(id)sender;
|
||||
- (void)setRPCUsername:(id)sender;
|
||||
- (void)setRPCPassword:(id)sender;
|
||||
- (void)updateRPCPassword;
|
||||
- (void)setRPCPort:(id)sender;
|
||||
- (void)setRPCUseWhitelist:(id)sender;
|
||||
- (void)setRPCWebUIDiscovery:(id)sender;
|
||||
- (void)updateRPCWhitelist;
|
||||
- (void)addRemoveRPCIP:(id)sender;
|
||||
|
||||
- (void)helpForScript:(id)sender;
|
||||
- (void)helpForPeers:(id)sender;
|
||||
- (void)helpForNetwork:(id)sender;
|
||||
- (void)helpForRemote:(id)sender;
|
||||
- (instancetype)initWithHandle:(tr_session*)handle;
|
||||
|
||||
- (void)rpcUpdatePrefs;
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -5,7 +5,5 @@
|
|||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
@interface PrefsWindow : NSWindow
|
||||
{
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -5,25 +5,6 @@
|
|||
#import "ProgressGradients.h"
|
||||
#import "NSApplicationAdditions.h"
|
||||
|
||||
@implementation ProgressGradients (Private)
|
||||
|
||||
+ (NSGradient*)progressGradientForRed:(CGFloat)redComponent green:(CGFloat)greenComponent blue:(CGFloat)blueComponent
|
||||
{
|
||||
CGFloat const alpha = [NSUserDefaults.standardUserDefaults boolForKey:@"SmallView"] ? 0.27 : 1.0;
|
||||
|
||||
NSColor* baseColor = [NSColor colorWithCalibratedRed:redComponent green:greenComponent blue:blueComponent alpha:alpha];
|
||||
|
||||
NSColor* color2 = [NSColor colorWithCalibratedRed:redComponent * 0.95 green:greenComponent * 0.95 blue:blueComponent * 0.95
|
||||
alpha:alpha];
|
||||
|
||||
NSColor* color3 = [NSColor colorWithCalibratedRed:redComponent * 0.85 green:greenComponent * 0.85 blue:blueComponent * 0.85
|
||||
alpha:alpha];
|
||||
|
||||
return [[NSGradient alloc] initWithColorsAndLocations:baseColor, 0.0, color2, 0.5, color3, 0.5, baseColor, 1.0, nil];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation ProgressGradients
|
||||
|
||||
+ (NSGradient*)progressWhiteGradient
|
||||
|
@ -146,4 +127,21 @@
|
|||
}
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
+ (NSGradient*)progressGradientForRed:(CGFloat)redComponent green:(CGFloat)greenComponent blue:(CGFloat)blueComponent
|
||||
{
|
||||
CGFloat const alpha = [NSUserDefaults.standardUserDefaults boolForKey:@"SmallView"] ? 0.27 : 1.0;
|
||||
|
||||
NSColor* baseColor = [NSColor colorWithCalibratedRed:redComponent green:greenComponent blue:blueComponent alpha:alpha];
|
||||
|
||||
NSColor* color2 = [NSColor colorWithCalibratedRed:redComponent * 0.95 green:greenComponent * 0.95 blue:blueComponent * 0.95
|
||||
alpha:alpha];
|
||||
|
||||
NSColor* color3 = [NSColor colorWithCalibratedRed:redComponent * 0.85 green:greenComponent * 0.85 blue:blueComponent * 0.85
|
||||
alpha:alpha];
|
||||
|
||||
return [[NSGradient alloc] initWithColorsAndLocations:baseColor, 0.0, color2, 0.5, color3, 0.5, baseColor, 1.0, nil];
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -7,24 +7,6 @@
|
|||
#include <libtransmission/transmission.h>
|
||||
|
||||
@interface StatsWindowController : NSWindowController
|
||||
{
|
||||
IBOutlet NSTextField* fUploadedField;
|
||||
IBOutlet NSTextField* fUploadedAllField;
|
||||
IBOutlet NSTextField* fDownloadedField;
|
||||
IBOutlet NSTextField* fDownloadedAllField;
|
||||
IBOutlet NSTextField* fRatioField;
|
||||
IBOutlet NSTextField* fRatioAllField;
|
||||
IBOutlet NSTextField* fTimeField;
|
||||
IBOutlet NSTextField* fTimeAllField;
|
||||
IBOutlet NSTextField* fNumOpenedField;
|
||||
IBOutlet NSTextField* fUploadedLabelField;
|
||||
IBOutlet NSTextField* fDownloadedLabelField;
|
||||
IBOutlet NSTextField* fRatioLabelField;
|
||||
IBOutlet NSTextField* fTimeLabelField;
|
||||
IBOutlet NSTextField* fNumOpenedLabelField;
|
||||
IBOutlet NSButton* fResetButton;
|
||||
NSTimer* fTimer;
|
||||
}
|
||||
|
||||
@property(nonatomic, class, readonly) StatsWindowController* statsWindow;
|
||||
|
||||
|
|
|
@ -11,6 +11,23 @@
|
|||
|
||||
@interface StatsWindowController ()
|
||||
|
||||
@property(nonatomic) IBOutlet NSTextField* fUploadedField;
|
||||
@property(nonatomic) IBOutlet NSTextField* fUploadedAllField;
|
||||
@property(nonatomic) IBOutlet NSTextField* fDownloadedField;
|
||||
@property(nonatomic) IBOutlet NSTextField* fDownloadedAllField;
|
||||
@property(nonatomic) IBOutlet NSTextField* fRatioField;
|
||||
@property(nonatomic) IBOutlet NSTextField* fRatioAllField;
|
||||
@property(nonatomic) IBOutlet NSTextField* fTimeField;
|
||||
@property(nonatomic) IBOutlet NSTextField* fTimeAllField;
|
||||
@property(nonatomic) IBOutlet NSTextField* fNumOpenedField;
|
||||
@property(nonatomic) IBOutlet NSTextField* fUploadedLabelField;
|
||||
@property(nonatomic) IBOutlet NSTextField* fDownloadedLabelField;
|
||||
@property(nonatomic) IBOutlet NSTextField* fRatioLabelField;
|
||||
@property(nonatomic) IBOutlet NSTextField* fTimeLabelField;
|
||||
@property(nonatomic) IBOutlet NSTextField* fNumOpenedLabelField;
|
||||
@property(nonatomic) IBOutlet NSButton* fResetButton;
|
||||
@property(nonatomic) NSTimer* fTimer;
|
||||
|
||||
- (void)updateStats;
|
||||
|
||||
- (void)performResetStats;
|
||||
|
@ -43,26 +60,26 @@ tr_session* fLib = NULL;
|
|||
{
|
||||
[self updateStats];
|
||||
|
||||
fTimer = [NSTimer scheduledTimerWithTimeInterval:UPDATE_SECONDS target:self selector:@selector(updateStats) userInfo:nil
|
||||
self.fTimer = [NSTimer scheduledTimerWithTimeInterval:UPDATE_SECONDS target:self selector:@selector(updateStats) userInfo:nil
|
||||
repeats:YES];
|
||||
[NSRunLoop.currentRunLoop addTimer:fTimer forMode:NSModalPanelRunLoopMode];
|
||||
[NSRunLoop.currentRunLoop addTimer:fTimer forMode:NSEventTrackingRunLoopMode];
|
||||
[NSRunLoop.currentRunLoop addTimer:self.fTimer forMode:NSModalPanelRunLoopMode];
|
||||
[NSRunLoop.currentRunLoop addTimer:self.fTimer forMode:NSEventTrackingRunLoopMode];
|
||||
|
||||
self.window.restorationClass = [self class];
|
||||
|
||||
self.window.title = NSLocalizedString(@"Statistics", "Stats window -> title");
|
||||
|
||||
//set label text
|
||||
fUploadedLabelField.stringValue = [NSLocalizedString(@"Uploaded", "Stats window -> label") stringByAppendingString:@":"];
|
||||
fDownloadedLabelField.stringValue = [NSLocalizedString(@"Downloaded", "Stats window -> label") stringByAppendingString:@":"];
|
||||
fRatioLabelField.stringValue = [NSLocalizedString(@"Ratio", "Stats window -> label") stringByAppendingString:@":"];
|
||||
fTimeLabelField.stringValue = [NSLocalizedString(@"Running Time", "Stats window -> label") stringByAppendingString:@":"];
|
||||
fNumOpenedLabelField.stringValue = [NSLocalizedString(@"Program Started", "Stats window -> label") stringByAppendingString:@":"];
|
||||
self.fUploadedLabelField.stringValue = [NSLocalizedString(@"Uploaded", "Stats window -> label") stringByAppendingString:@":"];
|
||||
self.fDownloadedLabelField.stringValue = [NSLocalizedString(@"Downloaded", "Stats window -> label") stringByAppendingString:@":"];
|
||||
self.fRatioLabelField.stringValue = [NSLocalizedString(@"Ratio", "Stats window -> label") stringByAppendingString:@":"];
|
||||
self.fTimeLabelField.stringValue = [NSLocalizedString(@"Running Time", "Stats window -> label") stringByAppendingString:@":"];
|
||||
self.fNumOpenedLabelField.stringValue = [NSLocalizedString(@"Program Started", "Stats window -> label") stringByAppendingString:@":"];
|
||||
|
||||
//size of all labels
|
||||
CGFloat const oldWidth = fUploadedLabelField.frame.size.width;
|
||||
CGFloat const oldWidth = self.fUploadedLabelField.frame.size.width;
|
||||
|
||||
NSArray* labels = @[ fUploadedLabelField, fDownloadedLabelField, fRatioLabelField, fTimeLabelField, fNumOpenedLabelField ];
|
||||
NSArray* labels = @[ self.fUploadedLabelField, self.fDownloadedLabelField, self.fRatioLabelField, self.fTimeLabelField, self.fNumOpenedLabelField ];
|
||||
|
||||
CGFloat maxWidth = CGFLOAT_MIN;
|
||||
for (NSTextField* label in labels)
|
||||
|
@ -86,21 +103,21 @@ tr_session* fLib = NULL;
|
|||
[self.window setFrame:windowRect display:YES];
|
||||
|
||||
//resize reset button
|
||||
CGFloat const oldButtonWidth = fResetButton.frame.size.width;
|
||||
CGFloat const oldButtonWidth = self.fResetButton.frame.size.width;
|
||||
|
||||
fResetButton.title = NSLocalizedString(@"Reset", "Stats window -> reset button");
|
||||
[fResetButton sizeToFit];
|
||||
self.fResetButton.title = NSLocalizedString(@"Reset", "Stats window -> reset button");
|
||||
[self.fResetButton sizeToFit];
|
||||
|
||||
NSRect buttonFrame = fResetButton.frame;
|
||||
NSRect buttonFrame = self.fResetButton.frame;
|
||||
buttonFrame.size.width += 10.0;
|
||||
buttonFrame.origin.x -= buttonFrame.size.width - oldButtonWidth;
|
||||
fResetButton.frame = buttonFrame;
|
||||
self.fResetButton.frame = buttonFrame;
|
||||
}
|
||||
|
||||
- (void)windowWillClose:(id)sender
|
||||
{
|
||||
[fTimer invalidate];
|
||||
fTimer = nil;
|
||||
[self.fTimer invalidate];
|
||||
self.fTimer = nil;
|
||||
fStatsWindowInstance = nil;
|
||||
}
|
||||
|
||||
|
@ -152,6 +169,8 @@ tr_session* fLib = NULL;
|
|||
return @"StatsWindow";
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
- (void)updateStats
|
||||
{
|
||||
tr_session_stats statsAll, statsSession;
|
||||
|
@ -161,24 +180,24 @@ tr_session* fLib = NULL;
|
|||
NSByteCountFormatter* byteFormatter = [[NSByteCountFormatter alloc] init];
|
||||
byteFormatter.allowedUnits = NSByteCountFormatterUseBytes;
|
||||
|
||||
fUploadedField.stringValue = [NSString stringForFileSize:statsSession.uploadedBytes];
|
||||
fUploadedField.toolTip = [byteFormatter stringFromByteCount:statsSession.uploadedBytes];
|
||||
fUploadedAllField.stringValue = [NSString
|
||||
self.fUploadedField.stringValue = [NSString stringForFileSize:statsSession.uploadedBytes];
|
||||
self.fUploadedField.toolTip = [byteFormatter stringFromByteCount:statsSession.uploadedBytes];
|
||||
self.fUploadedAllField.stringValue = [NSString
|
||||
stringWithFormat:NSLocalizedString(@"%@ total", "stats total"), [NSString stringForFileSize:statsAll.uploadedBytes]];
|
||||
fUploadedAllField.toolTip = [byteFormatter stringFromByteCount:statsAll.uploadedBytes];
|
||||
self.fUploadedAllField.toolTip = [byteFormatter stringFromByteCount:statsAll.uploadedBytes];
|
||||
|
||||
fDownloadedField.stringValue = [NSString stringForFileSize:statsSession.downloadedBytes];
|
||||
fDownloadedField.toolTip = [byteFormatter stringFromByteCount:statsSession.downloadedBytes];
|
||||
fDownloadedAllField.stringValue = [NSString
|
||||
self.fDownloadedField.stringValue = [NSString stringForFileSize:statsSession.downloadedBytes];
|
||||
self.fDownloadedField.toolTip = [byteFormatter stringFromByteCount:statsSession.downloadedBytes];
|
||||
self.fDownloadedAllField.stringValue = [NSString
|
||||
stringWithFormat:NSLocalizedString(@"%@ total", "stats total"), [NSString stringForFileSize:statsAll.downloadedBytes]];
|
||||
fDownloadedAllField.toolTip = [byteFormatter stringFromByteCount:statsAll.downloadedBytes];
|
||||
self.fDownloadedAllField.toolTip = [byteFormatter stringFromByteCount:statsAll.downloadedBytes];
|
||||
|
||||
fRatioField.stringValue = [NSString stringForRatio:statsSession.ratio];
|
||||
self.fRatioField.stringValue = [NSString stringForRatio:statsSession.ratio];
|
||||
|
||||
NSString* totalRatioString = statsAll.ratio != TR_RATIO_NA ?
|
||||
[NSString stringWithFormat:NSLocalizedString(@"%@ total", "stats total"), [NSString stringForRatio:statsAll.ratio]] :
|
||||
NSLocalizedString(@"Total N/A", "stats total");
|
||||
fRatioAllField.stringValue = totalRatioString;
|
||||
self.fRatioAllField.stringValue = totalRatioString;
|
||||
|
||||
static NSDateComponentsFormatter* timeFormatter;
|
||||
static dispatch_once_t onceToken;
|
||||
|
@ -190,17 +209,17 @@ tr_session* fLib = NULL;
|
|||
NSCalendarUnitHour | NSCalendarUnitMinute;
|
||||
});
|
||||
|
||||
fTimeField.stringValue = [timeFormatter stringFromTimeInterval:statsSession.secondsActive];
|
||||
fTimeAllField.stringValue = [NSString stringWithFormat:NSLocalizedString(@"%@ total", "stats total"),
|
||||
self.fTimeField.stringValue = [timeFormatter stringFromTimeInterval:statsSession.secondsActive];
|
||||
self.fTimeAllField.stringValue = [NSString stringWithFormat:NSLocalizedString(@"%@ total", "stats total"),
|
||||
[timeFormatter stringFromTimeInterval:statsAll.secondsActive]];
|
||||
|
||||
if (statsAll.sessionCount == 1)
|
||||
{
|
||||
fNumOpenedField.stringValue = NSLocalizedString(@"1 time", "stats window -> times opened");
|
||||
self.fNumOpenedField.stringValue = NSLocalizedString(@"1 time", "stats window -> times opened");
|
||||
}
|
||||
else
|
||||
{
|
||||
fNumOpenedField.stringValue = [NSString stringWithFormat:NSLocalizedString(@"%@ times", "stats window -> times opened"),
|
||||
self.fNumOpenedField.stringValue = [NSString stringWithFormat:NSLocalizedString(@"%@ times", "stats window -> times opened"),
|
||||
[NSString formattedUInteger:statsAll.sessionCount]];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,23 +7,10 @@
|
|||
#include <libtransmission/transmission.h>
|
||||
|
||||
@interface StatusBarController : NSViewController
|
||||
{
|
||||
IBOutlet NSButton* fStatusButton;
|
||||
IBOutlet NSTextField* fTotalDLField;
|
||||
IBOutlet NSTextField* fTotalULField;
|
||||
IBOutlet NSImageView* fTotalDLImageView;
|
||||
IBOutlet NSImageView* fTotalULImageView;
|
||||
|
||||
tr_session* fLib;
|
||||
|
||||
CGFloat fPreviousDownloadRate;
|
||||
CGFloat fPreviousUploadRate;
|
||||
}
|
||||
|
||||
- (instancetype)initWithLib:(tr_session*)lib;
|
||||
|
||||
- (void)updateWithDownload:(CGFloat)dlRate upload:(CGFloat)ulRate;
|
||||
- (void)setStatusLabel:(id)sender;
|
||||
|
||||
- (void)updateSpeedFieldsToolTips;
|
||||
|
||||
|
|
|
@ -21,6 +21,17 @@ typedef NS_ENUM(unsigned int, statusTag) {
|
|||
|
||||
@interface StatusBarController ()
|
||||
|
||||
@property(nonatomic) IBOutlet NSButton* fStatusButton;
|
||||
@property(nonatomic) IBOutlet NSTextField* fTotalDLField;
|
||||
@property(nonatomic) IBOutlet NSTextField* fTotalULField;
|
||||
@property(nonatomic) IBOutlet NSImageView* fTotalDLImageView;
|
||||
@property(nonatomic) IBOutlet NSImageView* fTotalULImageView;
|
||||
|
||||
@property(nonatomic, readonly) tr_session* fLib;
|
||||
|
||||
@property(nonatomic) CGFloat fPreviousDownloadRate;
|
||||
@property(nonatomic) CGFloat fPreviousUploadRate;
|
||||
|
||||
- (void)resizeStatusButton;
|
||||
|
||||
@end
|
||||
|
@ -31,10 +42,10 @@ typedef NS_ENUM(unsigned int, statusTag) {
|
|||
{
|
||||
if ((self = [super initWithNibName:@"StatusBar" bundle:nil]))
|
||||
{
|
||||
fLib = lib;
|
||||
_fLib = lib;
|
||||
|
||||
fPreviousDownloadRate = -1.0;
|
||||
fPreviousUploadRate = -1.0;
|
||||
_fPreviousDownloadRate = -1.0;
|
||||
_fPreviousUploadRate = -1.0;
|
||||
}
|
||||
|
||||
return self;
|
||||
|
@ -43,16 +54,16 @@ typedef NS_ENUM(unsigned int, statusTag) {
|
|||
- (void)awakeFromNib
|
||||
{
|
||||
//localize menu items
|
||||
[fStatusButton.menu itemWithTag:STATUS_RATIO_TOTAL_TAG].title = NSLocalizedString(@"Total Ratio", "Status Bar -> status menu");
|
||||
[fStatusButton.menu itemWithTag:STATUS_RATIO_SESSION_TAG].title = NSLocalizedString(@"Session Ratio", "Status Bar -> status menu");
|
||||
[fStatusButton.menu itemWithTag:STATUS_TRANSFER_TOTAL_TAG].title = NSLocalizedString(@"Total Transfer", "Status Bar -> status menu");
|
||||
[fStatusButton.menu itemWithTag:STATUS_TRANSFER_SESSION_TAG].title = NSLocalizedString(@"Session Transfer", "Status Bar -> status menu");
|
||||
[self.fStatusButton.menu itemWithTag:STATUS_RATIO_TOTAL_TAG].title = NSLocalizedString(@"Total Ratio", "Status Bar -> status menu");
|
||||
[self.fStatusButton.menu itemWithTag:STATUS_RATIO_SESSION_TAG].title = NSLocalizedString(@"Session Ratio", "Status Bar -> status menu");
|
||||
[self.fStatusButton.menu itemWithTag:STATUS_TRANSFER_TOTAL_TAG].title = NSLocalizedString(@"Total Transfer", "Status Bar -> status menu");
|
||||
[self.fStatusButton.menu itemWithTag:STATUS_TRANSFER_SESSION_TAG].title = NSLocalizedString(@"Session Transfer", "Status Bar -> status menu");
|
||||
|
||||
fStatusButton.cell.backgroundStyle = NSBackgroundStyleRaised;
|
||||
fTotalDLField.cell.backgroundStyle = NSBackgroundStyleRaised;
|
||||
fTotalULField.cell.backgroundStyle = NSBackgroundStyleRaised;
|
||||
fTotalDLImageView.cell.backgroundStyle = NSBackgroundStyleRaised;
|
||||
fTotalULImageView.cell.backgroundStyle = NSBackgroundStyleRaised;
|
||||
self.fStatusButton.cell.backgroundStyle = NSBackgroundStyleRaised;
|
||||
self.fTotalDLField.cell.backgroundStyle = NSBackgroundStyleRaised;
|
||||
self.fTotalULField.cell.backgroundStyle = NSBackgroundStyleRaised;
|
||||
self.fTotalDLImageView.cell.backgroundStyle = NSBackgroundStyleRaised;
|
||||
self.fTotalULImageView.cell.backgroundStyle = NSBackgroundStyleRaised;
|
||||
|
||||
[self updateSpeedFieldsToolTips];
|
||||
|
||||
|
@ -72,16 +83,16 @@ typedef NS_ENUM(unsigned int, statusTag) {
|
|||
- (void)updateWithDownload:(CGFloat)dlRate upload:(CGFloat)ulRate
|
||||
{
|
||||
//set rates
|
||||
if (dlRate != fPreviousDownloadRate)
|
||||
if (dlRate != self.fPreviousDownloadRate)
|
||||
{
|
||||
fTotalDLField.stringValue = [NSString stringForSpeed:dlRate];
|
||||
fPreviousDownloadRate = dlRate;
|
||||
self.fTotalDLField.stringValue = [NSString stringForSpeed:dlRate];
|
||||
self.fPreviousDownloadRate = dlRate;
|
||||
}
|
||||
|
||||
if (ulRate != fPreviousUploadRate)
|
||||
if (ulRate != self.fPreviousUploadRate)
|
||||
{
|
||||
fTotalULField.stringValue = [NSString stringForSpeed:ulRate];
|
||||
fPreviousUploadRate = ulRate;
|
||||
self.fTotalULField.stringValue = [NSString stringForSpeed:ulRate];
|
||||
self.fPreviousUploadRate = ulRate;
|
||||
}
|
||||
|
||||
//set status button text
|
||||
|
@ -92,11 +103,11 @@ typedef NS_ENUM(unsigned int, statusTag) {
|
|||
tr_session_stats stats;
|
||||
if (total)
|
||||
{
|
||||
tr_sessionGetCumulativeStats(fLib, &stats);
|
||||
tr_sessionGetCumulativeStats(self.fLib, &stats);
|
||||
}
|
||||
else
|
||||
{
|
||||
tr_sessionGetStats(fLib, &stats);
|
||||
tr_sessionGetStats(self.fLib, &stats);
|
||||
}
|
||||
|
||||
statusString = [NSLocalizedString(@"Ratio", "status bar -> status label")
|
||||
|
@ -109,11 +120,11 @@ typedef NS_ENUM(unsigned int, statusTag) {
|
|||
tr_session_stats stats;
|
||||
if (total)
|
||||
{
|
||||
tr_sessionGetCumulativeStats(fLib, &stats);
|
||||
tr_sessionGetCumulativeStats(self.fLib, &stats);
|
||||
}
|
||||
else
|
||||
{
|
||||
tr_sessionGetStats(fLib, &stats);
|
||||
tr_sessionGetStats(self.fLib, &stats);
|
||||
}
|
||||
|
||||
statusString = [NSString stringWithFormat:@"%@: %@ %@: %@",
|
||||
|
@ -123,9 +134,9 @@ typedef NS_ENUM(unsigned int, statusTag) {
|
|||
[NSString stringForFileSize:stats.uploadedBytes]];
|
||||
}
|
||||
|
||||
if (![fStatusButton.title isEqualToString:statusString])
|
||||
if (![self.fStatusButton.title isEqualToString:statusString])
|
||||
{
|
||||
fStatusButton.title = statusString;
|
||||
self.fStatusButton.title = statusString;
|
||||
[self resizeStatusButton];
|
||||
}
|
||||
}
|
||||
|
@ -196,8 +207,8 @@ typedef NS_ENUM(unsigned int, statusTag) {
|
|||
uploadText = [NSLocalizedString(@"Global upload limit", "Status Bar -> speed tooltip") stringByAppendingFormat:@": %@", uploadText];
|
||||
downloadText = [NSLocalizedString(@"Global download limit", "Status Bar -> speed tooltip") stringByAppendingFormat:@": %@", downloadText];
|
||||
|
||||
fTotalULField.toolTip = uploadText;
|
||||
fTotalDLField.toolTip = downloadText;
|
||||
self.fTotalULField.toolTip = uploadText;
|
||||
self.fTotalDLField.toolTip = downloadText;
|
||||
}
|
||||
|
||||
- (BOOL)validateMenuItem:(NSMenuItem*)menuItem
|
||||
|
@ -236,21 +247,23 @@ typedef NS_ENUM(unsigned int, statusTag) {
|
|||
return YES;
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
- (void)resizeStatusButton
|
||||
{
|
||||
[fStatusButton sizeToFit];
|
||||
[self.fStatusButton sizeToFit];
|
||||
|
||||
//width ends up being too long
|
||||
NSRect statusFrame = fStatusButton.frame;
|
||||
NSRect statusFrame = self.fStatusButton.frame;
|
||||
statusFrame.size.width -= 25.0;
|
||||
|
||||
CGFloat const difference = NSMaxX(statusFrame) + 5.0 - NSMinX(fTotalDLImageView.frame);
|
||||
CGFloat const difference = NSMaxX(statusFrame) + 5.0 - NSMinX(self.fTotalDLImageView.frame);
|
||||
if (difference > 0.0)
|
||||
{
|
||||
statusFrame.size.width -= difference;
|
||||
}
|
||||
|
||||
fStatusButton.frame = statusFrame;
|
||||
self.fStatusButton.frame = statusFrame;
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -3,10 +3,7 @@
|
|||
// License text can be found in the licenses/ folder.
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import <QuartzCore/QuartzCore.h>
|
||||
|
||||
@interface StatusBarView : NSView
|
||||
{
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -36,6 +36,8 @@
|
|||
}
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
- (void)reload
|
||||
{
|
||||
self.needsDisplay = YES;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -5,25 +5,11 @@
|
|||
#import <AppKit/AppKit.h>
|
||||
|
||||
@interface TorrentCell : NSActionCell
|
||||
{
|
||||
NSUserDefaults* fDefaults;
|
||||
|
||||
NSMutableDictionary* fTitleAttributes;
|
||||
NSMutableDictionary* fStatusAttributes;
|
||||
|
||||
BOOL fTracking;
|
||||
BOOL fMouseDownControlButton;
|
||||
BOOL fMouseDownRevealButton;
|
||||
BOOL fMouseDownActionButton;
|
||||
BOOL fHover;
|
||||
BOOL fHoverControl;
|
||||
BOOL fHoverReveal;
|
||||
BOOL fHoverAction;
|
||||
|
||||
NSColor* fBarBorderColor;
|
||||
NSColor* fBluePieceColor;
|
||||
NSColor* fBarMinimalBorderColor;
|
||||
}
|
||||
@property(nonatomic) BOOL hover;
|
||||
@property(nonatomic) BOOL hoverControl;
|
||||
@property(nonatomic) BOOL hoverReveal;
|
||||
@property(nonatomic) BOOL hoverAction;
|
||||
|
||||
- (NSRect)iconRectForBounds:(NSRect)bounds;
|
||||
|
||||
|
@ -31,10 +17,5 @@
|
|||
inRect:(NSRect)cellFrame
|
||||
withUserInfo:(NSDictionary*)userInfo
|
||||
mouseLocation:(NSPoint)mouseLocation;
|
||||
- (void)setHover:(BOOL)hover;
|
||||
- (void)setControlHover:(BOOL)hover;
|
||||
- (void)setRevealHover:(BOOL)hover;
|
||||
- (void)setActionHover:(BOOL)hover;
|
||||
- (void)setActionPushed:(BOOL)pushed;
|
||||
|
||||
@end
|
||||
|
|
|
@ -60,6 +60,20 @@
|
|||
- (NSRect)revealButtonRectForBounds:(NSRect)bounds;
|
||||
- (NSRect)actionButtonRectForBounds:(NSRect)bounds;
|
||||
|
||||
@property(nonatomic, readonly) NSUserDefaults* fDefaults;
|
||||
|
||||
@property(nonatomic, readonly) NSMutableDictionary* fTitleAttributes;
|
||||
@property(nonatomic, readonly) NSMutableDictionary* fStatusAttributes;
|
||||
|
||||
@property(nonatomic) BOOL fTracking;
|
||||
@property(nonatomic) BOOL fMouseDownControlButton;
|
||||
@property(nonatomic) BOOL fMouseDownRevealButton;
|
||||
@property(nonatomic) BOOL fMouseDownActionButton;
|
||||
|
||||
@property(nonatomic, readonly) NSColor* fBarBorderColor;
|
||||
@property(nonatomic, readonly) NSColor* fBluePieceColor;
|
||||
@property(nonatomic, readonly) NSColor* fBarMinimalBorderColor;
|
||||
|
||||
@property(nonatomic, readonly) NSAttributedString* attributedTitle;
|
||||
- (NSAttributedString*)attributedStatusString:(NSString*)string;
|
||||
|
||||
|
@ -76,22 +90,22 @@
|
|||
{
|
||||
if ((self = [super init]))
|
||||
{
|
||||
fDefaults = NSUserDefaults.standardUserDefaults;
|
||||
_fDefaults = NSUserDefaults.standardUserDefaults;
|
||||
|
||||
NSMutableParagraphStyle* paragraphStyle = [NSParagraphStyle.defaultParagraphStyle mutableCopy];
|
||||
paragraphStyle.lineBreakMode = NSLineBreakByTruncatingMiddle;
|
||||
|
||||
fTitleAttributes = [[NSMutableDictionary alloc] initWithCapacity:3];
|
||||
fTitleAttributes[NSFontAttributeName] = [NSFont messageFontOfSize:12.0];
|
||||
fTitleAttributes[NSParagraphStyleAttributeName] = paragraphStyle;
|
||||
_fTitleAttributes = [[NSMutableDictionary alloc] initWithCapacity:3];
|
||||
_fTitleAttributes[NSFontAttributeName] = [NSFont messageFontOfSize:12.0];
|
||||
_fTitleAttributes[NSParagraphStyleAttributeName] = paragraphStyle;
|
||||
|
||||
fStatusAttributes = [[NSMutableDictionary alloc] initWithCapacity:3];
|
||||
fStatusAttributes[NSFontAttributeName] = [NSFont messageFontOfSize:9.0];
|
||||
fStatusAttributes[NSParagraphStyleAttributeName] = paragraphStyle;
|
||||
_fStatusAttributes = [[NSMutableDictionary alloc] initWithCapacity:3];
|
||||
_fStatusAttributes[NSFontAttributeName] = [NSFont messageFontOfSize:9.0];
|
||||
_fStatusAttributes[NSParagraphStyleAttributeName] = paragraphStyle;
|
||||
|
||||
fBluePieceColor = [NSColor colorWithCalibratedRed:0.0 green:0.4 blue:0.8 alpha:1.0];
|
||||
fBarBorderColor = [NSColor colorWithCalibratedWhite:0.0 alpha:0.2];
|
||||
fBarMinimalBorderColor = [NSColor colorWithCalibratedWhite:0.0 alpha:0.015];
|
||||
_fBluePieceColor = [NSColor colorWithCalibratedRed:0.0 green:0.4 blue:0.8 alpha:1.0];
|
||||
_fBarBorderColor = [NSColor colorWithCalibratedWhite:0.0 alpha:0.2];
|
||||
_fBarMinimalBorderColor = [NSColor colorWithCalibratedWhite:0.0 alpha:0.015];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
@ -105,7 +119,7 @@
|
|||
|
||||
- (NSRect)iconRectForBounds:(NSRect)bounds
|
||||
{
|
||||
CGFloat const imageSize = [fDefaults boolForKey:@"SmallView"] ? IMAGE_SIZE_MIN : IMAGE_SIZE_REG;
|
||||
CGFloat const imageSize = [self.fDefaults boolForKey:@"SmallView"] ? IMAGE_SIZE_MIN : IMAGE_SIZE_REG;
|
||||
|
||||
return NSMakeRect(NSMinX(bounds) + PADDING_HORIZONTAL, ceil(NSMidY(bounds) - imageSize * 0.5), imageSize, imageSize);
|
||||
}
|
||||
|
@ -130,7 +144,7 @@
|
|||
|
||||
- (BOOL)trackMouse:(NSEvent*)event inRect:(NSRect)cellFrame ofView:(NSView*)controlView untilMouseUp:(BOOL)flag
|
||||
{
|
||||
fTracking = YES;
|
||||
self.fTracking = YES;
|
||||
|
||||
self.controlView = controlView;
|
||||
|
||||
|
@ -151,18 +165,18 @@
|
|||
if (checkControl)
|
||||
{
|
||||
BOOL const inControlButton = NSMouseInRect(point, controlRect, controlView.flipped);
|
||||
if (fMouseDownControlButton != inControlButton)
|
||||
if (self.fMouseDownControlButton != inControlButton)
|
||||
{
|
||||
fMouseDownControlButton = inControlButton;
|
||||
self.fMouseDownControlButton = inControlButton;
|
||||
[controlView setNeedsDisplayInRect:cellFrame];
|
||||
}
|
||||
}
|
||||
else if (checkReveal)
|
||||
{
|
||||
BOOL const inRevealButton = NSMouseInRect(point, revealRect, controlView.flipped);
|
||||
if (fMouseDownRevealButton != inRevealButton)
|
||||
if (self.fMouseDownRevealButton != inRevealButton)
|
||||
{
|
||||
fMouseDownRevealButton = inRevealButton;
|
||||
self.fMouseDownRevealButton = inRevealButton;
|
||||
[controlView setNeedsDisplayInRect:cellFrame];
|
||||
}
|
||||
}
|
||||
|
@ -178,17 +192,17 @@
|
|||
NSEventMaskMouseExited)];
|
||||
}
|
||||
|
||||
fTracking = NO;
|
||||
self.fTracking = NO;
|
||||
|
||||
if (fMouseDownControlButton)
|
||||
if (self.fMouseDownControlButton)
|
||||
{
|
||||
fMouseDownControlButton = NO;
|
||||
self.fMouseDownControlButton = NO;
|
||||
|
||||
[(TorrentTableView*)controlView toggleControlForTorrent:self.representedObject];
|
||||
}
|
||||
else if (fMouseDownRevealButton)
|
||||
else if (self.fMouseDownRevealButton)
|
||||
{
|
||||
fMouseDownRevealButton = NO;
|
||||
self.fMouseDownRevealButton = NO;
|
||||
[controlView setNeedsDisplayInRect:cellFrame];
|
||||
|
||||
NSString* location = ((Torrent*)self.representedObject).dataLocation;
|
||||
|
@ -212,13 +226,13 @@
|
|||
NSTrackingAreaOptions const options = NSTrackingEnabledDuringMouseDrag | NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways;
|
||||
|
||||
//whole row
|
||||
if ([fDefaults boolForKey:@"SmallView"])
|
||||
if ([self.fDefaults boolForKey:@"SmallView"])
|
||||
{
|
||||
NSTrackingAreaOptions rowOptions = options;
|
||||
if (NSMouseInRect(mouseLocation, cellFrame, controlView.flipped))
|
||||
{
|
||||
rowOptions |= NSTrackingAssumeInside;
|
||||
[(TorrentTableView*)controlView setRowHover:[userInfo[@"Row"] integerValue]];
|
||||
((TorrentTableView*)controlView).hoverRow = [userInfo[@"Row"] integerValue];
|
||||
}
|
||||
|
||||
NSMutableDictionary* rowInfo = [userInfo mutableCopy];
|
||||
|
@ -233,7 +247,7 @@
|
|||
if (NSMouseInRect(mouseLocation, controlButtonRect, controlView.flipped))
|
||||
{
|
||||
controlOptions |= NSTrackingAssumeInside;
|
||||
[(TorrentTableView*)controlView setControlButtonHover:[userInfo[@"Row"] integerValue]];
|
||||
((TorrentTableView*)controlView).controlButtonHoverRow = [userInfo[@"Row"] integerValue];
|
||||
}
|
||||
|
||||
NSMutableDictionary* controlInfo = [userInfo mutableCopy];
|
||||
|
@ -248,7 +262,7 @@
|
|||
if (NSMouseInRect(mouseLocation, revealButtonRect, controlView.flipped))
|
||||
{
|
||||
revealOptions |= NSTrackingAssumeInside;
|
||||
[(TorrentTableView*)controlView setRevealButtonHover:[userInfo[@"Row"] integerValue]];
|
||||
((TorrentTableView*)controlView).revealButtonHoverRow = [userInfo[@"Row"] integerValue];
|
||||
}
|
||||
|
||||
NSMutableDictionary* revealInfo = [userInfo mutableCopy];
|
||||
|
@ -262,7 +276,7 @@
|
|||
if (NSMouseInRect(mouseLocation, actionButtonRect, controlView.flipped))
|
||||
{
|
||||
actionOptions |= NSTrackingAssumeInside;
|
||||
[(TorrentTableView*)controlView setActionButtonHover:[userInfo[@"Row"] integerValue]];
|
||||
((TorrentTableView*)controlView).actionButtonHoverRow = [userInfo[@"Row"] integerValue];
|
||||
}
|
||||
|
||||
NSMutableDictionary* actionInfo = [userInfo mutableCopy];
|
||||
|
@ -271,37 +285,12 @@
|
|||
[controlView addTrackingArea:area];
|
||||
}
|
||||
|
||||
- (void)setHover:(BOOL)hover
|
||||
{
|
||||
fHover = hover;
|
||||
}
|
||||
|
||||
- (void)setControlHover:(BOOL)hover
|
||||
{
|
||||
fHoverControl = hover;
|
||||
}
|
||||
|
||||
- (void)setRevealHover:(BOOL)hover
|
||||
{
|
||||
fHoverReveal = hover;
|
||||
}
|
||||
|
||||
- (void)setActionHover:(BOOL)hover
|
||||
{
|
||||
fHoverAction = hover;
|
||||
}
|
||||
|
||||
- (void)setActionPushed:(BOOL)pushed
|
||||
{
|
||||
fMouseDownActionButton = pushed;
|
||||
}
|
||||
|
||||
- (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView*)controlView
|
||||
{
|
||||
Torrent* torrent = self.representedObject;
|
||||
NSAssert(torrent != nil, @"can't have a TorrentCell without a Torrent");
|
||||
|
||||
BOOL const minimal = [fDefaults boolForKey:@"SmallView"];
|
||||
BOOL const minimal = [self.fDefaults boolForKey:@"SmallView"];
|
||||
|
||||
//bar
|
||||
[self drawBar:minimal ? [self barRectMinForBounds:cellFrame] : [self barRectRegForBounds:cellFrame]];
|
||||
|
@ -340,7 +329,7 @@
|
|||
BOOL const error = torrent.anyErrorOrWarning;
|
||||
|
||||
//icon
|
||||
if (!minimal || !(!fTracking && fHoverAction)) //don't show in minimal mode when hovered over
|
||||
if (!minimal || !(!self.fTracking && self.hoverAction)) //don't show in minimal mode when hovered over
|
||||
{
|
||||
NSImage* icon = (minimal && error) ? [NSImage imageNamed:NSImageNameCaution] : torrent.icon;
|
||||
[icon drawInRect:iconRect fromRect:NSZeroRect operation:NSCompositingOperationSourceOver fraction:1.0 respectFlipped:YES hints:nil];
|
||||
|
@ -367,8 +356,8 @@
|
|||
statusColor = NSColor.secondaryLabelColor;
|
||||
}
|
||||
|
||||
fTitleAttributes[NSForegroundColorAttributeName] = titleColor;
|
||||
fStatusAttributes[NSForegroundColorAttributeName] = statusColor;
|
||||
self.fTitleAttributes[NSForegroundColorAttributeName] = titleColor;
|
||||
self.fStatusAttributes[NSForegroundColorAttributeName] = statusColor;
|
||||
|
||||
//minimal status
|
||||
CGFloat minimalTitleRightBound;
|
||||
|
@ -377,7 +366,7 @@
|
|||
NSAttributedString* minimalString = [self attributedStatusString:self.minimalStatusString];
|
||||
NSRect minimalStatusRect = [self rectForMinimalStatusWithString:minimalString inBounds:cellFrame];
|
||||
|
||||
if (!fHover)
|
||||
if (!self.hover)
|
||||
{
|
||||
[minimalString drawInRect:minimalStatusRect];
|
||||
}
|
||||
|
@ -394,15 +383,15 @@
|
|||
[progressString drawInRect:progressRect];
|
||||
}
|
||||
|
||||
if (!minimal || fHover)
|
||||
if (!minimal || self.hover)
|
||||
{
|
||||
//control button
|
||||
NSString* controlImageSuffix;
|
||||
if (fMouseDownControlButton)
|
||||
if (self.fMouseDownControlButton)
|
||||
{
|
||||
controlImageSuffix = @"On";
|
||||
}
|
||||
else if (!fTracking && fHoverControl)
|
||||
else if (!self.fTracking && self.hoverControl)
|
||||
{
|
||||
controlImageSuffix = @"Hover";
|
||||
}
|
||||
|
@ -439,11 +428,11 @@
|
|||
|
||||
//reveal button
|
||||
NSString* revealImageString;
|
||||
if (fMouseDownRevealButton)
|
||||
if (self.fMouseDownRevealButton)
|
||||
{
|
||||
revealImageString = @"RevealOn";
|
||||
}
|
||||
else if (!fTracking && fHoverReveal)
|
||||
else if (!self.fTracking && self.hoverReveal)
|
||||
{
|
||||
revealImageString = @"RevealHover";
|
||||
}
|
||||
|
@ -461,12 +450,12 @@
|
|||
//action button
|
||||
#warning image should use new gear
|
||||
NSString* actionImageString;
|
||||
if (fMouseDownActionButton)
|
||||
if (self.fMouseDownActionButton)
|
||||
{
|
||||
#warning we can get rid of this on 10.7
|
||||
actionImageString = @"ActionOn";
|
||||
}
|
||||
else if (!fTracking && fHoverAction)
|
||||
else if (!self.fTracking && self.hoverAction)
|
||||
{
|
||||
actionImageString = @"ActionHover";
|
||||
}
|
||||
|
@ -520,7 +509,7 @@
|
|||
|
||||
- (NSRect)expansionFrameWithFrame:(NSRect)cellFrame inView:(NSView*)view
|
||||
{
|
||||
BOOL minimal = [fDefaults boolForKey:@"SmallView"];
|
||||
BOOL minimal = [self.fDefaults boolForKey:@"SmallView"];
|
||||
|
||||
//this code needs to match the code in drawInteriorWithFrame:withView:
|
||||
CGFloat minimalTitleRightBound;
|
||||
|
@ -532,7 +521,7 @@
|
|||
minimalTitleRightBound = NSMinX(minimalStatusRect);
|
||||
}
|
||||
|
||||
if (!minimal || fHover)
|
||||
if (!minimal || self.hover)
|
||||
{
|
||||
NSRect const controlRect = [self controlButtonRectForBounds:cellFrame];
|
||||
minimalTitleRightBound = MIN(minimalTitleRightBound, NSMinX(controlRect));
|
||||
|
@ -558,14 +547,16 @@
|
|||
cellFrame.origin.x += PADDING_EXPANSION_FRAME;
|
||||
cellFrame.origin.y += PADDING_EXPANSION_FRAME;
|
||||
|
||||
fTitleAttributes[NSForegroundColorAttributeName] = NSColor.labelColor;
|
||||
self.fTitleAttributes[NSForegroundColorAttributeName] = NSColor.labelColor;
|
||||
NSAttributedString* titleString = self.attributedTitle;
|
||||
[titleString drawInRect:cellFrame];
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
- (void)drawBar:(NSRect)barRect
|
||||
{
|
||||
BOOL const minimal = [fDefaults boolForKey:@"SmallView"];
|
||||
BOOL const minimal = [self.fDefaults boolForKey:@"SmallView"];
|
||||
|
||||
CGFloat const piecesBarPercent = ((TorrentTableView*)self.controlView).piecesBarPercent;
|
||||
if (piecesBarPercent > 0.0)
|
||||
|
@ -583,7 +574,7 @@
|
|||
[self drawRegularBar:barRect];
|
||||
}
|
||||
|
||||
NSColor* borderColor = minimal ? fBarMinimalBorderColor : fBarBorderColor;
|
||||
NSColor* borderColor = minimal ? self.fBarMinimalBorderColor : self.fBarBorderColor;
|
||||
[borderColor set];
|
||||
[NSBezierPath strokeRect:NSInsetRect(barRect, 0.5, 0.5)];
|
||||
}
|
||||
|
@ -644,7 +635,7 @@
|
|||
NSDivideRect(missingRect, &wantedRect, &missingRect, widthRemaining, NSMinXEdge);
|
||||
|
||||
//not-available section
|
||||
if (torrent.active && !torrent.checking && torrent.availableDesired < 1.0 && [fDefaults boolForKey:@"DisplayProgressBarAvailable"])
|
||||
if (torrent.active && !torrent.checking && torrent.availableDesired < 1.0 && [self.fDefaults boolForKey:@"DisplayProgressBarAvailable"])
|
||||
{
|
||||
NSRect unavailableRect;
|
||||
NSDivideRect(wantedRect, &wantedRect, &unavailableRect, round(NSWidth(wantedRect) * torrent.availableDesired), NSMinXEdge);
|
||||
|
@ -677,7 +668,7 @@
|
|||
//fill an all-white bar for magnet links
|
||||
if (torrent.magnet)
|
||||
{
|
||||
[[NSColor colorWithCalibratedWhite:1.0 alpha:[fDefaults boolForKey:@"SmallView"] ? 0.25 : 1.0] set];
|
||||
[[NSColor colorWithCalibratedWhite:1.0 alpha:[self.fDefaults boolForKey:@"SmallView"] ? 0.25 : 1.0] set];
|
||||
NSRectFillUsingOperation(barRect, NSCompositingOperationSourceOver);
|
||||
return;
|
||||
}
|
||||
|
@ -709,13 +700,13 @@
|
|||
}
|
||||
else
|
||||
{
|
||||
pieceColor = fBluePieceColor;
|
||||
pieceColor = self.fBluePieceColor;
|
||||
}
|
||||
[finishedIndexes addIndex:i];
|
||||
}
|
||||
else
|
||||
{
|
||||
pieceColor = [NSColor.whiteColor blendedColorWithFraction:piecesPercent[i] ofColor:fBluePieceColor];
|
||||
pieceColor = [NSColor.whiteColor blendedColorWithFraction:piecesPercent[i] ofColor:self.fBluePieceColor];
|
||||
}
|
||||
|
||||
//it's faster to just set color instead of checking previous color
|
||||
|
@ -728,7 +719,7 @@
|
|||
|
||||
//actually draw image
|
||||
[bitmap drawInRect:barRect fromRect:NSZeroRect operation:NSCompositingOperationSourceOver
|
||||
fraction:([fDefaults boolForKey:@"SmallView"] ? 0.25 : 1.0)respectFlipped:YES
|
||||
fraction:([self.fDefaults boolForKey:@"SmallView"] ? 0.25 : 1.0)respectFlipped:YES
|
||||
hints:nil];
|
||||
}
|
||||
|
||||
|
@ -745,7 +736,7 @@
|
|||
|
||||
- (NSRect)rectForTitleWithString:(NSAttributedString*)string withRightBound:(CGFloat)rightBound inBounds:(NSRect)bounds
|
||||
{
|
||||
BOOL const minimal = [fDefaults boolForKey:@"SmallView"];
|
||||
BOOL const minimal = [self.fDefaults boolForKey:@"SmallView"];
|
||||
|
||||
NSRect result;
|
||||
result.origin.x = NSMinX(bounds) + PADDING_HORIZONTAL + (minimal ? IMAGE_SIZE_MIN : IMAGE_SIZE_REG) + PADDING_BETWEEN_IMAGE_AND_TITLE;
|
||||
|
@ -827,7 +818,7 @@
|
|||
result.size.width = NORMAL_BUTTON_WIDTH;
|
||||
result.origin.x = NSMaxX(bounds) - (PADDING_HORIZONTAL + NORMAL_BUTTON_WIDTH + PADDING_BETWEEN_BUTTONS + NORMAL_BUTTON_WIDTH);
|
||||
|
||||
if (![fDefaults boolForKey:@"SmallView"])
|
||||
if (![self.fDefaults boolForKey:@"SmallView"])
|
||||
{
|
||||
result.origin.y = NSMinY(bounds) + PADDING_ABOVE_TITLE + HEIGHT_TITLE - (NORMAL_BUTTON_WIDTH - BAR_HEIGHT) * 0.5 +
|
||||
PADDING_BETWEEN_TITLE_AND_PROGRESS + HEIGHT_STATUS + PADDING_BETWEEN_PROGRESS_AND_BAR;
|
||||
|
@ -847,7 +838,7 @@
|
|||
result.size.width = NORMAL_BUTTON_WIDTH;
|
||||
result.origin.x = NSMaxX(bounds) - (PADDING_HORIZONTAL + NORMAL_BUTTON_WIDTH);
|
||||
|
||||
if (![fDefaults boolForKey:@"SmallView"])
|
||||
if (![self.fDefaults boolForKey:@"SmallView"])
|
||||
{
|
||||
result.origin.y = NSMinY(bounds) + PADDING_ABOVE_TITLE + HEIGHT_TITLE - (NORMAL_BUTTON_WIDTH - BAR_HEIGHT) * 0.5 +
|
||||
PADDING_BETWEEN_TITLE_AND_PROGRESS + HEIGHT_STATUS + PADDING_BETWEEN_PROGRESS_AND_BAR;
|
||||
|
@ -871,21 +862,21 @@
|
|||
- (NSAttributedString*)attributedTitle
|
||||
{
|
||||
NSString* title = ((Torrent*)self.representedObject).name;
|
||||
return [[NSAttributedString alloc] initWithString:title attributes:fTitleAttributes];
|
||||
return [[NSAttributedString alloc] initWithString:title attributes:self.fTitleAttributes];
|
||||
}
|
||||
|
||||
- (NSAttributedString*)attributedStatusString:(NSString*)string
|
||||
{
|
||||
return [[NSAttributedString alloc] initWithString:string attributes:fStatusAttributes];
|
||||
return [[NSAttributedString alloc] initWithString:string attributes:self.fStatusAttributes];
|
||||
}
|
||||
|
||||
- (NSString*)buttonString
|
||||
{
|
||||
if (fMouseDownRevealButton || (!fTracking && fHoverReveal))
|
||||
if (self.fMouseDownRevealButton || (!self.fTracking && self.hoverReveal))
|
||||
{
|
||||
return NSLocalizedString(@"Show the data file in Finder", "Torrent cell -> button info");
|
||||
}
|
||||
else if (fMouseDownControlButton || (!fTracking && fHoverControl))
|
||||
else if (self.fMouseDownControlButton || (!self.fTracking && self.hoverControl))
|
||||
{
|
||||
Torrent* torrent = self.representedObject;
|
||||
if (torrent.active)
|
||||
|
@ -906,7 +897,7 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
else if (!fTracking && fHoverAction)
|
||||
else if (!self.fTracking && self.hoverAction)
|
||||
{
|
||||
return NSLocalizedString(@"Change transfer settings", "Torrent Table -> tooltip");
|
||||
}
|
||||
|
@ -932,7 +923,7 @@
|
|||
- (NSString*)minimalStatusString
|
||||
{
|
||||
Torrent* torrent = self.representedObject;
|
||||
return [fDefaults boolForKey:@"DisplaySmallStatusRegular"] ? torrent.shortStatusString : torrent.remainingTimeString;
|
||||
return [self.fDefaults boolForKey:@"DisplaySmallStatusRegular"] ? torrent.shortStatusString : torrent.remainingTimeString;
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -5,10 +5,6 @@
|
|||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
@interface TorrentGroup : NSObject
|
||||
{
|
||||
NSInteger fGroup;
|
||||
NSMutableArray* fTorrents;
|
||||
}
|
||||
|
||||
- (instancetype)initWithGroup:(NSInteger)group;
|
||||
|
||||
|
|
|
@ -15,36 +15,26 @@
|
|||
{
|
||||
if ((self = [super init]))
|
||||
{
|
||||
fGroup = group;
|
||||
fTorrents = [[NSMutableArray alloc] init];
|
||||
_groupIndex = group;
|
||||
_torrents = [[NSMutableArray alloc] init];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSString*)description
|
||||
{
|
||||
return [NSString stringWithFormat:@"Torrent Group %ld: %@", fGroup, fTorrents];
|
||||
}
|
||||
|
||||
- (NSInteger)groupIndex
|
||||
{
|
||||
return fGroup;
|
||||
return [NSString stringWithFormat:@"Torrent Group %ld: %@", self.groupIndex, self.torrents];
|
||||
}
|
||||
|
||||
- (NSInteger)groupOrderValue
|
||||
{
|
||||
return [GroupsController.groups rowValueForIndex:fGroup];
|
||||
}
|
||||
|
||||
- (NSMutableArray*)torrents
|
||||
{
|
||||
return fTorrents;
|
||||
return [GroupsController.groups rowValueForIndex:self.groupIndex];
|
||||
}
|
||||
|
||||
- (CGFloat)ratio
|
||||
{
|
||||
uint64_t uploaded = 0, downloaded = 0;
|
||||
for (Torrent* torrent in fTorrents)
|
||||
for (Torrent* torrent in self.torrents)
|
||||
{
|
||||
uploaded += torrent.uploadedTotal;
|
||||
downloaded += torrent.downloadedTotal;
|
||||
|
@ -56,7 +46,7 @@
|
|||
- (CGFloat)uploadRate
|
||||
{
|
||||
CGFloat rate = 0.0;
|
||||
for (Torrent* torrent in fTorrents)
|
||||
for (Torrent* torrent in self.torrents)
|
||||
{
|
||||
rate += torrent.uploadRate;
|
||||
}
|
||||
|
@ -67,7 +57,7 @@
|
|||
- (CGFloat)downloadRate
|
||||
{
|
||||
CGFloat rate = 0.0;
|
||||
for (Torrent* torrent in fTorrents)
|
||||
for (Torrent* torrent in self.torrents)
|
||||
{
|
||||
rate += torrent.downloadRate;
|
||||
}
|
||||
|
|
|
@ -6,44 +6,11 @@
|
|||
|
||||
#include <libtransmission/transmission.h>
|
||||
|
||||
@class Controller;
|
||||
@class Torrent;
|
||||
@class TorrentCell;
|
||||
|
||||
#define GROUP_SEPARATOR_HEIGHT 18.0
|
||||
|
||||
@interface TorrentTableView : NSOutlineView<NSOutlineViewDelegate, NSAnimationDelegate, NSPopoverDelegate>
|
||||
{
|
||||
IBOutlet Controller* fController;
|
||||
|
||||
TorrentCell* fTorrentCell;
|
||||
|
||||
NSUserDefaults* fDefaults;
|
||||
|
||||
NSMutableIndexSet* fCollapsedGroups;
|
||||
|
||||
IBOutlet NSMenu* fContextRow;
|
||||
IBOutlet NSMenu* fContextNoRow;
|
||||
|
||||
NSInteger fMouseRow;
|
||||
NSInteger fMouseControlRow;
|
||||
NSInteger fMouseRevealRow;
|
||||
NSInteger fMouseActionRow;
|
||||
NSArray* fSelectedValues;
|
||||
|
||||
IBOutlet NSMenu* fActionMenu;
|
||||
IBOutlet NSMenu* fUploadMenu;
|
||||
IBOutlet NSMenu* fDownloadMenu;
|
||||
IBOutlet NSMenu* fRatioMenu;
|
||||
IBOutlet NSMenu* fPriorityMenu;
|
||||
IBOutlet NSMenuItem* fGlobalLimitItem;
|
||||
Torrent* fMenuTorrent;
|
||||
|
||||
CGFloat fPiecesBarPercent;
|
||||
NSAnimation* fPiecesBarAnimation;
|
||||
|
||||
BOOL fActionPopoverShown;
|
||||
}
|
||||
|
||||
- (BOOL)isGroupCollapsed:(NSInteger)value;
|
||||
- (void)removeCollapsedGroup:(NSInteger)value;
|
||||
|
@ -51,10 +18,10 @@
|
|||
- (void)saveCollapsedGroups;
|
||||
|
||||
- (void)removeTrackingAreas;
|
||||
- (void)setRowHover:(NSInteger)row;
|
||||
- (void)setControlButtonHover:(NSInteger)row;
|
||||
- (void)setRevealButtonHover:(NSInteger)row;
|
||||
- (void)setActionButtonHover:(NSInteger)row;
|
||||
@property(nonatomic) NSInteger hoverRow;
|
||||
@property(nonatomic) NSInteger controlButtonHoverRow;
|
||||
@property(nonatomic) NSInteger revealButtonHoverRow;
|
||||
@property(nonatomic) NSInteger actionButtonHoverRow;
|
||||
|
||||
- (void)selectValues:(NSArray*)values;
|
||||
@property(nonatomic, readonly) NSArray* selectedValues;
|
||||
|
|
|
@ -27,6 +27,32 @@
|
|||
|
||||
@interface TorrentTableView ()
|
||||
|
||||
@property(nonatomic) IBOutlet Controller* fController;
|
||||
|
||||
@property(nonatomic) TorrentCell* fTorrentCell;
|
||||
|
||||
@property(nonatomic, readonly) NSUserDefaults* fDefaults;
|
||||
|
||||
@property(nonatomic, readonly) NSMutableIndexSet* fCollapsedGroups;
|
||||
|
||||
@property(nonatomic) IBOutlet NSMenu* fContextRow;
|
||||
@property(nonatomic) IBOutlet NSMenu* fContextNoRow;
|
||||
|
||||
@property(nonatomic) NSArray* fSelectedValues;
|
||||
|
||||
@property(nonatomic) IBOutlet NSMenu* fActionMenu;
|
||||
@property(nonatomic) IBOutlet NSMenu* fUploadMenu;
|
||||
@property(nonatomic) IBOutlet NSMenu* fDownloadMenu;
|
||||
@property(nonatomic) IBOutlet NSMenu* fRatioMenu;
|
||||
@property(nonatomic) IBOutlet NSMenu* fPriorityMenu;
|
||||
@property(nonatomic) IBOutlet NSMenuItem* fGlobalLimitItem;
|
||||
@property(nonatomic, readonly) Torrent* fMenuTorrent;
|
||||
|
||||
@property(nonatomic) CGFloat piecesBarPercent;
|
||||
@property(nonatomic) NSAnimation* fPiecesBarAnimation;
|
||||
|
||||
@property(nonatomic) BOOL fActionPopoverShown;
|
||||
|
||||
- (BOOL)pointInGroupStatusRect:(NSPoint)point;
|
||||
|
||||
- (void)setGroupStatusColumns;
|
||||
|
@ -39,30 +65,30 @@
|
|||
{
|
||||
if ((self = [super initWithCoder:decoder]))
|
||||
{
|
||||
fDefaults = NSUserDefaults.standardUserDefaults;
|
||||
_fDefaults = NSUserDefaults.standardUserDefaults;
|
||||
|
||||
fTorrentCell = [[TorrentCell alloc] init];
|
||||
_fTorrentCell = [[TorrentCell alloc] init];
|
||||
|
||||
NSData* groupData = [fDefaults dataForKey:@"CollapsedGroups"];
|
||||
NSData* groupData = [_fDefaults dataForKey:@"CollapsedGroups"];
|
||||
if (groupData)
|
||||
{
|
||||
fCollapsedGroups = [[NSUnarchiver unarchiveObjectWithData:groupData] mutableCopy];
|
||||
_fCollapsedGroups = [[NSUnarchiver unarchiveObjectWithData:groupData] mutableCopy];
|
||||
}
|
||||
else
|
||||
{
|
||||
fCollapsedGroups = [[NSMutableIndexSet alloc] init];
|
||||
_fCollapsedGroups = [[NSMutableIndexSet alloc] init];
|
||||
}
|
||||
|
||||
fMouseRow = -1;
|
||||
fMouseControlRow = -1;
|
||||
fMouseRevealRow = -1;
|
||||
fMouseActionRow = -1;
|
||||
_hoverRow = -1;
|
||||
_controlButtonHoverRow = -1;
|
||||
_revealButtonHoverRow = -1;
|
||||
_actionButtonHoverRow = -1;
|
||||
|
||||
fActionPopoverShown = NO;
|
||||
_fActionPopoverShown = NO;
|
||||
|
||||
self.delegate = self;
|
||||
|
||||
fPiecesBarPercent = [fDefaults boolForKey:@"PiecesBar"] ? 1.0 : 0.0;
|
||||
_piecesBarPercent = [_fDefaults boolForKey:@"PiecesBar"] ? 1.0 : 0.0;
|
||||
|
||||
if (@available(macOS 11.0, *))
|
||||
{
|
||||
|
@ -93,7 +119,7 @@
|
|||
value = MAX_GROUP;
|
||||
}
|
||||
|
||||
return [fCollapsedGroups containsIndex:value];
|
||||
return [self.fCollapsedGroups containsIndex:value];
|
||||
}
|
||||
|
||||
- (void)removeCollapsedGroup:(NSInteger)value
|
||||
|
@ -103,17 +129,17 @@
|
|||
value = MAX_GROUP;
|
||||
}
|
||||
|
||||
[fCollapsedGroups removeIndex:value];
|
||||
[self.fCollapsedGroups removeIndex:value];
|
||||
}
|
||||
|
||||
- (void)removeAllCollapsedGroups
|
||||
{
|
||||
[fCollapsedGroups removeAllIndexes];
|
||||
[self.fCollapsedGroups removeAllIndexes];
|
||||
}
|
||||
|
||||
- (void)saveCollapsedGroups
|
||||
{
|
||||
[fDefaults setObject:[NSArchiver archivedDataWithRootObject:fCollapsedGroups] forKey:@"CollapsedGroups"];
|
||||
[self.fDefaults setObject:[NSArchiver archivedDataWithRootObject:self.fCollapsedGroups] forKey:@"CollapsedGroups"];
|
||||
}
|
||||
|
||||
- (BOOL)outlineView:(NSOutlineView*)outlineView isGroupItem:(id)item
|
||||
|
@ -131,7 +157,7 @@
|
|||
BOOL const group = ![item isKindOfClass:[Torrent class]];
|
||||
if (!tableColumn)
|
||||
{
|
||||
return !group ? fTorrentCell : nil;
|
||||
return !group ? self.fTorrentCell : nil;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -152,10 +178,10 @@
|
|||
torrentCell.representedObject = item;
|
||||
|
||||
NSInteger const row = [self rowForItem:item];
|
||||
torrentCell.hover = (row == fMouseRow);
|
||||
torrentCell.controlHover = (row == fMouseControlRow);
|
||||
torrentCell.revealHover = (row == fMouseRevealRow);
|
||||
torrentCell.actionHover = (row == fMouseActionRow);
|
||||
torrentCell.hover = (row == self.hoverRow);
|
||||
torrentCell.hoverControl = (row == self.controlButtonHoverRow);
|
||||
torrentCell.hoverReveal = (row == self.revealButtonHoverRow);
|
||||
torrentCell.hoverAction = (row == self.actionButtonHoverRow);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -207,7 +233,7 @@
|
|||
}
|
||||
else if ([ident isEqualToString:@"UL"] || [ident isEqualToString:@"UL Image"])
|
||||
{
|
||||
return [fDefaults boolForKey:@"DisplayGroupRowRatio"] ?
|
||||
return [self.fDefaults boolForKey:@"DisplayGroupRowRatio"] ?
|
||||
NSLocalizedString(@"Ratio", "Torrent table -> group row -> tooltip") :
|
||||
NSLocalizedString(@"Upload speed", "Torrent table -> group row -> tooltip");
|
||||
}
|
||||
|
@ -257,10 +283,10 @@
|
|||
|
||||
- (void)removeTrackingAreas
|
||||
{
|
||||
fMouseRow = -1;
|
||||
fMouseControlRow = -1;
|
||||
fMouseRevealRow = -1;
|
||||
fMouseActionRow = -1;
|
||||
_hoverRow = -1;
|
||||
_controlButtonHoverRow = -1;
|
||||
_revealButtonHoverRow = -1;
|
||||
_actionButtonHoverRow = -1;
|
||||
|
||||
for (NSTrackingArea* area in self.trackingAreas)
|
||||
{
|
||||
|
@ -271,38 +297,38 @@
|
|||
}
|
||||
}
|
||||
|
||||
- (void)setRowHover:(NSInteger)row
|
||||
- (void)setHoverRow:(NSInteger)row
|
||||
{
|
||||
NSAssert([fDefaults boolForKey:@"SmallView"], @"cannot set a hover row when not in compact view");
|
||||
NSAssert([self.fDefaults boolForKey:@"SmallView"], @"cannot set a hover row when not in compact view");
|
||||
|
||||
fMouseRow = row;
|
||||
_hoverRow = row;
|
||||
if (row >= 0)
|
||||
{
|
||||
[self setNeedsDisplayInRect:[self rectOfRow:row]];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setControlButtonHover:(NSInteger)row
|
||||
- (void)setControlButtonHoverRow:(NSInteger)row
|
||||
{
|
||||
fMouseControlRow = row;
|
||||
_controlButtonHoverRow = row;
|
||||
if (row >= 0)
|
||||
{
|
||||
[self setNeedsDisplayInRect:[self rectOfRow:row]];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setRevealButtonHover:(NSInteger)row
|
||||
- (void)setRevealButtonHoverRow:(NSInteger)row
|
||||
{
|
||||
fMouseRevealRow = row;
|
||||
_revealButtonHoverRow = row;
|
||||
if (row >= 0)
|
||||
{
|
||||
[self setNeedsDisplayInRect:[self rectOfRow:row]];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setActionButtonHover:(NSInteger)row
|
||||
- (void)setActionButtonHoverRow:(NSInteger)row
|
||||
{
|
||||
fMouseActionRow = row;
|
||||
_actionButtonHoverRow = row;
|
||||
if (row >= 0)
|
||||
{
|
||||
[self setNeedsDisplayInRect:[self rectOfRow:row]];
|
||||
|
@ -320,20 +346,20 @@
|
|||
NSString* type = dict[@"Type"];
|
||||
if ([type isEqualToString:@"Action"])
|
||||
{
|
||||
fMouseActionRow = rowVal;
|
||||
_actionButtonHoverRow = rowVal;
|
||||
}
|
||||
else if ([type isEqualToString:@"Control"])
|
||||
{
|
||||
fMouseControlRow = rowVal;
|
||||
_controlButtonHoverRow = rowVal;
|
||||
}
|
||||
else if ([type isEqualToString:@"Reveal"])
|
||||
{
|
||||
fMouseRevealRow = rowVal;
|
||||
_revealButtonHoverRow = rowVal;
|
||||
}
|
||||
else
|
||||
{
|
||||
fMouseRow = rowVal;
|
||||
if (![fDefaults boolForKey:@"SmallView"])
|
||||
_hoverRow = rowVal;
|
||||
if (![self.fDefaults boolForKey:@"SmallView"])
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -353,20 +379,20 @@
|
|||
NSString* type = dict[@"Type"];
|
||||
if ([type isEqualToString:@"Action"])
|
||||
{
|
||||
fMouseActionRow = -1;
|
||||
_actionButtonHoverRow = -1;
|
||||
}
|
||||
else if ([type isEqualToString:@"Control"])
|
||||
{
|
||||
fMouseControlRow = -1;
|
||||
_controlButtonHoverRow = -1;
|
||||
}
|
||||
else if ([type isEqualToString:@"Reveal"])
|
||||
{
|
||||
fMouseRevealRow = -1;
|
||||
_revealButtonHoverRow = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
fMouseRow = -1;
|
||||
if (![fDefaults boolForKey:@"SmallView"])
|
||||
_hoverRow = -1;
|
||||
if (![self.fDefaults boolForKey:@"SmallView"])
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -380,9 +406,9 @@
|
|||
{
|
||||
#warning elliminate when view-based?
|
||||
//if pushing a button, don't change the selected rows
|
||||
if (fSelectedValues)
|
||||
if (self.fSelectedValues)
|
||||
{
|
||||
[self selectValues:fSelectedValues];
|
||||
[self selectValues:self.fSelectedValues];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -395,9 +421,9 @@
|
|||
value = MAX_GROUP;
|
||||
}
|
||||
|
||||
if ([fCollapsedGroups containsIndex:value])
|
||||
if ([self.fCollapsedGroups containsIndex:value])
|
||||
{
|
||||
[fCollapsedGroups removeIndex:value];
|
||||
[self.fCollapsedGroups removeIndex:value];
|
||||
[NSNotificationCenter.defaultCenter postNotificationName:@"OutlineExpandCollapse" object:self];
|
||||
}
|
||||
}
|
||||
|
@ -411,7 +437,7 @@
|
|||
value = MAX_GROUP;
|
||||
}
|
||||
|
||||
[fCollapsedGroups addIndex:value];
|
||||
[self.fCollapsedGroups addIndex:value];
|
||||
[NSNotificationCenter.defaultCenter postNotificationName:@"OutlineExpandCollapse" object:self];
|
||||
}
|
||||
|
||||
|
@ -423,26 +449,26 @@
|
|||
//check to toggle group status before anything else
|
||||
if ([self pointInGroupStatusRect:point])
|
||||
{
|
||||
[fDefaults setBool:![fDefaults boolForKey:@"DisplayGroupRowRatio"] forKey:@"DisplayGroupRowRatio"];
|
||||
[self.fDefaults setBool:![self.fDefaults boolForKey:@"DisplayGroupRowRatio"] forKey:@"DisplayGroupRowRatio"];
|
||||
[self setGroupStatusColumns];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
BOOL const pushed = row != -1 && (fMouseActionRow == row || fMouseRevealRow == row || fMouseControlRow == row);
|
||||
BOOL const pushed = row != -1 && (self.actionButtonHoverRow == row || self.revealButtonHoverRow == row || self.controlButtonHoverRow == row);
|
||||
|
||||
//if pushing a button, don't change the selected rows
|
||||
if (pushed)
|
||||
{
|
||||
fSelectedValues = self.selectedValues;
|
||||
self.fSelectedValues = self.selectedValues;
|
||||
}
|
||||
|
||||
[super mouseDown:event];
|
||||
|
||||
fSelectedValues = nil;
|
||||
self.fSelectedValues = nil;
|
||||
|
||||
//avoid weird behavior when showing menu by doing this after mouse down
|
||||
if (row != -1 && fMouseActionRow == row)
|
||||
if (row != -1 && self.actionButtonHoverRow == row)
|
||||
{
|
||||
#warning maybe make appear on mouse down
|
||||
[self displayTorrentActionPopoverForEvent:event];
|
||||
|
@ -457,7 +483,7 @@
|
|||
|
||||
if (!item || [item isKindOfClass:[Torrent class]])
|
||||
{
|
||||
[fController showInfo:nil];
|
||||
[self.fController showInfo:nil];
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -554,12 +580,12 @@
|
|||
{
|
||||
[self selectRowIndexes:[NSIndexSet indexSetWithIndex:row] byExtendingSelection:NO];
|
||||
}
|
||||
return fContextRow;
|
||||
return self.fContextRow;
|
||||
}
|
||||
else
|
||||
{
|
||||
[self deselectAll:self];
|
||||
return fContextNoRow;
|
||||
return self.fContextNoRow;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -579,11 +605,11 @@
|
|||
event.modifierFlags & NSEventModifierFlagOption &&
|
||||
event.modifierFlags & NSEventModifierFlagCommand)
|
||||
{
|
||||
[fController focusFilterField];
|
||||
[self.fController focusFilterField];
|
||||
}
|
||||
else if (firstChar == ' ')
|
||||
{
|
||||
[fController toggleQuickLook:nil];
|
||||
[self.fController toggleQuickLook:nil];
|
||||
}
|
||||
else if (event.keyCode == 53) //esc key
|
||||
{
|
||||
|
@ -597,7 +623,7 @@
|
|||
|
||||
- (NSRect)iconRectForRow:(NSInteger)row
|
||||
{
|
||||
return [fTorrentCell iconRectForBounds:[self rectOfRow:row]];
|
||||
return [self.fTorrentCell iconRectForBounds:[self rectOfRow:row]];
|
||||
}
|
||||
|
||||
- (void)paste:(id)sender
|
||||
|
@ -605,7 +631,7 @@
|
|||
NSURL* url;
|
||||
if ((url = [NSURL URLFromPasteboard:NSPasteboard.generalPasteboard]))
|
||||
{
|
||||
[fController openURL:url.absoluteString];
|
||||
[self.fController openURL:url.absoluteString];
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -618,14 +644,14 @@
|
|||
pbItem = [pbItem stringByTrimmingCharactersInSet:NSCharacterSet.whitespaceAndNewlineCharacterSet];
|
||||
if ([pbItem rangeOfString:@"magnet:" options:(NSAnchoredSearch | NSCaseInsensitiveSearch)].location != NSNotFound)
|
||||
{
|
||||
[fController openURL:pbItem];
|
||||
[self.fController openURL:pbItem];
|
||||
}
|
||||
else
|
||||
{
|
||||
#warning only accept full text?
|
||||
for (NSTextCheckingResult* result in [detector matchesInString:pbItem options:0
|
||||
range:NSMakeRange(0, pbItem.length)])
|
||||
[fController openURL:result.URL.absoluteString];
|
||||
[self.fController openURL:result.URL.absoluteString];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -668,21 +694,21 @@
|
|||
{
|
||||
if (torrent.active)
|
||||
{
|
||||
[fController stopTorrents:@[ torrent ]];
|
||||
[self.fController stopTorrents:@[ torrent ]];
|
||||
}
|
||||
else
|
||||
{
|
||||
if (NSEvent.modifierFlags & NSEventModifierFlagOption)
|
||||
{
|
||||
[fController resumeTorrentsNoWait:@[ torrent ]];
|
||||
[self.fController resumeTorrentsNoWait:@[ torrent ]];
|
||||
}
|
||||
else if (torrent.waitingToStart)
|
||||
{
|
||||
[fController stopTorrents:@[ torrent ]];
|
||||
[self.fController stopTorrents:@[ torrent ]];
|
||||
}
|
||||
else
|
||||
{
|
||||
[fController resumeTorrents:@[ torrent ]];
|
||||
[self.fController resumeTorrents:@[ torrent ]];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -695,9 +721,9 @@
|
|||
return;
|
||||
}
|
||||
|
||||
NSRect const rect = [fTorrentCell iconRectForBounds:[self rectOfRow:row]];
|
||||
NSRect const rect = [self.fTorrentCell iconRectForBounds:[self rectOfRow:row]];
|
||||
|
||||
if (fActionPopoverShown)
|
||||
if (self.fActionPopoverShown)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -718,24 +744,24 @@
|
|||
//don't show multiple popovers when clicking the gear button repeatedly
|
||||
- (void)popoverWillShow:(NSNotification*)notification
|
||||
{
|
||||
fActionPopoverShown = YES;
|
||||
self.fActionPopoverShown = YES;
|
||||
}
|
||||
|
||||
- (void)popoverWillClose:(NSNotification*)notification
|
||||
{
|
||||
fActionPopoverShown = NO;
|
||||
self.fActionPopoverShown = NO;
|
||||
}
|
||||
|
||||
//eliminate when Lion-only, along with all the menu item instance variables
|
||||
- (void)menuNeedsUpdate:(NSMenu*)menu
|
||||
{
|
||||
//this method seems to be called when it shouldn't be
|
||||
if (!fMenuTorrent || !menu.supermenu)
|
||||
if (!self.fMenuTorrent || !menu.supermenu)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (menu == fUploadMenu || menu == fDownloadMenu)
|
||||
if (menu == self.fUploadMenu || menu == self.fDownloadMenu)
|
||||
{
|
||||
NSMenuItem* item;
|
||||
if (menu.numberOfItems == 3)
|
||||
|
@ -756,18 +782,18 @@
|
|||
}
|
||||
}
|
||||
|
||||
BOOL const upload = menu == fUploadMenu;
|
||||
BOOL const limit = [fMenuTorrent usesSpeedLimit:upload];
|
||||
BOOL const upload = menu == self.fUploadMenu;
|
||||
BOOL const limit = [self.fMenuTorrent usesSpeedLimit:upload];
|
||||
|
||||
item = [menu itemWithTag:ACTION_MENU_LIMIT_TAG];
|
||||
item.state = limit ? NSControlStateValueOn : NSControlStateValueOff;
|
||||
item.title = [NSString stringWithFormat:NSLocalizedString(@"Limit (%d KB/s)", "torrent action menu -> upload/download limit"),
|
||||
[fMenuTorrent speedLimit:upload]];
|
||||
[self.fMenuTorrent speedLimit:upload]];
|
||||
|
||||
item = [menu itemWithTag:ACTION_MENU_UNLIMITED_TAG];
|
||||
item.state = !limit ? NSControlStateValueOn : NSControlStateValueOff;
|
||||
}
|
||||
else if (menu == fRatioMenu)
|
||||
else if (menu == self.fRatioMenu)
|
||||
{
|
||||
NSMenuItem* item;
|
||||
if (menu.numberOfItems == 4)
|
||||
|
@ -785,12 +811,12 @@
|
|||
}
|
||||
}
|
||||
|
||||
tr_ratiolimit const mode = fMenuTorrent.ratioSetting;
|
||||
tr_ratiolimit const mode = self.fMenuTorrent.ratioSetting;
|
||||
|
||||
item = [menu itemWithTag:ACTION_MENU_LIMIT_TAG];
|
||||
item.state = mode == TR_RATIOLIMIT_SINGLE ? NSControlStateValueOn : NSControlStateValueOff;
|
||||
item.title = [NSString localizedStringWithFormat:NSLocalizedString(@"Stop at Ratio (%.2f)", "torrent action menu -> ratio stop"),
|
||||
fMenuTorrent.ratioLimit];
|
||||
self.fMenuTorrent.ratioLimit];
|
||||
|
||||
item = [menu itemWithTag:ACTION_MENU_UNLIMITED_TAG];
|
||||
item.state = mode == TR_RATIOLIMIT_UNLIMITED ? NSControlStateValueOn : NSControlStateValueOff;
|
||||
|
@ -798,9 +824,9 @@
|
|||
item = [menu itemWithTag:ACTION_MENU_GLOBAL_TAG];
|
||||
item.state = mode == TR_RATIOLIMIT_GLOBAL ? NSControlStateValueOn : NSControlStateValueOff;
|
||||
}
|
||||
else if (menu == fPriorityMenu)
|
||||
else if (menu == self.fPriorityMenu)
|
||||
{
|
||||
tr_priority_t const priority = fMenuTorrent.priority;
|
||||
tr_priority_t const priority = self.fMenuTorrent.priority;
|
||||
|
||||
NSMenuItem* item = [menu itemWithTag:ACTION_MENU_PRIORITY_HIGH_TAG];
|
||||
item.state = priority == TR_PRI_HIGH ? NSControlStateValueOn : NSControlStateValueOff;
|
||||
|
@ -817,23 +843,23 @@
|
|||
- (void)setQuickLimitMode:(id)sender
|
||||
{
|
||||
BOOL const limit = [sender tag] == ACTION_MENU_LIMIT_TAG;
|
||||
[fMenuTorrent setUseSpeedLimit:limit upload:[sender menu] == fUploadMenu];
|
||||
[self.fMenuTorrent setUseSpeedLimit:limit upload:[sender menu] == self.fUploadMenu];
|
||||
|
||||
[NSNotificationCenter.defaultCenter postNotificationName:@"UpdateOptions" object:nil];
|
||||
}
|
||||
|
||||
- (void)setQuickLimit:(id)sender
|
||||
{
|
||||
BOOL const upload = [sender menu] == fUploadMenu;
|
||||
[fMenuTorrent setUseSpeedLimit:YES upload:upload];
|
||||
[fMenuTorrent setSpeedLimit:[[sender representedObject] intValue] upload:upload];
|
||||
BOOL const upload = [sender menu] == self.fUploadMenu;
|
||||
[self.fMenuTorrent setUseSpeedLimit:YES upload:upload];
|
||||
[self.fMenuTorrent setSpeedLimit:[[sender representedObject] intValue] upload:upload];
|
||||
|
||||
[NSNotificationCenter.defaultCenter postNotificationName:@"UpdateOptions" object:nil];
|
||||
}
|
||||
|
||||
- (void)setGlobalLimit:(id)sender
|
||||
{
|
||||
fMenuTorrent.usesGlobalSpeedLimit = ((NSButton*)sender).state != NSControlStateValueOn;
|
||||
self.fMenuTorrent.usesGlobalSpeedLimit = ((NSButton*)sender).state != NSControlStateValueOn;
|
||||
|
||||
[NSNotificationCenter.defaultCenter postNotificationName:@"UpdateOptions" object:nil];
|
||||
}
|
||||
|
@ -856,15 +882,15 @@
|
|||
return;
|
||||
}
|
||||
|
||||
fMenuTorrent.ratioSetting = mode;
|
||||
self.fMenuTorrent.ratioSetting = mode;
|
||||
|
||||
[NSNotificationCenter.defaultCenter postNotificationName:@"UpdateOptions" object:nil];
|
||||
}
|
||||
|
||||
- (void)setQuickRatio:(id)sender
|
||||
{
|
||||
fMenuTorrent.ratioSetting = TR_RATIOLIMIT_SINGLE;
|
||||
fMenuTorrent.ratioLimit = [[sender representedObject] floatValue];
|
||||
self.fMenuTorrent.ratioSetting = TR_RATIOLIMIT_SINGLE;
|
||||
self.fMenuTorrent.ratioLimit = [[sender representedObject] floatValue];
|
||||
|
||||
[NSNotificationCenter.defaultCenter postNotificationName:@"UpdateOptions" object:nil];
|
||||
}
|
||||
|
@ -888,7 +914,7 @@
|
|||
priority = TR_PRI_NORMAL;
|
||||
}
|
||||
|
||||
fMenuTorrent.priority = priority;
|
||||
self.fMenuTorrent.priority = priority;
|
||||
|
||||
[NSNotificationCenter.defaultCenter postNotificationName:@"UpdateUI" object:nil];
|
||||
}
|
||||
|
@ -902,44 +928,39 @@
|
|||
}
|
||||
|
||||
//this stops a previous animation
|
||||
fPiecesBarAnimation = [[NSAnimation alloc] initWithDuration:TOGGLE_PROGRESS_SECONDS animationCurve:NSAnimationEaseIn];
|
||||
fPiecesBarAnimation.animationBlockingMode = NSAnimationNonblocking;
|
||||
fPiecesBarAnimation.progressMarks = progressMarks;
|
||||
fPiecesBarAnimation.delegate = self;
|
||||
self.fPiecesBarAnimation = [[NSAnimation alloc] initWithDuration:TOGGLE_PROGRESS_SECONDS animationCurve:NSAnimationEaseIn];
|
||||
self.fPiecesBarAnimation.animationBlockingMode = NSAnimationNonblocking;
|
||||
self.fPiecesBarAnimation.progressMarks = progressMarks;
|
||||
self.fPiecesBarAnimation.delegate = self;
|
||||
|
||||
[fPiecesBarAnimation startAnimation];
|
||||
[self.fPiecesBarAnimation startAnimation];
|
||||
}
|
||||
|
||||
- (void)animationDidEnd:(NSAnimation*)animation
|
||||
{
|
||||
if (animation == fPiecesBarAnimation)
|
||||
if (animation == self.fPiecesBarAnimation)
|
||||
{
|
||||
fPiecesBarAnimation = nil;
|
||||
self.fPiecesBarAnimation = nil;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)animation:(NSAnimation*)animation didReachProgressMark:(NSAnimationProgress)progress
|
||||
{
|
||||
if (animation == fPiecesBarAnimation)
|
||||
if (animation == self.fPiecesBarAnimation)
|
||||
{
|
||||
if ([fDefaults boolForKey:@"PiecesBar"])
|
||||
if ([self.fDefaults boolForKey:@"PiecesBar"])
|
||||
{
|
||||
fPiecesBarPercent = progress;
|
||||
self.piecesBarPercent = progress;
|
||||
}
|
||||
else
|
||||
{
|
||||
fPiecesBarPercent = 1.0 - progress;
|
||||
self.piecesBarPercent = 1.0 - progress;
|
||||
}
|
||||
|
||||
self.needsDisplay = YES;
|
||||
}
|
||||
}
|
||||
|
||||
- (CGFloat)piecesBarPercent
|
||||
{
|
||||
return fPiecesBarPercent;
|
||||
}
|
||||
|
||||
- (void)selectAndScrollToRow:(NSInteger)row
|
||||
{
|
||||
NSParameterAssert(row >= 0);
|
||||
|
@ -960,6 +981,8 @@
|
|||
[[self.superview animator] setBoundsOrigin:scrollOrigin];
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
- (BOOL)pointInGroupStatusRect:(NSPoint)point
|
||||
{
|
||||
NSInteger row = [self rowAtPoint:point];
|
||||
|
@ -975,7 +998,7 @@
|
|||
|
||||
- (void)setGroupStatusColumns
|
||||
{
|
||||
BOOL const ratio = [fDefaults boolForKey:@"DisplayGroupRowRatio"];
|
||||
BOOL const ratio = [self.fDefaults boolForKey:@"DisplayGroupRowRatio"];
|
||||
|
||||
[self tableColumnWithIdentifier:@"DL"].hidden = ratio;
|
||||
[self tableColumnWithIdentifier:@"DL Image"].hidden = ratio;
|
||||
|
|
|
@ -5,8 +5,5 @@
|
|||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
@interface TrackerCell : NSActionCell
|
||||
{
|
||||
NSMutableDictionary *fNameAttributes, *fStatusAttributes;
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -21,6 +21,10 @@
|
|||
@interface TrackerCell ()
|
||||
|
||||
@property(nonatomic, readonly) NSImage* favIcon;
|
||||
@property(nonatomic, readonly) NSAttributedString* attributedName;
|
||||
@property(nonatomic, readonly) NSMutableDictionary* fNameAttributes;
|
||||
@property(nonatomic, readonly) NSMutableDictionary* fStatusAttributes;
|
||||
|
||||
- (void)loadTrackerIcon:(NSString*)baseAddress;
|
||||
|
||||
- (NSRect)imageRectForBounds:(NSRect)bounds;
|
||||
|
@ -32,7 +36,6 @@
|
|||
withRightRect:(NSRect)rightRect
|
||||
inBounds:(NSRect)bounds;
|
||||
|
||||
@property(nonatomic, readonly) NSAttributedString* attributedName;
|
||||
- (NSAttributedString*)attributedStatusWithString:(NSString*)statusString;
|
||||
- (NSAttributedString*)attributedCount:(NSInteger)count;
|
||||
|
||||
|
@ -57,10 +60,10 @@ NSMutableSet* fTrackerIconLoading;
|
|||
NSMutableParagraphStyle* paragraphStyle = [NSParagraphStyle.defaultParagraphStyle mutableCopy];
|
||||
paragraphStyle.lineBreakMode = NSLineBreakByTruncatingTail;
|
||||
|
||||
fNameAttributes = [[NSMutableDictionary alloc]
|
||||
_fNameAttributes = [[NSMutableDictionary alloc]
|
||||
initWithObjectsAndKeys:[NSFont messageFontOfSize:12.0], NSFontAttributeName, paragraphStyle, NSParagraphStyleAttributeName, nil];
|
||||
|
||||
fStatusAttributes = [[NSMutableDictionary alloc]
|
||||
_fStatusAttributes = [[NSMutableDictionary alloc]
|
||||
initWithObjectsAndKeys:[NSFont messageFontOfSize:9.0], NSFontAttributeName, paragraphStyle, NSParagraphStyleAttributeName, nil];
|
||||
}
|
||||
return self;
|
||||
|
@ -70,8 +73,8 @@ NSMutableSet* fTrackerIconLoading;
|
|||
{
|
||||
TrackerCell* copy = [super copyWithZone:zone];
|
||||
|
||||
copy->fNameAttributes = fNameAttributes;
|
||||
copy->fStatusAttributes = fStatusAttributes;
|
||||
copy->_fNameAttributes = _fNameAttributes;
|
||||
copy->_fStatusAttributes = _fStatusAttributes;
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
@ -96,8 +99,8 @@ NSMutableSet* fTrackerIconLoading;
|
|||
statusColor = NSColor.secondaryLabelColor;
|
||||
}
|
||||
|
||||
fNameAttributes[NSForegroundColorAttributeName] = nameColor;
|
||||
fStatusAttributes[NSForegroundColorAttributeName] = statusColor;
|
||||
self.fNameAttributes[NSForegroundColorAttributeName] = nameColor;
|
||||
self.fStatusAttributes[NSForegroundColorAttributeName] = statusColor;
|
||||
|
||||
TrackerNode* node = (TrackerNode*)self.objectValue;
|
||||
|
||||
|
@ -157,6 +160,8 @@ NSMutableSet* fTrackerIconLoading;
|
|||
[lastScrapeString drawInRect:lastScrapeRect];
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
- (NSImage*)favIcon
|
||||
{
|
||||
id icon = nil;
|
||||
|
@ -306,18 +311,18 @@ NSMutableSet* fTrackerIconLoading;
|
|||
- (NSAttributedString*)attributedName
|
||||
{
|
||||
NSString* name = ((TrackerNode*)self.objectValue).host;
|
||||
return [[NSAttributedString alloc] initWithString:name attributes:fNameAttributes];
|
||||
return [[NSAttributedString alloc] initWithString:name attributes:self.fNameAttributes];
|
||||
}
|
||||
|
||||
- (NSAttributedString*)attributedStatusWithString:(NSString*)statusString
|
||||
{
|
||||
return [[NSAttributedString alloc] initWithString:statusString attributes:fStatusAttributes];
|
||||
return [[NSAttributedString alloc] initWithString:statusString attributes:self.fStatusAttributes];
|
||||
}
|
||||
|
||||
- (NSAttributedString*)attributedCount:(NSInteger)count
|
||||
{
|
||||
NSString* countString = count != -1 ? [NSString stringWithFormat:@"%ld", count] : NSLocalizedString(@"N/A", "tracker peer stat");
|
||||
return [[NSAttributedString alloc] initWithString:countString attributes:fStatusAttributes];
|
||||
return [[NSAttributedString alloc] initWithString:countString attributes:self.fStatusAttributes];
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -6,16 +6,19 @@
|
|||
#import "NSApplicationAdditions.h"
|
||||
#import "NSStringAdditions.h"
|
||||
|
||||
@interface TrackerNode ()
|
||||
|
||||
@property(nonatomic, readonly) tr_tracker_view fStat;
|
||||
|
||||
@end
|
||||
|
||||
@implementation TrackerNode
|
||||
{
|
||||
tr_tracker_view fStat;
|
||||
}
|
||||
|
||||
- (instancetype)initWithTrackerView:(tr_tracker_view const*)stat torrent:(Torrent*)torrent
|
||||
{
|
||||
if ((self = [super init]))
|
||||
{
|
||||
fStat = *stat;
|
||||
_fStat = *stat;
|
||||
_torrent = torrent; //weak reference
|
||||
}
|
||||
|
||||
|
@ -56,50 +59,50 @@
|
|||
|
||||
- (NSString*)host
|
||||
{
|
||||
return @(fStat.host);
|
||||
return @(self.fStat.host);
|
||||
}
|
||||
|
||||
- (NSString*)fullAnnounceAddress
|
||||
{
|
||||
return @(fStat.announce);
|
||||
return @(self.fStat.announce);
|
||||
}
|
||||
|
||||
- (NSInteger)tier
|
||||
{
|
||||
return fStat.tier;
|
||||
return self.fStat.tier;
|
||||
}
|
||||
|
||||
- (NSUInteger)identifier
|
||||
{
|
||||
return fStat.id;
|
||||
return self.fStat.id;
|
||||
}
|
||||
|
||||
- (NSInteger)totalSeeders
|
||||
{
|
||||
return fStat.seederCount;
|
||||
return self.fStat.seederCount;
|
||||
}
|
||||
|
||||
- (NSInteger)totalLeechers
|
||||
{
|
||||
return fStat.leecherCount;
|
||||
return self.fStat.leecherCount;
|
||||
}
|
||||
|
||||
- (NSInteger)totalDownloaded
|
||||
{
|
||||
return fStat.downloadCount;
|
||||
return self.fStat.downloadCount;
|
||||
}
|
||||
|
||||
- (NSString*)lastAnnounceStatusString
|
||||
{
|
||||
NSString* dateString;
|
||||
if (fStat.hasAnnounced)
|
||||
if (self.fStat.hasAnnounced)
|
||||
{
|
||||
NSDateFormatter* dateFormatter = [[NSDateFormatter alloc] init];
|
||||
dateFormatter.dateStyle = NSDateFormatterFullStyle;
|
||||
dateFormatter.timeStyle = NSDateFormatterShortStyle;
|
||||
dateFormatter.doesRelativeDateFormatting = YES;
|
||||
|
||||
dateString = [dateFormatter stringFromDate:[NSDate dateWithTimeIntervalSince1970:fStat.lastAnnounceTime]];
|
||||
dateString = [dateFormatter stringFromDate:[NSDate dateWithTimeIntervalSince1970:self.fStat.lastAnnounceTime]];
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -107,15 +110,15 @@
|
|||
}
|
||||
|
||||
NSString* baseString;
|
||||
if (fStat.hasAnnounced && fStat.lastAnnounceTimedOut)
|
||||
if (self.fStat.hasAnnounced && self.fStat.lastAnnounceTimedOut)
|
||||
{
|
||||
baseString = [NSLocalizedString(@"Announce timed out", "Tracker last announce") stringByAppendingFormat:@": %@", dateString];
|
||||
}
|
||||
else if (fStat.hasAnnounced && !fStat.lastAnnounceSucceeded)
|
||||
else if (self.fStat.hasAnnounced && !self.fStat.lastAnnounceSucceeded)
|
||||
{
|
||||
baseString = NSLocalizedString(@"Announce error", "Tracker last announce");
|
||||
|
||||
NSString* errorString = @(fStat.lastAnnounceResult);
|
||||
NSString* errorString = @(self.fStat.lastAnnounceResult);
|
||||
if ([errorString isEqualToString:@""])
|
||||
{
|
||||
baseString = [baseString stringByAppendingFormat:@": %@", dateString];
|
||||
|
@ -128,16 +131,16 @@
|
|||
else
|
||||
{
|
||||
baseString = [NSLocalizedString(@"Last Announce", "Tracker last announce") stringByAppendingFormat:@": %@", dateString];
|
||||
if (fStat.hasAnnounced && fStat.lastAnnounceSucceeded && fStat.lastAnnouncePeerCount > 0)
|
||||
if (self.fStat.hasAnnounced && self.fStat.lastAnnounceSucceeded && self.fStat.lastAnnouncePeerCount > 0)
|
||||
{
|
||||
NSString* peerString;
|
||||
if (fStat.lastAnnouncePeerCount == 1)
|
||||
if (self.fStat.lastAnnouncePeerCount == 1)
|
||||
{
|
||||
peerString = NSLocalizedString(@"got 1 peer", "Tracker last announce");
|
||||
}
|
||||
else
|
||||
{
|
||||
peerString = [NSString stringWithFormat:NSLocalizedString(@"got %d peers", "Tracker last announce"), fStat.lastAnnouncePeerCount];
|
||||
peerString = [NSString stringWithFormat:NSLocalizedString(@"got %d peers", "Tracker last announce"), self.fStat.lastAnnouncePeerCount];
|
||||
}
|
||||
baseString = [baseString stringByAppendingFormat:@" (%@)", peerString];
|
||||
}
|
||||
|
@ -148,14 +151,14 @@
|
|||
|
||||
- (NSString*)nextAnnounceStatusString
|
||||
{
|
||||
switch (fStat.announceState)
|
||||
switch (self.fStat.announceState)
|
||||
{
|
||||
case TR_TRACKER_ACTIVE:
|
||||
return [NSLocalizedString(@"Announce in progress", "Tracker next announce") stringByAppendingEllipsis];
|
||||
|
||||
case TR_TRACKER_WAITING:
|
||||
{
|
||||
NSTimeInterval const nextAnnounceTimeLeft = fStat.nextAnnounceTime - [NSDate date].timeIntervalSince1970;
|
||||
NSTimeInterval const nextAnnounceTimeLeft = self.fStat.nextAnnounceTime - [NSDate date].timeIntervalSince1970;
|
||||
|
||||
static NSDateComponentsFormatter* formatter;
|
||||
static dispatch_once_t onceToken;
|
||||
|
@ -173,11 +176,11 @@
|
|||
return [NSLocalizedString(@"Announce is queued", "Tracker next announce") stringByAppendingEllipsis];
|
||||
|
||||
case TR_TRACKER_INACTIVE:
|
||||
return fStat.isBackup ? NSLocalizedString(@"Tracker will be used as a backup", "Tracker next announce") :
|
||||
return self.fStat.isBackup ? NSLocalizedString(@"Tracker will be used as a backup", "Tracker next announce") :
|
||||
NSLocalizedString(@"Announce not scheduled", "Tracker next announce");
|
||||
|
||||
default:
|
||||
NSAssert1(NO, @"unknown announce state: %d", fStat.announceState);
|
||||
NSAssert1(NO, @"unknown announce state: %d", self.fStat.announceState);
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
@ -185,14 +188,14 @@
|
|||
- (NSString*)lastScrapeStatusString
|
||||
{
|
||||
NSString* dateString;
|
||||
if (fStat.hasScraped)
|
||||
if (self.fStat.hasScraped)
|
||||
{
|
||||
NSDateFormatter* dateFormatter = [[NSDateFormatter alloc] init];
|
||||
dateFormatter.dateStyle = NSDateFormatterFullStyle;
|
||||
dateFormatter.timeStyle = NSDateFormatterShortStyle;
|
||||
dateFormatter.doesRelativeDateFormatting = YES;
|
||||
|
||||
dateString = [dateFormatter stringFromDate:[NSDate dateWithTimeIntervalSince1970:fStat.lastScrapeTime]];
|
||||
dateString = [dateFormatter stringFromDate:[NSDate dateWithTimeIntervalSince1970:self.fStat.lastScrapeTime]];
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -200,15 +203,15 @@
|
|||
}
|
||||
|
||||
NSString* baseString;
|
||||
if (fStat.hasScraped && fStat.lastScrapeTimedOut)
|
||||
if (self.fStat.hasScraped && self.fStat.lastScrapeTimedOut)
|
||||
{
|
||||
baseString = [NSLocalizedString(@"Scrape timed out", "Tracker last scrape") stringByAppendingFormat:@": %@", dateString];
|
||||
}
|
||||
else if (fStat.hasScraped && !fStat.lastScrapeSucceeded)
|
||||
else if (self.fStat.hasScraped && !self.fStat.lastScrapeSucceeded)
|
||||
{
|
||||
baseString = NSLocalizedString(@"Scrape error", "Tracker last scrape");
|
||||
|
||||
NSString* errorString = @(fStat.lastScrapeResult);
|
||||
NSString* errorString = @(self.fStat.lastScrapeResult);
|
||||
if ([errorString isEqualToString:@""])
|
||||
{
|
||||
baseString = [baseString stringByAppendingFormat:@": %@", dateString];
|
||||
|
|
|
@ -7,14 +7,9 @@
|
|||
@class Torrent;
|
||||
|
||||
@interface TrackerTableView : NSTableView
|
||||
{
|
||||
//weak references
|
||||
Torrent* fTorrent;
|
||||
NSArray* fTrackers;
|
||||
}
|
||||
|
||||
- (void)setTorrent:(Torrent*)torrent;
|
||||
- (void)setTrackers:(NSArray*)trackers;
|
||||
@property(nonatomic, weak) Torrent* torrent;
|
||||
@property(nonatomic, weak) NSArray* trackers;
|
||||
|
||||
- (void)copy:(id)sender;
|
||||
- (void)paste:(id)sender;
|
||||
|
|
|
@ -14,28 +14,18 @@
|
|||
[super mouseDown:event];
|
||||
}
|
||||
|
||||
- (void)setTorrent:(Torrent*)torrent
|
||||
{
|
||||
fTorrent = torrent;
|
||||
}
|
||||
|
||||
- (void)setTrackers:(NSArray*)trackers
|
||||
{
|
||||
fTrackers = trackers;
|
||||
}
|
||||
|
||||
- (void)copy:(id)sender
|
||||
{
|
||||
NSMutableArray* addresses = [NSMutableArray arrayWithCapacity:fTrackers.count];
|
||||
NSMutableArray* addresses = [NSMutableArray arrayWithCapacity:self.trackers.count];
|
||||
NSIndexSet* indexes = self.selectedRowIndexes;
|
||||
for (NSUInteger i = indexes.firstIndex; i != NSNotFound; i = [indexes indexGreaterThanIndex:i])
|
||||
{
|
||||
id item = fTrackers[i];
|
||||
id item = self.trackers[i];
|
||||
if (![item isKindOfClass:[TrackerNode class]])
|
||||
{
|
||||
for (++i; i < fTrackers.count && [fTrackers[i] isKindOfClass:[TrackerNode class]]; ++i)
|
||||
for (++i; i < self.trackers.count && [self.trackers[i] isKindOfClass:[TrackerNode class]]; ++i)
|
||||
{
|
||||
[addresses addObject:((TrackerNode*)fTrackers[i]).fullAnnounceAddress];
|
||||
[addresses addObject:((TrackerNode*)self.trackers[i]).fullAnnounceAddress];
|
||||
}
|
||||
--i;
|
||||
}
|
||||
|
@ -54,7 +44,7 @@
|
|||
|
||||
- (void)paste:(id)sender
|
||||
{
|
||||
NSAssert(fTorrent != nil, @"no torrent but trying to paste; should not be able to call this method");
|
||||
NSAssert(self.torrent != nil, @"no torrent but trying to paste; should not be able to call this method");
|
||||
|
||||
BOOL added = NO;
|
||||
|
||||
|
@ -65,7 +55,7 @@
|
|||
{
|
||||
for (NSString* item in [pbItem componentsSeparatedByString:@"\n"])
|
||||
{
|
||||
if ([fTorrent addTrackerToNewTier:item])
|
||||
if ([self.torrent addTrackerToNewTier:item])
|
||||
{
|
||||
added = YES;
|
||||
}
|
||||
|
@ -90,7 +80,7 @@
|
|||
|
||||
if (action == @selector(paste:))
|
||||
{
|
||||
return fTorrent && [NSPasteboard.generalPasteboard canReadObjectForClasses:@[ [NSString class] ] options:nil];
|
||||
return self.torrent && [NSPasteboard.generalPasteboard canReadObjectForClasses:@[ [NSString class] ] options:nil];
|
||||
}
|
||||
|
||||
return YES;
|
||||
|
|
|
@ -4,23 +4,13 @@
|
|||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
@class Controller;
|
||||
|
||||
@interface URLSheetWindowController : NSWindowController
|
||||
{
|
||||
IBOutlet NSTextField* fLabelField;
|
||||
IBOutlet NSTextField* fTextField;
|
||||
IBOutlet NSButton* fOpenButton;
|
||||
IBOutlet NSButton* fCancelButton;
|
||||
|
||||
Controller* fController;
|
||||
}
|
||||
@property(nonatomic, readonly) NSString* urlString;
|
||||
|
||||
- (instancetype)initWithController:(Controller*)controller;
|
||||
- (instancetype)init;
|
||||
|
||||
- (void)openURLEndSheet:(id)sender;
|
||||
- (void)openURLCancelEndSheet:(id)sender;
|
||||
|
||||
@property(nonatomic, readonly) NSString* urlString;
|
||||
|
||||
@end
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue