fix: add logger import and safe widget access for HUD rebuild
- Add logging import and logger instance - Add _safe_set_text() helper to handle deleted widgets gracefully - Use safe access in _refresh_display to prevent RuntimeError on rebuild - Wrap stylesheet updates in try/except for safety
This commit is contained in:
parent
7a55e3b246
commit
64a68f3857
|
|
@ -5,12 +5,15 @@ Cleaner, customizable HUD with collapsible sections.
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
import json
|
import json
|
||||||
|
import logging
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from dataclasses import dataclass, asdict, field
|
from dataclasses import dataclass, asdict, field
|
||||||
from typing import Optional, Dict, Any, List, Set
|
from typing import Optional, Dict, Any, List, Set
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
# Windows-specific imports for click-through support
|
# Windows-specific imports for click-through support
|
||||||
if sys.platform == 'win32':
|
if sys.platform == 'win32':
|
||||||
import ctypes
|
import ctypes
|
||||||
|
|
@ -659,72 +662,72 @@ class HUDOverlay(QWidget):
|
||||||
if hasattr(self, 'time_label'):
|
if hasattr(self, 'time_label'):
|
||||||
self.time_label.setText(f"{hours:02d}:{minutes:02d}:{seconds:02d}")
|
self.time_label.setText(f"{hours:02d}:{minutes:02d}:{seconds:02d}")
|
||||||
|
|
||||||
|
def _safe_set_text(self, widget_name: str, text: str):
|
||||||
|
"""Safely set text on a widget if it exists and is valid."""
|
||||||
|
try:
|
||||||
|
widget = getattr(self, widget_name, None)
|
||||||
|
if widget is not None:
|
||||||
|
widget.setText(text)
|
||||||
|
except RuntimeError:
|
||||||
|
# Widget was deleted
|
||||||
|
pass
|
||||||
|
|
||||||
def _refresh_display(self):
|
def _refresh_display(self):
|
||||||
"""Refresh all display labels."""
|
"""Refresh all display labels."""
|
||||||
# Profit/Loss
|
# Profit/Loss
|
||||||
if hasattr(self, 'profit_label'):
|
profit = self._stats.profit_loss
|
||||||
profit = self._stats.profit_loss
|
color = "#7FFF7F" if profit >= 0 else "#FF7F7F"
|
||||||
color = "#7FFF7F" if profit >= 0 else "#FF7F7F"
|
self._safe_set_text('profit_label', f"{profit:+.2f} PED")
|
||||||
self.profit_label.setText(f"{profit:+.2f} PED")
|
if hasattr(self, 'profit_label') and self.profit_label is not None:
|
||||||
self.profit_label.setStyleSheet(f"font-size: 18px; font-weight: bold; color: {color};")
|
try:
|
||||||
|
self.profit_label.setStyleSheet(f"font-size: 18px; font-weight: bold; color: {color};")
|
||||||
|
except RuntimeError:
|
||||||
|
pass
|
||||||
|
|
||||||
# Return %
|
# Return %
|
||||||
if hasattr(self, 'return_label'):
|
ret = self._stats.return_percentage
|
||||||
ret = self._stats.return_percentage
|
if ret >= 100:
|
||||||
if ret >= 100:
|
color = "#7FFF7F"
|
||||||
color = "#7FFF7F"
|
elif ret >= 90:
|
||||||
elif ret >= 90:
|
color = "#FFFF7F"
|
||||||
color = "#FFFF7F"
|
else:
|
||||||
else:
|
color = "#FF7F7F"
|
||||||
color = "#FF7F7F"
|
self._safe_set_text('return_label', f"{ret:.1f}%")
|
||||||
self.return_label.setText(f"{ret:.1f}%")
|
if hasattr(self, 'return_label') and self.return_label is not None:
|
||||||
self.return_label.setStyleSheet(f"font-size: 16px; font-weight: bold; color: {color};")
|
try:
|
||||||
|
self.return_label.setStyleSheet(f"font-size: 16px; font-weight: bold; color: {color};")
|
||||||
|
except RuntimeError:
|
||||||
|
pass
|
||||||
|
|
||||||
# Total Cost + Loot
|
# Total Cost + Loot
|
||||||
if hasattr(self, 'total_cost_label'):
|
self._safe_set_text('total_cost_label', f"Cost: {self._stats.cost_total:.2f}")
|
||||||
self.total_cost_label.setText(f"Cost: {self._stats.cost_total:.2f}")
|
self._safe_set_text('total_loot_label', f"Loot: {self._stats.loot_total:.2f}")
|
||||||
if hasattr(self, 'total_loot_label'):
|
|
||||||
self.total_loot_label.setText(f"Loot: {self._stats.loot_total:.2f}")
|
|
||||||
|
|
||||||
# Cost metrics
|
# Cost metrics
|
||||||
if hasattr(self, 'cps_label'):
|
self._safe_set_text('cps_label', f"Shot: {self._stats.cost_per_shot:.4f}")
|
||||||
self.cps_label.setText(f"Shot: {self._stats.cost_per_shot:.4f}")
|
self._safe_set_text('cph_label', f"Hit: {self._stats.cost_per_hit:.4f}")
|
||||||
if hasattr(self, 'cph_label'):
|
self._safe_set_text('cphl_label', f"Heal: {self._stats.cost_per_heal:.4f}")
|
||||||
self.cph_label.setText(f"Hit: {self._stats.cost_per_hit:.4f}")
|
|
||||||
if hasattr(self, 'cphl_label'):
|
|
||||||
self.cphl_label.setText(f"Heal: {self._stats.cost_per_heal:.4f}")
|
|
||||||
|
|
||||||
# Gear
|
# Gear
|
||||||
if hasattr(self, 'weapon_label'):
|
self._safe_set_text('weapon_label', f"🔫 {self._stats.current_weapon[:20]}")
|
||||||
self.weapon_label.setText(f"🔫 {self._stats.current_weapon[:20]}")
|
self._safe_set_text('armor_label', f"🛡️ {self._stats.current_armor[:20]}")
|
||||||
if hasattr(self, 'armor_label'):
|
self._safe_set_text('loadout_label', f"📋 {self._stats.current_loadout[:20]}")
|
||||||
self.armor_label.setText(f"🛡️ {self._stats.current_armor[:20]}")
|
|
||||||
if hasattr(self, 'loadout_label'):
|
|
||||||
self.loadout_label.setText(f"📋 {self._stats.current_loadout[:20]}")
|
|
||||||
|
|
||||||
# Cost breakdown
|
# Cost breakdown
|
||||||
if hasattr(self, 'wep_cost_label'):
|
self._safe_set_text('wep_cost_label', f"{self._stats.weapon_cost_total:.2f}")
|
||||||
self.wep_cost_label.setText(f"{self._stats.weapon_cost_total:.2f}")
|
self._safe_set_text('arm_cost_label', f"{self._stats.armor_cost_total:.2f}")
|
||||||
if hasattr(self, 'arm_cost_label'):
|
self._safe_set_text('heal_cost_label', f"{self._stats.healing_cost_total:.2f}")
|
||||||
self.arm_cost_label.setText(f"{self._stats.armor_cost_total:.2f}")
|
|
||||||
if hasattr(self, 'heal_cost_label'):
|
|
||||||
self.heal_cost_label.setText(f"{self._stats.healing_cost_total:.2f}")
|
|
||||||
|
|
||||||
# Combat
|
# Combat
|
||||||
if hasattr(self, 'kills_label'):
|
self._safe_set_text('kills_label', f"Kills: {self._stats.kills}")
|
||||||
self.kills_label.setText(f"Kills: {self._stats.kills}")
|
self._safe_set_text('globals_label', f"Globals: {self._stats.globals_count}")
|
||||||
if hasattr(self, 'globals_label'):
|
|
||||||
self.globals_label.setText(f"Globals: {self._stats.globals_count}")
|
|
||||||
|
|
||||||
# Damage stats
|
# Damage stats
|
||||||
if hasattr(self, 'damage_dealt_label'):
|
self._safe_set_text('damage_dealt_label', f"Dealt: {int(self._stats.damage_dealt)}")
|
||||||
self.damage_dealt_label.setText(f"Dealt: {int(self._stats.damage_dealt)}")
|
self._safe_set_text('damage_taken_label', f"Taken: {int(self._stats.damage_taken)}")
|
||||||
if hasattr(self, 'damage_taken_label'):
|
|
||||||
self.damage_taken_label.setText(f"Taken: {int(self._stats.damage_taken)}")
|
|
||||||
|
|
||||||
# Shrapnel
|
# Shrapnel
|
||||||
if hasattr(self, 'shrapnel_label'):
|
self._safe_set_text('shrapnel_label', f"💎 Shrapnel: {self._stats.shrapnel_total:.2f} PED")
|
||||||
self.shrapnel_label.setText(f"💎 Shrapnel: {self._stats.shrapnel_total:.2f} PED")
|
|
||||||
|
|
||||||
# === Public Update Methods ===
|
# === Public Update Methods ===
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue