source: trunk/macosx/GroupsController.m @ 10448

Last change on this file since 10448 was 10448, checked in by livings124, 12 years ago

restore ability to toggle pieces view by clicking on it

  • Property svn:keywords set to Date Rev Author Id
File size: 15.5 KB
Line 
1/******************************************************************************
2 * $Id: GroupsController.m 10448 2010-04-06 01:41:16Z livings124 $
3 *
4 * Copyright (c) 2007-2010 Transmission authors and contributors
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 *****************************************************************************/
24
25#import "GroupsController.h"
26
27#define ICON_WIDTH 16.0
28#define ICON_WIDTH_SMALL 12.0
29
30@interface GroupsController (Private)
31
32- (void) saveGroups;
33
34- (NSImage *) imageForGroup: (NSMutableDictionary *) dict;
35
36- (BOOL) torrent: (Torrent *) torrent doesMatchRulesForGroupAtIndex: (NSInteger) index;
37
38@end
39
40@implementation GroupsController
41
42GroupsController * fGroupsInstance = nil;
43+ (GroupsController *) groups
44{
45    if (!fGroupsInstance)
46        fGroupsInstance = [[GroupsController alloc] init];
47    return fGroupsInstance;
48}
49
50- (id) init
51{
52    if ((self = [super init]))
53    {
54        NSData * data;
55        if ((data = [[NSUserDefaults standardUserDefaults] dataForKey: @"GroupDicts"]))
56            fGroups = [[NSKeyedUnarchiver unarchiveObjectWithData: data] retain];
57        else if ((data = [[NSUserDefaults standardUserDefaults] dataForKey: @"Groups"])) //handle old groups
58        {
59            fGroups = [[NSUnarchiver unarchiveObjectWithData: data] retain];
60            [[NSUserDefaults standardUserDefaults] removeObjectForKey: @"Groups"];
61            [self saveGroups];
62        }
63        else
64        {
65            //default groups
66            NSMutableDictionary * red = [NSMutableDictionary dictionaryWithObjectsAndKeys:
67                                            [NSColor redColor], @"Color",
68                                            NSLocalizedString(@"Red", "Groups -> Name"), @"Name",
69                                            [NSNumber numberWithInteger: 0], @"Index", nil];
70           
71            NSMutableDictionary * orange = [NSMutableDictionary dictionaryWithObjectsAndKeys:
72                                            [NSColor orangeColor], @"Color",
73                                            NSLocalizedString(@"Orange", "Groups -> Name"), @"Name",
74                                            [NSNumber numberWithInteger: 1], @"Index", nil];
75           
76            NSMutableDictionary * yellow = [NSMutableDictionary dictionaryWithObjectsAndKeys:
77                                            [NSColor yellowColor], @"Color",
78                                            NSLocalizedString(@"Yellow", "Groups -> Name"), @"Name",
79                                            [NSNumber numberWithInteger: 2], @"Index", nil];
80           
81            NSMutableDictionary * green = [NSMutableDictionary dictionaryWithObjectsAndKeys:
82                                            [NSColor greenColor], @"Color",
83                                            NSLocalizedString(@"Green", "Groups -> Name"), @"Name",
84                                            [NSNumber numberWithInteger: 3], @"Index", nil];
85           
86            NSMutableDictionary * blue = [NSMutableDictionary dictionaryWithObjectsAndKeys:
87                                            [NSColor blueColor], @"Color",
88                                            NSLocalizedString(@"Blue", "Groups -> Name"), @"Name",
89                                            [NSNumber numberWithInteger: 4], @"Index", nil];
90           
91            NSMutableDictionary * purple = [NSMutableDictionary dictionaryWithObjectsAndKeys:
92                                            [NSColor purpleColor], @"Color",
93                                            NSLocalizedString(@"Purple", "Groups -> Name"), @"Name",
94                                            [NSNumber numberWithInteger: 5], @"Index", nil];
95           
96            NSMutableDictionary * gray = [NSMutableDictionary dictionaryWithObjectsAndKeys:
97                                            [NSColor grayColor], @"Color",
98                                            NSLocalizedString(@"Gray", "Groups -> Name"), @"Name",
99                                            [NSNumber numberWithInteger: 6], @"Index", nil];
100           
101            fGroups = [[NSMutableArray alloc] initWithObjects: red, orange, yellow, green, blue, purple, gray, nil];
102            [self saveGroups]; //make sure this is saved right away
103        }
104    }
105   
106    return self;
107}
108
109- (void) dealloc
110{
111    [fGroups release];
112    [super dealloc];
113}
114
115- (NSInteger) numberOfGroups
116{
117    return [fGroups count];
118}
119
120- (NSInteger) rowValueForIndex: (NSInteger) index
121{
122    if (index != -1)
123    {
124        for (NSInteger i = 0; i < [fGroups count]; i++)
125            if (index == [[[fGroups objectAtIndex: i] objectForKey: @"Index"] integerValue])
126                return i;
127    }
128    return -1;
129}
130
131- (NSInteger) indexForRow: (NSInteger) row
132{
133    return [[[fGroups objectAtIndex: row] objectForKey: @"Index"] integerValue];
134}
135
136- (NSString *) nameForIndex: (NSInteger) index
137{
138    NSInteger orderIndex = [self rowValueForIndex: index];
139    return orderIndex != -1 ? [[fGroups objectAtIndex: orderIndex] objectForKey: @"Name"] : nil;
140}
141
142- (void) setName: (NSString *) name forIndex: (NSInteger) index
143{
144    NSInteger orderIndex = [self rowValueForIndex: index];
145    [[fGroups objectAtIndex: orderIndex] setObject: name forKey: @"Name"];
146    [self saveGroups];
147   
148    [[NSNotificationCenter defaultCenter] postNotificationName: @"UpdateGroups" object: self];
149}
150
151- (NSImage *) imageForIndex: (NSInteger) index
152{
153    NSInteger orderIndex = [self rowValueForIndex: index];
154    return orderIndex != -1 ? [self imageForGroup: [fGroups objectAtIndex: orderIndex]]
155                            : [NSImage imageNamed: @"GroupsNoneTemplate.png"];
156}
157
158- (NSColor *) colorForIndex: (NSInteger) index
159{
160    NSInteger orderIndex = [self rowValueForIndex: index];
161    return orderIndex != -1 ? [[fGroups objectAtIndex: orderIndex] objectForKey: @"Color"] : nil;
162}
163
164- (void) setColor: (NSColor *) color forIndex: (NSInteger) index
165{
166    NSMutableDictionary * dict = [fGroups objectAtIndex: [self rowValueForIndex: index]];
167    [dict removeObjectForKey: @"Icon"];
168   
169    [dict setObject: color forKey: @"Color"];
170   
171    [[GroupsController groups] saveGroups];
172    [[NSNotificationCenter defaultCenter] postNotificationName: @"UpdateGroups" object: self];
173}
174
175- (BOOL) usesCustomDownloadLocationForIndex: (NSInteger) index
176{
177    if (![self customDownloadLocationForIndex: index])
178        return NO;
179
180    NSInteger orderIndex = [self rowValueForIndex: index];
181    return [[[fGroups objectAtIndex: orderIndex] objectForKey: @"UsesCustomDownloadLocation"] boolValue];
182}
183
184- (void) setUsesCustomDownloadLocation: (BOOL) useCustomLocation forIndex: (NSInteger) index
185{
186    NSMutableDictionary * dict = [fGroups objectAtIndex: [self rowValueForIndex: index]];
187   
188    [dict setObject: [NSNumber numberWithBool: useCustomLocation] forKey: @"UsesCustomDownloadLocation"];
189   
190    [[GroupsController groups] saveGroups];
191}
192
193- (NSString *) customDownloadLocationForIndex: (NSInteger) index
194{
195    NSInteger orderIndex = [self rowValueForIndex: index];
196    return orderIndex != -1 ? [[fGroups objectAtIndex: orderIndex] objectForKey: @"CustomDownloadLocation"] : nil;
197}
198
199- (void) setCustomDownloadLocation: (NSString *) location forIndex: (NSInteger) index
200{
201    NSMutableDictionary * dict = [fGroups objectAtIndex: [self rowValueForIndex: index]];
202    [dict setObject: location forKey: @"CustomDownloadLocation"];
203   
204    [[GroupsController groups] saveGroups];
205}
206
207- (BOOL) usesAutoAssignRulesForIndex: (NSInteger) index
208{
209    NSInteger orderIndex = [self rowValueForIndex: index];
210    if (orderIndex == -1)
211        return NO;
212   
213    NSNumber * assignRules = [[fGroups objectAtIndex: orderIndex] objectForKey: @"UsesAutoGroupRules"];
214    return assignRules && [assignRules boolValue];
215}
216
217- (void) setUsesAutoAssignRules: (BOOL) useAutoAssignRules forIndex: (NSInteger) index
218{
219    NSMutableDictionary * dict = [fGroups objectAtIndex: [self rowValueForIndex: index]];
220   
221    [dict setObject: [NSNumber numberWithBool: useAutoAssignRules] forKey: @"UsesAutoGroupRules"];
222   
223    [[GroupsController groups] saveGroups];
224}
225
226- (NSPredicate *) autoAssignRulesForIndex: (NSInteger) index
227{
228    NSInteger orderIndex = [self rowValueForIndex: index];
229    if (orderIndex == -1)
230                return nil;
231       
232        return [[fGroups objectAtIndex: orderIndex] objectForKey: @"AutoGroupRules"];
233}
234
235- (void) setAutoAssignRules: (NSPredicate *) predicate forIndex: (NSInteger) index
236{
237    NSMutableDictionary * dict = [fGroups objectAtIndex: [self rowValueForIndex: index]];
238   
239    if (predicate)
240    {
241        [dict setObject: predicate forKey: @"AutoGroupRules"];
242        [[GroupsController groups] saveGroups];
243    }
244    else
245    {
246        [dict removeObjectForKey: @"AutoGroupRules"];
247        [self setUsesAutoAssignRules: NO forIndex: index];
248    }
249}
250
251- (void) addNewGroup
252{
253    //find the lowest index
254    NSMutableIndexSet * candidates = [NSMutableIndexSet indexSetWithIndexesInRange: NSMakeRange(0, [fGroups count]+1)];
255    for (NSDictionary * dict in fGroups)
256        [candidates removeIndex: [[dict objectForKey: @"Index"] integerValue]];
257   
258    const NSInteger index = [candidates firstIndex];
259   
260    [fGroups addObject: [NSMutableDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithInteger: index], @"Index",
261                            [NSColor colorWithCalibratedRed: 0.0 green: 0.65 blue: 1.0 alpha: 1.0], @"Color", @"", @"Name", nil]];
262   
263    [[NSNotificationCenter defaultCenter] postNotificationName: @"UpdateGroups" object: self];
264    [self saveGroups];
265}
266
267- (void) removeGroupWithRowIndex: (NSInteger) row
268{
269    NSInteger index = [[[fGroups objectAtIndex: row] objectForKey: @"Index"] integerValue];
270    [fGroups removeObjectAtIndex: row];
271   
272    [[NSNotificationCenter defaultCenter] postNotificationName: @"GroupValueRemoved" object: self userInfo:
273        [NSDictionary dictionaryWithObject: [NSNumber numberWithInteger: index] forKey: @"Index"]];
274   
275    if (index == [[NSUserDefaults standardUserDefaults] integerForKey: @"FilterGroup"])
276        [[NSUserDefaults standardUserDefaults] setInteger: -2 forKey: @"FilterGroup"];
277   
278    [[NSNotificationCenter defaultCenter] postNotificationName: @"UpdateGroups" object: self];
279    [self saveGroups];
280}
281
282- (void) moveGroupAtRow: (NSInteger) oldRow toRow: (NSInteger) newRow
283{
284    if (oldRow < newRow)
285        newRow--;
286   
287    //remove objects to reinsert
288    id movingGroup = [[fGroups objectAtIndex: oldRow] retain];
289    [fGroups removeObjectAtIndex: oldRow];
290   
291    //insert objects at new location
292    [fGroups insertObject: movingGroup atIndex: newRow];
293   
294    [movingGroup release];
295   
296    [self saveGroups];
297    [[NSNotificationCenter defaultCenter] postNotificationName: @"UpdateGroups" object: self];
298}
299
300- (NSMenu *) groupMenuWithTarget: (id) target action: (SEL) action isSmall: (BOOL) small
301{
302    NSMenu * menu = [[NSMenu alloc] initWithTitle: @"Groups"];
303   
304    NSMenuItem * item = [[NSMenuItem alloc] initWithTitle: NSLocalizedString(@"None", "Groups -> Menu") action: action
305                            keyEquivalent: @""];
306    [item setTarget: target];
307    [item setTag: -1];
308   
309    NSImage * icon = [NSImage imageNamed: @"GroupsNoneTemplate.png"];
310    if (small)
311    {
312        icon = [icon copy];
313        [icon setSize: NSMakeSize(ICON_WIDTH_SMALL, ICON_WIDTH_SMALL)];
314       
315        [item setImage: icon];
316        [icon release];
317    }
318    else
319        [item setImage: icon];
320   
321    [menu addItem: item];
322    [item release];
323   
324    for (NSMutableDictionary * dict in fGroups)
325    {
326        item = [[NSMenuItem alloc] initWithTitle: [dict objectForKey: @"Name"] action: action keyEquivalent: @""];
327        [item setTarget: target];
328       
329        [item setTag: [[dict objectForKey: @"Index"] integerValue]];
330       
331        NSImage * icon = [self imageForGroup: dict];
332        if (small)
333        {
334            icon = [icon copy];
335            [icon setSize: NSMakeSize(ICON_WIDTH_SMALL, ICON_WIDTH_SMALL)];
336           
337            [item setImage: icon];
338            [icon release];
339        }
340        else
341            [item setImage: icon];
342       
343        [menu addItem: item];
344        [item release];
345    }
346   
347    return [menu autorelease];
348}
349
350- (NSInteger) groupIndexForTorrent: (Torrent *) torrent;
351{
352    for (NSDictionary * group in fGroups)
353    {
354        NSInteger row = [[group objectForKey: @"Index"] integerValue];
355        if ([self torrent: torrent doesMatchRulesForGroupAtIndex: row])
356            return row;
357    }
358    return -1;
359}
360
361@end
362
363@implementation GroupsController (Private)
364
365- (void) saveGroups
366{
367    //don't archive the icon
368    NSMutableArray * groups = [NSMutableArray arrayWithCapacity: [fGroups count]];
369    for (NSDictionary * dict in fGroups)
370    {
371        NSMutableDictionary * tempDict = [dict mutableCopy];
372        [tempDict removeObjectForKey: @"Icon"];
373        [groups addObject: tempDict];
374        [tempDict release];
375    }
376   
377    [[NSUserDefaults standardUserDefaults] setObject: [NSKeyedArchiver archivedDataWithRootObject: groups] forKey: @"GroupDicts"];
378}
379
380- (NSImage *) imageForGroup: (NSMutableDictionary *) dict
381{
382    NSImage * image;
383    if ((image = [dict objectForKey: @"Icon"]))
384        return image;
385   
386    NSRect rect = NSMakeRect(0.0, 0.0, ICON_WIDTH, ICON_WIDTH);
387   
388    NSBezierPath * bp = [NSBezierPath bezierPathWithRoundedRect: rect xRadius: 3.0 yRadius: 3.0];
389    NSImage * icon = [[NSImage alloc] initWithSize: rect.size];
390   
391    NSColor * color = [dict objectForKey: @"Color"];
392   
393    [icon lockFocus];
394   
395    //border
396    NSGradient * gradient = [[NSGradient alloc] initWithStartingColor: [color blendedColorWithFraction: 0.45 ofColor:
397                                [NSColor whiteColor]] endingColor: color];
398    [gradient drawInBezierPath: bp angle: 270.0];
399    [gradient release];
400   
401    //inside
402    bp = [NSBezierPath bezierPathWithRoundedRect: NSInsetRect(rect, 1.0, 1.0) xRadius: 3.0 yRadius: 3.0];
403    gradient = [[NSGradient alloc] initWithStartingColor: [color blendedColorWithFraction: 0.75 ofColor: [NSColor whiteColor]]
404                endingColor: [color blendedColorWithFraction: 0.2 ofColor: [NSColor whiteColor]]];
405    [gradient drawInBezierPath: bp angle: 270.0];
406    [gradient release];
407   
408    [icon unlockFocus];
409   
410    [dict setObject: icon forKey: @"Icon"];
411    [icon release];
412   
413    return icon;
414}
415
416- (BOOL) torrent: (Torrent *) torrent doesMatchRulesForGroupAtIndex: (NSInteger) index
417{
418    if (![self usesAutoAssignRulesForIndex: index])
419        return NO;
420       
421    NSPredicate * predicate = [self autoAssignRulesForIndex: index];
422    BOOL eval = NO;
423    @try
424    {
425        eval = [predicate evaluateWithObject: torrent];
426    }
427    @catch (NSException * exception)
428    {
429        NSLog(@"Error when evaluating predicate (%@) - %@", predicate, exception);
430    }
431    @finally
432    {
433        return eval;
434    }
435}
436
437@end
Note: See TracBrowser for help on using the repository browser.