From 20f44a392775799448b37fd0eec93da7d04c9dfb Mon Sep 17 00:00:00 2001 From: Wolfgang Sourdeau Date: Thu, 10 Sep 2009 13:38:56 +0000 Subject: [PATCH 1/6] Monotone-Parent: dc5bdda4eee483eae805bffa6ff605e9995cd81d Monotone-Revision: 9f79dbe6555cff12bfb3ced124471b7ced0eb94f Monotone-Author: wsourdeau@inverse.ca Monotone-Date: 2009-09-10T13:38:56 Monotone-Branch: ca.inverse.sogo --- ChangeLog | 6 ++++++ UI/Scheduler/UIxComponentEditor.m | 5 +++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 337414d68..b157243db 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +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/UI/Scheduler/UIxComponentEditor.m b/UI/Scheduler/UIxComponentEditor.m index 73ed2fdc5..316ee34dc 100644 --- a/UI/Scheduler/UIxComponentEditor.m +++ b/UI/Scheduler/UIxComponentEditor.m @@ -806,12 +806,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 From acf5da06138b8544f15429e4a77259849037a9e2 Mon Sep 17 00:00:00 2001 From: C Robert Date: Thu, 10 Sep 2009 13:43:21 +0000 Subject: [PATCH 2/6] Forgotten changelog Monotone-Parent: 9f79dbe6555cff12bfb3ced124471b7ced0eb94f Monotone-Revision: e3d3033d4c1cc93bcec9f7e30f57cd4379866bdc Monotone-Author: crobert@inverse.ca Monotone-Date: 2009-09-10T13:43:21 Monotone-Branch: ca.inverse.sogo --- debian/changelog | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/debian/changelog b/debian/changelog index d0375550f..7ae44e882 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +sogo (X) unstable; urgency=low + + * Added a dependency on sope4.9-libxmlsaxdriver. + + -- Inverse Support Wed, 10 Sept 2009 09:42:15 -0400 + sogo (X) unstable; urgency=low * Install a default Apache 2 configuration file. From cec888b0c050c6efb0e1da23b9e3d82d759722c6 Mon Sep 17 00:00:00 2001 From: C Robert Date: Thu, 10 Sep 2009 13:45:56 +0000 Subject: [PATCH 3/6] Properly-formatted changelog Monotone-Parent: e3d3033d4c1cc93bcec9f7e30f57cd4379866bdc Monotone-Revision: a1fe20acf2d2d8408bcf2e8c36a38204f8d1bfad Monotone-Author: crobert@inverse.ca Monotone-Date: 2009-09-10T13:45:56 Monotone-Branch: ca.inverse.sogo --- debian/changelog | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/debian/changelog b/debian/changelog index 7ae44e882..54498a020 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,14 +1,9 @@ -sogo (X) unstable; urgency=low - - * Added a dependency on sope4.9-libxmlsaxdriver. - - -- Inverse Support Wed, 10 Sept 2009 09:42:15 -0400 - sogo (X) unstable; urgency=low * Install a default Apache 2 configuration file. + * Added a dependency on sope4.9-libxmlsaxdriver. - -- Inverse Support 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 From 9d46c890d1912b13291a3259a39ed9874708c25f Mon Sep 17 00:00:00 2001 From: C Robert Date: Thu, 10 Sep 2009 17:26:57 +0000 Subject: [PATCH 4/6] Added support for remote iCal calendars. Monotone-Parent: a1fe20acf2d2d8408bcf2e8c36a38204f8d1bfad Monotone-Revision: bb2513b08d345dfc89b0cd702a39ac0eeb276c3d Monotone-Author: crobert@inverse.ca Monotone-Date: 2009-09-10T17:26:57 Monotone-Branch: ca.inverse.sogo --- ChangeLog | 19 +++ SOPE/GDLContentStore/ChangeLog | 5 + SOPE/GDLContentStore/GCSFolder.h | 1 + SOPE/GDLContentStore/GCSFolder.m | 51 +++++++ SoObjects/Appointments/GNUmakefile | 1 + .../Appointments/SOGoAppointmentFolder.h | 2 + .../Appointments/SOGoAppointmentFolder.m | 37 +++++ .../Appointments/SOGoAppointmentFolders.m | 62 +++++++++ .../Appointments/SOGoWebAppointmentFolder.h | 35 +++++ .../Appointments/SOGoWebAppointmentFolder.m | 84 ++++++++++++ SoObjects/Appointments/product.plist | 18 +++ .../Localizable.strings | 3 + UI/Scheduler/Czech.lproj/Localizable.strings | 3 + UI/Scheduler/Dutch.lproj/Localizable.strings | 3 + .../English.lproj/Localizable.strings | 3 + UI/Scheduler/French.lproj/Localizable.strings | 3 + UI/Scheduler/GNUmakefile | 1 + UI/Scheduler/German.lproj/Localizable.strings | 3 + .../Hungarian.lproj/Localizable.strings | 3 + .../Italian.lproj/Localizable.strings | 3 + .../Russian.lproj/Localizable.strings | 3 + .../Spanish.lproj/Localizable.strings | 3 + UI/Scheduler/UIxCalFolderActions.m | 28 +--- UI/Scheduler/UIxCalMainActions.h | 35 +++++ UI/Scheduler/UIxCalMainActions.m | 129 ++++++++++++++++++ UI/Scheduler/UIxComponentEditor.m | 18 ++- UI/Scheduler/Welsh.lproj/Localizable.strings | 3 + UI/Scheduler/product.plist | 10 ++ .../SchedulerUI/UIxCalendarSelector.wox | 4 + UI/WebServerResources/SchedulerUI.js | 42 +++++- 30 files changed, 579 insertions(+), 36 deletions(-) create mode 100644 SoObjects/Appointments/SOGoWebAppointmentFolder.h create mode 100644 SoObjects/Appointments/SOGoWebAppointmentFolder.m create mode 100644 UI/Scheduler/UIxCalMainActions.h create mode 100644 UI/Scheduler/UIxCalMainActions.m diff --git a/ChangeLog b/ChangeLog index b157243db..d8013d946 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,22 @@ +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. + 2009-09-10 Wolfgang Sourdeau * UI/Scheduler/UIxComponentEditor.m (-setComment,comment): 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..7459793d6 --- /dev/null +++ b/SoObjects/Appointments/SOGoWebAppointmentFolder.m @@ -0,0 +1,84 @@ +/* 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]; + } + } + + 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..f2889626b --- /dev/null +++ b/UI/Scheduler/UIxCalMainActions.m @@ -0,0 +1,129 @@ +/* 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"]]; + [rc setObject: @"Web Calendar" forKey: @"displayname"]; + [rc setObject: name forKey: @"name"]; + [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 316ee34dc..94847d837 100644 --- a/UI/Scheduler/UIxComponentEditor.m +++ b/UI/Scheduler/UIxComponentEditor.m @@ -49,6 +49,7 @@ #import #import #import +#import #import #import #import @@ -2045,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 > + Date: Thu, 10 Sep 2009 17:49:07 +0000 Subject: [PATCH 5/6] Added error management for invalid urls Monotone-Parent: bb2513b08d345dfc89b0cd702a39ac0eeb276c3d Monotone-Revision: 44a5709167b1e665fbba7b3e8f30b4e8796d21b2 Monotone-Author: crobert@inverse.ca Monotone-Date: 2009-09-10T17:49:07 Monotone-Branch: ca.inverse.sogo --- ChangeLog | 2 ++ SoObjects/Appointments/SOGoWebAppointmentFolder.m | 4 ++++ UI/Scheduler/UIxCalMainActions.m | 12 ++++++++++-- UI/WebServerResources/SchedulerUI.js | 13 +++++++++---- 4 files changed, 25 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index d8013d946..adc318c5b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -16,6 +16,8 @@ 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 diff --git a/SoObjects/Appointments/SOGoWebAppointmentFolder.m b/SoObjects/Appointments/SOGoWebAppointmentFolder.m index 7459793d6..f6a65a2c1 100644 --- a/SoObjects/Appointments/SOGoWebAppointmentFolder.m +++ b/SoObjects/Appointments/SOGoWebAppointmentFolder.m @@ -53,6 +53,10 @@ [[self ocsFolder] deleteAllContent]; imported = [self importCalendar: calendar]; } + else + { + imported = -1; + } } return imported; diff --git a/UI/Scheduler/UIxCalMainActions.m b/UI/Scheduler/UIxCalMainActions.m index f2889626b..24ae6ac95 100644 --- a/UI/Scheduler/UIxCalMainActions.m +++ b/UI/Scheduler/UIxCalMainActions.m @@ -62,8 +62,16 @@ if (folder) { imported = [folder loadWebCalendar: [r formValueForKey: @"url"]]; - [rc setObject: @"Web Calendar" forKey: @"displayname"]; - [rc setObject: name forKey: @"name"]; + + if (imported >= 0) + { + [rc setObject: @"Web Calendar" forKey: @"displayname"]; + [rc setObject: name forKey: @"name"]; + } + else + { + [folder delete]; + } [rc setObject: [NSNumber numberWithInt: imported] forKey: @"imported"]; } diff --git a/UI/WebServerResources/SchedulerUI.js b/UI/WebServerResources/SchedulerUI.js index 793db201f..f4488ab83 100644 --- a/UI/WebServerResources/SchedulerUI.js +++ b/UI/WebServerResources/SchedulerUI.js @@ -1905,10 +1905,15 @@ function onCalendarWebAdd(event) { } function addWebCalendarCallback (http) { var data = http.responseText.evalJSON(true); - appendCalendar(data.displayname, "/" + data.name); - refreshEvents(); - refreshTasks(); - changeCalendarDisplay(); + if (data.imported > 0) { + appendCalendar(data.displayname, "/" + data.name); + refreshEvents(); + refreshTasks(); + changeCalendarDisplay(); + } + else { + alert (labels["An error occured while importing calendar."]); + } } function onCalendarExport(event) { From 91b2623d6fea6be4a8680c8ed018910a4c392c2f Mon Sep 17 00:00:00 2001 From: C Robert Date: Thu, 10 Sep 2009 18:19:12 +0000 Subject: [PATCH 6/6] =?UTF-8?q?Mantis=203660:=20Sogo=20-=20104=20-=20compo?= =?UTF-8?q?sition=20de=20messages=20en=20HTML=20-=20"Placement=20de=20la?= =?UTF-8?q?=20r=C3=A9ponse=20apr=C3=A8s=20la=20citation"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Monotone-Parent: 44a5709167b1e665fbba7b3e8f30b4e8796d21b2 Monotone-Revision: 3665058235c9d303e295671add1811764b128816 Monotone-Author: crobert@inverse.ca Monotone-Date: 2009-09-10T18:19:12 Monotone-Branch: ca.inverse.sogo --- UI/WebServerResources/UIxPreferences.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/UI/WebServerResources/UIxPreferences.js b/UI/WebServerResources/UIxPreferences.js index 7dca8a788..a7fcac14a 100644 --- a/UI/WebServerResources/UIxPreferences.js +++ b/UI/WebServerResources/UIxPreferences.js @@ -56,6 +56,15 @@ function initPreferences() { resetTableActions (); $("categoryAdd").observe ("click", onCategoryAdd); $("categoryDelete").observe ("click", onCategoryDelete); + + // Disable placement (after) if composing in HTML + if ($("composeMessagesType")) { + if ($("composeMessagesType").value == 1) { + $("replyPlacementList").selectedIndex = 0; + $("replyPlacementList").disabled = 1; + onReplyPlacementListChange (); + } + } } function resetTableActions() {