GSI Object Oriented Online Offline (Go4)  GO4-6.1.2
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
QRootCanvas.cpp
Go to the documentation of this file.
1 // $Id: QRootCanvas.cpp 3145 2021-03-30 14:33:08Z 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 /****************************************************************************
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 
66 QRootCanvas::QRootCanvas(QWidget *parent) :
67  QWidget(parent),
68  fMaskDoubleClick(false),
69  fxShowEventStatus(false),
70  fQtScalingfactor(1.0)
71 {
72  setObjectName( "QRootCanvas");
73 
74  setSizeIncrement( QSize( 100, 100 ) );
75 
76  TGo4LockGuard threadlock;
77  // set defaults
78  setUpdatesEnabled( true );
79  setMouseTracking(true);
80 
81  setFocusPolicy( Qt::TabFocus );
82  setCursor( Qt::CrossCursor );
83 
84  // disable option that at least background is redrawn immediately
85  // and canvas content after 100 ms timeout
86  //setAttribute(Qt::WA_NoSystemBackground);
87  setAttribute(Qt::WA_PaintOnScreen);
88  setAttribute(Qt::WA_PaintUnclipped);
89 
90  // add the Qt::WinId to TGX11 interface
91  fQtWindowId = winId();
92  fRootWindowId = gVirtualX->AddWindow((ULong_t)fQtWindowId, 100, 30);
93 
94  fCanvas = new TCanvas("Canvas", width(), height(), fRootWindowId);
95 
96 #if QT_VERSION > QT_VERSION_CHECK(5,6,0)
97  // JAM the following is pure empiric. hopefully default denominator won't change in future qt?
98  fQtScalingfactor=(double) metric(QPaintDevice::PdmDevicePixelRatioScaled)/65536.;
99 #endif
100  //std::cout <<"Found Qt scaling factor:"<<fQtScalingfactor << std::endl;
101  // create the context menu
102  fMousePosX = 0;
103  fMousePosY = 0;
104  fMenuMethods = 0;
105  fMenuObj = 0;
106 
107  setAcceptDrops(true);
108 
109  fRepaintMode = 0;
110  fRepaintTimer = new QTimer;
111  fRepaintTimer->setSingleShot(true);
112  connect(fRepaintTimer, SIGNAL(timeout()), this, SLOT(processRepaintTimer()));
113 
114  fEditorFrame = 0;
115  fxPeditor = 0;
116  fxRooteditor = 0;
117  fDummyHisto = 0;
118 
119  fStatusBar = 0;
120 }
121 
123 {
124  // cannot call here, must be done before until X11 frame is exists
125  // cleanupEditor();
126 
127  if (fDummyHisto) {
128  delete fDummyHisto;
129  fDummyHisto = 0;
130  }
131 
132 #ifndef __NOGO4GED__
133  if (gTQSender == getCanvas())
134  gTQSender = 0;
135 
136  // prevent problems with root's subeditor cache
137  if (fxPeditor != 0) {
138  fxPeditor->DeleteEditors();
139  delete fxPeditor;
140  fxPeditor = 0;
141  }
142 #endif
143 
144  if(fCanvas) {
145  delete fCanvas;
146  fCanvas = 0;
147  }
148 
149  if (fMenuMethods) {
150  delete fMenuMethods;
151  fMenuMethods = 0;
152  }
153 
154  delete fRepaintTimer;
155 }
156 
157 QPoint QRootCanvas::scaledMousePoint(QMouseEvent *e)
158 {
159 #if QT_VERSION < QT_VERSION_CHECK(6,0,0)
160  int scaledX = scaledPosition(e->x());
161  int scaledY = scaledPosition(e->y());
162 #else
163  int scaledX = scaledPosition(e->position().x());
164  int scaledY = scaledPosition(e->position().y());
165 #endif
166  return QPoint(scaledX, scaledY);
167 }
168 
169 void QRootCanvas::mouseMoveEvent(QMouseEvent *e)
170 {
171  TGo4LockGuard threadlock;
172 #if QT_VERSION > QT_VERSION_CHECK(5,0,0)
173  // JAM use event timestamp for reduction of events (qt5 bug):
174  static ulong lastprocesstime=0;
175  static ulong delta=100; // maybe ms units?
176  ulong timestamp=e->timestamp();
177  if(timestamp-delta<lastprocesstime)
178  {
179  // just eat too old events
180  e->accept();
181  // std::cout <<"----- EATING timestamp:"<<timestamp<< std::endl;
182  return;
183  }
184 
185  //std::cout <<"----- QRootCanvas::mouseMoveEvent with timestamp:"<<timestamp<<", oldstamp:"<<lastprocesstime << std::endl;
186 #endif
187 
188 
189  if (fCanvas) {
190  QPoint pnt = scaledMousePoint(e);
191 
192  if (e->buttons() & Qt::LeftButton)
193  fCanvas->HandleInput(kButton1Motion, pnt.x(), pnt.y());
194  else
195  fCanvas->HandleInput(kMouseMotion, pnt.x(), pnt.y());
196  }
197 
198  if(fxShowEventStatus) {
199  TObject* selected = fCanvas->GetSelected();
200  Int_t px = fCanvas->GetEventX();
201  Int_t py = fCanvas->GetEventY();
202  QString buffer = "";
203  if (selected!=0) {
204  buffer = selected->GetName();
205  buffer += " ";
206  buffer += selected->GetObjectInfo(px, py);
207  } else {
208  buffer = "No selected object x = ";
209  buffer += QString::number(px);
210  buffer += " y = ";
211  buffer += QString::number(py);
212  }
213 
214  emit CanvasStatusEvent(buffer.toLatin1().constData());
215 
216  if (fStatusBar) fStatusBar->showMessage(buffer.toLatin1().constData());
217  }
218  e->accept();
219 #if QT_VERSION > QT_VERSION_CHECK(5,0,0)
220  lastprocesstime=timestamp;
221 #endif
222 }
223 
224 void QRootCanvas::wheelEvent( QWheelEvent* e)
225 {
226  TGo4LockGuard threadlock;
227  if (!fCanvas) return;
228  e->accept();
229 
230 #if QT_VERSION < QT_VERSION_CHECK(5,15,0)
231  bool positive = (e->delta() > 0);
232  int ex = e->x(), ey = e->y();
233 #else
234  QPoint delta = e->pixelDelta();
235  if (delta.isNull()) delta = e->angleDelta() / 8;
236  bool positive = delta.x() > 0 || delta.y() > 0;
237  int ex = e->position().x(), ey = e->position().y();
238 #endif
239 
240  fCanvas->HandleInput(positive ? kWheelUp : kWheelDown, scaledPosition(ex), scaledPosition(ey));
241 }
242 
243 
244 void QRootCanvas::mousePressEvent( QMouseEvent *e )
245 {
246  TGo4LockGuard threadlock;
247  TObjLink* pickobj = 0;
248  // JAM2016-9 test
249 // std::cout <<"QRootCanvas::mousePressEvent at ("<<e->x()<<", "<< e->y()<<")"<< std::endl;
250 
251  QPoint scaled = scaledMousePoint(e);
252 #if QT_VERSION < QT_VERSION_CHECK(6,0,0)
253  QPoint mouse_pnt = e->globalPos();
254 #else
255  QPoint mouse_pnt = e->globalPosition().toPoint();
256 #endif
257 
258  // std::cout <<" scaledX,scaledY: ("<<scaledX<<", "<<scaledY <<") "<< std::endl;
259 // std::cout <<"global from event: ("<<e->globalX()<<", "<< e->globalY()<< std::endl;
260 // QPoint globalp=QWidget::mapToGlobal(e->pos());
261 // std::cout <<"global from map: ("<<globalp.x()<<", "<<globalp.y() <<") "<< std::endl;
262 // QPoint parentp=QWidget::mapToParent(e->pos());
263 // std::cout <<"parent: ("<<parentp.x()<<", "<<parentp.y()<<") " << std::endl;
264 // QPoint backfromglobalp=QWidget::mapFromGlobal(globalp);
265 // std::cout <<"backglobal: ("<<backfromglobalp.x()<<", "<<backfromglobalp.y()<<") " << std::endl;
266 // Int_t destx=0, desty=0;
267 // Window_t child;
268 // Window_t rootwindow=gVirtualX->GetDefaultRootWindow();
269 // gVirtualX->TranslateCoordinates(rootwindow, fQtWindowId, globalp.x(), globalp.y(), destx, desty, child);
270 // std::cout <<"TGX11 global translated: ("<<destx<<", "<<desty<<") " << std::endl;
271 // std::cout <<"TGX11 winids - default root:"<<rootwindow<<", Qt:"<<fQtWindowId<<", child:" <<child<< std::endl;
272 
273 
274  /* int themetric= metric(QPaintDevice::PdmDevicePixelRatio);
275  int scaledmetric= metric(QPaintDevice::PdmDevicePixelRatioScaled);
276  std::cout <<"metric="<<themetric<<", scaled="<<scaledmetric << std::endl;
277  int scaledX=e->x() * scaledmetric/65536; // empiric
278  int scaledY=e->y() * scaledmetric/65536; // empiric
279  std::cout <<"scaledX,scaledY: ("<<scaledX<<", "<<scaledY <<") "<< std::endl;
280  */
281 
282 
283  TPad* pad = fCanvas->Pick(scaled.x(), scaled.y(), pickobj);
284  TObject *selected = fCanvas->GetSelected();
285 
286  switch(e->button()) {
287  case Qt::LeftButton :
288  fCanvas->HandleInput(kButton1Down, scaled.x(), scaled.y());
289  emit PadClicked(pad);
290  break;
291  case Qt::RightButton : {
292  TString selectedOpt("");
293  if (pad!=0) {
294  if (pickobj==0) {
295  fCanvas->SetSelected(pad);
296  selected = pad;
297  } else
298  if(selected==0) {
299  selected = pickobj->GetObject();
300  selectedOpt = pickobj->GetOption();
301  }
302  pad->cd();
303  }
304  fCanvas->SetSelectedPad(pad);
305  gROOT->SetSelectedPrimitive(selected);
306  fMousePosX = gPad->AbsPixeltoX(gPad->GetEventX());
307  fMousePosY = gPad->AbsPixeltoY(gPad->GetEventY());
308 
309  QMenu menu(this);
310  QSignalMapper map;
311  connect(&map, SIGNAL(mapped(int)), this, SLOT(executeMenu(int)));
312 
313  fMenuObj = selected;
314  fMenuMethods = new TList;
315  TClass *cl = fMenuObj->IsA();
316  int curId = -1;
317 
318  QString buffer = Form("%s::%s", cl->GetName(), fMenuObj->GetName());
319  addMenuAction(&menu, &map, buffer, curId++);
320 
321  cl->GetMenuItems(fMenuMethods);
322  menu.addSeparator();
323 
324  if(!cl->InheritsFrom(TLatex::Class())) {
325  addMenuAction(&menu, &map, "Insert Latex", 100 );
326  menu.addSeparator();
327  }
328 
329  if(cl->InheritsFrom(TH1::Class())) {
330  addMenuAction(&menu, &map, "Qt Hist Line Color ", 101 );
331  addMenuAction(&menu, &map, "Qt Hist Fill Color ", 102 );
332  menu.addSeparator();
333  }
334 
335  TIter iter(fMenuMethods);
336  TMethod *method=0;
337  while ( (method = dynamic_cast<TMethod*>(iter())) != 0) {
338  buffer = method->GetName();
339  addMenuAction(&menu, &map, buffer, curId++);
340  }
341 
342  if (menu.exec(mouse_pnt)==0) {
343  fMenuObj = 0;
344  delete fMenuMethods;
345  fMenuMethods = 0;
346  }
347 
348  break;
349  }
350  case Qt::MiddleButton :
351  fCanvas->HandleInput(kButton2Down, scaled.x(), scaled.y());
352  emit SelectedPadChanged(pad); // that inform the Qt-world that tha pad is changed
353  // and give the pointer to the new pad as argument
354  // of the signal (M. Al-Turany)
355  break;
356  case Qt::NoButton :
357  break;
358  default:
359  break;
360  }
361  e->accept();
362 }
363 
364 void QRootCanvas::mouseReleaseEvent( QMouseEvent *e )
365 {
366  QPoint scaled = scaledMousePoint(e);
367 
368  TGo4LockGuard threadlock;
369 
370  switch(e->button()) {
371  case Qt::LeftButton :
372  fCanvas->HandleInput(kButton1Up, scaled.x(), scaled.y());
373  break;
374  case Qt::RightButton :
375  fCanvas->HandleInput(kButton3Up, scaled.x(), scaled.y());
376  break;
377  case Qt::MiddleButton :
378  fCanvas->HandleInput(kButton2Up, scaled.x(), scaled.y());
379  break;
380  case Qt::NoButton :
381  break;
382  default:
383  break;
384  }
385  e->accept();
386 }
387 
389 {
390  QPoint scaled = scaledMousePoint(e);
391 
392  TGo4LockGuard threadlock;
393  switch(e->button()) {
394  case Qt::LeftButton : {
395  if (!fMaskDoubleClick)
396  fCanvas->HandleInput(kButton1Double, scaled.x(), scaled.y());
397  TObjLink* pickobj = 0;
398  TPad* pad = fCanvas->Pick(scaled.x(), scaled.y(), pickobj);
399  emit PadDoubleClicked(pad);
400  // prevent crash on following release event
401  // if new canvas will be created in between
402  // fCanvas->SetSelected(0);
403  break;
404  }
405  case Qt::RightButton :
406  fCanvas->HandleInput(kButton3Double, scaled.x(), scaled.y());
407  break;
408  case Qt::MiddleButton :
409  fCanvas->HandleInput(kButton2Double, scaled.x(), scaled.y());
410  break;
411  case Qt::NoButton :
412  break;
413  default:
414  break;
415  }
416  e->accept();
417 }
418 
420 {
421  fRepaintMode |= mode;
422 // if (fRepaintMode > 0) setUpdatesEnabled( false ); // JAM avoid flicker on Qt5 ?
423  fRepaintTimer->setSingleShot(true);
424  fRepaintTimer->start(100);
425 }
426 
427 void QRootCanvas::resizeEvent( QResizeEvent *)
428 {
429  //std::cout<< "QRootCanvas::resizeEvent"<<std::endl;
431 }
432 
433 void 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  //std::cout<< " QRootCanvas::processRepaintTimer()"<<std::endl;
450  //printf("processRepaintTimer with fRepaintMode %d\n",fRepaintMode);
451  TGo4LockGuard threadlock;
452 
453  WId newid = winId();
454  if(newid != fQtWindowId) {
455  //printf("processRepaintTimer - sees changed window id %d \n",newid);
456  // Qt has changed id for this widget (e.g. at QWorkspace::addWindow())
457  // need to adjust the ROOT X access:
458  delete fCanvas; // should also remove old x windows!
459  fRootWindowId = gVirtualX->AddWindow((ULong_t)newid, width(), height());
460  fCanvas = new TCanvas(objectName().toLatin1().constData(), width(), height(), fRootWindowId);
461  fQtWindowId = newid;
462  }
463 
464  if (fRepaintMode && act_Resize) fCanvas->Resize();
465  else fCanvas->Modified(kTRUE);
466 
467  fCanvas->Update();
468 
469  fRepaintMode = 0;
470  //std::cout<< std::endl;
471  emit CanvasUpdated();
472  //setUpdatesEnabled( true ); // JAM avoid flicker on Qt5 ?
473 }
474 
475 void QRootCanvas::leaveEvent( QEvent *e )
476 {
477  QWidget::leaveEvent(e);
478 
479  TGo4LockGuard threadlock;
480  if (fCanvas!=0)
481  fCanvas->HandleInput(kMouseLeave, 0, 0);
482 
483  emit CanvasLeaveEvent();
484 }
485 
487 {
488  fxShowEventStatus = s;
489 }
490 
492 {
493  return fxShowEventStatus;
494 }
495 
497 
498 void QRootCanvas::dragEnterEvent( QDragEnterEvent *e )
499 {
500  if (e->mimeData()->hasText())
501  e->acceptProposedAction();
502 }
503 
504 void QRootCanvas::dropEvent( QDropEvent *event )
505 {
506  TObject* obj = 0;
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 
522 void QRootCanvas::cd(Int_t subpadnumber)
523 {
524  fCanvas->cd(subpadnumber);
525 }
526 
527 void QRootCanvas::Browse(TBrowser *b)
528 {
529  fCanvas->Browse(b);
530 }
531 
532 void QRootCanvas::Clear(Option_t *option)
533 {
534  fCanvas->Clear(option);
535 }
536 
537 void QRootCanvas::Close(Option_t *option)
538 {
539  fCanvas->Close(option);
540 }
541 
542 void QRootCanvas::Draw(Option_t *option)
543 {
544  fCanvas->Draw(option);
545 }
546 
547 TObject* 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 
562 void 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 
707 void QRootCanvas::GetCanvasPar(Int_t &wtopx, Int_t &wtopy, UInt_t &ww, UInt_t &wh)
708 {
709  fCanvas->GetCanvasPar(wtopx, wtopy, ww, wh);
710 }
711 
712 void 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 
737 void QRootCanvas::ls(Option_t *option)
738 {
739  fCanvas->ls(option);
740 }
741 
742 void QRootCanvas::Modified(Bool_t mod)
743 {
744  fCanvas->Modified(mod);
745 }
746 
747 void QRootCanvas::MoveOpaque(Int_t set)
748 {
749  fCanvas->MoveOpaque(set);
750 }
751 
753 {
754  return fCanvas->OpaqueMoving();
755 }
756 
758 {
759  return fCanvas->OpaqueResizing();
760 }
761 
762 void QRootCanvas::Paint(Option_t *option)
763 {
764  fCanvas->Paint(option);
765 }
766 
767 TPad* QRootCanvas::Pick(Int_t px, Int_t py, TObjLink *&pickobj)
768 {
769  return fCanvas->Pick(px, py, pickobj);
770 }
771 
772 TPad* QRootCanvas::Pick(Int_t px, Int_t py, TObject *prevSelObj)
773 {
774  return fCanvas->Pick(px, py, prevSelObj);
775 }
776 
777 void QRootCanvas::Resize(Option_t *option)
778 {
779  fCanvas->Resize(option);
780 }
781 
783 {
784  fCanvas->ResizeOpaque(set);
785 }
786 
787 void QRootCanvas::SaveSource(const char *filename, Option_t *option)
788 {
789  fCanvas->SaveSource(filename, option);
790 }
791 
792 void QRootCanvas::SetCursor(ECursor cursor)
793 {
794  fCanvas->SetCursor(cursor);
795 }
796 
798 {
799  fCanvas->SetDoubleBuffer(mode);
800 }
801 
802 void QRootCanvas::SetWindowPosition(Int_t x, Int_t y)
803 {
804  fCanvas->SetWindowPosition(x, y) ;
805 }
806 
807 void QRootCanvas::SetWindowSize(UInt_t ww, UInt_t wh)
808 {
809  fCanvas->SetWindowSize(ww,wh) ;
810 }
811 
812 void QRootCanvas::SetCanvasSize(UInt_t ww, UInt_t wh)
813 {
814  fCanvas->SetCanvasSize(ww, wh);
815 }
816 
818 {
819  fCanvas->SetHighLightColor(col);
820 }
821 
822 void QRootCanvas::SetSelected(TObject *obj)
823 {
824  fCanvas->SetSelected(obj);
825 }
826 
828 {
829  fCanvas->SetSelectedPad(pad);
830 }
831 
833 {
834  fCanvas->Show();
835 }
836 
837 void QRootCanvas::Size(Float_t xsizeuser, Float_t ysizeuser)
838 {
839  fCanvas->Size(xsizeuser, ysizeuser);
840 }
841 
842 void QRootCanvas::SetBatch(Bool_t batch)
843 {
844  fCanvas->SetBatch(batch);
845 }
846 
847 void QRootCanvas::SetRetained(Bool_t retained)
848 {
849  fCanvas->SetRetained(retained);
850 }
851 
852 void 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 
873 void QRootCanvas::closeEvent(QCloseEvent * e)
874 {
875  if (fCanvas) {
876  delete fCanvas;
877  fCanvas = 0;
878  }
879 
880  e->accept();
881 }
882 
883 void QRootCanvas::methodDialog(TObject* object, TMethod* method)
884 {
885  if ((object==0) || (method==0)) return;
886 
887  TGo4LockGuard threadlock;
888  // Create dialog object with OK and Cancel buttons. This dialog
889  // prompts for the arguments of "method".
890 
891  QRootDialog dlg;
892 
893  dlg.setWindowTitle(Form("%s:%s", object->GetName(), method->GetName()));
894 
895  // iterate through all arguments and create apropriate input-data objects:
896  // inputlines, option menus...
897  TMethodArg *argument = 0;
898  TIter next(method->GetListOfMethodArgs());
899 
900  while ((argument = (TMethodArg *) next())) {
901  TString argTitle = TString::Format("(%s) %s", argument->GetTitle(), argument->GetName());
902  TString argDflt = argument->GetDefault() ? argument->GetDefault() : "";
903  if (argDflt.Length()>0)
904  argTitle += TString::Format(" [default: %s]", argDflt.Data());
905  TString type = argument->GetTypeName();
906  TDataType *datatype = gROOT->GetType(type);
907  TString basictype;
908 
909  if (datatype) {
910  basictype = datatype->GetTypeName();
911  } else {
912  if (type.CompareTo("enum") != 0)
913  std::cout << "*** Warning in Dialog(): data type is not basic type, assuming (int)\n";
914  basictype = "int";
915  }
916 
917  if (TString(argument->GetTitle()).Index("*")!=kNPOS) {
918  basictype += "*";
919  type = "char*";
920  }
921 
922  TDataMember *m = argument->GetDataMember();
923  if (m && m->GetterMethod()) {
924 
925  m->GetterMethod()->Init(object->IsA(), m->GetterMethod()->GetMethodName(), "");
926 
927  // Get the current value and form it as a text:
928 
929  TString val;
930 
931  if (basictype == "char*") {
932  char *tdefval(0);
933  m->GetterMethod()->Execute(object, "", &tdefval);
934  if (tdefval) val = tdefval;
935  } else
936  if ((basictype == "float") ||
937  (basictype == "double")) {
938  Double_t ddefval(0.);
939  m->GetterMethod()->Execute(object, "", ddefval);
940  val = TString::Format("%g", ddefval);
941  } else
942  if ((basictype == "char") ||
943  (basictype == "int") ||
944  (basictype == "long") ||
945  (basictype == "short")) {
946  Long_t ldefval(0);
947  m->GetterMethod()->Execute(object, "", ldefval);
948  val = TString::Format("%ld", ldefval);
949  }
950 
951  // Find out whether we have options ...
952 
953  TList *opt;
954  if ((opt = m->GetOptions()) != 0) {
955  //std::cout << "*** Warning in Dialog(): option menu not yet implemented " << opt << std::endl;
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  //std::cout<< "executeMethod" << fCurMethod->GetName() << std::endl;
988 
989  TObjArray tobjlist(method->GetListOfMethodArgs()->LastIndex() + 1);
990  for (int n=0; n<=method->GetListOfMethodArgs()->LastIndex(); n++) {
991  QString s = dlg.getArg(n);
992  qDebug( "** QString values (first ) :%s \n", s.toLatin1().constData() );
993  tobjlist.AddLast(new TObjString(s.toLatin1().constData())) ;
994  }
995 
996  // handle command if existing object
997  if(strcmp(method->GetName(),"Delete") == 0) {
998  // here call explicitly the dtor
999  qDebug(" DIAL obj name deleted :%s \n", object->GetName());
1000  emit MenuCommandExecuted(object, "Delete");
1001  delete object;
1002  object = 0;
1003  deletion = kTRUE;
1004  qDebug(" DIAL deletion done closing ... \n");
1005  } else
1006  if (strcmp(method->GetName(), "SetCanvasSize") == 0) {
1007  int width = dlg.getArg(0).toInt();
1008  int height = dlg.getArg(1).toInt();
1009  qDebug( " do resize with %i %i \n", width, height);
1010  resize(width, height);
1011  emit MenuCommandExecuted(fCanvas, "SetCanvasSize");
1012  } else {
1013  // here call cint call
1014  qDebug("TCint::Execute called !\n");
1015 
1016  object->Execute(method, &tobjlist);
1017 
1018  if (object->TestBit(TObject::kNotDeleted))
1019  emit MenuCommandExecuted(object, method->GetName());
1020  else {
1021  deletion = true;
1022  object = 0;
1023  }
1024  }
1025 
1026  if(!deletion ) {
1027  qDebug("DIAL set saved pad: %s herit:%s gPad:%s\n",
1028  psave->GetName(), psave->ClassName(), gPad->GetName());
1029  gROOT->SetSelectedPad(psave);
1030  gROOT->GetSelectedPad()->Modified();
1031  gROOT->GetSelectedPad()->Update();
1032  qDebug("DIAL update done on %s \n", gROOT->GetSelectedPad()->GetName());
1033  } else {
1034  gROOT->SetSelectedPad( gPad );
1035  gROOT->GetSelectedPad()->Update();
1036  }
1037 }
1038 
1039 QAction* QRootCanvas::addMenuAction(QMenu* menu, QSignalMapper* map, const QString& text, int id)
1040 {
1042 
1043  QAction* act = new QAction(text, menu);
1044 
1045  if (!enabled)
1046  if ((text.compare("DrawClone")==0) ||
1047  (text.compare("DrawClass")==0) ||
1048  (text.compare("Inspect")==0) ||
1049  (text.compare("SetShowProjectionX")==0) ||
1050  (text.compare("SetShowProjectionY")==0) ||
1051  (text.compare("DrawPanel")==0) ||
1052  (text.compare("FitPanel")==0))
1053  act->setEnabled(false);
1054 
1055  map->connect (act, SIGNAL(triggered()), map, SLOT(map()));
1056  menu->addAction(act);
1057  map->setMapping(act, id);
1058 
1059 
1060  return act;
1061 }
1062 
1064 {
1065  TGo4LockGuard threadlock;
1066  QString text("");
1067  bool ok = false;
1068  if (id >=100) {
1069  switch (id){
1070  case 100: {
1071  TLatex *fxLatex = new TLatex();
1072  text = QInputDialog::getText(this, tr( "Qt Root" ),
1073  tr( "Please enter your text" ),
1074  QLineEdit::Normal, QString(), &ok);
1075  //if (ok && !text.isEmpty())
1076  fxLatex->DrawLatex(fMousePosX, fMousePosY, text.toLatin1().constData());
1077  emit MenuCommandExecuted(fxLatex, "DrawLatex");
1078  break;
1079  }
1080  case 101: {
1081  TH1 *h1 = dynamic_cast<TH1*> (fMenuObj);
1082  if (h1!=0) {
1083  QColor col = QColorDialog::getColor();
1084  if (col.isValid()) {
1085  short int C_new = TColor::GetColor(col.red(), col.green(), col.blue());
1086  h1->SetLineColor(C_new);
1087  emit MenuCommandExecuted(h1, "SetLineColor");
1088  }
1089  }
1090  break;
1091  }
1092  case 102 : {
1093  TH1 *h1 = dynamic_cast<TH1*> (fMenuObj);
1094  if (h1!=0) {
1095  QColor col = QColorDialog::getColor();
1096  if (col.isValid()) {
1097  short int C_new = TColor::GetColor(col.red(), col.green(), col.blue());
1098  h1->SetFillColor(C_new);
1099  emit MenuCommandExecuted(h1,"SetFillColor");
1100  }
1101  }
1102  }
1103  }
1104  gROOT->GetSelectedPad()->Update();
1105  gROOT->GetSelectedPad()->Modified();
1106  fCanvas->Modified();
1107  fCanvas->ForceUpdate();
1108  gROOT->SetFromPopUp( kFALSE );
1109  } else
1110  if (id >=0) {
1111 
1112  // save global to Pad before calling TObject::Execute()
1113 
1114  TVirtualPad* psave = gROOT->GetSelectedPad();
1115  TMethod *method = (TMethod *) fMenuMethods->At(id);
1116 
1118  fCanvas->HandleInput(kButton3Up, gPad->XtoAbsPixel(fMousePosX), gPad->YtoAbsPixel(fMousePosY));
1119 
1120  // change current dir that all new histograms appear here
1121  gROOT->cd();
1122 
1123 
1124  if (method->GetListOfMethodArgs()->First()){
1125  if (strstr(method->GetName(), "Delete")){
1126  // JAM2016: do not allow mouse menu delete in Go4
1127  //std::cout << "Supressing Delete in menu!" << std::endl;
1128  }
1129  else {
1130  methodDialog(fMenuObj, method);
1131  }
1132  }
1133  else
1134  {
1135  gROOT->SetFromPopUp(kTRUE);
1136  fMenuObj->Execute(method->GetName(), "");
1137 
1138  if (fMenuObj->TestBit(TObject::kNotDeleted)) {
1139  emit MenuCommandExecuted(fMenuObj, method->GetName());
1140  } else {
1141  fMenuObj = 0;
1142  }
1143 
1144  }
1145 
1146  #ifndef __NOGO4GED__
1147  TGedEditor* ed = dynamic_cast<TGedEditor*>(TVirtualPadEditor::GetPadEditor(kFALSE));
1148  if (fMenuObj && ed) ed->SetModel(psave, fMenuObj, kButton1Down);
1149  #endif
1150 
1151  fCanvas->GetPadSave()->Update();
1152  fCanvas->GetPadSave()->Modified();
1153 
1154  gROOT->SetSelectedPad(psave);
1155 
1156  gROOT->GetSelectedPad()->Update();
1157  gROOT->GetSelectedPad()->Modified();
1158 
1159  fCanvas->Modified();
1160  fCanvas->ForceUpdate();
1161  gROOT->SetFromPopUp(kFALSE);
1162  }
1163 
1164  fMenuObj = 0;
1165  delete fMenuMethods;
1166  fMenuMethods = 0;
1167 }
1168 
1170 {
1171  return fEditorFrame ? fEditorFrame->isVisible() : false;
1172 }
1173 
1174 
1176 {
1177 #ifdef __NOGO4GED__
1178  return false;
1179 #else
1181 #endif
1182 }
1183 
1185 {
1186  if (!fEditorFrame) return;
1187 
1188 #ifndef __NOGO4GED__
1189  bool flag = !isEditorVisible();
1190 
1191  fEditorFrame->setVisible(flag);
1192  if (flag && (fxPeditor == 0)) {
1193 #if QT_VERSION > QT_VERSION_CHECK(5,6,0)
1194  // JAM the following is pure empiric. hopefully default denominator won't change in future qt?
1195  double scalefactor=(double) metric(QPaintDevice::PdmDevicePixelRatioScaled)/65536.;
1196  fEditorFrame->setMinimumWidth( fEditorFrame->minimumWidth()/scalefactor);
1197 #endif
1198 
1199 // JAM 5-2019: this part was moved to buildEditorWindow() because of init problems with Qt 4
1200 // std::cout<< "QRootCanvas::toggleEditor() will create Rooteditor" <<std::endl;
1201 // fxRooteditor = new QRootWindow(fEditorFrame, "rootwrapperwindow");
1202 // QVBoxLayout* gedlayout = new QVBoxLayout(fEditorFrame);
1203 // gedlayout->setContentsMargins(0, 0, 0, 0);
1204 // gedlayout->addWidget(fxRooteditor);
1206  TGo4LockGuard lock;
1207  fxRooteditor->SetResizeOnPaint(kFALSE); // disable internal resize on paintEvent, we use ResizeGedEditor
1208  fxRooteditor->SetEditable(); // mainframe will adopt pad editor window
1209 
1210  fxPeditor = TVirtualPadEditor::LoadEditor();
1211  fxPeditor->SetGlobal(kFALSE);
1212  fxRooteditor->SetEditable(kFALSE); // back to window manager as root window
1213  }
1214 #endif
1215 }
1216 
1218 {
1219 #ifndef __NOGO4GED__
1220  TGedEditor* ed = dynamic_cast<TGedEditor*>(fxPeditor);
1221  if ((ed != 0) && isEditorVisible() && fxRooteditor)
1223 #endif
1224 }
1225 
1226 
1227 void QRootCanvas::activateEditor(TPad *pad, TObject *obj)
1228 {
1229 #ifndef __NOGO4GED__
1230  TGedEditor* ed = dynamic_cast<TGedEditor*>(fxPeditor);
1231  if ((ed != 0) && (obj != 0) && isEditorVisible()) {
1232  gTQSender = getCanvas();
1233  ed->SetModel(pad, obj, kButton1Down);
1234  }
1235 #endif
1236 }
1237 
1239 {
1240 #ifndef __NOGO4GED__
1241 // std::cout << "QRootCanvas::CleanupGedEditor()" << std::endl;
1242  TGedEditor* ed = dynamic_cast<TGedEditor*>(fxPeditor);
1243  if (!ed) return;
1244  if (fDummyHisto == 0) {
1245  fDummyHisto = new TH1I("dummyhisto", "dummyhisto", 100, -10., 10.);
1246  fDummyHisto->FillRandom("gaus", 1000);
1247  fDummyHisto->SetDirectory(0);
1248  fDummyHisto->SetBit(kCanDelete, kFALSE);
1249  }
1250  gTQSender = getCanvas();
1251  ed->SetModel(0, fDummyHisto, kButton1Down);
1252  ed->SetModel(0, getCanvas(), kButton1Down);
1253 #endif
1254 }
1255 
1256 
1258 {
1259  if (fStatusBar) fStatusBar->showMessage(msg);
1260 }
1261 
1263 {
1264  return fStatusBar ? fStatusBar->isVisible() : false;
1265 }
1266 
1268 {
1269  if (!fStatusBar) return;
1270 
1271  setShowEventStatus(flag);
1272  fStatusBar->setVisible(flag);
1273 }
1274 
1275 
1276 // JAM2019 test order of creation for ged parent window in qt4:
1278 {
1279  if (!fxRooteditor) {
1280  fxRooteditor = new QRootWindow(fEditorFrame, "rootwrapperwindow");
1281  QVBoxLayout* gedlayout = new QVBoxLayout(fEditorFrame);
1282  gedlayout->setContentsMargins(0, 0, 0, 0);
1283  gedlayout->addWidget(fxRooteditor);
1284  }
1285 }
void SetBatch(Bool_t batch=kTRUE)
Bool_t IsRetained()
double scaledPosition(int p)
Definition: QRootCanvas.h:201
QRootWindow * fxRooteditor
Definition: QRootCanvas.h:223
void showStatusMessage(const char *msg)
Option_t * GetSelectedOpt()
Size_t GetYsizeUser()
void Iconify()
virtual void mouseDoubleClickEvent(QMouseEvent *e)
void Modified(Bool_t=1)
Int_t GetWindowTopX()
bool isStatusBarVisible()
virtual void Draw(Option_t *option="")
virtual void Size(Float_t xsizeuser=0, Float_t ysizeuser=0)
void SetRetained(Bool_t retained=kTRUE)
TVirtualPad * GetSelectedPad()
virtual void paintEvent(QPaintEvent *e)
void activateRepaint(int act)
virtual void dropEvent(QDropEvent *Event)
TObject * fMenuObj
Definition: QRootCanvas.h:233
Bool_t IsBatch()
TList * fMenuMethods
Definition: QRootCanvas.h:234
void MenuCommandExecuted(TObject *, const char *)
void CanvasLeaveEvent()
virtual void HandleInput(EEventType button, Int_t x, Int_t y)
void SelectedPadChanged(TPad *)
double ScaledHeight()
Int_t GetEventY()
virtual void ToggleEventStatus()
Bool_t OpaqueResizing()
virtual void ToggleAutoExec()
void FeedbackMode(Bool_t set)
void SetCanvasSize(UInt_t ww, UInt_t wh)
void EnterLeave(TPad *prevSelPad, TObject *prevSelObj)
void cleanupEditor()
void SetTitle(const char *title="")
void PadClicked(TPad *)
Int_t GetWindowTopY()
double ScaledWidth()
Int_t GetEventX()
void CanvasUpdated()
Int_t GetEvent()
virtual void Browse(TBrowser *b)
void SetEditable(bool on=true)
UInt_t GetWh()
int fRepaintMode
Definition: QRootCanvas.h:219
virtual TObject * DrawClone(Option_t *option="")
QRootCanvas(QWidget *parent=0)
Definition: QRootCanvas.cpp:66
Bool_t GetAutoExec()
virtual void SetDoubleBuffer(Int_t mode=1)
void SaveSource(const char *filename="", Option_t *option="")
bool fMaskDoubleClick
Definition: QRootCanvas.h:229
double fMousePosX
Definition: QRootCanvas.h:230
TObject * GetSelected()
void methodDialog(TObject *object, TMethod *method)
Int_t GetCanvasID()
QAction * addMenuAction(QMenu *menu, QSignalMapper *map, const QString &text, int id)
Bool_t OpaqueMoving()
virtual void SetCursor(ECursor cursor)
double fMousePosY
Definition: QRootCanvas.h:231
QFrame * fEditorFrame
Definition: QRootCanvas.h:221
Color_t GetHighLightColor()
void ResizeOpaque(Int_t set=1)
TCanvas * getCanvas()
Definition: QRootCanvas.h:67
TH1 * fDummyHisto
Definition: QRootCanvas.h:224
void cd(Int_t subpadnumber=0)
void ForceUpdate()
void setShowEventStatus(bool s)
void resizeEditor()
TContextMenu * GetContextMenu()
virtual void mouseReleaseEvent(QMouseEvent *e)
void SetHighLightColor(Color_t col)
void SetSelected(TObject *obj)
virtual void mousePressEvent(QMouseEvent *e)
void SetResizeOnPaint(bool on=true)
Definition: QRootWindow.h:52
void toggleEditor()
bool fxShowEventStatus
Definition: QRootCanvas.h:235
void Clear(Option_t *option="")
virtual void leaveEvent(QEvent *e)
virtual TObject * DrawClonePad()
virtual void resizeEvent(QResizeEvent *e)
void Close(Option_t *option="")
Int_t GetDoubleBuffer()
void CanvasDropEvent(QDropEvent *, TPad *)
static bool IsRootCanvasMenuEnabled()
QString getArg(int n)
Definition: QRootDialog.cpp:77
QTimer * fRepaintTimer
Definition: QRootCanvas.h:218
void addArg(const char *argname, const char *value, const char *type)
Definition: QRootDialog.cpp:63
virtual void GetCanvasPar(Int_t &wtopx, Int_t &wtopy, UInt_t &ww, UInt_t &wh)
QStatusBar * fStatusBar
Definition: QRootCanvas.h:226
virtual void Paint(Option_t *option="")
virtual TPad * Pick(Int_t px, Int_t py, TObjLink *&pickobj)
virtual void Resize(Option_t *option="")
TVirtualPad * GetPadSave()
bool isEditorVisible()
bool isEditorAllowed()
virtual void dragEnterEvent(QDragEnterEvent *e)
void SetWindowSize(UInt_t ww, UInt_t wh)
const char * GetDISPLAY()
bool showEventStatus() const
Bool_t HasMenuBar()
Size_t GetXsizeUser()
virtual void EditorBar()
QPoint scaledMousePoint(QMouseEvent *ev)
TCanvas * fCanvas
Definition: QRootCanvas.h:215
void processRepaintTimer()
void UseCurrentStyle()
virtual void closeEvent(QCloseEvent *e)
double fQtScalingfactor
Definition: QRootCanvas.h:237
UInt_t GetWindowHeight()
virtual void mouseMoveEvent(QMouseEvent *e)
void MoveOpaque(Int_t set=1)
UInt_t GetWw()
void buildEditorWindow()
Size_t GetYsizeReal()
virtual void ls(Option_t *option="")
void CanvasStatusEvent(const char *)
Size_t GetXsizeReal()
void SetWindowPosition(Int_t x, Int_t y)
void SetSelectedPad(TPad *pad)
TVirtualPadEditor * fxPeditor
Definition: QRootCanvas.h:222
void activateEditor(TPad *pad, TObject *obj)
void setStatusBarVisible(bool flag)
void executeMenu(int id)
virtual void wheelEvent(QWheelEvent *e)
void PadDoubleClicked(TPad *)
virtual ~QRootCanvas()
Bool_t GetShowEventStatus()
UInt_t GetWindowWidth()
Int_t fRootWindowId
Definition: QRootCanvas.h:216
string msg
Definition: go4init.py:11
virtual void Update()