Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
rootqt6.cpp
Go to the documentation of this file.
1// Author: Sergey Linev <S.Linev@gsi.de>
2// Date: 2017-06-29
3// Warning: This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback is welcome!
4
5/*************************************************************************
6 * Copyright (C) 1995-2023, Rene Brun and Fons Rademakers. *
7 * All rights reserved. *
8 * *
9 * For the licensing terms see $ROOTSYS/LICENSE. *
10 * For the list of contributors see $ROOTSYS/README/CREDITS. *
11 *************************************************************************/
12
13#include <QApplication>
14#include <QWebEngineView>
15#include <qtwebenginecoreglobal.h>
16#include <QWebEngineDownloadRequest>
17
18#include <QThread>
19#include <QWebEngineSettings>
20#include <QWebEngineProfile>
21#include <QtGlobal>
22
23#include <QWebEngineUrlScheme>
24
25#include "TROOT.h"
26#include "TApplication.h"
27#include "TTimer.h"
28#include "TEnv.h"
29#include "TThread.h"
30#include "THttpServer.h"
31#include "TSystem.h"
32
33#include "../qt5webdisplay/rootwebview.h"
34#include "../qt5webdisplay/rootwebpage.h"
35#include "../qt5webdisplay/rooturlschemehandler.h"
36
37#include <memory>
38
40#include <ROOT/RLogger.hxx>
41
42QWebEngineUrlScheme gRootScheme("rootscheme");
43
44
45/** \class TQt6Timer
46\ingroup qt6webdisplay
47*/
48
49class TQt6Timer : public TTimer {
50public:
51 TQt6Timer(Long_t milliSec, Bool_t mode) : TTimer(milliSec, mode) {}
52
53 /// timeout handler
54 /// used to process all qt6 events in main ROOT thread
55 void Timeout() override
56 {
57 QApplication::sendPostedEvents();
58 QApplication::processEvents();
59 }
60};
61
62namespace ROOT {
63
64/** \class RQt6WebDisplayHandle
65\ingroup qt6webdisplay
66*/
67
69protected:
70
71 RootWebView *fView{nullptr}; ///< pointer on widget, need to release when handle is destroyed
72
73 class Qt6Creator : public Creator {
74 QApplication *qapp{nullptr}; ///< created QApplication
75 int qargc{1}; ///< arg counter
76 char *qargv[2]; ///< arg values
77 std::unique_ptr<TQt6Timer> fTimer; ///< timer to process ROOT events
78 std::unique_ptr<RootUrlSchemeHandler> fHandler; ///< specialized handler
79 public:
80
81 Qt6Creator() = default;
82
83 ~Qt6Creator() override
84 {
85 /** Code executed during exit and sometime crashes.
86 * Disable it, while not clear if defaultProfile can be still used - seems to be not */
87 // if (fHandler)
88 // QWebEngineProfile::defaultProfile()->removeUrlSchemeHandler(fHandler.get());
89
90 R__LOG_DEBUG(0, QtWebDisplayLog()) << "Deleting Qt6Creator";
91 }
92
93 std::unique_ptr<RWebDisplayHandle> Display(const RWebDisplayArgs &args) override
94 {
95 if (!qapp && !QApplication::instance()) {
96
97 if (!gApplication) {
98 R__LOG_ERROR(QtWebDisplayLog()) << "Not found gApplication to create QApplication";
99 return nullptr;
100 }
101
102 // initialize web engine only before creating QApplication
103 // QtWebEngineQuick::initialize();
104
105 qargv[0] = gApplication->Argv(0);
106 qargv[1] = nullptr;
107
108 qapp = new QApplication(qargc, qargv);
109 }
110
111 // create timer to process Qt events from inside ROOT process events
112 // very much improve performance, even when Qt even loop runs by QApplication normally
113 if (!fTimer && !args.IsHeadless()) {
114 Int_t interval = gEnv->GetValue("WebGui.Qt5Timer", 1);
115 if (interval > 0) {
116 fTimer = std::make_unique<TQt6Timer>(interval, kTRUE);
117 fTimer->TurnOn();
118 }
119 }
120
121 QString fullurl = QString(args.GetFullUrl().c_str());
122
123 // if no server provided - normal HTTP will be allowed to use
124 if (args.GetHttpServer()) {
125 if (!fHandler) {
126 fHandler = std::make_unique<RootUrlSchemeHandler>();
127 QWebEngineProfile::defaultProfile()->installUrlSchemeHandler("rootscheme", fHandler.get());
128 QWebEngineProfile::defaultProfile()->connect(QWebEngineProfile::defaultProfile(), &QWebEngineProfile::downloadRequested,
129 [](QWebEngineDownloadRequest *request) { request->accept(); });
130 }
131
132 fullurl = fHandler->MakeFullUrl(args.GetHttpServer(), fullurl);
133 }
134
135 QWidget *qparent = static_cast<QWidget *>(args.GetDriverData());
136
137 auto handle = std::make_unique<RQt6WebDisplayHandle>(fullurl.toLatin1().constData());
138
139 RootWebView *view = new RootWebView(qparent, args.GetWidth(), args.GetHeight(), args.GetX(), args.GetY());
140
141 if (!args.IsHeadless()) {
142 if (!qparent) handle->fView = view;
143 view->load(QUrl(fullurl));
144 view->show();
145 } else {
146
147 int tmout_sec = 30, expired = tmout_sec * 100;
148 bool load_finished = false, did_try = false, get_content = false, is_error = false;
149 std::string content, pdffile;
150
151 if (!args.GetExtraArgs().empty() && (args.GetExtraArgs().find("--print-to-pdf=")==0))
152 pdffile = args.GetExtraArgs().substr(15);
153
154 QObject::connect(view, &RootWebView::loadFinished, [&load_finished, &is_error](bool is_ok) {
155 load_finished = true; is_error = !is_ok;
156 });
157
158 if (!pdffile.empty())
159 QObject::connect(view->page(), &RootWebPage::pdfPrintingFinished, [&expired, &is_error](const QString &, bool is_ok) {
160 expired = 0; is_error = !is_ok;
161 });
162
163 const std::string &page_content = args.GetPageContent();
164 if (page_content.empty())
165 view->load(QUrl(fullurl));
166 else
167 view->setHtml(QString::fromUtf8(page_content.data(), page_content.size()), QUrl("file:///batch_page.html"));
168
169 // loop here until content is configured
170 while ((--expired > 0) && !get_content && !is_error) {
171
172 if (gSystem->ProcessEvents()) break; // interrupted, has to return
173
174 QApplication::sendPostedEvents();
175 QApplication::processEvents();
176
177 if (load_finished && !did_try) {
178 did_try = true;
179
180 if (pdffile.empty()) {
181 view->page()->toHtml([&get_content, &content](const QString& res) {
182 get_content = true;
183 content = res.toLatin1().constData();
184 });
185 } else {
186 view->page()->printToPdf(QString::fromUtf8(pdffile.data(), pdffile.size()));
187 #if QT_VERSION < 0x050900
188 expired = 5; // no signal will be produced, just wait short time and break loop
189 #endif
190 }
191 }
192
193 gSystem->Sleep(10); // only 10 ms sleep
194 }
195
196 if(get_content)
197 handle->SetContent(content);
198
199 // delete view and process events
200 delete view;
201
202 for (expired=0;expired<100;++expired) {
203 QApplication::sendPostedEvents();
204 QApplication::processEvents();
205 }
206
207 }
208
209 return handle;
210 }
211
212 };
213
214public:
215 RQt6WebDisplayHandle(const std::string &url) : RWebDisplayHandle(url) {}
216
218 {
219 // now view can be safely destroyed
220 if (fView) {
221 delete fView;
222 fView = nullptr;
223 }
224 }
225
226 bool Resize(int width, int height) override
227 {
228 if (!fView)
229 return false;
230 fView->resize(QSize(width, height));
231 return true;
232 }
233
234 static void AddCreator()
235 {
236 auto &entry = FindCreator("qt6");
237 if (!entry)
238 GetMap().emplace("qt6", std::make_unique<Qt6Creator>());
239 }
240
241};
242
245 {
247
248 gRootScheme.setSyntax(QWebEngineUrlScheme::Syntax::HostAndPort);
249 gRootScheme.setDefaultPort(2345);
250 gRootScheme.setFlags(QWebEngineUrlScheme::SecureScheme);
251 QWebEngineUrlScheme::registerScheme(gRootScheme);
252
253 }
255
256} // namespace ROOT
#define R__LOG_ERROR(...)
Definition RLogger.hxx:362
#define R__LOG_DEBUG(DEBUGLEVEL,...)
Definition RLogger.hxx:365
long Long_t
Definition RtypesCore.h:54
constexpr Bool_t kTRUE
Definition RtypesCore.h:100
R__EXTERN TApplication * gApplication
R__EXTERN TEnv * gEnv
Definition TEnv.h:170
Option_t Option_t TPoint TPoint const char mode
Option_t Option_t width
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t height
R__EXTERN TSystem * gSystem
Definition TSystem.h:560
std::unique_ptr< RootUrlSchemeHandler > fHandler
specialized handler
Definition rootqt6.cpp:78
std::unique_ptr< RWebDisplayHandle > Display(const RWebDisplayArgs &args) override
Definition rootqt6.cpp:93
QApplication * qapp
created QApplication
Definition rootqt6.cpp:74
std::unique_ptr< TQt6Timer > fTimer
timer to process ROOT events
Definition rootqt6.cpp:77
bool Resize(int width, int height) override
resize web window - if possible
Definition rootqt6.cpp:226
RQt6WebDisplayHandle(const std::string &url)
Definition rootqt6.cpp:215
~RQt6WebDisplayHandle() override
Definition rootqt6.cpp:217
RootWebView * fView
pointer on widget, need to release when handle is destroyed
Definition rootqt6.cpp:71
Holds different arguments for starting browser with RWebDisplayHandle::Display() method.
THttpServer * GetHttpServer() const
returns http server instance, used for window display
int GetWidth() const
returns preferable web window width
int GetY() const
set preferable web window y position
std::string GetFullUrl() const
returns window url with append options
int GetHeight() const
returns preferable web window height
bool IsHeadless() const
returns headless mode
void * GetDriverData() const
[internal] returns web-driver data, used to start window
const std::string & GetExtraArgs() const
get extra command line arguments for starting web browser command
int GetX() const
set preferable web window x position
const std::string & GetPageContent() const
returns window url
Handle of created web-based display Depending from type of web display, holds handle of started brows...
static std::map< std::string, std::unique_ptr< Creator > > & GetMap()
Static holder of registered creators of web displays.
static std::unique_ptr< Creator > & FindCreator(const std::string &name, const std::string &libname="")
Search for specific browser creator If not found, try to add one.
char ** Argv() const
virtual Int_t GetValue(const char *name, Int_t dflt) const
Returns the integer value for a resource.
Definition TEnv.cxx:491
TQt6Timer(Long_t milliSec, Bool_t mode)
Definition rootqt6.cpp:51
void Timeout() override
timeout handler used to process all qt6 events in main ROOT thread
Definition rootqt6.cpp:55
virtual void Sleep(UInt_t milliSec)
Sleep milliSec milli seconds.
Definition TSystem.cxx:424
virtual Bool_t ProcessEvents()
Process pending events (GUI, timers, sockets).
Definition TSystem.cxx:403
Handles synchronous and a-synchronous timer events.
Definition TTimer.h:51
This file contains a specialised ROOT message handler to test for diagnostic in unit tests.
struct ROOT::RQt6CreatorReg newRQt6CreatorReg
QWebEngineUrlScheme gRootScheme("rootscheme")
QWebEngineUrlScheme gRootScheme("rootscheme")
ROOT::Experimental::RLogChannel & QtWebDisplayLog()