Add a small delete symbol in the right corner of the execution field that if the user clicks on it deletes everything in the execution field. Use pytside6 builtin function. Python 3.12 Code: import math
import re
from typing import Any, Union, Callable

from PySide6.QtWidgets import (
QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,
QLineEdit, QTextEdit, QScrollBar, QPushButton, QLabel, QFrame,
QGridLayout
)
from PySide6.QtGui import QFont
from PySide6.QtCore import Qt
-- Utility Functions --

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

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
New Conversion Functions for Temperature

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
-- Text Category --

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())

def remove_duplicates(text: str) -> str:
"""Remove duplicate words and empty lines from a string."""
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) -> dict:
"""Return a dictionary of safe globals 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,
"lb": kilograms_to_pounds,
"kg": pounds_to_kilograms,
"C": kelvin_to_celsius,
"K": celsius_to_kelvin,
"F": celsius_to_fahrenheit,
"CF": fahrenheit_to_celsius,
"capitalize": capitalize_sentence,
"duplicates": remove_duplicates,
}
safe_globals.update({
func: (lambda f: (lambda x, f=f: convert_angle(getattr(math, f), x, use_degrees)))(func)
for func in trig_funcs.union({'asin', 'acos'})
})
return safe_globals

def preprocess_text_functions(expression: str) -> str:
"""Preprocess text functions to ensure proper quoting of arguments."""
def add_quotes(match):
func, args = match.groups()
return f'{func}("{args}")' if func in ['capitalize', 'duplicates'] else match.group(0)
return re.sub(r'\b(capitalize|duplicates)(([^)]+))', add_quotes, expression)

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

def safe_evaluate(expression: str, safe_globals: dict) -> Union[float, str]:
"""Safely evaluate the expression and format the result."""
try:
result = eval(expression, {"builtins": None}, safe_globals)
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}"

def evaluate_expression(expression: str, use_degrees: bool = False) -> Union[float, str]:
"""Safely evaluate a mathematical expression considering degree mode."""
safe_globals = get_safe_globals(use_degrees)
expression = expression.replace("^", "**")
expression = preprocess_text_functions(expression)
error = validate_inverse_trig(expression, safe_globals)
return error or safe_evaluate(expression, safe_globals)
-- GUI --

class CalculatorGUI(QMainWindow):
"""PySide6-based Calculator with Degrees/Radians toggle and history."""

def __init__(self):
    super().__init__()
    self.use_degrees = False
    self.setup_window()
    self.create_widgets()
    self.layout_widgets()

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

def create_widgets(self) -> None:
    """Initialize all GUI components."""
    font = QFont()
    font.setPointSize(12)
    font.setFamily('Literata')
    
    self.entry = QLineEdit()
    self.entry.setFont(font)
    self.entry.returnPressed.connect(self.calculate)
    self.entry.setPlaceholderText('Enter expression')

    self.history_text = QTextEdit()
    self.history_text.setFont(font)
    self.history_text.setReadOnly(True)

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

    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"]
    }
    self.function_frame = QFrame()
    self.create_function_buttons(font)

def create_function_buttons(self, font: QFont) -> None:
    """Create buttons for inserting functions into the entry."""
    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, False))
                layout.addWidget(button, (i // 3) + 1, starting_col + (i % 3))
        
        elif category == "Settings":
            self.mode_button = QPushButton("Radians")
            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":
            for idx, func in enumerate(buttons):
                if func == "lb":
                    display_text = "lb(kg)"
                elif func == "kg":
                    display_text = "kg(lb)"
                elif func == "K":
                    display_text = "K(°C)"
                elif func == "C":
                    display_text = "°C(K)"
                elif func == "F":
                    display_text = "F(°C)"
                elif func == "CF":
                    display_text = "°C(F)"
                else:
                    display_text = func
                button = QPushButton(display_text)
                button.setFont(font)
                button.clicked.connect(lambda _, f=func: self.insert_function(f, False))
                row = 1 + (idx // col_span)
                col = starting_col + (idx % col_span)
                layout.addWidget(button, row, col)
        
        else:
            num_buttons = len(buttons)
            num_rows = math.ceil(num_buttons / col_span)

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

            for extra in range(col_span * num_rows - num_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 widgets within the 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 toggle_mode(self) -> None:
    """Switch between Degrees and Radians modes."""
    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) -> None:
    """Insert function or constant text into the expression entry."""
    current_text = self.entry.text()
    cursor_position = self.entry.cursorPosition()
    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.entry.setText(new_text)
    self.entry.setCursorPosition(new_cursor_position)
    self.entry.setFocus()

def calculate(self) -> None:
    """Evaluate the expression and update history."""
    expression = self.entry.text().strip()
    if expression:
        result = evaluate_expression(expression, use_degrees=self.use_degrees)
        self.display_result(expression, result)
        self.entry.clear()

def display_result(self, expression: str, result: Union[float, str]) -> None:
    """Append the calculation to the history log."""
    mode = "D" if self.use_degrees else "R"
    self.history_text.append(f"[{mode}] {expression} = {result}")
    self.history_text.verticalScrollBar().setValue(
        self.history_text.verticalScrollBar().maximum()
    )

def main() -> None:
"""Run the Calculator application."""
app = QApplication([])
calculator = CalculatorGUI()
calculator.show()
app.exec()

if name == "main":
main()