GSI Object Oriented Online Offline (Go4)  GO4-6.1.4
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
QWebCanvas.cpp
Go to the documentation of this file.
1 // $Id: QWebCanvas.cpp 3341 2021-10-18 13:18:09Z 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 include 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  fCanvas->SetCanvasImp(web);
124 
126 
127  web->SetCanCreateObjects(kFALSE); // not yet create objects on server side
128 
129  web->SetUpdatedHandler([this]() { ProcessCanvasUpdated(); });
130 
131  web->SetActivePadChangedHandler([this](TPad *pad){ ProcessActivePadChanged(pad); });
132 
133  web->SetPadClickedHandler([this](TPad *pad, int x, int y) { ProcessPadClicked(pad, x, y); });
134 
135  web->SetPadDblClickedHandler([this](TPad *pad, int x, int y) { ProcessPadDblClicked(pad, x, y); });
136 
137  ROOT::Experimental::RWebDisplayArgs args("qt5");
138  args.SetDriverData(this); // it is parent widget for created QWebEngineView element
139  args.SetUrlOpt("noopenui");
140 
141  web->ShowWebWindow(args);
142 
143  fView = findChild<QWebEngineView*>("RootWebView");
144  if (!fView) {
145  printf("FAIL TO FIND QWebEngineView - ROOT Qt5Web plugin does not work properly !!!!!\n");
146  exit(11);
147  }
148 
149  gridLayout->addWidget(fView);
150 
151  QObject::connect(fView, SIGNAL(drop(QDropEvent*)), this, SLOT(dropView(QDropEvent*)));
152 
153  fCanvas->SetCanvasSize(fView->width(), fView->height());
154 }
155 
157 {
158  if (fCanvas) {
159  SetPrivateCanvasFields(false);
160 
161  gROOT->GetListOfCanvases()->Remove(fCanvas);
162 
163  fCanvas->Close();
164  delete fCanvas;
165  fCanvas = nullptr;
166  }
167 }
168 
170 {
171  Long_t offset = TCanvas::Class()->GetDataMemberOffset("fCanvasID");
172  if (offset > 0) {
173  Int_t *id = (Int_t *)((char*) fCanvas + offset);
174  if (*id == fCanvas->GetCanvasID()) *id = on_init ? 111222333 : -1;
175  } else {
176  printf("ERROR: Cannot modify TCanvas::fCanvasID data member\n");
177  }
178 
179  offset = TCanvas::Class()->GetDataMemberOffset("fPixmapID");
180  if (offset > 0) {
181  Int_t *id = (Int_t *)((char*) fCanvas + offset);
182  if (*id == fCanvas->GetPixmapID()) *id = on_init ? 332211 : -1;
183  } else {
184  printf("ERROR: Cannot modify TCanvas::fPixmapID data member\n");
185  }
186 
187  offset = TCanvas::Class()->GetDataMemberOffset("fMother");
188  if (offset > 0) {
189  TPad **moth = (TPad **)((char*) fCanvas + offset);
190  if (*moth == fCanvas->GetMother()) *moth = on_init ? fCanvas : nullptr;
191  } else {
192  printf("ERROR: Cannot set TCanvas::fMother data member\n");
193  }
194 
195 }
196 
197 
198 void QWebCanvas::resizeEvent(QResizeEvent *event)
199 {
200  // printf("Resize width: %d %d height: %d %d\n", (int) width(), (int) fView->width(), (int) height(), (int) fView->height());
201 
202  fCanvas->SetCanvasSize(fView->width(), fView->height());
203 }
204 
205 void QWebCanvas::dropEvent(QDropEvent* event)
206 {
207  // TODO: remove, not needed at all
208 
209  TObject* obj(0);
210  QPoint pos = event->pos();
211  TPad* pad = fCanvas->Pick(scaledPosition(pos.x()), scaledPosition(pos.y()), obj);
212 
213  printf("Drop on pad %s\n", pad ? pad->GetName() : "---");
214 
215  emit CanvasDropEvent(event, pad ? pad : fCanvas);
216 }
217 
218 void QWebCanvas::dropView(QDropEvent* event)
219 {
220  TObject* obj(0);
221  QPoint pos = event->pos();
222  TPad* pad = fCanvas->Pick(scaledPosition(pos.x()), scaledPosition(pos.y()), obj);
223 
224  printf("Drop on view %s\n", pad ? pad->GetName() : "---");
225 
226  emit CanvasDropEvent(event, pad ? pad : fCanvas);
227 }
228 
229 void QWebCanvas::activateEditor(TPad *pad, TObject *obj)
230 {
231  TWebCanvas *cimp = dynamic_cast<TWebCanvas*> (fCanvas->GetCanvasImp());
232  if (cimp) {
233  cimp->ShowEditor(kTRUE);
234  cimp->ActivateInEditor(pad, obj);
235  }
236 }
237 
239 {
240  return fCanvas->GetShowEventStatus();
241 }
242 
244 {
245  return fCanvas->GetShowEditor();
246 }
247 
249 {
250  if (fCanvas->GetShowEventStatus() != flag)
251  fCanvas->ToggleEventStatus();
252 }
253 
255 {
256  TCanvasImp *cimp = fCanvas->GetCanvasImp();
257  if (cimp) cimp->ShowEditor(flag);
258 }
259 
261 {
262  TCanvasImp *cimp = fCanvas->GetCanvasImp();
263  if (cimp) cimp->ShowStatusBar(kTRUE);
264 }
265 
267 {
268  fCanvas->Update();
269 }
270 
272 {
273  fCanvas->Modified();
274 }
275 
277 {
278  fRepaintTimer->setSingleShot(true);
279  fRepaintTimer->start(100);
280 }
void SetPadDblClickedHandler(PadClickedSignal_t func)
void SetActivePadChangedHandler(PadSignal_t func)
QTimer * fRepaintTimer
Definition: QWebCanvas.h:94
void activateStatusLine()
Definition: QWebCanvas.cpp:260
bool isStatusBarVisible()
Definition: QWebCanvas.cpp:238
void ProcessPadDblClicked(TPad *pad, int x, int y)
Definition: QWebCanvas.h:88
virtual void dropEvent(QDropEvent *event)
Definition: QWebCanvas.cpp:205
void Update()
Definition: QWebCanvas.cpp:276
QWebEngineView * fView
qt webwidget to show
Definition: QWebCanvas.h:90
void activateEditor(TPad *pad=0, TObject *obj=0)
Definition: QWebCanvas.cpp:229
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:156
TCanvas * fCanvas
Definition: QWebCanvas.h:92
bool isEditorVisible()
Definition: QWebCanvas.cpp:243
void dropView(QDropEvent *event)
Definition: QWebCanvas.cpp:218
void setEditorVisible(bool flag=true)
Definition: QWebCanvas.cpp:254
virtual void resizeEvent(QResizeEvent *event)
Definition: QWebCanvas.cpp:198
double fQtScalingfactor
Definition: QWebCanvas.h:96
static TString subGO4SYS(const char *subdir)
Definition: TGo4Log.cxx:192
void SetCanCreateObjects(Bool_t on=kTRUE)
void SetPadClickedHandler(PadClickedSignal_t func)
void Modified()
Definition: QWebCanvas.cpp:271
void CanvasDropEvent(QDropEvent *, TPad *)
double scaledPosition(int p)
Definition: QWebCanvas.h:75
void processRepaintTimer()
Definition: QWebCanvas.cpp:266
void setStatusBarVisible(bool flag=true)
Definition: QWebCanvas.cpp:248
void SetPrivateCanvasFields(bool on_init)
Definition: QWebCanvas.cpp:169
void ProcessPadClicked(TPad *pad, int x, int y)
Definition: QWebCanvas.h:86