#!/usr/bin/env python3

from PyQt6.QtCore import Qt, QEvent, QObject, QVariant, QAbstractTableModel
from PyQt6.QtWidgets import (
    QApplication,
    QMainWindow,
    QMessageBox,
    QPlainTextEdit,
    QStyledItemDelegate,
    QTableView,
)

from PyQt6.QtGui import QKeyEvent

from typing import cast


class EscapeDelegate(QStyledItemDelegate):
    def __init__(self, parent=None):
        super().__init__(parent)

    def createEditor(self, parent, option, index):
        return QPlainTextEdit(parent)

    def eventFilter(self, editor: QObject, event: QEvent):
        """By default, QPlainTextEdit doesn't handle enter or return"""

        if event.type() == QEvent.Type.KeyPress:
            key_event = cast(QKeyEvent, event)
            print(key_event.key())
            if key_event.key() == Qt.Key.Key_Return:
                if key_event.modifiers() == (Qt.KeyboardModifier.ControlModifier):
                    print("save data")
                    self.commitData.emit(editor)
                    self.closeEditor.emit(editor)
                    return True
            elif key_event.key() == Qt.Key.Key_Escape:
                discard_edits = QMessageBox.question(
                    self.parent(), "Abandon edit", "Discard changes?"
                )
                if discard_edits == QMessageBox.StandardButton.Yes:
                    print("abandon edit")
                    self.closeEditor.emit(editor)
                    return True
        return False


class MyTableWidget(QTableView):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setItemDelegate(EscapeDelegate(self))
        self.setModel(MyModel())


class MyModel(QAbstractTableModel):

    def columnCount(self, index):
        return 2

    def rowCount(self, index):
        return 2

    def data(self, index, role):
        if not index.isValid() or not (0 <= index.row() < 2):
            return QVariant()

        row = index.row()
        column = index.column()
        if role == Qt.ItemDataRole.DisplayRole:
            return QVariant(f"Row {row}, Col {column}")
        return QVariant()

    def flags(self, index):
        return Qt.ItemFlag.ItemIsEnabled | Qt.ItemFlag.ItemIsSelectable | Qt.ItemFlag.ItemIsEditable


class MainWindow(QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.table_widget = MyTableWidget(self)
        self.setCentralWidget(self.table_widget)

        self.table_widget.resizeColumnsToContents()
        self.table_widget.resizeRowsToContents()


if __name__ == "__main__":
    app = QApplication([])
    window = MainWindow()
    window.show()
    app.exec()
