Optimize formatting (according to PEP 8) nothing else. Python 3.12 code: import tkinter as tk
from tkinter import ttk, messagebox, font
import sqlite3
import sys
Enable High DPI support on Windows

if sys.platform.startswith('win'):
try:
import ctypes
Set DPI awareness to per-monitor

ctypes.windll.shcore.SetProcessDpiAwareness(1)
except Exception as e:
print("Error setting DPI awareness:", e)
Database functions

def run_query(query, parameters=()):
with sqlite3.connect('media.db') as conn:
cursor = conn.cursor()
result = cursor.execute(query, parameters)
if query.strip().lower().startswith("select"):
return result.fetchall()
conn.commit()

def create_tables():
create_movies_table_sql = '''
CREATE TABLE IF NOT EXISTS movies (
id INTEGER PRIMARY KEY AUTOINCREMENT,
movie TEXT,
year TEXT,
present BOOLEAN,
watched BOOLEAN,
notes TEXT
);
'''
create_series_table_sql = '''
CREATE TABLE IF NOT EXISTS series (
id INTEGER PRIMARY KEY AUTOINCREMENT,
series TEXT,
seasons TEXT,
year TEXT,
present BOOLEAN,
seasons_present TEXT,
complete BOOLEAN,
watched BOOLEAN,
seasons_seen TEXT,
notes TEXT
);
'''
run_query(create_movies_table_sql)
run_query(create_series_table_sql)

class MediaTracker(tk.Tk):
def init(self):
super().init()

# Set scaling for High DPI displays
if sys.platform.startswith('win'):
    try:
        # Calculate scaling based on the system DPI
        scaling = self.winfo_fpixels('1i') / 72  # Tk uses 72 DPI as the base
        self.tk.call('tk', 'scaling', scaling)
    except Exception as e:
        print("Error setting scaling:", e)

self.title("Movies and Series Tracker")
self.geometry("1200x600")  # Adjusted for better layout

# Set font to Literata
try:
    self.custom_font = font.Font(family='Literata', size=12)
except:
    # Fallback to default font if 'Literata' is not available
    self.custom_font = font.Font(family='Arial', size=12)

# Calculate row height based on font metrics
font_line_space = self.custom_font.metrics('linespace')
desired_padding = 4  # Additional pixels for padding
row_height = font_line_space + desired_padding

# Initialize ttk Style
style = ttk.Style()

# Optionally, set a different theme if needed
# style.theme_use('clam')

# Configure the Treeview style with the custom font and rowheight
style.configure("Custom.Treeview",
                font=self.custom_font,
                rowheight=row_height)

# Configure the Treeview heading style
style.configure("Custom.Treeview.Heading",
                font=(self.custom_font.cget("family"), self.custom_font.cget("size"), "bold"))

# Optionally, configure Button style
style.configure("Custom.TButton", font=self.custom_font)

# Define the new sidebar background color
self.sidebar_bg = '#F7F8FC'  # RGB(247, 248, 252)

# Main frames
self.sidebar = tk.Frame(self, width=150, bg=self.sidebar_bg)  # Updated bg color
self.sidebar.pack(side='left', fill='y')

self.button_bar = tk.Frame(self, width=50, bg='white')
self.button_bar.pack(side='right', fill='y')

self.content = tk.Frame(self, bg='white')
self.content.pack(side='left', fill='both', expand=True)

# Sidebar labels instead of buttons
self.create_sidebar_label("Movies", self.show_movies)
self.create_sidebar_label("Series", self.show_series)

# Header Frame
self.header = tk.Frame(self.content, bg='white', height=50)
self.header.pack(fill='x')

self.header_label = tk.Label(
    self.header,
    text="Movies",
    bg='white',
    font=self.custom_font,
    anchor='w',  # Align text to the left
    padx=10
)
self.header_label.pack(fill='x', pady=10)

# Add and Delete buttons in button bar with custom style
self.add_button = ttk.Button(self.button_bar, text="+", command=self.add_entry, width=3, style="Custom.TButton")
self.add_button.pack(pady=20)

self.delete_button = ttk.Button(self.button_bar, text="-", command=self.delete_entry, width=3, style="Custom.TButton")
self.delete_button.pack(pady=10)

# Initialize Treeview and Scrollbar
self.tree = None
self.scrollbar = None  # Initialize scrollbar as None
self.current_table = None
self.current_row_id = None

# Define boolean columns for each table
self.boolean_columns = {
    'movies': ['Present', 'Watched'],
    'series': ['Present', 'Complete', 'Watched']
}

# Load data
self.show_movies()

def create_sidebar_label(self, text, command):
label = tk.Label(
self.sidebar,
text=text,
bg=self.sidebar_bg, # Updated bg color
font=self.custom_font,
cursor="hand2",
anchor='w',
padx=10,
pady=5
)
label.pack(pady=10, padx=10, fill='x')

# Bind hover effects
label.bind("<Enter>", lambda e: label.config(bg='lightblue'))
label.bind("<Leave>", lambda e: label.config(bg=self.sidebar_bg))  # Revert to sidebar_bg

# Bind click event
label.bind("<Button-1>", lambda e: command())

def clear_content(self):
"""Destroy existing Treeview and Scrollbar if they exist."""
if self.tree:
self.tree.destroy()
self.tree = None
if self.scrollbar:
self.scrollbar.destroy()
self.scrollbar = None

def setup_treeview(self, columns, headings):
"""Create and pack Treeview and Scrollbar."""
self.tree = ttk.Treeview(self.content, columns=columns, show='headings', selectmode='browse', style="Custom.Treeview")
for col, head in zip(columns, headings):
self.tree.heading(col, text=head)
if head.lower() in ['id']:
self.tree.column(col, width=50, anchor='center')
elif head.lower() in ['notes']:
self.tree.column(col, width=300, anchor='w')
else:
self.tree.column(col, width=100, anchor='center')
# Creating and configuring Scrollbar
self.scrollbar = ttk.Scrollbar(self.content, orient="vertical", command=self.tree.yview)
self.tree.configure(yscrollcommand=self.scrollbar.set)
self.scrollbar.pack(side='right', fill='y')
self.tree.pack(fill='both', expand=True)

# Bind events
self.tree.bind('<<TreeviewSelect>>', self.on_row_select)
self.tree.bind('<Double-1>', self.on_double_click)
self.tree.bind('<Button-1>', self.on_single_click)

def load_movie_data(self):
self.clear_content()
columns = ["ID", "Movie", "Year", "Present", "Watched", "Notes"]
headings = ["ID", "Movie", "Year", "Present", "Watched", "Notes"]
self.setup_treeview(columns, headings)
self.current_table = 'movies'

# Update header
self.header_label.config(text="Movies")

for row in run_query('SELECT * FROM movies'):
    # Convert boolean fields to 'Yes'/'No'
    display_row = list(row)
    display_row[3] = 'Yes' if row[3] else 'No'  # Present
    display_row[4] = 'Yes' if row[4] else 'No'  # Watched
    self.tree.insert('', 'end', values=display_row)

def load_series_data(self):
self.clear_content()
columns = ["ID", "Series", "Seasons", "Year", "Present", "Seasons Present",
"Complete", "Watched", "Seasons Seen", "Notes"]
headings = ["ID", "Series", "Seasons", "Year", "Present", "Seasons Present",
"Complete", "Watched", "Seasons Seen", "Notes"]
self.setup_treeview(columns, headings)
self.current_table = 'series'

# Update header
self.header_label.config(text="Series")

for row in run_query('SELECT * FROM series'):
    # Convert boolean fields to 'Yes'/'No'
    display_row = list(row)
    display_row[4] = 'Yes' if row[4] else 'No'      # Present
    display_row[6] = 'Yes' if row[6] else 'No'      # Complete
    display_row[7] = 'Yes' if row[7] else 'No'      # Watched
    self.tree.insert('', 'end', values=display_row)

def show_movies(self):
self.load_movie_data()

def show_series(self):
self.load_series_data()

def add_entry(self):
if self.current_table == 'movies':
run_query("INSERT INTO movies (movie, year, present, watched, notes) VALUES (?, ?, ?, ?, ?)",
('', '', False, False, ''))
self.load_movie_data()
elif self.current_table == 'series':
run_query("""INSERT INTO series
(series, seasons, year, present, seasons_present, complete, watched, seasons_seen, notes)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)""",
('', '', '', False, '', False, False, '', ''))
self.load_series_data()

def delete_entry(self):
selected_item = self.tree.selection()
if not selected_item:
messagebox.showwarning("No selection", "Please select a row to delete.")
return
item = self.tree.item(selected_item)
row_id = item['values'][0]
confirm = messagebox.askyesno("Confirm Delete", "Are you sure you want to delete the selected entry?")
if confirm:
if self.current_table == 'movies':
run_query("DELETE FROM movies WHERE id = ?", (row_id,))
self.load_movie_data()
elif self.current_table == 'series':
run_query("DELETE FROM series WHERE id = ?", (row_id,))
self.load_series_data()

def on_row_select(self, event):
selected_item = self.tree.selection()
if selected_item:
item = self.tree.item(selected_item)
self.current_row_id = item['values'][0]
else:
self.current_row_id = None

def on_single_click(self, event):
# Identify the region where the click occurred
region = self.tree.identify("region", event.x, event.y)
if region != "cell":
return

# Identify the row and column
row_id = self.tree.identify_row(event.y)
column = self.tree.identify_column(event.x)
if not row_id or not column:
    return

# Get column index
try:
    col_index = int(column.replace('#', '')) - 1
except ValueError:
    return  # Invalid column

if col_index < 0 or col_index >= len(self.tree['columns']):
    return  # Out of range

column_name = self.tree['columns'][col_index]

# Check if the column is a boolean field
if self.current_table and column_name in self.boolean_columns.get(self.current_table, []):
    # Get current value
    current_value = self.tree.set(row_id, column_name)
    # Toggle the value
    new_value = 'No' if current_value == 'Yes' else 'Yes'
    self.tree.set(row_id, column_name, new_value)

    # Update the database
    row_values = self.tree.item(row_id)['values']
    self.update_database(row_values)

def on_double_click(self, event):
item = self.tree.identify_row(event.y)
column = self.tree.identify_column(event.x)
if not item:
return
try:
col_num = int(column.replace('#', '')) - 1
except ValueError:
return # Invalid column
if col_num == 0:
return # ID column is read-only

if col_num < 0 or col_num >= len(self.tree['columns']):
    return  # Out of range

column_name = self.tree['columns'][col_num]
value = self.tree.set(item, column_name)

# Determine if the column is boolean (if so, do not allow editing here)
if self.current_table and column_name in self.boolean_columns.get(self.current_table, []):
    return  # Do nothing; handled by single-click

# Create entry widget for non-boolean fields
x, y, width, height = self.tree.bbox(item, column)
if not width or not height:
    return  # Invalid bounding box, possibly no cell

# Create entry widget
entry = tk.Entry(self.content, font=self.custom_font)
entry.place(x=x, y=y, width=width, height=height)
entry.insert(0, value)
entry.focus()

def save_edit(event):
    new_value = entry.get()
    entry.destroy()
    self.tree.set(item, column_name, new_value)
    row_values = self.tree.item(item)['values']
    self.update_database(row_values)

entry.bind('<Return>', save_edit)
entry.bind('<FocusOut>', save_edit)

def update_database(self, row_values):
if self.current_table == 'movies':
# Map 'Yes'/'No' back to boolean
present = self.yes_no_to_bool(row_values[3])
watched = self.yes_no_to_bool(row_values[4])
query = "UPDATE movies SET movie = ?, year = ?, present = ?, watched = ?, notes = ? WHERE id = ?"
parameters = (row_values[1], row_values[2], present, watched, row_values[5], row_values[0])
elif self.current_table == 'series':
# Map 'Yes'/'No' back to boolean
present = self.yes_no_to_bool(row_values[4])
complete = self.yes_no_to_bool(row_values[6])
watched = self.yes_no_to_bool(row_values[7])
query = """UPDATE series SET series = ?, seasons = ?, year = ?, present = ?,
seasons_present = ?, complete = ?, watched = ?, seasons_seen = ?, notes = ? WHERE id = ?"""
parameters = (row_values[1], row_values[2], row_values[3],
present, row_values[5],
complete, watched,
row_values[8], row_values[9], row_values[0])
run_query(query, parameters)

def yes_no_to_bool(self, value):
return True if value.lower() == 'yes' else False

if name == "main":
create_tables()
app = MediaTracker()
app.mainloop()