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 ( ) )