Recent

Author Topic: How can I list all Properties in a Component?  (Read 691 times)

Aruna

  • Hero Member
  • *****
  • Posts: 513
How can I list all Properties in a Component?
« on: July 17, 2024, 11:17:17 pm »
Hi, how can I list all properties available in a TButton or any other component? Lazarus displays them in the Object Inspector but I want to list them through code. What would be the best way to do this, please?

cdbc

  • Hero Member
  • *****
  • Posts: 1644
    • http://www.cdbc.dk
Re: How can I list all Properties in a Component?
« Reply #1 on: July 17, 2024, 11:30:13 pm »
Hi
Use unit 'TypInfo' and maybe (when it's ready) 'Rtti'.
and then something like this:
Code: Pascal  [Select][+][-]
  1. var
  2.   Cnt,Lp: ptrint;
  3.   OrdVal: ptrint;
  4.   StrName,StrVal: String;
  5.   FloatVal: Extended;
  6.   PropInfos: PPropList;
  7.   PropInfo: PPropInfo;
  8. begin
  9.   { Find out how many properties we'll be considering and get them }
  10.   Cnt := GetPropList(PTypeInfo(Self.ClassInfo),PropInfos);
  11.   try
  12.     for Lp:= 0 to Cnt - 1 do begin { Loop through all the selected properties }
  13.       PropInfo:= PropInfos^[Lp];
  14.       StrName:= PropInfo^.Name;
  15.       { Check the general type of the property and read/write it in an appropriate way }
  16.       case PropInfo^.PropType^.Kind of
  17.         tkInt64,tkInteger,tkChar,tkEnumeration,tkBool,tkQWord,
  18.         tkSet,tkClass,tkWChar: begin
  19.                                  OrdVal:= GetOrdProp(Self,PropInfo);
  20.                                  Ini.WriteInt64('General',StrName,OrdVal);
  21.                                end; { ordinal types }
  22.         tkFloat:               begin
  23.                                  FloatVal:= GetFloatProp(Self,PropInfo);
  24.                                  Ini.WriteFloat('General',StrName,FloatVal);
  25.                                end; { floating point types }
  26.         tkWString,tkLString,tkAString,
  27.         tkString:              begin
  28.                                  { Avoid copying 'Name' - components must have unique names }
  29. //                                 if UpperCase(PropInfo^.Name) = 'NAME' then Continue;
  30.                                  StrVal:= GetStrProp(Self,PropInfo);
  31.                                  Ini.WriteString('General',StrName,StrVal);
  32.                                end; { string types }
  33.         else ;
  34.       end;
  35.     end;
  36.   finally
  37.     FreeMem(PropInfos,Cnt*sizeof(pointer)); { typinfo allocates like this: getmem(PropList,result*sizeof(pointer)); }
  38.   end;
  39.   Ini.UpdateFile; { persist to disk }
  40.   Result:= true;;
  41. end;
The above example, writes the properties to an ini-file, but I think you'll get the gist of it...
HTH
Regards Benny
If it ain't broke, don't fix it ;)
PCLinuxOS(rolling release) 64bit -> KDE5 -> FPC 3.2.2 -> Lazarus 2.2.6 up until Jan 2024 from then on it's: KDE5/QT5 -> FPC 3.3.1 -> Lazarus 3.0

Aruna

  • Hero Member
  • *****
  • Posts: 513
Re: How can I list all Properties in a Component?
« Reply #2 on: July 18, 2024, 12:57:54 am »
Quote
Hi
Use unit 'TypInfo' and maybe (when it's ready) 'Rtti'.
and then something like this:
Code: Pascal  [Select][+][-]
  1. var
  2.   Cnt,Lp: ptrint;
  3.   OrdVal: ptrint;
  4.   StrName,StrVal: String;
  5.   FloatVal: Extended;
  6.   PropInfos: PPropList;
  7.   PropInfo: PPropInfo;
  8. begin
  9.   { Find out how many properties we'll be considering and get them }
  10.   Cnt := GetPropList(PTypeInfo(Self.ClassInfo),PropInfos);
  11.   try
  12.     for Lp:= 0 to Cnt - 1 do begin { Loop through all the selected properties }
  13.       PropInfo:= PropInfos^[Lp];
  14.       StrName:= PropInfo^.Name;
  15.       { Check the general type of the property and read/write it in an appropriate way }
  16.       case PropInfo^.PropType^.Kind of
  17.         tkInt64,tkInteger,tkChar,tkEnumeration,tkBool,tkQWord,
  18.         tkSet,tkClass,tkWChar: begin
  19.                                  OrdVal:= GetOrdProp(Self,PropInfo);
  20.                                  Ini.WriteInt64('General',StrName,OrdVal);
  21.                                end; { ordinal types }
  22.         tkFloat:               begin
  23.                                  FloatVal:= GetFloatProp(Self,PropInfo);
  24.                                  Ini.WriteFloat('General',StrName,FloatVal);
  25.                                end; { floating point types }
  26.         tkWString,tkLString,tkAString,
  27.         tkString:              begin
  28.                                  { Avoid copying 'Name' - components must have unique names }
  29. //                                 if UpperCase(PropInfo^.Name) = 'NAME' then Continue;
  30.                                  StrVal:= GetStrProp(Self,PropInfo);
  31.                                  Ini.WriteString('General',StrName,StrVal);
  32.                                end; { string types }
  33.         else ;
  34.       end;
  35.     end;
  36.   finally
  37.     FreeMem(PropInfos,Cnt*sizeof(pointer)); { typinfo allocates like this: getmem(PropList,result*sizeof(pointer)); }
  38.   end;
  39.   Ini.UpdateFile; { persist to disk }
  40.   Result:= true;;
  41. end;
The above example, writes the properties to an ini-file, but I think you'll get the gist of it...
HTH
Regards Benny
Thank you very much Benny. The code was way over my head right now. So I plugged it into chatGPT and asked for a breakdown. I was quite pleasantly surprised by the result. See below for what chatGPT broke down the code into. I would still like to see some code that does not use self and does not write to a ini file but simply gets the properties then lists them in a memoedit if possible. I am includinmg the breakdown from chatGPT because I sincerely think it can help other newbies understand somewhat what the code does. I was quite frankly lost until I asked chatGPT for help  :D

Breakdown of the Code:

    Variable Declarations:
        Cnt, Lp: ptrint;: Variables to hold counts and loop indices.
        OrdVal: ptrint;: Holds integer/ordinal property values.
        StrName, StrVal: String;: Hold property names and string values.
        FloatVal: Extended;: Holds floating-point property values.
        PropInfos: PPropList;: Pointer to an array of PPropInfo.
        PropInfo: PPropInfo;: Pointer to a TPropInfo structure.

    Getting Property Information:
        Cnt := GetPropList(PTypeInfo(Self.ClassInfo), PropInfos);:
            Retrieves a list of properties (PropInfos) for the current object (Self).
            Self.ClassInfo provides type information about the class of Self.
            GetPropList fills PropInfos with pointers to TPropInfo structures.
            Cnt holds the number of properties found.

    Iterating through Properties:
        for Lp := 0 to Cnt - 1 do begin ... end;:
            Iterates through each property in PropInfos.

    Processing Each Property:
        PropInfo := PropInfos^[Lp];: Gets the TPropInfo structure for the current property.
        StrName := PropInfo^.Name;: Retrieves the name of the property.

    Switch Statement (case):
        case PropInfo^.PropType^.Kind of ... end;:
            Checks the type (Kind) of the property.

    Handling Different Property Types:

        Ordinal Types (tkInt64, tkInteger, tkChar, tkEnumeration, tkBool, tkQWord, tkSet, tkClass, tkWChar):
            Uses GetOrdProp to retrieve the ordinal value (OrdVal) and writes it to an INI file section ('General') using Ini.WriteInt64.

        Floating Point Types (tkFloat):
            Uses GetFloatProp to retrieve the floating-point value (FloatVal) and writes it to the INI file section ('General') using Ini.WriteFloat.

        String Types (tkWString, tkLString, tkAString, tkString):
            Uses GetStrProp to retrieve the string value (StrVal) and writes it to the INI file section ('General') using Ini.WriteString.

    Memory Management:
        FreeMem(PropInfos, Cnt * SizeOf(Pointer));:
            Frees memory allocated for PropInfos after processing all properties.

    Persistence:
        Ini.UpdateFile;:
            Persists changes made to the INI file (Ini) to disk.

    Return Value:
        Result := True;: Returns True indicating successful processing.

Notes:

    TypInfo Unit: The TypInfo unit provides functions (GetPropList, GetOrdProp, GetFloatProp, GetStrProp) for inspecting and manipulating properties of objects at runtime.
    INI File Handling: The code assumes the use of an Ini object (presumably TIniFile or similar) to read from and write to an INI file for persistence.
    Property Types: Different types of properties (ordinal, floating-point, string) are handled differently based on their kind (tk*) using type information retrieved from TPropInfo.
    Error Handling: Error handling (e.g., checking for nil values, ensuring proper property names) is not explicitly shown in this snippet and should be considered for production code.

This code snippet showcases how to dynamically read and write object properties to an INI file based on their type, demonstrating the flexibility of Object Pascal in handling runtime reflection and data persistence tasks. Adjustments can be made based on specific application requirements and property types involved.

Aruna

  • Hero Member
  • *****
  • Posts: 513
Re: How can I list all Properties in a Component?
« Reply #3 on: July 18, 2024, 02:58:40 am »
I found a solution here

Joanna from IRC

  • Hero Member
  • *****
  • Posts: 1198
Re: How can I list all Properties in a Component?
« Reply #4 on: July 18, 2024, 03:00:17 am »
Quote
So I plugged it into chatGPT and asked for a breakdown. I was quite pleasantly surprised by the result.
That was nice of cdbc to help you with your chat gpt advertisement  :D
« Last Edit: July 18, 2024, 03:10:03 am by Joanna »
✨ 🙋🏻‍♀️ More Pascal enthusiasts are needed on IRC .. https://libera.chat/guides/ IRC.LIBERA.CHAT  Ports [6667 plaintext ] or [6697 secure] channel #fpc  #pascal Please private Message me if you have any questions or need assistance. 💁🏻‍♀️

cdbc

  • Hero Member
  • *****
  • Posts: 1644
    • http://www.cdbc.dk
Re: How can I list all Properties in a Component?
« Reply #5 on: July 18, 2024, 06:47:12 am »
Hi
That's ok Joanna, the first time, I had help too, I think it was from Peter Belows of "TeamB"  :D
Each to his own /chatgpt/  ;D
Regards Benny
If it ain't broke, don't fix it ;)
PCLinuxOS(rolling release) 64bit -> KDE5 -> FPC 3.2.2 -> Lazarus 2.2.6 up until Jan 2024 from then on it's: KDE5/QT5 -> FPC 3.3.1 -> Lazarus 3.0

 

TinyPortal © 2005-2018