OSDN Git Service

MacGui: Queue - Display varying row heights based on the content of the encode.
[handbrake-jp/handbrake-jp-git.git] / macosx / HBQueueController.mm
index 755692a..3a53192 100644 (file)
 /* HBQueueController
 
     This file is part of the HandBrake source code.
-    Homepage: <http://handbrake.m0k.org/>.
+    Homepage: <http://handbrake.fr/>.
     It may be used under the terms of the GNU General Public License. */
 
-#include "HBQueueController.h"
-#include "Controller.h"
+#import "HBQueueController.h"
+#import "Controller.h"
+#import "HBImageAndTextCell.h"
 
-#define HB_QUEUE_DRAGGING 0
-#define HBQueueDataType         @"HBQueueDataType"
+#define HB_ROW_HEIGHT_TITLE_ONLY           17.0
+#define HB_ROW_HEIGHT_FULL_DESCRIPTION           200.0
+// Pasteboard type for or drag operations
+#define DragDropSimplePboardType       @"MyCustomOutlineViewPboardType"
 
-// UNI_QUEUE turns on the feature where the first item in the queue NSTableView is the
-// current job followed by the jobs in hblib's queue. In this scheme, fCurrentJobPane
-// disappers.
-#define HB_UNI_QUEUE 0
-
-#define HB_ROW_HEIGHT_DETAIL       98.0
-#define HB_ROW_HEIGHT_NO_DETAIL    17.0
-#define HB_ROW_HEIGHT_ACTIVE_JOB   60.0
+//------------------------------------------------------------------------------------
+#pragma mark -
+//------------------------------------------------------------------------------------
 
 //------------------------------------------------------------------------------------
-#pragma mark Job group functions
+// NSMutableAttributedString (HBAdditions)
 //------------------------------------------------------------------------------------
-// These could be part of hblib if we think hblib should have knowledge of groups.
-// For now, I see groups as a metaphor that HBQueueController provides.
 
-/**
- * Returns the number of jobs groups in the queue.
- * @param h Handle to hb_handle_t.
- * @return Number of job groups.
- */
-static int hb_group_count(hb_handle_t * h)    
-{
-    hb_job_t * job;
-    int count = 0;
-    int index = 0;
-    while( ( job = hb_job( h, index++ ) ) )
-    {
-        if (job->sequence_id == 0)
-            count++;
-    }
-    return count;
-}
+@interface NSMutableAttributedString (HBAdditions)
+- (void) appendString: (NSString*)aString withAttributes: (NSDictionary *)aDictionary;
+@end
 
-/**
- * Returns handle to the first job in the i-th group within the job list.
- * @param h Handle to hb_handle_t.
- * @param i Index of group.
- * @returns Handle to hb_job_t of desired job.
- */
-static hb_job_t * hb_group(hb_handle_t * h, int i)    
+@implementation NSMutableAttributedString (HBAdditions)
+- (void) appendString: (NSString*)aString withAttributes: (NSDictionary *)aDictionary
 {
-    hb_job_t * job;
-    int count = 0;
-    int index = 0;
-    while( ( job = hb_job( h, index++ ) ) )
-    {
-        if (job->sequence_id == 0)
-        {
-            if (count == i)
-                return job;
-            count++;
-        }
-    }
-    return NULL;
+    NSAttributedString * s = [[[NSAttributedString alloc]
+        initWithString: aString
+        attributes: aDictionary] autorelease];
+    [self appendAttributedString: s];
 }
+@end
 
-/**
- * Removes a groups of jobs from the job list.
- * @param h Handle to hb_handle_t.
- * @param job Handle to the first job in the group.
- */
-static void hb_rem_group( hb_handle_t * h, hb_job_t * job )
-{
-    // Find job in list
-    hb_job_t * j;
-    int index = 0;
-    while( ( j = hb_job( h, index ) ) )
-    {
-        if (j == job)
-        {
-            // Delete this job plus the following ones in the sequence
-            hb_rem( h, job );
-            while( ( j = hb_job( h, index ) ) && (j->sequence_id != 0) )
-                hb_rem( h, j );
-            return;
-        }
-        else
-            index++;
-    }
-}
 
-/**
- * Returns handle to the next job after the given job.
- * @param h Handle to hb_handle_t.
- * @param job Handle to the a job in the group.
- * @returns Handle to hb_job_t of desired job or NULL if no such job.
- */
-static hb_job_t * hb_next_job( hb_handle_t * h, hb_job_t * job )
+@implementation HBQueueOutlineView
+
+- (void)viewDidEndLiveResize
 {
-    hb_job_t * j = NULL;
-    int index = 0;
-    while( ( j = hb_job( h, index++ ) ) )
-    {
-        if (j == job)
-            return hb_job( h, index );
-    }
-    return NULL;
+    // Since we disabled calculating row heights during a live resize, force them to
+    // recalculate now.
+    [self noteHeightOfRowsWithIndexesChanged:
+            [NSIndexSet indexSetWithIndexesInRange: NSMakeRange(0, [self numberOfRows])]];
+    [super viewDidEndLiveResize];
 }
 
-#pragma mark -
-//------------------------------------------------------------------------------------
-// HBJob
-//------------------------------------------------------------------------------------
 
-#if HB_OUTLINE_QUEUE
 
-@interface HBJob : NSObject
+/* This should be for dragging, we take this info from the presets right now */
+- (NSImage *)dragImageForRowsWithIndexes:(NSIndexSet *)dragRows tableColumns:(NSArray *)tableColumns event:(NSEvent*)dragEvent offset:(NSPointPointer)dragImageOffset
 {
-    hb_job_t                *fJob;
-}
-+ (HBJob*) jobWithJob: (hb_job_t *) job;
-- (id) initWithJob: (hb_job_t *) job;
-- (hb_job_t *) job;
-@end
+    fIsDragging = YES;
 
-@implementation HBJob
-+ (HBJob*) jobWithJob: (hb_job_t *) job
-{
-    return [[[HBJob alloc] initWithJob:job] autorelease];
+    // By default, NSTableView only drags an image of the first column. Change this to
+    // drag an image of the queue's icon and desc and action columns.
+    NSArray * cols = [NSArray arrayWithObjects: [self tableColumnWithIdentifier:@"desc"], [self tableColumnWithIdentifier:@"icon"],[self tableColumnWithIdentifier:@"action"], nil];
+    return [super dragImageForRowsWithIndexes:dragRows tableColumns:cols event:dragEvent offset:dragImageOffset];
 }
 
-- (id) initWithJob: (hb_job_t *) job
+
+
+- (void) mouseDown:(NSEvent *)theEvent
 {
-    if (self = [super init])
-    {
-        // job is not owned by HBJob. It does not get dealloacted when HBJob is released.
-        fJob = job;
-    }
-    return self; 
+    [super mouseDown:theEvent];
+       fIsDragging = NO;
 }
 
-- (hb_job_t*) job
+
+
+- (BOOL) isDragging;
 {
-    return fJob;
+    return fIsDragging;
 }
 
-@end
 
-#endif // HB_OUTLINE_QUEUE
 
-#pragma mark -
+@end
 
+#pragma mark Toolbar Identifiers
 // Toolbar identifiers
-static NSString*    HBQueueToolbar                            = @"HBQueueToolbar";
-static NSString*    HBStartPauseResumeToolbarIdentifier       = @"HBStartPauseResumeToolbarIdentifier";
-static NSString*    HBShowDetailToolbarIdentifier             = @"HBShowDetailToolbarIdentifier";
-static NSString*    HBShowGroupsToolbarIdentifier             = @"HBShowGroupsToolbarIdentifier";
+static NSString*    HBQueueToolbar                            = @"HBQueueToolbar1";
+static NSString*    HBQueueStartCancelToolbarIdentifier       = @"HBQueueStartCancelToolbarIdentifier";
+static NSString*    HBQueuePauseResumeToolbarIdentifier       = @"HBQueuePauseResumeToolbarIdentifier";
 
+#pragma mark -
 
 @implementation HBQueueController
 
@@ -166,8 +94,15 @@ static NSString*    HBShowGroupsToolbarIdentifier             = @"HBShowGroupsTo
 //------------------------------------------------------------------------------------
 - (id)init
 {
-    if (self = [super init])
+    if (self = [super initWithWindowNibName:@"Queue"])
     {
+        // NSWindowController likes to lazily load its window nib. Since this
+        // controller tries to touch the outlets before accessing the window, we
+        // need to force it to load immadiately by invoking its accessor.
+        //
+        // If/when we switch to using bindings, this can probably go away.
+        [self window];
+
         // Our defaults
         [[NSUserDefaults standardUserDefaults] registerDefaults:[NSDictionary dictionaryWithObjectsAndKeys:
             @"NO",      @"QueueWindowIsOpen",
@@ -175,18 +110,90 @@ static NSString*    HBShowGroupsToolbarIdentifier             = @"HBShowGroupsTo
             @"YES",     @"QueueShowsJobsAsGroups",
             nil]];
 
-        fShowsDetail = [[NSUserDefaults standardUserDefaults] boolForKey:@"QueueShowsDetail"];
-#if HB_OUTLINE_QUEUE
-        fShowsJobsAsGroups = YES;
-#else
-        fShowsJobsAsGroups = [[NSUserDefaults standardUserDefaults] boolForKey:@"QueueShowsJobsAsGroups"];
-#endif
+        fJobGroups = [[NSMutableArray arrayWithCapacity:0] retain];
+       } 
+        return self;
+}
 
-#if HB_OUTLINE_QUEUE
-        fEncodes = [[NSMutableArray arrayWithCapacity:0] retain];
-#endif
+- (void)setQueueArray: (NSMutableArray *)QueueFileArray
+{
+    [fJobGroups setArray:QueueFileArray];
+    fIsDragging = NO; 
+    /* First stop any timer working now */
+    [self stopAnimatingCurrentJobGroupInQueue];
+    [fOutlineView reloadData];
+    
+    
+    
+    /* lets get the stats on the status of the queue array */
+    
+    fEncodingQueueItem = 0;
+    fPendingCount = 0;
+    fCompletedCount = 0;
+    fCanceledCount = 0;
+    fWorkingCount = 0;
+    
+    /* We use a number system to set the encode status of the queue item
+     * in controller.mm
+     * 0 == already encoded
+     * 1 == is being encoded
+     * 2 == is yet to be encoded
+     * 3 == cancelled
+     */
+    
+       int i = 0;
+       for(id tempObject in fJobGroups)
+       {
+               NSDictionary *thisQueueDict = tempObject;
+               if ([[thisQueueDict objectForKey:@"Status"] intValue] == 0) // Completed
+               {
+                       fCompletedCount++;      
+               }
+               if ([[thisQueueDict objectForKey:@"Status"] intValue] == 1) // being encoded
+               {
+                       fWorkingCount++;
+            fEncodingQueueItem = i;    
+               }
+        if ([[thisQueueDict objectForKey:@"Status"] intValue] == 2) // pending         
+        {
+                       fPendingCount++;
+               }
+        if ([[thisQueueDict objectForKey:@"Status"] intValue] == 3) // cancelled               
+        {
+                       fCanceledCount++;
+               }
+               i++;
+       }
+    
+    /* We should fire up the encoding timer here based on fWorkingCount */
+    
+    if (fWorkingCount > 0)
+    {
+        /* we have an encoding job so, lets start the animation timer */
+        [self startAnimatingCurrentWorkingEncodeInQueue];
+    }
+    
+    /* Set the queue status field in the queue window */
+    NSMutableString * string;
+    if (fPendingCount == 1)
+    {
+        string = [NSMutableString stringWithFormat: NSLocalizedString( @"%d encode pending", @"" ), fPendingCount];
+    }
+    else
+    {
+        string = [NSMutableString stringWithFormat: NSLocalizedString( @"%d encode(s) pending", @"" ), fPendingCount];
     }
-    return self; 
+    [fQueueCountField setStringValue:string];
+    
+}
+/* This method sets the status string in the queue window
+ * and is called from Controller.mm (fHBController)
+ * instead of running another timer here polling libhb
+ * for encoding status
+ */
+- (void)setQueueStatusString: (NSString *)statusString
+{
+[fProgressTextField setStringValue:statusString];
 }
 
 //------------------------------------------------------------------------------------
@@ -194,15 +201,16 @@ static NSString*    HBShowGroupsToolbarIdentifier             = @"HBShowGroupsTo
 //------------------------------------------------------------------------------------
 - (void)dealloc
 {
-    [fAnimation release];
-    
     // clear the delegate so that windowWillClose is not attempted
-    if ([fQueueWindow delegate] == self)
-        [fQueueWindow setDelegate:nil];
-    
-#if HB_OUTLINE_QUEUE
-    [fEncodes release];
-#endif
+    if( [[self window] delegate] == self )
+        [[self window] setDelegate:nil];
+
+    [fJobGroups release];
+
+    [fSavedExpandedItems release];
+    [fSavedSelectedItems release];
+
+    [[NSNotificationCenter defaultCenter] removeObserver:self];
 
     [super dealloc];
 }
@@ -212,7 +220,7 @@ static NSString*    HBShowGroupsToolbarIdentifier             = @"HBShowGroupsTo
 //------------------------------------------------------------------------------------
 - (void)setHandle: (hb_handle_t *)handle
 {
-    fHandle = handle;
+    fQueueEncodeLibhb = handle;
 }
 
 //------------------------------------------------------------------------------------
@@ -223,1332 +231,1283 @@ static NSString*    HBShowGroupsToolbarIdentifier             = @"HBShowGroupsTo
     fHBController = controller;
 }
 
+#pragma mark -
+
 //------------------------------------------------------------------------------------
 // Displays and brings the queue window to the front
 //------------------------------------------------------------------------------------
 - (IBAction) showQueueWindow: (id)sender
 {
-    if (!fQueueWindow)
-    {
-        BOOL loadSucceeded = [NSBundle loadNibNamed:@"Queue" owner:self] && fQueueWindow;
-        NSAssert(loadSucceeded, @"Could not open Queue nib file");
-    }
+    [self showWindow:sender];
+    [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"QueueWindowIsOpen"];
+}
 
-    [self updateQueueUI];
-    [self updateCurrentJobUI];
 
-    [fQueueWindow makeKeyAndOrderFront: self];
 
-    [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"QueueWindowIsOpen"];
-}
 //------------------------------------------------------------------------------------
-// Show or hide the current job pane (fCurrentJobPane).
+// awakeFromNib
 //------------------------------------------------------------------------------------
-- (void) showCurrentJobPane: (BOOL)showPane
+- (void)awakeFromNib
 {
-    if (showPane != fCurrentJobHidden)
-        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];
+    [self setupToolbar];
 
-    // Resize fQueuePane
-    NSDictionary * dict2 = [NSDictionary dictionaryWithObjectsAndKeys:
-        fQueuePane, NSViewAnimationTargetKey,
-        [NSValue valueWithRect:queueFrame], NSViewAnimationEndFrameKey,
-        nil];
+    if( ![[self window] setFrameUsingName:@"Queue"] )
+        [[self window] center];
+    [self setWindowFrameAutosaveName:@"Queue"];
+    [[self window] setExcludedFromWindowsMenu:YES];
 
-    if (!fAnimation)
-        fAnimation = [[NSViewAnimation alloc] initWithViewAnimations:nil];
+    /* lets setup our queue list outline view for drag and drop here */
+    [fOutlineView registerForDraggedTypes: [NSArray arrayWithObject:DragDropSimplePboardType] ];
+    [fOutlineView setDraggingSourceOperationMask:NSDragOperationEvery forLocal:YES];
+    [fOutlineView setVerticalMotionCanBeginDrag: YES];
 
-    [fAnimation setViewAnimations:[NSArray arrayWithObjects:dict1, dict2, nil]];
-    [fAnimation setDuration:0.25];
-    [fAnimation setAnimationBlockingMode:NSAnimationBlocking]; // prevent user from resizing the window during an animation
-    [fAnimation startAnimation];
-    fCurrentJobHidden = !showPane;
-}
 
-//------------------------------------------------------------------------------------
-// Enables or disables the display of detail information for each job.
-//------------------------------------------------------------------------------------
-- (void)setShowsDetail: (BOOL)showsDetail
-{
-    fShowsDetail = showsDetail;
-    
-    [[NSUserDefaults standardUserDefaults] setBool:showsDetail forKey:@"QueueShowsDetail"];
-    [[NSUserDefaults standardUserDefaults] synchronize];
+    // Don't allow autoresizing of main column, else the "delete" column will get
+    // pushed out of view.
+    [fOutlineView setAutoresizesOutlineColumn: NO];
 
-    [fTaskView setRowHeight:showsDetail ? HB_ROW_HEIGHT_DETAIL : HB_ROW_HEIGHT_NO_DETAIL];
-#if HB_UNI_QUEUE
-    if (hb_count(fHandle))
-        [fTaskView noteHeightOfRowsWithIndexesChanged:[NSIndexSet indexSetWithIndex:0]];
+#if HB_OUTLINE_METRIC_CONTROLS
+    [fIndentation setHidden: NO];
+    [fSpacing setHidden: NO];
+    [fIndentation setIntegerValue:[fOutlineView indentationPerLevel]];  // debug
+    [fSpacing setIntegerValue:3];       // debug
 #endif
-#if HB_OUTLINE_QUEUE
 
-        [fOutlineView noteHeightOfRowsWithIndexesChanged:
-            [NSIndexSet indexSetWithIndexesInRange:
-                NSMakeRange(0,[fOutlineView numberOfRows])
-                ]];
-#endif
+    // Show/hide UI elements
+    fCurrentJobPaneShown = NO;     // it's shown in the nib
+    //[self showCurrentJobPane:NO];
 
-    if ([fTaskView selectedRow] != -1)
-        [fTaskView scrollRowToVisible:[fTaskView selectedRow]];
+    //[self updateQueueCountField];
 }
 
+
 //------------------------------------------------------------------------------------
-// Enables or disables the grouping of job passes into one item in the UI.
+// windowWillClose
 //------------------------------------------------------------------------------------
-- (void)setShowsJobsAsGroups: (BOOL)showsGroups
+- (void)windowWillClose:(NSNotification *)aNotification
 {
-#if HB_OUTLINE_QUEUE
-    return; // Can't modify this value. It's always YES.
-#endif
-    fShowsJobsAsGroups = showsGroups;
-    
-    [[NSUserDefaults standardUserDefaults] setBool:showsGroups forKey:@"QueueShowsJobsAsGroups"];
-    [[NSUserDefaults standardUserDefaults] synchronize];
+    [[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"QueueWindowIsOpen"];
+}
+
+#pragma mark Toolbar
+
+//------------------------------------------------------------------------------------
+// setupToolbar
+//------------------------------------------------------------------------------------
+- (void)setupToolbar
+{
+    // Create a new toolbar instance, and attach it to our window
+    NSToolbar *toolbar = [[[NSToolbar alloc] initWithIdentifier: HBQueueToolbar] autorelease];
+
+    // Set up toolbar properties: Allow customization, give a default display mode, and remember state in user defaults
+    [toolbar setAllowsUserCustomization: YES];
+    [toolbar setAutosavesConfiguration: YES];
+    [toolbar setDisplayMode: NSToolbarDisplayModeIconAndLabel];
 
-    [self updateQueueUI];
-    if ([fTaskView selectedRow] != -1)
-        [fTaskView scrollRowToVisible:[fTaskView selectedRow]];
+    // We are the delegate
+    [toolbar setDelegate: self];
+
+    // Attach the toolbar to our window
+    [[self window] setToolbar:toolbar];
 }
 
 //------------------------------------------------------------------------------------
-// Returns a 16x16 image that represents a job pass.
+// toolbar:itemForItemIdentifier:willBeInsertedIntoToolbar:
 //------------------------------------------------------------------------------------
-- (NSImage *)smallImageForPass: (int)pass
+- (NSToolbarItem *)toolbar:(NSToolbar *)toolbar
+        itemForItemIdentifier:(NSString *)itemIdentifier
+        willBeInsertedIntoToolbar:(BOOL)flag
 {
-    switch (pass)
+    // Required delegate method: Given an item identifier, this method returns an item.
+    // The toolbar will use this method to obtain toolbar items that can be displayed
+    // in the customization sheet, or in the toolbar itself.
+
+    NSToolbarItem *toolbarItem = nil;
+
+    if ([itemIdentifier isEqual: HBQueueStartCancelToolbarIdentifier])
+    {
+        toolbarItem = [[[NSToolbarItem alloc] initWithItemIdentifier: itemIdentifier] autorelease];
+
+        // Set the text label to be displayed in the toolbar and customization palette
+        [toolbarItem setLabel: @"Start"];
+        [toolbarItem setPaletteLabel: @"Start/Cancel"];
+
+        // Set up a reasonable tooltip, and image
+        [toolbarItem setToolTip: @"Start Encoding"];
+        [toolbarItem setImage: [NSImage imageNamed: @"Play"]];
+
+        // Tell the item what message to send when it is clicked
+        [toolbarItem setTarget: self];
+        [toolbarItem setAction: @selector(toggleStartCancel:)];
+    }
+
+    if ([itemIdentifier isEqual: HBQueuePauseResumeToolbarIdentifier])
     {
-        case -1: return [NSImage imageNamed: @"JobPassSubtitleSmall"];
-        case  1: return [NSImage imageNamed: @"JobPassFirstSmall"];
-        case  2: return [NSImage imageNamed: @"JobPassSecondSmall"];
-        default: return [NSImage imageNamed: @"JobPassUnknownSmall"];
+        toolbarItem = [[[NSToolbarItem alloc] initWithItemIdentifier: itemIdentifier] autorelease];
+
+        // Set the text label to be displayed in the toolbar and customization palette
+        [toolbarItem setLabel: @"Pause"];
+        [toolbarItem setPaletteLabel: @"Pause/Resume"];
+
+        // Set up a reasonable tooltip, and image
+        [toolbarItem setToolTip: @"Pause Encoding"];
+        [toolbarItem setImage: [NSImage imageNamed: @"Pause"]];
+
+        // Tell the item what message to send when it is clicked
+        [toolbarItem setTarget: self];
+        [toolbarItem setAction: @selector(togglePauseResume:)];
     }
+
+    return toolbarItem;
 }
 
 //------------------------------------------------------------------------------------
-// Returns a 64x64 image that represents a job pass.
+// toolbarDefaultItemIdentifiers:
 //------------------------------------------------------------------------------------
-- (NSImage *)largeImageForPass: (int)pass
+- (NSArray *) toolbarDefaultItemIdentifiers: (NSToolbar *) toolbar
 {
-    switch (pass)
-    {
-        case -1: return [NSImage imageNamed: @"JobPassSubtitleLarge"];
-        case  1: return [NSImage imageNamed: @"JobPassFirstLarge"];
-        case  2: return [NSImage imageNamed: @"JobPassSecondLarge"];
-        default: return [NSImage imageNamed: @"JobPassUnknownLarge"];
-    }
+    // Required delegate method: Returns the ordered list of items to be shown in the
+    // toolbar by default.
+
+    return [NSArray arrayWithObjects:
+        HBQueueStartCancelToolbarIdentifier,
+        HBQueuePauseResumeToolbarIdentifier,
+        nil];
 }
 
-#if HB_OUTLINE_QUEUE
 //------------------------------------------------------------------------------------
-// Rebuilds the contents of fEncodes which is a array of encodes and HBJobs.
+// toolbarAllowedItemIdentifiers:
 //------------------------------------------------------------------------------------
-- (void)rebuildEncodes
+- (NSArray *) toolbarAllowedItemIdentifiers: (NSToolbar *) toolbar
 {
-    [fEncodes removeAllObjects];
+    // Required delegate method: Returns the list of all allowed items by identifier.
+    // By default, the toolbar does not assume any items are allowed, even the
+    // separator. So, every allowed item must be explicitly listed.
 
-    NSMutableArray * aJobGroup = [NSMutableArray arrayWithCapacity:0];
-    hb_job_t * nextJob = hb_group( fHandle, 0 );
-    while( nextJob )
-    {
-        if (nextJob->sequence_id == 0)
-        {
-            // Encountered a new group. Add the current one to fEncodes and then start a new one.
-            if ([aJobGroup count] > 0)
-            {
-                [fEncodes addObject:aJobGroup];
-                aJobGroup = [NSMutableArray arrayWithCapacity:0];
-            }
-        }
-        [aJobGroup addObject: [HBJob jobWithJob:nextJob]];
-        nextJob = hb_next_job (fHandle, nextJob);
-    }
-    if ([aJobGroup count] > 0)
-        [fEncodes addObject:aJobGroup];
+    return [NSArray arrayWithObjects:
+        HBQueueStartCancelToolbarIdentifier,
+        HBQueuePauseResumeToolbarIdentifier,
+        NSToolbarCustomizeToolbarItemIdentifier,
+        NSToolbarFlexibleSpaceItemIdentifier,
+        NSToolbarSpaceItemIdentifier,
+        NSToolbarSeparatorItemIdentifier,
+        nil];
 }
-#endif
 
 //------------------------------------------------------------------------------------
-// Generates a multi-line text string that includes the job name on the first line
-// followed by details of the job on subsequent lines. If the text is to be drawn as
-// part of a highlighted cell, set isHighlighted to true. The returned string may
-// contain multiple fonts and paragraph formating.
+// validateToolbarItem:
 //------------------------------------------------------------------------------------
-- (NSAttributedString *)attributedDescriptionForJob: (hb_job_t *)job
-                                          withTitle: (BOOL)withTitle
-                                         withDetail: (BOOL)withDetail
-                                   withHighlighting: (BOOL)highlighted
+- (BOOL) validateToolbarItem: (NSToolbarItem *) toolbarItem
 {
-    NSMutableAttributedString * finalString;   // the return value
-    NSAttributedString* anAttributedString;    // a temp string for building up attributed substrings
-    NSMutableString* aMutableString;           // a temp string for non-attributed substrings
-    hb_title_t * title = job->title;
-    
-    NSMutableParagraphStyle *ps = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
-    [ps setLineBreakMode:NSLineBreakByClipping];
-
-    static NSDictionary* detailAttribute = [[NSDictionary dictionaryWithObjectsAndKeys:
-                [NSFont systemFontOfSize:10.0], NSFontAttributeName,
-                [NSColor darkGrayColor], NSForegroundColorAttributeName,
-                ps, NSParagraphStyleAttributeName,
-                nil] retain];
-    static NSDictionary* detailHighlightedAttribute = [[NSDictionary dictionaryWithObjectsAndKeys:
-                [NSFont systemFontOfSize:10.0], NSFontAttributeName,
-                [NSColor whiteColor], NSForegroundColorAttributeName,
-                ps, NSParagraphStyleAttributeName,
-                nil] retain];
-    static NSDictionary* titleAttribute = [[NSDictionary dictionaryWithObjectsAndKeys:
-                [NSFont systemFontOfSize:[NSFont systemFontSize]], NSFontAttributeName,
-                ps, NSParagraphStyleAttributeName,
-                nil] retain];
-
-    finalString = [[[NSMutableAttributedString alloc] init] autorelease];
-
-    // Title, in bold
-    // Show the name of the source Note: use title->name instead of title->dvd since
-    // name is just the chosen folder, instead of dvd which is the full path
-    if (withTitle)
-    {
-        anAttributedString = [[[NSAttributedString alloc] initWithString:[NSString stringWithUTF8String:title->name] attributes:titleAttribute] autorelease];
-        [finalString appendAttributedString:anAttributedString];
-    }
-    
-    // Other info in plain
-    
-    aMutableString = [NSMutableString stringWithCapacity:200];
+    // Optional method: This message is sent to us since we are the target of some
+    // toolbar item actions.
 
-    // The subtitle scan doesn't contain all the stuff we need (like x264opts).
-    // So grab the next job in the group for display purposes.
-    if (fShowsJobsAsGroups && job->pass == -1)
-    {
-        // When job is the one currently being processed, then the next in its group
-        // is the the first job in the queue.
-        hb_job_t * nextjob;
-        if (job == hb_current_job(fHandle))
-            nextjob = hb_job(fHandle, 0);
-        else
-            nextjob = hb_next_job(fHandle, job);
-        if (nextjob)    // Overly cautious in case there is no next job!
-            job = nextjob;
-    }
+    if (!fQueueEncodeLibhb) return NO;
 
-    if (withTitle)
-    {
-        NSString * chapterString = (job->chapter_start == job->chapter_end) ?
-                [NSString stringWithFormat:@"Chapter %d", job->chapter_start] :
-                [NSString stringWithFormat:@"Chapters %d through %d", job->chapter_start, job->chapter_end];
-    
-        // Scan pass
-        if (job->pass == -1)
-        {
-            [aMutableString appendString:[NSString stringWithFormat:
-                    @"  (Title %d, %@, Subtitle Scan)", title->index, chapterString]];
-        }
-        else
-        {
-            if (fShowsJobsAsGroups)
-                [aMutableString appendString:[NSString stringWithFormat:
-                        @"  (Title %d, %@, %d-Pass)",
-                        title->index, chapterString, MIN( 2, job->pass + 1 )]];
-            else
-                [aMutableString appendString:[NSString stringWithFormat:
-                        @"  (Title %d, %@, Pass %d of %d)",
-                        title->index, chapterString, MAX( 1, job->pass ), MIN( 2, job->pass + 1 )]];
-        }
-    }
-    
-    // End of title stuff
-    
-    
-    // Normal pass - show detail
-    if (withDetail && job->pass != -1)
+    BOOL enable = NO;
+
+    hb_state_t s;
+    hb_get_state2 (fQueueEncodeLibhb, &s);
+
+    if ([[toolbarItem itemIdentifier] isEqual: HBQueueStartCancelToolbarIdentifier])
     {
-        NSString * jobFormat;
-        NSString * jobPictureDetail;
-        NSString * jobVideoDetail;
-        NSString * jobVideoCodec;
-        NSString * jobVideoQuality;
-        NSString * jobAudioDetail;
-        NSString * jobAudioCodec;
-
-        /* Muxer settings (File Format in the gui) */
-        if (job->mux == 65536 || job->mux == 131072 || job->mux == 1048576)
-            jobFormat = @"MP4"; // HB_MUX_MP4,HB_MUX_PSP,HB_MUX_IPOD
-        else if (job->mux == 262144)
-            jobFormat = @"AVI"; // HB_MUX_AVI
-        else if (job->mux == 524288)
-            jobFormat = @"OGM"; // HB_MUX_OGM
-        else if (job->mux == 2097152)
-            jobFormat = @"MKV"; // HB_MUX_MKV
-        else
-            jobFormat = @"unknown";
-        
-        // 2097152
-        /* Video Codec settings (Encoder in the gui) */
-        if (job->vcodec == 1)
-            jobVideoCodec = @"FFmpeg"; // HB_VCODEC_FFMPEG
-        else if (job->vcodec == 2)
-            jobVideoCodec = @"XviD"; // HB_VCODEC_XVID
-        else if (job->vcodec == 4)
+        if ((s.state == HB_STATE_PAUSED) || (s.state == HB_STATE_WORKING) || (s.state == HB_STATE_MUXING))
         {
-            /* Deterimine for sure how we are now setting iPod uuid atom */
-            if (job->h264_level) // We are encoding for iPod
-                jobVideoCodec = @"x264 (H.264 iPod)"; // HB_VCODEC_X264    
-            else
-                jobVideoCodec = @"x264 (H.264 Main)"; // HB_VCODEC_X264
+            enable = YES;
+            [toolbarItem setImage:[NSImage imageNamed: @"Stop"]];
+            [toolbarItem setLabel: @"Stop"];
+            [toolbarItem setToolTip: @"Stop Encoding"];
         }
-        else
-            jobVideoCodec = @"unknown";
-        
-        /* Audio Codecs (Second half of Codecs in the gui) */
-        if (job->acodec == 256)
-            jobAudioCodec = @"AAC"; // HB_ACODEC_FAAC
-        else if (job->acodec == 512)
-            jobAudioCodec = @"MP3"; // HB_ACODEC_LAME
-        else if (job->acodec == 1024)
-            jobAudioCodec = @"Vorbis"; // HB_ACODEC_VORBIS
-        else if (job->acodec == 2048)
-            jobAudioCodec = @"AC3"; // HB_ACODEC_AC3
-        else
-            jobAudioCodec = @"unknown";
-        /* Show Basic File info */
-        if (job->chapter_markers == 1)
-            [aMutableString appendString:[NSString stringWithFormat:@"\nFormat: %@ Container, %@ Video + %@ Audio, Chapter Markers", jobFormat, jobVideoCodec, jobAudioCodec]];
-        else
-            [aMutableString appendString:[NSString stringWithFormat:@"\nFormat: %@ Container, %@ Video + %@ Audio", jobFormat, jobVideoCodec, jobAudioCodec]];
-            
-        /*Picture info*/
-        /*integers for picture values deinterlace, crop[4], keep_ratio, grayscale, pixel_ratio, pixel_aspect_width, pixel_aspect_height,
-         maxWidth, maxHeight */
-        if (job->pixel_ratio == 1)
+
+        else if (fPendingCount > 0)
         {
-            int titlewidth = title->width - job->crop[2] - job->crop[3];
-            int displayparwidth = titlewidth * job->pixel_aspect_width / job->pixel_aspect_height;
-            int displayparheight = title->height - job->crop[0] - job->crop[1];
-            jobPictureDetail = [NSString stringWithFormat:@"Picture: %dx%d (%dx%d Anamorphic)", displayparwidth, displayparheight, job->width, displayparheight];
+            enable = YES;
+            [toolbarItem setImage:[NSImage imageNamed: @"Play"]];
+            [toolbarItem setLabel: @"Start"];
+            [toolbarItem setToolTip: @"Start Encoding"];
         }
+
         else
-            jobPictureDetail = [NSString stringWithFormat:@"Picture: %dx%d", job->width, job->height];
-        if (job->keep_ratio == 1)
-            jobPictureDetail = [jobPictureDetail stringByAppendingString:@" Keep Aspect Ratio"];
-        
-        if (job->grayscale == 1)
-            jobPictureDetail = [jobPictureDetail stringByAppendingString:@", Grayscale"];
-        
-        if (job->deinterlace == 1)
-            jobPictureDetail = [jobPictureDetail stringByAppendingString:@", Deinterlace"];
-        /* Show Picture info */    
-        [aMutableString appendString:[NSString stringWithFormat:@"\n%@", jobPictureDetail]];
-        
-        /* Detailed Video info */
-        if (job->vquality <= 0 || job->vquality >= 1)
-            jobVideoQuality =[NSString stringWithFormat:@"%d kbps", job->vbitrate];
-        else
-        {
-            NSNumber * vidQuality;
-            vidQuality = [NSNumber numberWithInt:job->vquality * 100];
-            /* this is screwed up kind of. Needs to be formatted properly */
-            if (job->crf == 1)
-                jobVideoQuality =[NSString stringWithFormat:@"%@%% CRF", vidQuality];            
-            else
-                jobVideoQuality =[NSString stringWithFormat:@"%@%% CQP", vidQuality];
-        }
-        
-        if (job->vrate_base == 1126125)
         {
-            /* NTSC FILM 23.976 */
-            jobVideoDetail = [NSString stringWithFormat:@"Video: %@, %@, 23.976 fps", jobVideoCodec, jobVideoQuality];
+            enable = NO;
+            [toolbarItem setImage:[NSImage imageNamed: @"Play"]];
+            [toolbarItem setLabel: @"Start"];
+            [toolbarItem setToolTip: @"Start Encoding"];
         }
-        else if (job->vrate_base == 900900)
+    }
+
+    if ([[toolbarItem itemIdentifier] isEqual: HBQueuePauseResumeToolbarIdentifier])
+    {
+        if (s.state == HB_STATE_PAUSED)
         {
-            /* NTSC 29.97 */
-            jobVideoDetail = [NSString stringWithFormat:@"Video: %@, %@, 29.97 fps", jobVideoCodec, jobVideoQuality];
-        }
-        else
+            enable = YES;
+            [toolbarItem setImage:[NSImage imageNamed: @"Play"]];
+            [toolbarItem setLabel: @"Resume"];
+            [toolbarItem setToolTip: @"Resume Encoding"];
+       }
+
+        else if ((s.state == HB_STATE_WORKING) || (s.state == HB_STATE_MUXING))
         {
-            /* Everything else */
-            jobVideoDetail = [NSString stringWithFormat:@"Video: %@, %@, %d fps", jobVideoCodec, jobVideoQuality, job->vrate / job->vrate_base];
+            enable = YES;
+            [toolbarItem setImage:[NSImage imageNamed: @"Pause"]];
+            [toolbarItem setLabel: @"Pause"];
+            [toolbarItem setToolTip: @"Pause Encoding"];
         }
-        
-        /* Add the video detail string to the job filed in the window */
-        [aMutableString appendString:[NSString stringWithFormat:@"\n%@", jobVideoDetail]];
-        
-        /* if there is an x264 option string, lets add it here*/
-        /*NOTE: Due to size, lets get this in a tool tip*/
-        
-        if (job->x264opts)
-            [aMutableString appendString:[NSString stringWithFormat:@"\nx264 Options: %@", [NSString stringWithUTF8String:job->x264opts]]];
-        
-        /* Audio Detail */
-        if ([jobAudioCodec isEqualToString: @"AC3"])
-            jobAudioDetail = [NSString stringWithFormat:@"Audio: %@, Pass-Through", jobAudioCodec];
         else
-            jobAudioDetail = [NSString stringWithFormat:@"Audio: %@, %d kbps, %d Hz", jobAudioCodec, job->abitrate, job->arate];
-        
-        /* we now get the audio mixdown info for each of the two gui audio tracks */
-        /* lets do it the long way here to get a handle on things.
-            Hardcoded for two tracks for gui: audio_mixdowns[i] audio_mixdowns[i] */
-        int ai; // counter for each audios [] , macgui only allows for two audio tracks currently
-        for( ai = 0; ai < 2; ai++ )
         {
-            if (job->audio_mixdowns[ai] == HB_AMIXDOWN_MONO)
-                jobAudioDetail = [jobAudioDetail stringByAppendingString:[NSString stringWithFormat:@", Track %d: Mono",ai + 1]];
-            if (job->audio_mixdowns[ai] == HB_AMIXDOWN_STEREO)
-                jobAudioDetail = [jobAudioDetail stringByAppendingString:[NSString stringWithFormat:@", Track %d: Stereo",ai + 1]];
-            if (job->audio_mixdowns[ai] == HB_AMIXDOWN_DOLBY)
-                jobAudioDetail = [jobAudioDetail stringByAppendingString:[NSString stringWithFormat:@", Track %d: Dolby Surround",ai + 1]];
-            if (job->audio_mixdowns[ai] == HB_AMIXDOWN_DOLBYPLII)
-                jobAudioDetail = [jobAudioDetail stringByAppendingString:[NSString stringWithFormat:@", Track %d: Dolby Pro Logic II",ai + 1]];
-            if (job->audio_mixdowns[ai] == HB_AMIXDOWN_6CH)
-                jobAudioDetail = [jobAudioDetail stringByAppendingString:[NSString stringWithFormat:@", Track %d: 6-channel discreet",ai + 1]];
+            enable = NO;
+            [toolbarItem setImage:[NSImage imageNamed: @"Pause"]];
+            [toolbarItem setLabel: @"Pause"];
+            [toolbarItem setToolTip: @"Pause Encoding"];
         }
-        
-        /* Add the Audio detail string to the job filed in the window */
-        [aMutableString appendString:[NSString stringWithFormat: @"\n%@", jobAudioDetail]];
-        
-        /*Destination Field */
-        [aMutableString appendString:[NSString stringWithFormat:@"\nDestination: %@", [NSString stringWithUTF8String:job->file]]];
     }
-    
-    anAttributedString = [[[NSAttributedString alloc] initWithString:aMutableString attributes:highlighted ? detailHighlightedAttribute : detailAttribute] autorelease];
-    [finalString appendAttributedString:anAttributedString];
 
-            
-    return finalString;
+    return enable;
 }
 
+#pragma mark -
+
+
+#pragma mark Queue Item Controls
 //------------------------------------------------------------------------------------
-// Generate string to display in UI.
+// Delete encodes from the queue window and accompanying array
+// Also handling first cancelling the encode if in fact its currently encoding.
 //------------------------------------------------------------------------------------
-- (NSString *) progressStatusStringForJob: (hb_job_t *)job state: (hb_state_t *)s
+- (IBAction)removeSelectedQueueItem: (id)sender
 {
-    if (s->state == HB_STATE_WORKING)
+    NSIndexSet * selectedRows = [fOutlineView selectedRowIndexes];
+    NSUInteger row = [selectedRows firstIndex];
+    if( row == NSNotFound )
+        return;
+    /* if this is a currently encoding job, we need to be sure to alert the user,
+     * to let them decide to cancel it first, then if they do, we can come back and
+     * remove it */
+    
+    if ([[[fJobGroups objectAtIndex:row] objectForKey:@"Status"] integerValue] == 1)
     {
-        NSString * msg;
-        if (job->pass == -1)
-            msg = NSLocalizedString( @"Analyzing subtitles", 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;
-
+       /* We pause the encode here so that it doesn't finish right after and then
+        * screw up the sync while the window is open
+        */
+       [fHBController Pause:NULL];
+         NSString * alertTitle = [NSString stringWithFormat:NSLocalizedString(@"Stop This Encode and Remove It ?", nil)];
+        // Which window to attach the sheet to?
+        NSWindow * docWindow = nil;
+        if ([sender respondsToSelector: @selector(window)])
+            docWindow = [sender window];
+        
+        
+        NSBeginCriticalAlertSheet(
+                                  alertTitle,
+                                  NSLocalizedString(@"Keep Encoding", nil),
+                                  nil,
+                                  NSLocalizedString(@"Stop Encoding and Delete", nil),
+                                  docWindow, self,
+                                  nil, @selector(didDimissCancelCurrentJob:returnCode:contextInfo:), nil,
+                                  NSLocalizedString(@"Your movie will be lost if you don't continue encoding.", nil));
+        
+        // didDimissCancelCurrentJob:returnCode:contextInfo: will be called when the dialog is dismissed
     }
+    else
+    { 
+    /* since we are not a currently encoding item, we can just be cancelled */
+            [fHBController removeQueueFileItem:row];
+    }
+}
 
-    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 );
+- (void) didDimissCancelCurrentJob: (NSWindow *)sheet returnCode: (int)returnCode contextInfo: (void *)contextInfo
+{
+    /* We resume encoding and perform the appropriate actions 
+     * Note: Pause: is a toggle type method based on hb's current
+     * state, if it paused, it will resume encoding and vice versa.
+     * In this case, we are paused from the calling window, so calling
+     * [fHBController Pause:NULL]; Again will resume encoding
+     */
+       [fHBController Pause:NULL];
+    if (returnCode == NSAlertOtherReturn)
+    {
+    /* We need to save the currently encoding item number first */
+    int encodingItemToRemove = fEncodingQueueItem;
+    /* Since we are encoding, we need to let fHBController Cancel this job
+     * upon which it will move to the next one if there is one
+     */
+    [fHBController doCancelCurrentJob];
+    /* Now, we can go ahead and remove the job we just cancelled since
+     * we have its item number from above
+     */
+    [fHBController removeQueueFileItem:encodingItemToRemove];
+    }
     
-    return @"";
 }
 
 //------------------------------------------------------------------------------------
-// Generate string to display in UI.
+// Show the finished encode in the finder
 //------------------------------------------------------------------------------------
-- (NSString *) progressTimeRemainingStringForJob: (hb_job_t *)job state: (hb_state_t *)s
+- (IBAction)revealSelectedQueueItem: (id)sender
 {
-    if (s->state == HB_STATE_WORKING)
+    NSIndexSet * selectedRows = [fOutlineView selectedRowIndexes];
+    NSInteger row = [selectedRows firstIndex];
+    if (row != NSNotFound)
     {
-        #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
+        while (row != NSNotFound)
         {
-            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];
-        }
+           NSMutableDictionary *queueItemToOpen = [fOutlineView itemAtRow: row];
+         [[NSWorkspace sharedWorkspace] selectFile:[queueItemToOpen objectForKey:@"DestinationPath"] inFileViewerRootedAtPath:nil];
 
-/* 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 );
+            row = [selectedRows indexGreaterThanIndex: row];
         }
-        else
-            return NSLocalizedString( @"Time remaining: Calculating...", nil );
-*/
-        #undef p
     }
-    
-    return @"";
 }
 
+
 //------------------------------------------------------------------------------------
-// Refresh progress bar (fProgressBar) from current state.
+// Starts or cancels the processing of jobs depending on the current state
 //------------------------------------------------------------------------------------
-- (void) updateProgressBarWithState: (hb_state_t *)s
+- (IBAction)toggleStartCancel: (id)sender
 {
-    if (s->state == HB_STATE_WORKING)
-    {
-        #define p s->param.working
-        [fProgressBar setIndeterminate:NO];
+    if (!fQueueEncodeLibhb) return;
 
-        float progress_total = fShowsJobsAsGroups ?
-                100.0 * ( p.progress + p.job_cur - 1 ) / p.job_count :
-                100.0 * p.progress;
+    hb_state_t s;
+    hb_get_state2 (fQueueEncodeLibhb, &s);
 
-        [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
-    }
+    if ((s.state == HB_STATE_PAUSED) || (s.state == HB_STATE_WORKING) || (s.state == HB_STATE_MUXING))
+        [fHBController Cancel: fQueuePane]; // sender == fQueuePane so that warning alert shows up on queue window
 
-    else if (s->state == HB_STATE_WORKDONE)
-    {
-        [fProgressBar setIndeterminate:NO];
-        [fProgressBar setDoubleValue:0.0];
-    }
+    else if (fPendingCount > 0)
+        [fHBController Rip: NULL];
 }
 
 //------------------------------------------------------------------------------------
-// Refresh queue count text field (fQueueCountField).
+// Toggles the pause/resume state of libhb
 //------------------------------------------------------------------------------------
-- (void)updateQueueCountField
+- (IBAction)togglePauseResume: (id)sender
 {
-    NSString * msg;
-    int jobCount;
+    if (!fQueueEncodeLibhb) return;
+    
+    hb_state_t s;
+    hb_get_state2 (fQueueEncodeLibhb, &s);
     
-    if (fShowsJobsAsGroups)
+    if (s.state == HB_STATE_PAUSED)
     {
-        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];
+        hb_resume (fQueueEncodeLibhb);
+        [self startAnimatingCurrentWorkingEncodeInQueue];
     }
-    else
+    else if ((s.state == HB_STATE_WORKING) || (s.state == HB_STATE_MUXING))
     {
-        jobCount = fHandle ? hb_count(fHandle) : 0;
-        if (jobCount == 1)
-            msg = NSLocalizedString(@"1 pending pass", nil);
-        else
-            msg = [NSString stringWithFormat:NSLocalizedString(@"%d pending passes", nil), jobCount];
-
+        hb_pause (fQueueEncodeLibhb);
+        [self stopAnimatingCurrentJobGroupInQueue];
     }
-
-    [fQueueCountField setStringValue:msg];
 }
 
-//------------------------------------------------------------------------------------
-// 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)updateCurrentJobUI
-{
-    hb_state_t s;
-    hb_job_t * job = nil;
-    
-    if (fHandle)
-    {
-        hb_get_state2( fHandle, &s );
-        job = hb_current_job(fHandle);
-    }
+#pragma mark -
+
+
+#pragma mark Animate Endcoding Item
 
-    if (job)
-    {
-        [fJobDescTextField setAttributedStringValue:[self attributedDescriptionForJob:job withTitle:YES withDetail:YES withHighlighting:NO]];
 
-        [self showCurrentJobPane:YES];
-        [fJobIconView setImage: fShowsJobsAsGroups ? [NSImage imageNamed:@"JobLarge"] : [self largeImageForPass: job->pass] ];
-        
-        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];
-        [self updateProgressBarWithState:&s];
-    }
-    else
-    {
-        [fJobDescTextField setStringValue:NSLocalizedString(@"No job processing", nil)];
 
-        [self showCurrentJobPane:NO];
-        [fProgressBar stopAnimation:nil];    // just in case in was animating
-    }
-}
 
 //------------------------------------------------------------------------------------
-// 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.
+// Starts animating the job icon of the currently processing job in the queue outline
+// view.
 //------------------------------------------------------------------------------------
-- (void)updateQueueUI
+- (void) startAnimatingCurrentWorkingEncodeInQueue
 {
-#if HB_OUTLINE_QUEUE
-    [self rebuildEncodes];
-    [fOutlineView noteNumberOfRowsChanged];
-    [fOutlineView reloadData];
-#endif
-    [fTaskView noteNumberOfRowsChanged];
-    [fTaskView reloadData];
-    
-    [self updateQueueCountField];
+    if (!fAnimationTimer)
+        fAnimationTimer = [[NSTimer scheduledTimerWithTimeInterval:1.0/12.0     // 1/12 because there are 6 images in the animation cycle
+                target:self
+                selector:@selector(animateWorkingEncodeInQueue:)
+                userInfo:nil
+                repeats:YES] retain];
 }
 
 //------------------------------------------------------------------------------------
-// Deletes the selected job from HB and the queue UI
+// If a job is currently processing, its job icon in the queue outline view is
+// animated to its next state.
 //------------------------------------------------------------------------------------
-- (IBAction)removeSelectedJob: (id)sender
+- (void) animateWorkingEncodeInQueue:(NSTimer*)theTimer
 {
-    if (!fHandle) return;
-    
-    int row = [sender selectedRow];
-    if (row != -1)
+    if (fWorkingCount > 0)
     {
-#if HB_UNI_QUEUE
-        if (row == 0)
-        {
-            [self cancelCurrentJob:sender];
-        }
-        else
-        {
-            row--;
-            if (fShowsJobsAsGroups)
-                hb_rem_group( fHandle, hb_group( fHandle, row ) );
-            else
-                hb_rem( fHandle, hb_job( fHandle, row ) );
-        }
-#else
-        if (fShowsJobsAsGroups)
-            hb_rem_group( fHandle, hb_group( fHandle, row ) );
-        else
-            hb_rem( fHandle, hb_job( fHandle, row ) );
-#endif
-        [self updateQueueUI];
+        fAnimationIndex++;
+        fAnimationIndex %= 6;   // there are 6 animation images; see outlineView:objectValueForTableColumn:byItem: below.
+        [self animateWorkingEncodeIconInQueue];
     }
 }
 
-//------------------------------------------------------------------------------------
-// Prompts user if the want to cancel encoding of current job. If so, doCancelCurrentJob
-// gets called.
-//------------------------------------------------------------------------------------
-- (IBAction)cancelCurrentJob: (id)sender
-{
-    [fHBController Cancel:sender];
-}
 
-//------------------------------------------------------------------------------------
-// Turns on the display of detail information for each job. Does nothing if detail is
-// already turned on.
-//------------------------------------------------------------------------------------
-- (IBAction)showDetail: (id)sender
+- (void) animateWorkingEncodeIconInQueue
 {
-    if (!fShowsDetail)
-        [self setShowsDetail:YES];
+    NSInteger row = fEncodingQueueItem; /// need to set to fEncodingQueueItem
+    NSInteger col = [fOutlineView columnWithIdentifier: @"icon"];
+    if (row != -1 && col != -1)
+    {
+        NSRect frame = [fOutlineView frameOfCellAtColumn:col row:row];
+        [fOutlineView setNeedsDisplayInRect: frame];
+    }
 }
 
 //------------------------------------------------------------------------------------
-// Turns off the display of detail information for each job. Does nothing if detail is
-// already turned off.
+// Stops animating the job icon of the currently processing job in the queue outline
+// view.
 //------------------------------------------------------------------------------------
-- (IBAction)hideDetail: (id)sender
+- (void) stopAnimatingCurrentJobGroupInQueue
 {
-    if (fShowsDetail)
-        [self setShowsDetail:NO];
+    if (fAnimationTimer && [fAnimationTimer isValid])
+    {
+        [fAnimationTimer invalidate];
+        [fAnimationTimer release];
+        fAnimationTimer = nil;
+    }
 }
 
-//------------------------------------------------------------------------------------
-// Turns on displaying of jobs as groups by calling setShowsJobsAsGroups:YES. Does
-// nothing if groups are already turned on. 
-//------------------------------------------------------------------------------------
-- (IBAction)showJobsAsGroups: (id)sender
-{
-    if (!fShowsJobsAsGroups)
-        [self setShowsJobsAsGroups:YES];
-}
 
-//------------------------------------------------------------------------------------
-// Turns on displaying of jobs as individual items by calling setShowsJobsAsGroups:NO.
-// Does nothing if groups are already turned off. 
-//------------------------------------------------------------------------------------
-- (IBAction)showJobsAsPasses: (id)sender
-{
-    if (fShowsJobsAsGroups)
-        [self setShowsJobsAsGroups:NO];
-}
+#pragma mark -
 
-//------------------------------------------------------------------------------------
-// Toggles the processing of jobs on or off depending on the current state
-//------------------------------------------------------------------------------------
-- (IBAction)toggleStartPause: (id)sender
+- (void)moveObjectsInArray:(NSMutableArray *)array fromIndexes:(NSIndexSet *)indexSet toIndex:(NSUInteger)insertIndex
 {
-    if (!fHandle) return;
-    
-    hb_state_t s;
-    hb_get_state2 (fHandle, &s);
+    NSUInteger index = [indexSet lastIndex];
+    NSUInteger aboveInsertIndexCount = 0;
 
-    if (s.state == HB_STATE_PAUSED)
-        hb_resume (fHandle);
-    else if ((s.state == HB_STATE_WORKING) || (s.state == HB_STATE_MUXING))
-        hb_pause (fHandle);
-    else
+    while (index != NSNotFound)
     {
-        if (fShowsJobsAsGroups)
+        NSUInteger removeIndex;
+
+        if (index >= insertIndex)
+        {
+            removeIndex = index + aboveInsertIndexCount;
+            aboveInsertIndexCount++;
+        }
+        else
         {
-            if (hb_group_count(fHandle) > 0)
-                [fHBController doRip];
+            removeIndex = index;
+            insertIndex--;
         }
-        else if (hb_count(fHandle) > 0)
-            [fHBController doRip];
-    }    
+
+        id object = [[array objectAtIndex:removeIndex] retain];
+        [array removeObjectAtIndex:removeIndex];
+        [array insertObject:object atIndex:insertIndex];
+        [object release];
+
+        index = [indexSet indexLessThanIndex:index];
+    }
 }
 
+
 #pragma mark -
-#pragma mark Toolbar
+#pragma mark NSOutlineView delegate
 
-//------------------------------------------------------------------------------------
-// setupToolbar
-//------------------------------------------------------------------------------------
-- (void)setupToolbar
-{
-    // Create a new toolbar instance, and attach it to our window 
-    NSToolbar *toolbar = [[[NSToolbar alloc] initWithIdentifier: HBQueueToolbar] autorelease];
-    
-    // Set up toolbar properties: Allow customization, give a default display mode, and remember state in user defaults 
-    [toolbar setAllowsUserCustomization: YES];
-    [toolbar setAutosavesConfiguration: YES];
-    [toolbar setDisplayMode: NSToolbarDisplayModeIconAndLabel];
-    
-    // We are the delegate
-    [toolbar setDelegate: self];
-    
-    // Attach the toolbar to our window 
-    [fQueueWindow setToolbar: toolbar];
-}
 
-//------------------------------------------------------------------------------------
-// toolbar:itemForItemIdentifier:willBeInsertedIntoToolbar:
-//------------------------------------------------------------------------------------
-- (NSToolbarItem *)toolbar:(NSToolbar *)toolbar
-        itemForItemIdentifier:(NSString *)itemIdentifier
-        willBeInsertedIntoToolbar:(BOOL)flag
+- (id)outlineView:(NSOutlineView *)fOutlineView child:(NSInteger)index ofItem:(id)item
 {
-    // Required delegate method: Given an item identifier, this method returns an item.
-    // The toolbar will use this method to obtain toolbar items that can be displayed
-    // in the customization sheet, or in the toolbar itself.
-    
-    NSToolbarItem *toolbarItem = nil;
-    
-    if ([itemIdentifier isEqual: HBStartPauseResumeToolbarIdentifier])
-    {
-        toolbarItem = [[[NSToolbarItem alloc] initWithItemIdentifier: itemIdentifier] autorelease];
-               
-        // Set the text label to be displayed in the toolbar and customization palette 
-               [toolbarItem setLabel: @"Start"];
-               [toolbarItem setPaletteLabel: @"Start/Pause"];
-               
-               // Set up a reasonable tooltip, and image
-               [toolbarItem setToolTip: @"Start Encoding"];
-               [toolbarItem setImage: [NSImage imageNamed: @"Play"]];
-               
-               // Tell the item what message to send when it is clicked 
-               [toolbarItem setTarget: self];
-               [toolbarItem setAction: @selector(toggleStartPause:)];
-       }
-    
-    else if ([itemIdentifier isEqual: HBShowDetailToolbarIdentifier])
-    {
-        toolbarItem = [[[NSToolbarItem alloc] initWithItemIdentifier: itemIdentifier] autorelease];
-               
-        // Set the text label to be displayed in the toolbar and customization palette 
-               [toolbarItem setLabel: @"Detail"];
-               [toolbarItem setPaletteLabel: @"Detail"];
-               
-               // Set up a reasonable tooltip, and image
-               [toolbarItem setToolTip: @"Displays detailed information in the queue"];
-               [toolbarItem setImage: [NSImage imageNamed: @"Detail"]];
-               
-               // Tell the item what message to send when it is clicked 
-               [toolbarItem setTarget: self];
-               [toolbarItem setAction: fShowsDetail ? @selector(hideDetail:) : @selector(showDetail:)];
-       }
-    
-    else if ([itemIdentifier isEqual: HBShowGroupsToolbarIdentifier])
-    {
-        toolbarItem = [[[NSToolbarItem alloc] initWithItemIdentifier: itemIdentifier] autorelease];
-               
-/*
-        // Set the text label to be displayed in the toolbar and customization palette 
-               [toolbarItem setLabel: @"Passes"];
-               [toolbarItem setPaletteLabel: @"Passes"];
-               
-               // Set up a reasonable tooltip, and image
-               [toolbarItem setToolTip: @"Displays individual passes in the queue"];
-               [toolbarItem setImage: [NSImage imageNamed: @"Passes"]];
-        
-               // Tell the item what message to send when it is clicked 
-               [toolbarItem setTarget: self];
-               [toolbarItem setAction: fShowsJobsAsGroups ? @selector(showJobsAsPasses:) : @selector(showJobsAsGroups:)];
-*/
-  
-// Various attempts at other button types in the toolbar. A matrix worked fine to display
-// a button for encodes & passes, but ultimately I decided to go with a single button
-// called "Passes" that toggles on or off. All these suffer from the fact taht you need
-// to override NSToolbarItem for them in order to validate their state.
-               [toolbarItem setLabel: @"View"];
-               [toolbarItem setPaletteLabel: @"View"];
-
-        NSButtonCell * buttonCell = [[[NSButtonCell alloc] initImageCell:nil] autorelease];
-        [buttonCell setBezelStyle:NSShadowlessSquareBezelStyle];
-        [buttonCell setButtonType:NSToggleButton];
-        [buttonCell setBordered:NO];
-        [buttonCell setImagePosition:NSImageOnly];
-
-        NSMatrix * matrix = [[[NSMatrix alloc] initWithFrame:NSMakeRect(0,0,54,25)
-                mode:NSRadioModeMatrix
-                prototype:buttonCell
-                numberOfRows:1
-                numberOfColumns:2] autorelease];
-        [matrix setCellSize:NSMakeSize(27, 25)];
-        [matrix setIntercellSpacing:NSMakeSize(0, 0)];
-        [matrix selectCellAtRow:0 column:(fShowsJobsAsGroups ? 0 : 1)];
-
-        buttonCell = [matrix cellAtRow:0 column:0];
-        [buttonCell setTitle:@""];
-        [buttonCell setImage:[NSImage imageNamed: @"Encodes"]];
-        [buttonCell setAlternateImage:[NSImage imageNamed: @"EncodesPressed"]];
-               [buttonCell setAction: @selector(showJobsAsGroups:)];
-               [matrix setToolTip: @"Displays encodes in the queue" forCell:buttonCell];
-
-        buttonCell = [matrix cellAtRow:0 column:1];
-        [buttonCell setTitle:@""];
-        [buttonCell setImage:[NSImage imageNamed: @"Passes"]];
-        [buttonCell setAlternateImage:[NSImage imageNamed: @"PassesPressed"]];
-               [buttonCell setAction: @selector(showJobsAsPasses:)];
-               [matrix setToolTip: @"Displays individual passes in the queue" forCell:buttonCell];
-
-        [toolbarItem setMinSize: [matrix frame].size];
-        [toolbarItem setMaxSize: [matrix frame].size];
-               [toolbarItem setView: matrix];
-
-/*
-        NSSegmentedControl * segControl = [[[NSSegmentedControl alloc] initWithFrame:NSMakeRect(0,0,20,20)] autorelease];
-        [[segControl cell] setControlSize:NSSmallControlSize];
-        [segControl setSegmentCount:2];
-        [segControl setLabel:@"Encodes" forSegment:0];
-        [segControl setLabel:@"Passes" forSegment:1];
-        [segControl setImage:[NSImage imageNamed:@"Delete"] forSegment:0];
-        [segControl setImage:[NSImage imageNamed:@"Delete"] forSegment:1];
-        [segControl setSelectedSegment: (fShowsJobsAsGroups ? 0 : 1)];
-        [segControl sizeToFit];
-        [toolbarItem setMinSize: [segControl frame].size];
-        [toolbarItem setMaxSize: [segControl frame].size];
-               [toolbarItem setView: segControl];
-*/
+    if (item == nil)
+        return [fJobGroups objectAtIndex:index];
 
-/*
-        NSButton * button = [[[NSButton alloc] initWithFrame:NSMakeRect(0,0,32,32)] autorelease];
-        [button setButtonType:NSSwitchButton];
-        [button setTitle:@""];
-        [button setState: fShowsJobsAsGroups ? NSOnState : NSOffState];
-        [toolbarItem setMinSize: NSMakeSize(20,20)];
-        [toolbarItem setMaxSize: NSMakeSize(20,20)];
-               [toolbarItem setView: button];
-               
-               // Tell the item what message to send when it is clicked 
-               [toolbarItem setTarget: self];
-               [toolbarItem setAction: @selector(jobGroupsChanged:)];
-*/
-       }
-    
-    return toolbarItem;
+    // We are only one level deep, so we can't be asked about children
+    NSAssert (NO, @"HBQueueController outlineView:child:ofItem: can't handle nested items.");
+    return nil;
 }
 
-//------------------------------------------------------------------------------------
-// toolbarDefaultItemIdentifiers:
-//------------------------------------------------------------------------------------
-- (NSArray *) toolbarDefaultItemIdentifiers: (NSToolbar *) toolbar
+- (BOOL)outlineView:(NSOutlineView *)fOutlineView isItemExpandable:(id)item
 {
-    // Required delegate method: Returns the ordered list of items to be shown in the
-    // toolbar by default.
-    
-    return [NSArray arrayWithObjects:
-        HBStartPauseResumeToolbarIdentifier,
-               NSToolbarSeparatorItemIdentifier,
-               HBShowGroupsToolbarIdentifier,
-        HBShowDetailToolbarIdentifier,
-        nil];
+    // Our outline view has no levels, but we can still expand every item. Doing so
+    // just makes the row taller. See heightOfRowByItem below.
+    return YES;
 }
 
-//------------------------------------------------------------------------------------
-// toolbarAllowedItemIdentifiers:
-//------------------------------------------------------------------------------------
-- (NSArray *) toolbarAllowedItemIdentifiers: (NSToolbar *) toolbar
+- (BOOL)outlineView:(NSOutlineView *)outlineView shouldExpandItem:(id)item
 {
-    // Required delegate method: Returns the list of all allowed items by identifier.
-    // By default, the toolbar does not assume any items are allowed, even the
-    // separator. So, every allowed item must be explicitly listed.
-
-    return [NSArray arrayWithObjects:
-        HBStartPauseResumeToolbarIdentifier,
-               HBShowGroupsToolbarIdentifier,
-        HBShowDetailToolbarIdentifier,
-               NSToolbarCustomizeToolbarItemIdentifier,
-               NSToolbarFlexibleSpaceItemIdentifier,
-        NSToolbarSpaceItemIdentifier,
-               NSToolbarSeparatorItemIdentifier,
-        nil];
+    // Our outline view has no levels, but we can still expand every item. Doing so
+    // just makes the row taller. See heightOfRowByItem below.
+return ![(HBQueueOutlineView*)outlineView isDragging];
 }
 
-//------------------------------------------------------------------------------------
-// validateToolbarItem:
-//------------------------------------------------------------------------------------
-- (BOOL) validateToolbarItem: (NSToolbarItem *) toolbarItem
+- (NSInteger)outlineView:(NSOutlineView *)fOutlineView numberOfChildrenOfItem:(id)item
 {
-    // Optional method: This message is sent to us since we are the target of some
-    // toolbar item actions.
-
-    if (!fHandle) return NO;
+    // Our outline view has no levels, so number of children will be zero for all
+    // top-level items.
+    if (item == nil)
+        return [fJobGroups count];
+    else
+        return 0;
+}
 
-    BOOL enable = NO;
+- (void)outlineViewItemDidCollapse:(NSNotification *)notification
+{
+    id item = [[notification userInfo] objectForKey:@"NSObject"];
+    NSInteger row = [fOutlineView rowForItem:item];
+    [fOutlineView noteHeightOfRowsWithIndexesChanged:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(row,1)]];
+}
 
-    hb_state_t s;
-    hb_get_state2 (fHandle, &s);
+- (void)outlineViewItemDidExpand:(NSNotification *)notification
+{
+    id item = [[notification userInfo] objectForKey:@"NSObject"];
+    NSInteger row = [fOutlineView rowForItem:item];
+    [fOutlineView noteHeightOfRowsWithIndexesChanged:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(row,1)]];
+}
 
-    if ([[toolbarItem itemIdentifier] isEqual: HBStartPauseResumeToolbarIdentifier])
+- (CGFloat)outlineView:(NSOutlineView *)outlineView heightOfRowByItem:(id)item
+{
+    if ([outlineView isItemExpanded: item])
     {
-        if (s.state == HB_STATE_PAUSED)
+        /* Below is the original code to accommodate a live resize,
+         * however as stated in travistex's comments it's very buggy.
+         * For now I will leave it here ... commented out and use
+         * the code below to determine the row height based on each
+         * encodes optional parameters and how they are displayed. */
+        
+        // Short-circuit here if in a live resize primarily to fix a bug but also to
+        // increase resposivness during a resize. There's a bug in NSTableView that
+        // causes row heights to get messed up if you try to change them during a live
+        // resize. So if in a live resize, simply return the previously calculated
+        // height. The row heights will get fixed up after the resize because we have
+        // implemented viewDidEndLiveResize to force all of them to be recalculated.
+        // if ([outlineView inLiveResize] && [item lastDescriptionHeight] > 0)
+        //   return [item lastDescriptionHeight];
+        
+        // CGFloat width = [[outlineView tableColumnWithIdentifier: @"desc"] width];
+        // Column width is NOT what is ultimately used. I can't quite figure out what
+        // width to use for calculating text metrics. No matter how I tweak this value,
+        // there are a few conditions in which the drawn text extends below the bounds
+        // of the row cell. In previous versions, which ran under Tiger, I was
+        // reducing width by 47 pixles.
+        // width -= 2;     // (?) for intercell spacing
+        
+        // CGFloat height = [item heightOfDescriptionForWidth: width];
+        // return height;
+        
+        /* So, we know several rows of text that are in all queue items for display.
+         * These are the title line, Preset, Format, Destination, Picture, and Video Lines
+         */
+        CGFloat rowHeightNonTitle = 15.0;
+        /* Add the title line height, then the non title line height for Preset, Format, Destination
+         * Picture and Video
+         */
+        CGFloat itemHeightForDisplay = HB_ROW_HEIGHT_TITLE_ONLY + (rowHeightNonTitle * 5);
+        
+        /* get our item row number so we an use it to calc how many lines we have to display based
+         * on MP4 Options, Filter Options, X264 Options, Audio Tracks and Subtitles from our queue array */
+        int itemRowNum = [outlineView rowForItem: item];
+        NSMutableDictionary *queueItemToCheck = [outlineView itemAtRow: itemRowNum];
+        
+        /* Check to see if we need to allow for mp4 opts */
+        BOOL mp4OptsPresent = NO;
+        if ([[queueItemToCheck objectForKey:@"FileFormat"] isEqualToString: @"MP4 file"])
         {
-            enable = YES;
-            [toolbarItem setImage:[NSImage imageNamed: @"Play"]];
-                       [toolbarItem setLabel: @"Resume"];
-                       [toolbarItem setPaletteLabel: @"Resume"];
-                       [toolbarItem setToolTip: @"Resume Encoding"];
-       }
+            
+            if( [[queueItemToCheck objectForKey:@"Mp4LargeFile"] intValue] == 1)
+            {
+                mp4OptsPresent = YES;
+            }
+            if( [[queueItemToCheck objectForKey:@"Mp4HttpOptimize"] intValue] == 1)
+            {
+                mp4OptsPresent = YES;
+            }
+            if( [[queueItemToCheck objectForKey:@"Mp4iPodCompatible"] intValue] == 1)
+            {
+                mp4OptsPresent = YES;
+            }
+        }
         
-        else if ((s.state == HB_STATE_WORKING) || (s.state == HB_STATE_MUXING))
+        if (mp4OptsPresent == YES)
         {
-            enable = YES;
-            [toolbarItem setImage:[NSImage imageNamed: @"Pause"]];
-                       [toolbarItem setLabel: @"Pause"];
-                       [toolbarItem setPaletteLabel: @"Pause"];
-                       [toolbarItem setToolTip: @"Pause Encoding"];
+            itemHeightForDisplay +=  rowHeightNonTitle;   
         }
-
-        else if (hb_count(fHandle) > 0)
+        
+        /* check to see if we need to allow for the Picture Filters row */
+        BOOL pictureFiltersPresent = NO;
+        if( [[queueItemToCheck objectForKey:@"PictureDetelecine"] intValue] > 0)
         {
-            enable = YES;
-            [toolbarItem setImage:[NSImage imageNamed: @"Play"]];
-                       [toolbarItem setLabel: @"Start"];
-                       [toolbarItem setPaletteLabel: @"Start"];
-                       [toolbarItem setToolTip: @"Start Encoding"];
+            pictureFiltersPresent = YES;
         }
-
-        else
+        if( [[queueItemToCheck objectForKey:@"PictureDecomb"] intValue] > 0)
         {
-            enable = NO;
-            [toolbarItem setImage:[NSImage imageNamed: @"Play"]];
-                       [toolbarItem setLabel: @"Start"];
-                       [toolbarItem setPaletteLabel: @"Start"];
-                       [toolbarItem setToolTip: @"Start Encoding"];
+            pictureFiltersPresent = YES;
         }
-       }
-    
-    else if ([[toolbarItem itemIdentifier] isEqual: HBShowGroupsToolbarIdentifier])
-    {
-        enable = hb_count(fHandle) > 0;
-               [toolbarItem setAction: fShowsJobsAsGroups ? @selector(showJobsAsPasses:) : @selector(showJobsAsGroups:)];
-        if (fShowsJobsAsGroups)
+        if( [[queueItemToCheck objectForKey:@"PictureDeinterlace"] intValue] > 0)
         {
-            [toolbarItem setImage: [NSImage imageNamed: @"Passes"]];
-            [toolbarItem setToolTip: @"Displays individual passes in the queue"];
+            pictureFiltersPresent = YES;
         }
-        else
+        if( [[queueItemToCheck objectForKey:@"PictureDenoise"] intValue] > 0)
         {
-            [toolbarItem setImage: [NSImage imageNamed: @"PassesPressed"]];
-            [toolbarItem setToolTip: @"Displays encodes in the queue"];
+            pictureFiltersPresent = YES;
         }
-    }
-    
-    else if ([[toolbarItem itemIdentifier] isEqual: HBShowDetailToolbarIdentifier])
-    {
-        enable = hb_count(fHandle) > 0;
-               [toolbarItem setAction: fShowsDetail ? @selector(hideDetail:) : @selector(showDetail:)];
-        if (fShowsDetail)
+        if( [[queueItemToCheck objectForKey:@"PictureDeblock"] intValue] > 0)
         {
-            [toolbarItem setImage: [NSImage imageNamed: @"DetailPressed"]];
-            [toolbarItem setToolTip: @"Hides detailed information in the queue"];
+            pictureFiltersPresent = YES;
         }
-        else
+        if( [[queueItemToCheck objectForKey:@"VideoGrayScale"] intValue] > 0)
+        {
+            pictureFiltersPresent = YES;
+        }
+        
+        if (pictureFiltersPresent == YES)
+        {
+            itemHeightForDisplay +=  rowHeightNonTitle;
+        }
+        
+        /* check to see if we need a line to display x264 options */
+        if ([[queueItemToCheck objectForKey:@"VideoEncoder"] isEqualToString: @"H.264 (x264)"])
         {
-            [toolbarItem setImage: [NSImage imageNamed: @"Detail"]];
-            [toolbarItem setToolTip: @"Displays detailed information in the queue"];
+            itemHeightForDisplay +=  rowHeightNonTitle;
         }
+        
+        /* check to see how many audio track lines to allow for */
+        if ([[queueItemToCheck objectForKey:@"Audio1Track"] intValue] > 0)
+        {
+            itemHeightForDisplay +=  rowHeightNonTitle; 
+        }
+        if ([[queueItemToCheck objectForKey:@"Audio2Track"] intValue] > 0)
+        {
+            itemHeightForDisplay +=  rowHeightNonTitle; 
+        }
+        if ([[queueItemToCheck objectForKey:@"Audio3Track"] intValue] > 0)
+        {
+            itemHeightForDisplay +=  rowHeightNonTitle; 
+        }
+        if ([[queueItemToCheck objectForKey:@"Audio4Track"] intValue] > 0)
+        {
+            itemHeightForDisplay +=  rowHeightNonTitle; 
+        }
+        
+        /* add in subtitle lines for each subtitle in the SubtitleList array */
+        itemHeightForDisplay +=  rowHeightNonTitle * [[queueItemToCheck objectForKey:@"SubtitleList"] count];
+        
+        return itemHeightForDisplay;
+        
+    }
+    else
+    {
+        return HB_ROW_HEIGHT_TITLE_ONLY;
     }
-
-       return enable;
 }
 
-#pragma mark -
-
-//------------------------------------------------------------------------------------
-// awakeFromNib
-//------------------------------------------------------------------------------------
-- (void)awakeFromNib
-{
-    [self setupToolbar];
-    
-    if (![fQueueWindow setFrameUsingName:@"Queue"])
-        [fQueueWindow center];
-    [fQueueWindow setFrameAutosaveName: @"Queue"];
-    [fQueueWindow setExcludedFromWindowsMenu:YES];
-    
-    // Show/hide UI elements
-    [self setShowsDetail:fShowsDetail];
-    [self setShowsJobsAsGroups:fShowsJobsAsGroups];
-    [self showCurrentJobPane:NO];
-
-#if HB_QUEUE_DRAGGING
-    [fTaskView registerForDraggedTypes: [NSArray arrayWithObject:HBQueueDataType] ];
-#endif
-
-#if HB_OUTLINE_QUEUE
-    // Don't allow autoresizing of main column, else the "delete" column will get
-    // pushed out of view.
-    [fOutlineView setAutoresizesOutlineColumn: NO];
-#endif
-}
-
-
-//------------------------------------------------------------------------------------
-// windowWillClose
-//------------------------------------------------------------------------------------
-- (void)windowWillClose:(NSNotification *)aNotification
+- (CGFloat) heightOfDescriptionForWidth:(CGFloat)width
 {
-    [[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"QueueWindowIsOpen"];
+    // Try to return the cached value if no changes have happened since the last time
+    //if ((width == fLastDescriptionWidth) && (fLastDescriptionHeight != 0) && !fNeedsDescription)
+       // return fLastDescriptionHeight;
+
+    //if (fNeedsDescription)
+    //    [self updateDescription];
+
+    // Calculate the height
+    //NSRect bounds = [fDescription boundingRectWithSize:NSMakeSize(width, 10000) options:NSStringDrawingUsesLineFragmentOrigin];
+    //fLastDescriptionHeight = bounds.size.height + 6.0; // add some border to bottom
+    //fLastDescriptionWidth = width;
+    return HB_ROW_HEIGHT_FULL_DESCRIPTION;
+
+/* 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;
+*/
 }
 
-#pragma mark -
-#pragma mark NSTableView delegate
-
-//------------------------------------------------------------------------------------
-// NSTableView delegate
-//------------------------------------------------------------------------------------
-- (int)numberOfRowsInTableView: (NSTableView *)aTableView
+- (CGFloat) lastDescriptionHeight
 {
-#if HB_UNI_QUEUE
-    int numItems = hb_current_job(fHandle) ? 1 : 0;
-    if (fShowsJobsAsGroups)
-        return numItems + hb_group_count(fHandle);
-    else
-        return numItems + hb_count(fHandle);
-#else
-    if (fShowsJobsAsGroups)
-        return hb_group_count(fHandle);
-    else
-        return hb_count(fHandle);
-#endif
+    return HB_ROW_HEIGHT_FULL_DESCRIPTION;
 }
 
-//------------------------------------------------------------------------------------
-// NSTableView delegate
-//------------------------------------------------------------------------------------
-- (id)tableView: (NSTableView *)aTableView
-      objectValueForTableColumn: (NSTableColumn *)aTableColumn
-                            row: (int)rowIndex
+- (id)outlineView:(NSOutlineView *)fOutlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item
 {
-    if (!fHandle)
-        return @"";    // fatal error!
-        
-    hb_job_t * job = nil;
-
-#if HB_UNI_QUEUE
-    // Looking for the current job?
-    int jobIndex = rowIndex;
-    if (hb_current_job(fHandle))
+    // nb: The "desc" column is currently an HBImageAndTextCell. However, we are longer
+    // using the image portion of the cell so we could switch back to a regular NSTextFieldCell.
+    
+    if ([[tableColumn identifier] isEqualToString:@"desc"])
     {
-        if (rowIndex == 0)
-            job = hb_current_job(fHandle);
+        /* This should have caused the description we wanted to show*/
+        //return [item objectForKey:@"SourceName"];
+        
+        /* code to build the description as per old queue */
+        //return [self formatEncodeItemDescription:item];
+        
+        /* Below should be put into a separate method but I am way too f'ing lazy right now */
+        NSMutableAttributedString * finalString = [[[NSMutableAttributedString alloc] initWithString: @""] autorelease];
+        // Attributes
+        NSMutableParagraphStyle * ps = [[[NSParagraphStyle defaultParagraphStyle] mutableCopy] retain];
+        [ps setHeadIndent: 40.0];
+        [ps setParagraphSpacing: 1.0];
+        [ps setTabStops:[NSArray array]];    // clear all tabs
+        [ps addTabStop: [[[NSTextTab alloc] initWithType: NSLeftTabStopType location: 20.0] autorelease]];
+        
+        
+        NSDictionary* detailAttr = [NSDictionary dictionaryWithObjectsAndKeys:
+                                    [NSFont systemFontOfSize:10.0], NSFontAttributeName,
+                                    ps, NSParagraphStyleAttributeName,
+                                    nil];
+        
+        NSDictionary* detailBoldAttr = [NSDictionary dictionaryWithObjectsAndKeys:
+                                        [NSFont boldSystemFontOfSize:10.0], NSFontAttributeName,
+                                        ps, NSParagraphStyleAttributeName,
+                                        nil];
+        
+        NSDictionary* titleAttr = [NSDictionary dictionaryWithObjectsAndKeys:
+                                   [NSFont systemFontOfSize:[NSFont systemFontSize]], NSFontAttributeName,
+                                   ps, NSParagraphStyleAttributeName,
+                                   nil];
+        
+        NSDictionary* shortHeightAttr = [NSDictionary dictionaryWithObjectsAndKeys:
+                                         [NSFont systemFontOfSize:2.0], NSFontAttributeName,
+                                         nil];
+        
+        /* First line, we should strip the destination path and just show the file name and add the title num and chapters (if any) */
+        //finalDescription = [finalDescription stringByAppendingString:[NSString stringWithFormat:@"Source: %@ Output: %@\n", [item objectForKey:@"SourceName"],[item objectForKey:@"DestinationPath"]]];
+        NSString * summaryInfo;
+        
+        NSString * titleString = [NSString stringWithFormat:@"Title %d", [[item objectForKey:@"TitleNumber"] intValue]];
+        
+        NSString * chapterString = ([[item objectForKey:@"ChapterStart"] intValue] == [[item objectForKey:@"ChapterEnd"] intValue]) ?
+        [NSString stringWithFormat:@"Chapter %d", [[item objectForKey:@"ChapterStart"] intValue]] :
+        [NSString stringWithFormat:@"Chapters %d through %d", [[item objectForKey:@"ChapterStart"] intValue], [[item objectForKey:@"ChapterEnd"] intValue]];
+        
+        NSString * passesString;
+        if ([[item objectForKey:@"VideoTwoPass"] intValue] == 0)
+        {
+            passesString = [NSString stringWithFormat:@"1 Video Pass"];
+        }
+        else
+        {
+            if ([[item objectForKey:@"VideoTurboTwoPass"] intValue] == 1)
+            {
+                passesString = [NSString stringWithFormat:@"2 Video Passes Turbo"];
+            }
+            else
+            {
+                passesString = [NSString stringWithFormat:@"2 Video Passes"];
+            }
+        }
+        
+        [finalString appendString:[NSString stringWithFormat:@"%@", [item objectForKey:@"SourceName"]] withAttributes:titleAttr];
+        
+        /* lets add the output file name to the title string here */
+        NSString * outputFilenameString = [[item objectForKey:@"DestinationPath"] lastPathComponent];
+        
+        summaryInfo = [NSString stringWithFormat: @" (%@, %@, %@) -> %@", titleString, chapterString, passesString, outputFilenameString];
+        
+        [finalString appendString:[NSString stringWithFormat:@"%@\n", summaryInfo] withAttributes:detailAttr];  
+        
+        // Insert a short-in-height line to put some white space after the title
+        [finalString appendString:@"\n" withAttributes:shortHeightAttr];
+        // End of Title Stuff
+        
+        /* Second Line  (Preset Name)*/
+        [finalString appendString: @"Preset: " withAttributes:detailBoldAttr];
+        [finalString appendString:[NSString stringWithFormat:@"%@\n", [item objectForKey:@"PresetName"]] withAttributes:detailAttr];
+        
+        /* Third Line  (Format Summary) */
+        NSString * audioCodecSummary = @"";
+        /* Lets also get our audio track detail since we are going through the logic for use later */
+        NSString * audioDetail1 = @"";
+        NSString * audioDetail2 = @"";
+        NSString * audioDetail3 = @"";
+        NSString * audioDetail4 = @"";
+        if ([[item objectForKey:@"Audio1Track"] intValue] > 0)
+        {
+            audioCodecSummary = [NSString stringWithFormat:@"%@", [item objectForKey:@"Audio1Encoder"]];
+            audioDetail1 = [NSString stringWithFormat:@"%@ Encoder: %@ Mixdown: %@ SampleRate: %@(khz) Bitrate: %@(kbps)",
+                            [item objectForKey:@"Audio1TrackDescription"] ,
+                            [item objectForKey:@"Audio1Encoder"],
+                            [item objectForKey:@"Audio1Mixdown"] ,
+                            [item objectForKey:@"Audio1Samplerate"],
+                            [item objectForKey:@"Audio1Bitrate"]];
+            
+            if ([[item objectForKey:@"Audio1TrackDRCSlider"] floatValue] > 1.00)
+            {
+                audioDetail1 = [NSString stringWithFormat:@"%@, DRC: %@",audioDetail1,[item objectForKey:@"Audio1TrackDRCSlider"]];
+            }
+            else
+            {
+                audioDetail1 = [NSString stringWithFormat:@"%@, DRC: Off",audioDetail1];
+            }
+        }
+        
+        if ([[item objectForKey:@"Audio2Track"] intValue] > 0)
+        {
+            audioCodecSummary = [NSString stringWithFormat:@"%@, %@",audioCodecSummary ,[item objectForKey:@"Audio2Encoder"]];
+            audioDetail2 = [NSString stringWithFormat:@"%@ Encoder: %@ Mixdown: %@ SampleRate: %@(khz) Bitrate: %@(kbps)",
+                            [item objectForKey:@"Audio2TrackDescription"] ,
+                            [item objectForKey:@"Audio2Encoder"],
+                            [item objectForKey:@"Audio2Mixdown"] ,
+                            [item objectForKey:@"Audio2Samplerate"],
+                            [item objectForKey:@"Audio2Bitrate"]];
+            
+            if ([[item objectForKey:@"Audio2TrackDRCSlider"] floatValue] > 1.00)
+            {
+                audioDetail2 = [NSString stringWithFormat:@"%@, DRC: %@",audioDetail2,[item objectForKey:@"Audio2TrackDRCSlider"]];
+            }
+            else
+            {
+                audioDetail2 = [NSString stringWithFormat:@"%@, DRC: Off",audioDetail2];
+            }
+        }
+        
+        if ([[item objectForKey:@"Audio3Track"] intValue] > 0)
+        {
+            audioCodecSummary = [NSString stringWithFormat:@"%@, %@",audioCodecSummary ,[item objectForKey:@"Audio3Encoder"]];
+            audioDetail3 = [NSString stringWithFormat:@"%@ Encoder: %@ Mixdown: %@ SampleRate: %@(khz) Bitrate: %@(kbps)",
+                            [item objectForKey:@"Audio3TrackDescription"] ,
+                            [item objectForKey:@"Audio3Encoder"],
+                            [item objectForKey:@"Audio3Mixdown"] ,
+                            [item objectForKey:@"Audio3Samplerate"],
+                            [item objectForKey:@"Audio3Bitrate"]];
+            
+            if ([[item objectForKey:@"Audio3TrackDRCSlider"] floatValue] > 1.00)
+            {
+                audioDetail3 = [NSString stringWithFormat:@"%@, DRC: %@",audioDetail3,[item objectForKey:@"Audio3TrackDRCSlider"]];
+            }
+            else
+            {
+                audioDetail3 = [NSString stringWithFormat:@"%@, DRC: Off",audioDetail3];
+            }
+        }
+        
+        if ([[item objectForKey:@"Audio4Track"] intValue] > 0)
+        {
+            audioCodecSummary = [NSString stringWithFormat:@"%@, %@",audioCodecSummary ,[item objectForKey:@"Audio3Encoder"]];
+            audioDetail4 = [NSString stringWithFormat:@"%@ Encoder: %@ Mixdown: %@ SampleRate: %@(khz) Bitrate: %@(kbps)",
+                            [item objectForKey:@"Audio4TrackDescription"] ,
+                            [item objectForKey:@"Audio4Encoder"],
+                            [item objectForKey:@"Audio4Mixdown"] ,
+                            [item objectForKey:@"Audio4Samplerate"],
+                            [item objectForKey:@"Audio4Bitrate"]];
+            
+            if ([[item objectForKey:@"Audio4TrackDRCSlider"] floatValue] > 1.00)
+            {
+                audioDetail4 = [NSString stringWithFormat:@"%@, DRC: %@",audioDetail4,[item objectForKey:@"Audio4TrackDRCSlider"]];
+            }
+            else
+            {
+                audioDetail4 = [NSString stringWithFormat:@"%@, DRC: Off",audioDetail4];
+            }
+        }
+        
+        NSString * jobFormatInfo;
+        if ([[item objectForKey:@"ChapterMarkers"] intValue] == 1)
+            jobFormatInfo = [NSString stringWithFormat:@"%@ Container, %@ Video  %@ Audio, Chapter Markers\n", [item objectForKey:@"FileFormat"], [item objectForKey:@"VideoEncoder"], audioCodecSummary];
+        else
+            jobFormatInfo = [NSString stringWithFormat:@"%@ Container, %@ Video  %@ Audio\n", [item objectForKey:@"FileFormat"], [item objectForKey:@"VideoEncoder"], audioCodecSummary];
+        
+        
+        [finalString appendString: @"Format: " withAttributes:detailBoldAttr];
+        [finalString appendString: jobFormatInfo withAttributes:detailAttr];
+        
+        /* Optional String for mp4 options */
+        if ([[item objectForKey:@"FileFormat"] isEqualToString: @"MP4 file"])
+        {
+            NSString * MP4Opts = @"";
+            BOOL mp4OptsPresent = NO;
+            if( [[item objectForKey:@"Mp4LargeFile"] intValue] == 1)
+            {
+                mp4OptsPresent = YES;
+                MP4Opts = [MP4Opts stringByAppendingString:@" - Large file size"];
+            }
+            if( [[item objectForKey:@"Mp4HttpOptimize"] intValue] == 1)
+            {
+                mp4OptsPresent = YES;
+                MP4Opts = [MP4Opts stringByAppendingString:@" - Web optimized"];
+            }
+            
+            if( [[item objectForKey:@"Mp4iPodCompatible"] intValue] == 1)
+            {
+                mp4OptsPresent = YES;
+                MP4Opts = [MP4Opts stringByAppendingString:@" - iPod 5G support "];
+            }
+            if (mp4OptsPresent == YES)
+            {
+                [finalString appendString: @"MP4 Options: " withAttributes:detailBoldAttr];
+                [finalString appendString: MP4Opts withAttributes:detailAttr];
+                [finalString appendString:@"\n" withAttributes:detailAttr];
+            }
+        }
+        
+        /* Fourth Line (Destination Path)*/
+        [finalString appendString: @"Destination: " withAttributes:detailBoldAttr];
+        [finalString appendString: [item objectForKey:@"DestinationPath"] withAttributes:detailAttr];
+        [finalString appendString:@"\n" withAttributes:detailAttr];
+        /* Fifth Line Picture Details*/
+        NSString * pictureInfo;
+        pictureInfo = [NSString stringWithFormat:@"%@", [item objectForKey:@"PictureSizingSummary"]];
+        if ([[item objectForKey:@"PictureKeepRatio"] intValue] == 1)
+        {
+            pictureInfo = [pictureInfo stringByAppendingString:@" Keep Aspect Ratio"];
+        }
+        if ([[item objectForKey:@"VideoGrayScale"] intValue] == 1)
+        {
+            pictureInfo = [pictureInfo stringByAppendingString:@", Grayscale"];
+        }
+        
+        [finalString appendString: @"Picture: " withAttributes:detailBoldAttr];
+        [finalString appendString: pictureInfo withAttributes:detailAttr];
+        [finalString appendString:@"\n" withAttributes:detailAttr];
+        
+        /* Optional String for Picture Filters */
+        
+        NSString * pictureFilters = @"";
+        BOOL pictureFiltersPresent = NO;
+        
+        if( [[item objectForKey:@"PictureDetelecine"] intValue] == 1)
+        {
+            pictureFiltersPresent = YES;
+            pictureFilters = [pictureFilters stringByAppendingString:@" - Detelecine (Default)"];
+        }
+        else if( [[item objectForKey:@"PictureDetelecine"] intValue] == 2)
+        {
+            pictureFiltersPresent = YES;
+            pictureFilters = [pictureFilters stringByAppendingString:[NSString stringWithFormat:@" - Detelecine (%@)",[item objectForKey:@"PictureDetelecineCustom"]]];
+        }
+        
+        if( [[item objectForKey:@"PictureDecombDeinterlace"] intValue] == 1)
+        {
+            if ([[item objectForKey:@"PictureDecomb"] intValue] != 0)
+            {
+                pictureFiltersPresent = YES;
+                if( [[item objectForKey:@"PictureDecomb"] intValue] == 1)
+                {
+                    pictureFiltersPresent = YES;
+                    pictureFilters = [pictureFilters stringByAppendingString:@" - Decomb (Default)"];
+                }
+                if( [[item objectForKey:@"PictureDecomb"] intValue] == 2)
+                {
+                    pictureFiltersPresent = YES;
+                    pictureFilters = [pictureFilters stringByAppendingString:[NSString stringWithFormat:@" - Decomb (%@)",[item objectForKey:@"PictureDecombCustom"]]];
+                }
+            }
+        }
+        else
+        {
+            if ([[item objectForKey:@"PictureDeinterlace"] intValue] != 0)
+            {
+                pictureFiltersPresent = YES;
+                if ([[item objectForKey:@"PictureDeinterlace"] intValue] == 1)
+                {
+                    pictureFilters = [pictureFilters stringByAppendingString:@" - Deinterlace (Fast)"];
+                }
+                else if ([[item objectForKey:@"PictureDeinterlace"] intValue] == 2)
+                {
+                    pictureFilters = [pictureFilters stringByAppendingString:@" - Deinterlace (Slow)"];           
+                }
+                else if ([[item objectForKey:@"PictureDeinterlace"] intValue] == 3)
+                {
+                    pictureFilters = [pictureFilters stringByAppendingString:@" - Deinterlace (Slower)"];            
+                }
+                else if ([[item objectForKey:@"PictureDeinterlace"] intValue] == 4)
+                {
+                    pictureFilters = [pictureFilters stringByAppendingString:[NSString stringWithFormat:@" - Deinterlace (%@)",[item objectForKey:@"PictureDeinterlaceCustom"]]];            
+                }
+                
+            }
+        }
+        if ([[item objectForKey:@"PictureDenoise"] intValue] != 0)
+        {
+            pictureFiltersPresent = YES;
+            if ([[item objectForKey:@"PictureDenoise"] intValue] == 1)
+            {
+                pictureFilters = [pictureFilters stringByAppendingString:@" - Denoise (Weak)"];
+            }
+            else if ([[item objectForKey:@"PictureDenoise"] intValue] == 2)
+            {
+                pictureFilters = [pictureFilters stringByAppendingString:@" - Denoise (Medium)"];           
+            }
+            else if ([[item objectForKey:@"PictureDenoise"] intValue] == 3)
+            {
+                pictureFilters = [pictureFilters stringByAppendingString:@" - Denoise (Strong)"];            
+            }
+            else if ([[item objectForKey:@"PictureDenoise"] intValue] == 4)
+            {
+                pictureFilters = [pictureFilters stringByAppendingString:[NSString stringWithFormat:@" - Denoise (%@)",[item objectForKey:@"PictureDenoiseCustom"]]];            
+            }
+            
+        }
+        if ([[item objectForKey:@"PictureDeblock"] intValue] != 0)
+        {
+            pictureFiltersPresent = YES;
+            pictureFilters = [pictureFilters stringByAppendingString: [NSString stringWithFormat:@" - Deblock (pp7) (%d)",[[item objectForKey:@"PictureDeblock"] intValue]]];
+        }
+        
+        if ([[item objectForKey:@"VideoGrayScale"] intValue] == 1)
+        {
+            pictureFiltersPresent = YES;
+            pictureFilters = [pictureFilters stringByAppendingString:@" - Grayscale"];
+        }
+        
+        if (pictureFiltersPresent == YES)
+        {
+            [finalString appendString: @"Filters: " withAttributes:detailBoldAttr];
+            [finalString appendString: pictureFilters withAttributes:detailAttr];
+            [finalString appendString:@"\n" withAttributes:detailAttr];
+        }
+        
+        /* Sixth Line Video Details*/
+        NSString * videoInfo;
+        videoInfo = [NSString stringWithFormat:@"Encoder: %@", [item objectForKey:@"VideoEncoder"]];
+        
+        /* for framerate look to see if we are using vfr detelecine */
+        if ([[item objectForKey:@"JobIndexVideoFramerate"] intValue] == 0)
+        {
+            if ([[item objectForKey:@"PictureDetelecine"] intValue] == 1)
+            {
+                /* we are using same as source with vfr detelecine */
+                videoInfo = [NSString stringWithFormat:@"%@ Framerate: Same as source (vfr detelecine)", videoInfo];
+            }
+            else
+            {
+                /* we are using a variable framerate without dropping frames */
+                videoInfo = [NSString stringWithFormat:@"%@ Framerate: Same as source (variable)", videoInfo];
+            }
+        }
         else
-            jobIndex = rowIndex - 1;
+        {
+            /* we have a specified, constant framerate */
+            videoInfo = [NSString stringWithFormat:@"%@ Framerate: %@ (constant framerate)", videoInfo ,[item objectForKey:@"VideoFramerate"]];
+        }
+        
+        if ([[item objectForKey:@"VideoQualityType"] intValue] == 0)// Target Size MB
+        {
+            videoInfo = [NSString stringWithFormat:@"%@ Target Size: %@(MB) (%d(kbps) abr)", videoInfo ,[item objectForKey:@"VideoTargetSize"],[[item objectForKey:@"VideoAvgBitrate"] intValue]];
+        }
+        else if ([[item objectForKey:@"VideoQualityType"] intValue] == 1) // ABR
+        {
+            videoInfo = [NSString stringWithFormat:@"%@ Bitrate: %d(kbps)", videoInfo ,[[item objectForKey:@"VideoAvgBitrate"] intValue]];
+        }
+        else // CRF
+        {
+            videoInfo = [NSString stringWithFormat:@"%@ Constant Quality: %.2f", videoInfo ,[[item objectForKey:@"VideoQualitySlider"] floatValue]];
+        }
+        
+        [finalString appendString: @"Video: " withAttributes:detailBoldAttr];
+        [finalString appendString: videoInfo withAttributes:detailAttr];
+        [finalString appendString:@"\n" withAttributes:detailAttr];
+        
+        if ([[item objectForKey:@"VideoEncoder"] isEqualToString: @"H.264 (x264)"])
+        {
+            [finalString appendString: @"x264 Options: " withAttributes:detailBoldAttr];
+            [finalString appendString: [item objectForKey:@"x264Option"] withAttributes:detailAttr];
+            [finalString appendString:@"\n" withAttributes:detailAttr];
+        }
+        
+        
+        
+        /* Seventh Line Audio Details*/
+        if ([audioDetail1 length] != 0)
+        {
+            [finalString appendString: @"Audio Track 1: " withAttributes:detailBoldAttr];
+            [finalString appendString: audioDetail1 withAttributes:detailAttr];
+            [finalString appendString:@"\n" withAttributes:detailAttr];
+        }
+        
+        if ([audioDetail2 length] != 0)
+        {
+            [finalString appendString: @"Audio Track 2: " withAttributes:detailBoldAttr];
+            [finalString appendString: audioDetail2 withAttributes:detailAttr];
+            [finalString appendString:@"\n" withAttributes:detailAttr];
+        }
+        
+        if ([audioDetail3 length] != 0)
+        {
+            [finalString appendString: @"Audio Track 3: " withAttributes:detailBoldAttr];
+            [finalString appendString: audioDetail3 withAttributes:detailAttr];
+            [finalString appendString:@"\n" withAttributes:detailAttr];
+        }
+        
+        if ([audioDetail4 length] != 0)
+        {
+            [finalString appendString: @"Audio Track 4: " withAttributes:detailBoldAttr];
+            [finalString appendString: audioDetail4 withAttributes:detailAttr];
+            [finalString appendString:@"\n" withAttributes:detailAttr];
+        }
+        /* Eighth Line Subtitle Details */
+        
+        int i = 0;
+        NSEnumerator *enumerator = [[item objectForKey:@"SubtitleList"] objectEnumerator];
+        id tempObject;
+        while (tempObject = [enumerator nextObject])
+        {
+            /* since the subtitleSourceTrackNum 0 is "None" in our array of the subtitle popups,
+             * we want to ignore it for display as well as encoding.
+             */
+            if ([[tempObject objectForKey:@"subtitleSourceTrackNum"] intValue] > 0)
+            { 
+                /* remember that index 0 of Subtitles can contain "Foreign Audio Search*/
+                [finalString appendString: @"Subtitle: " withAttributes:detailBoldAttr];
+                [finalString appendString: [tempObject objectForKey:@"subtitleSourceTrackName"] withAttributes:detailAttr];
+                if ([[tempObject objectForKey:@"subtitleTrackForced"] intValue] == 1)
+                {
+                    [finalString appendString: @" - Forced Only" withAttributes:detailAttr];
+                }
+                if ([[tempObject objectForKey:@"subtitleTrackBurned"] intValue] == 1)
+                {
+                    [finalString appendString: @" - Burned In" withAttributes:detailAttr];
+                }
+                if ([[tempObject objectForKey:@"subtitleTrackDefault"] intValue] == 1)
+                {
+                    [finalString appendString: @" - Default" withAttributes:detailAttr];
+                }
+                [finalString appendString:@"\n" withAttributes:detailAttr];
+            }
+            i++;
+        }      
+        
+        return finalString;
     }
-    
-    if (!job)
+    else if ([[tableColumn identifier] isEqualToString:@"icon"])
     {
-        if (fShowsJobsAsGroups)
-            job = hb_group(fHandle, jobIndex);
+        if ([[item objectForKey:@"Status"] intValue] == 0)
+        {
+            return [NSImage imageNamed:@"EncodeComplete"];
+        }
+        else if ([[item objectForKey:@"Status"] intValue] == 1)
+        {
+            return [NSImage imageNamed: [NSString stringWithFormat: @"EncodeWorking%d", fAnimationIndex]];
+        }
+        else if ([[item objectForKey:@"Status"] intValue] == 3)
+        {
+            return [NSImage imageNamed:@"EncodeCanceled"];
+        }
         else
-            job = hb_job(fHandle, jobIndex);
+        {
+            return [NSImage imageNamed:@"JobSmall"];
+        }
+        
     }
-#else
-    if (fShowsJobsAsGroups)
-        job = hb_group(fHandle, rowIndex);
     else
-        job = hb_job(fHandle, rowIndex);
-#endif
-    
-    if (!job)
-        return @"";    // fatal error!
-
-    if ([[aTableColumn identifier] isEqualToString:@"desc"])
     {
-        BOOL highlighted = [aTableView isRowSelected:rowIndex] && [[aTableView window] isKeyWindow] && ([[aTableView window] firstResponder] == aTableView);
-        return [self attributedDescriptionForJob:job withTitle:YES withDetail:fShowsDetail withHighlighting:highlighted];    
-    }
-    
-    else if ([[aTableColumn identifier] isEqualToString:@"delete"])
         return @"";
-
-    else if ([[aTableColumn identifier] isEqualToString:@"icon"])
-        return fShowsJobsAsGroups ? [NSImage imageNamed:@"JobSmall"] : [self smallImageForPass: job->pass];
-
-    return @"";
+    }
 }
 
-//------------------------------------------------------------------------------------
-// NSTableView delegate
-//------------------------------------------------------------------------------------
-- (void)tableView: (NSTableView *)aTableView
-        willDisplayCell: (id)aCell
-         forTableColumn: (NSTableColumn *)aTableColumn
-                    row: (int)rowIndex
+- (void)outlineView:(NSOutlineView *)outlineView willDisplayCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item
 {
-    if ([[aTableColumn identifier] isEqualToString:@"delete"])
+    if ([[tableColumn identifier] isEqualToString:@"desc"])
+    {
+
+
+        // nb: The "desc" column is currently an HBImageAndTextCell. However, we are longer
+        // using the image portion of the cell so we could switch back to a regular NSTextFieldCell.
+
+        // Set the image here since the value returned from outlineView:objectValueForTableColumn: didn't specify the image part
+        [cell setImage:nil];
+    }
+    else if ([[tableColumn identifier] isEqualToString:@"action"])
     {
-        BOOL highlighted = [aTableView isRowSelected:rowIndex] && [[aTableView window] isKeyWindow] && ([[aTableView window] firstResponder] == aTableView);
-        if (highlighted)
+        [cell setEnabled: YES];
+        BOOL highlighted = [outlineView isRowSelected:[outlineView rowForItem: item]] && [[outlineView window] isKeyWindow] && ([[outlineView window] firstResponder] == outlineView);
+        if ([[item objectForKey:@"Status"] intValue] == 0)
         {
-            [aCell setImage:[NSImage imageNamed:@"DeleteHighlight"]];
-            [aCell setAlternateImage:[NSImage imageNamed:@"DeleteHighlightPressed"]];
+            [cell setAction: @selector(revealSelectedQueueItem:)];
+            if (highlighted)
+            {
+                [cell setImage:[NSImage imageNamed:@"RevealHighlight"]];
+                [cell setAlternateImage:[NSImage imageNamed:@"RevealHighlightPressed"]];
+            }
+            else
+                [cell setImage:[NSImage imageNamed:@"Reveal"]];
         }
         else
         {
-            [aCell setImage:[NSImage imageNamed:@"Delete"]];
+            [cell setAction: @selector(removeSelectedQueueItem:)];
+            if (highlighted)
+            {
+                [cell setImage:[NSImage imageNamed:@"DeleteHighlight"]];
+                [cell setAlternateImage:[NSImage imageNamed:@"DeleteHighlightPressed"]];
+            }
+            else
+                [cell setImage:[NSImage imageNamed:@"Delete"]];
         }
     }
 }
 
-//------------------------------------------------------------------------------------
-// NSTableView delegate
-//------------------------------------------------------------------------------------
-#if HB_UNI_QUEUE
-- (float)tableView:(NSTableView *)tableView heightOfRow:(int)row
+- (void)outlineView:(NSOutlineView *)outlineView willDisplayOutlineCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item
 {
-    if ((row == 0) && hb_current_job(fHandle))
-        return HB_ROW_HEIGHT_ACTIVE_JOB;
-    else 
-        return fShowsDetail ? HB_ROW_HEIGHT_DETAIL : HB_ROW_HEIGHT_NO_DETAIL;
+    // By default, the discolsure image gets centered vertically in the cell. We want
+    // always at the top.
+    if ([outlineView isItemExpanded: item])
+        [cell setImagePosition: NSImageAbove];
+    else
+        [cell setImagePosition: NSImageOnly];
 }
-#endif
 
-#if HB_QUEUE_DRAGGING
-- (BOOL)tableView:(NSTableView *)tv writeRowsWithIndexes:(NSIndexSet *)rowIndexes toPasteboard:(NSPasteboard*)pboard
-{
-    // Copy the row numbers to the pasteboard.
-    NSData *data = [NSKeyedArchiver archivedDataWithRootObject:rowIndexes];
-    [pboard declareTypes:[NSArray arrayWithObject:HBQueueDataType] owner:self];
-    [pboard setData:data forType:HBQueueDataType];
-    return YES;
-}
-#endif
+#pragma mark -
+#pragma mark NSOutlineView delegate (dragging related)
+
+//------------------------------------------------------------------------------------
+// NSTableView delegate
+//------------------------------------------------------------------------------------
 
-#if HB_QUEUE_DRAGGING
-- (NSDragOperation)tableView:(NSTableView*)tv validateDrop:(id <NSDraggingInfo>)info proposedRow:(int)row proposedDropOperation:(NSTableViewDropOperation)op
-{
-    // Add code here to validate the drop
-    NSLog(@"validate Drop");
-    return NSDragOperationEvery;
-}
-#endif
 
-#if HB_QUEUE_DRAGGING
-- (BOOL)tableView:(NSTableView *)aTableView acceptDrop:(id <NSDraggingInfo>)info
-            row:(int)row dropOperation:(NSTableViewDropOperation)operation
+- (BOOL)outlineView:(NSOutlineView *)outlineView writeItems:(NSArray *)items toPasteboard:(NSPasteboard *)pboard
 {
-    NSPasteboard* pboard = [info draggingPasteboard];
-    NSData* rowData = [pboard dataForType:HBQueueDataType];
-    NSIndexSet* rowIndexes = [NSKeyedUnarchiver unarchiveObjectWithData:rowData];
-    int dragRow = [rowIndexes firstIndex];
-    // Move the specified row to its new location...
+    // Dragging is only allowed of the pending items.
+    if ([[[items objectAtIndex:0] objectForKey:@"Status"] integerValue] != 2) // 2 is pending
+    {
+        return NO;
+    }
+    
+    // Don't retain since this is just holding temporaral drag information, and it is
+    //only used during a drag!  We could put this in the pboard actually.
+    fDraggedNodes = items;
+    
+    // Provide data for our custom type, and simple NSStrings.
+    [pboard declareTypes:[NSArray arrayWithObjects: DragDropSimplePboardType, nil] owner:self];
+    
+    // the actual data doesn't matter since DragDropSimplePboardType drags aren't recognized by anyone but us!.
+    [pboard setData:[NSData data] forType:DragDropSimplePboardType];
     
     return YES;
 }
-#endif
-
-
-#if HB_OUTLINE_QUEUE
-
-- (id)outlineView:(NSOutlineView *)outlineView child:(int)index ofItem:(id)item
-{
-    if (item == nil)
-        return [fEncodes objectAtIndex:index];
-    else
-        return [item objectAtIndex:index];
-}
-
-- (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item
-{
-    return ! [item isKindOfClass:[HBJob class]];
-}
 
-- (int)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item
-{
-    if (item == nil)
-        return [fEncodes count];
-    else
-        return [item count];
-}
 
-- (float)outlineView:(NSOutlineView *)outlineView heightOfRowByItem:(id)item
+/* This method is used to validate the drops. */
+- (NSDragOperation)outlineView:(NSOutlineView *)outlineView validateDrop:(id <NSDraggingInfo>)info proposedItem:(id)item proposedChildIndex:(NSInteger)index
 {
-    if (fShowsDetail && [item isKindOfClass:[HBJob class]])
-        return HB_ROW_HEIGHT_DETAIL;
-    else
-        return HB_ROW_HEIGHT_NO_DETAIL;
-}
-
-- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item
-{
-    BOOL highlighted = [outlineView isRowSelected:[outlineView rowForItem: item]] && [[outlineView window] isKeyWindow] && ([[outlineView window] firstResponder] == outlineView);
-    if ([item isKindOfClass:[HBJob class]])
+    // Don't allow dropping ONTO an item since they can't really contain any children.
+    BOOL isOnDropTypeProposal = index == NSOutlineViewDropOnItemIndex;
+    if (isOnDropTypeProposal)
     {
-        if ([[tableColumn identifier] isEqualToString:@"desc"])
-        {
-            hb_job_t * job = [item job];
-//            return [self attributedDescriptionForJob:job withTitle:NO withDetail:fShowsDetail withHighlighting:highlighted];
-            if (job->pass == -1)
-                return @"Subtitle Scan";
-            else
-            {
-                int passNum = MAX( 1, job->pass );
-                if (passNum == 1)
-                    return @"1st Pass";
-                if (passNum == 2)
-                    return @"2nd Pass";
-                else
-                    return [NSString stringWithFormat: @"Pass %d", passNum];
-            }
-        }
+        return NSDragOperationNone;
     }
     
-    else
+    // Don't allow dropping INTO an item since they can't really contain any children.
+    if (item != nil)
     {
-        hb_job_t * job = [[item objectAtIndex:0] job];
-        if ([[tableColumn identifier] isEqualToString:@"desc"])
-            return [self attributedDescriptionForJob:job withTitle:YES withDetail:NO withHighlighting:highlighted];    
+        index = [fOutlineView rowForItem: item] + 1;
+        item = nil;
     }
-
-    return @"";
+    
+    // NOTE: Should we allow dropping a pending job *above* the
+    // finished or already encoded jobs ?
+    // We do not let the user drop a pending job before or *above*
+    // already finished or currently encoding jobs.
+    if (index <= fEncodingQueueItem)
+    {
+        return NSDragOperationNone;
+        index = MAX (index, fEncodingQueueItem);
+       }
+    
+    [outlineView setDropItem:item dropChildIndex:index];
+    return NSDragOperationGeneric;
 }
 
-- (void)outlineView:(NSOutlineView *)outlineView willDisplayCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item
+- (BOOL)outlineView:(NSOutlineView *)outlineView acceptDrop:(id <NSDraggingInfo>)info item:(id)item childIndex:(NSInteger)index
 {
-    if ([[tableColumn identifier] isEqualToString:@"desc"])
-    {
-        if ([item isKindOfClass:[HBJob class]])
-            [cell setImage:[self smallImageForPass: [item job]->pass]];
-        else
-            [cell setImage:[NSImage imageNamed:@"JobSmall"]];
-    }
-    
-    else if ([[tableColumn identifier] isEqualToString:@"delete"])
-    {
-        // The Delete action can only be applied for group items, not indivdual jobs.
-        if ([item isKindOfClass:[HBJob class]])
-        {
-            [cell setEnabled: NO];
-            [cell setImage: nil];
-        }
-        else
-        {
-            [cell setEnabled: YES];
-            BOOL highlighted = [outlineView isRowSelected:[outlineView rowForItem: item]] && [[outlineView window] isKeyWindow] && ([[outlineView window] firstResponder] == outlineView);
-            if (highlighted)
-            {
-                [cell setImage:[NSImage imageNamed:@"DeleteHighlight"]];
-                [cell setAlternateImage:[NSImage imageNamed:@"DeleteHighlightPressed"]];
-            }
-            else
-                [cell setImage:[NSImage imageNamed:@"Delete"]];
-        }
-    }
+    NSMutableIndexSet *moveItems = [NSMutableIndexSet indexSet];
+
+    for( id obj in fDraggedNodes )
+        [moveItems addIndex:[fJobGroups indexOfObject:obj]];
+
+    // Successful drop, we use moveObjectsInQueueArray:... in fHBController
+    // to properly rearrange the queue array, save it to plist and then send it back here.
+    // since Controller.mm is handling all queue array manipulation.
+    // We *could do this here, but I think we are better served keeping that code together.
+    [fHBController moveObjectsInQueueArray:fJobGroups fromIndexes:moveItems toIndex: index];
+    return YES;
 }
 
-#endif
 
 @end