Refactor the code using customtkinter instead of pyside6. Python 3.12 code: import json
import math
import os
import re
from pathlib import Path
from typing import Any, Callable, Union

from PySide6.QtCore import Qt, QTimer, Signal
from PySide6.QtGui import QFont
from PySide6.QtWidgets import (
    QApplication, QFileDialog, QFrame, QGridLayout, QHBoxLayout, QLabel,
    QLineEdit, QMainWindow, QMessageBox, QPushButton, QScrollBar, QTextEdit,
    QVBoxLayout, QWidget
)

#--- Calculations ---

def convert_angle(func: Callable[[float], float], x: float, use_degrees: bool) -> float:
    """Convert angle based on mode (degrees/radians)."""
    return func(math.radians(x)) if use_degrees else func(x)

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

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

def celsius_to_kelvin(c: float) -> float:
    """Convert Celsius to Kelvin."""
    return c + 273.15

def kelvin_to_celsius(k: float) -> float:
    """Convert Kelvin to Celsius."""
    return k - 273.15

def celsius_to_fahrenheit(c: float) -> float:
    """Convert Celsius to Fahrenheit."""
    return c * 9 / 5 + 32

def fahrenheit_to_celsius(f: float) -> float:
    """Convert Fahrenheit to Celsius."""
    return (f - 32) * 5 / 9

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

def remove_duplicates(text: str) -> str:
    """Remove duplicate words from text."""
    words = ' '.join(line.strip() for line in text.splitlines() if line.strip()).split()
    return ' '.join(dict.fromkeys(words))

#--- Processing ---

def get_safe_globals(use_degrees: bool, variables: dict) -> dict:
    """Define safe global functions and variables for expression evaluation."""
    trig_funcs = {'sin', 'cos', 'tan', 'asin', 'acos', 'atan'}
    safe_globals = {
        "sqrt": math.sqrt,
        "log": math.log10,
        "ln": math.log,
        "pi": math.pi,
        "e": math.e,
        "KilogramToPound": kilograms_to_pounds,
        "PoundToKilogram": pounds_to_kilograms,
        "CelsiusToKelvin": celsius_to_kelvin,
        "KelvinToCelsius": kelvin_to_celsius,
        "CelsiusToFahrenheit": celsius_to_fahrenheit,
        "FahrenheitToCelsius": fahrenheit_to_celsius,
        "capitalize": capitalize_sentence,
        "duplicates": remove_duplicates,
    }
    safe_globals.update({func: lambda x, f=func: convert_angle(getattr(math, f), x, use_degrees) for func in trig_funcs})
    return safe_globals | variables

def preprocess_text_functions(expression: str) -> str:
    """Preprocess text functions by ensuring arguments are quoted."""
    return re.sub(r'\b(capitalize|duplicates)\s*\(\s*([^)]+)\s*\)', 
                  lambda m: f'{m.group(1)}("{m.group(2)}")' if not (m.group(2).startswith('"') and m.group(2).endswith('"')) else m.group(0), 
                  expression)

def validate_inverse_trig(expression: str, safe_globals: dict) -> Union[str, None]:
    """Validate the domain of inverse trig functions."""
    for func, arg in re.findall(r'\b(asin|acos)\s*\(\s*([^)]+)\s*\)', expression):
        try:
            if abs(eval(arg, {"builtins": None}, safe_globals)) > 1:
                return f"Error: {func}({arg}) is undefined for |{arg}| > 1"
        except Exception as e:
            return f"Error: {e}"
    return None

def safe_evaluate(expression: str, safe_globals: dict) -> Union[str, Any]:
    """Safely evaluate the mathematical expression."""
    try:
        result = eval(expression, {"builtins": None}, safe_globals)
        if isinstance(result, (int, float)):
            return format_number(result)
        return result
    except Exception as e:
        return f"Error: {e}"

def format_number(num: Union[int, float]) -> str:
    """Format a number for display."""
    if isinstance(num, int):
        return str(num) if len(str(abs(num))) <= 9 else f"{num:.3e}"
    epsilon = 1e-10
    if math.isclose(num, 0.0, abs_tol=epsilon):
        return "0"
    if math.isclose(num, round(num), abs_tol=epsilon):
        return str(int(round(num)))
    abs_num = abs(num)
    if abs_num >= 1e9 or (abs_num < 1e-6 and abs_num != 0):
        return f"{num:.3e}"
    return f"{num:.3f}".rstrip('0').rstrip('.')

def evaluate_expression(expression: str, variables: dict, use_degrees: bool = False) -> Union[float, str]:
    """Evaluate the user's expression, handling variable assignments."""
    expression = preprocess_text_functions(expression)
    base_safe_globals = get_safe_globals(use_degrees, {})
    assignment_match = re.match(r'^\s*([a-zA-Z_]\w*)\s*=\s*(.+)$', expression)

    if assignment_match:
        var_name, var_expr = assignment_match.groups()
        if var_name in base_safe_globals:
            return f"Error: '{var_name}' is a reserved name and cannot be used as a variable."
        safe_globals = get_safe_globals(use_degrees, variables)
        var_value = safe_evaluate(var_expr, safe_globals)
        if not isinstance(var_value, str) or not var_value.startswith("Error"):
            try:
                var_value_converted = float(var_value) if '.' in var_value else int(var_value)
                variables[var_name] = var_value_converted
                return f"{var_name} = {var_value_converted}"
            except ValueError:
                return f"Error: Cannot assign non-numeric value to variable '{var_name}'"
        return var_value
    else:
        safe_globals = get_safe_globals(use_degrees, variables)
        error = validate_inverse_trig(expression, safe_globals)
        return error or safe_evaluate(expression, safe_globals)

#--- GUI ---

class LongPressButton(QPushButton):
    """A QPushButton that emits a signal when pressed and held for a specified duration."""
    
    longPressed = Signal()

    def __init__(self, text: str = "", parent=None, hold_duration: int = 3000):
        """Initialize the long press button."""
        super().__init__(text, parent)
        self.hold_duration = hold_duration
        self.timer = QTimer(self)
        self.timer.setSingleShot(True)
        self.timer.timeout.connect(self._on_long_press)
        self.pressed.connect(self._on_press)
        self.released.connect(self._on_release)

    def _on_press(self):
        """Start the timer when the button is pressed."""
        self.timer.start(self.hold_duration)

    def _on_release(self):
        """Stop the timer if it's active when the button is released."""
        self.timer.stop()

    def _on_long_press(self):
        """Emit the longPressed signal."""
        self.longPressed.emit()


class CalculatorGUI(QMainWindow):
    def __init__(self):
        super().__init__()
        self.script_dir = Path(__file__).parent
        self.use_degrees = True
        self.variables = {}
        self.history_entries = []
        self.text_functions = ['capitalize', 'duplicates']
        self.setup_window()
        self.create_widgets()
        self.layout_widgets()
        self.connect_signals()
        self.load_saved_data()

    def setup_window(self) -> None:
        """Set up the main window properties."""
        self.setWindowTitle("Calculator")
        self.setGeometry(100, 100, 1280, 720)

    def create_widgets(self) -> None:
        """Create all widgets used in the application."""
        font = QFont()
        font.setPointSize(12)
        font.setFamily('Literata')

        self.entry = QLineEdit()
        self.entry.setFont(font)
        self.entry.setPlaceholderText('Enter Expression')
        self.entry.setClearButtonEnabled(True)
        self.entry.returnPressed.connect(self.calculate)

        self.history_text = QTextEdit()
        self.history_text.setFont(font)
        self.history_text.setReadOnly(True)
        self.history_text.setStyleSheet("position: relative;")

        self.scrollbar = QScrollBar(Qt.Vertical)
        self.history_text.setVerticalScrollBar(self.scrollbar)

        # --- Existing Buttons ---

        self.search_button = QPushButton("🔍", self.history_text)
        self.search_button.setFixedSize(24, 24)
        self.search_button.setToolTip("Search History")
        self.search_button.setStyleSheet("""
            QPushButton {
                border: none;
                background-color: rgba(255, 255, 255, 200);
                font-size: 14px;
                border-radius: 12px;
            }
            QPushButton:hover {
                background-color: rgba(234, 235, 239, 255);
                color: white;
            }
        """)
        self.search_button.clicked.connect(self.toggle_search)
        self.search_button.raise_()

        self.delete_button = LongPressButton("🗑️", self.history_text, hold_duration=3000)
        self.delete_button.setFixedSize(24, 24)
        self.delete_button.setToolTip("Clear History (Hold for 3 seconds)")
        self.delete_button.setStyleSheet("""
            QPushButton {
                border: none;
                background-color: rgba(255, 255, 255, 200);
                font-size: 14px;
                border-radius: 12px;
            }
            QPushButton:hover {
                background-color: rgba(234, 235, 239, 255);
                color: white;
            }
        """)
        self.delete_button.longPressed.connect(self.clear_history)
        self.delete_button.raise_()

        self.vars_button = QPushButton("🧮", self.history_text)
        self.vars_button.setFixedSize(24, 24)
        self.vars_button.setToolTip("Show Variables")
        self.vars_button.setStyleSheet("""
            QPushButton {
                border: none;
                background-color: rgba(255, 255, 255, 200);
                font-size: 14px;
                border-radius: 12px;
            }
            QPushButton:hover {
                background-color: rgba(234, 235, 239, 255);
                color: white;
            }
        """)
        self.vars_button.clicked.connect(self.toggle_vars_overlay)
        self.vars_button.raise_()

        self.vars_overlay = QLineEdit(self.history_text)
        self.vars_overlay.setReadOnly(True)
        self.vars_overlay.setPlaceholderText("a = 1, b = 85, ...")
        self.vars_overlay.setFixedHeight(24)
        self.vars_overlay.setFixedWidth(300)
        self.vars_overlay.setStyleSheet("""
            QLineEdit {
                border: 1px solid gray;
                border-radius: 4px;
                padding: 2px 4px;
                background-color: white;
            }
        """)
        self.vars_overlay.setVisible(False)

        self.vars_delete_button = LongPressButton("🗑️", self.vars_overlay, hold_duration=3000)
        self.vars_delete_button.setFixedSize(16, 16)
        self.vars_delete_button.setToolTip("Clear Variables (Hold for 3 seconds)")
        self.vars_delete_button.setStyleSheet("""
            QPushButton {
                border: none;
                background-color: rgba(255, 255, 255, 200);
                font-size: 10px;
                border-radius: 8px;
            }
            QPushButton:hover {
                background-color: rgba(234, 235, 239, 255);
                color: white;
            }
        """)
        self.vars_delete_button.longPressed.connect(self.clear_variables)
        self.vars_delete_button.setVisible(False)

        self.search_bar = QLineEdit(self.history_text)
        self.search_bar.setPlaceholderText("Search...")
        self.search_bar.setFixedHeight(24)
        self.search_bar.setFixedWidth(300)
        self.search_bar.setVisible(False)
        self.search_bar.setStyleSheet("""
            QLineEdit {
                border: 1px solid gray;
                border-radius: 4px;
                padding: 2px 4px;
                background-color: white;
            }
        """)
        self.search_bar.textChanged.connect(self.filter_history)
        self.search_bar.setClearButtonEnabled(True)

        self.save_button = QPushButton("💾", self.history_text)
        self.save_button.setFixedSize(24, 24)
        self.save_button.setToolTip("Export History and Variables")
        self.save_button.setStyleSheet("""
            QPushButton {
                border: none;
                background-color: rgba(255, 255, 255, 200);
                font-size: 14px;
                border-radius: 12px;
            }
            QPushButton:hover {
                background-color: rgba(234, 235, 239, 255);
                color: white;
            }
        """)
        self.save_button.clicked.connect(self.save_data)
        self.save_button.raise_()

        self.load_button = QPushButton("📂", self.history_text)
        self.load_button.setFixedSize(24, 24)
        self.load_button.setToolTip("Import History and Variables")
        self.load_button.setStyleSheet("""
            QPushButton {
                border: none;
                background-color: rgba(255, 255, 255, 200);
                font-size: 14px;
                border-radius: 12px;
            }
            QPushButton:hover {
                background-color: rgba(234, 235, 239, 255);
                color: white;
            }
        """)
        self.load_button.clicked.connect(self.load_data)
        self.load_button.raise_()

        self.function_buttons = {
            "Functions": ["sqrt", "sin", "cos", "tan", "asin", "acos", "atan", "log", "ln"],
            "Conversions": ["lb", "kg", "K", "C", "F", "CF"],
            "Text": ["capitalize", "duplicates"],
            "Constants": ["pi", "e"],
            "Settings": []
        }
        self.function_frame = QFrame()
        self.create_function_buttons(font)

    def create_function_buttons(self, font: QFont) -> None:
        """Create and arrange function buttons."""
        layout = QGridLayout()
        categories = [("Functions", 3), ("Conversions", 2), ("Text", 2), ("Constants", 2), ("Settings", 1)]
        starting_col = 0

        for category, col_span in categories:
            label = QLabel(category)
            label.setFont(font)
            layout.addWidget(label, 0, starting_col, 1, col_span, Qt.AlignCenter)

            buttons = self.function_buttons.get(category, [])
            if category == "Functions":
                for i, func in enumerate(buttons):
                    button = QPushButton(func)
                    button.setFont(font)
                    button.clicked.connect(
                        lambda _, f=func: self.insert_function(f, is_text_function=(f in self.text_functions))
                    )
                    layout.addWidget(button, (i // 3) + 1, starting_col + (i % 3))

            elif category == "Settings":
                self.mode_button = QPushButton("Degrees")
                self.mode_button.setFont(font)
                self.mode_button.clicked.connect(self.toggle_mode)
                layout.addWidget(self.mode_button, 1, starting_col, 1, 1)

            elif category == "Conversions":
                conversion_mapping = {
                    "lb": "KilogramToPound",
                    "kg": "PoundToKilogram",
                    "K": "CelsiusToKelvin",
                    "C": "KelvinToCelsius",
                    "F": "CelsiusToFahrenheit",
                    "CF": "FahrenheitToCelsius"
                }

                for idx, func in enumerate(buttons):
                    display_text = {
                        "lb": "lb(Kg)",
                        "kg": "kg(lb)",
                        "K": "K(°C)",
                        "C": "°C(K)",
                        "F": "F(°C)",
                        "CF": "°C(F)"
                    }.get(func, func)

                    button = QPushButton(display_text)
                    button.setFont(font)

                    function_to_insert = conversion_mapping.get(func, func)

                    button.clicked.connect(
                        lambda _, f=function_to_insert: self.insert_function(f, is_text_function=False)
                    )
                    row, col = 1 + idx // 2, starting_col + idx % 2
                    layout.addWidget(button, row, col)

            elif category == "Text":
                for idx, func in enumerate(buttons):
                    button = QPushButton(func)
                    button.setFont(font)
                    button.clicked.connect(
                        lambda _, f=func: self.insert_function(f, is_text_function=True)
                    )
                    row, col = 1 + idx // col_span, starting_col + idx % col_span
                    layout.addWidget(button, row, col)

            elif category == "Constants":
                for idx, func in enumerate(buttons):
                    button = QPushButton(func)
                    button.setFont(font)
                    button.clicked.connect(
                        lambda _, f=func: self.insert_function(f, is_constant=True)
                    )
                    row, col = 1 + idx // col_span, starting_col + idx % col_span
                    layout.addWidget(button, row, col)

            total_rows = math.ceil(len(buttons) / col_span)
            
            for extra in range(col_span * total_rows - len(buttons)):
                layout.addWidget(QLabel(""), 1 + extra // col_span, starting_col + extra % col_span)

            starting_col += col_span

        self.function_frame.setLayout(layout)

    def layout_widgets(self) -> None:
        """Arrange all widgets in the main window."""
        central_widget = QWidget()
        main_layout = QVBoxLayout()

        main_layout.addWidget(self.entry)

        history_layout = QHBoxLayout()
        history_layout.addWidget(self.history_text)
        history_layout.addWidget(self.scrollbar)
        main_layout.addLayout(history_layout)

        main_layout.addWidget(self.function_frame)

        central_widget.setLayout(main_layout)
        self.setCentralWidget(central_widget)

    def connect_signals(self) -> None:
        """Connect global signals."""
        QApplication.instance().focusChanged.connect(self.on_focus_changed)

    def toggle_mode(self) -> None:
        """Toggle between degrees and radians for trigonometric functions."""
        self.use_degrees = not self.use_degrees
        self.mode_button.setText("Degrees" if self.use_degrees else "Radians")

    def insert_function(self, function: str, is_constant: bool = False, is_text_function: bool = False) -> None:
        """Insert the selected function into the entry field."""
        current_text = self.entry.text()
        cursor_position = self.entry.cursorPosition()
        if is_constant:
            new_text = f"{current_text[:cursor_position]}{function} "
            new_cursor_position = cursor_position + len(function) + 1
        elif is_text_function and function in self.text_functions:
            new_text = f'{current_text[:cursor_position]}{function}() {current_text[cursor_position:]}'
            new_cursor_position = cursor_position + len(function) + 1
        else:
            new_text = f"{current_text[:cursor_position]}{function}() {current_text[cursor_position:]}"
            new_cursor_position = cursor_position + len(function) + 1
        self.entry.setText(new_text)
        self.entry.setCursorPosition(new_cursor_position)
        self.entry.setFocus()

    def calculate(self) -> None:
        """Evaluate the expression entered by the user."""
        expression = self.entry.text().strip()
        if expression:
            result = evaluate_expression(
                expression, self.variables, use_degrees=self.use_degrees
            )
            self.display_result(expression, result)
            self.entry.clear()

    def display_result(self, expression: str, result: Union[float, str]) -> None:
        """Display the result in the history."""
        mode = "D" if self.use_degrees else "R"
        if re.match(r'^\s*[a-zA-Z_]\w*\s*=\s*.+$', expression):
            history_entry = f"[{mode}] {result}"
        else:
            history_entry = f"[{mode}] {expression} = {result}"
        self.history_entries.append(history_entry)
        self.refresh_history()
        self.history_text.verticalScrollBar().setValue(
            self.history_text.verticalScrollBar().maximum()
        )

    def toggle_search(self) -> None:
        """Toggle the visibility of the search bar."""
        if self.search_bar.isVisible():
            self.search_bar.setVisible(False)
        else:
            self.search_bar.setVisible(True)
            self.search_bar.setFocus()
        self.update_overlay_buttons_position()

    def filter_history(self, text: str) -> None:
        """Filter the history based on search text."""
        self.refresh_history(text)

    def refresh_history(self, filter_text: str = "") -> None:
        """Refresh the history display, optionally filtering results."""
        self.history_text.clear()
        for entry in self.history_entries:
            if filter_text.lower() in entry.lower():
                self.history_text.append(entry)

    def resizeEvent(self, event) -> None:
        """Handle window resize events."""
        super().resizeEvent(event)
        self.update_overlay_buttons_position()

    def update_overlay_buttons_position(self) -> None:
        """Update the position of overlay buttons based on current window size."""
        size = self.history_text.viewport().size()

        margin_right = 5
        margin_top = 5
        spacing = 5

        available_width = size.width()

        search_offset = self.search_bar.width() + spacing if self.search_bar.isVisible() else 0
        load_offset = self.load_button.width() + spacing if self.load_button.isVisible() else 0
        save_offset = self.save_button.width() + spacing if self.save_button.isVisible() else 0

        self.search_button.move(
            available_width - search_offset - self.search_button.width() - margin_right,
            margin_top
        )

        vars_offset = self.vars_overlay.width() + spacing if self.vars_overlay.isVisible() else 0
        vars_button_y = self.search_button.y() + self.search_button.height() + spacing
        self.vars_button.move(
            available_width - vars_offset - self.vars_button.width() - margin_right,
            vars_button_y
        )

        save_button_y = self.vars_button.y() + self.vars_button.height() + spacing
        self.save_button.move(
            available_width - self.save_button.width() - margin_right,
            save_button_y
        )

        load_button_y = self.save_button.y() + self.save_button.height() + spacing
        self.load_button.move(
            available_width - self.load_button.width() - margin_right,
            load_button_y
        )

        delete_button_y = self.load_button.y() + self.load_button.height() + spacing
        self.delete_button.move(
            available_width - self.delete_button.width() - margin_right,
            delete_button_y
        )

        if self.vars_overlay.isVisible():
            self.vars_overlay.move(
                available_width - self.vars_overlay.width() - margin_right,
                self.vars_button.y()
            )
            self.vars_delete_button.move(
                self.vars_overlay.width() - self.vars_delete_button.width() - margin_right,
                (self.vars_overlay.height() - self.vars_delete_button.height()) // 2
            )
            self.vars_delete_button.setVisible(True)

        if self.search_bar.isVisible():
            self.search_bar.move(
                available_width - self.search_bar.width() - margin_right,
                margin_top
            )

    def on_focus_changed(self, old: QWidget, new: QWidget) -> None:
        """Handle focus changes to hide overlays when necessary."""
        if self.vars_overlay.isVisible() and new not in {self.vars_overlay, self.vars_delete_button, self.vars_button}:
            self.vars_overlay.setVisible(False)
            self.vars_delete_button.setVisible(False)
            self.update_overlay_buttons_position()
        if self.search_bar.isVisible() and not self.search_bar.text().strip() and new != self.search_bar:
            self.toggle_search()

    def showEvent(self, event) -> None:
        """Handle the show event to position overlays correctly."""
        super().showEvent(event)
        self.update_overlay_buttons_position()

    def clear_history(self) -> None:
        """Clear the calculation history."""
        self.history_entries.clear()
        self.refresh_history()

    def toggle_vars_overlay(self) -> None:
        """Toggle the visibility of the variables overlay."""
        if self.vars_overlay.isVisible():
            self.vars_overlay.setVisible(False)
            self.vars_delete_button.setVisible(False)
        else:
            self.update_vars_overlay()
            self.vars_overlay.setVisible(True)
            self.vars_delete_button.setVisible(True)
        self.update_overlay_buttons_position()

    def update_vars_overlay(self) -> None:
        """Update the text displayed in the variables overlay."""
        if not self.variables:
            self.vars_overlay.setText("No variables assigned.")
        else:
            vars_text = ", ".join(f"{var} = {value}" for var, value in self.variables.items())
            self.vars_overlay.setText(vars_text)

    def clear_variables(self) -> None:
        """Clear all assigned variables."""
        self.variables.clear()
        self.update_vars_overlay()
        self.vars_overlay.setVisible(True)
        self.vars_delete_button.setVisible(True)

    def save_data(self) -> None:
        """Save history and variables to a file."""
        try:
            data = {
                'history': self.history_entries,
                'variables': self.variables
            }

            options = QFileDialog.Options()
            options |= QFileDialog.DontUseNativeDialog
            file_path, _ = QFileDialog.getSaveFileName(
                self,
                "Save Calculator Data",
                "",
                "JSON Files (*.json);;All Files (*)",
                options=options
            )
            if file_path:
                with open(file_path, 'w') as f:
                    json.dump(data, f, indent=4)
                QMessageBox.information(self, "Save Successful", f"Data saved to {file_path}")
        except Exception as e:
            QMessageBox.critical(self, "Save Failed", f"An error occurred while saving: {e}")

    def load_data(self) -> None:
        """Load history and variables from a file."""
        try:
            options = QFileDialog.Options()
            options |= QFileDialog.DontUseNativeDialog
            file_path, _ = QFileDialog.getOpenFileName(
                self,
                "Load Calculator Data",
                "",
                "JSON Files (*.json);;All Files (*)",
                options=options
            )
            if file_path:
                with open(file_path, 'r') as f:
                    data = json.load(f)
                if 'history' in data and 'variables' in data:
                    self.history_entries = data['history']
                    self.variables = data['variables']
                    self.refresh_history()
                    self.update_vars_overlay()
                    QMessageBox.information(self, "Load Successful", f"Data loaded from {file_path}")
                else:
                    QMessageBox.warning(self, "Invalid Data", "The selected file does not contain valid calculator data.")
        except Exception as e:
            QMessageBox.critical(self, "Load Failed", f"An error occurred while loading: {e}")

    def load_saved_data(self) -> None:
        """Load history and variables from a default save file if it exists."""
        default_save = self.script_dir / 'calculator_save.json'
        if default_save.exists():
            try:
                with default_save.open('r') as f:
                    data = json.load(f)
                self.history_entries = data.get('history', [])
                self.variables = data.get('variables', {})
                self.refresh_history()
                self.update_vars_overlay()
            except Exception as e:
                QMessageBox.warning(self, "Load Failed", f"Failed to load saved data: {e}")

    def closeEvent(self, event) -> None:
        """Save data before closing the application."""
        try:
            data = {
                'history': self.history_entries,
                'variables': self.variables
            }
            default_save = self.script_dir / 'calculator_save.json'
            with default_save.open('w') as f:
                json.dump(data, f, indent=4)
        except Exception as e:
            QMessageBox.warning(self, "Auto-Save Failed", f"Failed to auto-save data: {e}")
        event.accept()

def main() -> None:
    """Main function to run the calculator application."""
    app = QApplication([])
    calculator = CalculatorGUI()
    calculator.show()
    app.exec()

if __name__ == "__main__":
    main()