diff --git a/components/tvplanit/languages/vpsr.de.po b/components/tvplanit/languages/vpsr.de.po index 019af4c94..07431f0da 100644 --- a/components/tvplanit/languages/vpsr.de.po +++ b/components/tvplanit/languages/vpsr.de.po @@ -1023,11 +1023,6 @@ msgctxt "vpsr.rspopupaddevent" msgid "Add event..." msgstr "Ereignis hinzufügen..." -#: vpsr.rspopupaddtaskfromical -msgctxt "vpsr.rspopupaddtaskfromical" -msgid "Import from iCalendar file(s)..." -msgstr "Von iCalendar-Dateien importieren..." - #: vpsr.rspopupchangedate msgctxt "vpsr.rspopupchangedate" msgid "Change date" @@ -1043,13 +1038,13 @@ msgctxt "vpsr.rspopupeditevent" msgid "Edit event..." msgstr "Ereignis bearbeiten..." -#: vpsr.rspopupexporteventtoical +#: vpsr.rspopupexporttoical +msgctxt "vpsr.rspopupexporttoical" msgid "Export to iCalendar file..." -msgstr "" +msgstr "Als iCalendar-Datei exportieren..." -#: vpsr.rspopupimporteventfromical -#, fuzzy -msgctxt "vpsr.rspopupimporteventfromical" +#: vpsr.rspopupimportfromical +msgctxt "vpsr.rspopupimportfromical" msgid "Import from iCalendar file(s)..." msgstr "Von iCalendar-Datei(en) importieren..." @@ -1213,7 +1208,7 @@ msgstr "Format speichern als \"%s\"?" #: vpsr.rssaveicaltitle msgid "Export to iCal file" -msgstr "" +msgstr "Als iCal-Datei exportieren" #: vpsr.rssavevcardtitle msgid "Export to vCard" @@ -1807,4 +1802,3 @@ msgstr "Unbekannte Achsen-Spezifikation: %s" #: vpsr.sxmldecnotatbeg msgid "The XML declaration must appear before the first element" msgstr "Die XML-Deklaration muss vor dem ersten Element erscheinen" - diff --git a/components/tvplanit/languages/vpsr.en.po b/components/tvplanit/languages/vpsr.en.po index 9e49fa737..3900fe061 100644 --- a/components/tvplanit/languages/vpsr.en.po +++ b/components/tvplanit/languages/vpsr.en.po @@ -1014,11 +1014,6 @@ msgstr "Pixels" msgid "Add event..." msgstr "Add event..." -#: vpsr.rspopupaddtaskfromical -msgctxt "vpsr.rspopupaddtaskfromical" -msgid "Import from iCalendar file(s)..." -msgstr "Import from iCalendar file(s)..." - #: vpsr.rspopupchangedate msgid "Change date" msgstr "Change date" @@ -1031,13 +1026,13 @@ msgstr "&Delete event..." msgid "Edit event..." msgstr "Edit event..." -#: vpsr.rspopupexporteventtoical +#: vpsr.rspopupexporttoical +msgctxt "vpsr.rspopupexporttoical" msgid "Export to iCalendar file..." -msgstr "" +msgstr "Export to iCalendar file..." -#: vpsr.rspopupimporteventfromical -#, fuzzy -msgctxt "vpsr.rspopupimporteventfromical" +#: vpsr.rspopupimportfromical +msgctxt "vpsr.rspopupimportfromical" msgid "Import from iCalendar file(s)..." msgstr "Import from iCalendar file(s)..." @@ -1199,7 +1194,7 @@ msgstr "Save format to \"%s\"?" #: vpsr.rssaveicaltitle msgid "Export to iCal file" -msgstr "" +msgstr "Export to iCal file" #: vpsr.rssavevcardtitle msgid "Export to vCard" @@ -1788,4 +1783,3 @@ msgstr "Unknown axis specifier: %s" #: vpsr.sxmldecnotatbeg msgid "The XML declaration must appear before the first element" msgstr "The XML declaration must appear before the first element" - diff --git a/components/tvplanit/languages/vpsr.fi.po b/components/tvplanit/languages/vpsr.fi.po index e3dd9b1ab..cb30e2711 100644 --- a/components/tvplanit/languages/vpsr.fi.po +++ b/components/tvplanit/languages/vpsr.fi.po @@ -1014,11 +1014,6 @@ msgctxt "vpsr.rspopupaddevent" msgid "Add event..." msgstr "" -#: vpsr.rspopupaddtaskfromical -msgctxt "vpsr.rspopupaddtaskfromical" -msgid "Import from iCalendar file(s)..." -msgstr "" - #: vpsr.rspopupchangedate msgctxt "vpsr.rspopupchangedate" msgid "Change date" @@ -1034,12 +1029,13 @@ msgctxt "vpsr.rspopupeditevent" msgid "Edit event..." msgstr "" -#: vpsr.rspopupexporteventtoical +#: vpsr.rspopupexporttoical +msgctxt "vpsr.rspopupexporttoical" msgid "Export to iCalendar file..." msgstr "" -#: vpsr.rspopupimporteventfromical -msgctxt "vpsr.rspopupimporteventfromical" +#: vpsr.rspopupimportfromical +msgctxt "vpsr.rspopupimportfromical" msgid "Import from iCalendar file(s)..." msgstr "" diff --git a/components/tvplanit/languages/vpsr.fr.po b/components/tvplanit/languages/vpsr.fr.po index 8dfb59392..efbbb5dad 100644 --- a/components/tvplanit/languages/vpsr.fr.po +++ b/components/tvplanit/languages/vpsr.fr.po @@ -1029,11 +1029,6 @@ msgctxt "vpsr.rspopupaddevent" msgid "Add event..." msgstr "Ajouter un événement..." -#: vpsr.rspopupaddtaskfromical -msgctxt "vpsr.rspopupaddtaskfromical" -msgid "Import from iCalendar file(s)..." -msgstr "" - #: vpsr.rspopupchangedate msgctxt "vpsr.rspopupchangedate" msgid "Change date" @@ -1049,12 +1044,13 @@ msgctxt "vpsr.rspopupeditevent" msgid "Edit event..." msgstr "Modifier un événement" -#: vpsr.rspopupexporteventtoical +#: vpsr.rspopupexporttoical +msgctxt "vpsr.rspopupexporttoical" msgid "Export to iCalendar file..." msgstr "" -#: vpsr.rspopupimporteventfromical -msgctxt "vpsr.rspopupimporteventfromical" +#: vpsr.rspopupimportfromical +msgctxt "vpsr.rspopupimportfromical" msgid "Import from iCalendar file(s)..." msgstr "" diff --git a/components/tvplanit/languages/vpsr.nl.po b/components/tvplanit/languages/vpsr.nl.po index 34d17d082..80a1a752f 100644 --- a/components/tvplanit/languages/vpsr.nl.po +++ b/components/tvplanit/languages/vpsr.nl.po @@ -1023,11 +1023,6 @@ msgctxt "vpsr.rspopupaddevent" msgid "Add event..." msgstr "Gebeurtenis toevoegen..." -#: vpsr.rspopupaddtaskfromical -msgctxt "vpsr.rspopupaddtaskfromical" -msgid "Import from iCalendar file(s)..." -msgstr "" - #: vpsr.rspopupchangedate msgctxt "vpsr.rspopupchangedate" msgid "Change date" @@ -1043,12 +1038,13 @@ msgctxt "vpsr.rspopupeditevent" msgid "Edit event..." msgstr "Gebeurtenis bewerken..." -#: vpsr.rspopupexporteventtoical +#: vpsr.rspopupexporttoical +msgctxt "vpsr.rspopupexporttoical" msgid "Export to iCalendar file..." msgstr "" -#: vpsr.rspopupimporteventfromical -msgctxt "vpsr.rspopupimporteventfromical" +#: vpsr.rspopupimportfromical +msgctxt "vpsr.rspopupimportfromical" msgid "Import from iCalendar file(s)..." msgstr "" diff --git a/components/tvplanit/languages/vpsr.pl.po b/components/tvplanit/languages/vpsr.pl.po index 5ecdb720f..ac5ab9fd4 100644 --- a/components/tvplanit/languages/vpsr.pl.po +++ b/components/tvplanit/languages/vpsr.pl.po @@ -1022,11 +1022,6 @@ msgstr "Pixele" msgid "Add event..." msgstr "Dodaj wydarzenie..." -#: vpsr.rspopupaddtaskfromical -msgctxt "vpsr.rspopupaddtaskfromical" -msgid "Import from iCalendar file(s)..." -msgstr "Import z pliku iCalendar..." - #: vpsr.rspopupchangedate msgctxt "vpsr.rspopupchangedate" msgid "Change date" @@ -1042,15 +1037,16 @@ msgctxt "vpsr.rspopupeditevent" msgid "Edit event..." msgstr "Edytuj wydarzenie..." -#: vpsr.rspopupexporteventtoical +#: vpsr.rspopupexporttoical +msgctxt "vpsr.rspopupexporttoical" msgid "Export to iCalendar file..." msgstr "" -#: vpsr.rspopupimporteventfromical +#: vpsr.rspopupimportfromical #, fuzzy -msgctxt "vpsr.rspopupimporteventfromical" +msgctxt "vpsr.rspopupimportfromical" msgid "Import from iCalendar file(s)..." -msgstr "Import z pliku iCalendar" +msgstr "Import z pliku iCalendar..." #: vpsr.rspopupresourcegroups msgid "Overlay events" diff --git a/components/tvplanit/languages/vpsr.pot b/components/tvplanit/languages/vpsr.pot index c0d9f0c4e..cf294d1df 100644 --- a/components/tvplanit/languages/vpsr.pot +++ b/components/tvplanit/languages/vpsr.pot @@ -1004,11 +1004,6 @@ msgstr "" msgid "Add event..." msgstr "" -#: vpsr.rspopupaddtaskfromical -msgctxt "vpsr.rspopupaddtaskfromical" -msgid "Import from iCalendar file(s)..." -msgstr "" - #: vpsr.rspopupchangedate msgid "Change date" msgstr "" @@ -1021,12 +1016,13 @@ msgstr "" msgid "Edit event..." msgstr "" -#: vpsr.rspopupexporteventtoical +#: vpsr.rspopupexporttoical +msgctxt "vpsr.rspopupexporttoical" msgid "Export to iCalendar file..." msgstr "" -#: vpsr.rspopupimporteventfromical -msgctxt "vpsr.rspopupimporteventfromical" +#: vpsr.rspopupimportfromical +msgctxt "vpsr.rspopupimportfromical" msgid "Import from iCalendar file(s)..." msgstr "" diff --git a/components/tvplanit/languages/vpsr.ru.po b/components/tvplanit/languages/vpsr.ru.po index 7555af341..f52d3f9cd 100644 --- a/components/tvplanit/languages/vpsr.ru.po +++ b/components/tvplanit/languages/vpsr.ru.po @@ -1023,11 +1023,6 @@ msgctxt "vpsr.rspopupaddevent" msgid "Add event..." msgstr "Добавить событие..." -#: vpsr.rspopupaddtaskfromical -msgctxt "vpsr.rspopupaddtaskfromical" -msgid "Import from iCalendar file(s)..." -msgstr "" - #: vpsr.rspopupchangedate msgctxt "vpsr.rspopupchangedate" msgid "Change date" @@ -1043,12 +1038,13 @@ msgctxt "vpsr.rspopupeditevent" msgid "Edit event..." msgstr "Изменить событие..." -#: vpsr.rspopupexporteventtoical +#: vpsr.rspopupexporttoical +msgctxt "vpsr.rspopupexporttoical" msgid "Export to iCalendar file..." msgstr "" -#: vpsr.rspopupimporteventfromical -msgctxt "vpsr.rspopupimporteventfromical" +#: vpsr.rspopupimportfromical +msgctxt "vpsr.rspopupimportfromical" msgid "Import from iCalendar file(s)..." msgstr "" diff --git a/components/tvplanit/source/include/vpsr.inc b/components/tvplanit/source/include/vpsr.inc index d05e1b7ea..27867c626 100644 --- a/components/tvplanit/source/include/vpsr.inc +++ b/components/tvplanit/source/include/vpsr.inc @@ -199,7 +199,6 @@ resourcestring {Task Specific} RSConfirmDeleteTask = 'Delete this task from your list?'; RSTaskPopupAdd = 'Add task...'; - RSPopupAddTaskFromICal = 'Import from iCalendar file(s)...'; RSTaskPopupEdit = 'Edit task...'; RSTaskPopupDelete = 'Delete task...'; RSTaskTitleResource = 'Task list - '; {!!.01} @@ -208,8 +207,8 @@ resourcestring { Popup specific } RSPopupAddEvent = 'Add event...'; - RSPopupImportEventFromICal= 'Import from iCalendar file(s)...'; - RSPopupExportEventToICal = 'Export to iCalendar file...'; + RSPopupImportFromICal = 'Import from iCalendar file(s)...'; + RSPopupExportToICal = 'Export to iCalendar file...'; RSPopupEditEvent = 'Edit event...'; RSPopupDeleteEvent = '&Delete event...'; RSPopupChangeDate = 'Change date'; diff --git a/components/tvplanit/source/vpbase.pas b/components/tvplanit/source/vpbase.pas index 3959c1354..1e0cc0299 100644 --- a/components/tvplanit/source/vpbase.pas +++ b/components/tvplanit/source/vpbase.pas @@ -82,7 +82,7 @@ type mikAddTask, mikEditTask, mikDeleteTask, mikAddContact, mikEditContact, mikDeleteContact, mikImportEventFromICal, mikExportEventToICal, - mikImportTaskFromICal, + mikImportTaskFromICal, mikExportTaskToICal, mikImportContactFromVCards, mikExportContactToVCard, mikResourceGroups, mikNoOverlaidEvents, mikChangeDate, mikCustomDate, mikToday, mikYesterday, mikTomorrow, @@ -95,8 +95,8 @@ type RSPopupAddEvent, RSPopupEditEvent, RSPopupDeleteEvent, RSTaskPopupAdd, RSTaskPopupEdit, RSTaskPopupDelete, RSContactPopupAdd, RSContactPopupEdit, RSContactPopupDelete, - RSPopupImportEventFromICal, RSPopupExportEventToICal, - RSPopupAddTaskFromICal, + RSPopupImportFromICal, RSPopupExportToICal, + RSPopupImportFromICal, RSPopupExportToICal, RSContactPopupImportVCards, RSContactPopupExportVCard, RSPopupResourceGroups, RSNoOverlayedEvents, RSPopupChangeDate, RSCustomDate, RSToday, RSYesterday, RSTomorrow, diff --git a/components/tvplanit/source/vpdata.pas b/components/tvplanit/source/vpdata.pas index f261fb5a1..0f307a5b1 100644 --- a/components/tvplanit/source/vpdata.pas +++ b/components/tvplanit/source/vpdata.pas @@ -387,6 +387,7 @@ type procedure DeleteTask(Task: TVpTask); function First: TVpTask; function FirstByDay(Date: TDateTime): TVpTask; + procedure ExportICalFile(const AFileName: String; const ATasks: TVpTaskArr); function ImportICalFile(const AFileName: String; APreview: Boolean = false; ADefaultCategory: Integer = -1): TVpTaskArr; function IndexOf(ATask: TVpTask): Integer; @@ -439,6 +440,7 @@ type public constructor Create(Owner: TVpTasks); destructor Destroy; override; + function CreateICalTask(ACalendar: TVpICalendar): TVpICalToDo; procedure LoadFromICalendar(AEntry: TVpICalToDo); class function GetTaskPriority(APriority:Integer): TVpTaskPriority; property Loading: Boolean read FLoading write FLoading; @@ -3146,6 +3148,31 @@ begin inherited; end; +function TVpTask.CreateICalTask(ACalendar: TVpICalendar): TVpICalToDo; +begin + Result := TVpICalToDo.Create(ACalendar); + Result.Summary := FDescription; + Result.Comment := FDetails; + Result.CreatedTime[false] := FCreatedOn; + Result.StartTime[false] := FCreatedOn; + Result.DueTime[false] := FDueDate; + if FComplete then + Result.CompletedTime[false] := FCompletedOn + else + Result.CompletedTime[false] := 0; + Result.Categories.Add(CategoryLabel(TVpCategoryType(FCategory))); + case TVpTaskPriority(FPriority) of + tpHigh: Result.Priority := 1; + tpNormal: Result.Priority := 5; + tpLow: Result.Priority := 9; + end; + if FComplete then + Result.Status := 'COMPLETED' + else + Result.Status := 'NEEDS-ACTION'; +end; + + { Converts the priority numbers from ical files (1=highest ... 9=lowest) to the TvPlanit type TVpTaskPriority. } class function TVpTask.GetTaskPriority(APriority:Integer): TVpTaskPriority; @@ -3328,6 +3355,23 @@ begin result := FTaskList.Count; end; +procedure TVpTasks.ExportICalFile(const AFileName: String; + const ATasks: TVpTaskArr); +var + cal: TVpICalendar; + lTask: TVpTask; +begin + cal := TVpICalendar.Create; + try + for lTask in ATasks do + if lTask <> nil then + cal.Add(lTask.CreateICalTask(cal)); + cal.SaveToFile(AFileName); + finally + cal.Free; + end; +end; + function TVpTasks.ImportICalFile(const AFileName: String; APreview: Boolean = false; ADefaultCategory: Integer = -1): TVpTaskArr; const diff --git a/components/tvplanit/source/vpdayview.pas b/components/tvplanit/source/vpdayview.pas index 15b3a34d9..f5e5f8641 100644 --- a/components/tvplanit/source/vpdayview.pas +++ b/components/tvplanit/source/vpdayview.pas @@ -1199,7 +1199,7 @@ begin NewItem.Kind := mikSeparator; FDefaultPopup.Items.Add(NewItem); - if RSPopupImportEventFromICal <> '' then begin + if RSPopupImportFromICal <> '' then begin NewItem := TVpMenuItem.Create(Self); // Import from iCal NewItem.Kind := mikImportEventFromICal; NewItem.OnClick := PopupImportICalFile; @@ -1207,7 +1207,7 @@ begin FDefaultPopup.Items.Add(NewItem); end; - if RSPopupExportEventToICal <> '' then begin // Export ical + if RSPopupExportToICal <> '' then begin // Export ical NewItem := TVpMenuItem.Create(Self); NewItem.Kind := mikExportEventToICal; NewItem.OnClick := PopupExportICalFile; diff --git a/components/tvplanit/source/vpical.pas b/components/tvplanit/source/vpical.pas index 53ee6846d..ed8beaea8 100644 --- a/components/tvplanit/source/vpical.pas +++ b/components/tvplanit/source/vpical.pas @@ -106,6 +106,8 @@ type private FSummary: String; FComment: String; + FCreatedTime: TDateTime; + FCreatedTimeTZ: String; FStartTime: TDateTime; FStartTimeTZ: String; FDueTime: TDateTime; @@ -120,24 +122,30 @@ type function GetCategory(AIndex: integer): String; function GetCategoryCount: Integer; function GetCompletedTime(UTC: Boolean): TDateTime; + function GetCreatedTime(UTC: Boolean): TDateTime; function GetDueTime(UTC: Boolean): TDateTime; function GetStartTime(UTC: Boolean): TDateTime; + procedure SetCompletedTime(UTC: Boolean; const AValue: TDateTime); + procedure SetCreatedTime(UTC: Boolean; const AValue: TDateTime); + procedure SetDueTime(UTC: Boolean; const AValue: TDateTime); + procedure SetStartTime(UTC: Boolean; const AValue: TDateTime); public constructor Create(AOwner: TVpICalendar); override; destructor Destroy; override; procedure Analyze; override; function Categories: TStrings; procedure SaveToStrings(const AList: TStrings); override; - property Summary: String read FSummary; - property Comment: String read FComment; - property StartTime[UTC: Boolean]: TDateTime read GetStartTime; - property DueTime[UTC: Boolean]: TDateTime read GetDueTime; - property CompletedTime[UTC: Boolean]: TDateTime read GetCompletedTime; + property Summary: String read FSummary write FSummary; + property Comment: String read FComment write FComment; + property CreatedTime[UTC: Boolean]: TDateTime read GetCreatedTime write SetCreatedTime; + property StartTime[UTC: Boolean]: TDateTime read GetStartTime write SetStartTime; + property DueTime[UTC: Boolean]: TDateTime read GetDueTime write SetDueTime; + property CompletedTime[UTC: Boolean]: TDateTime read GetCompletedTime write SetCompletedTime; property Category[AIndex: Integer]: String read GetCategory; property CategoryCount: Integer read GetCategoryCount; property PickedCategory: Integer read FPickedCategory write FPickedCategory; - property Priority: Integer read FPriority; // 0=undefined, 1-highest, 9=lowest - property Status: String read FStatus; + property Priority: Integer read FPriority write FPriority; // 0=undefined, 1-highest, 9=lowest + property Status: String read FStatus write FStatus; end; TVpICalendar = class @@ -647,6 +655,13 @@ begin FSummary := item.Value; 'COMMENT': FComment := item.Value; + 'DTSTAMP': + begin + FCreatedTimeTZ := item.GetAttribute('TZID'); + FCreatedTime := iCalDateTime(item.Value, isUTC); + if not isUTC then + FCreatedTime := FCalendar.LocalTimeToUTC(FCreatedTime, FCreatedTimeTZ); + end; 'DTSTART': begin FStartTimeTZ := item.GetAttribute('TZID'); @@ -705,6 +720,13 @@ begin Result := FCalendar.UTCToLocalTime(Result, FCompletedTimeTZ); end; +function TVpICalToDo.GetCreatedTime(UTC: Boolean): TDateTime; +begin + Result := FCreatedTime; + if (Result > 0) and (not UTC) then + Result := FCalendar.UTCToLocalTime(Result, FCreatedTimeTZ); +end; + function TVpICalToDo.GetDueTime(UTC: Boolean): TDateTime; begin if FDueTime <> 0 then @@ -724,8 +746,102 @@ begin end; procedure TVpICalToDo.SaveToStrings(const AList: TStrings); +var + key: String; + dt: TDateTime; begin - // to do... + AList.Add('BEGIN:TODO'); + + if FCreatedTimeTZ <> '' then + key := 'DTSTAMP;TZID=' + FCreatedTimeTZ + ':' + else + key := 'DTSTAMP:'; + AList.Add(key + FormatDateTime(TIME_FORMAT_UTC, CreatedTime[true])); + + if FSummary <> '' then + AList.Add('SUMMARY:' + FSummary); + + if FComment <> '' then + AList.Add('COMMENT:' + FComment); + + if FCategories.Count > 0 then + AList.Add('CATEGORIES:' + FCategories.DelimitedText); + + // todo: check time zones! + if FStartTimeTZ <> '' then + key := 'DTSTART;TZID=' + FStartTimeTZ + ':' + else + key := 'DTSTART:'; + AList.Add(key + FormatDateTime(TIME_FORMAT_UTC, StartTime[true])); + + if FDueTimeTZ <> '' then + key := 'DUE;TZID=' + FDueTimeTZ + ':' + else + key := 'DUE:'; + AList.Add(key + FormatDateTime(TIME_FORMAT_UTC, DueTime[true])); + + dt := CompletedTime[true]; + if dt > 0 then // 0 means here: "not completed yet" + begin + if FCompletedTimeTZ <> '' then + key := 'COMPLETE;TZID=' + FCompletedTimeTZ + ':' + else + key := 'COMPLETED:'; + AList.Add(key + FormatDateTime(TIME_FORMAT_UTC, CompletedTime[true])); + end; + + if FDuration <> 0 then + AList.Add('DURATION:' + Duration2iCalStr(FDuration)); // wp: Is this correct? + + AList.Add('PRIORITY:' + IntToStr(FPriority)); + if FStatus <> '' then + AList.Add('STATUS:' + FStatus); + + AList.Add('END:TODO'); +end; + +procedure TVpICalToDo.SetCompletedTime(UTC: Boolean; const AValue: TDateTime); +begin + if AValue = NO_DATE then + FCompletedTime := NO_DATE + else + if UTC then + FCompletedTime := AValue + else + FCompletedTime := FCalendar.LocalTimeToUTC(AValue, FCompletedTimeTZ); +end; + +procedure TVpICalToDo.SetCreatedTime(UTC: Boolean; const AValue: TDateTime); +begin + if AValue = NO_DATE then + FCreatedTime := NO_DATE + else + if UTC then + FCreatedTime := AValue + else + FCreatedTime := FCalendar.LocalTimeToUTC(AValue, FCreatedTimeTZ); +end; + +procedure TVpICalToDo.SetDueTime(UTC: Boolean; const AValue: TDateTime); +begin + if AValue = NO_DATE then + FDueTime := NO_DATE + else + if UTC then + FDueTime := AValue + else + FDueTime := FCalendar.LocalTimeToUTC(AValue, FDueTimeTZ); +end; + +procedure TVpICalToDo.SetStartTime(UTC: Boolean; const AValue: TDateTime); +begin + if AValue = NO_DATE then + FStartTime := NO_DATE + else + if UTC then + FStartTime := AValue + else + FStartTime := FCalendar.LocalTimeToUTC(AValue, FStartTimeTZ); end; diff --git a/components/tvplanit/source/vpmonthview.pas b/components/tvplanit/source/vpmonthview.pas index f4d71fd1f..f0c65f0b2 100644 --- a/components/tvplanit/source/vpmonthview.pas +++ b/components/tvplanit/source/vpmonthview.pas @@ -1134,8 +1134,8 @@ procedure TVpMonthView.WMRButtonDown(var Msg: TLMRButtonDown); {$ENDIF} begin inherited; - if not Assigned (PopupMenu) then begin - if not focused then + if (PopupMenu = FDefaultPopup) then begin + if not Focused then SetFocus; if FRightClickChangeDate then mvSetDateByCoord (Point (Msg.XPos, Msg.YPos)); diff --git a/components/tvplanit/source/vptasklist.pas b/components/tvplanit/source/vptasklist.pas index 27a7361bd..853b4d399 100644 --- a/components/tvplanit/source/vptasklist.pas +++ b/components/tvplanit/source/vptasklist.pas @@ -172,13 +172,8 @@ type procedure SetColor(const Value: TColor); reintroduce; procedure SetShowIcon(const v: Boolean); procedure SetShowResourceName(Value: Boolean); + { internal methods } - function GetPopupMenu: TPopupMenu; override; - procedure InitializeDefaultPopup; - procedure PopupAddTask(Sender: TObject); - procedure PopupAddFromICalFile(Sender: TObject); - procedure PopupDeleteTask(Sender: TObject); - procedure PopupEditTask(Sender: TObject); procedure tlSetVScrollPos; procedure tlCalcRowHeight; procedure tlEditInPlace(Sender: TObject); @@ -196,6 +191,15 @@ type procedure EndEdit(Sender: TObject); procedure KeyDown(var Key: Word; Shift: TShiftState); override; + { Popup menu } + function GetPopupMenu: TPopupMenu; override; + procedure InitializeDefaultPopup; + procedure PopupAddTask(Sender: TObject); + procedure PopupDeleteTask(Sender: TObject); + procedure PopupEditTask(Sender: TObject); + procedure PopupExportToICalFile(Sender: TObject); + procedure PopupImportFromICalFile(Sender: TObject); + { message handlers } {$IFNDEF LCL} procedure WMLButtonDown(var Msg: TWMLButtonDown); message WM_LBUTTONDOWN; @@ -220,6 +224,7 @@ type procedure LinkHandler(Sender: TComponent; NotificationType: TVpNotificationType; const Value: Variant); override; function GetControlType: TVpItemType; override; + procedure ExportICalFile(const AFileName: String; const ATasks: TVpTaskArr); function ImportICalFile(const AFileName: String; APreview: Boolean = false; ADefaultCategory: Integer = -1): TVpTaskArr; procedure PaintToCanvas(ACanvas: TCanvas; ARect: TRect; Angle: TVpRotationAngle); @@ -631,7 +636,14 @@ begin Result := itTasks; end; -function TVpTaskList.ImportICalFile(const AFileName: String; +procedure TVpTaskList.ExportICalFile(const AFileName: String; + const ATasks: TVpTaskArr); +begin + if Assigned(Datastore) and Assigned(Datastore.Resource) then + Datastore.Resource.Tasks.ExportICalFile(AFileName, ATasks); +end; + +function TVpTaskList.ImportICalFile(const AFileName: String; APreview: Boolean = false; ADefaultCategory: Integer = -1): TVpTaskArr; begin if ReadOnly or (not CheckCreateResource) or @@ -822,7 +834,7 @@ var begin inherited; - if not Assigned (PopupMenu) then begin + if (PopupMenu = FDefaultPopup) then begin if not Focused then SetFocus; tlSetActiveTaskByCoord(Point(Msg.XPos, Msg.YPos)); @@ -906,16 +918,22 @@ begin FDefaultPopup.Items.Add(NewItem); end; - if RSPopupAddTaskFromICal <> '' then begin // Import from iCal + if (RSPopupImportFromICal <> '') or (RSPopupExportToICal <> '') then begin NewItem := TVpMenuItem.Create(Self); NewItem.Kind := mikSeparator; FDefaultPopup.Items.Add(NewItem); - NewItem := TVpMenuItem.Create(Self); + NewItem := TVpMenuItem.Create(Self); // Import from iCal NewItem.Kind := mikImportTaskFromICal; - NewItem.OnClick := PopupAddFromICalFile; + NewItem.OnClick := PopupImportFromICalFile; NewItem.Tag := 0; FDefaultPopup.Items.Add(NewItem); + + NewItem := TVpMenuItem.Create(Self); // Export to iCal + NewItem.Kind := mikExportTaskToICal; + NewItem.OnClick := PopupExportToICalFile; + NewItem.Tag := 1; + FDefaultPopup.Items.Add(NewItem); end; end; @@ -930,7 +948,50 @@ begin tlSpawnTaskEditDialog(True); end; -procedure TVpTaskList.PopupAddFromICalFile(Sender: TObject); +procedure TVpTaskList.PopupDeleteTask(Sender: TObject); +begin + if ReadOnly then + Exit; + if FActiveTask <> nil then begin + Repaint; + DeleteActiveTask(True); + end; +end; + +procedure TVpTaskList.PopupEditTask(Sender: TObject); +begin + if ReadOnly then + Exit; + if FActiveTask <> nil then begin + Repaint; + { edit this Task } + tlSpawnTaskEditDialog(False); + end; +end; + +procedure TVpTaskList.PopupExportToICalFile(Sender: TObject); +var + dlg: TSaveDialog; +begin + if (not Assigned(Datastore)) or (not Assigned(Datastore.Resource)) or + (FActiveTask = nil) + then + exit; + + dlg := TSaveDialog.Create(nil); + try + dlg.Title := RSSaveICalTitle; + dlg.Filter := RSICalFilter; + dlg.FileName := ''; + dlg.Options := dlg.Options - [ofAllowMultiSelect] + [ofOverwritePrompt]; + if dlg.Execute then + ExportICalFile(dlg.FileName, [FActiveTask]); + finally + dlg.Free; + end; +end; + +procedure TVpTaskList.PopupImportFromICalFile(Sender: TObject); var dlg: TOpenDialog; fn: String; @@ -955,27 +1016,6 @@ begin end; end; -procedure TVpTaskList.PopupDeleteTask(Sender: TObject); -begin - if ReadOnly then - Exit; - if FActiveTask <> nil then begin - Repaint; - DeleteActiveTask(True); - end; -end; - -procedure TVpTaskList.PopupEditTask(Sender: TObject); -begin - if ReadOnly then - Exit; - if FActiveTask <> nil then begin - Repaint; - { edit this Task } - tlSpawnTaskEditDialog(False); - end; -end; - procedure TVpTaskList.tlSpawnTaskEditDialog(IsNewTask: Boolean); var AllowIt: Boolean; diff --git a/components/tvplanit/source/vpweekview.pas b/components/tvplanit/source/vpweekview.pas index 8fb5663f7..9fb12b5fc 100644 --- a/components/tvplanit/source/vpweekview.pas +++ b/components/tvplanit/source/vpweekview.pas @@ -1236,7 +1236,7 @@ begin NewItem.Kind := mikSeparator; FDefaultPopup.Items.Add(NewItem); - if RSPopupImportEventFromICal <> '' then begin + if RSPopupImportFromICal <> '' then begin NewItem := TVpMenuItem.Create(Self); NewItem.Kind := mikImportEventFromICal; // Import from iCal NewItem.OnClick := PopupImportFromICalFile; @@ -1244,7 +1244,7 @@ begin FDefaultPopup.Items.Add(NewItem); end; - if RSPopupExportEventToICal <> '' then begin + if RSPopupExportToICal <> '' then begin NewItem := TVpMenuItem.Create(Self); NewItem.Kind := mikExportEventToICal; // Export to iCal NewItem.OnClick := PopupExportToICalFile; @@ -1832,7 +1832,7 @@ begin { Right button } if Button = mbRight then begin - if not Assigned(PopupMenu) then + if (PopupMenu <> FDefaultPopup) then exit; { The mouse click landed inside the client area }