245 lines
9.4 KiB
Python
245 lines
9.4 KiB
Python
"""
|
|
Searchable Healing Tool Selector for Lemontropia Suite
|
|
Browse and search healing tools 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, QComboBox
|
|
)
|
|
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, NexusHealingTool
|
|
|
|
|
|
class HealingLoaderThread(QThread):
|
|
"""Background thread for loading healing tools from API."""
|
|
tools_loaded = pyqtSignal(list)
|
|
error_occurred = pyqtSignal(str)
|
|
|
|
def run(self):
|
|
try:
|
|
api = get_nexus_api()
|
|
tools = api.get_all_healing_tools()
|
|
self.tools_loaded.emit(tools)
|
|
except Exception as e:
|
|
self.error_occurred.emit(str(e))
|
|
|
|
|
|
class HealingSelectorDialog(QDialog):
|
|
"""Dialog for selecting healing tools from Entropia Nexus API with search."""
|
|
|
|
tool_selected = pyqtSignal(NexusHealingTool)
|
|
|
|
def __init__(self, parent=None):
|
|
super().__init__(parent)
|
|
self.setWindowTitle("Select Healing Tool - Entropia Nexus")
|
|
self.setMinimumSize(900, 600)
|
|
|
|
self.all_tools: List[NexusHealingTool] = []
|
|
self.selected_tool: Optional[NexusHealingTool] = None
|
|
|
|
self._setup_ui()
|
|
self._load_data()
|
|
|
|
def _setup_ui(self):
|
|
layout = QVBoxLayout(self)
|
|
layout.setSpacing(10)
|
|
|
|
# Status
|
|
self.status_label = QLabel("Loading healing tools 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", "FAP (Medical Tool)", "Restoration Chip", "Limited (L)"])
|
|
self.type_combo.currentTextChanged.connect(self._apply_filters)
|
|
filter_layout.addWidget(self.type_combo)
|
|
|
|
filter_layout.addWidget(QLabel("Min Heal:"))
|
|
self.min_heal_combo = QComboBox()
|
|
self.min_heal_combo.addItems(["Any", "10+", "25+", "50+", "75+", "100+"])
|
|
self.min_heal_combo.currentTextChanged.connect(self._apply_filters)
|
|
filter_layout.addWidget(self.min_heal_combo)
|
|
|
|
layout.addLayout(filter_layout)
|
|
|
|
# Search
|
|
search_layout = QHBoxLayout()
|
|
search_layout.addWidget(QLabel("Search:"))
|
|
self.search_input = QLineEdit()
|
|
self.search_input.setPlaceholderText("Type to search healing tools...")
|
|
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", "Heal Amount", "Decay (PEC)", "Economy (hp/pec)", "Prof. Level", "Limited"
|
|
])
|
|
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("Healing Tool Preview")
|
|
preview_layout = QFormLayout(self.preview_group)
|
|
self.preview_name = QLabel("-")
|
|
self.preview_heal = QLabel("-")
|
|
self.preview_decay = QLabel("-")
|
|
self.preview_economy = QLabel("-")
|
|
self.preview_cost = QLabel("-")
|
|
preview_layout.addRow("Name:", self.preview_name)
|
|
preview_layout.addRow("Heal Amount:", self.preview_heal)
|
|
preview_layout.addRow("Decay:", self.preview_decay)
|
|
preview_layout.addRow("Economy:", self.preview_economy)
|
|
preview_layout.addRow("Cost/Heal:", self.preview_cost)
|
|
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 healing tools in background thread."""
|
|
self.loader = HealingLoaderThread()
|
|
self.loader.tools_loaded.connect(self._on_tools_loaded)
|
|
self.loader.error_occurred.connect(self._on_load_error)
|
|
self.loader.start()
|
|
|
|
def _on_tools_loaded(self, tools: List[NexusHealingTool]):
|
|
"""Handle loaded tools."""
|
|
self.all_tools = tools
|
|
self.status_label.setText(f"Loaded {len(tools)} healing tools 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 healing tools: {error}")
|
|
self.progress.setRange(0, 100)
|
|
self.progress.setValue(0)
|
|
|
|
def _apply_filters(self):
|
|
"""Apply all filters and search."""
|
|
tools = self.all_tools.copy()
|
|
|
|
# Type filter
|
|
type_filter = self.type_combo.currentText()
|
|
if type_filter == "FAP (Medical Tool)":
|
|
tools = [t for t in tools if t.type == 'fap']
|
|
elif type_filter == "Restoration Chip":
|
|
tools = [t for t in tools if 'chip' in t.type.lower()]
|
|
elif type_filter == "Limited (L)":
|
|
tools = [t for t in tools if t.is_limited]
|
|
|
|
# Min heal filter
|
|
min_heal = self.min_heal_combo.currentText()
|
|
if min_heal != "Any":
|
|
min_val = int(min_heal.replace("+", ""))
|
|
tools = [t for t in tools if t.heal_amount >= min_val]
|
|
|
|
# Search filter
|
|
search_text = self.search_input.text()
|
|
if search_text:
|
|
query = search_text.lower()
|
|
tools = [t for t in tools if query in t.name.lower()]
|
|
|
|
self._populate_results(tools)
|
|
|
|
# Update status
|
|
if search_text:
|
|
self.status_label.setText(f"Found {len(tools)} tools matching '{search_text}'")
|
|
else:
|
|
self.status_label.setText(f"Showing {len(tools)} of {len(self.all_tools)} tools")
|
|
|
|
def _populate_results(self, tools: List[NexusHealingTool]):
|
|
"""Populate results tree."""
|
|
self.results_tree.clear()
|
|
|
|
# Sort by economy (best first)
|
|
tools = sorted(tools, key=lambda t: t.heal_per_pec, reverse=True)
|
|
|
|
for tool in tools:
|
|
item = QTreeWidgetItem()
|
|
item.setText(0, tool.name)
|
|
item.setText(1, tool.type)
|
|
item.setText(2, str(tool.heal_amount))
|
|
item.setText(3, f"{tool.decay:.2f}")
|
|
item.setText(4, f"{tool.heal_per_pec:.2f}")
|
|
item.setText(5, str(tool.profession_level) if tool.profession_level > 0 else "-")
|
|
item.setText(6, "Yes" if tool.is_limited else "No")
|
|
|
|
# Color code by economy (green = good, red = bad)
|
|
if tool.heal_per_pec >= 20:
|
|
item.setForeground(4, QColor("#4caf50")) # Green
|
|
elif tool.heal_per_pec >= 15:
|
|
item.setForeground(4, QColor("#ff9800")) # Orange
|
|
else:
|
|
item.setForeground(4, QColor("#f44336")) # Red
|
|
|
|
item.setData(0, Qt.ItemDataRole.UserRole, tool)
|
|
self.results_tree.addTopLevelItem(item)
|
|
|
|
def _clear_search(self):
|
|
"""Clear search and filters."""
|
|
self.search_input.clear()
|
|
self.type_combo.setCurrentIndex(0)
|
|
self.min_heal_combo.setCurrentIndex(0)
|
|
self._apply_filters()
|
|
|
|
def _on_selection_changed(self):
|
|
"""Handle selection change."""
|
|
items = self.results_tree.selectedItems()
|
|
if items:
|
|
self.selected_tool = items[0].data(0, Qt.ItemDataRole.UserRole)
|
|
self.ok_button.setEnabled(True)
|
|
self._update_preview(self.selected_tool)
|
|
else:
|
|
self.selected_tool = None
|
|
self.ok_button.setEnabled(False)
|
|
|
|
def _update_preview(self, tool: NexusHealingTool):
|
|
"""Update preview panel."""
|
|
self.preview_name.setText(tool.name)
|
|
self.preview_heal.setText(f"{tool.heal_amount} HP")
|
|
self.preview_decay.setText(f"{tool.decay:.2f} PEC")
|
|
self.preview_economy.setText(f"{tool.heal_per_pec:.2f} hp/pec")
|
|
self.preview_cost.setText(f"{tool.decay / Decimal('100'):.4f} PED")
|
|
|
|
def _on_double_click(self, item, column):
|
|
"""Handle double click."""
|
|
self._on_accept()
|
|
|
|
def _on_accept(self):
|
|
"""Handle OK button."""
|
|
if self.selected_tool:
|
|
self.tool_selected.emit(self.selected_tool)
|
|
self.accept()
|