Test your websites with this simple GUI based scripted webtester. Generate simple testscripts directly from surfng on the webpage, enhance them with your commands, with variables, loops, checks, … and finally run automated web tests.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

830 lines
44 KiB

/*! @file
@id $Id$
*/
// 1 2 3 4 5 6 7 8
// 45678901234567890123456789012345678901234567890123456789012345678901234567890
#ifndef TESTGUI_HXX
#define TESTGUI_HXX
#include <webpage.hxx>
#include <commands.hxx>
#include <QMainWindow>
#include <QSettings>
#include <QWebFrame>
#include <QWebElement>
#include <QFileDialog>
#include <QScrollBar>
#include <QFile>
#include <QMessageBox>
#include <ui_testgui.hxx>
#include <stdexcept>
#include <QNetworkReply>
#include <QEvent>
#include <QTextDocumentFragment>
#include <mrw/stdext.hxx>
class TestGUI: public QMainWindow, protected Ui::TestGUI {
Q_OBJECT;
public:
explicit TestGUI(QWidget *parent = 0,
QString url = QString(),
QString setupScript = QString(),
QString scriptFile = QString()):
QMainWindow(parent),
_typing(false),
_inEventFilter(false) {
setupUi(this);
QSettings settings("mrw", "webtester");
restoreGeometry(settings.value("geometry").toByteArray());
restoreState(settings.value("windowstate").toByteArray());
if (!url.isEmpty()) {
_url->setText(url);
}
TestWebPage* page(new TestWebPage(_web));
_web->setPage(page);
_web->installEventFilter(this); // track mouse and keyboard
page->setForwardUnsupportedContent(true);
_commands->setText(Script().commands(Script::HTML));
connect(page, SIGNAL(uploadFile(QString)), SLOT(uploadFile(QString)));
connect(page, SIGNAL(unsupportedContent(QNetworkReply*)),
SLOT(unsupportedContent(QNetworkReply*)));
connect(page, SIGNAL(downloadRequested(const QNetworkRequest&)),
SLOT(downloadRequested(const QNetworkRequest&)));
if (setupScript.size()) loadSetup(setupScript);
if (scriptFile.size()) loadFile(scriptFile);
}
virtual ~TestGUI() {}
public Q_SLOTS:
void on__load_clicked() {
enterText(true);
if (_record->isChecked())
appendCommand("load "+map(_url->text()));
_web->load(_url->text());
}
void on__abort_clicked() {
enterText(true);
_web->stop();
}
void on__actionOpen_triggered() {
QString name(QFileDialog::getOpenFileName(this, tr("Open Test Script")));
if (name.isEmpty()) return;
loadFile(name);
}
void on__actionOpenSetupScript_triggered() {
QString name(QFileDialog::getOpenFileName(this, tr("Open Setup Script")));
if (name.isEmpty()) return;
loadSetup(name);
}
void on__actionRevertToSaved_triggered() {
loadFile(_filename);
}
void on__actionSaveAs_triggered() {
QString name(QFileDialog::getSaveFileName(this, tr("Save Test Script")));
if (name.isEmpty()) return;
_filename = name;
on__actionSave_triggered();
}
void on__actionSave_triggered() {
QFile file(_filename);
try {
if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
throw std::runtime_error("file open failed");
QTextStream out(&file);
out<<_testscript->toPlainText();
if (out.status()!=QTextStream::Ok)
throw std::runtime_error(std::string("file write failed (")
+char(out.status()+48)+")");
_actionSave->setEnabled(true);
_actionRevertToSaved->setEnabled(true);
} catch(const std::exception& x) {
QMessageBox::critical(this, tr("Save Failed"),
tr("Saving test script failed, %2. "
"Cannot write test script to file %1.")
.arg(_filename).arg(x.what()));
}
}
void on__actionClear_triggered() {
_testscript->clear();
_log->clear();
_filename.clear();
_actionSave->setEnabled(false);
_actionRevertToSaved->setEnabled(false);
}
void on__run_clicked() {
bool oldRecordState(_record->isChecked());
_record->setChecked(false);
_record->setEnabled(false);
_run->setEnabled(false);
try {
Script script;
connect(&script, SIGNAL(logging(QString)), SLOT(logging(QString)));
std::shared_ptr<xml::Node> testsuites(new xml::Node("testsuite"));
if (_setupscriptactive->isEnabled()
&& _setupscriptactive->isChecked()) {
script.parse(_setupscript->toPlainText().split('\n'), "setup");
script.run(_web->page()->mainFrame(), testsuites, QString(),
_screenshots->isChecked());
script.reset();
}
QString text(_testscript->textCursor().selection().toPlainText());
if (text.isEmpty()) text = _testscript->toPlainText();
script.parse(text.split('\n'), "script");
script.run(_web->page()->mainFrame(), testsuites, QString(),
_screenshots->isChecked());
} catch (std::exception &x) {
QMessageBox::critical(this, tr("Script Failed"),
tr("Script failed with message:\n%1")
.arg(x.what()));
}
_run->setEnabled(true);
_record->setEnabled(true);
_record->setChecked(oldRecordState);
}
void on__focused_clicked() {
enterText(true);
QWebElement element(focused());
if (element.isNull()) return;
highlight(element);
_focusedText->setText(selector(element));
}
void on__select_clicked() {
enterText(true);
highlight(_web->page()->mainFrame()->documentElement()
.findFirst(_selector->text()));
}
void on__jsExecute_clicked() {
enterText(true);
_jsResult->setText(execute(selector(), _javascriptCode->toPlainText()));
}
void on__web_linkClicked(const QUrl& url) {
enterText(true);
if (_record->isChecked())
appendCommand("load "+map(url.url()));
}
void on__web_loadProgress(int progress) {
enterText(true);
_progress->setValue(progress);
}
void on__web_loadStarted() {
enterText(true);
if (_record->isChecked())
appendCommand("expect "+map("loadStarted"));
_progress->setValue(0);
_urlStack->setCurrentIndex(PROGRESS_VIEW);
}
void on__web_statusBarMessage(const QString&) {
//std::cout<<"statusBarMessage: "<<text.toStdString()<<std::endl;
}
void on__web_titleChanged(const QString&) {
//std::cout<<"titleChanged: "<<title.toStdString()<<std::endl;
}
void on__web_urlChanged(const QUrl& url) {
enterText(true);
if (_record->isChecked())
appendCommand("expect "+map("urlChanged "+url.url()));
}
void on__web_selectionChanged() {
_source->setPlainText(_web->hasSelection()
? _web->selectedHtml()
: _web->page()->mainFrame()->toHtml());
}
void on__web_loadFinished(bool ok) {
enterText(true);
if (_record->isChecked()) {
QString text(_testscript->toPlainText());
QStringList lines(text.split("\n"));
if (ok && lines.size()>1 &&
lines.last().startsWith("expect urlChanged") &&
lines.at(lines.size()-2)=="expect loadStarted") {
// replace three expect lines by one single line
QString url(lines.last().replace("expect urlChanged", "").trimmed());
lines.removeLast(); lines.removeLast();
_testscript->setPlainText(lines.join("\n"));
_testscript->moveCursor(QTextCursor::End);
_testscript->ensureCursorVisible();
appendCommand("expect "+map("load "+url));
} else {
appendCommand("expect "+map("loadFinished "
+QString(ok?"true":"false")));
}
}
_urlStack->setCurrentIndex(URL_VIEW);
on__web_selectionChanged();
setLinks();
setForms();
setDom();
}
void on__setupscript_textChanged() {
bool oldRecordState(_record->isChecked());
_run->setEnabled(false);
_setupscriptactive->setEnabled(false);
try {
_setupscriptstatus->setText(trUtf8("?"));
std::shared_ptr<xml::Node> testsuites(new xml::Node("testsuite"));
Script script;
TestWebPage page(0, true);
script.parse(_setupscript->toPlainText().split('\n'), "setup");
script.run(page.mainFrame(), testsuites, QString(), false);
_setupScript.cleanup();
_setupScript.parse(_setupscript->toPlainText().split('\n'), "setup");
_setupScript.run(page.mainFrame(), testsuites, QString(), false);
_setupscriptstatus->setText(trUtf8(""));
_setupscriptactive->setEnabled(true);
} catch (std::exception &x) {
_setupscriptstatus->setText(trUtf8(""));
}
_run->setEnabled(true);
_record->setChecked(oldRecordState);
}
void on__forms_currentItemChanged(QTreeWidgetItem* item, QTreeWidgetItem*) {
if (!item) return;
_source->setPlainText(item->data(0, Qt::UserRole).toString());
}
void on__dom_currentItemChanged(QTreeWidgetItem* item, QTreeWidgetItem*) {
if (!item) return;
_source->setPlainText(item->data(0, Qt::UserRole).toString());
}
void uploadFile(QString filename) {
enterText(true);
if (_record->isChecked())
appendCommand("upload "+map(filename));
}
void unsupportedContent(QNetworkReply* reply) {
if (!_record->isChecked()) return;
QString filename(reply->url().toString().split('/').last());
if (reply->header(QNetworkRequest::ContentDispositionHeader).isValid()) {
QString part(reply->header(QNetworkRequest::ContentDispositionHeader)
.toString());
if (part.contains(QRegularExpression("attachment; *filename="))) {
part.replace(QRegularExpression(".*attachment; *filename="), "");
if (part.size()) filename = part;
}
}
QString text(_testscript->toPlainText());
int pos1(text.lastIndexOf(QRegularExpression("^do ")));
int pos2(text.lastIndexOf(QRegularExpression("^load ")));
int pos3(text.lastIndexOf(QRegularExpression("^click ")));
text.insert(std::max({pos1, pos2, pos3}), "download "+filename);
_testscript->setPlainText(text);
_testscript->moveCursor(QTextCursor::End);
_testscript->ensureCursorVisible();
}
void downloadRequested(const QNetworkRequest&) {
if (_record->isChecked())
appendCommand("download2");
}
void logging(const QString& txt) {
_log->appendPlainText(txt);
QScrollBar *vb(_log->verticalScrollBar());
if (!vb) return;
vb->setValue(vb->maximum());
}
void appendCommand(const QString& txt) {
_testscript->appendPlainText(txt);
QScrollBar *vb(_testscript->verticalScrollBar());
_testscript->moveCursor(QTextCursor::End);
_testscript->ensureCursorVisible();
if (!vb) return;
vb->setValue(vb->maximum());
}
protected:
void closeEvent(QCloseEvent* event) {
QSettings settings("mrw", "webtester");
settings.setValue("geometry", saveGeometry());
settings.setValue("windowstate", saveState());
QMainWindow::closeEvent(event);
}
bool eventFilter(QObject*, QEvent* event) {
if (_inEventFilter) return false;
_inEventFilter = true;
enterText();
QWebElement element(focused(dynamic_cast<QMouseEvent*>(event)));
switch (event->type()) {
case QEvent::KeyPress: {
QKeyEvent* k(dynamic_cast<QKeyEvent*>(event));
switch (k->key()) {
case Qt::Key_Tab:
case Qt::Key_Backtab: {
enterText(true);
} break;
case Qt::Key_Backspace: {
_keyStrokes.chop(1);
} break;
case Qt::Key_Shift: break;
case Qt::Key_Enter:
case Qt::Key_Return: {
_keyStrokes += "\\n";
_lastFocused=element;
_typing = true;
} break;
default: {
_keyStrokes += k->text();
_lastFocused=element;
_typing = true;
}
}
} break;
case QEvent::MouseButtonRelease: {
enterText(true);
_lastFocused=element;
if (_record->isChecked()) {
if (!element.isNull()) {
QString selected(selector(element));
if (handleMooTools(_lastFocused)) {
// handled in handleMooTools
} else if (_lastFocused.tagName()=="SELECT") {
// click on a select results in a value change
// find all selected options ...
QStringList v;
Q_FOREACH(QWebElement option,
_lastFocused.findAll("option")) {
//! @bug QT does not support selected
if (option.evaluateJavaScript("this.selected").toBool())
v += value(option);
}
setValue(selected, v);
} else if (_lastFocused.tagName()=="TEXTAREA" ||
_lastFocused.tagName()=="INPUT" &&
_lastFocused.attribute("type")=="text") {
// user clickt in a text edit field, so not the klick
// is important, but the text that will be typed
_typing = true;
} else {
if (_web->page()->selectedText() != "")
// user has selected a text, append a check
appendCommand("expect "+map(selected)
+" -> "+_web->page()->selectedText());
else
// user has clicked without selection, append a click
appendCommand("click "+map(selected));
}
} else {
appendCommand("# click, but where?");
}
}
} break;
case QEvent::MouseButtonPress: {
} break;
case QEvent::ChildRemoved: { // select option value changed
enterText(true);
_typing = true;
_lastFocused=element;
} break;
case QEvent::InputMethodQuery:
case QEvent::ToolTipChange:
case QEvent::MouseMove:
case QEvent::UpdateLater:
case QEvent::Paint: break;
default:;
/* _log->appendPlainText(QString("Event: %1")
.arg(eventName(event->type()))); */
}
_inEventFilter = false;
return false;
}
private:
void loadFile(QString name) {
QFile file(name);
try {
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
throw std::runtime_error("file open failed");
_testscript->setPlainText(QString::fromUtf8(file.readAll()));
if (file.error()!=QFileDevice::NoError)
throw std::runtime_error("file read failed");
_filename = name;
_actionSave->setEnabled(true);
_actionRevertToSaved->setEnabled(true);
} catch(const std::exception& x) {
QMessageBox::critical(this, tr("Open Failed"),
tr("Reading test script failed, %2. "
"Cannot read test script from file %1.")
.arg(name).arg(x.what()));
}
}
void loadSetup(QString name) {
QFile file(name);
try {
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
throw std::runtime_error("file open failed");
_setupscript->setPlainText(QString::fromUtf8(file.readAll()));
if (file.error()!=QFileDevice::NoError)
throw std::runtime_error("file read failed");
on__setupscript_textChanged();
} catch(const std::exception& x) {
QMessageBox::critical(this, tr("Open Failed"),
tr("Reading test script failed, %2. "
"Cannot read test script from file %1.")
.arg(name).arg(x.what()));
}
}
void enterText(bool force=false) {
if (!force && (!_typing || _lastFocused==focused())) return;
if (_typing && !_lastFocused.isNull())
setValue(selector(_lastFocused), value(_lastFocused));
_lastFocused = QWebElement();
_keyStrokes.clear();
_typing = false;
}
QWebElement selected() {
return _web->page()->mainFrame()->documentElement().findFirst(selector());
}
QString selector() {
if (_takeFocused->isChecked())
return selector(focused());
else if (_takeSelect->isChecked())
return _selector->text();
else
return QString(); // error
}
void highlight(QWebElement element) {
element
.evaluateJavaScript("var selection = window.getSelection();"
"selection.setBaseAndExtent(this, 0, this, 1);");
}
QWebElement focused(QMouseEvent* event = 0) {
Q_FOREACH(QWebElement element,
_web->page()->currentFrame()->findAllElements("*")) {
if (element.hasFocus()) {
return element;
}
}
if (event) { // try to find element using mouse position
QWebFrame* frame(_web->page()->frameAt(event->pos()));
if (frame) {
QWebHitTestResult hit(frame->hitTestContent(event->pos()));
if (!hit.element().isNull())
return hit.element();
if (!hit.enclosingBlockElement().isNull())
return hit.enclosingBlockElement();
}
}
return QWebElement();
}
bool unique(QString selector) {
return _web->page()->mainFrame()->findAllElements(selector).count()==1;
}
QString quote(QString txt) {
if (txt.contains('"')) return "'"+txt+"'";
return '"'+txt+'"';
}
QString selector(const QWebElement& element) {
if (element.isNull()) return QString();
if (element.hasAttribute("id") && unique("#"+element.attribute("id"))) {
return "#"+element.attribute("id");
} else if (element.hasAttribute("name") &&
unique(element.tagName().toLower()
+"[name="+quote(element.attribute("name"))+"]")) {
return element.tagName().toLower()
+"[name="+quote(element.attribute("name"))+"]";
} else {
QString res;
Q_FOREACH(QString attr, element.attributeNames()) {
if (attr=="id")
res = "#"+element.attribute("id")+res;
else if (attr=="class")
Q_FOREACH(QString c, element.attribute(attr).split(' ')) {
if (!c.isEmpty()) res = '.'+c+res;
}
else if (element.attribute(attr).isEmpty())
res+="["+attr+"]";
else
res+="["+attr+"="+quote(element.attribute(attr))+"]";
if (unique(element.tagName().toLower()+res))
return element.tagName().toLower()+res;
}
QString p(selector(element.parent()));
if (unique(p+">"+element.tagName().toLower()+res))
return p+">"+element.tagName().toLower()+res;
QString s(selector(element.previousSibling()));
if (unique(s+"+"+element.tagName().toLower()+res))
return s+"+"+element.tagName().toLower()+res;
if (!p.isEmpty())
return p+">"+element.tagName().toLower()+res;
if (!s.isEmpty())
return s+"+"+element.tagName().toLower()+res;
return element.tagName().toLower()+res;
}
}
QString value(QWebElement element) {
return element.evaluateJavaScript("this.value").toString();
//! @bug Bug in Qt, attribute("value") is always empty
// if (element.hasAttribute("value"))
// return element.attribute("value");
// else
// return element.toPlainText();
}
QString map(QString in) {
if (_setupscriptactive->isEnabled()
&& _setupscriptactive->isChecked()) {
return _setupScript.insertvars(in);
}
return in;
}
void javascript(const QString& selector, QString code) {
if (_record->isChecked())
appendCommand("do "+map(selector)+"\n "
+map(code).replace("\n", "\n "));
}
void cleanup(const QString& selector) {
QString text(_testscript->toPlainText());
QStringList lines(text.split("\n"));
bool changed(false);
while (lines.size() &&
(lines.last()=="click "+selector ||
lines.last().startsWith("setvalue "+selector+" -> "))) {
lines.removeLast();
changed = true;
}
if (changed) {
_testscript->setPlainText(lines.join("\n"));
_testscript->moveCursor(QTextCursor::End);
_testscript->ensureCursorVisible();
}
}
void setValue(const QString& selector, QString code) {
if (_record->isChecked()) {
cleanup(selector);
appendCommand("setvalue "+map(selector)+" -> '"
+map(code).replace("'", "\\'").replace("\n", "\\n")+"'");
}
}
void setValue(const QString& selector, QStringList code) {
if (_record->isChecked()) {
cleanup(selector);
appendCommand("setvalue "+map(selector)+" -> '"+
map(code.replaceInStrings("'", "\\'")
.replaceInStrings("\n", "\\n")
.join("', '")+"'"));
}
}
bool handleMooTools(QWebElement element) {
QString selected(selector(element));
QRegularExpressionMatch mooCombo
(QRegularExpression("^(#jform_[_A-Za-z0-9]+)_chzn>.*$")
.match(selected));
QRegularExpressionMatch mooComboItem
(QRegularExpression
("^li\\.highlighted(\\.result-selected)?\\.active-result$")
.match(selected));
if (mooCombo.hasMatch()) {
// special treatment for moo tools combobox (e.g. used
// in joomla)
appendCommand("click realmouse "+map(mooCombo.captured(1)+">a"));
appendCommand("sleep "+map("1"));
return true;
} else if (mooComboItem.hasMatch()) {
// special treatment for item in moo tools combobox
appendCommand
("click realmouse "+map("li.active-result[data-option-array-index=\""
+element.attribute("data-option-array-index")
+"\"]"));
appendCommand("sleep "+map("1"));
return true;
} else if (element.tagName()=="INPUT") {
for (QWebElement e(element); !(e=e.parent()).isNull();)
if (e.hasClass("chzn-container")) {
_lastFocused = e;
appendCommand("# moo tools combobox with search field");
appendCommand("# first set all elements visible");
javascript(map(selector(e)+" ul"),
"this.style.height = \"auto\";\n"
"this.style.maxHeight = \"auto\";\n"
"this.style.overflow = \"visible\"");
appendCommand("sleep "+map("1"));
appendCommand("# moo tools open combobox");
appendCommand("click realmouse "+map(selector(e)));
return true;
}
} else if (element.hasAttribute("id") && // is it a selected option?
element.attribute("id").contains("_chzn_o_")) {
appendCommand("# moo tools select item");
appendCommand("click realmouse "+map(selector(element)));
_lastFocused = element;
return true;
}
return false;
}
QString execute(const QString& selector, const QString& code) {
javascript(selector, code);
return _web->page()->mainFrame()->documentElement().findFirst(selector)
.evaluateJavaScript(code).toString();
}
void setLinks() {
QWebElementCollection links(_web->page()->mainFrame()->documentElement()
.findAll("a"));
_links->setRowCount(links.count());
for (int row(0); row<_links->rowCount(); ++row) {
{
QTableWidgetItem* item(new QTableWidgetItem());
item->setText(links[row].attribute("href"));
_links->setItem(row, 0, item);
} {
QTableWidgetItem* item(new QTableWidgetItem());
item->setText(links[row].hasAttribute("title")
? links[row].attribute("title")
: links[row].toInnerXml());
_links->setItem(row, 1, item);
}
_links->horizontalHeader()->resizeSections(QHeaderView::Stretch);
}
}
void setForms() {
QWebElementCollection forms(_web->page()->mainFrame()->documentElement()
.findAll("form"));
_forms->clear();
Q_FOREACH(const QWebElement &form, forms) {
addDomElement(form, _forms->invisibleRootItem());
}
}
void setDom() {
_dom->clear();
addDomElement(_web->page()->mainFrame()->documentElement(),
_dom->invisibleRootItem());
}
//void addDomChildren(const QWebElement&, QTreeWidgetItem*);
void addDomElement(const QWebElement &element,
QTreeWidgetItem *parent) {
QTreeWidgetItem *item(new QTreeWidgetItem());
item->setText(0, element.tagName());
item->setData(0, Qt::UserRole, element.toOuterXml());
parent->addChild(item);
addDomChildren(element, item);
}
void addDomChildren(const QWebElement &parentElement,
QTreeWidgetItem *parentItem) {
for (QWebElement element = parentElement.firstChild();
!element.isNull();
element = element.nextSibling()) {
addDomElement(element, parentItem);
}
}
QString eventName(QEvent::Type t) {
switch (t) {
case QEvent::None: return "QEvent::None - Not an event.";
case QEvent::ActionAdded: return "QEvent::ActionAdded - A new action has been added (QActionEvent).";
case QEvent::ActionChanged: return "QEvent::ActionChanged - An action has been changed (QActionEvent).";
case QEvent::ActionRemoved: return "QEvent::ActionRemoved - An action has been removed (QActionEvent).";
case QEvent::ActivationChange: return "QEvent::ActivationChange - A widget's top-level window activation state has changed.";
case QEvent::ApplicationActivate: return "QEvent::ApplicationActivate - This enum has been deprecated. Use ApplicationStateChange instead.";
//case QEvent::ApplicationActivated: return "QEvent::ApplicationActivated - This enum has been deprecated. Use ApplicationStateChange instead.";
case QEvent::ApplicationDeactivate: return "QEvent::ApplicationDeactivate - This enum has been deprecated. Use ApplicationStateChange instead.";
case QEvent::ApplicationFontChange: return "QEvent::ApplicationFontChange - The default application font has changed.";
case QEvent::ApplicationLayoutDirectionChange: return "QEvent::ApplicationLayoutDirectionChange - The default application layout direction has changed.";
case QEvent::ApplicationPaletteChange: return "QEvent::ApplicationPaletteChange - The default application palette has changed.";
case QEvent::ApplicationStateChange: return "QEvent::ApplicationStateChange - The state of the application has changed.";
case QEvent::ApplicationWindowIconChange: return "QEvent::ApplicationWindowIconChange - The application's icon has changed.";
case QEvent::ChildAdded: return "QEvent::ChildAdded - An object gets a child (QChildEvent).";
case QEvent::ChildPolished: return "QEvent::ChildPolished - A widget child gets polished (QChildEvent).";
case QEvent::ChildRemoved: return "QEvent::ChildRemoved - An object loses a child (QChildEvent).";
case QEvent::Clipboard: return "QEvent::Clipboard - The clipboard contents have changed (QClipboardEvent).";
case QEvent::Close: return "QEvent::Close - Widget was closed (QCloseEvent).";
case QEvent::CloseSoftwareInputPanel: return "QEvent::CloseSoftwareInputPanel - A widget wants to close the software input panel (SIP).";
case QEvent::ContentsRectChange: return "QEvent::ContentsRectChange - The margins of the widget's content rect changed.";
case QEvent::ContextMenu: return "QEvent::ContextMenu - Context popup menu (QContextMenuEvent).";
case QEvent::CursorChange: return "QEvent::CursorChange - The widget's cursor has changed.";
case QEvent::DeferredDelete: return "QEvent::DeferredDelete - The object will be deleted after it has cleaned up (QDeferredDeleteEvent).";
case QEvent::DragEnter: return "QEvent::DragEnter - The cursor enters a widget during a drag and drop operation (QDragEnterEvent).";
case QEvent::DragLeave: return "QEvent::DragLeave - The cursor leaves a widget during a drag and drop operation (QDragLeaveEvent).";
case QEvent::DragMove: return "QEvent::DragMove - A drag and drop operation is in progress (QDragMoveEvent).";
case QEvent::Drop: return "QEvent::Drop - A drag and drop operation is completed (QDropEvent).";
case QEvent::DynamicPropertyChange: return "QEvent::DynamicPropertyChange - A dynamic property was added, changed, or removed from the object.";
case QEvent::EnabledChange: return "QEvent::EnabledChange - Widget's enabled state has changed.";
case QEvent::Enter: return "QEvent::Enter - Mouse enters widget's boundaries (QEnterEvent).";
//case QEvent::EnterEditFocus: return "QEvent::EnterEditFocus - An editor widget gains focus for editing. QT_KEYPAD_NAVIGATION must be defined.";
case QEvent::EnterWhatsThisMode: return "QEvent::EnterWhatsThisMode - Send to toplevel widgets when the application enters \"What's This?\" mode.";
case QEvent::Expose: return "QEvent::Expose - Sent to a window when its on-screen contents are invalidated and need to be flushed from the backing store.";
case QEvent::FileOpen: return "QEvent::FileOpen - File open request (QFileOpenEvent).";
case QEvent::FocusIn: return "QEvent::FocusIn - Widget or Window gains keyboard focus (QFocusEvent).";
case QEvent::FocusOut: return "QEvent::FocusOut - Widget or Window loses keyboard focus (QFocusEvent).";
case QEvent::FocusAboutToChange: return "QEvent::FocusAboutToChange - Widget or Window focus is about to change (QFocusEvent)";
case QEvent::FontChange: return "QEvent::FontChange - Widget's font has changed.";
case QEvent::Gesture: return "QEvent::Gesture - A gesture was triggered (QGestureEvent).";
case QEvent::GestureOverride: return "QEvent::GestureOverride - A gesture override was triggered (QGestureEvent).";
case QEvent::GrabKeyboard: return "QEvent::GrabKeyboard - Item gains keyboard grab (QGraphicsItem only).";
case QEvent::GrabMouse: return "QEvent::GrabMouse - Item gains mouse grab (QGraphicsItem only).";
case QEvent::GraphicsSceneContextMenu: return "QEvent::GraphicsSceneContextMenu - Context popup menu over a graphics scene (QGraphicsSceneContextMenuEvent).";
case QEvent::GraphicsSceneDragEnter: return "QEvent::GraphicsSceneDragEnter - The cursor enters a graphics scene during a drag and drop operation (QGraphicsSceneDragDropEvent).";
case QEvent::GraphicsSceneDragLeave: return "QEvent::GraphicsSceneDragLeave - The cursor leaves a graphics scene during a drag and drop operation (QGraphicsSceneDragDropEvent).";
case QEvent::GraphicsSceneDragMove: return "QEvent::GraphicsSceneDragMove - A drag and drop operation is in progress over a scene (QGraphicsSceneDragDropEvent).";
case QEvent::GraphicsSceneDrop: return "QEvent::GraphicsSceneDrop - A drag and drop operation is completed over a scene (QGraphicsSceneDragDropEvent).";
case QEvent::GraphicsSceneHelp: return "QEvent::GraphicsSceneHelp - The user requests help for a graphics scene (QHelpEvent).";
case QEvent::GraphicsSceneHoverEnter: return "QEvent::GraphicsSceneHoverEnter - The mouse cursor enters a hover item in a graphics scene (QGraphicsSceneHoverEvent).";
case QEvent::GraphicsSceneHoverLeave: return "QEvent::GraphicsSceneHoverLeave - The mouse cursor leaves a hover item in a graphics scene (QGraphicsSceneHoverEvent).";
case QEvent::GraphicsSceneHoverMove: return "QEvent::GraphicsSceneHoverMove - The mouse cursor moves inside a hover item in a graphics scene (QGraphicsSceneHoverEvent).";
case QEvent::GraphicsSceneMouseDoubleClick: return "QEvent::GraphicsSceneMouseDoubleClick - Mouse press again (double click) in a graphics scene (QGraphicsSceneMouseEvent).";
case QEvent::GraphicsSceneMouseMove: return "QEvent::GraphicsSceneMouseMove - Move mouse in a graphics scene (QGraphicsSceneMouseEvent).";
case QEvent::GraphicsSceneMousePress: return "QEvent::GraphicsSceneMousePress - Mouse press in a graphics scene (QGraphicsSceneMouseEvent).";
case QEvent::GraphicsSceneMouseRelease: return "QEvent::GraphicsSceneMouseRelease - Mouse release in a graphics scene (QGraphicsSceneMouseEvent).";
case QEvent::GraphicsSceneMove: return "QEvent::GraphicsSceneMove - Widget was moved (QGraphicsSceneMoveEvent).";
case QEvent::GraphicsSceneResize: return "QEvent::GraphicsSceneResize - Widget was resized (QGraphicsSceneResizeEvent).";
case QEvent::GraphicsSceneWheel: return "QEvent::GraphicsSceneWheel - Mouse wheel rolled in a graphics scene (QGraphicsSceneWheelEvent).";
case QEvent::Hide: return "QEvent::Hide - Widget was hidden (QHideEvent).";
case QEvent::HideToParent: return "QEvent::HideToParent - A child widget has been hidden.";
case QEvent::HoverEnter: return "QEvent::HoverEnter - The mouse cursor enters a hover widget (QHoverEvent).";
case QEvent::HoverLeave: return "QEvent::HoverLeave - The mouse cursor leaves a hover widget (QHoverEvent).";
case QEvent::HoverMove: return "QEvent::HoverMove - The mouse cursor moves inside a hover widget (QHoverEvent).";
case QEvent::IconDrag: return "QEvent::IconDrag - The main icon of a window has been dragged away (QIconDragEvent).";
case QEvent::IconTextChange: return "QEvent::IconTextChange - Widget's icon text has been changed.";
case QEvent::InputMethod: return "QEvent::InputMethod - An input method is being used (QInputMethodEvent).";
case QEvent::InputMethodQuery: return "QEvent::InputMethodQuery - A input method query event (QInputMethodQueryEvent)";
case QEvent::KeyboardLayoutChange: return "QEvent::KeyboardLayoutChange - The keyboard layout has changed.";
case QEvent::KeyPress: return "QEvent::KeyPress - Key press (QKeyEvent).";
case QEvent::KeyRelease: return "QEvent::KeyRelease - Key release (QKeyEvent).";
case QEvent::LanguageChange: return "QEvent::LanguageChange - The application translation changed.";
case QEvent::LayoutDirectionChange: return "QEvent::LayoutDirectionChange - The direction of layouts changed.";
case QEvent::LayoutRequest: return "QEvent::LayoutRequest - Widget layout needs to be redone.";
case QEvent::Leave: return "QEvent::Leave - Mouse leaves widget's boundaries.";
//case QEvent::LeaveEditFocus: return "QEvent::LeaveEditFocus - An editor widget loses focus for editing. QT_KEYPAD_NAVIGATION must be defined.";
case QEvent::LeaveWhatsThisMode: return "QEvent::LeaveWhatsThisMode - Send to toplevel widgets when the application leaves \"What's This?\" mode.";
case QEvent::LocaleChange: return "QEvent::LocaleChange - The system locale has changed.";
case QEvent::NonClientAreaMouseButtonDblClick: return "QEvent::NonClientAreaMouseButtonDblClick - A mouse double click occurred outside the client area.";
case QEvent::NonClientAreaMouseButtonPress: return "QEvent::NonClientAreaMouseButtonPress - A mouse button press occurred outside the client area.";
case QEvent::NonClientAreaMouseButtonRelease: return "QEvent::NonClientAreaMouseButtonRelease - A mouse button release occurred outside the client area.";
case QEvent::NonClientAreaMouseMove: return "QEvent::NonClientAreaMouseMove - A mouse move occurred outside the client area.";
case QEvent::MacSizeChange: return "QEvent::MacSizeChange - The user changed his widget sizes (Mac OS X only).";
case QEvent::MetaCall: return "QEvent::MetaCall - An asynchronous method invocation via QMetaObject::invokeMethod().";
case QEvent::ModifiedChange: return "QEvent::ModifiedChange - Widgets modification state has been changed.";
case QEvent::MouseButtonDblClick: return "QEvent::MouseButtonDblClick - Mouse press again (QMouseEvent).";
case QEvent::MouseButtonPress: return "QEvent::MouseButtonPress - Mouse press (QMouseEvent).";
case QEvent::MouseButtonRelease: return "QEvent::MouseButtonRelease - Mouse release (QMouseEvent).";
case QEvent::MouseMove: return "QEvent::MouseMove - Mouse move (QMouseEvent).";
case QEvent::MouseTrackingChange: return "QEvent::MouseTrackingChange - The mouse tracking state has changed.";
case QEvent::Move: return "QEvent::Move - Widget's position changed (QMoveEvent).";
case QEvent::NativeGesture: return "QEvent::NativeGesture - The system has detected a gesture (QNativeGestureEvent).";
case QEvent::OrientationChange: return "QEvent::OrientationChange - The screens orientation has changes (QScreenOrientationChangeEvent)";
case QEvent::Paint: return "QEvent::Paint - Screen update necessary (QPaintEvent).";
case QEvent::PaletteChange: return "QEvent::PaletteChange - Palette of the widget changed.";
case QEvent::ParentAboutToChange: return "QEvent::ParentAboutToChange - The widget parent is about to change.";
case QEvent::ParentChange: return "QEvent::ParentChange - The widget parent has changed.";
case QEvent::PlatformPanel: return "QEvent::PlatformPanel - A platform specific panel has been requested.";
case QEvent::Polish: return "QEvent::Polish - The widget is polished.";
case QEvent::PolishRequest: return "QEvent::PolishRequest - The widget should be polished.";
case QEvent::QueryWhatsThis: return "QEvent::QueryWhatsThis - The widget should accept the event if it has \"What's This?\" help.";
//case QEvent::ReadOnlyChange: return "QEvent::ReadOnlyChange - Widget's read-only state has changed (since Qt 5.4).";
case QEvent::RequestSoftwareInputPanel: return "QEvent::RequestSoftwareInputPanel - A widget wants to open a software input panel (SIP).";
case QEvent::Resize: return "QEvent::Resize - Widget's size changed (QResizeEvent).";
case QEvent::ScrollPrepare: return "QEvent::ScrollPrepare - The object needs to fill in its geometry information (QScrollPrepareEvent).";
case QEvent::Scroll: return "QEvent::Scroll - The object needs to scroll to the supplied position (QScrollEvent).";
case QEvent::Shortcut: return "QEvent::Shortcut - Key press in child for shortcut key handling (QShortcutEvent).";
case QEvent::ShortcutOverride: return "QEvent::ShortcutOverride - Key press in child, for overriding shortcut key handling (QKeyEvent).";
case QEvent::Show: return "QEvent::Show - Widget was shown on screen (QShowEvent).";
case QEvent::ShowToParent: return "QEvent::ShowToParent - A child widget has been shown.";
case QEvent::SockAct: return "QEvent::SockAct - Socket activated, used to implement QSocketNotifier.";
case QEvent::StateMachineSignal: return "QEvent::StateMachineSignal - A signal delivered to a state machine (QStateMachine::SignalEvent).";
case QEvent::StateMachineWrapped: return "QEvent::StateMachineWrapped - The event is a wrapper for, i.e., contains, another event (QStateMachine::WrappedEvent).";
case QEvent::StatusTip: return "QEvent::StatusTip - A status tip is requested (QStatusTipEvent).";
case QEvent::StyleChange: return "QEvent::StyleChange - Widget's style has been changed.";
case QEvent::TabletMove: return "QEvent::TabletMove - Wacom tablet move (QTabletEvent).";
case QEvent::TabletPress: return "QEvent::TabletPress - Wacom tablet press (QTabletEvent).";
case QEvent::TabletRelease: return "QEvent::TabletRelease - Wacom tablet release (QTabletEvent).";
case QEvent::OkRequest: return "QEvent::OkRequest - Ok button in decoration pressed. Supported only for Windows CE.";
case QEvent::TabletEnterProximity: return "QEvent::TabletEnterProximity - Wacom tablet enter proximity event (QTabletEvent), sent to QApplication.";
case QEvent::TabletLeaveProximity: return "QEvent::TabletLeaveProximity - Wacom tablet leave proximity event (QTabletEvent), sent to QApplication.";
case QEvent::ThreadChange: return "QEvent::ThreadChange - The object is moved to another thread. This is the last event sent to this object in the previous thread. See QObject::moveToThread().";
case QEvent::Timer: return "QEvent::Timer - Regular timer events (QTimerEvent).";
case QEvent::ToolBarChange: return "QEvent::ToolBarChange - The toolbar button is toggled on Mac OS X.";
case QEvent::ToolTip: return "QEvent::ToolTip - A tooltip was requested (QHelpEvent).";
case QEvent::ToolTipChange: return "QEvent::ToolTipChange - The widget's tooltip has changed.";
case QEvent::TouchBegin: return "QEvent::TouchBegin - Beginning of a sequence of touch-screen or track-pad events (QTouchEvent).";
case QEvent::TouchCancel: return "QEvent::TouchCancel - Cancellation of touch-event sequence (QTouchEvent).";
case QEvent::TouchEnd: return "QEvent::TouchEnd - End of touch-event sequence (QTouchEvent).";
case QEvent::TouchUpdate: return "QEvent::TouchUpdate - Touch-screen event (QTouchEvent).";
case QEvent::UngrabKeyboard: return "QEvent::UngrabKeyboard - Item loses keyboard grab (QGraphicsItem only).";
case QEvent::UngrabMouse: return "QEvent::UngrabMouse - Item loses mouse grab (QGraphicsItem only).";
case QEvent::UpdateLater: return "QEvent::UpdateLater - The widget should be queued to be repainted at a later time.";
case QEvent::UpdateRequest: return "QEvent::UpdateRequest - The widget should be repainted.";
case QEvent::WhatsThis: return "QEvent::WhatsThis - The widget should reveal \"What's This?\" help (QHelpEvent).";
case QEvent::WhatsThisClicked: return "QEvent::WhatsThisClicked - A link in a widget's \"What's This?\" help was clicked.";
case QEvent::Wheel: return "QEvent::Wheel - Mouse wheel rolled (QWheelEvent).";
case QEvent::WinEventAct: return "QEvent::WinEventAct - A Windows-specific activation event has occurred.";
case QEvent::WindowActivate: return "QEvent::WindowActivate - Window was activated.";
case QEvent::WindowBlocked: return "QEvent::WindowBlocked - The window is blocked by a modal dialog.";
case QEvent::WindowDeactivate: return "QEvent::WindowDeactivate - Window was deactivated.";
case QEvent::WindowIconChange: return "QEvent::WindowIconChange - The window's icon has changed.";
case QEvent::WindowStateChange: return "QEvent::WindowStateChange - The window's state (minimized, maximized or full-screen) has changed (QWindowStateChangeEvent).";
case QEvent::WindowTitleChange: return "QEvent::WindowTitleChange - The window title has changed.";
case QEvent::WindowUnblocked: return "QEvent::WindowUnblocked - The window is unblocked after a modal dialog exited.";
case QEvent::WinIdChange: return "QEvent::WinIdChange - The window system identifer for this native widget has changed.";
case QEvent::ZOrderChange: return "QEvent::ZOrderChange - The widget's z-order has changed. This event is never sent to top level windows.";
default:
return QString("%1").arg(t);
}
}
private:
enum UrlStack {
URL_VIEW = 0,
PROGRESS_VIEW
};
private:
QString _filename;
QWebElement _lastFocused; // cache for last focussed element
QString _keyStrokes; // collect key strokes
bool _typing; // user is typing
bool _inEventFilter; // actually handling event filter
Script _setupScript;
};
#endif // TESTGUI_HXX