Switch to NSFileWrapper based documents

This commit is contained in:
Matthias Neeracher 2006-10-29 07:49:33 +00:00
parent 6f67b7df9e
commit a970adcbc9
10 changed files with 156 additions and 57 deletions

Binary file not shown.

View File

@ -22,12 +22,13 @@
<key>CFBundleTypeRole</key> <key>CFBundleTypeRole</key>
<string>Editor</string> <string>Editor</string>
<key>LSTypeIsPackage</key> <key>LSTypeIsPackage</key>
<false/> <true/>
<key>NSDocumentClass</key> <key>NSDocumentClass</key>
<string>VLDocument</string> <string>VLDocument</string>
<key>NSExportableAs</key> <key>NSExportableAs</key>
<array> <array>
<string>VLLilypondType</string> <string>VLLilypondType</string>
<string>VLMusicXMLType</string>
</array> </array>
<key>NSPersistentStoreTypeKey</key> <key>NSPersistentStoreTypeKey</key>
<string>XML</string> <string>XML</string>
@ -50,6 +51,20 @@
<key>NSPersistentStoreTypeKey</key> <key>NSPersistentStoreTypeKey</key>
<string>Binary</string> <string>Binary</string>
</dict> </dict>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>xml</string>
</array>
<key>CFBundleTypeName</key>
<string>VLMusicXMLType</string>
<key>CFBundleTypeRole</key>
<string>None</string>
<key>LSTypeIsPackage</key>
<false/>
<key>NSPersistentStoreTypeKey</key>
<string>Binary</string>
</dict>
</array> </array>
<key>CFBundleExecutable</key> <key>CFBundleExecutable</key>
<string>VocalEasel</string> <string>VocalEasel</string>

Binary file not shown.

View File

@ -67,14 +67,13 @@
char line[1000]; char line[1000];
FILE * output = popen([command UTF8String], "r"); FILE * output = popen([command UTF8String], "r");
if (fgets(line, 1000, output)) { if (fgets(line, 1000, output)) {
fprintf(stderr, "Line %s", line);
size_t len = strlen(line); size_t len = strlen(line);
if (len && line[len-1]=='\n') { if (len && line[len-1]=='\n') {
line[len-1] = 0; line[len-1] = 0;
return [NSString stringWithUTF8String:line]; return [NSString stringWithUTF8String:line];
} }
} else } else
NSLog(@"Failed command: %@ (%d)\n", command, errno); NSLog(@"Failed command: %@ %s (%d)\n", command, feof(output) ? "EOF" : "Error", errno);
pclose(output); pclose(output);
return nil; return nil;
} }
@ -181,9 +180,4 @@
} }
} }
- (BOOL)applicationShouldOpenUntitledFile:(NSApplication *)sender
{
return NO;
}
@end @end

View File

@ -32,21 +32,29 @@
return self; return self;
} }
- (void) close
{
[logWin close];
[pdfWin close];
[super close];
}
- (void) dealloc - (void) dealloc
{ {
delete song; delete song;
[lilypondTemplate release];
[songTitle release];
[songLyricist release];
[songComposer release];
[songArranger release];
[super dealloc]; [super dealloc];
} }
- (void)removeWindowController:(NSWindowController *)win
{
if (win == logWin)
logWin = nil;
else if (win == pdfWin)
pdfWin = nil;
[super removeWindowController:win];
}
- (VLLogWindow *)logWin - (VLLogWindow *)logWin
{ {
if (!logWin) { if (!logWin) {
@ -141,12 +149,14 @@
[self updateChangeCount:NSChangeDone]; [self updateChangeCount:NSChangeDone];
} }
- (NSData *)dataOfType:(NSString *)typeName error:(NSError **)outError - (NSFileWrapper *)fileWrapperOfType:(NSString *)typeName error:(NSError **)outError
{ {
if ([typeName isEqual:@"VLNativeType"]) { if ([typeName isEqual:@"VLNativeType"]) {
return [self XMLDataWithError:outError]; return [self XMLFileWrapperWithError:outError flat:NO];
} else if ([typeName isEqual:@"VLMusicXMLType"]) {
return [self XMLFileWrapperWithError:outError flat:YES];
} else if ([typeName isEqual:@"VLLilypondType"]) { } else if ([typeName isEqual:@"VLLilypondType"]) {
return [self lilypondDataWithError:outError]; return [self lilypondFileWrapperWithError:outError];
} else { } else {
if (outError) if (outError)
*outError = [NSError errorWithDomain:NSCocoaErrorDomain *outError = [NSError errorWithDomain:NSCocoaErrorDomain
@ -156,10 +166,10 @@
} }
} }
- (BOOL)readFromData:(NSData *)data ofType:(NSString *)typeName error:(NSError **)outError - (BOOL)readFromFileWrapper:(NSFileWrapper *)wrapper ofType:(NSString *)typeName error:(NSError **)outError
{ {
if ([typeName isEqual:@"VLNativeType"]) { if ([typeName isEqual:@"VLNativeType"]) {
return [self readFromXMLData:data error:outError]; return [self readFromXMLFileWrapper:wrapper error:outError];
} else { } else {
if (outError) if (outError)
*outError = [NSError errorWithDomain:NSCocoaErrorDomain *outError = [NSError errorWithDomain:NSCocoaErrorDomain
@ -169,14 +179,12 @@
} }
} }
- (IBAction) performEngrave:(id)sender
- (IBAction) engrave:(id)sender
{ {
NSTask * lilypondTask = [[NSTask alloc] init]; NSTask * lilypondTask = [[NSTask alloc] init];
NSString * path = [[self fileURL] path]; NSString * path = [[self fileURL] path];
NSString * root = NSString * base = [[path lastPathComponent]
[[path lastPathComponent] stringByDeletingPathExtension]; stringByDeletingPathExtension];
NSString * tmpDir = @"/var/tmp";
NSBundle * mainBundle = [NSBundle mainBundle]; NSBundle * mainBundle = [NSBundle mainBundle];
// //
@ -184,21 +192,20 @@
// //
NSError * err; NSError * err;
[self writeToURL: [self writeToURL:
[NSURL fileURLWithPath: [NSURL fileURLWithPath:[[path stringByAppendingPathComponent:base]
[[tmpDir stringByAppendingPathComponent:root] stringByAppendingPathExtension:@"ly"]]
stringByAppendingPathExtension:@"ly"]]
ofType:@"VLLilypondType" error:&err]; ofType:@"VLLilypondType" error:&err];
NSPipe * pipe = [NSPipe pipe]; NSPipe * pipe = [NSPipe pipe];
NSString * tool = NSString * tool =
[[NSUserDefaults standardUserDefaults] [[NSUserDefaults standardUserDefaults]
stringForKey:@"VLLilypondPath"]; stringForKey:@"VLLilypondPath"];
NSArray * arguments = [NSArray arrayWithObjects:tool, root, nil]; NSArray * arguments = [NSArray arrayWithObjects:tool, base, nil];
[[NSNotificationCenter defaultCenter] [[NSNotificationCenter defaultCenter]
addObserver:self selector:@selector(engraveDone:) addObserver:self selector:@selector(engraveDone:)
name:NSTaskDidTerminateNotification object:lilypondTask]; name:NSTaskDidTerminateNotification object:lilypondTask];
[lilypondTask setCurrentDirectoryPath:tmpDir]; [lilypondTask setCurrentDirectoryPath:path];
[lilypondTask setStandardOutput: pipe]; [lilypondTask setStandardOutput: pipe];
[lilypondTask setStandardError: pipe]; [lilypondTask setStandardError: pipe];
[lilypondTask setArguments: arguments]; [lilypondTask setArguments: arguments];
@ -216,26 +223,45 @@
[[NSNotificationCenter defaultCenter] removeObserver: self]; [[NSNotificationCenter defaultCenter] removeObserver: self];
int status = [[notification object] terminationStatus]; int status = [[notification object] terminationStatus];
if (!status) { if (!status) {
NSFileManager * fileManager = [NSFileManager defaultManager];
NSString * path = [[self fileURL] path];
NSString * root =
[[path lastPathComponent] stringByDeletingPathExtension];
NSString * tmpDir = @"/var/tmp";
NSString * dstDir = [path stringByDeletingLastPathComponent];
NSString * pdf =
[root stringByAppendingPathExtension:@"pdf"];
[fileManager
removeFileAtPath:[dstDir stringByAppendingPathComponent:pdf]
handler:nil];
[fileManager
movePath:[tmpDir stringByAppendingPathComponent:pdf]
toPath:[dstDir stringByAppendingPathComponent:pdf]
handler:nil];
[[self pdfWin] showWindow: self]; [[self pdfWin] showWindow: self];
[pdfWin reloadPDF]; [pdfWin reloadPDF];
} else {
NSBeep();
} }
} }
- (void) engrave:(NSDocument *)doc didSave:(BOOL)didSave contextInfo:(void *)contextInfo
{
if (didSave)
[self performEngrave:(id)contextInfo];
}
- (void)engrave:(NSAlert *)alert returnCode:(int)returnCode contextInfo:(id)sender
{
if (returnCode == NSAlertDefaultReturn) {
[[alert window] orderOut:self];
[self saveDocumentWithDelegate:self
didSaveSelector:@selector(engrave:didSave:contextInfo:)
contextInfo:sender];
}
}
- (IBAction) engrave:(id)sender
{
if ([self isDocumentEdited]) {
NSAlert * alert =
[NSAlert alertWithMessageText:@"Do you want to save your changes?"
defaultButton:[self fileURL] ? @"Save" : @"Save..."
alternateButton:@"Cancel" otherButton:nil
informativeTextWithFormat:@"You need to save your document before typesetting."];
[alert beginSheetModalForWindow:[sheetWin window]
modalDelegate:self
didEndSelector:@selector(engrave:returnCode:contextInfo:)
contextInfo:sender];
} else
[self performEngrave:sender];
}
- (IBAction) showOutput:(id)sender - (IBAction) showOutput:(id)sender
{ {
[[self pdfWin] showWindow:sender]; [[self pdfWin] showWindow:sender];

View File

@ -11,6 +11,6 @@
@interface VLDocument (Lilypond) @interface VLDocument (Lilypond)
- (NSData *)lilypondDataWithError:(NSError **)outError; - (NSFileWrapper *)lilypondFileWrapperWithError:(NSError **)outError;
@end @end

View File

@ -131,4 +131,16 @@ const char * sKeyNames[] = {
return [ly dataUsingEncoding:enc]; return [ly dataUsingEncoding:enc];
} }
- (NSFileWrapper *)lilypondFileWrapperWithError:(NSError **)outError
{
NSData * data = [self lilypondDataWithError:outError];
if (!data)
return nil;
else
return [[[NSFileWrapper alloc]
initRegularFileWithContents:data]
autorelease];
}
@end @end

View File

@ -36,13 +36,36 @@ static NSString* sZoomOutToolbarItemIdentifier = @"Zoom Out Toolbar Item Identif
- (void)reloadPDF - (void)reloadPDF
{ {
if (pdfView) { if (pdfView) {
NSString * inString = [[[self document] fileURL] path]; NSString * path = [[[self document] fileURL] path];
NSString * baseString = [inString stringByDeletingPathExtension]; if (!path)
NSString * outString = [baseString stringByAppendingPathExtension: @"pdf"]; return;
NSURL * pdfURL = [NSURL fileURLWithPath: outString]; NSFileWrapper * wrapper =
PDFDocument * pdfDoc = [[[PDFDocument alloc] initWithURL: pdfURL] autorelease]; [[[NSFileWrapper alloc] initWithPath:path] autorelease];
[(PDFView *)pdfView setDocument: pdfDoc]; //
[pdfView setNeedsDisplay:YES]; // Find newest pdf file
//
NSEnumerator * w = [[wrapper fileWrappers] objectEnumerator];
NSString * pdfPath = nil;
NSDate * pdfDate = nil;
while (wrapper = [w nextObject]) {
NSString * path = [wrapper filename];
if (![[path pathExtension] isEqual:@"pdf"])
continue;
NSDate * date = [[wrapper fileAttributes]
objectForKey:NSFileModificationDate];
if (!pdfPath || [date compare:pdfDate]==NSOrderedAscending) {
pdfPath = path;
pdfDate = date;
}
}
if (pdfPath) {
NSURL * pdfURL =
[NSURL fileURLWithPath:[path stringByAppendingPathComponent:pdfPath]];
PDFDocument * pdfDoc =
[[[PDFDocument alloc] initWithURL:pdfURL] autorelease];
[(PDFView *)pdfView setDocument: pdfDoc];
[pdfView setNeedsDisplay:YES];
}
} }
} }

View File

@ -11,7 +11,7 @@
@interface VLDocument (XML) @interface VLDocument (XML)
- (NSData *)XMLDataWithError:(NSError **)outError; - (NSFileWrapper *)XMLFileWrapperWithError:(NSError **)outError flat:(BOOL)flat;
- (BOOL)readFromXMLData:(NSData *)data error:(NSError **)outError; - (BOOL)readFromXMLFileWrapper:(NSFileWrapper *)wrapper error:(NSError **)outError;
@end @end

View File

@ -283,6 +283,28 @@ const char * sSteps = "C DbD EbE F GbG AbA BbB ";
return [doc XMLDataWithOptions:NSXMLNodePrettyPrint|NSXMLNodeCompactEmptyElement]; return [doc XMLDataWithOptions:NSXMLNodePrettyPrint|NSXMLNodeCompactEmptyElement];
} }
- (NSFileWrapper *)XMLFileWrapperWithError:(NSError **)outError flat:(BOOL)flat;
{
NSData * contents = [self XMLDataWithError:outError];
if (!contents) {
return nil;
} else if (flat) {
return [[[NSFileWrapper alloc]
initRegularFileWithContents:contents]
autorelease];
} else {
NSFileWrapper * wrap = [[[NSFileWrapper alloc]
initDirectoryWithFileWrappers:
[NSDictionary dictionary]]
autorelease];
[wrap addRegularFileWithContents:contents
preferredFilename:@"Song"];
return wrap;
}
}
- (BOOL)readPropsFromAttributes:(NSXMLElement*)attr error:(NSError **)outError - (BOOL)readPropsFromAttributes:(NSXMLElement*)attr error:(NSError **)outError
{ {
VLProperties & prop = song->fProperties.front(); VLProperties & prop = song->fProperties.front();
@ -432,4 +454,11 @@ int8_t sStepToPitch[] = {
return YES; return YES;
} }
- (BOOL)readFromXMLFileWrapper:(NSFileWrapper *)wrapper error:(NSError **)outError
{
return [self readFromXMLData: [[[wrapper fileWrappers] objectForKey:@"Song"]
regularFileContents]
error:outError];
}
@end @end