Jump to content

Ali Dehban

Members
  • Content Count

    26
  • Joined

  • Last visited

  • Days Won

    7

Ali Dehban last won the day on June 27

Ali Dehban had the most liked content!

Community Reputation

38 Excellent

About Ali Dehban

  • Birthday 05/29/1986

Technical Information

  • Delphi-Version
    Delphi Community Edition

Recent Profile Visitors

1273 profile views
  1. Ali Dehban

    OpenAPIClientWizard

    Hey everyone, this plug-in is currently in beta version, so there may be some bugs or issues. I've already got some valuable advice from the great @Uwe Raabe but any contributions are welcome too, as I may not have much time to work on it until the end of July. I'll be improving it in time, so please be patient and help me make it better and production-ready. Please open an issue on GitHub with a sample specification file so that I can duplicate the error/bug to fix it. Best regards, Ali.
  2. Ali Dehban

    What is the best AI at Delphi

    Another option where I had a better experience than with OpenAI and Gemini is YouChat
  3. Ali Dehban

    OpenAPIClientWizard

    A new Delphi plug-in for automatically implementing the client side of a Rest API is now available in beta version. Repository: https://github.com/AliDehbansiahkarbon/OpenAPIClientWizard Demo video: https://www.youtube.com/watch?v=7B7nSHIsV64
  4. Ali Dehban

    ChatGPT plug-in for RAD Studio.

    Hey guys, FYI: This plug-in (ChatGPTWizard) supports Ollama the offline/local GPT-like API too.
  5. You're absolutely right, this is the normal usage, but at the moment you want to have one function to avoid repeating with the "obj" as input parameter then Delphi forces you to write that function in this way. As I mentioned this is not necessary and what you wrote is ok 99 percent of the time. There is one benefit with such a function that is the possibility to limit the input type to classes.(No primitive types like integer) I'm writing a library and I wanted to force the developers to use it in this way in this case.
  6. @pmcgee Hi. In most scenarios your sample would be enough, I agree. But why I used this: function UseInterface<T> ( obj: IMyInterface<T> ) : T; begin Result := obj.DoSomething; end; Because I wanted to call ClassObj.DoSomething from within another class and using one function which is not necessary but I wanted to know how it works in Delphi. When you are calling something like these generic object's generic members/methods from within another object(different class) then Delphi forces you to write like that. For instance, something like this won't be compiled which was my desired call but it's not allowed: function UseInterface(obj: T): T; Besides, I wanted to limit the input type to classes (no primitive types at all) which is possible if I use such a function, so my final function is even more complicated like this: function UseInterface<T: class>(obj: IMyInterface<T>): T; The keyword "class" here can limit the input type only to classes, so Integer or String is no longer allowed here.
  7. Ali Dehban

    ChatGPT plug-in for RAD Studio.

    The wrong warning is fixed now. @Die Holländer GitHub and release has been updated. If you prefer to follow it here it's ok but it would be easier for me to follow everything in one place, GitHub. If possible, please open an issue on GitHub in the future.
  8. Ali Dehban

    ChatGPT plug-in for RAD Studio.

    Perfect. Thank you for your reply. It's just a warning and won't be a problem but the warning shouldn't appear. I'm wondering how can I duplicate this. I'll try to fix it.
  9. Ali Dehban

    ChatGPT plug-in for RAD Studio.

    Hi fellows, I wanted to inform you that I have made an improvement to my AI-integration plug-in called ChatGPTWizard. Now it supports Ollama, the offline AI chatbot server. You can download the latest version (v3.0) to try it out here: https://github.com/AliDehbansiahkarbon/ChatGPTWizard To set up your offline GPT-like server read this section: https://github.com/AliDehbansiahkarbon/ChatGPTWizard#:~:text=How to use it in Offline mode I am eagerly looking forward to receiving your valuable feedback. Thank you in advance.
  10. I see. Well, beyond the curiosity, it depends on the nature of the project. As a general sample, it could/might be useful to implement something like an ORM, especially in an Active-Record structure or like that. (More info about the Active-Record: https://guides.rubyonrails.org/active_record_basics.html) In my case, I need it in a multi-purpose data access layer of a project but with complex data types, not Integer and String parameters combined heavily to RTTI functionalities. Thank you for your feedback.
  11. First, thank you for your response. Second, I thought so but! It seems using RTTI's TValue it is possible to handle this situation somehow. I'm just not sure if everything goes right with this code or not at the end, I tested with "ReportMemoryLeaksOnShutdown := True;" and there is no memory leak. Please have a look at the final version and share your thoughts with me. Best regards. type IMyInterface<T> = interface ['{D68085A3-6AFB-46D9-A4EE-B46563758127}'] function DoSomething: T; end; TMyClass<T> = class(TInterfacedObject, IMyInterface<T>) function DoSomething: T; end; TForm1 = class(TForm) Button1: TButton; procedure Button1Click(Sender: TObject); private { Private declarations } function UseInterface<T>(obj: IMyInterface<T>): T; public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} { TMyClass<T> } function TMyClass<T>.DoSomething: T; var ctx: TRttiContext; typ: TRttiType; val: TValue; begin ctx := TRttiContext.Create; typ := ctx.GetType(TypeInfo(T)); if typ.TypeKind = tkInteger then val := 20 else if (typ.TypeKind = tkString) or (typ.TypeKind = tkUString) then val := 'Hello' else if typ.AsInstance.MetaclassType.InheritsFrom(TStringList) then begin val := TStringList.Create; val.AsType<TStringList>.Add('Hello from StringList'); end; Result := Val.AsType<T>; ctx.Free; end; { TForm1 } function TForm1.UseInterface<T>(obj: IMyInterface<T>): T; begin Result := obj.DoSomething; end; procedure TForm1.Button1Click(Sender: TObject); var obj1: IMyInterface<Integer>; obj2: IMyInterface<String>; obj3: IMyInterface<TStringList>; lvstr: TStringList; begin try try obj1 := TMyClass<Integer>.Create; obj2 := TMyClass<String>.Create; obj3 := TMyClass<TStringList>.Create; ShowMessage(UseInterface<Integer>(obj1).ToString); ShowMessage(UseInterface<String>(obj2)); lvstr := UseInterface<TStringList>(obj3); ShowMessage(lvstr.Text); except on E: Exception do ShowMessage('Exception: ' + E.ClassName + ': ' + E.Message); end; finally lvstr.Free; obj1 := nil; obj2 := nil; obj3 := nil; end; end; Generic Interface-final.zip
  12. Hi mates, I have something on my mind but I couldn't implement it correctly, imagine a generic interface, some classes inherited from that interface, and one method in each class with the same name, now I'm trying to use this interface type every where for different approaches but it doesn't compile correctly. Please have a look at the code if you get a chance and share your thoughts with me, I do appreciate you in advance. The question is how can I implement such an idea properly and safely? I have attached a sample project to save you time too. unit Unit1; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, System.Rtti; type IMyInterface<T> = interface function DoSomething: T; end; TMyClass<T> = class(TInterfacedObject, IMyInterface<T>) function DoSomething: T; end; TForm1 = class(TForm) procedure FormCreate(Sender: TObject); private { Private declarations } function UseInterface<T>(obj: IMyInterface<T>): T; public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} { TMyClass<T> } function TMyClass<T>.DoSomething: T; var ctx: TRttiContext; typ: TRttiType; begin ctx := TRttiContext.Create; typ := ctx.GetType(TypeInfo(T)); if typ.TypeKind = tkInteger then Result := 20 // E2010 Incompatible types: 'T' and 'Integer' else if typ.TypeKind = tkString then Result := T('Hello') // E2089 Invalid typecast else if typ.AsInstance.MetaclassType.InheritsFrom(TStringList) then Result := (typ.AsInstance.MetaclassType.InitInstance(typ) as TStringList) //E2010 Incompatible types: 'T' and 'TStringList' else Result := Default(T); ctx.Free; end; { TForm1 } function TForm1.UseInterface<T>(obj: IMyInterface<T>): T; begin Result := obj.DoSomething; end; procedure TForm1.FormCreate(Sender: TObject); var obj1: IMyInterface<Integer>; obj2: IMyInterface<String>; obj3: IMyInterface<TStringList>; begin try obj1 := TMyClass<Integer>.Create; obj2 := TMyClass<String>.Create; obj3 := TMyClass<TStringList>.Create; ShowMessage(UseInterface<Integer>(obj1).ToString); ShowMessage(UseInterface<String>(obj2)); ShowMessage(UseInterface<TStringList>(obj3).Text); except on E: Exception do Writeln('Exception: ', E.ClassName, ': ', E.Message); end; end; end. Generic Interface.zip
  13. Ali Dehban

    DateTime problem in fastreport's PFD export.

    It seems "mm" is defined in the fast report format options for minute, what does it mean "hh:mm" in fast report equals "hh:nn" in Delphi likely.
  14. Ali Dehban

    DateTime problem in fastreport's PFD export.

    You are right, It's designed by the customer itself, and the designer used IIF() to fill the MemoView to select one from two available TdateTime fields by some conditions and the result of IIF is text.
  15. Ali Dehban

    DateTime problem in fastreport's PFD export.

    Sure, I mean the retrieved data field from the database is TDateTime, but when you read from a TfrxMemoView you'll get it as text.
×