""" Mindforce Implant Selector for Lemontropia Suite Browse and select mindforce implants 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, NexusMindforceImplant class MindforceImplantLoaderThread(QThread): """Background thread for loading mindforce implants from API.""" implants_loaded = pyqtSignal(list) error_occurred = pyqtSignal(str) def run(self): try: api = get_nexus_api() implants = api.get_all_mindforce_implants() self.implants_loaded.emit(implants) except Exception as e: self.error_occurred.emit(str(e)) class MindforceImplantSelectorDialog(QDialog): """Dialog for selecting mindforce implants from Entropia Nexus API.""" implant_selected = pyqtSignal(NexusMindforceImplant) def __init__(self, parent=None, implant_type: str = ""): super().__init__(parent) self.preferred_type = implant_type.lower() type_names = { "healing": "Healing Chip", "damage": "Damage Chip", "utility": "Utility Chip" } title_type = type_names.get(self.preferred_type, "Mindforce Implant") self.setWindowTitle(f"Select {title_type} - Entropia Nexus") self.setMinimumSize(800, 500) self.all_implants: List[NexusMindforceImplant] = [] self.selected_implant: Optional[NexusMindforceImplant] = None self._setup_ui() self._load_data() def _setup_ui(self): layout = QVBoxLayout(self) layout.setSpacing(10) # Status self.status_label = QLabel("Loading mindforce implants 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", "Healing", "Damage", "Utility"]) if self.preferred_type: type_map = {"healing": 1, "damage": 2, "utility": 3} self.type_combo.setCurrentIndex(type_map.get(self.preferred_type, 0)) self.type_combo.currentTextChanged.connect(self._filter_implants) filter_layout.addWidget(self.type_combo) filter_layout.addWidget(QLabel("Search:")) self.search_input = QLineEdit() self.search_input.setPlaceholderText("Search implants...") self.search_input.textChanged.connect(self._filter_implants) filter_layout.addWidget(self.search_input) clear_btn = QPushButton("Clear") clear_btn.clicked.connect(self.search_input.clear) filter_layout.addWidget(clear_btn) layout.addLayout(filter_layout) # Results tree self.results_tree = QTreeWidget() self.results_tree.setHeaderLabels([ "Name", "Type", "Chip Type", "Decay (PEC)", "Prof. Level", "Limited" ]) header = self.results_tree.header() header.setSectionResizeMode(QHeaderView.ResizeMode.ResizeToContents) 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("Implant Preview") preview_layout = QFormLayout(self.preview_group) self.preview_name = QLabel("-") self.preview_type = QLabel("-") self.preview_decay = QLabel("-") preview_layout.addRow("Name:", self.preview_name) preview_layout.addRow("Type:", self.preview_type) preview_layout.addRow("Decay/Use:", self.preview_decay) 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 implants in background thread.""" self.loader = MindforceImplantLoaderThread() self.loader.implants_loaded.connect(self._on_implants_loaded) self.loader.error_occurred.connect(self._on_load_error) self.loader.start() def _on_implants_loaded(self, implants: List[NexusMindforceImplant]): """Handle loaded implants.""" self.all_implants = implants self._filter_implants() self.status_label.setText(f"Loaded {len(implants)} mindforce implants") self.progress.setRange(0, 100) self.progress.setValue(100) def _on_load_error(self, error: str): """Handle load error.""" self.status_label.setText(f"Error loading implants: {error}") self.progress.setRange(0, 100) self.progress.setValue(0) def _populate_results(self, implants: List[NexusMindforceImplant]): """Populate results tree.""" self.results_tree.clear() if not implants: item = QTreeWidgetItem() item.setText(0, "No implants available") item.setForeground(0, QColor("#888888")) self.results_tree.addTopLevelItem(item) return # Sort by decay (lower is better economy) implants = sorted(implants, key=lambda i: i.decay) for implant in implants: item = QTreeWidgetItem() item.setText(0, implant.name) item.setText(1, implant.implant_type.title()) item.setText(2, implant.chip_type) item.setText(3, f"{implant.decay:.2f}") item.setText(4, str(implant.profession_level) if implant.profession_level > 0 else "-") item.setText(5, "Yes" if implant.is_limited else "No") # Color limited items if implant.is_limited: item.setForeground(5, QColor("#ff9800")) # Color by type if implant.implant_type == "healing": item.setForeground(1, QColor("#4caf50")) elif implant.implant_type == "damage": item.setForeground(1, QColor("#f44336")) item.setData(0, Qt.ItemDataRole.UserRole, implant) self.results_tree.addTopLevelItem(item) def _filter_implants(self): """Filter implants based on search and type.""" type_filter = self.type_combo.currentText().lower() search = self.search_input.text().lower() filtered = self.all_implants # Filter by type if type_filter != "all": filtered = [i for i in filtered if i.implant_type == type_filter] # Filter by search if search: filtered = [ i for i in filtered if search in i.name.lower() or search in i.chip_type.lower() ] self._populate_results(filtered) def _on_selection_changed(self): """Handle selection change.""" items = self.results_tree.selectedItems() if items: self.selected_implant = items[0].data(0, Qt.ItemDataRole.UserRole) self._update_preview(self.selected_implant) self.ok_button.setEnabled(True) else: self.selected_implant = None self.ok_button.setEnabled(False) def _update_preview(self, implant: NexusMindforceImplant): """Update preview panel.""" self.preview_name.setText(implant.name) self.preview_type.setText(f"{implant.implant_type.title()} ({implant.chip_type})") self.preview_decay.setText(f"{implant.decay:.4f} PEC per use") # Color by type if implant.implant_type == "healing": self.preview_type.setStyleSheet("color: #4caf50;") elif implant.implant_type == "damage": self.preview_type.setStyleSheet("color: #f44336;") else: self.preview_type.setStyleSheet("color: #4a90d9;") def _on_double_click(self, item: QTreeWidgetItem, column: int): """Handle double click.""" if item.data(0, Qt.ItemDataRole.UserRole): self._on_accept() def _on_accept(self): """Handle OK button.""" if self.selected_implant: self.implant_selected.emit(self.selected_implant) self.accept() # Main entry for testing if __name__ == "__main__": import sys import logging from PyQt6.QtWidgets import QApplication logging.basicConfig(level=logging.INFO) app = QApplication(sys.argv) app.setStyle('Fusion') dialog = MindforceImplantSelectorDialog() # Connect signal for testing dialog.implant_selected.connect(lambda i: print(f"Selected implant: {i.name}")) if dialog.exec() == QDialog.DialogCode.Accepted: print("Implant selected!") sys.exit(0)