diff options
Diffstat (limited to 'old/plugins/qtuitest_widgets/qtwidgets/testabstractitemview.cpp')
-rw-r--r-- | old/plugins/qtuitest_widgets/qtwidgets/testabstractitemview.cpp | 475 |
1 files changed, 475 insertions, 0 deletions
diff --git a/old/plugins/qtuitest_widgets/qtwidgets/testabstractitemview.cpp b/old/plugins/qtuitest_widgets/qtwidgets/testabstractitemview.cpp new file mode 100644 index 0000000..ccb1371 --- /dev/null +++ b/old/plugins/qtuitest_widgets/qtwidgets/testabstractitemview.cpp @@ -0,0 +1,475 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of QtUiTest. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "testabstractitemview.h" +#include "testwidgetslog.h" + +#include <QListView> +#include <QTimer> +#include <QScrollBar> +#include <QComboBox> +#include <QGraphicsProxyWidget> +#include <QGraphicsView> + +#include <qtuitestnamespace.h> + +namespace QtUiTest { + +TestAbstractItemView::TestAbstractItemView(QObject *_q) + : TestWidget(_q), q(qobject_cast<QAbstractItemView*>(_q)) +{ + if (q && q->parent() && qobject_cast<QComboBox*>(q->parent()->parent())) { + // The test object of the combobox will handle recording + return; + } + + QtUiTest::connectFirst(q, SIGNAL(activated(QModelIndex)), + this, SLOT(on_activated(QModelIndex))); + QtUiTest::connectFirst(q, SIGNAL(pressed(QModelIndex)), + this, SLOT(on_activated(QModelIndex))); +} + +void TestAbstractItemView::on_activated(QModelIndex const& ind) +{ + // Timer discourages duplicate signal emission. + if (m_lastActivatedTimer.elapsed() > 500 || m_lastActivatedTimer.elapsed() < 0) { + TestWidgetsLog() << "emit selected" << ind.data().toString(); + emit selected(printable(ind.data().toString())); + m_lastActivatedTimer.start(); + } else { + TestWidgetsLog() << "Would emit selected" << ind.data().toString() + << "except we have already done that recently."; + } +} + +QString TestAbstractItemView::selectedText() const +{ + TestWidgetsLog(); + return printable(q->currentIndex().data().toString()); +} + +QString TestAbstractItemView::text() const +{ + TestWidgetsLog(); + return list().join("\n"); +} + +QStringList TestAbstractItemView::list() const +{ + class QModelListGetter : public QModelViewIterator<QAbstractItemView> + { + public: + QModelListGetter(QAbstractItemView *view) + : QModelViewIterator<QAbstractItemView>(view) {}; + + QStringList getList() { + list.clear(); + iterate(view()->rootIndex()); + return list; + } + protected: + virtual void visit(QModelIndex const &index) + { list << itemForIndex(index); } + + QStringList list; + }; + + return QModelListGetter(q).getList(); +} + +QModelIndex TestAbstractItemView::indexForItem(QString const &item) const +{ + QModelIndex ret; + + class QModelIndexGetter : public QModelViewIterator<QAbstractItemView> + { + public: + QModelIndexGetter(QAbstractItemView *view, QString const &item) + : QModelViewIterator<QAbstractItemView>(view), matches(0), m_item(item) {}; + QModelIndex index; + int matches; + + protected: + void visit(QModelIndex const &idx) { + + if (itemForIndex(idx) == m_item) { + ++matches; + index = idx; + } + } + private: + QString m_item; + }; + + QModelIndexGetter indexGetter(q, item); + indexGetter.iterate(q->rootIndex()); + + // No matching item + if (!indexGetter.matches) { + TestWidgetsLog() << "no matching item for" << item; + } + + // More than one matching item + else if (indexGetter.matches > 1) { + qWarning("QtUitest: more than one item matches '%s' in item view", qPrintable(item)); + TestWidgetsLog() << indexGetter.matches << "matches for" << item; + } + + else + ret = indexGetter.index; + + return ret; +} + +QModelIndex TestAbstractItemView::indexFromList(QVariantList const &list) const +{ + QVariantList indexList = list; + QModelIndex ret; + if (list.size() > 1) { + int column = indexList.takeLast().toInt(); + int row = indexList.takeLast().toInt(); + ret = q->model()->index(row, column, indexFromList(indexList)); + } + return ret; +} + + +QVariantList TestAbstractItemView::listFromIndex(QModelIndex const &index) const +{ + QVariantList ret; + if (index.parent().isValid()) { + ret << listFromIndex(index.parent()); + } + if (index.isValid()) { + ret << index.row() << index.column(); + } + + return ret; +} + +QRect TestAbstractItemView::visualRect(QString const &item) const +{ + QRect ret; + + QModelIndex index = indexForItem(item); + + if (index.isValid()) { + ret = q->visualRect(index); + ret.moveTopLeft(q->mapFromGlobal(q->viewport()->mapToGlobal(ret.topLeft()))); + } + + return ret; +} + +bool TestAbstractItemView::isMultiSelection() const +{ return (q->selectionMode() > QAbstractItemView::SingleSelection); } + +bool TestAbstractItemView::canSelect(QString const &item) const +{ + if (q->selectionMode() == QAbstractItemView::NoSelection) + return false; + + return list().contains(item); +} + +bool TestAbstractItemView::canSelectMulti(QStringList const &items) const +{ + if (!isMultiSelection()) + return false; + + QSet<QString> itemSet = items.toSet(); + return ((itemSet & list().toSet()) == itemSet); +} + +bool TestAbstractItemView::select(QString const &item) +{ + TestWidgetsLog() << item; + + if (!canSelect(item)) { + TestWidgetsLog() << "can't select" << item; + return false; + } + + if (!QtUiTest::mousePreferred() && (!setFocus() || !hasFocus())) { + QtUiTest::setErrorString("Couldn't give focus to item view"); + return false; + } + + return select(indexForItem(item)); +} + +bool TestAbstractItemView::select(QModelIndex const &index) +{ + if (QtUiTest::mousePreferred()) { + if (!ensureVisible(index)) { + TestWidgetsLog() << "couldn't make item visible"; + return false; + } + QPoint pos = q->visualRect(index).center(); + TestWidgetsLog() << "after ensureVisible, item is at" << pos; + + while (q->parentWidget()) { + // Workaround to allow selection from QComboBoxes embedded in a QGraphicsView + QGraphicsProxyWidget *gpw = q->parentWidget()->graphicsProxyWidget(); + if (!gpw) break; + QGraphicsScene *scene = gpw->scene(); + if (!scene) break; + QGraphicsView *view = scene->views().first(); + if (!view) break; + QtUiTest::mouseClick(view->mapToGlobal(view->mapFromScene(gpw->mapToScene(pos))), Qt::LeftButton); + return true; + } + + QtUiTest::mouseClick(q->viewport()->mapToGlobal(pos), Qt::LeftButton); + return true; + + } else { + // Consume pending key events, if any. + while (QtUiTest::waitForEvent(q, QEvent::KeyRelease, 200, Qt::QueuedConnection)) + {} + + const int maxtries = 100; + + // Move vertically + int desiredY = q->visualRect(index).center().y(); + int currentY = q->visualRect(q->currentIndex()).center().y(); + + for (int i = 0; i < maxtries && desiredY != currentY; ++i) { + Qt::Key key; + if (desiredY < currentY) { + key = Qt::Key_Up; + TestWidgetsLog() << "Up (desired=" << desiredY << ", current=" << currentY << ")"; + } else { + key = Qt::Key_Down; + TestWidgetsLog() << "Down (desired=" << desiredY << ", current=" << currentY << ")"; + } + if (!QtUiTest::keyClick(q, key)) return false; + desiredY = q->visualRect(index).center().y(); + currentY = q->visualRect(q->currentIndex()).center().y(); + } + if (desiredY != currentY) { + QtUiTest::setErrorString(QString( + "Up/down keys failed to move highlight vertically; desired position %1, " + "current position %2").arg(desiredY).arg(currentY)); + return false; + } + + // Move horizontally + int desiredX = q->visualRect(index).center().x(); + int currentX = q->visualRect(q->currentIndex()).center().x(); + + for (int i = 0; i < maxtries && desiredX != currentX; ++i) { + Qt::Key key; + if (desiredX < currentX) { + key = Qt::Key_Left; + TestWidgetsLog() << "Left (desired=" << desiredX << ", current=" << currentX << ")"; + } else { + key = Qt::Key_Right; + TestWidgetsLog() << "Right (desired=" << desiredX << ", current=" << currentX << ")"; + } + if (!QtUiTest::keyClick(q, key)) return false; + desiredX = q->visualRect(index).center().x(); + currentX = q->visualRect(q->currentIndex()).center().x(); + } + if (desiredX != currentX) { + QtUiTest::setErrorString(QString( + "Left/right keys failed to move highlight horizontally; desired position %1, " + "current position %2").arg(desiredX).arg(currentX)); + return false; + } + + TestWidgetsLog() << "hit activate key"; + if (!QtUiTest::keyClick(q, QtUiTest::Key_Activate)) return false; + return true; + } + + return false; +} + +bool TestAbstractItemView::selectMulti(QStringList const &items) +{ + if (!canSelectMulti(items)) return false; + + TestWidgetsLog() << items; + + return false; +} + +bool TestAbstractItemView::selectIndex(QVariantList const &indexList) +{ + QModelIndex idx = indexFromList(indexList); + if (idx.isValid()) { + return select(idx); + } + else { + QtUiTest::setErrorString("Invalid index"); + return false; + } +} + +QVariantList TestAbstractItemView::selectedIndex() const +{ + return listFromIndex(q->currentIndex()); +} + +bool TestAbstractItemView::ensureVisible(QString const &item) +{ + return ensureVisible(indexForItem(item)); +} + +bool TestAbstractItemView::ensureVisible(QModelIndex const &index) +{ + QPoint p = q->visualRect(index).center(); + + if (q->viewport()->rect().contains(p)) { + TestWidgetsLog() << "item is already visible"; + return true; + } + + if (!QtUiTest::mousePreferred()) + return false; + + /* Figure out the points to click for scrolling in each direction */ + QScrollBar *vbar = q->verticalScrollBar(); + QScrollBar *hbar = q->horizontalScrollBar(); + QPoint up = vbar->mapToGlobal(QPoint(vbar->width()/2,5)); + QPoint down = vbar->mapToGlobal(QPoint(vbar->width()/2,vbar->height()-5)); + QPoint left = hbar->mapToGlobal(QPoint(5, hbar->height()/2)); + QPoint right = hbar->mapToGlobal(QPoint(hbar->width()-5,hbar->height()/2)); + + // While p is above rect... + while (p.y() < q->viewport()->rect().top()) { + if (!vbar->isVisible()) return false; + TestWidgetsLog() << "up" << "\nrect:" << rect() << "p:" << p; + QtUiTest::mouseClick(up); + waitForSignal(vbar, SIGNAL(valueChanged(int))); + p = q->visualRect(index).center(); + } + // While p is below rect... + while (p.y() > q->viewport()->rect().bottom()) { + if (!vbar->isVisible()) return false; + TestWidgetsLog() << "down" << "\nrect:" << rect() << "p:" << p; + QtUiTest::mouseClick(down); + waitForSignal(vbar, SIGNAL(valueChanged(int))); + p = q->visualRect(index).center(); + } + // While p is left of rect... + while (p.x() < q->viewport()->rect().left()) { + if (!hbar->isVisible()) return false; + TestWidgetsLog() << "left" << "\nrect:" << rect() << "p:" << p; + QtUiTest::mouseClick(left); + waitForSignal(hbar, SIGNAL(valueChanged(int))); + p = q->visualRect(index).center(); + } + // While p is right of rect... + while (p.x() > q->viewport()->rect().right()) { + if (!hbar->isVisible()) return false; + TestWidgetsLog() << "right" << "\nrect:" << rect() << "p:" << p; + QtUiTest::mouseClick(right); + waitForSignal(hbar, SIGNAL(valueChanged(int))); + p = q->visualRect(index).center(); + } + + if (!q->viewport()->rect().contains(p)) { + TestWidgetsLog() << "failed" << "\nrect:" << q->viewport()->rect() << "p:" << p; + return false; + } + + return true; +} + +bool TestAbstractItemView::canEnter(QVariant const& item) const +{ + bool ret = false; + QModelIndex ci = q->currentIndex(); + if (ci.isValid() && q->selectionMode() != QAbstractItemView::NoSelection && ci.flags() & Qt::ItemIsEditable) { + QWidget *indexWidget = q->indexWidget(ci); + if (!indexWidget) { + // FIXME: Should simulate correct events to enter edit mode + q->edit(ci); + indexWidget = q->indexWidget(ci); + } + InputWidget* iw = qtuitest_cast<InputWidget*>(indexWidget); + if (iw) { + ret = iw->canEnter(item); + // FIXME: Should simulate correct events to leave edit mode + q->setFocus(); + } else { + SelectWidget* sw = qtuitest_cast<SelectWidget*>(indexWidget); + if (sw) { + ret = sw->canSelect(item.toString()); + q->setFocus(); + } + } + } + return ret; +} + +bool TestAbstractItemView::enter(QVariant const& item, bool noCommit) +{ + bool ret = false; + QModelIndex ci = q->currentIndex(); + if (ci.isValid() && q->selectionMode() != QAbstractItemView::NoSelection && ci.flags() & Qt::ItemIsEditable) { + QWidget *indexWidget = q->indexWidget(ci); + if (!indexWidget) { + // FIXME: Should simulate correct events to enter edit mode + q->edit(ci); + indexWidget = q->indexWidget(ci); + } + InputWidget* iw = qtuitest_cast<InputWidget*>(indexWidget); + if (iw) { + ret = iw->enter(item, noCommit); + // FIXME: Should simulate correct events to leave edit mode + q->setFocus(); + } else { + SelectWidget* sw = qtuitest_cast<SelectWidget*>(indexWidget); + ret = sw->select(item.toString()); + q->setFocus(); + } + } + + return ret; +} + +bool TestAbstractItemView::canWrap(QObject* o) +{ return qobject_cast<QAbstractItemView*>(o); } + +} |