Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

367 lines (320 sloc) 10.833 kB
//
// InfoWindow.m
// Vienna
//
// Created by Steve on 4/21/06.
// Copyright (c) 2004-2006 Steve Palmer. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#import "InfoWindow.h"
#import "Database.h"
#import "CalendarExtensions.h"
#import "StringExtensions.h"
#import "AppController.h"
// Singleton controller for all info windows
static InfoWindowManager * _infoWindowManager = nil;
@interface InfoWindow (private)
-(id)initWithFolder:(int)folderId;
-(void)enableValidateButton;
-(void)updateFolder;
@end
@implementation InfoWindowManager
/* infoWindowManager
* Returns the shared instance of the InfoWindowManager
*/
+(InfoWindowManager *)infoWindowManager
{
@synchronized(self)
{
if (_infoWindowManager == nil)
_infoWindowManager = [[InfoWindowManager alloc] init];
}
return _infoWindowManager;
}
/* allocWithZone
* Override to ensure that only one instance can be initialised.
*/
+(id)allocWithZone:(NSZone *)zone
{
@synchronized(self)
{
if (_infoWindowManager == nil)
return [super allocWithZone:zone];
}
return _infoWindowManager;
}
/* copyWithZone
* Override to return ourself.
*/
-(id)copyWithZone:(NSZone *)zone
{
return self;
}
/* retain
* Override to return ourself.
*/
-(id)retain
{
return self;
}
/* retainCount
* Return NSUIntegerMax to denote an object that cannot be released.
*/
-(NSUInteger)retainCount
{
return NSUIntegerMax;
}
/* release
* Override to do nothing.
*/
-(oneway void)release
{
}
/* autorelease
* Override to return ourself
*/
-(id)autorelease
{
return self;
}
/* init
* Inits the single instance of the info window manager.
*/
-(id)init
{
NSAssert(_infoWindowManager == nil, @"");
if ((self = [super init]) != nil)
{
controllerList = [[NSMutableDictionary alloc] initWithCapacity:10];
NSNotificationCenter * nc = [NSNotificationCenter defaultCenter];
[nc addObserver:self selector:@selector(handleFolderDeleted:) name:@"MA_Notify_FolderDeleted" object:nil];
[nc addObserver:self selector:@selector(handleFolderChange:) name:@"MA_Notify_FolderNameChanged" object:nil];
[nc addObserver:self selector:@selector(handleFolderChange:) name:@"MA_Notify_FoldersUpdated" object:nil];
[nc addObserver:self selector:@selector(handleFolderChange:) name:@"MA_Notify_LoadFullHTMLChange" object:nil];
}
return self;
}
/* dealloc
*/
-(void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
[super dealloc];
}
/* handleFolderDeleted
* Deals with the case where a folder is deleted while its Info window is
* open. We close the info window and remove it from the list.
*/
-(void)handleFolderDeleted:(NSNotification *)nc
{
int folderId = [(NSNumber *)[nc object] intValue];
NSNumber * folderNumber = [NSNumber numberWithInt:folderId];
InfoWindow * infoWindow;
infoWindow = [controllerList objectForKey:folderNumber];
if (infoWindow != nil)
{
[infoWindow close];
[controllerList removeObjectForKey:folderNumber];
}
}
/* handleFolderChange
* Deals with the case where a folder's information is changed while its Info
* window is open. We send the window update folder message.
*/
-(void)handleFolderChange:(NSNotification *)nc
{
int folderId = [(NSNumber *)[nc object] intValue];
NSNumber * folderNumber = [NSNumber numberWithInt:folderId];
InfoWindow * infoWindow;
infoWindow = [controllerList objectForKey:folderNumber];
if (infoWindow != nil)
[infoWindow updateFolder];
}
/* showInfoWindowForFolder
* If there's an active info window for the specified folder then it is activated
* and brought to the front. Otherwise a new window is created for the folder.
*/
-(void)showInfoWindowForFolder:(int)folderId
{
NSNumber * folderNumber = [NSNumber numberWithInt:folderId];
InfoWindow * infoWindow;
infoWindow = [[controllerList objectForKey:folderNumber] retain];
if (infoWindow == nil)
{
infoWindow = [[InfoWindow alloc] initWithFolder:folderId];
[controllerList setObject:infoWindow forKey:folderNumber];
}
[infoWindow showWindow:[NSApp mainWindow]];
[infoWindow release];
}
@end
@implementation InfoWindow
/* init
* Just init the Info window.
*/
-(id)initWithFolder:(int)folderId
{
if ((self = [super initWithWindowNibName:@"InfoWindow"]) != nil)
infoFolderId = folderId;
return self;
}
/* dealloc
*/
-(void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
[super dealloc];
}
/* awakeFromNib
* Called after the NIB is loaded.
*/
-(void)awakeFromNib
{
[self updateFolder];
[self enableValidateButton];
[[self window] setInitialFirstResponder:urlField];
[[self window] setDelegate:self];
NSNotificationCenter * nc = [NSNotificationCenter defaultCenter];
[nc addObserver:self selector:@selector(handleUrlTextDidChange:) name:NSControlTextDidChangeNotification object:urlField];
[nc addObserver:self selector:@selector(handleFolderNameTextDidChange:) name:NSControlTextDidChangeNotification object:folderName];
[folderName setEditable:YES];
}
/* updateFolder
* Update the folder info in response to changes on the folder itself.
*/
-(void)updateFolder
{
Folder * folder = [[Database sharedDatabase] folderFromID:infoFolderId];
// Set the window caption
NSString * caption = [NSString stringWithFormat:NSLocalizedString(@"%@ Info", nil), [folder name]];
[[self window] setTitle:caption];
// Set the header details
[folderName setStringValue:[folder name]];
[folderImage setImage:[folder image]];
if ([[folder lastUpdate] isEqualToDate:[NSDate distantPast]])
[lastRefreshDate setStringValue:NSLocalizedString(@"Never", nil)];
else
[lastRefreshDate setStringValue:[[[folder lastUpdate] dateWithCalendarFormat:nil timeZone:nil] friendlyDescription]];
// Fill out the panels
[urlField setStringValue:[folder feedURL]];
[username setStringValue:[folder username]];
[password setStringValue:[folder password]];
[folderDescription setStringValue:[folder feedDescription]];
[folderSize setStringValue:[NSString stringWithFormat:NSLocalizedString(@"%u articles", nil), MAX(0, [folder countOfCachedArticles])]];
[folderUnread setStringValue:[NSString stringWithFormat:NSLocalizedString(@"%u unread", nil), [folder unreadCount]]];
[isSubscribed setState:([folder flags] & MA_FFlag_Unsubscribed) ? NSOffState : NSOnState];
[loadFullHTML setState:([folder flags] & MA_FFlag_LoadFullHTML) ? NSOnState : NSOffState];
}
/* urlFieldChanged
* Called when the URL field is changed.
*/
-(IBAction)urlFieldChanged:(id)sender
{
NSString * newUrl = [[urlField stringValue] trim];
[[Database sharedDatabase] setFolderFeedURL:infoFolderId newFeedURL:newUrl];
}
/* subscribedChanged
* Called when the subscribe button is changed.
*/
-(IBAction)subscribedChanged:(id)sender
{
if ([isSubscribed state] == NSOnState)
[[Database sharedDatabase] clearFolderFlag:infoFolderId flagToClear:MA_FFlag_Unsubscribed];
else
[[Database sharedDatabase] setFolderFlag:infoFolderId flagToSet:MA_FFlag_Unsubscribed];
[[NSNotificationCenter defaultCenter] postNotificationName:@"MA_Notify_FoldersUpdated" object:[NSNumber numberWithInt:infoFolderId]];
}
/* loadFullHTMLChanged
* Called when the loadFullHTML button is changed.
*/
-(IBAction)loadFullHTMLChanged:(id)sender
{
if ([loadFullHTML state] == NSOnState)
[[Database sharedDatabase] setFolderFlag:infoFolderId flagToSet:MA_FFlag_LoadFullHTML];
else
[[Database sharedDatabase] clearFolderFlag:infoFolderId flagToClear:MA_FFlag_LoadFullHTML];
[[NSNotificationCenter defaultCenter] postNotificationName:@"MA_Notify_LoadFullHTMLChange" object:[NSNumber numberWithInt:infoFolderId]];
}
/* handleUrlTextDidChange [delegate]
* This function is called when the contents of the url field is changed.
* We disable the Subscribe button if the input fields are empty or enable it otherwise.
*/
-(void)handleUrlTextDidChange:(NSNotification *)aNotification
{
[self enableValidateButton];
}
/* handleFolderNameTextDidChange [delegate]
* This function is called when the contents of the folder name field is changed.
* We update the folder's name.
*/
-(void)handleFolderNameTextDidChange:(NSNotification *)aNotification
{
[[Database sharedDatabase] setFolderName:infoFolderId newName:[folderName stringValue]];
}
/* enableValidateButton
* Disable the Validate button if the URL field is empty.
*/
-(void)enableValidateButton
{
[validateButton setEnabled:![[urlField stringValue] isBlank]];
}
/* validateURL
* Validate the URL in the text field.
*/
-(IBAction)validateURL:(id)sender
{
NSString * validatorPage = [[[NSApp delegate] standardURLs] valueForKey:@"FeedValidatorTemplate"];
if (validatorPage != nil)
{
NSString * url = [[urlField stringValue] trim];
// Escape any special query characters in the URL, because the URL itself will be in a query.
NSString * query = [[NSURL URLWithString:url] query];
if (query != nil)
{
NSMutableString * escapedQuery = [NSMutableString stringWithString:query];
[escapedQuery replaceOccurrencesOfString:@"&" withString:@"%26" options:0u range:NSMakeRange(0u, [escapedQuery length])];
[escapedQuery replaceOccurrencesOfString:@"=" withString:@"%3D" options:0u range:NSMakeRange(0u, [escapedQuery length])];
if (![query isEqualToString:escapedQuery])
{
url = [[url substringToIndex:[url rangeOfString:query].location] stringByAppendingString:escapedQuery];
}
}
NSString * validatorURL = [NSString stringWithFormat:validatorPage, url];
[[NSApp delegate] openURLFromString:validatorURL inPreferredBrowser:YES];
}
}
/* authenticationChanged
* Update the authentication information for this feed when the Update button is
* clicked.
*/
-(IBAction)authenticationChanged:(id)sender
{
NSString * usernameString = [[username stringValue] trim];
NSString * passwordString = [password stringValue];
Database * db = [Database sharedDatabase];
Folder * folder = [db folderFromID:infoFolderId];
[db setFolderUsername:[folder itemId] newUsername:usernameString];
[folder setPassword:passwordString];
}
/* windowShouldClose
* Commit the window's current first responder before closing.
*/
- (BOOL)windowShouldClose:(id)sender
{
// Set the first responder so any open edit fields get committed.
[[self window] makeFirstResponder:[self window]];
// Go ahead and close the window.
return YES;
}
@end
Jump to Line
Something went wrong with that request. Please try again.