You've already forked lazarus-ccr
tvplanit: Implement import of events from iCal files (*.ics). Some issues left.
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@6499 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@ -520,6 +520,10 @@ msgstr "Zuhause"
|
|||||||
msgid "Hours"
|
msgid "Hours"
|
||||||
msgstr "Stunden"
|
msgstr "Stunden"
|
||||||
|
|
||||||
|
#: vpsr.rsicalfilter
|
||||||
|
msgid "iCalendar files (*.ical;*.ics)|*.ical;*.ics"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: vpsr.rsinches
|
#: vpsr.rsinches
|
||||||
msgid "Inches"
|
msgid "Inches"
|
||||||
msgstr "Zoll"
|
msgstr "Zoll"
|
||||||
@ -581,8 +585,12 @@ msgstr "M"
|
|||||||
msgid "Load file..."
|
msgid "Load file..."
|
||||||
msgstr "Datei laden..."
|
msgstr "Datei laden..."
|
||||||
|
|
||||||
|
#: vpsr.rsloadicaltitle
|
||||||
|
msgid "Import from iCal file(s)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: vpsr.rsloadvcardstitle
|
#: vpsr.rsloadvcardstitle
|
||||||
msgid "Load vCard(s)"
|
msgid "Import from vCard(s)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: vpsr.rslocation
|
#: vpsr.rslocation
|
||||||
@ -920,6 +928,10 @@ msgctxt "vpsr.rspopupaddevent"
|
|||||||
msgid "Add event..."
|
msgid "Add event..."
|
||||||
msgstr "Ereignis hinzufügen..."
|
msgstr "Ereignis hinzufügen..."
|
||||||
|
|
||||||
|
#: vpsr.rspopupaddeventfromical
|
||||||
|
msgid "Import from iCalendar file(s)..."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: vpsr.rspopupchangedate
|
#: vpsr.rspopupchangedate
|
||||||
msgctxt "vpsr.rspopupchangedate"
|
msgctxt "vpsr.rspopupchangedate"
|
||||||
msgid "Change date"
|
msgid "Change date"
|
||||||
@ -1128,6 +1140,10 @@ msgstr "Fehler: Kann nicht updaten"
|
|||||||
msgid "Incorrect order of start and end times. Do you want to exchange them?"
|
msgid "Incorrect order of start and end times. Do you want to exchange them?"
|
||||||
msgstr "Falsche Reihenfolge der Start- und Ende-Zeit. Wollen Sie die beiden vertauschen?"
|
msgstr "Falsche Reihenfolge der Start- und Ende-Zeit. Wollen Sie die beiden vertauschen?"
|
||||||
|
|
||||||
|
#: vpsr.rsstartendtimesequal
|
||||||
|
msgid "Start and end times cannot be equal."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: vpsr.rsstarttimelbl
|
#: vpsr.rsstarttimelbl
|
||||||
msgid "Start time:"
|
msgid "Start time:"
|
||||||
msgstr "Start-Zeit:"
|
msgstr "Start-Zeit:"
|
||||||
|
@ -511,6 +511,10 @@ msgstr ""
|
|||||||
msgid "Hours"
|
msgid "Hours"
|
||||||
msgstr "Tunnit"
|
msgstr "Tunnit"
|
||||||
|
|
||||||
|
#: vpsr.rsicalfilter
|
||||||
|
msgid "iCalendar files (*.ical;*.ics)|*.ical;*.ics"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: vpsr.rsinches
|
#: vpsr.rsinches
|
||||||
msgid "Inches"
|
msgid "Inches"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -572,8 +576,12 @@ msgstr "M"
|
|||||||
msgid "Load file..."
|
msgid "Load file..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: vpsr.rsloadicaltitle
|
||||||
|
msgid "Import from iCal file(s)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: vpsr.rsloadvcardstitle
|
#: vpsr.rsloadvcardstitle
|
||||||
msgid "Load vCard(s)"
|
msgid "Import from vCard(s)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: vpsr.rslocation
|
#: vpsr.rslocation
|
||||||
@ -911,6 +919,10 @@ msgctxt "vpsr.rspopupaddevent"
|
|||||||
msgid "Add event..."
|
msgid "Add event..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: vpsr.rspopupaddeventfromical
|
||||||
|
msgid "Import from iCalendar file(s)..."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: vpsr.rspopupchangedate
|
#: vpsr.rspopupchangedate
|
||||||
msgctxt "vpsr.rspopupchangedate"
|
msgctxt "vpsr.rspopupchangedate"
|
||||||
msgid "Change date"
|
msgid "Change date"
|
||||||
@ -1117,6 +1129,10 @@ msgstr ""
|
|||||||
msgid "Incorrect order of start and end times. Do you want to exchange them?"
|
msgid "Incorrect order of start and end times. Do you want to exchange them?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: vpsr.rsstartendtimesequal
|
||||||
|
msgid "Start and end times cannot be equal."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: vpsr.rsstarttimelbl
|
#: vpsr.rsstarttimelbl
|
||||||
msgid "Start time:"
|
msgid "Start time:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -526,6 +526,10 @@ msgstr "Maison"
|
|||||||
msgid "Hours"
|
msgid "Hours"
|
||||||
msgstr "Heures"
|
msgstr "Heures"
|
||||||
|
|
||||||
|
#: vpsr.rsicalfilter
|
||||||
|
msgid "iCalendar files (*.ical;*.ics)|*.ical;*.ics"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: vpsr.rsinches
|
#: vpsr.rsinches
|
||||||
msgid "Inches"
|
msgid "Inches"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -587,8 +591,12 @@ msgstr ""
|
|||||||
msgid "Load file..."
|
msgid "Load file..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: vpsr.rsloadicaltitle
|
||||||
|
msgid "Import from iCal file(s)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: vpsr.rsloadvcardstitle
|
#: vpsr.rsloadvcardstitle
|
||||||
msgid "Load vCard(s)"
|
msgid "Import from vCard(s)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: vpsr.rslocation
|
#: vpsr.rslocation
|
||||||
@ -926,6 +934,10 @@ msgctxt "vpsr.rspopupaddevent"
|
|||||||
msgid "Add event..."
|
msgid "Add event..."
|
||||||
msgstr "Ajouter un événement..."
|
msgstr "Ajouter un événement..."
|
||||||
|
|
||||||
|
#: vpsr.rspopupaddeventfromical
|
||||||
|
msgid "Import from iCalendar file(s)..."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: vpsr.rspopupchangedate
|
#: vpsr.rspopupchangedate
|
||||||
msgctxt "vpsr.rspopupchangedate"
|
msgctxt "vpsr.rspopupchangedate"
|
||||||
msgid "Change date"
|
msgid "Change date"
|
||||||
@ -1134,6 +1146,10 @@ msgstr "Erreur: Modification à echoué"
|
|||||||
msgid "Incorrect order of start and end times. Do you want to exchange them?"
|
msgid "Incorrect order of start and end times. Do you want to exchange them?"
|
||||||
msgstr "Ordre incorrect des heures de début et de fin. Voulez-vous les retourner?"
|
msgstr "Ordre incorrect des heures de début et de fin. Voulez-vous les retourner?"
|
||||||
|
|
||||||
|
#: vpsr.rsstartendtimesequal
|
||||||
|
msgid "Start and end times cannot be equal."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: vpsr.rsstarttimelbl
|
#: vpsr.rsstarttimelbl
|
||||||
msgid "Start time:"
|
msgid "Start time:"
|
||||||
msgstr "Début"
|
msgstr "Début"
|
||||||
|
@ -520,6 +520,10 @@ msgstr "Thuis"
|
|||||||
msgid "Hours"
|
msgid "Hours"
|
||||||
msgstr "Uren"
|
msgstr "Uren"
|
||||||
|
|
||||||
|
#: vpsr.rsicalfilter
|
||||||
|
msgid "iCalendar files (*.ical;*.ics)|*.ical;*.ics"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: vpsr.rsinches
|
#: vpsr.rsinches
|
||||||
msgid "Inches"
|
msgid "Inches"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -581,8 +585,12 @@ msgstr "M"
|
|||||||
msgid "Load file..."
|
msgid "Load file..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: vpsr.rsloadicaltitle
|
||||||
|
msgid "Import from iCal file(s)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: vpsr.rsloadvcardstitle
|
#: vpsr.rsloadvcardstitle
|
||||||
msgid "Load vCard(s)"
|
msgid "Import from vCard(s)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: vpsr.rslocation
|
#: vpsr.rslocation
|
||||||
@ -920,6 +928,10 @@ msgctxt "vpsr.rspopupaddevent"
|
|||||||
msgid "Add event..."
|
msgid "Add event..."
|
||||||
msgstr "Gebeurtenis toevoegen..."
|
msgstr "Gebeurtenis toevoegen..."
|
||||||
|
|
||||||
|
#: vpsr.rspopupaddeventfromical
|
||||||
|
msgid "Import from iCalendar file(s)..."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: vpsr.rspopupchangedate
|
#: vpsr.rspopupchangedate
|
||||||
msgctxt "vpsr.rspopupchangedate"
|
msgctxt "vpsr.rspopupchangedate"
|
||||||
msgid "Change date"
|
msgid "Change date"
|
||||||
@ -1128,6 +1140,10 @@ msgstr "Fout: Updaten niet mogelijk "
|
|||||||
msgid "Incorrect order of start and end times. Do you want to exchange them?"
|
msgid "Incorrect order of start and end times. Do you want to exchange them?"
|
||||||
msgstr "Incorrecte volgorde van start- en eindtijden. Wilt u ze verwisselen?"
|
msgstr "Incorrecte volgorde van start- en eindtijden. Wilt u ze verwisselen?"
|
||||||
|
|
||||||
|
#: vpsr.rsstartendtimesequal
|
||||||
|
msgid "Start and end times cannot be equal."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: vpsr.rsstarttimelbl
|
#: vpsr.rsstarttimelbl
|
||||||
msgid "Start time:"
|
msgid "Start time:"
|
||||||
msgstr "Starttijd:"
|
msgstr "Starttijd:"
|
||||||
|
@ -510,6 +510,10 @@ msgstr ""
|
|||||||
msgid "Hours"
|
msgid "Hours"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: vpsr.rsicalfilter
|
||||||
|
msgid "iCalendar files (*.ical;*.ics)|*.ical;*.ics"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: vpsr.rsinches
|
#: vpsr.rsinches
|
||||||
msgid "Inches"
|
msgid "Inches"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -571,8 +575,12 @@ msgstr ""
|
|||||||
msgid "Load file..."
|
msgid "Load file..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: vpsr.rsloadicaltitle
|
||||||
|
msgid "Import from iCal file(s)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: vpsr.rsloadvcardstitle
|
#: vpsr.rsloadvcardstitle
|
||||||
msgid "Load vCard(s)"
|
msgid "Import from vCard(s)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: vpsr.rslocation
|
#: vpsr.rslocation
|
||||||
@ -910,6 +918,10 @@ msgctxt "vpsr.rspopupaddevent"
|
|||||||
msgid "Add event..."
|
msgid "Add event..."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: vpsr.rspopupaddeventfromical
|
||||||
|
msgid "Import from iCalendar file(s)..."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: vpsr.rspopupchangedate
|
#: vpsr.rspopupchangedate
|
||||||
msgctxt "vpsr.rspopupchangedate"
|
msgctxt "vpsr.rspopupchangedate"
|
||||||
msgid "Change date"
|
msgid "Change date"
|
||||||
@ -1116,6 +1128,10 @@ msgstr ""
|
|||||||
msgid "Incorrect order of start and end times. Do you want to exchange them?"
|
msgid "Incorrect order of start and end times. Do you want to exchange them?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: vpsr.rsstartendtimesequal
|
||||||
|
msgid "Start and end times cannot be equal."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: vpsr.rsstarttimelbl
|
#: vpsr.rsstarttimelbl
|
||||||
msgid "Start time:"
|
msgid "Start time:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -520,6 +520,10 @@ msgstr "Домашний"
|
|||||||
msgid "Hours"
|
msgid "Hours"
|
||||||
msgstr "Часы"
|
msgstr "Часы"
|
||||||
|
|
||||||
|
#: vpsr.rsicalfilter
|
||||||
|
msgid "iCalendar files (*.ical;*.ics)|*.ical;*.ics"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: vpsr.rsinches
|
#: vpsr.rsinches
|
||||||
msgid "Inches"
|
msgid "Inches"
|
||||||
msgstr "Дюймы"
|
msgstr "Дюймы"
|
||||||
@ -581,8 +585,12 @@ msgstr ""
|
|||||||
msgid "Load file..."
|
msgid "Load file..."
|
||||||
msgstr "Загрузить файл..."
|
msgstr "Загрузить файл..."
|
||||||
|
|
||||||
|
#: vpsr.rsloadicaltitle
|
||||||
|
msgid "Import from iCal file(s)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: vpsr.rsloadvcardstitle
|
#: vpsr.rsloadvcardstitle
|
||||||
msgid "Load vCard(s)"
|
msgid "Import from vCard(s)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: vpsr.rslocation
|
#: vpsr.rslocation
|
||||||
@ -920,6 +928,10 @@ msgctxt "vpsr.rspopupaddevent"
|
|||||||
msgid "Add event..."
|
msgid "Add event..."
|
||||||
msgstr "Добавить событие..."
|
msgstr "Добавить событие..."
|
||||||
|
|
||||||
|
#: vpsr.rspopupaddeventfromical
|
||||||
|
msgid "Import from iCalendar file(s)..."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: vpsr.rspopupchangedate
|
#: vpsr.rspopupchangedate
|
||||||
msgctxt "vpsr.rspopupchangedate"
|
msgctxt "vpsr.rspopupchangedate"
|
||||||
msgid "Change date"
|
msgid "Change date"
|
||||||
@ -1126,6 +1138,10 @@ msgstr "Ошибка обновления"
|
|||||||
msgid "Incorrect order of start and end times. Do you want to exchange them?"
|
msgid "Incorrect order of start and end times. Do you want to exchange them?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: vpsr.rsstartendtimesequal
|
||||||
|
msgid "Start and end times cannot be equal."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: vpsr.rsstarttimelbl
|
#: vpsr.rsstarttimelbl
|
||||||
msgid "Start time:"
|
msgid "Start time:"
|
||||||
msgstr "Время начала:"
|
msgstr "Время начала:"
|
||||||
|
@ -32,7 +32,7 @@ Portions created by TurboPower Software Inc. are Copyright (C) 2002 TurboPower S
|
|||||||
|
|
||||||
Contributor(s): "/>
|
Contributor(s): "/>
|
||||||
<Version Major="1" Release="11"/>
|
<Version Major="1" Release="11"/>
|
||||||
<Files Count="73">
|
<Files Count="74">
|
||||||
<Item1>
|
<Item1>
|
||||||
<Filename Value="source\vpbase.pas"/>
|
<Filename Value="source\vpbase.pas"/>
|
||||||
<UnitName Value="VpBase"/>
|
<UnitName Value="VpBase"/>
|
||||||
@ -325,6 +325,10 @@ Contributor(s): "/>
|
|||||||
<Filename Value="source\vpbasedatafiles.pas"/>
|
<Filename Value="source\vpbasedatafiles.pas"/>
|
||||||
<UnitName Value="vpbasedatafiles"/>
|
<UnitName Value="vpbasedatafiles"/>
|
||||||
</Item73>
|
</Item73>
|
||||||
|
<Item74>
|
||||||
|
<Filename Value="source\vpical.pas"/>
|
||||||
|
<UnitName Value="VpICAL"/>
|
||||||
|
</Item74>
|
||||||
</Files>
|
</Files>
|
||||||
<i18n>
|
<i18n>
|
||||||
<EnableI18N Value="True"/>
|
<EnableI18N Value="True"/>
|
||||||
|
@ -165,7 +165,7 @@ resourcestring
|
|||||||
RSContactPopupEdit = 'Edit contact...';
|
RSContactPopupEdit = 'Edit contact...';
|
||||||
RSContactPopupDelete = 'Delete contact...';
|
RSContactPopupDelete = 'Delete contact...';
|
||||||
RSConfirmDeleteContact = 'Delete contact %s?';
|
RSConfirmDeleteContact = 'Delete contact %s?';
|
||||||
RSLoadVCardsTitle = 'Load vCard(s)';
|
RSLoadVCardsTitle = 'Import from vCard(s)';
|
||||||
RSVCardFilter = 'vCard files (*.vcf)|*.vcf';
|
RSVCardFilter = 'vCard files (*.vcf)|*.vcf';
|
||||||
|
|
||||||
{Event Specific}
|
{Event Specific}
|
||||||
@ -174,10 +174,13 @@ resourcestring
|
|||||||
RSConfirmDeleteEvent = 'Delete event from schedule?';
|
RSConfirmDeleteEvent = 'Delete event from schedule?';
|
||||||
RSStartEndTimeError = 'Incorrect order of start and end times. ' +
|
RSStartEndTimeError = 'Incorrect order of start and end times. ' +
|
||||||
'Do you want to exchange them?';
|
'Do you want to exchange them?';
|
||||||
|
RSStartEndTimesEqual = 'Start and end times cannot be equal.';
|
||||||
RSCannotEditOverlayedEvent= 'Cannot edit this overlayed event.';
|
RSCannotEditOverlayedEvent= 'Cannot edit this overlayed event.';
|
||||||
|
RSLoadICalTitle = 'Import from iCal file(s)';
|
||||||
RSNoOverlayedEvents = 'none';
|
RSNoOverlayedEvents = 'none';
|
||||||
RSOverlayedEvent = 'overlayed';
|
RSOverlayedEvent = 'overlayed';
|
||||||
RSOverlayed = 'Overlayed';
|
RSOverlayed = 'Overlayed';
|
||||||
|
RSICalFilter = 'iCalendar files (*.ical;*.ics)|*.ical;*.ics';
|
||||||
|
|
||||||
{Task Specific}
|
{Task Specific}
|
||||||
RSConfirmDeleteTask = 'Delete this task from your list?';
|
RSConfirmDeleteTask = 'Delete this task from your list?';
|
||||||
@ -189,6 +192,7 @@ resourcestring
|
|||||||
|
|
||||||
{ Popup specific }
|
{ Popup specific }
|
||||||
RSPopupAddEvent = 'Add event...';
|
RSPopupAddEvent = 'Add event...';
|
||||||
|
RSPopupAddEventFromICal = 'Import from iCalendar file(s)...';
|
||||||
RSPopupEditEvent = 'Edit event...';
|
RSPopupEditEvent = 'Edit event...';
|
||||||
RSPopupDeleteEvent = '&Delete event...';
|
RSPopupDeleteEvent = '&Delete event...';
|
||||||
RSPopupChangeDate = 'Change date';
|
RSPopupChangeDate = 'Change date';
|
||||||
|
@ -15,9 +15,9 @@ type
|
|||||||
protected
|
protected
|
||||||
FRaw: String;
|
FRaw: String;
|
||||||
FKey: String;
|
FKey: String;
|
||||||
FTags: TStrings;
|
FAttributes: TStrings;
|
||||||
FValue: String;
|
FValue: String;
|
||||||
procedure GetParts(AText: String; out AKey: String; out ATags: TStringArray;
|
procedure GetParts(AText: String; out AKey: String; out Attr: TStringArray;
|
||||||
out AValue: String);
|
out AValue: String);
|
||||||
function UnEscape(AValueText: String): String;
|
function UnEscape(AValueText: String): String;
|
||||||
function UnquotePrintable(AValueText: String): String;
|
function UnquotePrintable(AValueText: String): String;
|
||||||
@ -26,7 +26,7 @@ type
|
|||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
procedure Analyze;
|
procedure Analyze;
|
||||||
property Key: String read FKey;
|
property Key: String read FKey;
|
||||||
property Tags: TStrings read FTags;
|
property Attributes: TStrings read FAttributes;
|
||||||
property Value: String read FValue;
|
property Value: String read FValue;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -35,7 +35,7 @@ type
|
|||||||
TVpFileBlock = class
|
TVpFileBlock = class
|
||||||
private
|
private
|
||||||
FItemClass: TVpFileItemClass;
|
FItemClass: TVpFileItemClass;
|
||||||
function GetValue(const AKey, ATags: String): String;
|
function GetValue(const AKey, Attributes: String): String;
|
||||||
protected
|
protected
|
||||||
FItems: TObjectList;
|
FItems: TObjectList;
|
||||||
public
|
public
|
||||||
@ -43,8 +43,8 @@ type
|
|||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
procedure Add(const AText: String);
|
procedure Add(const AText: String);
|
||||||
procedure Analyze; virtual;
|
procedure Analyze; virtual;
|
||||||
function FindItem(AKey, ATags: String): TVpFileItem;
|
function FindItem(AKey, Attributes: String): TVpFileItem;
|
||||||
property Value[AKey: String; const ATags: String]: String read GetValue;
|
property Value[AKey: String; const Attributes: String]: String read GetValue;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
const
|
const
|
||||||
@ -71,25 +71,25 @@ end;
|
|||||||
|
|
||||||
destructor TVpFileItem.Destroy;
|
destructor TVpFileItem.Destroy;
|
||||||
begin
|
begin
|
||||||
FTags.Free;
|
FAttributes.Free;
|
||||||
inherited;
|
inherited;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TVpFileItem.Analyze;
|
procedure TVpFileItem.Analyze;
|
||||||
var
|
var
|
||||||
tagarray: TStringArray;
|
attrArray: TStringArray;
|
||||||
i: Integer;
|
i: Integer;
|
||||||
begin
|
begin
|
||||||
GetParts(FRaw, FKey, tagarray, FValue);
|
GetParts(FRaw, FKey, attrArray, FValue);
|
||||||
FTags := TStringList.Create;
|
FAttributes := TStringList.Create;
|
||||||
for i:=Low(tagarray) to High(tagarray) do
|
for i:=Low(attrArray) to High(attrArray) do
|
||||||
FTags.Add(tagarray[i]);
|
FAttributes.Add(attrArray[i]);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// Example
|
// Example
|
||||||
// ADR;TYPE=WORK,POSTAL,PARCEL:;;One Microsoft Way;Redmond;WA;98052-6399;USA
|
// ADR;TYPE=WORK,POSTAL,PARCEL:;;One Microsoft Way;Redmond;WA;98052-6399;USA
|
||||||
procedure TVpFileItem.GetParts(AText: String; out AKey: String;
|
procedure TVpFileItem.GetParts(AText: String; out AKey: String;
|
||||||
out ATags: TStringArray; out AValue: String);
|
out Attr: TStringArray; out AValue: String);
|
||||||
var
|
var
|
||||||
p: Integer;
|
p: Integer;
|
||||||
keypart, valuepart: String;
|
keypart, valuepart: String;
|
||||||
@ -107,17 +107,17 @@ begin
|
|||||||
p := pos(KEY_DELIMITER, keypart);
|
p := pos(KEY_DELIMITER, keypart);
|
||||||
if p = 0 then begin
|
if p = 0 then begin
|
||||||
AKey := keypart;
|
AKey := keypart;
|
||||||
SetLength(ATags, 0);
|
SetLength(Attr, 0);
|
||||||
end else begin
|
end else begin
|
||||||
AKey := Copy(keypart, 1, p-1);
|
AKey := Copy(keypart, 1, p-1);
|
||||||
keypart := Copy(keypart, p+1, MaxInt);
|
keypart := Copy(keypart, p+1, MaxInt);
|
||||||
if pos('TYPE=', keypart) = 1 then begin
|
if pos('TYPE=', keypart) = 1 then begin
|
||||||
keypart := copy(keypart, Length('TYPE='), MaxInt);
|
keypart := copy(keypart, Length('TYPE='), MaxInt);
|
||||||
ATags := Split(keypart, TYPE_DELIMITER); // Split at ','
|
Attr := Split(keypart, TYPE_DELIMITER); // Split at ','
|
||||||
end else
|
end else
|
||||||
ATags := Split(keypart, KEY_DELIMITER); // Split at ';'
|
Attr := Split(keypart, KEY_DELIMITER); // Split at ';'
|
||||||
for i:=Low(ATags) to High(ATags) do
|
for i:=Low(Attr) to High(Attr) do
|
||||||
if ATags[i] = 'QUOTED-PRINTABLE' then begin
|
if Attr[i] = 'QUOTED-PRINTABLE' then begin
|
||||||
QuotedPrintable := true;
|
QuotedPrintable := true;
|
||||||
break;
|
break;
|
||||||
end;
|
end;
|
||||||
@ -256,34 +256,39 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ Finds the item with the specified key and tags. Several tags can be combined
|
{ Finds the item with the specified key and attributes.
|
||||||
by a semicolon. If a tag name begins with a '-' then it must NOT be present.
|
Several attributes can be combined by a semicolon.
|
||||||
|
If an attribute name begins with a '-' then it must NOT be present.
|
||||||
The conditions are and-ed, i.e. all conditions must be met for the item to
|
The conditions are and-ed, i.e. all conditions must be met for the item to
|
||||||
be accepted. }
|
be accepted. }
|
||||||
function TVpFileBlock.FindItem(AKey, ATags: String): TVpFileItem;
|
function TVpFileBlock.FindItem(AKey, Attributes: String): TVpFileItem;
|
||||||
var
|
var
|
||||||
i: Integer;
|
i: Integer;
|
||||||
item: TVpFileItem;
|
item: TVpFileItem;
|
||||||
tagArr: TStringArray;
|
attrArray: TStringArray;
|
||||||
tag, notTag: String;
|
attr, notAttr: String;
|
||||||
ok: Boolean;
|
ok: Boolean;
|
||||||
begin
|
begin
|
||||||
tagArr := Split(ATags, ';');
|
attrArray := Split(Attributes, ';');
|
||||||
|
|
||||||
for i:=0 to FItems.Count-1 do begin
|
for i:=0 to FItems.Count-1 do begin
|
||||||
item := TVpFileItem(FItems[i]);
|
item := TVpFileItem(FItems[i]);
|
||||||
if (AKey = item.Key) then
|
if (AKey = item.Key) then
|
||||||
begin
|
begin
|
||||||
ok := true; // No tags specified --> use first item found
|
ok := true; // No attr specified --> use first item found
|
||||||
if Length(tagArr) > 0 then begin
|
if Length(attrArray) > 0 then begin
|
||||||
for tag in tagArr do begin
|
for attr in attrArray do begin
|
||||||
if tag[1] = '-' then
|
if attr[1] = '-' then
|
||||||
notTag := Copy(tag, 2, MaxInt);
|
notAttr := Copy(attr, 2, MaxInt)
|
||||||
if item.Tags.IndexOf(tag) = -1 then begin // Tag not found --> reject
|
else
|
||||||
|
notAttr := '';
|
||||||
|
if item.Attributes.IndexOf(attr) = -1 then begin
|
||||||
|
// required attribute not found --> reject
|
||||||
ok := false;
|
ok := false;
|
||||||
break;
|
break;
|
||||||
end;
|
end;
|
||||||
if item.Tags.Indexof(notTag) <> -1 then begin // "NOT" tag found --> reject
|
if (notAttr <> '') and (item.Attributes.IndexOf(notAttr) <> -1) then begin
|
||||||
|
// forbidden attribute found --> reject
|
||||||
ok := false;
|
ok := false;
|
||||||
break;
|
break;
|
||||||
end;
|
end;
|
||||||
@ -298,11 +303,11 @@ begin
|
|||||||
Result := nil;
|
Result := nil;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TVpFileBlock.GetValue(const AKey, ATags: String): String;
|
function TVpFileBlock.GetValue(const AKey, Attributes: String): String;
|
||||||
var
|
var
|
||||||
item: TVpFileItem;
|
item: TVpFileItem;
|
||||||
begin
|
begin
|
||||||
item := FindItem(AKey, ATags);
|
item := FindItem(AKey, Attributes);
|
||||||
if item <> nil then
|
if item <> nil then
|
||||||
Result := item.Value
|
Result := item.Value
|
||||||
else
|
else
|
||||||
|
@ -26,7 +26,9 @@
|
|||||||
{* *}
|
{* *}
|
||||||
{* ***** END LICENSE BLOCK ***** *}
|
{* ***** END LICENSE BLOCK ***** *}
|
||||||
|
|
||||||
{$I vp.inc}
|
{$MODE ObjFPC}{$H+}
|
||||||
|
|
||||||
|
//{$I vp.inc}
|
||||||
|
|
||||||
unit VpData;
|
unit VpData;
|
||||||
{ Data classes for Visual PlanIt's resources, events, tasks, contacts, etc... }
|
{ Data classes for Visual PlanIt's resources, events, tasks, contacts, etc... }
|
||||||
@ -34,14 +36,9 @@ unit VpData;
|
|||||||
interface
|
interface
|
||||||
|
|
||||||
uses
|
uses
|
||||||
{$IFDEF LCL}
|
|
||||||
LCLProc, LCLType,
|
LCLProc, LCLType,
|
||||||
{$ELSE}
|
|
||||||
Windows,
|
|
||||||
{$ENDIF}
|
|
||||||
SysUtils, Classes, Dialogs, Graphics,
|
SysUtils, Classes, Dialogs, Graphics,
|
||||||
{$IFDEF VERSION6} Types, {$ENDIF}
|
VpSR, VpVCard, VpICal;
|
||||||
VpSR, VpVCard;
|
|
||||||
|
|
||||||
type
|
type
|
||||||
TVpEventRec = packed record
|
TVpEventRec = packed record
|
||||||
@ -307,6 +304,7 @@ type
|
|||||||
function CanEdit: Boolean;
|
function CanEdit: Boolean;
|
||||||
function GetResource: TVpResource;
|
function GetResource: TVpResource;
|
||||||
function IsOverlayed: Boolean;
|
function IsOverlayed: Boolean;
|
||||||
|
procedure LoadFromICalendar(AEntry: TVpICalEvent);
|
||||||
property Owner: TVpSchedule read FOwner;
|
property Owner: TVpSchedule read FOwner;
|
||||||
property ResourceID: Integer read FResourceID write FResourceID;
|
property ResourceID: Integer read FResourceID write FResourceID;
|
||||||
property Loading : Boolean read FLoading write FLoading;
|
property Loading : Boolean read FLoading write FLoading;
|
||||||
@ -696,7 +694,7 @@ function CompareEventsByTimeOnly(Item1, Item2: Pointer): Integer;
|
|||||||
implementation
|
implementation
|
||||||
|
|
||||||
uses
|
uses
|
||||||
Math,
|
Math, DateUtils,
|
||||||
VpException, VpConst, VpMisc;
|
VpException, VpConst, VpMisc;
|
||||||
|
|
||||||
const
|
const
|
||||||
@ -913,7 +911,7 @@ var
|
|||||||
begin
|
begin
|
||||||
result := nil;
|
result := nil;
|
||||||
for I := 0 to pred(FResourceList.Count) do begin
|
for I := 0 to pred(FResourceList.Count) do begin
|
||||||
res := FResourceList.Items[I];
|
res := TVpResource(FResourceList.Items[I]);
|
||||||
if Res.ResourceID = ID then begin
|
if Res.ResourceID = ID then begin
|
||||||
result := Res;
|
result := Res;
|
||||||
Exit;
|
Exit;
|
||||||
@ -1263,6 +1261,111 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function IsInteger(d, Epsilon: Double): Boolean;
|
||||||
|
begin
|
||||||
|
Result := abs(d - round(d)) < Epsilon;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TVpEvent.LoadFromICalendar(AEntry: TVpICalEvent);
|
||||||
|
var
|
||||||
|
dt: Double;
|
||||||
|
begin
|
||||||
|
if AEntry = nil then
|
||||||
|
exit;
|
||||||
|
|
||||||
|
{ Standard event properties }
|
||||||
|
FDescription := AEntry.Summary;
|
||||||
|
FNotes := AEntry.Description;
|
||||||
|
FLocation := AEntry.Location;
|
||||||
|
// Start and end time already have been set --> Skip .
|
||||||
|
|
||||||
|
{ All-day event }
|
||||||
|
FAllDayEvent := (frac(FStartTime) = 0) and (frac(FEndTime) = 0);
|
||||||
|
|
||||||
|
{ Alarm properties }
|
||||||
|
if AEntry.Alarm <> nil then begin
|
||||||
|
FAlarmSet := true;
|
||||||
|
dt := abs(AEntry.Alarm.Trigger);
|
||||||
|
if IsInteger(dt, 1.0 / SecondsInDay) then begin
|
||||||
|
FAlarmAdvType := atDays;
|
||||||
|
FAlarmAdv := round(dt);
|
||||||
|
end else
|
||||||
|
if IsInteger(dt*HoursInDay, HoursInDay / SecondsInDay) then begin
|
||||||
|
FAlarmAdvType := atHours;
|
||||||
|
FAlarmAdv := round(dt * HoursInDay);
|
||||||
|
end else begin
|
||||||
|
FAlarmAdvType := atMinutes;
|
||||||
|
FAlarmAdv := round(dt * MinutesInDay);
|
||||||
|
end;
|
||||||
|
FDingPath := AEntry.Alarm.AudioSrc;
|
||||||
|
if not FileExists(FDingPath) then FDingPath := '';
|
||||||
|
end else
|
||||||
|
FAlarmSet := false;
|
||||||
|
|
||||||
|
{ Recurrence }
|
||||||
|
FRepeatCode := rtNone;
|
||||||
|
FRepeatRangeEnd := 0;
|
||||||
|
case AEntry.RecurrenceFrequency of
|
||||||
|
'YEARLY':
|
||||||
|
if AEntry.RecurrenceInterval = 0 then
|
||||||
|
FRepeatCode := rtYearlyByDate // or rtYearlyByDay ?
|
||||||
|
else begin
|
||||||
|
FRepeatCode := rtCustom;
|
||||||
|
FCustInterval := AEntry.RecurrenceInterval * 365; // * SecondsInDay;
|
||||||
|
end;
|
||||||
|
'MONTHLY':
|
||||||
|
if AEntry.RecurrenceInterval = 0 then
|
||||||
|
FRepeatCode := rtMonthlyByDate // or rtMonthlyByDay ?
|
||||||
|
else begin
|
||||||
|
FRepeatCode := rtCustom;
|
||||||
|
FCustInterval := AEntry.RecurrenceInterval * 30; // * SecondsInDay;
|
||||||
|
end;
|
||||||
|
'WEEKLY':
|
||||||
|
if AEntry.RecurrenceInterval = 0 then
|
||||||
|
FRepeatCode := rtWeekly
|
||||||
|
else begin
|
||||||
|
FRepeatCode := rtCustom;
|
||||||
|
FCustInterval := AEntry.RecurrenceInterval * 7; // * SecondsInDay;
|
||||||
|
end;
|
||||||
|
'DAILY':
|
||||||
|
if AEntry.RecurrenceInterval = 0 then
|
||||||
|
FRepeatCode := rtDaily
|
||||||
|
else begin
|
||||||
|
FRepeatCode := rtCustom;
|
||||||
|
FCustInterval := AEntry.RecurrenceInterval; // * SecondsInDay;
|
||||||
|
end;
|
||||||
|
(*
|
||||||
|
'HOURLY':
|
||||||
|
begin
|
||||||
|
FRepeatCode := rtCustom;
|
||||||
|
FCustInterval := AEntry.RecurrenceInterval * SecondsInHour;
|
||||||
|
end;
|
||||||
|
'MINUTELY':
|
||||||
|
begin
|
||||||
|
FRepeatCode := rtCustom;
|
||||||
|
FCustInterval := AEntry.RecurrenceInterval * SecondsInMinute;
|
||||||
|
end;
|
||||||
|
*)
|
||||||
|
end;
|
||||||
|
if (AEntry.RecurrenceEndDate = 0) and (AEntry.RecurrenceCount > 0) then begin
|
||||||
|
FRepeatRangeEnd := trunc(FStartTime);
|
||||||
|
case FRepeatCode of
|
||||||
|
rtYearlyByDate:
|
||||||
|
FRepeatRangeEnd := IncYear(FRepeatRangeEnd, AEntry.RecurrenceCount);
|
||||||
|
rtMonthlyByDate:
|
||||||
|
FRepeatRangeEnd := IncMonth(FRepeatRangeEnd, AEntry.RecurrenceCount);
|
||||||
|
rtWeekly:
|
||||||
|
FRepeatRangeEnd := FRepeatRangeEnd + 7 * AEntry.RecurrenceCount;
|
||||||
|
rtDaily:
|
||||||
|
FRepeatRangeEnd := FRepeatRangeEnd + AEntry.RecurrenceCount;
|
||||||
|
end;
|
||||||
|
end else
|
||||||
|
FRepeatRangeEnd := AEntry.RecurrenceEndDate;
|
||||||
|
|
||||||
|
// There is also "CustomInterval" which may be extracted from the RecurrenceByXXXX data
|
||||||
|
// But this is very complex...
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TVpEvent.SetAlarmAdv(Value: Integer);
|
procedure TVpEvent.SetAlarmAdv(Value: Integer);
|
||||||
begin
|
begin
|
||||||
if Value <> FAlarmAdv then begin
|
if Value <> FAlarmAdv then begin
|
||||||
@ -1451,93 +1554,22 @@ begin
|
|||||||
FEventList.Sort(@CompareEvents);
|
FEventList.Sort(@CompareEvents);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
(*
|
|
||||||
procedure TVpSchedule.Sort;
|
|
||||||
var
|
|
||||||
i, j : integer;
|
|
||||||
IndexOfMin : integer;
|
|
||||||
Temp : pointer;
|
|
||||||
CompResult : integer; {Comparison Result}
|
|
||||||
begin
|
|
||||||
{ WARNING!! The DayView component is heavily dependent upon the events }
|
|
||||||
{ being properly sorted. If you change the way this procedure works, }
|
|
||||||
{ you WILL break the DayView component!!! }
|
|
||||||
|
|
||||||
{ for greater performance, we don't sort while doing batch updates. }
|
|
||||||
if FBatchUpdate > 0 then exit;
|
|
||||||
|
|
||||||
for i := 0 to pred(FEventList.Count) do begin
|
|
||||||
IndexOfMin := i;
|
|
||||||
for j := i to FEventList.Count - 1 do begin
|
|
||||||
|
|
||||||
{ compare start times of item[j] and item[i] }
|
|
||||||
CompResult := Compare(TVpEvent(FEventList.List^[j]).StartTime,
|
|
||||||
TVpEvent(FEventList.List^[IndexOfMin]).StartTime);
|
|
||||||
|
|
||||||
{ if the starttime of j is less than the starttime of i then flip 'em}
|
|
||||||
if CompResult < 0 then
|
|
||||||
IndexOfMin := j
|
|
||||||
|
|
||||||
{ if the start times match then sort by end time }
|
|
||||||
else if CompResult = 0 then begin
|
|
||||||
|
|
||||||
{ if the endtime of j is less than the end time of i then flip 'em}
|
|
||||||
if (Compare(TVpEvent(FEventList.List^[j]).EndTime,
|
|
||||||
TVpEvent(FEventList.List^[IndexOfMin]).EndTime) < 0)
|
|
||||||
then
|
|
||||||
IndexOfMin := j;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
Temp := FEventList.List^[i];
|
|
||||||
FEventList.List^[i] := FEventList.List^[IndexOfMin];
|
|
||||||
FEventList.List^[IndexOfMin] := Temp;
|
|
||||||
end;
|
|
||||||
|
|
||||||
{ Fix object embedded ItemIndexes }
|
|
||||||
{
|
|
||||||
for i := 0 to pred(FEventList.Count) do begin
|
|
||||||
TVpEvent(FEventList.List^[i]).FItemIndex := i;
|
|
||||||
end;
|
|
||||||
}
|
|
||||||
end;
|
|
||||||
|
|
||||||
{ Used in the above sort procedure. Compares the start times of the two }
|
|
||||||
{ passed in events. }
|
|
||||||
function TVpSchedule.Compare(Time1, Time2: TDateTime): Integer;
|
|
||||||
begin
|
|
||||||
{ Compares the value of the Item start dates }
|
|
||||||
|
|
||||||
if Time1 < Time2 then
|
|
||||||
result := -1
|
|
||||||
|
|
||||||
else if Time1 = Time2 then
|
|
||||||
result := 0
|
|
||||||
|
|
||||||
else
|
|
||||||
{Time2 is earlier than Time1}
|
|
||||||
result := 1;
|
|
||||||
end; *)
|
|
||||||
|
|
||||||
{Adds the event to the eventlist and returns a pointer to it, or nil on failure}
|
{Adds the event to the eventlist and returns a pointer to it, or nil on failure}
|
||||||
function TVpSchedule.AddEvent(RecordID: Integer; StartTime,
|
function TVpSchedule.AddEvent(RecordID: Integer; StartTime,
|
||||||
EndTime: TDateTime): TVpEvent;
|
EndTime: TDateTime): TVpEvent;
|
||||||
begin
|
begin
|
||||||
Result := nil;
|
Result := TVpEvent.Create(Self);
|
||||||
if EndTime > StartTime then begin
|
try
|
||||||
Result := TVpEvent.Create(Self);
|
Result.Loading := true;
|
||||||
try
|
FEventList.Add(Result);
|
||||||
Result.Loading := true;
|
Result.RecordID := RecordID;
|
||||||
FEventList.Add(Result);
|
Result.StartTime := StartTime;
|
||||||
Result.RecordID := RecordID;
|
Result.EndTime := EndTime;
|
||||||
Result.StartTime := StartTime;
|
Result.Loading := false;
|
||||||
Result.EndTime := EndTime;
|
Sort;
|
||||||
Result.Loading := false;
|
except
|
||||||
Sort;
|
Result.Free;
|
||||||
except
|
raise EFailToCreateEvent.Create;
|
||||||
Result.free;
|
|
||||||
raise EFailToCreateEvent.Create;
|
|
||||||
end;
|
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -1590,7 +1622,7 @@ end;
|
|||||||
function TVpSchedule.GetEvent(Index: Integer): TVpEvent;
|
function TVpSchedule.GetEvent(Index: Integer): TVpEvent;
|
||||||
begin
|
begin
|
||||||
{ Returns an event on success or nil on failure }
|
{ Returns an event on success or nil on failure }
|
||||||
result := FEventList.Items[Index];
|
result := TVpEvent(FEventList[Index]);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TVpSchedule.RepeatsOn(Event: TVpEvent; Day: TDateTime): Boolean;
|
function TVpSchedule.RepeatsOn(Event: TVpEvent; Day: TDateTime): Boolean;
|
||||||
@ -1600,22 +1632,30 @@ var
|
|||||||
EventWkDay, EventDayCount: Word;
|
EventWkDay, EventDayCount: Word;
|
||||||
ThisWkDay, ThisDayCount: Word;
|
ThisWkDay, ThisDayCount: Word;
|
||||||
EventJulian, ThisJulian: Word;
|
EventJulian, ThisJulian: Word;
|
||||||
|
DayInRepeatRange: Boolean;
|
||||||
begin
|
begin
|
||||||
result := false;
|
result := false;
|
||||||
|
|
||||||
if (Event.RepeatCode <> rtNone) and (trunc(Event.RepeatRangeEnd + 1) > now) then
|
DayInRepeatRange := (Day > trunc(Event.StartTime)) and
|
||||||
|
((Event.RepeatRangeEnd = 0) or (Day < trunc(Event.RepeatRangeEnd) + 1));
|
||||||
|
|
||||||
|
if (Event.RepeatCode <> rtNone) and
|
||||||
|
((Event.RepeatRangeEnd = 0) or (trunc(Event.RepeatRangeEnd + 1) > now)) then
|
||||||
begin
|
begin
|
||||||
case Event.RepeatCode of
|
case Event.RepeatCode of
|
||||||
rtDaily:
|
rtDaily:
|
||||||
if (Day < trunc(Event.RepeatRangeEnd) + 1) and (Day > trunc(Event.StartTime)) then
|
if DayInRepeatRange then
|
||||||
|
// if (Day < trunc(Event.RepeatRangeEnd) + 1) and (Day > trunc(Event.StartTime)) then
|
||||||
result := true;
|
result := true;
|
||||||
|
|
||||||
rtWeekly:
|
rtWeekly:
|
||||||
if (Day < trunc(Event.RepeatRangeEnd) + 1) and (Day > trunc(Event.StartTime)) then
|
if DayInRepeatRange then
|
||||||
|
// if (Day < trunc(Event.RepeatRangeEnd) + 1) and (Day > trunc(Event.StartTime)) then
|
||||||
result := (Trunc(Day) - Trunc(Event.StartTime)) mod 7 = 0;
|
result := (Trunc(Day) - Trunc(Event.StartTime)) mod 7 = 0;
|
||||||
|
|
||||||
rtMonthlyByDay:
|
rtMonthlyByDay:
|
||||||
if (Day < trunc(Event.RepeatRangeEnd) + 1) and (Day > trunc(Event.StartTime)) then
|
if DayInRepeatRange then
|
||||||
|
//if (Day < trunc(Event.RepeatRangeEnd) + 1) and (Day > trunc(Event.StartTime)) then
|
||||||
begin
|
begin
|
||||||
// Get the year, month and day of the first event in the series
|
// Get the year, month and day of the first event in the series
|
||||||
DecodeDate(Event.StartTime, EY, EM, ED);
|
DecodeDate(Event.StartTime, EY, EM, ED);
|
||||||
@ -1635,7 +1675,8 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
rtMonthlyByDate:
|
rtMonthlyByDate:
|
||||||
if (Day < trunc(Event.RepeatRangeEnd) + 1) and (Day > trunc(Event.StartTime)) then
|
if DayInRepeatRange then
|
||||||
|
// if (Day < trunc(Event.RepeatRangeEnd) + 1) and (Day > trunc(Event.StartTime)) then
|
||||||
begin
|
begin
|
||||||
// Get the year, month and day of the first event in the series
|
// Get the year, month and day of the first event in the series
|
||||||
DecodeDate(Event.StartTime, EY, EM, ED);
|
DecodeDate(Event.StartTime, EY, EM, ED);
|
||||||
@ -1646,7 +1687,8 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
rtYearlyByDay:
|
rtYearlyByDay:
|
||||||
if (Day < trunc(Event.RepeatRangeEnd) + 1) and (Day > trunc(Event.StartTime)) then
|
if DayInRepeatRange then
|
||||||
|
// if (Day < trunc(Event.RepeatRangeEnd) + 1) and (Day > trunc(Event.StartTime)) then
|
||||||
begin
|
begin
|
||||||
// Get the julian date of the first event in the series
|
// Get the julian date of the first event in the series
|
||||||
EventJulian := GetJulianDate(Event.StartTime);
|
EventJulian := GetJulianDate(Event.StartTime);
|
||||||
@ -1657,7 +1699,8 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
rtYearlyByDate:
|
rtYearlyByDate:
|
||||||
if (Day < trunc(Event.RepeatRangeEnd) + 1) and (Day > trunc(Event.StartTime)) then
|
if DayInRepeatRange then
|
||||||
|
// if (Day < trunc(Event.RepeatRangeEnd) + 1) and (Day > trunc(Event.StartTime)) then
|
||||||
begin
|
begin
|
||||||
// Get the year, month and day of the first event in the series.
|
// Get the year, month and day of the first event in the series.
|
||||||
DecodeDate(Event.StartTime, EY, EM, ED);
|
DecodeDate(Event.StartTime, EY, EM, ED);
|
||||||
@ -1668,7 +1711,8 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
rtCustom:
|
rtCustom:
|
||||||
if (Day < trunc(Event.RepeatRangeEnd) + 1) and (Day > trunc(Event.StartTime)) then
|
if DayInRepeatRange and (Event.CustomInterval > 0) then
|
||||||
|
// if (Day < trunc(Event.RepeatRangeEnd) + 1) and (Day > trunc(Event.StartTime)) then
|
||||||
begin
|
begin
|
||||||
// If the number of elapsed days between the "Day" parameter and
|
// If the number of elapsed days between the "Day" parameter and
|
||||||
// the event start time is evenly divisible by the event's custom
|
// the event start time is evenly divisible by the event's custom
|
||||||
@ -1743,8 +1787,6 @@ begin
|
|||||||
if Event.AllDayEvent and
|
if Event.AllDayEvent and
|
||||||
(DateInRange(Date, Event.StartTime, Event.EndTime, true) or RepeatsOn(Event, Date))
|
(DateInRange(Date, Event.StartTime, Event.EndTime, true) or RepeatsOn(Event, Date))
|
||||||
then
|
then
|
||||||
// if (((trunc(Date) >= trunc(Event.StartTime)) and (trunc(Date) <= trunc(Event.EndTime))) or (RepeatsOn(Event,Date)))
|
|
||||||
// and (Event.AllDayEvent) then
|
|
||||||
EventList.Add(Event);
|
EventList.Add(Event);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@ -2483,12 +2525,12 @@ end;
|
|||||||
|
|
||||||
function TVpContacts.Last: TVpContact;
|
function TVpContacts.Last: TVpContact;
|
||||||
begin
|
begin
|
||||||
result := FContactsList.Items[FContactsList.Count - 1];
|
result := TVpContact(FContactsList[FContactsList.Count - 1]);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TVpContacts.First: TVpContact;
|
function TVpContacts.First: TVpContact;
|
||||||
begin
|
begin
|
||||||
result := FContactsList.Items[0];
|
result := TVpContact(FContactsList[0]);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TVpContacts.DeleteContact(Contact: TVpContact);
|
procedure TVpContacts.DeleteContact(Contact: TVpContact);
|
||||||
@ -2499,7 +2541,7 @@ end;
|
|||||||
|
|
||||||
function TVpContacts.GetContact(Index: Integer): TVpContact;
|
function TVpContacts.GetContact(Index: Integer): TVpContact;
|
||||||
begin
|
begin
|
||||||
result := FContactsList.Items[Index];
|
result := TVpContact(FContactsList[Index]);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TVpContacts.ClearContacts;
|
procedure TVpContacts.ClearContacts;
|
||||||
@ -2537,7 +2579,7 @@ begin
|
|||||||
if Copy(uppercase(TVpContact(FContactsList[I]).LastName), 1, SearchLength) = SearchStr
|
if Copy(uppercase(TVpContact(FContactsList[I]).LastName), 1, SearchLength) = SearchStr
|
||||||
then begin
|
then begin
|
||||||
// We found a match, so return it and bail out
|
// We found a match, so return it and bail out
|
||||||
Result := FContactsList[I];
|
Result := TVpContact(FContactsList[I]);
|
||||||
Exit;
|
Exit;
|
||||||
end;
|
end;
|
||||||
end else begin
|
end else begin
|
||||||
@ -2545,7 +2587,7 @@ begin
|
|||||||
if Copy(TVpContact(FContactsList[I]).LastName, 1, SearchLength) = SearchStr
|
if Copy(TVpContact(FContactsList[I]).LastName, 1, SearchLength) = SearchStr
|
||||||
then begin
|
then begin
|
||||||
// We found a match, so return it and bail out
|
// We found a match, so return it and bail out
|
||||||
Result := FContactsList[I];
|
Result := TVpContact(FContactsList[I]);
|
||||||
Exit;
|
Exit;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
@ -2736,12 +2778,12 @@ end;
|
|||||||
|
|
||||||
function TVpTasks.Last: TVpTask;
|
function TVpTasks.Last: TVpTask;
|
||||||
begin
|
begin
|
||||||
result := FTaskList.Last;
|
result := TVpTask(FTaskList.Last);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TVpTasks.First: TVpTask;
|
function TVpTasks.First: TVpTask;
|
||||||
begin
|
begin
|
||||||
result := FTaskList.First;
|
result := TVpTask(FTaskList.First);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TVpTasks.CountByDay(Date: TDateTime): Integer;
|
function TVpTasks.CountByDay(Date: TDateTime): Integer;
|
||||||
@ -2833,7 +2875,7 @@ end;
|
|||||||
|
|
||||||
function TVpTasks.GetTask(Index: Integer): TVpTask;
|
function TVpTasks.GetTask(Index: Integer): TVpTask;
|
||||||
begin
|
begin
|
||||||
result := FTaskList.Items[Index];
|
result := TVpTask(FTaskList[Index]);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
@ -367,6 +367,7 @@ type
|
|||||||
procedure dvEditInPlace(Sender: TObject);
|
procedure dvEditInPlace(Sender: TObject);
|
||||||
procedure dvHookUp;
|
procedure dvHookUp;
|
||||||
procedure PopupAddEvent(Sender: TObject);
|
procedure PopupAddEvent(Sender: TObject);
|
||||||
|
procedure PopupAddFromICalFile(Sender: TObject);
|
||||||
procedure PopupDeleteEvent(Sender: TObject);
|
procedure PopupDeleteEvent(Sender: TObject);
|
||||||
procedure PopupEditEvent(Sender: TObject);
|
procedure PopupEditEvent(Sender: TObject);
|
||||||
procedure PopupToday(Sender: TObject);
|
procedure PopupToday(Sender: TObject);
|
||||||
@ -530,7 +531,7 @@ uses
|
|||||||
DateUtils,
|
DateUtils,
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
SysUtils, StrUtils, Math, Dialogs,
|
SysUtils, StrUtils, Math, Dialogs,
|
||||||
VpEvntEditDlg, VpDayViewPainter;
|
VpEvntEditDlg, VpDayViewPainter, VpICal;
|
||||||
|
|
||||||
(*****************************************************************************)
|
(*****************************************************************************)
|
||||||
{ TVpTGInPlaceEdit }
|
{ TVpTGInPlaceEdit }
|
||||||
@ -1119,7 +1120,7 @@ begin
|
|||||||
canEdit := (FActiveEvent <> nil) and FActiveEvent.CanEdit;
|
canEdit := (FActiveEvent <> nil) and FActiveEvent.CanEdit;
|
||||||
FDefaultPopup.Items.Clear;
|
FDefaultPopup.Items.Clear;
|
||||||
|
|
||||||
if RSPopupAddEvent <> '' then begin
|
if RSPopupAddEvent <> '' then begin // Add
|
||||||
NewItem := TMenuItem.Create(Self);
|
NewItem := TMenuItem.Create(Self);
|
||||||
NewItem.Caption := RSPopupAddEvent;
|
NewItem.Caption := RSPopupAddEvent;
|
||||||
NewItem.OnClick := PopupAddEvent;
|
NewItem.OnClick := PopupAddEvent;
|
||||||
@ -1127,7 +1128,15 @@ begin
|
|||||||
FDefaultPopup.Items.Add(NewItem);
|
FDefaultPopup.Items.Add(NewItem);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if RSPopupEditEvent <> '' then begin
|
if RSPopupAddEventFromICal <> '' then begin
|
||||||
|
NewItem := TMenuItem.Create(Self);
|
||||||
|
NewItem.Caption := RSPopupAddEventFromICal; // Import from iCal
|
||||||
|
NewItem.OnClick := PopupAddFromICalFile;
|
||||||
|
NewItem.Tag := 0;
|
||||||
|
FDefaultPopup.Items.Add(NewItem);
|
||||||
|
end;
|
||||||
|
|
||||||
|
if RSPopupEditEvent <> '' then begin // Edit
|
||||||
NewItem := TMenuItem.Create(Self);
|
NewItem := TMenuItem.Create(Self);
|
||||||
NewItem.Caption := RSPopupEditEvent;
|
NewItem.Caption := RSPopupEditEvent;
|
||||||
NewItem.Enabled := canEdit;
|
NewItem.Enabled := canEdit;
|
||||||
@ -1136,7 +1145,7 @@ begin
|
|||||||
FDefaultPopup.Items.Add(NewItem);
|
FDefaultPopup.Items.Add(NewItem);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if RSPopupDeleteEvent <> '' then begin
|
if RSPopupDeleteEvent <> '' then begin // Delete
|
||||||
NewItem := TMenuItem.Create(Self);
|
NewItem := TMenuItem.Create(Self);
|
||||||
NewItem.Caption := RSPopupDeleteEvent;
|
NewItem.Caption := RSPopupDeleteEvent;
|
||||||
NewItem.Enabled := canEdit;
|
NewItem.Enabled := canEdit;
|
||||||
@ -1145,17 +1154,17 @@ begin
|
|||||||
FDefaultPopup.Items.Add(NewItem);
|
FDefaultPopup.Items.Add(NewItem);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
NewItem := TMenuItem.Create(Self);
|
NewItem := TMenuItem.Create(Self); // ----
|
||||||
NewItem.Caption := '-';
|
NewItem.Caption := '-';
|
||||||
FDefaultPopup.Items.Add(NewItem);
|
FDefaultPopup.Items.Add(NewItem);
|
||||||
|
|
||||||
if RSPopupChangeDate <> '' then begin
|
if RSPopupChangeDate <> '' then begin // Change date >
|
||||||
NewItem := TMenuItem.Create(Self);
|
NewItem := TMenuItem.Create(Self);
|
||||||
NewItem.Caption := RSPopupChangeDate;
|
NewItem.Caption := RSPopupChangeDate;
|
||||||
NewItem.Tag := 0;
|
NewItem.Tag := 0;
|
||||||
FDefaultPopup.Items.Add(NewItem);
|
FDefaultPopup.Items.Add(NewItem);
|
||||||
|
|
||||||
if RSToday <> '' then begin
|
if RSToday <> '' then begin // Today
|
||||||
NewSubItem := TMenuItem.Create(Self);
|
NewSubItem := TMenuItem.Create(Self);
|
||||||
NewSubItem.Caption := RSToday;
|
NewSubItem.Caption := RSToday;
|
||||||
NewSubItem.OnClick := PopupToday;
|
NewSubItem.OnClick := PopupToday;
|
||||||
@ -1163,11 +1172,11 @@ begin
|
|||||||
NewItem.Add(NewSubItem);
|
NewItem.Add(NewSubItem);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
NewSubItem := TMenuItem.Create(Self);
|
NewSubItem := TMenuItem.Create(Self); // ---
|
||||||
NewSubItem.Caption := '-';
|
NewSubItem.Caption := '-';
|
||||||
NewItem.Add(NewSubItem);
|
NewItem.Add(NewSubItem);
|
||||||
|
|
||||||
if RSYesterday <> '' then begin
|
if RSYesterday <> '' then begin // Yesterday
|
||||||
NewSubItem := TMenuItem.Create(Self);
|
NewSubItem := TMenuItem.Create(Self);
|
||||||
NewSubItem.Caption := RSYesterday;
|
NewSubItem.Caption := RSYesterday;
|
||||||
NewSubItem.OnClick := PopupYesterday;
|
NewSubItem.OnClick := PopupYesterday;
|
||||||
@ -1175,7 +1184,7 @@ begin
|
|||||||
NewItem.Add(NewSubItem);
|
NewItem.Add(NewSubItem);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if RSTomorrow <> '' then begin
|
if RSTomorrow <> '' then begin // Tomorrow
|
||||||
NewSubItem := TMenuItem.Create(Self);
|
NewSubItem := TMenuItem.Create(Self);
|
||||||
NewSubItem.Caption := RSTomorrow;
|
NewSubItem.Caption := RSTomorrow;
|
||||||
NewSubItem.OnClick := PopupTomorrow;
|
NewSubItem.OnClick := PopupTomorrow;
|
||||||
@ -1183,11 +1192,11 @@ begin
|
|||||||
NewItem.Add(NewSubItem);
|
NewItem.Add(NewSubItem);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
NewSubItem := TMenuItem.Create(Self);
|
NewSubItem := TMenuItem.Create(Self); // --
|
||||||
NewSubItem.Caption := '-';
|
NewSubItem.Caption := '-';
|
||||||
NewItem.Add(NewSubItem);
|
NewItem.Add(NewSubItem);
|
||||||
|
|
||||||
if RSNextDay <> '' then begin
|
if RSNextDay <> '' then begin // Next day
|
||||||
NewSubItem := TMenuItem.Create(Self);
|
NewSubItem := TMenuItem.Create(Self);
|
||||||
NewSubItem.Caption := RSNextDay;
|
NewSubItem.Caption := RSNextDay;
|
||||||
NewSubItem.OnClick := PopupNextDay;
|
NewSubItem.OnClick := PopupNextDay;
|
||||||
@ -1195,7 +1204,7 @@ begin
|
|||||||
NewItem.Add(NewSubItem);
|
NewItem.Add(NewSubItem);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if RSPrevDay <> '' then begin
|
if RSPrevDay <> '' then begin // Prev day
|
||||||
NewSubItem := TMenuItem.Create(Self);
|
NewSubItem := TMenuItem.Create(Self);
|
||||||
NewSubItem.Caption := RSPrevDay;
|
NewSubItem.Caption := RSPrevDay;
|
||||||
NewSubItem.OnClick := PopupPrevDay;
|
NewSubItem.OnClick := PopupPrevDay;
|
||||||
@ -1203,11 +1212,11 @@ begin
|
|||||||
NewItem.Add(NewSubItem);
|
NewItem.Add(NewSubItem);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
NewSubItem := TMenuItem.Create(Self);
|
NewSubItem := TMenuItem.Create(Self); // ---
|
||||||
NewSubItem.Caption := '-';
|
NewSubItem.Caption := '-';
|
||||||
NewItem.Add(NewSubItem);
|
NewItem.Add(NewSubItem);
|
||||||
|
|
||||||
if RSNextWeek <> '' then begin
|
if RSNextWeek <> '' then begin // Next week
|
||||||
NewSubItem := TMenuItem.Create(Self);
|
NewSubItem := TMenuItem.Create(Self);
|
||||||
NewSubItem.Caption := RSNextWeek;
|
NewSubItem.Caption := RSNextWeek;
|
||||||
NewSubItem.OnClick := PopupNextWeek;
|
NewSubItem.OnClick := PopupNextWeek;
|
||||||
@ -1215,7 +1224,7 @@ begin
|
|||||||
NewItem.Add(NewSubItem);
|
NewItem.Add(NewSubItem);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if RSPrevWeek <> '' then begin
|
if RSPrevWeek <> '' then begin // Prev week
|
||||||
NewSubItem := TMenuItem.Create(Self);
|
NewSubItem := TMenuItem.Create(Self);
|
||||||
NewSubItem.Caption := RSPrevWeek;
|
NewSubItem.Caption := RSPrevWeek;
|
||||||
NewSubItem.OnClick := PopupPrevWeek;
|
NewSubItem.OnClick := PopupPrevWeek;
|
||||||
@ -1223,11 +1232,11 @@ begin
|
|||||||
NewItem.Add(NewSubItem);
|
NewItem.Add(NewSubItem);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
NewSubItem := TMenuItem.Create(Self);
|
NewSubItem := TMenuItem.Create(Self); // ---
|
||||||
NewSubItem.Caption := '-';
|
NewSubItem.Caption := '-';
|
||||||
NewItem.Add(NewSubItem);
|
NewItem.Add(NewSubItem);
|
||||||
|
|
||||||
if RSNextMonth <> '' then begin
|
if RSNextMonth <> '' then begin // Next month
|
||||||
NewSubItem := TMenuItem.Create(Self);
|
NewSubItem := TMenuItem.Create(Self);
|
||||||
NewSubItem.Caption := RSNextMonth;
|
NewSubItem.Caption := RSNextMonth;
|
||||||
NewSubItem.OnClick := PopupNextMonth;
|
NewSubItem.OnClick := PopupNextMonth;
|
||||||
@ -1235,7 +1244,7 @@ begin
|
|||||||
NewItem.Add(NewSubItem);
|
NewItem.Add(NewSubItem);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if RSPrevMonth <> '' then begin
|
if RSPrevMonth <> '' then begin // Prev Month
|
||||||
NewSubItem := TMenuItem.Create(Self);
|
NewSubItem := TMenuItem.Create(Self);
|
||||||
NewSubItem.Caption := RSPrevMonth;
|
NewSubItem.Caption := RSPrevMonth;
|
||||||
NewSubItem.OnClick := PopupPrevMonth;
|
NewSubItem.OnClick := PopupPrevMonth;
|
||||||
@ -1243,11 +1252,11 @@ begin
|
|||||||
NewItem.Add(NewSubItem);
|
NewItem.Add(NewSubItem);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
NewSubItem := TMenuItem.Create(Self);
|
NewSubItem := TMenuItem.Create(Self); // ---
|
||||||
NewSubItem.Caption := '-';
|
NewSubItem.Caption := '-';
|
||||||
NewItem.Add(NewSubItem);
|
NewItem.Add(NewSubItem);
|
||||||
|
|
||||||
if RSNextYear <> '' then begin
|
if RSNextYear <> '' then begin // Next year
|
||||||
NewSubItem := TMenuItem.Create(Self);
|
NewSubItem := TMenuItem.Create(Self);
|
||||||
NewSubItem.Caption := RSNextYear;
|
NewSubItem.Caption := RSNextYear;
|
||||||
NewSubItem.OnClick := PopupNextYear;
|
NewSubItem.OnClick := PopupNextYear;
|
||||||
@ -1255,7 +1264,7 @@ begin
|
|||||||
NewItem.Add(NewSubItem);
|
NewItem.Add(NewSubItem);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if RSPrevYear <> '' then begin
|
if RSPrevYear <> '' then begin // Prev year
|
||||||
NewSubItem := TMenuItem.Create(Self);
|
NewSubItem := TMenuItem.Create(Self);
|
||||||
NewSubItem.Caption := RSPrevYear;
|
NewSubItem.Caption := RSPrevYear;
|
||||||
NewSubItem.OnClick := PopupPrevYear;
|
NewSubItem.OnClick := PopupPrevYear;
|
||||||
@ -1274,13 +1283,9 @@ var
|
|||||||
StartTime: TDateTime;
|
StartTime: TDateTime;
|
||||||
EndTime: TDateTime;
|
EndTime: TDateTime;
|
||||||
begin
|
begin
|
||||||
if ReadOnly then
|
if ReadOnly or (not CheckCreateResource) or
|
||||||
Exit;
|
(not Assigned(DataStore)) or (not Assigned(DataStore.Resource))
|
||||||
if not CheckCreateResource then
|
then
|
||||||
Exit;
|
|
||||||
if not Assigned (DataStore) then
|
|
||||||
Exit;
|
|
||||||
if not Assigned (DataStore.Resource) then
|
|
||||||
Exit;
|
Exit;
|
||||||
|
|
||||||
StartTime := trunc(FDisplayDate + ActiveCol) + dvLineMatrix[ActiveCol, ActiveRow].Time;
|
StartTime := trunc(FDisplayDate + ActiveCol) + dvLineMatrix[ActiveCol, ActiveRow].Time;
|
||||||
@ -1290,12 +1295,58 @@ begin
|
|||||||
StartTime,
|
StartTime,
|
||||||
EndTime
|
EndTime
|
||||||
);
|
);
|
||||||
|
|
||||||
Repaint;
|
Repaint;
|
||||||
|
|
||||||
{ edit this new event }
|
{ edit this new event }
|
||||||
dvSpawnEventEditDialog(True);
|
dvSpawnEventEditDialog(True);
|
||||||
end;
|
end;
|
||||||
{=====}
|
|
||||||
|
procedure TVpDayView.PopupAddFromICalFile(Sender: TObject);
|
||||||
|
var
|
||||||
|
dlg: TOpenDialog;
|
||||||
|
ical: TVpICalendar;
|
||||||
|
fn: String;
|
||||||
|
i: Integer;
|
||||||
|
id: Integer;
|
||||||
|
startTime, endTime: TDateTime;
|
||||||
|
begin
|
||||||
|
dlg := TOpenDialog.Create(nil);
|
||||||
|
try
|
||||||
|
dlg.Title := RSLoadICalTitle;
|
||||||
|
dlg.Filter := RSICalFilter;
|
||||||
|
dlg.FileName := '';
|
||||||
|
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.LoadFromICalendar(TVpICalEvent(ical[i]));
|
||||||
|
Datastore.PostEvents;
|
||||||
|
Datastore.NotifyDependents;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
Invalidate;
|
||||||
|
finally
|
||||||
|
ical.Free;
|
||||||
|
Screen.Cursor := crDefault;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
finally
|
||||||
|
dlg.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TVpDayView.PopupDeleteEvent(Sender: TObject);
|
procedure TVpDayView.PopupDeleteEvent(Sender: TObject);
|
||||||
begin
|
begin
|
||||||
|
@ -286,6 +286,10 @@ begin
|
|||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
end else
|
end else
|
||||||
exit;
|
exit;
|
||||||
|
end else
|
||||||
|
if (tStart = tEnd) and not CbAllDay.Checked then begin
|
||||||
|
MessageDlg(RSStartEndTimesEqual, mtError, [mbOK], 0);
|
||||||
|
exit;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
ReturnCode := rtCommit;
|
ReturnCode := rtCommit;
|
||||||
@ -608,13 +612,15 @@ end;
|
|||||||
|
|
||||||
procedure TDlgEventEdit.RecurringTypeChange(Sender: TObject);
|
procedure TDlgEventEdit.RecurringTypeChange(Sender: TObject);
|
||||||
begin
|
begin
|
||||||
if (RecurringType.ItemIndex > 0) and (RepeatUntil.Date <= StartDate.Date) then
|
if (RecurringType.ItemIndex > 0) and
|
||||||
|
(RepeatUntil.Date > 0) and (RepeatUntil.Date <= StartDate.Date)
|
||||||
|
then
|
||||||
RepeatUntil.Date := StartDate.Date + 365;
|
RepeatUntil.Date := StartDate.Date + 365;
|
||||||
|
|
||||||
RecurrenceEndsLbl.Enabled := (RecurringType.ItemIndex > 0);
|
RecurrenceEndsLbl.Enabled := (RecurringType.ItemIndex > 0);
|
||||||
RepeatUntil.Enabled := RecurrenceEndsLbl.Enabled;
|
RepeatUntil.Enabled := RecurrenceEndsLbl.Enabled;
|
||||||
|
|
||||||
CustomInterval.Enabled := RecurringType.ItemIndex = 7;
|
CustomInterval.Enabled := RecurringType.ItemIndex = ord(rtCustom);
|
||||||
IntervalLbl.Enabled := CustomInterval.Enabled;
|
IntervalLbl.Enabled := CustomInterval.Enabled;
|
||||||
IntervalUpDown.Enabled := CustomInterval.Enabled;
|
IntervalUpDown.Enabled := CustomInterval.Enabled;
|
||||||
if CustomInterval.Enabled then begin
|
if CustomInterval.Enabled then begin
|
||||||
|
558
components/tvplanit/source/vpical.pas
Normal file
558
components/tvplanit/source/vpical.pas
Normal file
@ -0,0 +1,558 @@
|
|||||||
|
unit VpICAL;
|
||||||
|
|
||||||
|
{$mode objfpc}{$H+}
|
||||||
|
|
||||||
|
interface
|
||||||
|
|
||||||
|
uses
|
||||||
|
Classes, SysUtils, VpBaseDataFiles;
|
||||||
|
|
||||||
|
type
|
||||||
|
TVpICalendar = class;
|
||||||
|
|
||||||
|
TVpICalItem = class(TVpFileItem)
|
||||||
|
public
|
||||||
|
function GetAttribute(AName: String): string;
|
||||||
|
end;
|
||||||
|
|
||||||
|
TVpICalEntry = class(TVpFileBlock)
|
||||||
|
private
|
||||||
|
FCalendar: TVpICalendar;
|
||||||
|
public
|
||||||
|
constructor Create(ACalendar: TVpICalendar);
|
||||||
|
function FindItem(AKey: String): TVpICalItem;
|
||||||
|
end;
|
||||||
|
|
||||||
|
TVpICalTimeZoneInfo = class(TVpICalEntry)
|
||||||
|
public
|
||||||
|
TimeZoneID: String; // e.g. Europe/Berlin
|
||||||
|
TimeZoneName: String; // e.g. CEST
|
||||||
|
UTCOffset: Double; // add to UTC to get local time
|
||||||
|
end;
|
||||||
|
|
||||||
|
TVpICalAlarm = class(TVpICalEntry)
|
||||||
|
private
|
||||||
|
FDuration: Double; // "SnoozeTime"
|
||||||
|
FRepeat: Integer;
|
||||||
|
FTrigger: Double; // "AlarmAdvance"
|
||||||
|
FAudio: Boolean;
|
||||||
|
FAudioSrc: String;
|
||||||
|
public
|
||||||
|
procedure Analyze; override;
|
||||||
|
property Duration: Double read FDuration;
|
||||||
|
property RepeatCount: Integer read FRepeat;
|
||||||
|
property Trigger: Double read FTrigger;
|
||||||
|
property Audio: Boolean read FAudio;
|
||||||
|
property AudioSrc: String read FAudioSrc;
|
||||||
|
end;
|
||||||
|
|
||||||
|
TVpICalEvent = class(TVpICalEntry)
|
||||||
|
private
|
||||||
|
FSummary: String; // --> Description
|
||||||
|
FDescription: String; // --> Notes
|
||||||
|
FLocation: String;
|
||||||
|
FStartTime: TDateTime;
|
||||||
|
FStartTimeTZ: String;
|
||||||
|
FEndTime: TDateTime;
|
||||||
|
FEndTimeTZ: String;
|
||||||
|
FDuration: double;
|
||||||
|
FRecurrenceFreq: String;
|
||||||
|
FRecurrenceInterval: Integer;
|
||||||
|
FRecurrenceEndDate: TDateTime;
|
||||||
|
FRecurrenceCount: Integer;
|
||||||
|
FRecurrenceByXXX: String;
|
||||||
|
FAlarm: TVpICalAlarm;
|
||||||
|
function GetEndTime(UTC: Boolean): TDateTime;
|
||||||
|
function GetStartTime(UTC: Boolean): TDateTime;
|
||||||
|
public
|
||||||
|
destructor Destroy; override;
|
||||||
|
procedure Analyze; override;
|
||||||
|
procedure UseAlarm;
|
||||||
|
property Summary: String read FSummary; // is "Description" of tvp
|
||||||
|
property Description: String read FDescription; // is "Notes" of tvp
|
||||||
|
property Location: String read FLocation;
|
||||||
|
property StartTime[UTC: Boolean]: TDateTime read GetStartTime;
|
||||||
|
property EndTime[UTC: Boolean]: TDateTime read GetEndTime;
|
||||||
|
property Alarm: TVpICalAlarm read FAlarm;
|
||||||
|
property RecurrenceFrequency: String read FRecurrenceFreq;
|
||||||
|
property RecurrenceInterval: Integer read FRecurrenceInterval;
|
||||||
|
property RecurrenceEndDate: TDateTime read FRecurrenceEndDate;
|
||||||
|
property RecurrenceCount: Integer read FRecurrenceCount;
|
||||||
|
property RecurrenceByXXX: String read FRecurrenceByXXX;
|
||||||
|
end;
|
||||||
|
|
||||||
|
TVpICalendar = class
|
||||||
|
private
|
||||||
|
FEntries: array of TVpICalEntry;
|
||||||
|
FVersion: String;
|
||||||
|
function GetCount: Integer;
|
||||||
|
function GetEntry(AIndex: Integer): TVpICalEntry;
|
||||||
|
protected
|
||||||
|
// Reading
|
||||||
|
procedure LoadFromStrings(const AStrings: TStrings);
|
||||||
|
// Time conversion
|
||||||
|
function ConvertTime(ADateTime: TDateTime; ATimeZoneID: String; ToUTC: Boolean): TDateTime;
|
||||||
|
function LocalTimeToUTC(ADateTime: TDateTime; ATimeZoneID: String): TDateTime;
|
||||||
|
function UTCToLocalTime(ADateTime: TDateTime; ATimeZoneID: String): TDateTime;
|
||||||
|
public
|
||||||
|
constructor Create;
|
||||||
|
destructor Destroy; override;
|
||||||
|
procedure Clear;
|
||||||
|
procedure LoadFromFile(const AFileName: String);
|
||||||
|
procedure LoadFromStream(const AStream: TStream);
|
||||||
|
property Count: Integer read GetCount;
|
||||||
|
property Entry[AIndex: Integer]: TVpICalEntry read GetEntry; default;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
implementation
|
||||||
|
|
||||||
|
uses
|
||||||
|
VpConst, VpBase;
|
||||||
|
|
||||||
|
const
|
||||||
|
ITEMS_DELIMITER = ';';
|
||||||
|
|
||||||
|
// Examples: 19970702T160000, or T123000, or 20120101
|
||||||
|
function iCalDateTime(AText: String; out IsUTC: Boolean): TDateTime;
|
||||||
|
type
|
||||||
|
TDateMask = packed record
|
||||||
|
year: array[1..4] of char;
|
||||||
|
month: array[1..2] of char;
|
||||||
|
day: array[1..2] of char;
|
||||||
|
end;
|
||||||
|
PDateMask = ^TDatemask;
|
||||||
|
TTimeMask = packed record
|
||||||
|
hour: array[1..2] of char;
|
||||||
|
minute: array[1..2] of char;
|
||||||
|
second: array[1..2] of char;
|
||||||
|
end;
|
||||||
|
PTimeMask = ^TTimeMask;
|
||||||
|
var
|
||||||
|
shour, smin, ssec: String;
|
||||||
|
yr, mon, day, hr, min, sec: Integer;
|
||||||
|
p: Integer;
|
||||||
|
d: TDate = 0;
|
||||||
|
t: TTime = 0;
|
||||||
|
begin
|
||||||
|
Result := 0;
|
||||||
|
if AText = '' then exit;
|
||||||
|
|
||||||
|
if AText = '' then
|
||||||
|
exit;
|
||||||
|
|
||||||
|
if (AText[1] <> 'T') and (Length(AText) >= 8) then begin
|
||||||
|
if TryStrToInt(Copy(AText, 1, 4), yr) and
|
||||||
|
TryStrToInt(Copy(AText, 5, 2), mon) and
|
||||||
|
TryStrToInt(Copy(AText, 7, 2), day)
|
||||||
|
then
|
||||||
|
if not TryEncodeDate(yr, mon, day, d) then exit;
|
||||||
|
end;
|
||||||
|
|
||||||
|
shour := '0';
|
||||||
|
smin := '0';
|
||||||
|
ssec := '0';
|
||||||
|
p := pos('T', AText);
|
||||||
|
if p > 0 then begin
|
||||||
|
if Length(AText) >= p + 2 then shour := Copy(AText, p+1, 2);
|
||||||
|
if Length(AText) >= p + 4 then smin := Copy(AText, p+3, 2);
|
||||||
|
if Length(AText) >= p + 6 then ssec := Copy(AText, p+5, 2);
|
||||||
|
end;
|
||||||
|
if TryStrToInt(shour, hr) and
|
||||||
|
TryStrToInt(smin, min) and
|
||||||
|
TryStrToInt(ssec, sec)
|
||||||
|
then
|
||||||
|
if not TryEncodeTime(hr, min, sec, 0, t) then exit;
|
||||||
|
|
||||||
|
Result := d + t;
|
||||||
|
IsUTC := AText[Length(AText)] = 'Z';
|
||||||
|
end;
|
||||||
|
|
||||||
|
// Example: PT0H20M0S, or -PT15M, or -P2D
|
||||||
|
function iCalDuration(AText: String): Double;
|
||||||
|
var
|
||||||
|
isNeg: Boolean = false;
|
||||||
|
inDate: Boolean = true;
|
||||||
|
p: PChar;
|
||||||
|
s: String;
|
||||||
|
n: Integer;
|
||||||
|
begin
|
||||||
|
Result := 0;
|
||||||
|
if AText = '' then
|
||||||
|
exit;
|
||||||
|
|
||||||
|
p := @AText[1];
|
||||||
|
if p^ = '-' then begin
|
||||||
|
isNeg := true;
|
||||||
|
inc(p);
|
||||||
|
end;
|
||||||
|
if p^ <> 'P' then // 'P' = "period"
|
||||||
|
exit;
|
||||||
|
|
||||||
|
inc(p);
|
||||||
|
s := '';
|
||||||
|
while true do begin
|
||||||
|
case p^ of
|
||||||
|
#0 : break;
|
||||||
|
'T': begin
|
||||||
|
inDate := false;
|
||||||
|
s := '';
|
||||||
|
end;
|
||||||
|
'D': begin
|
||||||
|
Result := Result + StrToInt(s);
|
||||||
|
s := '';
|
||||||
|
end;
|
||||||
|
'H': begin
|
||||||
|
Result := Result + StrToInt(s)/24;
|
||||||
|
s := '';
|
||||||
|
end;
|
||||||
|
'M': begin
|
||||||
|
if inDate then
|
||||||
|
// don't know about months... ?!
|
||||||
|
else
|
||||||
|
Result := Result + StrToInt(s)/MinutesInDay;
|
||||||
|
; // don't know about months... ?!
|
||||||
|
s := '';
|
||||||
|
end;
|
||||||
|
'S': begin
|
||||||
|
Result := Result + StrToInt(s) / SecondsInDay;
|
||||||
|
s := '';
|
||||||
|
end;
|
||||||
|
'0'..'9': s := s + p^;
|
||||||
|
else raise EVpException.CreateFmt('Invalid character in DURATION string "%s"', [AText]);
|
||||||
|
end;
|
||||||
|
inc(p);
|
||||||
|
end;
|
||||||
|
if isNeg then Result := -Result;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
{==============================================================================}
|
||||||
|
{ TVpICalItem }
|
||||||
|
{==============================================================================}
|
||||||
|
|
||||||
|
function TVpICalItem.GetAttribute(AName: String): String;
|
||||||
|
begin
|
||||||
|
Result := FAttributes.Values[AName];
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
{==============================================================================}
|
||||||
|
{ TVpICalEntry }
|
||||||
|
{==============================================================================}
|
||||||
|
|
||||||
|
constructor TVpICalEntry.Create(ACalendar: TVpICalendar);
|
||||||
|
begin
|
||||||
|
inherited Create(TVpICalItem);
|
||||||
|
FCalendar := ACalendar;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TVpICalEntry.FindItem(AKey: String): TVpICalItem;
|
||||||
|
begin
|
||||||
|
Result := TVpICalItem(inherited FindItem(AKey, ''));
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
{==============================================================================}
|
||||||
|
{ TVpICalAlarm }
|
||||||
|
{==============================================================================}
|
||||||
|
procedure TVpICalAlarm.Analyze;
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
item: TVpICalItem;
|
||||||
|
s: String;
|
||||||
|
isUTC: Boolean;
|
||||||
|
begin
|
||||||
|
inherited;
|
||||||
|
for i := 0 to FItems.Count-1 do begin
|
||||||
|
item := TVpICalItem(FItems[i]);
|
||||||
|
case item.Key of
|
||||||
|
'TRIGGER':
|
||||||
|
FTrigger := ICalDuration(item.Value);
|
||||||
|
'DURATION' :
|
||||||
|
FDuration := ICalDuration(item.Value);
|
||||||
|
'REPEAT':
|
||||||
|
FRepeat := StrToInt(item.Value);
|
||||||
|
'ACTION':
|
||||||
|
FAudio := Uppercase(item.Value) = 'AUDIO';
|
||||||
|
'ATTACH':
|
||||||
|
if Lowercase(item.GetAttribute('FMTTYPE')) = 'audio' then
|
||||||
|
FAudioSrc := item.Value;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
{==============================================================================}
|
||||||
|
{ TVpICalEvent }
|
||||||
|
{==============================================================================}
|
||||||
|
|
||||||
|
destructor TVpICalEvent.Destroy;
|
||||||
|
begin
|
||||||
|
FAlarm.Free;
|
||||||
|
inherited;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TVpICalEvent.Analyze;
|
||||||
|
var
|
||||||
|
i, j: Integer;
|
||||||
|
item: TVpICalItem;
|
||||||
|
L: TStrings;
|
||||||
|
s: String;
|
||||||
|
isUTC: Boolean;
|
||||||
|
begin
|
||||||
|
inherited;
|
||||||
|
|
||||||
|
for i := 0 to FItems.Count-1 do begin
|
||||||
|
item := TVpICalItem(FItems[i]);
|
||||||
|
case item.Key of
|
||||||
|
'SUMMARY':
|
||||||
|
FSummary := item.Value;
|
||||||
|
'DTSTART':
|
||||||
|
begin
|
||||||
|
FStartTimeTZ := item.GetAttribute('TZID');
|
||||||
|
FStartTime := iCalDateTime(item.Value, isUTC);
|
||||||
|
if not isUTC then
|
||||||
|
FStartTime := FCalendar.LocalTimeToUTC(FStartTime, FStartTimeTZ);
|
||||||
|
end;
|
||||||
|
'DTEND':
|
||||||
|
begin
|
||||||
|
FEndTimeTZ := item.GetAttribute('TZID');
|
||||||
|
FEndTime := iCalDateTime(item.Value, isUTC);
|
||||||
|
if not isUTC then
|
||||||
|
FEndTime := FCalendar.LocalTimeToUTC(FEndTime, FEndTimeTZ);
|
||||||
|
end;
|
||||||
|
'DESCRIPTION':
|
||||||
|
FDescription := item.Value;
|
||||||
|
'LOCATION':
|
||||||
|
FLocation := item.Value;
|
||||||
|
'DURATION':
|
||||||
|
FDuration := ICalDuration(item.Value);
|
||||||
|
'RRULE':
|
||||||
|
begin
|
||||||
|
L := TStringList.Create;
|
||||||
|
try
|
||||||
|
L.StrictDelimiter := true;
|
||||||
|
L.Delimiter := VALUE_DELIMITER; // ';'
|
||||||
|
L.DelimitedText := item.Value;
|
||||||
|
FRecurrenceFreq := L.Values['FREQ'];
|
||||||
|
FRecurrenceInterval := StrToIntDef(L.Values['INTERVAL'], 0);
|
||||||
|
FRecurrenceEndDate := iCalDateTime(L.Values['UNTIL'], isUTC);
|
||||||
|
FRecurrenceCount := StrToIntDef(L.Values['COUNT'], 0);
|
||||||
|
FRecurrenceByXXX := '';
|
||||||
|
for j:=0 to L.Count-1 do begin
|
||||||
|
s := L[j];
|
||||||
|
if pos('BY', s) = 1 then FRecurrenceByXXX := FRecurrenceByXXX + ';' + s;
|
||||||
|
end;
|
||||||
|
if FRecurrenceByXXX <> '' then
|
||||||
|
Delete(FRecurrenceByXXX, 1, 1);
|
||||||
|
finally
|
||||||
|
L.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TVpICalEvent.GetEndTime(UTC: Boolean): TDateTime;
|
||||||
|
begin
|
||||||
|
if FEndTime <> 0 then
|
||||||
|
Result := FEndTime
|
||||||
|
else
|
||||||
|
Result := FStartTime + FDuration;
|
||||||
|
if not UTC then
|
||||||
|
Result := FCalendar.UTCToLocalTime(Result, FEndTimeTZ);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TVpICalEvent.GetStartTime(UTC: Boolean): TDateTime;
|
||||||
|
begin
|
||||||
|
if UTC then
|
||||||
|
Result := FStartTime
|
||||||
|
else
|
||||||
|
Result := FCalendar.LocalTimeToUTC(FStartTime, FStartTimeTZ);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TVpICalEvent.UseAlarm;
|
||||||
|
begin
|
||||||
|
FAlarm.Free;
|
||||||
|
FAlarm := TVpICalAlarm.Create(FCalendar);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
{==============================================================================}
|
||||||
|
{ TVpICalendar }
|
||||||
|
{==============================================================================}
|
||||||
|
|
||||||
|
constructor TVpICalendar.Create;
|
||||||
|
begin
|
||||||
|
inherited;
|
||||||
|
SetLength(FEntries, 0);
|
||||||
|
end;
|
||||||
|
|
||||||
|
destructor TVpICalendar.Destroy;
|
||||||
|
begin
|
||||||
|
SetLength(FEntries, 0);
|
||||||
|
inherited;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TVpICalendar.Clear;
|
||||||
|
var
|
||||||
|
j: Integer;
|
||||||
|
begin
|
||||||
|
for j := Count-1 downto 0 do
|
||||||
|
FEntries[j].Free;
|
||||||
|
SetLength(FEntries, 0);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TVpICalendar.GetCount: Integer;
|
||||||
|
begin
|
||||||
|
Result := Length(FEntries);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TVpICalendar.GetEntry(AIndex: Integer): TVpICalEntry;
|
||||||
|
begin
|
||||||
|
Result := FEntries[AIndex];
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TVpICalendar.LoadFromFile(const AFilename: String);
|
||||||
|
var
|
||||||
|
L: TStrings;
|
||||||
|
begin
|
||||||
|
L := TStringList.Create;
|
||||||
|
try
|
||||||
|
L.LoadFromFile(AFileName);
|
||||||
|
LoadFromStrings(L);
|
||||||
|
finally
|
||||||
|
L.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TVpICalendar.LoadFromStream(const AStream: TStream);
|
||||||
|
var
|
||||||
|
L: TStrings;
|
||||||
|
begin
|
||||||
|
L := TStringList.Create;
|
||||||
|
try
|
||||||
|
L.LoadFromStream(AStream);
|
||||||
|
LoadFromStrings(L);
|
||||||
|
finally
|
||||||
|
L.Free;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TVpICalendar.LoadFromStrings(const AStrings: TStrings);
|
||||||
|
const
|
||||||
|
BLOCK_SIZE = 100;
|
||||||
|
var
|
||||||
|
p: Integer;
|
||||||
|
itemName: String;
|
||||||
|
itemValue: String;
|
||||||
|
i, n: Integer;
|
||||||
|
s: String;
|
||||||
|
currEntry: TVpICalEntry = nil;
|
||||||
|
oldEntry: TVpICalEntry = nil;
|
||||||
|
begin
|
||||||
|
// Clear item list
|
||||||
|
Clear;
|
||||||
|
n := 0;
|
||||||
|
SetLength(FEntries, BLOCK_SIZE);
|
||||||
|
for i:=0 to AStrings.Count-1 do begin
|
||||||
|
s := AStrings[i];
|
||||||
|
if s = '' then
|
||||||
|
continue;
|
||||||
|
p := pos(':', s);
|
||||||
|
if p = 0 then
|
||||||
|
continue;
|
||||||
|
itemName := Uppercase(copy(s, 1, p-1));
|
||||||
|
itemValue := Uppercase(copy(s, p+1, MaxInt));
|
||||||
|
case ItemName of
|
||||||
|
'BEGIN':
|
||||||
|
begin
|
||||||
|
FEntries[n] := nil;
|
||||||
|
case itemValue of
|
||||||
|
'VTIMEZONE':
|
||||||
|
begin
|
||||||
|
currEntry := TVpICalTimeZoneInfo.Create(self);
|
||||||
|
FEntries[n] := currEntry;
|
||||||
|
end;
|
||||||
|
'VEVENT':
|
||||||
|
begin
|
||||||
|
currEntry := TVpICalEvent.Create(self);
|
||||||
|
FEntries[n] := currEntry;
|
||||||
|
end;
|
||||||
|
'VFREEBUSY':
|
||||||
|
currEntry := nil;
|
||||||
|
'VTODO':
|
||||||
|
currEntry := nil;
|
||||||
|
'VJOURNAL':
|
||||||
|
currEntry := nil;
|
||||||
|
'VALARM':
|
||||||
|
if currEntry is TVpICalEvent then begin
|
||||||
|
oldEntry := currEntry;
|
||||||
|
TVpICalEvent(currEntry).UseAlarm;
|
||||||
|
currEntry := TVpICalEvent(currEntry).Alarm;
|
||||||
|
end;
|
||||||
|
else
|
||||||
|
Continue;
|
||||||
|
end;
|
||||||
|
if FEntries[n] <> nil then begin
|
||||||
|
inc(n);
|
||||||
|
if n mod BLOCK_SIZE = 0 then
|
||||||
|
SetLength(FEntries, Length(FEntries) + BLOCK_SIZE);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
'END':
|
||||||
|
begin
|
||||||
|
if currEntry <> nil then
|
||||||
|
currEntry.Analyze;
|
||||||
|
if oldEntry <> nil then begin
|
||||||
|
currEntry := oldEntry;
|
||||||
|
oldEntry := nil;
|
||||||
|
end else
|
||||||
|
currEntry := nil;
|
||||||
|
end;
|
||||||
|
'VERSION':
|
||||||
|
FVersion := itemValue;
|
||||||
|
else
|
||||||
|
if currEntry <> nil then
|
||||||
|
currEntry.Add(s);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
SetLength(FEntries, n);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TVpICalendar.ConvertTime(ADateTime: TDateTime;
|
||||||
|
ATimeZoneID: String; ToUTC: Boolean): TDateTime;
|
||||||
|
var
|
||||||
|
offs: Double;
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
offs := 0;
|
||||||
|
for i:=0 to Count-1 do begin
|
||||||
|
if (FEntries[i] is TVpICalTimeZoneInfo) and
|
||||||
|
(TVpICalTimeZoneInfo(FEntries[i]).TimeZoneID = ATimeZoneID) then
|
||||||
|
begin
|
||||||
|
offs := TVpICalTimeZoneInfo(FEntries[i]).UTCOffset;
|
||||||
|
break;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
if ToUTC then
|
||||||
|
Result := ADateTime - offs
|
||||||
|
else
|
||||||
|
Result := ADateTime + offs;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TVpICalendar.LocalTimeToUTC(ADateTime: TDateTime;
|
||||||
|
ATimeZoneID: String): TDateTime;
|
||||||
|
begin
|
||||||
|
Result := ConvertTime(ADateTime, ATimeZoneID, true);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TVpICalendar.UTCToLocalTime(ADateTime: TDateTime;
|
||||||
|
ATimeZoneID: String): TDateTime;
|
||||||
|
begin
|
||||||
|
Result := ConvertTime(ADateTime, ATimeZoneID, false);
|
||||||
|
end;
|
||||||
|
|
||||||
|
end.
|
||||||
|
|
@ -205,9 +205,9 @@ begin
|
|||||||
'ORG':
|
'ORG':
|
||||||
FCompany := item.Value;
|
FCompany := item.Value;
|
||||||
'ADR':
|
'ADR':
|
||||||
if item.Tags.IndexOf('WORK') <> -1 then
|
if item.Attributes.IndexOf('WORK') <> -1 then
|
||||||
VCardAddress(item.Value, FWorkAddress, FWorkCity, FWorkZip, FWorkState, FWorkCountry)
|
VCardAddress(item.Value, FWorkAddress, FWorkCity, FWorkZip, FWorkState, FWorkCountry)
|
||||||
else if item.Tags.IndexOf('HOME') <> -1 then
|
else if item.Attributes.IndexOf('HOME') <> -1 then
|
||||||
VCardAddress(item.value, FHomeAddress, FHomeCity, FHomeZip, FHomeState, FHomeCountry)
|
VCardAddress(item.value, FHomeAddress, FHomeCity, FHomeZip, FHomeState, FHomeCountry)
|
||||||
else
|
else
|
||||||
if FCompany = '' then
|
if FCompany = '' then
|
||||||
@ -215,30 +215,30 @@ begin
|
|||||||
else
|
else
|
||||||
VCardAddress(item.Value, FWorkAddress, FWorkCity, FWorkZip, FWorkState, FWorkCountry);
|
VCardAddress(item.Value, FWorkAddress, FWorkCity, FWorkZip, FWorkState, FWorkCountry);
|
||||||
'EMAIL':
|
'EMAIL':
|
||||||
if (FCompany = '') or (item.Tags.IndexOf('HOME') <> -1) then
|
if (FCompany = '') or (item.Attributes.IndexOf('HOME') <> -1) then
|
||||||
FHomeEMail := IfThen(FHomeEMail = '', item.Value, FHomeEMail + ITEM_SEPARATOR + item.Value)
|
FHomeEMail := IfThen(FHomeEMail = '', item.Value, FHomeEMail + ITEM_SEPARATOR + item.Value)
|
||||||
else
|
else
|
||||||
FWorkEMail := IfThen(FWorkEMail = '', item.Value, FWorkEMail + ITEM_SEPARATOR + item.Value);
|
FWorkEMail := IfThen(FWorkEMail = '', item.Value, FWorkEMail + ITEM_SEPARATOR + item.Value);
|
||||||
'TEL':
|
'TEL':
|
||||||
if item.Tags.IndexOf('CELL') <> -1 then
|
if item.Attributes.IndexOf('CELL') <> -1 then
|
||||||
FMobile := item.Value
|
FMobile := item.Value
|
||||||
else
|
else
|
||||||
if item.Tags.IndexOf('PAGER') <> -1 then
|
if item.Attributes.IndexOf('PAGER') <> -1 then
|
||||||
FPager := item.Value
|
FPager := item.Value
|
||||||
else
|
else
|
||||||
if item.Tags.IndexOf('FAX') <> -1 then begin
|
if item.Attributes.IndexOf('FAX') <> -1 then begin
|
||||||
if (FCompany = '') or (item.Tags.IndexOf('HOME') <> -1) then
|
if (FCompany = '') or (item.Attributes.IndexOf('HOME') <> -1) then
|
||||||
FHomeFax := item.Value
|
FHomeFax := item.Value
|
||||||
else
|
else
|
||||||
FWorkFax := item.Value;
|
FWorkFax := item.Value;
|
||||||
end else
|
end else
|
||||||
if item.Tags.IndexOf('CAR') <> -1 then
|
if item.Attributes.IndexOf('CAR') <> -1 then
|
||||||
FCarPhone := item.Value
|
FCarPhone := item.Value
|
||||||
else
|
else
|
||||||
if item.Tags.IndexOf('ISDN') <> -1 then
|
if item.Attributes.IndexOf('ISDN') <> -1 then
|
||||||
FISDN := item.Value
|
FISDN := item.Value
|
||||||
else
|
else
|
||||||
if (FCompany = '') or (item.tags.IndexOf('HOME') <> -1) then
|
if (FCompany = '') or (item.Attributes.IndexOf('HOME') <> -1) then
|
||||||
FHomePhone := IfThen(FHomePhone = '', item.Value, FHomePhone + ITEM_SEPARATOR + item.Value)
|
FHomePhone := IfThen(FHomePhone = '', item.Value, FHomePhone + ITEM_SEPARATOR + item.Value)
|
||||||
else
|
else
|
||||||
FWorkPhone := IfThen(FWorkPhone = '', item.Value, FWorkPhone + ITEM_SEPARATOR + item.Value);
|
FWorkPhone := IfThen(FWorkPhone = '', item.Value, FWorkPhone + ITEM_SEPARATOR + item.Value);
|
||||||
|
@ -79,8 +79,9 @@ object FrmSoundDialog: TFrmSoundDialog
|
|||||||
Left = 0
|
Left = 0
|
||||||
Height = 25
|
Height = 25
|
||||||
Top = 4
|
Top = 4
|
||||||
Width = 48
|
Width = 77
|
||||||
Anchors = [akTop, akLeft, akBottom]
|
Anchors = [akTop, akLeft, akBottom]
|
||||||
|
Caption = 'Play'
|
||||||
Glyph.Data = {
|
Glyph.Data = {
|
||||||
DE010000424DDE01000000000000760000002800000024000000120000000100
|
DE010000424DDE01000000000000760000002800000024000000120000000100
|
||||||
0400000000006801000000000000000000001000000010000000000000000000
|
0400000000006801000000000000000000001000000010000000000000000000
|
||||||
@ -99,8 +100,9 @@ object FrmSoundDialog: TFrmSoundDialog
|
|||||||
6666666666666688666666660000666666666666666666666666666666666666
|
6666666666666688666666660000666666666666666666666666666666666666
|
||||||
0000
|
0000
|
||||||
}
|
}
|
||||||
Layout = blGlyphRight
|
Margin = 4
|
||||||
NumGlyphs = 2
|
NumGlyphs = 2
|
||||||
|
Spacing = -1
|
||||||
OnClick = PlayButtonClick
|
OnClick = PlayButtonClick
|
||||||
end
|
end
|
||||||
object OkBtn: TButton
|
object OkBtn: TButton
|
||||||
|
@ -139,11 +139,11 @@ end;
|
|||||||
|
|
||||||
procedure TFrmSoundDialog.FormShow(Sender: TObject);
|
procedure TFrmSoundDialog.FormShow(Sender: TObject);
|
||||||
begin
|
begin
|
||||||
AlignOKCancel(OkBtn, CancelBtn, ButtonPanel);
|
|
||||||
PlayButton.Width := MulDiv(PlayButton.Height, 3, 2) ;
|
|
||||||
{$IFDEF NEW_ICONS}
|
{$IFDEF NEW_ICONS}
|
||||||
LoadGlyphFromRCDATA(PlayButton.Glyph, 'VpSpeaker', 16, 24, 32);
|
LoadGlyphFromRCDATA(PlayButton.Glyph, 'VpSpeaker', 16, 24, 32);
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
|
AlignOKCancel(OkBtn, CancelBtn, ButtonPanel);
|
||||||
|
PlayButton.Width := CancelBtn.Width; //MulDiv(PlayButton.Height, 3, 2) ;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TFrmSoundDialog.GetSelectedFileName: String;
|
function TFrmSoundDialog.GetSelectedFileName: String;
|
||||||
@ -181,32 +181,6 @@ begin
|
|||||||
Label3.Caption := RSNothingToSelectFrom;
|
Label3.Caption := RSNothingToSelectFrom;
|
||||||
Label4.Caption := RSNothingToSelectFrom;
|
Label4.Caption := RSNothingToSelectFrom;
|
||||||
|
|
||||||
(*
|
|
||||||
DIST := ScaleX(DIST, DesignTimeDPI);
|
|
||||||
VDist := ScaleY(VDist, DesignTimeDPI);
|
|
||||||
HBORDER := ScaleX(HBORDER, DesignTimeDPI);
|
|
||||||
|
|
||||||
OKBtn.Height := ScaleX(OKBtn.Height, DesignTimeDPI);
|
|
||||||
CancelBtn.Height := OKBtn.Height;
|
|
||||||
ButtonPanel.Height := VDist + OKBtn.Height + VDist;
|
|
||||||
OKBtn.Top := VDist;
|
|
||||||
CancelBtn.Top := VDist;
|
|
||||||
PlayButton.Top := (ButtonPanel.Height - PlayButton.Height) div 2;
|
|
||||||
|
|
||||||
OKBtn.Width := Max(GetButtonWidth(OKBtn), GetButtonWidth(CancelBtn));
|
|
||||||
CancelBtn.Width := OKBtn.Width;
|
|
||||||
{$IFDEF MSWINDOWS}
|
|
||||||
CancelBtn.Left := ButtonPanel.ClientWidth - HBORDER - CancelBtn.Width;
|
|
||||||
OKBtn.Left := CancelBtn.Left - DIST - OKBtn.Width;
|
|
||||||
OKBtn.TabOrder := 0;
|
|
||||||
CancelBtn.TabOrder := 1;
|
|
||||||
{$ELSE}
|
|
||||||
OKBtn.Left := ButtonPanel.ClientWidth - HBORDER - OKBtn.Width;
|
|
||||||
CancelBtn.Left := OKBtn.Left - DIST - CancelBtn.Width;
|
|
||||||
CancelBtn.TabOrder := 0;
|
|
||||||
OKBtn.TabOrder := 1;
|
|
||||||
{$ENDIF}
|
|
||||||
*)
|
|
||||||
if DingPath = '' then begin
|
if DingPath = '' then begin
|
||||||
CBDefault.Checked := true;
|
CBDefault.Checked := true;
|
||||||
if (MediaFolder <> '') and DirectoryExists(MediaFolder) then
|
if (MediaFolder <> '') and DirectoryExists(MediaFolder) then
|
||||||
@ -215,6 +189,7 @@ begin
|
|||||||
if FileExists(DingPath) then begin
|
if FileExists(DingPath) then begin
|
||||||
ShellTreeview.Path := ExtractFileDir(DingPath);
|
ShellTreeview.Path := ExtractFileDir(DingPath);
|
||||||
ShellListview.Selected := FindFileItem(DingPath);
|
ShellListview.Selected := FindFileItem(DingPath);
|
||||||
|
CbDefault.Checked := false;
|
||||||
end else begin
|
end else begin
|
||||||
ShellTreeView.Path := MediaFolder;
|
ShellTreeView.Path := MediaFolder;
|
||||||
end;
|
end;
|
||||||
|
Reference in New Issue
Block a user