TvPlanIt: Fix ical import (issue #39047)

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@8643 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
wp_xxyyzz
2022-12-11 13:08:39 +00:00
parent 68e8dba861
commit deede7b752
11 changed files with 117 additions and 92 deletions

View File

@ -471,13 +471,16 @@ msgid "Edit shape"
msgstr "Form bearbeiten" msgstr "Form bearbeiten"
#: vpsr.rselementalreadyexists #: vpsr.rselementalreadyexists
#, object-pascal-format #, object-pascal-format,fuzzy
#| msgid ""
#| "An element named %s already exists.\n"
#| "Please use a different name.\n"
msgid "" msgid ""
"An element named %s already exists.\n" "An element named %s already exists.\n"
"Please use a different name." "Please use a different name.\n"
msgstr "" msgstr ""
"Ein Element mit Namen %s existiert bereits.\n" "Ein Element mit Namen %s existiert bereits.\n"
"Bitte einen anderen Namen verwenden." "Bitte einen anderen Namen verwenden.\n"
#: vpsr.rselements #: vpsr.rselements
msgid "Elements:" msgid "Elements:"
@ -1128,13 +1131,16 @@ msgid "&Print"
msgstr "&Drucken" msgstr "&Drucken"
#: vpsr.rsprintformatalreadyexists #: vpsr.rsprintformatalreadyexists
#, object-pascal-format #, object-pascal-format,fuzzy
#| msgid ""
#| "A print template named %s already exists.\n"
#| "Please use a different name.\n"
msgid "" msgid ""
"A print template named %s already exists.\n" "A print template named %s already exists.\n"
"Please use a different name." "Please use a different name.\n"
msgstr "" msgstr ""
"Eine Druckvorlage mit Namen %s existiert bereits.\n" "Eine Druckvorlage mit Namen %s existiert bereits.\n"
"Bitte einen anderen Namen verwenden." "Bitte einen anderen Namen verwenden.\n"
#: vpsr.rsprintformatdesigner #: vpsr.rsprintformatdesigner
msgid "Print template designer" msgid "Print template designer"
@ -1144,7 +1150,7 @@ msgstr "Druckvorlagen-Designer"
msgid "Print order" msgid "Print order"
msgstr "" msgstr ""
"Druck-\n" "Druck-\n"
"Reihenfolge" "Reihenfolge\n"
#: vpsr.rsprintprvcancel #: vpsr.rsprintprvcancel
msgctxt "vpsr.rsprintprvcancel" msgctxt "vpsr.rsprintprvcancel"
@ -1858,3 +1864,4 @@ msgstr "Unbekannte Achsen-Spezifikation: %s"
#: vpsr.sxmldecnotatbeg #: vpsr.sxmldecnotatbeg
msgid "The XML declaration must appear before the first element" msgid "The XML declaration must appear before the first element"
msgstr "Die XML-Deklaration muss vor dem ersten Element erscheinen" msgstr "Die XML-Deklaration muss vor dem ersten Element erscheinen"

View File

@ -466,13 +466,16 @@ msgid "Edit shape"
msgstr "Edit shape" msgstr "Edit shape"
#: vpsr.rselementalreadyexists #: vpsr.rselementalreadyexists
#, object-pascal-format #, object-pascal-format,fuzzy
#| msgid ""
#| "An element named %s already exists.\n"
#| "Please use a different name.\n"
msgid "" msgid ""
"An element named %s already exists.\n" "An element named %s already exists.\n"
"Please use a different name." "Please use a different name.\n"
msgstr "" msgstr ""
"An element named %s already exists.\n" "An element named %s already exists.\n"
"Please use a different name." "Please use a different name.\n"
#: vpsr.rselements #: vpsr.rselements
msgid "Elements:" msgid "Elements:"
@ -1115,13 +1118,16 @@ msgid "&Print"
msgstr "&Print" msgstr "&Print"
#: vpsr.rsprintformatalreadyexists #: vpsr.rsprintformatalreadyexists
#, object-pascal-format #, object-pascal-format,fuzzy
#| msgid ""
#| "A print template named %s already exists.\n"
#| "Please use a different name.\n"
msgid "" msgid ""
"A print template named %s already exists.\n" "A print template named %s already exists.\n"
"Please use a different name." "Please use a different name.\n"
msgstr "" msgstr ""
"A print template named %s already exists.\n" "A print template named %s already exists.\n"
"Please use a different name." "Please use a different name.\n"
#: vpsr.rsprintformatdesigner #: vpsr.rsprintformatdesigner
msgid "Print template designer" msgid "Print template designer"
@ -1838,3 +1844,4 @@ msgstr "Unknown axis specifier: %s"
#: vpsr.sxmldecnotatbeg #: vpsr.sxmldecnotatbeg
msgid "The XML declaration must appear before the first element" msgid "The XML declaration must appear before the first element"
msgstr "The XML declaration must appear before the first element" msgstr "The XML declaration must appear before the first element"

View File

@ -464,7 +464,7 @@ msgstr ""
#, object-pascal-format #, object-pascal-format
msgid "" msgid ""
"An element named %s already exists.\n" "An element named %s already exists.\n"
"Please use a different name." "Please use a different name.\n"
msgstr "" msgstr ""
#: vpsr.rselements #: vpsr.rselements
@ -1122,7 +1122,7 @@ msgstr ""
#, object-pascal-format #, object-pascal-format
msgid "" msgid ""
"A print template named %s already exists.\n" "A print template named %s already exists.\n"
"Please use a different name." "Please use a different name.\n"
msgstr "" msgstr ""
#: vpsr.rsprintformatdesigner #: vpsr.rsprintformatdesigner

View File

@ -484,7 +484,7 @@ msgstr ""
#, object-pascal-format #, object-pascal-format
msgid "" msgid ""
"An element named %s already exists.\n" "An element named %s already exists.\n"
"Please use a different name." "Please use a different name.\n"
msgstr "" msgstr ""
#: vpsr.rselements #: vpsr.rselements
@ -1139,7 +1139,7 @@ msgstr "&Imprimer"
#, object-pascal-format #, object-pascal-format
msgid "" msgid ""
"A print template named %s already exists.\n" "A print template named %s already exists.\n"
"Please use a different name." "Please use a different name.\n"
msgstr "" msgstr ""
#: vpsr.rsprintformatdesigner #: vpsr.rsprintformatdesigner

View File

@ -478,7 +478,7 @@ msgstr ""
#, object-pascal-format #, object-pascal-format
msgid "" msgid ""
"An element named %s already exists.\n" "An element named %s already exists.\n"
"Please use a different name." "Please use a different name.\n"
msgstr "" msgstr ""
#: vpsr.rselements #: vpsr.rselements
@ -1133,7 +1133,7 @@ msgstr "&Printen"
#, object-pascal-format #, object-pascal-format
msgid "" msgid ""
"A print template named %s already exists.\n" "A print template named %s already exists.\n"
"Please use a different name." "Please use a different name.\n"
msgstr "" msgstr ""
#: vpsr.rsprintformatdesigner #: vpsr.rsprintformatdesigner

View File

@ -480,7 +480,7 @@ msgstr "Edycja kształtu"
#, object-pascal-format #, object-pascal-format
msgid "" msgid ""
"An element named %s already exists.\n" "An element named %s already exists.\n"
"Please use a different name." "Please use a different name.\n"
msgstr "" msgstr ""
#: vpsr.rselements #: vpsr.rselements
@ -1143,7 +1143,7 @@ msgstr "&Drukuj"
#, object-pascal-format #, object-pascal-format
msgid "" msgid ""
"A print template named %s already exists.\n" "A print template named %s already exists.\n"
"Please use a different name." "Please use a different name.\n"
msgstr "" msgstr ""
#: vpsr.rsprintformatdesigner #: vpsr.rsprintformatdesigner

View File

@ -480,7 +480,7 @@ msgstr ""
#, object-pascal-format #, object-pascal-format
msgid "" msgid ""
"An element named %s already exists.\n" "An element named %s already exists.\n"
"Please use a different name." "Please use a different name.\n"
msgstr "" msgstr ""
#: vpsr.rselements #: vpsr.rselements
@ -1139,7 +1139,7 @@ msgstr "Печать"
#, object-pascal-format #, object-pascal-format
msgid "" msgid ""
"A print template named %s already exists.\n" "A print template named %s already exists.\n"
"Please use a different name." "Please use a different name.\n"
msgstr "" msgstr ""
#: vpsr.rsprintformatdesigner #: vpsr.rsprintformatdesigner

View File

@ -245,6 +245,7 @@ type
function GetEvent(Index: Integer): TVpEvent; function GetEvent(Index: Integer): TVpEvent;
function ImportICalFile(const AFileName: String; APreview: Boolean = false; function ImportICalFile(const AFileName: String; APreview: Boolean = false;
ADefaultCategory: Integer = -1): TVpEventArr; ADefaultCategory: Integer = -1): TVpEventArr;
function IsEventOfThisDate(ADate: TDateTime; AEvent: TVpEvent): Boolean;
function RepeatsOn(Event: TVpEvent; Day: TDateTime): Boolean; function RepeatsOn(Event: TVpEvent; Day: TDateTime): Boolean;
procedure Sort; procedure Sort;
property Owner: TVpResource read FOwner; property Owner: TVpResource read FOwner;
@ -1927,7 +1928,10 @@ begin
if (not ical[i].Checked) or (not (ical[i] is TVpICalEvent)) then if (not ical[i].Checked) or (not (ical[i] is TVpICalEvent)) then
Continue; Continue;
startTime := TVpICalEvent(ical[i]).StartTime[false]; // use local times startTime := TVpICalEvent(ical[i]).StartTime[false]; // use local times
endTime := TVpICalEvent(ical[i]).EndTime[false]; if TVpICalEvent(ical[i]).IsAllDayEvent then
endTime := trunc(startTime) + 1 - OneSecond
else
endTime := TVpICalEvent(ical[i]).EndTime[false];
if startTime = NO_DATE then if startTime = NO_DATE then
continue; continue;
id := dataStore.GetNextID(EventsTableName); id := dataStore.GetNextID(EventsTableName);
@ -2048,16 +2052,11 @@ var
I: Integer; I: Integer;
Event: TVpEvent; Event: TVpEvent;
begin begin
result := 0; Result := 0;
for I := 0 to pred(EventCount) do begin for I := 0 to pred(EventCount) do begin
Event := GetEvent(I); Event := GetEvent(I);
// If this is a repeating event and it falls on today then inc result if IsEventOfThisDate(Value, Event) then
if (Event.RepeatCode > rtNone) and RepeatsOn(Event, Value) then inc(Result);
Inc(Result)
// Otherwise if it is an event that naturally falls on today, then inc result
else
if DateInRange(Value, Event.StartTime, Event.EndTime, true) then
Inc(Result);
end; end;
end; end;
@ -2068,18 +2067,13 @@ var
begin begin
if EventCountByDay(Date) = 0 then if EventCountByDay(Date) = 0 then
EventList.Clear EventList.Clear
else
else begin begin
// Add this day's events to the Event List. // Add this day's events to the Event List.
for I := 0 to pred(EventCount) do begin for I := 0 to pred(EventCount) do
begin
Event := GetEvent(I); Event := GetEvent(I);
if IsEventOfThisDate(Date, Event) then
// If this is a repeating event and it falls on "Date" then add it to the list.
if (Event.RepeatCode > rtNone) and RepeatsOn(Event, Date) then
EventList.Add(Event)
else
// otherwise if this event naturally falls on "Date" then add it to the list.
if DateInRange(Date, Event.StartTime, Event.EndTime, true) then
EventList.Add(Event); EventList.Add(Event);
end; end;
end; end;
@ -2190,6 +2184,20 @@ begin
result := FEventList.Count; result := FEventList.Count;
end; end;
function TVpSchedule.IsEventOfThisDate(ADate: TDateTime; AEvent: TVpEvent): Boolean;
begin
Result := false;
// Is is a non-repeating event that naturally falls on the given day?
if (AEvent.RepeatCode = rtNone) then
begin
if (AEvent.EndTime <> FOREVER_DATE) and DateInRange(ADate, AEvent.Starttime, AEvent.EndTime, true) then
Result := true;
end else
// Is it a repeating event that falls on the given day?
if RepeatsOn(AEvent, ADate) then
Result := true;
end;
(*****************************************************************************) (*****************************************************************************)
{ TVpContact } { TVpContact }

View File

@ -588,7 +588,7 @@ begin
lValue := 'FREQ=' + RecurrenceFrequency; lValue := 'FREQ=' + RecurrenceFrequency;
if RecurrenceInterval > 0 then if RecurrenceInterval > 0 then
lValue := lValue + ';INTERVAL=' + IntToStr(RecurrenceInterval); lValue := lValue + ';INTERVAL=' + IntToStr(RecurrenceInterval);
if RecurrenceEndDate <> 0 then if (RecurrenceEndDate <> 0) and (RecurrenceEndDate <> FOREVER_DATE) then
lValue := lValue + ';UNTIL=' + FormatDateTime(TIME_FORMAT, RecurrenceEndDate); lValue := lValue + ';UNTIL=' + FormatDateTime(TIME_FORMAT, RecurrenceEndDate);
if RecurrenceCount > 0 then if RecurrenceCount > 0 then
lValue := lValue + ';COUNT=' + IntToStr(RecurrenceCount); lValue := lValue + ';COUNT=' + IntToStr(RecurrenceCount);

View File

@ -335,7 +335,8 @@ begin
L.AddField('AlarmAdvanceType', GetEnumName(TypeInfo(TVpAlarmAdvType), ord(AEvent.AlarmAdvanceType))); L.AddField('AlarmAdvanceType', GetEnumName(TypeInfo(TVpAlarmAdvType), ord(AEvent.AlarmAdvanceType)));
L.AddDateTimeField('SnoozeTime', AEvent.SnoozeTime, 'tt'); // long time format L.AddDateTimeField('SnoozeTime', AEvent.SnoozeTime, 'tt'); // long time format
L.AddField('RepeatCode', GetEnumName(TypeInfo(TVpRepeatType), ord(AEvent.RepeatCode))); L.AddField('RepeatCode', GetEnumName(TypeInfo(TVpRepeatType), ord(AEvent.RepeatCode)));
L.AddDateTimeField('RepeatRangeEnd', AEvent.RepeatRangeEnd, 'ddddd'); // short date format if (AEvent.RepeatRangeEnd <> 0) and (AEvent.RepeatRangeEnd <> FOREVER_DATE) then
L.AddDateTimeField('RepeatRangeEnd', AEvent.RepeatRangeEnd, 'ddddd'); // short date format
L.AddField('CustomInterval', IntToStr(AEvent.CustomInterval)); L.AddField('CustomInterval', IntToStr(AEvent.CustomInterval));
L.AddField('UserField0', AEvent.UserField0); // 15 L.AddField('UserField0', AEvent.UserField0); // 15
L.AddField('UserField1', AEvent.UserField1); L.AddField('UserField1', AEvent.UserField1);
@ -802,7 +803,8 @@ begin
AEvent.SnoozeTime := StrToTime(L.Extract(11)); AEvent.SnoozeTime := StrToTime(L.Extract(11));
AEvent.RepeatCode := TVpRepeatType(GetEnumValue(TypeInfo(TVpRepeatType), L.Extract(12))); AEvent.RepeatCode := TVpRepeatType(GetEnumValue(TypeInfo(TVpRepeatType), L.Extract(12)));
if L[13] = '' then if L[13] = '' then
AEvent.RepeatRangeEnd := 0 else AEvent.RepeatRangeEnd := FOREVER_DATE
else
AEvent.RepeatRangeEnd := StrToDate(L.Extract(13), FFormatSettings); AEvent.RepeatRangeEnd := StrToDate(L.Extract(13), FFormatSettings);
AEvent.CustomInterval := StrToInt(L.Extract(14)); AEvent.CustomInterval := StrToInt(L.Extract(14));
AEvent.UserField0 := L.Extract(15); AEvent.UserField0 := L.Extract(15);

View File

@ -294,63 +294,64 @@ begin
DrawDayHeader(ADayIndex, holiday, TextRect); DrawDayHeader(ADayIndex, holiday, TextRect);
if (FWeekView.DataStore <> nil) and (FWeekView.DataStore.Resource <> nil) and if (FWeekView.DataStore <> nil) and (FWeekView.DataStore.Resource <> nil) and
(FWeekView.DataStore.Resource.Schedule.EventCountByDay(StartDate + ADayIndex) > 0) and // (FWeekView.DataStore.Resource.Schedule.EventCountByDay(StartDate + ADayIndex) > 0) and
(HeightOf(DayRect) >= FWeekView.TextMargin * 2 + FDayHeadHeight) (HeightOf(DayRect) >= FWeekView.TextMargin * 2 + FDayHeadHeight)
then begin then begin
// Events exist for this day // EventList is supposesd to collect the events for the day handled in this procedure
EventList := TList.Create; EventList := TList.Create;
try try
// Populate the event list with events for this day // Populate the event list with events for this day
FWeekView.DataStore.Resource.Schedule.EventsByDate(StartDate + ADayIndex, EventList); FWeekView.DataStore.Resource.Schedule.EventsByDate(StartDate + ADayIndex, EventList);
if EventList.Count > 0 then
{ Now sort times in ascending order. This must be done because the event
list can contain recurring events which have the wrong date part }
EventList.Sort(CompareEventsByTimeOnly);
// Initialize TextRect for this day
TextRect := DayRect;
TextRect.Top := DayRect.Top + FDayHeadHeight + 1;
TextRect.Bottom := TextRect.Top + rowHeight;
// Handle all-day events
tmpRect := TextRect;
tmpRect.Bottom := DayRect.Bottom;
if DrawAllDayEvents(StartDate + ADayIndex, tmpRect, EAIndex) then
begin begin
TextRect.Bottom := TextRect.Bottom + ADEventsRect.Bottom - TextRect.Top; { Now sort times in ascending order. This must be done because the event
TextRect.Top := ADEventsRect.Bottom; list can contain recurring events which have the wrong date part }
end; EventList.Sort(CompareEventsByTimeOnly);
// Discard AllDayEvents, because they are drawn above. // Initialize TextRect for this day
for J := pred(EventList.Count) downto 0 do TextRect := DayRect;
if TVpEvent(EventList[J]).AllDayEvent then TextRect.Top := DayRect.Top + FDayHeadHeight + 1;
EventList.Delete(J);
// Iterate the events, painting them one by one
for J := 0 to pred(EventList.Count) do begin
{ if the TextRect extends below the available space then draw a }
{ dot dot dot to indicate there are more events than can be drawn }
{ in the available space }
if TextRect.Bottom - FWeekView.TextMargin > DayRect.Bottom then begin
{ Draw ". . ." }
DrawDotDotDot(DayRect, DotDotDotColor);
break;
end;
// Write the event text
DrawEvent(TVpEvent(EventList.List^[J]), TextRect, ADayIndex);
// Update the EventArray
with TVpWeekViewOpener(FWeekView).wvEventArray[EAIndex] do begin
Rec := TextRect;
Event := TVpEvent(EventList[J]);
end;
Inc(EAIndex);
TextRect.Top := TextRect.Bottom;
TextRect.Bottom := TextRect.Top + rowHeight; TextRect.Bottom := TextRect.Top + rowHeight;
end; { for loop }
// Handle all-day events
tmpRect := TextRect;
tmpRect.Bottom := DayRect.Bottom;
if DrawAllDayEvents(StartDate + ADayIndex, tmpRect, EAIndex) then
begin
TextRect.Bottom := TextRect.Bottom + ADEventsRect.Bottom - TextRect.Top;
TextRect.Top := ADEventsRect.Bottom;
end;
// Discard AllDayEvents, because they are drawn above.
for J := pred(EventList.Count) downto 0 do
if TVpEvent(EventList[J]).AllDayEvent then
EventList.Delete(J);
// Iterate the events, painting them one by one
for J := 0 to pred(EventList.Count) do begin
{ if the TextRect extends below the available space then draw a }
{ dot dot dot to indicate there are more events than can be drawn }
{ in the available space }
if TextRect.Bottom - FWeekView.TextMargin > DayRect.Bottom then begin
{ Draw ". . ." }
DrawDotDotDot(DayRect, DotDotDotColor);
break;
end;
// Write the event text
DrawEvent(TVpEvent(EventList.List^[J]), TextRect, ADayIndex);
// Update the EventArray
with TVpWeekViewOpener(FWeekView).wvEventArray[EAIndex] do begin
Rec := TextRect;
Event := TVpEvent(EventList[J]);
end;
Inc(EAIndex);
TextRect.Top := TextRect.Bottom;
TextRect.Bottom := TextRect.Top + rowHeight;
end; { for loop }
end;
finally finally
EventList.Free; EventList.Free;
end; end;