From ce9850e1c29cec920ba55be02c7ee697ca2f5f8a Mon Sep 17 00:00:00 2001 From: sandorstormen Date: Sat, 6 Dec 2025 08:46:51 +0100 Subject: [PATCH 1/2] Add itemChange method to AttackerItem to handle scene removal --- mal_gui/object_explorer/attacker_item.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/mal_gui/object_explorer/attacker_item.py b/mal_gui/object_explorer/attacker_item.py index ece318b..ef056c6 100644 --- a/mal_gui/object_explorer/attacker_item.py +++ b/mal_gui/object_explorer/attacker_item.py @@ -1,5 +1,6 @@ from PySide6.QtGui import QColor from PySide6.QtCore import QTimer +from PySide6.QtWidgets import QGraphicsItem from .item_base import ItemBase @@ -43,6 +44,12 @@ def get_item_attribute_values(self): } def update_status_color(self): + # Check if the item is still in a scene before updating + if self.scene() is None: + # Item has been removed from scene, stop the timer + self.timer.stop() + return + self.attacker_toggle_state = not self.attacker_toggle_state if self.attacker_toggle_state: self.status_color = QColor(0, 255, 0) # Green @@ -50,6 +57,14 @@ def update_status_color(self): self.status_color = QColor(255, 0, 0) # Red self.update() + def itemChange(self, change, value): + """Override to stop timer when item is removed from scene""" + if change == QGraphicsItem.ItemSceneChange: + # If the item is being removed from the scene (value is None) + if value is None and self.timer.isActive(): + self.timer.stop() + return super().itemChange(change, value) + def serialize(self): return { 'title': self.title, From 2826f7dc48320d925ca882159115da6574d9b6cd Mon Sep 17 00:00:00 2001 From: Joakim Loxdal Date: Tue, 9 Dec 2025 11:45:58 +0100 Subject: [PATCH 2/2] fix: make sure attacker update_status_color is only called if C++ object exists --- mal_gui/object_explorer/attacker_item.py | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/mal_gui/object_explorer/attacker_item.py b/mal_gui/object_explorer/attacker_item.py index ef056c6..88c8cd4 100644 --- a/mal_gui/object_explorer/attacker_item.py +++ b/mal_gui/object_explorer/attacker_item.py @@ -1,6 +1,7 @@ from PySide6.QtGui import QColor from PySide6.QtCore import QTimer from PySide6.QtWidgets import QGraphicsItem +from shiboken6 import isValid from .item_base import ItemBase @@ -20,7 +21,7 @@ def __init__( self.attacker_toggle_state = False self.timer = QTimer() - self.status_color = QColor(0, 255, 0) + self.status_color = QColor(0, 255, 0) self.attacker_toggle_state = False self.timer.timeout.connect(self.update_status_color) self.timer.start(500) @@ -30,7 +31,7 @@ def __init__( def update_type_text_item_position(self): super().update_type_text_item_position() # For Attacker make the background of type As Red - self.asset_type_background_color = QColor(255, 0, 0) #Red + self.asset_type_background_color = QColor(255, 0, 0) # Red def update_name(self): """Update the name of the attacker""" @@ -44,23 +45,26 @@ def get_item_attribute_values(self): } def update_status_color(self): - # Check if the item is still in a scene before updating + # Object may already be deleted on C++ side + if not isValid(self): + return + + # Still check if removed from scene if self.scene() is None: - # Item has been removed from scene, stop the timer - self.timer.stop() + if self.timer.isActive(): + self.timer.stop() return - + self.attacker_toggle_state = not self.attacker_toggle_state if self.attacker_toggle_state: - self.status_color = QColor(0, 255, 0) # Green + self.status_color = QColor(0, 255, 0) # Green else: - self.status_color = QColor(255, 0, 0) # Red + self.status_color = QColor(255, 0, 0) # Red self.update() def itemChange(self, change, value): """Override to stop timer when item is removed from scene""" if change == QGraphicsItem.ItemSceneChange: - # If the item is being removed from the scene (value is None) if value is None and self.timer.isActive(): self.timer.stop() return super().itemChange(change, value)