Geant4  10.01.p03
G4OpenGLQtViewer.cc
Go to the documentation of this file.
1 //
2 // ********************************************************************
3 // * License and Disclaimer *
4 // * *
5 // * The Geant4 software is copyright of the Copyright Holders of *
6 // * the Geant4 Collaboration. It is provided under the terms and *
7 // * conditions of the Geant4 Software License, included in the file *
8 // * LICENSE and available at http://cern.ch/geant4/license . These *
9 // * include a list of copyright holders. *
10 // * *
11 // * Neither the authors of this software system, nor their employing *
12 // * institutes,nor the agencies providing financial support for this *
13 // * work make any representation or warranty, express or implied, *
14 // * regarding this software system or assume any liability for its *
15 // * use. Please see the license in the file LICENSE and URL above *
16 // * for the full disclaimer and the limitation of liability. *
17 // * *
18 // * This code implementation is the result of the scientific and *
19 // * technical work of the GEANT4 collaboration. *
20 // * By using, copying, modifying or distributing the software (or *
21 // * any work based on the software) you agree to acknowledge its *
22 // * use in resulting scientific publications, and indicate your *
23 // * acceptance of all terms of the Geant4 Software license. *
24 // ********************************************************************
25 //
26 //
27 // $Id: G4OpenGLQtViewer.cc 87164 2014-11-26 08:48:31Z gcosmo $
28 //
29 //
30 // G4OpenGLQtViewer : Class to provide Qt specific
31 // functionality for OpenGL in GEANT4
32 //
33 // 27/06/2003 : G.Barrand : implementation (at last !).
34 // 30/06/2014 : M.Kelsey : Change QPixmap objects to pointers
35 
36 #ifdef G4VIS_BUILD_OPENGLQT_DRIVER
37 
38 #include "G4OpenGLQtViewer.hh"
39 
40 #include "G4OpenGLSceneHandler.hh"
41 #include "G4VSolid.hh"
43 #include "G4OpenGLQtMovieDialog.hh"
44 #include "G4Qt.hh"
45 #include "G4UIQt.hh"
46 #include "G4UImanager.hh"
47 #include "G4UIcommandTree.hh"
48 #include "G4LogicalVolumeStore.hh"
49 #include "G4PhysicalVolumeStore.hh"
51 #include "G4PhysicalVolumeModel.hh"
52 #include "G4Text.hh"
53 #include "G4UnitsTable.hh"
55 
56 #include <CLHEP/Units/SystemOfUnits.h>
57 
58 #include <typeinfo>
59 
60 #include <qlayout.h>
61 #include <qlabel.h>
62 #include <qdialog.h>
63 #include <qpushbutton.h>
64 #include <qprocess.h>
65 #include <qdesktopwidget.h>
66 
67 #include <qmenu.h>
68 #include <qimagewriter.h>
69 
70 #include <qtextedit.h>
71 #include <qtreewidget.h>
72 #include <qapplication.h>
73 #include <qmessagebox.h>
74 #include <qfiledialog.h>
75 #include <qprinter.h>
76 #include <qdatetime.h>
77 #include <qpainter.h>
78 #include <qgl.h> // include <qglwidget.h>
79 #include <qdialog.h>
80 #include <qcolordialog.h>
81 #include <qevent.h> //include <qcontextmenuevent.h>
82 #include <qobject.h>
83 #include <qgroupbox.h>
84 #include <qcombobox.h>
85 #include <qlineedit.h>
86 #include <qsignalmapper.h>
87 #include <qmainwindow.h>
88 #include <qtablewidget.h>
89 #include <qheaderview.h>
90 #include <qscrollarea.h>
91 #include <qsplitter.h>
92 #include <qcheckbox.h>
93 #include <qcursor.h>
94 
96 void G4OpenGLQtViewer::CreateMainWindow (
97  QGLWidget* glWidget
98  ,const QString& name
99 )
100 {
103 
104  if(fGLWidget) return; //Done.
105 
106  fGLWidget = glWidget ;
107  // fGLWidget->makeCurrent();
108 
109  G4Qt* interactorManager = G4Qt::getInstance ();
110 
111  ResizeWindow(fVP.GetWindowSizeHintX(),fVP.GetWindowSizeHintY());
112 
113  // FIXME L.Garnier 9/11/09 Has to be check !!!
114  // Qt UI with Qt Vis
115  // Qt UI with X Vis
116  // X UI with Qt Vis
117  // X UI with X Vis
118  // Ne marche pas avec un UIBatch !! (ecran blanc)
119 
120  // return false if G4UIQt was not launch
121 
123  if (UI == NULL) return;
124 
125  if (! static_cast<G4UIQt*> (UI->GetG4UIWindow())) {
126  // NO UI, should be batch mode
127  fBatchMode = true;
128  return;
129  }
130  fUiQt = static_cast<G4UIQt*> (UI->GetG4UIWindow());
131 
132  bool isTabbedView = false;
133  if ( fUiQt) {
134  if (!fBatchMode) {
135  if (!interactorManager->IsExternalApp()) {
136  // INIT size
137  fWinSize_x = fVP.GetWindowSizeHintX();
138  fWinSize_y = fVP.GetWindowSizeHintY();
139 
140  isTabbedView = fUiQt->AddTabWidget((QWidget*)fGLWidget,name);
141  }
142  fUISceneTreeComponentsTBWidget = fUiQt->GetSceneTreeComponentsTBWidget();
143 
144  // activate scene tree
145  fUiQt->GetViewersWidget()->setCurrentWidget(fUISceneTreeComponentsTBWidget);
146 
147  // initialize scene tree / viewer properties / picking
148  fSceneTreeWidget = new QWidget();
149  QVBoxLayout* layoutSceneTree = new QVBoxLayout();
150  fSceneTreeWidget->setStyleSheet ("padding: 0px ");
151 
152  fSceneTreeWidget->setLayout(layoutSceneTree);
153  fSceneTreeWidget->layout()->setContentsMargins(5,5,5,5);
154 
155  if (fUISceneTreeComponentsTBWidget != NULL) {
156  fUISceneTreeComponentsTBWidget->addTab(fSceneTreeWidget,QString(GetName().data()));
157  }
158 
159  // not available for Immediate mode
160  if (dynamic_cast<G4OpenGLStoredQtViewer*> (this)) {
161  initSceneTreeComponent();
162  toggleSceneTreeViewerInfos();
163  }
164 
165  initViewerPropertiesComponent();
166  initPickingComponent();
167 
168  // activate them
169  toggleSceneTreeComponentTreeWidgetInfos();
170  }
171  }
172 #ifdef G4DEBUG_VIS_OGL
173  else {
174  printf("G4OpenGLQtViewer::CreateMainWindow :: UIQt NOt found \n");
175  }
176 #endif
177 
178  if (!isTabbedView) { // we have to do a dialog
179 
180  QWidget *glDialogWidget = getParentWidget();
181 #ifdef G4DEBUG_VIS_OGL
182  printf("G4OpenGLQtViewer::CreateMainWindow :: getParent OK \n");
183 #endif
184  if (glDialogWidget != NULL) {
185  glWidget->setParent(glDialogWidget);
186  }
187  QHBoxLayout *mainLayout = new QHBoxLayout();
188 
189  mainLayout->setMargin(0);
190  mainLayout->setSpacing(0);
191  mainLayout->addWidget(fGLWidget);
192  if (fGLWidget->inherits("QMainWindow")) {
193  fGLWidget->setWindowTitle( name);
194  }
195  glDialogWidget->setLayout(mainLayout);
196 
197 
198  //useful for MACOSX, we have to compt the menuBar height
199  int offset = QApplication::desktop()->height()
200  - QApplication::desktop()->availableGeometry().height();
201 
202  G4int YPos= fVP.GetWindowAbsoluteLocationHintY(QApplication::desktop()->height());
203  if (fVP.GetWindowAbsoluteLocationHintY(QApplication::desktop()->height())< offset) {
204  YPos = offset;
205  }
206  glDialogWidget->resize(getWinWidth(), getWinHeight());
207 #ifdef G4DEBUG_VIS_OGL
208  printf("G4OpenGLQtViewer::CreateMainWindow :: resizing to %d %d \n",getWinWidth(), getWinHeight());
209 #endif
210  glDialogWidget->move(fVP.GetWindowAbsoluteLocationHintX(QApplication::desktop()->width()),YPos);
211  glDialogWidget->show();
212  }
213 
214  if(!fGLWidget) return;
215 
216  if (!fContextMenu)
217  createPopupMenu();
218 
219 }
220 
221 
223 G4OpenGLQtViewer::G4OpenGLQtViewer (
224  G4OpenGLSceneHandler& scene
225 )
226  :G4VViewer (scene, -1)
227  ,G4OpenGLViewer (scene)
228  ,fGLWidget(NULL)
229  ,fRecordFrameNumber(0)
230  ,fContextMenu(0)
231  ,fDeltaDepth(0.01)
232  ,fDeltaZoom(0.05)
233  ,fHoldKeyEvent(false)
234  ,fHoldMoveEvent(false)
235  ,fHoldRotateEvent(false)
236  ,fAutoMove(false)
237  ,fEncoderPath("")
238  ,fTempFolderPath("")
239  ,fMovieTempFolderPath("")
240  ,fSaveFileName("")
241  ,fParameterFileName("ppmtompeg_encode_parameter_file.par")
242  ,fMovieParametersDialog(NULL)
243  ,fRecordingStep(WAIT)
244  ,fProcess(NULL)
245  ,fNbMaxFramesPerSec(100)
246  ,fNbMaxAnglePerSec(360)
247  ,fLaunchSpinDelay(100)
248  ,fUISceneTreeComponentsTBWidget(NULL)
249  ,fNoKeyPress(true)
250  ,fAltKeyPress(false)
251  ,fControlKeyPress(false)
252  ,fShiftKeyPress(false)
253  ,fBatchMode(false)
254  ,fCheckSceneTreeComponentSignalLock(false)
255  ,fSceneTreeComponentTreeWidget(NULL)
256  ,fOldSceneTreeComponentTreeWidget(NULL)
257  ,fSceneTreeWidget(NULL)
258  ,fPVRootNodeCreate(false)
259  ,fFilterOutput(NULL)
260  ,fViewerPropertiesButton(NULL)
261  ,fNbRotation(0)
262  ,fTimeRotation(0)
263  ,fTouchableVolumes("Touchables")
264  ,fShortcutsDialog(NULL)
265  ,fSceneTreeComponentTreeWidgetInfos(NULL)
266  ,fSceneTreeComponentPickingInfos(NULL)
267  ,fSceneTreeComponentPickingScrollArea(NULL)
268  ,fTreeWidgetInfosIgnoredCommands(0)
269  ,fSceneTreeDepthSlider(NULL)
270  ,fSceneTreeDepth(1)
271  ,fModelShortNameItem(NULL)
272  ,fMaxPOindexInserted(-1)
273  ,fUiQt(NULL)
274  ,fSignalMapperMouse(NULL)
275  ,fSignalMapperSurface(NULL)
276  ,fSignalMapperPicking(NULL)
277  ,fTreeIconOpen(NULL)
278  ,fTreeIconClosed(NULL)
279  ,fLastExportSliderValue(80)
280  ,fLastHighlightColor(G4Color(0,0,0,0))
281  ,fLastHighlightName(0)
282  ,fIsDeleting(false)
283 {
284 
285  // launch Qt if not
286  if (QCoreApplication::instance () == NULL) {
287  fBatchMode = true;
288  }
289  G4Qt::getInstance ();
290 
291  fLastPos3 = QPoint(-1,-1);
292  fLastPos2 = QPoint(-1,-1);
293  fLastPos1 = QPoint(-1,-1);
294 
295  initMovieParameters();
296 
297  fLastEventTime = new QTime();
298  fSignalMapperMouse = new QSignalMapper(this);
299  fSignalMapperSurface = new QSignalMapper(this);
300 
301  // Set default path and format
302  fFileSavePath = QDir::currentPath();
303 
304  // add available export format
305  QList<QByteArray> formats = QImageWriter::supportedImageFormats ();
306  for (int i = 0; i < formats.size(); ++i) {
307  addExportImageFormat(formats.at(i).data());
308  }
309 
310  const char * const icon1[]={
311  /* columns rows colors chars-per-pixel */
312  "20 20 34 1",
313  " c None",
314  ". c #7C7C7C7C7C7C",
315  "X c #7D7D7D7D7D7D",
316  "o c #828282828282",
317  "O c #838383838383",
318  "+ c #848484848484",
319  "@ c #858585858585",
320  "# c #878787878787",
321  "$ c #888888888888",
322  "% c #8B8B8B8B8B8B",
323  "& c #8C8C8C8C8C8C",
324  "* c #8F8F8F8F8F8F",
325  "= c #909090909090",
326  "- c #919191919191",
327  "; c #999999999999",
328  ": c #9D9D9D9D9D9D",
329  "> c #A2A2A2A2A2A2",
330  ", c #A3A3A3A3A3A3",
331  "< c #A5A5A5A5A5A5",
332  "1 c #A6A6A6A6A6A6",
333  "2 c #B3B3B3B3B3B3",
334  "3 c #B6B6B6B6B6B6",
335  "4 c #C2C2C2C2C2C2",
336  "5 c #C6C6C6C6C6C6",
337  "6 c #CACACACACACA",
338  "7 c #CFCFCFCFCFCF",
339  "8 c #D0D0D0D0D0D0",
340  "9 c #D4D4D4D4D4D4",
341  "0 c #D7D7D7D7D7D7",
342  "q c #DEDEDEDEDEDE",
343  "w c #E0E0E0E0E0E0",
344  "e c #E7E7E7E7E7E7",
345  "r c #F4F4F4F4F4F4",
346  "t c #F7F7F7F7F7F7",
347  " ",
348  " ",
349  " ",
350  " ",
351  " ",
352  " ",
353  " =========> ",
354  " 7&X+++Oo<e ",
355  " 2o+@@+-8 ",
356  " w;.#@+3 ",
357  " 4$o@:q ",
358  " r1X%5 ",
359  " 9*,t ",
360  " 60 ",
361  " ",
362  " ",
363  " ",
364  " ",
365  " ",
366  " "
367  };
368  const char * const icon2[]={
369  "20 20 68 1",
370  " c None",
371  ". c #5F5F10102323",
372  "X c #40405F5F1010",
373  "o c #696963632E2E",
374  "O c #101019194C4C",
375  "+ c #101023237070",
376  "@ c #70702D2D6363",
377  "# c #73732D2D6464",
378  "$ c #79792E2E6767",
379  "% c #19194C4C5353",
380  "& c #2D2D63636161",
381  "* c #2E2E61617070",
382  "= c #6F6F6E6E4343",
383  "- c #707065655F5F",
384  "; c #727279795454",
385  ": c #535341417070",
386  "> c #797954547979",
387  ", c #434361617474",
388  "< c #414170707070",
389  "1 c #686869696363",
390  "2 c #6C6C69696363",
391  "3 c #656567676F6F",
392  "4 c #69696F6F6E6E",
393  "5 c #747465656767",
394  "6 c #757562626C6C",
395  "7 c #70706C6C6969",
396  "8 c #616174746565",
397  "9 c #656573736969",
398  "0 c #616174746969",
399  "q c #707075756262",
400  "w c #797970706565",
401  "e c #636361617474",
402  "r c #67676F6F7272",
403  "t c #727261617070",
404  "y c #616170707070",
405  "u c #6F6F72727979",
406  "i c #67676E6ED1D1",
407  "p c #808080808080",
408  "a c #828282828282",
409  "s c #838383838383",
410  "d c #848484848484",
411  "f c #858585858585",
412  "g c #868686868686",
413  "h c #888888888888",
414  "j c #8A8A8A8A8A8A",
415  "k c #8D8D8D8D8D8D",
416  "l c #8F8F8F8F8F8F",
417  "z c #909090909090",
418  "x c #949494949494",
419  "c c #9C9C9C9C9C9C",
420  "v c #9F9F9F9F9F9F",
421  "b c #A2A2A2A2A2A2",
422  "n c #AEAEAEAEAEAE",
423  "m c #B7B7B7B7B7B7",
424  "M c #C7C7C7C7C7C7",
425  "N c #C9C9C9C9C9C9",
426  "B c #D1D1D1D1D1D1",
427  "V c #D4D4D4D4D4D4",
428  "C c #D9D9D9D9D9D9",
429  "Z c #E0E0E0E0E0E0",
430  "A c #E2E2E2E2E2E2",
431  "S c #EEEEEEEEEEEE",
432  "D c #F0F0F0F0F0F0",
433  "F c #F5F5F5F5F5F5",
434  "G c #F6F6F6F6F6F6",
435  "H c #F9F9F9F9F9F9",
436  "J c #FCFCFCFCFCFC",
437  "K c #FDFDFDFDFDFD",
438  " ",
439  " ",
440  " ",
441  " ",
442  " ",
443  " bC ",
444  " zjnD ",
445  " ldjjMK ",
446  " zdhdjcA ",
447  " zddhdddVK ",
448  " zghdalBH ",
449  " zghamSK ",
450  " lubZH ",
451  " xMF ",
452  " G ",
453  " ",
454  " ",
455  " ",
456  " ",
457  " ",
458 
459  };
460 
461  const char * const search[] = {
462  /* columns rows colors chars-per-pixel */
463  "19 19 8 1",
464  " c #5C5C5C",
465  ". c #7D7D7D",
466  "X c #9B9B9B",
467  "o c #C3C3C3",
468  "O c None",
469  "+ c #000000",
470  "@ c #000000",
471  "# c None",
472  /* pixels */
473  "OOOOOOOOOOOOOOOOOOO",
474  "OOOOOOOOOOOOOOOOOOO",
475  "OOOOOOOo. .oOOOOOO",
476  "OOOOOOX XOOOOO",
477  "OOOOOo XOOX oOOOO",
478  "OOOOO. XOOOOX .OOOO",
479  "OOOOO OOOOOO OOOO",
480  "OOOOO OOOOOO OOOO",
481  "OOOOO. XOOOOo .OOOO",
482  "OOOOOo oOOo oOOOO",
483  "OOOOOOX XOOOO",
484  "OOOOOOOo. . XOOO",
485  "OOOOOOOOOOOOO. XOO",
486  "OOOOOOOOOOOOOO. XOO",
487  "OOOOOOOOOOOOOOOoOOO",
488  "OOOOOOOOOOOOOOOOOOO",
489  "OOOOOOOOOOOOOOOOOOO",
490  "OOOOOOOOOOOOOOOOOOO",
491  "OOOOOOOOOOOOOOOOOOO"
492  };
493 
494  fSearchIcon = new QPixmap(search);
495  fTreeIconOpen = new QPixmap(icon1);
496  fTreeIconClosed = new QPixmap(icon2);
497 
498 #ifdef G4DEBUG_VIS_OGL
499  printf("G4OpenGLQtViewer::G4OpenGLQtViewer END\n");
500 #endif
501 }
502 
504 G4OpenGLQtViewer::~G4OpenGLQtViewer (
505 )
506 {
509  fIsDeleting = true;
510 
511  // remove scene tree from layout
512  // Delete all the existing buttons in the layout
513  QLayoutItem *wItem;
514  if (fSceneTreeWidget != NULL) {
515  if (fSceneTreeWidget->layout() != NULL) {
516  while ((wItem = fSceneTreeWidget->layout()->takeAt(0)) != 0) {
517  delete wItem->widget();
518  delete wItem;
519  }
520  }
521  if (fUISceneTreeComponentsTBWidget != NULL) {
522  fUISceneTreeComponentsTBWidget->removeTab(fUISceneTreeComponentsTBWidget->indexOf(fSceneTreeWidget));
523  }
524  }
525 
526  // Delete the open/close icons
527  delete fTreeIconOpen;
528  delete fTreeIconClosed;
529 
530  G4cout <<removeTempFolder().toStdString().c_str() <<G4endl;
531 }
532 
533 
534 //
535 // Create a popup menu for the widget. This menu is activated by right-mouse click
536 //
537 void G4OpenGLQtViewer::createPopupMenu() {
538 
539  fContextMenu = new QMenu("All");
540 
541  QMenu *mMouseAction = fContextMenu->addMenu("&Mouse actions");
542 
543  fMouseRotateAction = mMouseAction->addAction("Rotate", fSignalMapperMouse, SLOT(map()));
544  fMouseMoveAction = mMouseAction->addAction("Move", fSignalMapperMouse, SLOT(map()));
545  fMousePickAction = mMouseAction->addAction("Pick", fSignalMapperMouse, SLOT(map()));
546  fMouseZoomOutAction = mMouseAction->addAction("Zoom out", fSignalMapperMouse, SLOT(map()));
547  fMouseZoomInAction = mMouseAction->addAction("Zoom in", fSignalMapperMouse, SLOT(map()));
548  QAction *shortcutsAction = mMouseAction->addAction("Show shortcuts");
549 
550  fMouseRotateAction->setCheckable(true);
551  fMouseMoveAction->setCheckable(true);
552  fMousePickAction->setCheckable(true);
553  fMouseZoomOutAction->setCheckable(true);
554  fMouseZoomInAction->setCheckable(true);
555  shortcutsAction->setCheckable(false);
556 
557  connect(fSignalMapperMouse, SIGNAL(mapped(int)),this, SLOT(toggleMouseAction(int)));
558  fSignalMapperMouse->setMapping(fMouseRotateAction,1);
559  fSignalMapperMouse->setMapping(fMouseMoveAction,2);
560  fSignalMapperMouse->setMapping(fMousePickAction,3);
561  fSignalMapperMouse->setMapping(fMouseZoomOutAction,4);
562  fSignalMapperMouse->setMapping(fMouseZoomInAction,5);
563 
564  QObject::connect(shortcutsAction,
565  SIGNAL(triggered(bool)),
566  this,
567  SLOT(showShortcuts()));
568 
569  // === Style Menu ===
570  QMenu *mStyle = fContextMenu->addMenu("&Style");
571 
572  QMenu *mProjection = mStyle->addMenu("&Projection");
573 
574  fProjectionOrtho = mProjection->addAction("Orthographic", fSignalMapperSurface, SLOT(map()));
575  fProjectionPerspective = mProjection->addAction("Persepective", fSignalMapperSurface, SLOT(map()));
576 
577  // INIT mProjection
578  if (fVP.GetFieldHalfAngle() == 0) {
579  createRadioAction(fProjectionOrtho, fProjectionPerspective,SLOT(toggleProjection(bool)),1);
580  } else {
581  createRadioAction(fProjectionOrtho, fProjectionPerspective,SLOT(toggleProjection(bool)),2);
582  }
583 
584  // === Drawing Menu ===
585  QMenu *mDrawing = mStyle->addMenu("&Drawing");
586 
587  fDrawingWireframe = mDrawing->addAction("Wireframe", fSignalMapperSurface, SLOT(map()));
588 
589  fDrawingLineRemoval = mDrawing->addAction("Hidden line removal", fSignalMapperSurface, SLOT(map()));
590 
591  fDrawingSurfaceRemoval = mDrawing->addAction("Hidden Surface removal", fSignalMapperSurface, SLOT(map()));
592 
593  fDrawingLineSurfaceRemoval = mDrawing->addAction("Hidden line and surface removal", fSignalMapperSurface, SLOT(map()));
594 
595  fDrawingWireframe->setCheckable(true);
596  fDrawingLineRemoval->setCheckable(true);
597  fDrawingSurfaceRemoval->setCheckable(true);
598  fDrawingLineSurfaceRemoval->setCheckable(true);
599 
600  connect(fSignalMapperSurface, SIGNAL(mapped(int)),this, SLOT(toggleSurfaceAction(int)));
601  fSignalMapperSurface->setMapping(fDrawingWireframe,1);
602  fSignalMapperSurface->setMapping(fDrawingLineRemoval,2);
603  fSignalMapperSurface->setMapping(fDrawingSurfaceRemoval,3);
604  fSignalMapperSurface->setMapping(fDrawingLineSurfaceRemoval,4);
605 
606 
607  // Background Color
608 
609  QAction *backgroundColorChooser ;
610  // === Action Menu ===
611  backgroundColorChooser = mStyle->addAction("Background color");
612  QObject ::connect(backgroundColorChooser,
613  SIGNAL(triggered()),
614  this,
615  SLOT(actionChangeBackgroundColor()));
616 
617  // Text Color
618 
619  QAction *textColorChooser ;
620  // === Action Menu ===
621  textColorChooser = mStyle->addAction("Text color");
622  QObject ::connect(textColorChooser,
623  SIGNAL(triggered()),
624  this,
625  SLOT(actionChangeTextColor()));
626 
627  // Default Color
628 
629  QAction *defaultColorChooser ;
630  // === Action Menu ===
631  defaultColorChooser = mStyle->addAction("Default color");
632  QObject ::connect(defaultColorChooser,
633  SIGNAL(triggered()),
634  this,
635  SLOT(actionChangeDefaultColor()));
636 
637 
638  // === Action Menu ===
639  QMenu *mActions = fContextMenu->addMenu("&Actions");
640  QAction *createEPS = mActions->addAction("Save as ...");
641  QObject ::connect(createEPS,
642  SIGNAL(triggered()),
643  this,
644  SLOT(actionSaveImage()));
645 
646  // === Action Menu ===
647  QAction *movieParameters = mActions->addAction("Save as movie...");
648  QObject ::connect(movieParameters,
649  SIGNAL(triggered()),
650  this,
651  SLOT(actionMovieParameters()));
652 
653 
654 
655 
656  // === Special Menu ===
657  QMenu *mSpecial = fContextMenu->addMenu("S&pecial");
658  QMenu *mTransparency = mSpecial->addMenu("Transparency");
659  QAction *transparencyOn = mTransparency->addAction("On");
660  QAction *transparencyOff = mTransparency->addAction("Off");
661 
662  if (transparency_enabled == false) {
663  createRadioAction(transparencyOn,transparencyOff,SLOT(toggleTransparency(bool)),2);
664  } else if (transparency_enabled == true) {
665  createRadioAction(transparencyOn,transparencyOff,SLOT(toggleTransparency(bool)),1);
666  } else {
667  mSpecial->clear();
668  }
669 
670 
671  QMenu *mAntialiasing = mSpecial->addMenu("Antialiasing");
672  QAction *antialiasingOn = mAntialiasing->addAction("On");
673  QAction *antialiasingOff = mAntialiasing->addAction("Off");
674 
675  if (antialiasing_enabled == false) {
676  createRadioAction(antialiasingOn,antialiasingOff,SLOT(toggleAntialiasing(bool)),2);
677  } else if (antialiasing_enabled == true) {
678  createRadioAction(antialiasingOn,antialiasingOff,SLOT(toggleAntialiasing(bool)),1);
679  } else {
680  mAntialiasing->clear();
681  }
682 
683  QMenu *mHaloing = mSpecial->addMenu("Haloing");
684  QAction *haloingOn = mHaloing->addAction("On");
685  QAction *haloingOff = mHaloing->addAction("Off");
686  if (haloing_enabled == false) {
687  createRadioAction(haloingOn,haloingOff,SLOT(toggleHaloing(bool)),2);
688  } else if (haloing_enabled == true) {
689  createRadioAction(haloingOn,haloingOff,SLOT(toggleHaloing(bool)),1);
690  } else {
691  mHaloing->clear();
692  }
693 
694  QMenu *mAux = mSpecial->addMenu("Auxiliary edges");
695  QAction *auxOn = mAux->addAction("On");
696  QAction *auxOff = mAux->addAction("Off");
697  if (!fVP.IsAuxEdgeVisible()) {
698  createRadioAction(auxOn,auxOff,SLOT(toggleAux(bool)),2);
699  } else {
700  createRadioAction(auxOn,auxOff,SLOT(toggleAux(bool)),1);
701  }
702 
703 
704  QMenu *mHiddenMarkers = mSpecial->addMenu("Hidden markers");
705  QAction *hiddenMarkersOn = mHiddenMarkers->addAction("On");
706  QAction *hiddenMarkersOff = mHiddenMarkers->addAction("Off");
707  if (fVP.IsMarkerNotHidden()) {
708  createRadioAction(hiddenMarkersOn,hiddenMarkersOff,SLOT(toggleHiddenMarkers(bool)),2);
709  } else {
710  createRadioAction(hiddenMarkersOn,hiddenMarkersOff,SLOT(toggleHiddenMarkers(bool)),1);
711  }
712 
713 
714 
715  QMenu *mFullScreen = mSpecial->addMenu("&Full screen");
716  fFullScreenOn = mFullScreen->addAction("On");
717  fFullScreenOff = mFullScreen->addAction("Off");
718  createRadioAction(fFullScreenOn,fFullScreenOff,SLOT(toggleFullScreen(bool)),2);
719 
720  // INIT All
721  updateToolbarAndMouseContextMenu();
722 }
723 
724 void G4OpenGLQtViewer::G4manageContextMenuEvent(QContextMenuEvent *e)
725 {
726  if (!fGLWidget) {
727  G4cerr << "Visualization window not defined, please choose one before" << G4endl;
728  } else {
729 
730  if (!fContextMenu)
731  createPopupMenu();
732 
733  // launch menu
734  if ( fContextMenu ) {
735  fContextMenu->exec( e->globalPos() );
736  // delete fContextMenu;
737  }
738  }
739  e->accept();
740 }
741 
742 
751 void G4OpenGLQtViewer::createRadioAction(QAction *action1,QAction *action2, const std::string& method,unsigned int nCheck) {
752 
753  action1->setCheckable(true);
754  action2->setCheckable(true);
755 
756  if (nCheck ==1)
757  action1->setChecked (true);
758  else
759  action2->setChecked (true);
760 
761  QObject ::connect(action1, SIGNAL(triggered(bool)),action2, SLOT(toggle()));
762  QObject ::connect(action2, SIGNAL(triggered(bool)),action1, SLOT(toggle()));
763 
764  QObject ::connect(action1, SIGNAL(toggled(bool)),this, method.c_str());
765 
766 }
767 
768 
769 
773 void G4OpenGLQtViewer::showShortcuts() {
774  G4String text;
775 
776  text = "========= Mouse Shortcuts =========\n";
777  if (fUiQt != NULL) {
778  if (fUiQt->IsIconRotateSelected()) { // rotate
779  text += "Click and move mouse to rotate volume \n";
780  text += "ALT + Click and move mouse to rotate volume (Toggle View/Theta-Phi Direction) \n";
781  text += "CTRL + Click and move mouse to zoom in/out \n";
782  text += "SHIFT + Click and move mouse to change camera point of view \n";
783  } else if (fUiQt->IsIconMoveSelected()) { //move
784  text += "Move camera point of view with mouse \n";
785  } else if (fUiQt->IsIconPickSelected()) { //pick
786  text += "Click and pick \n";
787  }
788  } else {
789  text += "Click and move mouse to rotate volume \n";
790  text += "ALT + Click and move mouse to rotate volume (Toggle View/Theta-Phi Direction) \n";
791  text += "CTRL + Click and zoom mouse to zoom in/out \n";
792  text += "SHIFT + Click and zoommove camera point of view \n";
793  }
794  text += "========= Move Shortcuts ========= \n";
795  text += "Press left/right arrows to move volume left/right \n";
796  text += "Press up/down arrows to move volume up/down \n";
797  text += "Press '+'/'-' to move volume toward/forward \n";
798  text += "\n";
799  text += "========= Rotation (Theta/Phi) Shortcuts ========= \n";
800  text += "Press SHIFT + left/right arrows to rotate volume left/right \n";
801  text += "Press SHIFT + up/down arrows to rotate volume up/down \n";
802  text += "\n";
803  text += "========= Rotation (View Direction) Shortcuts ========= \n";
804  text += "Press ALT + left/right to rotate volume around vertical direction \n";
805  text += "Press ALT + up/down to rotate volume around horizontal direction \n";
806  text += "\n";
807  text += "========= Zoom View ========= \n";
808  text += "Press CTRL + '+'/'-' to zoom into volume \n";
809  text += "\n";
810  text += "========= Misc ========= \n";
811  text += "Press ALT +/- to slow/speed rotation/move \n";
812  text += "Press H to reset view \n";
813  text += "Press Esc to exit FullScreen \n";
814  text += "\n";
815  text += "========= Video ========= \n";
816  text += "In video mode : \n";
817  text += " Press SPACE to Start/Pause video recording \n";
818  text += " Press RETURN to Stop video recording \n";
819  text += "\n";
820 
821  G4cout << text;
822 
823  if ( fShortcutsDialog == NULL) {
824  fShortcutsDialog = new QDialog();
825  fShortcutsDialogInfos = new QTextEdit() ;
826  QVBoxLayout *mainLayout = new QVBoxLayout;
827  mainLayout->addWidget(fShortcutsDialogInfos);
828  fShortcutsDialog->setLayout(mainLayout);
829  fShortcutsDialog->setWindowTitle(tr("Shortcuts"));
830  }
831 
832  fShortcutsDialogInfos->setPlainText(text.data());
833  fShortcutsDialog->show();
834 }
835 
836 
837 
844 void G4OpenGLQtViewer::toggleMouseAction(int aAction) {
845 
846  if (aAction == 1) {
847  fUiQt->SetIconRotateSelected();
848  } else if (aAction == 2) {
849  fUiQt->SetIconMoveSelected();
850  } else if (aAction == 3) {
851  togglePicking();
852  } else if (aAction == 4) {
853  fUiQt->SetIconZoomOutSelected();
854  } else if (aAction == 5) {
855  fUiQt->SetIconZoomInSelected();
856  }
857 
858  updateQWidget();
859  updateToolbarAndMouseContextMenu();
860 }
861 
862 
873 void G4OpenGLQtViewer::toggleSurfaceAction(int aAction) {
874 
876 
877  if (aAction ==1) {
878  d_style = G4ViewParameters::wireframe;
879 
880  } else if (aAction ==2) {
881  d_style = G4ViewParameters::hlr;
882 
883  } else if (aAction ==3) {
884  d_style = G4ViewParameters::hsr;
885 
886  } else if (aAction ==4) {
887  d_style = G4ViewParameters::hlhsr;
888  }
889  fVP.SetDrawingStyle(d_style);
890 
891  updateToolbarAndMouseContextMenu();
892  updateQWidget();
893 }
894 
895 
906 void G4OpenGLQtViewer::toggleProjection(bool check) {
907 
908  if (check == 1) {
909  fVP.SetOrthogonalProjection ();
910  } else {
911  fVP.SetPerspectiveProjection();
912  }
913  updateToolbarAndMouseContextMenu();
914  updateQWidget();
915 }
916 
917 
922 void G4OpenGLQtViewer::toggleTransparency(bool check) {
923 
924  if (check) {
925  transparency_enabled = true;
926  } else {
927  transparency_enabled = false;
928  }
929  SetNeedKernelVisit (true);
930  updateToolbarAndMouseContextMenu();
931  updateQWidget();
932 }
933 
938 void G4OpenGLQtViewer::toggleAntialiasing(bool check) {
939 
940  if (!check) {
941  antialiasing_enabled = false;
942  glDisable (GL_LINE_SMOOTH);
943  glDisable (GL_POLYGON_SMOOTH);
944  } else {
945  antialiasing_enabled = true;
946  glEnable (GL_LINE_SMOOTH);
947  glHint (GL_LINE_SMOOTH_HINT, GL_NICEST);
948  glEnable (GL_POLYGON_SMOOTH);
949  glHint (GL_POLYGON_SMOOTH_HINT, GL_NICEST);
950  }
951 
952  updateToolbarAndMouseContextMenu();
953  updateQWidget();
954 }
955 
960 //FIXME : I SEE NOTHING...
961 void G4OpenGLQtViewer::toggleHaloing(bool check) {
962  if (check) {
963  haloing_enabled = false;
964  } else {
965  haloing_enabled = true;
966  }
967 
968  updateToolbarAndMouseContextMenu();
969  updateQWidget();
970 
971 }
972 
977 void G4OpenGLQtViewer::toggleAux(bool check) {
978  if (check) {
979  fVP.SetAuxEdgeVisible(true);
980  } else {
981  fVP.SetAuxEdgeVisible(false);
982  }
983  SetNeedKernelVisit (true);
984  updateToolbarAndMouseContextMenu();
985  updateQWidget();
986 }
987 
988 
989 void G4OpenGLQtViewer::togglePicking() {
990  // FIXME : Not the good way to do, we should handle the multiple cases of Icon/ContextMenu and CheckBox in a better way
991  if (fUiQt) {
992  if (!fVP.IsPicking()) {
993  fUiQt->SetIconPickSelected();
994  } else {
995  fUiQt->SetIconRotateSelected();
996  }
997  }
998 
1000  if(UI != NULL) {
1001  if (!fVP.IsPicking()) {
1002  UI->ApplyCommand(std::string("/vis/viewer/set/picking true"));
1003  } else {
1004  UI->ApplyCommand(std::string("/vis/viewer/set/picking false"));
1005  }
1006  }
1007 
1008 }
1009 
1010 
1015 void G4OpenGLQtViewer::toggleHiddenMarkers(bool check) {
1016  if (check) {
1017  fVP.SetMarkerHidden();
1018  } else {
1019  fVP.SetMarkerNotHidden();
1020  }
1021  // SetNeedKernelVisit (true);
1022  updateToolbarAndMouseContextMenu();
1023  updateQWidget();
1024 }
1025 
1029 void G4OpenGLQtViewer::toggleFullScreen(bool check) {
1030  if (check != fGLWidget->isFullScreen()) { //toggle
1031  fGLWidget->setWindowState(fGLWidget->windowState() ^ Qt::WindowFullScreen);
1032  }
1033 }
1034 
1035 
1036 void G4OpenGLQtViewer::savePPMToTemp() {
1037  if (fMovieTempFolderPath == "") {
1038  return;
1039  }
1040  QGLWidget* qGLW = dynamic_cast<QGLWidget*> (fGLWidget) ;
1041  if (! qGLW) {
1042  return;
1043  }
1044  QString fileName ="Test"+QString::number(fRecordFrameNumber)+".ppm";
1045  QString filePath =fMovieTempFolderPath+fileName;
1046 
1047  QImage image;
1048  image = qGLW->grabFrameBuffer();
1049  bool res = false;
1050 
1051  res = image.save(filePath,0);
1052  if (res == false) {
1053  resetRecording();
1054  setRecordingInfos("Can't save tmp file "+filePath);
1055  return;
1056  }
1057 
1058  setRecordingInfos("File "+fileName+" saved");
1059  fRecordFrameNumber++;
1060 }
1061 
1062 
1063 
1064 void G4OpenGLQtViewer::actionSaveImage() {
1065  QString filters;
1066  for (unsigned int i = 0; i < fExportImageFormatVector.size(); ++i) {
1067  filters += QString("*.") + fExportImageFormatVector.at(i).c_str() + ";;";
1068  }
1069 
1070  QString* selectedFormat = new QString(fDefaultExportImageFormat.c_str());
1071  QString qFilename;
1072  qFilename = QFileDialog::getSaveFileName ( fGLWidget,
1073  tr("Save as ..."),
1074  fFileSavePath,
1075  filters,
1076  selectedFormat );
1077 
1078 
1079  std::string name = qFilename.toStdString().c_str();
1080 
1081  // bmp jpg jpeg png ppm xbm xpm
1082  if (name.empty()) {
1083  return;
1084  }
1085 
1086  fFileSavePath = QFileInfo(qFilename).path();
1087 
1088  std::string format = selectedFormat->toLower().toStdString().c_str();
1089 
1090  // set the format to current
1091  fExportImageFormat = format.substr(format.find_last_of(".") + 1);
1092 
1093  std::string filename = name;
1094  std::string extension = "";
1095  if (name.find_last_of(".") != std::string::npos) {
1096  filename = name.substr(0,name.find_last_of(".") + 1);
1097  extension = name.substr(name.find_last_of(".") + 1);
1098  } else {
1099  extension = fExportImageFormat;
1100  }
1101 
1102  filename+= "."+ extension;
1103 
1104  if (!setExportFilename(filename.c_str(),0)) {
1105  return;
1106  }
1107 
1108  G4OpenGLQtExportDialog* exportDialog= new G4OpenGLQtExportDialog(fGLWidget,format.c_str(),fGLWidget->height(),fGLWidget->width());
1109  if( exportDialog->exec()) {
1110 
1111  if ((exportDialog->getWidth() !=fGLWidget->width()) ||
1112  (exportDialog->getHeight() !=fGLWidget->height())) {
1113  setExportSize(exportDialog->getWidth(),exportDialog->getHeight());
1114 
1115  }
1116  if (fExportImageFormat == "eps") {
1117  fVectoredPs = exportDialog->getVectorEPS();
1118  } else if (fExportImageFormat == "ps") {
1119  fVectoredPs = true;
1120  }
1121  fLastExportSliderValue = exportDialog->getSliderValue();
1122 
1123  if (exportImage(filename + "." + fExportImageFormat)) {
1124  // set the default format to current
1125  fDefaultExportImageFormat = format;
1126  }
1127  } else { // cancel selected
1128  return;
1129  }
1130 
1131 }
1132 
1133 
1134 void G4OpenGLQtViewer::actionChangeBackgroundColor() {
1135 
1136  // //I need to revisit the kernel if the background colour changes and
1137  // //hidden line removal is enabled, because hlr drawing utilises the
1138  // //background colour in its drawing...
1139  // // (Note added by JA 13/9/2005) Background now handled in view
1140  // // parameters. A kernel visit is triggered on change of background.
1141 
1142 #if QT_VERSION < 0x040500
1143  bool a;
1144  const QColor color = QColor(QColorDialog::getRgba (QColor(Qt::black).rgba(),&a,fGLWidget));
1145 #else
1146  const QColor color =
1147  QColorDialog::getColor(Qt::black,
1148  fGLWidget,
1149  " Get background color and transparency",
1150  QColorDialog::ShowAlphaChannel);
1151 #endif
1152  if (color.isValid()) {
1153  G4Colour colour(((G4double)color.red())/255,
1154  ((G4double)color.green())/255,
1155  ((G4double)color.blue())/255,
1156  ((G4double)color.alpha())/255);
1157  fVP.SetBackgroundColour(colour);
1158 
1159  updateToolbarAndMouseContextMenu();
1160  updateQWidget();
1161  }
1162 }
1163 
1164 void G4OpenGLQtViewer::actionChangeTextColor() {
1165 
1166 #if QT_VERSION < 0x040500
1167  bool a;
1168  const QColor color = QColor(QColorDialog::getRgba (QColor(Qt::yellow).rgba(),&a,fGLWidget));
1169 #else
1170  const QColor& color =
1171  QColorDialog::getColor(Qt::yellow,
1172  fGLWidget,
1173  " Get text color and transparency",
1174  QColorDialog::ShowAlphaChannel);
1175 #endif
1176  if (color.isValid()) {
1177  G4Colour colour(((G4double)color.red())/255,
1178  ((G4double)color.green())/255,
1179  ((G4double)color.blue())/255,
1180  ((G4double)color.alpha())/255);
1181 
1182  fVP.SetDefaultTextColour(colour);
1183 
1184  updateToolbarAndMouseContextMenu();
1185  updateQWidget();
1186  }
1187 }
1188 
1189 void G4OpenGLQtViewer::actionChangeDefaultColor() {
1190 
1191 #if QT_VERSION < 0x040500
1192  bool a;
1193  const QColor color = QColor(QColorDialog::getRgba (QColor(Qt::white).rgba(),&a,fGLWidget));
1194 #else
1195  const QColor& color =
1196  QColorDialog::getColor(Qt::white,
1197  fGLWidget,
1198  " Get default color and transparency",
1199  QColorDialog::ShowAlphaChannel);
1200 #endif
1201  if (color.isValid()) {
1202  G4Colour colour(((G4double)color.red())/255,
1203  ((G4double)color.green())/255,
1204  ((G4double)color.blue())/255,
1205  ((G4double)color.alpha())/255);
1206 
1207  fVP.SetDefaultColour(colour);
1208 
1209  updateToolbarAndMouseContextMenu();
1210  updateQWidget();
1211  }
1212 }
1213 
1214 
1215 void G4OpenGLQtViewer::actionMovieParameters() {
1216  showMovieParametersDialog();
1217 }
1218 
1219 
1220 void G4OpenGLQtViewer::showMovieParametersDialog() {
1221  if (!fMovieParametersDialog) {
1222  fMovieParametersDialog= new G4OpenGLQtMovieDialog(this,fGLWidget);
1223  displayRecordingStatus();
1224  fMovieParametersDialog->checkEncoderSwParameters();
1225  fMovieParametersDialog->checkSaveFileNameParameters();
1226  fMovieParametersDialog->checkTempFolderParameters();
1227  if (getEncoderPath() == "") {
1228  setRecordingInfos("ppmtompeg is needed to encode in video format. It is available here: http://netpbm.sourceforge.net ");
1229  }
1230  }
1231  fMovieParametersDialog->show();
1232 }
1233 
1234 
1235 
1236 void G4OpenGLQtViewer::FinishView()
1237 {
1238  /* From Apple doc:
1239  CGLFlushDrawable : Copies the back buffer of a double-buffered context to the front buffer.
1240  If the backing store attribute is set to false, the buffers can be exchanged rather than copied
1241  */
1242  glFlush ();
1243 
1244  // L. Garnier 10/2009 : Not necessary and cause problems on mac OS X 10.6
1245  // fGLWidget->swapBuffers ();
1246 }
1247 
1252 void G4OpenGLQtViewer::G4MousePressEvent(QMouseEvent *evnt)
1253 {
1254  if (evnt->button() == Qt::RightButton) {
1255  return;
1256  }
1257  if ((evnt->button() & Qt::LeftButton) && (! (evnt->modifiers() & Qt::ControlModifier ))){
1258  fGLWidget->setMouseTracking(true);
1259  fAutoMove = false; // stop automove
1260  fLastPos1 = evnt->pos();
1261  fLastPos2 = fLastPos1;
1262  fLastPos3 = fLastPos2;
1263  fLastEventTime->start();
1264  if (fUiQt != NULL) {
1265 
1266  if (fUiQt->IsIconZoomInSelected()) { // zoomIn
1267  // Move click point to center of OGL
1268 
1269  float deltaX = ((float)getWinWidth()/2-evnt->pos().x());
1270  float deltaY = ((float)getWinHeight()/2-evnt->pos().y());
1271 
1272  G4double coefTrans = 0;
1273  coefTrans = ((G4double)getSceneNearWidth())/((G4double)getWinWidth());
1274  if (getWinHeight() <getWinWidth()) {
1275  coefTrans = ((G4double)getSceneNearWidth())/((G4double)getWinHeight());
1276  }
1277  fVP.IncrementPan(-deltaX*coefTrans,deltaY*coefTrans,0);
1278  fVP.SetZoomFactor(1.5 * fVP.GetZoomFactor());
1279 
1280  updateQWidget();
1281 
1282  } else if (fUiQt->IsIconZoomOutSelected()) { // zoomOut
1283  // Move click point to center of OGL
1284  moveScene(((float)getWinWidth()/2-evnt->pos().x()),((float)getWinHeight()/2-evnt->pos().y()),0,true);
1285 
1286  fVP.SetZoomFactor(0.75 * fVP.GetZoomFactor());
1287  updateQWidget();
1288 
1289  } else if (fUiQt->IsIconRotateSelected() ) {
1290 
1291  if (fShiftKeyPress) { // move
1292  fGLWidget->setCursor(QCursor(Qt::SizeAllCursor));
1293 
1294  } else { // rotate
1295  fGLWidget->setCursor(QCursor(Qt::ClosedHandCursor));
1296  }
1297  } else if (fUiQt->IsIconMoveSelected()) {
1298  fGLWidget->setCursor(QCursor(Qt::SizeAllCursor));
1299  } else if (fUiQt->IsIconPickSelected()) {
1300  fGLWidget->setCursor(QCursor(Qt::PointingHandCursor));
1301  }
1302  }
1303  }
1304 }
1305 
1308 void G4OpenGLQtViewer::G4MouseReleaseEvent(QMouseEvent *evnt)
1309 {
1310  fSpinningDelay = fLastEventTime->elapsed();
1311  QPoint delta = (fLastPos3-fLastPos1);
1312 
1313  // reset cursor state
1314  fGLWidget->setCursor(QCursor(Qt::ArrowCursor));
1315 
1316  if (fVP.IsPicking()){ // pick
1317  if ((delta.x() != 0) || (delta.y() != 0)) {
1318  return;
1319  }
1320  std::vector < G4OpenGLViewerPickMap* > pickMap = GetPickDetails(evnt->pos().x(),evnt->pos().y());
1321 
1322  // remove all previous widgets
1323  QLayoutItem * wItem;
1324  while ((wItem = fSceneTreeComponentPickingInfos->layout()->takeAt(0)) != 0) {
1325  delete wItem->widget();
1326  delete wItem;
1327  }
1328 
1329  // Create a new signalMapper
1330  delete fSignalMapperPicking;
1331  fSignalMapperPicking = new QSignalMapper(this);
1332 
1333  // parse all pick results
1334  for (unsigned int a=0; a< pickMap.size(); a++) {
1335  // Add a box inside the pick viewer box
1336  std::ostringstream label;
1337  label << "Hit number:" << a << ", PickName: " << pickMap[a]->getPickName();
1338 
1339  QPushButton* pickCoutButton = new QPushButton(label.str().c_str());
1340  pickCoutButton->setStyleSheet ("text-align: left; padding: 1px; border: 0px;");
1341  pickCoutButton->setIcon(*fTreeIconClosed);
1342  fSceneTreeComponentPickingInfos->layout()->addWidget(pickCoutButton);
1343 
1344  QStringList newStr;
1345 
1346  // Add to stringList
1347  newStr = QStringList(QString(pickMap[a]->print().data()).trimmed());
1348 
1349  QTextEdit* ed = new QTextEdit();
1350  ed->setFontFamily("Courier");
1351  ed->setFontPointSize(12);
1352  ed->setReadOnly(true);
1353  fSceneTreeComponentPickingInfos->layout()->addWidget(ed);
1354  ed->setVisible((false));
1355  ed->append(newStr.join(""));
1356 
1357  connect(pickCoutButton, SIGNAL(clicked()), fSignalMapperPicking, SLOT(map()));
1358  fSignalMapperPicking->setMapping(pickCoutButton,fSceneTreeComponentPickingInfos->layout()->count()-1);
1359  }
1360 
1361  connect(fSignalMapperPicking, SIGNAL(mapped(int)),this, SLOT(toggleSceneTreeComponentPickingCout(int)));
1362 
1363  // add a label to push everything up!
1364  QLabel * pushUp = new QLabel("");
1365  QSizePolicy vPolicy = QSizePolicy(QSizePolicy::Minimum,QSizePolicy::Minimum);
1366  vPolicy.setVerticalStretch(10);
1367  pushUp->setSizePolicy(vPolicy);
1368  fSceneTreeComponentPickingInfos->layout()->addWidget(pushUp);
1369 
1370  // highlight the first one :
1371 
1372  // first un-highlight the last selected
1373  changeColorAndTransparency(fLastHighlightName,fLastHighlightColor);
1374 
1375  if (pickMap.size() > 0 ) {
1376  // get the new one
1377  fLastHighlightName = pickMap[0]->getPickName();
1378  fLastHighlightColor = getColorForPoIndex(fLastHighlightName);
1379  // set the new one
1380  changeColorAndTransparency(fLastHighlightName,G4Color(1,1,1,1));
1381  updateQWidget();
1382  }
1383  // set picking cout visible
1384  fSceneTreeComponentPickingScrollArea->setVisible(true);
1385 
1386  } else if (fSpinningDelay < fLaunchSpinDelay ) {
1387  if ((delta.x() == 0) && (delta.y() == 0)) {
1388  return;
1389  }
1390 
1391  fAutoMove = true;
1392  QTime lastMoveTime;
1393  lastMoveTime.start();
1394  // try to addapt speed move/rotate looking to drawing speed
1395  float correctionFactor = 5;
1396  while (fAutoMove) {
1397  if ( lastMoveTime.elapsed() >= (int)(1000/fNbMaxFramesPerSec)) {
1398  float lTime = 1000/lastMoveTime.elapsed();
1399  if (((((float)delta.x())/correctionFactor)*lTime > fNbMaxAnglePerSec) ||
1400  ((((float)delta.x())/correctionFactor)*lTime < -fNbMaxAnglePerSec) ) {
1401  correctionFactor = (float)delta.x()*(lTime/fNbMaxAnglePerSec);
1402  if (delta.x() <0 ) {
1403  correctionFactor = -correctionFactor;
1404  }
1405  }
1406  if (((((float)delta.y())/correctionFactor)*lTime > fNbMaxAnglePerSec) ||
1407  ((((float)delta.y())/correctionFactor)*lTime < -fNbMaxAnglePerSec) ) {
1408  correctionFactor = (float)delta.y()*(lTime/fNbMaxAnglePerSec);
1409  if (delta.y() <0 ) {
1410  correctionFactor = -correctionFactor;
1411  }
1412  }
1413 
1414  // Check Qt Versions for META Keys
1415 
1416  // Click and move mouse to rotate volume
1417  // ALT + Click and move mouse to rotate volume (View Direction)
1418  // SHIFT + Click and move camera point of view
1419  // CTRL + Click and zoom mouse to zoom in/out
1420 
1421  lastMoveTime.start();
1422 
1423  bool rotate = false;
1424  bool move = false;
1425 
1426  if (fUiQt != NULL) {
1427  if (fUiQt->IsIconRotateSelected()) { // rotate
1428  rotate = true;
1429  } else if (fUiQt->IsIconMoveSelected()) { // move
1430  move = true;
1431  }
1432  } else {
1433  rotate = true;
1434  }
1435  // prevent from closing widget when rotating (cause a crash)
1436  if (fIsDeleting) {
1437  return;
1438  }
1439 
1440  if (rotate) { // rotate
1441  if (fNoKeyPress) {
1442  rotateQtScene(((float)delta.x())/correctionFactor,((float)delta.y())/correctionFactor);
1443  } else if (fAltKeyPress) {
1444  rotateQtSceneToggle(((float)delta.x())/correctionFactor,((float)delta.y())/correctionFactor);
1445  }
1446 #ifdef G4DEBUG_VIS_OGL
1447  fNbRotation ++;
1448  fTimeRotation += lastMoveTime.elapsed();
1449  printf("G4OpenGLQtViewer %f \n",fTimeRotation/(float)fNbRotation);
1450 #endif
1451 
1452  } else if (move) { // move
1453  moveScene(-((float)delta.x())/correctionFactor,-((float)delta.y())/correctionFactor,0,true);
1454  }
1455  }
1456  ((QApplication*)G4Qt::getInstance ())->processEvents();
1457  }
1458  }
1459  fGLWidget->setMouseTracking(false);
1460 
1461 }
1462 
1463 
1464 void G4OpenGLQtViewer::G4MouseDoubleClickEvent()
1465 {
1466  fGLWidget->setMouseTracking(true);
1467 }
1468 
1469 
1477 void G4OpenGLQtViewer::G4MouseMoveEvent(QMouseEvent *evnt)
1478 {
1479 
1480  Qt::MouseButtons mButtons = evnt->buttons();
1481 
1482  updateKeyModifierState(evnt->modifiers());
1483 
1484  if (fAutoMove) {
1485  return;
1486  }
1487 
1488  fLastPos3 = fLastPos2;
1489  fLastPos2 = fLastPos1;
1490  fLastPos1 = QPoint(evnt->x(), evnt->y());
1491 
1492  int deltaX = fLastPos2.x()-fLastPos1.x();
1493  int deltaY = fLastPos2.y()-fLastPos1.y();
1494 
1495  bool move = false;
1496  if (fUiQt != NULL) {
1497  if (fUiQt->IsIconMoveSelected()) { // move
1498  move = true;
1499  }
1500  }
1501  if (!move) { // rotate, pick, zoom...
1502  if (mButtons & Qt::LeftButton) {
1503  if (fNoKeyPress) {
1504  rotateQtScene(((float)deltaX),((float)deltaY));
1505  } else if (fAltKeyPress) {
1506  rotateQtSceneToggle(((float)deltaX),((float)deltaY));
1507  } else if (fShiftKeyPress) {
1508  unsigned int sizeWin;
1509  sizeWin = getWinWidth();
1510  if (getWinHeight() < getWinWidth()) {
1511  sizeWin = getWinHeight();
1512  }
1513 
1514  // L.Garnier : 08/2010 100 is the good value, but don't ask me why !
1515  float factor = ((float)100/(float)sizeWin) ;
1516  moveScene(-(float)deltaX*factor,-(float)deltaY*factor,0,false);
1517  } else if (fControlKeyPress) {
1518  fVP.SetZoomFactor(fVP.GetZoomFactor()*(1+((float)deltaY)));
1519  }
1520  }
1521  } else if (move) { // move
1522  if (mButtons & Qt::LeftButton) {
1523  moveScene(-(float)deltaX,-(float)deltaY,0,true);
1524  }
1525  }
1526 
1527  fLastEventTime->start();
1528 }
1529 
1530 
1538 void G4OpenGLQtViewer::moveScene(float dx,float dy, float dz,bool mouseMove)
1539 {
1540  if (fHoldMoveEvent)
1541  return;
1542  fHoldMoveEvent = true;
1543 
1544  G4double coefTrans = 0;
1545  GLdouble coefDepth = 0;
1546  if(mouseMove) {
1547  coefTrans = ((G4double)getSceneNearWidth())/((G4double)getWinWidth());
1548  if (getWinHeight() <getWinWidth()) {
1549  coefTrans = ((G4double)getSceneNearWidth())/((G4double)getWinHeight());
1550  }
1551  } else {
1552  coefTrans = getSceneNearWidth()*fPan_sens;
1553  coefDepth = getSceneDepth()*fDeltaDepth;
1554  }
1555  fVP.IncrementPan(-dx*coefTrans,dy*coefTrans,dz*coefDepth);
1556 
1557  updateQWidget();
1558  if (fAutoMove)
1559  ((QApplication*)G4Qt::getInstance ())->processEvents();
1560 
1561  fHoldMoveEvent = false;
1562 }
1563 
1564 
1570 void G4OpenGLQtViewer::rotateQtScene(float dx, float dy)
1571 {
1572  if (fHoldRotateEvent)
1573  return;
1574  fHoldRotateEvent = true;
1575 
1576  rotateScene(dx,dy);
1577 
1578  updateQWidget();
1579 
1580  fHoldRotateEvent = false;
1581 }
1582 
1588 void G4OpenGLQtViewer::rotateQtSceneToggle(float dx, float dy)
1589 {
1590  if (fHoldRotateEvent)
1591  return;
1592  fHoldRotateEvent = true;
1593 
1594  rotateSceneToggle(dx,dy);
1595 
1596  updateQWidget();
1597 
1598  fHoldRotateEvent = false;
1599 }
1600 
1601 
1602 
1603 
1604 
1609 void G4OpenGLQtViewer::rescaleImage(
1610  int /* aWidth */
1611 ,int /* aHeight */
1612 ){
1613  // GLfloat* feedback_buffer;
1614  // GLint returned;
1615  // FILE* file;
1616 
1617  // feedback_buffer = new GLfloat[size];
1618  // glFeedbackBuffer (size, GL_3D_COLOR, feedback_buffer);
1619  // glRenderMode (GL_FEEDBACK);
1620 
1621  // DrawView();
1622  // returned = glRenderMode (GL_RENDER);
1623 
1624 }
1625 
1626 
1627 
1628 
1629 void G4OpenGLQtViewer::G4wheelEvent (QWheelEvent * evnt)
1630 {
1631  fVP.SetZoomFactor(fVP.GetZoomFactor()+(fVP.GetZoomFactor()*(evnt->delta())/1200));
1632  updateQWidget();
1633 }
1634 
1635 
1636 void G4OpenGLQtViewer::G4keyPressEvent (QKeyEvent * evnt)
1637 {
1638  if (fHoldKeyEvent)
1639  return;
1640 
1641  fHoldKeyEvent = true;
1642 
1643 
1644  // with no modifiers
1645  updateKeyModifierState(evnt->modifiers());
1646  if ((fNoKeyPress) || (evnt->modifiers() == Qt::KeypadModifier )) {
1647  if (evnt->key() == Qt::Key_Down) { // go down
1648  moveScene(0,1,0,false);
1649  }
1650  else if (evnt->key() == Qt::Key_Up) { // go up
1651  moveScene(0,-1,0,false);
1652  }
1653  if (evnt->key() == Qt::Key_Left) { // go left
1654  moveScene(-1,0,0,false);
1655  }
1656  else if (evnt->key() == Qt::Key_Right) { // go right
1657  moveScene(1,0,0,false);
1658  }
1659  if (evnt->key() == Qt::Key_Minus) { // go backward
1660  moveScene(0,0,1,false);
1661  }
1662  else if (evnt->key() == Qt::Key_Plus) { // go forward
1663  moveScene(0,0,-1,false);
1664  }
1665 
1666  // escaped from full screen
1667  if (evnt->key() == Qt::Key_Escape) {
1668  toggleFullScreen(false);
1669  }
1670  }
1671  // several case here : If return is pressed, in every case -> display the movie parameters dialog
1672  // If one parameter is wrong -> put it in red (only save filenam could be wrong..)
1673  // If encoder not found-> does nothing.Only display a message in status box
1674  // If all ok-> generate parameter file
1675  // If ok -> put encoder button enabled
1676 
1677  if ((evnt->key() == Qt::Key_Return) || (evnt->key() == Qt::Key_Enter)){ // end of video
1678  stopVideo();
1679  }
1680  if (evnt->key() == Qt::Key_Space){ // start/pause of video
1681  startPauseVideo();
1682  }
1683 
1684  // H : Return Home view
1685  if (evnt->key() == Qt::Key_H){ // go Home
1686  ResetView();
1687 
1688  updateQWidget();
1689  }
1690 
1691  // Shift Modifier
1692  if (fShiftKeyPress) {
1693  fGLWidget->setCursor(QCursor(Qt::SizeAllCursor));
1694 
1695  if (evnt->key() == Qt::Key_Down) { // rotate phi
1696  rotateQtScene(0,-fRot_sens);
1697  }
1698  else if (evnt->key() == Qt::Key_Up) { // rotate phi
1699  rotateQtScene(0,fRot_sens);
1700  }
1701  if (evnt->key() == Qt::Key_Left) { // rotate theta
1702  rotateQtScene(fRot_sens,0);
1703  }
1704  else if (evnt->key() == Qt::Key_Right) { // rotate theta
1705  rotateQtScene(-fRot_sens,0);
1706  }
1707  if (evnt->key() == Qt::Key_Plus) { // go forward ("Plus" imply
1708  // "Shift" on Mac French keyboard
1709  moveScene(0,0,-1,false);
1710  }
1711 
1712  // Alt Modifier
1713  }
1714  if ((fAltKeyPress)) {
1715  fGLWidget->setCursor(QCursor(Qt::ClosedHandCursor));
1716 
1717  if (evnt->key() == Qt::Key_Down) { // rotate phi
1718  rotateQtSceneToggle(0,-fRot_sens);
1719  }
1720  else if (evnt->key() == Qt::Key_Up) { // rotate phi
1721  rotateQtSceneToggle(0,fRot_sens);
1722  }
1723  if (evnt->key() == Qt::Key_Left) { // rotate theta
1724  rotateQtSceneToggle(fRot_sens,0);
1725  }
1726  else if (evnt->key() == Qt::Key_Right) { // rotate theta
1727  rotateQtSceneToggle(-fRot_sens,0);
1728  }
1729 
1730  // Rotatio +/-
1731  if (evnt->key() == Qt::Key_Plus) {
1732  fRot_sens = fRot_sens/0.7;
1733  G4cout << "Auto-rotation set to : " << fRot_sens << G4endl;
1734  }
1735  else if (evnt->key() == Qt::Key_Minus) {
1736  fRot_sens = fRot_sens*0.7;
1737  G4cout << "Auto-rotation set to : " << fRot_sens << G4endl;
1738  }
1739 
1740  // Control Modifier OR Command on MAC
1741  }
1742  if ((fControlKeyPress)) {
1743  if (evnt->key() == Qt::Key_Plus) {
1744  fVP.SetZoomFactor(fVP.GetZoomFactor()*(1+fDeltaZoom));
1745  updateQWidget();
1746  }
1747  else if (evnt->key() == Qt::Key_Minus) {
1748  fVP.SetZoomFactor(fVP.GetZoomFactor()*(1-fDeltaZoom));
1749  updateQWidget();
1750  }
1751  }
1752 
1753  fHoldKeyEvent = false;
1754 }
1755 
1756 
1757 void G4OpenGLQtViewer::G4keyReleaseEvent (QKeyEvent *)
1758 {
1759  fGLWidget->setCursor(QCursor(Qt::ArrowCursor));
1760 }
1761 
1762 
1763 void G4OpenGLQtViewer::updateKeyModifierState(const Qt::KeyboardModifiers& modifier) {
1764  // Check Qt Versions for META Keys
1765 
1766  fNoKeyPress = true;
1767  fAltKeyPress = false;
1768  fShiftKeyPress = false;
1769  fControlKeyPress = false;
1770 
1771  if (modifier & Qt::AltModifier ) {
1772  fAltKeyPress = true;
1773  fNoKeyPress = false;
1774  }
1775  if (modifier & Qt::ShiftModifier ) {
1776  fShiftKeyPress = true;
1777  fNoKeyPress = false;
1778  }
1779  if (modifier & Qt::ControlModifier ) {
1780  fControlKeyPress = true;
1781  fNoKeyPress = false;
1782  }
1783 }
1784 
1785 
1788 void G4OpenGLQtViewer::stopVideo() {
1789 
1790  // if encoder parameter is wrong, display parameters dialog and return
1791  if (!fMovieParametersDialog) {
1792  showMovieParametersDialog();
1793  }
1794  setRecordingStatus(STOP);
1795 
1796  if (fRecordFrameNumber >0) {
1797  // check parameters if they were modified (Re APPLY them...)
1798  if (!(fMovieParametersDialog->checkEncoderSwParameters())) {
1799  setRecordingStatus(BAD_ENCODER);
1800  } else if (!(fMovieParametersDialog->checkSaveFileNameParameters())) {
1801  setRecordingStatus(BAD_OUTPUT);
1802  }
1803  } else {
1804  resetRecording();
1805  setRecordingInfos("No frame to encode.");
1806  }
1807 }
1808 
1811 void G4OpenGLQtViewer::saveVideo() {
1812 
1813  // if encoder parameter is wrong, display parameters dialog and return
1814  if (!fMovieParametersDialog) {
1815  showMovieParametersDialog();
1816  }
1817 
1818  fMovieParametersDialog->checkEncoderSwParameters();
1819  fMovieParametersDialog->checkSaveFileNameParameters();
1820 
1821  if (fRecordingStep == STOP) {
1822  setRecordingStatus(SAVE);
1823  generateMpegEncoderParameters();
1824  encodeVideo();
1825  }
1826 }
1827 
1828 
1831 void G4OpenGLQtViewer::startPauseVideo() {
1832 
1833  // first time, if temp parameter is wrong, display parameters dialog and return
1834 
1835  if ( fRecordingStep == WAIT) {
1836  if ( fRecordFrameNumber == 0) {
1837  if (getTempFolderPath() == "") { // BAD_OUTPUT
1838  showMovieParametersDialog();
1839  setRecordingInfos("You should specified the temp folder in order to make movie");
1840  return;
1841  } else {
1842  // remove temp folder if it was create
1843  QString tmp = removeTempFolder();
1844  if (tmp !="") {
1845  setRecordingInfos(tmp);
1846  return;
1847  }
1848  tmp = createTempFolder();
1849  if (tmp != "") {
1850  setRecordingInfos("Can't create temp folder."+tmp);
1851  return;
1852  }
1853  }
1854  }
1855  }
1856  if (fRecordingStep == WAIT) {
1857  setRecordingStatus(START);
1858  } else if (fRecordingStep == START) {
1859  setRecordingStatus(PAUSE);
1860  } else if (fRecordingStep == PAUSE) {
1861  setRecordingStatus(CONTINUE);
1862  } else if (fRecordingStep == CONTINUE) {
1863  setRecordingStatus(PAUSE);
1864  }
1865 }
1866 
1867 void G4OpenGLQtViewer::setRecordingStatus(RECORDING_STEP step) {
1868 
1869  fRecordingStep = step;
1870  displayRecordingStatus();
1871 }
1872 
1873 
1874 void G4OpenGLQtViewer::displayRecordingStatus() {
1875 
1876  QString txtStatus = "";
1877  if (fRecordingStep == WAIT) {
1878  txtStatus = "Waiting to start...";
1879  fRecordFrameNumber = 0; // reset the frame number
1880  } else if (fRecordingStep == START) {
1881  txtStatus = "Start Recording...";
1882  } else if (fRecordingStep == PAUSE) {
1883  txtStatus = "Pause Recording...";
1884  } else if (fRecordingStep == CONTINUE) {
1885  txtStatus = "Continue Recording...";
1886  } else if (fRecordingStep == STOP) {
1887  txtStatus = "Stop Recording...";
1888  } else if (fRecordingStep == READY_TO_ENCODE) {
1889  txtStatus = "Ready to Encode...";
1890  } else if (fRecordingStep == ENCODING) {
1891  txtStatus = "Encoding...";
1892  } else if (fRecordingStep == FAILED) {
1893  txtStatus = "Failed to encode...";
1894  } else if ((fRecordingStep == BAD_ENCODER)
1895  || (fRecordingStep == BAD_OUTPUT)
1896  || (fRecordingStep == BAD_TMP)) {
1897  txtStatus = "Correct above errors first";
1898  } else if (fRecordingStep == SUCCESS) {
1899  txtStatus = "File encoded successfully";
1900  } else {
1901  }
1902 
1903  if (fMovieParametersDialog) {
1904  fMovieParametersDialog->setRecordingStatus(txtStatus);
1905  } else {
1906  G4cout << txtStatus.toStdString().c_str() << G4endl;
1907  }
1908  setRecordingInfos("");
1909 }
1910 
1911 
1912 void G4OpenGLQtViewer::setRecordingInfos(const QString& txt) {
1913  if (fMovieParametersDialog) {
1914  fMovieParametersDialog->setRecordingInfos(txt);
1915  } else {
1916  G4cout << txt.toStdString().c_str() << G4endl;
1917  }
1918 }
1919 
1922 void G4OpenGLQtViewer::initMovieParameters() {
1923  //init encoder
1924 
1925  //look for encoderPath
1926  fProcess = new QProcess();
1927 
1928  QObject ::connect(fProcess,SIGNAL(finished ( int)),
1929  this,SLOT(processLookForFinished()));
1930  fProcess->setReadChannelMode(QProcess::MergedChannels);
1931  fProcess->start ("which ppmtompeg");
1932 
1933 }
1934 
1937 QString G4OpenGLQtViewer::getEncoderPath() {
1938  return fEncoderPath;
1939 }
1940 
1941 
1946 QString G4OpenGLQtViewer::setEncoderPath(QString path) {
1947  if (path == "") {
1948  return "File does not exist";
1949  }
1950 
1951  path = QDir::cleanPath(path);
1952  QFileInfo *f = new QFileInfo(path);
1953  if (!f->exists()) {
1954  return "File does not exist";
1955  } else if (f->isDir()) {
1956  return "This is a directory";
1957  } else if (!f->isExecutable()) {
1958  return "File exist but is not executable";
1959  } else if (!f->isFile()) {
1960  return "This is not a file";
1961  }
1962  fEncoderPath = path;
1963 
1964  if (fRecordingStep == BAD_ENCODER) {
1965  setRecordingStatus(STOP);
1966  }
1967  return "";
1968 }
1969 
1970 
1971 bool G4OpenGLQtViewer::isRecording(){
1972  if ((fRecordingStep == START) || (fRecordingStep == CONTINUE)) {
1973  return true;
1974  }
1975  return false;
1976 }
1977 
1978 bool G4OpenGLQtViewer::isPaused(){
1979  if (fRecordingStep == PAUSE) {
1980  return true;
1981  }
1982  return false;
1983 }
1984 
1985 bool G4OpenGLQtViewer::isEncoding(){
1986  if (fRecordingStep == ENCODING) {
1987  return true;
1988  }
1989  return false;
1990 }
1991 
1992 bool G4OpenGLQtViewer::isWaiting(){
1993  if (fRecordingStep == WAIT) {
1994  return true;
1995  }
1996  return false;
1997 }
1998 
1999 bool G4OpenGLQtViewer::isStopped(){
2000  if (fRecordingStep == STOP) {
2001  return true;
2002  }
2003  return false;
2004 }
2005 
2006 bool G4OpenGLQtViewer::isFailed(){
2007  if (fRecordingStep == FAILED) {
2008  return true;
2009  }
2010  return false;
2011 }
2012 
2013 bool G4OpenGLQtViewer::isSuccess(){
2014  if (fRecordingStep == SUCCESS) {
2015  return true;
2016  }
2017  return false;
2018 }
2019 
2020 bool G4OpenGLQtViewer::isBadEncoder(){
2021  if (fRecordingStep == BAD_ENCODER) {
2022  return true;
2023  }
2024  return false;
2025 }
2026 bool G4OpenGLQtViewer::isBadTmp(){
2027  if (fRecordingStep == BAD_TMP) {
2028  return true;
2029  }
2030  return false;
2031 }
2032 bool G4OpenGLQtViewer::isBadOutput(){
2033  if (fRecordingStep == BAD_OUTPUT) {
2034  return true;
2035  }
2036  return false;
2037 }
2038 
2039 void G4OpenGLQtViewer::setBadEncoder(){
2040  fRecordingStep = BAD_ENCODER;
2041  displayRecordingStatus();
2042 }
2043 void G4OpenGLQtViewer::setBadTmp(){
2044  fRecordingStep = BAD_TMP;
2045  displayRecordingStatus();
2046 }
2047 void G4OpenGLQtViewer::setBadOutput(){
2048  fRecordingStep = BAD_OUTPUT;
2049  displayRecordingStatus();
2050 }
2051 
2052 void G4OpenGLQtViewer::setWaiting(){
2053  fRecordingStep = WAIT;
2054  displayRecordingStatus();
2055 }
2056 
2057 
2058 bool G4OpenGLQtViewer::isReadyToEncode(){
2059  if (fRecordingStep == READY_TO_ENCODE) {
2060  return true;
2061  }
2062  return false;
2063 }
2064 
2065 void G4OpenGLQtViewer::resetRecording() {
2066  setRecordingStatus(WAIT);
2067 }
2068 
2073 QString G4OpenGLQtViewer::setTempFolderPath(QString path) {
2074 
2075  if (path == "") {
2076  return "Path does not exist";
2077  }
2078  path = QDir::cleanPath(path);
2079  QFileInfo *d = new QFileInfo(path);
2080  if (!d->exists()) {
2081  return "Path does not exist";
2082  } else if (!d->isDir()) {
2083  return "This is not a directory";
2084  } else if (!d->isReadable()) {
2085  return path +" is read protected";
2086  } else if (!d->isWritable()) {
2087  return path +" is write protected";
2088  }
2089 
2090  if (fRecordingStep == BAD_TMP) {
2091  setRecordingStatus(WAIT);
2092  }
2093  fTempFolderPath = path;
2094  return "";
2095 }
2096 
2099 QString G4OpenGLQtViewer::getTempFolderPath() {
2100  return fTempFolderPath;
2101 }
2102 
2107 QString G4OpenGLQtViewer::setSaveFileName(QString path) {
2108 
2109  if (path == "") {
2110  return "Path does not exist";
2111  }
2112 
2113  QFileInfo *file = new QFileInfo(path);
2114  QDir dir = file->dir();
2115  path = QDir::cleanPath(path);
2116  if (file->exists()) {
2117  return "File already exist, please choose a new one";
2118  } else if (!dir.exists()) {
2119  return "Dir does not exist";
2120  } else if (!dir.isReadable()) {
2121  return path +" is read protected";
2122  }
2123 
2124  if (fRecordingStep == BAD_OUTPUT) {
2125  setRecordingStatus(STOP);
2126  }
2127  fSaveFileName = path;
2128  return "";
2129 }
2130 
2133 QString G4OpenGLQtViewer::getSaveFileName() {
2134  return fSaveFileName ;
2135 }
2136 
2141 QString G4OpenGLQtViewer::createTempFolder() {
2142  fMovieTempFolderPath = "";
2143  //check
2144  QString tmp = setTempFolderPath(fTempFolderPath);
2145  if (tmp != "") {
2146  return tmp;
2147  }
2148  QString sep = QString(QDir::separator());
2149  QString path = sep+"QtMovie_"+QDateTime::currentDateTime ().toString("dd-MM-yyyy_hh-mm-ss")+sep;
2150  QDir *d = new QDir(QDir::cleanPath(fTempFolderPath));
2151  // check if it is already present
2152  if (d->exists(path)) {
2153  return "Folder "+path+" already exists.Please remove it first";
2154  }
2155  if (d->mkdir(fTempFolderPath+path)) {
2156  fMovieTempFolderPath = fTempFolderPath+path;
2157  return "";
2158  }
2159  return "Can't create "+fTempFolderPath+path;
2160 }
2161 
2164 QString G4OpenGLQtViewer::removeTempFolder() {
2165  // remove files in Qt_temp folder
2166  if (fMovieTempFolderPath == "") {
2167  return "";
2168  }
2169  QDir *d = new QDir(QDir::cleanPath(fMovieTempFolderPath));
2170  if (!d->exists()) {
2171  return ""; // already remove
2172  }
2173 
2174  d->setFilter( QDir::Files );
2175  QStringList subDirList = d->entryList();
2176  int res = true;
2177  QString error = "";
2178  for (QStringList::ConstIterator it = subDirList.begin() ;(it != subDirList.end()) ; it++) {
2179  const QString currentFile = *it;
2180  if (!d->remove(currentFile)) {
2181  res = false;
2182  QString file = fMovieTempFolderPath+currentFile;
2183  error +="Removing file failed : "+file;
2184  } else {
2185  }
2186  }
2187  if (res) {
2188  if (d->rmdir(fMovieTempFolderPath)) {
2189  fMovieTempFolderPath = "";
2190  return "";
2191  } else {
2192  return "Dir "+fMovieTempFolderPath+" should be empty, but could not remove it";
2193  }
2194 
2195  }
2196  return "Could not remove "+fMovieTempFolderPath+" because of the following errors :"+error;
2197 }
2198 
2206 bool G4OpenGLQtViewer::exportImage(std::string name, int width, int height) {
2207 
2208  QGLWidget* qGLW = dynamic_cast<QGLWidget*> (fGLWidget) ;
2209  if (! qGLW) {
2210  return false;
2211  }
2212  // If there is already an extention
2213  bool increaseFileNumber = true;
2214  // if
2215  if (name.size() != name.substr(name.find_last_of(".") + 1).size()) {
2216  increaseFileNumber = false;
2217  }
2218  if (! setExportFilename(name,increaseFileNumber)) {
2219  return false;
2220  }
2221  if ((width !=-1) && (height != -1)) {
2222  setExportSize(width, height);
2223  }
2224  // first, try to do it with generic function
2225  if (G4OpenGLViewer::exportImage()) {
2226  return true;
2227 
2228  // Then try Qt saving functions
2229  } else {
2230  QImage image;
2231  image = qGLW->grabFrameBuffer();
2232 
2233  bool res = image.save(QString(getRealPrintFilename().c_str()),0,fLastExportSliderValue);
2234 
2235  if (!res) {
2236  G4cerr << "Error saving file... " << getRealPrintFilename().c_str() << G4endl;
2237  return false;
2238  } else {
2239  G4cout << "File " << getRealPrintFilename().c_str() << " size: " << fGLWidget->width() << "x" << fGLWidget->height() << " has been saved " << G4endl;
2240  fExportFilenameIndex++;
2241  }
2242  }
2243  return true;
2244 }
2245 
2246 
2247 
2248 bool G4OpenGLQtViewer::hasPendingEvents () {
2249  return ((QApplication*)G4Qt::getInstance ())->hasPendingEvents ();
2250 }
2251 
2252 bool G4OpenGLQtViewer::generateMpegEncoderParameters () {
2253 
2254  // save the parameter file
2255  FILE* fp;
2256  fp = fopen (QString(fMovieTempFolderPath+fParameterFileName).toStdString().c_str(), "w");
2257 
2258  if (fp == NULL) {
2259  setRecordingInfos("Generation of parameter file failed");
2260  return false;
2261  }
2262 
2263  fprintf (fp,"# Pattern affects speed, quality and compression. See the User's Guide\n");
2264  fprintf (fp,"# for more info.\n");
2265  fprintf (fp,"\n");
2266  fprintf (fp,"PATTERN IBBPBBPBBPBBPBBP\n");
2267  fprintf (fp,"OUTPUT %s\n",getSaveFileName().toStdString().c_str());
2268  fprintf (fp,"\n");
2269  fprintf (fp,"# You must specify the type of the input files. The choices are:\n");
2270  fprintf (fp,"# YUV, PPM, JMOVIE, Y, JPEG, PNM\n");
2271  fprintf (fp,"# (must be upper case)\n");
2272  fprintf (fp,"#\n");
2273  fprintf (fp,"BASE_FILE_FORMAT PPM\n");
2274  fprintf (fp,"\n");
2275  fprintf (fp,"#\n");
2276  fprintf (fp,"# if YUV format (or using parallel version), must provide width and height\n");
2277  fprintf (fp,"# YUV_SIZE widthxheight\n");
2278  fprintf (fp,"# this option is ignored if BASE_FILE_FORMAT is not YUV and you're running\n");
2279  fprintf (fp,"# on just one machine\n");
2280  fprintf (fp,"#\n");
2281  fprintf (fp,"YUV_SIZE 352x240\n");
2282  fprintf (fp,"\n");
2283  fprintf (fp,"# If you are using YUV, there are different supported file formats.\n");
2284  fprintf (fp,"# EYUV or UCB are the same as previous versions of this encoder.\n");
2285  fprintf (fp,"# (All the Y's, then U's then V's, in 4:2:0 subsampling.)\n");
2286  fprintf (fp,"# Other formats, such as Abekas, Phillips, or a general format are\n");
2287  fprintf (fp,"# permissible, the general format is a string of Y's, U's, and V's\n");
2288  fprintf (fp,"# to specify the file order.\n");
2289  fprintf (fp,"\n");
2290  fprintf (fp,"INPUT_FORMAT UCB\n");
2291  fprintf (fp,"\n");
2292  fprintf (fp,"# the conversion statement\n");
2293  fprintf (fp,"#\n");
2294  fprintf (fp,"# Each occurrence of '*' will be replaced by the input file\n");
2295  fprintf (fp,"#\n");
2296  fprintf (fp,"# e.g., if you have a bunch of GIF files, then this might be:\n");
2297  fprintf (fp,"# INPUT_CONVERT giftoppm *\n");
2298  fprintf (fp,"#\n");
2299  fprintf (fp,"# e.g., if you have a bunch of files like a.Y a.U a.V, etc., then:\n");
2300  fprintf (fp,"# INPUT_CONVERT cat *.Y *.U *.V\n");
2301  fprintf (fp,"#\n");
2302  fprintf (fp,"# e.g., if you are grabbing from laser disc you might have something like\n");
2303  fprintf (fp,"# INPUT_CONVERT goto frame *; grabppm\n");
2304  fprintf (fp,"# 'INPUT_CONVERT *' means the files are already in the base file format\n");
2305  fprintf (fp,"#\n");
2306  fprintf (fp,"INPUT_CONVERT * \n");
2307  fprintf (fp,"\n");
2308  fprintf (fp,"# number of frames in a GOP.\n");
2309  fprintf (fp,"#\n");
2310  fprintf (fp,"# since each GOP must have at least one I-frame, the encoder will find the\n");
2311  fprintf (fp,"# the first I-frame after GOP_SIZE frames to start the next GOP\n");
2312  fprintf (fp,"#\n");
2313  fprintf (fp,"# later, will add more flexible GOP signalling\n");
2314  fprintf (fp,"#\n");
2315  fprintf (fp,"GOP_SIZE 16\n");
2316  fprintf (fp,"\n");
2317  fprintf (fp,"# number of slices in a frame\n");
2318  fprintf (fp,"#\n");
2319  fprintf (fp,"# 1 is a good number. another possibility is the number of macroblock rows\n");
2320  fprintf (fp,"# (which is the height divided by 16)\n");
2321  fprintf (fp,"#\n");
2322  fprintf (fp,"SLICES_PER_FRAME 1\n");
2323  fprintf (fp,"\n");
2324  fprintf (fp,"# directory to get all input files from (makes this file easier to read)\n");
2325  fprintf (fp,"INPUT_DIR %s\n",fMovieTempFolderPath.toStdString().c_str());
2326  fprintf (fp,"\n");
2327  fprintf (fp,"# There are a bunch of ways to specify the input files.\n");
2328  fprintf (fp,"# from a simple one-per-line listing, to the following \n");
2329  fprintf (fp,"# way of numbering them. See the manual for more information.\n");
2330  fprintf (fp,"INPUT\n");
2331  fprintf (fp,"# '*' is replaced by the numbers 01, 02, 03, 04\n");
2332  fprintf (fp,"# if I instead do [01-11], it would be 01, 02, ..., 09, 10, 11\n");
2333  fprintf (fp,"# if I instead do [1-11], it would be 1, 2, 3, ..., 9, 10, 11\n");
2334  fprintf (fp,"# if I instead do [1-11+3], it would be 1, 4, 7, 10\n");
2335  fprintf (fp,"# the program assumes none of your input files has a name ending in ']'\n");
2336  fprintf (fp,"# if you do, too bad!!!\n");
2337  fprintf (fp,"#\n");
2338  fprintf (fp,"#\n");
2339  fprintf (fp,"Test*.ppm [0-%d]\n",fRecordFrameNumber-1);
2340  fprintf (fp,"# can have more files here if you want...there is no limit on the number\n");
2341  fprintf (fp,"# of files\n");
2342  fprintf (fp,"END_INPUT\n");
2343  fprintf (fp,"\n");
2344  fprintf (fp,"\n");
2345  fprintf (fp,"\n");
2346  fprintf (fp,"# Many of the remaining options have to do with the motion search and qscale\n");
2347  fprintf (fp,"\n");
2348  fprintf (fp,"# FULL or HALF -- must be upper case\n");
2349  fprintf (fp,"# Should be FULL for computer generated images\n");
2350  fprintf (fp,"PIXEL FULL\n");
2351  fprintf (fp,"\n");
2352  fprintf (fp,"# means +/- this many pixels for both P and B frame searches\n");
2353  fprintf (fp,"# specify two numbers if you wish to serc different ranges in the two.\n");
2354  fprintf (fp,"RANGE 10\n");
2355  fprintf (fp,"\n");
2356  fprintf (fp,"# The two search algorithm parameters below mostly affect speed,\n");
2357  fprintf (fp,"# with some affect on compression and almost none on quality.\n");
2358  fprintf (fp,"\n");
2359  fprintf (fp,"# this must be one of {EXHAUSTIVE, SUBSAMPLE, LOGARITHMIC}\n");
2360  fprintf (fp,"PSEARCH_ALG LOGARITHMIC\n");
2361  fprintf (fp,"\n");
2362  fprintf (fp,"# this must be one of {SIMPLE, CROSS2, EXHAUSTIVE}\n");
2363  fprintf (fp,"#\n");
2364  fprintf (fp,"# note that EXHAUSTIVE is really, really, really slow\n");
2365  fprintf (fp,"#\n");
2366  fprintf (fp,"BSEARCH_ALG SIMPLE\n");
2367  fprintf (fp,"\n");
2368  fprintf (fp,"#\n");
2369  fprintf (fp,"# these specify the q-scale for I, P, and B frames\n");
2370  fprintf (fp,"# (values must be between 1 and 31)\n");
2371  fprintf (fp,"# These are the Qscale values for the entire frame in variable bit-rate\n");
2372  fprintf (fp,"# mode, and starting points (but not important) for constant bit rate\n");
2373  fprintf (fp,"#\n");
2374  fprintf (fp,"\n");
2375  fprintf (fp,"# Qscale (Quantization scale) affects quality and compression,\n");
2376  fprintf (fp,"# but has very little effect on speed.\n");
2377  fprintf (fp,"\n");
2378  fprintf (fp,"IQSCALE 4\n");
2379  fprintf (fp,"PQSCALE 5\n");
2380  fprintf (fp,"BQSCALE 12\n");
2381  fprintf (fp,"\n");
2382  fprintf (fp,"# this must be ORIGINAL or DECODED\n");
2383  fprintf (fp,"REFERENCE_FRAME ORIGINAL\n");
2384  fprintf (fp,"\n");
2385  fprintf (fp,"# for parallel parameters see parallel.param in the exmaples subdirectory\n");
2386  fprintf (fp,"\n");
2387  fprintf (fp,"# if you want constant bit-rate mode, specify it as follows (number is bits/sec):\n");
2388  fprintf (fp,"#BIT_RATE 1000000\n");
2389  fprintf (fp,"\n");
2390  fprintf (fp,"# To specify the buffer size (327680 is default, measused in bits, for 16bit words)\n");
2391  fprintf (fp,"BUFFER_SIZE 327680\n");
2392  fprintf (fp,"\n");
2393  fprintf (fp,"# The frame rate is the number of frames/second (legal values:\n");
2394  fprintf (fp,"# 23.976, 24, 25, 29.97, 30, 50 ,59.94, 60\n");
2395  fprintf (fp,"FRAME_RATE 30\n");
2396  fprintf (fp,"\n");
2397  fprintf (fp,"# There are many more options, see the users manual for examples....\n");
2398  fprintf (fp,"# ASPECT_RATIO, USER_DATA, GAMMA, IQTABLE, etc.\n");
2399  fprintf (fp,"\n");
2400  fprintf (fp,"\n");
2401  fclose (fp);
2402 
2403  setRecordingInfos("Parameter file "+fParameterFileName+" generated in "+fMovieTempFolderPath);
2404  setRecordingStatus(READY_TO_ENCODE);
2405  return true;
2406 }
2407 
2408 void G4OpenGLQtViewer::encodeVideo()
2409 {
2410  if ((getEncoderPath() != "") && (getSaveFileName() != "")) {
2411  setRecordingStatus(ENCODING);
2412 
2413  fProcess = new QProcess();
2414 #if QT_VERSION > 0x040100
2415  QObject ::connect(fProcess,SIGNAL(finished ( int,QProcess::ExitStatus)),
2416  this,SLOT(processEncodeFinished()));
2417  QObject ::connect(fProcess,SIGNAL(readyReadStandardOutput ()),
2418  this,SLOT(processEncodeStdout()));
2419 #else
2420  QObject ::connect(fProcess,SIGNAL(finished ( int)),
2421  this,SLOT(processEncodeFinished()));
2422  QObject ::connect(fProcess,SIGNAL(readyReadStandardOutput ()),
2423  this,SLOT(processEncodeStdout()));
2424 #endif
2425  fProcess->setReadChannelMode(QProcess::MergedChannels);
2426  fProcess->start (fEncoderPath, QStringList(fMovieTempFolderPath+fParameterFileName));
2427  }
2428 }
2429 
2430 
2431 // FIXME : does not work on Qt3
2432 void G4OpenGLQtViewer::processEncodeStdout()
2433 {
2434  QString tmp = fProcess->readAllStandardOutput ().data();
2435  int start = tmp.lastIndexOf("ESTIMATED TIME");
2436  tmp = tmp.mid(start,tmp.indexOf("\n",start)-start);
2437  setRecordingInfos(tmp);
2438 }
2439 
2440 
2441 void G4OpenGLQtViewer::processEncodeFinished()
2442 {
2443 
2444  QString txt = "";
2445  txt = getProcessErrorMsg();
2446  if (txt == "") {
2447  setRecordingStatus(SUCCESS);
2448  } else {
2449  setRecordingStatus(FAILED);
2450  }
2451  // setRecordingInfos(txt+removeTempFolder());
2452 }
2453 
2454 
2455 void G4OpenGLQtViewer::processLookForFinished()
2456 {
2457 
2458  QString txt = getProcessErrorMsg();
2459  if (txt != "") {
2460  fEncoderPath = "";
2461  } else {
2462  fEncoderPath = QString(fProcess->readAllStandardOutput ().data()).trimmed();
2463  // if not found, return "not found"
2464  if (fEncoderPath.contains(" ")) {
2465  fEncoderPath = "";
2466  } else if (!fEncoderPath.contains("ppmtompeg")) {
2467  fEncoderPath = "";
2468  }
2469  setEncoderPath(fEncoderPath);
2470  }
2471  // init temp folder
2472  setTempFolderPath(QDir::temp ().absolutePath ());
2473 }
2474 
2475 
2476 QString G4OpenGLQtViewer::getProcessErrorMsg()
2477 {
2478  QString txt = "";
2479  if (fProcess->exitCode() != 0) {
2480  switch (fProcess->error()) {
2481  case QProcess::FailedToStart:
2482  txt = "The process failed to start. Either the invoked program is missing, or you may have insufficient permissions to invoke the program.\n";
2483  break;
2484  case QProcess::Crashed:
2485  txt = "The process crashed some time after starting successfully.\n";
2486  break;
2487  case QProcess::Timedout:
2488  txt = "The last waitFor...() function timed out. The state of QProcess is unchanged, and you can try calling waitFor...() again.\n";
2489  break;
2490  case QProcess::WriteError:
2491  txt = "An error occurred when attempting to write to the process. For example, the process may not be running, or it may have closed its input channel.\n";
2492  break;
2493  case QProcess::ReadError:
2494  txt = "An error occurred when attempting to read from the process. For example, the process may not be running.\n";
2495  break;
2496  case QProcess::UnknownError:
2497  txt = "An unknown error occurred. This is the default return value of error().\n";
2498  break;
2499  }
2500  }
2501  return txt;
2502 }
2503 
2504 
2505 
2506 
2507 QWidget *G4OpenGLQtViewer::getParentWidget()
2508 {
2509  // launch Qt if not
2510  G4Qt* interactorManager = G4Qt::getInstance ();
2511  // G4UImanager* UI =
2512  // G4UImanager::GetUIpointer();
2513 
2514  bool found = false;
2515  QDialog* dialog = NULL;
2516  // create window
2517  if (((QApplication*)interactorManager->GetMainInteractor())) {
2518  // look for the main window
2519  QWidgetList wl = QApplication::allWidgets();
2520  QWidget *widget = NULL;
2521  for (int i=0; i < wl.size(); i++) {
2522  widget = wl.at(i);
2523  if ((found== false) && (widget->inherits("QMainWindow"))) {
2524  dialog = new QDialog(widget,Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowMinMaxButtonsHint);
2525  found = true;
2526  }
2527  }
2528 
2529  if (found==false) {
2530 #ifdef G4DEBUG_VIS_OGL
2531  printf("G4OpenGLQtViewer::CreateMainWindow case Qapp exist, but not found\n");
2532 #endif
2533  dialog = new QDialog();
2534  }
2535  } else {
2536 #ifdef G4DEBUG_VIS_OGL
2537  printf("G4OpenGLQtViewer::CreateMainWindow case Qapp exist\n");
2538 #endif
2539  dialog= new QDialog();
2540 #ifdef G4DEBUG_VIS_OGL
2541  printf("G4OpenGLQtViewer::GetParentWidget fGLWidget\n");
2542 #endif
2543  }
2544  if (found) {
2545  return dialog;
2546  } else {
2547  return NULL;
2548  }
2549 }
2550 
2551 
2552 void G4OpenGLQtViewer::initSceneTreeComponent(){
2553 
2554  QGroupBox *groupBox = new QGroupBox("");
2555  QVBoxLayout *vbox = new QVBoxLayout;
2556 
2557  fSceneTreeViewerButton = new QPushButton("Scene tree");
2558  fSceneTreeViewerButton->setStyleSheet ("text-align: left; padding: 5px; border:0px; ");
2559  fSceneTreeViewerButton->setIcon(*fTreeIconClosed);
2560 
2561  vbox->addWidget(fSceneTreeViewerButton);
2562  connect(fSceneTreeViewerButton,SIGNAL(clicked()),this, SLOT(toggleSceneTreeViewerInfos()));
2563 
2564  fSceneTreeViewerInfos = new QWidget();
2565  fSceneTreeViewerInfos->setStyleSheet ("padding: 0px ");
2566  fSceneTreeViewerInfos->setVisible(false);
2567  fSceneTreeViewerInfos->setSizePolicy(QSizePolicy::Minimum,QSizePolicy::Minimum);
2568 
2569  QVBoxLayout* vLayout = new QVBoxLayout();
2570  fSceneTreeViewerInfos->setLayout (vLayout);
2571 
2572  // Search line
2573  QWidget* coutButtonWidget = new QWidget();
2574  QHBoxLayout* layoutCoutTBButtons = new QHBoxLayout();
2575 
2576  fFilterOutput = new QLineEdit();
2577  fFilterOutput->setToolTip("Filter output by...");
2578  fFilterOutput->setStyleSheet ("padding: 0px ");
2579 
2580  QPixmap* searchIcon = fUiQt->getSearchIcon();
2581 #if QT_VERSION > 0x050100
2582  fFilterOutput->addAction(*searchIcon,QLineEdit::TrailingPosition);
2583  fFilterOutput->setStyleSheet ("border-radius:7px;");
2584 #else
2585  QPushButton *coutTBFilterButton = new QPushButton();
2586  coutTBFilterButton->setIcon(*searchIcon);
2587  coutTBFilterButton->setStyleSheet ("padding-left: 0px; border:0px;");
2588  fFilterOutput->setStyleSheet ("padding-right: 0px;");
2589 #endif
2590  layoutCoutTBButtons->addWidget(fFilterOutput);
2591 
2592 #if QT_VERSION <= 0x050100
2593  layoutCoutTBButtons->addWidget(coutTBFilterButton);
2594 #endif
2595 
2596  coutButtonWidget->setLayout(layoutCoutTBButtons);
2597  vLayout->addWidget(coutButtonWidget);
2598 
2599  // reduce margins
2600  vLayout->setContentsMargins(5,5,5,5);
2601 
2602 
2603  fSceneTreeComponentTreeWidget = new QTreeWidget();
2604  fSceneTreeComponentTreeWidget->setSelectionMode(QAbstractItemView::SingleSelection);
2605  fSceneTreeComponentTreeWidget->setHeaderLabel ("Scene tree : "+QString(GetName().data()));
2606  fSceneTreeComponentTreeWidget->setColumnHidden (1,true); // copy number
2607  fSceneTreeComponentTreeWidget->setColumnHidden (2,true); // PO index
2608  fSceneTreeComponentTreeWidget->setColumnHidden (3,true); // Informations
2609  // data(0) : POindex
2610  // data(1) : copy number
2611  // data(2) : g4color
2612 
2613  vLayout->addWidget(fSceneTreeComponentTreeWidget);
2614 
2615  connect(fSceneTreeComponentTreeWidget,SIGNAL(itemChanged(QTreeWidgetItem*, int)),SLOT(sceneTreeComponentItemChanged(QTreeWidgetItem*, int)));
2616  connect(fSceneTreeComponentTreeWidget,SIGNAL(itemSelectionChanged ()),SLOT(sceneTreeComponentSelected()));
2617  connect(fSceneTreeComponentTreeWidget,SIGNAL(itemDoubleClicked ( QTreeWidgetItem*, int)),SLOT(changeColorAndTransparency( QTreeWidgetItem*, int)));
2618 
2619 
2620  // Depth slider
2621  QWidget *helpWidget = new QWidget();
2622  QHBoxLayout *helpLayout = new QHBoxLayout();
2623 
2624  QWidget* depthWidget = new QWidget();
2625  QWidget *showBox = new QWidget(depthWidget);
2626  QHBoxLayout *showBoxLayout = new QHBoxLayout();
2627 
2628  // reduce margins
2629  showBoxLayout->setContentsMargins(5,5,5,5);
2630 
2631  QLabel *zero = new QLabel();
2632  zero->setText("Show all");
2633  QLabel *one = new QLabel();
2634  one->setText("Hide all");
2635  fSceneTreeDepthSlider = new QSlider ( Qt::Horizontal);
2636  fSceneTreeDepthSlider->setMaximum (1000);
2637  fSceneTreeDepthSlider->setMinimum (0);
2638  fSceneTreeDepthSlider->setTickPosition(QSlider::TicksAbove);
2639  // set a minimum size
2640  fSceneTreeDepthSlider->setMinimumWidth (40);
2641 
2642  showBoxLayout->addWidget(zero);
2643  showBoxLayout->addWidget(fSceneTreeDepthSlider);
2644  showBoxLayout->addWidget(one);
2645 
2646  showBox->setLayout(showBoxLayout);
2647 
2648  helpLayout->addWidget(showBox);
2649  helpWidget->setLayout(helpLayout);
2650  helpLayout->setContentsMargins(0,0,0,0);
2651 
2652  vLayout->addWidget(helpWidget);
2653  QSizePolicy vPolicy = fSceneTreeViewerInfos->sizePolicy();
2654  vPolicy.setVerticalStretch(4);
2655 
2656  vbox->addWidget(fSceneTreeViewerInfos);
2657 
2658  groupBox->setLayout(vbox);
2659  fSceneTreeWidget->layout()->addWidget(groupBox);
2660 
2661  connect( fSceneTreeDepthSlider, SIGNAL( valueChanged(int) ), this, SLOT( changeDepthInSceneTree(int) ) );
2662  fTreeItemModels.clear();
2663 
2664  fPVRootNodeCreate = false;
2665 
2666  fMaxPOindexInserted = -1;
2667 
2668 
2669 }
2670 
2671 
2672 void G4OpenGLQtViewer::initViewerPropertiesComponent() {
2673 
2674  // add properties
2675  QGroupBox *groupBox = new QGroupBox("");
2676  QVBoxLayout *vbox = new QVBoxLayout;
2677  fViewerPropertiesButton = new QPushButton("Viewer properties");
2678  fViewerPropertiesButton->setStyleSheet ("text-align: left; padding: 5px; border:0px; ");
2679  fViewerPropertiesButton->setIcon(*fTreeIconClosed);
2680 
2681  vbox->addWidget(fViewerPropertiesButton);
2682  connect(fViewerPropertiesButton,SIGNAL(clicked()),this, SLOT(toggleSceneTreeComponentTreeWidgetInfos()));
2683 
2684  // add properties content
2685  fSceneTreeComponentTreeWidgetInfos = new QTableWidget();
2686  fSceneTreeComponentTreeWidgetInfos->setVisible(false);
2687  fSceneTreeComponentTreeWidgetInfos->setStyleSheet ("padding: 0px ");
2688  vbox->addWidget(fSceneTreeComponentTreeWidgetInfos);
2689 
2690  groupBox->setLayout(vbox);
2691  fSceneTreeWidget->layout()->addWidget(groupBox);
2692  QSizePolicy vPolicy = fSceneTreeComponentTreeWidgetInfos->sizePolicy();
2693  vPolicy.setVerticalStretch(4);
2694 
2695  connect(fSceneTreeComponentTreeWidgetInfos, SIGNAL(itemChanged(QTableWidgetItem*)),this, SLOT(tableWidgetViewerSetItemChanged(QTableWidgetItem *)));
2696 
2697  updateSceneTreeComponentTreeWidgetInfos();
2698 }
2699 
2700 
2701 void G4OpenGLQtViewer::initPickingComponent(){
2702 
2703  QGroupBox *groupBox = new QGroupBox("");
2704  QVBoxLayout *vbox = new QVBoxLayout;
2705 
2706  // add picking infos
2707  QWidget *pickingInfoWidget = new QWidget();
2708  QHBoxLayout *pickingInfoLayout = new QHBoxLayout();
2709 
2710  fViewerPickingButton = new QPushButton("Picking informations");
2711  fViewerPickingButton->setStyleSheet ("text-align: left; padding: 5px; border:0px; ");
2712  fViewerPickingButton->setIcon(*fTreeIconClosed);
2713 
2714  // initialise picking infos
2715 
2716  QCheckBox * activatePicking = new QCheckBox("Picking mode active");
2717  if (fVP.IsPicking()) {
2718  activatePicking->setCheckState(Qt::Checked);
2719  } else {
2720  activatePicking->setCheckState(Qt::Unchecked);
2721  }
2722  activatePicking->setToolTip("Enable picking allow you to display properties of a selected object on the scene");
2723  connect(activatePicking, SIGNAL(clicked()), this, SLOT(togglePicking()));
2724 
2725  pickingInfoLayout->addWidget(fViewerPickingButton);
2726  pickingInfoLayout->addWidget(activatePicking);
2727 
2728  pickingInfoWidget->setStyleSheet ("padding-left: 0px; border:0px;");
2729  pickingInfoWidget->setLayout(pickingInfoLayout);
2730 
2731  vbox->addWidget(pickingInfoWidget);
2732  connect(fViewerPickingButton,SIGNAL(clicked()),this, SLOT(toggleSceneTreeComponentPickingInfos()));
2733 
2734  // add picking content
2735 
2736  fSceneTreeComponentPickingScrollArea = new QScrollArea();
2737  fSceneTreeComponentPickingScrollArea->setWidgetResizable(true);
2738 
2739 
2740  fSceneTreeComponentPickingInfos = new QWidget();
2741  fSceneTreeComponentPickingInfos->setStyleSheet ("padding: 0px ");
2742  fSceneTreeComponentPickingScrollArea->setVisible(false);
2743 
2744 
2745  QVBoxLayout* vLayout = new QVBoxLayout();
2746  fSceneTreeComponentPickingInfos->setLayout (vLayout);
2747  fSceneTreeComponentPickingScrollArea->setWidget(fSceneTreeComponentPickingInfos);
2748 
2749  QSizePolicy vPolicy = fSceneTreeComponentPickingInfos->sizePolicy();
2750  vPolicy.setVerticalStretch(4);
2751  vbox->addWidget(fSceneTreeComponentPickingScrollArea);
2752 
2753  groupBox->setLayout(vbox);
2754  fSceneTreeWidget->layout()->addWidget(groupBox);
2755  connect( fFilterOutput, SIGNAL( textEdited ( const QString &) ), this, SLOT(changeSearchSelection()));
2756 
2757 }
2758 
2759 
2760 // set the component to check/unchecked, also go into its child
2761 // and set the same status to all his childs
2762 void G4OpenGLQtViewer::setCheckComponent(QTreeWidgetItem* item,bool check)
2763 {
2764  if (item != NULL) {
2765  if (check) {
2766  item->setCheckState(0,Qt::Checked);
2767  } else {
2768  item->setCheckState(0,Qt::Unchecked);
2769  }
2770  updatePositivePoIndexSceneTreeWidgetQuickMap(item->data(0,Qt::UserRole).toInt(),item);
2771  int nChildCount = item->childCount();
2772  for (int i = 0; i < nChildCount; i++) {
2773  setCheckComponent(item->child(i),check);
2774  }
2775  }
2776 }
2777 
2778 
2779 void G4OpenGLQtViewer::DrawText(const G4Text& g4text)
2780 {
2781  QGLWidget* qGLW = dynamic_cast<QGLWidget*> (fGLWidget) ;
2782  if (! qGLW) {
2783  return;
2784  }
2785  if (isGl2psWriting()) {
2786 
2787  G4OpenGLViewer::DrawText(g4text);
2788 
2789  } else {
2790 
2791  if (!fGLWidget) return;
2792 
2794  G4double size = fSceneHandler.GetMarkerSize(g4text,sizeType);
2795 
2796  QFont font = QFont();
2797  font.setPointSizeF(size);
2798 
2799  const G4Colour& c = fSceneHandler.GetTextColour(g4text);
2800  glColor4d(c.GetRed(),c.GetGreen(),c.GetBlue(),c.GetAlpha());
2801 
2802  G4Point3D position = g4text.GetPosition();
2803 
2804  const G4String& textString = g4text.GetText();
2805  const char* textCString = textString.c_str();
2806 
2807  glRasterPos3d(position.x(),position.y(),position.z());
2808 
2809  // Calculate move for centre and right adjustment
2810  QFontMetrics* f = new QFontMetrics (font);
2811  G4double span = f->width(textCString);
2812  G4double xmove = 0., ymove = 0.;
2813  switch (g4text.GetLayout()) {
2814  case G4Text::left: break;
2815  case G4Text::centre: xmove -= span / 2.; break;
2816  case G4Text::right: xmove -= span;
2817  }
2818 
2819  //Add offsets
2820  xmove += g4text.GetXOffset();
2821  ymove += g4text.GetYOffset();
2822 
2823  qGLW->renderText
2824  ((position.x()+(2*xmove)/getWinWidth()),
2825  (position.y()+(2*ymove)/getWinHeight()),
2826  position.z(),
2827  textCString,
2828  font);
2829 
2830  }
2831 }
2832 
2833 
2834 void G4OpenGLQtViewer::ResetView () {
2835  G4OpenGLViewer::ResetView();
2836  fDeltaDepth = 0.01;
2837  fDeltaZoom = 0.05;
2838 }
2839 
2840 
2841 
2842 
2843 void G4OpenGLQtViewer::addPVSceneTreeElement(const G4String& model, G4PhysicalVolumeModel* pPVModel, int currentPOIndex) {
2844 
2845  const QString& modelShortName = getModelShortName(model);
2846 
2847  if (modelShortName == "") {
2848  return ;
2849  }
2850  // try to init it
2851  if (fSceneTreeComponentTreeWidget == NULL) {
2852  initSceneTreeComponent();
2853  }
2854 
2855  // if no UI
2856  if (fSceneTreeComponentTreeWidget == NULL) {
2857  return;
2858  }
2859 
2860  fSceneTreeComponentTreeWidget->blockSignals(true);
2861 
2862  // Create the "volume" node if not
2863  // if (fSceneTreeComponentTreeWidget->topLevelItemCount () == 0) {
2864  if (!fPVRootNodeCreate) {
2865  const G4VisAttributes* visAttr = GetApplicableVisAttributes(pPVModel->GetFullPVPath().at(0).GetPhysicalVolume()->GetLogicalVolume()->GetVisAttributes());
2866  const G4Colour& color = visAttr->GetColour();
2867 
2868  fModelShortNameItem = createTreeWidgetItem(pPVModel->GetFullPVPath(),
2869  modelShortName,
2870  0, // currentPVCopyNb
2871  -1, // currentPVPOIndex
2872  "",
2873  Qt::Checked,
2874  NULL,
2875  color);
2876  fPVRootNodeCreate = true;
2877  }
2878 
2879  bool added = parseAndInsertInSceneTree(fModelShortNameItem,pPVModel,0,modelShortName,0,currentPOIndex);
2880  if (!added) {
2881  }
2882 
2883  fSceneTreeComponentTreeWidget->blockSignals(false);
2884 
2885 }
2886 
2887 
2892 QTreeWidgetItem* G4OpenGLQtViewer::createTreeWidgetItem(
2893  const PVPath& fullPath
2894  ,const QString& name
2895  ,int copyNb
2896  ,int POIndex
2897  ,const QString& logicalName
2898  ,Qt::CheckState state
2899  ,QTreeWidgetItem * parentTreeNode
2900  ,const G4Colour& color
2901 ) {
2902 
2903  // Set depth
2904  if (fullPath.size() > fSceneTreeDepth) {
2905  fSceneTreeDepth = fullPath.size();
2906  // Change slider value
2907  if (fSceneTreeDepthSlider) {
2908  fSceneTreeDepthSlider->setTickInterval(1000/(fSceneTreeDepth+1));
2909  }
2910  }
2911  QTreeWidgetItem * newItem = NULL;
2912  if (parentTreeNode == NULL) {
2913  newItem = new QTreeWidgetItem();
2914  fSceneTreeComponentTreeWidget->addTopLevelItem(newItem);
2915  } else {
2916  newItem = new QTreeWidgetItem(parentTreeNode);
2917  fSceneTreeComponentTreeWidget->addTopLevelItem(parentTreeNode);
2918  }
2919 
2920 
2921  newItem->setText(0,name);
2922  newItem->setData(1,Qt::UserRole,copyNb);
2923  newItem->setText(2,QString::number(POIndex));
2924  newItem->setData(0, Qt::UserRole, POIndex);
2925  newItem->setText(3,logicalName);
2926  newItem->setFlags(newItem->flags()|Qt::ItemIsUserCheckable);
2927  newItem->setCheckState(0,state);
2928  newItem->setExpanded(true);
2929  updatePositivePoIndexSceneTreeWidgetQuickMap(POIndex,newItem);
2930 
2931  changeQColorForTreeWidgetItem(newItem,QColor((int)(color.GetRed()*255),
2932  (int)(color.GetGreen()*255),
2933  (int)(color.GetBlue()*255),
2934  (int)(color.GetAlpha()*255)));
2935 
2936  // If invisible
2937  if ((state == Qt::Unchecked) && (POIndex == -1)) {
2938  newItem->setForeground (0, QBrush( Qt::gray) );
2939 
2940  // Set a tootip
2941  newItem->setToolTip (0,QString(
2942  "This node exists in the geometry but has not been\n")+
2943  "drawn, perhaps because it has been set invisible. It \n"+
2944  "cannot be made visible with a click on the button.\n"+
2945  "To see it, change the visibility, for example, with \n"+
2946  "/vis/geometry/set/visibility " + logicalName + " 0 true\n"+
2947  "and rebuild the view with /vis/viewer/rebuild.\n"+
2948  "Click here will only show/hide all child components");
2949  } else {
2950  // Set a tootip
2951  newItem->setToolTip (0,QString("double-click to change the color"));
2952  }
2953 
2954  // special case: if alpha=0, it is a totally transparent objet,
2955  // then, do not redraw it
2956  if (color.GetAlpha() == 0) {
2957  state = Qt::Unchecked;
2958  newItem->setCheckState(0,state);
2959  updatePositivePoIndexSceneTreeWidgetQuickMap(POIndex,newItem);
2960  }
2961 
2962  fTreeItemModels.insert(std::pair <int, PVPath > (POIndex,fullPath) );
2963 
2964  // Check last status of this item and change if necessary
2965  // open/close/hidden/visible/selected
2966  changeOpenCloseVisibleHiddenSelectedColorSceneTreeElement(newItem);
2967  return newItem;
2968 }
2969 
2970 
2971 //
2972 // Recursive function.
2973 // Try to insert the given item :
2974 // - If not present and last item of the path: insert it and mark it CHECK
2975 // - If not present and NOT last item of the path: insert it and mark it UNCHECKED
2976 // - If already present and name/PO/Transformation identical, then it is a transparent
2977 // object : Change the PO number and transparency
2978 // - If already present and PO different, then it is an unvisible item : Have to
2979 // set it visible
2980 // - else : Create a new element
2981 // @return true if inserted, false if already present
2982 //
2983 bool G4OpenGLQtViewer::parseAndInsertInSceneTree(
2984  QTreeWidgetItem * parentItem
2985  ,G4PhysicalVolumeModel* pPVModel
2986  ,unsigned int fullPathIndex
2987  ,const QString& parentRoot
2988  ,unsigned int currentIndexInTreeSceneHandler
2989  ,int currentPVPOIndex
2990 ) {
2991 
2992  if (parentItem == NULL) {
2993  return false;
2994  }
2995 
2996  const PVPath& fullPath = pPVModel->GetFullPVPath();
2997 
2998  std::ostringstream oss;
2999  oss << fullPath.at(fullPathIndex).GetCopyNo();
3000  std::string currentPVName = G4String(fullPath.at(fullPathIndex).GetPhysicalVolume()->GetName()+" ["+oss.str()+"]").data();
3001 
3002  int currentPVCopyNb = fullPath.at(fullPathIndex).GetCopyNo();
3003 
3004  const G4VisAttributes* visAttr = GetApplicableVisAttributes(fullPath.at(fullPathIndex).GetPhysicalVolume()->GetLogicalVolume()->GetVisAttributes());
3005  const G4Colour& color = visAttr->GetColour();
3006 
3007  // look in all children in order to get if their is already a
3008  // child corresponding:
3009  // - if so, go into this child
3010  // - if not : create it as invisible
3011 
3012  // Realy quick check if the POindex is already there
3013  QTreeWidgetItem* subItem = NULL;
3014  QList<QTreeWidgetItem *> parentItemList;
3015 
3016 
3017  // first of all, very quick check if it was not the same as last one
3018 
3019  // Check only if it is a transparent object
3020  // If it is the last item and it is not transparent -> nothing to look for,
3021  // simply add it.
3022  if ((currentIndexInTreeSceneHandler == (fullPath.size()-1)) && ((color.GetAlpha() == 1.))) {
3023  } else {
3024  QString lookForString = QString(currentPVName.c_str());
3025  for (int i = 0;i < parentItem->childCount(); i++ ) {
3026  if (parentItem->child(i)->text(0) == lookForString) {
3027  parentItemList.push_back(parentItem->child(i));
3028  }
3029  }
3030  }
3031 
3032  for (int i = 0; i < parentItemList.size(); ++i) {
3033  const std::string& parentItemName = parentItemList.at(i)->text(0).toStdString();
3034  int parentItemCopyNb = parentItemList.at(i)->data(1,Qt::UserRole).toInt();
3035  int parentItemPOIndex = parentItemList.at(i)->data(0,Qt::UserRole).toInt();
3036 
3037  // if already inside
3038  // -> return true
3039  // special case, do not have to deal with hierarchy except for PhysicalVolume
3040 
3041 
3042  /* Physical Volume AND copy number equal AND name equal */
3043  if (((parentRoot == fTouchableVolumes) && (currentPVCopyNb == parentItemCopyNb)
3044  && (currentPVName == parentItemName)) ||
3045  /* NOT a Physical Volume AND copy number equal */
3046  ((parentRoot != fTouchableVolumes) && (currentPVCopyNb == parentItemCopyNb)
3047  /*AND name equal AND PO index equal*/
3048  && (currentPVName == parentItemName) && (currentPVPOIndex == parentItemPOIndex) )) {
3049 
3050  // then check for the Transform3D
3051  bool sameTransform = true;
3052  if (parentItemPOIndex >= 0) {
3053  const PVPath& fullPathTmp = fTreeItemModels[parentItemPOIndex];
3054  if (fullPathTmp.size() > 0) {
3055  if (fullPathTmp.at(fullPathTmp.size()-1).GetTransform () == pPVModel->GetTransformation ()) {
3056  sameTransform = true;
3057  } else {
3058  sameTransform = false;
3059  }
3060  }
3061  }
3062 
3063  // Same transformation, then try to change the PO index
3064  if (sameTransform == true) {
3065  // already exist in the tree, is it a transparent object ?
3066  // If so, then have to change the PO index ONLY if it is the last
3067  // and then change the state ONLY if POIndex has change
3068  // If not, then go deaper
3069 
3070  // last element
3071  if (currentIndexInTreeSceneHandler == (fullPath.size()-1)) {
3072 
3073  parentItemList.at(i)->setText(2,QString::number(currentPVPOIndex));
3074  parentItemList.at(i)->setData(0, Qt::UserRole,currentPVPOIndex);
3075 
3076  fTreeItemModels.insert(std::pair <int, PVPath >(currentPVPOIndex,fullPath) );
3077 
3078  // Then remove tooltip and special font
3079  QFont f = QFont();
3080  parentItemList.at(i)->setFont (0,f);
3081 
3082  // set foreground
3083  parentItemList.at(i)->setForeground (0,QBrush());
3084 
3085  // Set a tootip
3086  parentItemList.at(i)->setToolTip (0,"");
3087 
3088  changeQColorForTreeWidgetItem(parentItemList.at(i),QColor((int)(color.GetRed()*255),
3089  (int)(color.GetGreen()*255),
3090  (int)(color.GetBlue()*255),
3091  (int)(color.GetAlpha()*255)));
3092 
3093  // set check only if there is something to display
3094  if (color.GetAlpha() > 0) {
3095  parentItemList.at(i)->setCheckState(0,Qt::Checked);
3096  updatePositivePoIndexSceneTreeWidgetQuickMap(currentPVPOIndex,parentItemList.at(i));
3097  }
3098  return false;
3099  } else {
3100  subItem = parentItemList.at(i);
3101  }
3102 
3103  // Exists but not the end of path, then forget get it
3104  } else if (currentIndexInTreeSceneHandler < (fullPath.size()-1)) {
3105  subItem = parentItemList.at(i);
3106  }
3107  }
3108 
3109  } // end for
3110 
3111  // if it the last, then add it and set it checked
3112  if (currentIndexInTreeSceneHandler == (fullPath.size()-1)) {
3113  /* subItem =*/ createTreeWidgetItem(fullPath,
3114  QString(currentPVName.c_str()),
3115  currentPVCopyNb,
3116  currentPVPOIndex,
3117  QString(fullPath.at(fullPathIndex).GetPhysicalVolume()->GetLogicalVolume()->GetName().data()),
3118  Qt::Checked,
3119  parentItem,
3120  color);
3121 
3122  if (currentPVPOIndex > fMaxPOindexInserted) {
3123  fMaxPOindexInserted = currentPVPOIndex;
3124  }
3125 
3126  } else {
3127 
3128  // if no child found, then this child is create and marked as invisible, then go inside
3129  if (subItem == NULL) {
3130 
3131  if (currentIndexInTreeSceneHandler < (fullPath.size()-1)) {
3132  subItem = createTreeWidgetItem(fullPath,
3133  QString(currentPVName.c_str()),
3134  currentPVCopyNb,
3135  -1,
3136  QString(fullPath.at(fullPathIndex).GetPhysicalVolume()->GetLogicalVolume()->GetName().data()),
3137  Qt::Unchecked,
3138  parentItem,
3139  color);
3140  }
3141  }
3142 
3143  return parseAndInsertInSceneTree(subItem,pPVModel,fullPathIndex+1,parentRoot,currentIndexInTreeSceneHandler+1,currentPVPOIndex);
3144  }
3145  return true;
3146 }
3147 
3148 
3149 void G4OpenGLQtViewer::changeOpenCloseVisibleHiddenSelectedColorSceneTreeElement(
3150  QTreeWidgetItem* subItem
3151 )
3152 {
3153  // Check if object with the same POIndex is the same in old tree
3154  QTreeWidgetItem* oldItem = NULL;
3155 
3156  QTreeWidgetItem* foundItem = getOldTreeWidgetItem(subItem->data(0,Qt::UserRole).toInt());
3157 
3158  if (foundItem != NULL) {
3159  if (isSameSceneTreeElement(foundItem,subItem)) {
3160  oldItem = foundItem;
3161  }
3162  }
3163  if (foundItem == NULL) { // PO should have change, parse all
3164 
3165  // POindex > 0
3166  std::map <int, QTreeWidgetItem*>::const_iterator i;
3167  i = fOldPositivePoIndexSceneTreeWidgetQuickMap.begin();
3168  while (i != fOldPositivePoIndexSceneTreeWidgetQuickMap.end()) {
3169  if (isSameSceneTreeElement(i->second,subItem)) {
3170  oldItem = i->second;
3171  i = fOldPositivePoIndexSceneTreeWidgetQuickMap.end();
3172  } else {
3173  i++;
3174  }
3175  }
3176  // POindex == 0 ?
3177  if (oldItem == NULL) {
3178  unsigned int a = 0;
3179  while (a < fOldNullPoIndexSceneTreeWidgetQuickVector.size()) {
3180  if (isSameSceneTreeElement(fOldNullPoIndexSceneTreeWidgetQuickVector[a],subItem)) {
3181  oldItem = fOldNullPoIndexSceneTreeWidgetQuickVector[a];
3182  a = fOldNullPoIndexSceneTreeWidgetQuickVector.size();
3183  } else {
3184  a++;
3185  }
3186  }
3187  }
3188  }
3189 
3190  // if found : retore old state
3191  if (oldItem != NULL) {
3192  subItem->setFlags(oldItem->flags()); // flags
3193  subItem->setCheckState(0,oldItem->checkState(0)); // check state
3194  subItem->setSelected(oldItem->isSelected()); // selected
3195  subItem->setExpanded(oldItem->isExpanded ()); // expand
3196 
3197  // change color
3198  // when we call this function, the color in the item is the one of vis Attr
3199 
3200  std::map <int, QTreeWidgetItem* >::iterator it;
3201 
3202  // getOldPO
3203  int oldPOIndex = oldItem->data(0,Qt::UserRole).toInt();
3204  it = fOldPositivePoIndexSceneTreeWidgetQuickMap.find(oldPOIndex);
3205  QColor color;
3206 
3207  // get old Vis Attr Color
3208  std::map <int, QColor >::iterator itVis;
3209  itVis = fOldVisAttrColorMap.find(oldPOIndex);
3210 
3211  QColor oldVisAttrColor;
3212  const QColor& newVisAttrColor = subItem->data(2,Qt::UserRole).value<QColor>();
3213 
3214  bool visAttrChange = false;
3215  // if old vis attr color found
3216  if (itVis != fOldVisAttrColorMap.end()) {
3217  oldVisAttrColor = itVis->second;
3218  if (oldVisAttrColor != newVisAttrColor) {
3219  visAttrChange = true;
3220  }
3221  } else {
3222  visAttrChange = true;
3223  }
3224 
3225  if (visAttrChange) {
3226  fOldVisAttrColorMap.insert(std::pair <int, QColor > (subItem->data(0,Qt::UserRole).toInt(),newVisAttrColor) );
3227 
3228  } else { // if no changes, get old PO value
3229  // if old PO found
3230  if (it != fOldPositivePoIndexSceneTreeWidgetQuickMap.end()) {
3231  color = (it->second)->data(2,Qt::UserRole).value<QColor>();
3232  } else {
3233  color = oldItem->data(2,Qt::UserRole).value<QColor>();
3234  }
3235 #ifdef G4DEBUG_VIS_OGL
3236  printf("====color name:%s\n",color.name().toStdString().c_str());
3237 #endif
3238  changeQColorForTreeWidgetItem(subItem,color);
3239  }
3240  }
3241 
3242  return;
3243 }
3244 
3245 
3246 
3247 // Check if both items are identical.
3248 // For that, check name, copy number, transformation
3249 // special case for "non Touchables", do not check the PO index, check only the name
3250 bool G4OpenGLQtViewer::isSameSceneTreeElement(
3251  QTreeWidgetItem* parentOldItem
3252  ,QTreeWidgetItem* parentNewItem
3253 ) {
3254 
3255  int newPO = -1;
3256  int oldPO = -1;
3257 
3258  int newCpNumber = -1;
3259  int oldCpNumber = -1;
3260 
3261  bool firstWhile = true;
3262 
3263  while ((parentOldItem != NULL) && (parentNewItem != NULL)) {
3264 
3265  // check transform, optimize getting data(..,..) that consume lot of time
3266  if (!firstWhile) {
3267  oldPO = parentOldItem->data(0,Qt::UserRole).toInt();
3268  newPO = parentNewItem->data(0,Qt::UserRole).toInt();
3269  }
3270  firstWhile = false;
3271 
3272  if ((oldPO >= 0) &&
3273  (newPO >= 0)) {
3274  const PVPath& oldFullPath = fOldTreeItemModels[oldPO];
3275  const PVPath& newFullPath = fTreeItemModels[newPO];
3276  if ((oldFullPath.size() > 0) &&
3277  (newFullPath.size() > 0)) {
3278  if (oldFullPath.size() != newFullPath.size()) {
3279  return false;
3280  }
3281  if (oldFullPath.at(oldFullPath.size()-1).GetTransform () == newFullPath.at(newFullPath.size()-1).GetTransform ()) {
3282  newCpNumber = newFullPath.at(newFullPath.size()-1).GetCopyNo();
3283  oldCpNumber = oldFullPath.at(oldFullPath.size()-1).GetCopyNo();
3284  // ok
3285  } else {
3286  return false;
3287  }
3288  }
3289  }
3290 
3291  // Check copy Number
3292  if (oldCpNumber == -1) {
3293  oldCpNumber = parentOldItem->data(1,Qt::UserRole).toInt();
3294  }
3295  if (newCpNumber == -1) {
3296  newCpNumber = parentNewItem->data(1,Qt::UserRole).toInt();
3297  }
3298  if ((oldCpNumber != newCpNumber) ||
3299  // Check name
3300  (parentOldItem->text(0) != parentNewItem->text(0)) ) {
3301  // try to optimize
3302  return false;
3303  } else if ((parentOldItem->text(0) != parentNewItem->text(0)) || // Logical Name
3304  (parentOldItem->text(3) != parentNewItem->text(3))) { // Check logical name
3305  return false;
3306  } else {
3307  parentOldItem = parentOldItem->parent();
3308  parentNewItem = parentNewItem->parent();
3309  }
3310  } // end while
3311 
3312  return true;
3313 }
3314 
3315 
3316 void G4OpenGLQtViewer::addNonPVSceneTreeElement(
3317  const G4String& model
3318  ,int currentPOIndex
3319  ,const std::string& modelDescription
3320  ,const G4Visible& visible
3321 ) {
3322 
3323  QString modelShortName = getModelShortName(model);
3324  G4Colour color;
3325 
3326  // Special case for text
3327  try {
3328  const G4Text& g4Text = dynamic_cast<const G4Text&>(visible);
3329  color = fSceneHandler.GetTextColour(g4Text);
3330  }
3331  catch (std::bad_cast) {
3332  color = fSceneHandler.GetColour(visible);
3333  }
3334  if (modelShortName == "") {
3335  return ;
3336  }
3337  // try to init it
3338  if (fSceneTreeComponentTreeWidget == NULL) {
3339  initSceneTreeComponent();
3340  }
3341 
3342  // if no UI
3343  if (fSceneTreeComponentTreeWidget == NULL) {
3344  return;
3345  }
3346 
3347  fSceneTreeComponentTreeWidget->blockSignals(true);
3348 
3349  // Create the "Model" node if not
3350 
3351  QList<QTreeWidgetItem *> resItem;
3352  resItem = fSceneTreeComponentTreeWidget->findItems (modelShortName, Qt::MatchExactly, 0 );
3353  QTreeWidgetItem * currentItem = NULL;
3354  const PVPath tmpFullPath;
3355 
3356  if (resItem.empty()) {
3357  currentItem = createTreeWidgetItem(tmpFullPath,
3358  modelShortName,
3359  0, // currentPVCopyNb
3360  -1, // currentPVPOIndex
3361  "",
3362  Qt::Checked,
3363  NULL,
3364  color);
3365  } else {
3366  currentItem = resItem.first();
3367  }
3368 
3369  // Is this volume already in the tree AND PO is not the same?
3370  const QList<QTreeWidgetItem *>&
3371  resItems = fSceneTreeComponentTreeWidget->findItems (QString(modelDescription.c_str()), Qt::MatchFixedString| Qt::MatchCaseSensitive|Qt::MatchRecursive, 0 );
3372 
3373  bool alreadyPresent = false;
3374  for (int i = 0; i < resItems.size(); ++i) {
3375  if (currentPOIndex == resItems.at(i)->data(0,Qt::UserRole).toInt()) {
3376  alreadyPresent = true;
3377  }
3378  }
3379  if (!alreadyPresent) {
3380  createTreeWidgetItem(tmpFullPath,
3381  QString(modelDescription.c_str()),
3382  0, // currentPVCopyNb
3383  currentPOIndex,
3384  "",
3385  Qt::Checked,
3386  currentItem,
3387  color);
3388  }
3389  fSceneTreeComponentTreeWidget->blockSignals(false);
3390 
3391 }
3392 
3393 
3397 QString G4OpenGLQtViewer::getModelShortName(const G4String& model) {
3398 
3399  QString modelShortName = model.data();
3400  if (modelShortName.mid(0,modelShortName.indexOf(" ")) == "G4PhysicalVolumeModel") {
3401  modelShortName = fTouchableVolumes;
3402  } else {
3403  if (modelShortName.mid(0,2) == "G4") {
3404  modelShortName = modelShortName.mid(2);
3405  }
3406  if (modelShortName.indexOf("Model") != -1) {
3407  modelShortName = modelShortName.mid(0,modelShortName.indexOf("Model"));
3408  }
3409  }
3410  return modelShortName;
3411 }
3412 
3413 
3414 
3415 bool G4OpenGLQtViewer::isTouchableVisible(int POindex){
3416 
3417  // If no scene tree (Immediate viewer)
3418  if (fSceneTreeComponentTreeWidget == NULL) {
3419  return false;
3420  }
3421 
3422  // should be the next one
3423  // Prevent to get out the std::map
3424  if (fLastSceneTreeWidgetAskForIterator != fLastSceneTreeWidgetAskForIteratorEnd) {
3425  fLastSceneTreeWidgetAskForIterator++;
3426  }
3427  QTreeWidgetItem* item = getTreeWidgetItem(POindex);
3428 
3429  if (item != NULL) {
3430  if ( item->checkState(0) == Qt::Checked) {
3431  return true;
3432  }
3433  }
3434  return false;
3435 }
3436 
3437 
3438 bool G4OpenGLQtViewer::parseAndCheckVisibility(QTreeWidgetItem * treeNode,int POindex){
3439  bool isFound = false;
3440  for (int i = 0; i < treeNode->childCount() ; ++i) {
3441 
3442  if (treeNode->child(i)->data(0,Qt::UserRole).toInt() == POindex) {
3443  if (treeNode->child(i)->checkState(0) == Qt::Checked) {
3444  return true;
3445  }
3446  }
3447  isFound = parseAndCheckVisibility(treeNode->child(i),POindex);
3448  if (isFound) {
3449  return true;
3450  }
3451  } // end for
3452  return false;
3453 }
3454 
3455 
3456 std::string G4OpenGLQtViewer::parseSceneTreeAndSaveState(){
3457  std::string commandLine = "";
3458  for (int b=0;b<fSceneTreeComponentTreeWidget->topLevelItemCount();b++) {
3459  commandLine += parseSceneTreeElementAndSaveState(fSceneTreeComponentTreeWidget->topLevelItem(b),1)+"\n";
3460  }
3461  if (commandLine != "") {
3462  commandLine = std::string("# Disable auto refresh and quieten vis messages whilst scene and\n") +
3463  "# trajectories are established:\n" +
3464  "/vis/viewer/set/autoRefresh false\n" +
3465  "/vis/verbose errors" +
3466  commandLine +
3467  "# Re-establish auto refreshing and verbosity:\n" +
3468  "/vis/viewer/set/autoRefresh true\n" +
3469  "/vis/verbose confirmations\n";
3470  }
3471  return commandLine;
3472 }
3473 
3474 
3475 std::string G4OpenGLQtViewer::parseSceneTreeElementAndSaveState(QTreeWidgetItem* item, unsigned int level){
3476  // parse current item
3477  std::string str( level, ' ' );
3478  std::string commandLine = "\n#"+ str + "PV Name: " + item->text(0).toStdString();
3479 
3480  if (item->text(3) != "") {
3481  commandLine += " LV Name: "+item->text(3).toStdString()+"\n";
3482  // save check state
3483  commandLine += "/vis/geometry/set/visibility " + item->text(3).toStdString() + " ! "; // let default value for depth
3484  if (item->checkState(0) == Qt::Checked) {
3485  commandLine += "1";
3486  }
3487  if (item->checkState(0) == Qt::Unchecked) {
3488  commandLine += "0";
3489  }
3490  commandLine +="\n";
3491 
3492  // save color
3493  const QColor& c = item->data(2,Qt::UserRole).value<QColor>();
3494  std::stringstream red;
3495  red << ((double)c.red())/255;
3496  std::stringstream green;
3497  green << (double)c.green()/255;
3498  std::stringstream blue;
3499  blue << ((double)c.blue())/255;
3500  std::stringstream alpha;
3501  alpha << ((double)c.alpha())/255;
3502 
3503  commandLine += "/vis/geometry/set/colour " + item->text(3).toStdString() + " ! " + red.str() + " " + green.str() + " " + blue.str() + " " + alpha.str()+"\n";
3504 
3505  } else {
3506  commandLine += "\n";
3507  }
3508 
3509  // parse childs
3510  for (int b=0;b< item->childCount();b++) {
3511  commandLine += parseSceneTreeElementAndSaveState(item->child(b),level+1);
3512  }
3513 
3514  return commandLine;
3515 }
3516 
3517 
3518 void G4OpenGLQtViewer::sceneTreeComponentItemChanged(QTreeWidgetItem* item, int) {
3519 
3520  if (fCheckSceneTreeComponentSignalLock == false) {
3521  fCheckSceneTreeComponentSignalLock = true;
3522  G4bool checked = false;
3523  if (item->checkState(0) == Qt::Checked) {
3524  checked = true;
3525  }
3526  setCheckComponent(item,checked);
3527  updateQWidget();
3528 
3529  fCheckSceneTreeComponentSignalLock = false;
3530  }
3531 }
3532 
3533 
3534 void G4OpenGLQtViewer::sceneTreeComponentSelected() {
3535  /*
3536  if (fSceneTreeComponentTreeWidget) {
3537  if (! fSceneTreeComponentTreeWidget->selectedItems().isEmpty ()) {
3538  QTreeWidgetItem* item = fSceneTreeComponentTreeWidget->selectedItems ().first();
3539  if (item) {
3540 
3541  const PVPath& fullPath = fTreeItemModels[item->data(0,Qt::UserRole).toInt()];
3542  if (fullPath.size() > 0) {
3543  const G4VisAttributes* visAttr2 = GetApplicableVisAttributes(fullPath.at(fullPath.size()-1).GetPhysicalVolume()->GetLogicalVolume()->GetVisAttributes());
3544  }
3545  }
3546  }
3547  }
3548  */
3549 }
3550 
3551 
3552 void G4OpenGLQtViewer::changeDepthInSceneTree (int val){
3553 
3554  // If no scene tree (Immediate viewer)
3555  if (fSceneTreeComponentTreeWidget == NULL) {
3556  return;
3557  }
3558 
3559  // max depth : fSceneTreeDepth
3560  // val is between 0 and 1
3561  // 0 .1 .2 .3 .4 .5 .6 .7 .8 .9 1
3562  // 1 1.4 2
3563  // 1 2 3 4
3564 
3565  // Get the depth :
3566  double depth = 1 + ((double)val)/1000 * ((double)fSceneTreeDepth+1);
3567 
3568  // lock update on scene tree items
3569  fCheckSceneTreeComponentSignalLock = true;
3570 
3571  // Disable redraw each time !
3572  G4bool currentAutoRefresh = fVP.IsAutoRefresh();
3573  fVP.SetAutoRefresh(false);
3574 
3575  for (int b=0;b<fSceneTreeComponentTreeWidget->topLevelItemCount();b++) {
3576  changeDepthOnSceneTreeItem(depth,1.,fSceneTreeComponentTreeWidget->topLevelItem(b));
3577  }
3578 
3579  // Enable redraw !
3580  fVP.SetAutoRefresh(currentAutoRefresh);
3581  updateQWidget();
3582 
3583  // unlock update on scene tree items
3584  fCheckSceneTreeComponentSignalLock = false;
3585 
3586 }
3587 
3588 
3589 void G4OpenGLQtViewer::changeColorAndTransparency(QTreeWidgetItem* item,int) {
3590 
3591  if (item == NULL) {
3592  return;
3593  }
3594  const QColor& old = QColor(item->data(2,Qt::UserRole).value<QColor>());
3595 
3596 #if QT_VERSION < 0x040500
3597  bool a;
3598  const QColor& color = QColor(QColorDialog::getRgba (old.rgba(),&a,fSceneTreeComponentTreeWidget));
3599 #else
3600  const QColor& color = QColorDialog::getColor(old,
3601  fSceneTreeComponentTreeWidget,
3602  " Get color and transparency",
3603  QColorDialog::ShowAlphaChannel);
3604 #endif
3605 
3606  if (color.isValid()) {
3607 
3608  changeColorAndTransparency(item->data(0,Qt::UserRole).toInt(),
3609  G4Colour (((G4double)color.red())/255,
3610  ((G4double)color.green())/255,
3611  ((G4double)color.blue())/255,
3612  ((G4double)color.alpha())/255));
3613 
3614  // set scene tree parameters
3615  changeQColorForTreeWidgetItem(item,color);
3616  }
3617 }
3618 
3619 
3620 void G4OpenGLQtViewer::changeColorAndTransparency(GLuint index, G4Color color) {
3621 
3622  // change vis attributes to set new colour
3623  G4int iPO = index;
3624  if (iPO >= 0 && fTreeItemModels.find(iPO) != fTreeItemModels.end()) {
3625  const PVPath& fullPath = fTreeItemModels[iPO];
3626  // If a physical volume
3627  if (fullPath.size()) {
3628 
3629  // Instantiate a working copy of a G4VisAttributes object...
3630  G4VisAttributes workingVisAtts;
3631  // and set the colour.
3632  workingVisAtts.SetColour(color);
3633 
3634  // Add a vis atts modifier to the view parameters...
3635  fVP.AddVisAttributesModifier
3637  (workingVisAtts,
3639  fullPath));
3640  // G4ModelingParameters::VASColour tells G4PhysicalVolumeModel that it is
3641  // the colour that should be picked out and merged with the touchable's
3642  // normal vis attributes.
3643  }
3644  }
3645 }
3646 
3647 
3648 G4Colour G4OpenGLQtViewer::getColorForPoIndex(int poIndex) {
3649  // FIXME 09/2014 : Could be optimize by searching in a tab instead of item->data
3650  QTreeWidgetItem* item = getTreeWidgetItem(poIndex);
3651 
3652  if (item != NULL) {
3653 
3654  const QColor& color = item->data(2,Qt::UserRole).value<QColor>();
3655  G4Colour g4c(((G4double)color.red())/255,
3656  ((G4double)color.green())/255,
3657  ((G4double)color.blue())/255,
3658  ((G4double)color.alpha())/255);
3659 
3660  return g4c;
3661  }
3662  return G4Colour();
3663 }
3664 
3665 
3666 const std::vector<G4ModelingParameters::VisAttributesModifier>*
3667 G4OpenGLQtViewer::GetPrivateVisAttributesModifiers() const
3668 {
3669  static std::vector<G4ModelingParameters::VisAttributesModifier>
3670  privateVisAttributesModifiers;
3671 
3672  privateVisAttributesModifiers.clear();
3673 
3674 // // For each modified touchable...
3675 // std::map<int,PVPath>::const_iterator i;
3676 // for (i = fTreeItemModels.begin();
3677 // i != fTreeItemModels.end();
3678 // ++i) {
3679 //
3680 // // How do I know if it's been modified or not?
3681 //
3682 // int iPO = i->first;
3683 // const PVPath& fullPath = i->second;
3684 //
3685 // // If a physical volume
3686 // if (fullPath.size()) {
3687 //
3688 // // const G4bool& visibilityChanged = ???
3689 // // const G4bool& visibility = ???
3690 // // const G4bool& colourChanged = ???
3691 // // const QColor& colour = ???
3692 // // G4Colour g4colour(((G4double)colour.red())/255,
3693 // // ((G4double)colour.green())/255,
3694 // // ((G4double)colour.blue())/255,
3695 // // ((G4double)colour.alpha())/255);
3696 // // Next 4 lines are for testing, to be replaced by the above...
3697 // G4bool visibilityChanged = true;
3698 // G4bool visibility = true;
3699 // G4bool colourChanged = true;
3700 // G4Colour g4colour(G4Colour::Red());
3701 //
3702 // // Instantiate a working copy of a G4VisAttributes object...
3703 // G4VisAttributes workingVisAtts;
3704 // // ...and use it to create vis attribute modifiers...
3705 // if (visibilityChanged) {
3706 // workingVisAtts.SetVisibility(visibility);
3707 // privateVisAttributesModifiers.push_back
3708 // (G4ModelingParameters::VisAttributesModifier
3709 // (workingVisAtts,
3710 // G4ModelingParameters::VASVisibility,
3711 // fullPath));
3712 // }
3713 // if (colourChanged) {
3714 // workingVisAtts.SetColour(g4colour);
3715 // privateVisAttributesModifiers.push_back
3716 // (G4ModelingParameters::VisAttributesModifier
3717 // (workingVisAtts,
3718 // G4ModelingParameters::VASColour,
3719 // fullPath));
3720 // }
3721 // }
3722 // }
3723 
3724  return &privateVisAttributesModifiers;
3725 }
3726 
3727 
3728 void G4OpenGLQtViewer::changeSearchSelection()
3729 {
3730  const QString& searchText = fFilterOutput->text();
3731  if (fSceneTreeComponentTreeWidget == NULL) {
3732  return;
3733  }
3734 
3735  // unselect all
3736  for (int a=0; a<fSceneTreeComponentTreeWidget->topLevelItemCount(); a++) {
3737  fSceneTreeComponentTreeWidget->topLevelItem(a)->setExpanded(false);
3738  fSceneTreeComponentTreeWidget->topLevelItem(a)->setSelected(false);
3739  clearSceneTreeSelection(fSceneTreeComponentTreeWidget->topLevelItem(a));
3740  }
3741 
3742  QList<QTreeWidgetItem *> itemList = fSceneTreeComponentTreeWidget->findItems (searchText,Qt::MatchContains | Qt::MatchRecursive,0);
3743 
3744  for (int i = 0; i < itemList.size(); ++i) {
3745  QTreeWidgetItem* expandParentItem = itemList.at(i);
3746  while (expandParentItem->parent() != NULL) {
3747  expandParentItem->parent()->setExpanded(true);
3748  expandParentItem = expandParentItem->parent();
3749  }
3750  itemList.at(i)->setSelected(true);
3751  }
3752 
3753 }
3754 
3755 
3756 void G4OpenGLQtViewer::clearSceneTreeSelection(QTreeWidgetItem* item) {
3757  for (int a=0; a<item->childCount(); a++) {
3758  item->child(a)->setSelected(false);
3759  item->child(a)->setExpanded(false);
3760  clearSceneTreeSelection(item->child(a));
3761  }
3762 
3763 }
3764 
3765 
3766 bool G4OpenGLQtViewer::isPVVolume(QTreeWidgetItem* item) {
3767  QTreeWidgetItem* sParent = item;
3768  while (sParent->parent() != NULL) {
3769  sParent = sParent->parent();
3770  }
3771  if (sParent->text(0) != fTouchableVolumes) {
3772  return false;
3773  }
3774  // item is the "Touchable" node
3775  if (item->text(0) == fTouchableVolumes) {
3776  return false;
3777  }
3778  return true;
3779 }
3780 
3781 
3782 void G4OpenGLQtViewer::changeDepthOnSceneTreeItem(
3783  double lookForDepth
3784  ,double currentDepth
3785  ,QTreeWidgetItem* item
3786 ) {
3787  double transparencyLevel = 0.;
3788 
3789  // look for a 2.2 depth and we are at level 3
3790  // -> Set all theses items to Opaque
3791  // ONLY if it is a PV volume !
3792  if (isPVVolume(item)) {
3793  if ((lookForDepth-currentDepth) < 0) {
3794  item->setCheckState(0,Qt::Checked);
3795  updatePositivePoIndexSceneTreeWidgetQuickMap(item->data(0,Qt::UserRole).toInt(),item);
3796  transparencyLevel = 1;
3797  } else if ((lookForDepth-currentDepth) > 1 ){
3798  item->setCheckState(0,Qt::Unchecked);
3799  updatePositivePoIndexSceneTreeWidgetQuickMap(item->data(0,Qt::UserRole).toInt(),item);
3800  transparencyLevel = 0;
3801  } else {
3802  item->setCheckState(0,Qt::Checked);
3803  updatePositivePoIndexSceneTreeWidgetQuickMap(item->data(0,Qt::UserRole).toInt(),item);
3804  transparencyLevel = 1-(lookForDepth-currentDepth);
3805  }
3806  }
3807 
3808  if (item->data(0,Qt::UserRole).toInt() >= 0) {
3809  const G4Colour& color = getColorForPoIndex(item->data(0,Qt::UserRole).toInt());
3810 
3811  // We are less depper (ex:tree depth:2) than lookForDepth (ex:3.1)
3812  // -> Have to hide this level ONLY if it was not hidden before
3813 
3814  // Not on a top level item case
3815  // Do not set if it was already set
3816 
3817  // Should add them all the time in case of an older command has change transparency
3818  // before. Should be checked in changeDepthInSceneTree for duplicated commands
3819  // Do not change transparency if not visible by humain (and avoid precision value
3820  // problems..)
3821  if (((color.GetAlpha()-transparencyLevel) > 0.000001) ||
3822  ((color.GetAlpha()-transparencyLevel) < -0.000001)) {
3823  if ((item->text(3) != "")) {
3824  // FIXME : Should not test this here because of transparent
3825  // volume that will came after and with a different alpha level
3826  // Good thing to do is to check and suppress doubles in changeDepthInSceneTree
3827  // and then check if last (transparents volumes) has to change alpha
3828 
3829  changeQColorForTreeWidgetItem(item,QColor((int)(color.GetRed()*255),
3830  (int)(color.GetGreen()*255),
3831  (int)(color.GetBlue()*255),
3832  (int)(transparencyLevel*255)));
3833  }
3834  }
3835  }
3836 
3837  for (int b=0;b< item->childCount();b++) {
3838  changeDepthOnSceneTreeItem(lookForDepth,currentDepth+1,item->child(b));
3839  }
3840 }
3841 
3842 
3843 void G4OpenGLQtViewer::clearTreeWidget(){
3844  // be careful about calling this twice
3845 
3846  if (fSceneTreeComponentTreeWidget) {
3847 
3848  if (fOldSceneTreeComponentTreeWidget == NULL) {
3849  fOldSceneTreeComponentTreeWidget = new QTreeWidget();
3850  }
3851  // clear old scene tree
3852  int tmp = fOldSceneTreeComponentTreeWidget->topLevelItemCount();
3853  while (tmp > 0) {
3854  delete fOldSceneTreeComponentTreeWidget->takeTopLevelItem (0);
3855  tmp = fOldSceneTreeComponentTreeWidget->topLevelItemCount();
3856  }
3857 
3858  if (fSceneTreeComponentTreeWidget->topLevelItemCount () > 0) {
3859 
3860  fPVRootNodeCreate = false;
3861 
3862  // reset all old
3863  fOldPositivePoIndexSceneTreeWidgetQuickMap.clear();
3864  fOldNullPoIndexSceneTreeWidgetQuickVector.clear();
3865  fOldTreeItemModels.clear();
3866 
3867  // Clone everything
3868  for (int b =0; b <fSceneTreeComponentTreeWidget->topLevelItemCount();b++) {
3869  // All tree widgets are in :
3870  // then we could get the old POindex and get
3871  // .visible/Hidden
3872  // .Check/Uncheck
3873  // .selected
3874  // .colour status from std::map
3875 
3876  // clone top level items
3877  int poIndex = fSceneTreeComponentTreeWidget->topLevelItem(b)->data(0,Qt::UserRole).toInt();
3878  if (poIndex != -1) {
3879  fOldPositivePoIndexSceneTreeWidgetQuickMap.insert(std::pair <int, QTreeWidgetItem*> (poIndex,cloneWidgetItem(fSceneTreeComponentTreeWidget->topLevelItem(b))));
3880  } else {
3881  fOldNullPoIndexSceneTreeWidgetQuickVector.push_back(cloneWidgetItem(fSceneTreeComponentTreeWidget->topLevelItem(b)));
3882  }
3883 
3884  // clone leaves
3885  cloneSceneTree(fSceneTreeComponentTreeWidget->topLevelItem(b));
3886  }
3887  // delete all elements
3888 
3889  fOldTreeItemModels.insert(fTreeItemModels.begin(), fTreeItemModels.end());
3890 
3891  // all is copy, then clear scene tree
3892  int tmp2 = fSceneTreeComponentTreeWidget->topLevelItemCount();
3893  while (tmp2 > 0) {
3894  delete fSceneTreeComponentTreeWidget->takeTopLevelItem (0);
3895  tmp2 = fSceneTreeComponentTreeWidget->topLevelItemCount();
3896  }
3897  fPositivePoIndexSceneTreeWidgetQuickMap.clear();
3898 
3899  // put correct value in paramaters
3900  fOldLastSceneTreeWidgetAskForIterator = fOldPositivePoIndexSceneTreeWidgetQuickMap.begin();
3901  fOldLastSceneTreeWidgetAskForIteratorEnd = fOldPositivePoIndexSceneTreeWidgetQuickMap.end();
3902  fSceneTreeDepth = 1;
3903  fModelShortNameItem = NULL;
3904  fMaxPOindexInserted = -1;
3905 
3906  }
3907  }
3908 }
3909 
3910 
3917 QTreeWidgetItem * G4OpenGLQtViewer::cloneWidgetItem(QTreeWidgetItem* item) {
3918 
3919  QTreeWidgetItem* cloneItem = new QTreeWidgetItem();
3920 
3921  // Clone what is create createTreeWidgetItem step
3922 
3923  cloneItem->setText(0,item->text(0));
3924  cloneItem->setData(1,Qt::UserRole,item->data(1,Qt::UserRole).toInt());
3925  cloneItem->setText(2,item->text(2));
3926  cloneItem->setData(0, Qt::UserRole,item->data(0,Qt::UserRole).toInt());
3927  cloneItem->setText(3,item->text(3));
3928  cloneItem->setFlags(item->flags());
3929  cloneItem->setToolTip(0,item->toolTip(0));
3930  cloneItem->setCheckState(0,item->checkState(0));
3931  cloneItem->setSelected(item->isSelected());
3932  cloneItem->setExpanded(item->isExpanded ());
3933 
3934  cloneItem->setData(2,Qt::UserRole,item->data(2,Qt::UserRole).value<QColor>());
3935 
3936  return cloneItem;
3937 }
3938 
3939 
3943 void G4OpenGLQtViewer::cloneSceneTree(
3944  QTreeWidgetItem* rootItem
3945 ) {
3946 
3947  for (int b=0;b< rootItem->childCount();b++) {
3948 
3949  QTreeWidgetItem *child = rootItem->child(b);
3950 
3951  // clone top level items
3952  int poIndex = child->data(0,Qt::UserRole).toInt();
3953  if (poIndex != -1) {
3954  fOldPositivePoIndexSceneTreeWidgetQuickMap.insert(std::pair <int, QTreeWidgetItem*> (poIndex,cloneWidgetItem(child)));
3955  } else {
3956  fOldNullPoIndexSceneTreeWidgetQuickVector.push_back(cloneWidgetItem(child));
3957  }
3958  cloneSceneTree(child);
3959  }
3960 }
3961 
3962 
3966  void G4OpenGLQtViewer::updatePositivePoIndexSceneTreeWidgetQuickMap(int POindex,QTreeWidgetItem* item) {
3967 
3968  // Check state
3969  std::map <int, QTreeWidgetItem*>::iterator i;
3970  i = fPositivePoIndexSceneTreeWidgetQuickMap.find(POindex);
3971 
3972  if (i == fPositivePoIndexSceneTreeWidgetQuickMap.end()) {
3973  fPositivePoIndexSceneTreeWidgetQuickMap.insert(std::pair <int, QTreeWidgetItem*> (POindex,item) );
3974  fLastSceneTreeWidgetAskForIterator = fPositivePoIndexSceneTreeWidgetQuickMap.end();
3975  fLastSceneTreeWidgetAskForIteratorEnd = fPositivePoIndexSceneTreeWidgetQuickMap.end();
3976  } else {
3977  i->second = item;
3978  }
3979  }
3980 
3981 
3982 
3983 void G4OpenGLQtViewer::changeQColorForTreeWidgetItem(QTreeWidgetItem* item,const QColor& qc) {
3984 
3985  int POIndex = item->data(0,Qt::UserRole).toInt();
3986  updatePositivePoIndexSceneTreeWidgetQuickMap(POIndex,item );
3987 
3988  QPixmap pixmap = QPixmap(QSize(16, 16));
3989  if (item->data(0,Qt::UserRole).toInt() != -1) {
3990  pixmap.fill (qc);
3991  } else {
3992  pixmap.fill (QColor(255,255,255,255));
3993  }
3994  QPainter painter(&pixmap);
3995  painter.setPen(Qt::black);
3996  painter.drawRect(0,0,15,15); // Draw contour
3997 
3998  item->setIcon(0,pixmap);
3999  item->setData(2,Qt::UserRole,qc);
4000 }
4001 
4002 
4003 
4008 QTreeWidgetItem* G4OpenGLQtViewer::getTreeWidgetItem(int POindex){
4009 
4010  // -1 is not a visible item
4011  if (POindex == -1) {
4012  return NULL;
4013  }
4014 
4015  if (fPositivePoIndexSceneTreeWidgetQuickMap.size() == 0){
4016  return NULL;
4017  }
4018 
4019  if (fLastSceneTreeWidgetAskForIterator != fLastSceneTreeWidgetAskForIteratorEnd) {
4020  if (POindex == fLastSceneTreeWidgetAskForIterator->first) {
4021  if (fLastSceneTreeWidgetAskForIterator->second != NULL) {
4022  return fLastSceneTreeWidgetAskForIterator->second;
4023  }
4024  }
4025  }
4026 
4027  // if not, use the "find" algorithm
4028  fLastSceneTreeWidgetAskForIterator = fPositivePoIndexSceneTreeWidgetQuickMap.find(POindex);
4029  fLastSceneTreeWidgetAskForIteratorEnd = fPositivePoIndexSceneTreeWidgetQuickMap.end();
4030 
4031  if (fLastSceneTreeWidgetAskForIterator != fPositivePoIndexSceneTreeWidgetQuickMap.end()) {
4032  return fLastSceneTreeWidgetAskForIterator->second;
4033  }
4034  return NULL;
4035 }
4036 
4041 QTreeWidgetItem* G4OpenGLQtViewer::getOldTreeWidgetItem(int POindex){
4042 
4043 
4044  // -1 is not a visible item
4045  if (POindex == -1) {
4046  return NULL;
4047  }
4048 
4049  if (fOldPositivePoIndexSceneTreeWidgetQuickMap.size() == 0){
4050  return NULL;
4051  }
4052 
4053  // Should be call only once by item addition
4054  // Prevent to get out the std::map
4055  if (fOldLastSceneTreeWidgetAskForIterator != fOldLastSceneTreeWidgetAskForIteratorEnd) {
4056  fOldLastSceneTreeWidgetAskForIterator++;
4057  }
4058 
4059  if (fOldLastSceneTreeWidgetAskForIterator != fOldPositivePoIndexSceneTreeWidgetQuickMap.end()) {
4060  if (POindex == fOldLastSceneTreeWidgetAskForIterator->first) {
4061  if (fOldLastSceneTreeWidgetAskForIterator->second != NULL) {
4062  return fOldLastSceneTreeWidgetAskForIterator->second;
4063  }
4064  }
4065  }
4066 
4067  // if not, use the "find" algorithm
4068  fOldLastSceneTreeWidgetAskForIterator = fOldPositivePoIndexSceneTreeWidgetQuickMap.find(POindex);
4069  fOldLastSceneTreeWidgetAskForIteratorEnd = fOldPositivePoIndexSceneTreeWidgetQuickMap.end();
4070 
4071  if (fOldLastSceneTreeWidgetAskForIterator != fOldPositivePoIndexSceneTreeWidgetQuickMap.end()) {
4072  return fOldLastSceneTreeWidgetAskForIterator->second;
4073  }
4074  return NULL;
4075 }
4076 
4077 
4078 
4083 void G4OpenGLQtViewer::displaySceneTreeComponent() {
4084  // no UI
4085  if (fUISceneTreeComponentsTBWidget == NULL) {
4086  return;
4087  }
4088  if (fSceneTreeComponentTreeWidget == NULL) {
4089  return;
4090  }
4091 
4092  // sort tree items
4093  fSceneTreeComponentTreeWidget->sortItems (0, Qt::AscendingOrder );
4094 
4095  return;
4096 }
4097 
4098 
4105 void G4OpenGLQtViewer::updateToolbarAndMouseContextMenu(){
4106  if (fBatchMode) {
4107  return;
4108  }
4109 
4111  d_style = fVP.GetDrawingStyle();
4112 
4113  // Surface style
4114  if (d_style == G4ViewParameters::wireframe) {
4115  if (fUiQt) fUiQt->SetIconWireframeSelected();
4116  if (fContextMenu) {
4117  fDrawingWireframe->setChecked(true);
4118  fDrawingLineRemoval->setChecked(false);
4119  fDrawingSurfaceRemoval->setChecked(false);
4120  fDrawingLineSurfaceRemoval->setChecked(false);
4121  }
4122  } else if (d_style == G4ViewParameters::hlr) {
4123  if (fUiQt) fUiQt->SetIconHLRSelected();
4124  if (fContextMenu) {
4125  fDrawingLineRemoval->setChecked(true);
4126  fDrawingWireframe->setChecked(false);
4127  fDrawingSurfaceRemoval->setChecked(false);
4128  fDrawingLineSurfaceRemoval->setChecked(false);
4129  }
4130  } else if (d_style == G4ViewParameters::hsr) {
4131  if (fUiQt) fUiQt->SetIconSolidSelected();
4132  if (fContextMenu) {
4133  fDrawingSurfaceRemoval->setChecked(true);
4134  fDrawingWireframe->setChecked(false);
4135  fDrawingLineRemoval->setChecked(false);
4136  fDrawingLineSurfaceRemoval->setChecked(false);
4137  }
4138  } else if (d_style == G4ViewParameters::hlhsr) {
4139  if (fUiQt) fUiQt->SetIconHLHSRSelected();
4140  if (fContextMenu) {
4141  fDrawingLineSurfaceRemoval->setChecked(true);
4142  fDrawingWireframe->setChecked(false);
4143  fDrawingLineRemoval->setChecked(false);
4144  fDrawingSurfaceRemoval->setChecked(false);
4145  fDrawingLineSurfaceRemoval->setChecked(false);
4146  }
4147  }
4148 
4149 
4150  // projection style
4151  G4double d_proj = fVP.GetFieldHalfAngle () ;
4152  if (d_proj == 0.) { // ortho
4153  if (fUiQt) fUiQt->SetIconOrthoSelected();
4154  if (fContextMenu) {
4155  fProjectionOrtho->setChecked(true);
4156  fProjectionPerspective->setChecked(false);
4157  }
4158  } else {
4159  if (fUiQt) fUiQt->SetIconPerspectiveSelected();
4160  if (fContextMenu) {
4161  fProjectionPerspective->setChecked(true);
4162  fProjectionOrtho->setChecked(false);
4163  }
4164  }
4165 
4166 
4167  // mouse style : They are controlled by UI !
4168  if (fUiQt && fContextMenu) {
4169  if (fUiQt->IsIconPickSelected()) {
4170  fMousePickAction->setChecked(true);
4171  fMouseZoomOutAction->setChecked(false);
4172  fMouseZoomInAction->setChecked(false);
4173  fMouseRotateAction->setChecked(false);
4174  fMouseMoveAction->setChecked(false);
4175  } else if (fUiQt->IsIconZoomOutSelected()) {
4176  fMouseZoomOutAction->setChecked(true);
4177  fMousePickAction->setChecked(false);
4178  fMouseZoomInAction->setChecked(false);
4179  fMouseRotateAction->setChecked(false);
4180  fMouseMoveAction->setChecked(false);
4181  } else if (fUiQt->IsIconZoomInSelected()) {
4182  fMouseZoomInAction->setChecked(true);
4183  fMousePickAction->setChecked(false);
4184  fMouseZoomOutAction->setChecked(false);
4185  fMouseRotateAction->setChecked(false);
4186  fMouseMoveAction->setChecked(false);
4187  } else if (fUiQt->IsIconRotateSelected()) {
4188  fMouseRotateAction->setChecked(true);
4189  fMousePickAction->setChecked(false);
4190  fMouseZoomOutAction->setChecked(false);
4191  fMouseZoomInAction->setChecked(false);
4192  fMouseMoveAction->setChecked(false);
4193  } else if (fUiQt->IsIconMoveSelected()) {
4194  fMouseMoveAction->setChecked(true);
4195  fMousePickAction->setChecked(false);
4196  fMouseZoomOutAction->setChecked(false);
4197  fMouseZoomInAction->setChecked(false);
4198  fMouseRotateAction->setChecked(false);
4199  }
4200  }
4201 }
4202 
4207 void G4OpenGLQtViewer::updateSceneTreeComponentTreeWidgetInfos() {
4208 
4209  if (!fSceneTreeComponentTreeWidgetInfos) {
4210  return;
4211  }
4212  int treeWidgetInfosIgnoredCommands = 0;
4214  G4UIcommandTree * commandTreeTop = UI->GetTree();
4215  G4UIcommandTree* path = commandTreeTop->FindCommandTree("/vis/viewer/set/");
4216 
4217  if (!path) {
4218  return;
4219  }
4220 
4221  // clear old table
4222  if ((path->GetCommandEntry()-fTreeWidgetInfosIgnoredCommands) != fSceneTreeComponentTreeWidgetInfos->rowCount()) {
4223  fSceneTreeComponentTreeWidgetInfos->clear();
4224  }
4225 
4226  fSceneTreeComponentTreeWidgetInfos->blockSignals(true);
4227  // TODO : Could be optimized by comparing current command to old commands. That should not change so much
4228 
4229  fSceneTreeComponentTreeWidgetInfos->setColumnCount (2);
4230  fSceneTreeComponentTreeWidgetInfos->setRowCount (path->GetCommandEntry()-fTreeWidgetInfosIgnoredCommands);
4231  fSceneTreeComponentTreeWidgetInfos->setHorizontalHeaderLabels(QStringList() << tr("Property")
4232  << tr("Value"));
4233  fSceneTreeComponentTreeWidgetInfos->verticalHeader()->setVisible(false);
4234  fSceneTreeComponentTreeWidgetInfos->setAlternatingRowColors (true);
4235 
4236  // For the moment, we do only command that have a "set" command in UI
4237 
4238  for (int a=0;a<path->GetCommandEntry();a++) {
4239  G4UIcommand* commandTmp = path->GetCommand(a+1);
4240 
4241  // get current parameters
4242  QString params = "";
4243 
4244  if(commandTmp->GetCommandName() == "autoRefresh") {
4245  if (fVP.IsAutoRefresh()) {
4246  params = "True";
4247  } else {
4248  params = "False";
4249  }
4250  } else if(commandTmp->GetCommandName() == "auxiliaryEdge") {
4251  if (fVP.IsAuxEdgeVisible()) {
4252  params = "True";
4253  } else {
4254  params = "False";
4255  }
4256  } else if(commandTmp->GetCommandName() == "background") {
4257  params = QString().number(fVP.GetBackgroundColour().GetRed()) + " "+
4258  QString().number(fVP.GetBackgroundColour().GetGreen()) + " "+
4259  QString().number(fVP.GetBackgroundColour().GetBlue()) + " "+
4260  QString().number(fVP.GetBackgroundColour().GetAlpha());
4261 
4262  } else if(commandTmp->GetCommandName() == "culling") {
4263  params = QString().number(fVP. IsCulling ());
4264  } else if(commandTmp->GetCommandName() == "cutawayMode") {
4265  if (fVP.GetCutawayMode() == G4ViewParameters::cutawayUnion) {
4266  params = "union";
4267  } else {
4268  params = "intersection";
4269  }
4270 
4271  } else if(commandTmp->GetCommandName() == "defaultColour") {
4272  params = QString().number(fVP.GetDefaultVisAttributes()->GetColor().GetRed()) + " "+
4273  QString().number(fVP.GetDefaultVisAttributes()->GetColor().GetGreen()) + " "+
4274  QString().number(fVP.GetDefaultVisAttributes()->GetColor().GetBlue()) + " "+
4275  QString().number(fVP.GetDefaultVisAttributes()->GetColor().GetAlpha());
4276 
4277  } else if(commandTmp->GetCommandName() == "defaultTextColour") {
4278  params = QString().number(fVP.GetDefaultTextVisAttributes()->GetColor().GetRed()) + " "+
4279  QString().number(fVP.GetDefaultTextVisAttributes()->GetColor().GetGreen()) + " "+
4280  QString().number(fVP.GetDefaultTextVisAttributes()->GetColor().GetBlue()) + " "+
4281  QString().number(fVP.GetDefaultTextVisAttributes()->GetColor().GetAlpha());
4282 
4283  } else if(commandTmp->GetCommandName() == "edge") {
4284  G4ViewParameters::DrawingStyle existingStyle = fVP.GetDrawingStyle();
4285  params = "False";
4286  if (existingStyle == G4ViewParameters::hsr) {
4287  params = "True";
4288  }
4289 
4290  } else if(commandTmp->GetCommandName() == "explodeFactor") {
4291  params = QString().number(fVP.GetExplodeFactor()) + " " + QString(G4String(G4BestUnit(fVP.GetExplodeFactor(),"Length")).data());
4292 
4293  } else if(commandTmp->GetCommandName() == "globalLineWidthScale") {
4294  params = QString().number(fVP.GetGlobalLineWidthScale());
4295 
4296  } else if(commandTmp->GetCommandName() == "globalMarkerScale") {
4297  params = QString().number(fVP.GetGlobalMarkerScale());
4298 
4299  } else if(commandTmp->GetCommandName() == "hiddenEdge") {
4300  G4ViewParameters::DrawingStyle style = fVP.GetDrawingStyle();
4301  if ((style == G4ViewParameters::hlr) ||
4302  (style == G4ViewParameters::hlhsr)) {
4303  params = "True";
4304  } else {
4305  params = "False";
4306  }
4307 
4308  } else if(commandTmp->GetCommandName() == "hiddenMarker") {
4309  if (fVP.IsMarkerNotHidden()) {
4310  params = "False";
4311  } else {
4312  params = "True";
4313  }
4314 
4315  } else if(commandTmp->GetCommandName() == "lightsMove") {
4316  if (fVP.GetLightsMoveWithCamera()) {
4317  params = "camera";
4318  } else {
4319  params = "object";
4320  }
4321  } else if(commandTmp->GetCommandName() == "lightsThetaPhi") {
4322  G4Vector3D direction = fVP.GetLightpointDirection();
4323  // degree
4324  params = QString().number(direction.theta()/CLHEP::degree)+ " "+ QString().number(direction.phi()/CLHEP::degree)+" deg";
4325  if (commandTmp->GetParameterEntries() == 3) {
4326  if (commandTmp->GetParameter(2)->GetDefaultValue() != "deg") {
4327  params = QString().number(direction.theta())+ " "+ QString().number(direction.phi())+" "+commandTmp->GetParameter(2)->GetDefaultValue().data();
4328  }
4329  }
4330  } else if(commandTmp->GetCommandName() == "lightsVector") {
4331  params = QString().number(fVP.GetLightpointDirection().x()) + " "+
4332  QString().number(fVP.GetLightpointDirection().y()) + " "+
4333  QString().number(fVP.GetLightpointDirection().z());
4334 
4335  } else if(commandTmp->GetCommandName() == "lineSegmentsPerCircle") {
4336  params = QString().number(fVP.GetNoOfSides());
4337 
4338  } else if(commandTmp->GetCommandName() == "picking") {
4339  if (fVP.IsPicking()) {
4340  params = "True";
4341  } else {
4342  params = "False";
4343  }
4344 
4345  } else if(commandTmp->GetCommandName() == "projection") {
4346  if (fVP.GetFieldHalfAngle() == 0.) {
4347  params = "orthogonal";
4348  } else {
4349  params = QString("perspective ") + QString().number(fVP.GetFieldHalfAngle()/CLHEP::degree) + " deg";
4350  }
4351 
4352  } else if(commandTmp->GetCommandName() == "rotationStyle") {
4353  if (fVP.GetRotationStyle() == G4ViewParameters::constrainUpDirection) {
4354  params = "constrainUpDirection";
4355  } else {
4356  params = "freeRotation";
4357  }
4358 
4359  } else if(commandTmp->GetCommandName() == "sectionPlane") {
4360  if (fVP.IsSection()) {
4361  params = QString("on ") +
4362  G4String(G4BestUnit(fVP.GetSectionPlane().point(),"Length")).data()+
4363  QString().number(fVP.GetSectionPlane().normal().x())
4364  + " " + QString().number(fVP.GetSectionPlane().normal().y())
4365  + " " + QString().number(fVP.GetSectionPlane().normal().z());
4366  } else {
4367  params = "off";
4368  }
4369 
4370  } else if(commandTmp->GetCommandName() == "style") {
4371  if (fVP.GetDrawingStyle() == G4ViewParameters::wireframe || fVP.GetDrawingStyle() == G4ViewParameters::hlr) {
4372  params = "wireframe";
4373  } else {
4374  params = "surface";
4375  }
4376 
4377 
4378  } else if(commandTmp->GetCommandName() == "targetPoint") {
4379  G4Point3D point = fVP.GetCurrentTargetPoint();
4380  if (fSceneHandler.GetScene()) {
4381  G4String b = G4BestUnit(fSceneHandler.GetScene()->GetStandardTargetPoint() + fVP.GetCurrentTargetPoint(),"Length");
4382  params = b.data();
4383  }
4384  } else if(commandTmp->GetCommandName() == "upThetaPhi") {
4385  G4Vector3D up = fVP.GetUpVector();
4386  // degree
4387  params = QString().number(up.theta()/CLHEP::degree)+ " "+ QString().number(up.phi()/CLHEP::degree)+" deg";
4388  if (commandTmp->GetParameterEntries() == 3) {
4389  if (commandTmp->GetParameter(2)->GetDefaultValue() != "deg") {
4390  params = QString().number(up.theta())+ " "+ QString().number(up.phi())+" "+commandTmp->GetParameter(2)->GetDefaultValue().data();
4391  }
4392  }
4393  } else if(commandTmp->GetCommandName() == "upVector") {
4394  G4Vector3D up = fVP.GetUpVector();
4395  params = QString().number(up.x())+ " "+ QString().number(up.y())+" "+QString().number(up.z())+ " ";
4396 
4397  } else if(commandTmp->GetCommandName() == "viewpointThetaPhi") {
4398  G4Vector3D direction = fVP.GetViewpointDirection();
4399  // degree
4400  params = QString().number(direction.theta()/CLHEP::degree)+ " "+ QString().number(direction.phi()/CLHEP::degree)+" deg";
4401  if (commandTmp->GetParameterEntries() == 3) {
4402  if (commandTmp->GetParameter(2)->GetDefaultValue() != "deg") {
4403  params = QString().number(direction.theta())+ " "+ QString().number(direction.phi())+" "+commandTmp->GetParameter(2)->GetDefaultValue().data();
4404  }
4405  }
4406  } else if(commandTmp->GetCommandName() == "viewpointVector") {
4407  G4Vector3D direction = fVP.GetViewpointDirection();
4408  params = QString().number(direction.x())+ " "+ QString().number(direction.y())+" "+QString().number(direction.z());
4409  } else {
4410  // No help
4411  }
4412 
4413  /* DO NOT DISPLAY COMMANDS WITHOUT ANY PARAMETERS SET
4414  if (params == "") {
4415  // TODO : display default parameters // should not be editable ?
4416 
4417  for( G4int i_thParameter=0; i_thParameter<commandTmp->GetParameterEntries(); i_thParameter++ ) {
4418  commandParam = commandTmp->GetParameter(i_thParameter);
4419 
4420  if (QString(QChar(commandParam->GetParameterType())) == "b") {
4421  if (commandParam->GetDefaultValue().data()) {
4422  params += "True";
4423  } else {
4424  params += "False";
4425  }
4426  } else {
4427  params += QString((char*)(commandParam->GetDefaultValue()).data());
4428  }
4429  if (i_thParameter<commandTmp->GetParameterEntries()-1) {
4430  params += " ";
4431  }
4432  }
4433  }
4434  */
4435 
4436  if (params != "") {
4437 
4438  QTableWidgetItem *nameItem;
4439  QTableWidgetItem *paramItem;
4440 
4441  // already present ?
4442  QList<QTableWidgetItem *> list = fSceneTreeComponentTreeWidgetInfos->findItems (commandTmp->GetCommandName().data(),Qt::MatchExactly);
4443  if (list.size() == 1) {
4444  nameItem = list.first();
4445  paramItem = fSceneTreeComponentTreeWidgetInfos->item(nameItem->row(),1);
4446 
4447  } else {
4448  nameItem = new QTableWidgetItem();
4449  paramItem = new QTableWidgetItem();
4450  fSceneTreeComponentTreeWidgetInfos->setItem(a-treeWidgetInfosIgnoredCommands, 0, nameItem);
4451  fSceneTreeComponentTreeWidgetInfos->setItem(a-treeWidgetInfosIgnoredCommands, 1, paramItem);
4452 
4453  // Set Guidance
4454  QString guidance;
4455  G4int n_guidanceEntry = commandTmp->GetGuidanceEntries();
4456  for( G4int i_thGuidance=0; i_thGuidance < n_guidanceEntry; i_thGuidance++ ) {
4457  guidance += QString((char*)(commandTmp->GetGuidanceLine(i_thGuidance)).data()) + "\n";
4458  }
4459 
4460  nameItem->setToolTip(guidance);
4461  paramItem->setToolTip(GetCommandParameterList(commandTmp));
4462 
4463  fSceneTreeComponentTreeWidgetInfos->setRowHeight(a-treeWidgetInfosIgnoredCommands,15);
4464  }
4465 
4466  // set current name and parameters
4467  nameItem->setText(commandTmp->GetCommandName().data());
4468  paramItem->setText(params);
4469 
4470  nameItem->setFlags(Qt::NoItemFlags);
4471  nameItem->setForeground(QBrush());
4472 
4473  } else {
4474  treeWidgetInfosIgnoredCommands++;
4475  }
4476  }
4477  // remove empty content row
4478  for (int i=0; i<treeWidgetInfosIgnoredCommands; i++) {
4479  fSceneTreeComponentTreeWidgetInfos->removeRow (fSceneTreeComponentTreeWidgetInfos->rowCount() - 1);
4480  }
4481 
4482  fSceneTreeComponentTreeWidgetInfos->resizeColumnToContents(0);
4483  fSceneTreeComponentTreeWidgetInfos->horizontalHeader()->setStretchLastSection(true);
4484  fSceneTreeComponentTreeWidgetInfos->blockSignals(false);
4485 
4486  fTreeWidgetInfosIgnoredCommands = treeWidgetInfosIgnoredCommands;
4487 }
4488 
4489 
4490 
4491 void G4OpenGLQtViewer::toggleSceneTreeViewerInfos() {
4492  if (! fSceneTreeViewerButton) {
4493  return;
4494  }
4495  fSceneTreeViewerInfos->setVisible(!fSceneTreeViewerInfos->isVisible());
4496  if (fSceneTreeViewerInfos->isVisible()) {
4497  fSceneTreeViewerButton->setIcon(*fTreeIconOpen);
4498  } else {
4499  fSceneTreeViewerButton->setIcon(*fTreeIconClosed);
4500  }
4501 }
4502 
4503 
4504 void G4OpenGLQtViewer::toggleSceneTreeComponentTreeWidgetInfos() {
4505  fSceneTreeComponentTreeWidgetInfos->setVisible(!fSceneTreeComponentTreeWidgetInfos->isVisible());
4506  if (fSceneTreeComponentTreeWidgetInfos->isVisible()) {
4507  fViewerPropertiesButton->setIcon(*fTreeIconOpen);
4508  } else {
4509  fViewerPropertiesButton->setIcon(*fTreeIconClosed);
4510  }
4511 }
4512 
4513 
4514 void G4OpenGLQtViewer::toggleSceneTreeComponentPickingInfos() {
4515  fSceneTreeComponentPickingScrollArea->setVisible(!fSceneTreeComponentPickingScrollArea->isVisible());
4516  if (fViewerPickingButton->isVisible()) {
4517  fViewerPickingButton->setIcon(*fTreeIconOpen);
4518  } else {
4519  fViewerPickingButton->setIcon(*fTreeIconClosed);
4520  }
4521 }
4522 
4523 
4524 void G4OpenGLQtViewer::toggleSceneTreeComponentPickingCout(int pickItem) {
4525 
4526  QWidget* w;
4527  // close other items, it could take too much space
4528 
4529  for (int a=0; a<fSceneTreeComponentPickingInfos->layout()->count(); a++) {
4530  w = fSceneTreeComponentPickingInfos->layout()->itemAt(a)->widget();
4531  QTextEdit* ed = dynamic_cast<QTextEdit*>(w);
4532  QPushButton* button;
4533  if (ed) {
4534  if (a == pickItem) {
4535  w->setVisible(!w->isVisible());
4536  } else {
4537  w->setVisible(false);
4538  }
4539  if (a >= 1) {
4540  button = dynamic_cast<QPushButton*>(fSceneTreeComponentPickingInfos->layout()->itemAt(a-1)->widget());
4541  if (button) {
4542  if (button->isVisible()) {
4543  button->setIcon(*fTreeIconOpen);
4544  } else {
4545  button->setIcon(*fTreeIconClosed);
4546  }
4547  }
4548  }
4549  }
4550  }
4551 }
4552 
4553 
4554 void G4OpenGLQtViewer::tableWidgetViewerSetItemChanged(QTableWidgetItem * item) {
4556  if(UI != NULL) {
4557  QTableWidgetItem* previous = fSceneTreeComponentTreeWidgetInfos->item(fSceneTreeComponentTreeWidgetInfos->row(item),0);
4558  if (previous) {
4559  fSceneTreeComponentTreeWidgetInfos->blockSignals(true);
4560  UI->ApplyCommand((std::string("/vis/viewer/set/")
4561  + previous->text().toStdString()
4562  + " "
4563  + item->text().toStdString()).c_str());
4564  fSceneTreeComponentTreeWidgetInfos->blockSignals(false);
4565  }
4566  }
4567 }
4568 
4569 
4577 QString G4OpenGLQtViewer::GetCommandParameterList (
4578  const G4UIcommand *aCommand
4579  )
4580 {
4581  G4int n_parameterEntry = aCommand->GetParameterEntries();
4582  QString txt;
4583 
4584  if( n_parameterEntry > 0 ) {
4585  G4UIparameter *param;
4586 
4587  // Re-implementation of G4UIparameter.cc
4588 
4589  for( G4int i_thParameter=0; i_thParameter<n_parameterEntry; i_thParameter++ ) {
4590  param = aCommand->GetParameter(i_thParameter);
4591  txt += "\nParameter : " + QString((char*)(param->GetParameterName()).data()) + "\n";
4592  if( ! param->GetParameterGuidance().isNull() )
4593  txt += QString((char*)(param->GetParameterGuidance()).data())+ "\n" ;
4594  txt += " Parameter type : " + QString(QChar(param->GetParameterType())) + "\n";
4595  if(param->IsOmittable()){
4596  txt += " Omittable : True\n";
4597  } else {
4598  txt += " Omittable : False\n";
4599  }
4600  if( param->GetCurrentAsDefault() ) {
4601  txt += " Default value : taken from the current value\n";
4602  } else if( ! param->GetDefaultValue().isNull() ) {
4603  txt += " Default value : " + QString((char*)(param->GetDefaultValue()).data())+ "\n";
4604  }
4605  if( ! param->GetParameterRange().isNull() ) {
4606  txt += " Parameter range : " + QString((char*)(param->GetParameterRange()).data())+ "\n";
4607  }
4608  if( ! param->GetParameterCandidates().isNull() ) {
4609  txt += " Candidates : " + QString((char*)(param->GetParameterCandidates()).data())+ "\n";
4610  }
4611  }
4612  }
4613  return txt;
4614 }
4615 
4616 #ifdef G4MULTITHREADED
4617 
4618 void G4OpenGLQtViewer::SwitchToVisSubThread()
4619 {
4620  G4cout << "G4OpenGLQtViewer::SwitchToVisSubThread" << G4endl;
4621  QGLWidget* qGLW = dynamic_cast<QGLWidget*> (fGLWidget) ;
4622  if (! qGLW) {
4623  return;
4624  }
4625  qGLW->makeCurrent();
4626 }
4627 
4628 void G4OpenGLQtViewer::SwitchToMasterThread()
4629 {
4630  G4cout << "G4OpenGLQtViewer::SwitchToMasterThread" << G4endl;
4631 }
4632 
4633 #endif
4634 
4635 
4636 /*
4637 
4638 void MultiLayer::exportToSVG(const QString& fname)
4639 {
4640 QPicture picture;
4641 QPainter p(&picture);
4642 for (int i=0;i<(int)graphsList->count();i++)
4643 {
4644 Graph *gr=(Graph *)graphsList->at(i);
4645 Plot *myPlot= (Plot *)gr->plotWidget();
4646 
4647 QPoint pos=gr->pos();
4648 
4649 int width=int(myPlot->frameGeometry().width());
4650 int height=int(myPlot->frameGeometry().height());
4651 
4652 myPlot->print(&p, QRect(pos,QSize(width,height)));
4653 }
4654 
4655 p.end();
4656 picture.save(fname, "svg");
4657 }
4658 */
4659 #endif
G4UIcommandTree * FindCommandTree(const char *commandPath)
Try to match a command or a path with the one given.
void SetColour(const G4Colour &)
G4String GetParameterCandidates() const
Definition: G4Text.hh:73
G4double GetAlpha() const
Definition: G4Colour.hh:142
Definition: test07.cc:36
G4int GetCommandEntry() const
Definition: G4UIGAG.hh:45
G4String name
Definition: TRTMaterials.hh:40
G4String GetParameterName() const
G4UIcommand * GetCommand(G4int i)
const G4Transform3D & GetTransformation() const
static G4bool GetColour(const G4String &key, G4Colour &result)
Definition: G4Colour.cc:126
const G4Colour & GetColour() const
#define width
HepGeom::Point3D< G4double > G4Point3D
Definition: G4Point3D.hh:35
HepGeom::Vector3D< G4double > G4Vector3D
Definition: G4Vector3D.hh:35
G4double a
Definition: TRTMaterials.hh:39
G4double GetBlue() const
Definition: G4Colour.hh:141
#define G4BestUnit(a, b)
#define G4_USE_G4BESTUNIT_FOR_VERBOSE 1
G4Point3D GetPosition() const
Definition: test07.cc:36
Definition: test07.cc:36
int G4int
Definition: G4Types.hh:78
const G4String & GetGuidanceLine(G4int i) const
Definition: G4UIcommand.hh:137
static G4UImanager * GetUIpointer()
Definition: G4UImanager.cc:58
G4bool IsOmittable() const
G4double GetYOffset() const
#define position
Definition: xmlparse.cc:605
G4GLOB_DLL std::ostream G4cout
G4double GetRed() const
Definition: G4Colour.hh:139
Layout GetLayout() const
bool G4bool
Definition: G4Types.hh:79
G4double GetGreen() const
Definition: G4Colour.hh:140
G4UIparameter * GetParameter(G4int i) const
Definition: G4UIcommand.hh:145
std::vector< PVNodeID > PVPath
G4Colour G4Color
Definition: G4Color.hh:42
const std::vector< G4PhysicalVolumeNodeID > & GetFullPVPath() const
static const double gray
Definition: G4SIunits.hh:276
const G4String & GetCommandName() const
Definition: G4UIcommand.hh:141
const char * data() const
G4double GetXOffset() const
static const G4double factor
G4UIcommandTree * GetTree() const
Definition: G4UImanager.hh:206
G4String GetText() const
G4String GetDefaultValue() const
char GetParameterType() const
static const double degree
Definition: G4SIunits.hh:125
#define G4endl
Definition: G4ios.hh:61
static MCTruthManager * instance
static PROLOG_HANDLER error
Definition: xmlrole.cc:108
const G4String GetParameterGuidance() const
double G4double
Definition: G4Types.hh:76
void print(const std::vector< T > &data)
Definition: DicomRun.hh:109
G4String GetParameterRange() const
static const G4double alpha
G4int GetGuidanceEntries() const
Definition: G4UIcommand.hh:135
G4int GetParameterEntries() const
Definition: G4UIcommand.hh:143
G4bool GetCurrentAsDefault() const
G4bool isNull() const
static const G4double pos
G4int ApplyCommand(const char *aCommand)
Definition: G4UImanager.cc:432
std::vector< G4PolyconeSideRZ > g4c
Definition: ExP02Classes.hh:79
G4GLOB_DLL std::ostream G4cerr