0

I am having trouble augmenting the default edit behavior of QTableView. I want the following behavior when the Enter key is pressed:

  1. Start editing the current cell if it is not already being edited.
  2. If the cell is being edited,
    • 2a. commit the data and close the editor. Then,
    • 2b. make the cell below, if present, the current cell.

2a is the default behavior, and 2b can likely be achieved by using QAbstractItemView::setCurrentIndex() in a re-implementation of QItemDelegate::eventFilter() (as suggested here in a similar context).

The problem is in achieving 1. I list below the approaches I have tried till now.

  • Reconfigure the "platform edit key" By default, "Editing starts when the platform edit key has been pressed over an item." (QAbstractItemView::EditKeyPressed) This key is F2 on my platform (Ubuntu 12.04). I could reconfigure the platform edit key to Enter but
    • Altering platform defaults seems like a bad idea.
    • I could not find out how to do it.
  • Capture the Enter key press I use QShortCut to do this as follows:

    class CourseTable : public QTableView {
    /* ... */
    };
    /* ... */
    CourseTable::CourseTable(/* ... */) {
      /* ... */
      QShortcut* shortcut = new QShortcut(QKeySequence(Qt::Key_Return), this);
      connect(shortcut, SIGNAL(activated()), this, SLOT(handleEnter_()));
      /* ... */
    }
    /* ... */
    void CourseTable::handleEnter_() {
      QModelIndex idx = this->currentIndex();
      if (this->state() != QAbstractItemView::EditingState)
        this->edit(idx);
      /* else  // see below */
    }
    

    This does capture the Enter key-press and accomplishes 1 (from above) but now 2 is broken. So, I need to look into the else clause in CourseTable::handleEnter_() above, possibly calling QAbstractItemView::commitData() and QAbstractItemView::closeEditor in it. The problem is that both these functions require a QWidget *editor argument which I just cannot figure out how to get. I could subclass QAbstractItemDelegate, add a getEditor() method to the derived class, and modify existing code to pass instances of the derived delegate class to CourseTable::setItemDelegate*() functions. But that sounds like too much work.

So, any ideas how I can cleanly accomplish both 1 and 2 without having to rewrite my code?

wsaleem
  • 594
  • 8
  • 25
  • So then, `QWidget* QItemDelegate::createEditor()` turns out to be a `const` function, so I cannot even save a pointer to the created editor in a member variable. – wsaleem Sep 18 '12 at 04:59

1 Answers1

2

Why cant you just filter the event also for starting the edit?

Just handle the event if state is != QAbstractItemView::EditingState

Returning true in this function makes the event stop propagating to the filtered object.

If state is Editing you can just return falseand allow the table and editor continue processing the event.

Something like this:

 bool FilterObject::eventFilter(QObject *object, QEvent *event)
 {
   if (object == tableView && event->type() == QEvent::KeyPress) {
       QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
       if (keyEvent->key() == Qt::Key_Return && tableView->state() != QAbstractItemView::EditingState) {
           // set current cell to edit
         return true;
       } else
         return false;
   }
   return false;
 }
trompa
  • 1,967
  • 1
  • 18
  • 26