now, multi document editing works mostly as designed; unfortunately qt does not send an event when the visibility of a tab window changes
This commit is contained in:
@@ -1,23 +1,32 @@
|
|||||||
#ifndef __SCRIPTFILE__HXX
|
#ifndef __SCRIPTFILE__HXX
|
||||||
#define __SCRIPTFILE__HXX
|
#define __SCRIPTFILE__HXX
|
||||||
|
|
||||||
|
#include <commands.hxx>
|
||||||
#include <ui_scriptfile.hxx>
|
#include <ui_scriptfile.hxx>
|
||||||
|
#include <QMessageBox>
|
||||||
|
#include <QScrollBar>
|
||||||
|
#include <QTextDocumentFragment>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
class ScriptFile: public QDockWidget, protected Ui::ScriptFile {
|
class ScriptFile: public QDockWidget, protected Ui::ScriptFile {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
|
void modified(ScriptFile*);
|
||||||
void link(QString);
|
void link(QString);
|
||||||
void include(QString);
|
void include(QString);
|
||||||
void close(ScriptFile*);
|
void close(ScriptFile*);
|
||||||
|
void run(const QString&, const QString&, bool, Script&);
|
||||||
public:
|
public:
|
||||||
ScriptFile(QWidget* p=0): QDockWidget(p) {
|
ScriptFile(QWidget* p = nullptr): QDockWidget(p) {
|
||||||
setupUi(this);
|
setupUi(this);
|
||||||
|
assert(connect(_editor, SIGNAL(textChanged()), SLOT(modified())));
|
||||||
assert(connect(_editor, SIGNAL(include(QString)), SIGNAL(include(QString))));
|
assert(connect(_editor, SIGNAL(include(QString)), SIGNAL(include(QString))));
|
||||||
assert(connect(_editor, SIGNAL(link(QString)), SIGNAL(link(QString))));
|
assert(connect(_editor, SIGNAL(link(QString)), SIGNAL(link(QString))));
|
||||||
_searchBar->hide();
|
_searchBar->hide();
|
||||||
_replaceBar->hide();
|
_replaceBar->hide();
|
||||||
_pageBar->hide();
|
_lineBar->hide();
|
||||||
|
_progress->hide();
|
||||||
|
_status->setCurrentIndex(STATUS_NONE);
|
||||||
}
|
}
|
||||||
CodeEditor* editor() {
|
CodeEditor* editor() {
|
||||||
return _editor;
|
return _editor;
|
||||||
@@ -30,10 +39,208 @@ class ScriptFile: public QDockWidget, protected Ui::ScriptFile {
|
|||||||
setWindowTitle(name+"[*]");
|
setWindowTitle(name+"[*]");
|
||||||
setWindowModified(false);
|
setWindowModified(false);
|
||||||
}
|
}
|
||||||
|
public Q_SLOTS:
|
||||||
|
void load(QString name = QString()) {
|
||||||
|
if (isWindowModified() &&
|
||||||
|
QMessageBox::question(this, tr("Changes Not Saved"),
|
||||||
|
tr("Load script without saving changes?"))
|
||||||
|
!= QMessageBox::Yes)
|
||||||
|
return;
|
||||||
|
QString oldname(_name);
|
||||||
|
if (!name.isEmpty()) _name = name;
|
||||||
|
QFileInfo info(name);
|
||||||
|
if (info.absoluteDir()==QDir::current()) _name = info.fileName();
|
||||||
|
try {
|
||||||
|
QFile file(_name);
|
||||||
|
if (!file.open(QIODevice::ReadOnly|QIODevice::Text))
|
||||||
|
throw std::runtime_error("file open failed");
|
||||||
|
_editor->setPlainText(QString::fromUtf8(file.readAll()));
|
||||||
|
if (file.error()!=QFileDevice::NoError)
|
||||||
|
throw std::runtime_error("file read failed");
|
||||||
|
setWindowTitle(_name+"[*]");
|
||||||
|
setWindowModified(false);
|
||||||
|
_status->setCurrentIndex(STATUS_NONE);
|
||||||
|
} 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()));
|
||||||
|
_name = oldname;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void save(QString name = QString()) {
|
||||||
|
QString oldname(_name);
|
||||||
|
if (!name.isEmpty()) _name = name;
|
||||||
|
QFile file(_name);
|
||||||
|
try {
|
||||||
|
if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
|
||||||
|
throw std::runtime_error("file open failed");
|
||||||
|
QTextStream out(&file);
|
||||||
|
out<<_editor->toPlainText();
|
||||||
|
if (out.status()!=QTextStream::Ok)
|
||||||
|
throw std::runtime_error(std::string("file write failed (")
|
||||||
|
+char(out.status()+48)+")");
|
||||||
|
setWindowModified(false);
|
||||||
|
setWindowTitle(_name+"[*]");
|
||||||
|
} 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(_name).arg(x.what()));
|
||||||
|
_name = oldname;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void clear() {
|
||||||
|
if (isWindowModified() &&
|
||||||
|
QMessageBox::question(this, tr("Changes Not Saved"),
|
||||||
|
tr("Clear script without saving changes?"))
|
||||||
|
!= QMessageBox::Yes)
|
||||||
|
return;
|
||||||
|
_editor->clear();
|
||||||
|
setWindowModified(false);
|
||||||
|
}
|
||||||
|
void modified() {
|
||||||
|
setWindowModified(true);
|
||||||
|
modified(this);
|
||||||
|
}
|
||||||
|
void run() {
|
||||||
|
_progress->reset();
|
||||||
|
_progress->show();
|
||||||
|
_status->setCurrentIndex(STATUS_RUNNING);
|
||||||
|
bool oldRecordState(_record->isChecked());
|
||||||
|
_record->setChecked(false);
|
||||||
|
_record->setEnabled(false);
|
||||||
|
_run->setEnabled(false);
|
||||||
|
Script script;
|
||||||
|
try {
|
||||||
|
assert(connect(&script, SIGNAL(progress(QString, int, int)), SLOT(progress(QString, int, int))));
|
||||||
|
QString text(_editor->textCursor().selection().toPlainText());
|
||||||
|
if (text.isEmpty()) text = _editor->toPlainText();
|
||||||
|
run(_name, text, _screenshots->isChecked(), script);
|
||||||
|
_status->setCurrentIndex(STATUS_SUCCESS);
|
||||||
|
} catch (std::exception &x) {
|
||||||
|
_status->setCurrentIndex(STATUS_ERROR);
|
||||||
|
std::shared_ptr<Command> cmd(script.command());
|
||||||
|
if (cmd)
|
||||||
|
QMessageBox::critical(this,
|
||||||
|
tr("Test Failed"),
|
||||||
|
tr("<html>"
|
||||||
|
" <h1>Error [%1]</h1>"
|
||||||
|
" <dl>"
|
||||||
|
" <dt>Command:</dt><dd><code>%3</code></dd>"
|
||||||
|
" <dt>File:</dt><dd>%4</dd>"
|
||||||
|
" <dt>Line:</dt><dd>%5</dd>"
|
||||||
|
" <dt>Error Message:</dt><dd><pre>%2</pre></dd>"
|
||||||
|
" </dl>"
|
||||||
|
"</html>")
|
||||||
|
.arg(demangle(typeid(x).name()))
|
||||||
|
.arg(x.what())
|
||||||
|
.arg(cmd->command())
|
||||||
|
.arg(cmd->file())
|
||||||
|
.arg(cmd->line()));
|
||||||
|
else
|
||||||
|
QMessageBox::critical(this,
|
||||||
|
tr("Test Failed"),
|
||||||
|
tr("<html>"
|
||||||
|
" <h1>Error [%1]</h1>"
|
||||||
|
" <p><code>%2</code></p>"
|
||||||
|
"</html>")
|
||||||
|
.arg(demangle(typeid(x).name()))
|
||||||
|
.arg(QString(x.what()).replace("\n", "<br/>")));
|
||||||
|
}
|
||||||
|
_run->setEnabled(true);
|
||||||
|
_record->setEnabled(true);
|
||||||
|
_record->setChecked(oldRecordState);
|
||||||
|
_progress->hide();
|
||||||
|
}
|
||||||
|
void appendCommand(const QString& txt) {
|
||||||
|
if (!_record->isChecked()) return;
|
||||||
|
_editor->appendPlainText(txt);
|
||||||
|
QScrollBar *vb(_editor->verticalScrollBar());
|
||||||
|
_editor->moveCursor(QTextCursor::End);
|
||||||
|
_editor->ensureCursorVisible();
|
||||||
|
if (!vb) return;
|
||||||
|
vb->setValue(vb->maximum());
|
||||||
|
}
|
||||||
|
void appendCommand(const QString& selector, const QString& txt) {
|
||||||
|
if (!_record->isChecked()) return;
|
||||||
|
QString text(_editor->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) {
|
||||||
|
_editor->setPlainText(lines.join("\n"));
|
||||||
|
_editor->moveCursor(QTextCursor::End);
|
||||||
|
_editor->ensureCursorVisible();
|
||||||
|
}
|
||||||
|
appendCommand(txt);
|
||||||
|
}
|
||||||
|
void appendWebLoadFinished(bool ok) {
|
||||||
|
if (!_record->isChecked()) return;
|
||||||
|
QString text(_editor->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();
|
||||||
|
_editor->setPlainText(lines.join("\n"));
|
||||||
|
_editor->moveCursor(QTextCursor::End);
|
||||||
|
_editor->ensureCursorVisible();
|
||||||
|
appendCommand("expect load "+url);
|
||||||
|
} else {
|
||||||
|
appendCommand("expect loadFinished "+QString(ok?"true":"false"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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(_editor->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);
|
||||||
|
_editor->setPlainText(text);
|
||||||
|
_editor->moveCursor(QTextCursor::End);
|
||||||
|
_editor->ensureCursorVisible();
|
||||||
|
}
|
||||||
|
void progress(const QString& txt, int pos, int max) {
|
||||||
|
_progress->setFormat(QString("%1 — %p%").arg(txt));
|
||||||
|
_progress->setMinimum(0);
|
||||||
|
_progress->setMaximum(max);
|
||||||
|
_progress->setValue(pos);
|
||||||
|
}
|
||||||
|
void runEnabled(bool f = true) {
|
||||||
|
_run->setEnabled(false);
|
||||||
|
}
|
||||||
|
void on__run_clicked() {
|
||||||
|
run();
|
||||||
|
}
|
||||||
protected:
|
protected:
|
||||||
void closeEvent (QCloseEvent*) {
|
void closeEvent(QCloseEvent*) {
|
||||||
close(this);
|
close(this);
|
||||||
}
|
}
|
||||||
|
private:
|
||||||
|
enum RunStatus {
|
||||||
|
STATUS_NONE = 0,
|
||||||
|
STATUS_RUNNING,
|
||||||
|
STATUS_SUCCESS,
|
||||||
|
STATUS_ERROR
|
||||||
|
};
|
||||||
private:
|
private:
|
||||||
QString _name;
|
QString _name;
|
||||||
};
|
};
|
||||||
|
@@ -7,17 +7,136 @@
|
|||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>628</width>
|
<width>628</width>
|
||||||
<height>378</height>
|
<height>593</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
<string>DockW&idget</string>
|
<string>Do&ckWidget</string>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QWidget" name="dockWidgetContents">
|
<widget class="QWidget" name="dockWidgetContents">
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
|
<item>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout"/>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||||
<item>
|
<item>
|
||||||
<widget class="CodeEditor" name="_editor"/>
|
<widget class="CodeEditor" name="_editor"/>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_8">
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="_record">
|
||||||
|
<property name="text">
|
||||||
|
<string>Record</string>
|
||||||
|
</property>
|
||||||
|
<property name="checkable">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="checked">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="_run">
|
||||||
|
<property name="text">
|
||||||
|
<string>Run</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="_screenshots">
|
||||||
|
<property name="text">
|
||||||
|
<string>Screenshots</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="verticalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>28</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item alignment="Qt::AlignHCenter">
|
||||||
|
<widget class="QStackedWidget" name="_status">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="currentIndex">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="page_6"/>
|
||||||
|
<widget class="QWidget" name="page_5">
|
||||||
|
<layout class="QGridLayout" name="gridLayout_9">
|
||||||
|
<item row="0" column="0" alignment="Qt::AlignHCenter">
|
||||||
|
<widget class="QLabel" name="label_6">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string><div style="font-size: xx-large">⌛</div></string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<widget class="QWidget" name="page_3">
|
||||||
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
|
<item row="0" column="0" alignment="Qt::AlignHCenter">
|
||||||
|
<widget class="QLabel" name="label_4">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string><div style="font-size: xx-large; color: green">✔</div></string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<widget class="QWidget" name="page_4">
|
||||||
|
<layout class="QGridLayout" name="gridLayout_8">
|
||||||
|
<item row="0" column="0" alignment="Qt::AlignHCenter">
|
||||||
|
<widget class="QLabel" name="label_5">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string><div style="font-size: xx-large; color: red">✘</div></string>
|
||||||
|
</property>
|
||||||
|
<property name="scaledContents">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QWidget" name="_searchBar" native="true">
|
<widget class="QWidget" name="_searchBar" native="true">
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
@@ -72,21 +191,28 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QWidget" name="_pageBar" native="true">
|
<widget class="QWidget" name="_lineBar" native="true">
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QSpinBox" name="_page"/>
|
<widget class="QSpinBox" name="_line"/>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="_goPage">
|
<widget class="QPushButton" name="_goLine">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>page</string>
|
<string>line</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QProgressBar" name="_progress">
|
||||||
|
<property name="value">
|
||||||
|
<number>24</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
|
338
src/testgui.hxx
338
src/testgui.hxx
@@ -1,7 +1,7 @@
|
|||||||
/*! @file
|
/*! @file
|
||||||
|
|
||||||
@id $Id$
|
@id $Id$
|
||||||
*/
|
*/
|
||||||
// 1 2 3 4 5 6 7 8
|
// 1 2 3 4 5 6 7 8
|
||||||
// 45678901234567890123456789012345678901234567890123456789012345678901234567890
|
// 45678901234567890123456789012345678901234567890123456789012345678901234567890
|
||||||
#ifndef TESTGUI_HXX
|
#ifndef TESTGUI_HXX
|
||||||
@@ -24,7 +24,6 @@
|
|||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <QNetworkReply>
|
#include <QNetworkReply>
|
||||||
#include <QEvent>
|
#include <QEvent>
|
||||||
#include <QTextDocumentFragment>
|
|
||||||
#include <mrw/stdext.hxx>
|
#include <mrw/stdext.hxx>
|
||||||
|
|
||||||
class TestGUI: public QMainWindow, protected Ui::TestGUI {
|
class TestGUI: public QMainWindow, protected Ui::TestGUI {
|
||||||
@@ -39,7 +38,7 @@ class TestGUI: public QMainWindow, protected Ui::TestGUI {
|
|||||||
_inEventFilter(false) {
|
_inEventFilter(false) {
|
||||||
setWindowTitle("[*]");
|
setWindowTitle("[*]");
|
||||||
setupUi(this);
|
setupUi(this);
|
||||||
menuViews->addAction(_scriptDock->toggleViewAction());
|
setDockOptions(dockOptions()|QMainWindow::GroupedDragging);
|
||||||
menuViews->addAction(_setupScriptDock->toggleViewAction());
|
menuViews->addAction(_setupScriptDock->toggleViewAction());
|
||||||
menuViews->addAction(_scriptCommandsDock->toggleViewAction());
|
menuViews->addAction(_scriptCommandsDock->toggleViewAction());
|
||||||
menuViews->addAction(_domDock->toggleViewAction());
|
menuViews->addAction(_domDock->toggleViewAction());
|
||||||
@@ -48,8 +47,7 @@ class TestGUI: public QMainWindow, protected Ui::TestGUI {
|
|||||||
menuViews->addAction(_logDock->toggleViewAction());
|
menuViews->addAction(_logDock->toggleViewAction());
|
||||||
menuViews->addAction(_sourceDock->toggleViewAction());
|
menuViews->addAction(_sourceDock->toggleViewAction());
|
||||||
menuViews->addAction(_executeDock->toggleViewAction());
|
menuViews->addAction(_executeDock->toggleViewAction());
|
||||||
_progress->hide();
|
|
||||||
_status->setCurrentIndex(STATUS_NONE);
|
|
||||||
QSettings settings("mrw", "webtester");
|
QSettings settings("mrw", "webtester");
|
||||||
restoreGeometry(settings.value("geometry").toByteArray());
|
restoreGeometry(settings.value("geometry").toByteArray());
|
||||||
restoreState(settings.value("windowstate").toByteArray());
|
restoreState(settings.value("windowstate").toByteArray());
|
||||||
@@ -64,21 +62,21 @@ class TestGUI: public QMainWindow, protected Ui::TestGUI {
|
|||||||
_web->installEventFilter(this); // track mouse and keyboard
|
_web->installEventFilter(this); // track mouse and keyboard
|
||||||
pg->setForwardUnsupportedContent(true);
|
pg->setForwardUnsupportedContent(true);
|
||||||
_commands->setText(Script().commands(Script::HTML));
|
_commands->setText(Script().commands(Script::HTML));
|
||||||
|
assert(connect(menuFile, SIGNAL(aboutToShow()), SLOT(fileMenuOpened())));
|
||||||
|
assert(connect(QApplication::instance(), SIGNAL(focusChanged(QWidget*, QWidget*)),
|
||||||
|
SLOT(focusChanged(QWidget*, QWidget*))));
|
||||||
assert(connect(pg, SIGNAL(uploadFile(QString)), SLOT(uploadFile(QString))));
|
assert(connect(pg, SIGNAL(uploadFile(QString)), SLOT(uploadFile(QString))));
|
||||||
assert(connect(pg, SIGNAL(unsupportedContent(QNetworkReply*)),
|
assert(connect(pg, SIGNAL(unsupportedContent(QNetworkReply*)),
|
||||||
SLOT(unsupportedContent(QNetworkReply*))));
|
SLOT(unsupportedContent(QNetworkReply*))));
|
||||||
assert(connect(pg, SIGNAL(downloadRequested(const QNetworkRequest&)),
|
assert(connect(pg, SIGNAL(downloadRequested(const QNetworkRequest&)),
|
||||||
SLOT(downloadRequested(const QNetworkRequest&))));
|
SLOT(downloadRequested(const QNetworkRequest&))));
|
||||||
//assert(connect(_testscript, SIGNAL(include(QString)), SLOT(include(QString))));
|
|
||||||
assert(connect(_testscript, SIGNAL(link(QString)), SLOT(include(QString))));
|
|
||||||
if (setupScript.size()) loadSetup(setupScript);
|
if (setupScript.size()) loadSetup(setupScript);
|
||||||
if (scriptFile.size()) loadFile(scriptFile);
|
if (scriptFile.size()) load(scriptFile);
|
||||||
}
|
}
|
||||||
virtual ~TestGUI() {}
|
virtual ~TestGUI() {}
|
||||||
public Q_SLOTS:
|
public Q_SLOTS:
|
||||||
void on__load_clicked() {
|
void on__load_clicked() {
|
||||||
enterText(true);
|
enterText(true);
|
||||||
if (_record->isChecked())
|
|
||||||
appendCommand("load "+map(_url->currentText()));
|
appendCommand("load "+map(_url->currentText()));
|
||||||
storeUrl(_url->currentText());
|
storeUrl(_url->currentText());
|
||||||
_webprogress->setFormat(_url->currentText());
|
_webprogress->setFormat(_url->currentText());
|
||||||
@@ -91,123 +89,34 @@ class TestGUI: public QMainWindow, protected Ui::TestGUI {
|
|||||||
void on__actionOpen_triggered() {
|
void on__actionOpen_triggered() {
|
||||||
QString name(QFileDialog::getOpenFileName(this, tr("Open Test Script")));
|
QString name(QFileDialog::getOpenFileName(this, tr("Open Test Script")));
|
||||||
if (name.isEmpty()) return;
|
if (name.isEmpty()) return;
|
||||||
loadFile(name);
|
load(name);
|
||||||
_status->setCurrentIndex(STATUS_NONE);
|
|
||||||
}
|
}
|
||||||
void on__actionOpenSetupScript_triggered() {
|
void on__actionOpenSetupScript_triggered() {
|
||||||
QString name(QFileDialog::getOpenFileName(this, tr("Open Setup Script")));
|
QString name(QFileDialog::getOpenFileName(this, tr("Open Setup Script")));
|
||||||
if (name.isEmpty()) return;
|
if (name.isEmpty()) return;
|
||||||
loadSetup(name);
|
loadSetup(name);
|
||||||
_status->setCurrentIndex(STATUS_NONE);
|
|
||||||
}
|
}
|
||||||
void on__actionRevertToSaved_triggered() {
|
void on__actionRevertToSaved_triggered() {
|
||||||
loadFile(_filename);
|
ScriptFile* active(activeScriptFile());
|
||||||
_status->setCurrentIndex(STATUS_NONE);
|
if (active) active->load();
|
||||||
}
|
}
|
||||||
void on__actionSaveAs_triggered() {
|
void on__actionSaveAs_triggered() {
|
||||||
|
ScriptFile* active(activeScriptFile());
|
||||||
|
if (!active) return;
|
||||||
QString name(QFileDialog::getSaveFileName(this, tr("Save Test Script")));
|
QString name(QFileDialog::getSaveFileName(this, tr("Save Test Script")));
|
||||||
if (name.isEmpty()) return;
|
if (!name.isEmpty()) active->save(name);
|
||||||
_filename = name;
|
|
||||||
on__actionSave_triggered();
|
|
||||||
_status->setCurrentIndex(STATUS_NONE);
|
|
||||||
}
|
}
|
||||||
void on__actionSave_triggered() {
|
void on__actionSave_triggered() {
|
||||||
QFile file(_filename);
|
ScriptFile* active(activeScriptFile());
|
||||||
try {
|
if (active) active->save();
|
||||||
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);
|
|
||||||
setWindowModified(false);
|
|
||||||
setWindowTitle(_filename+"[*]");
|
|
||||||
} 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()));
|
|
||||||
}
|
|
||||||
_status->setCurrentIndex(STATUS_NONE);
|
|
||||||
}
|
}
|
||||||
void on__actionClear_triggered() {
|
void on__actionClear_triggered() {
|
||||||
if (isWindowModified() &&
|
ScriptFile* active(activeScriptFile());
|
||||||
QMessageBox::question(this, tr("Changes Not Saved"),
|
if (active) active->clear();
|
||||||
tr("Clear script without saving changes?"))
|
|
||||||
!= QMessageBox::Yes)
|
|
||||||
return;
|
|
||||||
_testscript->clear();
|
|
||||||
_log->clear();
|
|
||||||
_filename.clear();
|
|
||||||
_actionSave->setEnabled(false);
|
|
||||||
_actionRevertToSaved->setEnabled(false);
|
|
||||||
setWindowTitle("[*]");
|
|
||||||
setWindowModified(false);
|
|
||||||
_status->setCurrentIndex(STATUS_NONE);
|
|
||||||
}
|
}
|
||||||
void on__run_clicked() {
|
void on__actionRun_triggered() {
|
||||||
_progress->reset();
|
ScriptFile* active(activeScriptFile());
|
||||||
_progress->show();
|
if (active) active->run();
|
||||||
_status->setCurrentIndex(STATUS_RUNNING);
|
|
||||||
bool oldRecordState(_record->isChecked());
|
|
||||||
_record->setChecked(false);
|
|
||||||
_record->setEnabled(false);
|
|
||||||
_run->setEnabled(false);
|
|
||||||
Script script;
|
|
||||||
try {
|
|
||||||
connect(&script, SIGNAL(logging(QString)), SLOT(logging(QString)));
|
|
||||||
connect(&script, SIGNAL(progress(QString, int, int)), SLOT(progress(QString, int, int)));
|
|
||||||
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());
|
|
||||||
_status->setCurrentIndex(STATUS_SUCCESS);
|
|
||||||
} catch (std::exception &x) {
|
|
||||||
_status->setCurrentIndex(STATUS_ERROR);
|
|
||||||
std::shared_ptr<Command> cmd(script.command());
|
|
||||||
if (cmd)
|
|
||||||
QMessageBox::critical(this,
|
|
||||||
tr("Test Failed"),
|
|
||||||
tr("<html>"
|
|
||||||
" <h1>Error [%1]</h1>"
|
|
||||||
" <dl>"
|
|
||||||
" <dt>Command:</dt><dd><code>%3</code></dd>"
|
|
||||||
" <dt>File:</dt><dd>%4</dd>"
|
|
||||||
" <dt>Line:</dt><dd>%5</dd>"
|
|
||||||
" <dt>Error Message:</dt><dd><pre>%2</pre></dd>"
|
|
||||||
" </dl>"
|
|
||||||
"</html>")
|
|
||||||
.arg(demangle(typeid(x).name()))
|
|
||||||
.arg(x.what())
|
|
||||||
.arg(cmd->command())
|
|
||||||
.arg(cmd->file())
|
|
||||||
.arg(cmd->line()));
|
|
||||||
else
|
|
||||||
QMessageBox::critical(this,
|
|
||||||
tr("Test Failed"),
|
|
||||||
tr("<html>"
|
|
||||||
" <h1>Error [%1]</h1>"
|
|
||||||
" <p><code>%2</code></p>"
|
|
||||||
"</html>")
|
|
||||||
.arg(demangle(typeid(x).name()))
|
|
||||||
.arg(QString(x.what()).replace("\n", "<br/>")));
|
|
||||||
}
|
|
||||||
_run->setEnabled(true);
|
|
||||||
_record->setEnabled(true);
|
|
||||||
_record->setChecked(oldRecordState);
|
|
||||||
_progress->hide();
|
|
||||||
}
|
}
|
||||||
void on__focused_clicked() {
|
void on__focused_clicked() {
|
||||||
enterText(true);
|
enterText(true);
|
||||||
@@ -228,7 +137,6 @@ class TestGUI: public QMainWindow, protected Ui::TestGUI {
|
|||||||
}
|
}
|
||||||
void on__web_linkClicked(const QUrl& url) {
|
void on__web_linkClicked(const QUrl& url) {
|
||||||
enterText(true);
|
enterText(true);
|
||||||
if (_record->isChecked())
|
|
||||||
appendCommand("load "+map(url.url()));
|
appendCommand("load "+map(url.url()));
|
||||||
}
|
}
|
||||||
void on__web_loadProgress(int progress) {
|
void on__web_loadProgress(int progress) {
|
||||||
@@ -237,7 +145,6 @@ class TestGUI: public QMainWindow, protected Ui::TestGUI {
|
|||||||
}
|
}
|
||||||
void on__web_loadStarted() {
|
void on__web_loadStarted() {
|
||||||
enterText(true);
|
enterText(true);
|
||||||
if (_record->isChecked())
|
|
||||||
appendCommand("expect "+map("loadStarted"));
|
appendCommand("expect "+map("loadStarted"));
|
||||||
_webprogress->setValue(0);
|
_webprogress->setValue(0);
|
||||||
_urlStack->setCurrentIndex(PROGRESS_VIEW);
|
_urlStack->setCurrentIndex(PROGRESS_VIEW);
|
||||||
@@ -252,7 +159,6 @@ class TestGUI: public QMainWindow, protected Ui::TestGUI {
|
|||||||
_webprogress->setFormat(url.url());
|
_webprogress->setFormat(url.url());
|
||||||
storeUrl(url);
|
storeUrl(url);
|
||||||
enterText(true);
|
enterText(true);
|
||||||
if (_record->isChecked())
|
|
||||||
appendCommand("expect "+map("urlChanged "+url.url()));
|
appendCommand("expect "+map("urlChanged "+url.url()));
|
||||||
}
|
}
|
||||||
void on__web_selectionChanged() {
|
void on__web_selectionChanged() {
|
||||||
@@ -262,24 +168,8 @@ class TestGUI: public QMainWindow, protected Ui::TestGUI {
|
|||||||
}
|
}
|
||||||
void on__web_loadFinished(bool ok) {
|
void on__web_loadFinished(bool ok) {
|
||||||
enterText(true);
|
enterText(true);
|
||||||
if (_record->isChecked()) {
|
for (auto testscript: _testscripts)
|
||||||
QString text(_testscript->toPlainText());
|
testscript->appendWebLoadFinished(ok);
|
||||||
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);
|
_urlStack->setCurrentIndex(URL_VIEW);
|
||||||
on__web_selectionChanged();
|
on__web_selectionChanged();
|
||||||
setLinks();
|
setLinks();
|
||||||
@@ -287,8 +177,7 @@ class TestGUI: public QMainWindow, protected Ui::TestGUI {
|
|||||||
setDom();
|
setDom();
|
||||||
}
|
}
|
||||||
void on__setupscript_textChanged() {
|
void on__setupscript_textChanged() {
|
||||||
bool oldRecordState(_record->isChecked());
|
for (auto testscript: _testscripts) testscript->runEnabled(false);
|
||||||
_run->setEnabled(false);
|
|
||||||
_setupscriptactive->setEnabled(false);
|
_setupscriptactive->setEnabled(false);
|
||||||
try {
|
try {
|
||||||
_setupscriptstatus->setText(trUtf8("?"));
|
_setupscriptstatus->setText(trUtf8("?"));
|
||||||
@@ -305,8 +194,7 @@ class TestGUI: public QMainWindow, protected Ui::TestGUI {
|
|||||||
} catch (std::exception &x) {
|
} catch (std::exception &x) {
|
||||||
_setupscriptstatus->setText(trUtf8("✘"));
|
_setupscriptstatus->setText(trUtf8("✘"));
|
||||||
}
|
}
|
||||||
_run->setEnabled(true);
|
for (auto testscript: _testscripts) testscript->runEnabled(true);
|
||||||
_record->setChecked(oldRecordState);
|
|
||||||
}
|
}
|
||||||
void on__forms_currentItemChanged(QTreeWidgetItem* item, QTreeWidgetItem*) {
|
void on__forms_currentItemChanged(QTreeWidgetItem* item, QTreeWidgetItem*) {
|
||||||
if (!item) return;
|
if (!item) return;
|
||||||
@@ -318,31 +206,12 @@ class TestGUI: public QMainWindow, protected Ui::TestGUI {
|
|||||||
}
|
}
|
||||||
void uploadFile(QString filename) {
|
void uploadFile(QString filename) {
|
||||||
enterText(true);
|
enterText(true);
|
||||||
if (_record->isChecked())
|
|
||||||
appendCommand("upload "+map(filename));
|
appendCommand("upload "+map(filename));
|
||||||
}
|
}
|
||||||
void unsupportedContent(QNetworkReply* reply) {
|
void unsupportedContent(QNetworkReply* reply) {
|
||||||
if (!_record->isChecked()) return;
|
for (auto testscript: _testscripts) testscript->unsupportedContent(reply);
|
||||||
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&) {
|
void downloadRequested(const QNetworkRequest&) {
|
||||||
if (_record->isChecked())
|
|
||||||
appendCommand("download2");
|
appendCommand("download2");
|
||||||
}
|
}
|
||||||
void logging(const QString& txt) {
|
void logging(const QString& txt) {
|
||||||
@@ -351,49 +220,80 @@ class TestGUI: public QMainWindow, protected Ui::TestGUI {
|
|||||||
if (!vb) return;
|
if (!vb) return;
|
||||||
vb->setValue(vb->maximum());
|
vb->setValue(vb->maximum());
|
||||||
}
|
}
|
||||||
void progress(const QString& txt, int pos, int max) {
|
void fileMenuOpened() {
|
||||||
_progress->setFormat(QString("%1 — %p%").arg(txt));
|
focusChanged(nullptr, nullptr);
|
||||||
_progress->setMinimum(0);
|
|
||||||
_progress->setMaximum(max);
|
|
||||||
_progress->setValue(pos);
|
|
||||||
}
|
}
|
||||||
void appendCommand(const QString& txt) {
|
void modified(ScriptFile* win) {
|
||||||
_testscript->appendPlainText(txt);
|
focusChanged(nullptr, win);
|
||||||
QScrollBar *vb(_testscript->verticalScrollBar());
|
|
||||||
_testscript->moveCursor(QTextCursor::End);
|
|
||||||
_testscript->ensureCursorVisible();
|
|
||||||
if (!vb) return;
|
|
||||||
vb->setValue(vb->maximum());
|
|
||||||
}
|
}
|
||||||
void include(QString name) {
|
void focusChanged(QWidget*, QWidget* focus) {
|
||||||
if (_testscripts.contains(name)) return;
|
ScriptFile* active(activeScriptFile(focus));
|
||||||
_testscripts[name] = new ScriptFile(this);
|
if (active)
|
||||||
// assert(connect(_testscripts[name], SIGNAL(include(QString)), SLOT(include(QString))));
|
setWindowFilePath(active->name());
|
||||||
assert(connect(_testscripts[name], SIGNAL(link(QString)), SLOT(include(QString))));
|
else
|
||||||
assert(connect(_testscripts[name], SIGNAL(close(ScriptFile*)), SLOT(remove(ScriptFile*))));
|
setWindowFilePath(QString());
|
||||||
QFile file(name);
|
_actionRevertToSaved->setEnabled(active);
|
||||||
try {
|
_actionSaveAs->setEnabled(active);
|
||||||
if (!file.open(QIODevice::ReadOnly|QIODevice::Text))
|
_actionSave->setEnabled(active&&active->isWindowModified());
|
||||||
throw std::runtime_error("file open failed");
|
_actionClear->setEnabled(active);
|
||||||
_testscripts[name]->editor()->setPlainText(QString::fromUtf8(file.readAll()));
|
_actionRun->setEnabled(active);
|
||||||
if (file.error()!=QFileDevice::NoError)
|
}
|
||||||
throw std::runtime_error("file read failed");
|
void activate(QString name) {
|
||||||
_testscripts[name]->name(name);
|
QFileInfo info(name);
|
||||||
tabifyDockWidget(_scriptDock, _testscripts[name]);
|
if (info.absoluteDir()==QDir::current()) name = info.fileName();
|
||||||
// QDockWidget* d(0);
|
if (!_testscripts.contains(name)) return load(name);
|
||||||
// for (QWidget* w(QApplication::focusWidget()); w&&!(d=qobject_cast<QDockWidget*>(w));
|
_testscripts[name]->show();
|
||||||
// w=qobject_cast<QWidget*>(w->parent()));
|
|
||||||
// if (d) d->raise();
|
|
||||||
_testscripts[name]->raise();
|
_testscripts[name]->raise();
|
||||||
|
_testscripts[name]->activateWindow();
|
||||||
|
}
|
||||||
|
void load(QString name) {
|
||||||
|
QFileInfo info(name);
|
||||||
|
if (info.absoluteDir()==QDir::current()) name = info.fileName();
|
||||||
|
if (_testscripts.contains(name)) try {
|
||||||
|
_testscripts[name]->load(name);
|
||||||
|
return activate(name);
|
||||||
|
} catch(const std::exception& x) {
|
||||||
|
remove(_testscripts[name]);
|
||||||
|
}
|
||||||
|
QDockWidget* first(_testscripts.isEmpty()?_setupScriptDock:_testscripts.last());
|
||||||
|
_testscripts[name] = new ScriptFile(this);
|
||||||
|
assert(connect(_testscripts[name], SIGNAL(modified(ScriptFile*)), SLOT(modified(ScriptFile*))));
|
||||||
|
assert(connect(_testscripts[name], SIGNAL(link(QString)), SLOT(activate(QString))));
|
||||||
|
assert(connect(_testscripts[name], SIGNAL(close(ScriptFile*)), SLOT(remove(ScriptFile*))));
|
||||||
|
assert(connect(_testscripts[name], SIGNAL(run(const QString&, const QString&, bool, Script&)), SLOT(run(const QString&, const QString&, bool, Script&))));
|
||||||
|
try {
|
||||||
|
_testscripts[name]->load(name);
|
||||||
|
tabifyDockWidget(first, _testscripts[name]);
|
||||||
|
activate(name);
|
||||||
} catch(const std::exception& x) {
|
} catch(const std::exception& x) {
|
||||||
remove(_testscripts[name]);
|
remove(_testscripts[name]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void remove(ScriptFile* scriptfile) {
|
void remove(ScriptFile* scriptfile) {
|
||||||
|
/// @todo check if modified
|
||||||
_testscripts.remove(scriptfile->name());
|
_testscripts.remove(scriptfile->name());
|
||||||
delete scriptfile;
|
delete scriptfile;
|
||||||
}
|
}
|
||||||
|
void run(const QString& name, const QString& text, bool screenshots, Script& script) {
|
||||||
|
std::shared_ptr<xml::Node> testsuites(new xml::Node("testsuite"));
|
||||||
|
assert(connect(&script, SIGNAL(logging(QString)), SLOT(logging(QString))));
|
||||||
|
if (_setupscriptactive->isEnabled()
|
||||||
|
&& _setupscriptactive->isChecked()) {
|
||||||
|
script.parse(_setupscript->toPlainText().split('\n'), "setup");
|
||||||
|
script.run(_web->page()->mainFrame(), testsuites, QString(), screenshots);
|
||||||
|
script.reset();
|
||||||
|
}
|
||||||
|
script.parse(text.split('\n'), name);
|
||||||
|
script.run(_web->page()->mainFrame(), testsuites, QString(), screenshots);
|
||||||
|
}
|
||||||
protected:
|
protected:
|
||||||
|
ScriptFile* activeScriptFile(QWidget* focus=nullptr) {
|
||||||
|
//for (auto win: _testscripts) if (win->isActiveWindow()) return win;
|
||||||
|
ScriptFile* active(nullptr);
|
||||||
|
for (QObject* wid(focus?focus:QApplication::focusWidget()); !active && wid; wid = wid->parent())
|
||||||
|
active = dynamic_cast<ScriptFile*>(wid);
|
||||||
|
return active;
|
||||||
|
}
|
||||||
void closeEvent(QCloseEvent* event) {
|
void closeEvent(QCloseEvent* event) {
|
||||||
QSettings settings("mrw", "webtester");
|
QSettings settings("mrw", "webtester");
|
||||||
settings.setValue("geometry", saveGeometry());
|
settings.setValue("geometry", saveGeometry());
|
||||||
@@ -440,7 +340,6 @@ class TestGUI: public QMainWindow, protected Ui::TestGUI {
|
|||||||
case QEvent::MouseButtonRelease: {
|
case QEvent::MouseButtonRelease: {
|
||||||
enterText(true);
|
enterText(true);
|
||||||
_lastFocused=element;
|
_lastFocused=element;
|
||||||
if (_record->isChecked()) {
|
|
||||||
if (!element.isNull()) {
|
if (!element.isNull()) {
|
||||||
QString selected(selector(element));
|
QString selected(selector(element));
|
||||||
if (handleMooTools(_lastFocused)) {
|
if (handleMooTools(_lastFocused)) {
|
||||||
@@ -475,7 +374,6 @@ class TestGUI: public QMainWindow, protected Ui::TestGUI {
|
|||||||
} else {
|
} else {
|
||||||
appendCommand("# click, but where?");
|
appendCommand("# click, but where?");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} break;
|
} break;
|
||||||
case QEvent::MouseButtonPress: {
|
case QEvent::MouseButtonPress: {
|
||||||
} break;
|
} break;
|
||||||
@@ -505,26 +403,6 @@ class TestGUI: public QMainWindow, protected Ui::TestGUI {
|
|||||||
_url->setCurrentText(u.url());
|
_url->setCurrentText(u.url());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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);
|
|
||||||
setWindowTitle(name+"[*]");
|
|
||||||
setWindowModified(false);
|
|
||||||
} 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) {
|
void loadSetup(QString name) {
|
||||||
QFile file(name);
|
QFile file(name);
|
||||||
try {
|
try {
|
||||||
@@ -644,41 +522,26 @@ class TestGUI: public QMainWindow, protected Ui::TestGUI {
|
|||||||
return in;
|
return in;
|
||||||
}
|
}
|
||||||
void javascript(const QString& selector, QString code) {
|
void javascript(const QString& selector, QString code) {
|
||||||
if (_record->isChecked())
|
|
||||||
appendCommand("do "+map(selector)+"\n "
|
appendCommand("do "+map(selector)+"\n "
|
||||||
+map(code).replace("\n", "\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) {
|
void setValue(const QString& selector, QString code) {
|
||||||
if (_record->isChecked()) {
|
appendCommand(selector,
|
||||||
cleanup(selector);
|
"setvalue "+map(selector)+" -> '"
|
||||||
appendCommand("setvalue "+map(selector)+" -> '"
|
|
||||||
+map(code).replace("'", "\\'").replace("\n", "\\n")+"'");
|
+map(code).replace("'", "\\'").replace("\n", "\\n")+"'");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
void setValue(const QString& selector, QStringList code) {
|
void setValue(const QString& selector, QStringList code) {
|
||||||
if (_record->isChecked()) {
|
appendCommand(selector,
|
||||||
cleanup(selector);
|
"setvalue "+map(selector)+" -> '"+
|
||||||
appendCommand("setvalue "+map(selector)+" -> '"+
|
|
||||||
map(code.replaceInStrings("'", "\\'")
|
map(code.replaceInStrings("'", "\\'")
|
||||||
.replaceInStrings("\n", "\\n")
|
.replaceInStrings("\n", "\\n")
|
||||||
.join("', '")+"'"));
|
.join("', '")+"'"));
|
||||||
}
|
}
|
||||||
|
void appendCommand(const QString& txt) {
|
||||||
|
for (auto testscript: _testscripts) testscript->appendCommand(txt);
|
||||||
|
}
|
||||||
|
void appendCommand(const QString& selector, const QString& txt) {
|
||||||
|
for (auto testscript: _testscripts) testscript->appendCommand(selector, txt);
|
||||||
}
|
}
|
||||||
bool handleMooTools(QWebElement element) {
|
bool handleMooTools(QWebElement element) {
|
||||||
QString selected(selector(element));
|
QString selected(selector(element));
|
||||||
@@ -697,8 +560,7 @@ class TestGUI: public QMainWindow, protected Ui::TestGUI {
|
|||||||
return true;
|
return true;
|
||||||
} else if (mooComboItem.hasMatch()) {
|
} else if (mooComboItem.hasMatch()) {
|
||||||
// special treatment for item in moo tools combobox
|
// special treatment for item in moo tools combobox
|
||||||
appendCommand
|
appendCommand("click realmouse "+map("li.active-result[data-option-array-index=\""
|
||||||
("click realmouse "+map("li.active-result[data-option-array-index=\""
|
|
||||||
+element.attribute("data-option-array-index")
|
+element.attribute("data-option-array-index")
|
||||||
+"\"]"));
|
+"\"]"));
|
||||||
appendCommand("sleep "+map("1"));
|
appendCommand("sleep "+map("1"));
|
||||||
@@ -942,12 +804,6 @@ class TestGUI: public QMainWindow, protected Ui::TestGUI {
|
|||||||
URL_VIEW = 0,
|
URL_VIEW = 0,
|
||||||
PROGRESS_VIEW
|
PROGRESS_VIEW
|
||||||
};
|
};
|
||||||
enum RunStatus {
|
|
||||||
STATUS_NONE = 0,
|
|
||||||
STATUS_RUNNING,
|
|
||||||
STATUS_SUCCESS,
|
|
||||||
STATUS_ERROR
|
|
||||||
};
|
|
||||||
private:
|
private:
|
||||||
QString _filename;
|
QString _filename;
|
||||||
QWebElement _lastFocused; // cache for last focussed element
|
QWebElement _lastFocused; // cache for last focussed element
|
||||||
|
225
src/testgui.ui
225
src/testgui.ui
@@ -10,6 +10,9 @@
|
|||||||
<height>1180</height>
|
<height>1180</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
<string/>
|
<string/>
|
||||||
</property>
|
</property>
|
||||||
@@ -101,7 +104,7 @@
|
|||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>888</width>
|
<width>888</width>
|
||||||
<height>30</height>
|
<height>34</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QMenu" name="menuViews">
|
<widget class="QMenu" name="menuViews">
|
||||||
@@ -115,14 +118,13 @@
|
|||||||
</property>
|
</property>
|
||||||
<addaction name="_actionOpen"/>
|
<addaction name="_actionOpen"/>
|
||||||
<addaction name="_actionOpenSetupScript"/>
|
<addaction name="_actionOpenSetupScript"/>
|
||||||
|
<addaction name="separator"/>
|
||||||
<addaction name="_actionSave"/>
|
<addaction name="_actionSave"/>
|
||||||
<addaction name="_actionSaveAs"/>
|
<addaction name="_actionSaveAs"/>
|
||||||
<addaction name="separator"/>
|
|
||||||
<addaction name="_actionRun"/>
|
|
||||||
<addaction name="_actionRunLine"/>
|
|
||||||
<addaction name="separator"/>
|
|
||||||
<addaction name="_actionRevertToSaved"/>
|
<addaction name="_actionRevertToSaved"/>
|
||||||
<addaction name="_actionClear"/>
|
<addaction name="_actionClear"/>
|
||||||
|
<addaction name="_actionRun"/>
|
||||||
|
<addaction name="separator"/>
|
||||||
<addaction name="_actionQuit"/>
|
<addaction name="_actionQuit"/>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QMenu" name="menuHelp">
|
<widget class="QMenu" name="menuHelp">
|
||||||
@@ -138,7 +140,7 @@
|
|||||||
<widget class="QStatusBar" name="statusbar"/>
|
<widget class="QStatusBar" name="statusbar"/>
|
||||||
<widget class="QDockWidget" name="_domDock">
|
<widget class="QDockWidget" name="_domDock">
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
<string>D&OM Tree</string>
|
<string>DOM &Tree</string>
|
||||||
</property>
|
</property>
|
||||||
<attribute name="dockWidgetArea">
|
<attribute name="dockWidgetArea">
|
||||||
<number>2</number>
|
<number>2</number>
|
||||||
@@ -393,144 +395,6 @@ this.dispatchEvent(evObj);</string>
|
|||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QDockWidget" name="_scriptDock">
|
|
||||||
<property name="windowTitle">
|
|
||||||
<string>&Test Script</string>
|
|
||||||
</property>
|
|
||||||
<attribute name="dockWidgetArea">
|
|
||||||
<number>4</number>
|
|
||||||
</attribute>
|
|
||||||
<widget class="QWidget" name="dockWidgetContents_12">
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_9">
|
|
||||||
<item>
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_6">
|
|
||||||
<item>
|
|
||||||
<widget class="CodeEditor" name="_testscript"/>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_8">
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="_record">
|
|
||||||
<property name="text">
|
|
||||||
<string>Record</string>
|
|
||||||
</property>
|
|
||||||
<property name="checkable">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
<property name="checked">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="_run">
|
|
||||||
<property name="text">
|
|
||||||
<string>Run</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QCheckBox" name="_screenshots">
|
|
||||||
<property name="text">
|
|
||||||
<string>Screenshots</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<spacer name="verticalSpacer">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Vertical</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>20</width>
|
|
||||||
<height>28</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
<item alignment="Qt::AlignHCenter">
|
|
||||||
<widget class="QStackedWidget" name="_status">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="currentIndex">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<widget class="QWidget" name="page_6"/>
|
|
||||||
<widget class="QWidget" name="page_5">
|
|
||||||
<layout class="QGridLayout" name="gridLayout_9">
|
|
||||||
<item row="0" column="0" alignment="Qt::AlignHCenter">
|
|
||||||
<widget class="QLabel" name="label_6">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string><div style="font-size: xx-large">⌛</div></string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
<widget class="QWidget" name="page_3">
|
|
||||||
<layout class="QGridLayout" name="gridLayout">
|
|
||||||
<item row="0" column="0" alignment="Qt::AlignHCenter">
|
|
||||||
<widget class="QLabel" name="label_4">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string><div style="font-size: xx-large; color: green">✔</div></string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
<widget class="QWidget" name="page_4">
|
|
||||||
<layout class="QGridLayout" name="gridLayout_8">
|
|
||||||
<item row="0" column="0" alignment="Qt::AlignHCenter">
|
|
||||||
<widget class="QLabel" name="label_5">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string><div style="font-size: xx-large; color: red">✘</div></string>
|
|
||||||
</property>
|
|
||||||
<property name="scaledContents">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QProgressBar" name="_progress">
|
|
||||||
<property name="value">
|
|
||||||
<number>24</number>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</widget>
|
|
||||||
<widget class="QDockWidget" name="_logDock">
|
<widget class="QDockWidget" name="_logDock">
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
<string>Scri&pt Run Log</string>
|
<string>Scri&pt Run Log</string>
|
||||||
@@ -699,6 +563,9 @@ this.dispatchEvent(evObj);</string>
|
|||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="_actionSaveAs">
|
<action name="_actionSaveAs">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Save &As ...</string>
|
<string>Save &As ...</string>
|
||||||
</property>
|
</property>
|
||||||
@@ -715,6 +582,9 @@ this.dispatchEvent(evObj);</string>
|
|||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="_actionRun">
|
<action name="_actionRun">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>&Run</string>
|
<string>&Run</string>
|
||||||
</property>
|
</property>
|
||||||
@@ -728,6 +598,9 @@ this.dispatchEvent(evObj);</string>
|
|||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="_actionClear">
|
<action name="_actionClear">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>&Clear</string>
|
<string>&Clear</string>
|
||||||
</property>
|
</property>
|
||||||
@@ -986,38 +859,6 @@ this.dispatchEvent(evObj);</string>
|
|||||||
</hint>
|
</hint>
|
||||||
</hints>
|
</hints>
|
||||||
</connection>
|
</connection>
|
||||||
<connection>
|
|
||||||
<sender>_actionTestScript</sender>
|
|
||||||
<signal>triggered(bool)</signal>
|
|
||||||
<receiver>_scriptDock</receiver>
|
|
||||||
<slot>setVisible(bool)</slot>
|
|
||||||
<hints>
|
|
||||||
<hint type="sourcelabel">
|
|
||||||
<x>-1</x>
|
|
||||||
<y>-1</y>
|
|
||||||
</hint>
|
|
||||||
<hint type="destinationlabel">
|
|
||||||
<x>443</x>
|
|
||||||
<y>155</y>
|
|
||||||
</hint>
|
|
||||||
</hints>
|
|
||||||
</connection>
|
|
||||||
<connection>
|
|
||||||
<sender>_scriptDock</sender>
|
|
||||||
<signal>visibilityChanged(bool)</signal>
|
|
||||||
<receiver>_actionTestScript</receiver>
|
|
||||||
<slot>setChecked(bool)</slot>
|
|
||||||
<hints>
|
|
||||||
<hint type="sourcelabel">
|
|
||||||
<x>443</x>
|
|
||||||
<y>155</y>
|
|
||||||
</hint>
|
|
||||||
<hint type="destinationlabel">
|
|
||||||
<x>-1</x>
|
|
||||||
<y>-1</y>
|
|
||||||
</hint>
|
|
||||||
</hints>
|
|
||||||
</connection>
|
|
||||||
<connection>
|
<connection>
|
||||||
<sender>_actionLog</sender>
|
<sender>_actionLog</sender>
|
||||||
<signal>triggered(bool)</signal>
|
<signal>triggered(bool)</signal>
|
||||||
@@ -1066,22 +907,6 @@ this.dispatchEvent(evObj);</string>
|
|||||||
</hint>
|
</hint>
|
||||||
</hints>
|
</hints>
|
||||||
</connection>
|
</connection>
|
||||||
<connection>
|
|
||||||
<sender>_actionRun</sender>
|
|
||||||
<signal>triggered()</signal>
|
|
||||||
<receiver>_run</receiver>
|
|
||||||
<slot>click()</slot>
|
|
||||||
<hints>
|
|
||||||
<hint type="sourcelabel">
|
|
||||||
<x>-1</x>
|
|
||||||
<y>-1</y>
|
|
||||||
</hint>
|
|
||||||
<hint type="destinationlabel">
|
|
||||||
<x>299</x>
|
|
||||||
<y>90</y>
|
|
||||||
</hint>
|
|
||||||
</hints>
|
|
||||||
</connection>
|
|
||||||
<connection>
|
<connection>
|
||||||
<sender>_url</sender>
|
<sender>_url</sender>
|
||||||
<signal>activated(int)</signal>
|
<signal>activated(int)</signal>
|
||||||
@@ -1098,21 +923,5 @@ this.dispatchEvent(evObj);</string>
|
|||||||
</hint>
|
</hint>
|
||||||
</hints>
|
</hints>
|
||||||
</connection>
|
</connection>
|
||||||
<connection>
|
|
||||||
<sender>_testscript</sender>
|
|
||||||
<signal>modificationChanged(bool)</signal>
|
|
||||||
<receiver>TestGUI</receiver>
|
|
||||||
<slot>setWindowModified(bool)</slot>
|
|
||||||
<hints>
|
|
||||||
<hint type="sourcelabel">
|
|
||||||
<x>126</x>
|
|
||||||
<y>144</y>
|
|
||||||
</hint>
|
|
||||||
<hint type="destinationlabel">
|
|
||||||
<x>443</x>
|
|
||||||
<y>589</y>
|
|
||||||
</hint>
|
|
||||||
</hints>
|
|
||||||
</connection>
|
|
||||||
</connections>
|
</connections>
|
||||||
</ui>
|
</ui>
|
||||||
|
@@ -4,22 +4,22 @@
|
|||||||
#include <version.hxx>
|
#include <version.hxx>
|
||||||
|
|
||||||
int main(int argc, char *argv[]) try {
|
int main(int argc, char *argv[]) try {
|
||||||
QApplication a(argc, argv);
|
QApplication app(argc, argv);
|
||||||
a.setApplicationDisplayName(a.tr("WebTester"));
|
app.setApplicationDisplayName(app.tr("WebTester"));
|
||||||
a.setApplicationName(webtester::package_name().c_str());
|
app.setApplicationName(webtester::package_name().c_str());
|
||||||
a.setApplicationVersion(webtester::version().c_str());
|
app.setApplicationVersion(webtester::version().c_str());
|
||||||
QCommandLineParser parser;
|
QCommandLineParser parser;
|
||||||
parser.addHelpOption();
|
parser.addHelpOption();
|
||||||
parser.addOption(QCommandLineOption
|
parser.addOption(QCommandLineOption
|
||||||
(QStringList()<<"u"<<"url",
|
(QStringList()<<"u"<<"url",
|
||||||
"set initial URL to <url>", "url"));
|
"set initial URL to <url>", "url"));
|
||||||
parser.process(a);
|
parser.process(app);
|
||||||
QStringList scripts(parser.positionalArguments());
|
QStringList scripts(parser.positionalArguments());
|
||||||
TestGUI w(0, parser.value("url"),
|
TestGUI win(0, parser.value("url"),
|
||||||
scripts.size()>1?scripts[0]:"",
|
scripts.size()>1?scripts[0]:"",
|
||||||
scripts.size()>1?scripts[1]:scripts.size()?scripts[0]:"");
|
scripts.size()>1?scripts[1]:scripts.size()?scripts[0]:"");
|
||||||
w.show();
|
win.show();
|
||||||
return a.exec();
|
return app.exec();
|
||||||
} catch (std::exception &x) {
|
} catch (std::exception &x) {
|
||||||
std::cerr<<"**** error: "<<x.what()<<std::endl;
|
std::cerr<<"**** error: "<<x.what()<<std::endl;
|
||||||
return 1;
|
return 1;
|
||||||
|
Reference in New Issue
Block a user