Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding a struct type with editor #181

Draft
wants to merge 303 commits into
base: master
Choose a base branch
from
Draft

Conversation

jahorta
Copy link
Contributor

@jahorta jahorta commented Feb 9, 2025

This is an attempt to introduce a new struct type. This type would allow the user to define a block of memory using a list of entries with any type. Then the struct would automatically be created when assigned to a memory watch. This includes a number of new features to accomplish this:

  • A struct definition class (StructDef) which holds the definition of a struct.

    • This contains a name, length, and list of fields
  • A struct field definition class (FieldDef) which holds the field information.

    • The offset within the struct. These are generated based on the size of the fields before it.
    • the field's size within the struct
    • a MemWatchEntry defining the type of the field.
      • All current types are supported, including structs and pointers to structs. For these last two, the inter-struct references are stored in case of name or field changes.
      • The only restrictions are that there can be no cyclic references to structs as it would make it impossible to determine the size of the struct. Pointers to structs do not have this restriction.
      • When editing the entry of a struct field, The DlgAddWatchEntry class ignores the address and preview.
    • Struct fields are currently checked for validity by making sure they do not overlap each other.
  • A struct editor widget as a separate window to organize and edit struct definitions.

    • Tree-style organization to allow grouping of structs.
    • Struct definitions are identified using a "Namespace" created from combining group names and the struct name.
    • Struct definitions can be edited using the context menu. When editing a struct, its fields will appear in a tableview on the right. Since struct offsets are currently generated from the field definitions, the user can enter padding fields to get a field to the correct offset.
    • When editing a struct, a copy is made to edit. If a change has been made to a struct, the save button will be enabled. The state of this button is used to determine whether there are any unsaved changes on the current struct.
  • The ability to select a struct in the DlgAddWatchEntry for memory watches.

    • A list of names is currently passed to the DlgAddWatchEntry to select from and a simple combo box is shown to the user to select a struct from.
  • The automatic creation and deletion of memory watches using struct definitions as a template.

    • When a mem watch node has a struct type entry, if its definition is known it will get a placeholder watch node as a child.
    • If the node is expanded, the placeholder node will be deleted and the fields of the struct definition will be copied as new child nodes under the struct node.
    • If a node is collapsed, the child nodes will be removed and a placeholder node will be added again.
  • Saving and loading the struct tree to/from the settings on application start and close.

  • Saving and loading any currently used struct definitions to/from a memory watch file.

    • When loading from a file, any namespace collisions are presented to the user to resolve. If a new name is needed, it currently just auto-generates one.

This is a draft pull request while I do some testing, bug fixing, and refactoring, but has most of the features fully implemented, so I wanted some feedback. I am open to any feedback, but am wondering about a few design choices in particular:

  • In the mem watcher, structs are expandable, so if a struct type with a known struct definition is found it will be given a "placeholder" child to allow the user to expand the struct. At the moment, the fields of the struct will be created on expansion and deleted on collapsing of the struct.

    1. I think the creation on expansion is necessary because the struct can handle pointers to its own type and in a situation where you have a doubly linked list you would have infinite generation if you try to generate everything since the next and previous pointers would form cycles.
    2. I am not sure if the deletion of the field entries on collapse of a node is necessary, or even good. The reason for this was that the hidden entries would take up memory and processing power on update that is not visible to the user which may eventually lead to problems, but the amount of memory that is taken by each entry is so small that I don't really see it being a problem. Also, since fields of a struct are deleted at the moment, expansion of any struct fields is lost, so the user would need to re-expand any nodes that they had open previously.
  • I added an icon to identify structs in the mem watcher.

    1. Is this easy to see?
    2. Should there also be an icon for fields of a struct since they are not as flexible as a normal watch entry?
  • Struct fields are currently checked to make sure that they do not overlap. This is not strictly necessary, and there is a case to be made for fields that may overlap (Unions, bitfields, etc.).

    1. Should the user be allowed to overlap struct fields?
    2. Should there be a checkbox for this?

…t a struct map with namespace, structDef* pairs
…truct for use if a struct has been updated. Implemented updateStructEntries to use update struct node for all recorded nodes which use an updated struct definition.
…s to having a nullptr in the structDef* which would indicate a remove action. If a structDef* is included, it indicates an add action
…th is greater than the old field length, any padding fields after the changed field that would overlap with the updated field are now removed.
…the save struct button. When struct details are saved, now disables the save struct button
…save the currently loaded struct, now uses the onSaveStruct method for consistency with the save struct button.
…r convert padding to an actual field, or it will change the details of the field.
…saving the struct to prevent unlinking of the struct length and the fields it contains.
…t should not be saved when validating a new length.
…will be populated with the appropriate child nodes.
…f the initial entry or edited entry was a container and will populate it appropriately.
…r type but the new one is not, should delete all children of the node.
…l if a name is taken. This is used by the widget to display the name taken warning.
…ct model now returns the new node so that the structAddedRemoved signal can be emitted.
…mits the struct name changed signal when data is edited in the select model.
… structs available since this dialog should prevent any interaction with the struct editor while it is open.
… need to update the struct type label in the node in the editor as well as the detail model for any pointer references
… a node in the detail editor, need to update that node as well.
…update any pointer reference names in the node and in the struct detail model.
@dreamsyntax
Copy link
Collaborator

This feature sounds great. Ill be trying some builds of this in the interim. Review is huge so it may be a while, even after you've fully completed it.

… type_struct, now hides the struct select combobox.
…ormatting of more details field when there is a struct with the same name already in the struct editor
…ng over the nodes, if a nested node was a pointer to the same type but was changed to a different type, the loop could use nodes that were out of date. Now checks that the nodes are still valid nodes and are contained in the structNodes object
…ild fields should only be populated if the struct def has child fields. That way it cannot be expanded if there are no fields in the struct def
…be added to the struct node map even if the struct def has no fields, but it should have no placeholder node if there are no fields.
…odes, check if the struct def has fields and if it does, add a placeholder. If it has child nodes, collapse them. Then if it marked expanded, expand the struct node.
…iew. For now only duplicates the field that was right clicked and does not handle selections.
… that will be set by the updateFieldOffsets method.
@dreamsyntax
Copy link
Collaborator

Hey there, I know this is WIP so I'm not expecting action on this, but when its closer to being finished, the commits will have to be sorted out:
image

@jahorta
Copy link
Contributor Author

jahorta commented Feb 23, 2025

Definitely, I'll rebase the commits into a single commit before review.

@cristian64
Copy link
Collaborator

Definitely, I'll rebase the commits into a single commit before review.

...but notice that a single commit would be unwieldy from a code review point of view.

@jahorta
Copy link
Contributor Author

jahorta commented Feb 25, 2025

Okay. I'm still pretty new to pull requests, how should I organize the commits so that they are easier to review?

@dreamsyntax
Copy link
Collaborator

For now just focus on your feature and when its done we can rediscuss. Its already an unmanageable amount of commits, so easiest scenario is squashing post completion

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants