mirror of
https://github.com/danieleteti/delphimvcframework.git
synced 2024-11-15 15:55:54 +01:00
Almost completed merge method for tmvcactiverecord
This commit is contained in:
parent
d9ebea3d0f
commit
962bd6fbf3
@ -442,7 +442,7 @@ begin
|
||||
Result := '';
|
||||
if PKIsNull then
|
||||
Result := '<null>';
|
||||
Result := Format('[ID: %6s][CODE: %6s][CompanyName: %15s][City: %10s][Rating: %3d][Note: %s]',[
|
||||
Result := Format('[ID: %6s][CODE: %6s][CompanyName: %18s][City: %16s][Rating: %3d][Note: %s]',[
|
||||
Result, fCode.ValueOrDefault, fCompanyName.ValueOrDefault, fCity, fRating.ValueOrDefault, fNote]);
|
||||
end;
|
||||
|
||||
|
@ -72,7 +72,6 @@ type
|
||||
private
|
||||
procedure Log(const Value: string);
|
||||
procedure LoadCustomers;
|
||||
function Merge<T: TMVCActiveRecord>(CurrentList, NewList: TObjectList<T>): IMVCMultiExecutor<T>;
|
||||
public
|
||||
{ Public declarations }
|
||||
end;
|
||||
@ -441,36 +440,74 @@ var
|
||||
lCustomersChanges: TObjectList<TCustomer>;
|
||||
lMultiExecutor: IMVCMultiExecutor<TCustomer>;
|
||||
begin
|
||||
Log('** IMVCMultiExecutor demo');
|
||||
TMVCActiveRecord.DeleteAll(TCustomer);
|
||||
LoadCustomers;
|
||||
lCustomers := TMVCActiveRecord.All<TCustomer>;
|
||||
lCustomers := TMVCActiveRecord.SelectRQL<TCustomer>('eq(rating,1)', 1000);
|
||||
try
|
||||
lCustomersChanges := TMVCActiveRecord.SelectRQL<TCustomer>('eq(city,"Rome")', 1000);
|
||||
lCustomersChanges := TObjectList<TCustomer>.Create(True);
|
||||
try
|
||||
lCustomersChanges.Delete(0);
|
||||
lCustomersChanges[1].CompanyName := 'Changed';
|
||||
//these 2 customers will be updated
|
||||
lCustomer := TCustomer.Create;
|
||||
lCustomersChanges.Add(lCustomer);
|
||||
lCustomer.ID := lCustomers[0].ID;
|
||||
lCustomer.Code := 'C8765';
|
||||
lCustomer.CompanyName := 'New Company';
|
||||
lCustomer.City := 'New City';
|
||||
lCustomer.Rating := 3;
|
||||
lCustomer.CompanyName := '(changed) Company1';
|
||||
lCustomer.City := '(changed) City';
|
||||
lCustomer.Rating := 1;
|
||||
|
||||
lCustomer := TCustomer.Create;
|
||||
lCustomersChanges.Add(lCustomer);
|
||||
lCustomer.ID := lCustomers[1].ID;
|
||||
lCustomer.Code := lCustomers[1].Code;
|
||||
lCustomer.CompanyName := '(changed) Company2';
|
||||
lCustomer.City := '(changed) City';
|
||||
lCustomer.Rating := 1;
|
||||
|
||||
|
||||
//these 2 customer will be created
|
||||
lCustomer := TCustomer.Create;
|
||||
lCustomersChanges.Add(lCustomer);
|
||||
lCustomer.Code := 'C9898';
|
||||
lCustomer.CompanyName := 'New Company2';
|
||||
lCustomer.City := 'New City2';
|
||||
lCustomer.Rating := 5;
|
||||
lCustomer.CompanyName := '(new) Company3';
|
||||
lCustomer.City := '(new) New City2';
|
||||
lCustomer.Rating := 1;
|
||||
|
||||
lMultiExecutor := Merge<TCustomer>(lCustomers, lCustomersChanges);
|
||||
lMultiExecutor.Apply;
|
||||
lCustomer := TCustomer.Create;
|
||||
lCustomersChanges.Add(lCustomer);
|
||||
lCustomer.Code := 'C2343';
|
||||
lCustomer.CompanyName := '(new) Company4';
|
||||
lCustomer.City := '(new) New City2';
|
||||
lCustomer.Rating := 1;
|
||||
|
||||
//all the other customers will be deleted
|
||||
|
||||
|
||||
//calculate the unitofwork to merge the lists
|
||||
TMVCActiveRecord.Merge<TCustomer>(lCustomers, lCustomersChanges).Apply(
|
||||
procedure (const Customer: TCustomer; const EntityAction: TMVCEntityAction; var Handled: Boolean)
|
||||
begin
|
||||
Handled := False; //set it to true to execute action manually
|
||||
case EntityAction of
|
||||
eaCreate: Log('Inserting Customer : ' + Customer.ToString);
|
||||
eaUpdate: Log('Updating Customer : ' + Customer.ToString);
|
||||
eaDelete: Log('Deleting Customer : ' + Customer.ToString);
|
||||
end;
|
||||
end);
|
||||
finally
|
||||
lCustomers.Free;
|
||||
end;
|
||||
finally
|
||||
lCustomersChanges.Free;
|
||||
end;
|
||||
|
||||
|
||||
lCustomers := TMVCActiveRecord.SelectRQL<TCustomer>('eq(rating,1)', 1000);
|
||||
try
|
||||
Assert(lCustomers.Count = 4, 'Expected 4 customers, got ' + lCustomers.Count.ToString);
|
||||
finally
|
||||
lCustomers.Free;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TMainForm.btnMultiThreadingClick(Sender: TObject);
|
||||
@ -1326,57 +1363,5 @@ begin
|
||||
Memo1.Update;
|
||||
end;
|
||||
|
||||
function TMainForm.Merge<T>(CurrentList, NewList: TObjectList<T>): IMVCMultiExecutor<T>;
|
||||
var
|
||||
I: Integer;
|
||||
lFoundAtIndex: Integer;
|
||||
lCurrPKValue: Integer;
|
||||
lPKValue: TValue;
|
||||
lUnitOfWork: IMVCUnitOfWork<T>;
|
||||
begin
|
||||
lUnitOfWork := TMVCUnitOfWork<T>.Create;
|
||||
lUnitOfWork.RegisterDelete(CurrentList);
|
||||
for I := 0 to NewList.Count - 1 do
|
||||
begin
|
||||
if NewList[I].PKIsNull then
|
||||
begin
|
||||
lUnitOfWork.RegisterInsert(NewList[I]);
|
||||
Continue;
|
||||
end;
|
||||
lCurrPKValue := NewList[I].GetPK.AsInteger;
|
||||
if TMVCUnitOfWork<T>.KeyExists(CurrentList, lCurrPKValue, lFoundAtIndex) then
|
||||
begin
|
||||
// update
|
||||
lUnitOfWork.RegisterUpdate(NewList[I]);
|
||||
// if KeyExists<T>(lToDelete, lCurrPKValue, lFoundAtIndex) then
|
||||
// begin
|
||||
// lUnitOfWork.UnregisterDelete(NewList[I]);
|
||||
// end
|
||||
// else
|
||||
// begin
|
||||
// raise EMVCActiveRecordNotFound.CreateFmt
|
||||
// ('Cannot update a non existent record [PK: %s]', [lCurrPKValue.ToString]);
|
||||
// end;
|
||||
end
|
||||
else
|
||||
begin
|
||||
// insert
|
||||
lUnitOfWork.RegisterInsert(NewList[I]);
|
||||
end;
|
||||
end;
|
||||
Result := lUnitOfWork as IMVCMultiExecutor<T>;
|
||||
// for I := 0 to lToInsert.Count - 1 do
|
||||
// begin
|
||||
// Log('INSERT: ' + lToInsert[I].ToString);
|
||||
// end;
|
||||
// for I := 0 to lToUpdate.Count - 1 do
|
||||
// begin
|
||||
// Log('UPDATE: ' + lToUpdate[I].ToString);
|
||||
// end;
|
||||
// for I := 0 to lToDelete.Count - 1 do
|
||||
// begin
|
||||
// Log('DELETE: ' + lToDelete[I].ToString);
|
||||
// end;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
@ -58,6 +58,7 @@ type
|
||||
end;
|
||||
|
||||
TMVCActiveRecordClass = class of TMVCActiveRecord;
|
||||
TMVCActiveRecord = class;
|
||||
TMVCActiveRecordFieldOption = (foPrimaryKey, { it's the primary key of the mapped table }
|
||||
foAutoGenerated, { not written, read - similar to readonly }
|
||||
foTransient, { not written, not read }
|
||||
@ -83,6 +84,25 @@ type
|
||||
const id: Integer; var Handled: Boolean);
|
||||
end;
|
||||
|
||||
IMVCUnitOfWork<T: TMVCActiveRecord> = interface
|
||||
['{68B55DD3-57F6-4CC0-A4DE-BFDE7C3AA287}']
|
||||
procedure RegisterDelete(const Value: T); overload;
|
||||
procedure RegisterDelete(const Enumerable: TEnumerable<T>); overload;
|
||||
procedure RegisterUpdate(const Value: T);
|
||||
procedure RegisterInsert(const Value: T);
|
||||
procedure UnregisterDelete(const Value: T);
|
||||
procedure UnregisterUpdate(const Value: T);
|
||||
procedure UnregisterInsert(const Value: T);
|
||||
end;
|
||||
|
||||
|
||||
TMVCItemApplyAction<T: TMVCActiveRecord> = reference to procedure (const Obj: T; const EntityAction: TMVCEntityAction; var Handled: Boolean);
|
||||
|
||||
IMVCMultiExecutor<T: TMVCActiveRecord> = interface
|
||||
['{C815246B-19CA-4F6C-AA67-8E491F809340}']
|
||||
procedure Apply(const ItemApplyAction: TMVCItemApplyAction<T> = nil);
|
||||
end;
|
||||
|
||||
TFieldInfo = class
|
||||
public
|
||||
// TableName: string;
|
||||
@ -135,8 +155,6 @@ type
|
||||
|
||||
end;
|
||||
|
||||
TMVCActiveRecord = class;
|
||||
|
||||
TMVCSQLGenerator = class;
|
||||
|
||||
TMVCActiveRecordList = class(TObjectList<TMVCActiveRecord>)
|
||||
@ -170,8 +188,6 @@ type
|
||||
fPropsAttributes: TArray<TCustomAttribute>;
|
||||
fTableName: string;
|
||||
fMap: TFieldsMap;
|
||||
// fMapNonTransientFields: TFieldsMap;
|
||||
// fMapFieldDataTypes: TDictionary<string, string>;
|
||||
fPrimaryKey: TRTTIField;
|
||||
fBackendDriver: string;
|
||||
fMapping: TMVCFieldsMapping;
|
||||
@ -353,6 +369,8 @@ type
|
||||
class function GetFirstByWhere<T: TMVCActiveRecord, constructor>(const SQLWhere: string;
|
||||
const Params: array of Variant; const ParamTypes: array of TFieldType;
|
||||
const RaiseExceptionIfNotFound: Boolean = True): T; overload;
|
||||
class function Merge<T: TMVCActiveRecord>(CurrentList,
|
||||
NewList: TObjectList<T>): IMVCMultiExecutor<T>;
|
||||
end;
|
||||
|
||||
IMVCEntitiesRegistry = interface
|
||||
@ -489,32 +507,14 @@ type
|
||||
function GetSQLGenerator(const aBackend: string): TMVCSQLGeneratorClass;
|
||||
end;
|
||||
|
||||
IMVCUnitOfWork<T: TMVCActiveRecord> = interface
|
||||
['{68B55DD3-57F6-4CC0-A4DE-BFDE7C3AA287}']
|
||||
procedure RegisterDelete(const Value: T); overload;
|
||||
procedure RegisterDelete(const Enumerable: TEnumerable<T>); overload;
|
||||
procedure RegisterUpdate(const Value: T);
|
||||
procedure RegisterInsert(const Value: T);
|
||||
procedure UnregisterDelete(const Value: T);
|
||||
procedure UnregisterUpdate(const Value: T);
|
||||
procedure UnregisterInsert(const Value: T);
|
||||
end;
|
||||
|
||||
IMVCMultiExecutor<T: TMVCActiveRecord> = interface
|
||||
['{C815246B-19CA-4F6C-AA67-8E491F809340}']
|
||||
procedure Apply;
|
||||
end;
|
||||
|
||||
TMVCUnitOfWork<T: TMVCActiveRecord> = class(TInterfacedObject, IMVCUnitOfWork<T>, IMVCMultiExecutor<T>)
|
||||
private
|
||||
fListToDelete: TObjectList<T>;
|
||||
fListToUpdate: TObjectList<T>;
|
||||
fListToInsert: TObjectList<T>;
|
||||
protected
|
||||
|
||||
|
||||
//multiexecutor
|
||||
procedure Apply;
|
||||
procedure Apply(const ItemApplyAction: TMVCItemApplyAction<T> = nil);
|
||||
//unitofwork
|
||||
procedure RegisterDelete(const Value: T); overload;
|
||||
procedure RegisterDelete(const Enumerable: TEnumerable<T>); overload;
|
||||
@ -524,10 +524,9 @@ type
|
||||
procedure UnregisterUpdate(const Value: T);
|
||||
procedure UnregisterInsert(const Value: T);
|
||||
|
||||
//other methods
|
||||
function GetListToDelete: TList<T>;
|
||||
function GetListToUpdate: TList<T>;
|
||||
function GetListToInsert: TList<T>;
|
||||
//events
|
||||
procedure DoItemApplyAction(const Obj: TMVCActiveRecord; const EntityAction: TMVCEntityAction; const ItemApplyAction: TMVCItemApplyAction<T>; var Handled: Boolean);
|
||||
|
||||
class function KeyExists(const NewList: TObjectList<T>; const KeyValue: Integer;
|
||||
out Index: Integer): Boolean;
|
||||
public
|
||||
@ -536,9 +535,7 @@ type
|
||||
end;
|
||||
|
||||
function ActiveRecordConnectionsRegistry: IMVCActiveRecordConnections;
|
||||
|
||||
function ActiveRecordMappingRegistry: IMVCEntitiesRegistry;
|
||||
|
||||
function GetBackEndByConnection(aConnection: TFDConnection): string;
|
||||
|
||||
implementation
|
||||
@ -2592,6 +2589,61 @@ class function TMVCActiveRecordHelper.Where<T>(const SQLWhere: string; const Par
|
||||
begin
|
||||
Result := Where<T>(SQLWhere, Params, []);
|
||||
end;
|
||||
|
||||
class function TMVCActiveRecordHelper.Merge<T>(CurrentList, NewList: TObjectList<T>): IMVCMultiExecutor<T>;
|
||||
var
|
||||
I: Integer;
|
||||
lFoundAtIndex: Integer;
|
||||
lCurrPKValue: Integer;
|
||||
lPKValue: TValue;
|
||||
lUnitOfWork: IMVCUnitOfWork<T>;
|
||||
begin
|
||||
lUnitOfWork := TMVCUnitOfWork<T>.Create;
|
||||
lUnitOfWork.RegisterDelete(CurrentList);
|
||||
for I := 0 to NewList.Count - 1 do
|
||||
begin
|
||||
if NewList[I].PKIsNull then
|
||||
begin
|
||||
lUnitOfWork.RegisterInsert(NewList[I]);
|
||||
Continue;
|
||||
end;
|
||||
lCurrPKValue := NewList[I].GetPK.AsInteger;
|
||||
if TMVCUnitOfWork<T>.KeyExists(CurrentList, lCurrPKValue, lFoundAtIndex) then
|
||||
begin
|
||||
// update
|
||||
lUnitOfWork.RegisterUpdate(NewList[I]);
|
||||
// if KeyExists<T>(lToDelete, lCurrPKValue, lFoundAtIndex) then
|
||||
// begin
|
||||
// lUnitOfWork.UnregisterDelete(NewList[I]);
|
||||
// end
|
||||
// else
|
||||
// begin
|
||||
// raise EMVCActiveRecordNotFound.CreateFmt
|
||||
// ('Cannot update a non existent record [PK: %s]', [lCurrPKValue.ToString]);
|
||||
// end;
|
||||
end
|
||||
else
|
||||
begin
|
||||
// insert
|
||||
lUnitOfWork.RegisterInsert(NewList[I]);
|
||||
end;
|
||||
end;
|
||||
Result := lUnitOfWork as IMVCMultiExecutor<T>;
|
||||
// for I := 0 to lToInsert.Count - 1 do
|
||||
// begin
|
||||
// Log('INSERT: ' + lToInsert[I].ToString);
|
||||
// end;
|
||||
// for I := 0 to lToUpdate.Count - 1 do
|
||||
// begin
|
||||
// Log('UPDATE: ' + lToUpdate[I].ToString);
|
||||
// end;
|
||||
// for I := 0 to lToDelete.Count - 1 do
|
||||
// begin
|
||||
// Log('DELETE: ' + lToDelete[I].ToString);
|
||||
// end;
|
||||
end;
|
||||
|
||||
|
||||
{ PrimaryKeyAttribute }
|
||||
|
||||
// constructor MVCPrimaryKeyAttribute.Create(const aFieldName: string);
|
||||
@ -2965,21 +3017,37 @@ end;
|
||||
|
||||
{ TMVCUnitOfWork<T> }
|
||||
|
||||
procedure TMVCUnitOfWork<T>.Apply;
|
||||
procedure TMVCUnitOfWork<T>.Apply(const ItemApplyAction: TMVCItemApplyAction<T>);
|
||||
var
|
||||
I: UInt32;
|
||||
lHandled: Boolean;
|
||||
begin
|
||||
for I := 0 to fListToInsert.Count - 1 do
|
||||
begin
|
||||
fListToInsert[I].Insert;
|
||||
lHandled := False;
|
||||
DoItemApplyAction(fListToInsert[I], eaCreate, ItemApplyAction, lHandled);
|
||||
if not lHandled then
|
||||
begin
|
||||
fListToInsert[I].Insert;
|
||||
end;
|
||||
end;
|
||||
for I := 0 to fListToUpdate.Count - 1 do
|
||||
begin
|
||||
fListToUpdate[I].Update;
|
||||
lHandled := False;
|
||||
DoItemApplyAction(fListToUpdate[I], eaUpdate, ItemApplyAction, lHandled);
|
||||
if not lHandled then
|
||||
begin
|
||||
fListToUpdate[I].Update;
|
||||
end;
|
||||
end;
|
||||
for I := 0 to fListToDelete.Count - 1 do
|
||||
begin
|
||||
fListToDelete[I].Delete;
|
||||
lHandled := False;
|
||||
DoItemApplyAction(fListToDelete[I], eaDelete, ItemApplyAction, lHandled);
|
||||
if not lHandled then
|
||||
begin
|
||||
fListToDelete[I].Delete;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -2999,20 +3067,31 @@ begin
|
||||
inherited;
|
||||
end;
|
||||
|
||||
function TMVCUnitOfWork<T>.GetListToDelete: TList<T>;
|
||||
procedure TMVCUnitOfWork<T>.DoItemApplyAction(const Obj: TMVCActiveRecord;
|
||||
const EntityAction: TMVCEntityAction;
|
||||
const ItemApplyAction: TMVCItemApplyAction<T>;
|
||||
var Handled: Boolean);
|
||||
begin
|
||||
Result := fListToDelete;
|
||||
if Assigned(ItemApplyAction) then
|
||||
begin
|
||||
ItemApplyAction(Obj, EntityAction, Handled);
|
||||
end;
|
||||
end;
|
||||
|
||||
function TMVCUnitOfWork<T>.GetListToInsert: TList<T>;
|
||||
begin
|
||||
Result := fListToInsert;
|
||||
end;
|
||||
|
||||
function TMVCUnitOfWork<T>.GetListToUpdate: TList<T>;
|
||||
begin
|
||||
Result := fListToUpdate;
|
||||
end;
|
||||
//function TMVCUnitOfWork<T>.GetListToDelete: TList<T>;
|
||||
//begin
|
||||
// Result := fListToDelete;
|
||||
//end;
|
||||
//
|
||||
//function TMVCUnitOfWork<T>.GetListToInsert: TList<T>;
|
||||
//begin
|
||||
// Result := fListToInsert;
|
||||
//end;
|
||||
//
|
||||
//function TMVCUnitOfWork<T>.GetListToUpdate: TList<T>;
|
||||
//begin
|
||||
// Result := fListToUpdate;
|
||||
//end;
|
||||
|
||||
class function TMVCUnitOfWork<T>.KeyExists(const NewList: TObjectList<T>;
|
||||
const KeyValue: Integer; out Index: Integer): Boolean;
|
||||
@ -3032,17 +3111,17 @@ end;
|
||||
|
||||
procedure TMVCUnitOfWork<T>.RegisterDelete(const Value: T);
|
||||
begin
|
||||
GetListToDelete.Add(Value);
|
||||
fListToDelete.Add(Value);
|
||||
end;
|
||||
|
||||
procedure TMVCUnitOfWork<T>.RegisterDelete(const Enumerable: TEnumerable<T>);
|
||||
begin
|
||||
GetListToDelete.AddRange(Enumerable);
|
||||
fListToDelete.AddRange(Enumerable);
|
||||
end;
|
||||
|
||||
procedure TMVCUnitOfWork<T>.RegisterInsert(const Value: T);
|
||||
begin
|
||||
GetListToInsert.Add(Value);
|
||||
fListToInsert.Add(Value);
|
||||
end;
|
||||
|
||||
procedure TMVCUnitOfWork<T>.RegisterUpdate(const Value: T);
|
||||
@ -3050,7 +3129,7 @@ var
|
||||
lCurrPKValue: Integer;
|
||||
lFoundAtIndex: Integer;
|
||||
begin
|
||||
GetListToUpdate.Add(Value);
|
||||
fListToUpdate.Add(Value);
|
||||
lCurrPKValue := Value.GetPK.AsInteger;
|
||||
if KeyExists(fListToDelete, lCurrPKValue, lFoundAtIndex) then
|
||||
begin
|
||||
@ -3060,17 +3139,17 @@ end;
|
||||
|
||||
procedure TMVCUnitOfWork<T>.UnregisterDelete(const Value: T);
|
||||
begin
|
||||
GetListToDelete.Remove(Value);
|
||||
fListToDelete.Remove(Value);
|
||||
end;
|
||||
|
||||
procedure TMVCUnitOfWork<T>.UnregisterInsert(const Value: T);
|
||||
begin
|
||||
GetListToInsert.Remove(Value);
|
||||
fListToInsert.Remove(Value);
|
||||
end;
|
||||
|
||||
procedure TMVCUnitOfWork<T>.UnregisterUpdate(const Value: T);
|
||||
begin
|
||||
GetListToUpdate.Remove(Value);
|
||||
fListToUpdate.Remove(Value);
|
||||
end;
|
||||
|
||||
initialization
|
||||
|
@ -1,7 +1,7 @@
|
||||
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<ProjectGuid>{ABDCF3F4-55C9-4C93-9DA7-7E7D35B0FE68}</ProjectGuid>
|
||||
<ProjectVersion>18.8</ProjectVersion>
|
||||
<ProjectVersion>19.2</ProjectVersion>
|
||||
<FrameworkType>VCL</FrameworkType>
|
||||
<MainSource>MVCAREntitiesGenerator.dpr</MainSource>
|
||||
<Base>True</Base>
|
||||
@ -326,6 +326,16 @@
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="Android_LauncherIcon192">
|
||||
<Platform Name="Android">
|
||||
<RemoteDir>res\drawable-xxxhdpi</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="Android64">
|
||||
<RemoteDir>res\drawable-xxxhdpi</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="Android_LauncherIcon36">
|
||||
<Platform Name="Android">
|
||||
<RemoteDir>res\drawable-ldpi</RemoteDir>
|
||||
@ -577,6 +587,32 @@
|
||||
<Operation>0</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iOS_AppStore1024">
|
||||
<Platform Name="iOSDevice64">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPad_AppIcon152">
|
||||
<Platform Name="iOSDevice64">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPad_AppIcon167">
|
||||
<Platform Name="iOSDevice64">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPad_Launch1024">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
@ -709,6 +745,16 @@
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPad_Launch2x">
|
||||
<Platform Name="iOSDevice64">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPad_Launch768">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
@ -731,6 +777,66 @@
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPad_LaunchDark2x">
|
||||
<Platform Name="iOSDevice64">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPad_Notification40">
|
||||
<Platform Name="iOSDevice64">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPad_Setting58">
|
||||
<Platform Name="iOSDevice64">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPad_SpotLight80">
|
||||
<Platform Name="iOSDevice64">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_AppIcon120">
|
||||
<Platform Name="iOSDevice64">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_AppIcon180">
|
||||
<Platform Name="iOSDevice64">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_Launch1125">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
@ -830,6 +936,16 @@
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_Launch2x">
|
||||
<Platform Name="iOSDevice64">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_Launch320">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
@ -841,6 +957,16 @@
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_Launch3x">
|
||||
<Platform Name="iOSDevice64">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_Launch640">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
@ -885,6 +1011,86 @@
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_LaunchDark2x">
|
||||
<Platform Name="iOSDevice64">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_LaunchDark3x">
|
||||
<Platform Name="iOSDevice64">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_Notification40">
|
||||
<Platform Name="iOSDevice64">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_Notification60">
|
||||
<Platform Name="iOSDevice64">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_Setting58">
|
||||
<Platform Name="iOSDevice64">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_Setting87">
|
||||
<Platform Name="iOSDevice64">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_Spotlight120">
|
||||
<Platform Name="iOSDevice64">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="iPhone_Spotlight80">
|
||||
<Platform Name="iOSDevice64">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="ProjectAndroidManifest">
|
||||
<Platform Name="Android">
|
||||
<Operation>1</Operation>
|
||||
@ -932,6 +1138,16 @@
|
||||
<Operation>1</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="ProjectiOSLaunchScreen">
|
||||
<Platform Name="iOSDevice64">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen</RemoteDir>
|
||||
<Operation>64</Operation>
|
||||
</Platform>
|
||||
<Platform Name="iOSSimulator">
|
||||
<RemoteDir>..\$(PROJECTNAME).launchscreen</RemoteDir>
|
||||
<Operation>64</Operation>
|
||||
</Platform>
|
||||
</DeployClass>
|
||||
<DeployClass Name="ProjectiOSResource">
|
||||
<Platform Name="iOSDevice32">
|
||||
<Operation>1</Operation>
|
||||
|
@ -3,7 +3,7 @@ object MainForm: TMainForm
|
||||
Top = 0
|
||||
Caption = '[DMVCFramework] MVCActiveRecord Entity Generator'
|
||||
ClientHeight = 630
|
||||
ClientWidth = 863
|
||||
ClientWidth = 909
|
||||
Color = clBtnFace
|
||||
Font.Charset = DEFAULT_CHARSET
|
||||
Font.Color = clWindowText
|
||||
@ -18,7 +18,7 @@ object MainForm: TMainForm
|
||||
object Splitter1: TSplitter
|
||||
Left = 0
|
||||
Top = 207
|
||||
Width = 863
|
||||
Width = 909
|
||||
Height = 3
|
||||
Cursor = crVSplit
|
||||
Align = alTop
|
||||
@ -28,13 +28,14 @@ object MainForm: TMainForm
|
||||
object Panel1: TPanel
|
||||
Left = 0
|
||||
Top = 0
|
||||
Width = 863
|
||||
Width = 909
|
||||
Height = 39
|
||||
Align = alTop
|
||||
TabOrder = 0
|
||||
ExplicitWidth = 863
|
||||
object Label1: TLabel
|
||||
AlignWithMargins = True
|
||||
Left = 497
|
||||
Left = 543
|
||||
Top = 11
|
||||
Width = 190
|
||||
Height = 17
|
||||
@ -45,11 +46,12 @@ object MainForm: TMainForm
|
||||
Align = alRight
|
||||
Caption = 'Select a FireDAC Connection Definitions'
|
||||
Layout = tlCenter
|
||||
ExplicitLeft = 497
|
||||
ExplicitHeight = 13
|
||||
end
|
||||
object cboConnectionDefs: TComboBox
|
||||
AlignWithMargins = True
|
||||
Left = 707
|
||||
Left = 753
|
||||
Top = 11
|
||||
Width = 145
|
||||
Height = 21
|
||||
@ -60,12 +62,13 @@ object MainForm: TMainForm
|
||||
Align = alRight
|
||||
TabOrder = 0
|
||||
OnChange = cboConnectionDefsChange
|
||||
ExplicitLeft = 707
|
||||
end
|
||||
end
|
||||
object Panel2: TPanel
|
||||
Left = 0
|
||||
Top = 39
|
||||
Width = 863
|
||||
Width = 909
|
||||
Height = 168
|
||||
Align = alTop
|
||||
Caption = 'Panel1'
|
||||
@ -76,11 +79,12 @@ object MainForm: TMainForm
|
||||
Font.Style = []
|
||||
ParentFont = False
|
||||
TabOrder = 1
|
||||
ExplicitWidth = 863
|
||||
object Label2: TLabel
|
||||
AlignWithMargins = True
|
||||
Left = 4
|
||||
Top = 4
|
||||
Width = 855
|
||||
Width = 901
|
||||
Height = 13
|
||||
Align = alTop
|
||||
Caption = 'FireDAC connection parameters'
|
||||
@ -90,7 +94,7 @@ object MainForm: TMainForm
|
||||
AlignWithMargins = True
|
||||
Left = 4
|
||||
Top = 23
|
||||
Width = 489
|
||||
Width = 535
|
||||
Height = 141
|
||||
Align = alClient
|
||||
Font.Charset = ANSI_CHARSET
|
||||
@ -103,9 +107,10 @@ object MainForm: TMainForm
|
||||
TabOrder = 0
|
||||
WordWrap = False
|
||||
OnChange = mmConnectionParamsChange
|
||||
ExplicitWidth = 489
|
||||
end
|
||||
object Panel6: TPanel
|
||||
Left = 496
|
||||
Left = 542
|
||||
Top = 20
|
||||
Width = 366
|
||||
Height = 147
|
||||
@ -114,6 +119,7 @@ object MainForm: TMainForm
|
||||
Caption = 'Panel6'
|
||||
ShowCaption = False
|
||||
TabOrder = 1
|
||||
ExplicitLeft = 496
|
||||
object GroupBox1: TGroupBox
|
||||
AlignWithMargins = True
|
||||
Left = 3
|
||||
@ -166,28 +172,69 @@ object MainForm: TMainForm
|
||||
object Panel3: TPanel
|
||||
Left = 0
|
||||
Top = 210
|
||||
Width = 863
|
||||
Width = 909
|
||||
Height = 420
|
||||
Align = alClient
|
||||
Caption = 'Panel3'
|
||||
TabOrder = 2
|
||||
ExplicitWidth = 863
|
||||
object Panel4: TPanel
|
||||
Left = 1
|
||||
Top = 1
|
||||
Width = 861
|
||||
Height = 41
|
||||
Width = 907
|
||||
Height = 120
|
||||
Align = alTop
|
||||
BevelOuter = bvNone
|
||||
Caption = 'Panel4'
|
||||
ShowCaption = False
|
||||
TabOrder = 0
|
||||
ExplicitWidth = 861
|
||||
DesignSize = (
|
||||
907
|
||||
120)
|
||||
object SpeedButton1: TSpeedButton
|
||||
AlignWithMargins = True
|
||||
Left = 140
|
||||
Top = 4
|
||||
Width = 100
|
||||
Height = 29
|
||||
Margins.Top = 2
|
||||
Margins.Right = 2
|
||||
Margins.Bottom = 2
|
||||
Caption = 'Select All'
|
||||
OnClick = SpeedButton1Click
|
||||
end
|
||||
object SpeedButton2: TSpeedButton
|
||||
AlignWithMargins = True
|
||||
Left = 245
|
||||
Top = 4
|
||||
Width = 100
|
||||
Height = 29
|
||||
Margins.Top = 2
|
||||
Margins.Right = 2
|
||||
Margins.Bottom = 2
|
||||
Caption = 'Select None'
|
||||
OnClick = SpeedButton2Click
|
||||
end
|
||||
object SpeedButton3: TSpeedButton
|
||||
AlignWithMargins = True
|
||||
Left = 350
|
||||
Top = 4
|
||||
Width = 100
|
||||
Height = 29
|
||||
Margins.Top = 2
|
||||
Margins.Right = 2
|
||||
Margins.Bottom = 2
|
||||
Caption = 'Invert Selection'
|
||||
OnClick = SpeedButton3Click
|
||||
end
|
||||
object btnGenEntities: TButton
|
||||
AlignWithMargins = True
|
||||
Left = 129
|
||||
Top = 3
|
||||
Left = 774
|
||||
Top = 82
|
||||
Width = 120
|
||||
Height = 35
|
||||
Align = alLeft
|
||||
Anchors = [akRight, akBottom]
|
||||
Caption = 'Generate Entities'
|
||||
Font.Charset = DEFAULT_CHARSET
|
||||
Font.Color = clWindowText
|
||||
@ -204,7 +251,6 @@ object MainForm: TMainForm
|
||||
Top = 3
|
||||
Width = 120
|
||||
Height = 35
|
||||
Align = alLeft
|
||||
Caption = 'Get Tables'
|
||||
Font.Charset = DEFAULT_CHARSET
|
||||
Font.Color = clWindowText
|
||||
@ -216,42 +262,87 @@ object MainForm: TMainForm
|
||||
OnClick = btnGetTablesClick
|
||||
end
|
||||
object chGenerateMapping: TCheckBox
|
||||
Left = 255
|
||||
Top = 12
|
||||
Width = 514
|
||||
Height = 17
|
||||
AlignWithMargins = True
|
||||
Left = 470
|
||||
Top = -2
|
||||
Width = 262
|
||||
Height = 48
|
||||
Caption =
|
||||
'Register entities in ActiveRecordMappingRegistry (needed by TMVC' +
|
||||
'ActiveRecordController)'
|
||||
Checked = True
|
||||
State = cbChecked
|
||||
TabOrder = 2
|
||||
WordWrap = True
|
||||
end
|
||||
object RadioGroup1: TRadioGroup
|
||||
Left = 7
|
||||
Top = 47
|
||||
Width = 443
|
||||
Height = 70
|
||||
Caption = 'MVCNameCase'
|
||||
Columns = 3
|
||||
ItemIndex = 0
|
||||
Items.Strings = (
|
||||
'LowerCase'
|
||||
'UpperCase'
|
||||
'CamelCase'
|
||||
'PascalCase'
|
||||
'SnakeCase'
|
||||
'AsIs')
|
||||
TabOrder = 3
|
||||
end
|
||||
end
|
||||
object PageControl1: TPageControl
|
||||
AlignWithMargins = True
|
||||
Left = 4
|
||||
Top = 45
|
||||
Width = 855
|
||||
Height = 371
|
||||
Top = 124
|
||||
Width = 901
|
||||
Height = 292
|
||||
ActivePage = TabSheet1
|
||||
Align = alClient
|
||||
TabOrder = 1
|
||||
ExplicitTop = 45
|
||||
ExplicitWidth = 855
|
||||
ExplicitHeight = 371
|
||||
object TabSheet1: TTabSheet
|
||||
Caption = 'Tables'
|
||||
object DBGrid1: TDBGrid
|
||||
Left = 0
|
||||
Top = 0
|
||||
Width = 847
|
||||
Height = 343
|
||||
Width = 893
|
||||
Height = 264
|
||||
Align = alClient
|
||||
DataSource = dsrcTablesMapping
|
||||
DefaultDrawing = False
|
||||
TabOrder = 0
|
||||
TitleFont.Charset = DEFAULT_CHARSET
|
||||
TitleFont.Color = clWindowText
|
||||
TitleFont.Height = -11
|
||||
TitleFont.Name = 'Tahoma'
|
||||
TitleFont.Style = []
|
||||
OnCellClick = DBGrid1CellClick
|
||||
OnDrawColumnCell = DBGrid1DrawColumnCell
|
||||
Columns = <
|
||||
item
|
||||
Expanded = False
|
||||
FieldName = 'GENERATE'
|
||||
PickList.Strings = (
|
||||
'yes'
|
||||
'no')
|
||||
Width = 58
|
||||
Visible = True
|
||||
end
|
||||
item
|
||||
Expanded = False
|
||||
FieldName = 'TABLE_NAME'
|
||||
Visible = True
|
||||
end
|
||||
item
|
||||
Expanded = False
|
||||
FieldName = 'CLASS_NAME'
|
||||
Visible = True
|
||||
end>
|
||||
end
|
||||
end
|
||||
object TabSheet2: TTabSheet
|
||||
@ -261,8 +352,8 @@ object MainForm: TMainForm
|
||||
AlignWithMargins = True
|
||||
Left = 3
|
||||
Top = 44
|
||||
Width = 841
|
||||
Height = 296
|
||||
Width = 887
|
||||
Height = 217
|
||||
Align = alClient
|
||||
BevelInner = bvNone
|
||||
BevelOuter = bvNone
|
||||
@ -277,16 +368,19 @@ object MainForm: TMainForm
|
||||
ScrollBars = ssBoth
|
||||
TabOrder = 0
|
||||
WordWrap = False
|
||||
ExplicitWidth = 841
|
||||
ExplicitHeight = 296
|
||||
end
|
||||
object Panel5: TPanel
|
||||
Left = 0
|
||||
Top = 0
|
||||
Width = 847
|
||||
Width = 893
|
||||
Height = 41
|
||||
Align = alTop
|
||||
Caption = 'Panel5'
|
||||
ShowCaption = False
|
||||
TabOrder = 1
|
||||
ExplicitWidth = 847
|
||||
object btnSaveCode: TButton
|
||||
AlignWithMargins = True
|
||||
Left = 4
|
||||
@ -325,7 +419,7 @@ object MainForm: TMainForm
|
||||
Top = 152
|
||||
end
|
||||
object FDPhysFBDriverLink1: TFDPhysFBDriverLink
|
||||
Left = 616
|
||||
Left = 504
|
||||
Top = 496
|
||||
end
|
||||
object FDGUIxWaitCursor1: TFDGUIxWaitCursor
|
||||
@ -334,8 +428,8 @@ object MainForm: TMainForm
|
||||
Top = 104
|
||||
end
|
||||
object FDPhysMSSQLDriverLink1: TFDPhysMSSQLDriverLink
|
||||
Left = 752
|
||||
Top = 360
|
||||
Left = 784
|
||||
Top = 568
|
||||
end
|
||||
object FileSaveDialog1: TFileSaveDialog
|
||||
FavoriteLinks = <>
|
||||
@ -345,35 +439,51 @@ object MainForm: TMainForm
|
||||
FileMask = '*.pas'
|
||||
end>
|
||||
Options = []
|
||||
Left = 424
|
||||
Top = 320
|
||||
Left = 328
|
||||
Top = 416
|
||||
end
|
||||
object FDPhysMySQLDriverLink1: TFDPhysMySQLDriverLink
|
||||
Left = 752
|
||||
Top = 496
|
||||
Left = 616
|
||||
Top = 568
|
||||
end
|
||||
object FDPhysPgDriverLink1: TFDPhysPgDriverLink
|
||||
Left = 752
|
||||
Top = 424
|
||||
Left = 784
|
||||
Top = 496
|
||||
end
|
||||
object FDPhysFBDriverLink2: TFDPhysFBDriverLink
|
||||
Left = 616
|
||||
Top = 424
|
||||
Top = 408
|
||||
end
|
||||
object FDPhysIBDriverLink1: TFDPhysIBDriverLink
|
||||
Left = 752
|
||||
Top = 280
|
||||
Left = 616
|
||||
Top = 496
|
||||
end
|
||||
object FDPhysMySQLDriverLink2: TFDPhysMySQLDriverLink
|
||||
Left = 616
|
||||
Top = 360
|
||||
Left = 504
|
||||
Top = 568
|
||||
end
|
||||
object FDPhysSQLiteDriverLink1: TFDPhysSQLiteDriverLink
|
||||
Left = 608
|
||||
Top = 280
|
||||
Left = 504
|
||||
Top = 408
|
||||
end
|
||||
object dsTablesMapping: TFDMemTable
|
||||
Active = True
|
||||
FieldDefs = <
|
||||
item
|
||||
Name = 'TABLE_NAME'
|
||||
DataType = ftString
|
||||
Size = 100
|
||||
end
|
||||
item
|
||||
Name = 'CLASS_NAME'
|
||||
DataType = ftString
|
||||
Size = 100
|
||||
end
|
||||
item
|
||||
Name = 'GENERATE'
|
||||
DataType = ftBoolean
|
||||
end>
|
||||
IndexDefs = <>
|
||||
FetchOptions.AssignedValues = [evMode]
|
||||
FetchOptions.Mode = fmAll
|
||||
ResourceOptions.AssignedValues = [rvSilentMode]
|
||||
@ -381,8 +491,13 @@ object MainForm: TMainForm
|
||||
UpdateOptions.AssignedValues = [uvCheckRequired, uvAutoCommitUpdates]
|
||||
UpdateOptions.CheckRequired = False
|
||||
UpdateOptions.AutoCommitUpdates = True
|
||||
Left = 48
|
||||
Top = 304
|
||||
StoreDefs = True
|
||||
Left = 96
|
||||
Top = 504
|
||||
object dsTablesMappingGENERATE: TBooleanField
|
||||
DisplayLabel = 'Generate?'
|
||||
FieldName = 'GENERATE'
|
||||
end
|
||||
object dsTablesMappingTABLE_NAME: TStringField
|
||||
DisplayLabel = 'Table Name'
|
||||
DisplayWidth = 60
|
||||
@ -398,7 +513,7 @@ object MainForm: TMainForm
|
||||
end
|
||||
object dsrcTablesMapping: TDataSource
|
||||
DataSet = dsTablesMapping
|
||||
Left = 48
|
||||
Top = 368
|
||||
Left = 96
|
||||
Top = 448
|
||||
end
|
||||
end
|
||||
|
@ -49,9 +49,11 @@ uses
|
||||
FireDAC.Phys.IB,
|
||||
FireDAC.Stan.ExprFuncs,
|
||||
FireDAC.Phys.SQLiteDef,
|
||||
FireDAC.Phys.SQLite, Vcl.DBGrids, FireDAC.Phys.SQLiteWrapper.Stat;
|
||||
FireDAC.Phys.SQLite, Vcl.DBGrids, FireDAC.Phys.SQLiteWrapper.Stat, Vcl.Buttons;
|
||||
|
||||
type
|
||||
TSelectionType = (stAll, stNone, stInverse);
|
||||
|
||||
TMainForm = class(TForm)
|
||||
FDConnection1: TFDConnection;
|
||||
Panel1: TPanel;
|
||||
@ -93,6 +95,11 @@ type
|
||||
btnRefreshCatalog: TButton;
|
||||
Label1: TLabel;
|
||||
chGenerateMapping: TCheckBox;
|
||||
dsTablesMappingGENERATE: TBooleanField;
|
||||
SpeedButton1: TSpeedButton;
|
||||
SpeedButton2: TSpeedButton;
|
||||
SpeedButton3: TSpeedButton;
|
||||
RadioGroup1: TRadioGroup;
|
||||
procedure btnGenEntitiesClick(Sender: TObject);
|
||||
procedure btnGetTablesClick(Sender: TObject);
|
||||
procedure btnSaveCodeClick(Sender: TObject);
|
||||
@ -103,22 +110,30 @@ type
|
||||
procedure btnRefreshCatalogClick(Sender: TObject);
|
||||
procedure mmConnectionParamsChange(Sender: TObject);
|
||||
procedure lstSchemaDblClick(Sender: TObject);
|
||||
procedure DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect;
|
||||
DataCol: Integer; Column: TColumn; State: TGridDrawState);
|
||||
procedure DBGrid1CellClick(Column: TColumn);
|
||||
procedure SpeedButton2Click(Sender: TObject);
|
||||
procedure SpeedButton3Click(Sender: TObject);
|
||||
procedure SpeedButton1Click(Sender: TObject);
|
||||
private
|
||||
fCatalog: string;
|
||||
fSchema: string;
|
||||
fIntfBuff, fImplBuff, fInitializationBuff: TStringStream;
|
||||
FHistoryFileName: string;
|
||||
lTypesName: TArray<string>;
|
||||
fBookmark: TArray<Byte>;
|
||||
procedure EmitHeaderComments;
|
||||
function GetClassName(const aTableName: string): string;
|
||||
procedure EmitUnit;
|
||||
procedure EmitUnitEnd;
|
||||
procedure EmitProperty(F: TField);
|
||||
procedure EmitField(F: TField; const IsPK: Boolean);
|
||||
procedure EmitClass(const aTableName, aClassName: string);
|
||||
procedure EmitClass(const aTableName, aClassName, aNameCase: string);
|
||||
procedure EmitClassEnd;
|
||||
function GetDelphiType(FT: TFieldType): string;
|
||||
function GetFieldName(const Value: string): string;
|
||||
procedure DoSelection(const SelectionType: TSelectionType);
|
||||
public
|
||||
{ Public declarations }
|
||||
end;
|
||||
@ -126,10 +141,13 @@ type
|
||||
var
|
||||
MainForm: TMainForm;
|
||||
|
||||
const
|
||||
LOG_TAG = 'generator';
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
System.IOUtils, System.TypInfo, System.DateUtils;
|
||||
System.IOUtils, System.TypInfo, System.DateUtils, LoggerPro.GlobalLogger;
|
||||
|
||||
{$R *.dfm}
|
||||
|
||||
@ -146,6 +164,7 @@ var
|
||||
lFieldsName: TArray<string>;
|
||||
lKeyFields: TStringList;
|
||||
begin
|
||||
Log.Info('Starting entities generation', LOG_TAG);
|
||||
fIntfBuff.Clear;
|
||||
fImplBuff.Clear;
|
||||
fInitializationBuff.Clear;
|
||||
@ -157,11 +176,24 @@ begin
|
||||
I := 0;
|
||||
while not dsTablesMapping.Eof do
|
||||
begin
|
||||
if not dsTablesMappingGENERATE.Value then
|
||||
begin
|
||||
Log.Info('Skipping table %s', [dsTablesMappingTABLE_NAME.AsString], LOG_TAG);
|
||||
dsTablesMapping.Next;
|
||||
Continue;
|
||||
end;
|
||||
lTableName := dsTablesMappingTABLE_NAME.AsString;
|
||||
Log.Info('Generating entity %s for table %s', [dsTablesMappingCLASS_NAME.AsString,
|
||||
dsTablesMappingTABLE_NAME.AsString], LOG_TAG);
|
||||
lClassName := dsTablesMappingCLASS_NAME.AsString;
|
||||
EmitClass(lTableName, lClassName);
|
||||
EmitClass(lTableName, lClassName, RadioGroup1.Items[RadioGroup1.ItemIndex]);
|
||||
lKeyFields.Clear;
|
||||
qry.Close;
|
||||
qry.Open('select * from ' + lTableName + ' where 1=0');
|
||||
FDConnection1.GetKeyFieldNames(fCatalog, fSchema, lTableName, '', lKeyFields);
|
||||
try
|
||||
FDConnection1.GetKeyFieldNames(fCatalog, fSchema, lTableName, '', lKeyFields);
|
||||
except
|
||||
end;
|
||||
lFieldsName := [];
|
||||
lTypesName := [];
|
||||
fIntfBuff.WriteString(INDENT + 'private' + sLineBreak);
|
||||
@ -185,7 +217,8 @@ begin
|
||||
fImplBuff.WriteString(' inherited Create;' + sLineBreak);
|
||||
for F := low(lFieldsName) to high(lFieldsName) do
|
||||
begin
|
||||
fImplBuff.WriteString(' ' + lFieldsName[F] + ' := ' + lTypesName[F] + '.Create;' + sLineBreak);
|
||||
fImplBuff.WriteString(' ' + lFieldsName[F] + ' := ' + lTypesName[F] + '.Create;' +
|
||||
sLineBreak);
|
||||
end;
|
||||
fImplBuff.WriteString('end;' + sLineBreak + sLineBreak);
|
||||
|
||||
@ -208,7 +241,8 @@ begin
|
||||
dsTablesMapping.Next;
|
||||
end;
|
||||
EmitUnitEnd;
|
||||
mmOutput.Lines.Text := fIntfBuff.DataString + fImplBuff.DataString + fInitializationBuff.DataString;
|
||||
mmOutput.Lines.Text := fIntfBuff.DataString + fImplBuff.DataString +
|
||||
fInitializationBuff.DataString;
|
||||
|
||||
finally
|
||||
lKeyFields.Free;
|
||||
@ -248,7 +282,7 @@ begin
|
||||
for lTable in lTables do
|
||||
begin
|
||||
lClassName := GetClassName(lTable);
|
||||
dsTablesMapping.AppendRecord([lTable, lClassName]);
|
||||
dsTablesMapping.AppendRecord([True, lTable, lClassName]);
|
||||
end;
|
||||
dsTablesMapping.First;
|
||||
finally
|
||||
@ -286,15 +320,74 @@ begin
|
||||
FDConnection1.Params.Text := mmConnectionParams.Text;
|
||||
end;
|
||||
|
||||
procedure TMainForm.EmitClass(const aTableName, aClassName: string);
|
||||
procedure TMainForm.DBGrid1CellClick(Column: TColumn);
|
||||
begin
|
||||
fIntfBuff.WriteString(INDENT + '[MVCNameCase(ncLowerCase)]' + sLineBreak);
|
||||
if Column.FieldName = 'GENERATE' then
|
||||
begin
|
||||
if not(dsTablesMapping.State = dsEdit) then
|
||||
begin
|
||||
dsTablesMapping.Edit;
|
||||
end;
|
||||
dsTablesMappingGENERATE.Value := not dsTablesMappingGENERATE.Value;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TMainForm.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect;
|
||||
DataCol: Integer; Column: TColumn; State: TGridDrawState);
|
||||
const
|
||||
IsChecked: array [Boolean] of Integer = (DFCS_BUTTONCHECK, DFCS_BUTTONCHECK or DFCS_CHECKED);
|
||||
var
|
||||
DrawState: Integer;
|
||||
DrawRect: TRect;
|
||||
begin
|
||||
if (Column.Field.FieldName = 'GENERATE') then
|
||||
begin
|
||||
DrawRect := Rect;
|
||||
InflateRect(DrawRect, -1, -1);
|
||||
DrawState := IsChecked[Column.Field.AsBoolean];
|
||||
DBGrid1.Canvas.FillRect(Rect);
|
||||
DrawFrameControl(DBGrid1.Canvas.Handle, DrawRect,
|
||||
DFC_BUTTON, DrawState);
|
||||
end
|
||||
else
|
||||
begin
|
||||
DBGrid1.DefaultDrawColumnCell(Rect, DataCol, Column, State);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TMainForm.DoSelection(const SelectionType: TSelectionType);
|
||||
begin
|
||||
dsTablesMapping.DisableControls;
|
||||
try
|
||||
fBookmark := dsTablesMapping.GetBookmark;
|
||||
dsTablesMapping.First;
|
||||
while not dsTablesMapping.Eof do
|
||||
begin
|
||||
dsTablesMapping.Edit;
|
||||
case SelectionType of
|
||||
stAll: dsTablesMappingGENERATE.Value := True;
|
||||
stNone: dsTablesMappingGENERATE.Value := False;
|
||||
stInverse: dsTablesMappingGENERATE.Value := not dsTablesMappingGENERATE.Value;
|
||||
end;
|
||||
dsTablesMapping.Post;
|
||||
dsTablesMapping.Next;
|
||||
end;
|
||||
dsTablesMapping.Bookmark := fBookmark;
|
||||
finally
|
||||
dsTablesMapping.EnableControls;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TMainForm.EmitClass(const aTableName, aClassName, aNameCase: string);
|
||||
begin
|
||||
fIntfBuff.WriteString(INDENT + '[MVCNameCase(nc' + aNameCase + ')]' + sLineBreak);
|
||||
fIntfBuff.WriteString(INDENT + Format('[MVCTable(''%s'')]', [aTableName]) + sLineBreak);
|
||||
if trim(aClassName) = '' then
|
||||
raise Exception.Create('Invalid class name');
|
||||
fIntfBuff.WriteString(INDENT + aClassName + ' = class(TMVCActiveRecord)' + sLineBreak);
|
||||
if chGenerateMapping.Checked then
|
||||
fInitializationBuff.WriteString(INDENT + Format('ActiveRecordMappingRegistry.AddEntity(''%s'',%s);',
|
||||
fInitializationBuff.WriteString
|
||||
(INDENT + Format('ActiveRecordMappingRegistry.AddEntity(''%s'',%s);',
|
||||
[aTableName.ToLower, aClassName]) + sLineBreak);
|
||||
end;
|
||||
|
||||
@ -332,30 +425,40 @@ end;
|
||||
|
||||
procedure TMainForm.EmitHeaderComments;
|
||||
begin
|
||||
fIntfBuff.WriteString('// *************************************************************************** }' +
|
||||
fIntfBuff.WriteString
|
||||
('// *************************************************************************** }' +
|
||||
sLineBreak);
|
||||
fIntfBuff.WriteString('//' + sLineBreak);
|
||||
fIntfBuff.WriteString('// Delphi MVC Framework' + sLineBreak);
|
||||
fIntfBuff.WriteString('//' + sLineBreak);
|
||||
fIntfBuff.WriteString('// Copyright (c) 2010-' + YearOf(Date).ToString + ' Daniele Teti and the DMVCFramework Team' + sLineBreak);
|
||||
fIntfBuff.WriteString('// Copyright (c) 2010-' + YearOf(Date).ToString +
|
||||
' Daniele Teti and the DMVCFramework Team' + sLineBreak);
|
||||
fIntfBuff.WriteString('//' + sLineBreak);
|
||||
fIntfBuff.WriteString('// https://github.com/danieleteti/delphimvcframework' + sLineBreak);
|
||||
fIntfBuff.WriteString('//' + sLineBreak);
|
||||
fIntfBuff.WriteString('// ***************************************************************************' + sLineBreak);
|
||||
fIntfBuff.WriteString
|
||||
('// ***************************************************************************' + sLineBreak);
|
||||
fIntfBuff.WriteString('//' + sLineBreak);
|
||||
fIntfBuff.WriteString('// Licensed under the Apache License, Version 2.0 (the "License");' + sLineBreak);
|
||||
fIntfBuff.WriteString('// you may not use this file except in compliance with the License.' + sLineBreak);
|
||||
fIntfBuff.WriteString('// Licensed under the Apache License, Version 2.0 (the "License");' +
|
||||
sLineBreak);
|
||||
fIntfBuff.WriteString('// you may not use this file except in compliance with the License.' +
|
||||
sLineBreak);
|
||||
fIntfBuff.WriteString('// You may obtain a copy of the License at' + sLineBreak);
|
||||
fIntfBuff.WriteString('//' + sLineBreak);
|
||||
fIntfBuff.WriteString('// http://www.apache.org/licenses/LICENSE-2.0' + sLineBreak);
|
||||
fIntfBuff.WriteString('//' + sLineBreak);
|
||||
fIntfBuff.WriteString('// Unless required by applicable law or agreed to in writing, software' + sLineBreak);
|
||||
fIntfBuff.WriteString('// distributed under the License is distributed on an "AS IS" BASIS,' + sLineBreak);
|
||||
fIntfBuff.WriteString('// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.' + sLineBreak);
|
||||
fIntfBuff.WriteString('// See the License for the specific language governing permissions and' + sLineBreak);
|
||||
fIntfBuff.WriteString('// Unless required by applicable law or agreed to in writing, software' +
|
||||
sLineBreak);
|
||||
fIntfBuff.WriteString('// distributed under the License is distributed on an "AS IS" BASIS,' +
|
||||
sLineBreak);
|
||||
fIntfBuff.WriteString
|
||||
('// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.' + sLineBreak);
|
||||
fIntfBuff.WriteString('// See the License for the specific language governing permissions and' +
|
||||
sLineBreak);
|
||||
fIntfBuff.WriteString('// limitations under the License.' + sLineBreak);
|
||||
fIntfBuff.WriteString('//' + sLineBreak);
|
||||
fIntfBuff.WriteString('// ***************************************************************************' + sLineBreak);
|
||||
fIntfBuff.WriteString
|
||||
('// ***************************************************************************' + sLineBreak);
|
||||
fIntfBuff.WriteString(sLineBreak);
|
||||
end;
|
||||
|
||||
@ -368,7 +471,8 @@ begin
|
||||
lProp := Format('[MVCNameAs(''%s'')]', [F.FieldName]) + sLineBreak + INDENT + INDENT;
|
||||
end;
|
||||
lProp := lProp + 'property ' + GetFieldName(F.FieldName).Substring(1) { remove f } + ': ' +
|
||||
GetDelphiType(F.DataType) + ' read ' + GetFieldName(F.FieldName) + ' write ' + GetFieldName(F.FieldName) + ';' +
|
||||
GetDelphiType(F.DataType) + ' read ' + GetFieldName(F.FieldName) + ' write ' +
|
||||
GetFieldName(F.FieldName) + ';' +
|
||||
sLineBreak;
|
||||
|
||||
if GetDelphiType(F.DataType).ToUpper.Contains('UNSUPPORTED TYPE') then
|
||||
@ -418,7 +522,8 @@ begin
|
||||
fIntfBuff := TStringStream.Create;
|
||||
fImplBuff := TStringStream.Create;
|
||||
fInitializationBuff := TStringStream.Create;
|
||||
FHistoryFileName := TPath.Combine(TPath.GetDocumentsPath, TPath.GetFileNameWithoutExtension(ParamStr(0)) +
|
||||
FHistoryFileName := TPath.Combine(TPath.GetDocumentsPath,
|
||||
TPath.GetFileNameWithoutExtension(ParamStr(0)) +
|
||||
'.history');
|
||||
try
|
||||
if TFile.Exists(FHistoryFileName) then
|
||||
@ -532,4 +637,19 @@ begin
|
||||
lstCatalog.Clear;
|
||||
end;
|
||||
|
||||
procedure TMainForm.SpeedButton1Click(Sender: TObject);
|
||||
begin
|
||||
DoSelection(stAll);
|
||||
end;
|
||||
|
||||
procedure TMainForm.SpeedButton2Click(Sender: TObject);
|
||||
begin
|
||||
DoSelection(stNone);
|
||||
end;
|
||||
|
||||
procedure TMainForm.SpeedButton3Click(Sender: TObject);
|
||||
begin
|
||||
DoSelection(stInverse);
|
||||
end;
|
||||
|
||||
end.
|
||||
|
Loading…
Reference in New Issue
Block a user