Ignore:
Timestamp:
Jan 9, 2007, 3:46:21 AM (16 years ago)
Author:
livings124
Message:

when a download finishes, stop and make wait if the seeding queue is full

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/macosx/Controller.m

    r1327 r1328  
    11361136}
    11371137
    1138 - (void) torrentFinishedDownloading: (NSNotification *) notification
    1139 {
    1140     Torrent * torrent = [notification object];
    1141    
    1142     [fInfoController updateInfoStats];
    1143    
    1144     [self updateTorrentsInQueue];
    1145    
    1146     if ([fDefaults boolForKey: @"PlayDownloadSound"])
    1147     {
    1148         NSSound * sound;
    1149         if ((sound = [NSSound soundNamed: [fDefaults stringForKey: @"DownloadSound"]]))
    1150             [sound play];
    1151     }
    1152    
    1153     [GrowlApplicationBridge notifyWithTitle: NSLocalizedString(@"Download Complete", "Growl notification title")
    1154         description: [torrent name]
    1155         notificationName: GROWL_DOWNLOAD_COMPLETE iconData: nil priority: 0 isSticky: NO clickContext: nil];
    1156    
    1157     if (![fWindow isKeyWindow])
    1158         fCompleted++;
    1159 }
    1160 
    1161 - (void) updateTorrentHistory
    1162 {
    1163     NSMutableArray * history = [NSMutableArray arrayWithCapacity: [fTorrents count]];
    1164 
    1165     NSEnumerator * enumerator = [fTorrents objectEnumerator];
    1166     Torrent * torrent;
    1167     while ((torrent = [enumerator nextObject]))
    1168         [history addObject: [torrent history]];
    1169 
    1170     [fDefaults setObject: history forKey: @"History"];
    1171     [fDefaults synchronize];
    1172 }
    1173 
    1174 - (void) sortTorrents
    1175 {
    1176     //remember selected rows if needed
    1177     NSArray * selectedTorrents = nil;
    1178     int numSelected = [fTableView numberOfSelectedRows];
    1179     if (numSelected > 0 && numSelected < [fDisplayedTorrents count])
    1180         selectedTorrents = [fDisplayedTorrents objectsAtIndexes: [fTableView selectedRowIndexes]];
    1181 
    1182     [self sortTorrentsIgnoreSelected]; //actually sort
    1183    
    1184     //set selected rows if needed
    1185     if (selectedTorrents)
    1186     {
    1187         Torrent * torrent;
    1188         NSEnumerator * enumerator = [selectedTorrents objectEnumerator];
    1189         NSMutableIndexSet * indexSet = [[NSMutableIndexSet alloc] init];
    1190         while ((torrent = [enumerator nextObject]))
    1191             [indexSet addIndex: [fDisplayedTorrents indexOfObject: torrent]];
    1192        
    1193         [fTableView selectRowIndexes: indexSet byExtendingSelection: NO];
    1194         [indexSet release];
    1195     }
    1196 }
    1197 
    1198 //doesn't remember selected rows
    1199 - (void) sortTorrentsIgnoreSelected
    1200 {
    1201     NSSortDescriptor * nameDescriptor = [[[NSSortDescriptor alloc] initWithKey: @"name"
    1202                             ascending: YES selector: @selector(caseInsensitiveCompare:)] autorelease],
    1203                     * orderDescriptor = [[[NSSortDescriptor alloc] initWithKey: @"orderValue"
    1204                                             ascending: YES] autorelease];
    1205 
    1206     NSArray * descriptors;
    1207     if ([fSortType isEqualToString: @"Name"])
    1208         descriptors = [[NSArray alloc] initWithObjects: nameDescriptor, orderDescriptor, nil];
    1209     else if ([fSortType isEqualToString: @"State"])
    1210     {
    1211         NSSortDescriptor * stateDescriptor = [[[NSSortDescriptor alloc] initWithKey:
    1212                                                 @"stateSortKey" ascending: NO] autorelease],
    1213                         * progressDescriptor = [[[NSSortDescriptor alloc] initWithKey:
    1214                                             @"progressSortKey" ascending: NO] autorelease];
    1215        
    1216         descriptors = [[NSArray alloc] initWithObjects: stateDescriptor, progressDescriptor,
    1217                                                             nameDescriptor, orderDescriptor, nil];
    1218     }
    1219     else if ([fSortType isEqualToString: @"Progress"])
    1220     {
    1221         NSSortDescriptor * progressDescriptor = [[[NSSortDescriptor alloc] initWithKey:
    1222                                             @"progressSortKey" ascending: YES] autorelease];
    1223        
    1224         descriptors = [[NSArray alloc] initWithObjects: progressDescriptor, nameDescriptor, orderDescriptor, nil];
    1225     }
    1226     else if ([fSortType isEqualToString: @"Date"])
    1227     {
    1228         NSSortDescriptor * dateDescriptor = [[[NSSortDescriptor alloc] initWithKey: @"date" ascending: YES] autorelease];
    1229    
    1230         descriptors = [[NSArray alloc] initWithObjects: dateDescriptor, orderDescriptor, nil];
    1231     }
    1232     else
    1233         descriptors = [[NSArray alloc] initWithObjects: orderDescriptor, nil];
    1234 
    1235     [fDisplayedTorrents sortUsingDescriptors: descriptors];
    1236     [descriptors release];
    1237    
    1238     [fTableView reloadData];
    1239 }
    1240 
    1241 - (void) setSort: (id) sender
    1242 {
    1243     //get checked items
    1244     NSMenuItem * prevSortItem, * prevSortActionItem;
    1245     if ([fSortType isEqualToString: @"Name"])
    1246     {
    1247         prevSortItem = fNameSortItem;
    1248         prevSortActionItem = fNameSortActionItem;
    1249     }
    1250     else if ([fSortType isEqualToString: @"State"])
    1251     {
    1252         prevSortItem = fStateSortItem;
    1253         prevSortActionItem = fStateSortActionItem;
    1254     }
    1255     else if ([fSortType isEqualToString: @"Progress"])
    1256     {
    1257         prevSortItem = fProgressSortItem;
    1258         prevSortActionItem = fProgressSortActionItem;
    1259     }
    1260     else if ([fSortType isEqualToString: @"Date"])
    1261     {
    1262         prevSortItem = fDateSortItem;
    1263         prevSortActionItem = fDateSortActionItem;
    1264     }
    1265     else
    1266     {
    1267         prevSortItem = fOrderSortItem;
    1268         prevSortActionItem = fOrderSortActionItem;
    1269     }
    1270    
    1271     if (sender != prevSortItem && sender != prevSortActionItem)
    1272     {
    1273         [fSortType release];
    1274        
    1275         //get new items to check
    1276         NSMenuItem * currentSortItem, * currentSortActionItem;
    1277         if (sender == fNameSortItem || sender == fNameSortActionItem)
    1278         {
    1279             currentSortItem = fNameSortItem;
    1280             currentSortActionItem = fNameSortActionItem;
    1281             fSortType = [[NSString alloc] initWithString: @"Name"];
    1282         }
    1283         else if (sender == fStateSortItem || sender == fStateSortActionItem)
    1284         {
    1285             currentSortItem = fStateSortItem;
    1286             currentSortActionItem = fStateSortActionItem;
    1287             fSortType = [[NSString alloc] initWithString: @"State"];
    1288         }
    1289         else if (sender == fProgressSortItem || sender == fProgressSortActionItem)
    1290         {
    1291             currentSortItem = fProgressSortItem;
    1292             currentSortActionItem = fProgressSortActionItem;
    1293             fSortType = [[NSString alloc] initWithString: @"Progress"];
    1294         }
    1295         else if (sender == fDateSortItem || sender == fDateSortActionItem)
    1296         {
    1297             currentSortItem = fDateSortItem;
    1298             currentSortActionItem = fDateSortActionItem;
    1299             fSortType = [[NSString alloc] initWithString: @"Date"];
    1300         }
    1301         else
    1302         {
    1303             currentSortItem = fOrderSortItem;
    1304             currentSortActionItem = fOrderSortActionItem;
    1305             fSortType = [[NSString alloc] initWithString: @"Order"];
    1306         }
    1307    
    1308         [prevSortItem setState: NSOffState];
    1309         [prevSortActionItem setState: NSOffState];
    1310         [currentSortItem setState: NSOnState];
    1311         [currentSortActionItem setState: NSOnState];
    1312        
    1313         [fDefaults setObject: fSortType forKey: @"Sort"];
    1314     }
    1315 
    1316     [self sortTorrents];
    1317 }
    1318 
    1319 - (void) applyFilter: (id) sender
    1320 {
    1321     //remember selected rows if needed
    1322     NSArray * selectedTorrents = [fTableView numberOfSelectedRows] > 0
    1323                 ? [fDisplayedTorrents objectsAtIndexes: [fTableView selectedRowIndexes]] : nil;
    1324 
    1325     NSMutableArray * tempTorrents = [[NSMutableArray alloc] initWithCapacity: [fTorrents count]];
    1326 
    1327     BOOL filtering = YES;
    1328     if ([fFilterType isEqualToString: @"Pause"])
    1329     {
    1330         NSEnumerator * enumerator = [fTorrents objectEnumerator];
    1331         Torrent * torrent;
    1332         while ((torrent = [enumerator nextObject]))
    1333             if (![torrent isActive])
    1334                 [tempTorrents addObject: torrent];
    1335     }
    1336     else if ([fFilterType isEqualToString: @"Seed"])
    1337     {
    1338         NSEnumerator * enumerator = [fTorrents objectEnumerator];
    1339         Torrent * torrent;
    1340         while ((torrent = [enumerator nextObject]))
    1341             if ([torrent isActive] && [torrent progress] >= 1.0)
    1342                 [tempTorrents addObject: torrent];
    1343     }
    1344     else if ([fFilterType isEqualToString: @"Download"])
    1345     {
    1346         NSEnumerator * enumerator = [fTorrents objectEnumerator];
    1347         Torrent * torrent;
    1348         while ((torrent = [enumerator nextObject]))
    1349             if ([torrent isActive] && [torrent progress] < 1.0)
    1350                 [tempTorrents addObject: torrent];
    1351     }
    1352     else
    1353     {
    1354         filtering = NO;
    1355         [tempTorrents setArray: fTorrents];
    1356     }
    1357    
    1358     NSString * searchString = [fSearchFilterField stringValue];
    1359     if ([searchString length] > 0)
    1360     {
    1361         filtering = YES;
    1362        
    1363         int i;
    1364         for (i = [tempTorrents count] - 1; i >= 0; i--)
    1365             if ([[[tempTorrents objectAtIndex: i] name] rangeOfString: searchString
    1366                                         options: NSCaseInsensitiveSearch].location == NSNotFound)
    1367                 [tempTorrents removeObjectAtIndex: i];
    1368     }
    1369    
    1370     [fDisplayedTorrents setArray: tempTorrents];
    1371     [tempTorrents release];
    1372    
    1373     [self sortTorrentsIgnoreSelected];
    1374    
    1375     //set selected rows if needed
    1376     if (selectedTorrents)
    1377     {
    1378         Torrent * torrent;
    1379         NSEnumerator * enumerator = [selectedTorrents objectEnumerator];
    1380         NSMutableIndexSet * indexSet = [[NSMutableIndexSet alloc] init];
    1381         unsigned index;
    1382         while ((torrent = [enumerator nextObject]))
    1383             if ((index = [fDisplayedTorrents indexOfObject: torrent]) != NSNotFound)
    1384                 [indexSet addIndex: index];
    1385        
    1386         [fTableView selectRowIndexes: indexSet byExtendingSelection: NO];
    1387         [indexSet release];
    1388     }
    1389    
    1390     //set status bar torrent count text
    1391     NSMutableString * totalTorrentsString = [NSMutableString stringWithString: @""];
    1392     if (filtering)
    1393         [totalTorrentsString appendFormat: @"%d/", [fDisplayedTorrents count]];
    1394    
    1395     int totalCount = [fTorrents count];
    1396     if (totalCount > 1)
    1397         [totalTorrentsString appendFormat: NSLocalizedString(@"%d Transfers", "Status bar transfer count"), totalCount];
    1398     else
    1399         [totalTorrentsString appendFormat: NSLocalizedString(@"%d Transfer", "Status bar transfer count"), totalCount];
    1400    
    1401     [fTotalTorrentsField setStringValue: totalTorrentsString];
    1402 
    1403     [self setWindowSizeToFit];
    1404 }
    1405 
    1406 //resets filter and sorts torrents
    1407 - (void) setFilter: (id) sender
    1408 {
    1409     BarButton * prevFilterButton;
    1410     if ([fFilterType isEqualToString: @"Pause"])
    1411         prevFilterButton = fPauseFilterButton;
    1412     else if ([fFilterType isEqualToString: @"Seed"])
    1413         prevFilterButton = fSeedFilterButton;
    1414     else if ([fFilterType isEqualToString: @"Download"])
    1415         prevFilterButton = fDownloadFilterButton;
    1416     else
    1417         prevFilterButton = fNoFilterButton;
    1418    
    1419     if (sender != prevFilterButton)
    1420     {
    1421         [prevFilterButton setEnabled: NO];
    1422         [sender setEnabled: YES];
    1423 
    1424         [fFilterType release];
    1425         if (sender == fDownloadFilterButton)
    1426             fFilterType = [[NSString alloc] initWithString: @"Download"];
    1427         else if (sender == fPauseFilterButton)
    1428             fFilterType = [[NSString alloc] initWithString: @"Pause"];
    1429         else if (sender == fSeedFilterButton)
    1430             fFilterType = [[NSString alloc] initWithString: @"Seed"];
    1431         else
    1432             fFilterType = [[NSString alloc] initWithString: @"None"];
    1433 
    1434         [fDefaults setObject: fFilterType forKey: @"Filter"];
    1435     }
    1436 
    1437     [self applyFilter: nil];
    1438 }
    1439 
    1440 - (void) switchFilter: (id) sender
    1441 {
    1442     NSButton * button;
    1443     if ([fFilterType isEqualToString: @"None"])
    1444         button = sender == fNextFilterItem ? fDownloadFilterButton : fPauseFilterButton;
    1445     else if ([fFilterType isEqualToString: @"Download"])
    1446         button = sender == fNextFilterItem ? fSeedFilterButton : fNoFilterButton;
    1447     else if ([fFilterType isEqualToString: @"Seed"])
    1448         button = sender == fNextFilterItem ? fPauseFilterButton : fDownloadFilterButton;
    1449     else if ([fFilterType isEqualToString: @"Pause"])
    1450         button = sender == fNextFilterItem ? fNoFilterButton : fSeedFilterButton;
    1451     else
    1452         button = fNoFilterButton;
    1453    
    1454     [self setFilter: button];
    1455 }
    1456 
    1457 - (void) updateControlTint: (NSNotification *) notification
    1458 {
    1459     if ([fDefaults boolForKey: @"SpeedLimit"])
    1460         [fSpeedLimitButton setImage: [NSColor currentControlTint] == NSBlueControlTint
    1461             ? [NSImage imageNamed: @"SpeedLimitButtonBlue.png"] : [NSImage imageNamed: @"SpeedLimitButtonGraphite.png"]];
    1462 }
    1463 
    1464 - (void) applySpeedLimit: (id) sender
    1465 {
    1466     [fPrefsController applySpeedSettings: nil];
    1467 }
    1468 
    1469 - (void) toggleSpeedLimit: (id) sender
    1470 {
    1471     [fDefaults setBool: ![fDefaults boolForKey: @"SpeedLimit"] forKey: @"SpeedLimit"];
    1472     [self applySpeedLimit: nil];
    1473 }
    1474 
    1475 - (void) autoSpeedLimitChange: (NSNotification *) notification
    1476 {
    1477     if (![fDefaults boolForKey: @"SpeedLimitAuto"])
    1478         return;
    1479  
    1480     NSCalendarDate * onDate = [NSCalendarDate dateWithTimeIntervalSinceReferenceDate:
    1481                         [[fDefaults objectForKey: @"SpeedLimitAutoOnDate"] timeIntervalSinceReferenceDate]],
    1482         * offDate = [NSCalendarDate dateWithTimeIntervalSinceReferenceDate:
    1483                         [[fDefaults objectForKey: @"SpeedLimitAutoOffDate"] timeIntervalSinceReferenceDate]],
    1484         * nowDate = [NSCalendarDate calendarDate];
    1485    
    1486     //check if should be on if within range
    1487     BOOL shouldBeOn;
    1488    
    1489     int onTime = [onDate hourOfDay] * 60 + [onDate minuteOfHour],
    1490         offTime = [offDate hourOfDay] * 60 + [offDate minuteOfHour],
    1491         nowTime = [nowDate hourOfDay] * 60 + [nowDate minuteOfHour];
    1492    
    1493     if (onTime == offTime)
    1494         shouldBeOn = NO;
    1495     else if (onTime < offTime)
    1496         shouldBeOn = onTime <= nowTime && nowTime < offTime;
    1497     else
    1498         shouldBeOn = onTime <= nowTime || nowTime < offTime;
    1499    
    1500     if ([fDefaults boolForKey: @"SpeedLimit"] != shouldBeOn)
    1501         [self toggleSpeedLimit: nil];
    1502 }
    1503 
    1504 - (void) autoSpeedLimit: (NSTimer *) timer
    1505 {
    1506     if (![fDefaults boolForKey: @"SpeedLimitAuto"])
    1507         return;
    1508    
    1509     //only toggle if within first few seconds of minutes
    1510     NSCalendarDate * nowDate = [NSCalendarDate calendarDate];
    1511     if ([nowDate secondOfMinute] < AUTO_SPEED_LIMIT_SECONDS)
    1512         return;
    1513    
    1514     NSCalendarDate * offDate = [NSCalendarDate dateWithTimeIntervalSinceReferenceDate:
    1515                         [[fDefaults objectForKey: @"SpeedLimitAutoOffDate"] timeIntervalSinceReferenceDate]];
    1516    
    1517     BOOL toggle;
    1518     if ([fDefaults boolForKey: @"SpeedLimit"])
    1519         toggle = [nowDate hourOfDay] == [offDate hourOfDay] && [nowDate minuteOfHour] == [offDate minuteOfHour];
    1520     else
    1521     {
    1522         NSCalendarDate * onDate = [NSCalendarDate dateWithTimeIntervalSinceReferenceDate:
    1523                         [[fDefaults objectForKey: @"SpeedLimitAutoOnDate"] timeIntervalSinceReferenceDate]];
    1524         toggle = ([nowDate hourOfDay] == [onDate hourOfDay] && [nowDate minuteOfHour] == [onDate minuteOfHour])
    1525                     && !([onDate hourOfDay] == [offDate hourOfDay] && [onDate minuteOfHour] == [offDate minuteOfHour]);
    1526     }
    1527    
    1528     if (toggle)
    1529     {
    1530         [self toggleSpeedLimit: nil];
    1531        
    1532         [GrowlApplicationBridge notifyWithTitle: [fDefaults boolForKey: @"SpeedLimit"]
    1533                 ? NSLocalizedString(@"Speed Limit Auto Enabled", "Growl notification title")
    1534                 : NSLocalizedString(@"Speed Limit Auto Disabled", "Growl notification title")
    1535             description: NSLocalizedString(@"Bandwidth settings changed", "Growl notification description")
    1536             notificationName: GROWL_AUTO_SPEED_LIMIT iconData: nil priority: 0 isSticky: NO clickContext: nil];
    1537     }
    1538 }
    1539 
    1540 - (void) setLimitGlobalEnabled: (id) sender
    1541 {
    1542     [fPrefsController applySpeedSettings: nil];
    1543 }
    1544 
    1545 - (void) setQuickLimitGlobal: (id) sender
    1546 {
    1547     [fDefaults setInteger: [[sender title] intValue] forKey: [sender menu] == fUploadMenu ? @"UploadLimit" : @"DownloadLimit"];
    1548     [fDefaults setBool: YES forKey: [sender menu] == fUploadMenu ? @"CheckUpload" : @"CheckDownload"];
    1549    
    1550     [fPrefsController updateLimitFields];
    1551     [fPrefsController applySpeedSettings: nil];
    1552 }
    1553 
    1554 - (void) setQuickRatioGlobal: (id) sender
    1555 {
    1556     [fDefaults setBool: YES forKey: @"RatioCheck"];
    1557     [fDefaults setFloat: [[sender title] floatValue] forKey: @"RatioLimit"];
    1558    
    1559     [fPrefsController updateRatioStopField];
    1560 }
    1561 
    1562 - (void) torrentStoppedForRatio: (NSNotification *) notification
    1563 {
    1564     [self updateTorrentsInQueue];
    1565     [fInfoController updateInfoStats];
    1566    
    1567     if ([fDefaults boolForKey: @"PlaySeedingSound"])
    1568     {
    1569         NSSound * sound;
    1570         if ((sound = [NSSound soundNamed: [fDefaults stringForKey: @"SeedingSound"]]))
    1571             [sound play];
    1572     }
    1573    
    1574     [GrowlApplicationBridge notifyWithTitle: NSLocalizedString(@"Seeding Complete", "Growl notification title")
    1575         description: [[notification object] name]
    1576         notificationName: GROWL_SEEDING_COMPLETE iconData: nil priority: 0 isSticky: NO clickContext: nil];
    1577 }
    1578 
    15791138- (void) updateTorrentsInQueue
    15801139{
     
    16621221}
    16631222
     1223- (void) torrentFinishedDownloading: (NSNotification *) notification
     1224{
     1225    Torrent * torrent = [notification object];
     1226   
     1227    [fInfoController updateInfoStats];
     1228   
     1229    if ([fDefaults boolForKey: @"PlayDownloadSound"])
     1230    {
     1231        NSSound * sound;
     1232        if ((sound = [NSSound soundNamed: [fDefaults stringForKey: @"DownloadSound"]]))
     1233            [sound play];
     1234    }
     1235   
     1236    [GrowlApplicationBridge notifyWithTitle: NSLocalizedString(@"Download Complete", "Growl notification title")
     1237        description: [torrent name]
     1238        notificationName: GROWL_DOWNLOAD_COMPLETE iconData: nil priority: 0 isSticky: NO clickContext: nil];
     1239   
     1240    if (![fWindow isKeyWindow])
     1241        fCompleted++;
     1242   
     1243    //update queue if there is a seeding queue
     1244    if ([fDefaults boolForKey: @"QueueSeed"])
     1245    {
     1246        int desiredSeedActive = [fDefaults integerForKey: @"QueueSeedNumber"];
     1247           
     1248        NSEnumerator * enumerator = [fTorrents objectEnumerator];
     1249        Torrent * otherTorrent;
     1250        while ((otherTorrent = [enumerator nextObject]))
     1251            if (otherTorrent != torrent && [otherTorrent isSeeding] && [otherTorrent isActive] && ![otherTorrent isError])
     1252            {
     1253                desiredSeedActive--;
     1254                if (desiredSeedActive <= 0)
     1255                    break;
     1256            }
     1257
     1258        if (desiredSeedActive <= 0)
     1259        {
     1260            [torrent stopTransfer];
     1261            [torrent setWaitToStart: YES];
     1262            [torrent update];
     1263        }
     1264    }
     1265   
     1266    [self updateUI: nil];
     1267    [self applyFilter: nil];
     1268    [self updateTorrentHistory];
     1269}
     1270
     1271- (void) updateTorrentHistory
     1272{
     1273    NSMutableArray * history = [NSMutableArray arrayWithCapacity: [fTorrents count]];
     1274
     1275    NSEnumerator * enumerator = [fTorrents objectEnumerator];
     1276    Torrent * torrent;
     1277    while ((torrent = [enumerator nextObject]))
     1278        [history addObject: [torrent history]];
     1279
     1280    [fDefaults setObject: history forKey: @"History"];
     1281    [fDefaults synchronize];
     1282}
     1283
     1284- (void) sortTorrents
     1285{
     1286    //remember selected rows if needed
     1287    NSArray * selectedTorrents = nil;
     1288    int numSelected = [fTableView numberOfSelectedRows];
     1289    if (numSelected > 0 && numSelected < [fDisplayedTorrents count])
     1290        selectedTorrents = [fDisplayedTorrents objectsAtIndexes: [fTableView selectedRowIndexes]];
     1291
     1292    [self sortTorrentsIgnoreSelected]; //actually sort
     1293   
     1294    //set selected rows if needed
     1295    if (selectedTorrents)
     1296    {
     1297        Torrent * torrent;
     1298        NSEnumerator * enumerator = [selectedTorrents objectEnumerator];
     1299        NSMutableIndexSet * indexSet = [[NSMutableIndexSet alloc] init];
     1300        while ((torrent = [enumerator nextObject]))
     1301            [indexSet addIndex: [fDisplayedTorrents indexOfObject: torrent]];
     1302       
     1303        [fTableView selectRowIndexes: indexSet byExtendingSelection: NO];
     1304        [indexSet release];
     1305    }
     1306}
     1307
     1308//doesn't remember selected rows
     1309- (void) sortTorrentsIgnoreSelected
     1310{
     1311    NSSortDescriptor * nameDescriptor = [[[NSSortDescriptor alloc] initWithKey: @"name"
     1312                            ascending: YES selector: @selector(caseInsensitiveCompare:)] autorelease],
     1313                    * orderDescriptor = [[[NSSortDescriptor alloc] initWithKey: @"orderValue"
     1314                                            ascending: YES] autorelease];
     1315
     1316    NSArray * descriptors;
     1317    if ([fSortType isEqualToString: @"Name"])
     1318        descriptors = [[NSArray alloc] initWithObjects: nameDescriptor, orderDescriptor, nil];
     1319    else if ([fSortType isEqualToString: @"State"])
     1320    {
     1321        NSSortDescriptor * stateDescriptor = [[[NSSortDescriptor alloc] initWithKey:
     1322                                                @"stateSortKey" ascending: NO] autorelease],
     1323                        * progressDescriptor = [[[NSSortDescriptor alloc] initWithKey:
     1324                                            @"progressSortKey" ascending: NO] autorelease];
     1325       
     1326        descriptors = [[NSArray alloc] initWithObjects: stateDescriptor, progressDescriptor,
     1327                                                            nameDescriptor, orderDescriptor, nil];
     1328    }
     1329    else if ([fSortType isEqualToString: @"Progress"])
     1330    {
     1331        NSSortDescriptor * progressDescriptor = [[[NSSortDescriptor alloc] initWithKey:
     1332                                            @"progressSortKey" ascending: YES] autorelease];
     1333       
     1334        descriptors = [[NSArray alloc] initWithObjects: progressDescriptor, nameDescriptor, orderDescriptor, nil];
     1335    }
     1336    else if ([fSortType isEqualToString: @"Date"])
     1337    {
     1338        NSSortDescriptor * dateDescriptor = [[[NSSortDescriptor alloc] initWithKey: @"date" ascending: YES] autorelease];
     1339   
     1340        descriptors = [[NSArray alloc] initWithObjects: dateDescriptor, orderDescriptor, nil];
     1341    }
     1342    else
     1343        descriptors = [[NSArray alloc] initWithObjects: orderDescriptor, nil];
     1344
     1345    [fDisplayedTorrents sortUsingDescriptors: descriptors];
     1346    [descriptors release];
     1347   
     1348    [fTableView reloadData];
     1349}
     1350
     1351- (void) setSort: (id) sender
     1352{
     1353    //get checked items
     1354    NSMenuItem * prevSortItem, * prevSortActionItem;
     1355    if ([fSortType isEqualToString: @"Name"])
     1356    {
     1357        prevSortItem = fNameSortItem;
     1358        prevSortActionItem = fNameSortActionItem;
     1359    }
     1360    else if ([fSortType isEqualToString: @"State"])
     1361    {
     1362        prevSortItem = fStateSortItem;
     1363        prevSortActionItem = fStateSortActionItem;
     1364    }
     1365    else if ([fSortType isEqualToString: @"Progress"])
     1366    {
     1367        prevSortItem = fProgressSortItem;
     1368        prevSortActionItem = fProgressSortActionItem;
     1369    }
     1370    else if ([fSortType isEqualToString: @"Date"])
     1371    {
     1372        prevSortItem = fDateSortItem;
     1373        prevSortActionItem = fDateSortActionItem;
     1374    }
     1375    else
     1376    {
     1377        prevSortItem = fOrderSortItem;
     1378        prevSortActionItem = fOrderSortActionItem;
     1379    }
     1380   
     1381    if (sender != prevSortItem && sender != prevSortActionItem)
     1382    {
     1383        [fSortType release];
     1384       
     1385        //get new items to check
     1386        NSMenuItem * currentSortItem, * currentSortActionItem;
     1387        if (sender == fNameSortItem || sender == fNameSortActionItem)
     1388        {
     1389            currentSortItem = fNameSortItem;
     1390            currentSortActionItem = fNameSortActionItem;
     1391            fSortType = [[NSString alloc] initWithString: @"Name"];
     1392        }
     1393        else if (sender == fStateSortItem || sender == fStateSortActionItem)
     1394        {
     1395            currentSortItem = fStateSortItem;
     1396            currentSortActionItem = fStateSortActionItem;
     1397            fSortType = [[NSString alloc] initWithString: @"State"];
     1398        }
     1399        else if (sender == fProgressSortItem || sender == fProgressSortActionItem)
     1400        {
     1401            currentSortItem = fProgressSortItem;
     1402            currentSortActionItem = fProgressSortActionItem;
     1403            fSortType = [[NSString alloc] initWithString: @"Progress"];
     1404        }
     1405        else if (sender == fDateSortItem || sender == fDateSortActionItem)
     1406        {
     1407            currentSortItem = fDateSortItem;
     1408            currentSortActionItem = fDateSortActionItem;
     1409            fSortType = [[NSString alloc] initWithString: @"Date"];
     1410        }
     1411        else
     1412        {
     1413            currentSortItem = fOrderSortItem;
     1414            currentSortActionItem = fOrderSortActionItem;
     1415            fSortType = [[NSString alloc] initWithString: @"Order"];
     1416        }
     1417   
     1418        [prevSortItem setState: NSOffState];
     1419        [prevSortActionItem setState: NSOffState];
     1420        [currentSortItem setState: NSOnState];
     1421        [currentSortActionItem setState: NSOnState];
     1422       
     1423        [fDefaults setObject: fSortType forKey: @"Sort"];
     1424    }
     1425
     1426    [self sortTorrents];
     1427}
     1428
     1429- (void) applyFilter: (id) sender
     1430{
     1431    //remember selected rows if needed
     1432    NSArray * selectedTorrents = [fTableView numberOfSelectedRows] > 0
     1433                ? [fDisplayedTorrents objectsAtIndexes: [fTableView selectedRowIndexes]] : nil;
     1434
     1435    NSMutableArray * tempTorrents = [[NSMutableArray alloc] initWithCapacity: [fTorrents count]];
     1436
     1437    BOOL filtering = YES;
     1438    if ([fFilterType isEqualToString: @"Pause"])
     1439    {
     1440        NSEnumerator * enumerator = [fTorrents objectEnumerator];
     1441        Torrent * torrent;
     1442        while ((torrent = [enumerator nextObject]))
     1443            if (![torrent isActive])
     1444                [tempTorrents addObject: torrent];
     1445    }
     1446    else if ([fFilterType isEqualToString: @"Seed"])
     1447    {
     1448        NSEnumerator * enumerator = [fTorrents objectEnumerator];
     1449        Torrent * torrent;
     1450        while ((torrent = [enumerator nextObject]))
     1451            if ([torrent isActive] && [torrent progress] >= 1.0)
     1452                [tempTorrents addObject: torrent];
     1453    }
     1454    else if ([fFilterType isEqualToString: @"Download"])
     1455    {
     1456        NSEnumerator * enumerator = [fTorrents objectEnumerator];
     1457        Torrent * torrent;
     1458        while ((torrent = [enumerator nextObject]))
     1459            if ([torrent isActive] && [torrent progress] < 1.0)
     1460                [tempTorrents addObject: torrent];
     1461    }
     1462    else
     1463    {
     1464        filtering = NO;
     1465        [tempTorrents setArray: fTorrents];
     1466    }
     1467   
     1468    NSString * searchString = [fSearchFilterField stringValue];
     1469    if ([searchString length] > 0)
     1470    {
     1471        filtering = YES;
     1472       
     1473        int i;
     1474        for (i = [tempTorrents count] - 1; i >= 0; i--)
     1475            if ([[[tempTorrents objectAtIndex: i] name] rangeOfString: searchString
     1476                                        options: NSCaseInsensitiveSearch].location == NSNotFound)
     1477                [tempTorrents removeObjectAtIndex: i];
     1478    }
     1479   
     1480    [fDisplayedTorrents setArray: tempTorrents];
     1481    [tempTorrents release];
     1482   
     1483    [self sortTorrentsIgnoreSelected];
     1484   
     1485    //set selected rows if needed
     1486    if (selectedTorrents)
     1487    {
     1488        Torrent * torrent;
     1489        NSEnumerator * enumerator = [selectedTorrents objectEnumerator];
     1490        NSMutableIndexSet * indexSet = [[NSMutableIndexSet alloc] init];
     1491        unsigned index;
     1492        while ((torrent = [enumerator nextObject]))
     1493            if ((index = [fDisplayedTorrents indexOfObject: torrent]) != NSNotFound)
     1494                [indexSet addIndex: index];
     1495       
     1496        [fTableView selectRowIndexes: indexSet byExtendingSelection: NO];
     1497        [indexSet release];
     1498    }
     1499   
     1500    //set status bar torrent count text
     1501    NSMutableString * totalTorrentsString = [NSMutableString stringWithString: @""];
     1502    if (filtering)
     1503        [totalTorrentsString appendFormat: @"%d/", [fDisplayedTorrents count]];
     1504   
     1505    int totalCount = [fTorrents count];
     1506    if (totalCount > 1)
     1507        [totalTorrentsString appendFormat: NSLocalizedString(@"%d Transfers", "Status bar transfer count"), totalCount];
     1508    else
     1509        [totalTorrentsString appendFormat: NSLocalizedString(@"%d Transfer", "Status bar transfer count"), totalCount];
     1510   
     1511    [fTotalTorrentsField setStringValue: totalTorrentsString];
     1512
     1513    [self setWindowSizeToFit];
     1514}
     1515
     1516//resets filter and sorts torrents
     1517- (void) setFilter: (id) sender
     1518{
     1519    BarButton * prevFilterButton;
     1520    if ([fFilterType isEqualToString: @"Pause"])
     1521        prevFilterButton = fPauseFilterButton;
     1522    else if ([fFilterType isEqualToString: @"Seed"])
     1523        prevFilterButton = fSeedFilterButton;
     1524    else if ([fFilterType isEqualToString: @"Download"])
     1525        prevFilterButton = fDownloadFilterButton;
     1526    else
     1527        prevFilterButton = fNoFilterButton;
     1528   
     1529    if (sender != prevFilterButton)
     1530    {
     1531        [prevFilterButton setEnabled: NO];
     1532        [sender setEnabled: YES];
     1533
     1534        [fFilterType release];
     1535        if (sender == fDownloadFilterButton)
     1536            fFilterType = [[NSString alloc] initWithString: @"Download"];
     1537        else if (sender == fPauseFilterButton)
     1538            fFilterType = [[NSString alloc] initWithString: @"Pause"];
     1539        else if (sender == fSeedFilterButton)
     1540            fFilterType = [[NSString alloc] initWithString: @"Seed"];
     1541        else
     1542            fFilterType = [[NSString alloc] initWithString: @"None"];
     1543
     1544        [fDefaults setObject: fFilterType forKey: @"Filter"];
     1545    }
     1546
     1547    [self applyFilter: nil];
     1548}
     1549
     1550- (void) switchFilter: (id) sender
     1551{
     1552    NSButton * button;
     1553    if ([fFilterType isEqualToString: @"None"])
     1554        button = sender == fNextFilterItem ? fDownloadFilterButton : fPauseFilterButton;
     1555    else if ([fFilterType isEqualToString: @"Download"])
     1556        button = sender == fNextFilterItem ? fSeedFilterButton : fNoFilterButton;
     1557    else if ([fFilterType isEqualToString: @"Seed"])
     1558        button = sender == fNextFilterItem ? fPauseFilterButton : fDownloadFilterButton;
     1559    else if ([fFilterType isEqualToString: @"Pause"])
     1560        button = sender == fNextFilterItem ? fNoFilterButton : fSeedFilterButton;
     1561    else
     1562        button = fNoFilterButton;
     1563   
     1564    [self setFilter: button];
     1565}
     1566
     1567- (void) updateControlTint: (NSNotification *) notification
     1568{
     1569    if ([fDefaults boolForKey: @"SpeedLimit"])
     1570        [fSpeedLimitButton setImage: [NSColor currentControlTint] == NSBlueControlTint
     1571            ? [NSImage imageNamed: @"SpeedLimitButtonBlue.png"] : [NSImage imageNamed: @"SpeedLimitButtonGraphite.png"]];
     1572}
     1573
     1574- (void) applySpeedLimit: (id) sender
     1575{
     1576    [fPrefsController applySpeedSettings: nil];
     1577}
     1578
     1579- (void) toggleSpeedLimit: (id) sender
     1580{
     1581    [fDefaults setBool: ![fDefaults boolForKey: @"SpeedLimit"] forKey: @"SpeedLimit"];
     1582    [self applySpeedLimit: nil];
     1583}
     1584
     1585- (void) autoSpeedLimitChange: (NSNotification *) notification
     1586{
     1587    if (![fDefaults boolForKey: @"SpeedLimitAuto"])
     1588        return;
     1589 
     1590    NSCalendarDate * onDate = [NSCalendarDate dateWithTimeIntervalSinceReferenceDate:
     1591                        [[fDefaults objectForKey: @"SpeedLimitAutoOnDate"] timeIntervalSinceReferenceDate]],
     1592        * offDate = [NSCalendarDate dateWithTimeIntervalSinceReferenceDate:
     1593                        [[fDefaults objectForKey: @"SpeedLimitAutoOffDate"] timeIntervalSinceReferenceDate]],
     1594        * nowDate = [NSCalendarDate calendarDate];
     1595   
     1596    //check if should be on if within range
     1597    BOOL shouldBeOn;
     1598   
     1599    int onTime = [onDate hourOfDay] * 60 + [onDate minuteOfHour],
     1600        offTime = [offDate hourOfDay] * 60 + [offDate minuteOfHour],
     1601        nowTime = [nowDate hourOfDay] * 60 + [nowDate minuteOfHour];
     1602   
     1603    if (onTime == offTime)
     1604        shouldBeOn = NO;
     1605    else if (onTime < offTime)
     1606        shouldBeOn = onTime <= nowTime && nowTime < offTime;
     1607    else
     1608        shouldBeOn = onTime <= nowTime || nowTime < offTime;
     1609   
     1610    if ([fDefaults boolForKey: @"SpeedLimit"] != shouldBeOn)
     1611        [self toggleSpeedLimit: nil];
     1612}
     1613
     1614- (void) autoSpeedLimit: (NSTimer *) timer
     1615{
     1616    if (![fDefaults boolForKey: @"SpeedLimitAuto"])
     1617        return;
     1618   
     1619    //only toggle if within first few seconds of minutes
     1620    NSCalendarDate * nowDate = [NSCalendarDate calendarDate];
     1621    if ([nowDate secondOfMinute] < AUTO_SPEED_LIMIT_SECONDS)
     1622        return;
     1623   
     1624    NSCalendarDate * offDate = [NSCalendarDate dateWithTimeIntervalSinceReferenceDate:
     1625                        [[fDefaults objectForKey: @"SpeedLimitAutoOffDate"] timeIntervalSinceReferenceDate]];
     1626   
     1627    BOOL toggle;
     1628    if ([fDefaults boolForKey: @"SpeedLimit"])
     1629        toggle = [nowDate hourOfDay] == [offDate hourOfDay] && [nowDate minuteOfHour] == [offDate minuteOfHour];
     1630    else
     1631    {
     1632        NSCalendarDate * onDate = [NSCalendarDate dateWithTimeIntervalSinceReferenceDate:
     1633                        [[fDefaults objectForKey: @"SpeedLimitAutoOnDate"] timeIntervalSinceReferenceDate]];
     1634        toggle = ([nowDate hourOfDay] == [onDate hourOfDay] && [nowDate minuteOfHour] == [onDate minuteOfHour])
     1635                    && !([onDate hourOfDay] == [offDate hourOfDay] && [onDate minuteOfHour] == [offDate minuteOfHour]);
     1636    }
     1637   
     1638    if (toggle)
     1639    {
     1640        [self toggleSpeedLimit: nil];
     1641       
     1642        [GrowlApplicationBridge notifyWithTitle: [fDefaults boolForKey: @"SpeedLimit"]
     1643                ? NSLocalizedString(@"Speed Limit Auto Enabled", "Growl notification title")
     1644                : NSLocalizedString(@"Speed Limit Auto Disabled", "Growl notification title")
     1645            description: NSLocalizedString(@"Bandwidth settings changed", "Growl notification description")
     1646            notificationName: GROWL_AUTO_SPEED_LIMIT iconData: nil priority: 0 isSticky: NO clickContext: nil];
     1647    }
     1648}
     1649
     1650- (void) setLimitGlobalEnabled: (id) sender
     1651{
     1652    [fPrefsController applySpeedSettings: nil];
     1653}
     1654
     1655- (void) setQuickLimitGlobal: (id) sender
     1656{
     1657    [fDefaults setInteger: [[sender title] intValue] forKey: [sender menu] == fUploadMenu ? @"UploadLimit" : @"DownloadLimit"];
     1658    [fDefaults setBool: YES forKey: [sender menu] == fUploadMenu ? @"CheckUpload" : @"CheckDownload"];
     1659   
     1660    [fPrefsController updateLimitFields];
     1661    [fPrefsController applySpeedSettings: nil];
     1662}
     1663
     1664- (void) setQuickRatioGlobal: (id) sender
     1665{
     1666    [fDefaults setBool: YES forKey: @"RatioCheck"];
     1667    [fDefaults setFloat: [[sender title] floatValue] forKey: @"RatioLimit"];
     1668   
     1669    [fPrefsController updateRatioStopField];
     1670}
     1671
     1672- (void) torrentStoppedForRatio: (NSNotification *) notification
     1673{
     1674    [self updateTorrentsInQueue];
     1675    [fInfoController updateInfoStats];
     1676   
     1677    if ([fDefaults boolForKey: @"PlaySeedingSound"])
     1678    {
     1679        NSSound * sound;
     1680        if ((sound = [NSSound soundNamed: [fDefaults stringForKey: @"SeedingSound"]]))
     1681            [sound play];
     1682    }
     1683   
     1684    [GrowlApplicationBridge notifyWithTitle: NSLocalizedString(@"Seeding Complete", "Growl notification title")
     1685        description: [[notification object] name]
     1686        notificationName: GROWL_SEEDING_COMPLETE iconData: nil priority: 0 isSticky: NO clickContext: nil];
     1687}
     1688
    16641689-(void) watcher: (id<UKFileWatcher>) watcher receivedNotification: (NSString *) notification forPath: (NSString *) path
    16651690{
Note: See TracChangeset for help on using the changeset viewer.