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.
296 lines
11 KiB
296 lines
11 KiB
import sys
|
|
import os
|
|
import sqlite3
|
|
from PyQt5.QtWidgets import (QApplication, QMainWindow, QTableWidget, QTableWidgetItem, QPushButton, QVBoxLayout,
|
|
QHBoxLayout, QWidget, QLineEdit, QLabel, QMessageBox, QTabWidget, QScrollArea, QFrame, QGridLayout)
|
|
from PyQt5.QtCore import Qt
|
|
from PyQt5.QtGui import QPixmap
|
|
|
|
class PokemonEvolutionWidget(QWidget):
|
|
def __init__(self, conn, pfic):
|
|
super().__init__()
|
|
self.conn = conn
|
|
self.pfic = pfic
|
|
self.layout = QVBoxLayout()
|
|
self.setLayout(self.layout)
|
|
self.stage_width = 200 # Fixed width for each evolution stage
|
|
self.stage_height = 250 # Fixed height for each evolution stage
|
|
self.build_evolution_chain()
|
|
|
|
def build_evolution_chain(self):
|
|
chain = self.get_full_evolution_chain(self.pfic)
|
|
self.display_evolution_chain(chain)
|
|
|
|
def get_full_evolution_chain(self, pfic):
|
|
cursor = self.conn.cursor()
|
|
chain = []
|
|
visited = set()
|
|
|
|
def build_chain(current_pfic):
|
|
if current_pfic in visited:
|
|
return None
|
|
visited.add(current_pfic)
|
|
|
|
cursor.execute('SELECT name, form_name FROM pokemon_forms WHERE PFIC = ?', (current_pfic,))
|
|
pokemon = cursor.fetchone()
|
|
if not pokemon:
|
|
return None
|
|
|
|
name, form_name = pokemon
|
|
node = {"pfic": current_pfic, "name": name, "form_name": form_name, "evolutions": []}
|
|
|
|
cursor.execute('''
|
|
SELECT ec.to_pfic, pf.name, pf.form_name, ec.method
|
|
FROM evolution_chains ec
|
|
JOIN pokemon_forms pf ON ec.to_pfic = pf.PFIC
|
|
WHERE ec.from_pfic = ?
|
|
''', (current_pfic,))
|
|
evolutions = cursor.fetchall()
|
|
|
|
for evo_pfic, evo_name, evo_form, method in evolutions:
|
|
evo_node = build_chain(evo_pfic)
|
|
if evo_node:
|
|
node["evolutions"].append({"node": evo_node, "method": method})
|
|
|
|
return node
|
|
|
|
chain = build_chain(pfic)
|
|
return chain
|
|
|
|
def display_evolution_chain(self, chain):
|
|
if not chain:
|
|
return
|
|
|
|
main_layout = QHBoxLayout()
|
|
self.layout.addLayout(main_layout)
|
|
|
|
stages = self.split_into_stages(chain)
|
|
for stage_index, stage in enumerate(stages):
|
|
stage_widget = QWidget()
|
|
stage_layout = QGridLayout()
|
|
stage_widget.setLayout(stage_layout)
|
|
stage_widget.setFixedSize(self.stage_width, self.stage_height * len(stage))
|
|
|
|
for row, pokemon in enumerate(stage):
|
|
pokemon_widget = self.create_pokemon_widget(pokemon["pfic"], pokemon["name"], pokemon["form_name"])
|
|
stage_layout.addWidget(pokemon_widget, row, 0, Qt.AlignCenter)
|
|
|
|
if stage_index < len(stages) - 1 and pokemon.get("method"):
|
|
arrow_label = QLabel("→")
|
|
arrow_label.setStyleSheet("font-size: 24px;")
|
|
stage_layout.addWidget(arrow_label, row, 1, Qt.AlignCenter)
|
|
|
|
method_label = QLabel(pokemon["method"])
|
|
method_label.setWordWrap(True)
|
|
method_label.setFixedWidth(80)
|
|
stage_layout.addWidget(method_label, row, 2, Qt.AlignCenter)
|
|
|
|
main_layout.addWidget(stage_widget)
|
|
|
|
def split_into_stages(self, chain):
|
|
stages = []
|
|
current_stage = [{"pfic": chain["pfic"], "name": chain["name"], "form_name": chain["form_name"]}]
|
|
stages.append(current_stage)
|
|
|
|
while current_stage:
|
|
next_stage = []
|
|
for pokemon in current_stage:
|
|
evolutions = self.get_evolutions(pokemon["pfic"])
|
|
for evolution in evolutions:
|
|
next_stage.append({
|
|
"pfic": evolution["to_pfic"],
|
|
"name": evolution["name"],
|
|
"form_name": evolution["form_name"],
|
|
"method": evolution["method"]
|
|
})
|
|
if next_stage:
|
|
stages.append(next_stage)
|
|
current_stage = next_stage
|
|
|
|
return stages
|
|
|
|
def get_evolutions(self, pfic):
|
|
cursor = self.conn.cursor()
|
|
cursor.execute('''
|
|
SELECT ec.to_pfic, pf.name, pf.form_name, ec.method
|
|
FROM evolution_chains ec
|
|
JOIN pokemon_forms pf ON ec.to_pfic = pf.PFIC
|
|
WHERE ec.from_pfic = ?
|
|
''', (pfic,))
|
|
evolutions = cursor.fetchall()
|
|
return [{"to_pfic": to_pfic, "name": name, "form_name": form_name, "method": method} for to_pfic, name, form_name, method in evolutions]
|
|
|
|
def create_pokemon_widget(self, pfic, name, form_name):
|
|
widget = QWidget()
|
|
layout = QVBoxLayout()
|
|
widget.setLayout(layout)
|
|
|
|
image_path = f"images-new/{pfic}.png"
|
|
if os.path.exists(image_path):
|
|
pixmap = QPixmap(image_path)
|
|
image_label = QLabel()
|
|
image_label.setPixmap(pixmap.scaled(96, 96, Qt.KeepAspectRatio, Qt.SmoothTransformation))
|
|
layout.addWidget(image_label, alignment=Qt.AlignCenter)
|
|
|
|
name_label = QLabel(name)
|
|
name_label.setAlignment(Qt.AlignCenter)
|
|
layout.addWidget(name_label)
|
|
|
|
if form_name:
|
|
form_label = QLabel(form_name)
|
|
form_label.setAlignment(Qt.AlignCenter)
|
|
layout.addWidget(form_label)
|
|
|
|
return widget
|
|
|
|
class DatabaseVisualizer(QMainWindow):
|
|
def __init__(self):
|
|
super().__init__()
|
|
self.setWindowTitle("Pokémon Database Visualizer")
|
|
self.setGeometry(100, 100, 1200, 800)
|
|
|
|
self.conn = sqlite3.connect('pokemon_forms.db')
|
|
self.cursor = self.conn.cursor()
|
|
|
|
self.central_widget = QWidget()
|
|
self.setCentralWidget(self.central_widget)
|
|
|
|
self.layout = QVBoxLayout()
|
|
self.central_widget.setLayout(self.layout)
|
|
|
|
self.tab_widget = QTabWidget()
|
|
self.layout.addWidget(self.tab_widget)
|
|
|
|
self.forms_tab = QWidget()
|
|
self.evolutions_tab = QWidget()
|
|
self.tab_widget.addTab(self.forms_tab, "Pokémon Forms")
|
|
self.tab_widget.addTab(self.evolutions_tab, "Evolution Chains")
|
|
|
|
self.setup_forms_tab()
|
|
self.setup_evolutions_tab()
|
|
|
|
def setup_forms_tab(self):
|
|
layout = QVBoxLayout()
|
|
self.forms_tab.setLayout(layout)
|
|
|
|
self.search_layout = QHBoxLayout()
|
|
self.search_label = QLabel("Search:")
|
|
self.search_input = QLineEdit()
|
|
self.search_button = QPushButton("Search")
|
|
self.search_button.clicked.connect(self.search_pokemon)
|
|
self.search_layout.addWidget(self.search_label)
|
|
self.search_layout.addWidget(self.search_input)
|
|
self.search_layout.addWidget(self.search_button)
|
|
layout.addLayout(self.search_layout)
|
|
|
|
self.table = QTableWidget()
|
|
layout.addWidget(self.table)
|
|
|
|
self.save_button = QPushButton("Save Changes")
|
|
self.save_button.clicked.connect(self.save_changes)
|
|
layout.addWidget(self.save_button)
|
|
|
|
self.load_forms_data()
|
|
|
|
def setup_evolutions_tab(self):
|
|
layout = QVBoxLayout()
|
|
self.evolutions_tab.setLayout(layout)
|
|
|
|
self.evolution_search_layout = QHBoxLayout()
|
|
self.evolution_search_label = QLabel("Search Pokémon:")
|
|
self.evolution_search_input = QLineEdit()
|
|
self.evolution_search_button = QPushButton("Search")
|
|
self.evolution_search_button.clicked.connect(self.search_evolution)
|
|
self.evolution_search_layout.addWidget(self.evolution_search_label)
|
|
self.evolution_search_layout.addWidget(self.evolution_search_input)
|
|
self.evolution_search_layout.addWidget(self.evolution_search_button)
|
|
layout.addLayout(self.evolution_search_layout)
|
|
|
|
self.evolution_scroll_area = QScrollArea()
|
|
self.evolution_scroll_area.setWidgetResizable(True)
|
|
layout.addWidget(self.evolution_scroll_area)
|
|
|
|
def load_forms_data(self):
|
|
self.cursor.execute('''
|
|
SELECT pf.PFIC, 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
|
|
''')
|
|
data = self.cursor.fetchall()
|
|
|
|
self.table.setColumnCount(6)
|
|
self.table.setHorizontalHeaderLabels(["PFIC", "Name", "Form Name", "National Dex", "Generation", "Storable in Home"])
|
|
self.table.setRowCount(len(data))
|
|
|
|
for row, record in enumerate(data):
|
|
for col, value in enumerate(record):
|
|
item = QTableWidgetItem(str(value))
|
|
if col == 0: # PFIC column
|
|
item.setFlags(item.flags() & ~Qt.ItemIsEditable) # Make PFIC non-editable
|
|
self.table.setItem(row, col, item)
|
|
|
|
self.table.resizeColumnsToContents()
|
|
|
|
def search_pokemon(self):
|
|
search_term = self.search_input.text().lower()
|
|
for row in range(self.table.rowCount()):
|
|
match = False
|
|
for col in range(self.table.columnCount()):
|
|
item = self.table.item(row, col)
|
|
if item and search_term in item.text().lower():
|
|
match = True
|
|
break
|
|
self.table.setRowHidden(row, not match)
|
|
|
|
def save_changes(self):
|
|
try:
|
|
for row in range(self.table.rowCount()):
|
|
pfic = self.table.item(row, 0).text()
|
|
name = self.table.item(row, 1).text()
|
|
form_name = self.table.item(row, 2).text() or None
|
|
national_dex = int(self.table.item(row, 3).text())
|
|
generation = int(self.table.item(row, 4).text())
|
|
storable_in_home = self.table.item(row, 5).text().lower() == 'true'
|
|
|
|
self.cursor.execute('''
|
|
UPDATE pokemon_forms
|
|
SET name = ?, form_name = ?, national_dex = ?, generation = ?
|
|
WHERE PFIC = ?
|
|
''', (name, form_name, national_dex, generation, pfic))
|
|
|
|
self.cursor.execute('''
|
|
INSERT OR REPLACE INTO pokemon_storage (PFIC, storable_in_home)
|
|
VALUES (?, ?)
|
|
''', (pfic, storable_in_home))
|
|
|
|
self.conn.commit()
|
|
QMessageBox.information(self, "Success", "Changes saved successfully!")
|
|
except Exception as e:
|
|
QMessageBox.critical(self, "Error", f"An error occurred while saving changes: {str(e)}")
|
|
|
|
def search_evolution(self):
|
|
search_term = self.evolution_search_input.text().lower()
|
|
|
|
self.cursor.execute('''
|
|
SELECT DISTINCT name, PFIC
|
|
FROM pokemon_forms
|
|
WHERE LOWER(name) LIKE ?
|
|
''', (f'%{search_term}%',))
|
|
|
|
matching_pokemon = self.cursor.fetchall()
|
|
|
|
if matching_pokemon:
|
|
pokemon_name, pfic = matching_pokemon[0]
|
|
evolution_widget = PokemonEvolutionWidget(self.conn, pfic)
|
|
self.evolution_scroll_area.setWidget(evolution_widget)
|
|
else:
|
|
QMessageBox.information(self, "No Results", "No Pokémon found matching the search term.")
|
|
|
|
def closeEvent(self, event):
|
|
self.conn.close()
|
|
|
|
if __name__ == "__main__":
|
|
app = QApplication(sys.argv)
|
|
window = DatabaseVisualizer()
|
|
window.show()
|
|
sys.exit(app.exec_())
|