181 lines
7.1 KiB
Python
181 lines
7.1 KiB
Python
"""
|
|
Effects Search View - Search for effects across all owned cards
|
|
Updated for CustomTkinter
|
|
"""
|
|
|
|
import tkinter as tk
|
|
from tkinter import ttk, messagebox
|
|
import customtkinter as ctk
|
|
import sys
|
|
import os
|
|
import re
|
|
from PIL import Image, ImageTk # Added missing import
|
|
|
|
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
|
|
|
from db.db_queries import search_owned_effects
|
|
from gui.theme import (
|
|
BG_DARK, BG_MEDIUM, BG_LIGHT, BG_HIGHLIGHT,
|
|
ACCENT_PRIMARY, ACCENT_SECONDARY, ACCENT_SUCCESS, ACCENT_TERTIARY,
|
|
TEXT_PRIMARY, TEXT_SECONDARY, TEXT_MUTED,
|
|
FONT_HEADER, FONT_SUBHEADER, FONT_BODY, FONT_BODY_BOLD, FONT_SMALL,
|
|
create_styled_button, create_styled_entry
|
|
)
|
|
from utils import resolve_image_path
|
|
|
|
class EffectsFrame(ctk.CTkFrame):
|
|
"""Frame for searching effects across owned cards"""
|
|
|
|
def __init__(self, parent):
|
|
super().__init__(parent, fg_color="transparent")
|
|
self.icon_cache = {}
|
|
self.create_widgets()
|
|
|
|
def create_widgets(self):
|
|
"""Create the effects search interface"""
|
|
# Header / Search Bar
|
|
header_frame = ctk.CTkFrame(self, fg_color="transparent")
|
|
header_frame.pack(fill=tk.X, padx=20, pady=15)
|
|
|
|
# Search container
|
|
search_container = ctk.CTkFrame(header_frame, fg_color="transparent")
|
|
search_container.pack(fill=tk.X)
|
|
|
|
ctk.CTkLabel(search_container, text="🔍 Search Effect:",
|
|
font=FONT_HEADER, text_color=TEXT_PRIMARY).pack(side=tk.LEFT, padx=(0, 10))
|
|
|
|
self.search_var = tk.StringVar()
|
|
self.search_entry = ctk.CTkEntry(search_container, textvariable=self.search_var, width=300)
|
|
self.search_entry.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=(0, 10))
|
|
self.search_entry.bind('<Return>', lambda e: self.perform_search())
|
|
|
|
search_btn = create_styled_button(search_container, text="Search",
|
|
command=self.perform_search, style_type='accent')
|
|
search_btn.pack(side=tk.LEFT)
|
|
|
|
# Example/Help text
|
|
help_frame = ctk.CTkFrame(header_frame, fg_color="transparent")
|
|
help_frame.pack(fill=tk.X, pady=(5, 0))
|
|
ctk.CTkLabel(help_frame, text="Examples: Friendship, Motivation, Race Bonus, Skill Pt",
|
|
font=FONT_SMALL, text_color=TEXT_MUTED).pack(side=tk.LEFT)
|
|
|
|
# Results Area
|
|
results_container = ctk.CTkFrame(self, fg_color="transparent")
|
|
results_container.pack(fill=tk.BOTH, expand=True, padx=20, pady=(0, 20))
|
|
|
|
# Label for the frame
|
|
ctk.CTkLabel(results_container, text="Search Results (Owned Cards)",
|
|
font=FONT_SUBHEADER, text_color=ACCENT_PRIMARY).pack(pady=(10, 5))
|
|
|
|
# Treeview Container
|
|
tree_frame = ctk.CTkFrame(results_container, fg_color="transparent")
|
|
tree_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=(0, 10))
|
|
|
|
# Treeview - ADDING IMAGE COLUMN
|
|
# Note: Treeview column #0 is the tree column where icons live.
|
|
# We will put the image in #0 and text in #0 if possible, or name in #1
|
|
# Treeview - ADDING IMAGE COLUMN
|
|
# Use #0 for Icon only, like Card View
|
|
columns = ('card_name', 'level', 'current_value', 'effect_name')
|
|
self.tree = ttk.Treeview(tree_frame, columns=columns, show='tree headings', selectmode='browse', style="CardList.Treeview")
|
|
|
|
self.tree.heading('#0', text='Image')
|
|
self.tree.column('#0', width=100, anchor='center')
|
|
|
|
self.tree.heading('card_name', text='Card Name', anchor='w')
|
|
self.tree.heading('level', text='Level', anchor='center')
|
|
self.tree.heading('current_value', text='Value', anchor='center')
|
|
self.tree.heading('effect_name', text='Effect Name', anchor='w')
|
|
|
|
self.tree.column('card_name', width=200)
|
|
self.tree.column('level', width=60, anchor='center')
|
|
self.tree.column('current_value', width=80, anchor='center')
|
|
self.tree.column('effect_name', width=200)
|
|
|
|
scrollbar = ttk.Scrollbar(tree_frame, orient=tk.VERTICAL, command=self.tree.yview)
|
|
# ... (rest of scrollbar setup) ...
|
|
self.tree.configure(yscrollcommand=scrollbar.set)
|
|
|
|
self.tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
|
|
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
|
|
|
|
# Status Label
|
|
self.status_label = ctk.CTkLabel(results_container, text="", font=FONT_SMALL, text_color=TEXT_SECONDARY)
|
|
self.status_label.pack(side=tk.BOTTOM, fill=tk.X, pady=(5, 10))
|
|
|
|
def parse_value(self, value_str):
|
|
"""Parse effect value string to float for sorting"""
|
|
try:
|
|
clean = re.sub(r'[^\d.-]', '', str(value_str))
|
|
return float(clean)
|
|
except:
|
|
return -999999.0
|
|
|
|
def perform_search(self):
|
|
"""Execute search and update results"""
|
|
term = self.search_var.get().strip()
|
|
if not term:
|
|
messagebox.showwarning("Search", "Please enter a search term")
|
|
return
|
|
|
|
# clear current
|
|
for item in self.tree.get_children():
|
|
self.tree.delete(item)
|
|
|
|
# Query DB
|
|
results = search_owned_effects(term)
|
|
|
|
if not results:
|
|
self.status_label.configure(text="No matching effects found among owned cards.")
|
|
return
|
|
|
|
# Process and Sort
|
|
# Row: (card_id, card_name, image_path, effect_name, effect_value, level)
|
|
processed_results = []
|
|
for r in results:
|
|
val_num = self.parse_value(r[4])
|
|
processed_results.append({
|
|
'data': r,
|
|
'sort_val': val_num
|
|
})
|
|
|
|
# Sort by value descending
|
|
processed_results.sort(key=lambda x: x['sort_val'], reverse=True)
|
|
|
|
# Populate Tree
|
|
for item in processed_results:
|
|
r = item['data']
|
|
|
|
card_id = r[0]
|
|
image_path = r[2]
|
|
|
|
# Load Image
|
|
img = self.icon_cache.get(card_id)
|
|
if not img:
|
|
resolved_path = resolve_image_path(image_path)
|
|
if resolved_path and os.path.exists(resolved_path):
|
|
try:
|
|
pil_img = Image.open(resolved_path)
|
|
# Match CardList size
|
|
pil_img.thumbnail((78, 78), Image.Resampling.LANCZOS)
|
|
img = ImageTk.PhotoImage(pil_img)
|
|
self.icon_cache[card_id] = img
|
|
except:
|
|
pass
|
|
|
|
kv = {'image': img} if img else {}
|
|
|
|
# Insert into tree
|
|
# #0 = Image (Text '')
|
|
# Cols = Name, Level, Value, Effect
|
|
values = (r[1], f"Lv {r[5]}", r[4], r[3])
|
|
|
|
self.tree.insert('', tk.END, text='', values=values, **kv)
|
|
|
|
self.status_label.configure(text=f"Found {len(processed_results)} owned cards with matching effects.")
|
|
|
|
# Compatibility methods for main_window integration
|
|
def set_card(self, card_id):
|
|
pass
|
|
|