git-svn-id: https://192.168.0.254/svn/Componentes.Terceros.DevExpressVCL@38 05c56307-c608-d34a-929d-697000501d7a
1446 lines
48 KiB
ObjectPascal
1446 lines
48 KiB
ObjectPascal
{********************************************************************}
|
|
{ }
|
|
{ Developer Express Visual Component Library }
|
|
{ ExpressScheduler }
|
|
{ }
|
|
{ Copyright (c) 2003-2009 Developer Express Inc. }
|
|
{ ALL RIGHTS RESERVED }
|
|
{ }
|
|
{ The entire contents of this file is protected by U.S. and }
|
|
{ International Copyright Laws. Unauthorized reproduction, }
|
|
{ reverse-engineering, and distribution of all or any portion of }
|
|
{ the code contained in this file is strictly prohibited and may }
|
|
{ result in severe civil and criminal penalties and will be }
|
|
{ prosecuted to the maximum extent possible under the law. }
|
|
{ }
|
|
{ RESTRICTIONS }
|
|
{ }
|
|
{ THIS SOURCE CODE AND ALL RESULTING INTERMEDIATE FILES }
|
|
{ (DCU, OBJ, DLL, ETC.) ARE CONFIDENTIAL AND PROPRIETARY TRADE }
|
|
{ SECRETS OF DEVELOPER EXPRESS INC. THE REGISTERED DEVELOPER IS }
|
|
{ LICENSED TO DISTRIBUTE THE EXPRESSSCHEDULER AND ALL ACCOMPANYING }
|
|
{ VCL CONTROLS AS PART OF AN EXECUTABLE PROGRAM ONLY. }
|
|
{ }
|
|
{ THE SOURCE CODE CONTAINED WITHIN THIS FILE AND ALL RELATED }
|
|
{ FILES OR ANY PORTION OF ITS CONTENTS SHALL AT NO TIME BE }
|
|
{ COPIED, TRANSFERRED, SOLD, DISTRIBUTED, OR OTHERWISE MADE }
|
|
{ AVAILABLE TO OTHER INDIVIDUALS WITHOUT EXPRESS WRITTEN CONSENT }
|
|
{ AND PERMISSION FROM DEVELOPER EXPRESS INC. }
|
|
{ }
|
|
{ CONSULT THE END USER LICENSE AGREEMENT FOR INFORMATION ON }
|
|
{ ADDITIONAL RESTRICTIONS. }
|
|
{ }
|
|
{********************************************************************}
|
|
|
|
unit cxSchedulerOutlookExchange;
|
|
|
|
{$I cxVer.inc}
|
|
|
|
interface
|
|
|
|
uses
|
|
{$IFDEF DELPHI6}
|
|
Variants,
|
|
{$ENDIF}
|
|
Classes, cxSchedulerStorage, ComObj, cxClasses, cxDateUtils;
|
|
|
|
type
|
|
TcxSchedulerExchangeProgressProc = procedure(ACurrent, ACount: Integer; var Abort: Boolean);
|
|
TcxAcceptEventExportFunc = function(AEvent: TcxSchedulerEvent): Boolean;
|
|
TcxAcceptAppointmentItemImportFunc = function(const AppointmentItem: OleVariant): Boolean;
|
|
TcxAppointmentItemToEventProc = procedure(const AppointmentItem: OleVariant; AEvent: TcxSchedulerEvent);
|
|
TcxEventToAppointmentItemProc = procedure(AEvent: TcxSchedulerEvent; const AppointmentItem: OleVariant);
|
|
|
|
{ TcxAppointmentInfo }
|
|
|
|
TcxAppointmentInfo = class
|
|
private
|
|
FAppointmentItem: OleVariant;
|
|
FEntryID: string;
|
|
public
|
|
constructor Create(const AAppointmentItem: OleVariant);
|
|
|
|
property AppointmentItem: OleVariant read FAppointmentItem;
|
|
property EntryID: string read FEntryID;
|
|
end;
|
|
|
|
{ TcxAppointmentEntryIDList }
|
|
|
|
TcxAppointmentEntryIDList = class(TcxObjectList)
|
|
private
|
|
function GetItems(Index: Integer): TcxAppointmentInfo;
|
|
public
|
|
procedure Add(const AppointmentItem: OleVariant);
|
|
function ExtractAppointmentItem(AIndex: Integer): OleVariant;
|
|
function FindEntryID(const AEntryID: string; var Index: Integer): Boolean;
|
|
function IndexOfEntryID(const AEntryID: string): Integer;
|
|
procedure Populate(ACalendarFolder: OleVariant);
|
|
|
|
property Items[Index: Integer]: TcxAppointmentInfo read GetItems; default;
|
|
end;
|
|
|
|
{ TcxEventInfo }
|
|
|
|
TcxEventInfo = class
|
|
private
|
|
FEvent: TcxSchedulerEvent;
|
|
FEntryID: string;
|
|
public
|
|
constructor Create(AEvent: TcxSchedulerEvent; AEntryIDField: TcxCustomSchedulerStorageField);
|
|
|
|
property Event: TcxSchedulerEvent read FEvent;
|
|
property EntryID: string read FEntryID;
|
|
end;
|
|
|
|
{ TcxEventEntryIDList }
|
|
|
|
TcxEventEntryIDList = class(TcxObjectList)
|
|
private
|
|
function GetItems(Index: Integer): TcxEventInfo;
|
|
public
|
|
procedure Add(AEvent: TcxSchedulerEvent; AEntryIDField: TcxCustomSchedulerStorageField);
|
|
procedure DeleteEvent(AEvent: TcxSchedulerEvent);
|
|
function ExtractEvent(AIndex: Integer): TcxSchedulerEvent;
|
|
function FindEntryID(const AEntryID: string; var Index: Integer): Boolean;
|
|
function IndexOfEntryID(const AEntryID: string): Integer;
|
|
procedure Populate(AStorage: TcxCustomSchedulerStorage;
|
|
AEntryIDField: TcxCustomSchedulerStorageField);
|
|
|
|
property Items[Index: Integer]: TcxEventInfo read GetItems; default;
|
|
end;
|
|
|
|
{ TcxOutlookExchange }
|
|
|
|
TcxOutlookExchange = class
|
|
private
|
|
FCalendarFolder: OleVariant;
|
|
FOleInitialized: Boolean;
|
|
FOutlookApp: OleVariant;
|
|
FStorage: TcxCustomSchedulerStorage;
|
|
FWasCreated: Boolean;
|
|
FOnAcceptAppointmentItem: TcxAcceptAppointmentItemImportFunc;
|
|
FOnAcceptEvent: TcxAcceptEventExportFunc;
|
|
FOnConvertAppointmentItemToEvent: TcxAppointmentItemToEventProc;
|
|
FOnConvertEventToAppointmentItem: TcxEventToAppointmentItemProc;
|
|
FOnProgress: TcxSchedulerExchangeProgressProc;
|
|
function GetAllDayEvent(const AppointmentItem: OleVariant): Boolean;
|
|
function GetDaysOfWeekFromMask(AMask: Integer): TDays;
|
|
function GetDayTypeFromMask(AMask: Integer): TcxDayType;
|
|
function GetMaskFromDaysOfWeek(ADays: TDays): Integer;
|
|
function GetMaskFromDayType(ADayType: TcxDayType): Integer;
|
|
protected
|
|
function CanAcceptAppointmentItem(const AppointmentItem: OleVariant): Boolean;
|
|
function CanAcceptEvent(AEvent: TcxSchedulerEvent): Boolean;
|
|
function CanImportAppointmentItem(const AppointmentItem: OleVariant): Boolean; virtual;
|
|
procedure ConvertAppointmentItemToEvent(const AppointmentItem: OleVariant;
|
|
AEvent: TcxSchedulerEvent);
|
|
procedure ConvertEventToAppointmentItem(AEvent: TcxSchedulerEvent;
|
|
const AppointmentItem: OleVariant);
|
|
procedure ImportRecurrenceChain(APatternEvent: TcxSchedulerEvent;
|
|
const ARecurrencePattern: OleVariant);
|
|
procedure CheckRecurrencePatternExceptions(
|
|
const ARecurrencePattern: OleVariant;
|
|
APatternEvent: TcxSchedulerEvent);
|
|
procedure ExportRecurrenceChain(APatternEvent: TcxSchedulerEvent; const AppointmentItem: OleVariant);
|
|
|
|
function GetIsValid: Boolean; virtual;
|
|
function InitOleObject: Boolean;
|
|
procedure PostRecurrenceExeption(AOccurrence: TcxSchedulerEvent); virtual;
|
|
function RoundTime(ATime: TDateTime; ASaveDate: Boolean): TDateTime; virtual;
|
|
procedure SetAppointmentItemRecurrence(
|
|
const ARecurrencePattern: OleVariant; AEvent: TcxSchedulerEvent);
|
|
procedure SetupAppointmentItemInfo(const AppointmentItem: OleVariant;
|
|
const AEvent: TcxSchedulerEvent; ASetTime: Boolean = True);
|
|
procedure SetupEventInfo(AEvent: TcxSchedulerEvent;
|
|
const AppointmentItem: OleVariant);
|
|
procedure SetupEventRecurrenceInfo(AEvent: TcxSchedulerEvent;
|
|
const ARecurrencePattern: OleVariant);
|
|
procedure UpdateAppointmentItem(const AppointmentItem: OleVariant;
|
|
AEvent: TcxSchedulerEvent); virtual;
|
|
procedure UpdateEvent(AEvent: TcxSchedulerEvent;
|
|
const AppointmentItem: OleVariant; APostData: Boolean = True); virtual;
|
|
procedure UpdateEventWithRecurrenceInfo(AEvent: TcxSchedulerEvent;
|
|
const AppointmentItem: OleVariant);
|
|
function DoProgress(ACurrent, ACount: Integer): Boolean;
|
|
|
|
property CalendarFolder: OleVariant read FCalendarFolder;
|
|
property IsValid: Boolean read GetIsValid;
|
|
property OutlookApp: OleVariant read FOutlookApp;
|
|
property Storage: TcxCustomSchedulerStorage read FStorage;
|
|
public
|
|
constructor Create(AStorage: TcxCustomSchedulerStorage); virtual;
|
|
destructor Destroy; override;
|
|
procedure ExportEventToOutlook(AEvent: TcxSchedulerEvent);
|
|
procedure ExportToOutlook;
|
|
procedure ImportAppointmentItemFromOutlook(const AppointmentItem: OleVariant);
|
|
procedure ImportFromOutlook;
|
|
|
|
property OnAcceptAppointmentItem: TcxAcceptAppointmentItemImportFunc
|
|
read FOnAcceptAppointmentItem write FOnAcceptAppointmentItem;
|
|
property OnAcceptEvent: TcxAcceptEventExportFunc
|
|
read FOnAcceptEvent write FOnAcceptEvent;
|
|
property OnConvertAppointmentItemToEvent: TcxAppointmentItemToEventProc
|
|
read FOnConvertAppointmentItemToEvent write FOnConvertAppointmentItemToEvent;
|
|
property OnConvertEventToAppointmentItem: TcxEventToAppointmentItemProc
|
|
read FOnConvertEventToAppointmentItem write FOnConvertEventToAppointmentItem;
|
|
property OnProgress: TcxSchedulerExchangeProgressProc
|
|
read FOnProgress write FOnProgress;
|
|
end;
|
|
|
|
{ TcxOutlookSynchronize }
|
|
|
|
TcxOutlookSynchronize = class(TcxOutlookExchange)
|
|
private
|
|
FEntryIDField: TcxCustomSchedulerStorageField;
|
|
protected
|
|
procedure DeleteUnsynchronizedAppointments(AEntryIDs: TcxAppointmentEntryIDList);
|
|
procedure DeleteUnsynchronizedEvents(AEntryIDs: TcxEventEntryIDList);
|
|
function GetEntryIDFromEvent(AEvent: TcxSchedulerEvent): string;
|
|
function GetIsValid: Boolean; override;
|
|
function IsEqualRecurrencePattern(const AppointmentItem: OleVariant;
|
|
AEvent: TcxSchedulerEvent): Boolean;
|
|
procedure PostRecurrenceExeption(AOccurrence: TcxSchedulerEvent); override;
|
|
procedure PurgeDeletedOccurrences(APatternEvent: TcxSchedulerEvent;
|
|
AEntryIDs: TcxEventEntryIDList);
|
|
procedure UpdateAppointmentItem(const AppointmentItem: OleVariant;
|
|
AEvent: TcxSchedulerEvent); override;
|
|
procedure UpdateExistingAppointmentItem(const AppointmentItem: OleVariant;
|
|
AEvent: TcxSchedulerEvent);
|
|
procedure UpdateExistingEvent(AEvent: TcxSchedulerEvent;
|
|
const AppointmentItem: OleVariant; AEntryIDs: TcxEventEntryIDList);
|
|
procedure UpdateEvent(AEvent: TcxSchedulerEvent;
|
|
const AppointmentItem: OleVariant; APostData: Boolean = True); override;
|
|
procedure SynchronizeRecurrenceChainWithOutlook(
|
|
APatternEvent: TcxSchedulerEvent; const ARecurrencePattern: OleVariant;
|
|
AEntryIDs: TcxEventEntryIDList);
|
|
public
|
|
procedure SynchronizeWithOutlook(ADeleteUnsynchronizedEvents: Boolean = False);
|
|
procedure SynchronizeWithStorage(ADeleteUnsynchronizedAppointments: Boolean = False);
|
|
|
|
property EntryIDField: TcxCustomSchedulerStorageField
|
|
read FEntryIDField write FEntryIDField;
|
|
end;
|
|
|
|
procedure cxSchedulerExportToOutlook(AStorage: TcxCustomSchedulerStorage;
|
|
AcceptFunc: TcxAcceptEventExportFunc = nil;
|
|
AConvertProc: TcxEventToAppointmentItemProc = nil;
|
|
AProgressProc: TcxSchedulerExchangeProgressProc = nil);
|
|
|
|
procedure cxSchedulerImportFromOutlook(AStorage: TcxCustomSchedulerStorage;
|
|
AcceptFunc: TcxAcceptAppointmentItemImportFunc = nil;
|
|
AConvertProc: TcxAppointmentItemToEventProc = nil;
|
|
AProgressProc: TcxSchedulerExchangeProgressProc = nil);
|
|
|
|
procedure cxSchedulerSynchronizeOutlookWithStorage(AStorage: TcxCustomSchedulerStorage;
|
|
AppointmentItemIDField: TcxCustomSchedulerStorageField;
|
|
ADeleteUnsynchronizedAppointments: Boolean = False;
|
|
AcceptFunc: TcxAcceptEventExportFunc = nil;
|
|
AConvertProc: TcxEventToAppointmentItemProc = nil;
|
|
AProgressProc: TcxSchedulerExchangeProgressProc = nil);
|
|
|
|
procedure cxSchedulerSynchronizeStorageWithOutlook(AStorage: TcxCustomSchedulerStorage;
|
|
AppointmentItemIDField: TcxCustomSchedulerStorageField;
|
|
ADeleteUnsynchronizedEvents: Boolean = False;
|
|
AcceptFunc: TcxAcceptAppointmentItemImportFunc = nil;
|
|
AConvertProc: TcxAppointmentItemToEventProc = nil;
|
|
AProgressProc: TcxSchedulerExchangeProgressProc = nil);
|
|
|
|
implementation
|
|
|
|
uses
|
|
Windows, SysUtils, cxSchedulerUtils, cxVariants, Forms;
|
|
|
|
const
|
|
olFolderCalendar = $00000009;
|
|
olAppointmentItem = $00000001;
|
|
|
|
//recurrence
|
|
olRecursDaily = $00000000;
|
|
olRecursWeekly = $00000001;
|
|
olRecursMonthly = $00000002;
|
|
olRecursMonthNth = $00000003;
|
|
olRecursYearly = $00000005;
|
|
olRecursYearNth = $00000006;
|
|
|
|
// Constants for enum OlDaysOfWeek
|
|
olSunday = $00000001;
|
|
olMonday = $00000002;
|
|
olTuesday = $00000004;
|
|
olWednesday = $00000008;
|
|
olThursday = $00000010;
|
|
olFriday = $00000020;
|
|
olSaturday = $00000040;
|
|
olWeekDay = olMonday + olTuesday + olWednesday + olThursday + olFriday;
|
|
olWeekEndDay = olSunday + olSaturday;
|
|
olEveryDay = olWeekDay + olWeekEndDay;
|
|
|
|
// Constants for enum OlBusyStatus
|
|
olFree = $00000000;
|
|
olTentative = $00000001;
|
|
olBusy = $00000002;
|
|
olOutOfOffice = $00000003;
|
|
|
|
scxOutlookApp = 'outlook.application';
|
|
scxNameSpace = 'MAPI';
|
|
|
|
NullEntryID = '0000000000000000000000000000000000000000';
|
|
|
|
{ TcxAppointmentInfo }
|
|
|
|
constructor TcxAppointmentInfo.Create(const AAppointmentItem: OleVariant);
|
|
begin
|
|
FAppointmentItem := AAppointmentItem;
|
|
FEntryID := UpperCase(AAppointmentItem.EntryID);
|
|
end;
|
|
|
|
{ TcxAppointmentEntryIDList }
|
|
|
|
procedure TcxAppointmentEntryIDList.Add(const AppointmentItem: OleVariant);
|
|
begin
|
|
inherited Add(TcxAppointmentInfo.Create(AppointmentItem));
|
|
end;
|
|
|
|
function TcxAppointmentEntryIDList.ExtractAppointmentItem(
|
|
AIndex: Integer): OleVariant;
|
|
var
|
|
AppointmentInfo: TcxAppointmentInfo;
|
|
begin
|
|
AppointmentInfo := Items[AIndex];
|
|
Result := AppointmentInfo.AppointmentItem;
|
|
AppointmentInfo.Free;
|
|
Delete(AIndex);
|
|
end;
|
|
|
|
function TcxAppointmentEntryIDList.FindEntryID(const AEntryID: string; var Index: Integer): Boolean;
|
|
var
|
|
L, H, I, C: Integer;
|
|
begin
|
|
Result := False;
|
|
if Length(AEntryID) = 0 then Exit;
|
|
L := 0;
|
|
H := Count - 1;
|
|
while L <= H do
|
|
begin
|
|
I := (L + H) shr 1;
|
|
C := CompareStr(Items[I].EntryID, AEntryID);
|
|
if C < 0 then L := I + 1 else
|
|
begin
|
|
H := I - 1;
|
|
if C = 0 then
|
|
begin
|
|
Result := True;
|
|
L := I;
|
|
end;
|
|
end;
|
|
end;
|
|
Index := L;
|
|
end;
|
|
|
|
function TcxAppointmentEntryIDList.IndexOfEntryID(const AEntryID: string): Integer;
|
|
begin
|
|
if not FindEntryID(AEntryID, Result) then
|
|
Result := -1;
|
|
end;
|
|
|
|
function CompareAppointments(Item1, Item2: Pointer): Integer;
|
|
begin
|
|
Result := CompareStr(TcxAppointmentInfo(Item1).EntryID, TcxAppointmentInfo(Item2).EntryID);
|
|
end;
|
|
|
|
procedure TcxAppointmentEntryIDList.Populate(ACalendarFolder: OleVariant);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
Capacity := ACalendarFolder.Items.Count;
|
|
for I := 1 to ACalendarFolder.Items.Count do
|
|
Add(ACalendarFolder.Items(I));
|
|
Sort(CompareAppointments);
|
|
end;
|
|
|
|
function TcxAppointmentEntryIDList.GetItems(Index: Integer): TcxAppointmentInfo;
|
|
begin
|
|
Result := TcxAppointmentInfo(List^[Index]);
|
|
end;
|
|
|
|
{ TcxEventInfo }
|
|
|
|
constructor TcxEventInfo.Create(AEvent: TcxSchedulerEvent; AEntryIDField: TcxCustomSchedulerStorageField);
|
|
begin
|
|
FEvent := AEvent;
|
|
if AEvent.EventType in [etNone, etPattern] then
|
|
FEntryID := Trim(VarToStr(AEvent.GetCustomFieldValue(AEntryIDField)))
|
|
else
|
|
FEntryID := NullEntryID;
|
|
end;
|
|
|
|
{ TcxEventEntryIDList }
|
|
|
|
procedure TcxEventEntryIDList.Add(AEvent: TcxSchedulerEvent;
|
|
AEntryIDField: TcxCustomSchedulerStorageField);
|
|
begin
|
|
inherited Add(TcxEventInfo.Create(AEvent, AEntryIDField));
|
|
end;
|
|
|
|
procedure TcxEventEntryIDList.DeleteEvent(AEvent: TcxSchedulerEvent);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
for I := 0 to Count - 1 do
|
|
if Items[I].Event = AEvent then
|
|
begin
|
|
Items[I].Free;
|
|
Delete(I);
|
|
break;
|
|
end;
|
|
end;
|
|
|
|
function TcxEventEntryIDList.ExtractEvent(AIndex: Integer): TcxSchedulerEvent;
|
|
var
|
|
AEventInfo: TcxEventInfo;
|
|
begin
|
|
AEventInfo := Items[AIndex];
|
|
Result := AEventInfo.Event;
|
|
AEventInfo.Free;
|
|
Delete(AIndex);
|
|
end;
|
|
|
|
function TcxEventEntryIDList.FindEntryID(const AEntryID: string;
|
|
var Index: Integer): Boolean;
|
|
var
|
|
L, H, I, C: Integer;
|
|
begin
|
|
Result := False;
|
|
if Length(AEntryID) = 0 then Exit;
|
|
L := 0;
|
|
H := Count - 1;
|
|
while L <= H do
|
|
begin
|
|
I := (L + H) shr 1;
|
|
C := CompareStr(Items[I].EntryID, AEntryID);
|
|
if C < 0 then L := I + 1 else
|
|
begin
|
|
H := I - 1;
|
|
if C = 0 then
|
|
begin
|
|
Result := True;
|
|
L := I;
|
|
end;
|
|
end;
|
|
end;
|
|
Index := L;
|
|
end;
|
|
|
|
function TcxEventEntryIDList.IndexOfEntryID(
|
|
const AEntryID: string): Integer;
|
|
begin
|
|
if not FindEntryID(AEntryID, Result) then
|
|
Result := -1;
|
|
end;
|
|
|
|
function CompareEvents(Item1, Item2: Pointer): Integer;
|
|
begin
|
|
Result := CompareStr(TcxEventInfo(Item1).EntryID, TcxEventInfo(Item2).EntryID);
|
|
end;
|
|
|
|
procedure TcxEventEntryIDList.Populate(AStorage: TcxCustomSchedulerStorage;
|
|
AEntryIDField: TcxCustomSchedulerStorageField);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
Capacity := AStorage.EventCount;
|
|
for I := 0 to AStorage.EventCount - 1 do
|
|
Add(AStorage.Events[I], AEntryIDField);
|
|
Sort(CompareEvents);
|
|
end;
|
|
|
|
function TcxEventEntryIDList.GetItems(Index: Integer): TcxEventInfo;
|
|
begin
|
|
Result := TcxEventInfo(List^[Index]);
|
|
end;
|
|
|
|
{ TcxOutlookExchange }
|
|
|
|
constructor TcxOutlookExchange.Create(AStorage: TcxCustomSchedulerStorage);
|
|
begin
|
|
inherited Create;
|
|
FStorage := AStorage;
|
|
FOleInitialized := InitOleObject;
|
|
end;
|
|
|
|
destructor TcxOutlookExchange.Destroy;
|
|
begin
|
|
if FWasCreated then
|
|
FOutlookApp := Unassigned;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TcxOutlookExchange.ExportEventToOutlook(AEvent: TcxSchedulerEvent);
|
|
var
|
|
AppointmentItem: OleVariant;
|
|
begin
|
|
if AEvent.EventType in [etNone, etPattern] then
|
|
begin
|
|
AppointmentItem := OutlookApp.CreateItem(olAppointmentItem);
|
|
SetupAppointmentItemInfo(AppointmentItem, AEvent);
|
|
if AEvent.IsRecurring then
|
|
ExportRecurrenceChain(AEvent, AppointmentItem)
|
|
else
|
|
UpdateAppointmentItem(AppointmentItem, AEvent);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxOutlookExchange.ExportToOutlook;
|
|
var
|
|
AEvent: TcxSchedulerEvent;
|
|
I, ACount: Integer;
|
|
begin
|
|
if not IsValid then Exit;
|
|
Storage.BeginUpdate;
|
|
try
|
|
ACount := Storage.EventCount;
|
|
for I := 0 to ACount - 1 do
|
|
begin
|
|
AEvent := Storage.Events[I];
|
|
if CanAcceptEvent(AEvent) then
|
|
ExportEventToOutlook(AEvent);
|
|
if not DoProgress(I + 1, ACount) then
|
|
Break;
|
|
Application.ProcessMessages;
|
|
end;
|
|
finally
|
|
Storage.EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxOutlookExchange.ImportAppointmentItemFromOutlook(
|
|
const AppointmentItem: OleVariant);
|
|
var
|
|
AEvent: TcxSchedulerEvent;
|
|
ARecurrencePattern: OleVariant;
|
|
begin
|
|
AEvent := Storage.CreateEvent;
|
|
SetupEventInfo(AEvent, AppointmentItem);
|
|
if AppointmentItem.IsRecurring then
|
|
begin
|
|
ARecurrencePattern := AppointmentItem.GetRecurrencePattern;
|
|
UpdateEventWithRecurrenceInfo(AEvent, AppointmentItem);
|
|
ImportRecurrenceChain(AEvent, ARecurrencePattern);
|
|
end
|
|
else
|
|
UpdateEvent(AEvent, AppointmentItem);
|
|
end;
|
|
|
|
procedure TcxOutlookExchange.ImportFromOutlook;
|
|
var
|
|
I, ACount: Integer;
|
|
AppointmentItem: OleVariant;
|
|
begin
|
|
if not IsValid then Exit;
|
|
ACount := CalendarFolder.Items.Count;
|
|
for I := 1 to ACount do
|
|
begin
|
|
AppointmentItem := CalendarFolder.Items(I);
|
|
if CanImportAppointmentItem(AppointmentItem) and CanAcceptAppointmentItem(AppointmentItem) then
|
|
ImportAppointmentItemFromOutlook(AppointmentItem);
|
|
if not DoProgress(I, ACount) then
|
|
Break;
|
|
Application.ProcessMessages;
|
|
end;
|
|
end;
|
|
|
|
function TcxOutlookExchange.CanAcceptAppointmentItem(
|
|
const AppointmentItem: OleVariant): Boolean;
|
|
begin
|
|
Result := not Assigned(FOnAcceptAppointmentItem) or
|
|
FOnAcceptAppointmentItem(AppointmentItem);
|
|
end;
|
|
|
|
function TcxOutlookExchange.CanAcceptEvent(AEvent: TcxSchedulerEvent): Boolean;
|
|
begin
|
|
Result := not Assigned(FOnAcceptEvent) or FOnAcceptEvent(AEvent);
|
|
end;
|
|
|
|
function TcxOutlookExchange.CanImportAppointmentItem(
|
|
const AppointmentItem: OleVariant): Boolean;
|
|
begin
|
|
Result := not (AppointmentItem.IsRecurring and not Storage.IsRecurrenceAvailable);
|
|
end;
|
|
|
|
procedure TcxOutlookExchange.ConvertAppointmentItemToEvent(
|
|
const AppointmentItem: OleVariant; AEvent: TcxSchedulerEvent);
|
|
begin
|
|
if Assigned(FOnConvertAppointmentItemToEvent) then
|
|
FOnConvertAppointmentItemToEvent(AppointmentItem, AEvent);
|
|
end;
|
|
|
|
procedure TcxOutlookExchange.ConvertEventToAppointmentItem(
|
|
AEvent: TcxSchedulerEvent; const AppointmentItem: OleVariant);
|
|
begin
|
|
if Assigned(FOnConvertEventToAppointmentItem) then
|
|
FOnConvertEventToAppointmentItem(AEvent, AppointmentItem);
|
|
end;
|
|
|
|
procedure TcxOutlookExchange.ImportRecurrenceChain(
|
|
APatternEvent: TcxSchedulerEvent; const ARecurrencePattern: OleVariant);
|
|
const
|
|
ExceptionType: array[Boolean] of TcxEventType = (etCustom, etException);
|
|
var
|
|
I: Integer;
|
|
AException: OleVariant;
|
|
ADeleted: Boolean;
|
|
AOccurrence: TcxSchedulerEvent;
|
|
begin
|
|
for I := 1 to ARecurrencePattern.Exceptions.Count do
|
|
begin
|
|
AException := ARecurrencePattern.Exceptions.Item(I);
|
|
ADeleted := AException.Deleted;
|
|
if not ADeleted and not CanAcceptAppointmentItem(AException.AppointmentItem) then
|
|
continue;
|
|
AOccurrence := Storage.CreateOccurrence(APatternEvent,
|
|
AException.OriginalDate, ExceptionType[ADeleted]);
|
|
if not ADeleted then
|
|
begin
|
|
SetupEventInfo(AOccurrence, AException.AppointmentItem);
|
|
UpdateEvent(AOccurrence, AException.AppointmentItem);
|
|
end
|
|
else
|
|
PostRecurrenceExeption(AOccurrence);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxOutlookExchange.SetupEventRecurrenceInfo(AEvent: TcxSchedulerEvent;
|
|
const ARecurrencePattern: OleVariant);
|
|
var
|
|
AType, AInterval: Integer;
|
|
ADate: TDateTime;
|
|
begin
|
|
AEvent.EventType := etPattern;
|
|
ADate := ARecurrencePattern.PatternStartDate;
|
|
if not AEvent.AllDayEvent then
|
|
ADate := ADate + RoundTime(ARecurrencePattern.StartTime, False);
|
|
AEvent.RecurrenceInfo.Start := ADate;
|
|
if ARecurrencePattern.NoEndDate then
|
|
AEvent.RecurrenceInfo.Count := -1
|
|
else
|
|
begin
|
|
ADate := ARecurrencePattern.PatternEndDate;
|
|
if not AEvent.AllDayEvent then
|
|
ADate := ADate + RoundTime(ARecurrencePattern.EndTime, False);
|
|
AEvent.RecurrenceInfo.Finish := ADate;
|
|
AEvent.RecurrenceInfo.Count := ARecurrencePattern.Occurrences;
|
|
end;
|
|
AType := ARecurrencePattern.RecurrenceType;
|
|
case AType of
|
|
olRecursDaily:
|
|
begin
|
|
AEvent.RecurrenceInfo.Recurrence := cxreDaily;
|
|
AEvent.RecurrenceInfo.DayType := cxdtEveryDay;
|
|
AEvent.RecurrenceInfo.Periodicity := ARecurrencePattern.Interval;
|
|
end;
|
|
olRecursWeekly:
|
|
begin
|
|
AInterval := ARecurrencePattern.Interval;
|
|
if AInterval = 0 then
|
|
begin
|
|
AEvent.RecurrenceInfo.Recurrence := cxreDaily;
|
|
AEvent.RecurrenceInfo.DayType := cxdtWeekDay;
|
|
end
|
|
else
|
|
begin
|
|
AEvent.RecurrenceInfo.Recurrence := cxreWeekly;
|
|
AEvent.RecurrenceInfo.Periodicity := AInterval;
|
|
end;
|
|
AEvent.RecurrenceInfo.OccurDays :=
|
|
GetDaysOfWeekFromMask(ARecurrencePattern.DayOfWeekMask);
|
|
end;
|
|
olRecursMonthly:
|
|
begin
|
|
AEvent.RecurrenceInfo.DayType := cxdtDay;
|
|
AEvent.RecurrenceInfo.Recurrence := cxreMonthly;
|
|
AEvent.RecurrenceInfo.Periodicity := ARecurrencePattern.Interval;
|
|
AEvent.RecurrenceInfo.DayNumber := ARecurrencePattern.DayOfMonth
|
|
end;
|
|
olRecursMonthNth:
|
|
begin
|
|
AEvent.RecurrenceInfo.DayType := GetDayTypeFromMask(ARecurrencePattern.DayOfWeekMask);
|
|
AEvent.RecurrenceInfo.Recurrence := cxreMonthly;
|
|
AEvent.RecurrenceInfo.Periodicity := ARecurrencePattern.Interval;
|
|
AEvent.RecurrenceInfo.DayNumber := ARecurrencePattern.Instance;
|
|
end;
|
|
olRecursYearly:
|
|
begin
|
|
AEvent.RecurrenceInfo.DayType := cxdtDay;
|
|
AEvent.RecurrenceInfo.Recurrence := cxreYearly;
|
|
AEvent.RecurrenceInfo.Periodicity := ARecurrencePattern.MonthOfYear;
|
|
AEvent.RecurrenceInfo.DayNumber := ARecurrencePattern.DayOfMonth
|
|
end;
|
|
olRecursYearNth:
|
|
begin
|
|
AEvent.RecurrenceInfo.DayType := GetDayTypeFromMask(ARecurrencePattern.DayOfWeekMask);
|
|
AEvent.RecurrenceInfo.Recurrence := cxreYearly;
|
|
AEvent.RecurrenceInfo.Periodicity := ARecurrencePattern.MonthOfYear;
|
|
AEvent.RecurrenceInfo.DayNumber := ARecurrencePattern.Instance;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TcxOutlookExchange.GetIsValid: Boolean;
|
|
begin
|
|
Result := (FStorage <> nil) and FOleInitialized;
|
|
end;
|
|
|
|
{$HINTS OFF}
|
|
function TcxOutlookExchange.InitOleObject: Boolean;
|
|
var
|
|
ANameSpace: OleVariant;
|
|
begin
|
|
Result := False;
|
|
FWasCreated := False;
|
|
try
|
|
FOutlookApp := GetActiveOleObject(scxOutlookApp);
|
|
Result := True;
|
|
except
|
|
FOutlookApp := CreateOleObject(scxOutlookApp);
|
|
FWasCreated := True;
|
|
Result := True;
|
|
end;
|
|
if Result then
|
|
begin
|
|
ANameSpace := OutlookApp.GetNamespace(scxNameSpace);
|
|
FCalendarFolder := ANameSpace.GetDefaultFolder(olFolderCalendar);
|
|
end;
|
|
end;
|
|
{$HINTS ON}
|
|
|
|
procedure TcxOutlookExchange.PostRecurrenceExeption(
|
|
AOccurrence: TcxSchedulerEvent);
|
|
begin
|
|
AOccurrence.Post;
|
|
end;
|
|
|
|
function TcxOutlookExchange.RoundTime(ATime: TDateTime; ASaveDate: Boolean): TDateTime;
|
|
begin
|
|
if ASaveDate then
|
|
Result := DateTimeHelper.RoundTime(ATime)
|
|
else
|
|
Result := DateTimeHelper.RoundTime(TimeOf(ATime));
|
|
end;
|
|
|
|
procedure TcxOutlookExchange.UpdateAppointmentItem(
|
|
const AppointmentItem: OleVariant; AEvent: TcxSchedulerEvent);
|
|
begin
|
|
ConvertEventToAppointmentItem(AEvent, AppointmentItem);
|
|
try
|
|
AppointmentItem.Save;
|
|
except
|
|
end;
|
|
end;
|
|
|
|
procedure TcxOutlookExchange.UpdateEvent(AEvent: TcxSchedulerEvent;
|
|
const AppointmentItem: OleVariant; APostData: Boolean = True);
|
|
begin
|
|
ConvertAppointmentItemToEvent(AppointmentItem, AEvent);
|
|
if APostData then AEvent.Post;
|
|
end;
|
|
|
|
procedure TcxOutlookExchange.UpdateEventWithRecurrenceInfo(AEvent: TcxSchedulerEvent;
|
|
const AppointmentItem: OleVariant);
|
|
begin
|
|
AEvent.BeginEditing;
|
|
try
|
|
SetupEventRecurrenceInfo(AEvent, AppointmentItem.GetRecurrencePattern);
|
|
UpdateEvent(AEvent, AppointmentItem, False);
|
|
finally
|
|
AEvent.EndEditing;
|
|
end;
|
|
AEvent.Post;
|
|
end;
|
|
|
|
function TcxOutlookExchange.DoProgress(ACurrent, ACount: Integer): Boolean;
|
|
var
|
|
Abort: Boolean;
|
|
begin
|
|
Abort := False;
|
|
if Assigned(FOnProgress) then
|
|
FOnProgress(ACurrent, ACount, Abort);
|
|
Result := not Abort;
|
|
end;
|
|
|
|
procedure TcxOutlookExchange.CheckRecurrencePatternExceptions(
|
|
const ARecurrencePattern: OleVariant;
|
|
APatternEvent: TcxSchedulerEvent);
|
|
var
|
|
I: Integer;
|
|
AEvent: TcxSchedulerEvent;
|
|
AppointmentItem: OleVariant;
|
|
begin
|
|
with APatternEvent.GetRecurrenceChain do
|
|
try
|
|
for I := 0 to Count - 1 do
|
|
begin
|
|
AEvent := Items[I];
|
|
try
|
|
AppointmentItem := ARecurrencePattern.GetOccurrence(AEvent.GetOriginalDate);
|
|
if AEvent.EventType = etException then
|
|
AppointmentItem.Delete
|
|
else
|
|
if (AEvent.EventType = etCustom) and CanAcceptEvent(AEvent) then
|
|
begin
|
|
SetupAppointmentItemInfo(AppointmentItem, AEvent);
|
|
UpdateAppointmentItem(AppointmentItem, AEvent);
|
|
end;
|
|
except
|
|
end;
|
|
end;
|
|
finally
|
|
Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxOutlookExchange.ExportRecurrenceChain(
|
|
APatternEvent: TcxSchedulerEvent; const AppointmentItem: OleVariant);
|
|
var
|
|
ARecurrencePattern: OleVariant;
|
|
begin
|
|
if APatternEvent.EventType = etPattern then
|
|
begin
|
|
ARecurrencePattern := AppointmentItem.GetRecurrencePattern;
|
|
SetAppointmentItemRecurrence(ARecurrencePattern, APatternEvent);
|
|
UpdateAppointmentItem(AppointmentItem, APatternEvent);
|
|
CheckRecurrencePatternExceptions(ARecurrencePattern, APatternEvent);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxOutlookExchange.SetAppointmentItemRecurrence(
|
|
const ARecurrencePattern: OleVariant; AEvent: TcxSchedulerEvent);
|
|
begin
|
|
with AEvent.RecurrenceInfo do
|
|
begin
|
|
ARecurrencePattern.PatternStartDate := DateOf(AEvent.Start);
|
|
ARecurrencePattern.StartTime := RoundTime(AEvent.Start, False);
|
|
ARecurrencePattern.EndTime := RoundTime(AEvent.Finish, False);
|
|
case Recurrence of
|
|
cxreDaily:
|
|
begin
|
|
if DayType = cxdtEveryDay then
|
|
begin
|
|
ARecurrencePattern.RecurrenceType := olRecursDaily;
|
|
ARecurrencePattern.Interval := Periodicity;
|
|
end
|
|
else
|
|
if DayType = cxdtWeekDay then
|
|
begin
|
|
ARecurrencePattern.RecurrenceType := olRecursWeekly;
|
|
ARecurrencePattern.DayOfWeekMask := olWeekDay;
|
|
end;
|
|
end;
|
|
cxreWeekly:
|
|
begin
|
|
ARecurrencePattern.RecurrenceType := olRecursWeekly;
|
|
ARecurrencePattern.DayOfWeekMask := GetMaskFromDaysOfWeek(OccurDays);
|
|
ARecurrencePattern.Interval := Periodicity;
|
|
end;
|
|
cxreMonthly:
|
|
begin
|
|
if DayType = cxdtDay then
|
|
begin
|
|
ARecurrencePattern.RecurrenceType := olRecursMonthly;
|
|
ARecurrencePattern.DayOfMonth := DayNumber;
|
|
ARecurrencePattern.Interval := Periodicity;
|
|
end
|
|
else
|
|
begin
|
|
ARecurrencePattern.RecurrenceType := olRecursMonthNth;
|
|
ARecurrencePattern.Interval := Periodicity;
|
|
ARecurrencePattern.DayOfWeekMask := GetMaskFromDayType(DayType);
|
|
ARecurrencePattern.Instance := DayNumber;
|
|
end;
|
|
end;
|
|
cxreYearly:
|
|
begin
|
|
if DayType = cxdtDay then
|
|
begin
|
|
ARecurrencePattern.RecurrenceType := olRecursYearly;
|
|
ARecurrencePattern.DayOfMonth := DayNumber;
|
|
ARecurrencePattern.MonthOfYear := Periodicity;
|
|
end
|
|
else
|
|
begin
|
|
ARecurrencePattern.RecurrenceType := olRecursYearNth;
|
|
ARecurrencePattern.MonthOfYear := Periodicity;
|
|
ARecurrencePattern.DayOfWeekMask := GetMaskFromDayType(DayType);
|
|
ARecurrencePattern.Instance := DayNumber;
|
|
end;
|
|
end;
|
|
end;
|
|
if Count = -1 then
|
|
ARecurrencePattern.NoEndDate := True
|
|
else
|
|
if Count = 0 then
|
|
ARecurrencePattern.PatternEndDate := Finish
|
|
else
|
|
ARecurrencePattern.Occurrences := Count;
|
|
end;
|
|
end;
|
|
|
|
function TcxOutlookExchange.GetAllDayEvent(const AppointmentItem: OleVariant): Boolean;
|
|
var
|
|
ARecurrencePattern: OleVariant;
|
|
begin
|
|
Result := AppointmentItem.AllDayEvent;
|
|
if Result then
|
|
begin
|
|
if AppointmentItem.IsRecurring then
|
|
begin
|
|
ARecurrencePattern := AppointmentItem.GetRecurrencePattern;
|
|
if Integer(ARecurrencePattern.RecurrenceType) in
|
|
[olRecursMonthly, olRecursMonthNth, olRecursYearly, olRecursYearNth] then
|
|
begin
|
|
Result := (RoundTime(ARecurrencePattern.StartTime, False) = 0) and
|
|
(RoundTime(ARecurrencePattern.EndTime, False) = 0);
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TcxOutlookExchange.GetDaysOfWeekFromMask(AMask: Integer): TDays;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
Result := [];
|
|
for I := 0 to 6 do
|
|
if (1 shl I) and AMask <> 0 then
|
|
Include(Result, TDay(I));
|
|
end;
|
|
|
|
function TcxOutlookExchange.GetDayTypeFromMask(AMask: Integer): TcxDayType;
|
|
begin
|
|
case AMask of
|
|
olSunday : Result := cxdtSunday;
|
|
olMonday : Result := cxdtMonday;
|
|
olTuesday : Result := cxdtTuesday;
|
|
olWednesday : Result := cxdtWednesday;
|
|
olThursday: Result := cxdtThursday;
|
|
olFriday: Result := cxdtFriday;
|
|
olSaturday: Result := cxdtSaturday;
|
|
olWeekDay : Result := cxdtWeekDay;
|
|
olWeekEndDay: Result := cxdtWeekEndDay;
|
|
else
|
|
Result := cxdtEveryDay;
|
|
end;
|
|
end;
|
|
|
|
function TcxOutlookExchange.GetMaskFromDaysOfWeek(ADays: TDays): Integer;
|
|
var
|
|
I: TDay;
|
|
begin
|
|
Result := 0;
|
|
for I := dSunday to dSaturday do
|
|
if I in ADays then
|
|
Result := Result or (1 shl Ord(I));
|
|
end;
|
|
|
|
function TcxOutlookExchange.GetMaskFromDayType(ADayType: TcxDayType): Integer;
|
|
const
|
|
Masks: array[TcxDayType] of Byte = (olEveryDay, olEveryDay, olWeekDay,
|
|
olWeekEndDay, olSunday, olMonday, olTuesday, olWednesday, olThursday,
|
|
olFriday, olSaturday);
|
|
begin
|
|
Result := Masks[ADayType];
|
|
end;
|
|
|
|
{ TcxOutlookSynchronize }
|
|
|
|
procedure TcxOutlookSynchronize.SynchronizeWithOutlook(
|
|
ADeleteUnsynchronizedEvents: Boolean = False);
|
|
var
|
|
I, AIndex, ACount: Integer;
|
|
AppointmentItem: OleVariant;
|
|
AEvent: TcxSchedulerEvent;
|
|
AEntryIDs: TcxEventEntryIDList;
|
|
begin
|
|
if not IsValid then Exit;
|
|
AEntryIDs := TcxEventEntryIDList.Create;
|
|
try
|
|
AEntryIDs.Populate(Storage, EntryIDField);
|
|
ACount := CalendarFolder.Items.Count;
|
|
for I := 1 to ACount do
|
|
begin
|
|
AppointmentItem := CalendarFolder.Items(I);
|
|
if CanImportAppointmentItem(AppointmentItem) and CanAcceptAppointmentItem(AppointmentItem) then
|
|
begin
|
|
if AEntryIDs.FindEntryID(AppointmentItem.EntryID, AIndex) then
|
|
begin
|
|
AEvent := AEntryIDs.ExtractEvent(AIndex);
|
|
UpdateExistingEvent(AEvent, AppointmentItem, AEntryIDs);
|
|
end
|
|
else
|
|
ImportAppointmentItemFromOutlook(AppointmentItem);
|
|
end;
|
|
if not DoProgress(I, ACount) then
|
|
Exit;
|
|
Application.ProcessMessages;
|
|
end;
|
|
if ADeleteUnsynchronizedEvents then
|
|
DeleteUnsynchronizedEvents(AEntryIDs);
|
|
finally
|
|
AEntryIDs.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxOutlookSynchronize.SynchronizeWithStorage(
|
|
ADeleteUnsynchronizedAppointments: Boolean = False);
|
|
var
|
|
AppointmentItem: OleVariant;
|
|
AEntryIDs: TcxAppointmentEntryIDList;
|
|
AEvent: TcxSchedulerEvent;
|
|
I, AIndex, ACount: Integer;
|
|
begin
|
|
if not IsValid then Exit;
|
|
AEntryIDs := TcxAppointmentEntryIDList.Create;
|
|
try
|
|
AEntryIDs.Populate(CalendarFolder);
|
|
Storage.BeginUpdate;
|
|
try
|
|
ACount := Storage.EventCount;
|
|
for I := 0 to ACount - 1 do
|
|
begin
|
|
AEvent := Storage.Events[I];
|
|
if CanAcceptEvent(AEvent) then
|
|
begin
|
|
if AEntryIDs.FindEntryID(GetEntryIDFromEvent(AEvent), AIndex) then
|
|
begin
|
|
AppointmentItem := AEntryIDs.ExtractAppointmentItem(AIndex);
|
|
UpdateExistingAppointmentItem(AppointmentItem, AEvent);
|
|
end
|
|
else
|
|
ExportEventToOutlook(AEvent);
|
|
end;
|
|
if not DoProgress(I + 1, ACount) then
|
|
Exit;
|
|
Application.ProcessMessages;
|
|
end;
|
|
if ADeleteUnsynchronizedAppointments then
|
|
DeleteUnsynchronizedAppointments(AEntryIDs);
|
|
finally
|
|
Storage.EndUpdate;
|
|
end;
|
|
finally
|
|
AEntryIDs.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxOutlookSynchronize.UpdateAppointmentItem(
|
|
const AppointmentItem: OleVariant; AEvent: TcxSchedulerEvent);
|
|
var
|
|
AEntryID: OleVariant;
|
|
begin
|
|
ConvertEventToAppointmentItem(AEvent, AppointmentItem);
|
|
try
|
|
AppointmentItem.Save;
|
|
AEntryID := AppointmentItem.EntryID;
|
|
if not VarEqualsSoft(AEvent.GetCustomFieldValue(EntryIDField), AEntryID) then
|
|
begin
|
|
AEvent.SetCustomFieldValue(EntryIDField, AEntryID);
|
|
AEvent.Post;
|
|
end;
|
|
except
|
|
end;
|
|
end;
|
|
|
|
procedure TcxOutlookSynchronize.UpdateExistingAppointmentItem(
|
|
const AppointmentItem: OleVariant; AEvent: TcxSchedulerEvent);
|
|
begin
|
|
if AppointmentItem.IsRecurring then
|
|
AppointmentItem.ClearRecurrencePattern;
|
|
SetupAppointmentItemInfo(AppointmentItem, AEvent);
|
|
if AEvent.IsRecurring then
|
|
ExportRecurrenceChain(AEvent, AppointmentItem)
|
|
else
|
|
UpdateAppointmentItem(AppointmentItem, AEvent);
|
|
end;
|
|
|
|
procedure TcxOutlookSynchronize.SynchronizeRecurrenceChainWithOutlook(
|
|
APatternEvent: TcxSchedulerEvent;
|
|
const ARecurrencePattern: OleVariant;
|
|
AEntryIDs: TcxEventEntryIDList);
|
|
var
|
|
I, J: Integer;
|
|
AppointmentItem: OleVariant;
|
|
AException: OleVariant;
|
|
AOccurrence: TcxSchedulerEvent;
|
|
AOriginalDate: TDateTime;
|
|
ARecurrenceChain: TcxSchedulerEventList;
|
|
begin
|
|
PurgeDeletedOccurrences(APatternEvent, AEntryIDs);
|
|
ARecurrenceChain := APatternEvent.GetRecurrenceChain;
|
|
try
|
|
for I := 1 to ARecurrencePattern.Exceptions.Count do
|
|
begin
|
|
AException := ARecurrencePattern.Exceptions.Item(I);
|
|
AOriginalDate := DateOf(AException.OriginalDate);
|
|
AOccurrence := nil;
|
|
for J := 0 to ARecurrenceChain.Count - 1 do
|
|
begin
|
|
if DateOf(ARecurrenceChain[J].GetOriginalDate) = AOriginalDate then
|
|
begin
|
|
AOccurrence := ARecurrenceChain[J];
|
|
AEntryIDs.DeleteEvent(AOccurrence);
|
|
ARecurrenceChain.Delete(J);
|
|
break;
|
|
end;
|
|
end;
|
|
if not AException.Deleted then
|
|
begin
|
|
AppointmentItem := AException.AppointmentItem;
|
|
if not CanAcceptAppointmentItem(AppointmentItem) then
|
|
continue;
|
|
if AOccurrence = nil then
|
|
AOccurrence := Storage.CreateOccurrence(APatternEvent, AOriginalDate, etCustom);
|
|
SetupEventInfo(AOccurrence, AppointmentItem);
|
|
ConvertAppointmentItemToEvent(AppointmentItem, AOccurrence);
|
|
AOccurrence.Post;
|
|
end
|
|
else
|
|
begin
|
|
if AOccurrence = nil then
|
|
AOccurrence := APatternEvent.GetOccurrence(AOriginalDate);
|
|
if AOccurrence <> nil then
|
|
begin
|
|
AOccurrence.EventType := etException;
|
|
PostRecurrenceExeption(AOccurrence);
|
|
end;
|
|
end;
|
|
end;
|
|
for I := 0 to ARecurrenceChain.Count - 1 do
|
|
begin
|
|
AOccurrence := ARecurrenceChain[I];
|
|
AEntryIDs.DeleteEvent(AOccurrence);
|
|
AOccurrence.EventType := etNone;
|
|
AOccurrence.Delete;
|
|
end;
|
|
finally
|
|
ARecurrenceChain.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxOutlookSynchronize.UpdateExistingEvent(AEvent: TcxSchedulerEvent;
|
|
const AppointmentItem: OleVariant; AEntryIDs: TcxEventEntryIDList);
|
|
var
|
|
ARecurrencePattern: OleVariant;
|
|
begin
|
|
SetupEventInfo(AEvent, AppointmentItem);
|
|
if AppointmentItem.IsRecurring then
|
|
begin
|
|
ARecurrencePattern := AppointmentItem.GetRecurrencePattern;
|
|
if AEvent.IsRecurring then
|
|
begin
|
|
if not IsEqualRecurrencePattern(AppointmentItem, AEvent) then
|
|
AEvent.DeleteExceptions;
|
|
UpdateEventWithRecurrenceInfo(AEvent, AppointmentItem);
|
|
SynchronizeRecurrenceChainWithOutlook(AEvent, ARecurrencePattern, AEntryIDs);
|
|
end
|
|
else
|
|
begin
|
|
UpdateEventWithRecurrenceInfo(AEvent, AppointmentItem);
|
|
ImportRecurrenceChain(AEvent, AppointmentItem.GetRecurrencePattern);
|
|
end;
|
|
end
|
|
else
|
|
begin
|
|
AEvent.RemoveRecurrence;
|
|
UpdateEvent(AEvent, AppointmentItem);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxOutlookSynchronize.UpdateEvent(AEvent: TcxSchedulerEvent;
|
|
const AppointmentItem: OleVariant; APostData: Boolean = True);
|
|
var
|
|
AEntryID: string;
|
|
begin
|
|
if AEvent.EventType in [etPattern, etNone] then
|
|
AEntryID := AppointmentItem.EntryID
|
|
else
|
|
AEntryID := NullEntryID;
|
|
AEvent.SetCustomFieldValue(EntryIDField, AEntryID);
|
|
inherited UpdateEvent(AEvent, AppointmentItem, APostData);
|
|
end;
|
|
|
|
procedure TcxOutlookSynchronize.DeleteUnsynchronizedAppointments(
|
|
AEntryIDs: TcxAppointmentEntryIDList);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
for I := 0 to AEntryIDs.Count - 1 do
|
|
try
|
|
AEntryIDs[I].AppointmentItem.Delete;
|
|
except
|
|
end;
|
|
end;
|
|
|
|
procedure TcxOutlookSynchronize.DeleteUnsynchronizedEvents(
|
|
AEntryIDs: TcxEventEntryIDList);
|
|
var
|
|
I: Integer;
|
|
AEvent: TcxSchedulerEvent;
|
|
begin
|
|
Storage.BeginUpdate;
|
|
try
|
|
for I := 0 to AEntryIDs.Count - 1 do
|
|
begin
|
|
AEvent := AEntryIDs[I].Event;
|
|
AEvent.EventType := etNone;
|
|
AEvent.Delete;
|
|
end;
|
|
finally
|
|
Storage.EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
function TcxOutlookSynchronize.GetEntryIDFromEvent(
|
|
AEvent: TcxSchedulerEvent): string;
|
|
begin
|
|
Result := UpperCase(VarToStr(AEvent.GetCustomFieldValue(EntryIDField)))
|
|
end;
|
|
|
|
function TcxOutlookSynchronize.GetIsValid: Boolean;
|
|
begin
|
|
Result := inherited GetIsValid and (FEntryIDField <> nil)
|
|
end;
|
|
|
|
procedure TcxOutlookSynchronize.PostRecurrenceExeption(
|
|
AOccurrence: TcxSchedulerEvent);
|
|
begin
|
|
AOccurrence.SetCustomFieldValue(EntryIDField, NullEntryID);
|
|
AOccurrence.Post;
|
|
end;
|
|
|
|
procedure TcxOutlookSynchronize.PurgeDeletedOccurrences(
|
|
APatternEvent: TcxSchedulerEvent; AEntryIDs: TcxEventEntryIDList);
|
|
var
|
|
AEvent: TcxSchedulerEvent;
|
|
L: TcxSchedulerEventList;
|
|
I: Integer;
|
|
begin
|
|
Storage.BeginUpdate;
|
|
try
|
|
L := APatternEvent.GetRecurrenceChain;
|
|
try
|
|
for I := 0 to L.Count - 1 do
|
|
begin
|
|
AEvent := L[I];
|
|
if AEvent.EventType = etException then
|
|
begin
|
|
AEntryIDs.DeleteEvent(AEvent);
|
|
AEvent.Delete;
|
|
end;
|
|
end;
|
|
finally
|
|
L.Free;
|
|
end;
|
|
finally
|
|
Storage.EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
function TcxOutlookSynchronize.IsEqualRecurrencePattern(
|
|
const AppointmentItem: OleVariant; AEvent: TcxSchedulerEvent): Boolean;
|
|
var
|
|
ARecurrencePattern: OleVariant;
|
|
begin
|
|
with AEvent do
|
|
begin
|
|
Result := (AllDayEvent = GetAllDayEvent(AppointmentItem)) and
|
|
(RoundTime(Start, True) = RoundTime(AppointmentItem.Start, True)) and
|
|
(RoundTime(Finish, True) = RoundTime(AppointmentItem.End, True));
|
|
end;
|
|
if Result then
|
|
begin
|
|
ARecurrencePattern := AppointmentItem.GetRecurrencePattern;
|
|
with AEvent.RecurrenceInfo do
|
|
begin
|
|
Result := (ARecurrencePattern.PatternStartDate = DateOf(AEvent.Start)) and
|
|
(RoundTime(ARecurrencePattern.StartTime, False) = RoundTime(AEvent.Start, False)) and
|
|
(RoundTime(ARecurrencePattern.EndTime, False) = RoundTime(AEvent.Finish, False));
|
|
if not Result then Exit;
|
|
case Recurrence of
|
|
cxreDaily:
|
|
if DayType = cxdtEveryDay then
|
|
Result := (ARecurrencePattern.RecurrenceType = olRecursDaily) and
|
|
(ARecurrencePattern.Interval = Periodicity)
|
|
else
|
|
if DayType = cxdtWeekDay then
|
|
Result := (ARecurrencePattern.RecurrenceType = olRecursWeekly) and
|
|
(ARecurrencePattern.DayOfWeekMask = olWeekDay)
|
|
else
|
|
Result := False; //unknown status
|
|
cxreWeekly:
|
|
Result := (ARecurrencePattern.RecurrenceType = olRecursWeekly) and
|
|
(ARecurrencePattern.DayOfWeekMask = GetMaskFromDaysOfWeek(OccurDays)) and
|
|
(ARecurrencePattern.Interval = Periodicity);
|
|
cxreMonthly:
|
|
if DayType = cxdtDay then
|
|
Result := (ARecurrencePattern.RecurrenceType = olRecursMonthly) and
|
|
(ARecurrencePattern.DayOfMonth = DayNumber) and
|
|
(ARecurrencePattern.Interval = Periodicity)
|
|
else
|
|
Result := (ARecurrencePattern.RecurrenceType = olRecursMonthNth) and
|
|
(ARecurrencePattern.Interval = Periodicity) and
|
|
(ARecurrencePattern.DayOfWeekMask = GetMaskFromDayType(DayType)) and
|
|
(ARecurrencePattern.Instance = DayNumber);
|
|
cxreYearly:
|
|
if DayType = cxdtDay then
|
|
Result := (ARecurrencePattern.RecurrenceType = olRecursYearly) and
|
|
(ARecurrencePattern.DayOfMonth = DayNumber) and
|
|
(ARecurrencePattern.MonthOfYear = Periodicity)
|
|
else
|
|
Result := (ARecurrencePattern.RecurrenceType = olRecursYearNth) and
|
|
(ARecurrencePattern.MonthOfYear = Periodicity) and
|
|
(ARecurrencePattern.DayOfWeekMask = GetMaskFromDayType(DayType)) and
|
|
(ARecurrencePattern.Instance = DayNumber);
|
|
end;
|
|
if Result then
|
|
begin
|
|
if Count = -1 then
|
|
Result := ARecurrencePattern.NoEndDate
|
|
else
|
|
if Count = 0 then
|
|
Result := (ARecurrencePattern.PatternEndDate = DateOf(Finish))
|
|
else
|
|
Result := (ARecurrencePattern.Occurrences = Count);
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
//moved to the end because a bug in the delphi parser
|
|
|
|
procedure TcxOutlookExchange.SetupAppointmentItemInfo(const AppointmentItem: OleVariant;
|
|
const AEvent: TcxSchedulerEvent; ASetTime: Boolean = True);
|
|
var
|
|
AControlEvent: TcxSchedulerControlEvent;
|
|
begin
|
|
AControlEvent := TcxSchedulerControlEvent.Create(AEvent);
|
|
try
|
|
with AControlEvent do
|
|
begin
|
|
if AEvent.EventType = etCustom then
|
|
Pattern := AEvent.Pattern
|
|
else
|
|
Pattern := nil;
|
|
if ASetTime then
|
|
begin
|
|
AppointmentItem.AllDayEvent := AllDayEvent;
|
|
AppointmentItem.Start := Start;
|
|
AppointmentItem.End := Finish;
|
|
end;
|
|
AppointmentItem.Subject := Caption;
|
|
AppointmentItem.Body := Message;
|
|
AppointmentItem.BusyStatus := State;
|
|
AppointmentItem.Location := Location;
|
|
AppointmentItem.ReminderSet := Reminder;
|
|
if Reminder then
|
|
AppointmentItem.ReminderMinutesBeforeStart := ReminderMinutesBeforeStart;
|
|
end;
|
|
finally
|
|
AControlEvent.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxOutlookExchange.SetupEventInfo(AEvent: TcxSchedulerEvent;
|
|
const AppointmentItem: OleVariant);
|
|
begin
|
|
with AEvent do
|
|
begin
|
|
BeginEditing;
|
|
try
|
|
AllDayEvent := GetAllDayEvent(AppointmentItem);
|
|
Start := AppointmentItem.Start;
|
|
Finish := AppointmentItem.End;
|
|
Caption := AppointmentItem.Subject;
|
|
Message := AppointmentItem.Body;
|
|
State := AppointmentItem.BusyStatus;
|
|
Location := AppointmentItem.Location;
|
|
Reminder := AppointmentItem.ReminderSet;
|
|
if Reminder then
|
|
ReminderMinutesBeforeStart := AppointmentItem.ReminderMinutesBeforeStart;
|
|
finally
|
|
EndEditing;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
// import/export/synchronization
|
|
|
|
procedure cxSchedulerExportToOutlook(AStorage: TcxCustomSchedulerStorage;
|
|
AcceptFunc: TcxAcceptEventExportFunc = nil;
|
|
AConvertProc: TcxEventToAppointmentItemProc = nil;
|
|
AProgressProc: TcxSchedulerExchangeProgressProc = nil);
|
|
begin
|
|
with TcxOutlookExchange.Create(AStorage) do
|
|
try
|
|
OnAcceptEvent := AcceptFunc;
|
|
OnConvertEventToAppointmentItem := AConvertProc;
|
|
OnProgress := AProgressProc;
|
|
ExportToOutlook;
|
|
finally
|
|
Free;
|
|
end;
|
|
end;
|
|
|
|
procedure cxSchedulerImportFromOutlook(AStorage: TcxCustomSchedulerStorage;
|
|
AcceptFunc: TcxAcceptAppointmentItemImportFunc = nil;
|
|
AConvertProc: TcxAppointmentItemToEventProc = nil;
|
|
AProgressProc: TcxSchedulerExchangeProgressProc = nil);
|
|
begin
|
|
with TcxOutlookExchange.Create(AStorage) do
|
|
try
|
|
OnAcceptAppointmentItem := AcceptFunc;
|
|
OnConvertAppointmentItemToEvent := AConvertProc;
|
|
OnProgress := AProgressProc;
|
|
ImportFromOutlook;
|
|
finally
|
|
Free;
|
|
end;
|
|
end;
|
|
|
|
procedure cxSchedulerSynchronizeOutlookWithStorage(AStorage: TcxCustomSchedulerStorage;
|
|
AppointmentItemIDField: TcxCustomSchedulerStorageField;
|
|
ADeleteUnsynchronizedAppointments: Boolean = False;
|
|
AcceptFunc: TcxAcceptEventExportFunc = nil;
|
|
AConvertProc: TcxEventToAppointmentItemProc = nil;
|
|
AProgressProc: TcxSchedulerExchangeProgressProc = nil);
|
|
begin
|
|
with TcxOutlookSynchronize.Create(AStorage) do
|
|
try
|
|
EntryIDField := AppointmentItemIDField;
|
|
OnAcceptEvent := AcceptFunc;
|
|
OnConvertEventToAppointmentItem := AConvertProc;
|
|
OnProgress := AProgressProc;
|
|
SynchronizeWithStorage(ADeleteUnsynchronizedAppointments);
|
|
finally
|
|
Free;
|
|
end;
|
|
end;
|
|
|
|
procedure cxSchedulerSynchronizeStorageWithOutlook(AStorage: TcxCustomSchedulerStorage;
|
|
AppointmentItemIDField: TcxCustomSchedulerStorageField;
|
|
ADeleteUnsynchronizedEvents: Boolean = False;
|
|
AcceptFunc: TcxAcceptAppointmentItemImportFunc = nil;
|
|
AConvertProc: TcxAppointmentItemToEventProc = nil;
|
|
AProgressProc: TcxSchedulerExchangeProgressProc = nil);
|
|
begin
|
|
with TcxOutlookSynchronize.Create(AStorage) do
|
|
try
|
|
EntryIDField := AppointmentItemIDField;
|
|
OnAcceptAppointmentItem := AcceptFunc;
|
|
OnConvertAppointmentItemToEvent := AConvertProc;
|
|
OnProgress := AProgressProc;
|
|
SynchronizeWithOutlook(ADeleteUnsynchronizedEvents);
|
|
finally
|
|
Free;
|
|
end;
|
|
end;
|
|
|
|
end.
|