GSI Object Oriented Online Offline (Go4)  GO4-6.2.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
QWebCanvas.cpp
Go to the documentation of this file.
1 // $Id: QWebCanvas.cpp 3520 2022-01-26 15:44:30Z linev $
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 
22 #include "TGo4Log.h"
23 
24 #include <QGridLayout>
25 #include <QApplication>
26 #include <QTimer>
27 #include <QDropEvent>
28 
29 #include <cstdlib>
30 #include <cstdio>
31 
32 #if ROOT_VERSION_CODE >= ROOT_VERSION(6,23,0)
33 // starting from version 6.23 TWebCanvas includes all required functionality
34 #include "TWebCanvas.h"
35 #else
36 // before TWebCanvas was not complete and need to be extended with TWebCanvasFull
37 #include "TWebCanvasFull.h"
38 #endif
39 
40 
41 QWebCanvas::QWebCanvas(QWidget *parent) : QWidget(parent)
42 {
43  fQtScalingfactor = 1.0;
44 
45 #if QT_VERSION > QT_VERSION_CHECK(5,6,0)
46  // JAM the following is pure empiric. hopefully default denominator won't change in future qt?
47  fQtScalingfactor = (double) metric(QPaintDevice::PdmDevicePixelRatioScaled)/65536.;
48 #endif
49 
50  setObjectName( "QWebCanvas");
51 
52  setSizeIncrement( QSize( 100, 100 ) );
53 
54  setUpdatesEnabled( true );
55  setMouseTracking(true);
56 
57  setFocusPolicy( Qt::TabFocus );
58  setCursor( Qt::CrossCursor );
59 
60  setAcceptDrops(true);
61 
62  fRepaintTimer = new QTimer;
63  fRepaintTimer->setSingleShot(true);
64  connect(fRepaintTimer, SIGNAL(timeout()), this, SLOT(processRepaintTimer()));
65 
66  // disable option that at least background is redrawn immediately
67  // and canvas content after 100 ms timeout
68  //setAttribute(Qt::WA_NoSystemBackground);
69  //setAttribute(Qt::WA_PaintOnScreen);
70  //setAttribute(Qt::WA_PaintUnclipped);
71 
72  QGridLayout *gridLayout = new QGridLayout(this);
73  gridLayout->setSpacing(10);
74  gridLayout->setContentsMargins(1,1,1,1);
75 
76  //fView = new RootWebView(this);
77  //QObject::connect(fView, SIGNAL(drop(QDropEvent*)), this, SLOT(dropView(QDropEvent*)));
78  //gridLayout->addWidget(fView);
79 
80  //static TQt5Timer *qt5timer = nullptr;
81 
82  //if (!qt5timer) {
83  // qt5timer = new TQt5Timer(10, kTRUE);
84  // qt5timer->TurnOn();
85  //}
86 
87  static int wincnt = 1;
88 
89  fCanvas = new TCanvas(kFALSE);
90  fCanvas->SetName(Form("Canvas%d", wincnt++));
91  fCanvas->SetTitle("title");
92  fCanvas->ResetBit(TCanvas::kShowEditor);
93  fCanvas->SetCanvas(fCanvas);
94  fCanvas->SetBatch(kTRUE); // mark canvas as batch
95 
96  gPad = fCanvas;
97 
98 #if ROOT_VERSION_CODE >= ROOT_VERSION(6,23,0)
99  TWebCanvas *web = new TWebCanvas(fCanvas, "title", 0, 0, 800, 600, kFALSE);
100 #else
101  TWebCanvasFull *web = new TWebCanvasFull(fCanvas, "title", 0, 0, 800, 600);
102 #endif
103 
104 
105 #if ROOT_VERSION_CODE >= ROOT_VERSION(6,19,0)
106 
107  // this is Go4-special part to provide support of custom classes
108  static std::string go4script;
109 
110  if (go4script.empty()) {
111  TString fname = TGo4Log::subGO4SYS("html/go4canvas.js");
112  go4script = THttpServer::ReadFileContent(fname.Data());
113  }
114 
115  web->SetCustomScripts(go4script);
116  web->AddCustomClass("TGo4Marker");
117  web->AddCustomClass("TGo4Condition", true);
118  web->AddCustomClass("TGo4CondArray");
119  // this is end of Go4-special part
120 
121 #endif
122 
123 #if ROOT_VERSION_CODE >= ROOT_VERSION(6,26,0)
124  web->SetAsyncMode(kTRUE); // avoid blocking mode
125 #endif
126 
127  fCanvas->SetCanvasImp(web);
128 
130 
131  web->SetCanCreateObjects(kFALSE); // not yet create objects on server side
132 
133  web->SetUpdatedHandler([this]() { ProcessCanvasUpdated(); });
134 
135  web->SetActivePadChangedHandler([this](TPad *pad){ ProcessActivePadChanged(pad); });
136 
137  web->SetPadClickedHandler([this](TPad *pad, int x, int y) { ProcessPadClicked(pad, x, y); });
138 
139  web->SetPadDblClickedHandler([this](TPad *pad, int x, int y) { ProcessPadDblClicked(pad, x, y); });
140 
141 #if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
142  ROOT::Experimental::RWebDisplayArgs args("qt6");
143 #else
144  ROOT::Experimental::RWebDisplayArgs args("qt5");
145 #endif
146  args.SetDriverData(this); // it is parent widget for created QWebEngineView element
147  args.SetUrlOpt("noopenui");
148 
149  web->ShowWebWindow(args);
150 
151  fView = findChild<QWebEngineView*>("RootWebView");
152  if (!fView) {
153  printf("FAIL TO FIND QWebEngineView - ROOT Qt5Web plugin does not work properly !!!!!\n");
154  exit(11);
155  }
156 
157  gridLayout->addWidget(fView);
158 
159  QObject::connect(fView, SIGNAL(drop(QDropEvent*)), this, SLOT(dropView(QDropEvent*)));
160 
161  fCanvas->SetCanvasSize(fView->width(), fView->height());
162 }
163 
165 {
166  if (fCanvas) {
167  SetPrivateCanvasFields(false);
168 
169  gROOT->GetListOfCanvases()->Remove(fCanvas);
170 
171  fCanvas->Close();
172  delete fCanvas;
173  fCanvas = nullptr;
174  }
175 }
176 
178 {
179  Long_t offset = TCanvas::Class()->GetDataMemberOffset("fCanvasID");
180  if (offset > 0) {
181  Int_t *id = (Int_t *)((char*) fCanvas + offset);
182  if (*id == fCanvas->GetCanvasID()) *id = on_init ? 111222333 : -1;
183  } else {
184  printf("ERROR: Cannot modify TCanvas::fCanvasID data member\n");
185  }
186 
187  offset = TCanvas::Class()->GetDataMemberOffset("fPixmapID");
188  if (offset > 0) {
189  Int_t *id = (Int_t *)((char*) fCanvas + offset);
190  if (*id == fCanvas->GetPixmapID()) *id = on_init ? 332211 : -1;
191  } else {
192  printf("ERROR: Cannot modify TCanvas::fPixmapID data member\n");
193  }
194 
195  offset = TCanvas::Class()->GetDataMemberOffset("fMother");
196  if (offset > 0) {
197  TPad **moth = (TPad **)((char*) fCanvas + offset);
198  if (*moth == fCanvas->GetMother()) *moth = on_init ? fCanvas : nullptr;
199  } else {
200  printf("ERROR: Cannot set TCanvas::fMother data member\n");
201  }
202 
203 }
204 
205 
206 void QWebCanvas::resizeEvent(QResizeEvent *event)
207 {
208  // printf("Resize width: %d %d height: %d %d\n", (int) width(), (int) fView->width(), (int) height(), (int) fView->height());
209 
210  fCanvas->SetCanvasSize(fView->width(), fView->height());
211 }
212 
213 void QWebCanvas::dropEvent(QDropEvent* event)
214 {
215  // TODO: remove, not needed at all
216 
217  TObject* obj(0);
218 #if QT_VERSION < QT_VERSION_CHECK(6,0,0)
219  QPoint pos = event->pos();
220 #else
221  QPoint pos = event->position().toPoint();
222 #endif
223  TPad* pad = fCanvas->Pick(scaledPosition(pos.x()), scaledPosition(pos.y()), obj);
224 
225  printf("Drop on pad %s\n", pad ? pad->GetName() : "---");
226 
227  emit CanvasDropEvent(event, pad ? pad : fCanvas);
228 }
229 
230 void QWebCanvas::dropView(QDropEvent* event)
231 {
232  TObject* obj(0);
233 #if QT_VERSION < QT_VERSION_CHECK(6,0,0)
234  QPoint pos = event->pos();
235 #else
236  QPoint pos = event->position().toPoint();
237 #endif
238  TPad* pad = fCanvas->Pick(scaledPosition(pos.x()), scaledPosition(pos.y()), obj);
239 
240  printf("Drop on view %s\n", pad ? pad->GetName() : "---");
241 
242  emit CanvasDropEvent(event, pad ? pad : fCanvas);
243 }
244 
245 void QWebCanvas::activateEditor(TPad *pad, TObject *obj)
246 {
247  TWebCanvas *cimp = dynamic_cast<TWebCanvas*> (fCanvas->GetCanvasImp());
248  if (cimp) {
249  cimp->ShowEditor(kTRUE);
250  cimp->ActivateInEditor(pad, obj);
251  }
252 }
253 
255 {
256  return fCanvas->GetShowEventStatus();
257 }
258 
260 {
261  return fCanvas->GetShowEditor();
262 }
263 
265 {
266  if (fCanvas->GetShowEventStatus() != flag)
267  fCanvas->ToggleEventStatus();
268 }
269 
271 {
272  TCanvasImp *cimp = fCanvas->GetCanvasImp();
273  if (cimp) cimp->ShowEditor(flag);
274 }
275 
277 {
278  TCanvasImp *cimp = fCanvas->GetCanvasImp();
279  if (cimp) cimp->ShowStatusBar(kTRUE);
280 }
281 
283 {
284  fCanvas->Update();
285 }
286 
288 {
289  fCanvas->Modified();
290 }
291 
293 {
294  fRepaintTimer->setSingleShot(true);
295  fRepaintTimer->start(100);
296 }
void SetPadDblClickedHandler(PadClickedSignal_t func)
void SetActivePadChangedHandler(PadSignal_t func)
QTimer * fRepaintTimer
Definition: QWebCanvas.h:94
void activateStatusLine()
Definition: QWebCanvas.cpp:276
bool isStatusBarVisible()
Definition: QWebCanvas.cpp:254
void ProcessPadDblClicked(TPad *pad, int x, int y)
Definition: QWebCanvas.h:88
virtual void dropEvent(QDropEvent *event)
Definition: QWebCanvas.cpp:213
void Update()
Definition: QWebCanvas.cpp:292
QWebEngineView * fView
qt webwidget to show
Definition: QWebCanvas.h:90
void activateEditor(TPad *pad=0, TObject *obj=0)
Definition: QWebCanvas.cpp:245
QWebCanvas(QWidget *parent=0)
Definition: QWebCanvas.cpp:41
void ProcessCanvasUpdated()
Definition: QWebCanvas.h:82
void ProcessActivePadChanged(TPad *pad)
Definition: QWebCanvas.h:84
virtual ~QWebCanvas()
Definition: QWebCanvas.cpp:164
TCanvas * fCanvas
Definition: QWebCanvas.h:92
bool isEditorVisible()
Definition: QWebCanvas.cpp:259
void dropView(QDropEvent *event)
Definition: QWebCanvas.cpp:230
void setEditorVisible(bool flag=true)
Definition: QWebCanvas.cpp:270
virtual void resizeEvent(QResizeEvent *event)
Definition: QWebCanvas.cpp:206
double fQtScalingfactor
Definition: QWebCanvas.h:96
static TString subGO4SYS(const char *subdir)
Definition: TGo4Log.cxx:190
void SetCanCreateObjects(Bool_t on=kTRUE)
void SetPadClickedHandler(PadClickedSignal_t func)
void Modified()
Definition: QWebCanvas.cpp:287
void CanvasDropEvent(QDropEvent *, TPad *)
double scaledPosition(int p)
Definition: QWebCanvas.h:75
void processRepaintTimer()
Definition: QWebCanvas.cpp:282
void setStatusBarVisible(bool flag=true)
Definition: QWebCanvas.cpp:264
void SetPrivateCanvasFields(bool on_init)
Definition: QWebCanvas.cpp:177
void ProcessPadClicked(TPad *pad, int x, int y)
Definition: QWebCanvas.h:86