unit VisZctaConfig;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, DB, FIBDataSet, pFIBDataSet, FIBDatabase, pFIBDatabase, Grids,
  DBGridEh, Buttons, ExtCtrls, ToolWin, ActnMan, ActnCtrls, ActnList,
  XPStyleActnCtrls, StdCtrls, VisZcta, GridsEh, ComCtrls, FIBQuery,
  pFIBQuery, DBCtrls, ImgList, DBCtrlsEh, Mask;

type
  TVisZctaConfigForm = class(TForm)
    db1: TpFIBDatabase;
    trn1: TpFIBTransaction;
    trn2: TpFIBTransaction;
    pFIBTransaction1: TpFIBTransaction;
    ds2: TpFIBDataSet;
    pFIBTransaction2: TpFIBTransaction;
    Panel1: TPanel;
    ActionManager1: TActionManager;
    acAdd1: TAction;
    acDel1: TAction;
    acPost1: TAction;
    acRefresh1: TAction;
    acAdd2: TAction;
    acDel2: TAction;
    acPost2: TAction;
    Button2: TButton;
    acUp: TAction;
    acDown: TAction;
    ds2ID: TFIBIntegerField;
    ds2ADDR: TFIBIntegerField;
    ds2DEVTYPE: TFIBstringField;
    ds2NAME: TFIBstringField;
    ds2TAGNAME: TFIBstringField;
    ds2DATA: TMemoField;
    PageControl1: TPageControl;
    TabSheet1: TTabSheet;
    Splitter2: TSplitter;
    Panel5: TPanel;
    gridCurM: TDBGridEh;
    ActionToolBar3: TActionToolBar;
    Panel6: TPanel;
    ActionToolBar4: TActionToolBar;
    pFIBQuery1: TpFIBQuery;
    acCurAdd: TAction;
    acCurDel: TAction;
    acCurSet: TAction;
    acCurRefresh: TAction;
    acCurEdit: TAction;
    ImageList1: TImageList;
    acCheck: TAction;
    acReset: TAction;
    pnlHand: TPanel;
    gridCurD: TDBGridEh;
    ActionToolBar5: TActionToolBar;
    acHandAdd: TAction;
    acHandDel: TAction;
    acHandUp: TAction;
    acHandDown: TAction;
    acHandPost: TAction;
    Panel8: TPanel;
    Label2: TLabel;
    Label6: TLabel;
    Label9: TLabel;
    pFIBTransaction5: TpFIBTransaction;
    pFIBTransaction6: TpFIBTransaction;
    dsCurM: TpFIBDataSet;
    dsrcCurM: TDataSource;
    dsCurMID: TFIBIntegerField;
    dsCurMCODE: TFIBIntegerField;
    dsCurMNAME: TFIBstringField;
    dsCurMLAST_DEVICE_ID: TFIBIntegerField;
    dsCurMDESCR: TFIBstringField;
    dsCurMDLY_ALARM: TFIBSmallIntField;
    dsCurMDLY_STOPFLOW: TFIBSmallIntField;
    dsCurMDLY_STOPROUT: TFIBSmallIntField;
    dsCurMSTEPSIZE: TFIBSmallIntField;
    dsCurMSTEPTIME: TFIBSmallIntField;
    pFIBTransaction8: TpFIBTransaction;
    pFIBTransaction7: TpFIBTransaction;
    dsCurD: TpFIBDataSet;
    dsrcCurD: TDataSource;
    dsCurDID: TFIBIntegerField;
    dsCurDROUT_ID: TFIBIntegerField;
    dsCurDDEVICE_ID: TFIBIntegerField;
    dsCurDORDERNUM: TFIBIntegerField;
    dsCurDFL_ALARM: TFIBSmallIntField;
    dsCurDFL_STOPFLOW: TFIBSmallIntField;
    dsCurDFL_STOPROUT: TFIBSmallIntField;
    dsCurDDNAME: TStringField;
    pFIBTransaction3: TpFIBTransaction;
    pFIBTransaction4: TpFIBTransaction;
    ds2_DevDirs: TpFIBDataSet;
    dsrcDs2: TDataSource;
    ds2_DevDirsID: TFIBIntegerField;
    ds2_DevDirsDEVICE_ID: TFIBIntegerField;
    ds2_DevDirsDIRNAME: TFIBstringField;
    ds2_DevDirsDIRNUM: TFIBSmallIntField;
    pFIBTransaction9: TpFIBTransaction;
    pFIBTransaction10: TpFIBTransaction;
    dsDEVDIRS: TpFIBDataSet;
    dsrcDEVDIRS: TDataSource;
    dsDEVDIRSID: TFIBIntegerField;
    dsDEVDIRSDEVICE_ID: TFIBIntegerField;
    dsDEVDIRSDIRNAME: TFIBstringField;
    dsDEVDIRSDIRNUM: TFIBSmallIntField;
    dsCurDDIR_ID: TFIBIntegerField;
    dsCurDDIRNAME: TStringField;
    pFIBTransaction11: TpFIBTransaction;
    pFIBTransaction12: TpFIBTransaction;
    dsDEVDIRS_list: TpFIBDataSet;
    FIBIntegerField1: TFIBIntegerField;
    FIBIntegerField2: TFIBIntegerField;
    FIBstringField1: TFIBstringField;
    FIBSmallIntField1: TFIBSmallIntField;
    dsrcDEVDIRS_list: TDataSource;
    DBNumberEditEh1: TDBNumberEditEh;
    DBNumberEditEh2: TDBNumberEditEh;
    DBNumberEditEh3: TDBNumberEditEh;
    Label1: TLabel;
    DBNumberEditEh4: TDBNumberEditEh;
    DBNumberEditEh5: TDBNumberEditEh;
    Label3: TLabel;
    Label4: TLabel;
    dsCurDDADDR: TIntegerField;
    dsCurDDDEVTYPE: TStringField;
    dsCurDDIR_NUM: TIntegerField;
    dsCurDDIR_NUMNAME: TStringField;
    dsDEVDIRSDIRNUMNAME: TFIBstringField;
    dsCurDDTAGNAME: TStringField;
    procedure Button1Click(Sender: TObject);
    procedure acUpDownExecute(Sender: TObject);
    procedure dsrcMStateChange(Sender: TObject);
    procedure dsrcDStateChange(Sender: TObject);
    procedure dsDBeforePost(DataSet: TDataSet);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure Button2Click(Sender: TObject);
    procedure acCurRefreshExecute(Sender: TObject);
    procedure acCurSetExecute(Sender: TObject);
    procedure acCurAddExecute(Sender: TObject);
    procedure acCheckExecute(Sender: TObject);
    procedure acCurDelExecute(Sender: TObject);
    procedure acResetExecute(Sender: TObject);
    function SetAndCheck(OnlyCheck: boolean): boolean;
    procedure acHandAddExecute(Sender: TObject);
    procedure acHandDelExecute(Sender: TObject);
    procedure acHandPostExecute(Sender: TObject);
    procedure grid1SortMarkingChanged(Sender: TObject);
    procedure gridApplyFilter(Sender: TObject);
    procedure FormDeactivate(Sender: TObject);
    procedure dsrcCurMStateChange(Sender: TObject);
    procedure dsrcCurDDataChange(Sender: TObject; Field: TField);
    procedure dsCurDAfterPost(DataSet: TDataSet);
    procedure dsCurDAfterInsert(DataSet: TDataSet);
    procedure dsCurDBeforePost(DataSet: TDataSet);
  private

    procedure UpdateList(Sender: TObject);
  public
    FilterAdd, FilterDel: string;
    M: TVisZcta;
    procedure GetZdvaItems;
  end;

  function VisZctaConfigFormCreate(M: TVisZcta; dbname: string): boolean;
  procedure VisZctaConfigFormFree;
  procedure VisZctaOpenDatasets;
  procedure VisZctaOpenDevices(AFilterAdd, AFilterDel: string);
  procedure VisZctaLoadRootName(M: TVisZcta; ACode: integer);


  procedure update_dataset(dsrc: array of TDataSource);

var
  VisZctaConfigForm: TVisZctaConfigForm;

implementation
uses
  infodlg,
  InputDialog,
  VisZctaCheck,
  rpVisualParams,
  users,
  Status,
  rpSysUtils,
  VisSeqcDBCheck,
  tagstorage,
  numbers,
  ScadaBase,
  RpVisualGlobal,
  RpVisualLegacyPanels,
  RpVisualUtils,
  RpVisualMain;


{$R *.dfm}


function VisZctaConfigFormCreate(M: TVisZcta; dbname: string): boolean;
var
  edit_access: boolean;
begin
  if VisZctaConfigForm=nil then
    VisZctaConfigForm := TVisZctaConfigForm.Create(nil)
  else
    VisZctaConfigForm.WindowState := wsNormal;

  edit_access := CheckAccess(PREVILEG_SEQC_EDIT2, false);
  VisZctaConfigForm.acCurAdd.Enabled := edit_access;
  VisZctaConfigForm.acCurDel.Enabled := edit_access;
  VisZctaConfigForm.acCurEdit.Enabled := edit_access;

  try
    VisZctaConfigForm.M := M;
    with VisZctaConfigForm do begin

      if (db1.Connected) and (DBName <> dbname) then
        db1.Connected := false;

      if not db1.Connected then begin
        db1.DBName := dbname;
        db1.Connected := true;
        CheckDatabase(pFIBQuery1);
        Check_ZCTA_DEVDIRS(VisZctaConfigForm);
      end;
    end;
    result := true;
  except
    result := false;
  end;
end;

procedure VisZctaConfigFormFree;
begin
  if VisZctaConfigForm<>nil then begin

    if VisZctaConfigForm.db1.Connected then
        VisZctaConfigForm.db1.Connected := false;

    VisZctaConfigForm.Free;
  end;

  VisZctaConfigForm := nil;
end;


procedure VisZctaOpenDatasets;
begin
  VisZctaConfigForm.dsCurM.Open;
  VisZctaConfigForm.dsCurD.Open;
end;


procedure VisZctaOpenDevices(AFilterAdd, AFilterDel: string);
begin

  VisZctaConfigForm.FilterAdd := AFilterAdd;
  VisZctaConfigForm.FilterDel := AFilterDel;
  VisZctaConfigForm.ds2.Open;
  
end;


procedure TVisZctaConfigForm.Button1Click(Sender: TObject);
begin
  close;
end;

procedure update_dataset(dsrc: array of TDataSource);
var
  n,i: integer;
  id: array of integer;
begin
  try
    n := length(dsrc);
    if n=0 then exit;

    SetLength(id, n);

    for i:=0 to n-1 do
      id[i] := dsrc[i].DataSet.fieldbyname('ID').AsInteger;

    for i:=0 to n-1 do
      dsrc[i].Enabled := false;

    dsrc[0].DataSet.Close;
    dsrc[0].DataSet.Open;

    for i:=0 to n-1 do
      dsrc[i].DataSet.Locate('ID', id[i], []);

    for i:=0 to n-1 do
      dsrc[i].Enabled := true;
  except
  end;
end;


procedure TVisZctaConfigForm.acUpDownExecute(Sender: TObject);
var
  id1, id2, ordernum1, ordernum2: integer;
  ds: TpFIBDataSet;
  dsrc: TDataSource;
begin

  ds := dsCurD;
  dsrc := dsrcCurD;

  try
    id1 := ds.fieldByName('ID').AsInteger;
    ordernum1 := ds.fieldByName('ORDERNUM').AsInteger;

    if (Sender = acHandUp) then
      ds.Prior
    else
      ds.Next;

    id2 := ds.fieldByName('ID').AsInteger;
    ordernum2 := ds.fieldByName('ORDERNUM').AsInteger;

    if (id1>0) and (id2>0) and (id1<>id2) then begin
      ds.Edit;
      ds.fieldByName('ORDERNUM').AsInteger := ordernum1;
      ds.Post;

      if (Sender = acUp) or (Sender = acHandUp) then
        ds.Next
      else
        ds.Prior;

      ds.Edit;
      ds.fieldByName('ORDERNUM').AsInteger := ordernum2;
      ds.Post;

    end;

    update_dataset([dsrc]);
  except
  end;

end;

procedure TVisZctaConfigForm.dsrcMStateChange(Sender: TObject);
begin
{
  acPost1.Enabled := dsM.State in [dsEdit, dsInsert];
  ActionToolBar2.Enabled := not acPost1.Enabled;
  grid2.Enabled := not acPost1.Enabled;
}
end;

procedure TVisZctaConfigForm.dsrcDStateChange(Sender: TObject);
begin
{
  acPost2.Enabled := dsD.State in [dsEdit, dsInsert];
}
end;

procedure TVisZctaConfigForm.dsDBeforePost(DataSet: TDataSet);
begin
{
  if DataSet.FieldByName('TIMESTART').IsNull then
    DataSet.FieldByName('TIMESTART').AsInteger := 5;

  if DataSet.FieldByName('TIMESTOP').IsNull then
    DataSet.FieldByName('TIMESTOP').AsInteger := 5;
}
end;



////////////////////////////////////////////////////////////////////////////////
procedure TVisZctaConfigForm.acCurSetExecute(Sender: TObject);
begin

  OnDeactivate := nil;
  if not SetAndCheck(false) then
    ShowMessage('Установка данных не выполнена')
  else
    close;
  OnDeactivate := FormDeactivate;

end;

procedure TVisZctaConfigForm.acCheckExecute(Sender: TObject);
begin

  if SetAndCheck(true) then begin
    if Sender<>nil then
      ShowMessage('Проверка выполнена успешно')
  end else
    showInfoDlg('Данные в ПЛК не соответствуют выбранному маршруту. '+
          'Выполните установку маршрута в ПЛК!', mtWarning, [mbOK], 0);

end;

function TVisZctaConfigForm.SetAndCheck(OnlyCheck: boolean): boolean;
type
  _rec = record
    tag_addr: integer;
    tag_mode: integer;
    val_addr: integer;
    val_mode: integer;
  end;
var
  _tagname, _address, _mode: string;
  FTagCode, Code: integer;
  FTagStepSize, StepSize: integer;
  FTagStepTime, StepTime: integer;
  FTagDlyAlarm, DlyAlarm: integer;
  FTagDlyStopFlow, DlyStopFlow: integer;
  FTagDlyStopRout, DlyStopRout: integer;
  i,n,j,k: integer;
  arr: array of _rec;
  flag: boolean;
  s, bad_tags: string;

    function _init_tag(s: string): integer;
    begin
      result := GetTagIndex(s);
      if result=-1 then
        bad_tags := bad_tags + s + #13;
    end;

    procedure _set_tag(tg: integer; vl: integer);
    begin
      if tg <> -1 then
        if vl <> GetTagValue(tg) then begin
          if not OnlyCheck then
            SetTagValue(tg, vl);
          flag := false;
        end;
    end;

begin
  Result := False; // todo: ????

  acCurRefreshExecute(nil);

  _tagname := repl(M.Tagname, M.TagIdRoot, M.TagRoot);
  _address := M.TagPath + '.ZCTA_' + _TagName + '_Address';
  _mode := M.TagPath + '.ZCTA_' + _TagName + '_Mode';


  i := GetTagValueByName(M.TagPath + '.ZCTA_' + _TagName + '_Sost');
  if not OnlyCheck then
    if i <> 0 then begin
      close;
      exit;
    end;

  bad_tags := '';

  FTagCode        := _init_tag( M.TagPath + '.ZCTA_' + _TagName + '_Code' );
  FTagStepSize    := _init_tag( M.TagPath + '.ZCTA_' + _TagName + '_StepSize' );
  FTagStepTime    := _init_tag( M.TagPath + '.ZCTA_' + _TagName + '_StepTime' );
  FTagDlyAlarm    := _init_tag( M.TagPath + '.ZCTA_' + _TagName + '_DlyAlarm' );
  FTagDlyStopFlow := _init_tag( M.TagPath + '.ZCTA_' + _TagName + '_DlyStopFlow' );
  FTagDlyStopRout := _init_tag( M.TagPath + '.ZCTA_' + _TagName + '_DlyStopRout' );

  Code        := dsCurMCODE.AsInteger;
  StepSize    := dsCurMSTEPSIZE.AsInteger;
  StepTime    := dsCurMSTEPTIME.AsInteger;
  DlyAlarm    := dsCurMDLY_ALARM.AsInteger;
  DlyStopFlow := dsCurMDLY_STOPFLOW.AsInteger;
  DlyStopRout := dsCurMDLY_STOPROUT.AsInteger;


  if Code<=0 then
    exit;


  // формирование массива
  n := dsCurD.RecordCountFromSrv+1;
  SetLength(arr, n);
//  M.ZdvItemsInit(n-1);

  dsCurD.First;
  for i:=0 to n-2 do begin
    s := _address + inttostr(i);
    arr[i].tag_addr := GetTagIndex(s);
    if arr[i].tag_addr=-1 then bad_tags := bad_tags + s + #13;

    s := _mode + inttostr(i);
    arr[i].tag_mode := GetTagIndex(s);
    if arr[i].tag_mode=-1 then bad_tags := bad_tags + s + #13;


    arr[i].val_addr := dsCurDDADDR.AsInteger;

    arr[i].val_mode := dsCurDDIR_NUM.AsInteger;

    k:=0;
    if dsCurDDDEVTYPE.AsString='ZDVA' then k:=1;
    if dsCurDDDEVTYPE.AsString='ZDVT' then k:=2;
    arr[i].val_mode := arr[i].val_mode + (k shl 4);

    arr[i].val_mode := arr[i].val_mode +
          ((dsCurD.FieldByName('FL_ALARM').AsInteger) and 1) shl 8;

    arr[i].val_mode := arr[i].val_mode +
          ((dsCurD.FieldByName('FL_STOPFLOW').AsInteger) and 1) shl 9;

    arr[i].val_mode := arr[i].val_mode +
          ((dsCurD.FieldByName('FL_STOPROUT').AsInteger) and 1) shl 10;


    dsCurD.Next;

//    new(M.ZdvItems[i]);
//    M.ZdvItems[i].DeviceName := dsCurDDNAME.AsString;
//    M.ZdvItems[i].DirName := dsCurDDIRNAME.AsString;
//    M.ZdvItems[i].OutputTagName := M.TagPath + '.' + dsCurDDDEVTYPE.AsString + '_' +
//                                   dsCurDDTAGNAME.AsString + '_Output';
//    M.ZdvItems[i].OutputTagIndex := GetTagIndex(M.ZdvItems[i].OutputTagName);
  end;

  // конец массива
  i:=n-1;
  s := _address + inttostr(i);
  arr[i].tag_addr := GetTagIndex(s);
  if arr[i].tag_addr=-1 then bad_tags := bad_tags + s + #13;
  arr[i].tag_mode := -1;
  arr[i].val_addr := $FFFF;
  arr[i].val_mode := 0;


  // проверка что все теги нашлись
  if bad_tags<>'' then begin
    ShowMessage('Не найдены теги: '#13 + bad_tags);
    exit;
  end;


  // запись / контроль
  if not OnlyCheck then
    ShowStatusMessageA('Установка данных','подождите...', clLime);

  for j:=1 to 20 do begin
    flag := true;
    for i:=0 to n-1 do begin

      if arr[i].tag_addr <> -1 then
        if arr[i].val_addr <> GetTagValue(arr[i].tag_addr) then begin
          if not OnlyCheck then
            SetTagValue(arr[i].tag_addr, arr[i].val_addr);
          flag := false;
        end;

      if arr[i].tag_mode <> -1 then
        if arr[i].val_mode <> GetTagValue(arr[i].tag_mode) then begin
          if not OnlyCheck then
            SetTagValue(arr[i].tag_mode, arr[i].val_mode);
          flag := false;
        end;

    end;

    _set_tag(FTagCode, Code);
    _set_tag(FTagStepSize   , StepSize   );
    _set_tag(FTagStepTime   , StepTime   );
    _set_tag(FTagDlyAlarm   , DlyAlarm   );
    _set_tag(FTagDlyStopFlow, DlyStopFlow);
    _set_tag(FTagDlyStopRout, DlyStopRout);


    if flag then break;

    if OnlyCheck then break;

//    rpDelay(1000);
    DelayMs(1000, true);
  end;

  dsCurD.First;

  if not OnlyCheck then begin
    CloseStatusMessage;
    VisZctaLoadRootName(M, M.Code);
  end;

//  GetZdvaItems;

  result := flag;

end;

procedure VisZctaLoadRootName(M: TVisZcta; ACode: integer);
var
  form_exists: boolean;
begin

  if ACode=0 then begin
    M.objLabel.Caption := '';
    M.objLabel.Hint := '';
    M.ZdvItemsClear;
    exit;
  end;

  form_exists := VisZctaConfigForm <> nil;

  if not form_exists then begin
    if VisZctaConfigFormCreate(M, M.DBName) then begin
      VisZctaOpenDevices(M.FilterAdd, M.FilterDel);
      VisZctaOpenDatasets;
    end;
  end;

  VisZctaConfigForm.dsCurM.Locate('CODE', ACode, []);

  if VisZctaConfigForm.dsCurM.FieldByName('CODE').AsInteger = ACode then begin
    M.objLabel.Caption := VisZctaConfigForm.dsCurM.FieldByName('NAME').AsString;
    M.objLabel.Hint := VisZctaConfigForm.dsCurM.FieldByName('DESCR').AsString;
    VisZctaConfigForm.GetZdvaItems;
  end else begin
    M.objLabel.Caption := 'Маршрут Code=' + inttostr(ACode) + ' не найден';
    M.objLabel.Hint := '';
    M.ZdvItemsClear;
  end;



  if not form_exists then
    VisZctaConfigFormFree;
end;

procedure TVisZctaConfigForm.FormClose(Sender: TObject;
  var Action: TCloseAction);
begin
  Release;
  VisZctaConfigForm := nil;
end;

procedure TVisZctaConfigForm.Button2Click(Sender: TObject);
begin
  close;
end;

procedure TVisZctaConfigForm.acCurRefreshExecute(Sender: TObject);
begin
  update_dataset([dsrcCurM]);
end;


procedure TVisZctaConfigForm.acCurAddExecute(Sender: TObject);
var
  edit_mode: boolean;
  s: string;
begin

  edit_mode := (Sender = acCurEdit) or (sender = gridCurM);

  if edit_mode then begin
    if dsCurM.Eof then exit;
    s := dsCurMNAME.AsString;
  end else
    s := 'Новый маршрут';


  if not ShowInputDialog('Название маршрута', 'Введите название маршрута', s) then exit;
  if edit_mode then
    dsCurM.Edit
  else
    dsCurM.Append;

  dsCurMNAME.AsString := s;
  dsCurM.Post;
end;


procedure TVisZctaConfigForm.acCurDelExecute(Sender: TObject);
begin

  if showInfoDlg('Удалить маршрут?', mtConfirmation, mbOKCancel, 0) <> mrOk then exit;
  try
    if dsCurM.CanDelete then dsCurM.Delete;
  except
  end;

end;

procedure TVisZctaConfigForm.acResetExecute(Sender: TObject);
var
  _tagname: string;
begin

  if showInfoDlg('Сбросить установку маршрута в ПЛК?', mtConfirmation, mbOKCancel, 0) <> mrOk then exit;
  try
    _tagname := repl(M.Tagname, M.TagIdRoot, M.TagRoot);
    SetTagValue(GetTagIndex(M.TagPath + '.ZCTA_' + _TagName + '_Code'), 0);
    close;
  except
  end;

end;

procedure TVisZctaConfigForm.acHandAddExecute(Sender: TObject);
begin
  if dsCurD.CanInsert then dsCurD.Append;
  gridCurD.SetFocus;
end;

procedure TVisZctaConfigForm.acHandDelExecute(Sender: TObject);
begin

  if showInfoDlg('Удалить устройство?', mtConfirmation, mbOKCancel, 0) <> mrOk then exit;
  try
    if dsCurD.CanDelete then dsCurD.Delete;
  except
  end;

end;

procedure TVisZctaConfigForm.acHandPostExecute(Sender: TObject);
begin
  if dsCurM.State in [dsEdit, dsInsert] then
    if dsCurM.CanEdit then dsCurM.Post;

  if dsCurD.State in [dsEdit, dsInsert] then
    if dsCurD.CanEdit then dsCurD.Post;
end;

procedure TVisZctaConfigForm.grid1SortMarkingChanged(Sender: TObject);
begin
  SortMarkingChanged(sender);
end;

procedure TVisZctaConfigForm.UpdateList(Sender: TObject);
begin
  //todo: remove
end;




procedure TVisZctaConfigForm.gridApplyFilter(Sender: TObject);
begin
  UpdateList(sender);
end;

procedure TVisZctaConfigForm.FormDeactivate(Sender: TObject);
begin
  WindowState := wsMinimized;
end;

procedure TVisZctaConfigForm.dsrcCurMStateChange(Sender: TObject);
begin
  acHandPost.Enabled := (dsCurM.State in [dsEdit, dsInsert]) or (dsCurD.State in [dsEdit, dsInsert]);
end;

procedure TVisZctaConfigForm.dsrcCurDDataChange(Sender: TObject;
  Field: TField);
begin
  dsDEVDIRS_list.Close;
  dsDEVDIRS_list.ParamByName('DEVICE_ID').AsInteger := dsCurDDEVICE_ID.AsInteger;
  dsDEVDIRS_list.Prepare;
  dsDEVDIRS_list.Open;

  dsrcCurMStateChange(nil);
end;

procedure TVisZctaConfigForm.dsCurDAfterPost(DataSet: TDataSet);
begin

//  dsCurDDIR_ID.AsString + ' ' + dsDEVDIRS_list.fieldbyname('ID').AsString);
end;

procedure TVisZctaConfigForm.dsCurDAfterInsert(DataSet: TDataSet);
begin
//  ShowMessage( dsCurDDIR_ID.AsString + ' ' + dsDEVDIRS_list.fieldbyname('ID').AsString );

end;

procedure TVisZctaConfigForm.dsCurDBeforePost(DataSet: TDataSet);
begin
  if (dsCurDDIR_ID.IsNull) or (dsCurDDIR_ID.AsInteger=0) then
    if dsDEVDIRS_list.fieldbyname('ID').AsInteger > 0 then begin
//      dsCurD.Edit;
      dsCurDDIR_ID.AsInteger := dsDEVDIRS_list.fieldbyname('ID').AsInteger;
    end;
end;




procedure TVisZctaConfigForm.GetZdvaItems;
var
  i,n: integer;
begin
  n := dsCurD.RecordCountFromSrv;
  M.ZdvItemsInit(n);

  dsCurD.First;
  for i:=0 to n-1 do begin
    new(M.ZdvItems[i]);
    M.ZdvItems[i].DeviceName := dsCurDDNAME.AsString;
    M.ZdvItems[i].DirName := dsCurDDIRNAME.AsString;
    M.ZdvItems[i].DirNum := dsCurDDIR_NUM.AsInteger;
    M.ZdvItems[i].OutputTagName := M.TagPath + '.' + dsCurDDDEVTYPE.AsString + '_' +
                                   dsCurDDTAGNAME.AsString + '_Output';
    M.ZdvItems[i].OutputTagIndex := GetTagIndex(M.ZdvItems[i].OutputTagName);

    dsCurD.Next;
  end;

end;


end.
