Как вы можете редактировать ячейку QTableView из модульного теста QTest?

Я пишу модульный тест для пользовательского Validator в QTableView с использованием инфраструктуры QTestLib. Один из самых простых тестовых случаев можно описать так:

Дважды щелкните ячейку таблицы в третьем столбце и четвертой строке и добавьте число 5 к ее содержимому.

Недостаточно просто изменить значение в модели или что-либо еще, контрольный пример должен выполнить это так:

  1. Дважды щелкните ячейку таблицы, чтобы перевести ее в режим редактирования.
  2. Нажмите клавишу [Конец].
  3. Нажмите клавишу [5].

Примечание: на этот вопрос есть ответ о том, как перевести ячейку таблицы в режим редактирования из кода, однако модульный тест должен попытаться придерживаться возможностей человека, то есть действий мыши / клавиатуры.

Я обнаружил, что положение X/Y ячейки можно получить с помощью QTableView::columnViewportPosition( int) и QTableView:: rowViewportPosition (int). Однако двойной щелчок в указанном месте с помощью QTest::mouseDClick(...) не выделяет ячейку и не переводит ее в режим редактирования:

// Retrieve X/Y coordinates of the cell in the third column and the fourth row
int xPos = m_pTableView->columnViewportPosition( 2 );
int yPos = m_pTableView->rowViewportPosition( 3 );

// This does not work
QTest::mouseDClick( m_pTableView, Qt::LeftButton, QPoint( xPos, yPos ) );

Как я могу реализовать контрольный пример, который я описал выше, используя только действия мыши / клавиатуры?

PS: я пытаюсь это под Windows XP 32 бит и Qt 4.6.1

1 ответ

Решение

Есть несколько вещей, которые следует учитывать при попытке редактирования в QTableView с помощью смоделированных событий:

QTableView не отображает свои ячейки напрямую, он делает это с помощью своего viewport (). Аналогично, событие двойного щелчка должно быть отправлено в область просмотра вместо самого табличного представления.

Теперь, когда вы делаете

QTest::mouseDClick( m_pTableView->viewport(), Qt::LeftButton, 
                    NULL, QPoint( xPos, yPos ) );

ячейка будет выделена, но не в режиме редактирования (в отличие от двойного щелчка, инициированного человеком, который мгновенно переводит ячейку в режим редактирования, даже если представление таблицы ранее не имело фокусировки). Если вы добавите один щелчок в том же месте перед двойным щелчком, это сработает!

Если вы затем отправите нажатие клавиши [End] в область просмотра, курсор не перейдет к концу содержимого ячейки таблицы, а вместо этого будет выбрана последняя ячейка в текущей строке.
Чтобы изменить содержимое ячейки таблицы, вы должны вместо этого отправить событие в текущий виджет редактора. Самый простой способ сделать это - использовать QWidget::focusWidget()

QTest::keyClick( m_pTableView->viewport()->focusWidget(), Qt::Key_End );

Обратите внимание, что такое использование может быть небезопасным, так как focusWidget () может возвращать NULL.


Обладая этими знаниями, контрольный пример может быть запрограммирован следующим образом:

// Note: The table view must be visible at this point

// Retrieve X/Y coordinates of the cell in the third column and the fourth row
int xPos = m_pTableView->columnViewportPosition( 2 ) + 5;
int yPos = m_pTableView->rowViewportPosition( 3 ) + 10;

// Retrieve the viewport of the table view
QWidget* pViewport = m_pTableView->viewport();

// Double click the table cell to set it into editor mode
// Note: A simple double click did not work, Click->Double Click works, however
QTest::mouseClick ( pViewport, Qt::LeftButton, NULL, QPoint( xPos, yPos ) );
QTest::mouseDClick( pViewport, Qt::LeftButton, NULL, QPoint( xPos, yPos ) );

// Simulate [End] keypress
QTest::keyClick( pViewport->focusWidget(), Qt::Key_End );

// Simulate [5] keypress
QTest::keyClick( pViewport->focusWidget(), Qt::Key_5 );

(Примечание: если вы хотите это проверить, вы можете добавить команды QTest::qWait( 1000) после каждого события)


Если вы используете функции _data(), как описано здесь, обратите внимание, что вы не можете получить focusWidget () во время создания данных. Я решил эту проблему, создав пользовательский интерфейс ITestAction только с чисто виртуальной функцией execute(). Затем я добавил подклассы с похожим конструктором QTest::mouseClick(...) etc функции. Эти классы просто вызывают функции QTest, но используют либо сам виджет, либо его виджет фокуса в качестве параметра, в зависимости от дополнительного логического флага. Слот _data() затем сохраняет QList для каждой строки данных, и фактический тестовый слот выполняет итерации по этому списку и вызывает execute() для каждого элемента перед выполнением проверки.

Другие вопросы по тегам