Refactor the code using PySide6 instead of tkinter: import ctypes
import math
import re
from typing import Any, Dict, Union, Callable

import tkinter as tk
from tkinter import font as tkFont, ttk

#-- Unique Functions --

def capitalize_sentence(sentence: str) -> str:
    """Capitalize the first letter of each word in the sentence."""
    return ' '.join(word.capitalize() for word in sentence.split())

#-- Conversions --

def kg_to_lb(kg: float) -> float:
    """Convert kilograms to pounds."""
    return kg / 0.45359237

def lb_to_kg(lb: float) -> float:
    """Convert pounds to kilograms."""
    return lb * 0.45359237

#-- Processing --

def evaluate_expression(expression: str, use_degrees: bool = False) -> Union[float, str]:
    """Safely evaluate a mathematical expression considering degree mode."""
    
    def convert_angle(func: Callable[[float], float], x: float) -> float:
        return func(math.radians(x)) if use_degrees else func(x)

    def inverse_convert_angle(func: Callable[[float], float], x: float) -> float:
        result = func(x)
        return math.degrees(result) if use_degrees else result

    def safe_eval(expr: str) -> Any:
        safe_globals = {
            "sqrt": math.sqrt,
            "sin": lambda x: convert_angle(math.sin, x),
            "cos": lambda x: convert_angle(math.cos, x),
            "tan": lambda x: convert_angle(math.tan, x),
            "asin": lambda x: inverse_convert_angle(math.asin, x),
            "acos": lambda x: inverse_convert_angle(math.acos, x),
            "atan": lambda x: inverse_convert_angle(math.atan, x),
            "log": math.log10,
            "ln": math.log,
            "pi": math.pi,
            "e": math.e,
            "lb": kg_to_lb,
            "kg": lb_to_kg,
            "capitalize": capitalize_sentence
        }
        return eval(expr, {"__builtins__": None}, safe_globals)

    expression = expression.replace("^", "**")
    expression = re.sub(r'\bcapitalize\(([^\)]+)\)', 
                        lambda match: f'capitalize("{match.group(1)}")', 
                        expression)

    for func, arg in re.findall(r"(\b\w+\b)\(([^)]+)\)", expression):
        match func:
            case "asin" | "acos":
                try:
                    if (value := safe_eval(arg)) < -1 or value > 1:
                        return f"Error: {func}(x) is undefined for |x| > 1"
                except Exception as e:
                    return f"Error: {e}"

    try:
        result = safe_eval(expression)
        if isinstance(result, float) and abs(result) < 1e-10:
            result = 0.0
        return round(result, 2) if isinstance(result, (int, float)) else result
    except Exception as e:
        return f"Error: {e}"


class CalculatorGUI:
    """Tkinter-based Calculator with Degrees/Radians toggle and history."""

    def __init__(self, master: tk.Tk) -> None:
        self.master = master
        self.use_degrees = tk.BooleanVar(value=False)
        self.set_dpi_awareness()
        self.setup_window()
        self.create_widgets()
        self.layout_widgets()
        self.configure_grid()

    def set_dpi_awareness(self) -> None:
        """Enable high-DPI support on Windows."""
        try:
            ctypes.windll.shcore.SetProcessDpiAwareness(1)
        except Exception:
            pass

    def setup_window(self) -> None:
        """Configure the main application window."""
        self.master.title("Calculator")
        self.master.geometry("1200x720")

    def create_widgets(self) -> None:
        """Initialize all GUI components."""
        self.font = tkFont.Font(family="Roboto Flex", size=16)
        self.button_font = tkFont.Font(family="Roboto Flex", size=14)
        self.expression_var = tk.StringVar()
        self.entry = ttk.Entry(
            self.master, textvariable=self.expression_var, font=self.font, width=50
        )
        self.entry.bind("<Return>", self.calculate)

        self.history_text = tk.Text(
            self.master,
            width=70,
            height=10,
            font=self.font,
            wrap="none",
            state=tk.DISABLED,
        )

        self.scrollbar = ttk.Scrollbar(
            self.master, orient="vertical", command=self.history_text.yview
        )
        self.history_text.configure(yscrollcommand=self.scrollbar.set)

        self.function_buttons = {
            "Functions": ["sqrt", "sin", "cos", "tan", "asin", "acos", "atan", "log", "ln"],
            "Conversions": ["lb", "kg"],
            "Unique": ["capitalize"],
            "Constants": ["pi", "e"]
        }
        self.function_frame = ttk.Frame(self.master)
        self.create_function_buttons()

    def create_function_buttons(self):
        """Create buttons for inserting functions into the entry."""
        ttk.Label(self.function_frame, text="Functions", font=self.button_font).grid(
            row=0, column=0, columnspan=3, padx=5, pady=5, sticky="n"
        )
        for i, func in enumerate(self.function_buttons["Functions"]):
            ttk.Button(
                self.function_frame,
                text=func,
                command=lambda f=func: self.insert_function(f, is_constant=False),
                width=10,
                style='Function.TButton'
            ).grid(row=(i // 3) + 1, column=(i % 3), padx=5, pady=5)

        col = 0
        for category in ["Conversions", "Unique", "Constants"]:
            col += 3
            ttk.Label(self.function_frame, text=category, font=self.button_font).grid(
                row=0, column=col, padx=5, pady=5, sticky="n"
            )
            for i, func in enumerate(self.function_buttons[category]):
                button_text = f"{func}({'kg' if func == 'lb' else 'lb'})" if category == "Conversions" else func
                is_constant = category == "Constants"
                ttk.Button(
                    self.function_frame,
                    text=button_text,
                    command=lambda f=func, c=is_constant: self.insert_function(f, is_constant=c),
                    width=10,
                    style='Function.TButton'
                ).grid(row=i + 1, column=col, padx=5, pady=5)

        col += 1
        ttk.Label(self.function_frame, text="Settings", font=self.button_font).grid(
            row=0, column=col, padx=5, pady=5, sticky="n"
        )
        self.create_toggle_button(col)

    def create_toggle_button(self, col: int) -> None:
        """Create the Degrees/Radians toggle button in the settings column."""
        style = ttk.Style()
        style.configure("ToggleButton.TButton", font=self.button_font, padding=0)
        style.configure('Function.TButton', font=self.button_font)
        self.mode_button = ttk.Button(
            self.function_frame,
            text="Radians",
            command=self.toggle_mode,
            style="ToggleButton.TButton",
            width=10
        )
        self.mode_button.grid(row=1, column=col, padx=5, pady=5)

    def layout_widgets(self) -> None:
        """Arrange widgets within the window."""
        self.entry.grid(row=0, column=0, columnspan=5, padx=5, pady=5, sticky="ew")
        self.history_text.grid(row=1, column=0, columnspan=4, padx=5, pady=5, sticky="nsew")
        self.scrollbar.grid(row=1, column=4, padx=(0, 5), pady=5, sticky="ns")
        self.function_frame.grid(row=2, column=0, columnspan=5, padx=5, pady=5, sticky="ew")

    def configure_grid(self) -> None:
        """Make the grid layout responsive."""
        self.master.columnconfigure(0, weight=1)
        self.master.columnconfigure(1, weight=0)
        self.master.rowconfigure(1, weight=1)

    def toggle_mode(self) -> None:
        """Switch between Degrees and Radians modes."""
        self.use_degrees.set(not self.use_degrees.get())
        self.mode_button.config(text="Degrees" if self.use_degrees.get() else "Radians")

    def insert_function(self, function: str, is_constant: bool = False) -> None:
        """Insert function or constant text into the expression entry."""
        current_text = self.expression_var.get()
        cursor_position = self.entry.index(tk.INSERT)
        
        if is_constant:
            new_text = f"{current_text[:cursor_position]}{function}{current_text[cursor_position:]}"
            new_cursor_position = cursor_position + len(function)
        else:
            new_text = f"{current_text[:cursor_position]}{function}(){current_text[cursor_position:]}"
            new_cursor_position = cursor_position + len(function) + 1
        
        self.expression_var.set(new_text)
        self.entry.icursor(new_cursor_position)
        self.entry.focus()

    def calculate(self, event: tk.Event = None) -> None:
        """Evaluate the expression and update history."""
        if expression := self.expression_var.get().strip():
            result = evaluate_expression(expression, use_degrees=self.use_degrees.get())
            self.display_result(expression, result)
            self.expression_var.set("")

    def display_result(self, expression: str, result: Union[float, str]) -> None:
        """Append the calculation to the history log."""
        self.history_text.config(state=tk.NORMAL)
        mode = "Degrees" if self.use_degrees.get() else "Radians"
        self.history_text.insert(tk.END, f"[{mode}] {expression} = {result}\n")
        self.history_text.config(state=tk.DISABLED)
        self.history_text.see(tk.END)


def main() -> None:
    """Run the Calculator application."""
    root = tk.Tk()
    CalculatorGUI(root)
    root.mainloop()

if __name__ == "__main__":
    main()