From d155e971b5ece35c75efbd7572bcbd8515f25cf8 Mon Sep 17 00:00:00 2001 From: Sergey Linev <S.Linev@gsi.de> Date: Fri, 15 Mar 2019 17:07:06 +0100 Subject: [PATCH] webui: ensure Qt5 works with custom scheme handle Qt5 now requires that custom "rootscheme:" registered before Qt application created. Therefore now there is no separated handlers for different window - single handler created once. Works now with only THttpServer instance (like in CEF), can be enhanced later for many of them. --- gui/qt5webdisplay/rootqt5.cpp | 61 ++++++++++------------ gui/qt5webdisplay/rooturlschemehandler.cpp | 43 ++++++++------- gui/qt5webdisplay/rooturlschemehandler.h | 18 +++---- gui/qt5webdisplay/rootwebpage.cpp | 8 +-- gui/qt5webdisplay/rootwebpage.h | 4 +- gui/qt5webdisplay/rootwebview.cpp | 2 +- gui/qt5webdisplay/rootwebview.h | 4 +- 7 files changed, 66 insertions(+), 74 deletions(-) diff --git a/gui/qt5webdisplay/rootqt5.cpp b/gui/qt5webdisplay/rootqt5.cpp index 5eca8e0c368..43a2ed5f422 100644 --- a/gui/qt5webdisplay/rootqt5.cpp +++ b/gui/qt5webdisplay/rootqt5.cpp @@ -6,7 +6,7 @@ /// is welcome! /************************************************************************* - * Copyright (C) 1995-2017, Rene Brun and Fons Rademakers. * + * Copyright (C) 1995-2019, Rene Brun and Fons Rademakers. * * All rights reserved. * * * * For the licensing terms see $ROOTSYS/LICENSE. * @@ -19,6 +19,7 @@ #include <QThread> #include <QWebEngineSettings> #include <QWebEngineProfile> +#include <QWebEngineUrlScheme> #include "TROOT.h" #include "TApplication.h" @@ -40,10 +41,11 @@ class TQt5Timer : public TTimer { public: TQt5Timer(Long_t milliSec, Bool_t mode) : TTimer(milliSec, mode) {} - virtual void Timeout() + + /// timeout handler + /// used to process all qt5 events in main ROOT thread + void Timeout() override { - // timeout handler - // used to process all qt5 events in main ROOT thread QApplication::sendPostedEvents(); QApplication::processEvents(); } @@ -60,11 +62,18 @@ protected: int qargc{1}; ///< arg counter char *qargv[10]; ///< arg values bool fInitEngine{false}; ///< does engine was initialized - TQt5Timer *fTimer{nullptr}; ///< timer to process ROOT events + std::unique_ptr<TQt5Timer> fTimer; ///< timer to process ROOT events + std::unique_ptr<RootUrlSchemeHandler> fHandler; ///< specialized handler public: Qt5Creator() = default; + virtual ~Qt5Creator() + { + if (fHandler) + QWebEngineProfile::defaultProfile()->removeUrlSchemeHandler(fHandler.get()); + } + std::unique_ptr<RWebDisplayHandle> Display(const RWebDisplayArgs &args) override { if (args.IsHeadless()) @@ -77,6 +86,12 @@ protected: return nullptr; } + QWebEngineUrlScheme scheme("rootscheme"); + scheme.setSyntax(QWebEngineUrlScheme::Syntax::HostAndPort); + scheme.setDefaultPort(2345); + scheme.setFlags(QWebEngineUrlScheme::SecureScheme); + QWebEngineUrlScheme::registerScheme(scheme); + qargv[0] = gApplication->Argv(0); qargv[1] = nullptr; qapp = new QApplication(qargc, qargv); @@ -90,18 +105,21 @@ protected: if (!fTimer) { Int_t interval = gEnv->GetValue("WebGui.Qt5Timer", 1); if (interval > 0) { - fTimer = new TQt5Timer(interval, kTRUE); + fTimer = std::make_unique<TQt5Timer>(interval, kTRUE); fTimer->TurnOn(); } } - std::unique_ptr<RootUrlSchemeHandler> handler; QString fullurl = QString(args.GetUrl().c_str()); // if no server provided - normal HTTP will be allowed to use if (args.GetHttpServer()) { - handler = std::make_unique<RootUrlSchemeHandler>(args.GetHttpServer(), fCounter++); - fullurl = handler->MakeFullUrl(fullurl); + if (!fHandler) { + fHandler = std::make_unique<RootUrlSchemeHandler>(); + QWebEngineProfile::defaultProfile()->installUrlSchemeHandler("rootscheme", fHandler.get()); + } + + fullurl = fHandler->MakeFullUrl(args.GetHttpServer(), fullurl); } QWidget *qparent = (QWidget *) args.GetDriverData(); @@ -111,7 +129,7 @@ protected: fullurl.append(QString(args.GetUrlOpt().c_str())); } - auto handle = std::make_unique<RQt5WebDisplayHandle>(fullurl.toLatin1().constData(), handler); + auto handle = std::make_unique<RQt5WebDisplayHandle>(fullurl.toLatin1().constData()); if (args.IsHeadless()) { RootWebPage *page = new RootWebPage(); @@ -128,26 +146,10 @@ protected: return handle; } - virtual ~Qt5Creator() - { - if (fTimer) { - fTimer->TurnOff(); - delete fTimer; - } - - } }; - std::unique_ptr<RootUrlSchemeHandler> fHandler; - public: - RQt5WebDisplayHandle(const std::string &url, std::unique_ptr<RootUrlSchemeHandler> &handler) - : RWebDisplayHandle(url) - { - std::swap(fHandler, handler); - if (fHandler) - QWebEngineProfile::defaultProfile()->installUrlSchemeHandler(QByteArray(fHandler->GetProtocol()), fHandler.get()); - } + RQt5WebDisplayHandle(const std::string &url) : RWebDisplayHandle(url) {} static void AddCreator() { @@ -156,11 +158,6 @@ public: GetMap().emplace("qt5", std::make_unique<Qt5Creator>()); } - virtual ~RQt5WebDisplayHandle() - { - if (fHandler) - QWebEngineProfile::defaultProfile()->removeUrlSchemeHandler(fHandler.get()); - } }; struct RQt5CreatorReg { diff --git a/gui/qt5webdisplay/rooturlschemehandler.cpp b/gui/qt5webdisplay/rooturlschemehandler.cpp index 8871bf9240b..2296a5eb01f 100644 --- a/gui/qt5webdisplay/rooturlschemehandler.cpp +++ b/gui/qt5webdisplay/rooturlschemehandler.cpp @@ -1,4 +1,4 @@ -/// \file rootqt5.cpp +/// \file rooturlschemehandler.cpp /// \ingroup WebUI /// \author Sergey Linev <S.Linev@gsi.de> /// \date 2017-06-29 @@ -6,7 +6,7 @@ /// is welcome! /************************************************************************* - * Copyright (C) 1995-2017, Rene Brun and Fons Rademakers. * + * Copyright (C) 1995-2019, Rene Brun and Fons Rademakers. * * All rights reserved. * * * * For the licensing terms see $ROOTSYS/LICENSE. * @@ -128,14 +128,27 @@ public: }; -/////////////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////// +/// Returns fully qualified URL, required to open in QWindow -RootUrlSchemeHandler::RootUrlSchemeHandler(THttpServer *server, int counter) - : QWebEngineUrlSchemeHandler(), fServer(server) +QString RootUrlSchemeHandler::MakeFullUrl(THttpServer *serv, const QString &url) { - fProtocol = Form("roothandler%d", counter); + // TODO: provide support for many servers + fServer = serv; + + QString res = "rootscheme://root.server1"; + res.append(url); + if (url.indexOf("?") < 0) + res.append("?"); + else + res.append("&"); + + // TODO: with should be solved different way - maybe via replacements in main HTML page + res.append("platform=qt5&ws=rawlongpoll"); + return res; } + /////////////////////////////////////////////////////////////////////////////////////////////////// /// Start processing of emulated HTTP request in WebEngine scheme handler /// Either one reads file or redirect request to THttpServer @@ -154,6 +167,8 @@ void RootUrlSchemeHandler::requestStarted(QWebEngineUrlRequestJob *request) QString inp_query = url.query(); QString inp_method = request->requestMethod(); + // printf("REQUEST PATH:%s QUERY:%s\n", inp_path.toLatin1().data(), inp_query.toLatin1().data()); + auto arg = std::make_shared<TWebGuiCallArg>(request); TString fname; @@ -181,19 +196,3 @@ void RootUrlSchemeHandler::requestStarted(QWebEngineUrlRequestJob *request) // can process immediately - function called in main thread fServer->SubmitHttp(arg, kTRUE); } - -///////////////////////////////////////////////////////////////// -/// Returns fully qualified URL, required to open in QWindow - -QString RootUrlSchemeHandler::MakeFullUrl(const QString &url) -{ - QString res = fProtocol; - res.append(":"); - res.append(url); - if (url.indexOf("?")<0) - res.append("?"); - else - res.append("&"); - res.append("platform=qt5&ws=rawlongpoll"); - return res; -} diff --git a/gui/qt5webdisplay/rooturlschemehandler.h b/gui/qt5webdisplay/rooturlschemehandler.h index 2ed536d6ff0..bee192907c9 100644 --- a/gui/qt5webdisplay/rooturlschemehandler.h +++ b/gui/qt5webdisplay/rooturlschemehandler.h @@ -1,4 +1,4 @@ -/// \file rootwebpage.h +/// \file rooturlschemehandler.h /// \ingroup WebUI /// \author Sergey Linev <S.Linev@gsi.de> /// \date 2017-06-29 @@ -6,7 +6,7 @@ /// is welcome! /************************************************************************* - * Copyright (C) 1995-2017, Rene Brun and Fons Rademakers. * + * Copyright (C) 1995-2019, Rene Brun and Fons Rademakers. * * All rights reserved. * * * * For the licensing terms see $ROOTSYS/LICENSE. * @@ -33,7 +33,9 @@ public: void reset(); public slots: + void onRequestDeleted(QObject *obj); + }; // =============================================================== @@ -43,20 +45,12 @@ class RootUrlSchemeHandler : public QWebEngineUrlSchemeHandler { Q_OBJECT protected: - QString fProtocol; - THttpServer *fServer{nullptr}; ///< server instance which should handle requests public: - RootUrlSchemeHandler(THttpServer *server = nullptr, int counter = 0); - - virtual ~RootUrlSchemeHandler() = default; - - QByteArray GetProtocol() const { return QByteArray(fProtocol.toLatin1().constData(), fProtocol.length()); } - - QString MakeFullUrl(const QString &url); + QString MakeFullUrl(THttpServer *serv, const QString &url); - virtual void requestStarted(QWebEngineUrlRequestJob *request); + void requestStarted(QWebEngineUrlRequestJob *request) override; }; diff --git a/gui/qt5webdisplay/rootwebpage.cpp b/gui/qt5webdisplay/rootwebpage.cpp index 5334313ffef..dda988278b5 100644 --- a/gui/qt5webdisplay/rootwebpage.cpp +++ b/gui/qt5webdisplay/rootwebpage.cpp @@ -6,7 +6,7 @@ /// is welcome! /************************************************************************* - * Copyright (C) 1995-2017, Rene Brun and Fons Rademakers. * + * Copyright (C) 1995-2019, Rene Brun and Fons Rademakers. * * All rights reserved. * * * * For the licensing terms see $ROOTSYS/LICENSE. * @@ -24,10 +24,12 @@ void RootWebPage::javaScriptConsoleMessage(JavaScriptConsoleMessageLevel lvl, co switch (lvl) { case InfoMessageLevel: if (gDebug > 0) - R__DEBUG_HERE("Qt") << Form("%s:%d: %s", src.toLatin1().constData(), lineNumber, message.toLatin1().constData()); + R__DEBUG_HERE("Qt") << Form("%s:%d: %s", src.toLatin1().constData(), lineNumber, + message.toLatin1().constData()); break; case WarningMessageLevel: - R__WARNING_HERE("Qt") << Form("%s:%d: %s", src.toLatin1().constData(), lineNumber, message.toLatin1().constData()); + R__WARNING_HERE("Qt") << Form("%s:%d: %s", src.toLatin1().constData(), lineNumber, + message.toLatin1().constData()); break; case ErrorMessageLevel: R__ERROR_HERE("Qt") << Form("%s:%d: %s", src.toLatin1().constData(), lineNumber, message.toLatin1().constData()); diff --git a/gui/qt5webdisplay/rootwebpage.h b/gui/qt5webdisplay/rootwebpage.h index cb74de94852..5ec512af586 100644 --- a/gui/qt5webdisplay/rootwebpage.h +++ b/gui/qt5webdisplay/rootwebpage.h @@ -6,7 +6,7 @@ /// is welcome! /************************************************************************* - * Copyright (C) 1995-2017, Rene Brun and Fons Rademakers. * + * Copyright (C) 1995-2019, Rene Brun and Fons Rademakers. * * All rights reserved. * * * * For the licensing terms see $ROOTSYS/LICENSE. * @@ -25,7 +25,7 @@ protected: int lineNumber, const QString &sourceID); public: - RootWebPage(QObject *parent = 0) : QWebEnginePage(parent) {} + RootWebPage(QObject *parent = nullptr) : QWebEnginePage(parent) {} virtual ~RootWebPage() = default; }; diff --git a/gui/qt5webdisplay/rootwebview.cpp b/gui/qt5webdisplay/rootwebview.cpp index 662ed0966c0..8820266af62 100644 --- a/gui/qt5webdisplay/rootwebview.cpp +++ b/gui/qt5webdisplay/rootwebview.cpp @@ -6,7 +6,7 @@ /// is welcome! /************************************************************************* - * Copyright (C) 1995-2017, Rene Brun and Fons Rademakers. * + * Copyright (C) 1995-2019, Rene Brun and Fons Rademakers. * * All rights reserved. * * * * For the licensing terms see $ROOTSYS/LICENSE. * diff --git a/gui/qt5webdisplay/rootwebview.h b/gui/qt5webdisplay/rootwebview.h index ff98a4843ff..90efc42668c 100644 --- a/gui/qt5webdisplay/rootwebview.h +++ b/gui/qt5webdisplay/rootwebview.h @@ -6,7 +6,7 @@ /// is welcome! /************************************************************************* - * Copyright (C) 1995-2017, Rene Brun and Fons Rademakers. * + * Copyright (C) 1995-2019, Rene Brun and Fons Rademakers. * * All rights reserved. * * * * For the licensing terms see $ROOTSYS/LICENSE. * @@ -39,7 +39,7 @@ signals: void drop(QDropEvent* event); public: - RootWebView(QWidget *parent = 0, unsigned width = 0, unsigned height = 0); + RootWebView(QWidget *parent = nullptr, unsigned width = 0, unsigned height = 0); virtual ~RootWebView() = default; virtual QSize sizeHint() const; -- GitLab