From 0bbc465f6124b60b012c86a39687814017de202a Mon Sep 17 00:00:00 2001 From: Alessandro Portale Date: Wed, 12 Jan 2022 22:55:10 +0100 Subject: [PATCH] WebAssembly: Improve browser selection combobox of run configuation This adds a "Default Browser" entry to the browser selection combobox in WebAssembly' run configuration. Choosing that omits the "--browser" parameter and let's emrun determine which browser to launch (should by the system default browser). In order to implement that, the combobox items now got user data in addition to have display data. The parsing of emrun's output was extended to retrieve the long form of a browser name as display data: "Mozilla Firefox 96.0.0.8041" instead of just "firefox". The parsing of emrun's outout received a dedicated plugin test. Turning the result in parseEmrunOutput() non-static fixed QTCREATORBUG-26562 Fixes: QTCREATORBUG-25028 Fixes: QTCREATORBUG-26559 Change-Id: I18891b88b063903d1a9eeb88a6c906e596e561c1 Reviewed-by: Reviewed-by: Alessandro Portale --- src/plugins/webassembly/webassemblyplugin.h | 2 + .../webassemblyrunconfiguration.cpp | 25 ++-- .../webassemblyrunconfigurationaspects.cpp | 127 +++++++++++++----- .../webassemblyrunconfigurationaspects.h | 5 +- 4 files changed, 118 insertions(+), 41 deletions(-) diff --git a/src/plugins/webassembly/webassemblyplugin.h b/src/plugins/webassembly/webassemblyplugin.h index c17909542ba..92fff41e7cc 100644 --- a/src/plugins/webassembly/webassemblyplugin.h +++ b/src/plugins/webassembly/webassemblyplugin.h @@ -49,6 +49,8 @@ public: private slots: void testEmSdkEnvParsing(); void testEmSdkEnvParsing_data(); + void testEmrunBrowserListParsing(); + void testEmrunBrowserListParsing_data(); #endif // WITH_TESTS }; diff --git a/src/plugins/webassembly/webassemblyrunconfiguration.cpp b/src/plugins/webassembly/webassemblyrunconfiguration.cpp index 55230f93b3a..f06da53c093 100644 --- a/src/plugins/webassembly/webassemblyrunconfiguration.cpp +++ b/src/plugins/webassembly/webassemblyrunconfiguration.cpp @@ -66,14 +66,18 @@ static CommandLine emrunCommand(const RunConfiguration *rc, const QString &brows const FilePath target = rc->buildTargetInfo().targetFilePath; const FilePath html = target.absolutePath() / target.baseName() + ".html"; - return CommandLine(pythonInterpreter(env), { - emrunPy.path(), - "--browser", browser, - "--port", port, - "--no_emrun_detect", - "--serve_after_close", - html.toString() - }); + QStringList args(emrunPy.path()); + if (!browser.isEmpty()) { + args.append("--browser"); + args.append(browser); + } + args.append("--port"); + args.append(port); + args.append("--no_emrun_detect"); + args.append("--serve_after_close"); + args.append(html.toString()); + + return CommandLine(pythonInterpreter(env), args); } return {}; } @@ -99,6 +103,7 @@ public: "").toUserOutput()); }); + connect(webBrowserAspect, &BaseAspect::changed, this, &RunConfiguration::update); connect(target, &Target::buildSystemUpdated, this, &RunConfiguration::update); } }; @@ -114,8 +119,10 @@ public: setStarter([this, runControl, portsGatherer] { Runnable r; + const QString browserId = + runControl->aspect()->currentBrowser(); r.command = emrunCommand(runControl->runConfiguration(), - runControl->aspect()->currentBrowser(), + browserId, QString::number(portsGatherer->findEndPoint().port())); SimpleTargetRunner::doStart(r, {}); }); diff --git a/src/plugins/webassembly/webassemblyrunconfigurationaspects.cpp b/src/plugins/webassembly/webassemblyrunconfigurationaspects.cpp index ffd6a2d8d6e..32642ab90f5 100644 --- a/src/plugins/webassembly/webassemblyrunconfigurationaspects.cpp +++ b/src/plugins/webassembly/webassemblyrunconfigurationaspects.cpp @@ -34,6 +34,11 @@ #include +#ifdef WITH_TESTS +# include +# include "webassemblyplugin.h" +#endif // WITH_TESTS + using namespace Utils; namespace WebAssembly { @@ -41,40 +46,46 @@ namespace Internal { static const char BROWSER_KEY[] = "WASM.WebBrowserSelectionAspect.Browser"; -static QStringList detectedBrowsers(ProjectExplorer::Target *target) +static WebBrowserEntries parseEmrunOutput(const QByteArray &output) { - static QStringList result; - if (result.isEmpty()) { - if (auto bc = target->activeBuildConfiguration()) { - const Utils::Environment environment = bc->environment(); - const Utils::FilePath emrunPath = environment.searchInPath("emrun"); + WebBrowserEntries result; + QTextStream ts(output); + QString line; + const QRegularExpression regExp(" - (.*):(.*)"); + while (ts.readLineInto(&line)) { + const QRegularExpressionMatch match = regExp.match(line); + if (match.hasMatch()) + result << qMakePair(match.captured(1), match.captured(2).trimmed()); + } + return result; +} - QtcProcess browserLister; - browserLister.setEnvironment(environment); - browserLister.setCommand({emrunPath, {"--list_browsers"}}); - browserLister.start(); +static WebBrowserEntries emrunBrowsers(ProjectExplorer::Target *target) +{ + WebBrowserEntries result; + result.append(qMakePair(QString(), WebBrowserSelectionAspect::tr("Default Browser"))); + if (auto bc = target->activeBuildConfiguration()) { + const Utils::Environment environment = bc->environment(); + const Utils::FilePath emrunPath = environment.searchInPath("emrun"); - if (browserLister.waitForFinished()) { - const QByteArray output = browserLister.readAllStandardOutput(); - QTextStream ts(output); - QString line; - const QRegularExpression regExp(" - (.*):.*"); - while (ts.readLineInto(&line)) { - const QRegularExpressionMatch match = regExp.match(line); - if (match.hasMatch()) - result << match.captured(1); - } - } - } + QtcProcess browserLister; + browserLister.setEnvironment(environment); + browserLister.setCommand({emrunPath, {"--list_browsers"}}); + browserLister.start(); + + if (browserLister.waitForFinished()) + result.append(parseEmrunOutput(browserLister.readAllStandardOutput())); } return result; } WebBrowserSelectionAspect::WebBrowserSelectionAspect(ProjectExplorer::Target *target) - : m_availableBrowsers(detectedBrowsers(target)) + : m_availableBrowsers(emrunBrowsers(target)) { - if (!m_availableBrowsers.isEmpty()) - m_currentBrowser = m_availableBrowsers.first(); + if (!m_availableBrowsers.isEmpty()) { + const int defaultIndex = qBound(0, m_availableBrowsers.count() - 1, 1); + m_currentBrowser = m_availableBrowsers.at(defaultIndex).first; + } setDisplayName(tr("Web Browser")); setId("WebBrowserAspect"); setSettingsKey("RunConfiguration.WebBrowser"); @@ -84,11 +95,12 @@ void WebBrowserSelectionAspect::addToLayout(LayoutBuilder &builder) { QTC_CHECK(!m_webBrowserComboBox); m_webBrowserComboBox = new QComboBox; - m_webBrowserComboBox->addItems(m_availableBrowsers); - m_webBrowserComboBox->setCurrentText(m_currentBrowser); - connect(m_webBrowserComboBox, &QComboBox::currentTextChanged, - [this](const QString &selectedBrowser){ - m_currentBrowser = selectedBrowser; + for (const WebBrowserEntry &be : m_availableBrowsers) + m_webBrowserComboBox->addItem(be.second, be.first); + m_webBrowserComboBox->setCurrentIndex(m_webBrowserComboBox->findData(m_currentBrowser)); + connect(m_webBrowserComboBox, &QComboBox::currentIndexChanged, + [this]() { + m_currentBrowser = m_webBrowserComboBox->currentData().toString(); emit changed(); }); builder.addItems({tr("Web browser:"), m_webBrowserComboBox}); @@ -97,7 +109,7 @@ void WebBrowserSelectionAspect::addToLayout(LayoutBuilder &builder) void WebBrowserSelectionAspect::fromMap(const QVariantMap &map) { if (!m_availableBrowsers.isEmpty()) - m_currentBrowser = map.value(BROWSER_KEY, m_availableBrowsers.first()).toString(); + m_currentBrowser = map.value(BROWSER_KEY, m_availableBrowsers.first().first).toString(); } void WebBrowserSelectionAspect::toMap(QVariantMap &map) const @@ -110,5 +122,58 @@ QString WebBrowserSelectionAspect::currentBrowser() const return m_currentBrowser; } +// Unit tests: +#ifdef WITH_TESTS + +void testEmrunBrowserListParsing(); +void testEmrunBrowserListParsing_data(); + +void WebAssemblyPlugin::testEmrunBrowserListParsing() +{ + QFETCH(QByteArray, emrunOutput); + QFETCH(WebBrowserEntries, expectedBrowsers); + + QCOMPARE(parseEmrunOutput(emrunOutput), expectedBrowsers); +} + +void WebAssemblyPlugin::testEmrunBrowserListParsing_data() +{ + QTest::addColumn("emrunOutput"); + QTest::addColumn("expectedBrowsers"); + + QTest::newRow("emsdk 1.39.8") +// Output of "emrun --list_browsers" + << QByteArray( +R"(emrun has automatically found the following browsers in the default install locations on the system: + + - firefox: Mozilla Firefox + - chrome: Google Chrome + +You can pass the --browser option to launch with the given browser above. +Even if your browser was not detected, you can use --browser /path/to/browser/executable to launch with that browser. + +)") + << WebBrowserEntries({ + qMakePair(QLatin1String("firefox"), QLatin1String("Mozilla Firefox")), + qMakePair(QLatin1String("chrome"), QLatin1String("Google Chrome"))}); + + QTest::newRow("emsdk 2.0.14") + << QByteArray( +R"(emrun has automatically found the following browsers in the default install locations on the system: + + - firefox: Mozilla Firefox 96.0.0.8041 + - chrome: Google Chrome 97.0.4692.71 + +You can pass the --browser option to launch with the given browser above. +Even if your browser was not detected, you can use --browser /path/to/browser/executable to launch with that browser. + +)") + << WebBrowserEntries({ + qMakePair(QLatin1String("firefox"), QLatin1String("Mozilla Firefox 96.0.0.8041")), + qMakePair(QLatin1String("chrome"), QLatin1String("Google Chrome 97.0.4692.71"))}); +} + +#endif // WITH_TESTS + } // namespace Internal } // namespace Webassembly diff --git a/src/plugins/webassembly/webassemblyrunconfigurationaspects.h b/src/plugins/webassembly/webassemblyrunconfigurationaspects.h index 00cd2ac877d..b1360a79faf 100644 --- a/src/plugins/webassembly/webassemblyrunconfigurationaspects.h +++ b/src/plugins/webassembly/webassemblyrunconfigurationaspects.h @@ -32,6 +32,9 @@ QT_FORWARD_DECLARE_CLASS(QComboBox) namespace WebAssembly { namespace Internal { +using WebBrowserEntry = QPair; // first: id, second: display name +using WebBrowserEntries = QList; + class WebBrowserSelectionAspect : public Utils::BaseAspect { Q_OBJECT @@ -49,7 +52,7 @@ public: private: QComboBox *m_webBrowserComboBox = nullptr; QString m_currentBrowser; - QStringList m_availableBrowsers; + const WebBrowserEntries m_availableBrowsers; }; } // namespace Internal