3 This file is part of the HandBrake source code.
4 Homepage: <http://handbrake.fr/>.
5 It may be used under the terms of the GNU General Public License. */
7 #import "HBQueueController.h"
9 #import "HBImageAndTextCell.h"
11 #define HB_ROW_HEIGHT_TITLE_ONLY 17.0
12 #define HB_ROW_HEIGHT_FULL_DESCRIPTION 200.0
13 // Pasteboard type for or drag operations
14 #define DragDropSimplePboardType @"MyCustomOutlineViewPboardType"
16 //------------------------------------------------------------------------------------
18 //------------------------------------------------------------------------------------
20 //------------------------------------------------------------------------------------
21 // NSMutableAttributedString (HBAdditions)
22 //------------------------------------------------------------------------------------
24 @interface NSMutableAttributedString (HBAdditions)
25 - (void) appendString: (NSString*)aString withAttributes: (NSDictionary *)aDictionary;
28 @implementation NSMutableAttributedString (HBAdditions)
29 - (void) appendString: (NSString*)aString withAttributes: (NSDictionary *)aDictionary
31 NSAttributedString * s = [[[NSAttributedString alloc]
32 initWithString: aString
33 attributes: aDictionary] autorelease];
34 [self appendAttributedString: s];
39 @implementation HBQueueOutlineView
41 - (void)viewDidEndLiveResize
43 // Since we disabled calculating row heights during a live resize, force them to
45 [self noteHeightOfRowsWithIndexesChanged:
46 [NSIndexSet indexSetWithIndexesInRange: NSMakeRange(0, [self numberOfRows])]];
47 [super viewDidEndLiveResize];
52 /* This should be for dragging, we take this info from the presets right now */
53 - (NSImage *)dragImageForRowsWithIndexes:(NSIndexSet *)dragRows tableColumns:(NSArray *)tableColumns event:(NSEvent*)dragEvent offset:(NSPointPointer)dragImageOffset
57 // By default, NSTableView only drags an image of the first column. Change this to
58 // drag an image of the queue's icon and desc and action columns.
59 NSArray * cols = [NSArray arrayWithObjects: [self tableColumnWithIdentifier:@"desc"], [self tableColumnWithIdentifier:@"icon"],[self tableColumnWithIdentifier:@"action"], nil];
60 return [super dragImageForRowsWithIndexes:dragRows tableColumns:cols event:dragEvent offset:dragImageOffset];
65 - (void) mouseDown:(NSEvent *)theEvent
67 [super mouseDown:theEvent];
82 #pragma mark Toolbar Identifiers
83 // Toolbar identifiers
84 static NSString* HBQueueToolbar = @"HBQueueToolbar1";
85 static NSString* HBQueueStartCancelToolbarIdentifier = @"HBQueueStartCancelToolbarIdentifier";
86 static NSString* HBQueuePauseResumeToolbarIdentifier = @"HBQueuePauseResumeToolbarIdentifier";
90 @implementation HBQueueController
92 //------------------------------------------------------------------------------------
94 //------------------------------------------------------------------------------------
97 if (self = [super initWithWindowNibName:@"Queue"])
99 // NSWindowController likes to lazily load its window nib. Since this
100 // controller tries to touch the outlets before accessing the window, we
101 // need to force it to load immadiately by invoking its accessor.
103 // If/when we switch to using bindings, this can probably go away.
107 [[NSUserDefaults standardUserDefaults] registerDefaults:[NSDictionary dictionaryWithObjectsAndKeys:
108 @"NO", @"QueueWindowIsOpen",
109 @"NO", @"QueueShowsDetail",
110 @"YES", @"QueueShowsJobsAsGroups",
113 fJobGroups = [[NSMutableArray arrayWithCapacity:0] retain];
118 - (void)setQueueArray: (NSMutableArray *)QueueFileArray
120 [fJobGroups setArray:QueueFileArray];
122 /* First stop any timer working now */
123 [self stopAnimatingCurrentJobGroupInQueue];
124 [fOutlineView reloadData];
128 /* lets get the stats on the status of the queue array */
130 fEncodingQueueItem = 0;
136 /* We use a number system to set the encode status of the queue item
138 * 0 == already encoded
139 * 1 == is being encoded
140 * 2 == is yet to be encoded
145 NSEnumerator *enumerator = [fJobGroups objectEnumerator];
147 while (tempObject = [enumerator nextObject])
149 NSDictionary *thisQueueDict = tempObject;
150 if ([[thisQueueDict objectForKey:@"Status"] intValue] == 0) // Completed
154 if ([[thisQueueDict objectForKey:@"Status"] intValue] == 1) // being encoded
157 fEncodingQueueItem = i;
159 if ([[thisQueueDict objectForKey:@"Status"] intValue] == 2) // pending
163 if ([[thisQueueDict objectForKey:@"Status"] intValue] == 3) // cancelled
170 /* We should fire up the encoding timer here based on fWorkingCount */
172 if (fWorkingCount > 0)
174 /* we have an encoding job so, lets start the animation timer */
175 [self startAnimatingCurrentWorkingEncodeInQueue];
178 /* Set the queue status field in the queue window */
179 NSMutableString * string;
180 if (fPendingCount == 1)
182 string = [NSMutableString stringWithFormat: NSLocalizedStringFromTable( @"%d encode pending", @"Queue", @"" ), fPendingCount];
186 string = [NSMutableString stringWithFormat: NSLocalizedStringFromTable( @"%d encode(s) pending", @"Queue", @"" ), fPendingCount];
188 [fQueueCountField setStringValue:string];
191 /* This method sets the status string in the queue window
192 * and is called from Controller.mm (fHBController)
193 * instead of running another timer here polling libhb
194 * for encoding status
196 - (void)setQueueStatusString: (NSString *)statusString
198 [fProgressTextField setStringValue:statusString];
201 //------------------------------------------------------------------------------------
203 //------------------------------------------------------------------------------------
206 // clear the delegate so that windowWillClose is not attempted
207 if( [[self window] delegate] == self )
208 [[self window] setDelegate:nil];
210 [fJobGroups release];
212 [fSavedExpandedItems release];
213 [fSavedSelectedItems release];
215 [[NSNotificationCenter defaultCenter] removeObserver:self];
220 //------------------------------------------------------------------------------------
222 //------------------------------------------------------------------------------------
223 - (void)setHandle: (hb_handle_t *)handle
225 fQueueEncodeLibhb = handle;
228 //------------------------------------------------------------------------------------
229 // Receive HBController
230 //------------------------------------------------------------------------------------
231 - (void)setHBController: (HBController *)controller
233 fHBController = controller;
238 //------------------------------------------------------------------------------------
239 // Displays and brings the queue window to the front
240 //------------------------------------------------------------------------------------
241 - (IBAction) showQueueWindow: (id)sender
243 [self showWindow:sender];
244 [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"QueueWindowIsOpen"];
249 //------------------------------------------------------------------------------------
251 //------------------------------------------------------------------------------------
256 if( ![[self window] setFrameUsingName:@"Queue"] )
257 [[self window] center];
258 [self setWindowFrameAutosaveName:@"Queue"];
259 [[self window] setExcludedFromWindowsMenu:YES];
261 /* lets setup our queue list outline view for drag and drop here */
262 [fOutlineView registerForDraggedTypes: [NSArray arrayWithObject:DragDropSimplePboardType] ];
263 [fOutlineView setDraggingSourceOperationMask:NSDragOperationEvery forLocal:YES];
264 [fOutlineView setVerticalMotionCanBeginDrag: YES];
267 // Don't allow autoresizing of main column, else the "delete" column will get
268 // pushed out of view.
269 [fOutlineView setAutoresizesOutlineColumn: NO];
271 #if HB_OUTLINE_METRIC_CONTROLS
272 [fIndentation setHidden: NO];
273 [fSpacing setHidden: NO];
274 [fIndentation setIntegerValue:[fOutlineView indentationPerLevel]]; // debug
275 [fSpacing setIntegerValue:3]; // debug
278 // Show/hide UI elements
279 fCurrentJobPaneShown = NO; // it's shown in the nib
280 //[self showCurrentJobPane:NO];
282 //[self updateQueueCountField];
286 //------------------------------------------------------------------------------------
288 //------------------------------------------------------------------------------------
289 - (void)windowWillClose:(NSNotification *)aNotification
291 [[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"QueueWindowIsOpen"];
296 //------------------------------------------------------------------------------------
298 //------------------------------------------------------------------------------------
301 // Create a new toolbar instance, and attach it to our window
302 NSToolbar *toolbar = [[[NSToolbar alloc] initWithIdentifier: HBQueueToolbar] autorelease];
304 // Set up toolbar properties: Allow customization, give a default display mode, and remember state in user defaults
305 [toolbar setAllowsUserCustomization: YES];
306 [toolbar setAutosavesConfiguration: YES];
307 [toolbar setDisplayMode: NSToolbarDisplayModeIconAndLabel];
309 // We are the delegate
310 [toolbar setDelegate: self];
312 // Attach the toolbar to our window
313 [[self window] setToolbar:toolbar];
316 //------------------------------------------------------------------------------------
317 // toolbar:itemForItemIdentifier:willBeInsertedIntoToolbar:
318 //------------------------------------------------------------------------------------
319 - (NSToolbarItem *)toolbar:(NSToolbar *)toolbar
320 itemForItemIdentifier:(NSString *)itemIdentifier
321 willBeInsertedIntoToolbar:(BOOL)flag
323 // Required delegate method: Given an item identifier, this method returns an item.
324 // The toolbar will use this method to obtain toolbar items that can be displayed
325 // in the customization sheet, or in the toolbar itself.
327 NSToolbarItem *toolbarItem = nil;
329 if ([itemIdentifier isEqual: HBQueueStartCancelToolbarIdentifier])
331 toolbarItem = [[[NSToolbarItem alloc] initWithItemIdentifier: itemIdentifier] autorelease];
333 // Set the text label to be displayed in the toolbar and customization palette
334 [toolbarItem setLabel: NSLocalizedStringFromTable(@"Start", @"Queue",@"")];
335 [toolbarItem setPaletteLabel: NSLocalizedStringFromTable(@"Start/Cancel", @"Queue",@"")];
337 // Set up a reasonable tooltip, and image
338 [toolbarItem setToolTip: NSLocalizedStringFromTable(@"Start Encoding", @"Queue",@"")];
339 [toolbarItem setImage: [NSImage imageNamed: @"Play"]];
341 // Tell the item what message to send when it is clicked
342 [toolbarItem setTarget: self];
343 [toolbarItem setAction: @selector(toggleStartCancel:)];
346 if ([itemIdentifier isEqual: HBQueuePauseResumeToolbarIdentifier])
348 toolbarItem = [[[NSToolbarItem alloc] initWithItemIdentifier: itemIdentifier] autorelease];
350 // Set the text label to be displayed in the toolbar and customization palette
351 [toolbarItem setLabel: NSLocalizedStringFromTable(@"Pause", @"Queue",@"")];
352 [toolbarItem setPaletteLabel: NSLocalizedStringFromTable(@"Pause/Resume", @"Queue",@"")];
354 // Set up a reasonable tooltip, and image
355 [toolbarItem setToolTip: NSLocalizedStringFromTable(@"Pause Encoding", @"Queue",@"")];
356 [toolbarItem setImage: [NSImage imageNamed: @"Pause"]];
358 // Tell the item what message to send when it is clicked
359 [toolbarItem setTarget: self];
360 [toolbarItem setAction: @selector(togglePauseResume:)];
366 //------------------------------------------------------------------------------------
367 // toolbarDefaultItemIdentifiers:
368 //------------------------------------------------------------------------------------
369 - (NSArray *) toolbarDefaultItemIdentifiers: (NSToolbar *) toolbar
371 // Required delegate method: Returns the ordered list of items to be shown in the
372 // toolbar by default.
374 return [NSArray arrayWithObjects:
375 HBQueueStartCancelToolbarIdentifier,
376 HBQueuePauseResumeToolbarIdentifier,
380 //------------------------------------------------------------------------------------
381 // toolbarAllowedItemIdentifiers:
382 //------------------------------------------------------------------------------------
383 - (NSArray *) toolbarAllowedItemIdentifiers: (NSToolbar *) toolbar
385 // Required delegate method: Returns the list of all allowed items by identifier.
386 // By default, the toolbar does not assume any items are allowed, even the
387 // separator. So, every allowed item must be explicitly listed.
389 return [NSArray arrayWithObjects:
390 HBQueueStartCancelToolbarIdentifier,
391 HBQueuePauseResumeToolbarIdentifier,
392 NSToolbarCustomizeToolbarItemIdentifier,
393 NSToolbarFlexibleSpaceItemIdentifier,
394 NSToolbarSpaceItemIdentifier,
395 NSToolbarSeparatorItemIdentifier,
399 //------------------------------------------------------------------------------------
400 // validateToolbarItem:
401 //------------------------------------------------------------------------------------
402 - (BOOL) validateToolbarItem: (NSToolbarItem *) toolbarItem
404 // Optional method: This message is sent to us since we are the target of some
405 // toolbar item actions.
407 if (!fQueueEncodeLibhb) return NO;
412 hb_get_state2 (fQueueEncodeLibhb, &s);
414 if ([[toolbarItem itemIdentifier] isEqual: HBQueueStartCancelToolbarIdentifier])
416 if ((s.state == HB_STATE_PAUSED) || (s.state == HB_STATE_WORKING) || (s.state == HB_STATE_MUXING))
419 [toolbarItem setImage:[NSImage imageNamed: @"Stop"]];
420 [toolbarItem setLabel: NSLocalizedStringFromTable(@"Stop", @"Queue",@"")];
421 [toolbarItem setToolTip: NSLocalizedStringFromTable(@"Stop Encoding", @"Queue",@"")];
424 else if (fPendingCount > 0)
427 [toolbarItem setImage:[NSImage imageNamed: @"Play"]];
428 [toolbarItem setLabel: NSLocalizedStringFromTable(@"Start", @"Queue",@"")];
429 [toolbarItem setToolTip: NSLocalizedStringFromTable(@"Start Encoding", @"Queue",@"")];
435 [toolbarItem setImage:[NSImage imageNamed: @"Play"]];
436 [toolbarItem setLabel: NSLocalizedStringFromTable(@"Start", @"Queue",@"")];
437 [toolbarItem setToolTip: NSLocalizedStringFromTable(@"Start Encoding", @"Queue",@"")];
441 if ([[toolbarItem itemIdentifier] isEqual: HBQueuePauseResumeToolbarIdentifier])
443 if (s.state == HB_STATE_PAUSED)
446 [toolbarItem setImage:[NSImage imageNamed: @"Play"]];
447 [toolbarItem setLabel: NSLocalizedStringFromTable(@"Resume", @"Queue",@"")];
448 [toolbarItem setToolTip: NSLocalizedStringFromTable(@"Resume Encoding", @"Queue",@"")];
451 else if ((s.state == HB_STATE_WORKING) || (s.state == HB_STATE_MUXING))
454 [toolbarItem setImage:[NSImage imageNamed: @"Pause"]];
455 [toolbarItem setLabel: NSLocalizedStringFromTable(@"Pause", @"Queue",@"")];
456 [toolbarItem setToolTip: NSLocalizedStringFromTable(@"Pause Encoding", @"Queue",@"")];
461 [toolbarItem setImage:[NSImage imageNamed: @"Pause"]];
462 [toolbarItem setLabel: NSLocalizedStringFromTable(@"Pause", @"Queue",@"")];
463 [toolbarItem setToolTip: NSLocalizedStringFromTable(@"Pause Encoding", @"Queue",@"")];
473 #pragma mark Queue Item Controls
474 //------------------------------------------------------------------------------------
475 // Delete encodes from the queue window and accompanying array
476 // Also handling first cancelling the encode if in fact its currently encoding.
477 //------------------------------------------------------------------------------------
478 - (IBAction)removeSelectedQueueItem: (id)sender
480 NSIndexSet * selectedRows = [fOutlineView selectedRowIndexes];
481 int row = [selectedRows firstIndex];
482 /* if this is a currently encoding job, we need to be sure to alert the user,
483 * to let them decide to cancel it first, then if they do, we can come back and
486 if ([[[fJobGroups objectAtIndex:row] objectForKey:@"Status"] intValue] == 1)
488 /* We pause the encode here so that it doesn't finish right after and then
489 * screw up the sync while the window is open
491 [fHBController Pause:NULL];
492 NSString * alertTitle = [NSString stringWithFormat:NSLocalizedStringFromTable(@"Stop This Encode and Remove It ?", @"Queue", nil)];
493 // Which window to attach the sheet to?
494 NSWindow * docWindow;
495 if ([sender respondsToSelector: @selector(window)])
496 docWindow = [sender window];
499 NSBeginCriticalAlertSheet(
501 NSLocalizedStringFromTable(@"Keep Encoding", @"Queue", nil),
503 NSLocalizedStringFromTable(@"Stop Encoding and Delete", @"Queue", nil),
505 nil, @selector(didDimissCancelCurrentJob:returnCode:contextInfo:), nil,
506 NSLocalizedStringFromTable(@"Your movie will be lost if you don't continue encoding.", @"Queue", nil));
508 // didDimissCancelCurrentJob:returnCode:contextInfo: will be called when the dialog is dismissed
512 /* since we are not a currently encoding item, we can just be cancelled */
513 [fHBController removeQueueFileItem:row];
517 - (void) didDimissCancelCurrentJob: (NSWindow *)sheet returnCode: (int)returnCode contextInfo: (void *)contextInfo
519 /* We resume encoding and perform the appropriate actions
520 * Note: Pause: is a toggle type method based on hb's current
521 * state, if it paused, it will resume encoding and vice versa.
522 * In this case, we are paused from the calling window, so calling
523 * [fHBController Pause:NULL]; Again will resume encoding
525 [fHBController Pause:NULL];
526 if (returnCode == NSAlertOtherReturn)
528 /* We need to save the currently encoding item number first */
529 int encodingItemToRemove = fEncodingQueueItem;
530 /* Since we are encoding, we need to let fHBController Cancel this job
531 * upon which it will move to the next one if there is one
533 [fHBController doCancelCurrentJob];
534 /* Now, we can go ahead and remove the job we just cancelled since
535 * we have its item number from above
537 [fHBController removeQueueFileItem:encodingItemToRemove];
542 //------------------------------------------------------------------------------------
543 // Show the finished encode in the finder
544 //------------------------------------------------------------------------------------
545 - (IBAction)revealSelectedQueueItem: (id)sender
547 NSIndexSet * selectedRows = [fOutlineView selectedRowIndexes];
548 NSInteger row = [selectedRows firstIndex];
549 if (row != NSNotFound)
551 while (row != NSNotFound)
553 NSMutableDictionary *queueItemToOpen = [fOutlineView itemAtRow: row];
554 [[NSWorkspace sharedWorkspace] selectFile:[queueItemToOpen objectForKey:@"DestinationPath"] inFileViewerRootedAtPath:nil];
556 row = [selectedRows indexGreaterThanIndex: row];
562 //------------------------------------------------------------------------------------
563 // Starts or cancels the processing of jobs depending on the current state
564 //------------------------------------------------------------------------------------
565 - (IBAction)toggleStartCancel: (id)sender
567 if (!fQueueEncodeLibhb) return;
570 hb_get_state2 (fQueueEncodeLibhb, &s);
572 if ((s.state == HB_STATE_PAUSED) || (s.state == HB_STATE_WORKING) || (s.state == HB_STATE_MUXING))
573 [fHBController Cancel: fQueuePane]; // sender == fQueuePane so that warning alert shows up on queue window
575 else if (fPendingCount > 0)
576 [fHBController Rip: NULL];
579 //------------------------------------------------------------------------------------
580 // Toggles the pause/resume state of libhb
581 //------------------------------------------------------------------------------------
582 - (IBAction)togglePauseResume: (id)sender
584 if (!fQueueEncodeLibhb) return;
587 hb_get_state2 (fQueueEncodeLibhb, &s);
589 if (s.state == HB_STATE_PAUSED)
590 hb_resume (fQueueEncodeLibhb);
591 else if ((s.state == HB_STATE_WORKING) || (s.state == HB_STATE_MUXING))
592 hb_pause (fQueueEncodeLibhb);
598 #pragma mark Animate Endcoding Item
603 //------------------------------------------------------------------------------------
604 // Starts animating the job icon of the currently processing job in the queue outline
606 //------------------------------------------------------------------------------------
607 - (void) startAnimatingCurrentWorkingEncodeInQueue
609 if (!fAnimationTimer)
610 fAnimationTimer = [[NSTimer scheduledTimerWithTimeInterval:1.0/12.0 // 1/12 because there are 6 images in the animation cycle
612 selector:@selector(animateWorkingEncodeInQueue:)
614 repeats:YES] retain];
617 //------------------------------------------------------------------------------------
618 // If a job is currently processing, its job icon in the queue outline view is
619 // animated to its next state.
620 //------------------------------------------------------------------------------------
621 - (void) animateWorkingEncodeInQueue:(NSTimer*)theTimer
623 if (fWorkingCount > 0)
626 fAnimationIndex %= 6; // there are 6 animation images; see outlineView:objectValueForTableColumn:byItem: below.
627 [self animateWorkingEncodeIconInQueue];
632 - (void) animateWorkingEncodeIconInQueue
634 NSInteger row = fEncodingQueueItem; /// need to set to fEncodingQueueItem
635 NSInteger col = [fOutlineView columnWithIdentifier: @"icon"];
636 if (row != -1 && col != -1)
638 NSRect frame = [fOutlineView frameOfCellAtColumn:col row:row];
639 [fOutlineView setNeedsDisplayInRect: frame];
643 //------------------------------------------------------------------------------------
644 // Stops animating the job icon of the currently processing job in the queue outline
646 //------------------------------------------------------------------------------------
647 - (void) stopAnimatingCurrentJobGroupInQueue
649 if (fAnimationTimer && [fAnimationTimer isValid])
651 [fAnimationTimer invalidate];
652 [fAnimationTimer release];
653 fAnimationTimer = nil;
660 - (void)moveObjectsInArray:(NSMutableArray *)array fromIndexes:(NSIndexSet *)indexSet toIndex:(NSUInteger)insertIndex
662 NSUInteger index = [indexSet lastIndex];
663 NSUInteger aboveInsertIndexCount = 0;
665 while (index != NSNotFound)
667 NSUInteger removeIndex;
669 if (index >= insertIndex)
671 removeIndex = index + aboveInsertIndexCount;
672 aboveInsertIndexCount++;
680 id object = [[array objectAtIndex:removeIndex] retain];
681 [array removeObjectAtIndex:removeIndex];
682 [array insertObject:object atIndex:insertIndex];
685 index = [indexSet indexLessThanIndex:index];
691 #pragma mark NSOutlineView delegate
694 - (id)outlineView:(NSOutlineView *)fOutlineView child:(NSInteger)index ofItem:(id)item
697 return [fJobGroups objectAtIndex:index];
699 // We are only one level deep, so we can't be asked about children
700 NSAssert (NO, @"HBQueueController outlineView:child:ofItem: can't handle nested items.");
704 - (BOOL)outlineView:(NSOutlineView *)fOutlineView isItemExpandable:(id)item
706 // Our outline view has no levels, but we can still expand every item. Doing so
707 // just makes the row taller. See heightOfRowByItem below.
711 - (BOOL)outlineView:(NSOutlineView *)outlineView shouldExpandItem:(id)item
713 // Our outline view has no levels, but we can still expand every item. Doing so
714 // just makes the row taller. See heightOfRowByItem below.
715 return ![(HBQueueOutlineView*)outlineView isDragging];
718 - (NSInteger)outlineView:(NSOutlineView *)fOutlineView numberOfChildrenOfItem:(id)item
720 // Our outline view has no levels, so number of children will be zero for all
723 return [fJobGroups count];
728 - (void)outlineViewItemDidCollapse:(NSNotification *)notification
730 id item = [[notification userInfo] objectForKey:@"NSObject"];
731 NSInteger row = [fOutlineView rowForItem:item];
732 [fOutlineView noteHeightOfRowsWithIndexesChanged:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(row,1)]];
735 - (void)outlineViewItemDidExpand:(NSNotification *)notification
737 id item = [[notification userInfo] objectForKey:@"NSObject"];
738 NSInteger row = [fOutlineView rowForItem:item];
739 [fOutlineView noteHeightOfRowsWithIndexesChanged:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(row,1)]];
742 - (CGFloat)outlineView:(NSOutlineView *)outlineView heightOfRowByItem:(id)item
744 if ([outlineView isItemExpanded: item])
746 // Short-circuit here if in a live resize primarily to fix a bug but also to
747 // increase resposivness during a resize. There's a bug in NSTableView that
748 // causes row heights to get messed up if you try to change them during a live
749 // resize. So if in a live resize, simply return the previously calculated
750 // height. The row heights will get fixed up after the resize because we have
751 // implemented viewDidEndLiveResize to force all of them to be recalculated.
752 // if ([outlineView inLiveResize] && [item lastDescriptionHeight] > 0)
753 // return [item lastDescriptionHeight];
755 // CGFloat width = [[outlineView tableColumnWithIdentifier: @"desc"] width];
756 // Column width is NOT what is ultimately used. I can't quite figure out what
757 // width to use for calculating text metrics. No matter how I tweak this value,
758 // there are a few conditions in which the drawn text extends below the bounds
759 // of the row cell. In previous versions, which ran under Tiger, I was
760 // reducing width by 47 pixles.
761 // width -= 2; // (?) for intercell spacing
763 // CGFloat height = [item heightOfDescriptionForWidth: width];
766 return HB_ROW_HEIGHT_FULL_DESCRIPTION;
769 return HB_ROW_HEIGHT_TITLE_ONLY;
772 - (CGFloat) heightOfDescriptionForWidth:(CGFloat)width
774 // Try to return the cached value if no changes have happened since the last time
775 //if ((width == fLastDescriptionWidth) && (fLastDescriptionHeight != 0) && !fNeedsDescription)
776 // return fLastDescriptionHeight;
778 //if (fNeedsDescription)
779 // [self updateDescription];
781 // Calculate the height
782 //NSRect bounds = [fDescription boundingRectWithSize:NSMakeSize(width, 10000) options:NSStringDrawingUsesLineFragmentOrigin];
783 //fLastDescriptionHeight = bounds.size.height + 6.0; // add some border to bottom
784 //fLastDescriptionWidth = width;
785 return HB_ROW_HEIGHT_FULL_DESCRIPTION;
787 /* supposedly another way to do this, in case boundingRectWithSize isn't working
788 NSTextView* tmpView = [[NSTextView alloc] initWithFrame:NSMakeRect(0, 0, width, 1)];
789 [[tmpView textStorage] setAttributedString:aString];
790 [tmpView setHorizontallyResizable:NO];
791 [tmpView setVerticallyResizable:YES];
792 // [[tmpView textContainer] setHeightTracksTextView: YES];
793 // [[tmpView textContainer] setContainerSize: NSMakeSize(width, 10000)];
795 float height = [tmpView frame].size.height;
801 - (CGFloat) lastDescriptionHeight
803 return HB_ROW_HEIGHT_FULL_DESCRIPTION;
806 - (id)outlineView:(NSOutlineView *)fOutlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item
808 // nb: The "desc" column is currently an HBImageAndTextCell. However, we are longer
809 // using the image portion of the cell so we could switch back to a regular NSTextFieldCell.
811 if ([[tableColumn identifier] isEqualToString:@"desc"])
813 /* This should have caused the description we wanted to show*/
814 //return [item objectForKey:@"SourceName"];
816 /* code to build the description as per old queue */
817 //return [self formatEncodeItemDescription:item];
819 /* Below should be put into a separate method but I am way too f'ing lazy right now */
820 NSMutableAttributedString * finalString = [[[NSMutableAttributedString alloc] initWithString: @""] autorelease];
822 NSMutableParagraphStyle * ps = [[[NSParagraphStyle defaultParagraphStyle] mutableCopy] retain];
823 [ps setHeadIndent: 40.0];
824 [ps setParagraphSpacing: 1.0];
825 [ps setTabStops:[NSArray array]]; // clear all tabs
826 [ps addTabStop: [[[NSTextTab alloc] initWithType: NSLeftTabStopType location: 20.0] autorelease]];
829 NSDictionary* detailAttr = [NSDictionary dictionaryWithObjectsAndKeys:
830 [NSFont systemFontOfSize:10.0], NSFontAttributeName,
831 ps, NSParagraphStyleAttributeName,
834 NSDictionary* detailBoldAttr = [NSDictionary dictionaryWithObjectsAndKeys:
835 [NSFont boldSystemFontOfSize:10.0], NSFontAttributeName,
836 ps, NSParagraphStyleAttributeName,
839 NSDictionary* titleAttr = [NSDictionary dictionaryWithObjectsAndKeys:
840 [NSFont systemFontOfSize:[NSFont systemFontSize]], NSFontAttributeName,
841 ps, NSParagraphStyleAttributeName,
844 NSDictionary* shortHeightAttr = [NSDictionary dictionaryWithObjectsAndKeys:
845 [NSFont systemFontOfSize:2.0], NSFontAttributeName,
848 /* First line, we should strip the destination path and just show the file name and add the title num and chapters (if any) */
849 //finalDescription = [finalDescription stringByAppendingString:[NSString stringWithFormat:@"Source: %@ Output: %@\n", [item objectForKey:@"SourceName"],[item objectForKey:@"DestinationPath"]]];
850 NSString * summaryInfo;
852 NSString * titleString = [NSString stringWithFormat:NSLocalizedStringFromTable(@"Title %d", @"Queue",@""), [[item objectForKey:@"TitleNumber"] intValue]];
854 NSString * chapterString = ([[item objectForKey:@"ChapterStart"] intValue] == [[item objectForKey:@"ChapterEnd"] intValue]) ?
855 [NSString stringWithFormat:NSLocalizedStringFromTable(@"Chapter %d", @"Queue",@""), [[item objectForKey:@"ChapterStart"] intValue]] :
856 [NSString stringWithFormat:NSLocalizedStringFromTable(@"Chapters %d through %d", @"Queue",@""), [[item objectForKey:@"ChapterStart"] intValue], [[item objectForKey:@"ChapterEnd"] intValue]];
858 NSString * passesString;
859 if ([[item objectForKey:@"VideoTwoPass"] intValue] == 0)
861 passesString = [NSString stringWithFormat:NSLocalizedStringFromTable(@"1 Video Pass", @"Queue",@"")];
865 if ([[item objectForKey:@"VideoTurboTwoPass"] intValue] == 1)
867 passesString = [NSString stringWithFormat:NSLocalizedStringFromTable(@"2 Video Passes Turbo", @"Queue",@"")];
871 passesString = [NSString stringWithFormat:NSLocalizedStringFromTable(@"2 Video Passes", @"Queue",@"")];
875 [finalString appendString:[NSString stringWithFormat:@"%@", [item objectForKey:@"SourceName"]] withAttributes:titleAttr];
877 /* lets add the output file name to the title string here */
878 NSString * outputFilenameString = [[item objectForKey:@"DestinationPath"] lastPathComponent];
880 summaryInfo = [NSString stringWithFormat: @" (%@, %@, %@) -> %@", titleString, chapterString, passesString, outputFilenameString];
882 [finalString appendString:[NSString stringWithFormat:@"%@\n", summaryInfo] withAttributes:detailAttr];
884 // Insert a short-in-height line to put some white space after the title
885 [finalString appendString:@"\n" withAttributes:shortHeightAttr];
886 // End of Title Stuff
888 /* Second Line (Preset Name)*/
889 [finalString appendString: NSLocalizedStringFromTable(@"Preset: ", @"Queue",@"") withAttributes:detailBoldAttr];
890 [finalString appendString:[NSString stringWithFormat:@"%@\n", [item objectForKey:@"PresetName"]] withAttributes:detailAttr];
892 /* Third Line (Format Summary) */
893 NSString * audioCodecSummary = @"";
894 /* Lets also get our audio track detail since we are going through the logic for use later */
895 NSString * audioDetail1 = @"None";
896 NSString * audioDetail2 = @"None";
897 NSString * audioDetail3 = @"None";
898 NSString * audioDetail4 = @"None";
899 if ([[item objectForKey:@"Audio1Track"] intValue] > 0)
901 audioCodecSummary = [NSString stringWithFormat:@"%@", [item objectForKey:@"Audio1Encoder"]];
902 audioDetail1 = [NSString stringWithFormat:NSLocalizedStringFromTable(@"%@ Encoder: %@ Mixdown: %@ SampleRate: %@(khz) Bitrate: %@(kbps)", @"Queue",@""),
903 [item objectForKey:@"Audio1TrackDescription"] ,
904 [item objectForKey:@"Audio1Encoder"],
905 [item objectForKey:@"Audio1Mixdown"] ,
906 [item objectForKey:@"Audio1Samplerate"],
907 [item objectForKey:@"Audio1Bitrate"]];
909 if ([[item objectForKey:@"Audio1TrackDRCSlider"] floatValue] > 1.00)
911 audioDetail1 = [NSString stringWithFormat:NSLocalizedStringFromTable(@"%@, DRC: %@", @"Queue",@""),audioDetail1,[item objectForKey:@"Audio1TrackDRCSlider"]];
915 audioDetail1 = [NSString stringWithFormat:NSLocalizedStringFromTable(@"%@, DRC: Off", @"Queue",@""),audioDetail1];
919 if ([[item objectForKey:@"Audio2Track"] intValue] > 0)
921 audioCodecSummary = [NSString stringWithFormat:@"%@, %@",audioCodecSummary ,[item objectForKey:@"Audio2Encoder"]];
922 audioDetail2 = [NSString stringWithFormat:NSLocalizedStringFromTable(@"%@ Encoder: %@ Mixdown: %@ SampleRate: %@(khz) Bitrate: %@(kbps)", @"Queue",@""),
923 [item objectForKey:@"Audio2TrackDescription"] ,
924 [item objectForKey:@"Audio2Encoder"],
925 [item objectForKey:@"Audio2Mixdown"] ,
926 [item objectForKey:@"Audio2Samplerate"],
927 [item objectForKey:@"Audio2Bitrate"]];
929 if ([[item objectForKey:@"Audio2TrackDRCSlider"] floatValue] > 1.00)
931 audioDetail2 = [NSString stringWithFormat:NSLocalizedStringFromTable(@"%@, DRC: %@", @"Queue",@""),audioDetail2,[item objectForKey:@"Audio2TrackDRCSlider"]];
935 audioDetail2 = [NSString stringWithFormat:@"%@, DRC: Off",audioDetail2];
939 if ([[item objectForKey:@"Audio3Track"] intValue] > 0)
941 audioCodecSummary = [NSString stringWithFormat:@"%@, %@",audioCodecSummary ,[item objectForKey:@"Audio3Encoder"]];
942 audioDetail3 = [NSString stringWithFormat:NSLocalizedStringFromTable(@"%@ Encoder: %@ Mixdown: %@ SampleRate: %@(khz) Bitrate: %@(kbps)", @"Queue",@""),
943 [item objectForKey:@"Audio3TrackDescription"] ,
944 [item objectForKey:@"Audio3Encoder"],
945 [item objectForKey:@"Audio3Mixdown"] ,
946 [item objectForKey:@"Audio3Samplerate"],
947 [item objectForKey:@"Audio3Bitrate"]];
949 if ([[item objectForKey:@"Audio3TrackDRCSlider"] floatValue] > 1.00)
951 audioDetail3 = [NSString stringWithFormat:NSLocalizedStringFromTable(@"%@, DRC: %@", @"Queue",@""),audioDetail3,[item objectForKey:@"Audio3TrackDRCSlider"]];
955 audioDetail3 = [NSString stringWithFormat:NSLocalizedStringFromTable(@"%@, DRC: Off", @"Queue",@""),audioDetail3];
959 if ([[item objectForKey:@"Audio4Track"] intValue] > 0)
961 audioCodecSummary = [NSString stringWithFormat:@"%@, %@",audioCodecSummary ,[item objectForKey:@"Audio3Encoder"]];
962 audioDetail4 = [NSString stringWithFormat:NSLocalizedStringFromTable(@"%@ Encoder: %@ Mixdown: %@ SampleRate: %@(khz) Bitrate: %@(kbps)", @"Queue",@""),
963 [item objectForKey:@"Audio4TrackDescription"] ,
964 [item objectForKey:@"Audio4Encoder"],
965 [item objectForKey:@"Audio4Mixdown"] ,
966 [item objectForKey:@"Audio4Samplerate"],
967 [item objectForKey:@"Audio4Bitrate"]];
969 if ([[item objectForKey:@"Audio4TrackDRCSlider"] floatValue] > 1.00)
971 audioDetail4 = [NSString stringWithFormat:NSLocalizedStringFromTable(@"%@, DRC: %@", @"Queue",@""),audioDetail4,[item objectForKey:@"Audio4TrackDRCSlider"]];
975 audioDetail4 = [NSString stringWithFormat:NSLocalizedStringFromTable(@"%@, DRC: Off", @"Queue",@""),audioDetail4];
979 NSString * jobFormatInfo;
980 if ([[item objectForKey:@"ChapterMarkers"] intValue] == 1)
981 jobFormatInfo = [NSString stringWithFormat:NSLocalizedStringFromTable(@"%@ Container, %@ Video %@ Audio, Chapter Markers\n", @"Queue",@""), [item objectForKey:@"FileFormat"], [item objectForKey:@"VideoEncoder"], audioCodecSummary];
983 jobFormatInfo = [NSString stringWithFormat:NSLocalizedStringFromTable(@"%@ Container, %@ Video %@ Audio\n", @"Queue",@""), [item objectForKey:@"FileFormat"], [item objectForKey:@"VideoEncoder"], audioCodecSummary];
986 [finalString appendString: NSLocalizedStringFromTable(@"Format: ", @"Queue",@"") withAttributes:detailBoldAttr];
987 [finalString appendString: jobFormatInfo withAttributes:detailAttr];
989 /* Optional String for mp4 options */
990 if ([[item objectForKey:@"FileFormat"] isEqualToString: NSLocalizedStringFromTable(@"MP4 file", @"Queue",@"")])
992 NSString * MP4Opts = @"";
993 BOOL mp4OptsPresent = NO;
994 if( [[item objectForKey:@"Mp4LargeFile"] intValue] == 1)
996 mp4OptsPresent = YES;
997 MP4Opts = [MP4Opts stringByAppendingString:NSLocalizedStringFromTable(@" - Large file size", @"Queue",@"")];
999 if( [[item objectForKey:@"Mp4HttpOptimize"] intValue] == 1)
1001 mp4OptsPresent = YES;
1002 MP4Opts = [MP4Opts stringByAppendingString:NSLocalizedStringFromTable(@" - Web optimized", @"Queue",@"")];
1005 if( [[item objectForKey:@"Mp4iPodCompatible"] intValue] == 1)
1007 mp4OptsPresent = YES;
1008 MP4Opts = [MP4Opts stringByAppendingString:NSLocalizedStringFromTable(@" - iPod 5G support ", @"Queue",@"")];
1010 if (mp4OptsPresent == YES)
1012 [finalString appendString: NSLocalizedStringFromTable(@"MP4 Options: ", @"Queue",@"") withAttributes:detailBoldAttr];
1013 [finalString appendString: MP4Opts withAttributes:detailAttr];
1014 [finalString appendString:@"\n" withAttributes:detailAttr];
1018 /* Fourth Line (Destination Path)*/
1019 [finalString appendString: NSLocalizedStringFromTable(@"Destination: ", @"Queue",@"") withAttributes:detailBoldAttr];
1020 [finalString appendString: [item objectForKey:@"DestinationPath"] withAttributes:detailAttr];
1021 [finalString appendString:@"\n" withAttributes:detailAttr];
1022 /* Fifth Line Picture Details*/
1023 NSString * pictureInfo;
1024 pictureInfo = [NSString stringWithFormat:@"%@", [item objectForKey:@"PictureSizingSummary"]];
1025 if ([[item objectForKey:@"PictureKeepRatio"] intValue] == 1)
1027 pictureInfo = [pictureInfo stringByAppendingString:NSLocalizedStringFromTable(@" Keep Aspect Ratio", @"Queue",@"")];
1029 if ([[item objectForKey:@"VideoGrayScale"] intValue] == 1)
1031 pictureInfo = [pictureInfo stringByAppendingString:NSLocalizedStringFromTable(@", Grayscale", @"Queue",@"")];
1034 [finalString appendString: NSLocalizedStringFromTable(@"Picture: ", @"Queue",@"") withAttributes:detailBoldAttr];
1035 [finalString appendString: pictureInfo withAttributes:detailAttr];
1036 [finalString appendString:@"\n" withAttributes:detailAttr];
1038 /* Optional String for Picture Filters */
1040 NSString * pictureFilters = @"";
1041 BOOL pictureFiltersPresent = NO;
1042 if( [[item objectForKey:@"VFR"] intValue] == 1)
1044 pictureFiltersPresent = YES;
1045 pictureFilters = [pictureFilters stringByAppendingString:NSLocalizedStringFromTable(@" - VFR", @"Queue",@"")];
1047 if( [[item objectForKey:@"PictureDetelecine"] intValue] == 1 )
1049 pictureFiltersPresent = YES;
1050 pictureFilters = [pictureFilters stringByAppendingString:NSLocalizedStringFromTable(@" - Detelecine", @"Queue",@"")];
1053 if( [[item objectForKey:@"PictureDecomb"] intValue] == 1)
1055 pictureFiltersPresent = YES;
1056 pictureFilters = [pictureFilters stringByAppendingString:NSLocalizedStringFromTable(@" - Decomb ", @"Queue",@"")];
1059 if ([[item objectForKey:@"PictureDeinterlace"] intValue] != 0)
1061 pictureFiltersPresent = YES;
1062 if ([[item objectForKey:@"PictureDeinterlace"] intValue] == 1)
1064 pictureFilters = [pictureFilters stringByAppendingString:NSLocalizedStringFromTable(@" - Deinterlace: Fast ", @"Queue",@"")];
1066 else if ([[item objectForKey:@"PictureDeinterlace"] intValue] == 2)
1068 pictureFilters = [pictureFilters stringByAppendingString:NSLocalizedStringFromTable(@" - Deinterlace: Slow ", @"Queue",@"")];
1070 else if ([[item objectForKey:@"PictureDeinterlace"] intValue] == 3)
1072 pictureFilters = [pictureFilters stringByAppendingString:NSLocalizedStringFromTable(@" - Deinterlace: Slower ", @"Queue",@"")];
1076 if ([[item objectForKey:@"PictureDenoise"] intValue] != 0)
1078 pictureFiltersPresent = YES;
1079 if ([[item objectForKey:@"PictureDenoise"] intValue] == 1)
1081 pictureFilters = [pictureFilters stringByAppendingString:NSLocalizedStringFromTable(@" - Denoise: Weak ", @"Queue",@"")];
1083 else if ([[item objectForKey:@"PictureDenoise"] intValue] == 2)
1085 pictureFilters = [pictureFilters stringByAppendingString:NSLocalizedStringFromTable(@" - Denoise: Medium ", @"Queue",@"")];
1087 else if ([[item objectForKey:@"PictureDenoise"] intValue] == 3)
1089 pictureFilters = [pictureFilters stringByAppendingString:NSLocalizedStringFromTable(@" - Denoise: Strong ", @"Queue",@"")];
1093 if ([[item objectForKey:@"PictureDeblock"] intValue] != 0)
1095 pictureFiltersPresent = YES;
1096 pictureFilters = [pictureFilters stringByAppendingString: [NSString stringWithFormat:NSLocalizedStringFromTable(@" - Deblock (pp7) (%d) ", @"Queue",@""),[[item objectForKey:@"PictureDeblock"] intValue]]];
1098 if (pictureFiltersPresent == YES)
1100 [finalString appendString: NSLocalizedStringFromTable(@"Filters: ", @"Queue",@"") withAttributes:detailBoldAttr];
1101 [finalString appendString: pictureFilters withAttributes:detailAttr];
1102 [finalString appendString:@"\n" withAttributes:detailAttr];
1105 /* Sixth Line Video Details*/
1106 NSString * videoInfo;
1107 videoInfo = [NSString stringWithFormat:NSLocalizedStringFromTable(@"Encoder: %@", @"Queue",@""), [item objectForKey:@"VideoEncoder"]];
1109 /* for framerate look to see if we are using vfr detelecine */
1110 if ([[item objectForKey:@"JobIndexVideoFramerate"] intValue] == 0)
1112 if ([[item objectForKey:@"PictureDetelecine"] intValue] == 1)
1114 /* we are using same as source with vfr detelecine */
1115 videoInfo = [NSString stringWithFormat:NSLocalizedStringFromTable(@"%@ Framerate: Same as source (vfr detelecine)", @"Queue",@""), videoInfo];
1119 /* we are using a variable framerate without dropping frames */
1120 videoInfo = [NSString stringWithFormat:NSLocalizedStringFromTable(@"%@ Framerate: Same as source (variable)", @"Queue",@""), videoInfo];
1125 /* we have a specified, constant framerate */
1126 videoInfo = [NSString stringWithFormat:NSLocalizedStringFromTable(@"%@ Framerate: %@ (constant framerate)", @"Queue",@""), videoInfo ,[item objectForKey:@"VideoFramerate"]];
1129 if ([[item objectForKey:@"VideoQualityType"] intValue] == 0)// Target Size MB
1131 videoInfo = [NSString stringWithFormat:NSLocalizedStringFromTable(@"%@ Target Size: %@(MB) (%d(kbps) abr)", @"Queue",@""), videoInfo ,[item objectForKey:@"VideoTargetSize"],[[item objectForKey:@"VideoAvgBitrate"] intValue]];
1133 else if ([[item objectForKey:@"VideoQualityType"] intValue] == 1) // ABR
1135 videoInfo = [NSString stringWithFormat:NSLocalizedStringFromTable(@"%@ Bitrate: %d(kbps)", @"Queue",@""), videoInfo ,[[item objectForKey:@"VideoAvgBitrate"] intValue]];
1139 videoInfo = [NSString stringWithFormat:NSLocalizedStringFromTable(@"%@ Constant Quality: %.0f %%", @"Queue",@""), videoInfo ,[[item objectForKey:@"VideoQualitySlider"] floatValue] * 100];
1142 [finalString appendString: NSLocalizedStringFromTable(@"Video: ", @"Queue",@"") withAttributes:detailBoldAttr];
1143 [finalString appendString: videoInfo withAttributes:detailAttr];
1144 [finalString appendString:@"\n" withAttributes:detailAttr];
1146 if ([[item objectForKey:@"VideoEncoder"] isEqualToString: NSLocalizedStringFromTable(@"H.264 (x264)", @"Queue",@"")])
1148 [finalString appendString: NSLocalizedStringFromTable(@"x264 Options: ", @"Queue",@"") withAttributes:detailBoldAttr];
1149 [finalString appendString: [item objectForKey:@"x264Option"] withAttributes:detailAttr];
1150 [finalString appendString:@"\n" withAttributes:detailAttr];
1154 /* Seventh Line Audio Details*/
1155 [finalString appendString: NSLocalizedStringFromTable(@"Audio Track 1: ", @"Queue",@"") withAttributes:detailBoldAttr];
1156 [finalString appendString: audioDetail1 withAttributes:detailAttr];
1157 [finalString appendString:@"\n" withAttributes:detailAttr];
1159 [finalString appendString: NSLocalizedStringFromTable(@"Audio Track 2: ", @"Queue",@"") withAttributes:detailBoldAttr];
1160 [finalString appendString: audioDetail2 withAttributes:detailAttr];
1161 [finalString appendString:@"\n" withAttributes:detailAttr];
1163 [finalString appendString: NSLocalizedStringFromTable(@"Audio Track 3: ", @"Queue",@"") withAttributes:detailBoldAttr];
1164 [finalString appendString: audioDetail3 withAttributes:detailAttr];
1165 [finalString appendString:@"\n" withAttributes:detailAttr];
1167 [finalString appendString: NSLocalizedStringFromTable(@"Audio Track 4: ", @"Queue",@"") withAttributes:detailBoldAttr];
1168 [finalString appendString: audioDetail4 withAttributes:detailAttr];
1172 else if ([[tableColumn identifier] isEqualToString:@"icon"])
1174 if ([[item objectForKey:@"Status"] intValue] == 0)
1176 return [NSImage imageNamed:@"EncodeComplete"];
1178 else if ([[item objectForKey:@"Status"] intValue] == 1)
1180 return [NSImage imageNamed: [NSString stringWithFormat: NSLocalizedStringFromTable(@"EncodeWorking%d", @"Queue",@""), fAnimationIndex]];
1182 else if ([[item objectForKey:@"Status"] intValue] == 3)
1184 return [NSImage imageNamed:@"EncodeCanceled"];
1188 return [NSImage imageNamed:@"JobSmall"];
1198 - (void)outlineView:(NSOutlineView *)outlineView willDisplayCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item
1200 if ([[tableColumn identifier] isEqualToString:@"desc"])
1204 // nb: The "desc" column is currently an HBImageAndTextCell. However, we are longer
1205 // using the image portion of the cell so we could switch back to a regular NSTextFieldCell.
1207 // Set the image here since the value returned from outlineView:objectValueForTableColumn: didn't specify the image part
1208 [cell setImage:nil];
1210 else if ([[tableColumn identifier] isEqualToString:@"action"])
1212 [cell setEnabled: YES];
1213 BOOL highlighted = [outlineView isRowSelected:[outlineView rowForItem: item]] && [[outlineView window] isKeyWindow] && ([[outlineView window] firstResponder] == outlineView);
1214 if ([[item objectForKey:@"Status"] intValue] == 0)
1216 [cell setAction: @selector(revealSelectedQueueItem:)];
1219 [cell setImage:[NSImage imageNamed:@"RevealHighlight"]];
1220 [cell setAlternateImage:[NSImage imageNamed:@"RevealHighlightPressed"]];
1223 [cell setImage:[NSImage imageNamed:@"Reveal"]];
1227 [cell setAction: @selector(removeSelectedQueueItem:)];
1230 [cell setImage:[NSImage imageNamed:@"DeleteHighlight"]];
1231 [cell setAlternateImage:[NSImage imageNamed:@"DeleteHighlightPressed"]];
1234 [cell setImage:[NSImage imageNamed:@"Delete"]];
1239 - (void)outlineView:(NSOutlineView *)outlineView willDisplayOutlineCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item
1241 // By default, the discolsure image gets centered vertically in the cell. We want
1242 // always at the top.
1243 if ([outlineView isItemExpanded: item])
1244 [cell setImagePosition: NSImageAbove];
1246 [cell setImagePosition: NSImageOnly];
1250 #pragma mark NSOutlineView delegate (dragging related)
1252 //------------------------------------------------------------------------------------
1253 // NSTableView delegate
1254 //------------------------------------------------------------------------------------
1257 - (BOOL)outlineView:(NSOutlineView *)outlineView writeItems:(NSArray *)items toPasteboard:(NSPasteboard *)pboard
1259 // Dragging is only allowed of the pending items.
1260 if ([[[fJobGroups objectAtIndex:[outlineView selectedRow]] objectForKey:@"Status"] intValue] != 2) // 2 is pending
1265 // Don't retain since this is just holding temporaral drag information, and it is
1266 //only used during a drag! We could put this in the pboard actually.
1267 fDraggedNodes = items;
1269 // Provide data for our custom type, and simple NSStrings.
1270 [pboard declareTypes:[NSArray arrayWithObjects: DragDropSimplePboardType, nil] owner:self];
1272 // the actual data doesn't matter since DragDropSimplePboardType drags aren't recognized by anyone but us!.
1273 [pboard setData:[NSData data] forType:DragDropSimplePboardType];
1279 /* This method is used to validate the drops. */
1280 - (NSDragOperation)outlineView:(NSOutlineView *)outlineView validateDrop:(id <NSDraggingInfo>)info proposedItem:(id)item proposedChildIndex:(NSInteger)index
1282 // Don't allow dropping ONTO an item since they can't really contain any children.
1283 BOOL isOnDropTypeProposal = index == NSOutlineViewDropOnItemIndex;
1284 if (isOnDropTypeProposal)
1286 return NSDragOperationNone;
1289 // Don't allow dropping INTO an item since they can't really contain any children.
1292 index = [fOutlineView rowForItem: item] + 1;
1296 // NOTE: Should we allow dropping a pending job *above* the
1297 // finished or already encoded jobs ?
1298 // We do not let the user drop a pending job before or *above*
1299 // already finished or currently encoding jobs.
1300 if (index <= fEncodingQueueItem)
1302 return NSDragOperationNone;
1303 index = MAX (index, fEncodingQueueItem);
1306 [outlineView setDropItem:item dropChildIndex:index];
1307 return NSDragOperationGeneric;
1312 - (BOOL)outlineView:(NSOutlineView *)outlineView acceptDrop:(id <NSDraggingInfo>)info item:(id)item childIndex:(NSInteger)index
1314 NSMutableIndexSet *moveItems = [NSMutableIndexSet indexSet];
1317 NSEnumerator *enumerator = [fDraggedNodes objectEnumerator];
1318 while (obj = [enumerator nextObject])
1320 [moveItems addIndex:[fJobGroups indexOfObject:obj]];
1322 // Successful drop, we use moveObjectsInQueueArray:... in fHBController
1323 // to properly rearrange the queue array, save it to plist and then send it back here.
1324 // since Controller.mm is handling all queue array manipulation.
1325 // We *could do this here, but I think we are better served keeping that code together.
1326 [fHBController moveObjectsInQueueArray:fJobGroups fromIndexes:moveItems toIndex: index];