How to intercept key events when editing a cell in QTableWidget/QTableView

I need to intercept key events emitted when user is editing a cell in QTableWidget. Is there a simple way of doing this? I was thinking of installing event filter but I do not know how to get reference to the editor widget. Or do I need to somehow reimplement QItemDelegate? This seems as overkill to me and not sure how to do that, what exactly needs to be reimplemented. Or is there another way?

I need this because for example when the user presses left/right cursor key, I want to skip to the next cell on the left/right.

Upvotes: 0

Views: 1693

Answers (2)

Amol
Amol

Reputation: 56

Or alternatively you could use cellClicked signal like this:

  connect(ui->tbControl,SIGNAL(cellClicked(int,int)),this,SLOT(detectCellSelectionGraph(int,int)));

Upvotes: 0

It seems I have finally figured it out and it works exactly as I needed. Here is a solution in PySide (C++ is analogous) using overriding of QStyledItemDelegate. It seemed to me as overkill at first, but it was not that bad.

fromPySide import QtCore, QtGui

class LineEditDelegate(QtGui.QStyledItemDelegate):

    moveCurrentCellBy = QtCore.Signal(int, int)

    def __init__(self, parent=None):
        super(LineEditDelegate, self).__init__(parent)

    def createEditor(self, parent, option, index):
        self.editor = QtGui.QLineEdit(parent)
        self.editor.setFrame(False)
        self.editor.installEventFilter(self)
        return self.editor

    def setEditorData(self, editor, index):
        value = index.model().data(index, QtCore.Qt.EditRole)
        editor.setText(value)

    def setModelData(self, editor, model, index):
        value = editor.text()
        model.setData(index, value, QtCore.Qt.EditRole)

    def updateEditorGeometry(self, editor, option, index):
        editor.setGeometry(option.rect)

    def eventFilter(self, target, event):
        if target is self.editor:
            if event.type() == QtCore.QEvent.KeyPress:
                moveCell, row, column = False, 0, 0
                if event.key() in (QtCore.Qt.Key_Return, QtCore.Qt.Key_Enter, QtCore.Qt.Key_Down):
                    moveCell, row, column = True, 1, 0
                if event.key() in (QtCore.Qt.Key_Right, QtCore.Qt.Key_Tab):
                    moveCell, row, column = True, 0, 1
                if event.key() in (QtCore.Qt.Key_Left, QtCore.Qt.Key_Backtab):
                    moveCell, row, column = True, 0, -1
                if event.key() == QtCore.Qt.Key_Up:
                    moveCell, row, column = True, -1, 0
                if moveCell:
                    self.commitData.emit(self.editor)
                    self.closeEditor.emit(self.editor, QtGui.QAbstractItemDelegate.NoHint)
                    self.moveCurrentCellBy.emit(row, column)
                    return True
        return False     


class TableWidget(QtGui.QTableWidget):
    def __init__(self, parent=None):
        super(TableWidget, self).__init__(parent)
        delegate = LineEditDelegate()
        delegate.moveCurrentCellBy.connect(self.moveCurrentCellBy)
        self.setItemDelegate(delegate)

    def moveCurrentCellBy(self, rowStep, columnStep):
        row = self.currentRow() + rowStep
        column = self.currentColumn() + columnStep
        if row >= self.rowCount():
            self.setRowCount(row + 1)
        if column >= self.columnCount():
            self.setColumnCount(column + 1)
        self.setCurrentCell(row, column)

Upvotes: 2

Related Questions