GSI Object Oriented Online Offline (Go4) GO4-6.4.0
Loading...
Searching...
No Matches
QWebCanvas.cpp
Go to the documentation of this file.
1// $Id$
2//-----------------------------------------------------------------------
3// The GSI Online Offline Object Oriented (Go4) Project
4// Experiment Data Processing at EE department, GSI
5//-----------------------------------------------------------------------
6// Copyright (C) 2000- GSI Helmholtzzentrum fuer Schwerionenforschung GmbH
7// Planckstr. 1, 64291 Darmstadt, Germany
8// Contact: http://go4.gsi.de
9//-----------------------------------------------------------------------
10// This software can be used under the license agreements as stated
11// in Go4License.txt file which is part of the distribution.
12//-----------------------------------------------------------------------
13
14#include "QWebCanvas.h"
15
16#include "TCanvas.h"
17#include "TROOT.h"
18#include "TClass.h"
19#include "RVersion.h"
20#include "THttpServer.h"
21#include "ROOT/RWebWindowsManager.hxx"
22
23#include "TGo4Log.h"
24
25#include <QGridLayout>
26#include <QApplication>
27#include <QTimer>
28#include <QDropEvent>
29
30#include <cstdlib>
31#include <cstdio>
32
33// starting from version 6.23 TWebCanvas includes all required functionality
34#include "TWebCanvas.h"
35
36QWebCanvas::QWebCanvas(QWidget *parent) : QWidget(parent)
37{
38 // JAM the following is pure empiric. hopefully default denominator won't change in future qt?
39 fQtScalingfactor = (double) metric(QPaintDevice::PdmDevicePixelRatioScaled)/65536.;
40
41 setObjectName("QWebCanvas");
42
43 setSizeIncrement(QSize(100, 100));
44
45 setUpdatesEnabled(true);
46 setMouseTracking(true);
47
48 setFocusPolicy(Qt::TabFocus);
49 setCursor(Qt::CrossCursor);
50
51 setAcceptDrops(true);
52
53 fRepaintTimer = new QTimer;
54 fRepaintTimer->setSingleShot(true);
55 QObject::connect(fRepaintTimer, &QTimer::timeout, this, &QWebCanvas::processRepaintTimer);
56
57 // if ROOT compiled with X11 - batch mode is default, disable it before create web widget
58 if (gROOT->IsBatch())
59 gROOT->SetBatch(kFALSE);
60
61 // disable option that at least background is redrawn immediately
62 // and canvas content after 100 ms timeout
63 //setAttribute(Qt::WA_NoSystemBackground);
64 //setAttribute(Qt::WA_PaintOnScreen);
65 //setAttribute(Qt::WA_PaintUnclipped);
66
67 QGridLayout *gridLayout = new QGridLayout(this);
68 gridLayout->setSpacing(10);
69 gridLayout->setContentsMargins(1,1,1,1);
70
71 static int wincnt = 1;
72
73 fCanvas = new TCanvas(kFALSE);
74 fCanvas->SetName(TString::Format("Canvas%d", wincnt++).Data());
75 fCanvas->SetTitle("title");
76 fCanvas->ResetBit(TCanvas::kShowEditor);
77 fCanvas->SetCanvas(fCanvas);
78 fCanvas->SetBatch(kTRUE); // mark canvas as batch
79
80 gPad = fCanvas;
81
82 auto web = new TWebCanvas(fCanvas, "title", 0, 0, 800, 600, kFALSE);
83
84
85 #if ROOT_VERSION_CODE >= ROOT_VERSION(6,33,0) && QT_VERSION >= QT_VERSION_CHECK(6,0,0)
86 // this is usage of new JS modules functionality, works only with qt6
87 ROOT::RWebWindowsManager::AddServerLocation("go4sys", TGo4Log::GO4SYS());
88 static std::string go4script = "modules:go4sys/html5/go4canvas.mjs";
89 #else
90 // old method to load plain JS scripts as is
91 static std::string go4script = THttpServer::ReadFileContent(TGo4Log::subGO4SYS("html/go4canvas.js").Data());
92 #endif
93
94 // these methods are static in newer ROOT starting from 6.33
95 web->SetCustomScripts(go4script);
96
97 web->AddCustomClass("TGo4Marker");
98 web->AddCustomClass("TGo4Condition", true);
99 web->AddCustomClass("TGo4CondArray");
100
101 // this is end of Go4-special part
102
103#if ROOT_VERSION_CODE >= ROOT_VERSION(6,26,0)
104 web->SetAsyncMode(kTRUE); // avoid blocking mode
105#endif
106
107 fCanvas->SetCanvasImp(web);
108
110
111 web->SetCanCreateObjects(kFALSE); // not yet create objects on server side
112
113 web->SetUpdatedHandler([this]() { ProcessCanvasUpdated(); });
114
115 web->SetActivePadChangedHandler([this](TPad *pad){ ProcessActivePadChanged(pad); });
116
117 web->SetPadClickedHandler([this](TPad *pad, int x, int y) { ProcessPadClicked(pad, x, y); });
118
119 web->SetPadDblClickedHandler([this](TPad *pad, int x, int y) { ProcessPadDblClicked(pad, x, y); });
120
121#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
122 const char *kind = "qt6";
123#else
124 const char *kind = "qt5";
125#endif
126
127#if ROOT_VERSION_CODE > ROOT_VERSION(6,29,0)
128 ROOT::RWebDisplayArgs args(kind);
129#else
130 ROOT::Experimental::RWebDisplayArgs args(kind);
131#endif
132
133 args.SetDriverData(this); // it is parent widget for created QWebEngineView element
134 args.SetUrlOpt("noopenui");
135
136 web->ShowWebWindow(args);
137
138 fView = findChild<QWebEngineView *>("RootWebView");
139 if (!fView) {
140 printf("FAIL TO FIND QWebEngineView - ROOT %sweb plugin does not work properly !!!!!\n", kind);
141 exit(11);
142 }
143
144 gridLayout->addWidget(fView);
145
146 // keep symbolic connect while rootwebview class does not exported
147 QObject::connect(fView, SIGNAL(drop(QDropEvent*)), this, SLOT(dropView(QDropEvent*)));
148
149 fCanvas->SetCanvasSize(fView->width(), fView->height());
150}
151
153{
154 if (fCanvas) {
156
157 gROOT->GetListOfCanvases()->Remove(fCanvas);
158
159 fCanvas->Close();
160 delete fCanvas;
161 fCanvas = nullptr;
162 }
163}
164
166{
167 Long_t offset = TCanvas::Class()->GetDataMemberOffset("fCanvasID");
168 if (offset > 0) {
169 Int_t *id = (Int_t *)((char *) fCanvas + offset);
170 if (*id == fCanvas->GetCanvasID()) *id = on_init ? 111222333 : -1;
171 } else {
172 printf("ERROR: Cannot modify TCanvas::fCanvasID data member\n");
173 }
174
175 offset = TCanvas::Class()->GetDataMemberOffset("fPixmapID");
176 if (offset > 0) {
177 Int_t *id = (Int_t *)((char *) fCanvas + offset);
178 if (*id == fCanvas->GetPixmapID()) *id = on_init ? 332211 : -1;
179 } else {
180 printf("ERROR: Cannot modify TCanvas::fPixmapID data member\n");
181 }
182
183 offset = TCanvas::Class()->GetDataMemberOffset("fMother");
184 if (offset > 0) {
185 TPad **moth = (TPad **)((char *) fCanvas + offset);
186 if (*moth == fCanvas->GetMother()) *moth = on_init ? fCanvas : nullptr;
187 } else {
188 printf("ERROR: Cannot set TCanvas::fMother data member\n");
189 }
190
191}
192
193void QWebCanvas::resizeEvent(QResizeEvent *event)
194{
195 fCanvas->SetCanvasSize(fView->width(), fView->height());
196}
197
198void QWebCanvas::dropEvent(QDropEvent* event)
199{
200 // TODO: remove, not needed at all
201
202 TObject *obj = nullptr;
203#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
204 QPoint pos = event->pos();
205#else
206 QPoint pos = event->position().toPoint();
207#endif
208 auto pad = fCanvas->Pick(scaledPosition(pos.x()), scaledPosition(pos.y()), obj);
209
210 emit CanvasDropEvent(event, pad ? pad : fCanvas);
211}
212
213void QWebCanvas::dropView(QDropEvent* event)
214{
215 TObject *obj = nullptr;
216#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
217 QPoint pos = event->pos();
218#else
219 QPoint pos = event->position().toPoint();
220#endif
221 auto pad = fCanvas->Pick(scaledPosition(pos.x()), scaledPosition(pos.y()), obj);
222
223 emit CanvasDropEvent(event, pad ? pad : fCanvas);
224}
225
226void QWebCanvas::activateEditor(TPad *pad, TObject *obj)
227{
228 auto cimp = dynamic_cast<TWebCanvas *> (fCanvas->GetCanvasImp());
229 if (cimp) {
230 cimp->ShowEditor(kTRUE);
231 cimp->ActivateInEditor(pad, obj);
232 }
233}
234
236{
237 return fCanvas->GetShowEventStatus();
238}
239
241{
242 return fCanvas->GetShowEditor();
243}
244
246{
247 if (fCanvas->GetShowEventStatus() != flag)
248 fCanvas->ToggleEventStatus();
249}
250
252{
253 auto cimp = fCanvas->GetCanvasImp();
254 if (cimp) cimp->ShowEditor(flag);
255}
256
258{
259 auto cimp = fCanvas->GetCanvasImp();
260 if (cimp) cimp->ShowStatusBar(kTRUE);
261}
262
264{
265 fCanvas->Update();
266}
267
269{
270 fCanvas->Modified();
271}
272
274{
275 fRepaintTimer->setSingleShot(true);
276 fRepaintTimer->start(100);
277}
void dropEvent(QDropEvent *event) override
void SetPrivateCanvasFields(bool on_init)
void Update()
void Modified()
void CanvasDropEvent(QDropEvent *, TPad *)
void activateStatusLine()
bool isStatusBarVisible()
QWebEngineView * fView
qt webwidget to show
Definition QWebCanvas.h:87
void ProcessActivePadChanged(TPad *pad)
Definition QWebCanvas.h:81
virtual ~QWebCanvas()
void processRepaintTimer()
double scaledPosition(int p)
Definition QWebCanvas.h:75
void activateEditor(TPad *pad=nullptr, TObject *obj=nullptr)
QWebCanvas(QWidget *parent=nullptr)
QTimer * fRepaintTimer
Definition QWebCanvas.h:91
void ProcessCanvasUpdated()
Definition QWebCanvas.h:79
void setStatusBarVisible(bool flag=true)
void ProcessPadClicked(TPad *pad, int x, int y)
Definition QWebCanvas.h:83
void ProcessPadDblClicked(TPad *pad, int x, int y)
Definition QWebCanvas.h:85
bool isEditorVisible()
void dropView(QDropEvent *event)
void resizeEvent(QResizeEvent *event) override
TCanvas * fCanvas
Definition QWebCanvas.h:89
void setEditorVisible(bool flag=true)
double fQtScalingfactor
Definition QWebCanvas.h:93
static TString subGO4SYS(const char *subdir)
Return subdirectory in the GO4SYS.
Definition TGo4Log.cxx:189
static const char * GO4SYS()
Return GO4SYS environment variable or Go4 top directory during compile (if GO4SYS) not set.
Definition TGo4Log.cxx:156