#2 Re: mORMot 1 » How to use OnDrawCellBackground of TSQLTableToGrid? » 2013-02-05 08:34:48

not working with checking ARaw>0.

...
if ARow > 0 then
  with TDrawGrid(Sender).Canvas do begin
    if ATValue = 3 then
      Font.Style:= Font.Style + [fsBold]
    else
      Font.Style:= Font.Style - [fsBold];
//    if ARow > 0 then
      TDrawGrid(Sender).DefaultDrawing:= True;
  end;
...

#3 Re: mORMot 1 » How to use OnDrawCellBackground of TSQLTableToGrid? » 2013-02-05 07:58:18

Solved.
I just set the DefaultDrawing to True after Setting Canvas.Font.Style

procedure TBPBaseMainForm.DoOnDrawCellEvent(Sender: TObject; ACol, ARow: Longint; Rect: TRect; State: TGridDrawState);
var T2G: TSQLTableToGrid;
    ATIndex: Integer;
    ATValue: Integer;
begin
  T2G:= TSQLTableToGrid.From(TDrawGrid(Sender));
  ATIndex:= T2G.Table.FieldIndex('AccountType');
  ATValue:= T2G.Table.GetAsInteger(ARow,ATIndex);
//  if not(gdFixed in State) then
  with TDrawGrid(Sender).Canvas do begin
    if ATValue = 3 then
      Font.Style:= Font.Style + [fsBold]
    else
      Font.Style:= Font.Style - [fsBold];
      TDrawGrid(Sender).DefaultDrawing:= True; //Just add this line;
  end;
end;

But i loss the look and feel of the header.
any idea?

thanks

#4 Re: mORMot 1 » Problem with Currency properties » 2013-02-05 07:19:30

thank you.
BTW, what is the shortage when i use FloatToCurr(resDouble)?

#5 mORMot 1 » How to use OnDrawCellBackground of TSQLTableToGrid? » 2013-02-04 16:26:11

coblongpamor
Replies: 3

i want to set the font as Bold in the TSQLTableToGrid row for some special condition.
this code is working with font as Bold, but i can not select the row.

procedure TBPBaseMainForm.DoOnDrawCellEvent(Sender: TObject; ACol, ARow: Longint; Rect: TRect; State: TGridDrawState);
var T2G: TSQLTableToGrid;
    ATIndex: Integer;
    ATValue: Integer;
begin
  T2G:= TSQLTableToGrid.From(TDrawGrid(Sender));
  if not(gdFocused in State) then begin
    ATIndex:= T2G.Table.FieldIndex('AccountType');
      ATValue:= T2G.Table.GetAsInteger(ARow,ATIndex);
      with TDrawGrid(Sender) do begin
        if ATValue = 3 then
          Canvas.Font.Style:= Canvas.Font.Style + [fsBold]
        else
          Canvas.Font.Style:= Canvas.Font.Style - [fsBold];
      end;
  end;
end;

what is missing?

#7 Re: mORMot 1 » Problem with Currency properties » 2013-02-04 14:34:12

TSynLabeledEdit.IsValid doesn't work for me with sleCurrency Kind.

...
    sleCurrency: begin
      val(Txt,resDouble,err);
      if err<>0 then exit;
//      ToValue := Currency(resDouble); //this is not work as expected
      ToValue := FloatToCurr(resDouble); // i try this, and so far, its work
    end;
...

#8 mORMot 1 » where is Model and ModelTableIndex from RecordProps? » 2012-12-04 09:45:07

coblongpamor
Replies: 1

before we could get the Model and the Model Index from a Class Record, with Rec.RecordProps.
M: = Rec.RecordProps.Model. Also to get the Index of RecordClass from the Model,
RCIndex: = Rec.RecordProps.ModelTableIndex.
But now it does not get done.

Now I'm using:
M: = Client.Model and
RCIndex: = Model.GetTableIndex (aRecordClass);

Did I use the right way?

thank you

#9 Re: mORMot 1 » How to get mORMot to work with FastReport and Express Quantum Grid? » 2012-07-22 13:23:39

@mpv. i never use ClientDataSet before. thnks you for the explanation.

#10 Re: mORMot 1 » How to get mORMot to work with FastReport and Express Quantum Grid? » 2012-07-22 10:09:38

@mpv: i don't understand about

put dataset Delta back to TSQLRecord class

.
i'll try to implement OnBeforeApplyUpdate as you suggest.
thnk you.

another issue, i never succes with TSQLRawBlob field. the field never added to TCLientDataset.

#11 Re: mORMot 1 » How to get mORMot to work with FastReport and Express Quantum Grid? » 2012-07-21 11:13:57

Thanks for the quick response.
Actually I also do not want to use the RAD approach, I prefer to wear such a way that mORMot do (generate control from the code).
But I'm trying to work with mORMot to make scheduling application, that I use cxScheduler for the user interface.

I really do not want to use cxScheduler in BoundMode that requires TDataSet and TDataSource.
Working in UnboundMode also actually very easy, TcxScheduleStorage have LoadFromFile and SaveToFile method.
But I have trouble when trying to save it to mORMot.
Then I go back to the BoundMode, with TSQLTableToDataSet facilities of mORMot. And I still tend to want to use cxSchedulre in UnboundMode.

#12 Re: mORMot 1 » How to get mORMot to work with FastReport and Express Quantum Grid? » 2012-07-21 09:12:47

Yes, changing aTable.FieldLengthMax() into aTable.FieldLengthMax()+1 in the unit SQLite3VCL solved the problem.
and abaut

EDatabaseError with message 'Cannot access field 'ID' as type Variant

i just add 2 lines of code to handle TLargeintField, and so far it's work.

...
if result.Fields[F] is TLargeintField then
  result.Fields[F].AsInteger := aTable.GetAsInteger(i,F)
else
   result.Fields[F].AsVariant := aTable.GetVariant(i,F,aClient);

will you add method in the future to Fill TSQLTable Back from updated conten of TDataset?

thank you.

#13 Re: mORMot 1 » How to get mORMot to work with FastReport and Express Quantum Grid? » 2012-07-20 16:56:31

Yes, there one row data, but not all column have a value.
then, i delete the row data, and exception still ocured.

#14 Re: mORMot 1 » How to get mORMot to work with FastReport and Express Quantum Grid? » 2012-07-20 02:30:33

i also got exception class EDBClient with message 'Invalid Parameter' at line 140

TClientDataSet(result).CreateDataSet;

this is how i call the function:

fTableSchedule:= fClient.List([TSQLSchedule],'*');
fDataSetSchedule:= TSQLTableToDataSet(Self,fTableSchedule,fClient);

and this is TSQLSchedule class declaration;

  TSQLBaseSigned = class(TSQLRecordSigned)
  private
    fDocumentNumber: RawUTF8;
    fDate: TTimeLog;
    fData: TSQLRawBlob;
    fNote: TSQLRawBlob;
    fCreatedTime: TCreateTime;
    fModifiedTime: TModTime;
    fTimeLog: TTimeLog;
  protected
  public
  published
    property DocumentNumber: RawUTF8 read fDocumentNumber write fDocumentNumber stored False;
    property Date: TTimeLog read fDate write fDate;
    property Data: TSQLRawBlob read fData write fData;
    property Note: TSQLRawBlob read fNote write fNote;
    property CreatedTime: TCreateTime read fCreatedTime write fCreatedTime;
    property ModifiedTime: TModTime read fModifiedTime write fModifiedTime;
    property TimeLog: TTimeLog read fTimeLog write fTimeLog;
    property SignatureTime;
    property Signature;
  end;
	
  TSQLBaseSchedule = class(TSQLBaseSigned)
  private
    // internal fields
    fActualFinish: Integer;
    fActualStart: Integer;
    fCaption: RawUTF8;
    fEventType: Integer;
    fFinish: TTimeLog;
    fLabelColor: Integer;
    fLocation: RawUTF8;
    fMessage: RawUTF8;
    fOptions: Integer;
    fParentID: TSQLBaseSchedule;
    fRecurrenceIndex: Integer;
    fRecurrenceInfo: TSQLRawBlob;
    fReminderDate: TTimeLog;
    fReminderMinutesBeforeStart: Integer;
    fResourceID: TSQLRawBlob;
    fStart: TTimeLog;
    fState: Integer;
    // additional for tasks
    fTaskComplete: Integer;
    fTaskIndex: Integer;
    fTaskLinks: TSQLRawBlob;
    fTaskStatus: Integer;
    // additional for reminders
    fReminderResourcesData: TSQLRawBlob;
  protected
  public
  published
    // internal fields
    property ActualFinish: Integer read fActualFinish write fActualFinish;
    property ActualStart: Integer read fActualStart write fActualStart;
    property Caption: RawUTF8 read fCaption write fCaption;
    property EventType: Integer read fEventType write fEventType;
    property Finish: TTimeLog read fFinish write fFinish;
    property LabelColor: Integer read fLabelColor write fLabelColor;
    property Location: RawUTF8 read fLocation write fLocation;
    property Message: RawUTF8 read fMessage write fMessage;
    property Options: Integer read fOptions write fOptions;
    property ParentID: TSQLBaseSchedule read fParentID write fParentID;
    property RecurrenceIndex: Integer read fRecurrenceIndex write fRecurrenceIndex;
    property RecurrenceInfo: TSQLRawBlob read fRecurrenceInfo write fRecurrenceInfo;
    property ReminderDate: TTimeLog read fReminderDate write fReminderDate;
    property ReminderMinutesBeforeStart: Integer read fReminderMinutesBeforeStart write fReminderMinutesBeforeStart;
    property ResourceID: TSQLRawBlob read fResourceID write fResourceID;
    property Start: TTimeLog read fStart write fStart;
    property State: Integer read fState write fState;
    // additional for tasks
    property TaskComplete: Integer read fTaskComplete write fTaskComplete;
    property TaskIndex: Integer read fTaskIndex write fTaskIndex;
    property TaskLinks: TSQLRawBlob read fTaskLinks write fTaskLinks;
    property TaskStatus: Integer read fTaskStatus write fTaskStatus;
    // additional for reminders
    property ReminderResourcesData: TSQLRawBlob read fReminderResourcesData write fReminderResourcesData;
  end;

  TSQLSchedule = class(TSQLBaseSchedule)
  private
  protected
  public
  published
  end;

   

thanks for your support.

#15 Re: mORMot 1 » How to get mORMot to work with FastReport and Express Quantum Grid? » 2012-07-20 01:55:43

hi, i got this error when trying to fill DB VCL dataset with TSQLTable.

EDatabaseError with message 'Cannot access field 'ID' as type Variant

i use SQLite3VCL.

one more: how to save back from Dataset to the framework?

many thanks

#16 Re: Source Code repository » SQLite3 MainDemo source code uploaded to the repository » 2012-07-13 09:23:55

finally.., after all day trying..

RTP:= Pointer(fRibbon.GetParameter(RC));

thank you..

#17 Re: Source Code repository » SQLite3 MainDemo source code uploaded to the repository » 2012-07-13 09:13:46

hallo ab, i cannot compile this code:

..
RTP: ^TFileRibbonTabParameters;
..

RTP:= fRibbon.GetParameter(RC);

//[Error] BPBaseEdit.pas(380): Incompatible types: 'TSQLRibbonTabParameters' and 'TFileRibbonTabParameters'

i also try this code

RTP:= TFileRibbonTabParameters(fRibbon.GetParameter(RC));
or
RTP^:= TFileRibbonTabParameters(fRibbon.GetParameter(RC));
or
RTP:= TFileRibbonTabParameters(fRibbon.GetParameter(RC)^);

//with compiler error: Invalid typecast


what i'm doing wrong? I don't know much about pointer.
thank you

#18 Re: Source Code repository » SQLite3 MainDemo source code uploaded to the repository » 2012-07-13 05:52:04

Hallo ab, i tried create a unit to handle TSQLRecord and TSQLRecordMany published property. Just Inpired by TDBNavigatorButton from DB.pas unit.
i need some suggestion, the unit contain aroun 1200 lines of code. i want to share with the others even not so good code.
can i post here? or can i send to your email please?

#20 Re: Source Code repository » SQLite3 MainDemo source code uploaded to the repository » 2012-07-13 03:28:16

How to read customs Field from TSQLRibbonTabParameters?

TFileRibbonTabParameters = object(TSQLRibbonTabParameters)
  /// the SynFile actions
  Actions: TFileActions;
  Test1: string;
  ..
end;

...
var
  T: TFileRibbonTabParameters;
  Test: string;
begin
  T:= Ribbon.GetParameter(TSQLSomeRecord)^;
  Test:= T.Test1;
  ...
end;

is it possible to Save and load TSQLRibbonTabParameters to file on-the-fly?

thanks

#21 Re: mORMot 1 » SynDB Explorer (sample 10) not compiling » 2012-07-11 11:28:47

this line of code also not compiling in fileclient.pas from the synfile

DrawTextAcrossColsFromCSV(PC,$C0C0FF);

#22 Re: mORMot 1 » Need Help about SQLite3UIQuery » 2012-05-03 18:01:25

ab wrote:

Is it because e.g. the "Country" column does not have an easy way to filter the entry?

yes. i think there are an issue if the alias name same as Name of Field of the Primary table 

(SELECT Name FROM Country WHERE ID=Country) AS Country

but, if i change the alias name, e.g CountryName, it's work.
but qoContains sometimes not found matches row, even if with the sftUTF8Text.

#23 Re: mORMot 1 » Need Help about SQLite3UIQuery » 2012-05-03 16:24:47

I did not do anything on SQLite3UIQuery, just create an instance on the new form.

TSQLBase = class(TSQLRecord)
  private
    fCode: RawUTF8;
    fName: RawUTF8;
    fIsInactive: Boolean;
    fTimeLog: TTimeLog;
    fCreatedTime: TCreateTime;
    fModifiedTime: TModTime;
  protected
  public
    property Code: RawUTF8 read fCode write fCode;
    property Name: RawUTF8 read fName write fName;
    property IsInactive: Boolean read fIsInactive write fIsInactive;
    property TimeLog: TTimeLog read fTimeLog write fTimeLog;
    property CreatedTime: TCreateTime read fCreatedTime write fCreatedTime;
    property ModifiedTime: TModTime read fModifiedTime write fModifiedTime;
  end;

TSQLBaseRegion = class(TSQLBase)
  private
    fLatitude: Double;
    fLongitude: Double;
  protected
  public
  published
    property Code stored False;
    property Name;
    property Latitude: Double read fLatitude write fLatitude;
    property Longitude: Double read fLongitude write fLongitude;
  end;

  TSQLBaseRegionClass = class of TSQLBaseRegion;

  TSQLCity = class(TSQLBaseRegion)
  private
    fCityClass: TSQLBaseRegionClass;
  protected
  public
  published
    property CityClass: TSQLBaseRegionClass read fCityClass write fCityClass;
  end;

  TSQLCountry = class(TSQLBaseRegion)
  private
    fCity: TSQLCity;
    fPrimaryLanguage: TSQLLanguage;
  protected
  public
  published
    property City: TSQLCity read fCity write fCity;
    property PrimaryLanguage: TSQLLanguage read fPrimaryLanguage write fPrimaryLanguage;
  end;

  TSQLProvince = class(TSQLBaseRegion)
  private
    fCountry: TSQLCountry;
    fCity: TSQLCity;
  protected
  public
  published
    property Country: TSQLCountry read fCountry write fCountry;
    property City: TSQLCity read fCity write fCity;
  end;

  TSQLRegency = class(TSQLBaseRegion)
  private
    fProvince: TSQLProvince;
    fCity: TSQLCity;
  protected
  public
  published
    property Province: TSQLProvince read fProvince write fProvince;
    property City: TSQLCity read fCity write fCity;
  end;

  TSQLSubDistrict = class(TSQLBaseRegion)
  private
    fRegency: TSQLRegency;
    fCity: TSQLCity;
  protected
  public
  published
    property Regency: TSQLRegency read fRegency write fRegency;
    property City: TSQLCity read fCity write fCity;
  end;

  TSQLVillage = class(TSQLBaseRegion)
  private
    fSubDistrict: TSQLSubDistrict;
    fCity: TSQLCity;
  protected
  public
  published
    property SubDistrict: TSQLSubDistrict read fSubDistrict write fSubDistrict;
    property City: TSQLCity read fCity write fCity;
  end;

  TSQLHamlet = class(TSQLBaseRegion)
  private
    fVillage: TSQLVillage;
  protected
  public
  published
    property Village: TSQLVillage read fVillage write fVillage;
  end;

TSQLAddress = class(TSQLBase)
  private
    fStreetLine1: RawUTF8;
    fStreetLine2: RawUTF8;
    fStreetLine3: RawUTF8;
    fRTRW : RawUTF8;
    fCountry: TSQLCountry;
    fProvince: TSQLProvince;
    fRegency: TSQLRegency;
    fSubDistrict: TSQLSubDistrict;
    fVillage: TSQLVillage;
    fHamlet: TSQLHamlet;
    fZipCode: RawUTF8;
  protected
  public
  published
    property StreetLine1: RawUTF8 read fStreetLine1 write fStreetLine1;
    property StreetLine2: RawUTF8 read fStreetLine2 write fStreetLine2;
    property StreetLine3: RawUTF8 read fStreetLine3 write fStreetLine3;
    property RTRW: RawUTF8 read fRTRW write fRTRW;
    property Country: TSQLCountry read fCountry write fCountry;
    property Province: TSQLProvince read fProvince write fProvince;
    property Regency: TSQLRegency read fRegency write fRegency;
    property SubDistrict: TSQLSubDistrict read fSubDistrict write fSubDistrict;
    property Village: TSQLVillage read fVillage write fVillage;
    property Hamlet: TSQLHamlet read fHamlet write fHamlet;
    property ZipCode: RawUTF8 read fZipCode write fZipCode;
  end;

yes please, where I can send you a more complete version?

#24 mORMot 1 » Need Help about SQLite3UIQuery » 2012-05-03 15:43:52

coblongpamor
Replies: 3

I think, SQLite3UIQuery not handle sftid type of field with a sub select query.

ADDRESS_SELECT = 'StreetLine1,StreetLine2,StreetLine3,RTRW, '+
    '(SELECT Name FROM Country WHERE ID=Country) AS Country, '+
    '(SELECT Name FROM Province WHERE ID=Province) AS Province, '+
    '(SELECT Name FROM Regency WHERE ID=Regency) AS Regency, '+
    '(SELECT Name FROM SubDistrict WHERE ID=SubDistrict) AS SubDistrict, '+
    '(SELECT Name FROM Village WHERE ID=Village) AS Village ';

I also found that qoContains less accurate.
Could you check it?

many thanks.

#25 Re: mORMot 1 » delete many rows of TSQLRest with where condition » 2012-05-03 04:34:56

I think you just need a line of code to do so.

dbcache.EngineExecuteAll(FormatUTF8('DELETE FROM Cache WHERE Time < %d',[lastcache]));

hopefully can help.

#26 Re: mORMot 1 » Need Help about SQLite3UIEdit » 2012-05-03 03:41:59

yes please, i need it, and thanks.
a also plan to add Browse Button, to show Browse form that containing TSQLRecordClass data related to sftID.
in this form (browse form) i plan to use facility of SQLite3UIQuery.
but with filtering (not marking) the match row.
i mean, only the matches rows will be displayed on the grid.
is it possible?

#27 Re: mORMot 1 » Need Help about SQLite3UIEdit » 2012-05-02 14:59:57

thank you.
I tried to call the form automatically, by creating an instance of TSynButton.

TSQLRecordButtonClass = class of TSQLRecordButton;

  TSQLRecordButton = class(TSynButton)
  private
    fProp: PPropInfo;
    fRecordClass: TSQLRecordClass;
    fAssociateComponent: TWinControl;
  protected
  public
    property Prop: PPropInfo read fProp write fProp;
    property RecordClass: TSQLRecordClass read fRecordClass;
    property AssociateComponent: TWinControl read fAssociateComponent;

    constructor Create(aOwner: TComponent; P: PPropInfo; Comp: TWinControl); reintroduce;
    class function CreateButton(aOwner: TComponent; P: PPropInfo;
      Comp: TWinControl; RecordButtonClass: TSQLRecordButtonClass): TSQLRecordButton;
  end;

  TSQLRecordAddButton = class(TSQLRecordButton);

  TSQLRecordEditButton = class(TSQLRecordButton);

I'm not sure, if this is a good idea or not. but so far it's working fine,
except I can not get RibbonTabParameters, because not all of RecordClass listed on the ribbon.
I'm hoping to get suggestions for a better way.

The following is a complete unit of BPBaseEditForm.

unit BPBaseEdit;

interface

uses
  Windows,
  Messages,
  SysUtils,
  Variants,
  Classes,
  Graphics,
  Controls,
  Forms,
  Dialogs,
  StdCtrls,
  ExtCtrls,
  ComCtrls,
  SynCommons,
  SQLite3Commons,
  SQLite3i18n,
  SQLite3ToolBar,
  SQLite3UIEdit,
  SQLite3UILogin,
  SQLBaseModel,
  BPFrame,
  ImgList,
  SynTaskDialog;
type
  TSQLRecordButtonClass = class of TSQLRecordButton;

  TSQLRecordButton = class(TSynButton)
  private
    fProp: PPropInfo;
    fRecordClass: TSQLRecordClass;
    fAssociateComponent: TWinControl;
  protected
  public
    property Prop: PPropInfo read fProp write fProp;
    property RecordClass: TSQLRecordClass read fRecordClass;
    property AssociateComponent: TWinControl read fAssociateComponent;

    constructor Create(aOwner: TComponent; P: PPropInfo; Comp: TWinControl); reintroduce;
    class function CreateButton(aOwner: TComponent; P: PPropInfo;
      Comp: TWinControl; RecordButtonClass: TSQLRecordButtonClass): TSQLRecordButton;
  end;

  TSQLRecordAddButton = class(TSQLRecordButton);

  TSQLRecordEditButton = class(TSQLRecordButton);

  TBPBaseEditForm = class(TRecordEditForm)
    pnlFrame: TPanel;
    il16: TImageList;
    il32: TImageList;
    procedure BtnSaveClick(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure FormCreate(Sender: TObject);
    procedure FormShow(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    { Private declarations }
    fModified: Boolean;
    fPagerTop: TSynPager;
    fTB: TSQLCustomToolBar;
    fDetail: TFrameDetail;
  protected
    procedure CRUDActionClick(Sender: TObject);
    procedure CRUDManyActionClick(Sender: TObject);
    procedure DOOnChange(Sender: TObject);
    procedure SetDetail(aDetail:TFrameDetail);
  public
    { Public declarations }
    function DOOnComponentCreate(Obj: TObject; Prop: PPropInfo; Parent: TWinControl): TWinControl;
    procedure DOOnComponentCreated(Obj: TObject; Prop: PPropInfo; Comp: TWinControl);

    property Modified: Boolean read fModified write fModified;
    property Detail: TFrameDetail read fDetail write SetDetail;
  end;

//var BPBaseEditForm: TBPBaseEditForm;

implementation

uses Contnrs;

{$R *.dfm}

{TSQLRecordButton}
constructor TSQLRecordButton.Create(aOwner: TComponent; P: PPropInfo; Comp: TWinControl);
begin
  fProp:= P;
  fRecordClass:= TSQLRecordClass(fProp^.Proptype^^.ClassType^.Classtype);
  fAssociateComponent:= Comp;
  Inherited Create(aOwner);
end;

class function TSQLRecordButton.CreateButton(aOwner: TComponent; P: PPropInfo;
  Comp: TWinControl; RecordButtonClass: TSQLRecordButtonClass): TSQLRecordButton;
begin
  if (aOwner = nil) or (P = nil) then
    Result:= nil
  else Result:= RecordButtonClass.Create(aOwner,P,Comp);
end;

{TBPBaseEditForm}
procedure TBPBaseEditForm.CRUDActionClick(Sender: TObject);
var
  aRec: TSQLRecord;
  BaseEditForm: TBPBaseEditForm;
  aID, SetIndex: Integer;
  CB: TComboBox;
  IsOK: Boolean;

  function CRUD(aRec: TSQLRecord): Boolean;
  begin
    BaseEditForm.SetRecord(Client,aRec);
    Result := BaseEditForm.ShowModal= mrOk;
  end;

  procedure RefreshComboBox(aClient: TSQLRestClient; P: PPropInfo);
  var
    IDClass: TSQLRecordClass;
    SourceID,OldIndex: Integer;
  begin
    if aClient <> nil then begin
      OldIndex:= CB.ItemIndex;
      IDClass := TSQLRecordClass(P^.PropType^^.ClassType^.ClassType);
      SourceID := P^.GetOrdValue(Rec);
      with IDClass.RecordProps do
      if MainField[True] >= 0 then begin
        aClient.OneFieldValues(IDClass,FieldsName[MainField[True]],'',CB.Items,@SourceID);
        CB.ItemIndex:= OldIndex;
      end;
    end;
  end;
begin
  with TSQLRecordButton(Sender) do
  begin
    aRec:= RecordClass.Create;
    CB:= TComboBox(AssociateComponent);
    SetIndex:= CB.ItemIndex;
    if SetIndex < 0 then
      aID := 0
    else aID := PtrInt(CB.Items.Objects[SetIndex]);
  end;
  if aRec = nil then
    Exit;
  BaseEditForm:= TBPBaseEditForm.Create(Application);
  try
    if Sender.InheritsFrom(TSQLRecordAddButton) then
      while CRUD(aRec) do
      try
        aID:= Client.Add(aRec,True);
        if aID > 0 then begin
          aRec.ClearProperties;
        end;
      finally
        Client.UnLock(aRec);
      end else
    if Sender.InheritsFrom(TSQLRecordEditButton) then
    try
      if Client.Retrieve(aID,aRec,False) then
      try
        IsOK:= CRUD(aRec);
        if IsOK then
          Client.Update(aRec);
      finally
        Client.UnLock(aRec);
      end;
    finally
    end;
    RefreshComboBox(Client, TSQLRecordButton(Sender).Prop);
  finally
    aRec.Free;
    BaseEditForm.Free;
  end;
end;


procedure TBPBaseEditForm.CRUDManyActionClick(Sender: TObject);
var
  aRec: TSQLRecord;
  aMany: TSQLRecordMany;
  BaseEditForm: TBPBaseEditForm;
  aID,aTag: Integer;
  function CRUD(aRec: TSQLRecord): Boolean;
  begin
    BaseEditForm.SetRecord(Client,aRec);
    Result := BaseEditForm.ShowModal= mrOk;
  end;
begin
  aTag:= TSynToolButton(Sender).Tag;
  case aTag of
    Ord(caCreate)..Ord(caUpdate):begin
      BaseEditForm:= TBPBaseEditForm.Create(Application);
      try
        aRec:= Detail.CurrentPage.Dest;
        if aRec = nil then
          Exit;
        aMany:= Detail.CurrentPage.Many;
        if aTag = Ord(caCreate) then
          while CRUD(aRec) do
          try
            aID:= Client.Add(aRec,True);
            if aID > 0 then begin
              aMany.ManyAdd(Client,Rec.ID,aID,True);
              aRec.ClearProperties;
              Detail.RefreshCurrentPage;
            end;
          finally
            Client.UnLock(aRec);
          end else
        if aTag = Ord(caUpdate) then
        try
        finally
        end;
      finally
      end;
    end;
  end;
end;

procedure TBPBaseEditForm.DOOnChange(Sender: TObject);
begin
  Modified:= True;
end;

procedure TBPBaseEditForm.SetDetail(aDetail: TFrameDetail);
begin
  if aDetail <> nil then
    fDetail:= aDetail
  else
    fDetail:= TFrameDetail.Create(Self,Client,Rec);
end;

function TBPBaseEditForm.DOOnComponentCreate(Obj: TObject; Prop: PPropInfo; Parent: TWinControl): TWinControl;
var
  SQLFieldType: TSQLFieldType;
  P: PPropInfo;
begin
  Result:= nil;
  P:= Prop;
  SQLFieldType:= P^.PropType^^.SQLFieldType;
  case SQLFieldType of
    sftMany: begin
      Result := TComboBox.Create(Parent);
    end;
  end;
end;

procedure TBPBaseEditForm.DOOnComponentCreated(Obj: TObject; Prop: PPropInfo; Comp: TWinControl);
const
  W = 50;
var
  P: PPropInfo;
  SQLFieldType: TSQLFieldType;
  L: Integer;
begin
  P:= Prop;
  SQLFieldType:= P^.PropType^^.SQLFieldType;
  case SQLFieldType of
    sftID: begin
      with TSQLRecordButton.CreateButton(Comp.Parent,Prop,Comp,TSQLRecordAddButton) do begin
        Tag:= 0;
        Parent := Comp.Parent;
        L:= Comp.Left + Comp.Width + 1;
        SetBounds(L,Comp.Top - 1,W,Comp.Height + 2);
        Caption := 'Add';
        OnClick := CRUDActionClick;
        SetBitmap(BitmapArrow);
        Anchors := [akLeft, akTop];
      end;

      with TSQLRecordButton.CreateButton(Comp.Parent,Prop,Comp,TSQLRecordEditButton) do begin
        Tag:= 1;
        Parent := Comp.Parent;
        L:= L + W + 1;
        SetBounds(L,Comp.Top - 1,W,Comp.Height + 2);
        Caption := 'Edit';
        OnClick := CRUDActionClick;
        SetBitmap(BitmapArrow);
        Anchors := [akLeft, akTop];
      end;
    end;
  end;

  if Comp.InheritsFrom(TLabeledEdit) then begin
    if P^.Name = 'Name' then
      Comp.Width:= Comp.Width + 100;
    TLabeledEdit(Comp).OnChange:= DOOnChange;
  end else
  if Comp is TDateTimePicker then begin
    TDateTimePicker(Comp).OnChange:= DOOnChange;
  end else
  if Comp is TComboBox then begin
    TComboBox(Comp).OnChange:= DOOnChange;
  end;
end;

procedure TBPBaseEditForm.BtnSaveClick(Sender: TObject);
begin
  Modified:= False;
  inherited BtnSaveClick(Sender);
end;

resourcestring
  sSave= 'Save Changes ?';

procedure TBPBaseEditForm.FormClose(Sender: TObject;
  var Action: TCloseAction);
var
  aAnswer: Integer;
begin
  inherited;
  if Modified then begin
    aAnswer:= MessageDlg(sSave,mtConfirmation,mbYesNoCancel,0);
    case aAnswer of
      mrYes: BtnSaveClick(Sender);
      mrNo:;
      mrCancel:Action:= caNone;
    end;
  end;
end;

procedure TBPBaseEditForm.FormCreate(Sender: TObject);
begin
  inherited;
//  OnComponentCreate:= DOOnComponentCreate;
  OnComponentCreated:= DOOnComponentCreated;

  BottomPanel.BevelOuter:= bvNone;
  BottomPanel.Height:= 40;
  BtnSave.SetBounds(BtnSave.Parent.Width - 220,5,100,27);
  BtnCancel.SetBounds(BtnSave.Left + BtnSave.Width,5,100,27);
  BtnSave.OnClick:= BtnSaveClick;
end;

[b]
procedure TBPBaseEditForm.FormShow(Sender: TObject);
begin
  with Rec.RecordProps do
    if Pointer(ManyFields) <> nil then try
      Detail:= TFrameDetail.Create(pnlFrame,Client,Rec);
      Detail.Parent:= pnlFrame;

      fPagerTop:= TSynPager.Create(Detail);
      fPagerTop.Parent:= Detail;
      fPagerTop.Align:= alTop;
      fPagerTop.Height:= 40;
      fTB.Init(fPagerTop,TypeInfo(TCRUDAction),CRUDManyActionClick,nil,'');
      fTB.AddToolBar('');
      fTB.Toolbars[0].Align:= alClient;
    except
    end;
  pnlFrame.Visible:= Detail <> nil;
  if pnlFrame.Visible then begin
    ClientHeight:= ClientHeight + pnlFrame.Height;
  end;
  SetStyle(Self);
  inherited;
end;
[/b]

procedure TBPBaseEditForm.FormDestroy(Sender: TObject);
begin
  if fPagerTop <> nil then
    fPagerTop.Free;
  if fDetail <> nil then
    fDetail.Free;

  inherited;
end;

end.

I also tried to handle sftMany SQLFieldType.
please note the FormShow () and CRUDManyActionClick ().
It also works pretty well, but I'm still not satisfied with the results.
I feel this way is not true.
The following is what I am trying to do on the unit FrameDetai

unit BPFrame;

interface

uses
  Windows,
  Messages,
  SysUtils,
  Variants,
  Classes,
  Graphics,
  Controls,
  ComCtrls,
  Forms,
  Dialogs,
  SynCommons,
  SQLite3Commons,
  SQLite3UI,
  SQLite3ToolBar,
  SQLite3UILogin,
{$IFDEF USENEXTPACK}
  NxColumnClasses,
  NxColumns,
  NxScrollControl,
  NxCustomGridControl,
  NxCustomGrid,
  NxGrid,
{$ELSE}
  Grids,
{$ENDIF}
  ExtCtrls;
type
  TPagerMany= class;

  TPageMany= class(TSynPage)
  private
    fDest: TSQLRecord;
    fMany: TSQLRecordMany;
    fTable: TSQLTable;
    {$IFDEF USENEXTPACK}
    fGrid: TNextGrid;
    {$ELSE}
    fTableToGrid: TSQLTableToGrid;
    fGrid: TDrawGrid;
    {$ENDIF}
    fSourceCSVFieldNames: PUTF8Char;
    fDestCSVFieldNames: PUTF8Char;
  protected
    function CreateGrid:{$IFDEF USENEXTPACK}TNextGrid{$ELSE}TDrawGrid{$ENDIF};
  public
    class function CreatePageMany(aPager: TPagerMany; aMany: TSQLRecordMany;
      SourceCSVFieldNames: PUTF8Char=nil; DestCSVFieldNames: PUTF8Char=nil): TPageMany;

    property Dest: TSQLRecord read fDest write fDest;
    property Many: TSQLRecordMany read fMany;
    property Table: TSQLTable read fTable write fTable;
    property SourceCSVFieldNames: PUTF8Char read fSourceCSVFieldNames;
    property DestCSVFieldNames: PUTF8Char read fDestCSVFieldNames;
    {$IFDEF USENEXTPACK}
    property Grid: TNextGrid read fGrid write fGrid;
    {$ELSE}
    property TableToGrid: TSQLTableToGrid read fTableToGrid write fTableToGrid;
    property Grid: TDrawGrid read fGrid write fGrid;
    {$ENDIF}

    destructor Destroy; override;
  end;

  TPagerMany= class(TSynPager)
  private
    fClient: TSQLRestClient;
    fSource: TSQLRecord;
    function GetActivePageIndex: integer;
    procedure SetActivePageIndex(const Value: integer);
  protected
    procedure Change; override;
    function GetPageMany(aIndex: integer): TPageMany; {$ifdef HASINLINE}inline;{$endif}
    function GetSQLMany(aIndex: integer): TSQLRecordMany; {$ifdef HASINLINE}inline;{$endif}
  public
    class function CreatePagerMany(aOwner: TComponent; aClient: TSQLRestClient; aSource: TSQLRecord): TPagerMany;
    /// add a page instance
    function AddPage(aPage: TPageMany): integer; overload;
    /// create a new page with the specified caption
    function AddPage: integer; overload;
    /// mimic TTabSheet.Pages property
    property Pages[aIndex: Integer]: TPageMany read GetPageMany;
    /// force OnChange event to be triggered
    property ActivePageIndex: integer read GetActivePageIndex write SetActivePageIndex;

    property Client: TSQLRestClient read fClient;
    property Source: TSQLRecord read fSource;
  published
    property OnChange;
  end;

  TFrameDetail = class(TFrame)
  private
    { Private declarations }
    fClient: TSQLRestClient;
    fSource: TSQLRecord;
    fCurrentPage: TPageMany;
  protected
    function GetActivePage: TPageMany;
    procedure DoPageChange(Sender: TObject);
  public
    { Public declarations }
    PagerMany: TPagerMany;

    property Client: TSQLRestClient read fClient;
    property Source: TSQLRecord read fSource;
    property CurrentPage: TPageMany read GetActivePage write fCurrentPage;

    procedure RefreshCurrentPage;
    constructor Create(aOwner: TComponent; aClient: TSQLRestClient; aSource: TSQLRecord); reintroduce;
    destructor Destroy; override;
  end;

implementation

{$R *.dfm}

{TPageMany}
function TPageMany.CreateGrid:{$IFDEF USENEXTPACK}TNextGrid{$ELSE}TDrawGrid{$ENDIF};
var
  {$IFDEF USENEXTPACK}
  CC: TNxColumnClass;
  {$ENDIF}
  C,R,aID: Integer;
  S: String;
  aClient: TSQLRestClient;
  aSource: TSQLRecord;
  FieldTableClass, IDClass: TSQLRecordClass;
  aRecord: TSQLRecord;
  P: PPropInfo;
  NeedCreation: Boolean;
begin
  with TPagerMany(Self.PageControl) do begin
    aClient:= fClient;
    aSource:= fSource;
  end;
  
  NeedCreation:= Self.Grid = nil;

  if NeedCreation then begin
    Grid:= {$IFDEF USENEXTPACK}TNextGrid.Create(Self){$ELSE}TDrawGrid.Create(Self){$ENDIF};
  end;
  with Grid do try
    if NeedCreation then begin
      Parent:= Self;
      Align:= alClient;
    end;
    Table:= Many.DestGetJoinedTable(aClient,'',aSource.ID,jkDestFields);
    if Table <> nil then try
      {$IFDEF USENEXTPACK}
      if NeedCreation then begin
        for C := 0 to Table.FieldCount - 1 do begin
          case Table.FieldType(C,nil) of
            sftAnsiText,sftUTF8Text: CC:= TNxTextColumn;
            sftEnumerate,sftSet: CC:= TNxCheckBoxColumn;
            sftInteger: CC:= TNxIncrementColumn;
            sftID: CC:= TNxComboBoxColumn;
            sftDateTime,sftTimeLog,sftCreateTime,sftModTime: CC:= TNxDateColumn;
          end;
          with Columns.Add(CC, Table.GetCaption(0,C)) do begin
            Options:= [coCanInput];
          end;
        end;
        AppearanceOptions:= [aoBoldTextSelection,aoIndicateSortedColumn];
        Options:= [goDisableColumnMoving,goFooter,goGrid,goHeader,goInplaceEditEvents,goLockFixedCols,goIndicator,goInput];
      end;

      ClearRows;
      AddRow(Table.RowCount);
      for R := 1 to Table.RowCount do
        for C := 0 to Table.FieldCount - 1 do begin
          case Table.ExpandAsString(R,C,aClient,S) of
            sftID:
            if aClient <> nil then try
              FieldTableClass:= TSQLRecordClass(Table.FieldTable(C));
              aRecord:= FieldTableClass.Create(aClient,StrToInt(S));
              P:= FieldTableClass.RecordProps.Fields[C+1];
//              S:= FieldTableClass.RecordProps.Fields[C+1].Name;
              IDClass := TSQLRecordClass(P^.PropType^^.ClassType^.ClassType);
              aID := P^.GetOrdValue(aRecord);
              with IDClass.RecordProps do
              if MainField[true]>=0 then begin
                aClient.OneFieldValues(IDClass,FieldsName[MainField[True]],'',
                  TNxComboBoxColumn(Grid.Columns[C]).Items,@aID);
                TNxComboBoxColumn(Grid.Columns[C]).Index:= aID;
                if aID > 0 then
                  S:= TNxComboBoxColumn(Grid.Columns[C]).Items[aID];
              end;
            finally
              aRecord.Free;
            end;
          end;
          Cell[C,R-1].AsString:= S;
        end;
      {$ELSE}
        RowCount:= 1;
        ColCount:= 1;
      TableToGrid:= TSQLTableToGrid.Create(Grid,Table,TSQLRestClientURI(aClient));
      {$ENDIF};
    finally
    end;
  finally
  end;
  Result:= Grid;
end;

class function TPageMany.CreatePageMany(aPager: TPagerMany; aMany: TSQLRecordMany;
  SourceCSVFieldNames: PUTF8Char=nil; DestCSVFieldNames: PUTF8Char=nil): TPageMany;
var
  PM: TPageMany;
  DestClass: TSQLRecordClass;
begin
  PM:= TPageMany.Create(aPager);
  PM.Caption:= FormatUTF8('[%]',[aMany.SQLTableName]);
  aPager.AddPage(PM);
  PM.Name := 'P'+IntToStr(Random(GetTickCount));
  PM.Tag := PtrInt(PM);
  PM.fMany:= aMany;
  DestClass:= PM.fMany.RecordProps.RecordManyDestClass;
  PM.Dest:= DestClass.Create;
  PM.PageControl := aPager;
  PM.Grid:= PM.CreateGrid;
  SetStyle(PM);
  Result:= PM;
end;

destructor TPageMany.Destroy;
begin
  fDest.Free;
  fMany.Free;
  fTableToGrid.Free;
  fGrid.Free;
  inherited Destroy;
end;

{ TPagerMany }
function TPagerMany.AddPage(aPage: TPageMany): Integer;
begin
  aPage.PageControl := Self;
  Result := PageCount-1;
end;

function TPagerMany.AddPage: Integer;
var aPage: TPageMany;
begin
  aPage := TPageMany.Create(Self);
  aPage.Parent := Self;
  Result := AddPage(aPage);
end;

function TPagerMany.GetPageMany(aIndex: integer): TPageMany;
begin
  result := inherited Pages[aIndex] as TPageMany;
end;

function TPagerMany.GetSQLMany(aIndex: integer): TSQLRecordMany;
begin
  Result:= Pages[aIndex].Many;
end;

function TPagerMany.GetActivePageIndex: integer;
begin
  Result := inherited ActivePageIndex;
end;

procedure TPagerMany.SetActivePageIndex(const Value: integer);
begin
  inherited ActivePageIndex := Value;
  Change;
  if Assigned(OnChange) then
    OnChange(Self);
end;

procedure TPagerMany.Change;
begin
  inherited Change;
end;

class function TPagerMany.CreatePagerMany(aOwner: TComponent; aClient: TSQLRestClient; aSource: TSQLRecord): TPagerMany;
begin
  Result:= TPagerMany.Create(aOwner);
  if aOwner is TWinControl then
    Result.Parent := TWinControl(aOwner);
  Result.fClient:= aClient;
  Result.fSource:= aSource;
  Result.HotTrack := True;
  Result.ControlStyle := Result.ControlStyle+[csClickEvents]; // enable OnDblClick
  Result.Align := alClient;
  Result.Font.Style:= Result.Font.Style + [fsBold];
  Result.MultiLine:= True;
  Result.TabWidth:= 75;
  Result.OwnerDraw:= True;
  SetStyle(Result);
end;

{TFrameDetail}
function TFrameDetail.GetActivePage: TPageMany;
begin
  with PagerMany do
    Result:= Pages[GetActivePageIndex];
end;

procedure TFrameDetail.DoPageChange(Sender: TObject);
begin
  if not(Sender.InheritsFrom(TPageControl)) then
    Exit;
  CurrentPage:= GetActivePage;
  CurrentPage.CreateGrid;
end;

procedure TFrameDetail.RefreshCurrentPage;
begin
  CurrentPage.CreateGrid; //will do all the magiq
end;

constructor TFrameDetail.Create(aOwner: TComponent; aClient: TSQLRestClient; aSource: TSQLRecord);
var
  i: Integer;
  P: PPropInfo;
  aMany: TSQLRecordMany;
  IDClass: TSQLRecordClass;
begin
  inherited Create(aOwner);
  fClient:= aClient;
  fSource:= aSource;

  with Source.RecordProps do
  if PagerMany = nil then begin
    PagerMany:= TPagerMany.CreatePagerMany(Self,Client,Source);
    PagerMany.OnChange:= DoPageChange;
    for i := 0 to High(ManyFields) do begin
      aMany := TSQLRecordManyClass(ManyFields[i]^.PropType^^.ClassType^.ClassType).Create;
      TPageMany.CreatePageMany(PagerMany,aMany);
    end;
  end;

  if aOwner is TWinControl then
    Self.Parent:= TWinControl(aOwner);
  Self.Align:= alClient;
  SetStyle(Self);
end;

destructor TFrameDetail.Destroy;
begin
//  PagerTop.Free;
//  PagerMany.Free;
//  fSource.Free;
//  fClient.Free;
  inherited Destroy;
end;

end.

#28 Re: mORMot 1 » Need Help about SQLite3UIEdit » 2012-05-01 16:20:50

I tried to use the event OnComponentCreated on RecordEditForm to create two buttons on the right control for the sftid field type.

procedure TBPBaseEditForm.DOOnComponentCreated(Obj: TObject; Prop: PPropInfo; Comp: TWinControl);
var
  SQLFieldType: TSQLFieldType;
  P: PPropInfo;
  ButtonAdd, ButtonEdit: TSynButton;
begin
  P:= Prop;
  SQLFieldType:= P^.PropType^^.SQLFieldType;
  case SQLFieldType of
    sftID: begin
      ButtonAdd := TSynButton.Create(Comp.Parent);
      with ButtonAdd do begin
        Parent := Comp.Parent;
        SetBounds(Comp.Left + Comp.Width + 1,Comp.Top - 1,50,Comp.Height + 2);
        Caption := 'Add';
//      B.OnClick := BClick;
        SetBitmap(BitmapArrow);
        Anchors := [akLeft, akTop];
      end;
      ButtonEdit:= TSynButton.Create(Comp.Parent);
      with ButtonEdit do begin
        Parent := Comp.Parent;
        SetBounds(ButtonAdd.Left + ButtonAdd.Width + 1,ButtonAdd.Top,50,ButtonAdd.Height);
        Caption := 'Edit';
//      B.OnClick := BClick;
        SetBitmap(BitmapArrow);
        Anchors := [akLeft, akTop];
      end;
    end;
  end;
end;

but, I had trouble in adjusting the position of the buttons.
unless I move the trigger event, to the bottom.

....
fFieldComponents[i] := C;
//i move it to here
if Assigned(OnComponentCreated) then // allow component customization
  OnComponentCreated(aRecord,P,C); // e.g. set C.Enabled := false
inc(Y,aHeight);
...

one more, can you add BitmapAdd and BitmapEdit to the SynTaskDialog.res?

thank you

#29 Re: mORMot 1 » "has many" and "has many through" relationships » 2012-05-01 07:45:28

sorry for my english, that made you confused.
i mean, from current selected row to another row.
for example:
current selected row is row 1, then immediately i double click another row quickly.

note: this AV will not occure in synfile main demo, only on my project with using RecordEditForm.

#30 Re: mORMot 1 » "has many" and "has many through" relationships » 2012-05-01 03:55:17

I think I found the cause that triggered the emergence of AV.
AV would happen if I do double click on "another row" in the grid with a "very fast", but it never happened if I did it with normal speed.
But if we choose the line first, then the AV will not happen even if we do a very quick double click.

There may be issues on TSQLLister.OnSelectCell ()?

#32 Re: mORMot 1 » "has many" and "has many through" relationships » 2012-04-30 00:20:45

about vmtAutoTable, i think, i'm not using it for now.
i only use third-party grid component, but with conditional defines {$IFDEF USENEXTPACK}
i suspect the problem is that the Tab.CurrentRecord sometimes not get the right record.

...
faEdit: begin
      if Tab.Retrieve(Client,Tab.List.Row,False) then
      try
          isOK:= CRUD(Tab.CurrentRecord,'',False);
          if isOK then
            if Client.Update(Tab.CurrentRecord) then
              Ribbon.GotoRecord(Tab.CurrentRecord);
      finally
        Client.UnLock(Tab.CurrentRecord);
      end;
    end;
....

//CRUD
function TfrmMain.CRUD(aRec: TSQLRecord; const aTitle: string; aReadOnly: boolean): boolean;
var
  BPBaseEditForm: TBPBaseEditForm;
begin
  BPBaseEditForm:= TBPBaseEditForm.Create(Self);
  try
    BPBaseEditForm.SetRecord(Client,aRec,nil,Ribbon,'',0,'');
    Result := BPBaseEditForm.ShowModal= mrOk;
  finally
    BPBaseEditForm.Free;
  end;
end;

i'll try to step by step debuging more carefully.
ok i'll take a look the documentation again about TSQLRecordMany.

Thank you

#33 mORMot 1 » Problem with TSQLRecord.ClearProperties method » 2012-04-29 13:14:51

coblongpamor
Replies: 2

I get AV error when calling a method TSQLRecord.ClrearProperties with sftEnumerate  on property.
for the quick fix, i just add sftEnumerate to the subtraction of COPIABLE_FIELDS.

 
COPIABLE_FIELDS: TSQLFieldTypes =
    [low(TSQLFieldType)..high(TSQLFieldType)] - [sftUnknown, sftEnumerate, sftMany];

#34 Re: mORMot 1 » "has many" and "has many through" relationships » 2012-04-28 19:14:18

In your normal code, you should better know the exact type of PM.

Yes, i understand.

But I think you are using a more generic functionality here, for all TSQLRecordMany.

You are right. i like control generation from the RecordEditForm.
i try to inheriting RecordEditForm, then modify it to agree with my requirement.

But, sometimes i have AV error that i can not fix.
many times debuger break at the line 15057 of the SQLite3Commons

if MainField[ReturnFirstIfNoUnique]<0 then

also at the line 13952

mov edx,[eax+vmtAutoTable]

i just doubleclick the row in the MainForm then press the Save button.

You'll have to destroy the Dest instance created as such manually;

Yes, i understand.

If you use a JOINed query, the Dest instance may be created by the framework.

i don't understand with this one. did you mean that it also need destroy by manualy?

#35 Re: mORMot 1 » "has many" and "has many through" relationships » 2012-04-28 16:49:07

thank you. so, now i can write something like this:

DestClass:= PM.fMany.RecordProps.RecordManyDestClass;
PM.Dest:= DestClass.Create;

#36 Re: Source Code repository » SQLite3 Framework User Interface Generation using VCL » 2012-04-28 16:45:07

sorry for the question is not so obvious.
to make no.1 and no.2 more clear, might be better if I make it directly on the form as follows:

object Form1: TForm1
  Left = 192
  Top = 124
  Width = 870
  Height = 552
  Caption = 'Form1'
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'MS Sans Serif'
  Font.Style = []
  OldCreateOrder = False
  PixelsPerInch = 96
  TextHeight = 13
  object pgc1: TPageControl
    Left = 0
    Top = 0
    Width = 854
    Height = 145
    ActivePage = ts1
    Align = alTop
    TabOrder = 0
    object ts1: TTabSheet
      Caption = 'Home'
      object pgc2: TPageControl
        Left = 0
        Top = 0
        Width = 846
        Height = 117
        ActivePage = ts6
        Align = alClient
        TabOrder = 0
        object ts6: TTabSheet
          Caption = 'Family Card'
        end
        object ts23: TTabSheet
          Caption = '...'
          ImageIndex = 1
        end
      end
    end
    object ts2: TTabSheet
      Caption = 'Regional'
      ImageIndex = 1
      object pgc3: TPageControl
        Left = 0
        Top = 0
        Width = 846
        Height = 117
        ActivePage = ts13
        Align = alClient
        TabOrder = 0
        object ts7: TTabSheet
          Caption = 'City'
        end
        object ts8: TTabSheet
          Caption = 'Country'
          ImageIndex = 1
        end
        object ts9: TTabSheet
          Caption = 'Province'
          ImageIndex = 2
        end
        object ts10: TTabSheet
          Caption = 'Regency'
          ImageIndex = 3
        end
        object ts11: TTabSheet
          Caption = 'Sub District'
          ImageIndex = 4
        end
        object ts12: TTabSheet
          Caption = 'Village'
          ImageIndex = 5
        end
        object ts13: TTabSheet
          Caption = 'Hamlet'
          ImageIndex = 6
        end
      end
    end
    object ts3: TTabSheet
      Caption = 'People'
      ImageIndex = 2
      object pgc4: TPageControl
        Left = 0
        Top = 0
        Width = 846
        Height = 117
        ActivePage = ts22
        Align = alClient
        TabOrder = 0
        object ts14: TTabSheet
          Caption = 'Address'
        end
        object ts15: TTabSheet
          Caption = 'Education'
          ImageIndex = 1
        end
        object ts16: TTabSheet
          Caption = 'Job'
          ImageIndex = 2
        end
        object ts17: TTabSheet
          Caption = 'People'
          ImageIndex = 3
        end
        object ts22: TTabSheet
          Caption = '...'
          ImageIndex = 4
        end
      end
    end
    object ts4: TTabSheet
      Caption = 'Identity'
      ImageIndex = 3
      object pgc5: TPageControl
        Left = 0
        Top = 0
        Width = 846
        Height = 117
        ActivePage = ts21
        Align = alClient
        TabOrder = 0
        object ts18: TTabSheet
          Caption = 'SIN'
        end
        object ts19: TTabSheet
          Caption = 'Passport'
          ImageIndex = 1
        end
        object ts20: TTabSheet
          Caption = 'KITAS'
          ImageIndex = 2
        end
        object ts21: TTabSheet
          Caption = '...'
          ImageIndex = 3
        end
      end
    end
    object ts5: TTabSheet
      Caption = 'Utility'
      ImageIndex = 4
      object pgc6: TPageControl
        Left = 0
        Top = 0
        Width = 846
        Height = 117
        ActivePage = ts24
        Align = alClient
        TabOrder = 0
        object ts24: TTabSheet
          Caption = 'Audit Trail'
        end
        object ts25: TTabSheet
          Caption = 'User Log'
          ImageIndex = 1
        end
        object ts26: TTabSheet
          Caption = 'Error Log'
          ImageIndex = 2
        end
        object ts27: TTabSheet
          Caption = '....'
          ImageIndex = 3
        end
      end
    end
  end
  object pgc7: TPageControl
    Left = 0
    Top = 145
    Width = 854
    Height = 369
    ActivePage = ts28
    Align = alClient
    TabOrder = 1
    object ts28: TTabSheet
      Caption = 'Family Card'
      object lbl2: TLabel
        Left = 0
        Top = 0
        Width = 846
        Height = 13
        Align = alTop
        Caption = 
          'If TSQLFamilyCard is Selected, i want to show User Interface thi' +
          's.'
      end
      object pgc8: TPageControl
        Left = 0
        Top = 13
        Width = 846
        Height = 328
        ActivePage = ts29
        Align = alClient
        TabOrder = 0
        object ts29: TTabSheet
          Caption = 'Family Card-1'
          object pnl1: TPanel
            Left = 0
            Top = 0
            Width = 838
            Height = 73
            Align = alTop
            Caption = 'pnl1'
            TabOrder = 0
            object lbl1: TLabel
              Left = 32
              Top = 48
              Width = 45
              Height = 13
              Caption = 'Patriarch:'
            end
            object lbledt1: TLabeledEdit
              Left = 128
              Top = 16
              Width = 121
              Height = 21
              EditLabel.Width = 94
              EditLabel.Height = 13
              EditLabel.Caption = 'Family Card Number'
              EditLabel.Transparent = True
              LabelPosition = lpLeft
              TabOrder = 0
            end
            object cbb1: TComboBox
              Left = 128
              Top = 40
              Width = 145
              Height = 21
              ItemHeight = 13
              TabOrder = 1
              Text = 'cbb1'
            end
          end
          object grp1: TGroupBox
            Left = 0
            Top = 73
            Width = 838
            Height = 227
            Align = alClient
            Caption = 'Family Member'
            TabOrder = 1
            object dg1: TDrawGrid
              Left = 2
              Top = 15
              Width = 834
              Height = 210
              Align = alClient
              TabOrder = 0
            end
          end
        end
        object ts30: TTabSheet
          Caption = 'Family Card-2'
          ImageIndex = 1
        end
        object ts31: TTabSheet
          Caption = 'Family Card-3'
          ImageIndex = 2
        end
        object ts32: TTabSheet
          Caption = 'Family Card-4'
          ImageIndex = 3
        end
        object ts33: TTabSheet
          Caption = 'Family Card-5'
          ImageIndex = 4
        end
        object ts34: TTabSheet
          Caption = '...'
          ImageIndex = 5
        end
      end
    end
  end
end

3. ok. i do as follow

var
  TB: TSQLCustomToolBar;
begin
  SynPager:= TSynPager.Create(Self);
  SynPager.Parent:= pnl2;
  SynPager.Align:= alClient;
  TB.Init(SynPager,TypeInfo(TFileAction),nil,il32,sFileActionsHints);
  TB.Page.PageControl:= SynPager;
  TB.AddToolBar('Record');

thank you.

#37 Re: mORMot 1 » Overall RTTI usage » 2012-04-28 11:53:18

i need to know the Class of sftID SQLFieldType
this is what SetRecord() procedure does in the RecordEditForm

sftID:
  if aClient<>nil then begin
	// ID field (TSQLRecord descendant) is handled by a TComboBox component
	// with all possible values of the corresponding TSQLRecord descendant
	IDClass := TSQLRecordClass(P^.PropType^^.ClassType^.ClassType);
	CB := TComboBox.Create(Scroll);
....

#38 Re: mORMot 1 » Sample i18n » 2012-04-28 09:58:38

ok. thank you. maybe I'll use Notepad + +

I'd love to contribute, but frankly, I do not feel confident.

#39 Re: mORMot 1 » Sample i18n » 2012-04-28 09:52:57

ok. thank you. maybe I'll use Notepad + +

I'd love to contribute, but frankly, I do not feel confident.

#40 Re: mORMot 1 » "has many" and "has many through" relationships » 2012-04-28 07:44:27

could you add GetSourceClass and GetDestClass to the TSQLRecordMany?

thank you.

#41 Re: Source Code repository » SQLite3 Framework User Interface Generation using VCL » 2012-04-28 05:07:15

In the project I was developing, there are many records to be displayed on the Ribbon.
So that not all records can appear on the screen (although there are navigation buttons (Prev Page and Next Page) on TSynPager).
TabGroup also not all can appear on the screen, because one group can have a lot of records.
The following fact what I need to my current project, which is associated with the Ribbon and ToolBar.
1. only associate records (TSynPage) which the group must be shown.
- Might be better if TopMostPanel replaced by TPageControl.
2. in particular TSQLRecordClass I also need to show a different behavior. Is there an easy way to override TSynBodyPager?
- for instance, I do not want to display data in a grid, but with PageControl.
3. I also need TSQLCustomToolBar can be placed on the TPanel or the other TWinControl class. But TSQLCustomToolBar.Init () does not allow it.

Thank you

#42 Re: mORMot 1 » Sample i18n » 2012-04-28 04:13:12

What if after we call ExtractAllResources, and we've made a translation in the file *. Msg, and later we need to add or change the strings on the project we also need to be translate?
whether we should call ExtractAllResources again, then add and translate to the file *. msg?
I think this way is arduous.
is possible in the future will be made such a small program like kdlscan.exe?

Thank you.

#43 Re: mORMot 1 » Overall RTTI usage » 2012-04-28 03:08:51

is there any simple method to get classtype from PPropInfo? instead of using

TSQLRecordClass(P^.PropType^^.ClassType^.ClassType)

thank you.

#45 Re: mORMot 1 » Need Help about SQLite3UIEdit » 2012-04-19 18:00:25

hi. i solved the problem. should be

RecordEditForm.SetRecord(frmMain.Client,aRec,nil,Ribbon);

because Client variable exists in the RecordEditForm and frmMain form.

But, i have another issue with RecordEditForm.
How is the best way to implement the following scenario:
1. When RecordEditForm in mode to be Create, and everything is Ok to add a Record, I wish the form is still showing, and ready to receive new input from the user (all editor is blank).
- For that, I did it by adding a parameter CRUDAction: (caCreate, caRead, caUpdate, caDelete) on Procedure SetRecord(..)

if CRUDAction = caCreate then begin
	if Client.Add (Rec, True)> 0 then begin
		Rec.ClearProperties; //sometimes i get AV in this.
		Self.Hide;
		SetRecord (Client, Rec, caCreate, nil, fRibbon);
		Self.Show;
	end;
end else
	ModalResult: = mrOK;// Update Mode (CRUDAction = caUpdate)

2. When user click the Cancel button, and if there are field(s) had changed, firstly, I want ask to user, whether the changes they made to the save or not.
- For this purpose, I've tried doing a litle test as follows:

...
sftID: begin
           SetIndex if <0 then
             AID: = 0 else
           begin
             AID: = PtrInt (CB.Items.Objects [SetIndex]);
             if AID <> StrToInt (Rec.GetFieldValue (S2U (P ^. Name))) then / / this value is changed
               MessageBox (0, PAnsiChar (Rec.GetFieldValue (S2U (P ^. Name))), PAnsiChar (IntToStr (AID)), 0);
           end;
           P ^. SetOrdValue (Rec, AID);
           Include (ModifiedFields, FieldIndex);
         end;
...

but, likely I need to split BtnSaveClick procedure;

I need your advice.

#46 Re: mORMot 1 » Need Help about SQLite3UIEdit » 2012-04-18 15:29:43

ok, thank you. i'll try to debug more carefully.

#47 Re: mORMot 1 » Need Help about SQLite3UIEdit » 2012-04-18 09:31:33

that is what i don't understand.
at this time

RecordEditForm.SetRecord(Client,aRec,nil,Ribbon);

debuger show me hint something like

Client=(fCache:nil;fTransactionActive:0;fTransactionCriticalSession:(DebugInfo:$1F4CD8;.............

but, in the SQLite3UIEdit

..
fRec := aRecord;
fClient := aClient; //here debuger shown hint aClient = nil.
CW := Scroll.ClientWidth;
...

#48 Re: mORMot 1 » Need Help about SQLite3UIEdit » 2012-04-18 06:13:06

no. i'd toggled breakpoint (F5) at

RecordEditForm.SetRecord(Client,aRec,nil,Ribbon);

in this breakpoint, Client not nil.
i also toggled breakpoint in the SQLite3UIEdit.pas at this line:

..
fRec := aRecord;
fClient := aClient; //here aClient is nil.
CW := Scroll.ClientWidth;
...

thank you.

#50 Re: mORMot 1 » Need Help about SQLite3UIEdit » 2012-04-18 05:56:08

thank you. but with this way the aClient is still always nil.

Board footer

Powered by FluxBB