Archived
1

-Added Songtexte.com Lyrics Hoster

-Repositioned the load more results button into the outline view
-Improved the replacing of html escape characters
-Lyrics Hosters can now be dragged into a preferred order in the preference window
-Changed results outline's column ordering method
-Some code changes
-Replaced the Buttons in the lyrics pane with an action button
-Preferred order of lyrics hosters will now be saved
-Translation Improvements
This commit is contained in:
Kim Wittenburg
2012-06-24 14:22:37 +02:00
parent 98b0e70a8b
commit 41b1ef775c
27 changed files with 3611 additions and 2826 deletions

View File

@@ -10,46 +10,46 @@
@implementation MainController {
NSMutableArray *loadedResults;
id<LyricsHoster> currentHoster;
BOOL lyricsSelected;
NSInteger selectedSavePanelButton;
NSURL *saveFile;
iTunesApplication *iTunes;
SpotifyApplication *spotify;
Lyrics *currentLyrics;
int selectedRow;
iLyrics *ilyrics;
}
@synthesize iLyricsMenuItem;
@synthesize window;
@synthesize searchField;
@synthesize resultsOutline;
@synthesize loadMoreResultsButton;
@synthesize showPreviewCheckBox;
@synthesize previewPopover;
@synthesize previewTextArea;
@synthesize songLabel;
@synthesize artistLabel;
@synthesize sendToiTunesButton;
@synthesize downloadLyricsButton;
@synthesize lyricsArea;
-(id)init {
iTunes = [SBApplication applicationWithBundleIdentifier:@"com.apple.iTunes"];
spotify = [SBApplication applicationWithBundleIdentifier:@"com.spotify.client"];
loadedResults = [[NSMutableArray alloc] init];
currentHoster = [[Magistrix alloc] init];
ilyrics = [iLyrics sharediLyrics];
return [super init];
}
-(void)awakeFromNib {
[self lyricsSelectionChanged:resultsOutline];
}
#pragma mark -
#pragma mark Outline view Data Source and Delegate
-(NSInteger)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item {
return item == nil ? [loadedResults count] : 0;
return item == nil ? [loadedResults count] + 1 : 1;
}
-(id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)item {
if (index == [outlineView numberOfRows]-1) {
return NSLocalizedString(@"iLyrics.text.loadMoreResults", @"");
}
return [loadedResults objectAtIndex:index];
}
@@ -58,18 +58,41 @@
}
-(id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item {
if ([item isKindOfClass:[NSString class]]) {
return item;
}
if ([[tableColumn identifier] isEqualToString:@"song"]) {
return [item name];
} else {
} else if ([[tableColumn identifier] isEqualToString:@"artist"]) {
return [item artist];
} else {
return [[item loadedByHoster] name];
}
}
-(NSCell *)outlineView:(NSOutlineView *)outlineView dataCellForTableColumn:(NSTableColumn *)tableColumn item:(id)item {
if ([item isKindOfClass:[NSString class]]) {
NSPopUpButtonCell *cell = [[NSPopUpButtonCell alloc] init];
NSMenu *menu = [[NSMenu alloc] init];
NSMenuItem *titleItem = [[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"iLyrics.text.loadNextResultsFrom", @"") action:@selector(nothingResponsible:soDisable:titleItem:) keyEquivalent:@""];
[menu addItem:titleItem];
for (id<LyricsHoster> hoster in [ilyrics lyricsHosters]) {
NSMenuItem *menuItem = [[NSMenuItem alloc] initWithTitle:[NSString stringWithFormat:@" %@", [hoster name]] action:@selector(loadNextResults:) keyEquivalent:@""];
[menuItem setTarget:self];
[menu addItem:menuItem];
}
[cell setMenu:menu];
[cell setControlSize:NSMiniControlSize];
return cell;
}
return nil;
}
-(NSString *)outlineView:(NSOutlineView *)outlineView toolTipForCell:(NSCell *)cell rect:(NSRectPointer)rect tableColumn:(NSTableColumn *)tableColumn item:(id)item mouseLocation:(NSPoint)mouseLocation {
//item is an instance of SearchResult
[self shouldShowPreviewForCellRect:*rect searchResult:item];
if ([item isKindOfClass:[SearchResult class]]) {
[self shouldShowPreviewForCellRect:*rect searchResult:item];
}
return nil;
}
@@ -77,11 +100,7 @@
#pragma mark Responding to Lyrics Search
- (IBAction)getCurrentiTunesSong:(id)sender {
iTunesTrack *track = [iTunes currentTrack];
if (track == nil) {
NSBeginAlertSheet(NSLocalizedString(@"iTunes.messages.iTunesIdle.title", @""), NSLocalizedString(@"OK", @""), nil, nil, window, nil, nil, nil, nil, NSLocalizedString(@"iTunes.messages.iTunesIdle.detail", @""));
return;
}
iTunesTrack *track = [[ilyrics iTunes] currentTrack];
NSString *name = [track name];
NSString *artist = [track artist];
if (name == nil) {
@@ -94,7 +113,7 @@
}
- (IBAction)getCurrentSpotifySong:(id)sender {
SpotifyTrack *track = [spotify currentTrack];
SpotifyTrack *track = [[ilyrics spotify] currentTrack];
NSString *name = [track name];
NSString *artist = [track artist];
if (name == nil) {
@@ -109,36 +128,97 @@
- (IBAction)startNewSearch:(id)sender {
[self resetLoadedResults:sender];
if ([[searchField stringValue] length] > 0) {
[currentHoster startNewSearchForQuery:[searchField stringValue]];
[self loadNextResults:sender];
for (id<LyricsHoster> hoster in [ilyrics lyricsHosters]) {
[hoster startNewSearchForQuery:[searchField stringValue]];
}
//Load first results
BOOL networkError = YES;
BOOL resultsFound = NO;
for (id<LyricsHoster> hoster in [ilyrics lyricsHosters]) {
NSArray *results = [hoster nextResults];
if (results) {
networkError = NO;
if ([results count] > 0) {
resultsFound = YES;
[loadedResults addObjectsFromArray:results];
[resultsOutline reloadData];
break;
}
} else {
networkError = networkError && YES;
}
}
if (networkError) {
[self presentNetworkErrorWithHoster:nil];
} else if (!resultsFound) {
[self presentNoResultsErrorWithHoster:nil];
}
}
[self lyricsSelectionChanged:resultsOutline];
}
- (IBAction)loadNextResults:(id)sender {
NSArray *nextResults = [currentHoster nextResults];
[loadMoreResultsButton setEnabled:[currentHoster hasMoreResults]];
- (void)loadNextResults:(id)sender{
[self loadNextResultsFromHoster:[ilyrics hosterWithName:[sender title]]];
}
- (void) loadNextResultsFromHoster: (id<LyricsHoster>) hoster {
if (hoster == nil) {
return;
}
NSArray *nextResults = [hoster nextResults];
if (nextResults == nil) {
NSRunCriticalAlertPanel(NSLocalizedString(@"Hoster.messages.networkOrQueryError.title", @""), NSLocalizedString(@"Hoster.messages.networkOrQueryError.detail", @""), NSLocalizedString(@"OK", @""), nil, nil);
[self presentNetworkErrorWithHoster:hoster];
return;
}
if ([nextResults count] == 0) {
NSRunAlertPanel(NSLocalizedString(@"Hoster.messages.noResults.title", @""), NSLocalizedString(@"Hoster.messages.noResults.detail", @""), NSLocalizedString(@"OK", @""), nil, nil);
[self presentNoResultsErrorWithHoster:hoster];
return;
}
[loadedResults addObjectsFromArray:nextResults];
[resultsOutline reloadData];
}
-(void)presentNetworkErrorWithHoster: (id<LyricsHoster>)hoster {
NSString *title;
NSString *detail;
if (hoster) {
title = [NSLocalizedString(@"Hoster.messages.networkOrQueryError.title", @"") stringByReplacingOccurrencesOfString:@"%hoster%" withString:[hoster name]];
detail = [NSLocalizedString(@"Hoster.messages.networkOrQueryError.detail", @"") stringByReplacingOccurrencesOfString:@"%hoster%" withString:[hoster name]];
} else {
title = NSLocalizedString(@"iLyrics.messages.networkOrQueryError.title", @"");
detail = NSLocalizedString(@"iLyrics.messages.networkOrQueryError.detail", @"");
}
NSRunCriticalAlertPanel(title, detail, NSLocalizedString(@"OK", @""), nil, nil);
}
-(void)presentNoResultsErrorWithHoster: (id<LyricsHoster>)hoster {
NSString *title;
NSString *detail;
if (hoster) {
title = [NSLocalizedString(@"Hoster.messages.noResults.title", @"") stringByReplacingOccurrencesOfString:@"%hoster%" withString:[hoster name]];
detail = [NSLocalizedString(@"Hoster.messages.noResults.detail", @"") stringByReplacingOccurrencesOfString:@"%hoster%" withString:[hoster name]];
} else {
title = NSLocalizedString(@"iLyrics.messages.noResults.title", @"") ;
detail = NSLocalizedString(@"iLyrics.messages.noResults.detail", @"");
}
NSRunAlertPanel(title, detail, NSLocalizedString(@"OK", @""), nil, nil);
}
-(IBAction)resetLoadedResults:(id)sender {
[currentHoster resetLoadedResults];
for (id<LyricsHoster> hoster in [ilyrics lyricsHosters]) {
[hoster resetLoadedResults];
}
[loadedResults removeAllObjects];
[resultsOutline reloadData];
[loadMoreResultsButton setEnabled:[currentHoster hasMoreResults]];
[self lyricsSelectionChanged:resultsOutline];
}
- (IBAction)lyricsSelectionChanged:(NSOutlineView *)sender {
int index = [sender selectedRow];
if (index == [sender numberOfRows]-1) {
index = -1;
}
if (index < 0) {
lyricsSelected = NO;
currentLyrics = nil;
@@ -151,10 +231,12 @@
if (selectedRow != index) {
lyricsSelected = YES;
SearchResult *result = [loadedResults objectAtIndex:index];
Lyrics *lyrics = [currentHoster lyricsBySearchResult:result];
Lyrics *lyrics = [[result loadedByHoster] lyricsBySearchResult:result];
currentLyrics = lyrics;
if (lyrics == nil) {
NSRunCriticalAlertPanel(NSLocalizedString(@"Hoster.messages.networkError.title", @""), NSLocalizedString(@"Hoster.messages.networkError.detail", @""), NSLocalizedString(@"OK", @""), nil, nil);
NSString *title = [NSLocalizedString(@"Hoster.messages.networkOrQueryError.title", @"") stringByReplacingOccurrencesOfString:@"%hoster%" withString:[[result loadedByHoster] name]];
NSString *detail = [NSLocalizedString(@"Hoster.messages.networkOrQueryError.detail", @"") stringByReplacingOccurrencesOfString:@"%hoster%" withString:[[result loadedByHoster] name]];
NSRunCriticalAlertPanel(title, detail, NSLocalizedString(@"OK", @""), nil, nil);
NSString *noNetwork = NSLocalizedString(@"Hoster.text.noNetwork", @"");
[songLabel setStringValue:noNetwork];
[artistLabel setStringValue:noNetwork];
@@ -176,14 +258,14 @@
NSString *lyrics = [result preview];
if (lyrics) {
rect.size.width = [resultsOutline frame].size.width;
[previewTextArea setString:lyrics];
[previewTextArea setString:lyrics==nil?NSLocalizedString(@"Hoster.text.noPreviewAvailable", @""):lyrics];
[previewPopover showRelativeToRect:rect ofView:resultsOutline preferredEdge:NSMaxXEdge];
}
}
}
- (IBAction)sendLyricsToiTunes:(id)sender {
iTunesTrack *track = [iTunes currentTrack];
iTunesTrack *track = [[ilyrics iTunes] currentTrack];
NSString *name = [track name];
if (name == nil) {
NSBeginAlertSheet(NSLocalizedString(@"iTunes.messages.noTrackPlaying.title", @""), NSLocalizedString(@"OK", @""), nil, nil, window, nil, nil, nil, nil, NSLocalizedString(@"iTunes.messages.noTrackPlaying.detail", @""));
@@ -199,7 +281,7 @@
- (void)replaceLyricsSheetDidEnd:(NSWindow *)sheet returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo {
if (returnCode == NSAlertDefaultReturn) {
iTunesTrack *track = [iTunes currentTrack];
iTunesTrack *track = [[ilyrics iTunes] currentTrack];
[track setLyrics:[lyricsArea string]];
[GrowlApplicationBridge notifyWithTitle:NSLocalizedString(@"Growl.messages.lyricsSent.title", @"") description:[NSString stringWithFormat:NSLocalizedString(@"Growl.messages.lyricsSent.detail", @""), [track name]] notificationName:@"Lyrics sent to iTunes" iconData:nil priority:0 isSticky:NO clickContext:nil];
}
@@ -225,8 +307,8 @@
if (row < 0) {
row = [resultsOutline selectedRow];
}
NSURL *link = [[loadedResults objectAtIndex:row] link];
[[NSWorkspace sharedWorkspace] openURL:link];
SearchResult *result = [loadedResults objectAtIndex:row];
[[result loadedByHoster] showInBrowser:result];
}
-(void) savePanelDidClose: (NSNotification *) notification{
@@ -234,7 +316,7 @@
if (selectedSavePanelButton == NSOKButton) {
BOOL success = [[[lyricsArea string] dataUsingEncoding:NSUTF8StringEncoding] writeToURL:saveFile atomically:NO];
if (!success) {
NSBeginAlertSheet(NSLocalizedString(@"messages.error.saveLyrics.title", @""), NSLocalizedString(@"OK", @""), nil, nil, window, nil, nil, nil, nil, NSLocalizedString(@"messages.error.saveLyrics.detail", @""));
NSBeginAlertSheet(NSLocalizedString(@"iLyrics.messages.error.saveLyrics.title", @""), NSLocalizedString(@"OK", @""), nil, nil, window, nil, nil, nil, nil, NSLocalizedString(@"iLyrics.messages.error.saveLyrics.detail", @""));
} else {
[GrowlApplicationBridge notifyWithTitle:NSLocalizedString(@"Growl.messages.lyricsSaved.title", @"") description:[NSString stringWithFormat:NSLocalizedString(@"Growl.messages.lyricsSaved.detail", @""), [saveFile path]] notificationName:@"Lyrics saved to File" iconData:nil priority:0 isSticky:NO clickContext:nil];
}
@@ -270,6 +352,11 @@
#pragma mark window delegate
-(BOOL)validateMenuItem:(NSMenuItem *)menuItem {
SEL action = [menuItem action];
if (action == @selector(loadNextResults:)) {
BOOL hasMore = [[ilyrics hosterWithName:[menuItem title]] hasMoreResults];
return hasMore;
}
return [self validateUserInterfaceItem:menuItem];
}
@@ -280,28 +367,28 @@
-(BOOL)validateUserInterfaceItem:(id<NSValidatedUserInterfaceItem>)item {
SEL action = [item action];
if (action == @selector(downloadLyrics:)) {
[downloadLyricsButton setEnabled:lyricsSelected];
return lyricsSelected;
}
if (action == @selector(sendLyricsToiTunes:)) {
BOOL enabled = lyricsSelected && [iTunes isRunning];
[sendToiTunesButton setEnabled:enabled];
BOOL enabled = lyricsSelected && [[ilyrics iTunes] isRunning];
return enabled;
}
if (action == @selector(getCurrentiTunesSong:)) {
return [iTunes isRunning];
return [[ilyrics iTunes] isRunning];
}
if (action == @selector(getCurrentSpotifySong:)) {
return [spotify isRunning];
return [[ilyrics spotify] isRunning];
}
if (action == @selector(showPreview:)) {
return [resultsOutline clickedRow] >= 0;
}
if (action == @selector(showLyricsInBrowser:)) {
if ([resultsOutline clickedRow] >= 0) {
return YES;
} else if ([resultsOutline selectedRow] >= 0) {
return YES;
SearchResult *result = [loadedResults objectAtIndex:[resultsOutline clickedRow]];
return [[result loadedByHoster] canShowInBrowser:result];;
} else if ([resultsOutline selectedRow] >= 0) {
SearchResult *result = [loadedResults objectAtIndex:[resultsOutline selectedRow]];
return [[result loadedByHoster] canShowInBrowser:result];;
} else {
return NO;
}