Jump to content

Dave Novo

Members
  • Content Count

    182
  • Joined

  • Last visited

  • Days Won

    1

Everything posted by Dave Novo

  1. Dave Novo

    RAD AI Companion

    This is what Claude said. No idea if its true or not since I have never looked into this procedure GetCompleteVersionInfo(out ProductName, Version, BuildNumber: string); var Services: IOTAServices; AboutBox: IOTAAboutBoxServices; FullVersionString: string; Parts: TArray<string>; begin ProductName := ''; Version := ''; BuildNumber := ''; Services := BorlandIDEServices as IOTAServices; if Assigned(Services) then begin ProductName := Services.GetProductIdentifier; Version := Services.GetIDEVersionString; end; AboutBox := BorlandIDEServices as IOTAAboutBoxServices; if Assigned(AboutBox) then begin FullVersionString := AboutBox.GetVersionString; // Parse the build number from the full version string // Format is typically: "Embarcadero® Delphi 10.4 Version 27.0.40680.4203" Parts := FullVersionString.Split([' ']); if Length(Parts) > 0 then BuildNumber := Parts[High(Parts)]; // Get the last part end; end;
  2. Has anyone noticed any improvements in debugging inline variables in Delphi 13? In Delphi 12.3 it is basically broken, and does not work for me 90% of the time. Always said "undeclared identifier" and other nonsense while trying to debug.
  3. Dave Novo

    "Pass" parameters to Delphi compiler, from code

    @david berneda - this is where AI shines. Just fire up claude code and ask it to insert the include directive in a specific spot (i.e. "insert this include statement xxxxx right after the unit specifier at the top of units that start with the letter q in this folder" and it will just do it.
  4. Dave Novo

    Global in RTL for unit communication?

    The vmt of all Delphi classes has vmautotable that is not used. I have patched a particular class vmt and in the autotable slot and stuck a reference to an object in there. So both of your units can check that reference on some class from the vcl that you pick. Then they can patch the class. I dont remember the patching code but if you cannot find it on the web let me know and I can dig it up.
  5. Hello, Amazingly, after so many years, Delphi still does not have an effective TStrings implementation of InsertRange (insert a range of strings at a specified index), DeleteRange (delete a range of entries at a specific index). Of course IList<string> in Spring4D has these, but then you lose many of the helpful things that TStrings does have (like .CommaText, .Text, BOM handling and others). I see that Spring4D has a TStringsAdapter and implements many of the missing methods, but does so following the TStrings way (i.e. implements insertRange by calling FStrings.Insert over and over in a loop which is moving the memory around many times). Does anyone know of a TStringList replacement that keeps all the features of TStrings but adds more robust insertion, deletion etc in an efficient manner?
  6. Dave Novo

    Better TStringList in Spring4D or elsewhere

    @Uwe Raabe - done. I did not even know I could browse other issues because I can only access anything about the portal by selecting the "my account" icon on the top right. But at least now I can see other issues.
  7. Dave Novo

    Better TStringList in Spring4D or elsewhere

    Interestingly, @Stefan Glienke reported a similar issue for TList<T> many years ago, that was implemented. So maybe there is hope ([RSP-21316] TList<T>.InsertRange lacks optimization for passing another TList<T> - Embarcadero Technologies) I did create a new issue in the new quality portal RSS-4020. However, it seems impossible for me to browse other people's issues on this new portal so not sure anyone else can see it.
  8. Dave Novo

    Better TStringList in Spring4D or elsewhere

    Of course, it is one of the problems with the current TStrings. It was simply not designed for efficient bulk operations. For example, as long as I was notified which items were going to be removed/extracted/inserted either before or after the actual removal/extraction/insertion then I could handle whatever I needed to do. I dont need to be notified one item at a time. I am mainly wondering if in the last 30 years anyone had written a robust implementation that handled these bulk operations. I could spend a few hours/day creating something based on IList<string> and copy/pasting relevant code from TStringList to handle the missing/useful functionality but again, just wondering if anyone did so already.
  9. Dave Novo

    Better TStringList in Spring4D or elsewhere

    Hi Anders, Of course I can hack the FList, hack the Capacity, hack the count, hack the Notify and and/or reimplement the entire StringList. Just wondering if anyone has done so already.
  10. Dave Novo

    A smart case statement in Delphi?

    Hi Anders, Out of curiosity, what are the most effective ones? Based on your comments I did a quick google/AI search and both seemed to indicate that if you expect a high level of matching across your static set of strings (i.e. when you test a string against your set you expect a match most of the time, which is what I would guess based on a case statement of strings) then hashing is an effective algorithm. If you expect a lot of misses, then a Prefix Tree is a better choice because you don't have to read the entire string all the time. But Prefix tree is slow in the event you match a lot, since you have to read the entire string anyhow.
  11. Dave Novo

    SynEdit for FMX ?

    TMS just added this TMS Software | Blog | Enhance Your Delphi Apps with TTMSFNCMemo Custom Languages & Themes
  12. Dave Novo

    New file system monitoring component

    Thanks for all the amazing work you do and contribute to the community!
  13. Dave Novo

    TestInsight Question

    I am trying to create a "universal" Dproj file to use with DunitX, Delphi 12.3 and TestInsight 1.2.0.8. What I want to achieve is as follows: When I open the project the first time and open the TestInsight window in the IDE, the TestInsight window automatically populates with available tests. Not sure if that is even possible, or if I have to compile/run the program once. If so, that is an issue, my tests take about 2 minutes to run completely, and I am loath to have to wait 2 minutes to run all the tests just so they can be registered with the testInsight window. The workaround I have found is to find my shortest test and hit Alt+F9. Then all the tests get registered. But are the test names from the previous run not stored in some config file or something so that the IDE window can be refreshed (even if out of date potentially) when the TestInsight window first opens? The other issue is that the IsTestInsightRunning code below always returns True. Even if I reboot the machine, start Delphi and compile my project with the TestInsight IDE window closed, it still returns true and starts running the registered tests. I can see the testInsight window in the IDE briefly flash open with my one test selected (because RunRegisteredTests is executed), it runs that single test, and then closes. Is there a way to figure out whether or not the TestInsight window is open in the IDE? below is the code in my project file program TestingProj; {$IFDEF TESTINSIGHT} {$UNDEF UseConsole} {$ENDIF} {$IFDEF UseConsole} {$APPTYPE CONSOLE} {$ENDIF} {$STRONGLINKTYPES ON} uses System.SysUtils, {$IFDEF TESTINSIGHT} {$DEFINE UseVCL} TestInsight.Client, TestInsight.DUnitX, {$ENDIF} {$IFDEF UseVCL} VCL.Forms, DUnitx.Loggers.GUI.VCL, {$ENDIF } {$IFDEF UseConsole} DUnitX.Loggers.Console, {$ENDIF } DUnitX.TestFramework, TestingUnit in 'TestingUnit.pas'; {$IFDEF TESTINSIGHT} function IsTestInsightRunning: Boolean; var client: ITestInsightClient; begin client := TTestInsightRestClient.Create; client.StartedTesting(0); Result := not client.HasError; end; {$ENDIF} begin {$IFDEF TESTINSIGHT} if IsTestInsightRunning then begin TestInsight.DUnitX.RunRegisteredTests; exit; end; {$ENDIF} try {$IFDEF UseVCL} Application.Initialize; Application.CreateForm(TGUIVCLTestRunner, GUIVCLTestRunner); Application.Run; {$ENDIF} {$IFDEF UseConsole} //Check command line options, will exit if invalid TDUnitX.CheckCommandLine; //Create the test runner var runner := TDUnitX.CreateRunner; //Tell the runner to use RTTI to find Fixtures runner.UseRTTI := True; //When true, Assertions must be made during tests; runner.FailsOnNoAsserts := False; //tell the runner how we will log things //Log to the console window if desired if TDUnitX.Options.ConsoleMode <> TDunitXConsoleMode.Off then begin var logger := TDUnitXConsoleLogger.Create(TDUnitX.Options.ConsoleMode = TDunitXConsoleMode.Quiet); runner.AddLogger(logger); end; //Generate an NUnit compatible XML File var nunitLogger := TDUnitXXMLNUnitFileLogger.Create(TDUnitX.Options.XMLOutputFile); runner.AddLogger(nunitLogger); //Run tests var results := runner.Execute; if not results.AllPassed then System.ExitCode := EXIT_ERRORS; {$IFNDEF CI} //We don't want this happening when running under CI. if TDUnitX.Options.ExitBehavior = TDUnitXExitBehavior.Pause then begin System.Write('Done.. press <Enter> key to quit.'); System.Readln; end; {$ENDIF} {$ENDIF} except on E: Exception do System.Writeln(E.ClassName, ': ', E.Message); end;
  14. Dave Novo

    TestInsight Question

    I pressed the >> button on the TestInsight menu, with no tests populated in the window. It still ran all the tests, and then populated the window. It took 83 seconds. I am not sure if that is because my project file has the following code {$IFDEF TESTINSIGHT} if IsTestInsightRunning then begin TestInsight.DUnitX.RunRegisteredTests; exit; end; {$ENDIF} so when TESTINSIGHT is defined, it is running all the tests. I am not sure what I need to do in order to get the TestInsight window to populate without running the tests.
  15. Instead of adding complex features to modelMaker, this is exactly where AI shines. You simply setup Claude.ai and activate the Model Context Protocol that it can access files on your hard drive. Then tell the AI to read your units and tell it to move the relevant methods over. It can do this kind of stuff very easily, and understands much of Delphi and how do the refactorings. When I asked it to do similar things, it even filled in the uses clauses for me (even though I forgot to ask it specifically) and did the relevant initialization and finalization of the unit that was required.
  16. Dave Novo

    TestInsight Question

    Thanks all for the prompt response!
  17. I love using IShared with Spring4D. Particularly with inline variable declaration. However, the debugger behaves so finicky and random. See the following example For some reason, I can debug SharedBmp just fine, but not sharedForm. In this case, it does not matter if I use inline variable declaration or put it in the var section of the method. It also does not matter if I click "Al;low side effects and function calls". I cannot debug sharedForm. This is just an example. It has nothing to do with using Shared<T>.Make vs Shared.Make<T> variants. It randomly works or not either way. If I introduce a temporary variable with inline declaration, I can debug again but that means that I realize I need to debug something I need to recompile. I have tried lots of variants, like sharedForm().Width in the Watch list but it never works. Is there a trick to make IShared reliably work with the debugger? Sorry about the small screenshots. I have no idea why they look so small. They look much larger in Paint before I paste them into the editor.
  18. Dave Novo

    Debugging Reliably with IShared - Spring4D

    I don't think its as simple as that. Here is a real case from my production code. Both the variables 'allData' and 'recoveredMixMat' are of type IShared<MtxH.MtxWithHeader.TMtxWithHeader>, yet one can be debugged and the other cannot. In this case, both variables were created exactly the same by calling NewMtxHFromFile which loads a data file from disk and returning a IShared<MtxH.MtxWithHeader.TMtxWithHeader> yet the watch list I think the debugger is messed up in many different ways, both with inline variable declaration and dealing with anonymous functions that return objects. Other times I have gotten that the IShared variable is simple "inaccessible", which usually can be cleared up by doing "Allow side effects and function calls" but it does not resolve these.
  19. The difference between a ternary operator and iif<T> as you describe is that both operators are not evaluated with the ternary operator. Only the one satisfying the condition For example isVisible:=if Assigned(Foo) then Foo.Visible else False which will work vs isVisible:=iif<Boolean>(Assigned(Foo),Foo.Visible,False) which will crash if Foo is not assigned, according to the implementation you describe.
  20. Isn't the point of Future that you create the Future and it immediately begins processing something in a background thread? Usually, it is calculating some sort of value that you don't need for a while. Then you execute a bunch of other code. When then code is done, you request the future.Value. This will block until the thread calculation you started originally is completed (or not block at all if the calculation was already done). If you are not going to block and wait for the value at some point, why use a future? Why not just launch it in a background thread, like Dalija suggested above? For example, you have a large matrix of values, and you need to calculate the mean of all the columns. But you dont need the mean until the very end of the method. So you can start calculating the mean at the beginning of the method, in a future. The rest of the method can execute, and at the very end you request the mean of all the columns from the future and do what you need with it. Or this can be the result of a complex database query inside the future, or any number of examples. There is not much difference between a TFuture and launching a TTask at the beginning of the method and then doing TTask.WaitForAllTasks passing in the task you created as far as I can tell. Just some semantic niceties with TFuture if the background task you are running just has a single result.
  21. Dave Novo

    Stringgrid objects problem

    What you are doing is very error prone, for the reasons you describe. If you are using low valued integers, you could inspect the value of the objects[x,y] and if the value is below some threshold, then do not free it. One way of doing this is 1. Make sure to set all objects[x,y] to zero 2. if setting it to an integer value, set it to the negative of the integer you want. Make sure to when using the value to negate it again 3. If setting to an object, store the pointer as a positive integer then, when freeing, only free where objects[x,y] is a positive value. I think that will work for 32 and 64 bit until you have set your 32 bit app to specifically use memory above 2GB block.
  22. Dave Novo

    How to get a pandas dataframe in delphi

    Just to follow up on this, does anyone have an example of how to do this? There is a demo in the P4D showing how to use a numpy array that contains integers. But each column of a Pandas dataframe can be a different datatype. Does anyone have some code that shows how to check the datatype of a numpy array and then loop through the data and put in the appropriate data types (i.e. int, single, double, string, boolean).
  23. Can you just include the pascal code of what you are trying to size. Never mind implement it... The term "setlength for 3 TArray<Double>" is unclear. Are you trying to size arr_3D: Array of array of array of double? if so, SetLength(arr_3d, a,b,c) should work (where a,b.c are the dimensions you want) Note, SetLength will set the newly allocated memory to zero. or 3 different 1D array of double
  24. What we have done is have a centralized imageList in a datamodule for the application. We then have separate actionList/imageList pairs on every form. In the form Create, we copy the image(s) we need for that form from the central image list to the image list on the form being shown. Its a bit of a pain, we have a list of constants on the central datamodule so we can request images in an easy to read manner. So, on any given form's Create, we do something like actExportToExcel.ImageIndex:=CentralImageDataModule.AddImage(self.ImageList,IMG_EXPORT_TO_EXCEL) Its a bit of a pain and we have some utility functions like CentralDAtaModule.AddImageIndices([act1,act2,ac3],[CONST1,CONST2,CONST3]) to make it a bit simpler. But that way we can update the images in the central data module and have them update everywhere.
  25. Dave Novo

    MainModule.varname is cached?

    You can also do this from the python side and send a script to delete all global variables # List of built-in attributes to preserve preserve = set(dir(__builtins__)) # Iterate over global variables and delete those not in the preserve list for name in list(globals()): if name not in preserve and not name.startswith("__"): del globals()[name]
×