2015-02-04 14:01:55 +00:00
|
|
|
/*! @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>
|
2015-04-02 07:45:12 +00:00
|
|
|
#include <QScrollBar>
|
2015-02-04 14:01:55 +00:00
|
|
|
#include <QFile>
|
|
|
|
#include <QMessageBox>
|
|
|
|
#include <ui_testgui.h>
|
|
|
|
#include <stdexcept>
|
|
|
|
#include <QNetworkReply>
|
|
|
|
|
|
|
|
class TestGUI: public QMainWindow, protected Ui::TestGUI {
|
|
|
|
Q_OBJECT;
|
|
|
|
public:
|
|
|
|
explicit TestGUI(QWidget *parent = 0, QString url = 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);
|
|
|
|
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&)));
|
|
|
|
}
|
|
|
|
virtual ~TestGUI() {}
|
|
|
|
public Q_SLOTS:
|
|
|
|
void on__load_clicked() {
|
|
|
|
enterText(true);
|
|
|
|
if (_record->isChecked())
|
2015-04-02 07:45:12 +00:00
|
|
|
appendCommand("load "+_url->text());
|
2015-02-04 14:01:55 +00:00
|
|
|
_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;
|
|
|
|
on__actionRevertToSaved_triggered(name);
|
|
|
|
}
|
|
|
|
void on__actionRevertToSaved_triggered() {
|
|
|
|
on__actionRevertToSaved_triggered(_filename);
|
|
|
|
}
|
|
|
|
void on__actionRevertToSaved_triggered(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 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();
|
2015-04-02 07:45:12 +00:00
|
|
|
_log->clear();
|
2015-02-04 14:01:55 +00:00
|
|
|
_filename.clear();
|
|
|
|
_actionSave->setEnabled(false);
|
|
|
|
_actionRevertToSaved->setEnabled(false);
|
|
|
|
}
|
|
|
|
void on__run_clicked() {
|
|
|
|
bool oldRecordState(_record->isChecked());
|
|
|
|
_run->setEnabled(false);
|
|
|
|
try {
|
|
|
|
xml::Node testsuites("testsuites");
|
|
|
|
xml::Node testsuite("testsuite");
|
|
|
|
testsuite.attr("name") = "on-the-fly";
|
|
|
|
testsuite.attr("timestamp") =
|
|
|
|
QDateTime::currentDateTime().toString(Qt::ISODate).toStdString();
|
|
|
|
xml::Node testcase("testcase");
|
|
|
|
testcase.attr("classname") = "testsuite-preparation";
|
|
|
|
QString text(_testscript->textCursor().selectedText());
|
|
|
|
if (text.isEmpty()) text = _testscript->toPlainText();
|
|
|
|
Script script;
|
|
|
|
connect(&script, SIGNAL(logging(QString)), SLOT(logging(QString)));
|
|
|
|
script.parse(text.split('\n'));
|
|
|
|
script.run(_web->page()->mainFrame(), testsuite, QString(), false);
|
|
|
|
} catch (std::exception &x) {
|
|
|
|
QMessageBox::critical(this, tr("Script Failed"),
|
|
|
|
tr("Script failed with message:\n%1")
|
|
|
|
.arg(x.what()));
|
|
|
|
}
|
|
|
|
_run->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__jsClick_clicked() {
|
|
|
|
enterText(true);
|
|
|
|
execute(selector(),
|
|
|
|
"this.click();");
|
|
|
|
// "var evObj = document.createEvent('MouseEvents');\n"
|
|
|
|
// "evObj.initEvent( 'click', true, true );\n"
|
|
|
|
// "this.dispatchEvent(evObj);");
|
|
|
|
}
|
|
|
|
void on__jsValue_clicked() {
|
|
|
|
enterText(true);
|
|
|
|
QWebElement element(selected());
|
|
|
|
execute(selector(element),
|
|
|
|
"this.value='"+value(element).replace("\n", "\\n")+"';");
|
|
|
|
}
|
|
|
|
void on__jsExecute_clicked() {
|
|
|
|
enterText(true);
|
|
|
|
execute(selector(), _javascriptCode->toPlainText());
|
|
|
|
}
|
|
|
|
void on__web_linkClicked(const QUrl& url) {
|
|
|
|
enterText(true);
|
|
|
|
if (_record->isChecked())
|
2015-04-02 07:45:12 +00:00
|
|
|
appendCommand("load "+url.url());
|
2015-02-04 14:01:55 +00:00
|
|
|
}
|
|
|
|
void on__web_loadProgress(int progress) {
|
|
|
|
enterText(true);
|
|
|
|
_progress->setValue(progress);
|
|
|
|
}
|
|
|
|
void on__web_loadStarted() {
|
|
|
|
enterText(true);
|
|
|
|
if (_record->isChecked())
|
2015-04-02 07:45:12 +00:00
|
|
|
appendCommand("expect loadStarted");
|
2015-02-04 14:01:55 +00:00
|
|
|
_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())
|
2015-04-02 07:45:12 +00:00
|
|
|
appendCommand("expect urlChanged "+url.url());
|
2015-02-04 14:01:55 +00:00
|
|
|
}
|
|
|
|
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())
|
2015-04-02 07:45:12 +00:00
|
|
|
appendCommand("expect loadFinished "
|
2015-02-04 14:01:55 +00:00
|
|
|
+QString(ok?"true":"false"));
|
|
|
|
_urlStack->setCurrentIndex(URL_VIEW);
|
|
|
|
on__web_selectionChanged();
|
|
|
|
setLinks();
|
|
|
|
setForms();
|
|
|
|
setDom();
|
|
|
|
}
|
|
|
|
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())
|
2015-04-02 07:45:12 +00:00
|
|
|
appendCommand("upload "+filename);
|
2015-02-04 14:01:55 +00:00
|
|
|
}
|
|
|
|
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());
|
2015-02-27 15:39:08 +00:00
|
|
|
if (part.contains(QRegularExpression("attachment; *filename="))) {
|
|
|
|
part.replace(QRegularExpression(".*attachment; *filename="), "");
|
2015-02-04 14:01:55 +00:00
|
|
|
if (part.size()) filename = part;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
QString text(_testscript->toPlainText());
|
2015-02-27 15:39:08 +00:00
|
|
|
int pos1(text.lastIndexOf(QRegularExpression("^do ")));
|
|
|
|
int pos2(text.lastIndexOf(QRegularExpression("^load ")));
|
2015-02-04 14:01:55 +00:00
|
|
|
text.insert(pos1>pos2?pos1:pos2, "download "+filename);
|
|
|
|
_testscript->setPlainText(text);
|
|
|
|
_testscript->moveCursor(QTextCursor::End);
|
|
|
|
_testscript->ensureCursorVisible();
|
|
|
|
}
|
|
|
|
void downloadRequested(const QNetworkRequest&) {
|
|
|
|
if (_record->isChecked())
|
2015-04-02 07:45:12 +00:00
|
|
|
appendCommand("download2");
|
2015-02-04 14:01:55 +00:00
|
|
|
}
|
2015-04-02 07:45:12 +00:00
|
|
|
void logging(const QString& txt) {
|
2015-02-04 14:01:55 +00:00
|
|
|
_log->appendPlainText(txt);
|
2015-04-02 07:45:12 +00:00
|
|
|
QScrollBar *vb(_log->verticalScrollBar());
|
|
|
|
if (!vb) return;
|
|
|
|
vb->setValue(vb->maximum());
|
|
|
|
}
|
|
|
|
void appendCommand(const QString& txt) {
|
|
|
|
_testscript->appendPlainText(txt);
|
|
|
|
QScrollBar *vb(_testscript->verticalScrollBar());
|
|
|
|
if (!vb) return;
|
|
|
|
vb->setValue(vb->maximum());
|
2015-02-04 14:01:55 +00:00
|
|
|
}
|
|
|
|
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;
|
2015-02-27 15:39:08 +00:00
|
|
|
if (_record->isChecked() && !element.isNull()) {
|
|
|
|
QString selected(selector(_lastFocused));
|
|
|
|
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)
|
2015-04-02 07:45:12 +00:00
|
|
|
appendCommand("click "+mooCombo.captured(1)+">a");
|
|
|
|
appendCommand("sleep 1");
|
2015-02-27 15:39:08 +00:00
|
|
|
} else if (mooComboItem.hasMatch()) {
|
|
|
|
// special treatment for item in moo tools combobox
|
2015-04-02 07:45:12 +00:00
|
|
|
appendCommand
|
2015-02-27 15:39:08 +00:00
|
|
|
("click li.active-result[data-option-array-index=\""
|
|
|
|
+element.attribute("data-option-array-index")+"\"]");
|
2015-04-02 07:45:12 +00:00
|
|
|
appendCommand("sleep 1");
|
2015-02-27 15:39:08 +00:00
|
|
|
} else {
|
2015-04-02 07:45:12 +00:00
|
|
|
appendCommand("click "+selected);
|
2015-02-27 15:39:08 +00:00
|
|
|
}
|
|
|
|
}
|
2015-02-04 14:01:55 +00:00
|
|
|
} break;
|
|
|
|
case QEvent::InputMethodQuery:
|
|
|
|
case QEvent::ToolTipChange:
|
|
|
|
case QEvent::MouseMove:
|
|
|
|
case QEvent::UpdateLater:
|
|
|
|
case QEvent::Paint: break;
|
|
|
|
default: ;//LOG("Event: "<<event->type());
|
|
|
|
}
|
|
|
|
_inEventFilter = false;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
private:
|
|
|
|
void enterText(bool force=false) {
|
|
|
|
if (!force && (!_typing || _lastFocused==focused())) return;
|
|
|
|
if (_keyStrokes.size() && !_lastFocused.isNull()) {
|
|
|
|
store(selector(_lastFocused), "this.value='"
|
|
|
|
+value(_lastFocused).replace("\n", "\\n")+"';");
|
|
|
|
}
|
|
|
|
_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()));
|
2015-02-27 15:39:08 +00:00
|
|
|
if (frame) {
|
|
|
|
QWebHitTestResult hit(frame->hitTestContent(event->pos()));
|
|
|
|
if (!hit.element().isNull())
|
|
|
|
return hit.element();
|
|
|
|
if (!hit.enclosingBlockElement().isNull())
|
|
|
|
return hit.enclosingBlockElement();
|
|
|
|
}
|
2015-02-04 14:01:55 +00:00
|
|
|
}
|
|
|
|
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();
|
|
|
|
}
|
|
|
|
void store(const QString& selector, QString code) {
|
|
|
|
if (_record->isChecked())
|
2015-04-02 07:45:12 +00:00
|
|
|
appendCommand("do "+selector+"\n "
|
|
|
|
+code.replace("\n", "\\n"));
|
2015-02-04 14:01:55 +00:00
|
|
|
}
|
|
|
|
void execute(const QString& selector, const QString& code) {
|
|
|
|
store(selector, code);
|
|
|
|
_web->page()->mainFrame()->documentElement().findFirst(selector)
|
|
|
|
.evaluateJavaScript(code);
|
|
|
|
}
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
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
|
|
|
|
};
|
|
|
|
|
|
|
|
#endif // TESTGUI_HXX
|