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