feat(selectors): add enhancer and accessories selectors

- NEW: ui/enhancer_selector.py - Weapon/Armor enhancer browser
  - Filter by type (Damage, Economy, Range, etc.)
  - Filter by tier (1-5+)
  - Risk level indicator (Low/Medium/High break chance)
  - Warning about enhancer breakage

- NEW: ui/accessories_selector.py - Rings, Clothing, Pets browser
  - Tabbed interface: Rings / Clothing / Pets
  - Rings: Limited items highlighted
  - Clothing: Buff display, cosmetic indicator
  - Pets: Effect display, level requirements
This commit is contained in:
LemonNexus 2026-02-09 11:54:00 +00:00
parent 1c0d684c4c
commit c490a84982
2 changed files with 784 additions and 0 deletions

471
ui/accessories_selector.py Normal file
View File

@ -0,0 +1,471 @@
"""
Rings, Clothing & Pet Selector for Lemontropia Suite
Browse and search accessories from Entropia Nexus API
"""
from decimal import Decimal
from PyQt6.QtWidgets import (
QDialog, QVBoxLayout, QHBoxLayout, QLineEdit, QPushButton,
QTreeWidget, QTreeWidgetItem, QHeaderView, QLabel, QDialogButtonBox,
QProgressBar, QGroupBox, QFormLayout, QTabWidget, QWidget
)
from PyQt6.QtCore import Qt, QThread, pyqtSignal
from PyQt6.QtGui import QColor
from typing import Optional, List
from core.nexus_full_api import get_nexus_api, NexusRing, NexusClothing, NexusPet
class AccessoriesLoaderThread(QThread):
"""Background thread for loading accessories from API."""
rings_loaded = pyqtSignal(list)
clothing_loaded = pyqtSignal(list)
pets_loaded = pyqtSignal(list)
error_occurred = pyqtSignal(str)
def run(self):
try:
api = get_nexus_api()
rings = api.get_all_rings()
clothing = api.get_all_clothing()
pets = api.get_all_pets()
self.rings_loaded.emit(rings)
self.clothing_loaded.emit(clothing)
self.pets_loaded.emit(pets)
except Exception as e:
self.error_occurred.emit(str(e))
class AccessoriesSelectorDialog(QDialog):
"""Dialog for selecting rings, clothing, and pets from Entropia Nexus API."""
ring_selected = pyqtSignal(NexusRing)
clothing_selected = pyqtSignal(NexusClothing)
pet_selected = pyqtSignal(NexusPet)
def __init__(self, parent=None, initial_tab: str = "rings"):
super().__init__(parent)
self.setWindowTitle("Select Accessories - Entropia Nexus")
self.setMinimumSize(900, 600)
self.all_rings: List[NexusRing] = []
self.all_clothing: List[NexusClothing] = []
self.all_pets: List[NexusPet] = []
self.selected_ring: Optional[NexusRing] = None
self.selected_clothing: Optional[NexusClothing] = None
self.selected_pet: Optional[NexusPet] = None
self._setup_ui()
# Set initial tab
tab_map = {"rings": 0, "clothing": 1, "pets": 2}
self.tabs.setCurrentIndex(tab_map.get(initial_tab, 0))
self._load_data()
def _setup_ui(self):
layout = QVBoxLayout(self)
layout.setSpacing(10)
# Status
self.status_label = QLabel("Loading accessories from Entropia Nexus...")
layout.addWidget(self.status_label)
self.progress = QProgressBar()
self.progress.setRange(0, 0)
layout.addWidget(self.progress)
# Tabs
self.tabs = QTabWidget()
# Rings tab
self.tab_rings = self._create_rings_tab()
self.tabs.addTab(self.tab_rings["widget"], "💍 Rings")
# Clothing tab
self.tab_clothing = self._create_clothing_tab()
self.tabs.addTab(self.tab_clothing["widget"], "👕 Clothing")
# Pets tab
self.tab_pets = self._create_pets_tab()
self.tabs.addTab(self.tab_pets["widget"], "🐾 Pets")
self.tabs.currentChanged.connect(self._on_tab_changed)
layout.addWidget(self.tabs)
# Preview panel
self.preview_group = QGroupBox("Item Preview")
preview_layout = QFormLayout(self.preview_group)
self.preview_name = QLabel("-")
self.preview_type = QLabel("-")
self.preview_effect = QLabel("-")
self.preview_extra = QLabel("-")
preview_layout.addRow("Name:", self.preview_name)
preview_layout.addRow("Type:", self.preview_type)
preview_layout.addRow("Effect:", self.preview_effect)
preview_layout.addRow("", self.preview_extra)
layout.addWidget(self.preview_group)
# Buttons
buttons = QDialogButtonBox(
QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel
)
buttons.accepted.connect(self._on_accept)
buttons.rejected.connect(self.reject)
self.ok_button = buttons.button(QDialogButtonBox.StandardButton.Ok)
self.ok_button.setEnabled(False)
layout.addWidget(buttons)
def _create_rings_tab(self) -> dict:
"""Create rings selection tab."""
widget = QWidget()
layout = QVBoxLayout(widget)
# Filters
filter_layout = QHBoxLayout()
filter_layout.addWidget(QLabel("Side:"))
side_combo = QComboBox()
side_combo.addItems(["Any", "Left", "Right"])
filter_layout.addWidget(side_combo)
filter_layout.addWidget(QLabel("Limited:"))
limited_combo = QComboBox()
limited_combo.addItems(["Any", "Yes", "No"])
filter_layout.addWidget(limited_combo)
layout.addLayout(filter_layout)
# Search
search_layout = QHBoxLayout()
search_layout.addWidget(QLabel("Search:"))
search_input = QLineEdit()
search_input.setPlaceholderText("Search rings...")
search_layout.addWidget(search_input)
clear_btn = QPushButton("Clear")
search_layout.addWidget(clear_btn)
layout.addLayout(search_layout)
# Tree
tree = QTreeWidget()
tree.setHeaderLabels(["Name", "Effect Type", "Value", "Side", "Limited"])
header = tree.header()
header.setSectionResizeMode(QHeaderView.ResizeMode.ResizeToContents)
tree.itemSelectionChanged.connect(self._on_selection_changed)
tree.itemDoubleClicked.connect(self._on_double_click)
layout.addWidget(tree)
return {
"widget": widget,
"side": side_combo,
"limited": limited_combo,
"search": search_input,
"clear": clear_btn,
"tree": tree
}
def _create_clothing_tab(self) -> dict:
"""Create clothing selection tab."""
widget = QWidget()
layout = QVBoxLayout(widget)
# Filters
filter_layout = QHBoxLayout()
filter_layout.addWidget(QLabel("Slot:"))
slot_combo = QComboBox()
slot_combo.addItems(["Any", "Face", "Body", "Legs", "Feet", "Back"])
filter_layout.addWidget(slot_combo)
filter_layout.addWidget(QLabel("Cosmetic:"))
cosmetic_combo = QComboBox()
cosmetic_combo.addItems(["Any", "Yes", "No"])
filter_layout.addWidget(cosmetic_combo)
layout.addLayout(filter_layout)
# Search
search_layout = QHBoxLayout()
search_layout.addWidget(QLabel("Search:"))
search_input = QLineEdit()
search_input.setPlaceholderText("Search clothing...")
search_layout.addWidget(search_input)
clear_btn = QPushButton("Clear")
search_layout.addWidget(clear_btn)
layout.addLayout(search_layout)
# Tree
tree = QTreeWidget()
tree.setHeaderLabels(["Name", "Slot", "Buffs", "Cosmetic"])
header = tree.header()
header.setSectionResizeMode(QHeaderView.ResizeMode.ResizeToContents)
tree.itemSelectionChanged.connect(self._on_selection_changed)
tree.itemDoubleClicked.connect(self._on_double_click)
layout.addWidget(tree)
return {
"widget": widget,
"slot": slot_combo,
"cosmetic": cosmetic_combo,
"search": search_input,
"clear": clear_btn,
"tree": tree
}
def _create_pets_tab(self) -> dict:
"""Create pets selection tab."""
widget = QWidget()
layout = QVBoxLayout(widget)
# Search
search_layout = QHBoxLayout()
search_layout.addWidget(QLabel("Search:"))
search_input = QLineEdit()
search_input.setPlaceholderText("Search pets...")
search_layout.addWidget(search_input)
clear_btn = QPushButton("Clear")
search_layout.addWidget(clear_btn)
layout.addLayout(search_layout)
# Tree
tree = QTreeWidget()
tree.setHeaderLabels(["Name", "Effect Type", "Effect Value", "Level Req"])
header = tree.header()
header.setSectionResizeMode(QHeaderView.ResizeMode.ResizeToContents)
tree.itemSelectionChanged.connect(self._on_selection_changed)
tree.itemDoubleClicked.connect(self._on_double_click)
layout.addWidget(tree)
return {
"widget": widget,
"search": search_input,
"clear": clear_btn,
"tree": tree
}
def _load_data(self):
"""Load accessories in background thread."""
self.loader = AccessoriesLoaderThread()
self.loader.rings_loaded.connect(self._on_rings_loaded)
self.loader.clothing_loaded.connect(self._on_clothing_loaded)
self.loader.pets_loaded.connect(self._on_pets_loaded)
self.loader.error_occurred.connect(self._on_load_error)
self.loader.start()
def _on_rings_loaded(self, rings: List[NexusRing]):
"""Handle loaded rings."""
self.all_rings = rings
self._populate_rings()
self._update_status()
def _on_clothing_loaded(self, clothing: List[NexusClothing]):
"""Handle loaded clothing."""
self.all_clothing = clothing
self._populate_clothing()
self._update_status()
def _on_pets_loaded(self, pets: List[NexusPet]):
"""Handle loaded pets."""
self.all_pets = pets
self._populate_pets()
self._update_status()
def _on_load_error(self, error: str):
"""Handle load error."""
self.status_label.setText(f"Error loading accessories: {error}")
self.progress.setRange(0, 100)
self.progress.setValue(0)
def _update_status(self):
"""Update status label."""
total = len(self.all_rings) + len(self.all_clothing) + len(self.all_pets)
if total > 0:
self.status_label.setText(
f"Loaded {len(self.all_rings)} rings, "
f"{len(self.all_clothing)} clothing items, "
f"{len(self.all_pets)} pets"
)
self.progress.setRange(0, 100)
self.progress.setValue(100)
def _populate_rings(self):
"""Populate rings tree."""
tree = self.tab_rings["tree"]
tree.clear()
for ring in self.all_rings:
item = QTreeWidgetItem()
item.setText(0, ring.name)
item.setText(1, ring.effect_type)
item.setText(2, str(ring.effect_value))
item.setText(3, "Left/Right")
item.setText(4, "Yes" if ring.is_limited else "No")
# Color limited items
if ring.is_limited:
item.setForeground(4, QColor("#ff9800"))
item.setData(0, Qt.ItemDataRole.UserRole, ring)
tree.addTopLevelItem(item)
# Connect filters
self.tab_rings["search"].textChanged.connect(self._filter_rings)
self.tab_rings["clear"].clicked.connect(self.tab_rings["search"].clear)
def _populate_clothing(self):
"""Populate clothing tree."""
tree = self.tab_clothing["tree"]
tree.clear()
for item_data in self.all_clothing:
item = QTreeWidgetItem()
item.setText(0, item_data.name)
item.setText(1, item_data.slot)
buffs = ", ".join([f"{k}:{v}" for k, v in item_data.buffs.items()])
item.setText(2, buffs if buffs else "None")
item.setText(3, "Yes" if item_data.is_cosmetic else "No")
# Color cosmetic items
if not item_data.is_cosmetic:
item.setForeground(3, QColor("#4caf50"))
item.setData(0, Qt.ItemDataRole.UserRole, item_data)
tree.addTopLevelItem(item)
# Connect filters
self.tab_clothing["search"].textChanged.connect(self._filter_clothing)
self.tab_clothing["clear"].clicked.connect(self.tab_clothing["search"].clear)
def _populate_pets(self):
"""Populate pets tree."""
tree = self.tab_pets["tree"]
tree.clear()
for pet in self.all_pets:
item = QTreeWidgetItem()
item.setText(0, pet.name)
item.setText(1, pet.effect_type)
item.setText(2, str(pet.effect_value))
item.setText(3, str(pet.level_required) if pet.level_required > 0 else "-")
# Color by level requirement
if pet.level_required > 50:
item.setForeground(3, QColor("#f44336")) # Red
elif pet.level_required > 20:
item.setForeground(3, QColor("#ff9800")) # Orange
item.setData(0, Qt.ItemDataRole.UserRole, pet)
tree.addTopLevelItem(item)
# Connect filters
self.tab_pets["search"].textChanged.connect(self._filter_pets)
self.tab_pets["clear"].clicked.connect(self.tab_pets["search"].clear)
def _filter_rings(self):
"""Filter rings based on search and filters."""
search = self.tab_rings["search"].text().lower()
tree = self.tab_rings["tree"]
for i in range(tree.topLevelItemCount()):
item = tree.topLevelItem(i)
ring = item.data(0, Qt.ItemDataRole.UserRole)
visible = search in ring.name.lower() or search in ring.effect_type.lower()
item.setHidden(not visible)
def _filter_clothing(self):
"""Filter clothing based on search and filters."""
search = self.tab_clothing["search"].text().lower()
tree = self.tab_clothing["tree"]
for i in range(tree.topLevelItemCount()):
item = tree.topLevelItem(i)
clothing = item.data(0, Qt.ItemDataRole.UserRole)
visible = search in clothing.name.lower() or search in clothing.slot.lower()
item.setHidden(not visible)
def _filter_pets(self):
"""Filter pets based on search."""
search = self.tab_pets["search"].text().lower()
tree = self.tab_pets["tree"]
for i in range(tree.topLevelItemCount()):
item = tree.topLevelItem(i)
pet = item.data(0, Qt.ItemDataRole.UserRole)
visible = search in pet.name.lower() or search in pet.effect_type.lower()
item.setHidden(not visible)
def _on_tab_changed(self, index: int):
"""Handle tab change."""
self.selected_ring = None
self.selected_clothing = None
self.selected_pet = None
self.ok_button.setEnabled(False)
self.preview_name.setText("-")
self.preview_type.setText("-")
self.preview_effect.setText("-")
self.preview_extra.setText("-")
def _on_selection_changed(self):
"""Handle selection change."""
index = self.tabs.currentIndex()
if index == 0: # Rings
items = self.tab_rings["tree"].selectedItems()
if items:
self.selected_ring = items[0].data(0, Qt.ItemDataRole.UserRole)
self._update_preview_ring(self.selected_ring)
self.ok_button.setEnabled(True)
elif index == 1: # Clothing
items = self.tab_clothing["tree"].selectedItems()
if items:
self.selected_clothing = items[0].data(0, Qt.ItemDataRole.UserRole)
self._update_preview_clothing(self.selected_clothing)
self.ok_button.setEnabled(True)
elif index == 2: # Pets
items = self.tab_pets["tree"].selectedItems()
if items:
self.selected_pet = items[0].data(0, Qt.ItemDataRole.UserRole)
self._update_preview_pet(self.selected_pet)
self.ok_button.setEnabled(True)
def _update_preview_ring(self, ring: NexusRing):
"""Update preview for ring."""
self.preview_name.setText(ring.name)
self.preview_type.setText("Ring (Left/Right)")
self.preview_effect.setText(f"{ring.effect_type}: {ring.effect_value}")
self.preview_extra.setText(f"Limited: {'Yes' if ring.is_limited else 'No'}")
def _update_preview_clothing(self, clothing: NexusClothing):
"""Update preview for clothing."""
self.preview_name.setText(clothing.name)
self.preview_type.setText(f"Clothing ({clothing.slot})")
buffs = ", ".join([f"{k}:{v}" for k, v in clothing.buffs.items()])
self.preview_effect.setText(buffs if buffs else "No buffs")
self.preview_extra.setText(f"Cosmetic: {'Yes' if clothing.is_cosmetic else 'No'}")
def _update_preview_pet(self, pet: NexusPet):
"""Update preview for pet."""
self.preview_name.setText(pet.name)
self.preview_type.setText("Combat Pet")
self.preview_effect.setText(f"{pet.effect_type}: {pet.effect_value}")
self.preview_extra.setText(f"Level Required: {pet.level_required}" if pet.level_required > 0 else "No level requirement")
def _on_double_click(self, item, column):
"""Handle double click."""
self._on_accept()
def _on_accept(self):
"""Handle OK button."""
index = self.tabs.currentIndex()
if index == 0 and self.selected_ring:
self.ring_selected.emit(self.selected_ring)
self.accept()
elif index == 1 and self.selected_clothing:
self.clothing_selected.emit(self.selected_clothing)
self.accept()
elif index == 2 and self.selected_pet:
self.pet_selected.emit(self.selected_pet)
self.accept()

313
ui/enhancer_selector.py Normal file
View File

@ -0,0 +1,313 @@
"""
Enhancer Selector for Lemontropia Suite
Browse and search weapon/armor enhancers
"""
from decimal import Decimal
from PyQt6.QtWidgets import (
QDialog, QVBoxLayout, QHBoxLayout, QLineEdit, QPushButton,
QTreeWidget, QTreeWidgetItem, QHeaderView, QLabel, QDialogButtonBox,
QProgressBar, QGroupBox, QFormLayout, QComboBox, QCheckBox
)
from PyQt6.QtCore import Qt, QThread, pyqtSignal
from PyQt6.QtGui import QColor
from typing import Optional, List
from core.nexus_full_api import get_nexus_api, NexusEnhancer
class EnhancerLoaderThread(QThread):
"""Background thread for loading enhancers from API."""
enhancers_loaded = pyqtSignal(list)
error_occurred = pyqtSignal(str)
def run(self):
try:
api = get_nexus_api()
enhancers = api.get_all_enhancers()
self.enhancers_loaded.emit(enhancers)
except Exception as e:
self.error_occurred.emit(str(e))
class EnhancerSelectorDialog(QDialog):
"""Dialog for selecting enhancers from Entropia Nexus API."""
enhancer_selected = pyqtSignal(NexusEnhancer)
def __init__(self, parent=None, enhancer_type: str = "", target_tier: int = 1):
super().__init__(parent)
self.preferred_type = enhancer_type.lower()
self.target_tier = target_tier
type_names = {
"damage": "Damage Enhancer",
"economy": "Economy Enhancer",
"range": "Range Enhancer",
"accuracy": "Accuracy Enhancer",
"skillmod": "Skill Mod Enhancer"
}
title_type = type_names.get(self.preferred_type, "Enhancer")
self.setWindowTitle(f"Select {title_type} - Entropia Nexus")
self.setMinimumSize(900, 600)
self.all_enhancers: List[NexusEnhancer] = []
self.selected_enhancer: Optional[NexusEnhancer] = None
self._setup_ui()
self._load_data()
def _setup_ui(self):
layout = QVBoxLayout(self)
layout.setSpacing(10)
# Warning about enhancer breakage
warning = QLabel("⚠️ Warning: Enhancers have a chance to break on each use!")
warning.setStyleSheet("color: #ff9800; font-weight: bold; padding: 5px;")
layout.addWidget(warning)
# Status
self.status_label = QLabel("Loading enhancers from Entropia Nexus...")
layout.addWidget(self.status_label)
self.progress = QProgressBar()
self.progress.setRange(0, 0)
layout.addWidget(self.progress)
# Filters
filter_layout = QHBoxLayout()
filter_layout.addWidget(QLabel("Type:"))
self.type_combo = QComboBox()
self.type_combo.addItems([
"All Types", "Damage", "Economy", "Range",
"Accuracy", "Skill Mod", "Defense", "Durability"
])
if self.preferred_type:
# Map type names
type_map = {
"damage": "Damage",
"economy": "Economy",
"range": "Range",
"accuracy": "Accuracy",
"skillmod": "Skill Mod"
}
preferred = type_map.get(self.preferred_type, "")
index = self.type_combo.findText(preferred)
if index >= 0:
self.type_combo.setCurrentIndex(index)
self.type_combo.currentTextChanged.connect(self._apply_filters)
filter_layout.addWidget(self.type_combo)
filter_layout.addWidget(QLabel("Tier:"))
self.tier_combo = QComboBox()
self.tier_combo.addItems(["All Tiers", "Tier 1", "Tier 2", "Tier 3", "Tier 4", "Tier 5+"])
if self.target_tier > 0 and self.target_tier <= 5:
self.tier_combo.setCurrentIndex(self.target_tier)
self.tier_combo.currentTextChanged.connect(self._apply_filters)
filter_layout.addWidget(self.tier_combo)
# Show breakable only
self.breakable_check = QCheckBox("Show breakable only")
self.breakable_check.setChecked(False)
self.breakable_check.stateChanged.connect(self._apply_filters)
filter_layout.addWidget(self.breakable_check)
layout.addLayout(filter_layout)
# Search
search_layout = QHBoxLayout()
search_layout.addWidget(QLabel("Search:"))
self.search_input = QLineEdit()
self.search_input.setPlaceholderText("Search enhancers...")
self.search_input.textChanged.connect(self._apply_filters)
search_layout.addWidget(self.search_input)
self.clear_btn = QPushButton("Clear")
self.clear_btn.clicked.connect(self._clear_search)
search_layout.addWidget(self.clear_btn)
layout.addLayout(search_layout)
# Results tree
self.results_tree = QTreeWidget()
self.results_tree.setHeaderLabels([
"Name", "Type", "Tier", "Effect", "Break Chance", "Risk Level"
])
header = self.results_tree.header()
header.setSectionResizeMode(QHeaderView.ResizeMode.ResizeToContents)
header.setStretchLastSection(False)
self.results_tree.itemSelectionChanged.connect(self._on_selection_changed)
self.results_tree.itemDoubleClicked.connect(self._on_double_click)
layout.addWidget(self.results_tree)
# Preview panel
self.preview_group = QGroupBox("Enhancer Preview")
preview_layout = QFormLayout(self.preview_group)
self.preview_name = QLabel("-")
self.preview_type = QLabel("-")
self.preview_tier = QLabel("-")
self.preview_effect = QLabel("-")
self.preview_break = QLabel("-")
preview_layout.addRow("Name:", self.preview_name)
preview_layout.addRow("Type:", self.preview_type)
preview_layout.addRow("Tier:", self.preview_tier)
preview_layout.addRow("Effect:", self.preview_effect)
preview_layout.addRow("Break Chance:", self.preview_break)
layout.addWidget(self.preview_group)
# Buttons
buttons = QDialogButtonBox(
QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel
)
buttons.accepted.connect(self._on_accept)
buttons.rejected.connect(self.reject)
self.ok_button = buttons.button(QDialogButtonBox.StandardButton.Ok)
self.ok_button.setEnabled(False)
layout.addWidget(buttons)
def _load_data(self):
"""Load enhancers in background thread."""
self.loader = EnhancerLoaderThread()
self.loader.enhancers_loaded.connect(self._on_enhancers_loaded)
self.loader.error_occurred.connect(self._on_load_error)
self.loader.start()
def _on_enhancers_loaded(self, enhancers: List[NexusEnhancer]):
"""Handle loaded enhancers."""
self.all_enhancers = enhancers
self.status_label.setText(f"Loaded {len(enhancers)} enhancers from Entropia Nexus")
self.progress.setRange(0, 100)
self.progress.setValue(100)
self._apply_filters()
def _on_load_error(self, error: str):
"""Handle load error."""
self.status_label.setText(f"Error loading enhancers: {error}")
self.progress.setRange(0, 100)
self.progress.setValue(0)
def _apply_filters(self):
"""Apply all filters and search."""
enhancers = self.all_enhancers.copy()
# Type filter
type_filter = self.type_combo.currentText()
if type_filter != "All Types":
type_lower = type_filter.lower().replace(" ", "")
enhancers = [e for e in enhancers if type_lower in e.enhancer_type.lower()]
# Tier filter
tier_filter = self.tier_combo.currentText()
if tier_filter != "All Tiers":
if tier_filter == "Tier 5+":
enhancers = [e for e in enhancers if e.tier >= 5]
else:
tier_num = int(tier_filter.replace("Tier ", ""))
enhancers = [e for e in enhancers if e.tier == tier_num]
# Breakable filter
if self.breakable_check.isChecked():
enhancers = [e for e in enhancers if e.break_chance > 0]
# Search filter
search_text = self.search_input.text()
if search_text:
query = search_text.lower()
enhancers = [e for e in enhancers if query in e.name.lower()]
self._populate_results(enhancers)
# Update status
if search_text:
self.status_label.setText(f"Found {len(enhancers)} enhancers matching '{search_text}'")
else:
self.status_label.setText(f"Showing {len(enhancers)} of {len(self.all_enhancers)} enhancers")
def _populate_results(self, enhancers: List[NexusEnhancer]):
"""Populate results tree."""
self.results_tree.clear()
# Sort by tier (lowest first - safer) then effect value
enhancers = sorted(enhancers, key=lambda e: (e.tier, -e.effect_value))
for enhancer in enhancers:
item = QTreeWidgetItem()
item.setText(0, enhancer.name)
item.setText(1, enhancer.enhancer_type.title())
item.setText(2, str(enhancer.tier))
item.setText(3, f"+{enhancer.effect_value}%")
item.setText(4, f"{enhancer.break_chance * 100:.1f}%")
# Risk level
if enhancer.break_chance <= 0.01:
risk = "Low"
color = QColor("#4caf50") # Green
elif enhancer.break_chance <= 0.05:
risk = "Medium"
color = QColor("#ff9800") # Orange
else:
risk = "High"
color = QColor("#f44336") # Red
item.setText(5, risk)
item.setForeground(5, color)
# Color code tier
tier_colors = {
1: QColor("#4caf50"), # Green
2: QColor("#8bc34a"), # Light green
3: QColor("#ff9800"), # Orange
4: QColor("#ff5722"), # Deep orange
5: QColor("#f44336"), # Red
}
if enhancer.tier in tier_colors:
item.setForeground(2, tier_colors[enhancer.tier])
item.setData(0, Qt.ItemDataRole.UserRole, enhancer)
self.results_tree.addTopLevelItem(item)
def _clear_search(self):
"""Clear search and filters."""
self.search_input.clear()
self.type_combo.setCurrentIndex(0)
self.tier_combo.setCurrentIndex(0)
self.breakable_check.setChecked(False)
self._apply_filters()
def _on_selection_changed(self):
"""Handle selection change."""
items = self.results_tree.selectedItems()
if items:
self.selected_enhancer = items[0].data(0, Qt.ItemDataRole.UserRole)
self.ok_button.setEnabled(True)
self._update_preview(self.selected_enhancer)
else:
self.selected_enhancer = None
self.ok_button.setEnabled(False)
def _update_preview(self, enhancer: NexusEnhancer):
"""Update preview panel."""
self.preview_name.setText(enhancer.name)
self.preview_type.setText(enhancer.enhancer_type.title())
self.preview_tier.setText(str(enhancer.tier))
self.preview_effect.setText(f"+{enhancer.effect_value}%")
self.preview_break.setText(f"{enhancer.break_chance * 100:.1f}%")
# Color code break chance
if enhancer.break_chance <= 0.01:
self.preview_break.setStyleSheet("color: #4caf50;") # Green
elif enhancer.break_chance <= 0.05:
self.preview_break.setStyleSheet("color: #ff9800;") # Orange
else:
self.preview_break.setStyleSheet("color: #f44336;") # Red
def _on_double_click(self, item, column):
"""Handle double click."""
self._on_accept()
def _on_accept(self):
"""Handle OK button."""
if self.selected_enhancer:
self.enhancer_selected.emit(self.selected_enhancer)
self.accept()