GSI Object Oriented Online Offline (Go4) GO4-6.4.0
Loading...
Searching...
No Matches
QRootCanvas.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/****************************************************************************
15** Copyright ( C ) 2000 denis Bertini. All rights reserved.
16*****************************************************************************/
17
18#include "QRootCanvas.h"
19
20#include <iostream>
21
22#include <QtCore/QSignalMapper>
23#include <QtCore/QTimer>
24
25#include <QDragEnterEvent>
26#include <QDropEvent>
27#include <QMouseEvent>
28#include <QCloseEvent>
29#include <QInputDialog>
30#include <QColorDialog>
31#include <QMenu>
32#include <QAction>
33#include <QMimeData>
34#include <QVBoxLayout>
35#include <QStatusBar>
36
37#include "TCanvas.h"
38#include "TROOT.h"
39#include "TObjString.h"
40#include "TObjArray.h"
41#include "TH1.h"
42#include "TClass.h"
43#include "TDataType.h"
44#include "TDataMember.h"
45#include "TMethod.h"
46#include "TMethodCall.h"
47#include "TMethodArg.h"
48#include "TColor.h"
49#include "TLatex.h"
50
51#ifndef __NOGO4GED__
52#include "TGedEditor.h"
53#include "TVirtualPadEditor.h"
54#endif
55
56#ifdef __GO4X11__
57#include "TGo4LockGuard.h"
58#else
59#define TGo4LockGuard int
60#endif
61
62#include "QRootDialog.h"
63#include "QRootWindow.h"
64#include "QRootApplication.h"
65
66QRootCanvas::QRootCanvas(QWidget *parent) :
67 QWidget(parent),
68 fMaskDoubleClick(false),
69 fxShowEventStatus(false),
71{
72 setObjectName( "QRootCanvas");
73
74 setSizeIncrement( QSize( 100, 100 ) );
75
76 TGo4LockGuard threadlock;
77 (void) threadlock; // suppress compiler warnings
78 // set defaults
79 setUpdatesEnabled( true );
80 setMouseTracking(true);
81
82 setFocusPolicy( Qt::TabFocus );
83 setCursor( Qt::CrossCursor );
84
85 // disable option that at least background is redrawn immediately
86 // and canvas content after 100 ms timeout
87 //setAttribute(Qt::WA_NoSystemBackground);
88 setAttribute(Qt::WA_PaintOnScreen);
89 setAttribute(Qt::WA_PaintUnclipped);
90
91 // add the Qt::WinId to TGX11 interface
92 fQtWindowId = winId();
93 fRootWindowId = gVirtualX->AddWindow((ULong_t)fQtWindowId, 100, 30);
94
95 fCanvas = new TCanvas("Canvas", width(), height(), fRootWindowId);
96
97 // JAM the following is pure empiric. hopefully default denominator won't change in future qt?
98 fQtScalingfactor = (double) metric(QPaintDevice::PdmDevicePixelRatioScaled)/65536.;
99 // create the context menu
100 fMousePosX = 0;
101 fMousePosY = 0;
102 fMenuMethods = nullptr;
103 fMenuObj = nullptr;
104
105 setAcceptDrops(true);
106
107 fRepaintMode = 0;
108 fRepaintTimer = new QTimer;
109 fRepaintTimer->setSingleShot(true);
110 QObject::connect(fRepaintTimer, &QTimer::timeout, this, &QRootCanvas::processRepaintTimer);
111
112 fEditorFrame = nullptr;
113 fxPeditor = nullptr;
114 fxRooteditor = nullptr;
115 fDummyHisto = nullptr;
116
117 fStatusBar = nullptr;
118}
119
121{
122 // cannot call here, must be done before until X11 frame is exists
123 // cleanupEditor();
124
125 if (fDummyHisto) {
126 delete fDummyHisto;
127 fDummyHisto = nullptr;
128 }
129
130#ifndef __NOGO4GED__
131 if (gTQSender == getCanvas())
132 gTQSender = nullptr;
133
134 // prevent problems with root's subeditor cache
135 if (fxPeditor) {
136 fxPeditor->DeleteEditors();
137 delete fxPeditor;
138 fxPeditor = nullptr;
139 }
140#endif
141
142 if(fCanvas) {
143 delete fCanvas;
144 fCanvas = nullptr;
145 }
146
147 if (fMenuMethods) {
148 delete fMenuMethods;
149 fMenuMethods = nullptr;
150 }
151
152 delete fRepaintTimer;
153}
154
155QPoint QRootCanvas::scaledMousePoint(QMouseEvent *e)
156{
157#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
158 int scaledX = scaledPosition(e->x());
159 int scaledY = scaledPosition(e->y());
160#else
161 int scaledX = scaledPosition(e->position().x());
162 int scaledY = scaledPosition(e->position().y());
163#endif
164 return QPoint(scaledX, scaledY);
165}
166
167void QRootCanvas::mouseMoveEvent(QMouseEvent *e)
168{
169 TGo4LockGuard threadlock;
170 (void) threadlock; // suppress compiler warnings
171 // JAM use event timestamp for reduction of events (qt5 bug):
172 static ulong lastprocesstime = 0;
173 static ulong delta = 100; // maybe ms units?
174 ulong timestamp = e->timestamp();
175 if(timestamp-delta < lastprocesstime) {
176 // just eat too old events
177 e->accept();
178 // std::cout <<"----- EATING timestamp:"<<timestamp<< std::endl;
179 return;
180 }
181
182 if (fCanvas) {
183 QPoint pnt = scaledMousePoint(e);
184
185 if (e->buttons() & Qt::LeftButton)
186 fCanvas->HandleInput(kButton1Motion, pnt.x(), pnt.y());
187 else
188 fCanvas->HandleInput(kMouseMotion, pnt.x(), pnt.y());
189 }
190
192 TObject *selected = fCanvas->GetSelected();
193 Int_t px = fCanvas->GetEventX();
194 Int_t py = fCanvas->GetEventY();
195 QString buffer = "";
196 if (selected) {
197 buffer = selected->GetName();
198 buffer += " ";
199 buffer += selected->GetObjectInfo(px, py);
200 } else {
201 buffer = "No selected object x = ";
202 buffer += QString::number(px);
203 buffer += " y = ";
204 buffer += QString::number(py);
205 }
206
207 emit CanvasStatusEvent(buffer.toLatin1().constData());
208
209 if (fStatusBar) fStatusBar->showMessage(buffer.toLatin1().constData());
210 }
211 e->accept();
212 lastprocesstime = timestamp;
213}
214
215void QRootCanvas::wheelEvent( QWheelEvent* e)
216{
217 TGo4LockGuard threadlock;
218 (void) threadlock; // suppress compiler warnings
219
220 if (!fCanvas) return;
221 e->accept();
222
223#if QT_VERSION < QT_VERSION_CHECK(5,15,0)
224 bool positive = (e->delta() > 0);
225 int ex = e->x(), ey = e->y();
226#else
227 QPoint delta = e->pixelDelta();
228 if (delta.isNull()) delta = e->angleDelta() / 8;
229 bool positive = delta.x() > 0 || delta.y() > 0;
230 int ex = e->position().x(), ey = e->position().y();
231#endif
232
233 fCanvas->HandleInput(positive ? kWheelUp : kWheelDown, scaledPosition(ex), scaledPosition(ey));
234}
235
236
237void QRootCanvas::mousePressEvent( QMouseEvent *e )
238{
239 TGo4LockGuard threadlock;
240 (void) threadlock; // suppress compiler warnings
241
242 TObjLink* pickobj = nullptr;
243 // JAM2016-9 test
244// std::cout <<"QRootCanvas::mousePressEvent at ("<<e->x()<<", "<< e->y()<<")"<< std::endl;
245
246 QPoint scaled = scaledMousePoint(e);
247#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
248 QPoint mouse_pnt = e->globalPos();
249#else
250 QPoint mouse_pnt = e->globalPosition().toPoint();
251#endif
252
253 // std::cout <<" scaledX,scaledY: ("<<scaledX<<", "<<scaledY <<") "<< std::endl;
254// std::cout <<"global from event: ("<<e->globalX()<<", "<< e->globalY()<< std::endl;
255// QPoint globalp=QWidget::mapToGlobal(e->pos());
256// std::cout <<"global from map: ("<<globalp.x()<<", "<<globalp.y() <<") "<< std::endl;
257// QPoint parentp=QWidget::mapToParent(e->pos());
258// std::cout <<"parent: ("<<parentp.x()<<", "<<parentp.y()<<") " << std::endl;
259// QPoint backfromglobalp=QWidget::mapFromGlobal(globalp);
260// std::cout <<"backglobal: ("<<backfromglobalp.x()<<", "<<backfromglobalp.y()<<") " << std::endl;
261// Int_t destx = 0, desty = 0;
262// Window_t child;
263// Window_t rootwindow=gVirtualX->GetDefaultRootWindow();
264// gVirtualX->TranslateCoordinates(rootwindow, fQtWindowId, globalp.x(), globalp.y(), destx, desty, child);
265// std::cout <<"TGX11 global translated: ("<<destx<<", "<<desty<<") " << std::endl;
266// std::cout <<"TGX11 winids - default root:"<<rootwindow<<", Qt:"<<fQtWindowId<<", child:" <<child<< std::endl;
267
268
269 /* int themetric= metric(QPaintDevice::PdmDevicePixelRatio);
270 int scaledmetric= metric(QPaintDevice::PdmDevicePixelRatioScaled);
271 std::cout <<"metric="<<themetric<<", scaled="<<scaledmetric << std::endl;
272 int scaledX=e->x() * scaledmetric/65536; // empiric
273 int scaledY=e->y() * scaledmetric/65536; // empiric
274 std::cout <<"scaledX,scaledY: ("<<scaledX<<", "<<scaledY <<") "<< std::endl;
275 */
276
277
278 TPad *pad = fCanvas->Pick(scaled.x(), scaled.y(), pickobj);
279 TObject *selected = fCanvas->GetSelected();
280
281 switch(e->button()) {
282 case Qt::LeftButton :
283 fCanvas->HandleInput(kButton1Down, scaled.x(), scaled.y());
284 emit PadClicked(pad, scaled.x(), scaled.y());
285 break;
286 case Qt::RightButton : {
287 TString selectedOpt("");
288 if (pad) {
289 if (!pickobj) {
290 fCanvas->SetSelected(pad);
291 selected = pad;
292 } else if(!selected) {
293 selected = pickobj->GetObject();
294 selectedOpt = pickobj->GetOption();
295 }
296 pad->cd();
297 }
298 fCanvas->SetSelectedPad(pad);
299 gROOT->SetSelectedPrimitive(selected);
300 fMousePosX = gPad->AbsPixeltoX(gPad->GetEventX());
301 fMousePosY = gPad->AbsPixeltoY(gPad->GetEventY());
302
303 QMenu menu;
304 QSignalMapper map;
305 #if QT_VERSION < QT_VERSION_CHECK(5,15,0)
306 auto signal = QOverload<int>::of(&QSignalMapper::mapped);
307 #else
308 auto signal = &QSignalMapper::mappedInt;
309 #endif
310
311 QObject::connect(&map, signal, this, &QRootCanvas::executeMenu);
312 fMenuObj = selected;
313 fMenuMethods = new TList;
314 TClass *cl = fMenuObj->IsA();
315 int curId = -1;
316
317 QString buffer = TString::Format("%s::%s", cl->GetName(), fMenuObj->GetName()).Data();
318 addMenuAction(&menu, &map, buffer, curId++);
319
320 cl->GetMenuItems(fMenuMethods);
321 menu.addSeparator();
322
323 if(!cl->InheritsFrom(TLatex::Class())) {
324 addMenuAction(&menu, &map, "Insert Latex", 100);
325 menu.addSeparator();
326 }
327
328 if(cl->InheritsFrom(TH1::Class())) {
329 addMenuAction(&menu, &map, "Qt Hist Line Color ", 101);
330 addMenuAction(&menu, &map, "Qt Hist Fill Color ", 102);
331 menu.addSeparator();
332 }
333
334 TIter iter(fMenuMethods);
335 while (auto method = dynamic_cast<TMethod*>(iter())) {
336 buffer = method->GetName();
337 addMenuAction(&menu, &map, buffer, curId++);
338 }
339
340 if (menu.exec(mouse_pnt) == nullptr) {
341 fMenuObj = nullptr;
342 delete fMenuMethods;
343 fMenuMethods = nullptr;
344 }
345
346 break;
347 }
348 case Qt::MiddleButton :
349 fCanvas->HandleInput(kButton2Down, scaled.x(), scaled.y());
350 emit SelectedPadChanged(pad); // that inform the Qt-world that tha pad is changed
351 // and give the pointer to the new pad as argument
352 // of the signal (M. Al-Turany)
353 break;
354 case Qt::NoButton :
355 break;
356 default:
357 break;
358 }
359 e->accept();
360}
361
362void QRootCanvas::mouseReleaseEvent( QMouseEvent *e )
363{
364 QPoint scaled = scaledMousePoint(e);
365
366 TGo4LockGuard threadlock;
367 (void) threadlock; // suppress compiler warnings
368
369 switch(e->button()) {
370 case Qt::LeftButton :
371 fCanvas->HandleInput(kButton1Up, scaled.x(), scaled.y());
372 break;
373 case Qt::RightButton :
374 fCanvas->HandleInput(kButton3Up, scaled.x(), scaled.y());
375 break;
376 case Qt::MiddleButton :
377 fCanvas->HandleInput(kButton2Up, scaled.x(), scaled.y());
378 break;
379 case Qt::NoButton :
380 break;
381 default:
382 break;
383 }
384 e->accept();
385}
386
388{
389 QPoint scaled = scaledMousePoint(e);
390
391 TGo4LockGuard threadlock;
392 (void) threadlock; // suppress compiler warnings
393
394 switch(e->button()) {
395 case Qt::LeftButton : {
396 if (!fMaskDoubleClick)
397 fCanvas->HandleInput(kButton1Double, scaled.x(), scaled.y());
398 TObjLink* pickobj = nullptr;
399 TPad *pad = fCanvas->Pick(scaled.x(), scaled.y(), pickobj);
400 emit PadDoubleClicked(pad, scaled.x(), scaled.y());
401 // prevent crash on following release event
402 // if new canvas will be created in between
403 // fCanvas->SetSelected(0);
404 break;
405 }
406 case Qt::RightButton :
407 fCanvas->HandleInput(kButton3Double, scaled.x(), scaled.y());
408 break;
409 case Qt::MiddleButton :
410 fCanvas->HandleInput(kButton2Double, scaled.x(), scaled.y());
411 break;
412 case Qt::NoButton :
413 break;
414 default:
415 break;
416 }
417 e->accept();
418}
419
421{
422 fRepaintMode |= mode;
423// if (fRepaintMode > 0) setUpdatesEnabled( false ); // JAM avoid flicker on Qt5 ?
424 fRepaintTimer->setSingleShot(true);
425 fRepaintTimer->start(100);
426}
427
428void QRootCanvas::resizeEvent( QResizeEvent *)
429{
431}
432
433void QRootCanvas::paintEvent( QPaintEvent *)
434{
435 // this is workaround a problem, that after drawing canvas in
436 // viewpanel there is always 1 event after that
437 // therefore fRepaintMode set to -1 to ignore such first event
438 // In future behavior may change
439
440 if (fRepaintMode < 0)
441 fRepaintMode = 0;
442 else
444}
445
447{
448 if (fRepaintMode == 0) return;
449 TGo4LockGuard threadlock;
450 (void) threadlock; // suppress compiler warnings
451
452 WId newid = winId();
453 if(newid != fQtWindowId) {
454 //printf("processRepaintTimer - sees changed window id %d \n",newid);
455 // Qt has changed id for this widget (e.g. at QWorkspace::addWindow())
456 // need to adjust the ROOT X access:
457 delete fCanvas; // should also remove old x windows!
458 fRootWindowId = gVirtualX->AddWindow((ULong_t)newid, width(), height());
459 fCanvas = new TCanvas(objectName().toLatin1().constData(), width(), height(), fRootWindowId);
460 fQtWindowId = newid;
461 }
462
463 if (fRepaintMode & act_Resize) fCanvas->Resize();
464 else fCanvas->Modified(kTRUE);
465
466 fCanvas->Update();
467
468 fRepaintMode = 0;
469 emit CanvasUpdated();
470 //setUpdatesEnabled( true ); // JAM avoid flicker on Qt5 ?
471}
472
473void QRootCanvas::leaveEvent( QEvent *e )
474{
475 QWidget::leaveEvent(e);
476
477 TGo4LockGuard threadlock;
478 (void) threadlock; // suppress compiler warnings
479
480 if (fCanvas)
481 fCanvas->HandleInput(kMouseLeave, 0, 0);
482
483 emit CanvasLeaveEvent();
484}
485
490
492{
493 return fxShowEventStatus;
494}
495
497
498void QRootCanvas::dragEnterEvent( QDragEnterEvent *e )
499{
500 if (e->mimeData()->hasText())
501 e->acceptProposedAction();
502}
503
504void QRootCanvas::dropEvent( QDropEvent *event )
505{
506 TObject *obj = nullptr;
507
508#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
509 QPoint pos = event->pos();
510#else
511 QPoint pos = event->position().toPoint();
512#endif
513
514 TPad *pad = Pick(scaledPosition(pos.x()), scaledPosition(pos.y()), obj);
515
516 if (pad)
517 emit CanvasDropEvent(event, pad);
518}
519
521
522void QRootCanvas::cd(Int_t subpadnumber)
523{
524 fCanvas->cd(subpadnumber);
525}
526
527void QRootCanvas::Browse(TBrowser *b)
528{
529 fCanvas->Browse(b);
530}
531
532void QRootCanvas::Clear(Option_t *option)
533{
534 fCanvas->Clear(option);
535}
536
537void QRootCanvas::Close(Option_t *option)
538{
539 fCanvas->Close(option);
540}
541
542void QRootCanvas::Draw(Option_t *option)
543{
544 fCanvas->Draw(option);
545}
546
547TObject *QRootCanvas::DrawClone(Option_t *option)
548{
549 return fCanvas->DrawClone(option);
550}
551
553{
554 return fCanvas->DrawClonePad();
555}
556
558{
559 fCanvas->EditorBar();
560}
561
562void QRootCanvas::EnterLeave(TPad *prevSelPad, TObject *prevSelObj)
563{
564 fCanvas->EnterLeave(prevSelPad, prevSelObj);
565}
566
568{
569 fCanvas->FeedbackMode(set);
570}
571
573{
574 fCanvas->Flush();
575}
576
578{
579 fCanvas->UseCurrentStyle();
580}
581
583{
584 fCanvas->ForceUpdate();
585}
586
588{
589 return fCanvas->GetDISPLAY();
590}
591
593{
594 return fCanvas->GetContextMenu();
595}
596
598{
599 return fCanvas->GetDoubleBuffer();
600}
601
603{
604 return fCanvas->GetEvent();
605}
606
608{
609 return fCanvas->GetEventX();
610}
611
613{
614 return fCanvas->GetEventY();
615}
616
618{
619 return fCanvas->GetHighLightColor();
620}
621
623{
624 return fCanvas->GetPadSave();
625}
626
628{
629 return fCanvas->GetSelected();
630}
631
633{
634 return fCanvas->GetSelectedOpt();
635}
636
638{
639 return fCanvas->GetSelectedPad();
640}
641
643{
644 return fCanvas->GetShowEventStatus();
645}
646
648{
649 return fCanvas->GetAutoExec();
650}
651
653{
654 return fCanvas->GetXsizeUser();
655}
656
658{
659 return fCanvas->GetYsizeUser();
660}
661
663{
664 return fCanvas->GetXsizeReal();
665}
666
668{
669 return fCanvas->GetYsizeReal();
670}
671
673{
674 return fCanvas->GetCanvasID();
675}
676
678{
679 return fCanvas->GetWindowTopX();
680}
681
683{
684 return fCanvas->GetWindowTopY();
685}
686
688{
689 return fCanvas->GetWindowWidth();
690}
691
693{
694 return fCanvas->GetWindowHeight();
695}
696
698{
699 return fCanvas->GetWw();
700}
701
703{
704 return fCanvas->GetWh();
705}
706
707void QRootCanvas::GetCanvasPar(Int_t &wtopx, Int_t &wtopy, UInt_t &ww, UInt_t &wh)
708{
709 fCanvas->GetCanvasPar(wtopx, wtopy, ww, wh);
710}
711
712void QRootCanvas::HandleInput(EEventType button, Int_t x, Int_t y)
713{
714 fCanvas->HandleInput(button, scaledPosition(x), scaledPosition(y));
715}
716
718{
719 return fCanvas->HasMenuBar();
720}
721
723{
724 fCanvas->Iconify();
725}
726
728{
729 return fCanvas->IsBatch();
730}
731
733{
734 return fCanvas->IsRetained();
735}
736
737void QRootCanvas::ls(Option_t *option)
738{
739 fCanvas->ls(option);
740}
741
742void QRootCanvas::Modified(Bool_t mod)
743{
744 fCanvas->Modified(mod);
745}
746
748{
749 fCanvas->MoveOpaque(set);
750}
751
753{
754 return fCanvas->OpaqueMoving();
755}
756
758{
759 return fCanvas->OpaqueResizing();
760}
761
762void QRootCanvas::Paint(Option_t *option)
763{
764 fCanvas->Paint(option);
765}
766
767TPad *QRootCanvas::Pick(Int_t px, Int_t py, TObjLink *&pickobj)
768{
769 return fCanvas->Pick(px, py, pickobj);
770}
771
772TPad *QRootCanvas::Pick(Int_t px, Int_t py, TObject *prevSelObj)
773{
774 return fCanvas->Pick(px, py, prevSelObj);
775}
776
777void QRootCanvas::Resize(Option_t *option)
778{
779 fCanvas->Resize(option);
780}
781
783{
784 fCanvas->ResizeOpaque(set);
785}
786
787void QRootCanvas::SaveSource(const char *filename, Option_t *option)
788{
789 fCanvas->SaveSource(filename, option);
790}
791
792void QRootCanvas::SetCursor(ECursor cursor)
793{
794 fCanvas->SetCursor(cursor);
795}
796
798{
799 fCanvas->SetDoubleBuffer(mode);
800}
801
802void QRootCanvas::SetWindowPosition(Int_t x, Int_t y)
803{
804 fCanvas->SetWindowPosition(x, y);
805}
806
807void QRootCanvas::SetWindowSize(UInt_t ww, UInt_t wh)
808{
809 fCanvas->SetWindowSize(ww,wh);
810}
811
812void QRootCanvas::SetCanvasSize(UInt_t ww, UInt_t wh)
813{
814 fCanvas->SetCanvasSize(ww, wh);
815}
816
818{
819 fCanvas->SetHighLightColor(col);
820}
821
822void QRootCanvas::SetSelected(TObject *obj)
823{
824 fCanvas->SetSelected(obj);
825}
826
828{
829 fCanvas->SetSelectedPad(pad);
830}
831
833{
834 fCanvas->Show();
835}
836
837void QRootCanvas::Size(Float_t xsizeuser, Float_t ysizeuser)
838{
839 fCanvas->Size(xsizeuser, ysizeuser);
840}
841
842void QRootCanvas::SetBatch(Bool_t batch)
843{
844 fCanvas->SetBatch(batch);
845}
846
847void QRootCanvas::SetRetained(Bool_t retained)
848{
849 fCanvas->SetRetained(retained);
850}
851
852void QRootCanvas::SetTitle(const char *title)
853{
854 fCanvas->SetTitle(title);
855}
856
858{
859 fCanvas->ToggleEventStatus();
860}
861
863{
864 fCanvas->ToggleAutoExec();
865}
866
868{
869 // do not call update directly, use timer instead
871}
872
873void QRootCanvas::closeEvent(QCloseEvent * e)
874{
875 if (fCanvas) {
876 delete fCanvas;
877 fCanvas = nullptr;
878 }
879
880 e->accept();
881}
882
883void QRootCanvas::methodDialog(TObject *object, TMethod* method)
884{
885 if (!object || !method) return;
886
887 TGo4LockGuard threadlock;
888 (void) threadlock; // suppress compiler warnings
889
890 // Create dialog object with OK and Cancel buttons. This dialog
891 // prompts for the arguments of "method".
892
893 QRootDialog dlg;
894
895 dlg.setWindowTitle(TString::Format("%s:%s", object->GetName(), method->GetName()).Data());
896
897 // iterate through all arguments and create appropriate input-data objects:
898 // inputlines, option menus...
899 TIter next(method->GetListOfMethodArgs());
900
901 while (auto argument = (TMethodArg *) next()) {
902 TString argTitle = TString::Format("(%s) %s", argument->GetTitle(), argument->GetName());
903 TString argDflt = argument->GetDefault() ? argument->GetDefault() : "";
904 if (argDflt.Length() > 0)
905 argTitle += TString::Format(" [default: %s]", argDflt.Data());
906 TString type = argument->GetTypeName();
907 TDataType *datatype = gROOT->GetType(type);
908 TString basictype;
909
910 if (datatype) {
911 basictype = datatype->GetTypeName();
912 } else {
913 if (type.CompareTo("enum") != 0)
914 std::cout << "*** Warning in Dialog(): data type is not basic type, assuming (int)\n";
915 basictype = "int";
916 }
917
918 if (TString(argument->GetTitle()).Index("*") != kNPOS) {
919 basictype += "*";
920 type = "char*";
921 }
922
923 TDataMember *m = argument->GetDataMember();
924 if (m && m->GetterMethod()) {
925
926 m->GetterMethod()->Init(object->IsA(), m->GetterMethod()->GetMethodName(), "");
927
928 // Get the current value and form it as a text:
929
930 TString val;
931
932 if (basictype == "char*") {
933 char *tdefval = nullptr;
934 m->GetterMethod()->Execute(object, "", &tdefval);
935 if (tdefval) val = tdefval;
936 } else
937 if ((basictype == "float") ||
938 (basictype == "double")) {
939 Double_t ddefval = 0.;
940 m->GetterMethod()->Execute(object, "", ddefval);
941 val = TString::Format("%g", ddefval);
942 } else
943 if ((basictype == "char") ||
944 (basictype == "int") ||
945 (basictype == "long") ||
946 (basictype == "short")) {
947 Long_t ldefval = 0;
948 m->GetterMethod()->Execute(object, "", ldefval);
949 val = TString::Format("%ld", ldefval);
950 }
951
952 // Find out whether we have options ...
953
954 TList *opt;
955 if ((opt = m->GetOptions()) != nullptr) {
956 // should stop dialog
957 // workaround JAM: do not stop dialog, use textfield (for time display toggle)
958 dlg.addArg(argTitle.Data(), val.Data(), type.Data());
959 //return;
960 } else {
961 // we haven't got options - textfield ...
962 dlg.addArg(argTitle.Data(), val.Data(), type.Data());
963 }
964 } else { // if m not found ...
965 if ((argDflt.Length() > 1) &&
966 (argDflt[0]=='\"') && (argDflt[argDflt.Length()-1]=='\"')) {
967 // cut "" from the string argument
968 argDflt.Remove(0,1);
969 argDflt.Remove(argDflt.Length()-1,1);
970 }
971
972 dlg.addArg(argTitle.Data(), argDflt.Data(), type.Data());
973 }
974 }
975
976 if (dlg.exec() != QDialog::Accepted) return;
977
978 Bool_t deletion = kFALSE;
979
980 qDebug("DIAL executeMethod: simple version\n");
981 TVirtualPad *psave = gROOT->GetSelectedPad();
982
983 qDebug("DIAL saved pad: %s gPad:%s \n",psave->GetName(),gPad->GetName());
984
985 qDebug("DIAL obj:%s meth:%s \n", object->GetName(), method->GetName());
986
987 TObjArray tobjlist(method->GetListOfMethodArgs()->LastIndex() + 1);
988 for (int n = 0; n <= method->GetListOfMethodArgs()->LastIndex(); n++) {
989 QString s = dlg.getArg(n);
990 qDebug( "** QString values (first ) :%s \n", s.toLatin1().constData() );
991 tobjlist.AddLast(new TObjString(s.toLatin1().constData()));
992 }
993
994 // handle command if existing object
995 if(strcmp(method->GetName(),"Delete") == 0) {
996 // here call explicitly the dtor
997 qDebug(" DIAL obj name deleted :%s \n", object->GetName());
998 emit MenuCommandExecuted(object, "Delete");
999 delete object;
1000 object = nullptr;
1001 deletion = kTRUE;
1002 qDebug(" DIAL deletion done closing ... \n");
1003 } else
1004 if (strcmp(method->GetName(), "SetCanvasSize") == 0) {
1005 int width = dlg.getArg(0).toInt();
1006 int height = dlg.getArg(1).toInt();
1007 qDebug( " do resize with %i %i \n", width, height);
1008 resize(width, height);
1009 emit MenuCommandExecuted(fCanvas, "SetCanvasSize");
1010 } else {
1011 // here call cint call
1012 qDebug("TCint::Execute called !\n");
1013
1014 object->Execute(method, &tobjlist);
1015
1016 if (object->TestBit(TObject::kNotDeleted))
1017 emit MenuCommandExecuted(object, method->GetName());
1018 else {
1019 deletion = true;
1020 object = nullptr;
1021 }
1022 }
1023
1024 if(!deletion ) {
1025 qDebug("DIAL set saved pad: %s herit:%s gPad:%s\n",
1026 psave->GetName(), psave->ClassName(), gPad->GetName());
1027 gROOT->SetSelectedPad(psave);
1028 gROOT->GetSelectedPad()->Modified();
1029 gROOT->GetSelectedPad()->Update();
1030 qDebug("DIAL update done on %s \n", gROOT->GetSelectedPad()->GetName());
1031 } else {
1032 gROOT->SetSelectedPad(gPad);
1033 gROOT->GetSelectedPad()->Update();
1034 }
1035}
1036
1037QAction* QRootCanvas::addMenuAction(QMenu* menu, QSignalMapper* map, const QString& text, int id)
1038{
1040
1041 QAction* act = new QAction(text, menu);
1042
1043 if (!enabled)
1044 if ((text.compare("DrawClone") == 0) || (text.compare("DrawClass") == 0) || (text.compare("Inspect") == 0) ||
1045 (text.compare("SetShowProjectionX") == 0) || (text.compare("SetShowProjectionY") == 0) ||
1046 (text.compare("DrawPanel") == 0) || (text.compare("FitPanel") == 0))
1047 act->setEnabled(false);
1048
1049 QObject::connect(act, &QAction::triggered, [id, map]() {
1050#if QT_VERSION < QT_VERSION_CHECK(5,15,0)
1051 map->mapped(id);
1052#else
1053 map->mappedInt(id);
1054#endif
1055 });
1056
1057 menu->addAction(act);
1058 map->setMapping(act, id);
1059
1060 return act;
1061}
1062
1064{
1065 TGo4LockGuard threadlock;
1066 (void) threadlock; // suppress compiler warnings
1067
1068 QString text;
1069 bool ok = false;
1070 if (id >= 100) {
1071 switch (id){
1072 case 100: {
1073 TLatex *fxLatex = new TLatex();
1074 text = QInputDialog::getText(this, tr( "Qt Root" ),
1075 tr( "Please enter your text" ),
1076 QLineEdit::Normal, QString(), &ok);
1077 //if (ok && !text.isEmpty())
1078 fxLatex->DrawLatex(fMousePosX, fMousePosY, text.toLatin1().constData());
1079 emit MenuCommandExecuted(fxLatex, "DrawLatex");
1080 break;
1081 }
1082 case 101: {
1083 TH1 *h1 = dynamic_cast<TH1 *> (fMenuObj);
1084 if (h1) {
1085 QColor col = QColorDialog::getColor();
1086 if (col.isValid()) {
1087 short int C_new = TColor::GetColor(col.red(), col.green(), col.blue());
1088 h1->SetLineColor(C_new);
1089 emit MenuCommandExecuted(h1, "SetLineColor");
1090 }
1091 }
1092 break;
1093 }
1094 case 102: {
1095 TH1 *h1 = dynamic_cast<TH1 *> (fMenuObj);
1096 if (h1) {
1097 QColor col = QColorDialog::getColor();
1098 if (col.isValid()) {
1099 short int C_new = TColor::GetColor(col.red(), col.green(), col.blue());
1100 h1->SetFillColor(C_new);
1101 emit MenuCommandExecuted(h1,"SetFillColor");
1102 }
1103 }
1104 }
1105 }
1106 gROOT->GetSelectedPad()->Update();
1107 gROOT->GetSelectedPad()->Modified();
1108 fCanvas->Modified();
1109 fCanvas->ForceUpdate();
1110 gROOT->SetFromPopUp( kFALSE );
1111 } else
1112 if (id >= 0) {
1113
1114 // save global to Pad before calling TObject::Execute()
1115
1116 TVirtualPad *psave = gROOT->GetSelectedPad();
1117 TMethod *method = (TMethod *) fMenuMethods->At(id);
1118
1120 fCanvas->HandleInput(kButton3Up, gPad->XtoAbsPixel(fMousePosX), gPad->YtoAbsPixel(fMousePosY));
1121
1122 // change current dir that all new histograms appear here
1123 gROOT->cd();
1124
1125 if (method->GetListOfMethodArgs()->First()) {
1126 if (strstr(method->GetName(), "Delete")) {
1127 // JAM2016: do not allow mouse menu delete in Go4
1128 } else {
1129 methodDialog(fMenuObj, method);
1130 }
1131 }
1132 else
1133 {
1134 gROOT->SetFromPopUp(kTRUE);
1135 fMenuObj->Execute(method->GetName(), "");
1136
1137 if (fMenuObj->TestBit(TObject::kNotDeleted)) {
1138 emit MenuCommandExecuted(fMenuObj, method->GetName());
1139 } else {
1140 fMenuObj = nullptr;
1141 }
1142
1143 }
1144
1145 #ifndef __NOGO4GED__
1146 TGedEditor* ed = dynamic_cast<TGedEditor*>(TVirtualPadEditor::GetPadEditor(kFALSE));
1147 if (fMenuObj && ed) ed->SetModel(psave, fMenuObj, kButton1Down);
1148 #endif
1149
1150 fCanvas->GetPadSave()->Update();
1151 fCanvas->GetPadSave()->Modified();
1152
1153 gROOT->SetSelectedPad(psave);
1154
1155 gROOT->GetSelectedPad()->Update();
1156 gROOT->GetSelectedPad()->Modified();
1157
1158 fCanvas->Modified();
1159 fCanvas->ForceUpdate();
1160 gROOT->SetFromPopUp(kFALSE);
1161 }
1162
1163 fMenuObj = nullptr;
1164 delete fMenuMethods;
1165 fMenuMethods = nullptr;
1166}
1167
1169{
1170 return fEditorFrame ? fEditorFrame->isVisible() : false;
1171}
1172
1173
1175{
1176#ifdef __NOGO4GED__
1177 return false;
1178#else
1180#endif
1181}
1182
1184{
1185 if (!fEditorFrame) return;
1186
1187#ifndef __NOGO4GED__
1188 bool flag = !isEditorVisible();
1189
1190 fEditorFrame->setVisible(flag);
1191 if (flag && !fxPeditor) {
1192 // JAM the following is pure empiric. hopefully default denominator won't change in future qt?
1193 double scalefactor = (double) metric(QPaintDevice::PdmDevicePixelRatioScaled)/65536.;
1194 fEditorFrame->setMinimumWidth( fEditorFrame->minimumWidth()/scalefactor);
1195
1196// JAM 5-2019: this part was moved to buildEditorWindow() because of init problems with Qt 4
1197// std::cout<< "QRootCanvas::toggleEditor() will create Rooteditor" <<std::endl;
1198// fxRooteditor = new QRootWindow(fEditorFrame, "rootwrapperwindow");
1199// QVBoxLayout* gedlayout = new QVBoxLayout(fEditorFrame);
1200// gedlayout->setContentsMargins(0, 0, 0, 0);
1201// gedlayout->addWidget(fxRooteditor);
1203 TGo4LockGuard threadlock;
1204 (void) threadlock; // suppress compiler warnings
1205
1206 fxRooteditor->SetResizeOnPaint(kFALSE); // disable internal resize on paintEvent, we use ResizeGedEditor
1207 fxRooteditor->SetEditable(); // mainframe will adopt pad editor window
1208
1209 fxPeditor = TVirtualPadEditor::LoadEditor();
1210 fxPeditor->SetGlobal(kFALSE);
1211 fxRooteditor->SetEditable(kFALSE); // back to window manager as root window
1212 }
1213#endif
1214}
1215
1217{
1218#ifndef __NOGO4GED__
1219 TGedEditor* ed = dynamic_cast<TGedEditor*>(fxPeditor);
1220 if (ed && isEditorVisible() && fxRooteditor)
1221 ed->Resize(fxRooteditor->ScaledWidth(), fxRooteditor->ScaledHeight());
1222#endif
1223}
1224
1225
1226void QRootCanvas::activateEditor(TPad *pad, TObject *obj)
1227{
1228#ifndef __NOGO4GED__
1229 TGedEditor* ed = dynamic_cast<TGedEditor*>(fxPeditor);
1230 if (ed && obj && isEditorVisible()) {
1231 gTQSender = getCanvas();
1232 ed->SetModel(pad, obj, kButton1Down);
1233 }
1234#endif
1235}
1236
1238{
1239#ifndef __NOGO4GED__
1240 TGedEditor* ed = dynamic_cast<TGedEditor*>(fxPeditor);
1241 if (!ed) return;
1242 if (!fDummyHisto) {
1243 fDummyHisto = new TH1I("dummyhisto", "dummyhisto", 100, -10., 10.);
1244 fDummyHisto->FillRandom("gaus", 1000);
1245 fDummyHisto->SetDirectory(nullptr);
1246 fDummyHisto->SetBit(kCanDelete, kFALSE);
1247 }
1248 gTQSender = getCanvas();
1249 ed->SetModel(nullptr, fDummyHisto, kButton1Down);
1250 ed->SetModel(nullptr, getCanvas(), kButton1Down);
1251#endif
1252}
1253
1254
1256{
1257 if (fStatusBar) fStatusBar->showMessage(msg);
1258}
1259
1261{
1262 return fStatusBar ? fStatusBar->isVisible() : false;
1263}
1264
1266{
1267 if (!fStatusBar) return;
1268
1269 setShowEventStatus(flag);
1270 fStatusBar->setVisible(flag);
1271}
1272
1273
1274// JAM2019 test order of creation for ged parent window in qt4:
1276{
1277 if (!fxRooteditor) {
1278 fxRooteditor = new QRootWindow(fEditorFrame, "rootwrapperwindow");
1279 QVBoxLayout* gedlayout = new QVBoxLayout(fEditorFrame);
1280 gedlayout->setContentsMargins(0, 0, 0, 0);
1281 gedlayout->addWidget(fxRooteditor);
1282 }
1283}
#define TGo4LockGuard
static bool IsRootCanvasMenuEnabled()
virtual ~QRootCanvas()
void activateRepaint(int act)
virtual void ToggleEventStatus()
void SelectedPadChanged(TPad *)
signal which will be emitted when root selected pad is changed via clicking the mid-mouse button (M.
Int_t GetWindowTopX()
Bool_t IsRetained()
bool isStatusBarVisible()
void activateEditor(TPad *pad, TObject *obj)
Bool_t OpaqueResizing()
bool isEditorAllowed()
void CanvasLeaveEvent()
Int_t GetCanvasID()
virtual TPad * Pick(Int_t px, Int_t py, TObjLink *&pickobj)
void FeedbackMode(Bool_t set)
void showStatusMessage(const char *msg)
Size_t GetYsizeUser()
void dropEvent(QDropEvent *Event) override
TVirtualPadEditor * fxPeditor
UInt_t GetWh()
double scaledPosition(int p)
returns scaled point coordinate, for high dpi case
TObject * GetSelected()
virtual void SetDoubleBuffer(Int_t mode=1)
void paintEvent(QPaintEvent *e) override
TCanvas * getCanvas()
Definition QRootCanvas.h:67
TH1 * fDummyHisto
virtual TObject * DrawClonePad()
Int_t GetEventY()
void UseCurrentStyle()
void processRepaintTimer()
void SetTitle(const char *title="")
void closeEvent(QCloseEvent *e) override
void CanvasDropEvent(QDropEvent *, TPad *)
virtual void Browse(TBrowser *b)
void SetCanvasSize(UInt_t ww, UInt_t wh)
void cleanupEditor()
void mouseDoubleClickEvent(QMouseEvent *e) override
bool fxShowEventStatus
UInt_t GetWw()
virtual void Resize(Option_t *option="")
Int_t GetWindowTopY()
TVirtualPad * GetPadSave()
void CanvasUpdated()
Bool_t GetAutoExec()
void SetRetained(Bool_t retained=kTRUE)
const char * GetDISPLAY()
void ForceUpdate()
void setShowEventStatus(bool s)
void SaveSource(const char *filename="", Option_t *option="")
void MoveOpaque(Int_t set=1)
UInt_t GetWindowWidth()
TVirtualPad * GetSelectedPad()
Int_t GetEventX()
QAction * addMenuAction(QMenu *menu, QSignalMapper *map, const QString &text, int id)
Color_t GetHighLightColor()
QRootCanvas(QWidget *parent=nullptr)
virtual void Size(Float_t xsizeuser=0, Float_t ysizeuser=0)
virtual void ls(Option_t *option="")
void buildEditorWindow()
Int_t fRootWindowId
void setStatusBarVisible(bool flag)
void SetWindowPosition(Int_t x, Int_t y)
Bool_t HasMenuBar()
Bool_t OpaqueMoving()
virtual void SetCursor(ECursor cursor)
virtual void HandleInput(EEventType button, Int_t x, Int_t y)
double fMousePosX
Bool_t IsBatch()
virtual void GetCanvasPar(Int_t &wtopx, Int_t &wtopy, UInt_t &ww, UInt_t &wh)
bool isEditorVisible()
virtual void Paint(Option_t *option="")
Int_t GetDoubleBuffer()
void Modified(Bool_t=1)
virtual TObject * DrawClone(Option_t *option="")
bool fMaskDoubleClick
void methodDialog(TObject *object, TMethod *method)
void leaveEvent(QEvent *e) override
void mousePressEvent(QMouseEvent *e) override
QPoint scaledMousePoint(QMouseEvent *ev)
void wheelEvent(QWheelEvent *e) override
UInt_t GetWindowHeight()
void SetWindowSize(UInt_t ww, UInt_t wh)
TList * fMenuMethods
void PadDoubleClicked(TPad *, int, int)
signal emitted when user produce left mouse double-click on pad
TObject * fMenuObj
void mouseMoveEvent(QMouseEvent *e) override
Size_t GetYsizeReal()
void MenuCommandExecuted(TObject *, const char *)
QTimer * fRepaintTimer
void Clear(Option_t *option="")
Size_t GetXsizeReal()
void PadClicked(TPad *, int, int)
signal emitted when mouse clicks on pad
void ResizeOpaque(Int_t set=1)
void SetBatch(Bool_t batch=kTRUE)
TCanvas * fCanvas
void toggleEditor()
void Close(Option_t *option="")
void cd(Int_t subpadnumber=0)
virtual void Draw(Option_t *option="")
Option_t * GetSelectedOpt()
void SetSelected(TObject *obj)
virtual void ToggleAutoExec()
void SetSelectedPad(TPad *pad)
QFrame * fEditorFrame
virtual void Update()
Size_t GetXsizeUser()
void CanvasStatusEvent(const char *)
Bool_t GetShowEventStatus()
Int_t GetEvent()
void resizeEvent(QResizeEvent *e) override
double fQtScalingfactor
TContextMenu * GetContextMenu()
void resizeEditor()
void SetHighLightColor(Color_t col)
void EnterLeave(TPad *prevSelPad, TObject *prevSelObj)
bool showEventStatus() const
QStatusBar * fStatusBar
void mouseReleaseEvent(QMouseEvent *e) override
void executeMenu(int id)
QRootWindow * fxRooteditor
double fMousePosY
void dragEnterEvent(QDragEnterEvent *e) override
virtual void EditorBar()
QRootDialog.
Definition QRootDialog.h:49
void addArg(const char *argname, const char *value, const char *type)
QString getArg(int n)
Qt widget wrapper for ROOT TGWindow class.
Definition QRootWindow.h:32