Repository: pyqtgraph/pyqtgraph

Issue:
Right-clicking adds to plotItem.vb.menu.actions()
### Short description
Opening the context-menu via right-clicking adds an entry to the list returned by plotItem.vb.menu.actions(). Tbh this behaviour didn't lead to complications for me, but I don't think it should behave like this.

### Code to reproduce
In REPL
```python
import pyqtgraph as pg

p = pg.plot([1,2,3,[4,5,6])
len(p.plotItem.vb.menu.actions()) # = 4
# now right-click in plot window
len(p.plotItem.vb.menu.actions()) # = 7
# now right-click in plot window
len(p.plotItem.vb.menu.actions()) # = 8
# repeated right clicking and evaluation of len(...) shows always + 1
```

### Expected behavior
After first right-click, the actions-list should be constant (at 7 in this case).

### Tested environment(s)

 * PyQtGraph version: 0.12.4
 * Qt Python binding: PyQt6 6.3.0 Qt 6.3.0
 * Python version: 3.9.2

### Additional context
It might be due to what GraphicsScene.addParentContextMenus is doing:
https://github.com/pyqtgraph/pyqtgraph/blob/e0b3a30becef0c473dd99e9efd3a53ef12444eae/pyqtgraph/GraphicsScene/GraphicsScene.py#L492-L506
where it looks like it might in this case always call addSeparator. I'm not entirely sure, though.

BTW: the reason I came to this was, because I wanted to remove some of the entries of the contextmenu, as they don't work with the data I am plotting (different points have different brushes which clashes with some plot options).

Cheers
Right-clicking adds to plotItem.vb.menu.actions()
### Short description
Opening the context-menu via right-clicking adds an entry to the list returned by plotItem.vb.menu.actions(). Tbh this behaviour didn't lead to complications for me, but I don't think it should behave like this.

### Code to reproduce
In REPL
```python
import pyqtgraph as pg

p = pg.plot([1,2,3,[4,5,6])
len(p.plotItem.vb.menu.actions()) # = 4
# now right-click in plot window
len(p.plotItem.vb.menu.actions()) # = 7
# now right-click in plot window
len(p.plotItem.vb.menu.actions()) # = 8
# repeated right clicking and evaluation of len(...) shows always + 1
```

### Expected behavior
After first right-click, the actions-list should be constant (at 7 in this case).

### Tested environment(s)

 * PyQtGraph version: 0.12.4
 * Qt Python binding: PyQt6 6.3.0 Qt 6.3.0
 * Python version: 3.9.2

### Additional context
It might be due to what GraphicsScene.addParentContextMenus is doing:
https://github.com/pyqtgraph/pyqtgraph/blob/e0b3a30becef0c473dd99e9efd3a53ef12444eae/pyqtgraph/GraphicsScene/GraphicsScene.py#L492-L506
where it looks like it might in this case always call addSeparator. I'm not entirely sure, though.

BTW: the reason I came to this was, because I wanted to remove some of the entries of the contextmenu, as they don't work with the data I am plotting (different points have different brushes which clashes with some plot options).

Cheers


Discussion:

Resolving patch:
diff --git a/pyqtgraph/GraphicsScene/GraphicsScene.py b/pyqtgraph/GraphicsScene/GraphicsScene.py
--- a/pyqtgraph/GraphicsScene/GraphicsScene.py
+++ b/pyqtgraph/GraphicsScene/GraphicsScene.py
@@ -501,18 +501,23 @@ def addParentContextMenus(self, item, menu, event):
                 menusToAdd.extend(subMenus)
             else:
                 menusToAdd.append(subMenus)
+        # Filter out options that were previously added
+        existingActions = menu.actions()
+        actsToAdd = []
+        for menuOrAct in menusToAdd:
+            if isinstance(menuOrAct, QtWidgets.QMenu):
+                menuOrAct = menuOrAct.menuAction()
+            elif not isinstance(menuOrAct, QtGui.QAction):
+                raise Exception(
+                    f"Cannot add object {menuOrAct} (type={type(menuOrAct)}) to QMenu."
+                )
+            if menuOrAct not in existingActions:
+                actsToAdd.append(menuOrAct)
 
-        if menusToAdd:
+        if actsToAdd:
             menu.addSeparator()
 
-        for m in menusToAdd:
-            if isinstance(m, QtWidgets.QMenu):
-                menu.addAction(m.menuAction())
-            elif isinstance(m, QtGui.QAction):
-                menu.addAction(m)
-            else:
-                raise Exception("Cannot add object %s (type=%s) to QMenu." % (str(m), str(type(m))))
-            
+        menu.addActions(actsToAdd)
         return menu
 
     def getContextMenus(self, event):


Test patch: