diff --git a/ChangeLog b/ChangeLog index 337414d68..adc318c5b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,30 @@ +2009-09-10 Cyril Robert + + * SoObjects/Appointments/SOGoWebAppointmentFolder.m: New + SOGoAppointmentFolder subclass to manage iCal subscriptions. + * UI/Scheduler/UIxCalMainActions.m: New action class to handle actions on + the main calendar. + * SoObjects/Appointments/SOGoAppointmentFolder.m (importCalendar:): New + method to import everything from an iCalCalendar. (Refactoring from + UIxCalFolderActions) + * SoObjects/Appointments/SOGoAppointmentFolders.m (webCalendarIds): New + method to get uids of web calendar folders. + (_fetchPersonalFolders: withChannel:): Wrap the parent method to replace web + calendar folders with the correct class: SOGoWebAppointmentFolder. It also + removes invalid references in the WebCalendars setting. + * UI/Scheduler/UIxCalFolderActions.m (importAction): Moved a big part of the + method to [SOGoAppointmentFolder importCalendar:]. + * SoObjects/Appointments/SOGoWebAppointmentFolder.m (delete): Wrap the + parent method to remove the calendar for the user's settings. + * SoObjects/Appointments/SOGoWebAppointmentFolder.m: Added some error + management, for when the url is invalid / not ical / etc. + +2009-09-10 Wolfgang Sourdeau + + * UI/Scheduler/UIxComponentEditor.m (-setComment,comment): + properly substitute the form-provided "\r\n" sequences with "\n" + sequences and vice-versa. + 2009-09-09 Wolfgang Sourdeau * SoObjects/Appointments/SOGoAppointmentFolder.m diff --git a/SOPE/GDLContentStore/ChangeLog b/SOPE/GDLContentStore/ChangeLog index 1982b4d91..56331bf37 100644 --- a/SOPE/GDLContentStore/ChangeLog +++ b/SOPE/GDLContentStore/ChangeLog @@ -1,3 +1,8 @@ +2009-09-10 Cyril Robert + + * GCSFolder.m (deleteAllContent): New method to delete everything in the + folder (use with caution). + 2009-08-14 Wolfgang Sourdeau * GCSFolder.m (-deleteAclWithSpecification:): enable the deletion diff --git a/SOPE/GDLContentStore/GCSFolder.h b/SOPE/GDLContentStore/GCSFolder.h index 91debe945..670059c37 100644 --- a/SOPE/GDLContentStore/GCSFolder.h +++ b/SOPE/GDLContentStore/GCSFolder.h @@ -125,6 +125,7 @@ - (NSException *) writeContent: (NSString *) _content toName: (NSString *) _name; - (NSException *) deleteContentWithName: (NSString *) _name; +- (NSException *) deleteAllContent; - (NSException *) deleteFolder; diff --git a/SOPE/GDLContentStore/GCSFolder.m b/SOPE/GDLContentStore/GCSFolder.m index 7d7f31c90..d3c8943ed 100644 --- a/SOPE/GDLContentStore/GCSFolder.m +++ b/SOPE/GDLContentStore/GCSFolder.m @@ -1092,6 +1092,57 @@ static NSArray *contentFieldNames = nil; return error; } +- (NSException *) deleteAllContent { + NSException *error = nil; + NSString *query; + EOAdaptorChannel *storeChannel, *quickChannel; + + if ((storeChannel = [self acquireStoreChannel]) == nil) { + [self errorWithFormat:@"could not open storage channel!"]; + return nil; + } + if (ofFlags.sameTableForQuick) + quickChannel = nil; + else + { + quickChannel = [self acquireQuickChannel]; + if (!quickChannel) + { + [self errorWithFormat:@"could not open quick channel!"]; + [self releaseChannel:storeChannel]; + return nil; + } + } + + if (!ofFlags.sameTableForQuick) [[quickChannel adaptorContext] beginTransaction]; + [[storeChannel adaptorContext] beginTransaction]; + + query = [NSString stringWithFormat: @"DELETE FROM %@", [self storeTableName]]; + error = [storeChannel evaluateExpressionX:query]; + if (error) + [self errorWithFormat: @"%s: cannot delete content '%@': %@", + __PRETTY_FUNCTION__, query, error]; + else if (!ofFlags.sameTableForQuick) { + /* content row deleted, now delete the quick row */ + query = [NSString stringWithFormat: @"DELETE FROM %@", [self quickTableName]]; + error = [quickChannel evaluateExpressionX: query]; + if (error) + [self errorWithFormat: @"%s: cannot delete quick row '%@': %@", + __PRETTY_FUNCTION__, query, error]; + } + + /* release channels and return */ + [[storeChannel adaptorContext] commitTransaction]; + [self releaseChannel:storeChannel]; + + if (!ofFlags.sameTableForQuick) { + [[quickChannel adaptorContext] commitTransaction]; + [self releaseChannel:quickChannel]; + } + + return error; +} + - (NSException *)deleteFolder { EOAdaptorChannel *channel; NSString *delsql; diff --git a/SoObjects/Appointments/GNUmakefile b/SoObjects/Appointments/GNUmakefile index 38e2417a8..76b2227b6 100644 --- a/SoObjects/Appointments/GNUmakefile +++ b/SoObjects/Appointments/GNUmakefile @@ -24,6 +24,7 @@ Appointments_OBJC_FILES = \ SOGoAppointmentOccurence.m \ SOGoTaskOccurence.m \ SOGoAppointmentFolder.m \ + SOGoWebAppointmentFolder.m \ SOGoAppointmentFolders.m \ SOGoFreeBusyObject.m \ SOGoUserFolder+Appointments.m \ diff --git a/SoObjects/Appointments/SOGoAppointmentFolder.h b/SoObjects/Appointments/SOGoAppointmentFolder.h index cd96ed6e8..8b3d0ed68 100644 --- a/SoObjects/Appointments/SOGoAppointmentFolder.h +++ b/SoObjects/Appointments/SOGoAppointmentFolder.h @@ -48,6 +48,7 @@ @class NSString; @class NSTimeZone; @class GCSFolder; +@class iCalCalendar; @interface SOGoAppointmentFolder : SOGoGCSFolder { @@ -145,6 +146,7 @@ withWriteAccess: (BOOL) hasWriteAccess; - (BOOL) importComponent: (iCalEntityObject *) event; +- (int) importCalendar: (iCalCalendar *) calendar; @end diff --git a/SoObjects/Appointments/SOGoAppointmentFolder.m b/SoObjects/Appointments/SOGoAppointmentFolder.m index 9095a2abc..74d208053 100644 --- a/SoObjects/Appointments/SOGoAppointmentFolder.m +++ b/SoObjects/Appointments/SOGoAppointmentFolder.m @@ -3196,4 +3196,41 @@ firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir return ([object saveContentString: content] == nil); } +- (int) importCalendar: (iCalCalendar *) calendar +{ + NSArray *components; + int imported, count, i; + + imported = 0; + + if (calendar) + { + components = [calendar events]; + count = [components count]; + for (i = 0; i < count; i++) + if ([self importComponent: [components objectAtIndex: i]]) + imported++; + + components = [calendar todos]; + count = [components count]; + for (i = 0; i < count; i++) + if ([self importComponent: [components objectAtIndex: i]]) + imported++; + + components = [calendar journals]; + count = [components count]; + for (i = 0; i < count; i++) + if ([self importComponent: [components objectAtIndex: i]]) + imported++; + + components = [calendar freeBusys]; + count = [components count]; + for (i = 0; i < count; i++) + if ([self importComponent: [components objectAtIndex: i]]) + imported++; + } + + return imported; +} + @end /* SOGoAppointmentFolder */ diff --git a/SoObjects/Appointments/SOGoAppointmentFolders.m b/SoObjects/Appointments/SOGoAppointmentFolders.m index 6c2c6f1db..d170e319a 100644 --- a/SoObjects/Appointments/SOGoAppointmentFolders.m +++ b/SoObjects/Appointments/SOGoAppointmentFolders.m @@ -29,6 +29,7 @@ #import #import #import +#import #import @@ -37,6 +38,7 @@ #import #import #import "SOGoAppointmentFolder.h" +#import "SOGoWebAppointmentFolder.h" #import "SOGoAppointmentFolders.h" @@ -269,4 +271,64 @@ return proxyFolders; } +- (NSArray *) webCalendarIds +{ + NSUserDefaults *us; + NSDictionary *tmp, *calendars; + NSArray *rc; + + rc = nil; + + us = [[context activeUser] userSettings]; + tmp = [us objectForKey: @"Calendar"]; + if (tmp) + { + calendars = [tmp objectForKey: @"WebCalendars"]; + if (calendars) + rc = [calendars allKeys]; + } + + if (!rc) + rc = [NSArray array]; + + return rc; +} + +- (NSException *) _fetchPersonalFolders: (NSString *) sql + withChannel: (EOAdaptorChannel *) fc +{ + int count, max; + NSArray *webCalendarIds; + NSString *name; + SOGoAppointmentFolder *old; + SOGoWebAppointmentFolder *folder; + NSException *error; + BOOL isWebRequest; + + isWebRequest = [[context request] handledByDefaultHandler]; + error = [super _fetchPersonalFolders: sql withChannel: fc]; + + webCalendarIds = [self webCalendarIds]; + max = [webCalendarIds count]; + if (!error && max) + { + for (count = 0; count < max; count++) + { + name = [webCalendarIds objectAtIndex: count]; + if (isWebRequest) + { + old = [subFolders objectForKey: name]; + folder = [SOGoWebAppointmentFolder objectWithName: name + inContainer: self]; + [folder setOCSPath: [old ocsPath]]; + [subFolders setObject: folder forKey: name]; + } + else + [subFolders removeObjectForKey: name]; + } + } + + return error; +} + @end diff --git a/SoObjects/Appointments/SOGoWebAppointmentFolder.h b/SoObjects/Appointments/SOGoWebAppointmentFolder.h new file mode 100644 index 000000000..945e941f0 --- /dev/null +++ b/SoObjects/Appointments/SOGoWebAppointmentFolder.h @@ -0,0 +1,35 @@ +/* SOGoWebAppointmentFolder.h - this file is part of SOGo + * + * Copyright (C) 2009 Inverse inc. + * + * Author: Cyril Robert + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __Appointments_SOGoWebAppointmentFolder_H__ +#define __Appointments_SOGoWebAppointmentFolder_H__ + +#import "SOGoAppointmentFolder.h" + +@interface SOGoWebAppointmentFolder : SOGoAppointmentFolder + +- (int) loadWebCalendar: (NSString *) location; + + +@end + +#endif /* __Appointments_SOGoWebAppointmentFolder_H__ */ diff --git a/SoObjects/Appointments/SOGoWebAppointmentFolder.m b/SoObjects/Appointments/SOGoWebAppointmentFolder.m new file mode 100644 index 000000000..f6a65a2c1 --- /dev/null +++ b/SoObjects/Appointments/SOGoWebAppointmentFolder.m @@ -0,0 +1,88 @@ +/* SOGoWebAppointmentFolder.m - this file is part of SOGo + * + * Copyright (C) 2009 Inverse inc. + * + * Author: Cyril Robert + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#import +#import +#import +#import +#import + +#import "SOGoWebAppointmentFolder.h" + + +@implementation SOGoWebAppointmentFolder + +- (int) loadWebCalendar: (NSString *) location +{ + NSURL *url; + NSData *data; + NSString *contents; + iCalCalendar *calendar; + int imported = 0; + + url = [NSURL URLWithString: location]; + + if (url) + { + data = [NSData dataWithContentsOfURL: url]; + contents = [[NSString alloc] initWithData: data + encoding: NSUTF8StringEncoding]; + [contents autorelease]; + calendar = [iCalCalendar parseSingleFromSource: contents]; + if (calendar) + { + [[self ocsFolder] deleteAllContent]; + imported = [self importCalendar: calendar]; + } + else + { + imported = -1; + } + } + + return imported; +} + + +- (NSException *) delete +{ + NSException *error; + NSUserDefaults *settings; + NSMutableDictionary *calSettings, *webCalendars; + NSString *name; + + settings = [[context activeUser] userSettings]; + calSettings = [settings objectForKey: @"Calendar"]; + webCalendars = [calSettings objectForKey: @"WebCalendars"]; + name = [self nameInContainer]; + + error = [super delete]; + if (!error) + { + [webCalendars removeObjectForKey: name]; + [settings synchronize]; + } + + return error; +} + +@end /* SOGoAppointmentFolder */ diff --git a/SoObjects/Appointments/product.plist b/SoObjects/Appointments/product.plist index 96660024f..0d803808e 100644 --- a/SoObjects/Appointments/product.plist +++ b/SoObjects/Appointments/product.plist @@ -11,6 +11,24 @@ SOGoAppointmentFolders = { superclass = "SOGoParentFolder"; }; + SOGoWebAppointmentFolder = { + superclass = "SOGoGCSFolder"; + defaultRoles = { + "Access Contents Information" = ( "Owner", "PublicResponder", "PublicModifier", "PublicViewer", "PublicDAndTViewer", "PrivateResponder", "PrivateModifier", "PrivateViewer", "PrivateDAndTViewer", "ConfidentialResponder", "ConfidentialModifier", "ConfidentialViewer", "ConfidentialDAndTViewer" ); + "ViewWholePublicRecords" = ( "Owner", "PublicResponder", "PublicModifier", "PublicViewer" ); + "ViewWholePrivateRecords" = ( "Owner", "PrivateResponder", "PrivateModifier", "PrivateViewer" ); + "ViewWholeConfidentialRecords" = ( "Owner", "ConfidentialResponder", "ConfidentialModifier", "ConfidentialViewer" ); + "ViewDAndTOfPublicRecords" = ( "Owner", "PublicDAndTViewer" ); + "ViewDAndTOfPrivateRecords" = ( "Owner", "PrivateDAndTViewer" ); + "ViewDAndTOfConfidentialRecords" = ( "Owner", "ConfidentialDAndTViewer" ); + "ModifyPublicRecords" = ( ); + "ModifyPrivateRecords" = ( ); + "ModifyConfidentialRecords" = ( ); + "RespondToPublicRecords" = ( ); + "RespondToPrivateRecords" = ( ); + "RespondToConfidentialRecords" = ( ); + }; + }; SOGoAppointmentFolder = { superclass = "SOGoGCSFolder"; defaultRoles = { diff --git a/UI/Scheduler/BrazilianPortuguese.lproj/Localizable.strings b/UI/Scheduler/BrazilianPortuguese.lproj/Localizable.strings index 94020d22b..35a318601 100644 --- a/UI/Scheduler/BrazilianPortuguese.lproj/Localizable.strings +++ b/UI/Scheduler/BrazilianPortuguese.lproj/Localizable.strings @@ -533,3 +533,6 @@ vtodo_class2 = "(Tarefa Confidencial)"; "Open Task..." = "Open Task..."; "Mark Completed" = "Mark Completed"; "Delete Task" = "Delete Task"; + +"Subscribe to a web calendar..." = "Subscribe to a web calendar..."; +"URL of the Calendar" = "URL of the Calendar"; diff --git a/UI/Scheduler/Czech.lproj/Localizable.strings b/UI/Scheduler/Czech.lproj/Localizable.strings index 4cf9d4c65..df30ebf1d 100644 --- a/UI/Scheduler/Czech.lproj/Localizable.strings +++ b/UI/Scheduler/Czech.lproj/Localizable.strings @@ -533,3 +533,6 @@ vtodo_class2 = "(Důvěrný úkol)"; "Open Task..." = "Open Task..."; "Mark Completed" = "Mark Completed"; "Delete Task" = "Delete Task"; + +"Subscribe to a web calendar..." = "Subscribe to a web calendar..."; +"URL of the Calendar" = "URL of the Calendar"; diff --git a/UI/Scheduler/Dutch.lproj/Localizable.strings b/UI/Scheduler/Dutch.lproj/Localizable.strings index 3e27c1065..2ab0c41e0 100644 --- a/UI/Scheduler/Dutch.lproj/Localizable.strings +++ b/UI/Scheduler/Dutch.lproj/Localizable.strings @@ -533,3 +533,6 @@ vtodo_class2 = "(Vertrouwelijke taak)"; "Open Task..." = "Open Task..."; "Mark Completed" = "Mark Completed"; "Delete Task" = "Delete Task"; + +"Subscribe to a web calendar..." = "Subscribe to a web calendar..."; +"URL of the Calendar" = "URL of the Calendar"; diff --git a/UI/Scheduler/English.lproj/Localizable.strings b/UI/Scheduler/English.lproj/Localizable.strings index d05a1581e..7dd20e429 100644 --- a/UI/Scheduler/English.lproj/Localizable.strings +++ b/UI/Scheduler/English.lproj/Localizable.strings @@ -533,3 +533,6 @@ vtodo_class2 = "(Confidential task)"; "Open Task..." = "Open Task..."; "Mark Completed" = "Mark Completed"; "Delete Task" = "Delete Task"; + +"Subscribe to a web calendar..." = "Subscribe to a web calendar..."; +"URL of the Calendar" = "URL of the Calendar"; diff --git a/UI/Scheduler/French.lproj/Localizable.strings b/UI/Scheduler/French.lproj/Localizable.strings index 855395e5d..1f9ad73a6 100644 --- a/UI/Scheduler/French.lproj/Localizable.strings +++ b/UI/Scheduler/French.lproj/Localizable.strings @@ -533,3 +533,6 @@ vtodo_class2 = "(Tâche confidentielle)"; "Open Task..." = "Ouvrir la tâche..."; "Mark Completed" = "Marquer comme accomplie"; "Delete Task" = "Supprimer la tâche"; + +"Subscribe to a web calendar..." = "S'inscrire à un agenda en ligne..."; +"URL of the Calendar" = "URL de l'agenda"; diff --git a/UI/Scheduler/GNUmakefile b/UI/Scheduler/GNUmakefile index 70fefcb2a..60a007c21 100644 --- a/UI/Scheduler/GNUmakefile +++ b/UI/Scheduler/GNUmakefile @@ -31,6 +31,7 @@ SchedulerUI_OBJC_FILES = \ UIxAptTableView.m \ \ UIxCalListingActions.m \ + UIxCalMainActions.m \ \ UIxAttendeesEditor.m \ UIxComponentEditor.m \ diff --git a/UI/Scheduler/German.lproj/Localizable.strings b/UI/Scheduler/German.lproj/Localizable.strings index bc5a55049..40964a7b7 100644 --- a/UI/Scheduler/German.lproj/Localizable.strings +++ b/UI/Scheduler/German.lproj/Localizable.strings @@ -533,3 +533,6 @@ vtodo_class2 = "(Vertrauliche Aufgabe)"; "Open Task..." = "Open Task..."; "Mark Completed" = "Mark Completed"; "Delete Task" = "Delete Task"; + +"Subscribe to a web calendar..." = "Subscribe to a web calendar..."; +"URL of the Calendar" = "URL of the Calendar"; diff --git a/UI/Scheduler/Hungarian.lproj/Localizable.strings b/UI/Scheduler/Hungarian.lproj/Localizable.strings index 8d2102056..1f1715497 100644 --- a/UI/Scheduler/Hungarian.lproj/Localizable.strings +++ b/UI/Scheduler/Hungarian.lproj/Localizable.strings @@ -533,3 +533,6 @@ vtodo_class2 = "(Bizalmas feladat)"; "Open Task..." = "Open Task..."; "Mark Completed" = "Mark Completed"; "Delete Task" = "Delete Task"; + +"Subscribe to a web calendar..." = "Subscribe to a web calendar..."; +"URL of the Calendar" = "URL of the Calendar"; diff --git a/UI/Scheduler/Italian.lproj/Localizable.strings b/UI/Scheduler/Italian.lproj/Localizable.strings index f87e944ad..699c32437 100644 --- a/UI/Scheduler/Italian.lproj/Localizable.strings +++ b/UI/Scheduler/Italian.lproj/Localizable.strings @@ -533,3 +533,6 @@ vtodo_class2 = "(Attività confidenziale)"; "Open Task..." = "Open Task..."; "Mark Completed" = "Mark Completed"; "Delete Task" = "Delete Task"; + +"Subscribe to a web calendar..." = "Subscribe to a web calendar..."; +"URL of the Calendar" = "URL of the Calendar"; diff --git a/UI/Scheduler/Russian.lproj/Localizable.strings b/UI/Scheduler/Russian.lproj/Localizable.strings index 412209c4a..976b2e86b 100644 --- a/UI/Scheduler/Russian.lproj/Localizable.strings +++ b/UI/Scheduler/Russian.lproj/Localizable.strings @@ -533,3 +533,6 @@ vtodo_class2 = "(Confidential task)"; "Open Task..." = "Open Task..."; "Mark Completed" = "Mark Completed"; "Delete Task" = "Delete Task"; + +"Subscribe to a web calendar..." = "Subscribe to a web calendar..."; +"URL of the Calendar" = "URL of the Calendar"; diff --git a/UI/Scheduler/Spanish.lproj/Localizable.strings b/UI/Scheduler/Spanish.lproj/Localizable.strings index ac65b65db..23991ebc4 100644 --- a/UI/Scheduler/Spanish.lproj/Localizable.strings +++ b/UI/Scheduler/Spanish.lproj/Localizable.strings @@ -533,3 +533,6 @@ vtodo_class2 = "(Tarea confidencial)"; "Open Task..." = "Open Task..."; "Mark Completed" = "Mark Completed"; "Delete Task" = "Delete Task"; + +"Subscribe to a web calendar..." = "Subscribe to a web calendar..."; +"URL of the Calendar" = "URL of the Calendar"; diff --git a/UI/Scheduler/UIxCalFolderActions.m b/UI/Scheduler/UIxCalFolderActions.m index 100c460ae..04c70e874 100644 --- a/UI/Scheduler/UIxCalFolderActions.m +++ b/UI/Scheduler/UIxCalFolderActions.m @@ -20,7 +20,6 @@ */ #import -#import #import #import @@ -98,13 +97,12 @@ { SOGoAppointmentFolder *folder; NSMutableDictionary *rc; - NSArray *components; WORequest *request; WOResponse *response; NSString *fileContent; id data; iCalCalendar *additions; - int i, count, imported; + int imported; imported = 0; rc = [NSMutableDictionary dictionary]; @@ -124,29 +122,7 @@ && [fileContent hasPrefix: @"BEGIN:"]) { additions = [iCalCalendar parseSingleFromSource: fileContent]; - if (additions) - { - components = [additions events]; - count = [components count]; - for (i = 0; i < count; i++) - if ([folder importComponent: [components objectAtIndex: i]]) - imported++; - components = [additions todos]; - count = [components count]; - for (i = 0; i < count; i++) - if ([folder importComponent: [components objectAtIndex: i]]) - imported++; - components = [additions journals]; - count = [components count]; - for (i = 0; i < count; i++) - if ([folder importComponent: [components objectAtIndex: i]]) - imported++; - components = [additions freeBusys]; - count = [components count]; - for (i = 0; i < count; i++) - if ([folder importComponent: [components objectAtIndex: i]]) - imported++; - } + imported = [folder importCalendar: additions]; } [rc setObject: [NSNumber numberWithInt: imported] diff --git a/UI/Scheduler/UIxCalMainActions.h b/UI/Scheduler/UIxCalMainActions.h new file mode 100644 index 000000000..ee61f762a --- /dev/null +++ b/UI/Scheduler/UIxCalMainActions.h @@ -0,0 +1,35 @@ +/* UIxCalMainActions.h - this file is part of SOGo + * + * Copyright (C) 2009 Inverse inc. + * + * Author: Cyril Robert + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef UIXCALMAINACTIONS_H +#define UIXCALMAINACTIONS_H + +#import + +@interface UIxCalMainActions : WODirectAction + +- (void) saveUrl: (NSURL *) calendarURL + forCalendar: (NSString *) calendarName; + +@end + +#endif /* UIXCALMAINACTIONS_H */ diff --git a/UI/Scheduler/UIxCalMainActions.m b/UI/Scheduler/UIxCalMainActions.m new file mode 100644 index 000000000..24ae6ac95 --- /dev/null +++ b/UI/Scheduler/UIxCalMainActions.m @@ -0,0 +1,137 @@ +/* UIxCalMainActions.m - this file is part of SOGo + * + * Copyright (C) 2009 Inverse inc. + * + * Author: Cyril Robert + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#import + +#import +#import +#import +#import + +#import +#import +#import +#import + +#import "UIxCalMainActions.h" + +@implementation UIxCalMainActions + +- (WOResponse *) addWebCalendarAction +{ + WORequest *r; + WOResponse *response; + SOGoWebAppointmentFolder *folder; + NSURL *url; + NSString *name; + NSMutableDictionary *rc; + int imported = 0; + + r = [context request]; + rc = [NSMutableDictionary dictionary]; + + // Just a check + url = [NSURL URLWithString: [r formValueForKey: @"url"]]; + if (url) + { + [[self clientObject] newFolderWithName: @"Web Calendar" + nameInContainer: &name]; + [self saveUrl: url forCalendar: name]; + folder = [[self clientObject] lookupName: name + inContext: context + acquire: NO]; + if (folder) + { + imported = [folder loadWebCalendar: [r formValueForKey: @"url"]]; + + if (imported >= 0) + { + [rc setObject: @"Web Calendar" forKey: @"displayname"]; + [rc setObject: name forKey: @"name"]; + } + else + { + [folder delete]; + } + [rc setObject: [NSNumber numberWithInt: imported] + forKey: @"imported"]; + } + } + + response = [self responseWithStatus: 200]; + [response appendContentString: [rc jsonRepresentation]]; + return response; +} + +- (void) saveUrl: (NSURL *) calendarURL + forCalendar: (NSString *) calendarName +{ + NSUserDefaults *settings; + NSMutableDictionary *calSettings, *webCalendars; + + settings = [[context activeUser] userSettings]; + calSettings = [settings objectForKey: @"Calendar"]; + webCalendars = [calSettings objectForKey: @"WebCalendars"]; + if (!webCalendars) + { + webCalendars = [NSMutableDictionary dictionary]; + [calSettings setObject: webCalendars forKey: @"WebCalendars"]; + } + [webCalendars setObject: calendarURL forKey: calendarName]; + [settings synchronize]; +} + +- (WOResponse *) reloadWebCalendarsAction +{ + NSUserDefaults *settings; + NSMutableDictionary *calSettings, *webCalendars; + NSArray *calendarIds; + SOGoWebAppointmentFolder *folder; + NSString *name, *url; + int i, count, imported; + + settings = [[context activeUser] userSettings]; + calSettings = [settings objectForKey: @"Calendar"]; + webCalendars = [calSettings objectForKey: @"WebCalendars"]; + + if (webCalendars) + { + calendarIds = [webCalendars allKeys]; + count = [calendarIds count]; + for (i = 0; i < count; i++) + { + name = [calendarIds objectAtIndex: i]; + url = [webCalendars objectForKey: name]; + folder = [[self clientObject] lookupName: name + inContext: context + acquire: NO]; + if (folder) + imported = [folder loadWebCalendar: url]; + } + } + + return [self responseWith204]; +} + + + +@end diff --git a/UI/Scheduler/UIxComponentEditor.m b/UI/Scheduler/UIxComponentEditor.m index 73ed2fdc5..94847d837 100644 --- a/UI/Scheduler/UIxComponentEditor.m +++ b/UI/Scheduler/UIxComponentEditor.m @@ -49,6 +49,7 @@ #import #import #import +#import #import #import #import @@ -806,12 +807,13 @@ iRANGE(2); - (void) setComment: (NSString *) _value { - ASSIGN (comment, _value); +#warning should we do the same for "location" and "summary"? What about ContactsUI? + ASSIGN (comment, [_value stringByReplacingString: @"\r\n" withString: @"\n"]); } - (NSString *) comment { - return comment; + return [comment stringByReplacingString: @"\n" withString: @"\r\n"]; } - (BOOL) hasComment @@ -2044,18 +2046,23 @@ RANGE(2); { SOGoContentObject *clientObject; SOGoUser *ownerUser; - int rc = 0; + int rc; clientObject = [self clientObject]; ownerUser = [SOGoUser userWithLogin: [clientObject ownerInContext: context] roles: nil]; - if ([ownerUser isEqual: [context activeUser]]) - rc = [self ownerIsAttendee: ownerUser - andClientObject: clientObject]; + if ([componentCalendar isKindOfClass: [SOGoWebAppointmentFolder class]]) + rc = 1; else - rc = [self delegateIsAttendee: ownerUser - andClientObject: clientObject]; + { + if ([ownerUser isEqual: [context activeUser]]) + rc = [self ownerIsAttendee: ownerUser + andClientObject: clientObject]; + else + rc = [self delegateIsAttendee: ownerUser + andClientObject: clientObject]; + } return rc; } diff --git a/UI/Scheduler/Welsh.lproj/Localizable.strings b/UI/Scheduler/Welsh.lproj/Localizable.strings index f9fc6ad79..313fb4225 100644 --- a/UI/Scheduler/Welsh.lproj/Localizable.strings +++ b/UI/Scheduler/Welsh.lproj/Localizable.strings @@ -533,3 +533,6 @@ vtodo_class2 = "(Tasg gyhoeddus)"; "Open Task..." = "Open Task..."; "Mark Completed" = "Mark Completed"; "Delete Task" = "Delete Task"; + +"Subscribe to a web calendar..." = "Subscribe to a web calendar..."; +"URL of the Calendar" = "URL of the Calendar"; diff --git a/UI/Scheduler/product.plist b/UI/Scheduler/product.plist index 36c6e5664..ec2cd2c7e 100644 --- a/UI/Scheduler/product.plist +++ b/UI/Scheduler/product.plist @@ -40,6 +40,16 @@ protectedBy = "View"; pageName = "UIxCalMainView"; }; + addWebCalendar = { + protectedBy = "View"; + actionClass = "UIxCalMainActions"; + actionName = "addWebCalendar"; + }; + reloadWebCalendars = { + protectedBy = "View"; + actionClass = "UIxCalMainActions"; + actionName = "reloadWebCalendars"; + }; saveDragHandleState = { protectedBy = "View"; pageName = "UIxCalMainView"; diff --git a/UI/Templates/SchedulerUI/UIxCalendarSelector.wox b/UI/Templates/SchedulerUI/UIxCalendarSelector.wox index de60479ad..03e084fe7 100644 --- a/UI/Templates/SchedulerUI/UIxCalendarSelector.wox +++ b/UI/Templates/SchedulerUI/UIxCalendarSelector.wox @@ -20,6 +20,10 @@ div.colorBox.calendarFolder > + Wed, 19 Aug 2009 09:42:15 -0400 + -- Inverse Support Wed, 10 Sept 2009 09:42:15 -0400 sogo (1.0.4) unstable; urgency=low