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

Improve UX for MemViewer and better code flexibility #8

Merged
merged 4 commits into from
Jan 17, 2018

Conversation

Broxzier
Copy link
Contributor

@Broxzier Broxzier commented Jan 15, 2018

I originalle started with the idea to add a "Right-click Hex -> Add To Watch" option, but found a lot of other things that could be improved first 😄

Copied from the commit:

  1. Use smaller font
  2. The Home and End keys jumps to and selects the first and last byte respectively
  3. Fix calculation error when setting scrollbar upon pressing End
  4. Always set m_carretBetweenHex to false when navigating using the keyboard
  5. Fix selection jumping when pressing Left or Right when at the edges of the row
  6. Refactor to use defines for number of rows, columns and bytes shown
  7. Add support for clicking the ASCII table and typing in it
  8. Refactored writeHexCharacterToSelectedMemory to be usable for ASCII too
  9. Ignore non-left click events (you could middleclick a value to select it)
  10. Play system beep when a non-hex character is edited
  11. Update selection coords when scrolling

Some notes to clarify:

  1. The smaller font is a personal preference, but since the rest of the UI also doesn't use large text anywhere, I found it unnecessary.
  2. Previously they only scrolled to the beginning and end, now they select the bytes too
  3. When calculating the range of the scroll area, 1 was subtracted to remove the last row, but it should have subtracted the number of visible rows.
  4. no comments
  5. Easy to reproduce: Select the very last visible byte in the area, and press Right (or the very first and press left, same efffect). The window nicely scrolled down 1 row, but the selection jumped to the top row (or bottom row when going the opposite direction). Now it selects the correct byte.
  6. Can be used to easily change the number of rows for example, perhaps useful to save in a variable later, and should it easier to make the window resizable.
  7. The only point that really added new code
  8. (in my opinion) a easier to read function too.
  9. no comments
  10. Only tested on Windows, I assume Qt handles it well for all platforms.
  11. Srolling down 3 lines will move the selection up 3 lines, easy as that. Has some calculations for page up/down when near the beginning or end.

Before:
image

After (with extra rows just because):
image

- Use smaller font
- The Home and End keys jumps to and selects the first and last byte respectively
- Fix calculation error when setting scrollbar upon pressing End
- Always set `m_carretBetweenHex` to false when navigating using the keyboard
- Fix selection jumping when pressing Left or Right when at the edges of the row
- Refactor to use defines for number of rows, columns and bytes shown
- Add support for clicking the ASCII table and typing in it
- Refactored `writeHexCharacterToSelectedMemory` to be usable for ASCII too
- Ignore non-left click events (you could middleclick a value to select it)
- Play system beep when a non-hex character is edited
- Update selection coords when scrolling
@aldelaro5
Copy link
Owner

aldelaro5 commented Jan 15, 2018

I will do a more extensive review later when I have time, but for now, I am just going to give 2 comments.

About 1, I do not like the change. The reason is because a common theme I noticed with different hex viewers and more specifically Cheat Engine (which this program aims to replace when using with Dolphin) is that their hex viewer tends to be really difficult for me to look at for hours in a row simply because it's a lot of condensed data, in a rather small font (which really is hindered by the fact that I have a myopia).

Putting a bigger font was done for that reason, to ease the fact that it's a lot of info to read in a little space. Ideally, the best would be to make the size configurable, but considering how little settings this program may need (the only I can think of are the updates and freeze timers) and how less needed it is than other features, I prefer to not do it now and just make eveyrone happy by putting the font slightly larger.

It does make the number of possible rows to display slightly lower because of the added space, but in practice, what I noticed is you really don't need to consult that much memory in one sight often. I noticed this after using Cheat Engine for years on multiple games so I am not really concerned about the added space.

Which leads me to my second comment, change number 6, despite what I jsut said, I do approve, I agreed the code needed that refactor which means I would have done it eventually. However, what I do not approve is the use of define, I would rather have them be a class wide constant simply because it provides better type checking and I don't feel a preprocessor is a necessity here. Also, in my opinion, writting const makes it litterally obvious you are just going to use this as compile time and only there to have a nice label at read time. Finally, I am already doing this practice in the code anyway, check Source/Common/MemoryCommon.h which contains some constants about the GameCube/Wii RAM which are used when dealing with console addresses.

The other changes doesn't sound something I would have a problem with, but like I said, I still need to do an extensive review on them. Overall, this PR sounds really nice :)

@Broxzier
Copy link
Contributor Author

Agreed with both comments. I'll make both the font size and the defines and make them member variables. For the font size, what do you think about having a Ctrl+Scroll feature to increase/decrease the font size? Many editors work that way, but maybe it's not that obvious for this memory viewer. Otherwise maybe a A- and A+ button in the corner?

@aldelaro5
Copy link
Owner

I am fine, as long as the window size adapts itself and there is a limit because if you zoom too much, this might be bad, same for too much out.

I actually never thought of that, the code should even account for this because it's binded all to the EM size so you would just need to recalculate that once and redraw.

@Broxzier
Copy link
Contributor Author

The window adapts itself nicely already, I only had to move the calculations from initialize.
Right now there's only a minimum font size of 5 (hard coded), but no maximum. I don't think a maximum limit is really necessary, increasing the font to ridiculous numbers is not what this tool is intended for.

Copy link
Owner

@aldelaro5 aldelaro5 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Other than these changes, make the #define class wide const and everything is LGTM.

m_editingHex = false;
}
else
return;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Put the return inside braces here. I am okay to omit the braces, but only if the entire seqeunce of if, else if and else don't have them. This is not the case here and even if return is trivial, it's still a bit jarring to read.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With the new changes this can be removed entirely. Clicking the empty space is checked before this block now.

int x = event->pos().x();
int y = event->pos().y();
if (x >= m_rowHeaderWidth && x <= m_rowHeaderWidth + m_hexAreaWidth && y >= m_columnHeaderHeight)

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removing this actually doesn't work, you can select the first of the row if you click on the last hex character of the row header and it really does not ignore clicks on the header (clickedPosY is calculated using integer division while the left member, if you click on the column header, will always be equal or less then the right member which means, it's always 0 here). After testing a bit, this is the correct way to do this:

if (!(x >= m_rowHeaderWidth &&
        x <= m_rowHeaderWidth + m_hexAreaWidth + spacing + (m_charWidthEm * VISIBLE_COLS) &&
        y >= m_columnHeaderHeight && y <= m_columnHeaderHeight + m_charHeight * VISIBLE_ROWS))
    return;

It assumes spacing is declared a line above and obviously, replace the define constant by whatever name you give to the class wide const. Note also the addition of && y <= m_columnHeaderHeight + m_charHeight * VISIBLE_ROWS, this is because while testing this, I found a bug that is affecting master where if you click JUST RIGHT you can select an invisible row at the bottom, I found this PR fitting for the fix so I put it in there. Essentially, this condition ensure that whatever you clicked in is in the hex area or the ascii area, the entire rectangle.

You are free to put a comment there if it's confusing, but if you do go with this, remove the test you do on clickedPosY.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well spotted. Clicking the row, column headers or area between the two tables was due to the devision. I didn't take into account that any value between 0 and -width would return 0. I think a nicer way than having those concatinated conditions is to check if the relative click position is < 0 rather than checking the index.

{
m_byteSelectedPosX = 15;
m_byteSelectedPosY = 15;
m_byteSelectedPosY = 0;
scrollContentsBy(0, 1);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The scroll should be BEFORE assigning m_byteSelectedPosY because if you set it THEN scroll, it's going to be on the last column of the same row instead of being the last column of the previous row. Since you do it first for the right arrow key, do so here to remain consistent.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah yeah, the change that makes the selection move when scrolling changed this behaviour. Actually this entire part should be refactored, it's not taking the variable number of rows and columns into account.

@@ -166,7 +216,7 @@ bool MemViewer::handleNaviguationKey(const int key)
{
scrollContentsBy(0, 1);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here, you have to do m_byteSelectedPosY = 0; as you no longer stay the selection to the same place everytime. Do so after the scroll, this will make the selection jump one row above,

@@ -177,7 +227,7 @@ bool MemViewer::handleNaviguationKey(const int key)
{
scrollContentsBy(0, -1);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here, but you assign 15 this time, fixes the same thing, but down this time.

#define VISIBLE_COLS 16 // Should be a multiple of 16, or the header doesn't make sense
#define VISIBLE_ROWS 16
#define NUM_BYTES (VISIBLE_COLS * VISIBLE_ROWS)

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The last commit says the defines were replaced, but I still see them here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Forgot to push the latest changes, should be good now.

- Correctly check click location for hex and ASCII tables
- Simplify logic in `handleNavigationKey`
- Replace defines for table dimensions with const class members

// Ignore clicking the padding at the bottom
if (clickedPosY >= m_numRows)
return;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like this way of doing this for 2 reasons: 1: it doesn't consider the horizontal space after the ascii area and second, it's honestly more confusing to read to make sure this work because essentially, what you want to do is test that the click was inside the grid and having all these conditions separated doesn't make that part obvious. I would rather keep the 4 conditions I mentioned because they all set each boundaries of the grid.

Copy link
Contributor Author

@Broxzier Broxzier Jan 16, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The area to the right doesn't really need to be checked, since it touches the scroll bar, even when zoomed in very far, but (Actually scrap that, that's not the case anymore.) I do agree it would be nicer to do.
I don't agree on the readibility. I'd rather see conditions simply comparing two variables than having a bunch of additions within the condition. That's something I'm working on now. The code that you suggested earlier didn't match the areas exactly (pink box in the screenshot).
image
I'll combine the two, by storing the left/right and top/bottom in variables, then checking if the clicked locaiton is in either of those areas.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, sounds fine with better variable labels.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've got the correct area calculations for the hex table now:

  int spacing = m_charWidthEm / 2;
  int hexAreaLeft = m_rowHeaderWidth - spacing / 2;
  int hexAreaRight = m_rowHeaderWidth + m_hexAreaWidth - spacing / 2;
  int asciiAreaLeft = (m_hexAsciiSeparatorPosX + spacing);
  int asciiAreaRight = asciiAreaLeft + m_charWidthEm * m_numColumns;
  int AreaTop = m_columnHeaderHeight + m_charHeight - fontMetrics().overlinePos();
  int AreaBottom = AreaTop + m_charHeight * m_numRows;
  int cellWidth = m_charWidthEm * 2 + spacing;
  int cellHeight = m_charHeight;

image
The click area includes half of the spacing between each byte. Now to get the values for the ascii table and simplyfy it a bit, then I'll get this PR nice and clean! :P

@aldelaro5 aldelaro5 merged commit 4152638 into aldelaro5:master Jan 17, 2018
@Broxzier Broxzier deleted the memviewer-UX branch April 21, 2018 12:44
cristian64 added a commit to cristian64/dolphin-memory-engine that referenced this pull request May 17, 2024
…n the stack.

Previously, these dialogs were constructed dynamically in the heap, and
were never deleted explicitly; only when their parent QObject was
destroyed at a much later time would they be deleted.

This deferred destruction was in fact masking a segmentation fault
caused by a double-free: the entry in the dialog was not extracted
via `stealEntry()`; instead the reference was taking from the
`entryCopy` variable (same pointer), resulting in the entry getting
deleted twice, eventually.

Reproduction steps:
- Double click on an watch entry to bring up the **Edit Watch** dialog.
- Make any edit and press **OK**.
- Quit the application gracefully to force the destruction of the
  dialog.
- A segmentation fault would be produced:

```
(gdb) bt
#0  QArrayDataPointer<char16_t>::deref() (this=<optimised out>, this=0x558b5d1a35c0) at /usr/include/c++/11/bits/atomic_base.h:392
aldelaro5#1  QArrayDataPointer<char16_t>::~QArrayDataPointer() (this=0x558b5d1a35c0, __in_chrg=<optimised out>) at /usr/include/x86_64-linux-gnu/qt6/QtCore/qarraydatapointer.h:129
aldelaro5#2  QString::~QString() (this=0x558b5d1a35c0, __in_chrg=<optimised out>) at /usr/include/x86_64-linux-gnu/qt6/QtCore/qstring.h:1302
aldelaro5#3  MemWatchEntry::~MemWatchEntry() (this=0x558b5d1a35c0, __in_chrg=<optimised out>) at /w/dolphin-memory-engine/Source/MemoryWatch/MemWatchEntry.cpp:48
aldelaro5#4  0x0000558b5c517787 in DlgAddWatchEntry::~DlgAddWatchEntry() (this=0x558b5d1be8f0, __in_chrg=<optimised out>) at /w/dolphin-memory-engine/Source/GUI/MemWatcher/Dialogs/DlgAddWatchEntry.cpp:31
aldelaro5#5  0x0000558b5c51782d in DlgAddWatchEntry::~DlgAddWatchEntry() (this=0x558b5d1be8f0, __in_chrg=<optimised out>) at /w/dolphin-memory-engine/Source/GUI/MemWatcher/Dialogs/DlgAddWatchEntry.cpp:32
aldelaro5#6  0x00007fde5556599b in QObjectPrivate::deleteChildren() () at /lib/x86_64-linux-gnu/libQt6Core.so.6
aldelaro5#7  0x00007fde5624cab8 in QWidget::~QWidget() () at /lib/x86_64-linux-gnu/libQt6Widgets.so.6
aldelaro5#8  0x0000558b5c51d0cd in MemWatchWidget::~MemWatchWidget() (this=0x558b5cd068e0, __in_chrg=<optimised out>) at /w/dolphin-memory-engine/Source/GUI/MemWatcher/MemWatchWidget.cpp:41
aldelaro5#9  0x0000558b5c5367cd in MainWindow::~MainWindow() (this=0x7ffc70ef10f0, __in_chrg=<optimised out>) at /w/dolphin-memory-engine/Source/GUI/MainWindow.cpp:56
aldelaro5#10 0x0000558b5c4f1ad7 in main(int, char**) (argc=<optimised out>, argv=<optimised out>) at /w/dolphin-memory-engine/Source/main.cpp:56
```

# Please enter the commit message for your changes. Lines starting
# with '#' will be kept; you may remove them yourself if you want to.
# An empty message aborts the commit.
#
# Date:      Fri May 17 22:10:10 2024 +0100
#
# On branch watch_entry_dialog_segfault
# Changes to be committed:
#	modified:   Source/GUI/MemViewer/MemViewer.cpp
#	modified:   Source/GUI/MemWatcher/MemWatchWidget.cpp
#
cristian64 added a commit to cristian64/dolphin-memory-engine that referenced this pull request May 17, 2024
…n the stack.

Previously, these dialogs were constructed dynamically in the heap, and
were never deleted explicitly; only when their parent QObject was
destroyed at a much later time would they be deleted.

This deferred destruction was in fact masking a segmentation fault
caused by a double-free: the entry in the dialog was not extracted
via `stealEntry()`; instead the reference was taking from the
`entryCopy` variable (same pointer), resulting in the entry getting
deleted twice, eventually.

Reproduction steps:
- Double click on an watch entry to bring up the **Edit Watch** dialog.
- Make any edit and press **OK**.
- Quit the application gracefully to force the destruction of the
  dialog.
- A segmentation fault would be produced:

```
(gdb) bt
#0  QArrayDataPointer<char16_t>::deref() (this=<optimised out>, this=0x558b5d1a35c0) at /usr/include/c++/11/bits/atomic_base.h:392
aldelaro5#1  QArrayDataPointer<char16_t>::~QArrayDataPointer() (this=0x558b5d1a35c0, __in_chrg=<optimised out>) at /usr/include/x86_64-linux-gnu/qt6/QtCore/qarraydatapointer.h:129
aldelaro5#2  QString::~QString() (this=0x558b5d1a35c0, __in_chrg=<optimised out>) at /usr/include/x86_64-linux-gnu/qt6/QtCore/qstring.h:1302
aldelaro5#3  MemWatchEntry::~MemWatchEntry() (this=0x558b5d1a35c0, __in_chrg=<optimised out>) at /w/dolphin-memory-engine/Source/MemoryWatch/MemWatchEntry.cpp:48
aldelaro5#4  0x0000558b5c517787 in DlgAddWatchEntry::~DlgAddWatchEntry() (this=0x558b5d1be8f0, __in_chrg=<optimised out>) at /w/dolphin-memory-engine/Source/GUI/MemWatcher/Dialogs/DlgAddWatchEntry.cpp:31
aldelaro5#5  0x0000558b5c51782d in DlgAddWatchEntry::~DlgAddWatchEntry() (this=0x558b5d1be8f0, __in_chrg=<optimised out>) at /w/dolphin-memory-engine/Source/GUI/MemWatcher/Dialogs/DlgAddWatchEntry.cpp:32
aldelaro5#6  0x00007fde5556599b in QObjectPrivate::deleteChildren() () at /lib/x86_64-linux-gnu/libQt6Core.so.6
aldelaro5#7  0x00007fde5624cab8 in QWidget::~QWidget() () at /lib/x86_64-linux-gnu/libQt6Widgets.so.6
aldelaro5#8  0x0000558b5c51d0cd in MemWatchWidget::~MemWatchWidget() (this=0x558b5cd068e0, __in_chrg=<optimised out>) at /w/dolphin-memory-engine/Source/GUI/MemWatcher/MemWatchWidget.cpp:41
aldelaro5#9  0x0000558b5c5367cd in MainWindow::~MainWindow() (this=0x7ffc70ef10f0, __in_chrg=<optimised out>) at /w/dolphin-memory-engine/Source/GUI/MainWindow.cpp:56
aldelaro5#10 0x0000558b5c4f1ad7 in main(int, char**) (argc=<optimised out>, argv=<optimised out>) at /w/dolphin-memory-engine/Source/main.cpp:56
```
cristian64 added a commit to cristian64/dolphin-memory-engine that referenced this pull request May 17, 2024
…n the stack.

Previously, these dialogs were constructed dynamically in the heap, and
were never deleted explicitly; only when their parent QObject was
destroyed at a much later time would they be deleted.

This deferred destruction was in fact masking a segmentation fault
caused by a double-free: the entry in the dialog was not extracted
via `stealEntry()`; instead the reference was taken from the
`entryCopy` variable (same pointer), resulting in the entry getting
deleted twice, eventually.

Reproduction steps:
- Double-click on an watch entry to bring up the **Edit Watch** dialog.
- Make any edit and press **OK**.
- Quit the application gracefully to force the destruction of the
  dialog.
- A segmentation fault would be produced:

```
(gdb) bt
#0  QArrayDataPointer<char16_t>::deref() (this=<optimised out>, this=0x558b5d1a35c0) at /usr/include/c++/11/bits/atomic_base.h:392
aldelaro5#1  QArrayDataPointer<char16_t>::~QArrayDataPointer() (this=0x558b5d1a35c0, __in_chrg=<optimised out>) at /usr/include/x86_64-linux-gnu/qt6/QtCore/qarraydatapointer.h:129
aldelaro5#2  QString::~QString() (this=0x558b5d1a35c0, __in_chrg=<optimised out>) at /usr/include/x86_64-linux-gnu/qt6/QtCore/qstring.h:1302
aldelaro5#3  MemWatchEntry::~MemWatchEntry() (this=0x558b5d1a35c0, __in_chrg=<optimised out>) at /w/dolphin-memory-engine/Source/MemoryWatch/MemWatchEntry.cpp:48
aldelaro5#4  0x0000558b5c517787 in DlgAddWatchEntry::~DlgAddWatchEntry() (this=0x558b5d1be8f0, __in_chrg=<optimised out>) at /w/dolphin-memory-engine/Source/GUI/MemWatcher/Dialogs/DlgAddWatchEntry.cpp:31
aldelaro5#5  0x0000558b5c51782d in DlgAddWatchEntry::~DlgAddWatchEntry() (this=0x558b5d1be8f0, __in_chrg=<optimised out>) at /w/dolphin-memory-engine/Source/GUI/MemWatcher/Dialogs/DlgAddWatchEntry.cpp:32
aldelaro5#6  0x00007fde5556599b in QObjectPrivate::deleteChildren() () at /lib/x86_64-linux-gnu/libQt6Core.so.6
aldelaro5#7  0x00007fde5624cab8 in QWidget::~QWidget() () at /lib/x86_64-linux-gnu/libQt6Widgets.so.6
aldelaro5#8  0x0000558b5c51d0cd in MemWatchWidget::~MemWatchWidget() (this=0x558b5cd068e0, __in_chrg=<optimised out>) at /w/dolphin-memory-engine/Source/GUI/MemWatcher/MemWatchWidget.cpp:41
aldelaro5#9  0x0000558b5c5367cd in MainWindow::~MainWindow() (this=0x7ffc70ef10f0, __in_chrg=<optimised out>) at /w/dolphin-memory-engine/Source/GUI/MainWindow.cpp:56
aldelaro5#10 0x0000558b5c4f1ad7 in main(int, char**) (argc=<optimised out>, argv=<optimised out>) at /w/dolphin-memory-engine/Source/main.cpp:56
```
cristian64 added a commit to cristian64/dolphin-memory-engine that referenced this pull request Aug 11, 2024
…group node is right-clicked.

This was a regression in aldelaro5#167.

Group nodes do not have a watch entry associated with them. When a group
node was right-clicked, a null pointer would be fatally dereferenced:

```
#0  MemWatchEntry::isBoundToPointer() const (this=this@entry=0x0) at /w/dolphin-memory-engine/Source/MemoryWatch/MemWatchEntry.cpp:77
aldelaro5#1  0x0000561a4ab96c94 in MemWatchWidget::onMemWatchContextMenuRequested(QPoint const&) (this=0x561a4c28c580, pos=...) at /w/dolphin-memory-engine/Source/GUI/MemWatcher/MemWatchWidget.cpp:280
aldelaro5#2  0x00007f56ac7be023 in  () at /lib/x86_64-linux-gnu/libQt6Core.so.6
aldelaro5#3  0x00007f56ad489889 in QWidget::customContextMenuRequested(QPoint const&) () at /lib/x86_64-linux-gnu/libQt6Widgets.so.6
aldelaro5#4  0x00007f56ad4a6020 in QWidget::event(QEvent*) () at /lib/x86_64-linux-gnu/libQt6Widgets.so.6
aldelaro5#5  0x00007f56ad541406 in QFrame::event(QEvent*) () at /lib/x86_64-linux-gnu/libQt6Widgets.so.6
aldelaro5#6  0x00007f56ac765818 in QCoreApplicationPrivate::sendThroughObjectEventFilters(QObject*, QEvent*) () at /lib/x86_64-linux-gnu/libQt6Core.so.6
aldelaro5#7  0x00007f56ad44bd25 in QApplicationPrivate::notify_helper(QObject*, QEvent*) () at /lib/x86_64-linux-gnu/libQt6Widgets.so.6
aldelaro5#8  0x00007f56ad454c5e in QApplication::notify(QObject*, QEvent*) () at /lib/x86_64-linux-gnu/libQt6Widgets.so.6
aldelaro5#9  0x00007f56ac765a58 in QCoreApplication::notifyInternal2(QObject*, QEvent*) () at /lib/x86_64-linux-gnu/libQt6Core.so.6
aldelaro5#10 0x00007f56ad4b796c in  () at /lib/x86_64-linux-gnu/libQt6Widgets.so.6
aldelaro5#11 0x00007f56ad4ba635 in  () at /lib/x86_64-linux-gnu/libQt6Widgets.so.6
aldelaro5#12 0x00007f56ad44bd36 in QApplicationPrivate::notify_helper(QObject*, QEvent*) () at /lib/x86_64-linux-gnu/libQt6Widgets.so.6
aldelaro5#13 0x00007f56ac765a58 in QCoreApplication::notifyInternal2(QObject*, QEvent*) () at /lib/x86_64-linux-gnu/libQt6Core.so.6
aldelaro5#14 0x00007f56acd0a6bf in QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::MouseEvent*) () at /lib/x86_64-linux-gnu/libQt6Gui.so.6
aldelaro5#15 0x00007f56acd52c8c in QWindowSystemInterface::sendWindowSystemEvents(QFlags<QEventLoop::ProcessEventsFlag>) () at /lib/x86_64-linux-gnu/libQt6Gui.so.6
aldelaro5#16 0x00007f56a8c7686e in  () at /usr/lib/x86_64-linux-gnu/qt6/plugins/platforms/../../../libQt6XcbQpa.so.6
aldelaro5#17 0x00007f56abe32d3b in g_main_context_dispatch () at /lib/x86_64-linux-gnu/libglib-2.0.so.0
aldelaro5#18 0x00007f56abe882b8 in  () at /lib/x86_64-linux-gnu/libglib-2.0.so.0
aldelaro5#19 0x00007f56abe303e3 in g_main_context_iteration () at /lib/x86_64-linux-gnu/libglib-2.0.so.0
aldelaro5#20 0x00007f56ac98deae in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) () at /lib/x86_64-linux-gnu/libQt6Core.so.6
aldelaro5#21 0x00007f56ac772adb in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) () at /lib/x86_64-linux-gnu/libQt6Core.so.6
aldelaro5#22 0x00007f56ac76e0f3 in QCoreApplication::exec() () at /lib/x86_64-linux-gnu/libQt6Core.so.6
aldelaro5#23 0x0000561a4ab66e8c in main(int, char**) (argc=<optimised out>, argv=<optimised out>) at /w/dolphin-memory-engine/Source/main.cpp:54
```

Fixes aldelaro5#170.
dreamsyntax pushed a commit that referenced this pull request Aug 11, 2024
…group node is right-clicked.

This was a regression in #167.

Group nodes do not have a watch entry associated with them. When a group
node was right-clicked, a null pointer would be fatally dereferenced:

```
#0  MemWatchEntry::isBoundToPointer() const (this=this@entry=0x0) at /w/dolphin-memory-engine/Source/MemoryWatch/MemWatchEntry.cpp:77
#1  0x0000561a4ab96c94 in MemWatchWidget::onMemWatchContextMenuRequested(QPoint const&) (this=0x561a4c28c580, pos=...) at /w/dolphin-memory-engine/Source/GUI/MemWatcher/MemWatchWidget.cpp:280
#2  0x00007f56ac7be023 in  () at /lib/x86_64-linux-gnu/libQt6Core.so.6
#3  0x00007f56ad489889 in QWidget::customContextMenuRequested(QPoint const&) () at /lib/x86_64-linux-gnu/libQt6Widgets.so.6
#4  0x00007f56ad4a6020 in QWidget::event(QEvent*) () at /lib/x86_64-linux-gnu/libQt6Widgets.so.6
#5  0x00007f56ad541406 in QFrame::event(QEvent*) () at /lib/x86_64-linux-gnu/libQt6Widgets.so.6
#6  0x00007f56ac765818 in QCoreApplicationPrivate::sendThroughObjectEventFilters(QObject*, QEvent*) () at /lib/x86_64-linux-gnu/libQt6Core.so.6
#7  0x00007f56ad44bd25 in QApplicationPrivate::notify_helper(QObject*, QEvent*) () at /lib/x86_64-linux-gnu/libQt6Widgets.so.6
#8  0x00007f56ad454c5e in QApplication::notify(QObject*, QEvent*) () at /lib/x86_64-linux-gnu/libQt6Widgets.so.6
#9  0x00007f56ac765a58 in QCoreApplication::notifyInternal2(QObject*, QEvent*) () at /lib/x86_64-linux-gnu/libQt6Core.so.6
#10 0x00007f56ad4b796c in  () at /lib/x86_64-linux-gnu/libQt6Widgets.so.6
#11 0x00007f56ad4ba635 in  () at /lib/x86_64-linux-gnu/libQt6Widgets.so.6
#12 0x00007f56ad44bd36 in QApplicationPrivate::notify_helper(QObject*, QEvent*) () at /lib/x86_64-linux-gnu/libQt6Widgets.so.6
#13 0x00007f56ac765a58 in QCoreApplication::notifyInternal2(QObject*, QEvent*) () at /lib/x86_64-linux-gnu/libQt6Core.so.6
#14 0x00007f56acd0a6bf in QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::MouseEvent*) () at /lib/x86_64-linux-gnu/libQt6Gui.so.6
#15 0x00007f56acd52c8c in QWindowSystemInterface::sendWindowSystemEvents(QFlags<QEventLoop::ProcessEventsFlag>) () at /lib/x86_64-linux-gnu/libQt6Gui.so.6
#16 0x00007f56a8c7686e in  () at /usr/lib/x86_64-linux-gnu/qt6/plugins/platforms/../../../libQt6XcbQpa.so.6
#17 0x00007f56abe32d3b in g_main_context_dispatch () at /lib/x86_64-linux-gnu/libglib-2.0.so.0
#18 0x00007f56abe882b8 in  () at /lib/x86_64-linux-gnu/libglib-2.0.so.0
#19 0x00007f56abe303e3 in g_main_context_iteration () at /lib/x86_64-linux-gnu/libglib-2.0.so.0
#20 0x00007f56ac98deae in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) () at /lib/x86_64-linux-gnu/libQt6Core.so.6
#21 0x00007f56ac772adb in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) () at /lib/x86_64-linux-gnu/libQt6Core.so.6
#22 0x00007f56ac76e0f3 in QCoreApplication::exec() () at /lib/x86_64-linux-gnu/libQt6Core.so.6
#23 0x0000561a4ab66e8c in main(int, char**) (argc=<optimised out>, argv=<optimised out>) at /w/dolphin-memory-engine/Source/main.cpp:54
```

Fixes #170.
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.

2 participants