/* ChapterTitles.m $
This file is part of the HandBrake source code.
Homepage: .
It may be used under the terms of the GNU General Public License. */
#import "HBChapterTitlesController.h"
#import "Controller.h"
#include "hb.h"
@interface HBChapterTitlesController ()
{
NSMutableArray *fChapterTitlesArray;
IBOutlet NSTableView * fChapterTable;
IBOutlet NSButton * fLoadChaptersButton;
IBOutlet NSButton * fSaveChaptersButton;
IBOutlet NSButton * fCreateChaptersMarkers;
IBOutlet NSTableColumn * fChapterTableNameColumn;
}
@end
@implementation HBChapterTitlesController
- (instancetype)init
{
self = [super initWithNibName:@"ChaptersTitles" bundle:nil];
if (self)
{
fChapterTitlesArray = [[[NSMutableArray alloc] init] retain];
[[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(titleChanged:) name: HBTitleChangedNotification object: nil];
}
return self;
}
- (void)dealloc
{
[fChapterTitlesArray release];
[super dealloc];
}
- (void)titleChanged:(NSNotification *)aNotification
{
NSDictionary *notDict = [aNotification userInfo];
NSData *theData = [notDict objectForKey: keyTitleTag];
hb_title_t *title = NULL;
[theData getBytes: &title length: sizeof(title)];
[fChapterTitlesArray removeAllObjects];
if (title)
{
for (int i = 0; i < hb_list_count(title->job->list_chapter); i++)
{
hb_chapter_t *chapter = hb_list_item(title->job->list_chapter, i);
if (chapter != NULL)
{
if (chapter->title != NULL)
{
[fChapterTitlesArray addObject:[NSString
stringWithFormat:@"%s",
chapter->title]];
}
else
{
[fChapterTitlesArray addObject:[NSString
stringWithFormat:@"Chapter %d",
i + 1]];
}
}
}
}
[fChapterTable reloadData];
}
- (void)addChaptersFromQueue:(NSMutableArray *)newChaptersArray
{
[fChapterTitlesArray removeAllObjects];
[fChapterTitlesArray addObjectsFromArray:newChaptersArray];
[fChapterTable reloadData];
}
- (void)enableUI:(BOOL)b
{
[fCreateChaptersMarkers setEnabled:b];
[fChapterTable setEnabled:b];
[fLoadChaptersButton setEnabled:b];
[fSaveChaptersButton setEnabled:b];
}
- (NSArray *)chapterTitlesArray
{
return [NSArray arrayWithArray:fChapterTitlesArray];
}
- (IBAction)createChapterMarkersChanged:(id)sender
{
[[NSNotificationCenter defaultCenter] postNotificationName:HBMixdownChangedNotification object:self];
}
- (NSInteger)numberOfRowsInTableView:(NSTableView *)aTableView
{
return [fChapterTitlesArray count];
}
- (void)tableView:(NSTableView *)aTableView
setObjectValue:(id)anObject
forTableColumn:(NSTableColumn *)aTableColumn
row:(NSInteger)rowIndex
{
if (aTableColumn != nil && [[aTableColumn identifier] intValue] == 2)
{
[fChapterTitlesArray replaceObjectAtIndex:rowIndex
withObject:[NSString
stringWithString:anObject]];
}
}
- (id)tableView:(NSTableView *)aTableView
objectValueForTableColumn:(NSTableColumn *)aTableColumn
row:(NSInteger)rowIndex
{
if ([[aTableColumn identifier] intValue] == 1)
{
return [NSString stringWithFormat:@"%ld", rowIndex + 1];
}
else
{
return [NSString stringWithString:[fChapterTitlesArray
objectAtIndex:rowIndex]];
}
return @"__DATA ERROR__";
}
/* Method to edit the next chapter when the user presses Return. We have to use
a timer to avoid interfering with the chain of events that handles the edit. */
- (void)controlTextDidEndEditing: (NSNotification *) notification
{
NSTableView *chapterTable = [notification object];
NSInteger column = [chapterTable editedColumn];
NSInteger row = [chapterTable editedRow];
NSInteger textMovement;
// Edit the cell in the next row, same column
row++;
textMovement = [[[notification userInfo] objectForKey:@"NSTextMovement"] integerValue];
if( textMovement == NSReturnTextMovement && row < [chapterTable numberOfRows] )
{
NSArray *info = [NSArray arrayWithObjects:chapterTable,
[NSNumber numberWithInteger:column], [NSNumber numberWithInteger:row], nil];
/* The delay is unimportant; editNextRow: won't be called until the responder
chain finishes because the event loop containing the timer is on this thread */
[self performSelector:@selector(editNextRow:) withObject:info afterDelay:0.0];
}
}
- (void)editNextRow: (id) objects
{
NSTableView *chapterTable = [objects objectAtIndex:0];
NSInteger column = [[objects objectAtIndex:1] integerValue];
NSInteger row = [[objects objectAtIndex:2] integerValue];
if( row >= 0 && row < [chapterTable numberOfRows] )
{
[chapterTable selectRowIndexes:[NSIndexSet indexSetWithIndex:row] byExtendingSelection:NO];
[chapterTable editColumn:column row:row withEvent:nil select:YES];
}
}
#pragma mark -
#pragma mark Chapter Files Import / Export
- (IBAction) browseForChapterFile: (id) sender
{
/* We get the current file name and path from the destination field here */
NSString *sourceDirectory = [[NSUserDefaults standardUserDefaults] stringForKey:@"LastDestinationDirectory"];
/* Open a panel to let the user choose the file */
NSOpenPanel *panel = [NSOpenPanel openPanel];
[panel setDirectoryURL:[NSURL fileURLWithPath:sourceDirectory]];
[panel setAllowedFileTypes:@[@"csv"]];
[panel beginSheetModalForWindow:[[self view] window] completionHandler:^(NSInteger result) {
NSArray *chaptersArray = nil; /* temp array for chapters */
NSMutableArray *chaptersMutableArray = nil; /* temp array for chapters */
NSString *chapterName = nil; /* temp string from file */
NSInteger chapters, i;
if (result == NSOKButton) /* if they click OK */
{
chapterName = [[NSString alloc] initWithContentsOfURL:[panel URL] encoding:NSUTF8StringEncoding error:NULL];
chaptersArray = [chapterName componentsSeparatedByString:@"\n"];
[chapterName release];
chaptersMutableArray = [[chaptersArray mutableCopy] autorelease];
chapters = [self numberOfRowsInTableView:fChapterTable];
if ([chaptersMutableArray count] > 0)
{
/* if last item is empty remove it */
if ([[chaptersMutableArray objectAtIndex:[chaptersArray count]-1] length] == 0)
{
[chaptersMutableArray removeLastObject];
}
}
/* if chapters in table is not equal to array count */
if ((unsigned int) chapters != [chaptersMutableArray count])
{
[panel close];
[[NSAlert alertWithMessageText:NSLocalizedString(@"Unable to load chapter file", @"Unable to load chapter file")
defaultButton:NSLocalizedString(@"OK", @"OK")
alternateButton:NULL
otherButton:NULL
informativeTextWithFormat:NSLocalizedString(@"%d chapters expected, %d chapters found in %@", @"%d chapters expected, %d chapters found in %@"),
chapters, [chaptersMutableArray count], [[panel URL] lastPathComponent]] runModal];
return;
}
/* otherwise, go ahead and populate table with array */
for (i=0; i 5)
{
/* avoid a segfault */
/* Get the Range.location of the first comma in the line and then put everything after that into chapterTitle */
NSRange firstCommaRange = [[chaptersMutableArray objectAtIndex:i] rangeOfString:@","];
NSString *chapterTitle = [[chaptersMutableArray objectAtIndex:i] substringFromIndex:firstCommaRange.location + 1];
/* Since we store our chapterTitle commas as "\," for the cli, we now need to remove the escaping "\" from the title */
chapterTitle = [chapterTitle stringByReplacingOccurrencesOfString:@"\\," withString:@","];
[self tableView:fChapterTable
setObjectValue:chapterTitle
forTableColumn:fChapterTableNameColumn
row:i];
}
else
{
[panel close];
[[NSAlert alertWithMessageText:NSLocalizedString(@"Unable to load chapter file", @"Unable to load chapter file")
defaultButton:NSLocalizedString(@"OK", @"OK")
alternateButton:NULL
otherButton:NULL
informativeTextWithFormat:NSLocalizedString(@"%@ was not formatted as expected.", @"%@ was not formatted as expected."), [[panel URL] lastPathComponent]] runModal];
[fChapterTable reloadData];
return;
}
}
[fChapterTable reloadData];
}
}];
}
- (IBAction) browseForChapterFileSave: (id) sender
{
NSString *destinationDirectory = [[NSUserDefaults standardUserDefaults] stringForKey:@"LastDestinationDirectory"];
/* Open a panel to let the user save to a file */
NSSavePanel *panel = [NSSavePanel savePanel];
[panel setAllowedFileTypes:@[@"csv"]];
[panel setDirectoryURL:[NSURL fileURLWithPath:destinationDirectory]];
//[panel setNameFieldStringValue:[[[fDstFile2Field stringValue] lastPathComponent] stringByDeletingPathExtension]];
[panel beginSheetModalForWindow:[[self view] window] completionHandler:^(NSInteger result) {
NSString *chapterName; /* pointer for string for later file-writing */
NSString *chapterTitle;
NSError *saveError = nil;
NSInteger chapters, i; /* ints for the number of chapters in the table and the loop */
if( result == NSOKButton ) /* if they clicked OK */
{
chapters = [self numberOfRowsInTableView:fChapterTable];
chapterName = [NSString string];
for (i=0; i