diff options
Diffstat (limited to 'old/plugins/qtuitest_widgets/qtwidgets/testmenu.cpp')
-rw-r--r-- | old/plugins/qtuitest_widgets/qtwidgets/testmenu.cpp | 398 |
1 files changed, 398 insertions, 0 deletions
diff --git a/old/plugins/qtuitest_widgets/qtwidgets/testmenu.cpp b/old/plugins/qtuitest_widgets/qtwidgets/testmenu.cpp new file mode 100644 index 0000000..66e1e58 --- /dev/null +++ b/old/plugins/qtuitest_widgets/qtwidgets/testmenu.cpp @@ -0,0 +1,398 @@ +/**************************************************************************** +** +** 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 "testmenu.h" +#include "testwidgetslog.h" + +#include <QMenu> +#include <QAction> + +namespace QtUiTest { + +TestMenu::TestMenu(QObject *_q) + : TestWidget(_q), q(qobject_cast<QMenu*>(_q)), lastAction(0) +{ + // For accurate ordering of events recording, these connections + // must come before all others. + QtUiTest::connectFirst(q, SIGNAL(hovered(QAction*)), + this, SLOT(on_hovered(QAction*))); +} + +void TestMenu::on_hovered(QAction* a) +{ + if (lastAction) + QtUiTest::disconnectFirst(lastAction, 0, this, 0); + lastAction = a; + if (lastAction) { + QtUiTest::connectFirst(lastAction, SIGNAL(toggled(bool)), + this, SLOT(on_toggled(bool))); + QtUiTest::connectFirst(lastAction, SIGNAL(triggered(bool)), + this, SLOT(on_triggered(bool))); + } +} + +void TestMenu::on_toggled(bool state) +{ emit stateChanged(state); } + +QString textForAction(QMenu* m, QAction* a) +{ + QString ret; + foreach (QAction* child, m->actions()) { + if (child == a) { + ret = a->text(); + ret.replace("/","\\/"); + } else if (child->menu()) { + ret = textForAction(child->menu(), a); + if (!ret.isEmpty()) + ret.prepend(child->menu()->title().replace("/","\\/") + "/"); + } + if (!ret.isEmpty()) + break; + } + return ret; +} + +void TestMenu::on_triggered(bool) +{ + /* + Both the top level and submenus emit the triggered() signal. + We only want to emit selected() if we are the top level menu. + */ + bool top_level = true; + if (q->menuAction()) { + foreach (QWidget* w, q->menuAction()->associatedWidgets()) { + if (qobject_cast<QMenu*>(w)) { + top_level = false; + break; + } + } + } + + if (!top_level) return; + + emit selected(textForAction(q,lastAction)); +} + +QString TestMenu::text() const +{ + return list().join("\n"); +} + +QString TestMenu::selectedText() const +{ + QString ret; + + QAction *active = q->activeAction(); + if (!active) return ret; + + QMenu *child = active->menu(); + if (!child || !child->activeAction()) + return active->text().replace("/", "\\/"); + + return active->text().replace("/", "\\/") + "/" + qtuitest_cast<QtUiTest::TextWidget*>(child)->selectedText(); +} + +QStringList TestMenu::list() const +{ + QStringList ret; + + /* Iterate through every action */ + foreach( QAction *a, q->actions() ) { + if (!a->isEnabled() || a->isSeparator()) + continue; + QString t = a->text(); + t.replace("/","\\/"); + if (!t.isEmpty()) ret << t; + if (a->menu() && a->menu() != q) { + QStringList sub = qtuitest_cast<QtUiTest::ListWidget*>(a->menu())->list(); + foreach (QString s, sub) { + if (!s.isEmpty()) ret << t + "/" + s; + } + } + } + + return ret; +} + +QRect TestMenu::visualRect(QString const &item) const +{ + TestWidgetsLog() << item; + static QRegExp slashRe("[^\\\\]/"); + QRect ret; + + int ind; + if (0 != (ind = item.indexOf(slashRe)+1)) { + QString top(item.left(ind)); + QString rest(item.mid(ind+1)); + + QAction *a(q->activeAction()); + QString t = a->text(); + t.replace("/","\\/"); + if (!a || t != top || !a->menu()) { + TestWidgetsLog() << "The desired submenu" << item << "is not visible"; + return ret; + } + + ret = qtuitest_cast<QtUiTest::ListWidget*>(a->menu())->visualRect(rest); + ret.moveTopLeft( q->mapFromGlobal( a->menu()->mapToGlobal( ret.topLeft() ) ) ); + return ret; + } + + QAction *a = actionForItem(item); + if (a) ret = q->actionGeometry(a); + + return ret; +} + +QAction *TestMenu::actionForItem(QString const &item) const +{ + static QRegExp amperRe("&(.)"); + QAction *ret = 0; + foreach( QAction *a, q->actions() ) { + QString t = a->text(); + t.replace("/","\\/"); + if (t == item) { + ret = a; + break; + } else { + t.replace(amperRe, "\\1"); + if (t == item) { + ret = a; + } + } + } + + if (!ret) { + setErrorString("Item \"" + item + "\" is not available"); + } else if (!ret->isEnabled()) { + setErrorString("Item \"" + item + "\" is not enabled"); + ret = 0; + } + + return ret; +} + +Qt::CheckState TestMenu::checkState() const +{ + QAction *active = q->activeAction(); + return (active && active->isChecked()) ? Qt::Checked : Qt::Unchecked; +} + +bool TestMenu::ensureVisible(QString const&) +{ return false; } + +bool TestMenu::canSelect(QString const &item) const +{ + QStringList l = list(); + return l.contains(item) || l.contains(labelText(item)); +} + +bool TestMenu::select(QString const &item) +{ + if (!isVisible()) { + setErrorString("Can't select \"" + item + "\" because menu is not visible"); + return false; + } + + TestWidgetsLog() << item; + static QRegExp slashRe("[^\\\\]/"); + + QString topItem = item; + QString rest; + + int ind; + if (0 != (ind = item.indexOf(slashRe)+1)) { + topItem = item.left(ind); + rest = item.mid(ind+1); + } + + QRect r = visualRect(topItem); + if (r.isNull()) { + if (errorString().isEmpty()) { + setErrorString("Can't find visual rect for item \"" + topItem + "\" in menu"); + } + return false; + } + + QPoint pos = r.center(); + + bool useMouse = mousePreferred(); + if (useMouse) { + while (!rect().contains(pos)) { + QRect visibleRect = visibleRegion().boundingRect(); + QPoint globalPos = mapToGlobal(visibleRect.topLeft()); + if (pos.y() < globalPos.y()) { + TestWidgetsLog() << "click to scroll up"; + mouseClick(QPoint(globalPos.x() + visibleRect.width() / 2, globalPos.y() + 8)); + QtUiTest::wait(200); + } else { + TestWidgetsLog() << "click to scroll down"; + mouseClick(QPoint(globalPos.x() + visibleRect.width() / 2, globalPos.y() + visibleRect.height() - 8)); + QtUiTest::wait(200); + } + + pos = visualRect(topItem).center(); + } + TestWidgetsLog() << "click on item"; + if (!mouseClick(q, mapToGlobal(pos))) + return false; +// waitForSignal(q, SIGNAL(triggered(QAction*))); + } else { + Qt::Key key; + if ( pos.y() > q->actionGeometry(q->activeAction()).center().y() ) + key = Qt::Key_Down; + else + key = Qt::Key_Up; + + while ( selectedText() != topItem ) { + TestWidgetsLog() << "key" << ((key == Qt::Key_Down) ? "down" : "up"); + if (!keyClick(q, key)) return false; + } + + TestWidgetsLog() << "select key"; + // If this is the last item, it should be trigged... + if (item == topItem) { + if (!keyClick(q->activeAction(), SIGNAL(triggered(bool)), QtUiTest::Key_Activate)) + return false; + } + // ...but if it has a submenu, it won't be; rather, its menu will be shown. + else if (q->activeAction() && q->activeAction()->menu()) { + if (!keyClick(q->activeAction()->menu(), QtUiTest::Key_Activate)) + return false; + } + + // And if it doesn't have a submenu and isn't the final item... well, that shouldn't + // happen, but that will be caught below. + } + + if (topItem != item) { + QAction *a(q->activeAction()); + if (!a || !a->menu()) { + setErrorString("Failed to select \"" + item + "\" because " + + (!a ? "focus could not be given to a parent item." + : "an item was expected to have a submenu, but didn't.")); + return false; + } + + // Wait until the menu is visible + if (!a->menu()->isVisible() && !waitForEvent(a->menu(), QEvent::Show)) { + setErrorString("Failed to select \"" + item + "\" because a submenu did not become " + "visible when it should have."); + return false; + } + + TestWidgetsLog() << "calling select() on child"; + return qtuitest_cast<SelectWidget*>(a->menu())->select(rest); + } + return true; +} + +bool TestMenu::isCheckable(const QString &item) +{ + static QRegExp slashRe("[^\\\\]/"); + bool ret = false; + int ind; + if (0 != (ind = item.indexOf(slashRe)+1)) { + QString top(item.left(ind)); + QString rest(item.mid(ind+1)); + + QAction *a = actionForItem(top); + if (!a || !a->menu()) { + TestWidgetsLog() << "The desired submenu" << item << "is not valid"; + return ret; + } + + return qtuitest_cast<QtUiTest::CheckItemWidget*>(a->menu())->isCheckable(rest); + } + + QAction *a = actionForItem(item); + if (a) ret = a->isCheckable(); + + return ret; +} + +bool TestMenu::isChecked(const QString &item) const +{ + static QRegExp slashRe("[^\\\\]/"); + + bool ret = false; + int ind; + if (0 != (ind = item.indexOf(slashRe)+1)) { + QString top(item.left(ind)); + QString rest(item.mid(ind+1)); + + QAction *a = actionForItem(top); + if (!a || !a->menu()) { + TestWidgetsLog() << "The desired submenu" << item << "is not valid"; + return ret; + } + + return qtuitest_cast<QtUiTest::CheckItemWidget*>(a->menu())->isChecked(rest); + } + + QAction *a = actionForItem(item); + if (a) { + ret = a->isChecked(); + } else { + setErrorString("Cannot get check status for item \"" + item + "\""); + } + + return ret; +} + +bool TestMenu::setChecked(const QString &item, bool value) +{ + if (isChecked(item) == value) { + return true; + } + + return select(item); +} + +bool TestMenu::hasFocus() const +{ + return !q->isHidden(); +} + +bool TestMenu::canWrap(QObject *o) +{ return qobject_cast<QMenu*>(o); } + +} |