From 7bdd4a46fe799a721a4686fa19bfa1156c0b2693 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20W=C3=A4ckerlin?= Date: Mon, 19 Nov 2018 16:24:44 +0100 Subject: [PATCH] cursor follows files and lines; javascript interaction to be handled later --- src/commands.hxx | 26 ++++++++++++-------------- src/editor.hxx | 5 +++++ src/scriptfile.hxx | 13 ++++++++++--- src/testgui.hxx | 23 +++++++++++++++++++---- src/testgui.ui | 21 +++++++++++++++++++++ src/webpage.hxx | 16 ++++++++++++---- 6 files changed, 79 insertions(+), 25 deletions(-) diff --git a/src/commands.hxx b/src/commands.hxx index d8b14b0..ae5ed19 100644 --- a/src/commands.hxx +++ b/src/commands.hxx @@ -448,7 +448,7 @@ class Script: public QObject { Q_OBJECT Q_SIGNALS: void logging(QString); - void progress(QString, int, int); + void progress(QString, int, int, int); public: typedef std::pair Signal; enum ClickType { @@ -640,8 +640,7 @@ class Script: public QObject { int retries(0), back(0); for (auto cmd(_script.begin()); cmd!=_script.end(); _step+=(*cmd)->steps(this), ++cmd) { - progress(QString("%1:%2").arg((*cmd)->file()).arg((*cmd)->line()), - _step, countSteps()); + progress((*cmd)->file(), (*cmd)->line(), _step, countSteps()); xml::Node testcase("testcase"); try { testcase.attr("classname") = @@ -672,8 +671,7 @@ class Script: public QObject { _testsuites->last()<file()).arg((*cmd)->line()), - _step, countSteps()); + progress((*cmd)->file(), (*cmd)->line(), _step, countSteps()); } catch (PossibleRetryLoad& e) { _timer.stop(); // timeout may happen during load due to bad internet connection @@ -777,7 +775,7 @@ class Script: public QObject { } removeSignals(frame); if (!_signals.empty()) error(UnhandledSignals(_signals)); - progress("success", 0, 0); + progress(QString(), 0, 0, 0); return res; } std::shared_ptr command() { @@ -1074,8 +1072,8 @@ class Script: public QObject { _prototypes[c->tag()] = std::shared_ptr(c); } private Q_SLOTS: - void innerProgress(QString txt, int delta) { - progress(txt, _step+delta, countSteps()); + void innerProgress(QString file, int line, int delta) { + progress(file, line, _step+delta, countSteps()); } void authenticationRequired(QNetworkReply*, QAuthenticator* a) { if (_auth.contains(a->realm())) { @@ -3211,13 +3209,13 @@ inline bool Command::runScript(Logger& log, Command* parentCommand, try { assert(connect(&scriptCopy, SIGNAL(logging(QString)), parent, SLOT(parentlog(QString)))); - assert(connect(&scriptCopy, SIGNAL(progress(QString, int, int)), - parent, SLOT(innerProgress(QString, int)))); + assert(connect(&scriptCopy, SIGNAL(progress(QString, int, int, int)), + parent, SLOT(innerProgress(QString, int, int)))); parent->removeSignals(frame); bool res(scriptCopy.run(frame)); parent->addSignals(frame); - disconnect(&scriptCopy, SIGNAL(progress(QString, int, int)), - parent, SLOT(innerProgress(QString, int))); + disconnect(&scriptCopy, SIGNAL(progress(QString, int, int, int)), + parent, SLOT(innerProgress(QString, int, int))); disconnect(&scriptCopy, SIGNAL(logging(QString)), parent, SLOT(parentlog(QString))); parentCommand->_result = scriptCopy.result(); @@ -3229,8 +3227,8 @@ inline bool Command::runScript(Logger& log, Command* parentCommand, return res; } catch (const Exception& x) { parent->addSignals(frame); - disconnect(&scriptCopy, SIGNAL(progress(QString, int, int)), - parent, SLOT(innerProgress(QString, int))); + disconnect(&scriptCopy, SIGNAL(progress(QString, int, int, int)), + parent, SLOT(innerProgress(QString, int, int))); disconnect(&scriptCopy, SIGNAL(logging(QString)), parent, SLOT(parentlog(QString))); throw; diff --git a/src/editor.hxx b/src/editor.hxx index 9585270..f12b9eb 100644 --- a/src/editor.hxx +++ b/src/editor.hxx @@ -87,6 +87,11 @@ class CodeEditor: public QPlainTextEdit { updateLineNumberAreaWidth(0); highlightCurrentLine(); } + void gotoLine(int line) { + QTextCursor cursor(document()->findBlockByNumber(line-1)); + setTextCursor(cursor); + highlightCurrentLine(); + } void lineNumberAreaPaintEvent(QPaintEvent *event) { QPainter painter(lineNumberArea); painter.fillRect(event->rect(), Qt::lightGray); diff --git a/src/scriptfile.hxx b/src/scriptfile.hxx index 782d75d..8448732 100644 --- a/src/scriptfile.hxx +++ b/src/scriptfile.hxx @@ -16,6 +16,7 @@ class ScriptFile: public QDockWidget, protected Ui::ScriptFile { void include(QString); void close(ScriptFile*); void run(const QString&, const QString&, bool, Script&); + void running(QString file, int line); public: ScriptFile(QWidget* p = nullptr): QDockWidget(p) { setupUi(this); @@ -39,6 +40,9 @@ class ScriptFile: public QDockWidget, protected Ui::ScriptFile { setWindowTitle(name+"[*]"); setWindowModified(false); } + void gotoLine(int line) { + _editor->gotoLine(line); + } public Q_SLOTS: void load(QString name = QString()) { if (isWindowModified() && @@ -113,7 +117,10 @@ class ScriptFile: public QDockWidget, protected Ui::ScriptFile { _run->setEnabled(false); Script script; try { - assert(connect(&script, SIGNAL(progress(QString, int, int)), SLOT(progress(QString, int, int)))); + assert(connect(&script, SIGNAL(progress(QString, int, int, int)), + SLOT(progress(QString, int, int, int)))); + assert(connect(&script, SIGNAL(progress(QString, int, int, int)), + SIGNAL(running(QString, int)))); QString text(_editor->textCursor().selection().toPlainText()); if (text.isEmpty()) text = _editor->toPlainText(); run(_name, text, _screenshots->isChecked(), script); @@ -218,8 +225,8 @@ class ScriptFile: public QDockWidget, protected Ui::ScriptFile { _editor->moveCursor(QTextCursor::End); _editor->ensureCursorVisible(); } - void progress(const QString& txt, int pos, int max) { - _progress->setFormat(QString("%1 — %p%").arg(txt)); + void progress(const QString& file, int line, int pos, int max) { + _progress->setFormat(QString("%1:%2 — %p%").arg(file).arg(line)); _progress->setMinimum(0); _progress->setMaximum(max); _progress->setValue(pos); diff --git a/src/testgui.hxx b/src/testgui.hxx index 948d014..dd8fcd0 100644 --- a/src/testgui.hxx +++ b/src/testgui.hxx @@ -51,6 +51,7 @@ class TestGUI: public QMainWindow, protected Ui::TestGUI { QSettings settings("mrw", "webtester"); restoreGeometry(settings.value("geometry").toByteArray()); restoreState(settings.value("windowstate").toByteArray()); + _actionCursorFollowsFiles->setChecked(settings.value("cursorfollowsfiles").toBool()); _url->completer()->setFilterMode(Qt::MatchContains); _url->completer()->setCaseSensitivity(Qt::CaseInsensitive); _url->completer()->setCompletionMode(QCompleter::PopupCompletion); @@ -238,15 +239,16 @@ class TestGUI: public QMainWindow, protected Ui::TestGUI { _actionClear->setEnabled(active); _actionRun->setEnabled(active); } - void activate(QString name) { + QString activate(QString name) { QFileInfo info(name); if (info.absoluteDir()==QDir::current()) name = info.fileName(); if (!_testscripts.contains(name)) return load(name); _testscripts[name]->show(); _testscripts[name]->raise(); _testscripts[name]->activateWindow(); + return name; } - void load(QString name) { + QString load(QString name) { QFileInfo info(name); if (info.absoluteDir()==QDir::current()) name = info.fileName(); if (_testscripts.contains(name)) try { @@ -260,13 +262,17 @@ class TestGUI: public QMainWindow, protected Ui::TestGUI { 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&)))); + assert(connect(_testscripts[name], SIGNAL(run(const QString&, const QString&, bool, Script&)), + SLOT(run(const QString&, const QString&, bool, Script&)))); + assert(connect(_testscripts[name], SIGNAL(running(QString, int)), + SLOT(showFileLine(QString, int)))); try { _testscripts[name]->load(name); tabifyDockWidget(first, _testscripts[name]); - activate(name); + return activate(name); } catch(const std::exception& x) { remove(_testscripts[name]); + return QString(); } } void remove(ScriptFile* scriptfile) { @@ -286,6 +292,14 @@ class TestGUI: public QMainWindow, protected Ui::TestGUI { script.parse(text.split('\n'), name); script.run(_web->page()->mainFrame(), testsuites, QString(), screenshots); } + void showFileLine(QString file, int line) { + if (!_actionCursorFollowsFiles->isChecked() || file.isEmpty() || file=="setup") return; + try { + QString name(activate(file)); + if (!name.isEmpty() && _testscripts.contains(name)) + _testscripts[name]->gotoLine(line); + } catch (...) {} // ignore + } protected: ScriptFile* activeScriptFile(QWidget* focus=nullptr) { //for (auto win: _testscripts) if (win->isActiveWindow()) return win; @@ -298,6 +312,7 @@ class TestGUI: public QMainWindow, protected Ui::TestGUI { QSettings settings("mrw", "webtester"); settings.setValue("geometry", saveGeometry()); settings.setValue("windowstate", saveState()); + settings.setValue("cursorfollowsfiles", _actionCursorFollowsFiles->isChecked()); if (isWindowModified() && QMessageBox::question(this, tr("Changes Not Saved"), tr("Leave without saving changes?")) diff --git a/src/testgui.ui b/src/testgui.ui index 53db2a8..70121da 100644 --- a/src/testgui.ui +++ b/src/testgui.ui @@ -133,7 +133,14 @@ + + + Options + + + + @@ -648,6 +655,20 @@ this.dispatchEvent(evObj); &Commands ... + + + true + + + true + + + Cursor Follows Files + + + <html><head/><body><p>When running a script, the currently running file and line is highlighted. So the cursor follows the current file and line when running a script.</p></body></html> + + diff --git a/src/webpage.hxx b/src/webpage.hxx index ac8ee6c..512afc0 100644 --- a/src/webpage.hxx +++ b/src/webpage.hxx @@ -79,7 +79,9 @@ class TestWebPage: public QWebPage { if (_unattended) { return; } else { - return QWebPage::javaScriptAlert(frame, msg); + return; + /// @todo handle javascript alerts + //return QWebPage::javaScriptAlert(frame, msg); } } virtual bool javaScriptConfirm(QWebFrame* frame, const QString& msg) { @@ -87,7 +89,9 @@ class TestWebPage: public QWebPage { if (_unattended) { return true; } else { - return QWebPage::javaScriptConfirm(frame, msg); + return true; + /// @todo handle javascript confirmations + //return QWebPage::javaScriptConfirm(frame, msg); } } virtual void javaScriptConsoleMessage(const QString& msg, @@ -96,7 +100,9 @@ class TestWebPage: public QWebPage { if (_unattended) { return; } else { - return QWebPage::javaScriptConsoleMessage(msg, line, src); + return; + /// @todo handle javascript console messages + //return QWebPage::javaScriptConsoleMessage(msg, line, src); } } virtual bool javaScriptPrompt(QWebFrame* frame, const QString& msg, @@ -105,7 +111,9 @@ class TestWebPage: public QWebPage { if (_unattended) { return true; } else { - return QWebPage::javaScriptPrompt(frame, msg, defaultValue, result); + return true; + /// @todo handle javascript prompts + //return QWebPage::javaScriptPrompt(frame, msg, defaultValue, result); } } private: