You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

935 lines
38 KiB

import json
import os
import sqlite3
from PyQt6.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, QListWidget, QLineEdit,
QLabel, QCheckBox, QPushButton, QFormLayout, QListWidgetItem, QSplitter, QTreeWidget,
QTreeWidgetItem, QDialog, QDialogButtonBox, QComboBox, QMessageBox, QSpinBox, QMenu, QTabWidget,
QTextEdit)
from PyQt6.QtCore import Qt, QSize, QTimer, QMetaObject
from PyQt6.QtGui import QPixmap, QFontMetrics, QColor, QAction
from collections import deque
from event_system import event_system
import logging
class EvolutionEditDialog(QDialog):
def __init__(self, parent=None, from_pfic=None, to_pfic=None, method=None):
super().__init__(parent)
self.setWindowTitle("Edit Evolution")
self.setModal(True)
layout = QVBoxLayout(self)
self.from_combo = QComboBox()
self.to_combo = QComboBox()
self.method_edit = QLineEdit(method)
layout.addWidget(QLabel("From Pokémon:"))
layout.addWidget(self.from_combo)
layout.addWidget(QLabel("To Pokémon:"))
layout.addWidget(self.to_combo)
layout.addWidget(QLabel("Evolution Method:"))
layout.addWidget(self.method_edit)
self.button_box = QDialogButtonBox(QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel)
self.button_box.accepted.connect(self.accept)
self.button_box.rejected.connect(self.reject)
layout.addWidget(self.button_box)
self.delete_button = QPushButton("Delete Evolution")
self.delete_button.clicked.connect(self.delete_evolution)
layout.addWidget(self.delete_button)
self.populate_combos(from_pfic, to_pfic)
def populate_combos(self, from_pfic, to_pfic):
cursor = self.parent().cursor
cursor.execute('SELECT PFIC, name, form_name FROM pokemon_forms ORDER BY name, form_name')
for pfic, name, form_name in cursor.fetchall():
display_name = f"{name} ({form_name})" if form_name else name
self.from_combo.addItem(display_name, pfic)
self.to_combo.addItem(display_name, pfic)
if from_pfic:
self.from_combo.setCurrentIndex(self.from_combo.findData(from_pfic))
if to_pfic:
self.to_combo.setCurrentIndex(self.to_combo.findData(to_pfic))
def delete_evolution(self):
self.done(2) # Use a custom return code for delete action
class AddEncounterToSetDialog(QDialog):
def __init__(self, parent, set_id, game_id):
super().__init__(parent)
self.set_id = set_id
self.game_id = game_id
self.setWindowTitle("Add Encounter to Set")
layout = QVBoxLayout(self)
self.encounter_list = QListWidget()
layout.addWidget(QLabel("Available Encounters:"))
layout.addWidget(self.encounter_list)
buttons = QDialogButtonBox(QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel)
buttons.accepted.connect(self.accept)
buttons.rejected.connect(self.reject)
layout.addWidget(buttons)
self.load_available_encounters()
def load_available_encounters(self):
encounters = event_system.call_sync('get_available_encounters', (self.game_id))
for encounter in encounters:
encounter_id = encounter[0]
pfic = encounter[1]
location = encounter[2]
name = encounter[3]
form = encounter[4]
display_text = f"{name} ({form if form else 'Normal'}) - {location}"
item = QListWidgetItem(display_text)
item.setData(Qt.ItemDataRole.UserRole, (encounter_id))
self.encounter_list.addItem(item)
def accept(self):
selected_items = self.encounter_list.selectedItems()
if selected_items:
for item in selected_items:
encounter_id = item.data(Qt.ItemDataRole.UserRole)
event_system.emit_sync('add_encounter_to_set', (self.set_id, encounter_id))
super().accept()
class NewExclusiveSetDialog(QDialog):
def __init__(self, parent):
super().__init__(parent)
self.setWindowTitle("Add New Exclusive Encounter Set")
layout = QFormLayout(self)
self.name_edit = QLineEdit()
self.description_edit = QTextEdit()
self.game_combo = QComboBox()
layout.addRow("Name:", self.name_edit)
layout.addRow("Description:", self.description_edit)
layout.addRow("Game:", self.game_combo)
buttons = QDialogButtonBox(QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel)
buttons.accepted.connect(self.accept)
buttons.rejected.connect(self.reject)
layout.addRow(buttons)
self.load_games()
def load_games(self):
games = event_system.call_sync('get_games_list')
for game_id, game_name in games:
self.game_combo.addItem(game_name, game_id)
def accept(self):
name = self.name_edit.text()
description = self.description_edit.toPlainText()
game_id = self.game_combo.currentData()
if name and game_id:
event_system.emit_sync('add_new_exclusive_set', (name, description, game_id))
super().accept()
else:
QMessageBox.warning(self, "Invalid Input", "Please provide a name and select a game.")
class PokemonUI(QWidget): # Change from QMainWindow to QWidget
def __init__(self, parent=None):
super().__init__(parent)
self.log_queue = deque() # Queue to store log messages
self.log_timer = QTimer(self)
self.log_timer.timeout.connect(self.process_log_queue)
self.log_timer.start(100)
event_system.add_listener('refresh_pokemon_details_panel', self.refresh)
event_system.add_listener('update_log_display', self.queue_log_message)
event_system.add_listener('clear_log_display', self.clear_log_display)
self.logger = logging.getLogger('ui_feedback')
self.encounter_cache = {}
self.evolution_load_timer = QTimer()
self.evolution_load_timer.setSingleShot(True)
self.evolution_load_timer.timeout.connect(self._load_evolution_chain)
self.current_evolution_pfic = None
self.init_ui()
self.request_pokemon_list()
self.logger.info("Initializing PokemonUI")
def queue_log_message(self, message):
self.log_queue.append(message)
def process_log_queue(self):
while self.log_queue:
message = self.log_queue.popleft()
self.update_log_display(message)
def init_ui(self):
main_layout = QVBoxLayout(self) # Use self directly instead of a central widget
# Create a tab widget
self.tab_widget = QTabWidget()
main_layout.addWidget(self.tab_widget)
# Main tab (existing content)
main_tab = QWidget()
main_tab_layout = QHBoxLayout(main_tab)
self.tab_widget.addTab(main_tab, "Main")
# Left side: Search and List
left_layout = QVBoxLayout()
search_layout = QHBoxLayout()
self.search_bar = QLineEdit()
self.search_bar.setPlaceholderText("Search Pokémon...")
self.search_bar.textChanged.connect(self.filter_pokemon_list)
search_layout.addWidget(self.search_bar)
left_layout.addLayout(search_layout)
self.pokemon_list = QListWidget()
self.pokemon_list.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu)
self.pokemon_list.customContextMenuRequested.connect(self.show_pokemon_context_menu)
self.pokemon_list.currentItemChanged.connect(self.on_pokemon_selected)
left_layout.addWidget(self.pokemon_list)
# Move the checkbox here, after the pokemon_list
self.highlight_no_encounters = QCheckBox("Highlight Pokémon without encounters")
self.highlight_no_encounters.stateChanged.connect(self.toggle_highlight_mode)
left_layout.addWidget(self.highlight_no_encounters)
# Add the new checkbox for filtering Home-storable Pokémon
self.filter_home_storable = QCheckBox("Show only Home-storable Pokémon")
self.filter_home_storable.stateChanged.connect(self.filter_pokemon_list)
left_layout.addWidget(self.filter_home_storable)
main_tab_layout.addLayout(left_layout, 1)
# Right side: Edit panel
right_layout = QVBoxLayout()
# Left side of right panel: Text information
info_layout = QHBoxLayout()
text_layout = QVBoxLayout()
self.edit_form = QFormLayout()
self.name_label = QLabel()
self.form_name_label = QLabel()
self.national_dex_label = QLabel()
self.generation_label = QLabel()
self.home_checkbox = QCheckBox("Available in Home")
self.is_baby_form_checkbox = QCheckBox("Is Baby Form")
self.edit_form.addRow("Name:", self.name_label)
self.edit_form.addRow("Form:", self.form_name_label)
self.edit_form.addRow("National Dex:", self.national_dex_label)
self.edit_form.addRow("Generation:", self.generation_label)
self.edit_form.addRow(self.home_checkbox)
self.edit_form.addRow(self.is_baby_form_checkbox)
text_layout.addLayout(self.edit_form)
# Right side of right panel: Image
image_layout = QVBoxLayout()
self.image_label = QLabel()
self.image_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
self.image_label.setFixedSize(150, 150)
image_layout.addWidget(self.image_label)
image_layout.addStretch(1)
info_layout.addLayout(text_layout)
info_layout.addLayout(image_layout)
second_half_layout = QVBoxLayout()
# Evolution chain tree
self.evolution_tree = QTreeWidget()
self.evolution_tree.setHeaderLabels(["Pokémon", "Evolution Method"])
self.evolution_tree.setColumnWidth(0, 200)
second_half_layout.addWidget(self.evolution_tree)
# Add Locations tree
self.locations_tree = QTreeWidget()
self.locations_tree.setHeaderLabels(["Game/Location", "Details"])
self.locations_tree.setColumnWidth(0, 200)
self.locations_tree.itemDoubleClicked.connect(self.edit_encounter)
second_half_layout.addWidget(QLabel("Locations:"))
second_half_layout.addWidget(self.locations_tree)
# Add New Encounter button
self.add_encounter_button = QPushButton("Add New Encounter")
self.add_encounter_button.clicked.connect(self.add_new_encounter)
second_half_layout.addWidget(self.add_encounter_button)
# Move buttons to the bottom
second_half_layout.addStretch(1)
# Add New Evolution button
self.add_evolution_button = QPushButton("Add New Evolution")
self.add_evolution_button.clicked.connect(self.add_new_evolution)
second_half_layout.addWidget(self.add_evolution_button)
right_layout.addLayout(info_layout)
right_layout.addLayout(second_half_layout)
main_tab_layout.addLayout(right_layout, 1)
self.save_button = QPushButton("Save Changes")
self.save_button.clicked.connect(self.save_changes)
main_layout.addWidget(self.save_button)
self.export_button = QPushButton("Export Database")
self.export_button.clicked.connect(self.export_database)
main_layout.addWidget(self.export_button)
# Database Operations tab
db_tab = QWidget()
db_tab_layout = QVBoxLayout(db_tab)
self.tab_widget.addTab(db_tab, "Database Operations")
# Add buttons to the Database Operations tab
gather_forms_btn = QPushButton("Gather Pokémon Forms")
gather_forms_btn.clicked.connect(self.gather_pokemon_forms)
db_tab_layout.addWidget(gather_forms_btn)
gather_home_btn = QPushButton("Gather Home Storage Info")
gather_home_btn.clicked.connect(self.gather_home_storage_info)
db_tab_layout.addWidget(gather_home_btn)
gather_evolutions_btn = QPushButton("Gather Evolution Information")
gather_evolutions_btn.clicked.connect(self.gather_evolution_info)
db_tab_layout.addWidget(gather_evolutions_btn)
gather_encounters_btn = QPushButton("Gather Encounter Information")
gather_encounters_btn.clicked.connect(self.gather_encounter_info)
db_tab_layout.addWidget(gather_encounters_btn)
gather_marks_btn = QPushButton("Gather Marks Information")
gather_marks_btn.clicked.connect(self.gather_marks_info)
db_tab_layout.addWidget(gather_marks_btn)
load_shiftable_forms_btn = QPushButton("Load Shiftable Forms")
load_shiftable_forms_btn.clicked.connect(self.load_shiftable_forms)
db_tab_layout.addWidget(load_shiftable_forms_btn)
# Add QTextEdit for progress reporting
self.progress_text = QTextEdit()
self.progress_text.setReadOnly(True)
self.progress_text.setMinimumHeight(200) # Set a minimum height
db_tab_layout.addWidget(self.progress_text)
db_tab_layout.addStretch(1) # Add stretch to separate the last button
reinit_db_btn = QPushButton("Clear and Reinitialize Database")
reinit_db_btn.clicked.connect(self.reinitialize_database)
db_tab_layout.addWidget(reinit_db_btn)
manage_encounters = QWidget()
self.manage_encounters_tab = QHBoxLayout(manage_encounters)
self.tab_widget.addTab(manage_encounters, "Manage Encounters")
self.create_manage_encounters_ui()
def create_manage_encounters_ui(self):
# Left side: Exclusive encounter set list
left_layout = QVBoxLayout()
self.exclusive_set_list = QListWidget()
self.exclusive_set_list.currentItemChanged.connect(self.on_exclusive_set_selected)
left_layout.addWidget(QLabel("Exclusive Encounter Sets:"))
left_layout.addWidget(self.exclusive_set_list)
add_set_button = QPushButton("Add New Set")
add_set_button.clicked.connect(self.add_new_exclusive_set)
left_layout.addWidget(add_set_button)
# Right side: Set details and encounters
right_layout = QVBoxLayout()
self.set_name_label = QLabel()
self.set_description_label = QLabel()
self.set_game_label = QLabel()
right_layout.addWidget(self.set_name_label)
right_layout.addWidget(self.set_description_label)
right_layout.addWidget(self.set_game_label)
self.encounter_list = QListWidget()
self.encounter_list.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu)
self.encounter_list.customContextMenuRequested.connect(self.show_encounter_context_menu)
right_layout.addWidget(QLabel("Encounters in Set:"))
right_layout.addWidget(self.encounter_list)
add_encounter_button = QPushButton("Add Encounter to Set")
add_encounter_button.clicked.connect(self.add_encounter_to_set)
right_layout.addWidget(add_encounter_button)
self.manage_encounters_tab.addLayout(left_layout, 1)
self.manage_encounters_tab.addLayout(right_layout, 2)
self.load_exclusive_sets()
def load_exclusive_sets(self):
self.exclusive_set_list.clear()
sets = event_system.call_sync('get_exclusive_encounter_sets')
for set_id, name in sets:
item = QListWidgetItem(name)
item.setData(Qt.ItemDataRole.UserRole, set_id)
self.exclusive_set_list.addItem(item)
def on_exclusive_set_selected(self, current, previous):
if current:
set_id = current.data(Qt.ItemDataRole.UserRole)
set_details = event_system.call_sync('get_exclusive_set_details', set_id)
self.update_set_details(set_details)
self.load_set_encounters(set_id)
def update_set_details(self, details):
name, description, game = details
self.set_name_label.setText(f"Name: {name}")
self.set_description_label.setText(f"Description: {description}")
self.set_game_label.setText(f"Game: {game}")
def load_set_encounters(self, set_id):
self.encounter_list.clear()
encounters = event_system.call_sync('get_set_encounters', set_id)
for encounter in encounters:
encounter_id = encounter[0]
pfic = encounter[1]
location = encounter[2]
name = encounter[3]
form = encounter[4]
display_text = f"{name} ({form if form else 'Normal'}) - {location}"
item = QListWidgetItem(display_text)
item.setData(Qt.ItemDataRole.UserRole, (encounter_id))
self.encounter_list.addItem(item)
def show_encounter_context_menu(self, position):
item = self.encounter_list.itemAt(position)
if item:
context_menu = QMenu(self)
delete_action = QAction("Delete from Set", self)
delete_action.triggered.connect(lambda: self.delete_encounter_from_set(item))
context_menu.addAction(delete_action)
context_menu.exec(self.encounter_list.viewport().mapToGlobal(position))
def delete_encounter_from_set(self, item):
pfic, location = item.data(Qt.ItemDataRole.UserRole)
set_id = self.exclusive_set_list.currentItem().data(Qt.ItemDataRole.UserRole)
event_system.emit_sync('delete_encounter_from_set', (set_id, pfic, location))
self.load_set_encounters(set_id)
def add_encounter_to_set(self):
set_id = self.exclusive_set_list.currentItem().data(Qt.ItemDataRole.UserRole)
game = self.set_game_label.text().split(": ")[1]
dialog = AddEncounterToSetDialog(self, set_id, game)
if dialog.exec() == QDialog.DialogCode.Accepted:
self.load_set_encounters(set_id)
def add_new_exclusive_set(self):
dialog = NewExclusiveSetDialog(self)
if dialog.exec() == QDialog.DialogCode.Accepted:
self.load_exclusive_sets()
def on_pokemon_selected(self, item):
pfic = item.data(Qt.ItemDataRole.UserRole)
self.refresh_pokemon_details_panel(pfic)
def refresh(self, pfic):
self.refresh_pokemon_details_panel(pfic)
self.update_encounter_cache()
self.update_pokemon_list_highlights()
def refresh_pokemon_details_panel(self, pfic):
pokemon_data = event_system.call_sync('get_pokemon_data', data=pfic)
if pokemon_data:
name, form_name, national_dex, generation, storable_in_home, is_baby_form = pokemon_data
self.name_label.setText(name)
self.form_name_label.setText(form_name if form_name else "")
self.national_dex_label.setText(str(national_dex))
self.generation_label.setText(str(generation))
self.home_checkbox.setChecked(bool(storable_in_home))
#self.home_checkbox.stateChanged.connect(self.update_home_storable)
self.is_baby_form_checkbox.setChecked(bool(is_baby_form))
# Load and display the image
image_path = f"images-new/{pfic}.png"
if os.path.exists(image_path):
pixmap = QPixmap(image_path)
self.image_label.setPixmap(pixmap.scaled(150, 150, Qt.AspectRatioMode.KeepAspectRatio, Qt.TransformationMode.SmoothTransformation))
else:
self.image_label.setText("Image not found")
# Load and display evolution chain
self.load_evolution_chain(pfic)
# Load and display encounter locations
self.load_encounter_locations(pfic)
self.current_pfic = pfic
self.add_evolution_button.setEnabled(True) # Enable the button when a Pokémon is selected
def load_evolution_chain(self, pfic):
self.current_evolution_pfic = pfic
if self.evolution_load_timer.isActive():
self.evolution_load_timer.stop()
self.evolution_load_timer.start(50) # 50ms delay
def _load_evolution_chain(self):
if not hasattr(self, 'evolution_tree') or self.evolution_tree is None:
print("Evolution tree widget not initialized")
return
pfic = self.current_evolution_pfic
if pfic is None:
return
try:
self.evolution_tree.clear()
except RuntimeError:
print("Error clearing evolution tree. Widget might have been deleted.")
return
evolution_chain = event_system.call_sync('get_evolution_chain', data=pfic)
# Create a dictionary to store tree items
tree_items = {}
# First pass: create all tree items
for current_pfic, name, form_name, method in evolution_chain:
display_name = f"{name} ({form_name})" if form_name else name
item = QTreeWidgetItem([display_name, method if method else ""])
item.setData(0, Qt.ItemDataRole.UserRole, current_pfic)
tree_items[current_pfic] = item
if current_pfic == pfic:
item.setBackground(0, QColor(255, 255, 0, 100)) # Highlight selected Pokémon
# Second pass: build the tree structure
root = None
for current_pfic, name, form_name, method in evolution_chain:
item = tree_items[current_pfic]
# Find the parent of this item
parent_pfic = event_system.call_sync('get_evolution_parent', data=current_pfic)
if parent_pfic:
parent_item = tree_items.get(parent_pfic[0])
if parent_item:
parent_item.addChild(item)
elif not root:
root = item
self.evolution_tree.addTopLevelItem(root)
# Expand the entire tree
self.evolution_tree.expandAll()
# Scroll to and select the current Pokémon
current_item = tree_items[pfic]
self.evolution_tree.scrollToItem(current_item)
self.evolution_tree.setCurrentItem(current_item)
# Connect double-click signal
#self.evolution_tree.itemDoubleClicked.connect(self.edit_evolution)
def load_encounter_locations(self, pfic):
self.locations_tree.clear()
encounters = event_system.call_sync('get_encounter_locations', data=pfic)
game_items = {}
for encounter in encounters:
game, location, day, time, dual_slot, static_encounter_count, static_encounter, extra_text, stars, rods, fishing = encounter
if game not in game_items:
#print(f'finding generation for {game}')
game_item = QTreeWidgetItem([game])
game_items[game] = game_item
generation = event_system.call_sync('get_game_generation', data=game)
# Use generation for sorting, default to 0 if not found
game_item.setData(0, Qt.ItemDataRole.UserRole, generation)
#print(f'generation for {game} is {generation}')
location_item = QTreeWidgetItem([location])
details = []
if day:
details.append(f"Day: {day}")
if time:
details.append(f"Time: {time}")
if dual_slot:
details.append(f"Dual Slot: {dual_slot}")
if static_encounter:
details.append(f"Static Encounter (Count: {static_encounter_count})")
if extra_text:
details.append(f"Extra: {extra_text}")
if stars:
details.append(f"Stars: {stars}")
if fishing:
details.append(f"Fishing")
if rods:
details.append(f"Rods: {rods}")
location_item.setText(1, ", ".join(details))
game_items[game].addChild(location_item)
# Sort game items by generation and add them to the tree
sorted_game_items = sorted(game_items.values(), key=lambda x: x.data(0, Qt.ItemDataRole.UserRole))
self.locations_tree.addTopLevelItems(sorted_game_items)
self.locations_tree.expandAll()
# Update the cache for this Pokémon
self.encounter_cache[pfic] = len(encounters) > 0
# After updating the locations tree
self.update_pokemon_list_highlights()
def on_save_button_clicked(self):
# Gather data from UI elements
data = {
'name': self.name_input.text(),
'form': self.form_input.text(),
# ... other fields ...
}
event_system.emit('save_changes', data)
def request_pokemon_list(self):
pokemon_data = event_system.call_sync('get_pokemon_list')
self.update_pokemon_list(pokemon_data)
def update_pokemon_list(self, pokemon_data):
self.pokemon_list.clear()
for pfic, name, form_name, national_dex in pokemon_data:
display_name = f"{national_dex:04d} - {name}"
if form_name:
display_name += f" ({form_name})"
item = QListWidgetItem(display_name)
item.setData(Qt.ItemDataRole.UserRole, pfic)
self.pokemon_list.addItem(item)
self.update_encounter_cache()
self.update_pokemon_list_highlights()
self.adjust_list_width()
self.filter_pokemon_list()
def adjust_list_width(self):
max_width = 0
font_metrics = QFontMetrics(self.pokemon_list.font())
for i in range(self.pokemon_list.count()):
item_width = font_metrics.horizontalAdvance(self.pokemon_list.item(i).text())
max_width = max(max_width, item_width)
# Add some padding to the width
list_width = max_width + 50
self.pokemon_list.setFixedWidth(list_width)
self.search_bar.setFixedWidth(list_width)
def filter_pokemon_list(self):
search_text = self.search_bar.text().lower()
show_only_home_storable = self.filter_home_storable.isChecked()
for i in range(self.pokemon_list.count()):
item = self.pokemon_list.item(i)
pfic = item.data(Qt.ItemDataRole.UserRole)
# Check if the item matches the search text
text_match = search_text in item.text().lower()
# Check if the item is storable in Home (if the filter is active)
home_storable = True
if show_only_home_storable:
home_storable = event_system.call_sync('get_home_storable', pfic)
# Show the item only if it matches both filters
item.setHidden(not (text_match and home_storable))
self.update_pokemon_list_highlights()
def toggle_highlight_mode(self):
self.update_pokemon_list_highlights()
def update_encounter_cache(self):
pokemon_with_encounters = event_system.call_sync('get_pokemon_with_encounters')
for i in range(self.pokemon_list.count()):
item = self.pokemon_list.item(i)
pfic = item.data(Qt.ItemDataRole.UserRole)
self.encounter_cache[pfic] = pfic in pokemon_with_encounters
def update_pokemon_list_highlights(self):
highlight_mode = self.highlight_no_encounters.isChecked()
for i in range(self.pokemon_list.count()):
item = self.pokemon_list.item(i)
pfic = item.data(Qt.ItemDataRole.UserRole)
if highlight_mode:
has_encounters = self.encounter_cache.get(pfic, False)
if not has_encounters:
item.setData(Qt.ItemDataRole.BackgroundRole, QColor(255, 200, 200)) # Light red background
else:
item.setData(Qt.ItemDataRole.BackgroundRole, None) # White background
else:
item.setData(Qt.ItemDataRole.BackgroundRole, None) # White background
def edit_encounter(self, item, column):
if item.parent() is None: # This is a game item, not a location item
return
game = item.parent().text(0)
location = item.text(0)
dialog = QDialog(self)
dialog.setWindowTitle("Edit Encounter")
layout = QFormLayout(dialog)
game_edit = QLineEdit(game)
location_edit = QLineEdit(location)
day_edit = QLineEdit()
time_edit = QLineEdit()
dual_slot_edit = QLineEdit()
static_encounter_check = QCheckBox("Static Encounter")
static_encounter_count_edit = QSpinBox()
extra_text_edit = QLineEdit()
stars_edit = QLineEdit()
fishing_check = QCheckBox("Fishing")
rods_edit = QLineEdit()
layout.addRow("Game:", game_edit)
layout.addRow("Location:", location_edit)
layout.addRow("Day:", day_edit)
layout.addRow("Time:", time_edit)
layout.addRow("Dual Slot:", dual_slot_edit)
layout.addRow("Static Encounter:", static_encounter_check)
layout.addRow("Static Encounter Count:", static_encounter_count_edit)
layout.addRow("Extra Text:", extra_text_edit)
layout.addRow("Stars:", stars_edit)
layout.addRow("Fishing:", fishing_check)
layout.addRow("Rods:", rods_edit)
layout.addRow("Exclusive Group:", QLabel())
exclusive_group_combo = QComboBox()
layout.addRow(exclusive_group_combo)
# Fetch current values
self.cursor.execute('''
SELECT day, time, dual_slot, static_encounter_count, static_encounter, extra_text, stars, fishing, rods
FROM encounters
WHERE pfic = ? AND game = ? AND location = ?
''', (self.current_pfic, game, location))
current_values = self.cursor.fetchone()
if current_values:
day, time, dual_slot, static_encounter_count, static_encounter, extra_text, stars, fishing, rods = current_values
day_edit.setText(day or "")
time_edit.setText(time or "")
dual_slot_edit.setText(dual_slot or "")
static_encounter_check.setChecked(bool(static_encounter))
static_encounter_count_edit.setValue(static_encounter_count or 0)
extra_text_edit.setText(extra_text or "")
stars_edit.setText(stars or "")
fishing_check.setChecked(bool(fishing))
rods_edit.setText(rods or "")
#index = exclusive_group_combo.findData(exclusive_group_id)
#if index >= 0:
# exclusive_group_combo.setCurrentIndex(index)
buttons = QDialogButtonBox(
QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel,
Qt.Orientation.Horizontal, dialog)
buttons.accepted.connect(dialog.accept)
buttons.rejected.connect(dialog.reject)
layout.addRow(buttons)
if dialog.exec() == QDialog.DialogCode.Accepted:
new_game = game_edit.text()
new_location = location_edit.text()
new_day = day_edit.text() or None
new_time = time_edit.text() or None
new_dual_slot = dual_slot_edit.text() or None
new_static_encounter = static_encounter_check.isChecked()
new_static_encounter_count = static_encounter_count_edit.value()
new_extra_text = extra_text_edit.text() or None
new_stars = stars_edit.text() or None
new_fishing = fishing_check.isChecked()
new_rods = rods_edit.text() or None
new_exclusive_group_id = exclusive_group_combo.currentData()
game_id = event_system.call_sync('get_game_id_for_name', new_game)
# Update the database
self.cursor.execute('''
UPDATE encounters
SET game_id = ?, location = ?, day = ?, time = ?, dual_slot = ?,
static_encounter = ?, static_encounter_count = ?, extra_text = ?,
stars = ?, fishing = ?, rods = ?
WHERE pfic = ? AND game_id = ? AND location = ?
''', (game_id, new_location, new_day, new_time, new_dual_slot,
new_static_encounter, new_static_encounter_count, new_extra_text,
new_stars, new_fishing, new_rods,
self.current_pfic, game_id, location))
self.conn.commit()
# Update the cache if all encounters for this Pokémon were deleted
if not self.check_pokemon_has_encounters(self.current_pfic):
self.encounter_cache[self.current_pfic] = False
# Refresh the locations tree
self.load_encounter_locations(self.current_pfic)
def add_new_encounter(self):
dialog = QDialog(self)
dialog.setWindowTitle("Add New Encounter")
layout = QFormLayout(dialog)
game_edit = QLineEdit()
location_edit = QLineEdit()
day_edit = QLineEdit()
time_edit = QLineEdit()
dual_slot_edit = QLineEdit()
static_encounter_check = QCheckBox("Static Encounter")
static_encounter_count_edit = QSpinBox()
extra_text_edit = QLineEdit()
stars_edit = QLineEdit()
fishing_check = QCheckBox("Fishing")
rods_edit = QLineEdit()
layout.addRow("Game:", game_edit)
layout.addRow("Location:", location_edit)
layout.addRow("Day:", day_edit)
layout.addRow("Time:", time_edit)
layout.addRow("Dual Slot:", dual_slot_edit)
layout.addRow("Static Encounter:", static_encounter_check)
layout.addRow("Static Encounter Count:", static_encounter_count_edit)
layout.addRow("Extra Text:", extra_text_edit)
layout.addRow("Stars:", stars_edit)
layout.addRow("Fishing:", fishing_check)
layout.addRow("Rods:", rods_edit)
exclusive_group_combo = QComboBox()
exclusive_group_combo.addItem("None", None)
self.cursor.execute('SELECT id, group_name FROM exclusive_encounter_groups')
for group_id, group_name in self.cursor.fetchall():
exclusive_group_combo.addItem(group_name, group_id)
layout.addRow("Exclusive Group:", exclusive_group_combo)
buttons = QDialogButtonBox(
QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel,
Qt.Orientation.Horizontal, dialog)
buttons.accepted.connect(dialog.accept)
buttons.rejected.connect(dialog.reject)
layout.addRow(buttons)
if dialog.exec() == QDialog.DialogCode.Accepted:
game = game_edit.text()
location = location_edit.text()
day = day_edit.text() or None
time = time_edit.text() or None
dual_slot = dual_slot_edit.text() or None
static_encounter = static_encounter_check.isChecked()
static_encounter_count = static_encounter_count_edit.value()
extra_text = extra_text_edit.text() or None
stars = stars_edit.text() or None
fishing = fishing_check.isChecked()
rods = rods_edit.text() or None
game_id = event_system.call_sync('get_game_id_for_name', game)
# Insert new encounter into the in-memory database
self.cursor.execute('''
INSERT INTO encounters
(pfic, game_id, location, day, time, dual_slot, static_encounter, static_encounter_count, extra_text, stars, fishing, rods)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
''', (self.current_pfic, game_id, location, day, time, dual_slot, static_encounter, static_encounter_count, extra_text, stars, fishing, rods))
self.conn.commit()
# Update the cache
self.encounter_cache[self.current_pfic] = True
# Refresh the locations tree
self.load_encounter_locations(self.current_pfic)
def save_changes(self):
if hasattr(self, 'current_pfic'):
storable_in_home = self.home_checkbox.isChecked()
is_baby_form = self.is_baby_form_checkbox.isChecked()
event_system.emit_sync('save_changes')
QMessageBox.information(self, "Save Complete", "Changes have been saved to the database.")
def export_database(self):
event_system.emit_sync('export_database')
def add_new_evolution(self):
if not hasattr(self, 'current_pfic'):
return
dialog = EvolutionEditDialog(self, self.current_pfic, None, "")
result = dialog.exec()
if result == QDialog.DialogCode.Accepted:
new_from_pfic = dialog.from_combo.currentData()
new_to_pfic = dialog.to_combo.currentData()
new_method = dialog.method_edit.text()
# Update the in-memory database
self.cursor.execute('''
INSERT INTO evolution_chains (from_pfic, to_pfic, method)
VALUES (?, ?, ?)
''', (new_from_pfic, new_to_pfic, new_method))
# Refresh the evolution chain display
self.load_evolution_chain(self.current_pfic)
def show_pokemon_context_menu(self, position):
item = self.pokemon_list.itemAt(position)
if item is not None:
context_menu = QMenu(self)
refresh_action = QAction("Refresh Encounters", self)
refresh_action.triggered.connect(lambda: self.refresh_pokemon_encounters(item))
context_menu.addAction(refresh_action)
context_menu.exec(self.pokemon_list.viewport().mapToGlobal(position))
def refresh_pokemon_encounters(self, item):
pfic = item.data(Qt.ItemDataRole.UserRole)
event_system.emit_sync('refresh_pokemon_encounters', pfic)
def update_log_display(self, message):
if self.progress_text is not None:
self.progress_text.append(message)
#QMetaObject.invokeMethod(self.progress_text, "append", Qt.ConnectionType.QueuedConnection, message)
# Scroll to the bottom
scrollbar = self.progress_text.verticalScrollBar()
scrollbar.setValue(scrollbar.maximum())
def clear_log_display(self, data):
if self.progress_text is not None:
self.progress_text.clear()
# Reset scroll to top
scrollbar = self.progress_text.verticalScrollBar()
scrollbar.setValue(scrollbar.minimum())
def gather_pokemon_forms(self):
event_system.emit_sync('gather_pokemon_forms')
def gather_home_storage_info(self):
event_system.emit_sync('gather_home_storage_info')
def gather_evolution_info(self):
event_system.emit_sync('gather_evolution_info')
def reinitialize_database(self):
event_system.emit_sync('reinitialize_database')
def gather_encounter_info(self):
event_system.emit_sync('gather_encounter_info')
def gather_marks_info(self):
event_system.emit_sync('gather_marks_info')
def load_shiftable_forms(self):
event_system.emit_sync('load_shiftable_forms')