QItemDelegate, как предоставить свой собственный EndEditHint в сигнале closeEditor()?

У меня есть собственная модель таблицы, подкласс QAbstractTableModel. На мой взгляд, он установлен (подкласс QTableView). Внутри представления я использую класс делегата (подкласс QItemDelegate) для редактирования элементов.

Я хочу настроить следующее поведение: когда я закончу редактирование данных с помощью своего делегата, следующий элемент в модели (элемент в следующей строке и в том же столбце) должен стать редактируемым.

В документации сказано, что это обеспечивается подсказкой QAbstractItemDelegate::EditNextItem, которая отправляется в сигнале closeEditor(). Но по умолчанию этот сигнал отправляется с параметром QAbstractItemDelegate::NoHint. Проблема в том, что мне не нужно явно вызывать этот сигнал при повторной реализации базовых QItemDelegate виртуальных функций, таких как, например, setModelData().

В документации также говорится, что этот сигнал посылает фильтр внутренних событий, который устанавливается на делегате элемента при вызове конструктора QAbstractItemDelegate().

Как я могу обеспечить свой собственный сигнал EndEditHint в closeEditor()?


person DKurulyuk    schedule 11.04.2016    source источник


Ответы (1)


Когда вы закончите редактирование, делегат отправит сигнал closeEditor() с подсказкой SubmitModelCache. Вы должны сохранить это поведение, чтобы ваша модель была правильно обновлена.

Чтобы сразу открыть редактор в следующей ячейке после фиксации данных из предыдущего редактирования, вы можете переопределить QItemDelegate::eventFilter(), но я считаю, что намного проще просто переопределить метод QAbstractItemView::closeEditor():

void CMyTableView::closeEditor(QWidget *editor, QAbstractItemDelegate::EndEditHint hint)
{
    QTableView::closeEditor(editor, hint);

    QModelIndex index = moveCursor(MoveNext, Qt::NoModifier);
    if (!index.isValid()) 
        return;

    QPersistentModelIndex persistent(index);
    selectionModel()->setCurrentIndex(persistent, flags);

    // currentChanged signal would have already started editing
    if (index.flags() & Qt::ItemIsEditable && (!(editTriggers() & QAbstractItemView::CurrentChanged)))
        edit(persistent);
}

Еще более простым решением было бы (я не уверен в этом, но определенно стоит попробовать):

void CMyTableView::closeEditor(QWidget *editor, QAbstractItemDelegate::EndEditHint hint)
{
    QTableView::closeEditor(editor, hint);
    QTableView::closeEditor(nullptr, QAbstractItemDelegate::EditNextItem);       
}

Метод moveCursor() возвращает индекс следующего столбца и той же строки. Если вы хотите изменить это поведение, реализуйте его заново:

QModelIndex CMyTableView::moveCursor(CursorAction action, Qt::KeyboardModifiers modifiers)
{
    if (action == QAbstractItemView::MoveNext)
        action = QAbstractItemView::MoveDown;
    else if (action == QAbstractItemView::MovePrevious)
             action = QAbstractItemView::MoveUp;

    // Next row, same column.
    return QTableView::moveCursor(action, modifiers);
}

И кстати: когда вы нажимаете клавишу Tab, поведение QTableView по умолчанию заключается в том, что текущий редактор закрывается, данные сохраняются и редактируется следующая ячейка.
Поэтому, возможно, единственное, что вам нужно сделать, это просто переопределить метод QTableView::moveCursor().

person Tomas    schedule 15.04.2016