-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:
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user