How to get errors of the file using OTA? - delphi

I'd like to access the errors on the active file (.pas).
Now a days I can find it on the left side of the IDE, as you can see on image.
I found on OTA the interface IOTAModuleErrors, that seems to be what I want. But I didn't found it on BorlandIDEServices.QueryInterface or BorlandIDEServices.GetService. Someone knows how to access it ?

I found it!
It was much simpler than I thought, it's just a matter of casting the IOTAModule on the module to IOTAModuleErrors.
If you want a practical example you can check this project
I use on the unit Source/FindUnit.OTAUtils.pas, on function GetErrorListFromActiveModule.
Sample:
function GetErrorsListFromActiveModule: TOTAErrors;
var
ModuleServices: IOTAModuleServices;
ModuleErrors: IOTAModuleErrors;
begin
ModuleServices := BorlandIDEServices as IOTAModuleServices;
Assert(Assigned(ModuleServices));
ModuleErrors := ModuleServices.CurrentModule as IOTAModuleErrors;
Result := ModuleErrors.GetErrors(ModuleServices.CurrentModule.FileName);
end;
Thank you

Related

Delphi - mORMot Can not access data through client using full memory model and TSQLRestClientURI

I've been trying to start a new project using mORMOt the DDD-way and have created a few classes and begun to test one of them in an easy/simple way.
I used the regression test code from your DDD-sample about TUser and modified it to suit my class .
I have tried to minimize the code and hopefully, it could contain some clues for you to help me understand what's wrong here.
I found that when only using the server, everything works ok but when using client the ORMselection won't find the data.
I stripped down the code as much as possible and marked with some comments where it works and where it not works.
class procedure TInfraRepoPackageFactory.RegressionTestsPackage(test: TSynTestCase);
procedure TestOne(Rest: TSQLRest);
var cmd: IDomPackageCommand;
qry: IDomPackageQuery;
package: TPackage;
begin
test.Check(Rest.Services.Resolve(IDomPackageCommand,cmd));
package := TPackage.Create;
try
package.articleNo := 10000;
test.check(cmd.Add(package)=cqrsSuccess);
end;
test.check(cmd.Commit=cqrsSuccess);
finally
package.Free;
end;
package := TPackage.Create;
try
test.Check(Rest.Services.Resolve(IDompackageQuery,qry));
test.Check(qry.SelectByArticleNo(10000,false)=cqrsSuccess); // <<-- Debugging shows that it will not find anything when using client.
test.Check(qry.GetCount=1); // <<-- getCount returns zero when using client.
end;
finally
package.Free;
end;
end;
var RestServer: TSQLRestServerFullMemory;
RestClient: TSQLRestClientURI;
begin
RestServer := TSQLRestServerFullMemory.CreateWithOwnModel([TSQLRecordPackage]);
try // first try directly on server side
RestServer.ServiceContainer.InjectResolver([TInfraRepoPackageFactory.Create(RestServer)],true);
TestOne(RestServer); // sub function will ensure that all I*Command are released // <<=== Works
finally
RestServer.Free;
end;
RestServer := TSQLRestServerFullMemory.CreateWithOwnModel([TSQLRecordPackage]);
try // then try from a client-server process
RestServer.ServiceContainer.InjectResolver([TInfraRepoPackageFactory.Create(RestServer)],true);
RestServer.ServiceDefine(TInfraRepoPackage,[IDomPackageCommand,IDomPackageQuery],sicClientDriven);
test.Check(RestServer.ExportServer);
RestClient := TSQLRestClientURIDll.Create(TSQLModel.Create([TSQLRecordPackage]),#URIRequest);
try
RestClient.Model.Owner := RestClient;
RestClient.ServiceDefine([IDomPackageCommand],sicClientDriven);
TestOne(RestServer); // <<=== Works
RestServer.DropDatabase;
USEFASTMM4ALLOC := true; // for slightly faster process
TestOne(RestClient); // <<=== DO NOT Work !!!!
finally
RestClient.Free;
end;
finally
RestServer.Free;
end;
end;
I also tried to put this question on the mORMot forum but the mailer can not reach the site.
Got this message :
An error was encountered
Error: Unable to send email. Please contact the forum administrator with the following error message reported by the SMTP server: "450 4.1.2: Recipient address rejected: Domain not found ".
I finally found what's wrong.
In the agregate, class TPackage, I had set the property of packageNo to "stored AS_UNIQUE" - that resulted in that the commit just stored zero in that field and then the SELECT('packageNo=?,[10001]) couldn't find anything.
I didn't realize that because the package object contained just 10001 and could never think of the possibility that the commit should store a 0.
But when I tested with TSQLHttpServer and TSQLHttpClient and a real database I could see all records containing zeroes in the packageNo field.
Then I understood that it must be something with this field that's wrong. When I looked up TPackage I found my mistake.
I should have set the "STORED AS_UNIQUE" in the TSQLRecordPackage class instead, the one that's used by ORM.
The moral of the story... "OPEN YOUR EYES.. and you will see" ;-)

OpenOffice Desktop Instance can not be created (com object)

I have some problems to create an instance of the StarOffice Desktop object.
I used the standard construct below but whenever it comes to the line: StarDesktop := StarOffice.CreateInstance('com.sun.star.frame.Desktop');
My StarDesktop Variant stays unassigned. I am pretty sure that the code is ok until there but perhaps something with the OpenOffice installation is messed up.
Is there a way to check the com objects or did somebody had the same problem and could solve it...
uses
ComObj;
procedure OpenOfficeDocument;
var
StarOffice: Variant;
StarDesktop: Variant;
begin
StarOffice := CreateOleObject('com.sun.star.ServiceManager');
StarDesktop := StarOffice.CreateInstance('com.sun.star.frame.Desktop');
// StarDesktop is always "unassigned"
....
Yes, I know. I should have stated more clearly that I am too 100% sure that it would work normally in a correct environment.
But my question is what could be the cause why it doesn't work. Why the 'com.sun.star.frame.Desktop' instance is unassigned. I have no option/way to debug it...
And it is a bit unfair to vote me down, I researched for one hour without finding something to explain why it could not work.
Or how and where to check if something is wrong with the Office installation (I uninstalled and reinstalled it twice already"
Again, I know this will work for others and normally would work for me, but something is wrong at my system and I would like to know some help to point me in the direction what could be wrong in the system (and not in the code example...)
is OpenOffice installed on client?
doesn't throw any exception?
I'm using Bernard Marcelly's Delphi 7 OOo tool and as can you see his code like that;
var
OpenOffice, StarDesktop: Variant;
...
OpenOffice:= CreateOleObject('com.sun.star.ServiceManager');
if isNullEmpty(OpenOffice) then Raise Exception.Create('OpenOffice connection is impossible');
StarDesktop:= OpenOffice.createInstance('com.sun.star.frame.Desktop');
if isNullEmpty(Result) then Raise Exception.Create(Format('Impossible to create service : %s', ['com.sun.star.frame.Desktop']));
...
'some constants converted to string'
So, if StarDesktop is null, possible can not access Oo Desktop service. If OpenOffice installed properly some features may be missing, options have to set.
This works for me (in my application):
class procedure TOpenOffice.Connect;
begin
if IsConnected then
Exit;
try
FServiceManager := CreateOleObject('com.sun.star.ServiceManager');
except
FServiceManager := Null;
end;
if VarIsNull(FServiceManager) then
raise EOpenOfficeException.Create(StrConnectionFailed);
FDesktop := CreateService('com.sun.star.frame.Desktop');
FDispatchHelper := CreateService('com.sun.star.frame.DispatchHelper');
FIntrospection := CreateService('com.sun.star.beans.Introspection');
FReflection := CreateService('com.sun.star.reflection.CoreReflection');
end;
and:
class function TOpenOffice.CreateService(const ServiceName: string): Variant;
begin
Result := FServiceManager.createInstance(ServiceName);
if VarIsNull(Result) then
raise EOpenOfficeException.CreateFmt(StrCouldNotCreateService,
[ServiceName]);
end;

How can I translate the Firemonkey's Resource Strings?

I'm иrazilian and I need the Firemonkey's Resource Strings in my language, for example when I use the dialogs. I couldn't find a way to translate it. Does someone know how to do it?
What you need is something like this, but for FMX. In a quick search, the only file that I've found in help for Delphi XE2 is FMX.Consts. You take that file, translate it, and then put the translated file in your project.
Take care when Delphi got an update. The original file can be changed and you will need to update your translation. Also, you will probably want to change any others files that have Resource Strings, and are in use by your project.
Finally, I'm not expert in this, but if you are planing use multi-language, this could be not the better approach.
Translating FMX forms is done with the TLang component, although that won't work for most dialogs.
You can change dialogs using FMX.Consts.pas, but it fixes the language during compilation.
If you want to check the language version of the host OS in runtime, you should correct FMX.Platform.Android.pas or FMX.Platform.iOS.pas.
For Android, in FMX.Platform.Android.pas, in procedure TPlatformAndroid.MessageDialog... find ButtonCaptions and surround it with your own function, for example: ZSTranslate( ButtonCaptions[B]).
Declare ZSTranslate in the following way:
function ZSTranslate(txt: String):String;
var
LocaleSvc: IFMXLocaleService;
begin
LocaleSvc := TPlatformServices.Current.GetPlatformService(IFMXLocaleService) as IFMXLocaleService;
result:=txt;
if LocaleSvc.GetCurrentLangID ='your_language_two_letter_id' then
begin
if txt= 'Yes' then
result := 'yes in your language'
else
if txt= 'No' then
result := 'no in your language'
else
if txt= 'Confirm' then
result := 'confirm in your language'
else
if txt= 'Cancel' then
result := 'cancel in your language';
end
end;
Place ZSTranslate somewhere above TPlatformAndroid.MessageDialog in a copy of FMX.Platform.Android.pas, and add this corrected version of FMX.Platform.Android.pas to your project.
Note that above example is very simple, and as far as I remember there is unsolved case in Embarcadero quality system, suggesting translate method here (so TLang should work ok). I did not try with translate, my version did the job (as there are just a few button labels in dialogs and I wanted only two different languages).
For iOS you should look in FMX.Platform.iOS.pas for function TPlatformCocoaTouch.MessageDialog. Please note, that there are two overloaded versions. There are also MsgTitles and ButtonCaptions in iOS, as dialogs at iOS show captions.
PS. For Polish I had to correct also GetCurrentLangID method, because it always returned 'en' - please double-check the result for your language.
The versions that worked for me:
in FMX.Platform.iOS.pas:
function TPlatformCocoaTouch.GetCurrentLangID: string;
var
lngs : NSArray;
CurrentLocale: NSLocale;
LanguageISO: NSString;
begin
lngs := TNSLocale.OCClass.preferredLanguages;
LanguageISO:= TNSString.Wrap(lngs.objectAtIndex(0));
//CurrentLocale := TNSLocale.Wrap(TNSLocale.OCClass.currentLocale);
//LanguageISO := TNSString.Wrap(CurrentLocale.objectForKey((NSLocaleLanguageCode as ILocalObject).GetObjectID));
Result := UTF8ToString(LanguageISO.UTF8String);
if Length(Result) > 2 then
Delete(Result, 3, MaxInt);
end;
in FMX.Platform.Android.pas:
function TPlatformAndroid.GetCurrentLangID: string;
var
Locale: JLocale;
begin
Locale := TJLocale.JavaClass.getDefault;
Result := JStringToString(Locale.getLanguage);//getISO3Language); //zs
if Length(Result) > 2 then
Delete(Result, 3, MaxInt);
end;

Frank Shearar SIP Component

I am looking at the demo program by Frank Shearar and cannot build the demo program. I fixed up all the references to "missing files" and the last errors that I am trying to fix are related to differences in the interface in classes and how they are used now...
Self.CalleeMedia := TIdSDPMultimediaSession.Create(Self.Profile);
vs
Self.CalleeMedia := TIdSDPMultimediaSession.Create(Self.Profile, ???, ???);
I know the interface now looks like....
constructor TIdSDPMultimediaSession.Create(Profile: TIdRTPProfile;
Factory: TIdSdpMediaStreamFactory; ExecutionContext: TIdTimerQueue);
and I could just add...
x := TIdSdpMediaStreamFactory.Create;
y := TIdTimerQueue.Create;
and pass these in? Or pas nil in both cases. There are a few other places where I get similar errors when building the demo program. Do I just need to create other objects that are required? If not, what additional steps are needed? Any assistance to get me started would be great.
Thanks,
I suspect I simply forgot to update the demo in line with the SDP API's interface!
Create the TIdSdpMediaStreamFactory and TIdTimerQueue before instantiating the TIdSDPMultimediaSession.
In particular, take a look at how the test case is set up, in test\TestIdSdp.pas:
procedure TestTIdSDPMultimediaSession.SetUp;
begin
inherited SetUp;
Self.Factory := TMockMediaStreamFactory.Create;
Self.Profile := TIdAudioVisualProfile.Create;
Self.Timer := TIdThreadedTimerQueue.Create(false);
Self.MS := TIdSDPMultimediaSession.Create(Self.Profile, Self.Factory, Self.Timer);
Self.PortBlocker := TIdMockRTPPeer.Create;
// We only instantiate Server so that we know that GStack points to an
// instantiated stack.
Self.Server := TIdUdpServer.Create(nil);
end;
Demo project can not be compiled. He has a lot of links to test* files. Also all the factory's was declared at the test project.

Delphi - Form in DLL - Hints not showing

I have a Delphi form inside a DLL (I know that this restricts the use of the DLL to Delphi but this is not a problem in this case).
The DLL exports a function ShowForm that looks roughly like this:
procedure ShowForm (App : TApplication);
begin
OldApp := Application;
try
Application := App;
MyForm := TMyForm.Create (nil);
try
MyForm.ShowModal;
finally
FreeAndNil (MyForm);
end;
finally
Application := OldApp;
end;
end;
Now on the form I use a TAdvOfficeHint (from the TMS component pack). Unfortunately the hints do not show up.
Am I missing something here? How can I make the form behave exactly as it would if I showed it from the main application?
Thanks!
I don't know TAdvOfficeHint but I guess it hooks Application.OnShowHint to set its own THintWindowClass, and even if both the main executable and the DLL are linking in the TMS unit, they each have their own copy of the class which is where things go wrong.
Assigning Application is not enough: there are other global variables, like Screen, Mouse, etc. Others are even hidden in the implementation so I'd say your chances to make the form behave exactly as from the main application are slim.
Just found the reason why it does not work. As TOndrej states, TAdvOfficeHinthooks Application.OnShowHint and internally executes the following line of code:
FHintInfo.Assign (AHintInfo);
Assign internally uses a dynamic type check
if (Source is TAddvHintInfo) then ...
which fails due to the separate type registries of the DLL and the main application.
I have run into this problem a few times now and maybe I really have to switch to runtime packages to avoid all this stuff.
Anyway, if there's anything I can do to prevent this, please comment.
Wrong setting of Application.
Try this and see if it solves your problem:
procedure ShowForm (AppHandle : THandle);
begin
OldAppHandle := Application.Handle;
try
Application.Handle := AppHandle;
........
finally
Application.Handle := OldAppHandle;
end;
end;
I guess in Delphi 2006 and later versions you can call System.ShareMemoryManager method in the EXE code, so that its memory manager is shared with other modules loaded in the process memory space.

Resources