unit uDAReconcileDialog; {----------------------------------------------------------------------------} { Data Abstract Library - Core Library } { } { compiler: Delphi 6 and up, Kylix 3 and up } { platform: Win32, Linux } { } { (c)opyright RemObjects Software. all rights reserved. } { } { Using this code requires a valid license of the Data Abstract } { which can be obtained at http://www.remobjects.com. } {----------------------------------------------------------------------------} {$I DataAbstract.inc} interface uses Windows, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, uDADelta, uDADatatable, ComCtrls, {$IFDEF FPC} buttons,LResources,{$ENDIF} uDARemoteDataAdapter, ImgList; type TReconcileDialogForm = class(TForm) SkipButton: TButton; CancelButton: TButton; SkipAllButton: TButton; CancelAllButton: TButton; ShowDetailButton: TButton; lMessageError: TLabel; TreeView: TTreeView; ImageList: TImageList; Label1: TLabel; Label2: TLabel; Label3: TLabel; btn_Cancel: TButton; procedure SkipButtonClick(Sender: TObject); procedure CancelButtonClick(Sender: TObject); procedure SkipAllButtonClick(Sender: TObject); procedure CancelAllButtonClick(Sender: TObject); procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure ShowDetailButtonClick(Sender: TObject); procedure ListBoxClick(Sender: TObject); private { Private declarations } ChangeList: TList; TableList: TList; RDA: TDARemoteDataAdapter; procedure CancelChange(aNode: TTreeNode); procedure SkipChange(aNode: TTreeNode); procedure SkipAllChanges; procedure CancelAllChanges; procedure Setup; function FindDatatable(ADelta: IDADelta): TDADatatable; procedure DeleteNodeFromTreeView(aNode: TTreeNode); end; var ReconcileDialogForm: TReconcileDialogForm; procedure ReconcileDialog(RemoteDataAdapter: TDARemoteDataAdapter; var AFailedDeltaList: TList; aTableList: TList); implementation uses uDAReconcileDialogDetails, uDAInterfaces; {$IFNDEF FPC} {$R *.dfm} {$ENDIF} procedure ReconcileDialog(RemoteDataAdapter: TDARemoteDataAdapter; var AFailedDeltaList: TList; aTableList: TList); begin with TReconcileDialogForm.Create(Application) do try RDA:=RemoteDataAdapter; ChangeList.Assign(AFailedDeltaList); TableList.Assign(aTableList); Setup; ShowModal; AFailedDeltaList.Assign(ChangeList); finally Release; end; end; procedure TReconcileDialogForm.SkipButtonClick(Sender: TObject); begin SkipChange(TreeView.Selected); end; procedure TReconcileDialogForm.CancelButtonClick(Sender: TObject); begin CancelChange(TreeView.Selected); end; procedure TReconcileDialogForm.SkipAllButtonClick(Sender: TObject); begin SkipAllChanges; end; procedure TReconcileDialogForm.CancelAllButtonClick(Sender: TObject); begin CancelAllChanges; end; procedure TReconcileDialogForm.CancelAllChanges; begin if Application.MessageBox('Do you want cancel all changes?', 'Cancel All', MB_YESNO) = IDYES then begin while TreeView.Items.Count > 0 do CancelChange(TreeView.Items[0]); ModalResult := mrOk; end; end; procedure TReconcileDialogForm.SkipAllChanges; begin if Application.MessageBox('Do you want skip all changes?', 'Skip All', MB_YESNO) = IDYES then ModalResult := mrOk; end; procedure TReconcileDialogForm.FormCreate(Sender: TObject); begin inherited; ChangeList := TList.Create; TableList := TList.Create; end; procedure TReconcileDialogForm.FormDestroy(Sender: TObject); begin ChangeList.Free; TableList.Free; inherited; end; procedure TReconcileDialogForm.ShowDetailButtonClick(Sender: TObject); var lChange: TDADeltaChange; lHandled: Boolean; lAction: TDAReconcileDialogAction; begin lChange := TDADeltaChange(Treeview.Selected.Data); Hide; try lAction:= rdlgNone; lHandled:=False; if Assigned(rda) and Assigned(rda.OnShowReconcileRecordInAppUI) then rda.OnShowReconcileRecordInAppUI(RDA, lChange, FindDatatable(lChange.Delta),lHandled,lAction); if not lHandled then ReconcileDialogShowDetails(lChange, FindDatatable(lChange.Delta), Treeview.Selected.Text, lAction); finally Show; end; if lAction = rdlgSkip then SkipButton.Click else if lAction = rdlgCancel then CancelButton.Click; end; procedure TReconcileDialogForm.Setup; var i, j: integer; change: TDADeltaChange; anode: TTreeNode; s: string; begin TreeView.Items.Clear; for i := 0 to ChangeList.Count - 1 do begin change := TDADeltaChange(ChangeList[i]); s := change.Delta.LogicalName + ':'; for j := 0 to change.Delta.KeyFieldCount - 1 do begin if j > 0 then s := s + ';'; if change.ChangeType = ctDelete then s := s + VarToStr(change.OldValueByName[change.Delta.KeyFieldNames[j]]) else s := s + VarToStr(change.NewValueByName[change.Delta.KeyFieldNames[j]]); end; anode := TreeView.Items.AddChildObject(nil, s, Change); case Change.ChangeType of ctInsert: aNode.StateIndex := 2; ctUpdate: aNode.StateIndex := 3; ctDelete: aNode.StateIndex := 4; end; end; if TreeView.Items.Count > 0 then begin TreeView.Items[0].Selected := True; ListBoxClick(TreeView); end; end; procedure TReconcileDialogForm.CancelChange(aNode: TTreeNode); procedure DeleteChangeFromTreeView(aChange: TDADeltaChange); var i: integer; begin for i := TreeView.Items.Count - 1 downto 0 do if TreeView.Items[i].Data = aChange then begin TreeView.Items[i].Delete; Break; end; end; var lTable: TDADatatable; details: TList; detailChange: TDADeltaChange; i, j, k: integer; ChangePKValueArray: array of Variant; lNeedDeleteChange: boolean; keyvalue: variant; aChange: TDADeltaChange; begin aChange := TDADeltaChange(ANode.Data); if aChange <> nil then begin ChangeList.Remove(aChange); lTable := FindDatatable(aChange.Delta); if lTable <> nil then begin // remove changes for detail tables details := lTable.GetDetailTablesforApplyUpdate; try if Details.Count > 0 then begin SetLength(ChangePKValueArray, aChange.Delta.KeyFieldCount); for i := 1 to aChange.Delta.KeyFieldCount do begin if aChange.ChangeType = ctInsert then keyvalue := aChange.NewValueByName[aChange.Delta.KeyFieldNames[i - 1]] else keyvalue := aChange.OldValueByName[aChange.Delta.KeyFieldNames[i - 1]]; ChangePKValueArray[0] := keyvalue; end; for i := 0 to details.Count - 1 do begin for j := 0 to TDADataTable(details[i]).Delta.Count - 1 do begin detailChange := TDADataTable(details[i]).Delta.Changes[j]; if detailChange.Status <> csResolved then begin lNeedDeleteChange := True; for k := 0 to aChange.Delta.KeyFieldCount - 1 do begin if detailChange.ChangeType = ctInsert then keyvalue := detailChange.NewValueByName[aChange.Delta.KeyFieldNames[k]] else keyvalue := detailChange.oldValueByName[aChange.Delta.KeyFieldNames[k]]; if not VarSameValue(keyValue, ChangePKValueArray[k]) then begin lNeedDeleteChange := False; Break; end; end; if lNeedDeleteChange then DeleteChangeFromTreeView(detailChange); end; end; end; end; finally details.Free; end; DeleteNodeFromTreeView(aNode); lTable.CancelUpdateChange(aChange); end; end; if Treeview.Items.Count = 0 then ModalResult := MrOk; end; procedure TReconcileDialogForm.SkipChange(aNode: TTreeNode); begin DeleteNodeFromTreeView(ANode); if Treeview.Items.Count = 0 then ModalResult := MrOk; end; procedure TReconcileDialogForm.ListBoxClick(Sender: TObject); var s: string; change: TDADeltaChange; i: integer; begin if Treeview.Selected <> nil then begin change := TDADeltaChange(Treeview.Selected.Data); s := 'A problem occured while '; case change.ChangeType of ctInsert: s := s + 'inserting'; ctUpdate: s := s + 'updating'; ctDelete: s := s + 'deleting'; end; s := s + ' a record in table "' + change.Delta.LogicalName + '", record "'; for i := 1 to Change.Delta.KeyFieldCount do begin if i <> 1 then s := s + ';'; if Change.ChangeType = ctInsert then s := s + VarToStr(Change.NewValueByName[Change.Delta.KeyFieldNames[i - 1]]) else s := s + VarToStr(Change.OldValueByName[Change.Delta.KeyFieldNames[i - 1]]); end; s := s + '"'+ sLineBreak + sLineBreak + change.Message; if Assigned(RDA) and Assigned(RDA.OnGenerateRecordMessage) then RDA.OnGenerateRecordMessage(RDA, change,FindDatatable(change.Delta),s); lMessageError.Caption:=s; end; end; function TReconcileDialogForm.FindDatatable(ADelta: IDADelta): TDADatatable; var i: integer; begin Result := nil; for i := 0 to TableList.Count - 1 do if AnsiSameText(ADelta.LogicalName, TDADatatable(TableList[i]).LogicalName) then begin Result := TDADatatable(TableList[i]); Break; end; end; procedure TReconcileDialogForm.DeleteNodeFromTreeView(aNode: TTreeNode); begin aNode.Delete; ListBoxClick(TreeView); end; {$IFDEF FPC} initialization {$I uDAReconcileDialog.lrs} {$ENDIF} end.