Lemontropia-Suite/ui/gear_selector.py

230 lines
8.7 KiB
Python

"""
Gear Selector Dialog for Lemontropia Suite
Uses Entropia Nexus API to search and select real gear.
"""
from PyQt6.QtWidgets import (
QDialog, QVBoxLayout, QHBoxLayout, QLabel, QLineEdit,
QPushButton, QComboBox, QTreeWidget, QTreeWidgetItem,
QDialogButtonBox, QTabWidget, QGroupBox, QFormLayout,
QMessageBox, QHeaderView
)
from PyQt6.QtCore import Qt, pyqtSignal
from decimal import Decimal
import asyncio
from typing import Optional, List
class GearSelectorDialog(QDialog):
"""Dialog for selecting gear from Entropia Nexus."""
gear_selected = pyqtSignal(str, str, dict) # type, name, stats
def __init__(self, gear_type: str = "weapon", parent=None):
super().__init__(parent)
self.gear_type = gear_type # weapon, armor, tool
self.selected_gear = None
self.setWindowTitle(f"Select {gear_type.title()} - Entropia Nexus")
self.setMinimumSize(700, 500)
self.setup_ui()
# Load initial data
self.load_mock_data() # Use mock data for now
def setup_ui(self):
layout = QVBoxLayout(self)
layout.setSpacing(10)
# Search box
search_layout = QHBoxLayout()
search_layout.addWidget(QLabel("Search:"))
self.search_input = QLineEdit()
self.search_input.setPlaceholderText(f"Search for {self.gear_type}...")
self.search_input.returnPressed.connect(self.on_search)
search_layout.addWidget(self.search_input)
self.search_btn = QPushButton("Search")
self.search_btn.clicked.connect(self.on_search)
search_layout.addWidget(self.search_btn)
layout.addLayout(search_layout)
# Results list
self.results_tree = QTreeWidget()
self.results_tree.setHeaderLabels(["Name", "Damage/Protection", "DPP/Cost", "Range/Depth"])
self.results_tree.setAlternatingRowColors(True)
self.results_tree.setSelectionMode(QTreeWidget.SelectionMode.SingleSelection)
self.results_tree.itemSelectionChanged.connect(self.on_selection_changed)
self.results_tree.itemDoubleClicked.connect(self.on_item_double_clicked)
# Adjust columns
header = self.results_tree.header()
header.setSectionResizeMode(0, QHeaderView.ResizeMode.Stretch)
header.setSectionResizeMode(1, QHeaderView.ResizeMode.Fixed)
header.setSectionResizeMode(2, QHeaderView.ResizeMode.Fixed)
header.setSectionResizeMode(3, QHeaderView.ResizeMode.Fixed)
header.resizeSection(1, 120)
header.resizeSection(2, 100)
header.resizeSection(3, 100)
layout.addWidget(self.results_tree)
# Stats preview
self.stats_group = QGroupBox("Stats Preview")
self.stats_layout = QFormLayout(self.stats_group)
self.stats_layout.addRow("Select an item to view stats", QLabel(""))
layout.addWidget(self.stats_group)
# Buttons
button_box = QDialogButtonBox(
QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel
)
button_box.accepted.connect(self.on_accept)
button_box.rejected.connect(self.reject)
self.ok_btn = button_box.button(QDialogButtonBox.StandardButton.Ok)
self.ok_btn.setEnabled(False)
self.ok_btn.setText("Select Gear")
layout.addWidget(button_box)
def load_mock_data(self):
"""Load mock gear data for testing."""
from core.nexus_api import MOCK_WEAPONS, MOCK_ARMORS, MOCK_TOOLS
self.results_tree.clear()
if self.gear_type == "weapon":
for weapon_id, weapon in MOCK_WEAPONS.items():
item = QTreeWidgetItem([
weapon.name,
f"{weapon.damage}",
f"{weapon.dpp}",
f"{weapon.range}m"
])
item.setData(0, Qt.ItemDataRole.UserRole, {
'id': weapon_id,
'type': 'weapon',
'data': weapon
})
self.results_tree.addTopLevelItem(item)
elif self.gear_type == "armor":
for armor_id, armor in MOCK_ARMORS.items():
total_prot = armor.get_total_protection()
item = QTreeWidgetItem([
armor.name,
f"{total_prot}",
f"{armor.decay_pec} PEC",
"-"
])
item.setData(0, Qt.ItemDataRole.UserRole, {
'id': armor_id,
'type': 'armor',
'data': armor
})
self.results_tree.addTopLevelItem(item)
elif self.gear_type == "tool":
for tool_id, tool in MOCK_TOOLS.items():
item = QTreeWidgetItem([
tool.name,
f"{tool.depth}m",
f"{tool.decay_pec} PEC",
f"{tool.radius}m"
])
item.setData(0, Qt.ItemDataRole.UserRole, {
'id': tool_id,
'type': 'tool',
'data': tool
})
self.results_tree.addTopLevelItem(item)
def on_search(self):
"""Search for gear."""
query = self.search_input.text().strip().lower()
if not query:
self.load_mock_data()
return
# Filter results
for i in range(self.results_tree.topLevelItemCount()):
item = self.results_tree.topLevelItem(i)
name = item.text(0).lower()
item.setHidden(query not in name)
def on_selection_changed(self):
"""Handle selection change."""
selected = self.results_tree.selectedItems()
if selected:
item_data = selected[0].data(0, Qt.ItemDataRole.UserRole)
self.selected_gear = item_data
self.ok_btn.setEnabled(True)
self.update_stats_preview(item_data)
else:
self.selected_gear = None
self.ok_btn.setEnabled(False)
def update_stats_preview(self, item_data):
"""Update stats preview."""
# Clear previous
while self.stats_layout.rowCount() > 0:
self.stats_layout.removeRow(0)
gear = item_data['data']
if item_data['type'] == 'weapon':
self.stats_layout.addRow("Damage:", QLabel(f"{gear.damage}"))
self.stats_layout.addRow("DPP:", QLabel(f"{gear.dpp}"))
self.stats_layout.addRow("Decay:", QLabel(f"{gear.decay_pec} PEC"))
self.stats_layout.addRow("Ammo:", QLabel(f"{gear.ammo_pec} PEC"))
self.stats_layout.addRow("Range:", QLabel(f"{gear.range}m"))
self.stats_layout.addRow("Attacks/min:", QLabel(f"{gear.attacks_per_min}"))
self.stats_layout.addRow("Cost/hour:", QLabel(f"{gear.calculate_cost_per_hour():.2f} PED"))
elif item_data['type'] == 'armor':
self.stats_layout.addRow("Decay:", QLabel(f"{gear.decay_pec} PEC"))
self.stats_layout.addRow("Total Protection:", QLabel(f"{gear.get_total_protection()}"))
for dmg_type, value in gear.protection.items():
self.stats_layout.addRow(f" {dmg_type.title()}:", QLabel(f"{value}"))
elif item_data['type'] == 'tool':
self.stats_layout.addRow("Type:", QLabel(f"{gear.tool_type}"))
self.stats_layout.addRow("Depth:", QLabel(f"{gear.depth}m"))
self.stats_layout.addRow("Radius:", QLabel(f"{gear.radius}m"))
self.stats_layout.addRow("Decay:", QLabel(f"{gear.decay_pec} PEC"))
if gear.probe_cost:
self.stats_layout.addRow("Cost/drop:", QLabel(f"{gear.calculate_cost_per_drop():.3f} PED"))
def on_item_double_clicked(self, item, column):
"""Handle double click."""
self.on_accept()
def on_accept(self):
"""Handle OK button."""
if self.selected_gear:
gear = self.selected_gear['data']
self.gear_selected.emit(
self.selected_gear['type'],
gear.name,
{
'id': self.selected_gear['id'],
'dpp': getattr(gear, 'dpp', None),
'cost_per_hour': getattr(gear, 'calculate_cost_per_hour', lambda: 0)()
}
)
self.accept()
if __name__ == "__main__":
import sys
from PyQt6.QtWidgets import QApplication
app = QApplication(sys.argv)
dialog = GearSelectorDialog("weapon")
if dialog.exec() == QDialog.DialogCode.Accepted:
print("Selected gear:", dialog.selected_gear)
sys.exit(0)