Identify code logic errors in this python code "import sys
import csv
import traceback
from datetime import datetime
from PySide6.QtWidgets import (
    QApplication, QMainWindow, QWidget, QTableWidget, QTableWidgetItem,
    QVBoxLayout, QHBoxLayout, QSplitter, QFileDialog, QDialog,
    QLabel, QLineEdit, QPushButton, QMessageBox, QComboBox, QToolBar,
    QMenu, QInputDialog
)
from PySide6.QtGui import QIcon, QAction, QContextMenuEvent, QCursor, QDragEnterEvent, QDropEvent, QDragMoveEvent, QUndoStack, QUndoCommand
from PySide6.QtCore import Qt, Slot, Signal, QSize, QMimeData

class VariableDialog(QDialog):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setWindowTitle("Variable Properties")
        self.layout = QVBoxLayout()

        self.name_label = QLabel("Variable Name:")
        self.name_edit = QLineEdit()
        self.type_label = QLabel("Data Type:")
        self.type_combo = QComboBox()
        self.type_combo.addItems(["String", "Integer", "Float", "Date", "Boolean"])

        self.ok_button = QPushButton("OK")
        self.cancel_button = QPushButton("Cancel")

        self.layout.addWidget(self.name_label)
        self.layout.addWidget(self.name_edit)
        self.layout.addWidget(self.type_label)
        self.layout.addWidget(self.type_combo)

        self.button_layout = QHBoxLayout()
        self.button_layout.addWidget(self.ok_button)
        self.button_layout.addWidget(self.cancel_button)

        self.layout.addLayout(self.button_layout)
        self.setLayout(self.layout)

        self.ok_button.clicked.connect(self.accept)
        self.cancel_button.clicked.connect(self.reject)

    def get_data(self):
        return self.name_edit.text(), self.type_combo.currentText()

class VariableView(QTableWidget):
    variableAdded = Signal(str, str)
    variableEdited = Signal(int, str, str)
    variableDeleted = Signal(int)
    variableReordered = Signal(int, int)

    def __init__(self, parent=None):
        super().__init__(0, 2, parent)
        self.setHorizontalHeaderLabels(["Variable Name", "Data Type"])
        self.verticalHeader().setVisible(False)
        self.cellDoubleClicked.connect(self.edit_variable)
        self.setContextMenuPolicy(Qt.CustomContextMenu)
        self.customContextMenuRequested.connect(self.show_context_menu)
        self.setDragEnabled(True)
        self.setAcceptDrops(True)
        self.viewport().setAcceptDrops(True)
        self.setDragDropOverwriteMode(False)
        self.setDropIndicatorShown(True)
        self.setSelectionBehavior(QTableWidget.SelectRows)
        self.setSelectionMode(QTableWidget.ExtendedSelection)

    def add_variable(self, name, data_type):
        row = self.rowCount()
        self.insertRow(row)
        self.setItem(row, 0, QTableWidgetItem(name))
        self.setItem(row, 1, QTableWidgetItem(data_type))
        self.resizeColumnsToContents()
        self.resizeRowsToContents()
        self.variableAdded.emit(name, data_type)

    def edit_variable(self, row, column):
        name_item = self.item(row, 0)
        type_item = self.item(row, 1)

        dialog = VariableDialog(self)
        dialog.name_edit.setText(name_item.text())
        dialog.type_combo.setCurrentText(type_item.text())

        if dialog.exec():
            name, data_type = dialog.get_data()
            if name.strip() == "":
                QMessageBox.warning(self, "Invalid Name", "Variable name cannot be empty.")
                return

            for i in range(self.rowCount()):
                if i != row and self.item(i, 0).text() == name:
                    QMessageBox.warning(self, "Duplicate Name", "Variable name must be unique.")
                    return

            name_item.setText(name)
            type_item.setText(data_type)
            self.variableEdited.emit(row, name, data_type)
            self.resizeColumnsToContents()
            self.resizeRowsToContents()

    def delete_variable(self, row):
        self.removeRow(row)
        self.variableDeleted.emit(row)

    def show_context_menu(self, pos):
        menu = QMenu()
        add_action = menu.addAction("Add Variable")
        edit_action = menu.addAction("Edit Variable")
        delete_action = menu.addAction("Delete Variable")

        action = menu.exec_(self.viewport().mapToGlobal(pos))

        if action == add_action:
            self.add_variable()
        elif action == edit_action:
            self.edit_variable(self.currentRow(), 0)
        elif action == delete_action:
            self.delete_variable(self.currentRow())

    def dragEnterEvent(self, event):
        if event.mimeData().hasFormat("application/x-qabstractitemmodeldatalist"):
            event.accept()
        else:
            event.ignore()

    def dragMoveEvent(self, event):
        if event.mimeData().hasFormat("application/x-qabstractitemmodeldatalist"):
            event.setDropAction(Qt.MoveAction)
            event.accept()
        else:
            event.ignore()

    def dropEvent(self, event):
        if event.mimeData().hasFormat("application/x-qabstractitemmodeldatalist"):
            data = event.mimeData()
            source_row = data.data("application/x-qabstractitemmodeldatalist")[0]
            target_row = self.indexAt(event.pos()).row()

            if source_row != target_row:
                self.moveRow(source_row, target_row)
                self.variableReordered.emit(source_row, target_row)

            event.setDropAction(Qt.MoveAction)
            event.accept()
        else:
            event.ignore()

class DataTable(QTableWidget):
    def __init__(self, parent=None):
        super().__init__(0, 0, parent)
        self.setContextMenuPolicy(Qt.CustomContextMenu)
        self.customContextMenuRequested.connect(self.show_context_menu)
        self.setDragEnabled(True)
        self.setAcceptDrops(True)
        self.viewport().setAcceptDrops(True)
        self.setDragDropOverwriteMode(False)
        self.setDropIndicatorShown(True)
        self.setSelectionBehavior(QTableWidget.SelectItems)

    def add_variable(self, name, data_type):
        col = self.columnCount()
        self.insertColumn(col)
        self.setHorizontalHeaderItem(col, QTableWidgetItem(name))
        self.adjust_data_to_type(col, data_type)
        self.resizeColumnsToContents()
        self.resizeRowsToContents()

    def delete_variable(self, col):
        self.removeColumn(col)
        self.resizeColumnsToContents()
        self.resizeRowsToContents()

    def update_column_type(self, col, data_type):
        self.adjust_data_to_type(col, data_type)
        self.resizeColumnsToContents()
        self.resizeRowsToContents()

    def adjust_data_to_type(self, col, data_type):
        for row in range(self.rowCount()):
            item = self.item(row, col)
            if item is None:
                continue
            value = item.text()
            if data_type == "Integer":
                try:
                    int(value)
                except ValueError:
                    self.setItem(row, col, QTableWidgetItem(""))
            elif data_type == "Float":
                try:
                    float(value)
                except ValueError:
                    self.setItem(row, col, QTableWidgetItem(""))
            elif data_type == "Boolean":
                item.setText("True" if value.lower() in ("true", "1", "yes") else "False")
            elif data_type == "Date":
                try:
                    datetime.strptime(value, "%Y-%m-%d")
                except ValueError:
                    self.setItem(row, col, QTableWidgetItem(""))

    def show_context_menu(self, pos):
        menu = QMenu()
        insert_row_action = menu.addAction("Insert Row")
        delete_row_action = menu.addAction("Delete Row")
        insert_column_action = menu.addAction("Insert Column")
        delete_column_action = menu.addAction("Delete Column")

        action = menu.exec_(self.viewport().mapToGlobal(pos))

        if action == insert_row_action:
            self.insertRow(self.currentRow())
        elif action == delete_row_action:
            self.removeRow(self.currentRow())
        elif action == insert_column_action:
            self.insertColumn(self.currentColumn())
        elif action == delete_column_action:
            self.removeColumn(self.currentColumn())

    def dragEnterEvent(self, event):
        if event.mimeData().hasFormat("application/x-qabstractitemmodeldatalist"):
            event.accept()
        else:
            event.ignore()

    def dragMoveEvent(self, event):
        if event.mimeData().hasFormat("application/x-qabstractitemmodeldatalist"):
            event.setDropAction(Qt.MoveAction)
            event.accept()
        else:
            event.ignore()

    def dropEvent(self, event):
        if event.mimeData().hasFormat("application/x-qabstractitemmodeldatalist"):
            data = event.mimeData()
            source_row = data.data("application/x-qabstractitemmodeldatalist")[0]
            target_row = self.indexAt(event.pos()).row()

            if source_row != target_row:
                self.insertRow(target_row)
                for col in range(self.columnCount()):
                    item = self.takeItem(source_row, col)
                    self.setItem(target_row, col, item)
                self.removeRow(source_row)

            event.setDropAction(Qt.MoveAction)
            event.accept()
        else:
            event.ignore()

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Data Entry Editor")

        self.variable_view = VariableView()
        self.data_table = DataTable()

        splitter = QSplitter(Qt.Horizontal)
        splitter.addWidget(self.variable_view)
        splitter.addWidget(self.data_table)

        main_widget = QWidget()
        main_layout = QVBoxLayout()
        main_layout.addWidget(splitter)
        main_widget.setLayout(main_layout)
        self.setCentralWidget(main_widget)

        self.create_ribbon()
        self.create_data_manager()
        self.create_undo_stack()

        # Connect signals
        self.variable_view.variableAdded.connect(self.data_table.add_variable)
        self.variable_view.variableDeleted.connect(self.data_table.delete_variable)
        self.variable_view.variableEdited.connect(self.on_variable_edited)
        self.variable_view.variableReordered.connect(self.on_variable_reordered)

    def create_ribbon(self):
        toolbar = QToolBar("Ribbon")
        toolbar.setIconSize(QSize(16, 16))
        self.addToolBar(toolbar)

        new_act = QAction(QIcon.fromTheme("document-new"), "&New", self)
        new_act.triggered.connect(self.new_file)
        toolbar.addAction(new_act)

        open_act = QAction(QIcon.fromTheme("document-open"), "&Open", self)
        open_act.triggered.connect(self.open_file)
        toolbar.addAction(open_act)

        save_act = QAction(QIcon.fromTheme("document-save"), "&Save", self)
        save_act.triggered.connect(self.save_file)
        toolbar.addAction(save_act)

        toolbar.addSeparator()

        add_var_act = QAction(QIcon.fromTheme("list-add"), "Add &Variable", self)
        add_var_act.triggered.connect(self.add_variable)
        toolbar.addAction(add_var_act)

        del_var_act = QAction(QIcon.fromTheme("list-remove"), "Delete Variable", self)
        del_var_act.triggered.connect(self.delete_variable)
        toolbar.addAction(del_var_act)

    def create_data_manager(self):
        self.data_manager = DataManager(self)

    def create_undo_stack(self):
        self.undo_stack = QUndoStack(self)

    @Slot()
    def new_file(self):
        self.variable_view.setRowCount(0)
        self.data_table.setColumnCount(0)
        self.data_table.setRowCount(0)
        self.undo_stack.clear()

    @Slot()
    def open_file(self):
        file_name, _ = QFileDialog.getOpenFileName(self, "Open CSV", "", "CSV Files (.csv)")
        if file_name:
            try:
                self.load_csv(file_name)
            except Exception as e:
                QMessageBox.critical(self, "Error", f"Failed to open file: {e}")
                traceback.print_exc()

    @Slot()
    def save_file(self):
        file_name, _ = QFileDialog.getSaveFileName(self, "Save CSV", "", "CSV Files (.csv)")
        if file_name:
            try:
                self.save_csv(file_name)
            except Exception as e:
                QMessageBox.critical(self, "Error", f"Failed to save file: {e}")
                traceback.print_exc()

    @Slot()
    def add_variable(self):
        dialog = VariableDialog(self)
        if dialog.exec():
            name, data_type = dialog.get_data()
            if name.strip() == "":
                QMessageBox.warning(self, "Invalid Name", "Variable name cannot be empty.")
                return

            for row in range(self.variable_view.rowCount()):
                if self.variable_view.item(row, 0).text() == name:
                    QMessageBox.warning(self, "Duplicate Name", "Variable name must be unique.")
                    return

            self.undo_stack.push(AddVariableCommand(self.variable_view, name, data_type))

    @Slot()
    def delete_variable(self):
        selected = self.variable_view.selectedItems()
        if selected:
            row = self.variable_view.row(selected[0])
            self.undo_stack.push(DeleteVariableCommand(self.variable_view, row))
        else:
            QMessageBox.warning(self, "No Selection", "Please select a variable to delete.")

    @Slot()
    def on_variable_edited(self, row, name, data_type):
        self.data_table.setHorizontalHeaderItem(row, QTableWidgetItem(name))
        self.data_table.update_column_type(row, data_type)
        self.undo_stack.push(EditVariableCommand(self.variable_view, row, name, data_type))

    @Slot()
    def on_variable_reordered(self, source_row, target_row):
        self.data_table.moveColumn(source_row, target_row)
        self.undo_stack.push(ReorderVariableCommand(self.variable_view, source_row, target_row))

    def load_csv(self, file_name):
        with open(file_name, "r", encoding="utf-8") as file:
            reader = csv.reader(file)
            header = next(reader)  # Read the header row

            # Clear existing data
            self.new_file()

            # Add variables
            for i, col_name in enumerate(header):
                self.variable_view.add_variable(col_name, "String")

            # Add data rows
            for row in reader:
                self.data_table.insertRow(self.data_table.rowCount())
                for col, value in enumerate(row):
                    item = QTableWidgetItem(value)
                    self.data_table.setItem(self.data_table.rowCount() - 1, col, item)

    def save_csv(self, file_name):
        with open(file_name, "w", newline="", encoding="utf-8") as file:
            writer = csv.writer(file)

            # Write header row
            header = []
            for col in range(self.data_table.columnCount()):
                header.append(self.data_table.horizontalHeaderItem(col).text())
            writer.writerow(header)

            # Write data rows
            for row in range(self.data_table.rowCount()):
                row_data = []
                for col in range(self.data_table.columnCount()):
                    item = self.data_table.item(row, col)
                    row_data.append(item.text() if item else "")
                writer.writerow(row_data)

class DataManager:
    def __init__(self, parent=None):
        self.parent = parent

    def read_csv(self, file_path):
        try:
            with open(file_path, "r", encoding="utf-8") as file:
                reader = csv.reader(file)
                data = list(reader)
            return data
        except Exception as e:
            QMessageBox.critical(self.parent, "Error", f"Failed to read file: {e}")
            raise

    def write_csv(self, file_path, data):
        try:
            with open(file_path, "w", newline="", encoding="utf-8") as file:
                writer = csv.writer(file)
                writer.writerows(data)
        except Exception as e:
            QMessageBox.critical(self.parent, "Error", f"Failed to write file: {e}")
            raise

class AddVariableCommand(QUndoCommand):
    def __init__(self, variable_view, name, data_type):
        super().__init__()
        self.variable_view = variable_view
        self.name = name
        self.data_type = data_type

    def redo(self):
        self.variable_view.add_variable(self.name, self.data_type)

    def undo(self):
        row = self.variable_view.findItems(self.name, Qt.MatchExactly)[0].row()
        self.variable_view.delete_variable(row)

class DeleteVariableCommand(QUndoCommand):
    def __init__(self, variable_view, row):
        super().__init__()
        self.variable_view = variable_view
        self.row = row
        self.name = variable_view.item(row, 0).text()
        self.data_type = variable_view.item(row, 1).text()

    def redo(self):
        self.variable_view.delete_variable(self.row)

    def undo(self):
        self.variable_view.add_variable(self.name, self.data_type)

class EditVariableCommand(QUndoCommand):
    def __init__(self, variable_view, row, new_name, new_data_type):
        super().__init__()
        self.variable_view = variable_view
        self.row = row
        self.old_name = variable_view.item(row, 0).text()
        self.old_data_type = variable_view.item(row, 1).text()
        self.new_name = new_name
        self.new_data_type = new_data_type

    def redo(self):
        self.variable_view.edit_variable(self.row, 0)
        self.variable_view.item(self.row, 0).setText(self.new_name)
        self.variable_view.item(self.row, 1).setText(self.new_data_type)

    def undo(self):
        self.variable_view.item(self.row, 0).setText(self.old_name)
        self.variable_view.item(self.row, 1).setText(self.old_data_type)

class ReorderVariableCommand(QUndoCommand):
    def __init__(self, variable_view, source_row, target_row):
        super().__init__()
        self.variable_view = variable_view
        self.source_row = source_row
        self.target_row = target_row

    def redo(self):
        self.variable_view.variableReordered.emit(self.source_row, self.target_row)

    def undo(self):
        self.variable_view.variableReordered.emit(self.target_row, self.source_row)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec())"