I am writing a gui for a basic hex editor in QT and have a QGridLayout that contains 64 QLineEdits. I have it working that when I use the up and down arrow keys, the focus will shift to the lineEdit that is directly above or below respectively. The left and right functionality is written to be similar, but the focus only shifts to the previous/next lineEdit if the cursorPosition is at index 0 or 2 respectively (each lineEdit is limited to 2 characters). My issue is, the left and right arrow keys are only able to change the cursorPosition. If I remap the functionality for left and right to the up and down keys, the function works as intended.
How can I give the left and right arrow keys a secondary functionality given that the cursorPosition is at the correct position
Here is the event filter:
bool autoGenWidget::eventFilter(QObject *object, QEvent *event)
{
if(event->type() == QEvent::KeyPress)
{
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
if(keyEvent->key() == Qt::Key_Left && (focusedLineEdit->cursorPosition() == 0))
{
arrowKeyNavigation(focusRow, focusCol, arrowLeft);
}
else if(keyEvent->key() == Qt::Key_Right && (focusedLineEdit->cursorPosition() == 2))
{
arrowKeyNavigation(focusRow, focusCol, arrowRight);
}
else if(keyEvent->key() == Qt::Key_Up)
{
int cursor = focusedLineEdit->cursorPosition();
arrowKeyNavigation(focusRow, focusCol, arrowUp);
}
else if(keyEvent->key() == Qt::Key_Down)
{
arrowKeyNavigation(focusRow, focusCol, arrowDown);
}
return true;
}
return false;
}
And here is the navigation function
void autoGenWidget::arrowKeyNavigation(int row, int col, int state)
{
if(state == arrowLeft && focusedLineEdit->cursorPosition() == 0)
{
if(numRows - 1 > row && col == 0)
{
ui->dataGridLayout->itemAtPosition(row, 15)->widget()->setFocus();
focusedLineEdit->setCursorPosition(2);
}
else if(numRows - 1 == row && col == 0)
{
ui->dataGridLayout->itemAtPosition(row, numBottomRowCols - 1)->widget()->setFocus();
focusedLineEdit->setCursorPosition(2);
}
else if(col != 0)
{
ui->dataGridLayout->itemAtPosition(row, col - 1)->widget()->setFocus();
focusedLineEdit->setCursorPosition(2);
}
}
else if(state == arrowRight && focusedLineEdit->cursorPosition() == 2)
{
if((numRows - 1 > row && col == 15) || (numRows - 1 == row && col == numBottomRowCols - 1))
{
ui->dataGridLayout->itemAtPosition(row, 0)->widget()->setFocus();
focusedLineEdit->setCursorPosition(0);
}
else if(col != 15)
{
ui->dataGridLayout->itemAtPosition(row, col + 1)->widget()->setFocus();
focusedLineEdit->setCursorPosition(0);
}
}
else if(state == arrowUp)
{
if(row == 0 && col <= numBottomRowCols - 1)
{
ui->dataGridLayout->itemAtPosition(numRows - 1, col)->widget()->setFocus();
focusedLineEdit->setCursorPosition(0);
}
else if(row == 0 && col > numBottomRowCols - 1)
{
ui->dataGridLayout->itemAtPosition(numRows - 2, col)->widget()->setFocus();
focusedLineEdit->setCursorPosition(0);
}
else if(row > 0)
{
ui->dataGridLayout->itemAtPosition(row - 1, col)->widget()->setFocus();
focusedLineEdit->setCursorPosition(0);
}
}
else if(state == arrowDown)
{
if(row == numRows - 1 || (row == numRows - 2 && col > numBottomRowCols - 1))
{
ui->dataGridLayout->itemAtPosition(0, col)->widget()->setFocus();
focusedLineEdit->setCursorPosition(0);
}
else
{
ui->dataGridLayout->itemAtPosition(row + 1, col)->widget()->setFocus();
focusedLineEdit->setCursorPosition(0);
}
}
}
Again, the functionality works as intended but the left and right arrow keys do not. Any help would be greatly appreciated.
While the question title refers to C++, the tags also include PyQt, so I'm providing a possible solution for that.
I would start by creating a QLineEdit subclass that ignores key events based on the key and the cursor position:
Considering this, the parent will always process key events that are ignored by the children, so it's just a matter of finding the current grid "cell" of the focus widget and then setting the focus based on the key:
This implementation works, but I would suggest another approach, that could add more functionality to the whole editor, and that's by using a QTableWidget (or a QTableView with a custom QAbstractTableModel that is used to map the hex data).
Not only we can still use the QLineEdit subclass above, but the whole keyboard navigation is automatically implemented in the view, and also allows easy switching of the current cell.