Skip to content

Commit

Permalink
Improved add projects dialog; combox box remembers all urls and alrea…
Browse files Browse the repository at this point in the history
…dy added projects are displayed in grey.
  • Loading branch information
erikd committed Sep 24, 2007
1 parent 61b7d75 commit 1ef697e
Show file tree
Hide file tree
Showing 9 changed files with 175 additions and 59 deletions.
39 changes: 32 additions & 7 deletions Classes/CCMPreferencesController.m
Expand Up @@ -21,7 +21,7 @@ - (NSURL *)getServerURL
serverUrl = [@"http://" stringByAppendingString:serverUrl];
[serverUrlComboBox setStringValue:serverUrl];
}
NSArray *allFilenames = [NSArray arrayWithObjects:@"cctray.xml", @"xml.jsp", @"XmlStatusReport.aspx", @"XmlStatusReport.aspx", @"", nil];
NSArray *allFilenames = [NSArray arrayWithObjects:@"cctray.xml", @"xml", @"XmlStatusReport.aspx", @"XmlStatusReport.aspx", @"", nil];
NSString *filename = [allFilenames objectAtIndex:[serverTypeMatrix selectedTag]];
if(([serverUrl length] > 0) && (![serverUrl hasSuffix:filename]))
{
Expand Down Expand Up @@ -71,26 +71,46 @@ - (void)switchPreferencesPane:(id)sender

- (void)addProjects:(id)sender
{
NSArray *servers = [defaultsManager servers];
if([servers count] > 0)
NSArray *urls = [defaultsManager serverURLHistory];
if([urls count] > 0)
{
[serverUrlComboBox removeAllItems];
[serverUrlComboBox addItemsWithObjectValues:(id)[[servers collect] url]];
urls = [urls sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)];
[serverUrlComboBox addItemsWithObjectValues:urls];
}
[sheetTabView selectFirstTabViewItem:self];
[NSApp beginSheet:addProjectsSheet modalForWindow:preferencesWindow modalDelegate:self
didEndSelector:@selector(addProjectsSheetDidEnd:returnCode:contextInfo:) contextInfo:nil];
}

- (NSArray *)convertProjectInfos:(NSArray *)projectInfos withServerUrl:(NSString *)serverUrl
{
NSMutableArray *result = [NSMutableArray array];
NSEnumerator *projectInfoEnum = [projectInfos objectEnumerator];
NSDictionary *projectInfo;
while((projectInfo = [projectInfoEnum nextObject]) != nil)
{
NSMutableDictionary *listEntry = [NSMutableDictionary dictionary];
NSString *projectName = [projectInfo objectForKey:@"name"];
[listEntry setObject:projectName forKey:@"name"];
if([defaultsManager projectListContainsProject:projectName onServerWithURL:serverUrl])
[listEntry setObject:[NSColor disabledControlTextColor] forKey:@"textColor"];
[result addObject:listEntry];
}
return result;
}


- (void)chooseProjects:(id)sender
{
@try
{
[testServerProgressIndicator startAnimation:self];
CCMConnection *connection = [[[CCMConnection alloc] initWithURL:[self getServerURL]] autorelease];
NSURL *serverUrl = [self getServerURL];
CCMConnection *connection = [[[CCMConnection alloc] initWithURL:serverUrl] autorelease];
NSArray *projectInfos = [connection getProjectInfos];
[testServerProgressIndicator stopAnimation:self];
[chooseProjectsViewController setContent:projectInfos];
[chooseProjectsViewController setContent:[self convertProjectInfos:projectInfos withServerUrl:[serverUrl absoluteString]]];
[sheetTabView selectNextTabViewItem:self];
}
@catch(NSException *exception)
Expand All @@ -111,7 +131,12 @@ - (void)addProjectsSheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode cont
if(returnCode == 0)
return;

[defaultsManager updateWithProjectInfos:[chooseProjectsViewController selectedObjects] withServerURL:[self getServerURL]];
NSEnumerator *selectionEnum = [[chooseProjectsViewController selectedObjects] objectEnumerator];
NSDictionary *entry;
NSString *serverUrl = [[self getServerURL] absoluteString];
while((entry = [selectionEnum nextObject]) != nil)
[defaultsManager addProject:[entry objectForKey:@"name"] onServerWithURL:serverUrl];
[defaultsManager addServerURLToHistory:serverUrl];
[self preferencesChanged:self];
}

Expand Down
8 changes: 7 additions & 1 deletion Classes/CCMUserDefaultsManager.h
Expand Up @@ -9,10 +9,14 @@

- (int)pollInterval;

- (void)updateWithProjectInfos:(NSArray *)projectInfos withServerURL:(NSURL *)serverUrl;
- (void)addProject:(NSString *)projectName onServerWithURL:(NSString *)serverUrl;
- (BOOL)projectListContainsProject:(NSString *)projectName onServerWithURL:(NSString *)serverUrl;
- (NSArray *)projectListEntries;
- (NSArray *)servers;

- (void)addServerURLToHistory:(NSString *)serverUrl;
- (NSArray *)serverURLHistory;

@end


Expand All @@ -21,3 +25,5 @@ extern NSString *CCMDefaultsPollIntervalKey;
extern NSString *CCMDefaultsProjectListKey;
extern NSString *CCMDefaultsProjectEntryNameKey;
extern NSString *CCMDefaultsProjectEntryServerUrlKey;

extern NSString *CCMDefaultsServerUrlHistoryKey;
58 changes: 45 additions & 13 deletions Classes/CCMUserDefaultsManager.m
@@ -1,12 +1,14 @@

#import "CCMUserDefaultsManager.h"
#import "CCMServer.h"
#import "NSArray+CCMAdditions.h"
#import <EDCommon/EDCommon.h>

NSString *CCMDefaultsProjectListKey = @"Projects";
NSString *CCMDefaultsProjectEntryNameKey = @"projectName";
NSString *CCMDefaultsProjectEntryServerUrlKey = @"serverUrl";
NSString *CCMDefaultsPollIntervalKey = @"PollInterval";
NSString *CCMDefaultsServerUrlHistoryKey = @"ServerHistory";


@implementation CCMUserDefaultsManager
Expand All @@ -23,24 +25,27 @@ - (int)pollInterval
return interval;
}

- (void)updateWithProjectInfos:(NSArray *)projectInfos withServerURL:(NSURL *)serverUrl
- (NSDictionary *)createEntryWithProject:(NSString *)projectName andURL:(NSString *)serverUrl
{
return [NSDictionary dictionaryWithObjectsAndKeys: projectName, CCMDefaultsProjectEntryNameKey,
serverUrl, CCMDefaultsProjectEntryServerUrlKey, nil];
}

- (void)addProject:(NSString *)projectName onServerWithURL:(NSString *)serverUrl
{
if([self projectListContainsProject:projectName onServerWithURL:serverUrl])
return;
NSMutableArray *mutableList = [[[self projectListEntries] mutableCopy] autorelease];

NSEnumerator *projectInfoEnum = [projectInfos objectEnumerator];
NSDictionary *projectInfo;
while((projectInfo = [projectInfoEnum nextObject]) != nil)
{
NSDictionary *projectListEntry = [NSDictionary dictionaryWithObjectsAndKeys:
[projectInfo objectForKey:@"name"], CCMDefaultsProjectEntryNameKey,
[serverUrl absoluteString], CCMDefaultsProjectEntryServerUrlKey, nil];
if(![mutableList containsObject:projectListEntry])
[mutableList addObject:projectListEntry];
}
[mutableList addObject:[self createEntryWithProject:projectName andURL:serverUrl]];
NSData *data = [NSArchiver archivedDataWithRootObject:[mutableList copy]];
[userDefaults setObject:data forKey:CCMDefaultsProjectListKey];
}

- (BOOL)projectListContainsProject:(NSString *)projectName onServerWithURL:(NSString *)serverUrl
{
return [[self projectListEntries] containsObject:[self createEntryWithProject:projectName andURL:serverUrl]];
}

- (NSArray *)projectListEntries
{
NSData *defaultsData = [userDefaults dataForKey:CCMDefaultsProjectListKey];
Expand All @@ -58,7 +63,8 @@ - (NSArray *)servers
{
NSString *urlString = [projectListEntry objectForKey:CCMDefaultsProjectEntryServerUrlKey];
NSString *projectName = [projectListEntry objectForKey:CCMDefaultsProjectEntryNameKey];
[projectNamesByServer addObject:projectName toArrayForKey:urlString];
if((urlString != nil) && (projectName != nil))
[projectNamesByServer addObject:projectName toArrayForKey:urlString];
}

NSMutableArray *servers = [NSMutableArray array];
Expand All @@ -74,4 +80,30 @@ - (NSArray *)servers
return servers;
}

- (void)addServerURLToHistory:(NSString *)serverUrl
{
NSArray *list = [self serverURLHistory];
if([list containsObject:serverUrl])
return;
list = [list arrayByAddingObject:serverUrl];
[userDefaults setObject:list forKey:CCMDefaultsServerUrlHistoryKey];
}

- (NSArray *)serverURLHistory
{
NSArray *urls = [userDefaults arrayForKey:CCMDefaultsServerUrlHistoryKey];
if(urls != nil)
{
return urls;
}
NSArray *servers = [self servers];
if([servers count] > 0)
{
urls = (id)[[(id)[[servers collect] url] collect] absoluteString];
[userDefaults setObject:urls forKey:CCMDefaultsServerUrlHistoryKey];
return urls;
}
return [NSArray array];
}

@end
14 changes: 5 additions & 9 deletions English.lproj/Preferences.nib/info.nib

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Binary file modified English.lproj/Preferences.nib/keyedobjects.nib
Binary file not shown.
3 changes: 3 additions & 0 deletions RELEASENOTES.txt
Expand Up @@ -4,6 +4,9 @@ Changes listed by release.

CCMenu 0.9.5

* Now projects already monitored are greyed out in 'add project' dialog
* Server URL combo box now remembers all URLs seen before
* Fixed bug related to classic reporting app URLs
* Fixed bug that caused project window not to update when removing all projects


Expand Down
4 changes: 2 additions & 2 deletions Resources/Info.plist
Expand Up @@ -19,9 +19,9 @@
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>0.9.5d1</string>
<string>0.9.5d2</string>
<key>CFBundleShortVersionString</key>
<string>0.9.5d1</string>
<string>0.9.5d2</string>
<key>LSUIElement</key>
<string>1</string>
<key>NSMainNibFile</key>
Expand Down
5 changes: 2 additions & 3 deletions Tests/CCMPreferencesControllerTest.m
Expand Up @@ -52,9 +52,8 @@ - (void)testPrependsHttpSchemeIfNecessary

- (void)testAddsProjectWithServerUrlAndNameToDefaults
{
NSURL *url = [NSURL URLWithString:@"http://test/cctray.xml"];
NSDictionary *pi = [@"{ name = new; }" propertyList];
[[defaultsManagerMock expect] updateWithProjectInfos:[NSArray arrayWithObject:pi] withServerURL:url];
[[defaultsManagerMock expect] addProject:@"new" onServerWithURL:@"http://test/cctray.xml"];
[[defaultsManagerMock expect] addServerURLToHistory:@"http://test/cctray.xml"];

[controller addProjectsSheetDidEnd:nil returnCode:1 contextInfo:0];
}
Expand Down
103 changes: 79 additions & 24 deletions Tests/CCMUserDefaultsManagerTest.m
Expand Up @@ -29,7 +29,6 @@ - (void)testRetrievesPollInterval
STAssertEquals(1000, interval, @"Should have returned right interval.");
}


- (void)testRetrievesProjectListFromDefaults
{
NSDictionary *ple = [@"{ projectName = new; serverUrl = 'http://test/cctray.xml'; }" propertyList];
Expand All @@ -44,7 +43,6 @@ - (void)testRetrievesProjectListFromDefaults
STAssertEqualObjects(@"http://test/cctray.xml", [projectListEntry objectForKey:@"serverUrl"], @"Should have set right URL.");
}


- (void)testRetrievesEmptyListFromNonExistentDefaults
{
[[[defaultsMock expect] andReturn:nil] dataForKey:CCMDefaultsProjectListKey];
Expand All @@ -55,39 +53,45 @@ - (void)testRetrievesEmptyListFromNonExistentDefaults
STAssertEquals(0u, [entries count], @"Should have returned empty list.");
}

- (void)testCanCheckWhichProjectsAreInList
{
NSDictionary *ple = [@"{ projectName = project1; serverUrl = 'http://test/cctray.xml'; }" propertyList];
NSData *defaultsData = [NSArchiver archivedDataWithRootObject:[NSArray arrayWithObject:ple]];
[[[defaultsMock stub] andReturn:defaultsData] dataForKey:CCMDefaultsProjectListKey];

BOOL isInList = [manager projectListContainsProject:@"project1" onServerWithURL:@"http://test/cctray.xml"];
STAssertTrue(isInList, @"Should have returned true for matching project.");

- (void)testAddsProjectListEntriesForProjectInfos
isInList = [manager projectListContainsProject:@"otherProject" onServerWithURL:@"http://test/cctray.xml"];
STAssertFalse(isInList, @"Should have returned false for not matching project name.");

isInList = [manager projectListContainsProject:@"project1" onServerWithURL:@"http://otherserver/cctray.xml"];
STAssertFalse(isInList, @"Should have returned false for not matching url.");
}

- (void)testAddsProjects
{
[[[defaultsMock expect] andReturn:nil] dataForKey:CCMDefaultsProjectListKey];
[[[defaultsMock stub] andReturn:nil] dataForKey:CCMDefaultsProjectListKey];

// We have to create the dictionary this way, otherwise it serialises differently and data doesn't match
NSDictionary *ple = [NSDictionary dictionaryWithObjectsAndKeys:@"new", CCMDefaultsProjectEntryNameKey,
@"http://test/cctray.xml", CCMDefaultsProjectEntryServerUrlKey, nil];
NSDictionary *ple = [NSDictionary dictionaryWithObjectsAndKeys:
@"new", CCMDefaultsProjectEntryNameKey, @"http://localhost/cctray.xml", CCMDefaultsProjectEntryServerUrlKey, nil];
NSData *newData = [NSArchiver archivedDataWithRootObject:[NSArray arrayWithObject:ple]];
[[defaultsMock expect] setObject:newData forKey:CCMDefaultsProjectListKey];

NSDictionary *pi = [@"{ name = new; }" propertyList];
NSURL *url = [NSURL URLWithString:@"http://test/cctray.xml"];

[manager updateWithProjectInfos:[NSArray arrayWithObject:pi] withServerURL:url];
}

[manager addProject:@"new" onServerWithURL:@"http://localhost/cctray.xml"];
}

- (void)testSkipsProjectInfosAlreadyInList
- (void)testDoesNotAddProjectsAlreadyInList
{
NSDictionary *ple = [@"{ projectName = old; serverUrl = 'http://test/cctray.xml'; }" propertyList];
NSData *oldData = [NSArchiver archivedDataWithRootObject:[NSArray arrayWithObject:ple]];
[[[defaultsMock expect] andReturn:oldData] dataForKey:CCMDefaultsProjectListKey];

[[defaultsMock expect] setObject:oldData forKey:CCMDefaultsProjectListKey];

NSDictionary *pi = [@"{ name = old; }" propertyList];
NSURL *url = [NSURL URLWithString:@"http://test/cctray.xml"];

[manager updateWithProjectInfos:[NSArray arrayWithObject:pi] withServerURL:url];
NSDictionary *ple = [@"{ projectName = project1; serverUrl = 'http://localhost/cctray.xml'; }" propertyList];
NSData *defaultsData = [NSArchiver archivedDataWithRootObject:[NSArray arrayWithObject:ple]];
[[[defaultsMock stub] andReturn:defaultsData] dataForKey:CCMDefaultsProjectListKey];

[manager addProject:@"project1" onServerWithURL:@"http://localhost/cctray.xml"];
// we're not using a nice mock, so if the manager tried to set a new list, the mock would complain
}


- (void)testCreatesDomainObjects
{
NSDictionary *ple = [@"{ projectName = connectfour; serverUrl = 'http://test/cctray.xml'; }" propertyList];
Expand Down Expand Up @@ -120,4 +124,55 @@ - (void)testCreatesMinimumNumberOfServers
}


- (void)testAddsToEmptyServerUrlHistory
{
[[[defaultsMock stub] andReturn:[NSArray array]] arrayForKey:CCMDefaultsServerUrlHistoryKey];
NSArray *historyArray = [NSArray arrayWithObject:@"http://test/cctray.xml"];
[[defaultsMock expect] setObject:historyArray forKey:CCMDefaultsServerUrlHistoryKey];

[manager addServerURLToHistory:@"http://test/cctray.xml"];
}

- (void)testAddsToExistingServerUrlHistory
{
[[[defaultsMock stub] andReturn:[NSArray arrayWithObject:@"http://test/cctray.xml"]] arrayForKey:CCMDefaultsServerUrlHistoryKey];
NSArray *historyArray = [NSArray arrayWithObjects:@"http://test/cctray.xml", @"http://test2/xml", nil];
[[defaultsMock expect] setObject:historyArray forKey:CCMDefaultsServerUrlHistoryKey];

[manager addServerURLToHistory:@"http://test2/xml"];
}

- (void)testDoesNotAddDuplicatesToServerUrlHistory
{
[[[defaultsMock stub] andReturn:[NSArray arrayWithObject:@"http://test/cctray.xml"]] arrayForKey:CCMDefaultsServerUrlHistoryKey];

[manager addServerURLToHistory:@"http://test/cctray.xml"];
// we're not using a nice mock, so if the manager tried to set a new list, the mock would complain
}

- (void)testReturnsServerUrlHistory
{
[[[defaultsMock stub] andReturn:[NSArray arrayWithObject:@"http://test/cctray.xml"]] arrayForKey:CCMDefaultsServerUrlHistoryKey];

NSArray *history = [manager serverURLHistory];

STAssertEquals(1u, [history count], @"Should have returned correct list.");
STAssertEqualObjects(@"http://test/cctray.xml", [history objectAtIndex:0], @"Should have returned correct list.");
}

- (void)testInitializesServerUrlHistoryFromProjectList
{
[[[defaultsMock stub] andReturn:nil] arrayForKey:CCMDefaultsServerUrlHistoryKey];
NSDictionary *ple = [@"{ projectName = project1; serverUrl = 'http://test/cctray.xml'; }" propertyList];
NSData *defaultsData = [NSArchiver archivedDataWithRootObject:[NSArray arrayWithObject:ple]];
[[[defaultsMock stub] andReturn:defaultsData] dataForKey:CCMDefaultsProjectListKey];

NSArray *historyArray = [NSArray arrayWithObject:@"http://test/cctray.xml"];
[[defaultsMock expect] setObject:historyArray forKey:CCMDefaultsServerUrlHistoryKey];

NSArray *history = [manager serverURLHistory];

STAssertEqualObjects(@"http://test/cctray.xml", [history objectAtIndex:0], @"Should have returned URL from project list.");
}

@end

0 comments on commit 1ef697e

Please sign in to comment.