-/* supposedly another way to do this, in case boundingRectWithSize isn't working
- NSTextView* tmpView = [[NSTextView alloc] initWithFrame:NSMakeRect(0, 0, width, 1)];
- [[tmpView textStorage] setAttributedString:aString];
- [tmpView setHorizontallyResizable:NO];
- [tmpView setVerticallyResizable:YES];
-// [[tmpView textContainer] setHeightTracksTextView: YES];
-// [[tmpView textContainer] setContainerSize: NSMakeSize(width, 10000)];
- [tmpView sizeToFit];
- float height = [tmpView frame].size.height;
- [tmpView release];
- return height;
-*/
-}
-
-- (float) lastDescriptionHeight
-{
- return fLastDescriptionHeight;
-}
-
-- (void) setStatus: (HBQueueJobGroupStatus)status
-{
- self->fStatus = status;
-}
-
-- (HBQueueJobGroupStatus) status
-{
- return self->fStatus;
-}
-
-- (void) setPath: (NSString *)path
-{
- [path retain];
- [fPath release];
- fPath = path;
-}
-
-- (NSString *) path
-{
- return fPath;
-}
-
-@end
-
-
-#pragma mark -
-
-@interface HBQueueController (Private)
-- (void)updateQueueUI;
-@end
-
-// Toolbar identifiers
-static NSString* HBQueueToolbar = @"HBQueueToolbar1";
-static NSString* HBQueueStartCancelToolbarIdentifier = @"HBQueueStartCancelToolbarIdentifier";
-static NSString* HBQueuePauseResumeToolbarIdentifier = @"HBQueuePauseResumeToolbarIdentifier";
-
-#pragma mark -
-
-@implementation HBQueueController
-
-//------------------------------------------------------------------------------------
-// init
-//------------------------------------------------------------------------------------
-- (id)init
-{
- if (self = [super init])
- {
- // Our defaults
- [[NSUserDefaults standardUserDefaults] registerDefaults:[NSDictionary dictionaryWithObjectsAndKeys:
- @"NO", @"QueueWindowIsOpen",
- @"NO", @"QueueShowsDetail",
- @"YES", @"QueueShowsJobsAsGroups",
- nil]];
-
- fJobGroups = [[NSMutableArray arrayWithCapacity:0] retain];
- fCompleted = [[NSMutableArray arrayWithCapacity:0] retain];
-
- BOOL loadSucceeded = [NSBundle loadNibNamed:@"Queue" owner:self] && fQueueWindow;
- NSAssert(loadSucceeded, @"Could not open Queue nib");
- NSAssert(fQueueWindow, @"fQueueWindow not found in Queue nib");
- }
- return self;
-}
-
-//------------------------------------------------------------------------------------
-// dealloc
-//------------------------------------------------------------------------------------
-- (void)dealloc
-{
- // clear the delegate so that windowWillClose is not attempted
- if ([fQueueWindow delegate] == self)
- [fQueueWindow setDelegate:nil];
-
- [fJobGroups release];
- [fCompleted release];
- [fCurrentJobGroup release];
- [fSavedExpandedItems release];
- [fSavedSelectedItems release];
-
- [super dealloc];
-}
-
-//------------------------------------------------------------------------------------
-// Receive HB handle
-//------------------------------------------------------------------------------------
-- (void)setHandle: (hb_handle_t *)handle
-{
- fHandle = handle;
-}
-
-//------------------------------------------------------------------------------------
-// Receive HBController
-//------------------------------------------------------------------------------------
-- (void)setHBController: (HBController *)controller
-{
- fHBController = controller;
-}
-
-//------------------------------------------------------------------------------------
-// Displays and brings the queue window to the front
-//------------------------------------------------------------------------------------
-- (IBAction) showQueueWindow: (id)sender
-{
- [self updateQueueUI];
- [fQueueWindow makeKeyAndOrderFront: self];
- [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"QueueWindowIsOpen"];
-}
-//------------------------------------------------------------------------------------
-// Show or hide the current job pane (fCurrentJobPane).
-//------------------------------------------------------------------------------------
-- (void) showCurrentJobPane: (BOOL)showPane
-{
- if (showPane == fCurrentJobPaneShown)
- return;
-
- // Things to keep in mind:
- // - When the current job pane is shown, it occupies the upper portion of the
- // window with the queue occupying the bottom portion of the window.
- // - When the current job pane is hidden, it slides up and out of view.
- // NSView setHidden is NOT used. The queue pane is resized to occupy the full
- // window.
-
- NSRect windowFrame = [[fCurrentJobPane superview] frame];
- NSRect queueFrame, jobFrame;
- if (showPane)
- NSDivideRect(windowFrame, &jobFrame, &queueFrame, NSHeight([fCurrentJobPane frame]), NSMaxYEdge);
- else
- {
- queueFrame = windowFrame;
- jobFrame = [fCurrentJobPane frame];
- jobFrame.origin.y = NSHeight(windowFrame);
- }
-
- // Move fCurrentJobPane
- NSDictionary * dict1 = [NSDictionary dictionaryWithObjectsAndKeys:
- fCurrentJobPane, NSViewAnimationTargetKey,
- [NSValue valueWithRect:jobFrame], NSViewAnimationEndFrameKey,
- nil];
-
- // Resize fQueuePane
- NSDictionary * dict2 = [NSDictionary dictionaryWithObjectsAndKeys:
- fQueuePane, NSViewAnimationTargetKey,
- [NSValue valueWithRect:queueFrame], NSViewAnimationEndFrameKey,
- nil];
-
- NSViewAnimation * anAnimation = [[[NSViewAnimation alloc] initWithViewAnimations:nil] autorelease];
- [anAnimation setViewAnimations:[NSArray arrayWithObjects:dict1, dict2, nil]];
- [anAnimation setDuration:0.25];
- [anAnimation setAnimationBlockingMode:NSAnimationBlocking]; // prevent user from resizing the window during an animation
- [anAnimation startAnimation];
-
- fCurrentJobPaneShown = showPane;
-}
-
-//------------------------------------------------------------------------------------
-// Rebuilds the contents of fJobGroups which is a hierarchy of HBJobGroup and HBJobs.
-//------------------------------------------------------------------------------------
-- (void)rebuildJobGroups
-{
- // Currently, job groups are rdered like this:
- // Completed job groups
- // Current job group
- // Pending job groups
-
- [fJobGroups autorelease];
- fJobGroups = [[NSMutableArray arrayWithCapacity:0] retain];
-
- // Add all the completed job groups
- [fJobGroups addObjectsFromArray: fCompleted];
-
- // Add all the completed job groups
- if (fCurrentJobGroup)
- [fJobGroups addObject: fCurrentJobGroup];
-
- // Add all the pending job groups. These come from hblib
- HBJobGroup * aJobGroup = [HBJobGroup jobGroup];
-
- // If hblib is currently processing something, hb_group will skip over that group.
- // And that's exactly what we want -- fJobGroups contains only pending job groups.
-
- hb_job_t * nextJob = hb_group( fHandle, 0 );
- while( nextJob )
- {
- if (nextJob->sequence_id == 0)
- {
- // Encountered a new group. Add the current one to fJobGroups and then start a new one.
- if ([aJobGroup count] > 0)
- {
- [aJobGroup setStatus: HBStatusPending];
- [fJobGroups addObject: aJobGroup];
- aJobGroup = [HBJobGroup jobGroup];
- }
- }
- [aJobGroup addJob: [HBJob jobWithJob:nextJob]];
- [aJobGroup setPath: [NSString stringWithUTF8String:nextJob->file]];
- nextJob = hb_next_job (fHandle, nextJob);
- }
- if ([aJobGroup count] > 0)
- {
- [aJobGroup setStatus: HBStatusPending];
- [fJobGroups addObject:aJobGroup];
- }
-}
-
-//------------------------------------------------------------------------------------
-// Adds aJobGroup to the list of completed job groups, marking its status as
-// HBStatusComplete.
-//------------------------------------------------------------------------------------
-- (void) addCompletedJobGroup: (HBJobGroup *)aJobGroup
-{
- // Once hblib has completed its work, the hb_job_t objects will be freed, so we
- // can't keep a reference to them.
- [aJobGroup removeAllJobs];
-
- [aJobGroup setStatus: HBStatusComplete];
-
- // Put the group in the completed list for permanent storage, and also rebuild
- // the master job group list which contains completed and pending groups.
- [fCompleted addObject: aJobGroup];
-}
-
-- (void) setCurrentJobGroupFromJob: (hb_job_t *)aJob
-{
- HBJobGroup * aJobGroup = nil;
-
- // Try to find this new group in our existing job groups.
- if (aJob)
- {
- BOOL found = NO;
- NSEnumerator * groupEnum = [fJobGroups objectEnumerator];
- while ( !found && (aJobGroup = [groupEnum nextObject]) )
- {
- HBJob * j;
- NSEnumerator * jobEnum = [aJobGroup jobEnumerator];
- while ( !found && (j = [jobEnum nextObject]) )
- {
- if ([j job] == aJob)
- found = YES;
- }
- }
-
- // Or create the job group.
- if (!aJobGroup)
- {
- aJobGroup = [HBJobGroup jobGroup];
- [aJobGroup addJob: [HBJob jobWithJob: aJob]];
- [aJobGroup setPath: [NSString stringWithUTF8String:aJob->file]];
- while ( (aJob = hb_next_job(fHandle, aJob)) && (aJob->sequence_id != 0) )
- [aJobGroup addJob: [HBJob jobWithJob: aJob]];
-
- [aJobGroup updateDescriptionWithHBHandle: fHandle];
- }
-
- [aJobGroup setStatus: HBStatusWorking];
- }
-
- [aJobGroup retain];
- [fCurrentJobGroup release];
- fCurrentJobGroup = aJobGroup;
-}
-
-#pragma mark -
-#pragma mark UI Updating
-
-//------------------------------------------------------------------------------------
-// Saves the state of the items that are currently expanded. Calling restoreOutlineViewState
-// will restore the state of all items to match what was saved by saveOutlineViewState.
-//------------------------------------------------------------------------------------
-- (void) saveOutlineViewState
-{
- if (!fSavedExpandedItems)
- fSavedExpandedItems = [[NSMutableIndexSet alloc] init];
- else
- [fSavedExpandedItems removeAllIndexes];
-
- // NB: This code is stuffing the address of each job into an index set. While it
- // works 99.9% of the time, it's not the ideal solution. We need unique ids in
- // each job, possibly using the existing sequence_id field. Could use the high
- // word as a unique encode id and the low word the sequence number.
-
- HBJobGroup * aJobGroup;
- NSEnumerator * e = [fJobGroups objectEnumerator];
- while ( (aJobGroup = [e nextObject]) )
- {
- if ([fOutlineView isItemExpanded: aJobGroup])
- {
- if ([aJobGroup status] == HBStatusComplete)
- [fSavedExpandedItems addIndex: (unsigned int)aJobGroup];
- else
- [fSavedExpandedItems addIndex: (unsigned int)[[aJobGroup jobAtIndex:0] job]];
- }
- }
-
- // Save the selection also. This is really UGLY code. Since I have to rebuild the
- // entire outline hierachy every time hblib changes its job list, there's no easy
- // way for me to remember the selection state other than saving off the first
- // hb_job_t item in each selected group. This is done by saving the object's
- // address. This could go away if I'd save a unique id in each job object.
-
- if (!fSavedSelectedItems)
- fSavedSelectedItems = [[NSMutableIndexSet alloc] init];
- else
- [fSavedSelectedItems removeAllIndexes];
-
- NSIndexSet * selectedRows = [fOutlineView selectedRowIndexes];
- int row = [selectedRows firstIndex];
- while (row != NSNotFound)
- {
- aJobGroup = [fOutlineView itemAtRow: row];
- if ([aJobGroup status] == HBStatusComplete)
- [fSavedSelectedItems addIndex: (unsigned int)aJobGroup];
- else
- [fSavedSelectedItems addIndex: (unsigned int)[[aJobGroup jobAtIndex:0] job]];
- row = [selectedRows indexGreaterThanIndex: row];
- }
-
-}
-
-//------------------------------------------------------------------------------------
-// Restores the expanded state of items in the outline view to match those saved by a
-// previous call to saveOutlineViewState.
-//------------------------------------------------------------------------------------
-- (void) restoreOutlineViewState
-{
- if (fSavedExpandedItems)
- {
- HBJobGroup * aJobGroup;
- NSEnumerator * e = [fJobGroups objectEnumerator];
- while ( (aJobGroup = [e nextObject]) )
- {
- if ([aJobGroup status] == HBStatusComplete)
- {
- if ([fSavedExpandedItems containsIndex: (unsigned int)aJobGroup])
- [fOutlineView expandItem: aJobGroup];
- }
- else
- {
- hb_job_t * j = [[aJobGroup jobAtIndex:0] job];
- if ([fSavedExpandedItems containsIndex: (unsigned int)j])
- [fOutlineView expandItem: aJobGroup];
- }
- }
- }
-
- if (fSavedSelectedItems)
- {
- // Ugh. Have to cycle through each row looking for the previously selected job.
- // See the explanation in saveOutlineViewState about the logic here.
-
- NSMutableIndexSet * rowsToSelect = [[[NSMutableIndexSet alloc] init] autorelease];
- for (int i = 0; i < [fOutlineView numberOfRows]; i++)
- {
- HBJobGroup * aJobGroup = [fOutlineView itemAtRow: i];
- // Test to see if the group or the group's first job is a match
- if ([aJobGroup status] == HBStatusComplete)
- {
- if ([fSavedSelectedItems containsIndex: (unsigned int)aJobGroup])
- [rowsToSelect addIndex: i];
- }
- else
- {
- if ([fSavedSelectedItems containsIndex: (unsigned int)[[aJobGroup jobAtIndex:0] job]])
- [rowsToSelect addIndex: i];
- }
- }
- if ([rowsToSelect count] == 0)
- [fOutlineView deselectAll: nil];
- else
- [fOutlineView selectRowIndexes:rowsToSelect byExtendingSelection:NO];
- }
-}
-
-//------------------------------------------------------------------------------------
-// If a job is currently processing, its job icon in the queue outline view is
-// animated to its next state.
-//------------------------------------------------------------------------------------
-- (void) animateCurrentJobGroupInQueue:(NSTimer*)theTimer
-{
- int row = [fOutlineView rowForItem: fCurrentJobGroup];
- int col = [fOutlineView columnWithIdentifier: @"icon"];
- if (row != -1 && col != -1)
- {
- fAnimationIndex++;
- fAnimationIndex %= 6; // there are 6 animation images; see outlineView:objectValueForTableColumn:byItem: below.
- NSRect frame = [fOutlineView frameOfCellAtColumn:col row:row];
- [fOutlineView setNeedsDisplayInRect: frame];
- }
-}
-
-//------------------------------------------------------------------------------------
-// Starts animating the job icon of the currently processing job in the queue outline
-// view.
-//------------------------------------------------------------------------------------
-- (void) startAnimatingCurrentJobGroupInQueue
-{
- if (!fAnimationTimer)
- fAnimationTimer = [[NSTimer scheduledTimerWithTimeInterval:1.0/12.0 // 1/12 because there are 6 images in the animation cycle
- target:self
- selector:@selector(animateCurrentJobGroupInQueue:)
- userInfo:nil
- repeats:YES] retain];
-}
-
-//------------------------------------------------------------------------------------
-// Stops animating the job icon of the currently processing job in the queue outline
-// view.
-//------------------------------------------------------------------------------------
-- (void) stopAnimatingCurrentJobGroupInQueue
-{
- if (fAnimationTimer && [fAnimationTimer isValid])
- {
- [fAnimationTimer invalidate];
- [fAnimationTimer release];
- fAnimationTimer = nil;
- }
-}
-
-//------------------------------------------------------------------------------------
-// Generate string to display in UI.
-//------------------------------------------------------------------------------------
-- (NSString *) progressStatusStringForJob: (hb_job_t *)job state: (hb_state_t *)s
-{
- if (s->state == HB_STATE_WORKING)
- {
- NSString * msg;
- if (job->pass == -1)
- msg = NSLocalizedString( @"Deep Scan", nil );
- else if (job->pass == 1)
- msg = NSLocalizedString( @"Analyzing video", nil );
- else if ((job->pass == 0) || (job->pass == 2))
- msg = NSLocalizedString( @"Encoding movie", nil );
- else
- return @""; // unknown condition!
-
- if( s->param.working.seconds > -1 )
- {
- return [NSString stringWithFormat:
- NSLocalizedString( @"%@ (%.2f fps, avg %.2f fps)", nil ),
- msg, s->param.working.rate_cur, s->param.working.rate_avg];
- }
- else
- return msg;
-
- }
-
- else if (s->state == HB_STATE_MUXING)
- return NSLocalizedString( @"Muxing", nil );
-
- else if (s->state == HB_STATE_PAUSED)
- return NSLocalizedString( @"Paused", nil );
-
- else if (s->state == HB_STATE_WORKDONE)
- return NSLocalizedString( @"Done", nil );
-
- return @"";
-}
-
-//------------------------------------------------------------------------------------
-// Generate string to display in UI.
-//------------------------------------------------------------------------------------
-- (NSString *) progressTimeRemainingStringForJob: (hb_job_t *)job state: (hb_state_t *)s
-{
- if (s->state == HB_STATE_WORKING)
- {
- #define p s->param.working
- if (p.seconds < 0)
- return @"";
-
- // Minutes always needed
- NSString * minutes;
- if (p.minutes > 1)
- minutes = [NSString stringWithFormat:NSLocalizedString( @"%d minutes ", nil ), p.minutes];
- else if (p.minutes == 1)
- minutes = NSLocalizedString( @"1 minute ", nil );
- else
- minutes = @"";
-
- if (p.hours >= 1)
- {
- NSString * hours;
- if (p.hours > 1)
- hours = [NSString stringWithFormat:NSLocalizedString( @"%d hours ", nil ), p.hours];
- else
- hours = NSLocalizedString( @"1 hour ", nil );
-
- return [NSString stringWithFormat:NSLocalizedString( @"%@%@remaining", nil ), hours, minutes];
- }
-
- else
- {
- NSString * seconds;
- if (p.seconds > 1)
- seconds = [NSString stringWithFormat:NSLocalizedString( @"%d seconds ", nil ), p.seconds];
- else
- seconds = NSLocalizedString( @"1 second ", nil );
-
- return [NSString stringWithFormat:NSLocalizedString( @"%@%@remaining", nil ), minutes, seconds];
- }
-
-/* here is code that does it more like the Finder
- if( p.seconds > -1 )
- {
- float estHours = (p.hours + (p.minutes / 60.0));
- float estMinutes = (p.minutes + (p.seconds / 60.0));
-
- if (estHours > 1.5)
- return [NSString stringWithFormat:NSLocalizedString( @"Time remaining: About %d hours", nil ), lrintf(estHours)];
- else if (estHours > 0.983) // 59 minutes
- return NSLocalizedString( @"Time remaining: About 1 hour", nil );
- else if (estMinutes > 1.5)
- return [NSString stringWithFormat:NSLocalizedString( @"Time remaining: About %d minutes", nil ), lrintf(estMinutes)];
- else if (estMinutes > 0.983) // 59 seconds
- return NSLocalizedString( @"Time remaining: About 1 minute", nil );
- else if (p.seconds <= 5)
- return NSLocalizedString( @"Time remaining: Less than 5 seconds", nil );
- else if (p.seconds <= 10)
- return NSLocalizedString( @"Time remaining: Less than 10 seconds", nil );
- else
- return NSLocalizedString( @"Time remaining: Less than 1 minute", nil );
- }
- else
- return NSLocalizedString( @"Time remaining: Calculating...", nil );
-*/
- #undef p
- }
-
- return @"";
-}
-
-//------------------------------------------------------------------------------------
-// Refresh progress bar (fProgressTextField) from current state.
-//------------------------------------------------------------------------------------
-- (void) updateProgressTextForJob: (hb_job_t *)job state: (hb_state_t *)s
-{
- NSString * statusMsg = [self progressStatusStringForJob:job state:s];
- NSString * timeMsg = [self progressTimeRemainingStringForJob:job state:s];
- if ([timeMsg length] > 0)
- statusMsg = [NSString stringWithFormat:@"%@ - %@", statusMsg, timeMsg];
- [fProgressTextField setStringValue:statusMsg];
-}
-
-//------------------------------------------------------------------------------------
-// Refresh progress bar (fProgressBar) from current state.
-//------------------------------------------------------------------------------------
-- (void) updateProgressBarWithState: (hb_state_t *)s
-{
- if (s->state == HB_STATE_WORKING)
- {
- #define p s->param.working
- [fProgressBar setIndeterminate:NO];
- float progress_total = 100.0 * ( p.progress + p.job_cur - 1 ) / p.job_count;
- [fProgressBar setDoubleValue:progress_total];
- #undef p
- }
-
- else if (s->state == HB_STATE_MUXING)
- {
- #define p s->param.muxing
- [fProgressBar setIndeterminate:YES];
- [fProgressBar startAnimation:nil];
- #undef p
- }
-
- else if (s->state == HB_STATE_WORKDONE)
- {
- [fProgressBar setIndeterminate:NO];
- [fProgressBar stopAnimation:nil];
- [fProgressBar setDoubleValue:0.0];
- }
-
- else
- [fProgressBar stopAnimation:nil]; // just in case in was animating
-}
-
-//------------------------------------------------------------------------------------
-// Refresh queue count text field (fQueueCountField).
-//------------------------------------------------------------------------------------
-- (void)updateQueueCountField
-{
- NSString * msg;
- int jobCount;
-
- jobCount = fHandle ? hb_group_count(fHandle) : 0;
- if (jobCount == 1)
- msg = NSLocalizedString(@"1 pending encode", nil);
- else
- msg = [NSString stringWithFormat:NSLocalizedString(@"%d pending encodes", nil), jobCount];
-
- [fQueueCountField setStringValue:msg];
-}
-
-//------------------------------------------------------------------------------------
-// Refresh the UI in the current job pane. Should be called whenever the current job
-// being processed has changed.
-//------------------------------------------------------------------------------------
-- (void)updateCurrentJobDescription
-{
- hb_job_t * job = fHandle ? hb_current_job(fHandle) : nil;
-
- if (job)
- {
- HBJob * currentJob = [HBJob jobWithJob: job];
- switch (job->pass)
- {
- case -1: // Subtitle scan
- [fJobDescTextField setAttributedStringValue:
- [currentJob attributedDescriptionWithHBHandle:fHandle
- withIcon: NO
- withTitle: YES
- withPassName: YES
- withFormatInfo: NO
- withDestination: NO
- withPictureInfo: NO
- withVideoInfo: NO
- withx264Info: NO
- withAudioInfo: NO
- withSubtitleInfo: YES]];
- break;
-
- case 1: // video 1st pass
- [fJobDescTextField setAttributedStringValue:
- [currentJob attributedDescriptionWithHBHandle:fHandle
- withIcon: NO
- withTitle: YES
- withPassName: YES
- withFormatInfo: NO
- withDestination: NO
- withPictureInfo: YES
- withVideoInfo: YES
- withx264Info: YES
- withAudioInfo: NO
- withSubtitleInfo: NO]];
- break;
-
- case 0: // single pass
- case 2: // video 2nd pass + audio
- [fJobDescTextField setAttributedStringValue:
- [currentJob attributedDescriptionWithHBHandle:fHandle
- withIcon: NO
- withTitle: YES
- withPassName: YES
- withFormatInfo: NO
- withDestination: NO
- withPictureInfo: YES
- withVideoInfo: YES
- withx264Info: YES
- withAudioInfo: YES
- withSubtitleInfo: YES]];
- break;
-
- default: // unknown
- [fJobDescTextField setAttributedStringValue:
- [currentJob attributedDescriptionWithHBHandle:fHandle
- withIcon: NO
- withTitle: YES
- withPassName: YES
- withFormatInfo: NO
- withDestination: NO
- withPictureInfo: YES
- withVideoInfo: YES
- withx264Info: YES
- withAudioInfo: YES
- withSubtitleInfo: YES]];
- }
- }
-
- else
- [fJobDescTextField setStringValue: @"No encodes pending"];
-}
-
-//------------------------------------------------------------------------------------
-// Refresh the UI in the current job pane. Should be called whenever the current job
-// being processed has changed or when progress has changed.
-//------------------------------------------------------------------------------------
-- (void)updateCurrentJobProgress
-{
- hb_job_t * job = fHandle ? hb_current_job(fHandle) : nil;
- hb_state_t s;
- hb_get_state2( fHandle, &s );
- [self updateProgressTextForJob: job state: &s];
- [self updateProgressBarWithState:&s];
-}
-
-//------------------------------------------------------------------------------------
-// Refresh the UI in the queue pane. Should be called whenever the content of HB's job
-// list has changed so that HBQueueController can sync up.
-//------------------------------------------------------------------------------------
-- (void)updateQueueUI
-{
- [self saveOutlineViewState];
- [self rebuildJobGroups];
- [fOutlineView noteNumberOfRowsChanged];
- [fOutlineView reloadData];
- [self restoreOutlineViewState];
- [self updateQueueCountField];
-}
-
-#pragma mark -
-#pragma mark Actions
-
-//------------------------------------------------------------------------------------
-// Deletes the selected jobs from HB and the queue UI
-//------------------------------------------------------------------------------------
-- (IBAction)removeSelectedJobGroups: (id)sender
-{
- if (!fHandle) return;
-
- NSIndexSet * selectedRows = [fOutlineView selectedRowIndexes];
- int row = [selectedRows firstIndex];
- if (row != NSNotFound)
- {
- while (row != NSNotFound)
- {
- HBJobGroup * jobGroup = [fOutlineView itemAtRow: row];
- switch ([jobGroup status])
- {
- case HBStatusComplete:
- case HBStatusCanceled:
- [fCompleted removeObject: jobGroup];
- break;
- case HBStatusWorking:
- [self cancelCurrentJob: sender];
- break;
- case HBStatusPending:
- hb_job_t * job = [[jobGroup jobAtIndex: 0] job];
- hb_rem_group( fHandle, job );
- break;
- case HBStatusNone:
- break;
- }
-
- row = [selectedRows indexGreaterThanIndex: row];
- }