Here is my python code. The stylesheet needs to be reworked, it is not balanced properly now (for example black text on dark background etc). Also, the Paramters are overlaping onto the Control section, that shall be fixed. " import sys
from PySide6.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout,
                               QHBoxLayout, QTableWidget, QTableWidgetItem, QLabel, QSpinBox,
                               QPushButton, QTabWidget, QGroupBox, QMenuBar, QMenu, QFileDialog,
                               QMessageBox, QDockWidget, QSplitter, QComboBox, QFrame, QStackedWidget,
                               QLineEdit, QFormLayout, QListWidget, QListWidgetItem, QCheckBox, QHeaderView,
                               QToolBar, QStatusBar, QStyle, QInputDialog, QDoubleSpinBox)
from PySide6.QtCore import Qt, QPropertyAnimation, QEasingCurve, Signal, QObject, QSize
from PySide6.QtGui import QFont, QColor, QPalette
import pandas as pd
import numpy as np


class ModernStyle:
    """Class to handle application-wide styling"""

    PRIMARY_COLOR = "#32A67A"  # Green
    SECONDARY_COLOR = "#A63232"  # Red
    BACKGROUND_COLOR = "#252525"  # Dark Gray
    TEXT_COLOR = "#D4D4D4"  # Light Gray
    ACCENT_COLOR = "#A63232"  # Red

    @staticmethod
    def get_stylesheet():
        return f"""
        QMainWindow {{
            background-color: {ModernStyle.BACKGROUND_COLOR};
            color: {ModernStyle.TEXT_COLOR};
        }}

        QTableWidget {{
            background-color: {ModernStyle.BACKGROUND_COLOR};
            alternate-background-color: #353535;
            selection-background-color: {ModernStyle.PRIMARY_COLOR};
            selection-color: white;
            border: 1px solid #444;
            border-radius: 4px;
            color: {ModernStyle.TEXT_COLOR};
        }}

        QTableWidget::item {{
            padding: 5px;
        }}

        QPushButton {{
            background-color: {ModernStyle.PRIMARY_COLOR};
            color: white;
            border: none;
            padding: 8px 15px;
            border-radius: 4px;
            min-width: 80px;
        }}

        QPushButton:hover {{
            background-color: #288A65;
        }}

        QPushButton:pressed {{
            background-color: #1E6B4F;
        }}

        QGroupBox {{
            font-weight: bold;
            border: 1px solid #444;
            border-radius: 4px;
            margin-top: 1ex;
            padding: 10px;
            background-color: {ModernStyle.BACKGROUND_COLOR};
            color: {ModernStyle.TEXT_COLOR};
        }}

        QGroupBox::title {{
            subcontrol-origin: margin;
            left: 10px;
            padding: 0 3px;
        }}

        QComboBox {{
            padding: 5px;
            border: 1px solid #444;
            border-radius: 4px;
            min-width: 100px;
            background-color: {ModernStyle.BACKGROUND_COLOR};
            color: {ModernStyle.TEXT_COLOR};
        }}

        QLineEdit {{
            padding: 5px;
            border: 1px solid #444;
            border-radius: 4px;
            background-color: {ModernStyle.BACKGROUND_COLOR};
            color: {ModernStyle.TEXT_COLOR};
        }}

        QTabWidget::pane {{
            border: 1px solid #444;
            border-radius: 4px;
        }}

        QTabBar::tab {{
            background-color: {ModernStyle.BACKGROUND_COLOR};
            padding: 8px 15px;
            margin-right: 2px;
            color: {ModernStyle.TEXT_COLOR};
        }}

        QTabBar::tab:selected {{
            background-color: {ModernStyle.PRIMARY_COLOR};
            color: white;
        }}
        """

    @staticmethod
    def get_compact_stylesheet():
        return f"""
        QPushButton {{
            padding: 3px 8px;
            min-width: 60px;
            max-height: 24px;
        }}

        QGroupBox {{
            padding: 5px;
            margin-top: 0.5ex;
        }}

        QComboBox {{
            padding: 3px;
            min-width: 80px;
            max-height: 24px;
        }}

        QLineEdit {{
            padding: 3px;
            max-height: 24px;
        }}
        """


class VariableViewer(QWidget):
    variableChanged = Signal(int, str, str)

    def __init__(self, data_table):
        super().__init__()
        self.data_table = data_table
        self.setup_ui()

    def setup_ui(self):
        layout = QVBoxLayout(self)
        layout.setSpacing(5)  # Reduce spacing
        layout.setContentsMargins(5, 5, 5, 5)

        # Variable table group
        variable_table_group = QGroupBox("Variables")
        variable_table_layout = QVBoxLayout()
        variable_table_layout.setSpacing(3)
        variable_table_layout.setContentsMargins(5, 5, 5, 5)

        self.variable_table = QTableWidget()
        self.variable_table.setColumnCount(2)
        self.variable_table.setHorizontalHeaderLabels(['Variable Name', 'Data Type'])
        self.variable_table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        self.variable_table.setEditTriggers(QTableWidget.NoEditTriggers)  # Prevent direct editing

        variable_table_layout.addWidget(self.variable_table)
        variable_table_group.setLayout(variable_table_layout)
        layout.addWidget(variable_table_group)

        # Connect signals
        self.variable_table.cellDoubleClicked.connect(self.edit_variable_name)
        self.variable_table.currentCellChanged.connect(self.update_variable_details)

        # Style the table
        self.variable_table.setAlternatingRowColors(True)
        self.variable_table.setStyleSheet("""
            QTableWidget {
                border: 1px solid #444;
                border-radius: 4px;
            }
        """)

    def load_variables(self):
        self.variable_table.setRowCount(0)
        for column in range(self.data_table.columnCount()):
            row_position = self.variable_table.rowCount()
            self.variable_table.insertRow(row_position)

            header_item = self.data_table.horizontalHeaderItem(column)
            var_name = header_item.text() if header_item else f"Variable {column}"

            # Variable Name
            name_item = QTableWidgetItem(var_name)
            self.variable_table.setItem(row_position, 0, name_item)

            # Data Type with ComboBox
            type_combo = QComboBox()
            current_type = self.detect_column_type(column)
            type_combo.addItems(["Numeric", "String", "Date", "Boolean"])
            if current_type in ["Numeric", "String", "Date", "Boolean"]:
                type_combo.setCurrentText(current_type)
            else:
                type_combo.setCurrentText("String")
            type_combo.currentTextChanged.connect(lambda new_type, row=row_position: self.on_type_changed(row, new_type))
            self.variable_table.setCellWidget(row_position, 1, type_combo)

    def detect_column_type(self, column):
        # Simple type detection based on pandas data types
        try:
            # Access the data as pandas Series
            column_data = []
            for i in range(self.data_table.rowCount()):
                item = self.data_table.item(i, column)
                if item is not None:
                    column_data.append(item.text())
            series = pd.Series(column_data)
            if pd.api.types.is_numeric_dtype(pd.to_numeric(series, errors='coerce')):
                return "Numeric"
            else:
                return "String"
        except:
            return "String"

    def update_variable_details(self, currentRow, currentColumn, previousRow, previousColumn):
        pass  # Placeholder for future enhancements

    def edit_variable_name(self, row, column):
        if column == 0:  # Only allow editing of Variable Name
            current_name = self.variable_table.item(row, column).text()
            new_name, ok = QInputDialog.getText(self, "Edit Variable Name", "New Name:", text=current_name)
            if ok and new_name:
                self.variable_table.item(row, column).setText(new_name)
                self.data_table.setHorizontalHeaderItem(row, QTableWidgetItem(new_name))
                self.variableChanged.emit(row, new_name, self.get_variable_type(row))

    def on_type_changed(self, row, new_type):
        variable_name = self.variable_table.item(row, 0).text()
        old_type = self.get_variable_type(row)
        if old_type != new_type:
            success, message = self.convert_column_type(row, new_type)
            if success:
                self.variableChanged.emit(row, variable_name, new_type)
                self.parent().statusBar().showMessage(f"Variable '{variable_name}' converted to {new_type}", 2000)
            else:
                # Revert the ComboBox to the old type
                combo = self.variable_table.cellWidget(row, 1)
                combo.blockSignals(True)
                combo.setCurrentText(old_type)
                combo.blockSignals(False)
                QMessageBox.critical(self, "Conversion Error", f"Failed to convert '{variable_name}' to {new_type}.\nError: {message}")

    def get_variable_type(self, row):
        combo = self.variable_table.cellWidget(row, 1)
        return combo.currentText() if combo else "String"

    def convert_column_type(self, row, new_type):
        column = row  # Assuming each row in VariableViewer corresponds to a column in data_table
        try:
            column_data = []
            for i in range(self.data_table.rowCount()):
                item = self.data_table.item(i, column)
                column_data.append(item.text() if item else "")

            if new_type == "Numeric":
                converted_data = pd.to_numeric(column_data, errors='coerce')
                if converted_data.isnull().any():
                    raise ValueError("Some values could not be converted to Numeric.")
            elif new_type == "String":
                converted_data = [str(item) for item in column_data]
            elif new_type == "Date":
                converted_data = pd.to_datetime(column_data, errors='coerce')
                if converted_data.isnull().all():
                    raise ValueError("All values could not be converted to Date.")
                converted_data = converted_data.dt.strftime('%Y-%m-%d %H:%M:%S').fillna('')
            elif new_type == "Boolean":
                # Simple conversion: non-empty strings to True, empty to False
                converted_data = [bool(item) for item in column_data]
            else:
                return False, "Unsupported data type."

            # Update the table with converted data
            for i, value in enumerate(converted_data):
                self.data_table.setItem(i, column, QTableWidgetItem(str(value)))

            return True, ""
        except Exception as e:
            return False, str(e)


class TimeSeriesApp(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Time Series Analysis Tool")
        self.resize(1200, 800)

        # Set the application style
        self.setStyleSheet(ModernStyle.get_stylesheet() + ModernStyle.get_compact_stylesheet())

        self.data = pd.DataFrame()
        self.setup_ui()

    def setup_ui(self):
        self.create_menu_bar()

        central_widget = QWidget()
        self.setCentralWidget(central_widget)
        main_layout = QVBoxLayout(central_widget)

        tab_widget = QTabWidget()
        main_layout.addWidget(tab_widget)

        # Data View Tab
        data_tab = self.setup_data_tab()
        tab_widget.addTab(data_tab, "Data Editor")

        # Analysis Tab
        analysis_tab = self.setup_analysis_tab()
        tab_widget.addTab(analysis_tab, "Analysis")

        # Add a toolbar
        toolbar = self.addToolBar("Main Toolbar")
        toolbar.setMovable(False)

        # Add toolbar actions with icons
        new_action = toolbar.addAction("New")
        new_action.setIcon(self.style().standardIcon(QStyle.SP_FileIcon))
        new_action.triggered.connect(self.new_file)

        open_action = toolbar.addAction("Open")
        open_action.setIcon(self.style().standardIcon(QStyle.SP_DialogOpenButton))
        open_action.triggered.connect(self.open_file)

        save_action = toolbar.addAction("Save")
        save_action.setIcon(self.style().standardIcon(QStyle.SP_DialogSaveButton))
        save_action.triggered.connect(self.save_file)

        # Add status bar
        self.statusBar().showMessage("Ready")

        # Enhance the tab widget
        tab_widget.setDocumentMode(True)
        tab_widget.setTabPosition(QTabWidget.North)

        # Add icons to tabs
        tab_widget.setTabIcon(0, self.style().standardIcon(QStyle.SP_FileDialogDetailedView))
        tab_widget.setTabIcon(1, self.style().standardIcon(QStyle.SP_CommandLink))

    def create_menu_bar(self):
        menubar = self.menuBar()

        file_menu = menubar.addMenu("File")
        new_action = file_menu.addAction("New")
        new_action.triggered.connect(self.new_file)
        open_action = file_menu.addAction("Open")
        open_action.triggered.connect(self.open_file)
        save_action = file_menu.addAction("Save")
        save_action.triggered.connect(self.save_file)
        file_menu.addSeparator()
        exit_action = file_menu.addAction("Exit")
        exit_action.triggered.connect(self.close)

        edit_menu = menubar.addMenu("Edit")
        edit_menu.addAction("Copy")
        edit_menu.addAction("Paste")
        edit_menu.addAction("Clear All")

        help_menu = menubar.addMenu("Help")
        help_menu.addAction("Documentation")
        help_menu.addAction("About")

    def setup_data_tab(self):
        data_tab = QWidget()
        data_layout = QVBoxLayout(data_tab)
        data_layout.setSpacing(5)
        data_layout.setContentsMargins(5, 5, 5, 5)

        # Toolbar for data manipulation
        data_toolbar = QToolBar()
        data_toolbar.setIconSize(QSize(16, 16))  # Smaller icons

        add_row_btn = QPushButton()
        add_row_btn.setIcon(self.style().standardIcon(QStyle.SP_FileDialogNewFolder))
        add_row_btn.setToolTip("Add new row")
        add_row_btn.setMaximumWidth(30)
        add_row_btn.clicked.connect(self.add_row)

        delete_row_btn = QPushButton()
        delete_row_btn.setIcon(self.style().standardIcon(QStyle.SP_DialogCloseButton))
        delete_row_btn.setToolTip("Delete selected row")
        delete_row_btn.setMaximumWidth(30)
        delete_row_btn.clicked.connect(self.delete_row)

        add_column_btn = QPushButton()
        add_column_btn.setIcon(self.style().standardIcon(QStyle.SP_FileDialogNewFolder))
        add_column_btn.setToolTip("Add new column")
        add_column_btn.setMaximumWidth(30)
        add_column_btn.clicked.connect(self.add_column)

        delete_column_btn = QPushButton()
        delete_column_btn.setIcon(self.style().standardIcon(QStyle.SP_DialogCloseButton))
        delete_column_btn.setToolTip("Delete selected column")
        delete_column_btn.setMaximumWidth(30)
        delete_column_btn.clicked.connect(self.delete_column)

        # Add buttons to the toolbar
        data_toolbar.addWidget(add_row_btn)
        data_toolbar.addWidget(delete_row_btn)
        data_toolbar.addSeparator()
        data_toolbar.addWidget(add_column_btn)
        data_toolbar.addWidget(delete_column_btn)

        data_layout.addWidget(data_toolbar)

        # Main splitter with adjusted sizes
        self.data_table = QTableWidget()
        self.data_table.setColumnCount(3)
        self.data_table.setHorizontalHeaderLabels(['Time', 'Variable 1', 'Variable 2'])
        self.data_table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)

        self.variable_viewer = VariableViewer(self.data_table)
        self.variable_viewer.variableChanged.connect(self.update_variable)

        splitter = QSplitter(Qt.Horizontal)
        splitter.addWidget(self.data_table)
        splitter.addWidget(self.variable_viewer)
        splitter.setStretchFactor(0, 2)  # Data table gets more space
        splitter.setStretchFactor(1, 1)  # Variable viewer gets less space
        data_layout.addWidget(splitter)

        return data_tab

    def setup_analysis_tab(self):
        analysis_tab = QWidget()
        main_layout = QVBoxLayout(analysis_tab)
        main_layout.setSpacing(10)
        main_layout.setContentsMargins(10, 10, 10, 10)

        # Top Section: Method Selection
        method_group = QGroupBox("Analysis Method")
        method_layout = QHBoxLayout()
        method_label = QLabel("Select Method:")
        self.method_combo = QComboBox()
        self.method_combo.addItems([
            "Optimal Time Delay Analysis",
            "Optimal Embedding Dimension",
            "Convergent Cross Mapping"
        ])
        self.method_combo.currentIndexChanged.connect(self.update_method_parameters)

        method_layout.addWidget(method_label)
        method_layout.addWidget(self.method_combo)
        method_layout.addStretch()
        method_group.setLayout(method_layout)
        main_layout.addWidget(method_group)

        # Middle Section: Parameters and Controls
        params_results_layout = QHBoxLayout()

        # Parameters Panel
        params_group = QGroupBox("Parameters")
        params_layout = QVBoxLayout()
        self.params_stack = QStackedWidget()

        # Placeholder Widgets for Different Methods
        self.params_widgets = {}

        # Optimal Time Delay Analysis Parameters
        time_delay_widget = QWidget()
        time_delay_layout = QFormLayout()
        max_delay_spin = QSpinBox()
        max_delay_spin.setRange(1, 1000)
        max_delay_spin.setValue(100)
        step_size_spin = QSpinBox()
        step_size_spin.setRange(1, 100)
        step_size_spin.setValue(10)
        time_delay_layout.addRow("Max Time Delay:", max_delay_spin)
        time_delay_layout.addRow("Step Size:", step_size_spin)
        time_delay_widget.setLayout(time_delay_layout)

        # Optimal Embedding Dimension Parameters
        embedding_dim_widget = QWidget()
        embedding_dim_layout = QFormLayout()
        max_dim_spin = QSpinBox()
        max_dim_spin.setRange(1, 100)
        max_dim_spin.setValue(10)
        epsilon_spin = QDoubleSpinBox()
        epsilon_spin.setRange(0.0, 10.0)
        epsilon_spin.setSingleStep(0.1)
        epsilon_spin.setValue(1.0)
        embedding_dim_layout.addRow("Max Embedding Dimension:", max_dim_spin)
        embedding_dim_layout.addRow("Epsilon:", epsilon_spin)
        embedding_dim_widget.setLayout(embedding_dim_layout)

        # Convergent Cross Mapping Parameters
        ccm_widget = QWidget()
        ccm_layout = QFormLayout()
        library_size_spin = QSpinBox()
        library_size_spin.setRange(1, 1000)
        library_size_spin.setValue(500)
        num_trials_spin = QSpinBox()
        num_trials_spin.setRange(1, 100)
        num_trials_spin.setValue(10)
        ccm_layout.addRow("Library Size:", library_size_spin)
        ccm_layout.addRow("Number of Trials:", num_trials_spin)
        ccm_widget.setLayout(ccm_layout)

        # Add widgets to the stacked widget
        self.params_stack.addWidget(time_delay_widget)
        self.params_stack.addWidget(embedding_dim_widget)
        self.params_stack.addWidget(ccm_widget)

        self.params_widgets["Optimal Time Delay Analysis"] = time_delay_widget
        self.params_widgets["Optimal Embedding Dimension"] = embedding_dim_widget
        self.params_widgets["Convergent Cross Mapping"] = ccm_widget

        params_layout.addWidget(self.params_stack)
        params_group.setLayout(params_layout)
        params_results_layout.addWidget(params_group, 2)

        # Controls Panel (e.g., Run Analysis Button)
        controls_group = QGroupBox("Controls")
        controls_layout = QVBoxLayout()
        self.run_analysis_btn = QPushButton("Run Analysis")
        self.run_analysis_btn.setStyleSheet("padding: 8px 16px;")
        self.run_analysis_btn.clicked.connect(self.run_analysis)
        controls_layout.addStretch()
        controls_layout.addWidget(self.run_analysis_btn)
        controls_group.setLayout(controls_layout)
        params_results_layout.addWidget(controls_group, 1)

        main_layout.addLayout(params_results_layout)

        # Bottom Section: Plot and Results
        plot_results_layout = QHBoxLayout()

        # Plot Area
        plot_group = QGroupBox("Plot")
        plot_layout = QVBoxLayout()
        self.plot_label = QLabel("Plot will appear here")
        self.plot_label.setStyleSheet("background-color: #f0f0f0; border: 1px solid #ccc;")
        self.plot_label.setMinimumSize(400, 300)
        self.plot_label.setAlignment(Qt.AlignCenter)
        plot_layout.addWidget(self.plot_label)
        plot_group.setLayout(plot_layout)
        plot_results_layout.addWidget(plot_group, 3)

        # Results Table
        results_group = QGroupBox("Results")
        results_layout = QVBoxLayout()
        self.results_table = QTableWidget()
        self.results_table.setEditTriggers(QTableWidget.NoEditTriggers)
        self.results_table.setColumnCount(2)
        self.results_table.setHorizontalHeaderLabels(['Metric', 'Value'])
        self.results_table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        results_layout.addWidget(self.results_table)
        results_group.setLayout(results_layout)
        plot_results_layout.addWidget(results_group, 2)

        main_layout.addLayout(plot_results_layout)

        return analysis_tab

    def update_method_parameters(self):
        method = self.method_combo.currentText()
        index = self.method_combo.currentIndex()
        self.params_stack.setCurrentIndex(index)

    def run_analysis(self):
        method = self.method_combo.currentText()
        if method == "Optimal Time Delay Analysis":
            # Retrieve parameters
            max_delay = self.params_widgets[method].findChild(QSpinBox).value()
            step_size = self.params_widgets[method].findChildren(QSpinBox)[1].value()
            # TODO: Implement the analysis logic here
            self.display_results({"Max Delay": max_delay, "Step Size": step_size})
            self.update_plot("Sample Plot for Time Delay Analysis")
        elif method == "Optimal Embedding Dimension":
            # Retrieve parameters
            max_dim = self.params_widgets[method].findChild(QSpinBox).value()
            epsilon = self.params_widgets[method].findChild(QDoubleSpinBox).value()
            # TODO: Implement the analysis logic here
            self.display_results({"Max Dimension": max_dim, "Epsilon": epsilon})
            self.update_plot("Sample Plot for Embedding Dimension")
        elif method == "Convergent Cross Mapping":
            # Retrieve parameters
            library_size = self.params_widgets[method].findChild(QSpinBox).value()
            num_trials = self.params_widgets[method].findChildren(QSpinBox)[1].value()
            # TODO: Implement the analysis logic here
            self.display_results({"Library Size": library_size, "Number of Trials": num_trials})
            self.update_plot("Sample Plot for Convergent Cross Mapping")
        else:
            QMessageBox.warning(self, "Unknown Method", "Selected method is not recognized.")

    def display_results(self, results_dict):
        self.results_table.setRowCount(0)
        for key, value in results_dict.items():
            row_position = self.results_table.rowCount()
            self.results_table.insertRow(row_position)
            self.results_table.setItem(row_position, 0, QTableWidgetItem(str(key)))
            self.results_table.setItem(row_position, 1, QTableWidgetItem(str(value)))

    def update_plot(self, plot_description):
        self.plot_label.setText(plot_description)

    def update_variable(self, row, new_name, new_type):
        # Additional handling if needed when a variable is updated
        self.statusBar().showMessage(f"Variable '{new_name}' updated to type '{new_type}'", 2000)

    def add_row(self):
        current_rows = self.data_table.rowCount()
        self.data_table.insertRow(current_rows)
        self.variable_viewer.load_variables()
        self.statusBar().showMessage("Row added", 2000)

    def delete_row(self):
        current_row = self.data_table.currentRow()
        if current_row >= 0:
            reply = QMessageBox.question(
                self,
                'Delete Row',
                f"Are you sure you want to delete row {current_row + 1}?",
                QMessageBox.Yes | QMessageBox.No,
                QMessageBox.No
            )
            if reply == QMessageBox.Yes:
                self.data_table.removeRow(current_row)
                self.variable_viewer.load_variables()
                self.statusBar().showMessage("Row deleted", 2000)
        else:
            QMessageBox.warning(self, "No Selection", "No row selected to delete.")

    def add_column(self):
        current_cols = self.data_table.columnCount()
        self.data_table.setColumnCount(current_cols + 1)
        self.data_table.setHorizontalHeaderItem(
            current_cols,
            QTableWidgetItem(f"Variable {current_cols}")
        )
        self.variable_viewer.load_variables()
        self.statusBar().showMessage("Column added", 2000)

    def delete_column(self):
        current_column = self.data_table.currentColumn()
        if current_column >= 0:
            reply = QMessageBox.question(
                self,
                'Delete Column',
                f"Are you sure you want to delete column '{self.data_table.horizontalHeaderItem(current_column).text()}'?",
                QMessageBox.Yes | QMessageBox.No,
                QMessageBox.No
            )
            if reply == QMessageBox.Yes:
                self.data_table.removeColumn(current_column)
                self.variable_viewer.load_variables()
                self.statusBar().showMessage("Column deleted", 2000)
        else:
            QMessageBox.warning(self, "No Selection", "No column selected to delete.")

    def new_file(self):
        reply = QMessageBox.question(
            self,
            'New File',
            "Are you sure you want to create a new file? Unsaved changes will be lost.",
            QMessageBox.Yes | QMessageBox.No,
            QMessageBox.No
        )
        if reply == QMessageBox.Yes:
            self.data_table.clearContents()
            self.data_table.setRowCount(0)
            self.data_table.setColumnCount(0)
            self.variable_viewer.load_variables()
            self.statusBar().showMessage("New file created", 2000)

    def open_file(self):
        filename, _ = QFileDialog.getOpenFileName(
            self,
            "Open Data File",
            "",
            "CSV Files (*.csv);;All Files (*)"
        )
        if filename:
            try:
                data = pd.read_csv(filename)
                self.load_data_to_table(data)
                self.variable_viewer.load_variables()
                self.statusBar().showMessage(f"Loaded '{filename}'", 2000)
            except Exception as e:
                QMessageBox.critical(self, "Error", f"Could not open file: {str(e)}")

    def save_file(self):
        filename, _ = QFileDialog.getSaveFileName(
            self,
            "Save Data File",
            "",
            "CSV Files (*.csv);;All Files (*)"
        )
        if filename:
            try:
                data = self.get_data_from_table()
                data.to_csv(filename, index=False)
                self.statusBar().showMessage(f"Saved to '{filename}'", 2000)
            except Exception as e:
                QMessageBox.critical(self, "Error", f"Could not save file: {str(e)}")

    def load_data_to_table(self, data):
        self.data_table.setRowCount(len(data))
        self.data_table.setColumnCount(len(data.columns))
        self.data_table.setHorizontalHeaderLabels(data.columns)

        for i in range(len(data)):
            for j in range(len(data.columns)):
                self.data_table.setItem(
                    i, j,
                    QTableWidgetItem(str(data.iloc[i, j]))
                )

        self.variable_viewer.load_variables()

    def get_data_from_table(self):
        rows = self.data_table.rowCount()
        cols = self.data_table.columnCount()
        data = []

        headers = []
        for j in range(cols):
            header = self.data_table.horizontalHeaderItem(j)
            headers.append(header.text() if header else f"Column {j}")

        for i in range(rows):
            row_data = []
            for j in range(cols):
                item = self.data_table.item(i, j)
                row_data.append(item.text() if item else "")
            data.append(row_data)

        return pd.DataFrame(data, columns=headers)


def main():
    app = QApplication(sys.argv)

    # Set application-wide font
    font = QFont("Segoe UI", 9)
    app.setFont(font)

    # Enable high DPI scaling
    app.setAttribute(Qt.AA_EnableHighDpiScaling, True)
    app.setAttribute(Qt.AA_UseHighDpiPixmaps, True)

    window = TimeSeriesApp()
    window.show()
    sys.exit(app.exec())


if __name__ == "__main__":
    main()"