mirror of
https://github.com/transmission/transmission.git
synced 2025-12-20 10:28:32 +00:00
#1575 Auto-select a group for new torrents according to criteria for each group
This commit is contained in:
3
NEWS
3
NEWS
@@ -7,7 +7,8 @@ NEWS file for Transmission <http://www.transmissionbt.com/>
|
|||||||
+ Support BitTorrent Enhancement Proposal #6 "Fast Extension"
|
+ Support BitTorrent Enhancement Proposal #6 "Fast Extension"
|
||||||
+ Support BitTorrent Enhancement Proposal #21 "Extension for Partial Seeds"
|
+ Support BitTorrent Enhancement Proposal #21 "Extension for Partial Seeds"
|
||||||
- Mac
|
- Mac
|
||||||
+ Groups (moved to preferences) can have a default location when adding transfers
|
+ Groups (moved to preferences) can be auto-assigned to transfers when adding based on name and tracker (10.5-only)
|
||||||
|
+ Groups can have a default location when adding transfers
|
||||||
+ Bonjour support for the web interface
|
+ Bonjour support for the web interface
|
||||||
+ File filter field in the inspector
|
+ File filter field in the inspector
|
||||||
- GTK+
|
- GTK+
|
||||||
|
|||||||
@@ -108,6 +108,7 @@
|
|||||||
A234D0D20C79FB3600A82373 /* NSMenuAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = A234D0D00C79FB3600A82373 /* NSMenuAdditions.m */; };
|
A234D0D20C79FB3600A82373 /* NSMenuAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = A234D0D00C79FB3600A82373 /* NSMenuAdditions.m */; };
|
||||||
A2385DD40BFE06C800B24EF6 /* DragOverlayWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = A2385DD20BFE06C800B24EF6 /* DragOverlayWindow.m */; };
|
A2385DD40BFE06C800B24EF6 /* DragOverlayWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = A2385DD20BFE06C800B24EF6 /* DragOverlayWindow.m */; };
|
||||||
A2399CCD0CD3852300225B2B /* NSApplicationAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = A2399CCC0CD3852300225B2B /* NSApplicationAdditions.m */; };
|
A2399CCD0CD3852300225B2B /* NSApplicationAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = A2399CCC0CD3852300225B2B /* NSApplicationAdditions.m */; };
|
||||||
|
A23A0E310EECB0740091C885 /* GroupRules.xib in Resources */ = {isa = PBXBuildFile; fileRef = A23A0E300EECB0740091C885 /* GroupRules.xib */; };
|
||||||
A23F4FF20D1D98AD002FCB97 /* PrefsWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = A23F4FF00D1D98AD002FCB97 /* PrefsWindow.xib */; };
|
A23F4FF20D1D98AD002FCB97 /* PrefsWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = A23F4FF00D1D98AD002FCB97 /* PrefsWindow.xib */; };
|
||||||
A23F50020D1D99D7002FCB97 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = A23F50000D1D99D7002FCB97 /* MainMenu.xib */; };
|
A23F50020D1D99D7002FCB97 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = A23F50000D1D99D7002FCB97 /* MainMenu.xib */; };
|
||||||
A241528B0C0261B8007DD3B4 /* Globe.png in Resources */ = {isa = PBXBuildFile; fileRef = A2FB06950BFF484A0095564D /* Globe.png */; };
|
A241528B0C0261B8007DD3B4 /* Globe.png in Resources */ = {isa = PBXBuildFile; fileRef = A2FB06950BFF484A0095564D /* Globe.png */; };
|
||||||
@@ -513,6 +514,7 @@
|
|||||||
A2385DD30BFE06C800B24EF6 /* DragOverlayWindow.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = DragOverlayWindow.h; path = macosx/DragOverlayWindow.h; sourceTree = "<group>"; };
|
A2385DD30BFE06C800B24EF6 /* DragOverlayWindow.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = DragOverlayWindow.h; path = macosx/DragOverlayWindow.h; sourceTree = "<group>"; };
|
||||||
A2399CCB0CD3852300225B2B /* NSApplicationAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NSApplicationAdditions.h; path = macosx/NSApplicationAdditions.h; sourceTree = "<group>"; };
|
A2399CCB0CD3852300225B2B /* NSApplicationAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NSApplicationAdditions.h; path = macosx/NSApplicationAdditions.h; sourceTree = "<group>"; };
|
||||||
A2399CCC0CD3852300225B2B /* NSApplicationAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = NSApplicationAdditions.m; path = macosx/NSApplicationAdditions.m; sourceTree = "<group>"; };
|
A2399CCC0CD3852300225B2B /* NSApplicationAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = NSApplicationAdditions.m; path = macosx/NSApplicationAdditions.m; sourceTree = "<group>"; };
|
||||||
|
A23A0E300EECB0740091C885 /* GroupRules.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = GroupRules.xib; path = macosx/GroupRules.xib; sourceTree = "<group>"; };
|
||||||
A245030B0D6A1FB000B49D00 /* UpArrowGroupTemplate.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = UpArrowGroupTemplate.png; path = macosx/Images/UpArrowGroupTemplate.png; sourceTree = "<group>"; };
|
A245030B0D6A1FB000B49D00 /* UpArrowGroupTemplate.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = UpArrowGroupTemplate.png; path = macosx/Images/UpArrowGroupTemplate.png; sourceTree = "<group>"; };
|
||||||
A245030D0D6A1FBC00B49D00 /* DownArrowGroupTemplate.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = DownArrowGroupTemplate.png; path = macosx/Images/DownArrowGroupTemplate.png; sourceTree = "<group>"; };
|
A245030D0D6A1FBC00B49D00 /* DownArrowGroupTemplate.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = DownArrowGroupTemplate.png; path = macosx/Images/DownArrowGroupTemplate.png; sourceTree = "<group>"; };
|
||||||
A24621350C769CF400088E81 /* trevent.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = trevent.h; path = libtransmission/trevent.h; sourceTree = "<group>"; };
|
A24621350C769CF400088E81 /* trevent.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = trevent.h; path = libtransmission/trevent.h; sourceTree = "<group>"; };
|
||||||
@@ -1005,6 +1007,7 @@
|
|||||||
A29576110D11D8DD0093B167 /* InfoWindow.xib */,
|
A29576110D11D8DD0093B167 /* InfoWindow.xib */,
|
||||||
A29576010D11D63C0093B167 /* Creator.xib */,
|
A29576010D11D63C0093B167 /* Creator.xib */,
|
||||||
A26AF27C0D2DBDDF00FF7140 /* AddWindow.xib */,
|
A26AF27C0D2DBDDF00FF7140 /* AddWindow.xib */,
|
||||||
|
A23A0E300EECB0740091C885 /* GroupRules.xib */,
|
||||||
A233BD320D8C6585007EE7B4 /* MessageWindow.xib */,
|
A233BD320D8C6585007EE7B4 /* MessageWindow.xib */,
|
||||||
A233BD680D8CF2C7007EE7B4 /* StatsWindow.xib */,
|
A233BD680D8CF2C7007EE7B4 /* StatsWindow.xib */,
|
||||||
A231274B0D11D0B7003F9AFF /* AboutWindow.xib */,
|
A231274B0D11D0B7003F9AFF /* AboutWindow.xib */,
|
||||||
@@ -1769,6 +1772,7 @@
|
|||||||
A250EEB60E2ED87B00A688E6 /* web in Resources */,
|
A250EEB60E2ED87B00A688E6 /* web in Resources */,
|
||||||
A22F1E550E7DA8030065DB9D /* sparkle_dsa_pub.pem in Resources */,
|
A22F1E550E7DA8030065DB9D /* sparkle_dsa_pub.pem in Resources */,
|
||||||
A2E2EA920EE321C200EB6308 /* Groups.png in Resources */,
|
A2E2EA920EE321C200EB6308 /* Groups.png in Resources */,
|
||||||
|
A23A0E310EECB0740091C885 /* GroupRules.xib in Resources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -37,6 +37,8 @@
|
|||||||
|
|
||||||
- (void) confirmAdd;
|
- (void) confirmAdd;
|
||||||
|
|
||||||
|
- (void) setDestinationPath: (NSString *) destination;
|
||||||
|
|
||||||
- (void) folderChoiceClosed: (NSOpenPanel *) openPanel returnCode: (NSInteger) code contextInfo: (void *) contextInfo;
|
- (void) folderChoiceClosed: (NSOpenPanel *) openPanel returnCode: (NSInteger) code contextInfo: (void *) contextInfo;
|
||||||
|
|
||||||
- (void) setGroupsMenu;
|
- (void) setGroupsMenu;
|
||||||
@@ -64,7 +66,13 @@
|
|||||||
&& [[NSUserDefaults standardUserDefaults] boolForKey: @"DeleteOriginalTorrent"]);
|
&& [[NSUserDefaults standardUserDefaults] boolForKey: @"DeleteOriginalTorrent"]);
|
||||||
fDeleteEnable = deleteTorrent == TORRENT_FILE_DEFAULT;
|
fDeleteEnable = deleteTorrent == TORRENT_FILE_DEFAULT;
|
||||||
|
|
||||||
fGroupValue = -1;
|
fGroupValue = [torrent groupValue];
|
||||||
|
|
||||||
|
#warning factor in if there already is a destination
|
||||||
|
// set the group’s download location if there is one
|
||||||
|
if ([[GroupsController groups] usesCustomDownloadLocationForIndex: fGroupValue] &&
|
||||||
|
[[GroupsController groups] customDownloadLocationForIndex: fGroupValue])
|
||||||
|
[self setDestinationPath: [[GroupsController groups] customDownloadLocationForIndex: fGroupValue]];
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
@@ -91,7 +99,7 @@
|
|||||||
[self updateStatusField: nil];
|
[self updateStatusField: nil];
|
||||||
|
|
||||||
[self setGroupsMenu];
|
[self setGroupsMenu];
|
||||||
[fGroupPopUp selectItemWithTag: -1];
|
[fGroupPopUp selectItemWithTag: fGroupValue];
|
||||||
|
|
||||||
[fStartCheck setState: [[NSUserDefaults standardUserDefaults] boolForKey: @"AutoStartDownload"] ? NSOnState : NSOffState];
|
[fStartCheck setState: [[NSUserDefaults standardUserDefaults] boolForKey: @"AutoStartDownload"] ? NSOnState : NSOffState];
|
||||||
|
|
||||||
@@ -99,14 +107,7 @@
|
|||||||
[fDeleteCheck setEnabled: fDeleteEnable];
|
[fDeleteCheck setEnabled: fDeleteEnable];
|
||||||
|
|
||||||
if (fDestination)
|
if (fDestination)
|
||||||
{
|
[self setDestinationPath: fDestination];
|
||||||
[fLocationField setStringValue: [fDestination stringByAbbreviatingWithTildeInPath]];
|
|
||||||
[fLocationField setToolTip: fDestination];
|
|
||||||
|
|
||||||
ExpandedPathToIconTransformer * iconTransformer = [[ExpandedPathToIconTransformer alloc] init];
|
|
||||||
[fLocationImageView setImage: [iconTransformer transformedValue: fDestination]];
|
|
||||||
[iconTransformer release];
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
[fLocationField setStringValue: @""];
|
[fLocationField setStringValue: @""];
|
||||||
@@ -247,7 +248,7 @@
|
|||||||
fTimer = nil;
|
fTimer = nil;
|
||||||
|
|
||||||
[fTorrent setWaitToStart: [fStartCheck state] == NSOnState];
|
[fTorrent setWaitToStart: [fStartCheck state] == NSOnState];
|
||||||
[fTorrent setGroupValue: [[fGroupPopUp selectedItem] tag]];
|
[fTorrent setGroupValue: fGroupValue];
|
||||||
|
|
||||||
if ([fDeleteCheck state] == NSOnState)
|
if ([fDeleteCheck state] == NSOnState)
|
||||||
[fTorrent trashTorrent];
|
[fTorrent trashTorrent];
|
||||||
@@ -259,18 +260,22 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (void) setDestinationPath: (NSString *) destination
|
- (void) setDestinationPath: (NSString *) destination
|
||||||
|
{
|
||||||
|
destination = [destination stringByExpandingTildeInPath];
|
||||||
|
if (!fDestination || ![fDestination isEqualToString: destination])
|
||||||
{
|
{
|
||||||
[fDestination release];
|
[fDestination release];
|
||||||
fDestination = [destination retain];
|
fDestination = [destination retain];
|
||||||
|
|
||||||
|
[fTorrent changeDownloadFolder: fDestination];
|
||||||
|
}
|
||||||
|
|
||||||
[fLocationField setStringValue: [fDestination stringByAbbreviatingWithTildeInPath]];
|
[fLocationField setStringValue: [fDestination stringByAbbreviatingWithTildeInPath]];
|
||||||
[fLocationField setToolTip: fDestination];
|
[fLocationField setToolTip: fDestination];
|
||||||
|
|
||||||
ExpandedPathToIconTransformer * iconTransformer = [[ExpandedPathToIconTransformer alloc] init];
|
ExpandedPathToIconTransformer * iconTransformer = [[ExpandedPathToIconTransformer alloc] init];
|
||||||
[fLocationImageView setImage: [iconTransformer transformedValue: fDestination]];
|
[fLocationImageView setImage: [iconTransformer transformedValue: fDestination]];
|
||||||
[iconTransformer release];
|
[iconTransformer release];
|
||||||
|
|
||||||
[fTorrent changeDownloadFolder: fDestination];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) folderChoiceClosed: (NSOpenPanel *) openPanel returnCode: (NSInteger) code contextInfo: (void *) contextInfo
|
- (void) folderChoiceClosed: (NSOpenPanel *) openPanel returnCode: (NSInteger) code contextInfo: (void *) contextInfo
|
||||||
|
|||||||
@@ -860,6 +860,11 @@ static void sleepCallback(void * controller, io_service_t y, natural_t messageTy
|
|||||||
{
|
{
|
||||||
[torrent setWaitToStart: [fDefaults boolForKey: @"AutoStartDownload"]];
|
[torrent setWaitToStart: [fDefaults boolForKey: @"AutoStartDownload"]];
|
||||||
|
|
||||||
|
#warning move into torrent init?
|
||||||
|
if ([torrent groupValue] != -1 && [[GroupsController groups] usesCustomDownloadLocationForIndex: [torrent groupValue]]
|
||||||
|
&& [[GroupsController groups] customDownloadLocationForIndex: [torrent groupValue]])
|
||||||
|
[torrent changeDownloadFolder: [[GroupsController groups] customDownloadLocationForIndex: [torrent groupValue]]];
|
||||||
|
|
||||||
[torrent update];
|
[torrent update];
|
||||||
[fTorrents addObject: torrent];
|
[fTorrents addObject: torrent];
|
||||||
[torrent release];
|
[torrent release];
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
#import <Cocoa/Cocoa.h>
|
#import <Cocoa/Cocoa.h>
|
||||||
|
#import "Torrent.h"
|
||||||
|
|
||||||
@interface GroupsController : NSObject
|
@interface GroupsController : NSObject
|
||||||
{
|
{
|
||||||
@@ -50,6 +51,12 @@
|
|||||||
- (NSString *) customDownloadLocationForIndex: (NSInteger) index;
|
- (NSString *) customDownloadLocationForIndex: (NSInteger) index;
|
||||||
- (void) setCustomDownloadLocation: (NSString *) location forIndex: (NSInteger) index;
|
- (void) setCustomDownloadLocation: (NSString *) location forIndex: (NSInteger) index;
|
||||||
|
|
||||||
|
- (BOOL) usesAutoAssignRulesForIndex: (NSInteger) index;
|
||||||
|
- (void) setUsesAutoAssignRules: (BOOL) useAutoAssignRules forIndex: (NSInteger) index;
|
||||||
|
|
||||||
|
- (NSArray *) autoAssignRulesForIndex: (NSInteger) index;
|
||||||
|
- (void) setAutoAssignRules: (NSArray *) rules forIndex: (NSInteger) index;
|
||||||
|
|
||||||
- (void) addNewGroup;
|
- (void) addNewGroup;
|
||||||
- (void) removeGroupWithRowIndex: (NSInteger) row;
|
- (void) removeGroupWithRowIndex: (NSInteger) row;
|
||||||
|
|
||||||
@@ -57,4 +64,5 @@
|
|||||||
|
|
||||||
- (NSMenu *) groupMenuWithTarget: (id) target action: (SEL) action isSmall: (BOOL) small;
|
- (NSMenu *) groupMenuWithTarget: (id) target action: (SEL) action isSmall: (BOOL) small;
|
||||||
|
|
||||||
|
- (NSInteger) groupIndexForTorrent: (Torrent *) torrent;
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -35,6 +35,8 @@
|
|||||||
|
|
||||||
- (NSImage *) imageForGroup: (NSMutableDictionary *) dict;
|
- (NSImage *) imageForGroup: (NSMutableDictionary *) dict;
|
||||||
|
|
||||||
|
- (BOOL) torrent: (Torrent *) torrent doesMatchRulesForGroupAtIndex: (NSInteger) index;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation GroupsController
|
@implementation GroupsController
|
||||||
@@ -179,7 +181,6 @@ GroupsController * fGroupsInstance = nil;
|
|||||||
[dict setObject: [NSNumber numberWithBool: useCustomLocation] forKey: @"UsesCustomDownloadLocation"];
|
[dict setObject: [NSNumber numberWithBool: useCustomLocation] forKey: @"UsesCustomDownloadLocation"];
|
||||||
|
|
||||||
[[GroupsController groups] saveGroups];
|
[[GroupsController groups] saveGroups];
|
||||||
[[NSNotificationCenter defaultCenter] postNotificationName: @"UpdateGroups" object: self];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSString *) customDownloadLocationForIndex: (NSInteger) index
|
- (NSString *) customDownloadLocationForIndex: (NSInteger) index
|
||||||
@@ -195,10 +196,54 @@ GroupsController * fGroupsInstance = nil;
|
|||||||
if (location)
|
if (location)
|
||||||
[dict setObject: location forKey: @"CustomDownloadLocation"];
|
[dict setObject: location forKey: @"CustomDownloadLocation"];
|
||||||
else
|
else
|
||||||
|
{
|
||||||
[dict removeObjectForKey: @"CustomDownloadLocation"];
|
[dict removeObjectForKey: @"CustomDownloadLocation"];
|
||||||
|
[self setUsesCustomDownloadLocation: NO forIndex: index];
|
||||||
|
}
|
||||||
|
|
||||||
[[GroupsController groups] saveGroups];
|
[[GroupsController groups] saveGroups];
|
||||||
[[NSNotificationCenter defaultCenter] postNotificationName: @"UpdateGroups" object: self];
|
}
|
||||||
|
|
||||||
|
- (BOOL) usesAutoAssignRulesForIndex: (NSInteger) index
|
||||||
|
{
|
||||||
|
NSInteger orderIndex = [self rowValueForIndex: index];
|
||||||
|
if (orderIndex == -1)
|
||||||
|
return NO;
|
||||||
|
|
||||||
|
NSNumber * assignRules = [[fGroups objectAtIndex: orderIndex] objectForKey: @"UsesAutoAssignRules"];
|
||||||
|
return assignRules && [assignRules boolValue];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) setUsesAutoAssignRules: (BOOL) useAutoAssignRules forIndex: (NSInteger) index
|
||||||
|
{
|
||||||
|
NSMutableDictionary * dict = [fGroups objectAtIndex: [self rowValueForIndex: index]];
|
||||||
|
|
||||||
|
[dict setObject: [NSNumber numberWithBool: useAutoAssignRules] forKey: @"UsesAutoAssignRules"];
|
||||||
|
|
||||||
|
[[GroupsController groups] saveGroups];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSArray *) autoAssignRulesForIndex: (NSInteger) index
|
||||||
|
{
|
||||||
|
NSInteger orderIndex = [self rowValueForIndex: index];
|
||||||
|
return orderIndex != -1 ? [[fGroups objectAtIndex: orderIndex] objectForKey: @"AutoAssignRules"] : nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) setAutoAssignRules: (NSArray *) rules forIndex: (NSInteger) index
|
||||||
|
{
|
||||||
|
NSMutableDictionary * dict = [fGroups objectAtIndex: [self rowValueForIndex: index]];
|
||||||
|
|
||||||
|
if (rules && [rules count] > 0)
|
||||||
|
{
|
||||||
|
[dict setObject: rules forKey: @"AutoAssignRules"];
|
||||||
|
|
||||||
|
[[GroupsController groups] saveGroups];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
[dict removeObjectForKey: @"AutoAssignRules"];
|
||||||
|
[self setUsesAutoAssignRules: NO forIndex: index];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) addNewGroup
|
- (void) addNewGroup
|
||||||
@@ -315,6 +360,19 @@ GroupsController * fGroupsInstance = nil;
|
|||||||
return [menu autorelease];
|
return [menu autorelease];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (NSInteger) groupIndexForTorrent: (Torrent *) torrent;
|
||||||
|
{
|
||||||
|
NSEnumerator * enumerator = [fGroups objectEnumerator];
|
||||||
|
NSMutableDictionary * group;
|
||||||
|
while ((group = [enumerator nextObject]))
|
||||||
|
{
|
||||||
|
NSInteger row = [[group objectForKey: @"Index"] intValue];
|
||||||
|
if ([self torrent: torrent doesMatchRulesForGroupAtIndex: row])
|
||||||
|
return row;
|
||||||
|
}
|
||||||
|
return -1; // Default to no group
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation GroupsController (Private)
|
@implementation GroupsController (Private)
|
||||||
@@ -370,4 +428,56 @@ GroupsController * fGroupsInstance = nil;
|
|||||||
return icon;
|
return icon;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (BOOL) torrent: (Torrent *) torrent doesMatchRulesForGroupAtIndex: (NSInteger) index
|
||||||
|
{
|
||||||
|
if (![self usesAutoAssignRulesForIndex: index])
|
||||||
|
return NO;
|
||||||
|
|
||||||
|
NSArray * rules = [self autoAssignRulesForIndex: index];
|
||||||
|
if (!rules || [rules count] == 0)
|
||||||
|
return NO;
|
||||||
|
|
||||||
|
#warning should rules be dict instead of array?
|
||||||
|
NSEnumerator * iterator = [rules objectEnumerator];
|
||||||
|
NSArray * rule = nil;
|
||||||
|
while ((rule = [iterator nextObject]))
|
||||||
|
{
|
||||||
|
NSString * type = [rule objectAtIndex: 0], * place = [rule objectAtIndex: 1], * match = [rule objectAtIndex: 2],
|
||||||
|
* value = nil;
|
||||||
|
if ([type isEqualToString: @"title"])
|
||||||
|
value = [torrent name];
|
||||||
|
else if ([type isEqualToString: @"tracker"])
|
||||||
|
{
|
||||||
|
#warning consider all trackers
|
||||||
|
value = [torrent trackerAddressAnnounce];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
|
||||||
|
NSStringCompareOptions options = NSCaseInsensitiveSearch;
|
||||||
|
if ([place isEqualToString: @"ends"])
|
||||||
|
options += NSBackwardsSearch;
|
||||||
|
|
||||||
|
NSRange result = [value rangeOfString: match options: options];
|
||||||
|
if ([place isEqualToString: @"begins"])
|
||||||
|
{
|
||||||
|
if (result.location != 0)
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
else if ([place isEqualToString: @"contains"])
|
||||||
|
{
|
||||||
|
if (result.location == NSNotFound)
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
else if ([place isEqualToString: @"ends"])
|
||||||
|
{
|
||||||
|
if (NSMaxRange(result) == [value length])
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -35,10 +35,21 @@
|
|||||||
IBOutlet NSTextField * fSelectedColorNameField;
|
IBOutlet NSTextField * fSelectedColorNameField;
|
||||||
IBOutlet NSButton * fCustomLocationEnableCheck;
|
IBOutlet NSButton * fCustomLocationEnableCheck;
|
||||||
IBOutlet NSPopUpButton * fCustomLocationPopUp;
|
IBOutlet NSPopUpButton * fCustomLocationPopUp;
|
||||||
|
|
||||||
|
IBOutlet NSView * fGroupRulesPrefsContainer;
|
||||||
|
IBOutlet NSButton * fAutoAssignRulesEnableCheck;
|
||||||
|
IBOutlet NSButton * fAutoAssignRulesEditButton;
|
||||||
|
IBOutlet NSWindow * fGroupRulesSheetWindow;
|
||||||
|
IBOutlet NSRuleEditor * fRuleEditor;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) addRemoveGroup: (id) sender;
|
- (void) addRemoveGroup: (id) sender;
|
||||||
|
|
||||||
- (IBAction) toggleUseCustomDownloadLocation: (id) sender;
|
- (IBAction) toggleUseCustomDownloadLocation: (id) sender;
|
||||||
- (IBAction) customDownloadLocationSheetShow: (id) sender;
|
- (IBAction) customDownloadLocationSheetShow: (id) sender;
|
||||||
|
|
||||||
|
- (IBAction) toggleUseAutoAssignRules: (id) sender;
|
||||||
|
- (IBAction) orderFrontRulesSheet: (id) sender;
|
||||||
|
- (IBAction) cancelRules: (id) sender;
|
||||||
|
- (IBAction) saveRules: (id) sender;
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -50,6 +50,7 @@
|
|||||||
[fAddRemoveControl sizeToFit];
|
[fAddRemoveControl sizeToFit];
|
||||||
[fAddRemoveControl setLabel: @"+" forSegment: ADD_TAG];
|
[fAddRemoveControl setLabel: @"+" forSegment: ADD_TAG];
|
||||||
[fAddRemoveControl setLabel: @"-" forSegment: REMOVE_TAG];
|
[fAddRemoveControl setLabel: @"-" forSegment: REMOVE_TAG];
|
||||||
|
[fGroupRulesPrefsContainer setHidden: YES]; //get rid of container when 10.5-only
|
||||||
}
|
}
|
||||||
|
|
||||||
[fSelectedColorView addObserver: self forKeyPath: @"color" options: 0 context: NULL];
|
[fSelectedColorView addObserver: self forKeyPath: @"color" options: 0 context: NULL];
|
||||||
@@ -235,6 +236,155 @@
|
|||||||
[fCustomLocationPopUp selectItemAtIndex: 0];
|
[fCustomLocationPopUp selectItemAtIndex: 0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma mark -
|
||||||
|
#pragma mark Rule editor
|
||||||
|
|
||||||
|
- (IBAction) toggleUseAutoAssignRules: (id) sender;
|
||||||
|
{
|
||||||
|
NSInteger index = [[GroupsController groups] indexForRow: [fTableView selectedRow]];
|
||||||
|
if ([fAutoAssignRulesEnableCheck state] == NSOnState)
|
||||||
|
{
|
||||||
|
if ([[GroupsController groups] autoAssignRulesForIndex: index])
|
||||||
|
[[GroupsController groups] setUsesAutoAssignRules: YES forIndex: index];
|
||||||
|
else
|
||||||
|
[self orderFrontRulesSheet: nil];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
[[GroupsController groups] setUsesAutoAssignRules: NO forIndex: index];
|
||||||
|
|
||||||
|
[fAutoAssignRulesEditButton setEnabled: [fAutoAssignRulesEnableCheck state] == NSOnState];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (IBAction) orderFrontRulesSheet: (id) sender;
|
||||||
|
{
|
||||||
|
if (!fGroupRulesSheetWindow)
|
||||||
|
[NSBundle loadNibNamed: @"GroupRules" owner: self];
|
||||||
|
|
||||||
|
[fRuleEditor removeRowsAtIndexes: [NSIndexSet indexSetWithIndexesInRange: NSMakeRange(0, [fRuleEditor numberOfRows])]
|
||||||
|
includeSubrows: YES];
|
||||||
|
|
||||||
|
NSInteger index = [[GroupsController groups] indexForRow: [fTableView selectedRow]];
|
||||||
|
NSArray * rules = [[GroupsController groups] autoAssignRulesForIndex: index];
|
||||||
|
if (rules)
|
||||||
|
{
|
||||||
|
for (NSInteger index = 0; index < [rules count]; index++)
|
||||||
|
{
|
||||||
|
[fRuleEditor addRow: nil];
|
||||||
|
[fRuleEditor setCriteria: [rules objectAtIndex: index] andDisplayValues: [NSArray array] forRowAtIndex: index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ([fRuleEditor numberOfRows] == 0)
|
||||||
|
[fRuleEditor addRow: nil];
|
||||||
|
|
||||||
|
[NSApp beginSheet: fGroupRulesSheetWindow
|
||||||
|
modalForWindow: [fTableView window]
|
||||||
|
modalDelegate: nil
|
||||||
|
didEndSelector: NULL
|
||||||
|
contextInfo: NULL];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (IBAction) cancelRules: (id) sender;
|
||||||
|
{
|
||||||
|
[fGroupRulesSheetWindow orderOut: nil];
|
||||||
|
[NSApp endSheet: fGroupRulesSheetWindow];
|
||||||
|
|
||||||
|
NSInteger index = [[GroupsController groups] indexForRow: [fTableView selectedRow]];
|
||||||
|
if (![[GroupsController groups] autoAssignRulesForIndex: index])
|
||||||
|
{
|
||||||
|
[[GroupsController groups] setUsesAutoAssignRules: NO forIndex: index];
|
||||||
|
[fAutoAssignRulesEnableCheck setState: NO];
|
||||||
|
[fAutoAssignRulesEditButton setEnabled: NO];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (IBAction) saveRules: (id) sender;
|
||||||
|
{
|
||||||
|
[fGroupRulesSheetWindow orderOut: nil];
|
||||||
|
[NSApp endSheet: fGroupRulesSheetWindow];
|
||||||
|
|
||||||
|
NSInteger index = [[GroupsController groups] indexForRow: [fTableView selectedRow]];
|
||||||
|
[[GroupsController groups] setUsesAutoAssignRules: YES forIndex: index];
|
||||||
|
|
||||||
|
NSMutableArray * rules = [NSMutableArray arrayWithCapacity: [fRuleEditor numberOfRows]];
|
||||||
|
for (NSInteger index = 0; index < [fRuleEditor numberOfRows]; ++index)
|
||||||
|
{
|
||||||
|
NSString * string = [[[fRuleEditor displayValuesForRow: index] objectAtIndex: 2] stringValue];
|
||||||
|
if (string && [string length] > 0)
|
||||||
|
{
|
||||||
|
NSMutableArray * rule = [[[fRuleEditor criteriaForRow: index] mutableCopy] autorelease];
|
||||||
|
[rule replaceObjectAtIndex: 2 withObject: string];
|
||||||
|
[rules addObject: rule];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[[GroupsController groups] setAutoAssignRules: rules forIndex: index];
|
||||||
|
[fAutoAssignRulesEnableCheck setState: [[GroupsController groups] usesAutoAssignRulesForIndex: index]];
|
||||||
|
[fAutoAssignRulesEditButton setEnabled: [fAutoAssignRulesEnableCheck state] == NSOnState];
|
||||||
|
}
|
||||||
|
|
||||||
|
static NSString * torrentTitleCriteria = @"title";
|
||||||
|
static NSString * trackerURLCriteria = @"tracker";
|
||||||
|
static NSString * startsWithCriteria = @"begins";
|
||||||
|
static NSString * containsCriteria = @"contains";
|
||||||
|
static NSString * endsWithCriteria = @"ends";
|
||||||
|
|
||||||
|
- (NSInteger) ruleEditor: (NSRuleEditor *) editor numberOfChildrenForCriterion: (id) criterion withRowType: (NSRuleEditorRowType) rowType
|
||||||
|
{
|
||||||
|
if (!criterion)
|
||||||
|
return 2;
|
||||||
|
else if ([criterion isEqualToString: torrentTitleCriteria] || [criterion isEqualToString: trackerURLCriteria])
|
||||||
|
return 3;
|
||||||
|
else if ([criterion isEqualToString: startsWithCriteria] || [criterion isEqualToString: containsCriteria]
|
||||||
|
|| [criterion isEqualToString: endsWithCriteria])
|
||||||
|
return 1;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id) ruleEditor: (NSRuleEditor *) editor child: (NSInteger) index forCriterion: (id) criterion
|
||||||
|
withRowType: (NSRuleEditorRowType) rowType
|
||||||
|
{
|
||||||
|
if (criterion == nil)
|
||||||
|
return [[NSArray arrayWithObjects: torrentTitleCriteria, trackerURLCriteria, nil] objectAtIndex: index];
|
||||||
|
else if ([criterion isEqualToString: torrentTitleCriteria] || [criterion isEqualToString: trackerURLCriteria])
|
||||||
|
return [[NSArray arrayWithObjects: startsWithCriteria, containsCriteria, endsWithCriteria, nil] objectAtIndex: index];
|
||||||
|
else
|
||||||
|
return @"";
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id) ruleEditor: (NSRuleEditor *) editor displayValueForCriterion: (id) criterion inRow: (NSInteger) row
|
||||||
|
{
|
||||||
|
if ([criterion isEqualToString: torrentTitleCriteria])
|
||||||
|
return NSLocalizedString(@"Torrent Title", "Groups -> rule editor");
|
||||||
|
else if ([criterion isEqualToString: trackerURLCriteria])
|
||||||
|
return NSLocalizedString(@"Tracker URL", "Groups -> rule editor");
|
||||||
|
else if ([criterion isEqualToString: startsWithCriteria])
|
||||||
|
return NSLocalizedString(@"Starts With", "Groups -> rule editor");
|
||||||
|
else if ([criterion isEqualToString: containsCriteria])
|
||||||
|
return NSLocalizedString(@"Contains", "Groups -> rule editor");
|
||||||
|
else if ([criterion isEqualToString: endsWithCriteria])
|
||||||
|
return NSLocalizedString(@"Ends With", "Groups -> rule editor");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NSTextField * field = [[NSTextField alloc] initWithFrame: NSMakeRect(0, 0, 130, 22)];
|
||||||
|
[field setStringValue: criterion];
|
||||||
|
return [field autorelease];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) ruleEditorRowsDidChange: (NSNotification *) notification
|
||||||
|
{
|
||||||
|
CGFloat rowHeight = [fRuleEditor rowHeight];
|
||||||
|
NSInteger numberOfRows = [fRuleEditor numberOfRows];
|
||||||
|
CGFloat ruleEditorHeight = numberOfRows * rowHeight;
|
||||||
|
CGFloat heightDifference = ruleEditorHeight - [fRuleEditor frame].size.height;
|
||||||
|
NSRect windowFrame = [fRuleEditor window].frame;
|
||||||
|
windowFrame.size.height += heightDifference;
|
||||||
|
windowFrame.origin.y -= heightDifference;
|
||||||
|
[fRuleEditor.window setFrame: windowFrame display: YES animate: YES];
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation GroupsPrefsController (Private)
|
@implementation GroupsPrefsController (Private)
|
||||||
@@ -265,6 +415,10 @@
|
|||||||
[[fCustomLocationPopUp itemAtIndex: 0] setTitle: @""];
|
[[fCustomLocationPopUp itemAtIndex: 0] setTitle: @""];
|
||||||
[[fCustomLocationPopUp itemAtIndex: 0] setImage: nil];
|
[[fCustomLocationPopUp itemAtIndex: 0] setImage: nil];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[fAutoAssignRulesEnableCheck setState: [[GroupsController groups] usesAutoAssignRulesForIndex: index]];
|
||||||
|
[fAutoAssignRulesEnableCheck setEnabled: YES];
|
||||||
|
[fAutoAssignRulesEditButton setEnabled: ([fAutoAssignRulesEnableCheck state] == NSOnState)];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -274,6 +428,8 @@
|
|||||||
[fSelectedColorNameField setEnabled: NO];
|
[fSelectedColorNameField setEnabled: NO];
|
||||||
[fCustomLocationEnableCheck setEnabled: NO];
|
[fCustomLocationEnableCheck setEnabled: NO];
|
||||||
[fCustomLocationPopUp setEnabled: NO];
|
[fCustomLocationPopUp setEnabled: NO];
|
||||||
|
[fAutoAssignRulesEnableCheck setEnabled: NO];
|
||||||
|
[fAutoAssignRulesEditButton setEnabled: NO];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -221,6 +221,9 @@ void completenessChangeCallback(tr_torrent * torrent, tr_completeness status, vo
|
|||||||
|
|
||||||
- (void) changeDownloadFolder: (NSString *) folder
|
- (void) changeDownloadFolder: (NSString *) folder
|
||||||
{
|
{
|
||||||
|
if (fDownloadFolder && [folder isEqualToString: fDownloadFolder])
|
||||||
|
return;
|
||||||
|
|
||||||
[fDownloadFolder release];
|
[fDownloadFolder release];
|
||||||
fDownloadFolder = [folder retain];
|
fDownloadFolder = [folder retain];
|
||||||
|
|
||||||
@@ -1761,7 +1764,7 @@ void completenessChangeCallback(tr_torrent * torrent, tr_completeness status, vo
|
|||||||
fResumeOnWake = NO;
|
fResumeOnWake = NO;
|
||||||
|
|
||||||
fOrderValue = orderValue ? [orderValue intValue] : tr_sessionCountTorrents(lib) - 1;
|
fOrderValue = orderValue ? [orderValue intValue] : tr_sessionCountTorrents(lib) - 1;
|
||||||
fGroupValue = groupValue ? [groupValue intValue] : -1;
|
fGroupValue = groupValue ? [groupValue intValue] : [[GroupsController groups] groupIndexForTorrent: self];
|
||||||
|
|
||||||
fAddedTrackers = addedTrackers ? [addedTrackers boolValue] : NO;
|
fAddedTrackers = addedTrackers ? [addedTrackers boolValue] : NO;
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user