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.
756 lines
32 KiB
756 lines
32 KiB
import sys
|
|
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
|
|
from PyQt6.QtGui import QPixmap, QFontMetrics, QColor, QAction
|
|
import sqlite3
|
|
import json
|
|
import os
|
|
|
|
# Add the parent directory to the Python path
|
|
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
|
|
|
# Now try to import
|
|
from pokemon_db_ui import PokemonUI
|
|
from DataGatherers.update_location_information import process_pokemon_for_location_data
|
|
from DataGatherers.cache_manager import CacheManager
|
|
from event_system import event_system
|
|
|
|
def parse_pfic(pfic):
|
|
parts = pfic.split('-')
|
|
return tuple(int(part) if part.isdigit() else part for part in parts)
|
|
|
|
class DBEditor(QMainWindow):
|
|
def __init__(self):
|
|
super().__init__()
|
|
self.setWindowTitle("Pokémon Database Editor")
|
|
self.setGeometry(100, 100, 1000, 600)
|
|
|
|
event_system.add_listener('get_pokemon_data', self.load_pokemon_details)
|
|
event_system.add_listener('save_changes', self.save_changes)
|
|
event_system.add_listener('add_new_encounter', self.add_new_encounter)
|
|
event_system.add_listener('get_pokemon_list', self.send_pokemon_list)
|
|
event_system.add_listener('get_home_storable', self.get_home_storable)
|
|
event_system.add_listener('get_evolution_chain', self.get_evolution_chain)
|
|
event_system.add_listener('get_evolution_parent', self.get_evolution_parent)
|
|
|
|
self.conn = sqlite3.connect(':memory:', check_same_thread=False) # Use in-memory database for runtime
|
|
self.cursor = self.conn.cursor()
|
|
self.init_database()
|
|
self.patches = self.load_and_apply_patches()
|
|
|
|
self.encounter_cache = {} # Add this line
|
|
self.init_ui()
|
|
|
|
def init_database(self):
|
|
# Create or open the file-based database
|
|
disk_conn = sqlite3.connect('pokemon_forms.db')
|
|
disk_cursor = disk_conn.cursor()
|
|
|
|
# Create tables in the file-based database
|
|
self.create_games_table(disk_cursor)
|
|
self.create_pokemon_forms_table(disk_cursor)
|
|
self.create_pokemon_storage_table(disk_cursor)
|
|
self.create_evolution_chains_table(disk_cursor)
|
|
self.create_exclusive_encounter_groups_table(disk_cursor)
|
|
self.create_encounters_table(disk_cursor)
|
|
self.create_mark_table(disk_cursor)
|
|
|
|
# Commit changes to the file-based database
|
|
disk_conn.commit()
|
|
|
|
# Copy the file-based database to the in-memory database
|
|
disk_conn.backup(self.conn)
|
|
|
|
# Close the file-based database connection
|
|
disk_conn.close()
|
|
|
|
# Create tables in the in-memory database (in case they weren't copied)
|
|
self.create_pokemon_forms_table(self.cursor)
|
|
self.create_pokemon_storage_table(self.cursor)
|
|
self.create_evolution_chains_table(self.cursor)
|
|
self.create_exclusive_encounter_groups_table(self.cursor)
|
|
self.create_encounters_table(self.cursor)
|
|
|
|
# Commit changes to the in-memory database
|
|
self.conn.commit()
|
|
|
|
def create_pokemon_forms_table(self, cursor):
|
|
cursor.execute('''
|
|
CREATE TABLE IF NOT EXISTS pokemon_forms (
|
|
PFIC TEXT PRIMARY KEY,
|
|
name TEXT NOT NULL,
|
|
form_name TEXT,
|
|
national_dex INTEGER NOT NULL,
|
|
generation INTEGER NOT NULL,
|
|
is_baby_form BOOLEAN
|
|
)
|
|
''')
|
|
|
|
def create_pokemon_storage_table(self, cursor):
|
|
cursor.execute('''
|
|
CREATE TABLE IF NOT EXISTS pokemon_storage (
|
|
PFIC TEXT PRIMARY KEY,
|
|
storable_in_home BOOLEAN NOT NULL,
|
|
FOREIGN KEY (PFIC) REFERENCES pokemon_forms (PFIC)
|
|
)
|
|
''')
|
|
|
|
def create_evolution_chains_table(self, cursor):
|
|
cursor.execute('''
|
|
CREATE TABLE IF NOT EXISTS evolution_chains (
|
|
from_pfic TEXT,
|
|
to_pfic TEXT,
|
|
method TEXT,
|
|
PRIMARY KEY (from_pfic, to_pfic),
|
|
FOREIGN KEY (from_pfic) REFERENCES pokemon_forms (PFIC),
|
|
FOREIGN KEY (to_pfic) REFERENCES pokemon_forms (PFIC)
|
|
)
|
|
''')
|
|
|
|
def create_exclusive_encounter_groups_table(self, cursor):
|
|
cursor.execute('''
|
|
CREATE TABLE IF NOT EXISTS exclusive_encounter_groups (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
group_name TEXT NOT NULL,
|
|
description TEXT
|
|
)
|
|
''')
|
|
|
|
def create_encounters_table(self, cursor):
|
|
# First, check if the table exists
|
|
cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='encounters'")
|
|
table_exists = cursor.fetchone() is not None
|
|
|
|
if not table_exists:
|
|
# If the table doesn't exist, create it with all columns
|
|
cursor.execute('''
|
|
CREATE TABLE encounters (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
pfic TEXT,
|
|
game TEXT,
|
|
location TEXT,
|
|
day TEXT,
|
|
time TEXT,
|
|
dual_slot TEXT,
|
|
static_encounter BOOLEAN,
|
|
static_encounter_count INTEGER,
|
|
extra_text TEXT,
|
|
stars TEXT,
|
|
fishing BOOLEAN,
|
|
rods TEXT,
|
|
exclusive_group_id INTEGER,
|
|
FOREIGN KEY (pfic) REFERENCES pokemon_forms (PFIC),
|
|
FOREIGN KEY (exclusive_group_id) REFERENCES exclusive_encounter_groups (id)
|
|
)
|
|
''')
|
|
else:
|
|
# If the table exists, check if the exclusive_group_id column exists
|
|
cursor.execute("PRAGMA table_info(encounters)")
|
|
columns = [column[1] for column in cursor.fetchall()]
|
|
|
|
if 'exclusive_group_id' not in columns:
|
|
# If the column doesn't exist, add it
|
|
cursor.execute('''
|
|
ALTER TABLE encounters
|
|
ADD COLUMN exclusive_group_id INTEGER
|
|
REFERENCES exclusive_encounter_groups (id)
|
|
''')
|
|
|
|
if 'starter' not in columns:
|
|
# If the column doesn't exist, add it
|
|
cursor.execute('''
|
|
ALTER TABLE encounters
|
|
ADD COLUMN starter BOOLEAN
|
|
''')
|
|
|
|
def create_mark_table(self, cursor):
|
|
|
|
cursor.execute('''
|
|
CREATE TABLE IF NOT EXISTS marks (
|
|
id INTEGER PRIMARY KEY,
|
|
name TEXT NOT NULL,
|
|
icon_path TEXT NOT NULL
|
|
)
|
|
''')
|
|
|
|
cursor.execute('''
|
|
CREATE TABLE IF NOT EXISTS mark_game_associations (
|
|
mark_id INTEGER,
|
|
game_id INTEGER,
|
|
FOREIGN KEY (mark_id) REFERENCES marks (id),
|
|
FOREIGN KEY (game_id) REFERENCES games (id),
|
|
PRIMARY KEY (mark_id, game_id)
|
|
)
|
|
''')
|
|
|
|
marks = [
|
|
("Game Boy", "images/marks/GB_icon_HOME.png", ["Red", "Blue", "Yellow", "Gold", "Silver", "Crystal", "Ruby", "Sapphire", "Emerald", "FireRed", "LeafGreen"]),
|
|
("Kalos", "images/marks/Blue_pentagon_HOME.png", ["X", "Y", "Omega Ruby", "Alpha Sapphire"]),
|
|
("Alola", "images/marks/Black_clover_HOME.png", ["Sun", "Moon", "Ultra Sun", "Ultra Moon"]),
|
|
("Let's Go", "images/marks/Let's_Go_icon_HOME.png", ["Let's Go Pikachu", "Let's Go Eevee"]),
|
|
("Galar", "images/marks/Galar_symbol_HOME.png", ["Sword", "Shield"]),
|
|
("Sinnoh", "images/marks/BDSP_icon_HOME.png", ["Brilliant Diamond", "Shining Pearl"]),
|
|
("Hisui", "images/marks/Arceus_mark_HOME.png", ["Legends Arceus"]),
|
|
("Paldea", "images/marks/Paldea_icon_HOME.png", ["Scarlet", "Violet"]),
|
|
]
|
|
|
|
for mark in marks:
|
|
cursor.execute('''
|
|
INSERT OR IGNORE INTO marks (name, icon_path)
|
|
VALUES (?, ?)
|
|
''', (mark[0], mark[1]))
|
|
|
|
mark_id = cursor.lastrowid
|
|
|
|
for game_name in mark[2]:
|
|
cursor.execute('''
|
|
INSERT OR IGNORE INTO mark_game_associations (mark_id, game_id)
|
|
SELECT ?, id FROM games WHERE name = ?
|
|
''', (mark_id, game_name))
|
|
|
|
def create_games_table(self, cursor):
|
|
|
|
cursor.execute('''
|
|
CREATE TABLE IF NOT EXISTS games (
|
|
id INTEGER PRIMARY KEY,
|
|
name TEXT NOT NULL,
|
|
generation INTEGER NOT NULL
|
|
)
|
|
''')
|
|
|
|
cursor.execute('''
|
|
CREATE TABLE IF NOT EXISTS alternate_game_names (
|
|
id INTEGER PRIMARY KEY,
|
|
game_id INTEGER NOT NULL,
|
|
alternate_name TEXT NOT NULL,
|
|
FOREIGN KEY (game_id) REFERENCES games (id),
|
|
UNIQUE (alternate_name COLLATE NOCASE)
|
|
)
|
|
''')
|
|
|
|
games = [
|
|
("Red", 1, ["Red Version"]),
|
|
("Blue", 1, ["Blue Version"]),
|
|
("Yellow", 1, ["Yellow Version"]),
|
|
("Gold", 2, ["Gold Version"]),
|
|
("Silver", 2, ["Silver Version"]),
|
|
("Crystal", 2, ["Crystal Version"]),
|
|
("Ruby", 3, ["Ruby Version"]),
|
|
("Sapphire", 3, ["Sapphire Version"]),
|
|
("Emerald", 3, ["Emerald Version"]),
|
|
("FireRed", 3, ["Fire Red", "Fire-Red"]),
|
|
("LeafGreen", 3, ["Leaf Green", "Leaf-Green"]),
|
|
("Diamond", 4, ["Diamond Version"]),
|
|
("Pearl", 4, ["Pearl Version"]),
|
|
("Platinum", 4, ["Platinum Version"]),
|
|
("HeartGold", 4, ["Heart Gold", "Heart-Gold"]),
|
|
("SoulSilver", 4, ["Soul Silver", "Soul-Silver"]),
|
|
("Black", 5, ["Black Version"]),
|
|
("White", 5, ["White Version"]),
|
|
("Black 2", 5, ["Black Version 2", "Black-2"]),
|
|
("White 2", 5, ["White Version 2", "White-2"]),
|
|
("X", 6, ["X Version"]),
|
|
("Y", 6, ["Y Version"]),
|
|
("Omega Ruby", 6, ["Omega Ruby Version", "Omega-Ruby"]),
|
|
("Alpha Sapphire", 6, ["Alpha Sapphire Version", "Alpha-Sapphire"]),
|
|
("Sun", 7, ["Sun Version"]),
|
|
("Moon", 7, ["Moon Version"]),
|
|
("Ultra Sun", 7, ["Ultra Sun Version", "Ultra-Sun"]),
|
|
("Ultra Moon", 7, ["Ultra Moon Version", "Ultra-Moon"]),
|
|
("Let's Go Pikachu", 7, ["Let's Go, Pikachu!", "Lets Go Pikachu"]),
|
|
("Let's Go Eevee", 7, ["Let's Go, Eevee!", "Lets Go Eevee"]),
|
|
("Sword", 8, ["Sword Version"]),
|
|
("Shield", 8, ["Shield Version"]),
|
|
("Expansion Pass", 8, ["Expansion Pass (Sword)", "Expansion Pass (Shield)"]),
|
|
("Brilliant Diamond", 8, ["Brilliant Diamond Version", "Brilliant-Diamond"]),
|
|
("Shining Pearl", 8, ["Shining Pearl Version", "Shining-Pearl"]),
|
|
("Legends Arceus", 8, ["Legends: Arceus", "Legends-Arceus"]),
|
|
("Scarlet", 9, ["Scarlet Version"]),
|
|
("Violet", 9, ["Violet Version"]),
|
|
("The Teal Mask", 9, ["The Teal Mask Version", "The Teal Mask (Scarlet)", "The Teal Mask (Violet)"]),
|
|
("The Hidden Treasure of Area Zero", 9, ["The Hidden Treasure of Area Zero Version", "The Hidden Treasure of Area Zero (Scarlet)", "The Hidden Treasure of Area Zero (Violet)"]),
|
|
|
|
("Pokémon Home", 98, ["Pokémon HOME"]),
|
|
("Pokémon Go", 99, ["Pokémon GO"]),
|
|
]
|
|
|
|
for game in games:
|
|
cursor.execute('''
|
|
INSERT OR IGNORE INTO games (name, generation)
|
|
VALUES (?, ?)
|
|
''', (game[0], game[1]))
|
|
|
|
game_id = cursor.lastrowid
|
|
|
|
# Insert alternate names
|
|
for alt_name in game[2]:
|
|
cursor.execute('''
|
|
INSERT OR IGNORE INTO alternate_game_names (game_id, alternate_name)
|
|
VALUES (?, ?)
|
|
''', (game_id, alt_name))
|
|
|
|
def load_and_apply_patches(self):
|
|
try:
|
|
with open('patches.json', 'r') as f:
|
|
patches = json.load(f)
|
|
except FileNotFoundError:
|
|
patches = {}
|
|
|
|
# Apply patches to the in-memory database
|
|
for patch_key, patch in patches.items():
|
|
if patch_key.startswith('evolution_'):
|
|
from_pfic, to_pfic = patch_key.split('_')[1:]
|
|
if patch['action'] == 'delete':
|
|
self.cursor.execute('''
|
|
DELETE FROM evolution_chains
|
|
WHERE from_pfic = ? AND to_pfic = ?
|
|
''', (from_pfic, to_pfic))
|
|
elif patch['action'] == 'update':
|
|
self.cursor.execute('''
|
|
UPDATE evolution_chains
|
|
SET from_pfic = ?, to_pfic = ?, method = ?
|
|
WHERE from_pfic = ? AND to_pfic = ?
|
|
''', (patch['new_from_pfic'], patch['new_to_pfic'], patch['new_method'], from_pfic, to_pfic))
|
|
elif patch['action'] == 'add':
|
|
self.cursor.execute('''
|
|
INSERT OR REPLACE INTO evolution_chains (from_pfic, to_pfic, method)
|
|
VALUES (?, ?, ?)
|
|
''', (patch['from_pfic'], patch['to_pfic'], patch['method']))
|
|
else: # pokemon_storage patches
|
|
self.cursor.execute('''
|
|
UPDATE pokemon_storage
|
|
SET storable_in_home = ?
|
|
WHERE PFIC = ?
|
|
''', (patch['storable_in_home'], patch_key))
|
|
|
|
self.conn.commit()
|
|
return patches
|
|
|
|
def save_patches(self):
|
|
with open('patches.json', 'w') as f:
|
|
json.dump(self.patches, f)
|
|
|
|
def load_pokemon_details(self, pfic):
|
|
self.cursor.execute('''
|
|
SELECT pf.name, pf.form_name, pf.national_dex, pf.generation, ps.storable_in_home
|
|
FROM pokemon_forms pf
|
|
LEFT JOIN pokemon_storage ps ON pf.PFIC = ps.PFIC
|
|
WHERE pf.PFIC = ?
|
|
''', (pfic,))
|
|
|
|
return self.cursor.fetchone()
|
|
|
|
def save_changes(self, data):
|
|
# Your existing code to save changes
|
|
pass
|
|
|
|
def add_new_encounter(self, data):
|
|
# Your existing code to add a new encounter
|
|
pass
|
|
|
|
def send_pokemon_list(self, callback):
|
|
# Fetch pokemon list from database
|
|
self.cursor.execute('''
|
|
SELECT pf.PFIC, pf.name, pf.form_name, pf.national_dex
|
|
FROM pokemon_forms pf
|
|
''')
|
|
pokemon_data = self.cursor.fetchall()
|
|
|
|
# Sort the pokemon_data based on PFIC
|
|
pokemon_data.sort(key=lambda x: parse_pfic(x[0]))
|
|
callback(pokemon_data)
|
|
|
|
def init_ui(self):
|
|
# Create a central widget for the main window
|
|
central_widget = QWidget()
|
|
self.setCentralWidget(central_widget)
|
|
main_layout = QVBoxLayout(central_widget)
|
|
|
|
# Create the PokemonUI as a child widget
|
|
self.pokemon_ui = PokemonUI(self)
|
|
main_layout.addWidget(self.pokemon_ui)
|
|
|
|
def get_home_storable(self, pfic):
|
|
self.cursor.execute('SELECT storable_in_home FROM pokemon_storage WHERE PFIC = ?', (pfic,))
|
|
result = self.cursor.fetchone()
|
|
home_storable = result[0] if result else False
|
|
return home_storable
|
|
|
|
def update_home_storable(self):
|
|
if hasattr(self, 'current_pfic'):
|
|
storable_in_home = self.home_checkbox.isChecked()
|
|
self.cursor.execute('UPDATE pokemon_storage SET storable_in_home = ? WHERE PFIC = ?', (storable_in_home, self.current_pfic))
|
|
self.conn.commit()
|
|
self.filter_pokemon_list() # Reapply the filter
|
|
|
|
def edit_evolution(self, item, column):
|
|
parent = item.parent()
|
|
if not parent:
|
|
return # Don't edit the root item
|
|
|
|
#from_pfic = parent.data(0, Qt.ItemDataRole.UserRole)
|
|
#to_pfic = item.data(0, Qt.ItemDataRole.UserRole)
|
|
#method = item.text(1)
|
|
|
|
#dialog = EvolutionEditDialog(self, from_pfic, to_pfic, method)
|
|
#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('''
|
|
# UPDATE evolution_chains
|
|
# SET from_pfic = ?, to_pfic = ?, method = ?
|
|
# WHERE from_pfic = ? AND to_pfic = ?
|
|
# ''', (new_from_pfic, new_to_pfic, new_method, from_pfic, to_pfic))
|
|
|
|
# # Create or update the patch
|
|
# patch_key = f"evolution_{from_pfic}_{to_pfic}"
|
|
# self.patches[patch_key] = {
|
|
# 'action': 'update',
|
|
# 'new_from_pfic': new_from_pfic,
|
|
# 'new_to_pfic': new_to_pfic,
|
|
# 'new_method': new_method
|
|
# }
|
|
# self.save_patches()
|
|
|
|
# Refresh the evolution chain display
|
|
# self.load_evolution_chain(self.current_pfic)
|
|
|
|
#elif result == 2: # Delete action
|
|
# confirm = QMessageBox.question(self, "Confirm Deletion", "Are you sure you want to delete this evolution?",
|
|
# QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No)
|
|
# if confirm == QMessageBox.StandardButton.Yes:
|
|
# # Delete from the in-memory database
|
|
# self.cursor.execute('''
|
|
# DELETE FROM evolution_chains
|
|
# WHERE from_pfic = ? AND to_pfic = ?
|
|
# ''', (from_pfic, to_pfic))
|
|
|
|
# Create a delete patch
|
|
# patch_key = f"evolution_{from_pfic}_{to_pfic}"
|
|
# self.patches[patch_key] = {'action': 'delete'}
|
|
# self.save_patches()
|
|
|
|
# Refresh the evolution chain display
|
|
# self.load_evolution_chain(self.current_pfic)
|
|
|
|
def get_evolution_chain(self, pfic):
|
|
def follow_chain(start_pfic, visited=None):
|
|
if visited is None:
|
|
visited = set()
|
|
|
|
chain = []
|
|
stack = [(start_pfic, None)]
|
|
|
|
while stack:
|
|
current_pfic, method = stack.pop()
|
|
if current_pfic in visited:
|
|
continue
|
|
|
|
visited.add(current_pfic)
|
|
self.cursor.execute('SELECT name, form_name FROM pokemon_forms WHERE PFIC = ?', (current_pfic,))
|
|
name, form_name = self.cursor.fetchone()
|
|
|
|
chain.append((current_pfic, name, form_name, method))
|
|
|
|
# Get previous evolutions
|
|
self.cursor.execute('SELECT from_pfic, method FROM evolution_chains WHERE to_pfic = ?', (current_pfic,))
|
|
prev_evolutions = self.cursor.fetchall()
|
|
for prev_pfic, prev_method in prev_evolutions:
|
|
if prev_pfic not in visited:
|
|
stack.append((prev_pfic, prev_method))
|
|
|
|
# Get next evolutions
|
|
self.cursor.execute('SELECT to_pfic, method FROM evolution_chains WHERE from_pfic = ?', (current_pfic,))
|
|
next_evolutions = self.cursor.fetchall()
|
|
for next_pfic, next_method in next_evolutions:
|
|
if next_pfic not in visited:
|
|
stack.append((next_pfic, next_method))
|
|
|
|
return chain
|
|
|
|
return follow_chain(pfic)
|
|
|
|
def get_evolution_parent(self, pfic):
|
|
self.cursor.execute('SELECT from_pfic FROM evolution_chains WHERE to_pfic = ?', (pfic,))
|
|
return self.cursor.fetchone()
|
|
|
|
def closeEvent(self, event):
|
|
self.conn.close()
|
|
event.accept()
|
|
|
|
def load_encounter_locations(self, pfic):
|
|
self.locations_tree.clear()
|
|
self.cursor.execute('''
|
|
SELECT game, location, day, time, dual_slot, static_encounter_count, static_encounter, extra_text, stars, rods, fishing
|
|
FROM encounters
|
|
WHERE pfic = ?
|
|
ORDER BY game, location
|
|
''', (pfic,))
|
|
encounters = self.cursor.fetchall()
|
|
|
|
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:
|
|
game_item = QTreeWidgetItem([game])
|
|
game_items[game] = game_item
|
|
# Use generation for sorting, default to 0 if not found
|
|
game_item.setData(0, Qt.ItemDataRole.UserRole, self.game_generations.get(game, 0))
|
|
|
|
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()
|
|
|
|
# Add this as a class attribute in the DBEditor class
|
|
game_generations = {
|
|
"Red": 1, "Blue": 1, "Yellow": 1,
|
|
"Gold": 2, "Silver": 2, "Crystal": 2,
|
|
"Ruby": 3, "Sapphire": 3, "Emerald": 3, "FireRed": 3, "LeafGreen": 3,
|
|
"Diamond": 4, "Pearl": 4, "Platinum": 4, "HeartGold": 4, "SoulSilver": 4,
|
|
"Black": 5, "White": 5, "Black 2": 5, "White 2": 5,
|
|
"X": 6, "Y": 6, "Omega Ruby": 6, "Alpha Sapphire": 6,
|
|
"Sun": 7, "Moon": 7, "Ultra Sun": 7, "Ultra Moon": 7,
|
|
"Sword": 8, "Shield": 8, "Brilliant Diamond": 8, "Shining Pearl": 8, "Expansion Pass": 8,
|
|
"Legends: Arceus": 8,
|
|
"Scarlet": 9, "Violet": 9, "The Teal Mask": 9, "The Hidden Treasure of Area Zero": 9, "The Hidden Treasure of Area Zero (Scarlet)": 9, "The Hidden Treasure of Area Zero (Violet)": 9, "The Teal Mask (Scarlet)": 9, "The Teal Mask (Violet)": 9,
|
|
"Pokémon Go": 0, "Pokémon Home": 0
|
|
}
|
|
|
|
def update_encounter_cache(self):
|
|
self.cursor.execute('''
|
|
SELECT DISTINCT pfic
|
|
FROM encounters
|
|
''')
|
|
pokemon_with_encounters = set(row[0] for row in self.cursor.fetchall())
|
|
|
|
#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 check_pokemon_has_encounters(self, pfic):
|
|
return self.encounter_cache.get(pfic, False)
|
|
|
|
def manage_exclusive_groups(self):
|
|
dialog = QDialog(self)
|
|
dialog.setWindowTitle("Manage Exclusive Encounter Groups")
|
|
layout = QVBoxLayout(dialog)
|
|
|
|
group_list = QListWidget()
|
|
self.cursor.execute('SELECT id, group_name, description FROM exclusive_encounter_groups')
|
|
for group_id, group_name, description in self.cursor.fetchall():
|
|
item = QListWidgetItem(f"{group_name} - {description}")
|
|
item.setData(Qt.ItemDataRole.UserRole, group_id)
|
|
group_list.addItem(item)
|
|
|
|
layout.addWidget(group_list)
|
|
|
|
add_button = QPushButton("Add Group")
|
|
edit_button = QPushButton("Edit Group")
|
|
delete_button = QPushButton("Delete Group")
|
|
|
|
button_layout = QHBoxLayout()
|
|
button_layout.addWidget(add_button)
|
|
button_layout.addWidget(edit_button)
|
|
button_layout.addWidget(delete_button)
|
|
layout.addLayout(button_layout)
|
|
|
|
add_button.clicked.connect(lambda: self.add_edit_exclusive_group(dialog, group_list))
|
|
edit_button.clicked.connect(lambda: self.add_edit_exclusive_group(dialog, group_list, group_list.currentItem()))
|
|
delete_button.clicked.connect(lambda: self.delete_exclusive_group(dialog, group_list, group_list.currentItem()))
|
|
|
|
dialog.exec()
|
|
|
|
def add_edit_exclusive_group(self, parent_dialog, group_list, item=None):
|
|
dialog = QDialog(parent_dialog)
|
|
dialog.setWindowTitle("Add/Edit Exclusive Group")
|
|
layout = QFormLayout(dialog)
|
|
|
|
name_edit = QLineEdit()
|
|
description_edit = QLineEdit()
|
|
|
|
layout.addRow("Group Name:", name_edit)
|
|
layout.addRow("Description:", description_edit)
|
|
|
|
if item:
|
|
group_id = item.data(Qt.ItemDataRole.UserRole)
|
|
self.cursor.execute('SELECT group_name, description FROM exclusive_encounter_groups WHERE id = ?', (group_id,))
|
|
group_name, description = self.cursor.fetchone()
|
|
name_edit.setText(group_name)
|
|
description_edit.setText(description)
|
|
|
|
buttons = QDialogButtonBox(QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel)
|
|
buttons.accepted.connect(dialog.accept)
|
|
buttons.rejected.connect(dialog.reject)
|
|
layout.addRow(buttons)
|
|
|
|
if dialog.exec() == QDialog.DialogCode.Accepted:
|
|
name = name_edit.text()
|
|
description = description_edit.text()
|
|
if item:
|
|
self.cursor.execute('UPDATE exclusive_encounter_groups SET group_name = ?, description = ? WHERE id = ?', (name, description, group_id))
|
|
item.setText(f"{name} - {description}")
|
|
else:
|
|
self.cursor.execute('INSERT INTO exclusive_encounter_groups (group_name, description) VALUES (?, ?)', (name, description))
|
|
group_id = self.cursor.lastrowid
|
|
new_item = QListWidgetItem(f"{name} - {description}")
|
|
new_item.setData(Qt.ItemDataRole.UserRole, group_id)
|
|
group_list.addItem(new_item)
|
|
self.conn.commit()
|
|
|
|
def delete_exclusive_group(self, parent_dialog, group_list, item):
|
|
if item:
|
|
group_id = item.data(Qt.ItemDataRole.UserRole)
|
|
reply = QMessageBox.question(parent_dialog, 'Delete Group', 'Are you sure you want to delete this group?', QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No, QMessageBox.StandardButton.No)
|
|
if reply == QMessageBox.StandardButton.Yes:
|
|
self.cursor.execute('DELETE FROM exclusive_encounter_groups WHERE id = ?', (group_id,))
|
|
self.cursor.execute('UPDATE encounters SET exclusive_group_id = NULL WHERE exclusive_group_id = ?', (group_id,))
|
|
self.conn.commit()
|
|
group_list.takeItem(group_list.row(item))
|
|
|
|
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)
|
|
self.cursor.execute('''
|
|
SELECT name, form_name, national_dex
|
|
FROM pokemon_forms
|
|
WHERE PFIC = ?
|
|
''', (pfic,))
|
|
pokemon_data = self.cursor.fetchone()
|
|
if pokemon_data:
|
|
name, form, national_dex = pokemon_data
|
|
|
|
# Import the necessary function and classes
|
|
#from DataGatherers.update_location_information import process_pokemon_for_location_data
|
|
|
|
import json
|
|
|
|
# Create a temporary connection for this operation
|
|
temp_conn = sqlite3.connect('pokemon_forms.db')
|
|
|
|
# Load default forms
|
|
try:
|
|
with open('./DataGatherers/DefaultForms.json', 'r') as f:
|
|
default_forms = json.load(f)
|
|
except FileNotFoundError:
|
|
default_forms = []
|
|
|
|
# Create a cache manager instance
|
|
cache = CacheManager()
|
|
|
|
# Delete existing encounters for this Pokémon
|
|
self.cursor.execute('DELETE FROM encounters WHERE pfic = ?', (pfic,))
|
|
self.conn.commit()
|
|
|
|
# Process the Pokémon data
|
|
process_pokemon_for_location_data(pfic, name, form, national_dex, default_forms, cache, temp_conn)
|
|
|
|
temp_conn.backup(self.conn)
|
|
|
|
# Close the temporary connection
|
|
temp_conn.close()
|
|
|
|
# Refresh the encounter locations in the UI
|
|
self.load_encounter_locations(pfic)
|
|
|
|
# Update the encounter cache and highlights
|
|
self.update_encounter_cache()
|
|
self.update_pokemon_list_highlights()
|
|
|
|
print(f"Refreshed encounters for {name} {form if form else ''}")
|
|
|
|
def gather_pokemon_forms(self):
|
|
self.progress_text.clear() # Clear previous progress text
|
|
self.progress_text.append("Starting to gather Pokémon forms...")
|
|
# Implement the logic to gather Pokémon forms
|
|
# Update progress as you go, for example:
|
|
self.progress_text.append("Processed 100 Pokémon...")
|
|
self.progress_text.append("Processed 200 Pokémon...")
|
|
# ...
|
|
self.progress_text.append("Finished gathering Pokémon forms.")
|
|
|
|
def gather_home_storage_info(self):
|
|
self.progress_text.clear()
|
|
self.progress_text.append("Starting to gather Home storage information...")
|
|
# Implement the logic
|
|
# ...
|
|
|
|
def gather_evolution_info(self):
|
|
self.progress_text.clear()
|
|
self.progress_text.append("Starting to gather evolution information...")
|
|
# Implement the logic
|
|
# ...
|
|
|
|
def gather_encounter_info(self):
|
|
self.progress_text.clear()
|
|
self.progress_text.append("Starting to gather encounter information...")
|
|
# Implement the logic
|
|
# ...
|
|
|
|
def reinitialize_database(self):
|
|
reply = QMessageBox.question(self, 'Confirm Action',
|
|
'Are you sure you want to clear and reinitialize the database? This action cannot be undone.',
|
|
QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No, QMessageBox.StandardButton.No)
|
|
if reply == QMessageBox.StandardButton.Yes:
|
|
self.progress_text.clear()
|
|
self.progress_text.append("Starting database reinitialization...")
|
|
# Implement the logic to clear and reinitialize the database
|
|
self.conn.close()
|
|
os.remove('pokemon_forms.db') # Remove the existing database file
|
|
self.conn = sqlite3.connect('pokemon_forms.db')
|
|
self.cursor = self.conn.cursor()
|
|
self.init_database() # Reinitialize the database structure
|
|
self.progress_text.append("Database reinitialized successfully.")
|
|
QMessageBox.information(self, 'Database Reinitialized', 'The database has been cleared and reinitialized.')
|
|
|
|
if __name__ == '__main__':
|
|
app = QApplication(sys.argv)
|
|
editor = DBEditor()
|
|
editor.show()
|
|
sys.exit(app.exec())
|