diff options
Diffstat (limited to 'macosx/HBQueueTableViewController.m')
-rw-r--r-- | macosx/HBQueueTableViewController.m | 339 |
1 files changed, 339 insertions, 0 deletions
diff --git a/macosx/HBQueueTableViewController.m b/macosx/HBQueueTableViewController.m new file mode 100644 index 000000000..d0b4753cb --- /dev/null +++ b/macosx/HBQueueTableViewController.m @@ -0,0 +1,339 @@ +/* HBQueueTableViewController.m $ + + This file is part of the HandBrake source code. + Homepage: <http://handbrake.fr/>. + It may be used under the terms of the GNU General Public License. */ + +#import "HBQueueTableViewController.h" + +#import "HBTableView.h" +#import "HBQueueItemView.h" + +// Pasteboard type for or drag operations +#define HBQueueDragDropPboardType @"HBQueueCustomTableViewPboardType" + +@interface HBQueueTableViewController () <NSTableViewDataSource, NSTableViewDelegate, HBQueueItemViewDelegate> + +@property (nonatomic, readonly) HBQueue *queue; +@property (nonatomic) NSArray<HBQueueItem *> *dragNodesArray; + +@property (strong) id<HBQueueTableViewControllerDelegate> delegate; + +@property (weak) IBOutlet HBTableView *tableView; + +@end + +@implementation HBQueueTableViewController + +- (instancetype)initWithQueue:(HBQueue *)state delegate:(id<HBQueueTableViewControllerDelegate>)delegate +{ + self = [super init]; + if (self) + { + _queue = state; + _delegate = delegate; + } + return self; +} + +- (NSString *)nibName +{ + return @"HBQueueTableViewController"; +} + +- (void)viewDidLoad { + [super viewDidLoad]; + + // lets setup our queue list table view for drag and drop here + [self.tableView registerForDraggedTypes:@[HBQueueDragDropPboardType]]; + [self.tableView setDraggingSourceOperationMask:NSDragOperationEvery forLocal:YES]; + [self.tableView setVerticalMotionCanBeginDrag:YES]; + + // Reloads the queue, this is called + // when another HandBrake instances modifies the queue + [NSNotificationCenter.defaultCenter addObserverForName:HBQueueReloadItemsNotification object:_queue queue:NSOperationQueue.mainQueue usingBlock:^(NSNotification * _Nonnull note) { + [self.tableView reloadData]; + }]; + + [NSNotificationCenter.defaultCenter addObserverForName:HBQueueDidAddItemNotification object:_queue queue:NSOperationQueue.mainQueue usingBlock:^(NSNotification * _Nonnull note) { + NSIndexSet *indexes = note.userInfo[HBQueueItemNotificationIndexesKey]; + [self.tableView insertRowsAtIndexes:indexes withAnimation:NSTableViewAnimationSlideDown]; + }]; + + [NSNotificationCenter.defaultCenter addObserverForName:HBQueueDidRemoveItemNotification object:_queue queue:NSOperationQueue.mainQueue usingBlock:^(NSNotification * _Nonnull note) { + NSIndexSet *indexes = note.userInfo[HBQueueItemNotificationIndexesKey]; + [self.tableView removeRowsAtIndexes:indexes withAnimation:NSTableViewAnimationSlideUp]; + [self.tableView selectRowIndexes:[NSIndexSet indexSetWithIndex:indexes.firstIndex] byExtendingSelection:NO]; + }]; + + [NSNotificationCenter.defaultCenter addObserverForName:HBQueueDidMoveItemNotification object:_queue queue:NSOperationQueue.mainQueue usingBlock:^(NSNotification * _Nonnull note) { + NSArray<NSNumber *> *source = note.userInfo[HBQueueItemNotificationSourceIndexesKey]; + NSArray<NSNumber *> *target = note.userInfo[HBQueueItemNotificationTargetIndexesKey]; + + [self.tableView beginUpdates]; + for (NSInteger idx = 0; idx < source.count; idx++) + { + [self.tableView moveRowAtIndex:source[idx].integerValue toIndex:target[idx].integerValue]; + } + [self.tableView endUpdates]; + }]; + + [NSNotificationCenter.defaultCenter addObserverForName:HBQueueDidChangeItemNotification object:_queue queue:NSOperationQueue.mainQueue usingBlock:^(NSNotification * _Nonnull note) { + NSIndexSet *indexes = note.userInfo[HBQueueItemNotificationIndexesKey]; + NSIndexSet *columnIndexes = [NSIndexSet indexSetWithIndex:0]; + [self.tableView reloadDataForRowIndexes:indexes columnIndexes:columnIndexes]; + }]; + + [NSNotificationCenter.defaultCenter addObserverForName:HBQueueDidCompleteItemNotification object:_queue queue:NSOperationQueue.mainQueue usingBlock:^(NSNotification * _Nonnull note) { + NSIndexSet *indexes = note.userInfo[HBQueueItemNotificationIndexesKey]; + NSIndexSet *columnIndexes = [NSIndexSet indexSetWithIndex:0]; + if (indexes.count) + { + [self.tableView reloadDataForRowIndexes:indexes columnIndexes:columnIndexes]; + } + }]; +} + +#pragma mark - UI Actions + +/** + * Delete encodes from the queue window and accompanying array + * Also handling first cancelling the encode if in fact its currently encoding. + */ +- (IBAction)removeSelectedQueueItem:(id)sender +{ + NSMutableIndexSet *targetedRows = [[self.tableView targetedRowIndexes] mutableCopy]; + [self.delegate tableViewRemoveItemsAtIndexes:targetedRows]; +} + +/** + * Show the finished encode in the finder + */ +- (IBAction)revealSelectedQueueItems:(id)sender +{ + NSIndexSet *targetedRows = [self.tableView targetedRowIndexes]; + NSMutableArray<NSURL *> *urls = [[NSMutableArray alloc] init]; + + NSUInteger currentIndex = [targetedRows firstIndex]; + while (currentIndex != NSNotFound) { + NSURL *url = [[self.queue.items objectAtIndex:currentIndex] completeOutputURL]; + [urls addObject:url]; + currentIndex = [targetedRows indexGreaterThanIndex:currentIndex]; + } + + [[NSWorkspace sharedWorkspace] activateFileViewerSelectingURLs:urls]; +} + +- (IBAction)revealSelectedQueueItemsSources:(id)sender +{ + NSIndexSet *targetedRows = [self.tableView targetedRowIndexes]; + NSMutableArray<NSURL *> *urls = [[NSMutableArray alloc] init]; + + NSUInteger currentIndex = [targetedRows firstIndex]; + while (currentIndex != NSNotFound) { + NSURL *url = [[self.queue.items objectAtIndex:currentIndex] fileURL]; + [urls addObject:url]; + currentIndex = [targetedRows indexGreaterThanIndex:currentIndex]; + } + + [[NSWorkspace sharedWorkspace] activateFileViewerSelectingURLs:urls]; +} + +/** + * Resets the item state to ready. + */ +- (IBAction)resetJobState:(id)sender +{ + NSIndexSet *targetedRows = [self.tableView targetedRowIndexes]; + if (targetedRows.count) + { + [self.queue resetItemsStateAtIndexes:targetedRows]; + } +} + +/** + * Send the selected queue item back to the main window for rescan and possible edit. + */ +- (IBAction)editSelectedQueueItem:(id)sender +{ + NSInteger row = self.tableView.clickedRow; + HBQueueItem *item = [self.queue.items objectAtIndex:row]; + if (item) + { + [self.delegate tableViewEditItem:item]; + } +} + +- (IBAction)removeAll:(id)sender +{ + [self.queue removeNotWorkingItems]; +} + +- (IBAction)removeCompleted:(id)sender +{ + [self.queue removeCompletedItems]; +} + +#pragma mark - UI Validation + +- (BOOL)validateMenuItem:(NSMenuItem *)menuItem +{ + SEL action = menuItem.action; + + if (action == @selector(editSelectedQueueItem:) || + action == @selector(removeSelectedQueueItem:) || + action == @selector(revealSelectedQueueItems:) || + action == @selector(revealSelectedQueueItemsSources:)) + { + return (self.tableView.selectedRow != -1 || self.tableView.clickedRow != -1); + } + + if (action == @selector(resetJobState:)) + { + return self.tableView.targetedRowIndexes.count > 0; + } + + if (action == @selector(removeAll:)) + { + return self.queue.items.count > 0; + } + + if (action == @selector(removeCompleted:)) + { + return self.queue.completedItemsCount > 0; + } + + return YES; +} + +#pragma mark - NSTableView data source + +- (NSView *)tableView:(NSTableView *)tableView + viewForTableColumn:(NSTableColumn *)tableColumn + row:(NSInteger)row { + + HBQueueItemView *view = [tableView makeViewWithIdentifier:@"MainSimpleCell" owner:self]; + HBQueueItem *item = self.queue.items[row]; + + view.delegate = self; + view.item = item; + + return view; +} + +- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView +{ + return self.queue.items.count; +} + +- (CGFloat)tableView:(NSTableView *)tableView heightOfRow:(NSInteger)row +{ + return 22; +} + +- (void)toggleRowsAtIndexes:(NSIndexSet *)rowIndexes expand:(BOOL)expand +{ + NSMutableIndexSet *rowsToExpand = [NSMutableIndexSet indexSet]; + [rowIndexes enumerateIndexesUsingBlock:^(NSUInteger index, BOOL *stop) { + HBQueueItem *item = self.queue.items[index]; + BOOL expanded = item.expanded; + if (expanded != expand) + { + item.expanded = !expanded; + [rowsToExpand addIndex:index]; + } + + //HBQueueItemView *itemView = (HBQueueItemView *)[self.tableView viewAtColumn:0 row:index makeIfNecessary:NO]; + //if (expand) + //{ + //[itemView expand]; + //} + //else + //{ + //[itemView collapse]; + //} + }]; + [self.tableView noteHeightOfRowsWithIndexesChanged:rowsToExpand]; +} + +#pragma mark NSQueueItemView delegate + +- (void)removeQueueItem:(nonnull HBQueueItem *)item +{ + NSUInteger index = [self.queue.items indexOfObject:item]; + [self.queue removeQueueItemAtIndex:index]; +} + +- (void)revealQueueItem:(nonnull HBQueueItem *)item +{ + [[NSWorkspace sharedWorkspace] activateFileViewerSelectingURLs:@[item.completeOutputURL]]; +} + +- (void)toggleQueueItemHeight:(nonnull HBQueueItem *)item +{ + NSInteger row = [self.queue.items indexOfObject:item]; + [self toggleRowsAtIndexes:[NSIndexSet indexSetWithIndex:row] expand:!item.expanded]; +} + +#pragma mark NSTableView delegate + +- (void)tableViewSelectionDidChange:(NSNotification *)notification +{ + NSInteger selectedRow = self.tableView.selectedRow; + HBQueueItem *selectedItem = selectedRow > -1 ? self.queue.items[selectedRow] : nil; + [self.delegate tableViewDidSelectItem:selectedItem]; +} + +- (void)HB_deleteSelectionFromTableView:(NSTableView *)tableView +{ + [self removeSelectedQueueItem:tableView]; +} + +- (BOOL)tableView:(NSTableView *)tableView writeRowsWithIndexes:(NSIndexSet *)rowIndexes toPasteboard:(NSPasteboard *)pboard; +{ + NSArray<HBQueueItem *> *items = [self.queue.items objectsAtIndexes:rowIndexes]; + // Dragging is only allowed of the pending items. + if (items[0].state != HBQueueItemStateReady) + { + return NO; + } + + self.dragNodesArray = items; + + // Provide data for our custom type, and simple NSStrings. + [pboard declareTypes:@[HBQueueDragDropPboardType] owner:self]; + + // the actual data doesn't matter since DragDropSimplePboardType drags aren't recognized by anyone but us!. + [pboard setData:[NSData data] forType:HBQueueDragDropPboardType]; + + return YES; +} + +- (NSDragOperation)tableView:(NSTableView *)tableView validateDrop:(id<NSDraggingInfo>)info proposedRow:(NSInteger)row proposedDropOperation:(NSTableViewDropOperation)dropOperation +{ + // Don't allow dropping ONTO an item since they can't really contain any children. + BOOL isOnDropTypeProposal = dropOperation == NSTableViewDropOn; + if (isOnDropTypeProposal) + { + return NSDragOperationNone; + } + + // We do not let the user drop a pending item before or *above* + // already finished or currently encoding items. + NSInteger encodingRow = [self.queue.items indexOfObject:self.queue.currentItem]; + if (encodingRow != NSNotFound && row <= encodingRow) + { + return NSDragOperationNone; + row = MAX(row, encodingRow); + } + + return NSDragOperationMove; +} + +- (BOOL)tableView:(NSTableView *)tableView acceptDrop:(id<NSDraggingInfo>)info row:(NSInteger)row dropOperation:(NSTableViewDropOperation)dropOperation +{ + [self.queue moveQueueItems:self.dragNodesArray toIndex:row]; + return YES; +} + +@end |