From 080f303cd192b9fcaaaca9e62148df4848233434 Mon Sep 17 00:00:00 2001 From: wp_xxyyzz Date: Fri, 5 Aug 2022 20:12:52 +0000 Subject: [PATCH] tvplanit: Extract ImportICalFile also for TVpWeekView and TVpTaskList. Move the essential code into TVpSchedule and TVpTaskList to avoid too much duplication. git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@8370 8e941d3f-bd1b-0410-a28a-d453659cc2b4 --- components/tvplanit/source/vpdata.pas | 92 ++++++++++++++++++++++- components/tvplanit/source/vpdayview.pas | 58 +++----------- components/tvplanit/source/vptasklist.pas | 46 +++++++----- components/tvplanit/source/vpweekview.pas | 61 ++++++++------- 4 files changed, 164 insertions(+), 93 deletions(-) diff --git a/components/tvplanit/source/vpdata.pas b/components/tvplanit/source/vpdata.pas index 81efcfc69..949e13b56 100644 --- a/components/tvplanit/source/vpdata.pas +++ b/components/tvplanit/source/vpdata.pas @@ -76,7 +76,8 @@ type TVpContact = class; TVpTask = class; - TVpEvents = array of TVpEvent; + TVpEventArr = array of TVpEvent; + TVpTaskArr = array of TVpTask; TVpResources = class private @@ -240,6 +241,7 @@ type function EventCountByDay(Value: TDateTime): Integer; procedure EventsByDate(Date: TDateTime; EventList: TList); function GetEvent(Index: Integer): TVpEvent; + function ImportICalFile(const AFileName: String; ADefaultCategory: Integer = -1): TVpEventArr; function RepeatsOn(Event: TVpEvent; Day: TDateTime): Boolean; procedure Sort; property Owner: TVpResource read FOwner; @@ -378,6 +380,7 @@ type procedure DeleteTask(Task: TVpTask); function First: TVpTask; function FirstByDay(Date: TDateTime): TVpTask; + function ImportICalFile(const AFileName: String; ADefaultCategory: Integer = -1): TVpTaskArr; function IndexOf(ATask: TVpTask): Integer; function Last: TVpTask; function LastByDay(Date: TDateTime): TVpTask; @@ -1719,6 +1722,52 @@ begin result := TVpEvent(FEventList[Index]); end; +function TVpSchedule.ImportICalFile(const AFileName: String; + ADefaultCategory: Integer = -1): TVpEventArr; +const + BLOCK_SIZE = 10; +var + ical: TVpICalendar; + startTime, endTime: TDateTime; + i: Integer; + id: Integer; + event: TVpEvent; + eventCounter: Integer; + datastore: TVpCustomDatastore; +begin + Result := nil; + SetLength(Result, BLOCK_SIZE); + eventCounter := 0; + + datastore := Owner.Owner.Owner as TVpCustomDatastore; + + ical := TVpICalendar.Create; + try + ical.LoadFromFile(AFileName); + for i := 0 to ical.Count-1 do begin + if not (ical[i] is TVpICalEvent) then + Continue; + startTime := TVpICalEvent(ical[i]).StartTime[false]; // use local times + endTime := TVpICalEvent(ical[i]).EndTime[false]; + if (startTime = 0) and (endTime = 0) then + continue; + id := dataStore.GetNextID(EventsTableName); + event := AddEvent(id, starttime, endtime); + event.Changed := true; + event.LoadFromICalendar(TVpICalEvent(ical[i])); + if (event.Category = 0) and (ADefaultCategory <> -1) then + event.Category := ADefaultCategory; + Result[eventCounter] := event; + inc(eventCounter); + if eventCounter mod BLOCK_SIZE = 0 then + SetLength(Result, eventCounter + BLOCK_SIZE); + end; + SetLength(Result, eventCounter); + finally + ical.Free; + end; +end; + function TVpSchedule.RepeatsOn(Event: TVpEvent; Day: TDateTime): Boolean; var EY, EM, ED: Word; @@ -2903,6 +2952,47 @@ begin result := FTaskList.Count; end; +function TVpTasks.ImportICalFile(const AFileName: String; + ADefaultCategory: Integer = -1): TVpTaskArr; +const + BLOCK_SIZE = 10; +var + ical: TVpICalendar; + i: Integer; + id: Integer; + task: TVpTask; + taskCounter: Integer; + datastore: TVpCustomDatastore; +begin + Result := nil; + SetLength(Result, BLOCK_SIZE); + taskCounter := 0; + + datastore := Owner.Owner.Owner as TVpCustomDatastore; + + ical := TVpICalendar.Create; + try + ical.LoadFromFile(AFileName); + for i := 0 to ical.Count-1 do begin + if not (ical[i] is TVpICalToDo) then + Continue; + id := dataStore.GetNextID(TasksTableName); + task := AddTask(id); + task.Changed := true; + task.LoadFromICalendar(TVpICalToDo(ical[i])); + if (task.Category = ord(ctOther)) and (ADefaultCategory <> -1) then + task.Category := ADefaultCategory; + Result[taskCounter] := task; + inc(taskCounter); + if taskCounter mod BLOCK_SIZE = 0 then + SetLength(Result, taskCounter + BLOCK_SIZE); + end; + SetLength(Result, taskCounter); + finally + ical.Free; + end; +end; + function TVpTasks.IndexOf(ATask: TVpTask): Integer; begin Result := FTaskList.IndexOf(ATask); diff --git a/components/tvplanit/source/vpdayview.pas b/components/tvplanit/source/vpdayview.pas index b68cfdd4f..d8629d80f 100644 --- a/components/tvplanit/source/vpdayview.pas +++ b/components/tvplanit/source/vpdayview.pas @@ -447,7 +447,7 @@ type function BuildEventString(AEvent: TVpEvent; UseAsHint: Boolean): String; procedure DeleteActiveEvent(Verify: Boolean); procedure DragDrop(Source: TObject; X, Y: Integer); override; - function ImportICalFile(AFileName: String; ADefaultCategory: Integer = 0): TVpEvents; + function ImportICalFile(const AFileName: String; ADefaultCategory: Integer = -1): TVpEventArr; procedure Invalidate; override; function IsHoliday(ADate: TDate; out AHolidayName: String): Boolean; procedure LoadLanguage; @@ -546,7 +546,7 @@ uses DateUtils, {$ENDIF} SysUtils, StrUtils, Math, Dialogs, - VpEvntEditDlg, VpDayViewPainter, VpICal; + VpEvntEditDlg, VpDayViewPainter; (*****************************************************************************) { TVpTGInPlaceEdit } @@ -1336,11 +1336,7 @@ end; procedure TVpDayView.PopupAddFromICalFile(Sender: TObject); var dlg: TOpenDialog; - ical: TVpICalendar; fn: String; - i: Integer; - id: Integer; - startTime, endTime: TDateTime; begin if ReadOnly or (not CheckCreateResource) or (not Assigned(DataStore)) or (not Assigned(DataStore.Resource)) @@ -2384,55 +2380,25 @@ end; category has been found in the ical, i.e. when the event's category is 0. If you are not happy with this category replacement you can iterate over the Result array and change it. } -function TVpDayView.ImportICalFile(AFileName: String; - ADefaultCategory: Integer = 0): TVpEvents; -const - BLOCK_SIZE = 10; -var - ical: TVpICalendar; - startTime, endTime: TDateTime; - i: Integer; - id: Integer; - event: TVpEvent; - eventCounter: Integer; +function TVpDayView.ImportICalFile(const AFileName: String; + ADefaultCategory: Integer = -1): TVpEventArr; begin if ReadOnly or (not CheckCreateResource) or (not Assigned(DataStore)) or (not Assigned(DataStore.Resource)) then Exit; - SetLength(Result, BLOCK_SIZE); - eventCounter := 0; - - ical := TVpICalendar.Create; + Screen.Cursor := crHourglass; try - ical.LoadFromFile(AFileName); - for i := 0 to ical.Count-1 do begin - if not (ical[i] is TVpICalEvent) then - Continue; - startTime := TVpICalEvent(ical[i]).StartTime[false]; // use local times - endTime := TVpICalEvent(ical[i]).EndTime[false]; - if (startTime = 0) and (endTime = 0) then - continue; - id := DataStore.GetNextID(EventsTableName); - event := Datastore.Resource.Schedule.AddEvent(id, starttime, endtime); - event.Changed := true; - event.LoadFromICalendar(TVpICalEvent(ical[i])); - if (event.Category = 0) and (ADefaultCategory <> 0) then - event.Category := ADefaultCategory; - Result[eventCounter] := event; - inc(eventCounter); - if eventCounter mod BLOCK_SIZE = 0 then - SetLength(Result, eventCounter + BLOCK_SIZE); - end; - SetLength(Result, eventCounter); - if eventCounter > 0 then + Result := Datastore.Resource.Schedule.ImportICalFile(AFileName, ADefaultCategory); + if Length(Result) > 0 then + begin FActiveEvent := Result[High(Result)]; - Datastore.PostEvents; - Datastore.NotifyDependents; - Invalidate; + Datastore.PostEvents; + Datastore.NotifyDependents; + Invalidate; + end; finally - ical.Free; Screen.Cursor := crDefault; end; end; diff --git a/components/tvplanit/source/vptasklist.pas b/components/tvplanit/source/vptasklist.pas index bd835606a..42bdb5494 100644 --- a/components/tvplanit/source/vptasklist.pas +++ b/components/tvplanit/source/vptasklist.pas @@ -216,6 +216,7 @@ type procedure LinkHandler(Sender: TComponent; NotificationType: TVpNotificationType; const Value: Variant); override; function GetControlType: TVpItemType; override; + function ImportICalFile(const AFileName: String; ADefaultCategory: Integer = -1): TVpTaskArr; procedure PaintToCanvas(ACanvas: TCanvas; ARect: TRect; Angle: TVpRotationAngle); procedure RenderToCanvas(RenderCanvas: TCanvas; RenderIn: TRect; Angle: TVpRotationAngle; Scale: Extended; RenderDate: TDateTime; @@ -613,14 +614,35 @@ begin inherited; tlLoaded := true; end; -{=====} function TVpTaskList.GetControlType: TVpItemType; begin Result := itTasks; end; -{=====} +function TVpTaskList.ImportICalFile(const AFileName: String; + ADefaultCategory: Integer = -1): TVpTaskArr; +begin + if ReadOnly or (not CheckCreateResource) or + (not Assigned(DataStore)) or (not Assigned(DataStore.Resource)) + then + Exit; + + Screen.Cursor := crHourglass; + try + Result := Datastore.Resource.Tasks.ImportICalFile(AFileName, ADefaultCategory); + if Length(Result) > 0 then + begin + FActiveTask := Result[High(Result)]; + Datastore.PostTasks; + Datastore.NotifyDependents; + Invalidate; + end; + finally + Screen.Cursor := crDefault; + end; +end; + procedure TVpTaskList.Paint; begin { paint simply calls RenderToCanvas and passes in the screen canvas. } @@ -902,10 +924,7 @@ end; procedure TVpTaskList.PopupAddFromICalFile(Sender: TObject); var dlg: TOpenDialog; - ical: TVpICalendar; fn: String; - i: Integer; - id: Integer; begin if ReadOnly or (not CheckCreateResource) or (not Assigned(DataStore)) or (not Assigned(DataStore.Resource)) @@ -920,24 +939,11 @@ begin dlg.Options := dlg.Options + [ofAllowMultiSelect, ofFileMustExist]; if dlg.Execute then begin Screen.Cursor := crHourGlass; - Application.ProcessMessages; - ical := TVpICalendar.Create; try - for fn in dlg.Files do begin - ical.LoadFromFile(fn); - for i := 0 to ical.Count-1 do begin - if not (ical[i] is TVpICalToDo) then - Continue; - id := DataStore.GetNextID(EventsTableName); - FActiveTask := Datastore.Resource.Tasks.AddTask(id); - FActiveTask.LoadFromICalendar(TVpICalToDo(ical[i])); - Datastore.PostTasks; - Datastore.NotifyDependents; - end; - end; + for fn in dlg.Files do + Datastore.Resource.Tasks.ImportICalFile(fn); Invalidate; finally - ical.Free; Screen.Cursor := crDefault; end; end; diff --git a/components/tvplanit/source/vpweekview.pas b/components/tvplanit/source/vpweekview.pas index 170573f53..1d5f8777f 100644 --- a/components/tvplanit/source/vpweekview.pas +++ b/components/tvplanit/source/vpweekview.pas @@ -272,6 +272,7 @@ type procedure LoadLanguage; procedure DeleteActiveEvent(Verify: Boolean); procedure DragDrop(Source: TObject; X, Y: Integer); override; + function ImportICalFile(const AFileName: String; ADefaultCategory: Integer = -1): TVpEventArr; procedure Invalidate; override; function IsHoliday(ADate: TDate; out AHolidayName: String): Boolean; procedure LinkHandler(Sender: TComponent; @@ -341,7 +342,7 @@ uses DateUtils, {$ENDIF} SysUtils, StrUtils, LazUTF8, Dialogs, - VpEvntEditDlg, VpWeekViewPainter, VpICal; + VpEvntEditDlg, VpWeekViewPainter; (*****************************************************************************) { TVpTGInPlaceEdit } @@ -1084,6 +1085,36 @@ begin end; end; +{ Reads the events listed in the specified ical file and adds them to the + day view control. All events imported are collected in the Result array. + ADefaultCategory is the category to which the event is assigned if no fitting + category has been found in the ical, i.e. when the event's category is 0. + If you are not happy with this category replacement you can iterate over the + Result array and change it. } +function TVpWeekView.ImportICalFile(const AFileName: String; + ADefaultCategory: Integer = -1): TVpEventArr; +begin + if ReadOnly or (not CheckCreateResource) or + (not Assigned(DataStore)) or (not Assigned(DataStore.Resource)) + then + Exit; + + Screen.Cursor := crHourglass; + try + Result := Datastore.Resource.Schedule.ImportICalFile(AFileName, ADefaultCategory); + if Length(Result) > 0 then + begin + FActiveEvent := Result[High(Result)]; + Datastore.PostEvents; + Datastore.NotifyDependents; + Invalidate; + end; + finally + Screen.Cursor := crDefault; + end; +end; + + { Hints } procedure TVpWeekView.ShowHintWindow(APoint: TPoint; AEvent: TVpEvent); @@ -1290,11 +1321,7 @@ end; procedure TVpWeekView.PopupAddFromICalFile(Sender: TObject); var dlg: TOpenDialog; - ical: TVpICalendar; fn: String; - i: Integer; - id: Integer; - startTime, endTime: TDateTime; begin if ReadOnly or (not CheckCreateResource) or (not Assigned(DataStore)) or (not Assigned(DataStore.Resource)) @@ -1309,29 +1336,11 @@ begin dlg.Options := dlg.Options + [ofAllowMultiSelect, ofFileMustExist]; if dlg.Execute then begin Screen.Cursor := crHourGlass; - Application.ProcessMessages; - ical := TVpICalendar.Create; try - for fn in dlg.Files do begin - ical.LoadFromFile(fn); - for i := 0 to ical.Count-1 do begin - if not (ical[i] is TVpICalEvent) then - Continue; - startTime := TVpICalEvent(ical[i]).StartTime[false]; // use local times - endTime := TVpICalEvent(ical[i]).EndTime[false]; - if (startTime = 0) and (endTime = 0) then - continue; - id := DataStore.GetNextID(EventsTableName); - FActiveEvent := Datastore.Resource.Schedule.AddEvent(id, starttime, endtime); - FActiveEvent.Changed := true; - FActiveEvent.LoadFromICalendar(TVpICalEvent(ical[i])); - Datastore.PostEvents; - Datastore.NotifyDependents; - end; - end; - Invalidate; + Application.ProcessMessages; + for fn in dlg.Files do + ImportICalFile(fn); finally - ical.Free; Screen.Cursor := crDefault; end; end;