//
// Copyright (c) Zach Wily
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// - Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
//
// - Redistributions in binary form must reproduce the above copyright notice, this
// list of conditions and the following disclaimer in the documentation and/or
// other materials provided with the distribution.
//
// - Neither the name of Zach Wily nor the names of its contributors may be used to
// endorse or promote products derived from this software without specific prior
// written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
#import "iPhotoToGallery.h"
#import "ImageResizer.h"
#import "ZWAlbumNameFormatter.h"
#import "InterThreadMessaging.h"
#import "NSView+Fading.h"
#import "ZWGallery.h"
#import "ZWGalleryAlbum.h"
#import "ZWGalleryItem.h"
#include <Security/Security.h>
#include <CoreFoundation/CoreFoundation.h>
#include <Growl/Growl.h>
@interface iPhotoToGallery (PrivateStuff)
- (int)addAlbumAndChildren:(ZWGalleryAlbum *)album toMenu:(NSMenu *)menu indentLevel:(int)level addSub:(BOOL)addSub;
- (void)openAddGalleryPanel;
@end
@implementation iPhotoToGallery
static int loggingIn;
#pragma mark -
- (id)initWithExportImageObj:(id)exportMgr {
[NSThread prepareForInterThreadMessages];
exportManager = exportMgr; // weak reference - we don't expect our ExportManager to disappear on us
[GrowlApplicationBridge setGrowlDelegate:self];
preferences = [[NSMutableDictionary alloc] init];
NSDictionary *userDefaultsPreferences = [[NSUserDefaults standardUserDefaults] persistentDomainForName:[[NSBundle bundleForClass:[self class]] bundleIdentifier]];
if (userDefaultsPreferences)
[preferences addEntriesFromDictionary:userDefaultsPreferences];
// build the galleries
galleries = [[NSMutableArray alloc] init];
NSArray *galleryDictionaries = [preferences objectForKey:@"galleries"];
if ([galleryDictionaries isKindOfClass:[NSArray class]]) {
NSEnumerator *each = [galleryDictionaries objectEnumerator];
NSDictionary *galleryDictionary;
while (galleryDictionary = [each nextObject]) {
ZWGallery *gallery = [ZWGallery galleryWithDictionary:galleryDictionary];
if (gallery)
[galleries addObject:gallery];
}
}
return self;
}
- (void)dealloc {
[preferences release];
[galleries release];
[super dealloc];
}
#pragma mark -
#pragma mark NSNibAwaking
- (void)awakeFromNib {
// store initial size of advanced box
if (!heightOfAdvancedBox) {
NSRect advancedFrame = [gallerySettingsAdvancedBox frame];
heightOfAdvancedBox = advancedFrame.size.height;
}
// remove the donate button if so desired
if ([[preferences objectForKey:@"hideDonateButton"] boolValue]) {
[mainDonateButton removeFromSuperview];
}
[self updateGalleryPopupMenu];
// set the popup on the default gallery (if possible)
if ([preferences objectForKey:@"defaultGallery"]) {
if ([mainGalleryPopup indexOfItemWithTitle:[preferences objectForKey:@"defaultGallery"]] >= 0)
[mainGalleryPopup selectItemWithTitle:[preferences objectForKey:@"defaultGallery"]];
}
// set some user defined defaults
if ([preferences objectForKey:@"openBrowser"])
[mainOpenBrowserSwitch setState:[[preferences objectForKey:@"openBrowser"] intValue]];
if ([preferences objectForKey:@"scaleImages"])
[mainScaleImagesSwitch setState:[[preferences objectForKey:@"scaleImages"] intValue]];
if ([preferences objectForKey:@"scaleImagesWidth"])
[mainScaleImagesWidthField setIntValue:[[preferences objectForKey:@"scaleImagesWidth"] intValue]];
if ([preferences objectForKey:@"scaleImagesHeight"])
[mainScaleImagesHeightField setIntValue:[[preferences objectForKey:@"scaleImagesHeight"] intValue]];
if ([preferences objectForKey:@"exportComments"])
[mainExportCommentsSwitch setState:[[preferences objectForKey:@"exportComments"] intValue]];
// if this is their first time, pop down the "add gallery" sheet
if ([galleries count] == 0 && ![[preferences objectForKey:@"offeredToCreateGalleryOnFirstOpen"] boolValue]) {
[preferences setObject:[NSNumber numberWithBool:YES] forKey:@"offeredToCreateGalleryOnFirstOpen"];
[self savePreferences];
// We need to wait until the export window is on the screen before trying to pop the sheet down...
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(exportWindowDidBecomeKey:)
name:NSWindowDidBecomeKeyNotification
object:nil];
}
}
#pragma mark -
#pragma mark ExportPluginProtocol
- (NSString *)description {
return @"iPhotoToGallery Exporter by Zach Wily";
}
- (NSString *)name {
return @"iPhotoToGallery";
}
- (void)cancelExport {
}
- (void)unlockProgress {
}
- (void)lockProgress {
}
- (void *)progress {
return NULL;
}
- (void)performExport:fp16 {
}
- (void)startExport:fp16 {
// save the defaults
[preferences setObject:[NSNumber numberWithBool:[mainScaleImagesSwitch state]] forKey:@"scaleImages"];
if ([mainScaleImagesSwitch state] == NSOnState) {
[preferences setObject:[NSNumber numberWithInt:[mainScaleImagesWidthField intValue]] forKey:@"scaleImagesWidth"];
[preferences setObject:[NSNumber numberWithInt:[mainScaleImagesHeightField intValue]] forKey:@"scaleImagesHeight"];
}
[preferences setObject:[NSNumber numberWithBool:[mainOpenBrowserSwitch state]] forKey:@"openBrowser"];
[preferences setObject:[NSNumber numberWithBool:[mainExportCommentsSwitch state]] forKey:@"exportComments"];
[self savePreferences];
[progressUploadingTextField setStringValue:@"Starting Export..."];
[progressUploadingDetailField setStringValue:@""];
[progressProgressIndicator setMinValue:0.0];
[progressProgressIndicator setMaxValue:(double)([exportManager imageCount])];
[progressProgressIndicator setDoubleValue:0.0];
[progressProgressIndicator setUsesThreadedAnimation:YES];
[progressProgressIndicator startAnimation:self];
[progressImageView setImage:nil];
[NSThread detachNewThreadSelector:@selector(addItemsThread:) toTarget:self withObject:self];
[NSApp beginSheet:progressPanel modalForWindow:[exportManager window] modalDelegate:self didEndSelector:@selector(progressSheetDidEnd:returnCode:contextInfo:) contextInfo:NULL];
}
- (void)progressSheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
{
[progressProgressIndicator stopAnimation:self];
[sheet orderOut:self];
}
- (void)clickExport {
}
- (char)validateUserCreatedPath:fp16 {
return NO;
}
- (char)treatSingleSelectionDifferently {
return NO;
}
- (char)handlesMovieFiles {
return NO;
}
- (NSString *)defaultDirectory {
return [NSHomeDirectory() stringByAppendingPathComponent:@"Pictures"];
}
- (NSString *)defaultFileName {
return @"test";
}
- (NSString *)getDestinationPath {
return [NSHomeDirectory() stringByAppendingPathComponent:@"Pictures"];
}
- (char)wantsDestinationPrompt {
return NO;
}
- (id)requiredFileType {
return @"album";
}
- (void)viewWillBeDeactivated {
if ((currentGallery != nil) && ([currentGallery loggedIn])) {
[currentGallery logout];
[self setLoggedInOut];
}
}
- (void)viewWillBeActivated {
// logout if we're logged in (we shouldn't be)
if ((currentGallery != nil) && ([currentGallery loggedIn])) {
[currentGallery logout];
}
[self setLoggedInOut];
// attempt to login
if (!loggingIn) {
loggingIn = 1;
[self loginToSelectedGallery];
}
}
- (id)lastView {
return lastView;
}
- (id)firstView {
return firstView;
}
- (id)settingsView {
return settingsView;
}
#pragma mark -
#pragma mark IBActions
#pragma mark - Main Window
- (IBAction)clickGalleryPopup:(id)sender {
if ([mainGalleryPopup indexOfSelectedItem] == [mainGalleryPopup numberOfItems] - 1) {
// open the Edit Gallery List sheet
[galleryListTable reloadData];
[NSApp beginSheet:galleryListPanel modalForWindow:[exportManager window] modalDelegate:self didEndSelector:@selector(sheetDidEnd:returnCode:contextInfo:) contextInfo:NULL];
}
else if ([mainGalleryPopup indexOfSelectedItem] == [mainGalleryPopup numberOfItems] - 2) {
// open the Add Gallery sheet
[self openAddGalleryPanel];
}
else {
indexOfLastGallery = [mainGalleryPopup indexOfSelectedItem];
if (![[[mainGalleryPopup selectedItem] title] isEqual:@"(None)"]) {
[self loginToSelectedGallery];
[preferences setObject:[currentGallery identifier] forKey:@"defaultGallery"];
[self savePreferences];
}
}
}
- (IBAction)clickLogin:(id)sender {
}
- (IBAction)clickCancelLogin:(id)sender {
[currentGallery cancelOperation];
}
- (IBAction)clickCreateNewAlbum:(id)sender {
// set the ZWAlbumNameFormatter on the album name field
if (![albumSettingsNameField formatter]) {
ZWAlbumNameFormatter *nameFormatter = [[ZWAlbumNameFormatter alloc] init];
[albumSettingsNameField setFormatter:nameFormatter];
[nameFormatter release];
}
// Get defaults for the Title and Description fields (thx Nathaniel Gray)
NSString *currAlbum, *currComments = nil;
if ([exportManager respondsToSelector:@selector(albumName)]) {
currAlbum = [exportManager albumName];
if ([exportManager respondsToSelector:@selector(albumComments)])
currComments = [exportManager albumComments];
}
else if ([exportManager respondsToSelector:@selector(albumNameAtIndex:)]) {
// iPhoto 7
if ([exportManager albumCount] > 0) {
currAlbum = [exportManager albumNameAtIndex:0];
currComments = [exportManager albumCommentsAtIndex:0];
}
}
// Make these empty strings if they're nil
currAlbum = currAlbum ? currAlbum : @"";
currComments = currComments ? currComments : @"";
[albumSettingsPanel makeFirstResponder:albumSettingsTitleField];
[albumSettingsTitleField setStringValue:currAlbum];
[albumSettingsNameField setStringValue:@""];
[albumSettingsDescriptionField setString:currComments];
// populate the "nested in" popup
[albumSettingsNestedInPopup removeAllItems];
[albumSettingsNestedInPopup setAutoenablesItems:NO];
if (![currentGallery isGalleryV2])
[albumSettingsNestedInPopup addItemWithTitle:@"(None)"];
int count = 0;
NSEnumerator *enumerator = [[currentGallery albums] objectEnumerator];
ZWGalleryAlbum *album;
while (album = [enumerator nextObject]) {
if ([album canAddSubToAlbumOrSub] && ![album parent])
count += [self addAlbumAndChildren:album toMenu:[albumSettingsNestedInPopup menu] indentLevel:0 addSub:YES];
}
if (count)
[albumSettingsNestedInPopup setEnabled:YES];
else
[albumSettingsNestedInPopup setEnabled:NO];
// start the "nested in" popup on the currently selected gallery, if possible
// This is only relevant for G2 - for G1 we will default to an album at root level
if ([currentGallery isGalleryV2]) {
ZWGalleryAlbum *selectedAlbum = [[mainAddToAlbumPopup selectedItem] representedObject];
int idx = [albumSettingsNestedInPopup indexOfItemWithRepresentedObject:selectedAlbum];
if (idx >= 0 && [[albumSettingsNestedInPopup itemAtIndex:idx] isEnabled])
[albumSettingsNestedInPopup selectItemAtIndex:idx];
}
[NSApp beginSheet:albumSettingsPanel modalForWindow:[exportManager window] modalDelegate:self didEndSelector:@selector(sheetDidEnd:returnCode:contextInfo:) contextInfo:NULL];
}
- (void)sheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
{
[sheet orderOut:self];
}
- (IBAction)clickScaleImages:(id)sender {
[self setScaleImages];
}
- (IBAction)clickiPhotoToGalleryName:(id)sender {
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"http://zwily.com/iphoto"]];
}
- (IBAction)clickDonate:(id)sender
{
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"http://zwily.com/iphoto/donate.html"]];
}
#pragma mark - Add Gallery Panel
- (IBAction)clickGallerySettingsOK:(id)sender {
NSString *urlString = [gallerySettingsURLField stringValue];
NSString *username = [gallerySettingsUsernameField stringValue];
NSString *password = [gallery