Geant4  10.02.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 91686 2015-07-31 09:40:08Z 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 #include "G4Threading.hh"
56 
58 
59 #include <typeinfo>
60 
61 #include <qlayout.h>
62 #include <qlabel.h>
63 #include <qdialog.h>
64 #include <qpushbutton.h>
65 #include <qprocess.h>
66 #include <qdesktopwidget.h>
67 
68 #include <qmenu.h>
69 #include <qimagewriter.h>
70 
71 #include <qtextedit.h>
72 #include <qtreewidget.h>
73 #include <qapplication.h>
74 #include <qmessagebox.h>
75 #include <qfiledialog.h>
76 #include <qprinter.h>
77 #include <qdatetime.h>
78 #include <qpainter.h>
79 #include <qgl.h> // include <qglwidget.h>
80 #include <qdialog.h>
81 #include <qcolordialog.h>
82 #include <qevent.h> //include <qcontextmenuevent.h>
83 #include <qobject.h>
84 #include <qgroupbox.h>
85 #include <qcombobox.h>
86 #include <qlineedit.h>
87 #include <qsignalmapper.h>
88 #include <qmainwindow.h>
89 #include <qtablewidget.h>
90 #include <qheaderview.h>
91 #include <qscrollarea.h>
92 #include <qsplitter.h>
93 #include <qcheckbox.h>
94 #include <qcursor.h>
95 #include <qthread.h>
96 
97 #ifdef G4MULTITHREADED
98 #include "G4Threading.hh"
99 #endif
100 
101 namespace
102 {
103 #ifdef G4MULTITHREADED
104  G4Mutex mWaitForVisSubThreadQtOpenGLContextMoved = G4MUTEX_INITIALIZER;
105  G4Mutex mWaitForVisSubThreadQtOpenGLContextInitialized = G4MUTEX_INITIALIZER;
106  G4Condition c1_VisSubThreadQtOpenGLContextInitialized = G4CONDITION_INITIALIZER;
107  G4Condition c2_VisSubThreadQtOpenGLContextMoved = G4CONDITION_INITIALIZER;
108 #endif
109 }
110 
112 void G4OpenGLQtViewer::CreateMainWindow (
113  QGLWidget* glWidget
114  ,const QString& name
115 )
116 {
119 
120  if(fGLWidget) return; //Done.
121 
122  fGLWidget = glWidget ;
123  // fGLWidget->makeCurrent();
124 
125  G4Qt* interactorManager = G4Qt::getInstance ();
126 
127  ResizeWindow(fVP.GetWindowSizeHintX(),fVP.GetWindowSizeHintY());
128 
129  // FIXME L.Garnier 9/11/09 Has to be check !!!
130  // Qt UI with Qt Vis
131  // Qt UI with X Vis
132  // X UI with Qt Vis
133  // X UI with X Vis
134  // Ne marche pas avec un UIBatch !! (ecran blanc)
135 
136  // return false if G4UIQt was not launch
137 
139  if (UI == NULL) return;
140 
141  if (! static_cast<G4UIQt*> (UI->GetG4UIWindow())) {
142  // NO UI, should be batch mode
143  fBatchMode = true;
144  return;
145  }
146  fUiQt = static_cast<G4UIQt*> (UI->GetG4UIWindow());
147 
148  bool isTabbedView = false;
149  if ( fUiQt) {
150  if (!fBatchMode) {
151  if (!interactorManager->IsExternalApp()) {
152  // INIT size
153  fWinSize_x = fVP.GetWindowSizeHintX();
154  fWinSize_y = fVP.GetWindowSizeHintY();
155 
156  isTabbedView = fUiQt->AddTabWidget((QWidget*)fGLWidget,name);
157  }
158  fUISceneTreeComponentsTBWidget = fUiQt->GetSceneTreeComponentsTBWidget();
159 
160  // activate scene tree
161  fUiQt->GetViewersWidget()->setCurrentWidget(fUISceneTreeComponentsTBWidget);
162 
163  // initialize scene tree / viewer properties / picking
164  fSceneTreeWidget = new QWidget();
165  QVBoxLayout* layoutSceneTree = new QVBoxLayout();
166  fSceneTreeWidget->setStyleSheet ("padding: 0px ");
167 
168  fSceneTreeWidget->setLayout(layoutSceneTree);
169  fSceneTreeWidget->layout()->setContentsMargins(5,5,5,5);
170 
171  if (fUISceneTreeComponentsTBWidget != NULL) {
172  fUISceneTreeComponentsTBWidget->addTab(fSceneTreeWidget,QString(GetName().data()));
173  }
174 
175  // not available for Immediate mode
176  if (dynamic_cast<G4OpenGLStoredQtViewer*> (this)) {
177  createSceneTreeComponent();
178  }
179 
180  createViewerPropertiesComponent();
181  createPickingComponent();
182 
183  // activate them
184  }
185  }
186 
187  if (!isTabbedView) { // we have to do a dialog
188 
189  QWidget *glDialogWidget = getParentWidget();
190  if (glDialogWidget != NULL) {
191  glWidget->setParent(glDialogWidget);
192  }
193  QHBoxLayout *mainLayout = new QHBoxLayout();
194 
195  mainLayout->setMargin(0);
196  mainLayout->setSpacing(0);
197  mainLayout->addWidget(fGLWidget);
198  if (fGLWidget->inherits("QMainWindow")) {
199  fGLWidget->setWindowTitle( name);
200  }
201  glDialogWidget->setLayout(mainLayout);
202 
203 
204  //useful for MACOSX, we have to compt the menuBar height
205  int offset = QApplication::desktop()->height()
206  - QApplication::desktop()->availableGeometry().height();
207 
208  G4int YPos= fVP.GetWindowAbsoluteLocationHintY(QApplication::desktop()->height());
209  if (fVP.GetWindowAbsoluteLocationHintY(QApplication::desktop()->height())< offset) {
210  YPos = offset;
211  }
212  glDialogWidget->resize(getWinWidth(), getWinHeight());
213  glDialogWidget->move(fVP.GetWindowAbsoluteLocationHintX(QApplication::desktop()->width()),YPos);
214  glDialogWidget->show();
215  }
216 
217  if(!fGLWidget) return;
218 
219  if (!fContextMenu)
220  createPopupMenu();
221 
222 }
223 
224 
226 G4OpenGLQtViewer::G4OpenGLQtViewer (
227  G4OpenGLSceneHandler& scene
228 )
229  :G4VViewer (scene, -1)
230  ,G4OpenGLViewer (scene)
231  ,fGLWidget(NULL)
232  ,fRecordFrameNumber(0)
233  ,fContextMenu(0)
234  ,fDeltaDepth(0.01)
235  ,fDeltaZoom(0.05)
236  ,fHoldKeyEvent(false)
237  ,fHoldMoveEvent(false)
238  ,fHoldRotateEvent(false)
239  ,fAutoMove(false)
240  ,fEncoderPath("")
241  ,fTempFolderPath("")
242  ,fMovieTempFolderPath("")
243  ,fSaveFileName("")
244  ,fParameterFileName("ppmtompeg_encode_parameter_file.par")
245  ,fMovieParametersDialog(NULL)
246  ,fRecordingStep(WAIT)
247  ,fProcess(NULL)
248  ,fNbMaxFramesPerSec(100)
249  ,fNbMaxAnglePerSec(360)
250  ,fLaunchSpinDelay(100)
251  ,fUISceneTreeComponentsTBWidget(NULL)
252  ,fNoKeyPress(true)
253  ,fAltKeyPress(false)
254  ,fControlKeyPress(false)
255  ,fShiftKeyPress(false)
256  ,fBatchMode(false)
257  ,fCheckSceneTreeComponentSignalLock(false)
258  ,fSceneTreeComponentTreeWidget(NULL)
259  ,fOldSceneTreeComponentTreeWidget(NULL)
260  ,fSceneTreeWidget(NULL)
261  ,fPVRootNodeCreate(false)
262  ,fFilterOutput(NULL)
263  ,fViewerPropertiesButton(NULL)
264  ,fNbRotation(0)
265  ,fTimeRotation(0)
266  ,fTouchableVolumes("Touchables")
267  ,fShortcutsDialog(NULL)
268  ,fSceneTreeComponentTreeWidgetInfos(NULL)
269  ,fSceneTreeComponentPickingInfos(NULL)
270  ,fSceneTreeComponentPickingScrollArea(NULL)
271  ,fTreeWidgetInfosIgnoredCommands(0)
272  ,fSceneTreeDepthSlider(NULL)
273  ,fSceneTreeDepth(1)
274  ,fModelShortNameItem(NULL)
275  ,fMaxPOindexInserted(-1)
276  ,fUiQt(NULL)
277  ,fSignalMapperMouse(NULL)
278  ,fSignalMapperSurface(NULL)
279  ,fSignalMapperPicking(NULL)
280  ,fTreeIconOpen(NULL)
281  ,fTreeIconClosed(NULL)
282  ,fLastExportSliderValue(80)
283  ,fLastHighlightColor(G4Color(0,0,0,0))
284  ,fLastHighlightName(0)
285  ,fIsDeleting(false)
286 {
287 
288  // launch Qt if not
289  if (QCoreApplication::instance () == NULL) {
290  fBatchMode = true;
291  }
292  G4Qt::getInstance ();
293 
294  fLastPos3 = QPoint(-1,-1);
295  fLastPos2 = QPoint(-1,-1);
296  fLastPos1 = QPoint(-1,-1);
297 
298  initMovieParameters();
299 
300  fLastEventTime = new QTime();
301  fSignalMapperMouse = new QSignalMapper(this);
302  fSignalMapperSurface = new QSignalMapper(this);
303 
304  // Set default path and format
305  fFileSavePath = QDir::currentPath();
306 
307  // add available export format
308  QList<QByteArray> formats = QImageWriter::supportedImageFormats ();
309  for (int i = 0; i < formats.size(); ++i) {
310  addExportImageFormat(formats.at(i).data());
311  }
312 
313  const char * const icon1[]={
314  /* columns rows colors chars-per-pixel */
315  "20 20 34 1",
316  " c None",
317  ". c #7C7C7C7C7C7C",
318  "X c #7D7D7D7D7D7D",
319  "o c #828282828282",
320  "O c #838383838383",
321  "+ c #848484848484",
322  "@ c #858585858585",
323  "# c #878787878787",
324  "$ c #888888888888",
325  "% c #8B8B8B8B8B8B",
326  "& c #8C8C8C8C8C8C",
327  "* c #8F8F8F8F8F8F",
328  "= c #909090909090",
329  "- c #919191919191",
330  "; c #999999999999",
331  ": c #9D9D9D9D9D9D",
332  "> c #A2A2A2A2A2A2",
333  ", c #A3A3A3A3A3A3",
334  "< c #A5A5A5A5A5A5",
335  "1 c #A6A6A6A6A6A6",
336  "2 c #B3B3B3B3B3B3",
337  "3 c #B6B6B6B6B6B6",
338  "4 c #C2C2C2C2C2C2",
339  "5 c #C6C6C6C6C6C6",
340  "6 c #CACACACACACA",
341  "7 c #CFCFCFCFCFCF",
342  "8 c #D0D0D0D0D0D0",
343  "9 c #D4D4D4D4D4D4",
344  "0 c #D7D7D7D7D7D7",
345  "q c #DEDEDEDEDEDE",
346  "w c #E0E0E0E0E0E0",
347  "e c #E7E7E7E7E7E7",
348  "r c #F4F4F4F4F4F4",
349  "t c #F7F7F7F7F7F7",
350  " ",
351  " ",
352  " ",
353  " ",
354  " ",
355  " ",
356  " =========> ",
357  " 7&X+++Oo<e ",
358  " 2o+@@+-8 ",
359  " w;.#@+3 ",
360  " 4$o@:q ",
361  " r1X%5 ",
362  " 9*,t ",
363  " 60 ",
364  " ",
365  " ",
366  " ",
367  " ",
368  " ",
369  " "
370  };
371  const char * const icon2[]={
372  "20 20 68 1",
373  " c None",
374  ". c #5F5F10102323",
375  "X c #40405F5F1010",
376  "o c #696963632E2E",
377  "O c #101019194C4C",
378  "+ c #101023237070",
379  "@ c #70702D2D6363",
380  "# c #73732D2D6464",
381  "$ c #79792E2E6767",
382  "% c #19194C4C5353",
383  "& c #2D2D63636161",
384  "* c #2E2E61617070",
385  "= c #6F6F6E6E4343",
386  "- c #707065655F5F",
387  "; c #727279795454",
388  ": c #535341417070",
389  "> c #797954547979",
390  ", c #434361617474",
391  "< c #414170707070",
392  "1 c #686869696363",
393  "2 c #6C6C69696363",
394  "3 c #656567676F6F",
395  "4 c #69696F6F6E6E",
396  "5 c #747465656767",
397  "6 c #757562626C6C",
398  "7 c #70706C6C6969",
399  "8 c #616174746565",
400  "9 c #656573736969",
401  "0 c #616174746969",
402  "q c #707075756262",
403  "w c #797970706565",
404  "e c #636361617474",
405  "r c #67676F6F7272",
406  "t c #727261617070",
407  "y c #616170707070",
408  "u c #6F6F72727979",
409  "i c #67676E6ED1D1",
410  "p c #808080808080",
411  "a c #828282828282",
412  "s c #838383838383",
413  "d c #848484848484",
414  "f c #858585858585",
415  "g c #868686868686",
416  "h c #888888888888",
417  "j c #8A8A8A8A8A8A",
418  "k c #8D8D8D8D8D8D",
419  "l c #8F8F8F8F8F8F",
420  "z c #909090909090",
421  "x c #949494949494",
422  "c c #9C9C9C9C9C9C",
423  "v c #9F9F9F9F9F9F",
424  "b c #A2A2A2A2A2A2",
425  "n c #AEAEAEAEAEAE",
426  "m c #B7B7B7B7B7B7",
427  "M c #C7C7C7C7C7C7",
428  "N c #C9C9C9C9C9C9",
429  "B c #D1D1D1D1D1D1",
430  "V c #D4D4D4D4D4D4",
431  "C c #D9D9D9D9D9D9",
432  "Z c #E0E0E0E0E0E0",
433  "A c #E2E2E2E2E2E2",
434  "S c #EEEEEEEEEEEE",
435  "D c #F0F0F0F0F0F0",
436  "F c #F5F5F5F5F5F5",
437  "G c #F6F6F6F6F6F6",
438  "H c #F9F9F9F9F9F9",
439  "J c #FCFCFCFCFCFC",
440  "K c #FDFDFDFDFDFD",
441  " ",
442  " ",
443  " ",
444  " ",
445  " ",
446  " bC ",
447  " zjnD ",
448  " ldjjMK ",
449  " zdhdjcA ",
450  " zddhdddVK ",
451  " zghdalBH ",
452  " zghamSK ",
453  " lubZH ",
454  " xMF ",
455  " G ",
456  " ",
457  " ",
458  " ",
459  " ",
460  " ",
461 
462  };
463 
464  const char * const search[] = {
465  /* columns rows colors chars-per-pixel */
466  "19 19 8 1",
467  " c #5C5C5C",
468  ". c #7D7D7D",
469  "X c #9B9B9B",
470  "o c #C3C3C3",
471  "O c None",
472  "+ c #000000",
473  "@ c #000000",
474  "# c None",
475  /* pixels */
476  "OOOOOOOOOOOOOOOOOOO",
477  "OOOOOOOOOOOOOOOOOOO",
478  "OOOOOOOo. .oOOOOOO",
479  "OOOOOOX XOOOOO",
480  "OOOOOo XOOX oOOOO",
481  "OOOOO. XOOOOX .OOOO",
482  "OOOOO OOOOOO OOOO",
483  "OOOOO OOOOOO OOOO",
484  "OOOOO. XOOOOo .OOOO",
485  "OOOOOo oOOo oOOOO",
486  "OOOOOOX XOOOO",
487  "OOOOOOOo. . XOOO",
488  "OOOOOOOOOOOOO. XOO",
489  "OOOOOOOOOOOOOO. XOO",
490  "OOOOOOOOOOOOOOOoOOO",
491  "OOOOOOOOOOOOOOOOOOO",
492  "OOOOOOOOOOOOOOOOOOO",
493  "OOOOOOOOOOOOOOOOOOO",
494  "OOOOOOOOOOOOOOOOOOO"
495  };
496 
497  fSearchIcon = new QPixmap(search);
498  fTreeIconOpen = new QPixmap(icon1);
499  fTreeIconClosed = new QPixmap(icon2);
500 
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)) {
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 
1447  } else if (move) { // move
1448  moveScene(-((float)delta.x())/correctionFactor,-((float)delta.y())/correctionFactor,0,true);
1449  }
1450  }
1451  ((QApplication*)G4Qt::getInstance ())->processEvents();
1452  }
1453  }
1454  fGLWidget->setMouseTracking(false);
1455 
1456 }
1457 
1458 
1459 void G4OpenGLQtViewer::G4MouseDoubleClickEvent()
1460 {
1461  fGLWidget->setMouseTracking(true);
1462 }
1463 
1464 
1472 void G4OpenGLQtViewer::G4MouseMoveEvent(QMouseEvent *evnt)
1473 {
1474 
1475  Qt::MouseButtons mButtons = evnt->buttons();
1476 
1477  updateKeyModifierState(evnt->modifiers());
1478 
1479  if (fAutoMove) {
1480  return;
1481  }
1482 
1483  fLastPos3 = fLastPos2;
1484  fLastPos2 = fLastPos1;
1485  fLastPos1 = QPoint(evnt->x(), evnt->y());
1486 
1487  int deltaX = fLastPos2.x()-fLastPos1.x();
1488  int deltaY = fLastPos2.y()-fLastPos1.y();
1489 
1490  bool move = false;
1491  if (fUiQt != NULL) {
1492  if (fUiQt->IsIconMoveSelected()) { // move
1493  move = true;
1494  }
1495  }
1496  if (!move) { // rotate, pick, zoom...
1497  if (mButtons & Qt::LeftButton) {
1498  if (fNoKeyPress) {
1499  rotateQtScene(((float)deltaX),((float)deltaY));
1500  } else if (fAltKeyPress) {
1501  rotateQtSceneToggle(((float)deltaX),((float)deltaY));
1502  } else if (fShiftKeyPress) {
1503  unsigned int sizeWin;
1504  sizeWin = getWinWidth();
1505  if (getWinHeight() < getWinWidth()) {
1506  sizeWin = getWinHeight();
1507  }
1508 
1509  // L.Garnier : 08/2010 100 is the good value, but don't ask me why !
1510  float factor = ((float)100/(float)sizeWin) ;
1511  moveScene(-(float)deltaX*factor,-(float)deltaY*factor,0,false);
1512  } else if (fControlKeyPress) {
1513  fVP.SetZoomFactor(fVP.GetZoomFactor()*(1+((float)deltaY)));
1514  }
1515  }
1516  } else if (move) { // move
1517  if (mButtons & Qt::LeftButton) {
1518  moveScene(-(float)deltaX,-(float)deltaY,0,true);
1519  }
1520  }
1521 
1522  fLastEventTime->start();
1523 }
1524 
1525 
1533 void G4OpenGLQtViewer::moveScene(float dx,float dy, float dz,bool mouseMove)
1534 {
1535  if (fHoldMoveEvent)
1536  return;
1537  fHoldMoveEvent = true;
1538 
1539  G4double coefTrans = 0;
1540  GLdouble coefDepth = 0;
1541  if(mouseMove) {
1542  coefTrans = ((G4double)getSceneNearWidth())/((G4double)getWinWidth());
1543  if (getWinHeight() <getWinWidth()) {
1544  coefTrans = ((G4double)getSceneNearWidth())/((G4double)getWinHeight());
1545  }
1546  } else {
1547  coefTrans = getSceneNearWidth()*fPan_sens;
1548  coefDepth = getSceneDepth()*fDeltaDepth;
1549  }
1550  fVP.IncrementPan(-dx*coefTrans,dy*coefTrans,dz*coefDepth);
1551 
1552  updateQWidget();
1553  if (fAutoMove)
1554  ((QApplication*)G4Qt::getInstance ())->processEvents();
1555 
1556  fHoldMoveEvent = false;
1557 }
1558 
1559 
1565 void G4OpenGLQtViewer::rotateQtScene(float dx, float dy)
1566 {
1567  if (fHoldRotateEvent)
1568  return;
1569  fHoldRotateEvent = true;
1570 
1571  rotateScene(dx,dy);
1572 
1573  updateQWidget();
1574 
1575  fHoldRotateEvent = false;
1576 }
1577 
1583 void G4OpenGLQtViewer::rotateQtSceneToggle(float dx, float dy)
1584 {
1585  if (fHoldRotateEvent)
1586  return;
1587  fHoldRotateEvent = true;
1588 
1589  rotateSceneToggle(dx,dy);
1590 
1591  updateQWidget();
1592 
1593  fHoldRotateEvent = false;
1594 }
1595 
1596 
1597 
1598 
1599 
1604 void G4OpenGLQtViewer::rescaleImage(
1605  int /* aWidth */
1606 ,int /* aHeight */
1607 ){
1608  // GLfloat* feedback_buffer;
1609  // GLint returned;
1610  // FILE* file;
1611 
1612  // feedback_buffer = new GLfloat[size];
1613  // glFeedbackBuffer (size, GL_3D_COLOR, feedback_buffer);
1614  // glRenderMode (GL_FEEDBACK);
1615 
1616  // DrawView();
1617  // returned = glRenderMode (GL_RENDER);
1618 
1619 }
1620 
1621 
1622 
1623 
1624 void G4OpenGLQtViewer::G4wheelEvent (QWheelEvent * evnt)
1625 {
1626  fVP.SetZoomFactor(fVP.GetZoomFactor()+(fVP.GetZoomFactor()*(evnt->delta())/1200));
1627  updateQWidget();
1628 }
1629 
1630 
1631 void G4OpenGLQtViewer::G4keyPressEvent (QKeyEvent * evnt)
1632 {
1633  if (fHoldKeyEvent)
1634  return;
1635 
1636  fHoldKeyEvent = true;
1637 
1638 
1639  // with no modifiers
1640  updateKeyModifierState(evnt->modifiers());
1641  if ((fNoKeyPress) || (evnt->modifiers() == Qt::KeypadModifier )) {
1642  if (evnt->key() == Qt::Key_Down) { // go down
1643  moveScene(0,1,0,false);
1644  }
1645  else if (evnt->key() == Qt::Key_Up) { // go up
1646  moveScene(0,-1,0,false);
1647  }
1648  if (evnt->key() == Qt::Key_Left) { // go left
1649  moveScene(-1,0,0,false);
1650  }
1651  else if (evnt->key() == Qt::Key_Right) { // go right
1652  moveScene(1,0,0,false);
1653  }
1654  if (evnt->key() == Qt::Key_Minus) { // go backward
1655  moveScene(0,0,1,false);
1656  }
1657  else if (evnt->key() == Qt::Key_Plus) { // go forward
1658  moveScene(0,0,-1,false);
1659  }
1660 
1661  // escaped from full screen
1662  if (evnt->key() == Qt::Key_Escape) {
1663  toggleFullScreen(false);
1664  }
1665  }
1666  // several case here : If return is pressed, in every case -> display the movie parameters dialog
1667  // If one parameter is wrong -> put it in red (only save filenam could be wrong..)
1668  // If encoder not found-> does nothing.Only display a message in status box
1669  // If all ok-> generate parameter file
1670  // If ok -> put encoder button enabled
1671 
1672  if ((evnt->key() == Qt::Key_Return) || (evnt->key() == Qt::Key_Enter)){ // end of video
1673  stopVideo();
1674  }
1675  if (evnt->key() == Qt::Key_Space){ // start/pause of video
1676  startPauseVideo();
1677  }
1678 
1679  // H : Return Home view
1680  if (evnt->key() == Qt::Key_H){ // go Home
1681  ResetView();
1682 
1683  updateQWidget();
1684  }
1685 
1686  // Shift Modifier
1687  if (fShiftKeyPress) {
1688  fGLWidget->setCursor(QCursor(Qt::SizeAllCursor));
1689 
1690  if (evnt->key() == Qt::Key_Down) { // rotate phi
1691  rotateQtScene(0,-fRot_sens);
1692  }
1693  else if (evnt->key() == Qt::Key_Up) { // rotate phi
1694  rotateQtScene(0,fRot_sens);
1695  }
1696  if (evnt->key() == Qt::Key_Left) { // rotate theta
1697  rotateQtScene(fRot_sens,0);
1698  }
1699  else if (evnt->key() == Qt::Key_Right) { // rotate theta
1700  rotateQtScene(-fRot_sens,0);
1701  }
1702  if (evnt->key() == Qt::Key_Plus) { // go forward ("Plus" imply
1703  // "Shift" on Mac French keyboard
1704  moveScene(0,0,-1,false);
1705  }
1706 
1707  // Alt Modifier
1708  }
1709  if ((fAltKeyPress)) {
1710  fGLWidget->setCursor(QCursor(Qt::ClosedHandCursor));
1711 
1712  if (evnt->key() == Qt::Key_Down) { // rotate phi
1713  rotateQtSceneToggle(0,-fRot_sens);
1714  }
1715  else if (evnt->key() == Qt::Key_Up) { // rotate phi
1716  rotateQtSceneToggle(0,fRot_sens);
1717  }
1718  if (evnt->key() == Qt::Key_Left) { // rotate theta
1719  rotateQtSceneToggle(fRot_sens,0);
1720  }
1721  else if (evnt->key() == Qt::Key_Right) { // rotate theta
1722  rotateQtSceneToggle(-fRot_sens,0);
1723  }
1724 
1725  // Rotatio +/-
1726  if (evnt->key() == Qt::Key_Plus) {
1727  fRot_sens = fRot_sens/0.7;
1728  G4cout << "Auto-rotation set to : " << fRot_sens << G4endl;
1729  }
1730  else if (evnt->key() == Qt::Key_Minus) {
1731  fRot_sens = fRot_sens*0.7;
1732  G4cout << "Auto-rotation set to : " << fRot_sens << G4endl;
1733  }
1734 
1735  // Control Modifier OR Command on MAC
1736  }
1737  if ((fControlKeyPress)) {
1738  if (evnt->key() == Qt::Key_Plus) {
1739  fVP.SetZoomFactor(fVP.GetZoomFactor()*(1+fDeltaZoom));
1740  updateQWidget();
1741  }
1742  else if (evnt->key() == Qt::Key_Minus) {
1743  fVP.SetZoomFactor(fVP.GetZoomFactor()*(1-fDeltaZoom));
1744  updateQWidget();
1745  }
1746  }
1747 
1748  fHoldKeyEvent = false;
1749 }
1750 
1751 
1752 void G4OpenGLQtViewer::G4keyReleaseEvent (QKeyEvent *)
1753 {
1754  fGLWidget->setCursor(QCursor(Qt::ArrowCursor));
1755 }
1756 
1757 
1758 void G4OpenGLQtViewer::updateKeyModifierState(const Qt::KeyboardModifiers& modifier) {
1759  // Check Qt Versions for META Keys
1760 
1761  fNoKeyPress = true;
1762  fAltKeyPress = false;
1763  fShiftKeyPress = false;
1764  fControlKeyPress = false;
1765 
1766  if (modifier & Qt::AltModifier ) {
1767  fAltKeyPress = true;
1768  fNoKeyPress = false;
1769  }
1770  if (modifier & Qt::ShiftModifier ) {
1771  fShiftKeyPress = true;
1772  fNoKeyPress = false;
1773  }
1774  if (modifier & Qt::ControlModifier ) {
1775  fControlKeyPress = true;
1776  fNoKeyPress = false;
1777  }
1778 }
1779 
1780 
1783 void G4OpenGLQtViewer::stopVideo() {
1784 
1785  // if encoder parameter is wrong, display parameters dialog and return
1786  if (!fMovieParametersDialog) {
1787  showMovieParametersDialog();
1788  }
1789  setRecordingStatus(STOP);
1790 
1791  if (fRecordFrameNumber >0) {
1792  // check parameters if they were modified (Re APPLY them...)
1793  if (!(fMovieParametersDialog->checkEncoderSwParameters())) {
1794  setRecordingStatus(BAD_ENCODER);
1795  } else if (!(fMovieParametersDialog->checkSaveFileNameParameters())) {
1796  setRecordingStatus(BAD_OUTPUT);
1797  }
1798  } else {
1799  resetRecording();
1800  setRecordingInfos("No frame to encode.");
1801  }
1802 }
1803 
1806 void G4OpenGLQtViewer::saveVideo() {
1807 
1808  // if encoder parameter is wrong, display parameters dialog and return
1809  if (!fMovieParametersDialog) {
1810  showMovieParametersDialog();
1811  }
1812 
1813  fMovieParametersDialog->checkEncoderSwParameters();
1814  fMovieParametersDialog->checkSaveFileNameParameters();
1815 
1816  if (fRecordingStep == STOP) {
1817  setRecordingStatus(SAVE);
1818  generateMpegEncoderParameters();
1819  encodeVideo();
1820  }
1821 }
1822 
1823 
1826 void G4OpenGLQtViewer::startPauseVideo() {
1827 
1828  // first time, if temp parameter is wrong, display parameters dialog and return
1829 
1830  if ( fRecordingStep == WAIT) {
1831  if ( fRecordFrameNumber == 0) {
1832  if (getTempFolderPath() == "") { // BAD_OUTPUT
1833  showMovieParametersDialog();
1834  setRecordingInfos("You should specified the temp folder in order to make movie");
1835  return;
1836  } else {
1837  // remove temp folder if it was create
1838  QString tmp = removeTempFolder();
1839  if (tmp !="") {
1840  setRecordingInfos(tmp);
1841  return;
1842  }
1843  tmp = createTempFolder();
1844  if (tmp != "") {
1845  setRecordingInfos("Can't create temp folder."+tmp);
1846  return;
1847  }
1848  }
1849  }
1850  }
1851  if (fRecordingStep == WAIT) {
1852  setRecordingStatus(START);
1853  } else if (fRecordingStep == START) {
1854  setRecordingStatus(PAUSE);
1855  } else if (fRecordingStep == PAUSE) {
1856  setRecordingStatus(CONTINUE);
1857  } else if (fRecordingStep == CONTINUE) {
1858  setRecordingStatus(PAUSE);
1859  }
1860 }
1861 
1862 void G4OpenGLQtViewer::setRecordingStatus(RECORDING_STEP step) {
1863 
1864  fRecordingStep = step;
1865  displayRecordingStatus();
1866 }
1867 
1868 
1869 void G4OpenGLQtViewer::displayRecordingStatus() {
1870 
1871  QString txtStatus = "";
1872  if (fRecordingStep == WAIT) {
1873  txtStatus = "Waiting to start...";
1874  fRecordFrameNumber = 0; // reset the frame number
1875  } else if (fRecordingStep == START) {
1876  txtStatus = "Start Recording...";
1877  } else if (fRecordingStep == PAUSE) {
1878  txtStatus = "Pause Recording...";
1879  } else if (fRecordingStep == CONTINUE) {
1880  txtStatus = "Continue Recording...";
1881  } else if (fRecordingStep == STOP) {
1882  txtStatus = "Stop Recording...";
1883  } else if (fRecordingStep == READY_TO_ENCODE) {
1884  txtStatus = "Ready to Encode...";
1885  } else if (fRecordingStep == ENCODING) {
1886  txtStatus = "Encoding...";
1887  } else if (fRecordingStep == FAILED) {
1888  txtStatus = "Failed to encode...";
1889  } else if ((fRecordingStep == BAD_ENCODER)
1890  || (fRecordingStep == BAD_OUTPUT)
1891  || (fRecordingStep == BAD_TMP)) {
1892  txtStatus = "Correct above errors first";
1893  } else if (fRecordingStep == SUCCESS) {
1894  txtStatus = "File encoded successfully";
1895  } else {
1896  }
1897 
1898  if (fMovieParametersDialog) {
1899  fMovieParametersDialog->setRecordingStatus(txtStatus);
1900  } else {
1901  G4cout << txtStatus.toStdString().c_str() << G4endl;
1902  }
1903  setRecordingInfos("");
1904 }
1905 
1906 
1907 void G4OpenGLQtViewer::setRecordingInfos(const QString& txt) {
1908  if (fMovieParametersDialog) {
1909  fMovieParametersDialog->setRecordingInfos(txt);
1910  } else {
1911  G4cout << txt.toStdString().c_str() << G4endl;
1912  }
1913 }
1914 
1917 void G4OpenGLQtViewer::initMovieParameters() {
1918  //init encoder
1919 
1920  //look for encoderPath
1921  fProcess = new QProcess();
1922 
1923  QObject ::connect(fProcess,SIGNAL(finished ( int)),
1924  this,SLOT(processLookForFinished()));
1925  fProcess->setReadChannelMode(QProcess::MergedChannels);
1926  fProcess->start ("which ppmtompeg");
1927 
1928 }
1929 
1932 QString G4OpenGLQtViewer::getEncoderPath() {
1933  return fEncoderPath;
1934 }
1935 
1936 
1941 QString G4OpenGLQtViewer::setEncoderPath(QString path) {
1942  if (path == "") {
1943  return "ppmtompeg is needed to encode in video format. It is available here: http://netpbm.sourceforge.net ";
1944  }
1945 
1946  path = QDir::cleanPath(path);
1947  QFileInfo *f = new QFileInfo(path);
1948  if (!f->exists()) {
1949  return "File does not exist";
1950  } else if (f->isDir()) {
1951  return "This is a directory";
1952  } else if (!f->isExecutable()) {
1953  return "File exist but is not executable";
1954  } else if (!f->isFile()) {
1955  return "This is not a file";
1956  }
1957  fEncoderPath = path;
1958 
1959  if (fRecordingStep == BAD_ENCODER) {
1960  setRecordingStatus(STOP);
1961  }
1962  return "";
1963 }
1964 
1965 
1966 bool G4OpenGLQtViewer::isRecording(){
1967  if ((fRecordingStep == START) || (fRecordingStep == CONTINUE)) {
1968  return true;
1969  }
1970  return false;
1971 }
1972 
1973 bool G4OpenGLQtViewer::isPaused(){
1974  if (fRecordingStep == PAUSE) {
1975  return true;
1976  }
1977  return false;
1978 }
1979 
1980 bool G4OpenGLQtViewer::isEncoding(){
1981  if (fRecordingStep == ENCODING) {
1982  return true;
1983  }
1984  return false;
1985 }
1986 
1987 bool G4OpenGLQtViewer::isWaiting(){
1988  if (fRecordingStep == WAIT) {
1989  return true;
1990  }
1991  return false;
1992 }
1993 
1994 bool G4OpenGLQtViewer::isStopped(){
1995  if (fRecordingStep == STOP) {
1996  return true;
1997  }
1998  return false;
1999 }
2000 
2001 bool G4OpenGLQtViewer::isFailed(){
2002  if (fRecordingStep == FAILED) {
2003  return true;
2004  }
2005  return false;
2006 }
2007 
2008 bool G4OpenGLQtViewer::isSuccess(){
2009  if (fRecordingStep == SUCCESS) {
2010  return true;
2011  }
2012  return false;
2013 }
2014 
2015 bool G4OpenGLQtViewer::isBadEncoder(){
2016  if (fRecordingStep == BAD_ENCODER) {
2017  return true;
2018  }
2019  return false;
2020 }
2021 bool G4OpenGLQtViewer::isBadTmp(){
2022  if (fRecordingStep == BAD_TMP) {
2023  return true;
2024  }
2025  return false;
2026 }
2027 bool G4OpenGLQtViewer::isBadOutput(){
2028  if (fRecordingStep == BAD_OUTPUT) {
2029  return true;
2030  }
2031  return false;
2032 }
2033 
2034 void G4OpenGLQtViewer::setBadEncoder(){
2035  fRecordingStep = BAD_ENCODER;
2036  displayRecordingStatus();
2037 }
2038 void G4OpenGLQtViewer::setBadTmp(){
2039  fRecordingStep = BAD_TMP;
2040  displayRecordingStatus();
2041 }
2042 void G4OpenGLQtViewer::setBadOutput(){
2043  fRecordingStep = BAD_OUTPUT;
2044  displayRecordingStatus();
2045 }
2046 
2047 void G4OpenGLQtViewer::setWaiting(){
2048  fRecordingStep = WAIT;
2049  displayRecordingStatus();
2050 }
2051 
2052 
2053 bool G4OpenGLQtViewer::isReadyToEncode(){
2054  if (fRecordingStep == READY_TO_ENCODE) {
2055  return true;
2056  }
2057  return false;
2058 }
2059 
2060 void G4OpenGLQtViewer::resetRecording() {
2061  setRecordingStatus(WAIT);
2062 }
2063 
2068 QString G4OpenGLQtViewer::setTempFolderPath(QString path) {
2069 
2070  if (path == "") {
2071  return "Path does not exist";
2072  }
2073  path = QDir::cleanPath(path);
2074  QFileInfo *d = new QFileInfo(path);
2075  if (!d->exists()) {
2076  return "Path does not exist";
2077  } else if (!d->isDir()) {
2078  return "This is not a directory";
2079  } else if (!d->isReadable()) {
2080  return path +" is read protected";
2081  } else if (!d->isWritable()) {
2082  return path +" is write protected";
2083  }
2084 
2085  if (fRecordingStep == BAD_TMP) {
2086  setRecordingStatus(WAIT);
2087  }
2088  fTempFolderPath = path;
2089  return "";
2090 }
2091 
2094 QString G4OpenGLQtViewer::getTempFolderPath() {
2095  return fTempFolderPath;
2096 }
2097 
2102 QString G4OpenGLQtViewer::setSaveFileName(QString path) {
2103 
2104  if (path == "") {
2105  return "Path does not exist";
2106  }
2107 
2108  QFileInfo *file = new QFileInfo(path);
2109  QDir dir = file->dir();
2110  path = QDir::cleanPath(path);
2111  if (file->exists()) {
2112  return "File already exist, please choose a new one";
2113  } else if (!dir.exists()) {
2114  return "Dir does not exist";
2115  } else if (!dir.isReadable()) {
2116  return path +" is read protected";
2117  }
2118 
2119  if (fRecordingStep == BAD_OUTPUT) {
2120  setRecordingStatus(STOP);
2121  }
2122  fSaveFileName = path;
2123  return "";
2124 }
2125 
2128 QString G4OpenGLQtViewer::getSaveFileName() {
2129  return fSaveFileName ;
2130 }
2131 
2136 QString G4OpenGLQtViewer::createTempFolder() {
2137  fMovieTempFolderPath = "";
2138  //check
2139  QString tmp = setTempFolderPath(fTempFolderPath);
2140  if (tmp != "") {
2141  return tmp;
2142  }
2143  QString sep = QString(QDir::separator());
2144  QString path = sep+"QtMovie_"+QDateTime::currentDateTime ().toString("dd-MM-yyyy_hh-mm-ss")+sep;
2145  QDir *d = new QDir(QDir::cleanPath(fTempFolderPath));
2146  // check if it is already present
2147  if (d->exists(path)) {
2148  return "Folder "+path+" already exists.Please remove it first";
2149  }
2150  if (d->mkdir(fTempFolderPath+path)) {
2151  fMovieTempFolderPath = fTempFolderPath+path;
2152  return "";
2153  }
2154  return "Can't create "+fTempFolderPath+path;
2155 }
2156 
2159 QString G4OpenGLQtViewer::removeTempFolder() {
2160  // remove files in Qt_temp folder
2161  if (fMovieTempFolderPath == "") {
2162  return "";
2163  }
2164  QDir *d = new QDir(QDir::cleanPath(fMovieTempFolderPath));
2165  if (!d->exists()) {
2166  return ""; // already remove
2167  }
2168 
2169  d->setFilter( QDir::Files );
2170  QStringList subDirList = d->entryList();
2171  int res = true;
2172  QString error = "";
2173  for (QStringList::ConstIterator it = subDirList.begin() ;(it != subDirList.end()) ; it++) {
2174  const QString currentFile = *it;
2175  if (!d->remove(currentFile)) {
2176  res = false;
2177  QString file = fMovieTempFolderPath+currentFile;
2178  error +="Removing file failed : "+file;
2179  } else {
2180  }
2181  }
2182  if (res) {
2183  if (d->rmdir(fMovieTempFolderPath)) {
2184  fMovieTempFolderPath = "";
2185  return "";
2186  } else {
2187  return "Dir "+fMovieTempFolderPath+" should be empty, but could not remove it";
2188  }
2189 
2190  }
2191  return "Could not remove "+fMovieTempFolderPath+" because of the following errors :"+error;
2192 }
2193 
2201 bool G4OpenGLQtViewer::exportImage(std::string name, int width, int height) {
2202 
2203  QGLWidget* qGLW = dynamic_cast<QGLWidget*> (fGLWidget) ;
2204  if (! qGLW) {
2205  return false;
2206  }
2207  // If there is already an extention
2208  bool increaseFileNumber = true;
2209  // if
2210  if (name.size() != name.substr(name.find_last_of(".") + 1).size()) {
2211  increaseFileNumber = false;
2212  }
2213  if (! setExportFilename(name,increaseFileNumber)) {
2214  return false;
2215  }
2216  if ((width !=-1) && (height != -1)) {
2217  setExportSize(width, height);
2218  }
2219  // first, try to do it with generic function
2220  if (G4OpenGLViewer::exportImage()) {
2221  return true;
2222 
2223  // Then try Qt saving functions
2224  } else {
2225  QImage image;
2226  image = qGLW->grabFrameBuffer();
2227 
2228  bool res = image.save(QString(getRealPrintFilename().c_str()),0,fLastExportSliderValue);
2229 
2230  if (!res) {
2231  G4cerr << "Error saving file... " << getRealPrintFilename().c_str() << G4endl;
2232  return false;
2233  } else {
2234  G4cout << "File " << getRealPrintFilename().c_str() << " size: " << fGLWidget->width() << "x" << fGLWidget->height() << " has been saved " << G4endl;
2235  fExportFilenameIndex++;
2236  }
2237  }
2238  return true;
2239 }
2240 
2241 
2242 
2243 bool G4OpenGLQtViewer::hasPendingEvents () {
2244  return ((QApplication*)G4Qt::getInstance ())->hasPendingEvents ();
2245 }
2246 
2247 bool G4OpenGLQtViewer::generateMpegEncoderParameters () {
2248 
2249  // save the parameter file
2250  FILE* fp;
2251  fp = fopen (QString(fMovieTempFolderPath+fParameterFileName).toStdString().c_str(), "w");
2252 
2253  if (fp == NULL) {
2254  setRecordingInfos("Generation of parameter file failed");
2255  return false;
2256  }
2257 
2258  fprintf (fp,"# Pattern affects speed, quality and compression. See the User's Guide\n");
2259  fprintf (fp,"# for more info.\n");
2260  fprintf (fp,"\n");
2261  fprintf (fp,"PATTERN IBBPBBPBBPBBPBBP\n");
2262  fprintf (fp,"OUTPUT %s\n",getSaveFileName().toStdString().c_str());
2263  fprintf (fp,"\n");
2264  fprintf (fp,"# You must specify the type of the input files. The choices are:\n");
2265  fprintf (fp,"# YUV, PPM, JMOVIE, Y, JPEG, PNM\n");
2266  fprintf (fp,"# (must be upper case)\n");
2267  fprintf (fp,"#\n");
2268  fprintf (fp,"BASE_FILE_FORMAT PPM\n");
2269  fprintf (fp,"\n");
2270  fprintf (fp,"#\n");
2271  fprintf (fp,"# if YUV format (or using parallel version), must provide width and height\n");
2272  fprintf (fp,"# YUV_SIZE widthxheight\n");
2273  fprintf (fp,"# this option is ignored if BASE_FILE_FORMAT is not YUV and you're running\n");
2274  fprintf (fp,"# on just one machine\n");
2275  fprintf (fp,"#\n");
2276  fprintf (fp,"YUV_SIZE 352x240\n");
2277  fprintf (fp,"\n");
2278  fprintf (fp,"# If you are using YUV, there are different supported file formats.\n");
2279  fprintf (fp,"# EYUV or UCB are the same as previous versions of this encoder.\n");
2280  fprintf (fp,"# (All the Y's, then U's then V's, in 4:2:0 subsampling.)\n");
2281  fprintf (fp,"# Other formats, such as Abekas, Phillips, or a general format are\n");
2282  fprintf (fp,"# permissible, the general format is a string of Y's, U's, and V's\n");
2283  fprintf (fp,"# to specify the file order.\n");
2284  fprintf (fp,"\n");
2285  fprintf (fp,"INPUT_FORMAT UCB\n");
2286  fprintf (fp,"\n");
2287  fprintf (fp,"# the conversion statement\n");
2288  fprintf (fp,"#\n");
2289  fprintf (fp,"# Each occurrence of '*' will be replaced by the input file\n");
2290  fprintf (fp,"#\n");
2291  fprintf (fp,"# e.g., if you have a bunch of GIF files, then this might be:\n");
2292  fprintf (fp,"# INPUT_CONVERT giftoppm *\n");
2293  fprintf (fp,"#\n");
2294  fprintf (fp,"# e.g., if you have a bunch of files like a.Y a.U a.V, etc., then:\n");
2295  fprintf (fp,"# INPUT_CONVERT cat *.Y *.U *.V\n");
2296  fprintf (fp,"#\n");
2297  fprintf (fp,"# e.g., if you are grabbing from laser disc you might have something like\n");
2298  fprintf (fp,"# INPUT_CONVERT goto frame *; grabppm\n");
2299  fprintf (fp,"# 'INPUT_CONVERT *' means the files are already in the base file format\n");
2300  fprintf (fp,"#\n");
2301  fprintf (fp,"INPUT_CONVERT * \n");
2302  fprintf (fp,"\n");
2303  fprintf (fp,"# number of frames in a GOP.\n");
2304  fprintf (fp,"#\n");
2305  fprintf (fp,"# since each GOP must have at least one I-frame, the encoder will find the\n");
2306  fprintf (fp,"# the first I-frame after GOP_SIZE frames to start the next GOP\n");
2307  fprintf (fp,"#\n");
2308  fprintf (fp,"# later, will add more flexible GOP signalling\n");
2309  fprintf (fp,"#\n");
2310  fprintf (fp,"GOP_SIZE 16\n");
2311  fprintf (fp,"\n");
2312  fprintf (fp,"# number of slices in a frame\n");
2313  fprintf (fp,"#\n");
2314  fprintf (fp,"# 1 is a good number. another possibility is the number of macroblock rows\n");
2315  fprintf (fp,"# (which is the height divided by 16)\n");
2316  fprintf (fp,"#\n");
2317  fprintf (fp,"SLICES_PER_FRAME 1\n");
2318  fprintf (fp,"\n");
2319  fprintf (fp,"# directory to get all input files from (makes this file easier to read)\n");
2320  fprintf (fp,"INPUT_DIR %s\n",fMovieTempFolderPath.toStdString().c_str());
2321  fprintf (fp,"\n");
2322  fprintf (fp,"# There are a bunch of ways to specify the input files.\n");
2323  fprintf (fp,"# from a simple one-per-line listing, to the following \n");
2324  fprintf (fp,"# way of numbering them. See the manual for more information.\n");
2325  fprintf (fp,"INPUT\n");
2326  fprintf (fp,"# '*' is replaced by the numbers 01, 02, 03, 04\n");
2327  fprintf (fp,"# if I instead do [01-11], it would be 01, 02, ..., 09, 10, 11\n");
2328  fprintf (fp,"# if I instead do [1-11], it would be 1, 2, 3, ..., 9, 10, 11\n");
2329  fprintf (fp,"# if I instead do [1-11+3], it would be 1, 4, 7, 10\n");
2330  fprintf (fp,"# the program assumes none of your input files has a name ending in ']'\n");
2331  fprintf (fp,"# if you do, too bad!!!\n");
2332  fprintf (fp,"#\n");
2333  fprintf (fp,"#\n");
2334  fprintf (fp,"Test*.ppm [0-%d]\n",fRecordFrameNumber-1);
2335  fprintf (fp,"# can have more files here if you want...there is no limit on the number\n");
2336  fprintf (fp,"# of files\n");
2337  fprintf (fp,"END_INPUT\n");
2338  fprintf (fp,"\n");
2339  fprintf (fp,"\n");
2340  fprintf (fp,"\n");
2341  fprintf (fp,"# Many of the remaining options have to do with the motion search and qscale\n");
2342  fprintf (fp,"\n");
2343  fprintf (fp,"# FULL or HALF -- must be upper case\n");
2344  fprintf (fp,"# Should be FULL for computer generated images\n");
2345  fprintf (fp,"PIXEL FULL\n");
2346  fprintf (fp,"\n");
2347  fprintf (fp,"# means +/- this many pixels for both P and B frame searches\n");
2348  fprintf (fp,"# specify two numbers if you wish to serc different ranges in the two.\n");
2349  fprintf (fp,"RANGE 10\n");
2350  fprintf (fp,"\n");
2351  fprintf (fp,"# The two search algorithm parameters below mostly affect speed,\n");
2352  fprintf (fp,"# with some affect on compression and almost none on quality.\n");
2353  fprintf (fp,"\n");
2354  fprintf (fp,"# this must be one of {EXHAUSTIVE, SUBSAMPLE, LOGARITHMIC}\n");
2355  fprintf (fp,"PSEARCH_ALG LOGARITHMIC\n");
2356  fprintf (fp,"\n");
2357  fprintf (fp,"# this must be one of {SIMPLE, CROSS2, EXHAUSTIVE}\n");
2358  fprintf (fp,"#\n");
2359  fprintf (fp,"# note that EXHAUSTIVE is really, really, really slow\n");
2360  fprintf (fp,"#\n");
2361  fprintf (fp,"BSEARCH_ALG SIMPLE\n");
2362  fprintf (fp,"\n");
2363  fprintf (fp,"#\n");
2364  fprintf (fp,"# these specify the q-scale for I, P, and B frames\n");
2365  fprintf (fp,"# (values must be between 1 and 31)\n");
2366  fprintf (fp,"# These are the Qscale values for the entire frame in variable bit-rate\n");
2367  fprintf (fp,"# mode, and starting points (but not important) for constant bit rate\n");
2368  fprintf (fp,"#\n");
2369  fprintf (fp,"\n");
2370  fprintf (fp,"# Qscale (Quantization scale) affects quality and compression,\n");
2371  fprintf (fp,"# but has very little effect on speed.\n");
2372  fprintf (fp,"\n");
2373  fprintf (fp,"IQSCALE 4\n");
2374  fprintf (fp,"PQSCALE 5\n");
2375  fprintf (fp,"BQSCALE 12\n");
2376  fprintf (fp,"\n");
2377  fprintf (fp,"# this must be ORIGINAL or DECODED\n");
2378  fprintf (fp,"REFERENCE_FRAME ORIGINAL\n");
2379  fprintf (fp,"\n");
2380  fprintf (fp,"# for parallel parameters see parallel.param in the exmaples subdirectory\n");
2381  fprintf (fp,"\n");
2382  fprintf (fp,"# if you want constant bit-rate mode, specify it as follows (number is bits/sec):\n");
2383  fprintf (fp,"#BIT_RATE 1000000\n");
2384  fprintf (fp,"\n");
2385  fprintf (fp,"# To specify the buffer size (327680 is default, measused in bits, for 16bit words)\n");
2386  fprintf (fp,"BUFFER_SIZE 327680\n");
2387  fprintf (fp,"\n");
2388  fprintf (fp,"# The frame rate is the number of frames/second (legal values:\n");
2389  fprintf (fp,"# 23.976, 24, 25, 29.97, 30, 50 ,59.94, 60\n");
2390  fprintf (fp,"FRAME_RATE 30\n");
2391  fprintf (fp,"\n");
2392  fprintf (fp,"# There are many more options, see the users manual for examples....\n");
2393  fprintf (fp,"# ASPECT_RATIO, USER_DATA, GAMMA, IQTABLE, etc.\n");
2394  fprintf (fp,"\n");
2395  fprintf (fp,"\n");
2396  fclose (fp);
2397 
2398  setRecordingInfos("Parameter file "+fParameterFileName+" generated in "+fMovieTempFolderPath);
2399  setRecordingStatus(READY_TO_ENCODE);
2400  return true;
2401 }
2402 
2403 void G4OpenGLQtViewer::encodeVideo()
2404 {
2405  if ((getEncoderPath() != "") && (getSaveFileName() != "")) {
2406  setRecordingStatus(ENCODING);
2407 
2408  fProcess = new QProcess();
2409 #if QT_VERSION > 0x040100
2410  QObject ::connect(fProcess,SIGNAL(finished ( int,QProcess::ExitStatus)),
2411  this,SLOT(processEncodeFinished()));
2412  QObject ::connect(fProcess,SIGNAL(readyReadStandardOutput ()),
2413  this,SLOT(processEncodeStdout()));
2414 #else
2415  QObject ::connect(fProcess,SIGNAL(finished ( int)),
2416  this,SLOT(processEncodeFinished()));
2417  QObject ::connect(fProcess,SIGNAL(readyReadStandardOutput ()),
2418  this,SLOT(processEncodeStdout()));
2419 #endif
2420  fProcess->setReadChannelMode(QProcess::MergedChannels);
2421  fProcess->start (fEncoderPath, QStringList(fMovieTempFolderPath+fParameterFileName));
2422  }
2423 }
2424 
2425 
2426 // FIXME : does not work on Qt3
2427 void G4OpenGLQtViewer::processEncodeStdout()
2428 {
2429  QString tmp = fProcess->readAllStandardOutput ().data();
2430  int start = tmp.lastIndexOf("ESTIMATED TIME");
2431  tmp = tmp.mid(start,tmp.indexOf("\n",start)-start);
2432  setRecordingInfos(tmp);
2433 }
2434 
2435 
2436 void G4OpenGLQtViewer::processEncodeFinished()
2437 {
2438 
2439  QString txt = "";
2440  txt = getProcessErrorMsg();
2441  if (txt == "") {
2442  setRecordingStatus(SUCCESS);
2443  } else {
2444  setRecordingStatus(FAILED);
2445  }
2446  // setRecordingInfos(txt+removeTempFolder());
2447 }
2448 
2449 
2450 void G4OpenGLQtViewer::processLookForFinished()
2451 {
2452 
2453  QString txt = getProcessErrorMsg();
2454  if (txt != "") {
2455  fEncoderPath = "";
2456  } else {
2457  fEncoderPath = QString(fProcess->readAllStandardOutput ().data()).trimmed();
2458  // if not found, return "not found"
2459  if (fEncoderPath.contains(" ")) {
2460  fEncoderPath = "";
2461  } else if (!fEncoderPath.contains("ppmtompeg")) {
2462  fEncoderPath = "";
2463  }
2464  setEncoderPath(fEncoderPath);
2465  }
2466  // init temp folder
2467  setTempFolderPath(QDir::temp ().absolutePath ());
2468 }
2469 
2470 
2471 QString G4OpenGLQtViewer::getProcessErrorMsg()
2472 {
2473  QString txt = "";
2474  if (fProcess->exitCode() != 0) {
2475  switch (fProcess->error()) {
2476  case QProcess::FailedToStart:
2477  txt = "The process failed to start. Either the invoked program is missing, or you may have insufficient permissions to invoke the program.\n";
2478  break;
2479  case QProcess::Crashed:
2480  txt = "The process crashed some time after starting successfully.\n";
2481  break;
2482  case QProcess::Timedout:
2483  txt = "The last waitFor...() function timed out. The state of QProcess is unchanged, and you can try calling waitFor...() again.\n";
2484  break;
2485  case QProcess::WriteError:
2486  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";
2487  break;
2488  case QProcess::ReadError:
2489  txt = "An error occurred when attempting to read from the process. For example, the process may not be running.\n";
2490  break;
2491  case QProcess::UnknownError:
2492  txt = "An unknown error occurred. This is the default return value of error().\n";
2493  break;
2494  }
2495  }
2496  return txt;
2497 }
2498 
2499 
2500 
2501 
2502 QWidget *G4OpenGLQtViewer::getParentWidget()
2503 {
2504  // launch Qt if not
2505  G4Qt* interactorManager = G4Qt::getInstance ();
2506  // G4UImanager* UI =
2507  // G4UImanager::GetUIpointer();
2508 
2509  bool found = false;
2510  QDialog* dialog = NULL;
2511  // create window
2512  if (((QApplication*)interactorManager->GetMainInteractor())) {
2513  // look for the main window
2514  QWidgetList wl = QApplication::allWidgets();
2515  QWidget *widget = NULL;
2516  for (int i=0; i < wl.size(); i++) {
2517  widget = wl.at(i);
2518  if ((found== false) && (widget->inherits("QMainWindow"))) {
2519  dialog = new QDialog(widget,Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowMinMaxButtonsHint);
2520  found = true;
2521  }
2522  }
2523 
2524  if (found==false) {
2525  dialog = new QDialog();
2526  }
2527  } else {
2528  dialog= new QDialog();
2529  }
2530  if (found) {
2531  return dialog;
2532  } else {
2533  return NULL;
2534  }
2535 }
2536 
2537 
2538 void G4OpenGLQtViewer::createSceneTreeComponent(){
2539 
2540  QGroupBox *groupBox = new QGroupBox("");
2541  QVBoxLayout *vbox = new QVBoxLayout;
2542 
2543  fSceneTreeViewerButton = new QPushButton("Scene tree");
2544  fSceneTreeViewerButton->setStyleSheet ("text-align: left; padding: 2px; border:0px; background:#e0e5ef;");
2545  fSceneTreeViewerButton->setIcon(*fTreeIconOpen);
2546 
2547  vbox->addWidget(fSceneTreeViewerButton);
2548  connect(fSceneTreeViewerButton,SIGNAL(clicked()),this, SLOT(toggleSceneTreeViewerInfos()));
2549 
2550  fSceneTreeViewerInfos = new QWidget();
2551  fSceneTreeViewerInfos->setStyleSheet ("padding: 0px ");
2552  fSceneTreeViewerInfos->setSizePolicy(QSizePolicy::Minimum,QSizePolicy::Minimum);
2553 
2554  QVBoxLayout* vLayout = new QVBoxLayout();
2555  fSceneTreeViewerInfos->setLayout (vLayout);
2556 
2557  // Search line
2558  QWidget* coutButtonWidget = new QWidget();
2559  QHBoxLayout* layoutCoutTBButtons = new QHBoxLayout();
2560 
2561  fFilterOutput = new QLineEdit();
2562  fFilterOutput->setToolTip("Filter output by...");
2563  fFilterOutput->setStyleSheet ("padding: 0px ");
2564 
2565  QPixmap* searchIcon = fUiQt->getSearchIcon();
2566 #if QT_VERSION > 0x050100
2567  fFilterOutput->addAction(*searchIcon,QLineEdit::TrailingPosition);
2568  fFilterOutput->setStyleSheet ("border-radius:7px;");
2569 #else
2570  QPushButton *coutTBFilterButton = new QPushButton();
2571  coutTBFilterButton->setIcon(*searchIcon);
2572  coutTBFilterButton->setStyleSheet ("padding-left: 0px; border:0px;");
2573  fFilterOutput->setStyleSheet ("padding-right: 0px;");
2574 #endif
2575  layoutCoutTBButtons->addWidget(fFilterOutput);
2576 
2577 #if QT_VERSION <= 0x050100
2578  layoutCoutTBButtons->addWidget(coutTBFilterButton);
2579 #endif
2580 
2581  coutButtonWidget->setLayout(layoutCoutTBButtons);
2582  vLayout->addWidget(coutButtonWidget);
2583 
2584  // reduce margins
2585  vLayout->setContentsMargins(0,0,0,0);
2586  vbox->setContentsMargins(1,1,1,1);
2587 
2588 
2589  fSceneTreeComponentTreeWidget = new QTreeWidget();
2590  fSceneTreeComponentTreeWidget->setSelectionMode(QAbstractItemView::SingleSelection);
2591  fSceneTreeComponentTreeWidget->setHeaderLabel ("Scene tree : "+QString(GetName().data()));
2592  fSceneTreeComponentTreeWidget->setColumnHidden (1,true); // copy number
2593  fSceneTreeComponentTreeWidget->setColumnHidden (2,true); // PO index
2594  fSceneTreeComponentTreeWidget->setColumnHidden (3,true); // Informations
2595  // data(0) : POindex
2596  // data(1) : copy number
2597  // data(2) : g4color
2598 
2599  vLayout->addWidget(fSceneTreeComponentTreeWidget);
2600 
2601  connect(fSceneTreeComponentTreeWidget,SIGNAL(itemChanged(QTreeWidgetItem*, int)),SLOT(sceneTreeComponentItemChanged(QTreeWidgetItem*, int)));
2602  connect(fSceneTreeComponentTreeWidget,SIGNAL(itemSelectionChanged ()),SLOT(sceneTreeComponentSelected()));
2603  connect(fSceneTreeComponentTreeWidget,SIGNAL(itemDoubleClicked ( QTreeWidgetItem*, int)),SLOT(changeColorAndTransparency( QTreeWidgetItem*, int)));
2604 
2605 
2606  // Depth slider
2607  QWidget *helpWidget = new QWidget();
2608  QHBoxLayout *helpLayout = new QHBoxLayout();
2609 
2610  QWidget* depthWidget = new QWidget();
2611  QWidget *showBox = new QWidget(depthWidget);
2612  QHBoxLayout *showBoxLayout = new QHBoxLayout();
2613 
2614  // reduce margins
2615  showBoxLayout->setContentsMargins(5,5,5,5);
2616 
2617  QLabel *zero = new QLabel();
2618  zero->setText("Show all");
2619  QLabel *one = new QLabel();
2620  one->setText("Hide all");
2621  fSceneTreeDepthSlider = new QSlider ( Qt::Horizontal);
2622  fSceneTreeDepthSlider->setMaximum (1000);
2623  fSceneTreeDepthSlider->setMinimum (0);
2624  fSceneTreeDepthSlider->setTickPosition(QSlider::TicksAbove);
2625  // set a minimum size
2626  fSceneTreeDepthSlider->setMinimumWidth (40);
2627 
2628  showBoxLayout->addWidget(zero);
2629  showBoxLayout->addWidget(fSceneTreeDepthSlider);
2630  showBoxLayout->addWidget(one);
2631 
2632  showBox->setLayout(showBoxLayout);
2633 
2634  helpLayout->addWidget(showBox);
2635  helpWidget->setLayout(helpLayout);
2636  helpLayout->setContentsMargins(0,0,0,0);
2637 
2638  vLayout->addWidget(helpWidget);
2639  QSizePolicy vPolicy = fSceneTreeViewerInfos->sizePolicy();
2640  vPolicy.setVerticalStretch(4);
2641 
2642  vbox->addWidget(fSceneTreeViewerInfos);
2643 
2644  groupBox->setLayout(vbox);
2645  fSceneTreeWidget->layout()->addWidget(groupBox);
2646 
2647  connect( fSceneTreeDepthSlider, SIGNAL( valueChanged(int) ), this, SLOT( changeDepthInSceneTree(int) ) );
2648  fTreeItemModels.clear();
2649 
2650  fPVRootNodeCreate = false;
2651 
2652  fMaxPOindexInserted = -1;
2653 
2654 
2655 }
2656 
2657 
2658 void G4OpenGLQtViewer::createViewerPropertiesComponent() {
2659 
2660  // add properties
2661  QGroupBox *groupBox = new QGroupBox("");
2662  QVBoxLayout *vbox = new QVBoxLayout;
2663  fViewerPropertiesButton = new QPushButton("Viewer properties");
2664  fViewerPropertiesButton->setStyleSheet ("text-align: left; padding: 2px; border:0px; background:#e0e5ef;");
2665 
2666  fViewerPropertiesButton->setIcon(*fTreeIconOpen);
2667 
2668  vbox->addWidget(fViewerPropertiesButton);
2669  connect(fViewerPropertiesButton,SIGNAL(clicked()),this, SLOT(toggleSceneTreeComponentTreeWidgetInfos()));
2670 
2671  // add properties content
2672  fSceneTreeComponentTreeWidgetInfos = new QTableWidget();
2673  fSceneTreeComponentTreeWidgetInfos->setStyleSheet ("padding: 0px ");
2674  vbox->addWidget(fSceneTreeComponentTreeWidgetInfos);
2675  vbox->setContentsMargins(1,1,1,1);
2676 
2677  groupBox->setLayout(vbox);
2678  fSceneTreeWidget->layout()->addWidget(groupBox);
2679  QSizePolicy vPolicy = fSceneTreeComponentTreeWidgetInfos->sizePolicy();
2680  vPolicy.setVerticalStretch(4);
2681 
2682  connect(fSceneTreeComponentTreeWidgetInfos, SIGNAL(itemChanged(QTableWidgetItem*)),this, SLOT(tableWidgetViewerSetItemChanged(QTableWidgetItem *)));
2683 
2684  updateSceneTreeComponentTreeWidgetInfos();
2685 }
2686 
2687 
2688 void G4OpenGLQtViewer::createPickingComponent(){
2689 
2690  QGroupBox *groupBox = new QGroupBox("");
2691  QVBoxLayout *vbox = new QVBoxLayout;
2692 
2693  // add picking infos
2694  QWidget *pickingInfoWidget = new QWidget();
2695  QHBoxLayout *pickingInfoLayout = new QHBoxLayout();
2696 
2697  fViewerPickingButton = new QPushButton("Picking informations");
2698  fViewerPickingButton->setStyleSheet ("text-align: left; padding: 2px; border:0px; background:#e0e5ef;");
2699  fViewerPickingButton->setIcon(*fTreeIconOpen);
2700 
2701  // initialise picking infos
2702 
2703  QCheckBox * activatePicking = new QCheckBox("Picking mode active");
2704  if (fVP.IsPicking()) {
2705  activatePicking->setCheckState(Qt::Checked);
2706  } else {
2707  activatePicking->setCheckState(Qt::Unchecked);
2708  }
2709  activatePicking->setToolTip("Enable picking allow you to display properties of a selected object on the scene");
2710  connect(activatePicking, SIGNAL(clicked()), this, SLOT(togglePicking()));
2711 
2712  pickingInfoLayout->addWidget(fViewerPickingButton);
2713  pickingInfoLayout->addWidget(activatePicking);
2714 
2715  pickingInfoWidget->setStyleSheet ("padding-left: 0px; border:0px;");
2716  pickingInfoWidget->setLayout(pickingInfoLayout);
2717 
2718  vbox->addWidget(pickingInfoWidget);
2719  connect(fViewerPickingButton,SIGNAL(clicked()),this, SLOT(toggleSceneTreeComponentPickingInfos()));
2720 
2721  // add picking content
2722 
2723  fSceneTreeComponentPickingScrollArea = new QScrollArea();
2724  fSceneTreeComponentPickingScrollArea->setWidgetResizable(true);
2725 
2726 
2727  fSceneTreeComponentPickingInfos = new QWidget();
2728  fSceneTreeComponentPickingInfos->setStyleSheet ("padding: 0px ");
2729 
2730  QVBoxLayout* vLayout = new QVBoxLayout();
2731  fSceneTreeComponentPickingInfos->setLayout (vLayout);
2732  fSceneTreeComponentPickingScrollArea->setWidget(fSceneTreeComponentPickingInfos);
2733 
2734  QSizePolicy vPolicy = fSceneTreeComponentPickingInfos->sizePolicy();
2735  vPolicy.setVerticalStretch(4);
2736  vbox->addWidget(fSceneTreeComponentPickingScrollArea);
2737  pickingInfoLayout->setContentsMargins(0,0,0,0);
2738  vLayout->setContentsMargins(0,0,0,0);
2739  vbox->setContentsMargins(1,1,1,1);
2740 
2741  groupBox->setLayout(vbox);
2742  fSceneTreeWidget->layout()->addWidget(groupBox);
2743  connect( fFilterOutput, SIGNAL( textEdited ( const QString &) ), this, SLOT(changeSearchSelection()));
2744 
2745 }
2746 
2747 
2748 // set the component to check/unchecked, also go into its child
2749 // and set the same status to all his childs
2750 void G4OpenGLQtViewer::setCheckComponent(QTreeWidgetItem* item,bool check)
2751 {
2752  if (item != NULL) {
2753  if (check) {
2754  item->setCheckState(0,Qt::Checked);
2755  } else {
2756  item->setCheckState(0,Qt::Unchecked);
2757  }
2758  updatePositivePoIndexSceneTreeWidgetQuickMap(item->data(0,Qt::UserRole).toInt(),item);
2759  int nChildCount = item->childCount();
2760  for (int i = 0; i < nChildCount; i++) {
2761  setCheckComponent(item->child(i),check);
2762  }
2763  }
2764 }
2765 
2766 
2767 void G4OpenGLQtViewer::DrawText(const G4Text& g4text)
2768 {
2769  QGLWidget* qGLW = dynamic_cast<QGLWidget*> (fGLWidget) ;
2770  if (! qGLW) {
2771  return;
2772  }
2773  if (isGl2psWriting()) {
2774 
2775  G4OpenGLViewer::DrawText(g4text);
2776 
2777  } else {
2778 
2779  if (!fGLWidget) return;
2780 
2781 #ifdef G4MULTITHREADED
2783 #endif
2784 
2786  G4double size = fSceneHandler.GetMarkerSize(g4text,sizeType);
2787 
2788  QFont font = QFont();
2789  font.setPointSizeF(size);
2790 
2791  const G4Colour& c = fSceneHandler.GetTextColour(g4text);
2792  glColor4d(c.GetRed(),c.GetGreen(),c.GetBlue(),c.GetAlpha());
2793 
2794  G4Point3D position = g4text.GetPosition();
2795 
2796  const G4String& textString = g4text.GetText();
2797  const char* textCString = textString.c_str();
2798 
2799  glRasterPos3d(position.x(),position.y(),position.z());
2800 
2801  // Calculate move for centre and right adjustment
2802  QFontMetrics* f = new QFontMetrics (font);
2803  G4double span = f->width(textCString);
2804  G4double xmove = 0., ymove = 0.;
2805  switch (g4text.GetLayout()) {
2806  case G4Text::left: break;
2807  case G4Text::centre: xmove -= span / 2.; break;
2808  case G4Text::right: xmove -= span;
2809  }
2810 
2811  //Add offsets
2812  xmove += g4text.GetXOffset();
2813  ymove += g4text.GetYOffset();
2814 
2815  qGLW->renderText
2816  ((position.x()+(2*xmove)/getWinWidth()),
2817  (position.y()+(2*ymove)/getWinHeight()),
2818  position.z(),
2819  textCString,
2820  font);
2821 
2822  }
2823 }
2824 
2825 
2826 void G4OpenGLQtViewer::ResetView () {
2827  G4OpenGLViewer::ResetView();
2828  fDeltaDepth = 0.01;
2829  fDeltaZoom = 0.05;
2830 }
2831 
2832 
2833 
2834 
2835 void G4OpenGLQtViewer::addPVSceneTreeElement(const G4String& model, G4PhysicalVolumeModel* pPVModel, int currentPOIndex) {
2836 
2837  const QString& modelShortName = getModelShortName(model);
2838 
2839  if (modelShortName == "") {
2840  return ;
2841  }
2842  // try to init it
2843  if (fSceneTreeComponentTreeWidget == NULL) {
2844  createSceneTreeComponent();
2845  }
2846 
2847  // if no UI
2848  if (fSceneTreeComponentTreeWidget == NULL) {
2849  return;
2850  }
2851 
2852  fSceneTreeComponentTreeWidget->blockSignals(true);
2853 
2854  // Create the "volume" node if not
2855  // if (fSceneTreeComponentTreeWidget->topLevelItemCount () == 0) {
2856  if (!fPVRootNodeCreate) {
2857  const G4VisAttributes* visAttr = GetApplicableVisAttributes(pPVModel->GetFullPVPath().at(0).GetPhysicalVolume()->GetLogicalVolume()->GetVisAttributes());
2858  const G4Colour& color = visAttr->GetColour();
2859 
2860  fModelShortNameItem = createTreeWidgetItem(pPVModel->GetFullPVPath(),
2861  modelShortName,
2862  0, // currentPVCopyNb
2863  -1, // currentPVPOIndex
2864  "",
2865  Qt::Checked,
2866  NULL,
2867  color);
2868  fPVRootNodeCreate = true;
2869  }
2870 
2871  bool added = parseAndInsertInSceneTree(fModelShortNameItem,pPVModel,0,modelShortName,0,currentPOIndex);
2872  if (!added) {
2873  }
2874 
2875  fSceneTreeComponentTreeWidget->blockSignals(false);
2876 
2877 }
2878 
2879 
2884 QTreeWidgetItem* G4OpenGLQtViewer::createTreeWidgetItem(
2885  const PVPath& fullPath
2886  ,const QString& name
2887  ,int copyNb
2888  ,int POIndex
2889  ,const QString& logicalName
2890  ,Qt::CheckState state
2891  ,QTreeWidgetItem * parentTreeNode
2892  ,const G4Colour& color
2893 ) {
2894 
2895  // Set depth
2896  if (fullPath.size() > fSceneTreeDepth) {
2897  fSceneTreeDepth = fullPath.size();
2898  // Change slider value
2899  if (fSceneTreeDepthSlider) {
2900  fSceneTreeDepthSlider->setTickInterval(1000/(fSceneTreeDepth+1));
2901  }
2902  }
2903  QTreeWidgetItem * newItem = NULL;
2904  if (parentTreeNode == NULL) {
2905  newItem = new QTreeWidgetItem();
2906  fSceneTreeComponentTreeWidget->addTopLevelItem(newItem);
2907  } else {
2908  newItem = new QTreeWidgetItem(parentTreeNode);
2909  fSceneTreeComponentTreeWidget->addTopLevelItem(parentTreeNode);
2910  }
2911 
2912 
2913  newItem->setText(0,name);
2914  newItem->setData(1,Qt::UserRole,copyNb);
2915  newItem->setText(2,QString::number(POIndex));
2916  newItem->setData(0, Qt::UserRole, POIndex);
2917  newItem->setText(3,logicalName);
2918  newItem->setFlags(newItem->flags()|Qt::ItemIsUserCheckable);
2919  newItem->setCheckState(0,state);
2920  newItem->setExpanded(true);
2921  updatePositivePoIndexSceneTreeWidgetQuickMap(POIndex,newItem);
2922 
2923  changeQColorForTreeWidgetItem(newItem,QColor((int)(color.GetRed()*255),
2924  (int)(color.GetGreen()*255),
2925  (int)(color.GetBlue()*255),
2926  (int)(color.GetAlpha()*255)));
2927 
2928  // If invisible
2929  if ((state == Qt::Unchecked) && (POIndex == -1)) {
2930  newItem->setForeground (0, QBrush( Qt::gray) );
2931 
2932  // Set a tootip
2933  newItem->setToolTip (0,QString(
2934  "This node exists in the geometry but has not been\n")+
2935  "drawn, perhaps because it has been set invisible. It \n"+
2936  "cannot be made visible with a click on the button.\n"+
2937  "To see it, change the visibility, for example, with \n"+
2938  "/vis/geometry/set/visibility " + logicalName + " 0 true\n"+
2939  "and rebuild the view with /vis/viewer/rebuild.\n"+
2940  "Click here will only show/hide all child components");
2941  } else {
2942  // Set a tootip
2943  newItem->setToolTip (0,QString("double-click to change the color"));
2944  }
2945 
2946  // special case: if alpha=0, it is a totally transparent objet,
2947  // then, do not redraw it
2948  if (color.GetAlpha() == 0) {
2949  state = Qt::Unchecked;
2950  newItem->setCheckState(0,state);
2951  updatePositivePoIndexSceneTreeWidgetQuickMap(POIndex,newItem);
2952  }
2953 
2954  fTreeItemModels.insert(std::pair <int, PVPath > (POIndex,fullPath) );
2955 
2956  // Check last status of this item and change if necessary
2957  // open/close/hidden/visible/selected
2958  changeOpenCloseVisibleHiddenSelectedColorSceneTreeElement(newItem);
2959  return newItem;
2960 }
2961 
2962 
2963 //
2964 // Recursive function.
2965 // Try to insert the given item :
2966 // - If not present and last item of the path: insert it and mark it CHECK
2967 // - If not present and NOT last item of the path: insert it and mark it UNCHECKED
2968 // - If already present and name/PO/Transformation identical, then it is a transparent
2969 // object : Change the PO number and transparency
2970 // - If already present and PO different, then it is an unvisible item : Have to
2971 // set it visible
2972 // - else : Create a new element
2973 // @return true if inserted, false if already present
2974 //
2975 bool G4OpenGLQtViewer::parseAndInsertInSceneTree(
2976  QTreeWidgetItem * parentItem
2977  ,G4PhysicalVolumeModel* pPVModel
2978  ,unsigned int fullPathIndex
2979  ,const QString& parentRoot
2980  ,unsigned int currentIndexInTreeSceneHandler
2981  ,int currentPVPOIndex
2982 ) {
2983 
2984  if (parentItem == NULL) {
2985  return false;
2986  }
2987 
2988  const PVPath& fullPath = pPVModel->GetFullPVPath();
2989 
2990  std::ostringstream oss;
2991  oss << fullPath.at(fullPathIndex).GetCopyNo();
2992  std::string currentPVName = G4String(fullPath.at(fullPathIndex).GetPhysicalVolume()->GetName()+" ["+oss.str()+"]").data();
2993 
2994  int currentPVCopyNb = fullPath.at(fullPathIndex).GetCopyNo();
2995 
2996  const G4VisAttributes* visAttr = GetApplicableVisAttributes(fullPath.at(fullPathIndex).GetPhysicalVolume()->GetLogicalVolume()->GetVisAttributes());
2997  const G4Colour& color = visAttr->GetColour();
2998 
2999  // look in all children in order to get if their is already a
3000  // child corresponding:
3001  // - if so, go into this child
3002  // - if not : create it as invisible
3003 
3004  // Realy quick check if the POindex is already there
3005  QTreeWidgetItem* subItem = NULL;
3006  QList<QTreeWidgetItem *> parentItemList;
3007 
3008 
3009  // first of all, very quick check if it was not the same as last one
3010 
3011  // Check only if it is a transparent object
3012  // If it is the last item and it is not transparent -> nothing to look for,
3013  // simply add it.
3014  if ((currentIndexInTreeSceneHandler == (fullPath.size()-1)) && ((color.GetAlpha() == 1.))) {
3015  } else {
3016  QString lookForString = QString(currentPVName.c_str());
3017  for (int i = 0;i < parentItem->childCount(); i++ ) {
3018  if (parentItem->child(i)->text(0) == lookForString) {
3019  parentItemList.push_back(parentItem->child(i));
3020  }
3021  }
3022  }
3023 
3024  for (int i = 0; i < parentItemList.size(); ++i) {
3025  const std::string& parentItemName = parentItemList.at(i)->text(0).toStdString();
3026  int parentItemCopyNb = parentItemList.at(i)->data(1,Qt::UserRole).toInt();
3027  int parentItemPOIndex = parentItemList.at(i)->data(0,Qt::UserRole).toInt();
3028 
3029  // if already inside
3030  // -> return true
3031  // special case, do not have to deal with hierarchy except for PhysicalVolume
3032 
3033 
3034  /* Physical Volume AND copy number equal AND name equal */
3035  if (((parentRoot == fTouchableVolumes) && (currentPVCopyNb == parentItemCopyNb)
3036  && (currentPVName == parentItemName)) ||
3037  /* NOT a Physical Volume AND copy number equal */
3038  ((parentRoot != fTouchableVolumes) && (currentPVCopyNb == parentItemCopyNb)
3039  /*AND name equal AND PO index equal*/
3040  && (currentPVName == parentItemName) && (currentPVPOIndex == parentItemPOIndex) )) {
3041 
3042  // then check for the Transform3D
3043  bool sameTransform = true;
3044  if (parentItemPOIndex >= 0) {
3045  const PVPath& fullPathTmp = fTreeItemModels[parentItemPOIndex];
3046  if (fullPathTmp.size() > 0) {
3047  if (fullPathTmp.at(fullPathTmp.size()-1).GetTransform () == pPVModel->GetTransformation ()) {
3048  sameTransform = true;
3049  } else {
3050  sameTransform = false;
3051  }
3052  }
3053  }
3054 
3055  // Same transformation, then try to change the PO index
3056  if (sameTransform == true) {
3057  // already exist in the tree, is it a transparent object ?
3058  // If so, then have to change the PO index ONLY if it is the last
3059  // and then change the state ONLY if POIndex has change
3060  // If not, then go deaper
3061 
3062  // last element
3063  if (currentIndexInTreeSceneHandler == (fullPath.size()-1)) {
3064 
3065  parentItemList.at(i)->setText(2,QString::number(currentPVPOIndex));
3066  parentItemList.at(i)->setData(0, Qt::UserRole,currentPVPOIndex);
3067 
3068  fTreeItemModels.insert(std::pair <int, PVPath >(currentPVPOIndex,fullPath) );
3069 
3070  // Then remove tooltip and special font
3071  QFont f = QFont();
3072  parentItemList.at(i)->setFont (0,f);
3073 
3074  // set foreground
3075  parentItemList.at(i)->setForeground (0,QBrush());
3076 
3077  // Set a tootip
3078  parentItemList.at(i)->setToolTip (0,"");
3079 
3080  changeQColorForTreeWidgetItem(parentItemList.at(i),QColor((int)(color.GetRed()*255),
3081  (int)(color.GetGreen()*255),
3082  (int)(color.GetBlue()*255),
3083  (int)(color.GetAlpha()*255)));
3084 
3085  // set check only if there is something to display
3086  if (color.GetAlpha() > 0) {
3087  parentItemList.at(i)->setCheckState(0,Qt::Checked);
3088  updatePositivePoIndexSceneTreeWidgetQuickMap(currentPVPOIndex,parentItemList.at(i));
3089  }
3090  return false;
3091  } else {
3092  subItem = parentItemList.at(i);
3093  }
3094 
3095  // Exists but not the end of path, then forget get it
3096  } else if (currentIndexInTreeSceneHandler < (fullPath.size()-1)) {
3097  subItem = parentItemList.at(i);
3098  }
3099  }
3100 
3101  } // end for
3102 
3103  // if it the last, then add it and set it checked
3104  if (currentIndexInTreeSceneHandler == (fullPath.size()-1)) {
3105  /* subItem =*/ createTreeWidgetItem(fullPath,
3106  QString(currentPVName.c_str()),
3107  currentPVCopyNb,
3108  currentPVPOIndex,
3109  QString(fullPath.at(fullPathIndex).GetPhysicalVolume()->GetLogicalVolume()->GetName().data()),
3110  Qt::Checked,
3111  parentItem,
3112  color);
3113 
3114  if (currentPVPOIndex > fMaxPOindexInserted) {
3115  fMaxPOindexInserted = currentPVPOIndex;
3116  }
3117 
3118  } else {
3119 
3120  // if no child found, then this child is create and marked as invisible, then go inside
3121  if (subItem == NULL) {
3122 
3123  if (currentIndexInTreeSceneHandler < (fullPath.size()-1)) {
3124  subItem = createTreeWidgetItem(fullPath,
3125  QString(currentPVName.c_str()),
3126  currentPVCopyNb,
3127  -1,
3128  QString(fullPath.at(fullPathIndex).GetPhysicalVolume()->GetLogicalVolume()->GetName().data()),
3129  Qt::Unchecked,
3130  parentItem,
3131  color);
3132  }
3133  }
3134 
3135  return parseAndInsertInSceneTree(subItem,pPVModel,fullPathIndex+1,parentRoot,currentIndexInTreeSceneHandler+1,currentPVPOIndex);
3136  }
3137  return true;
3138 }
3139 
3140 
3141 void G4OpenGLQtViewer::changeOpenCloseVisibleHiddenSelectedColorSceneTreeElement(
3142  QTreeWidgetItem* subItem
3143 )
3144 {
3145  // Check if object with the same POIndex is the same in old tree
3146  QTreeWidgetItem* oldItem = NULL;
3147 
3148  QTreeWidgetItem* foundItem = getOldTreeWidgetItem(subItem->data(0,Qt::UserRole).toInt());
3149 
3150  if (foundItem != NULL) {
3151  if (isSameSceneTreeElement(foundItem,subItem)) {
3152  oldItem = foundItem;
3153  }
3154  }
3155  if (foundItem == NULL) { // PO should have change, parse all
3156 
3157  // POindex > 0
3158  std::map <int, QTreeWidgetItem*>::const_iterator i;
3159  i = fOldPositivePoIndexSceneTreeWidgetQuickMap.begin();
3160  while (i != fOldPositivePoIndexSceneTreeWidgetQuickMap.end()) {
3161  if (isSameSceneTreeElement(i->second,subItem)) {
3162  oldItem = i->second;
3163  i = fOldPositivePoIndexSceneTreeWidgetQuickMap.end();
3164  } else {
3165  i++;
3166  }
3167  }
3168  // POindex == 0 ?
3169  if (oldItem == NULL) {
3170  unsigned int a = 0;
3171  while (a < fOldNullPoIndexSceneTreeWidgetQuickVector.size()) {
3172  if (isSameSceneTreeElement(fOldNullPoIndexSceneTreeWidgetQuickVector[a],subItem)) {
3173  oldItem = fOldNullPoIndexSceneTreeWidgetQuickVector[a];
3174  a = fOldNullPoIndexSceneTreeWidgetQuickVector.size();
3175  } else {
3176  a++;
3177  }
3178  }
3179  }
3180  }
3181 
3182  // if found : retore old state
3183  if (oldItem != NULL) {
3184  subItem->setFlags(oldItem->flags()); // flags
3185  subItem->setCheckState(0,oldItem->checkState(0)); // check state
3186  subItem->setSelected(oldItem->isSelected()); // selected
3187  subItem->setExpanded(oldItem->isExpanded ()); // expand
3188 
3189  // change color
3190  // when we call this function, the color in the item is the one of vis Attr
3191 
3192  std::map <int, QTreeWidgetItem* >::iterator it;
3193 
3194  // getOldPO
3195  int oldPOIndex = oldItem->data(0,Qt::UserRole).toInt();
3196  it = fOldPositivePoIndexSceneTreeWidgetQuickMap.find(oldPOIndex);
3197  QColor color;
3198 
3199  // get old Vis Attr Color
3200  std::map <int, QColor >::iterator itVis;
3201  itVis = fOldVisAttrColorMap.find(oldPOIndex);
3202 
3203  QColor oldVisAttrColor;
3204  const QColor& newVisAttrColor = subItem->data(2,Qt::UserRole).value<QColor>();
3205 
3206  bool visAttrChange = false;
3207  // if old vis attr color found
3208  if (itVis != fOldVisAttrColorMap.end()) {
3209  oldVisAttrColor = itVis->second;
3210  if (oldVisAttrColor != newVisAttrColor) {
3211  visAttrChange = true;
3212  }
3213  } else {
3214  visAttrChange = true;
3215  }
3216 
3217  if (visAttrChange) {
3218  fOldVisAttrColorMap.insert(std::pair <int, QColor > (subItem->data(0,Qt::UserRole).toInt(),newVisAttrColor) );
3219 
3220  } else { // if no changes, get old PO value
3221  // if old PO found
3222  if (it != fOldPositivePoIndexSceneTreeWidgetQuickMap.end()) {
3223  color = (it->second)->data(2,Qt::UserRole).value<QColor>();
3224  } else {
3225  color = oldItem->data(2,Qt::UserRole).value<QColor>();
3226  }
3227  changeQColorForTreeWidgetItem(subItem,color);
3228  }
3229  }
3230 
3231  return;
3232 }
3233 
3234 
3235 
3236 // Check if both items are identical.
3237 // For that, check name, copy number, transformation
3238 // special case for "non Touchables", do not check the PO index, check only the name
3239 bool G4OpenGLQtViewer::isSameSceneTreeElement(
3240  QTreeWidgetItem* parentOldItem
3241  ,QTreeWidgetItem* parentNewItem
3242 ) {
3243 
3244  int newPO = -1;
3245  int oldPO = -1;
3246 
3247  int newCpNumber = -1;
3248  int oldCpNumber = -1;
3249 
3250  bool firstWhile = true;
3251 
3252  while ((parentOldItem != NULL) && (parentNewItem != NULL)) {
3253 
3254  // check transform, optimize getting data(..,..) that consume lot of time
3255  if (!firstWhile) {
3256  oldPO = parentOldItem->data(0,Qt::UserRole).toInt();
3257  newPO = parentNewItem->data(0,Qt::UserRole).toInt();
3258  }
3259  firstWhile = false;
3260 
3261  if ((oldPO >= 0) &&
3262  (newPO >= 0)) {
3263  const PVPath& oldFullPath = fOldTreeItemModels[oldPO];
3264  const PVPath& newFullPath = fTreeItemModels[newPO];
3265  if ((oldFullPath.size() > 0) &&
3266  (newFullPath.size() > 0)) {
3267  if (oldFullPath.size() != newFullPath.size()) {
3268  return false;
3269  }
3270  if (oldFullPath.at(oldFullPath.size()-1).GetTransform () == newFullPath.at(newFullPath.size()-1).GetTransform ()) {
3271  newCpNumber = newFullPath.at(newFullPath.size()-1).GetCopyNo();
3272  oldCpNumber = oldFullPath.at(oldFullPath.size()-1).GetCopyNo();
3273  // ok
3274  } else {
3275  return false;
3276  }
3277  }
3278  }
3279 
3280  // Check copy Number
3281  if (oldCpNumber == -1) {
3282  oldCpNumber = parentOldItem->data(1,Qt::UserRole).toInt();
3283  }
3284  if (newCpNumber == -1) {
3285  newCpNumber = parentNewItem->data(1,Qt::UserRole).toInt();
3286  }
3287  if ((oldCpNumber != newCpNumber) ||
3288  // Check name
3289  (parentOldItem->text(0) != parentNewItem->text(0)) ) {
3290  // try to optimize
3291  return false;
3292  } else if ((parentOldItem->text(0) != parentNewItem->text(0)) || // Logical Name
3293  (parentOldItem->text(3) != parentNewItem->text(3))) { // Check logical name
3294  return false;
3295  } else {
3296  parentOldItem = parentOldItem->parent();
3297  parentNewItem = parentNewItem->parent();
3298  }
3299  } // end while
3300 
3301  return true;
3302 }
3303 
3304 
3305 void G4OpenGLQtViewer::addNonPVSceneTreeElement(
3306  const G4String& model
3307  ,int currentPOIndex
3308  ,const std::string& modelDescription
3309  ,const G4Visible& visible
3310 ) {
3311 
3312  QString modelShortName = getModelShortName(model);
3313  G4Colour color;
3314 
3315  // Special case for text
3316  try {
3317  const G4Text& g4Text = dynamic_cast<const G4Text&>(visible);
3318  color = fSceneHandler.GetTextColour(g4Text);
3319  }
3320  catch (std::bad_cast) {
3321  color = fSceneHandler.GetColour(visible);
3322  }
3323  if (modelShortName == "") {
3324  return ;
3325  }
3326  // try to init it
3327  if (fSceneTreeComponentTreeWidget == NULL) {
3328  createSceneTreeComponent();
3329  }
3330 
3331  // if no UI
3332  if (fSceneTreeComponentTreeWidget == NULL) {
3333  return;
3334  }
3335 
3336  fSceneTreeComponentTreeWidget->blockSignals(true);
3337 
3338  // Create the "Model" node if not
3339 
3340  QList<QTreeWidgetItem *> resItem;
3341  resItem = fSceneTreeComponentTreeWidget->findItems (modelShortName, Qt::MatchExactly, 0 );
3342  QTreeWidgetItem * currentItem = NULL;
3343  const PVPath tmpFullPath;
3344 
3345  if (resItem.empty()) {
3346  currentItem = createTreeWidgetItem(tmpFullPath,
3347  modelShortName,
3348  0, // currentPVCopyNb
3349  -1, // currentPVPOIndex
3350  "",
3351  Qt::Checked,
3352  NULL,
3353  color);
3354  } else {
3355  currentItem = resItem.first();
3356  }
3357 
3358  // Is this volume already in the tree AND PO is not the same?
3359  const QList<QTreeWidgetItem *>&
3360  resItems = fSceneTreeComponentTreeWidget->findItems (QString(modelDescription.c_str()), Qt::MatchFixedString| Qt::MatchCaseSensitive|Qt::MatchRecursive, 0 );
3361 
3362  bool alreadyPresent = false;
3363  for (int i = 0; i < resItems.size(); ++i) {
3364  if (currentPOIndex == resItems.at(i)->data(0,Qt::UserRole).toInt()) {
3365  alreadyPresent = true;
3366  }
3367  }
3368  if (!alreadyPresent) {
3369  createTreeWidgetItem(tmpFullPath,
3370  QString(modelDescription.c_str()),
3371  0, // currentPVCopyNb
3372  currentPOIndex,
3373  "",
3374  Qt::Checked,
3375  currentItem,
3376  color);
3377  }
3378  fSceneTreeComponentTreeWidget->blockSignals(false);
3379 
3380 }
3381 
3382 
3386 QString G4OpenGLQtViewer::getModelShortName(const G4String& model) {
3387 
3388  QString modelShortName = model.data();
3389  if (modelShortName.mid(0,modelShortName.indexOf(" ")) == "G4PhysicalVolumeModel") {
3390  modelShortName = fTouchableVolumes;
3391  } else {
3392  if (modelShortName.mid(0,2) == "G4") {
3393  modelShortName = modelShortName.mid(2);
3394  }
3395  if (modelShortName.indexOf("Model") != -1) {
3396  modelShortName = modelShortName.mid(0,modelShortName.indexOf("Model"));
3397  }
3398  }
3399  return modelShortName;
3400 }
3401 
3402 
3403 
3404 bool G4OpenGLQtViewer::isTouchableVisible(int POindex){
3405 
3406  // If no scene tree (Immediate viewer)
3407  if (fSceneTreeComponentTreeWidget == NULL) {
3408  return false;
3409  }
3410 
3411  // should be the next one
3412  // Prevent to get out the std::map
3413  if (fLastSceneTreeWidgetAskForIterator != fLastSceneTreeWidgetAskForIteratorEnd) {
3414  fLastSceneTreeWidgetAskForIterator++;
3415  }
3416  QTreeWidgetItem* item = getTreeWidgetItem(POindex);
3417 
3418  if (item != NULL) {
3419  if ( item->checkState(0) == Qt::Checked) {
3420  return true;
3421  }
3422  }
3423  return false;
3424 }
3425 
3426 
3427 bool G4OpenGLQtViewer::parseAndCheckVisibility(QTreeWidgetItem * treeNode,int POindex){
3428  bool isFound = false;
3429  for (int i = 0; i < treeNode->childCount() ; ++i) {
3430 
3431  if (treeNode->child(i)->data(0,Qt::UserRole).toInt() == POindex) {
3432  if (treeNode->child(i)->checkState(0) == Qt::Checked) {
3433  return true;
3434  }
3435  }
3436  isFound = parseAndCheckVisibility(treeNode->child(i),POindex);
3437  if (isFound) {
3438  return true;
3439  }
3440  } // end for
3441  return false;
3442 }
3443 
3444 
3445 std::string G4OpenGLQtViewer::parseSceneTreeAndSaveState(){
3446  std::string commandLine = "";
3447  for (int b=0;b<fSceneTreeComponentTreeWidget->topLevelItemCount();b++) {
3448  commandLine += parseSceneTreeElementAndSaveState(fSceneTreeComponentTreeWidget->topLevelItem(b),1)+"\n";
3449  }
3450  if (commandLine != "") {
3451  commandLine = std::string("# Disable auto refresh and quieten vis messages whilst scene and\n") +
3452  "# trajectories are established:\n" +
3453  "/vis/viewer/set/autoRefresh false\n" +
3454  "/vis/verbose errors" +
3455  commandLine +
3456  "# Re-establish auto refreshing and verbosity:\n" +
3457  "/vis/viewer/set/autoRefresh true\n" +
3458  "/vis/verbose confirmations\n";
3459  }
3460  return commandLine;
3461 }
3462 
3463 
3464 std::string G4OpenGLQtViewer::parseSceneTreeElementAndSaveState(QTreeWidgetItem* item, unsigned int level){
3465  // parse current item
3466  std::string str( level, ' ' );
3467  std::string commandLine = "\n#"+ str + "PV Name: " + item->text(0).toStdString();
3468 
3469  if (item->text(3) != "") {
3470  commandLine += " LV Name: "+item->text(3).toStdString()+"\n";
3471  // save check state
3472  commandLine += "/vis/geometry/set/visibility " + item->text(3).toStdString() + " ! "; // let default value for depth
3473  if (item->checkState(0) == Qt::Checked) {
3474  commandLine += "1";
3475  }
3476  if (item->checkState(0) == Qt::Unchecked) {
3477  commandLine += "0";
3478  }
3479  commandLine +="\n";
3480 
3481  // save color
3482  const QColor& c = item->data(2,Qt::UserRole).value<QColor>();
3483  std::stringstream red;
3484  red << ((double)c.red())/255;
3485  std::stringstream green;
3486  green << (double)c.green()/255;
3487  std::stringstream blue;
3488  blue << ((double)c.blue())/255;
3489  std::stringstream alpha;
3490  alpha << ((double)c.alpha())/255;
3491 
3492  commandLine += "/vis/geometry/set/colour " + item->text(3).toStdString() + " ! " + red.str() + " " + green.str() + " " + blue.str() + " " + alpha.str()+"\n";
3493 
3494  } else {
3495  commandLine += "\n";
3496  }
3497 
3498  // parse childs
3499  for (int b=0;b< item->childCount();b++) {
3500  commandLine += parseSceneTreeElementAndSaveState(item->child(b),level+1);
3501  }
3502 
3503  return commandLine;
3504 }
3505 
3506 
3507 void G4OpenGLQtViewer::sceneTreeComponentItemChanged(QTreeWidgetItem* item, int) {
3508 
3509  if (fCheckSceneTreeComponentSignalLock == false) {
3510  fCheckSceneTreeComponentSignalLock = true;
3511  G4bool checked = false;
3512  if (item->checkState(0) == Qt::Checked) {
3513  checked = true;
3514  }
3515  setCheckComponent(item,checked);
3516  updateQWidget();
3517 
3518  fCheckSceneTreeComponentSignalLock = false;
3519  }
3520 }
3521 
3522 
3523 void G4OpenGLQtViewer::sceneTreeComponentSelected() {
3524  /*
3525  if (fSceneTreeComponentTreeWidget) {
3526  if (! fSceneTreeComponentTreeWidget->selectedItems().isEmpty ()) {
3527  QTreeWidgetItem* item = fSceneTreeComponentTreeWidget->selectedItems ().first();
3528  if (item) {
3529 
3530  const PVPath& fullPath = fTreeItemModels[item->data(0,Qt::UserRole).toInt()];
3531  if (fullPath.size() > 0) {
3532  const G4VisAttributes* visAttr2 = GetApplicableVisAttributes(fullPath.at(fullPath.size()-1).GetPhysicalVolume()->GetLogicalVolume()->GetVisAttributes());
3533  }
3534  }
3535  }
3536  }
3537  */
3538 }
3539 
3540 
3541 void G4OpenGLQtViewer::changeDepthInSceneTree (int val){
3542 
3543  // If no scene tree (Immediate viewer)
3544  if (fSceneTreeComponentTreeWidget == NULL) {
3545  return;
3546  }
3547 
3548  // max depth : fSceneTreeDepth
3549  // val is between 0 and 1
3550  // 0 .1 .2 .3 .4 .5 .6 .7 .8 .9 1
3551  // 1 1.4 2
3552  // 1 2 3 4
3553 
3554  // Get the depth :
3555  double depth = 1 + ((double)val)/1000 * ((double)fSceneTreeDepth+1);
3556 
3557  // lock update on scene tree items
3558  fCheckSceneTreeComponentSignalLock = true;
3559 
3560  // Disable redraw each time !
3561  G4bool currentAutoRefresh = fVP.IsAutoRefresh();
3562  fVP.SetAutoRefresh(false);
3563 
3564  for (int b=0;b<fSceneTreeComponentTreeWidget->topLevelItemCount();b++) {
3565  changeDepthOnSceneTreeItem(depth,1.,fSceneTreeComponentTreeWidget->topLevelItem(b));
3566  }
3567 
3568  // Enable redraw !
3569  fVP.SetAutoRefresh(currentAutoRefresh);
3570  updateQWidget();
3571 
3572  // unlock update on scene tree items
3573  fCheckSceneTreeComponentSignalLock = false;
3574 
3575 }
3576 
3577 
3578 void G4OpenGLQtViewer::changeColorAndTransparency(QTreeWidgetItem* item,int) {
3579 
3580  if (item == NULL) {
3581  return;
3582  }
3583  const QColor& old = QColor(item->data(2,Qt::UserRole).value<QColor>());
3584 
3585 #if QT_VERSION < 0x040500
3586  bool a;
3587  const QColor& color = QColor(QColorDialog::getRgba (old.rgba(),&a,fSceneTreeComponentTreeWidget));
3588 #else
3589  const QColor& color = QColorDialog::getColor(old,
3590  fSceneTreeComponentTreeWidget,
3591  " Get color and transparency",
3592  QColorDialog::ShowAlphaChannel);
3593 #endif
3594 
3595  if (color.isValid()) {
3596 
3597  changeColorAndTransparency(item->data(0,Qt::UserRole).toInt(),
3598  G4Colour (((G4double)color.red())/255,
3599  ((G4double)color.green())/255,
3600  ((G4double)color.blue())/255,
3601  ((G4double)color.alpha())/255));
3602 
3603  // set scene tree parameters
3604  changeQColorForTreeWidgetItem(item,color);
3605  }
3606 }
3607 
3608 
3609 void G4OpenGLQtViewer::changeColorAndTransparency(GLuint index, G4Color color) {
3610 
3611  // change vis attributes to set new colour
3612  G4int iPO = index;
3613  if (iPO >= 0 && fTreeItemModels.find(iPO) != fTreeItemModels.end()) {
3614  const PVPath& fullPath = fTreeItemModels[iPO];
3615  // If a physical volume
3616  if (fullPath.size()) {
3617 
3618  // Instantiate a working copy of a G4VisAttributes object...
3619  G4VisAttributes workingVisAtts;
3620  // and set the colour.
3621  workingVisAtts.SetColour(color);
3622 
3623  // Add a vis atts modifier to the view parameters...
3624  fVP.AddVisAttributesModifier
3626  (workingVisAtts,
3628  fullPath));
3629  // G4ModelingParameters::VASColour tells G4PhysicalVolumeModel that it is
3630  // the colour that should be picked out and merged with the touchable's
3631  // normal vis attributes.
3632  }
3633  }
3634 }
3635 
3636 
3637 G4Colour G4OpenGLQtViewer::getColorForPoIndex(int poIndex) {
3638  // FIXME 09/2014 : Could be optimize by searching in a tab instead of item->data
3639  QTreeWidgetItem* item = getTreeWidgetItem(poIndex);
3640 
3641  if (item != NULL) {
3642 
3643  const QColor& color = item->data(2,Qt::UserRole).value<QColor>();
3644  G4Colour g4c(((G4double)color.red())/255,
3645  ((G4double)color.green())/255,
3646  ((G4double)color.blue())/255,
3647  ((G4double)color.alpha())/255);
3648 
3649  return g4c;
3650  }
3651  return G4Colour();
3652 }
3653 
3654 
3655 const std::vector<G4ModelingParameters::VisAttributesModifier>*
3656 G4OpenGLQtViewer::GetPrivateVisAttributesModifiers() const
3657 {
3658  static std::vector<G4ModelingParameters::VisAttributesModifier>
3659  privateVisAttributesModifiers;
3660 
3661  privateVisAttributesModifiers.clear();
3662 
3663 // // For each modified touchable...
3664 // std::map<int,PVPath>::const_iterator i;
3665 // for (i = fTreeItemModels.begin();
3666 // i != fTreeItemModels.end();
3667 // ++i) {
3668 //
3669 // // How do I know if it's been modified or not?
3670 //
3671 // int iPO = i->first;
3672 // const PVPath& fullPath = i->second;
3673 //
3674 // // If a physical volume
3675 // if (fullPath.size()) {
3676 //
3677 // // const G4bool& visibilityChanged = ???
3678 // // const G4bool& visibility = ???
3679 // // const G4bool& colourChanged = ???
3680 // // const QColor& colour = ???
3681 // // G4Colour g4colour(((G4double)colour.red())/255,
3682 // // ((G4double)colour.green())/255,
3683 // // ((G4double)colour.blue())/255,
3684 // // ((G4double)colour.alpha())/255);
3685 // // Next 4 lines are for testing, to be replaced by the above...
3686 // G4bool visibilityChanged = true;
3687 // G4bool visibility = true;
3688 // G4bool colourChanged = true;
3689 // G4Colour g4colour(G4Colour::Red());
3690 //
3691 // // Instantiate a working copy of a G4VisAttributes object...
3692 // G4VisAttributes workingVisAtts;
3693 // // ...and use it to create vis attribute modifiers...
3694 // if (visibilityChanged) {
3695 // workingVisAtts.SetVisibility(visibility);
3696 // privateVisAttributesModifiers.push_back
3697 // (G4ModelingParameters::VisAttributesModifier
3698 // (workingVisAtts,
3699 // G4ModelingParameters::VASVisibility,
3700 // fullPath));
3701 // }
3702 // if (colourChanged) {
3703 // workingVisAtts.SetColour(g4colour);
3704 // privateVisAttributesModifiers.push_back
3705 // (G4ModelingParameters::VisAttributesModifier
3706 // (workingVisAtts,
3707 // G4ModelingParameters::VASColour,
3708 // fullPath));
3709 // }
3710 // }
3711 // }
3712 
3713  return &privateVisAttributesModifiers;
3714 }
3715 
3716 
3717 void G4OpenGLQtViewer::changeSearchSelection()
3718 {
3719  const QString& searchText = fFilterOutput->text();
3720  if (fSceneTreeComponentTreeWidget == NULL) {
3721  return;
3722  }
3723 
3724  // unselect all
3725  for (int a=0; a<fSceneTreeComponentTreeWidget->topLevelItemCount(); a++) {
3726  fSceneTreeComponentTreeWidget->topLevelItem(a)->setExpanded(false);
3727  fSceneTreeComponentTreeWidget->topLevelItem(a)->setSelected(false);
3728  clearSceneTreeSelection(fSceneTreeComponentTreeWidget->topLevelItem(a));
3729  }
3730 
3731  QList<QTreeWidgetItem *> itemList = fSceneTreeComponentTreeWidget->findItems (searchText,Qt::MatchContains | Qt::MatchRecursive,0);
3732 
3733  for (int i = 0; i < itemList.size(); ++i) {
3734  QTreeWidgetItem* expandParentItem = itemList.at(i);
3735  while (expandParentItem->parent() != NULL) {
3736  expandParentItem->parent()->setExpanded(true);
3737  expandParentItem = expandParentItem->parent();
3738  }
3739  itemList.at(i)->setSelected(true);
3740  }
3741 
3742 }
3743 
3744 
3745 void G4OpenGLQtViewer::clearSceneTreeSelection(QTreeWidgetItem* item) {
3746  for (int a=0; a<item->childCount(); a++) {
3747  item->child(a)->setSelected(false);
3748  item->child(a)->setExpanded(false);
3749  clearSceneTreeSelection(item->child(a));
3750  }
3751 
3752 }
3753 
3754 
3755 bool G4OpenGLQtViewer::isPVVolume(QTreeWidgetItem* item) {
3756  QTreeWidgetItem* sParent = item;
3757  while (sParent->parent() != NULL) {
3758  sParent = sParent->parent();
3759  }
3760  if (sParent->text(0) != fTouchableVolumes) {
3761  return false;
3762  }
3763  // item is the "Touchable" node
3764  if (item->text(0) == fTouchableVolumes) {
3765  return false;
3766  }
3767  return true;
3768 }
3769 
3770 
3771 void G4OpenGLQtViewer::changeDepthOnSceneTreeItem(
3772  double lookForDepth
3773  ,double currentDepth
3774  ,QTreeWidgetItem* item
3775 ) {
3776  double transparencyLevel = 0.;
3777 
3778  // look for a 2.2 depth and we are at level 3
3779  // -> Set all theses items to Opaque
3780  // ONLY if it is a PV volume !
3781  if (isPVVolume(item)) {
3782  if ((lookForDepth-currentDepth) < 0) {
3783  item->setCheckState(0,Qt::Checked);
3784  updatePositivePoIndexSceneTreeWidgetQuickMap(item->data(0,Qt::UserRole).toInt(),item);
3785  transparencyLevel = 1;
3786  } else if ((lookForDepth-currentDepth) > 1 ){
3787  item->setCheckState(0,Qt::Unchecked);
3788  updatePositivePoIndexSceneTreeWidgetQuickMap(item->data(0,Qt::UserRole).toInt(),item);
3789  transparencyLevel = 0;
3790  } else {
3791  item->setCheckState(0,Qt::Checked);
3792  updatePositivePoIndexSceneTreeWidgetQuickMap(item->data(0,Qt::UserRole).toInt(),item);
3793  transparencyLevel = 1-(lookForDepth-currentDepth);
3794  }
3795  }
3796 
3797  if (item->data(0,Qt::UserRole).toInt() >= 0) {
3798  const G4Colour& color = getColorForPoIndex(item->data(0,Qt::UserRole).toInt());
3799 
3800  // We are less depper (ex:tree depth:2) than lookForDepth (ex:3.1)
3801  // -> Have to hide this level ONLY if it was not hidden before
3802 
3803  // Not on a top level item case
3804  // Do not set if it was already set
3805 
3806  // Should add them all the time in case of an older command has change transparency
3807  // before. Should be checked in changeDepthInSceneTree for duplicated commands
3808  // Do not change transparency if not visible by humain (and avoid precision value
3809  // problems..)
3810  if (((color.GetAlpha()-transparencyLevel) > 0.000001) ||
3811  ((color.GetAlpha()-transparencyLevel) < -0.000001)) {
3812  if ((item->text(3) != "")) {
3813  // FIXME : Should not test this here because of transparent
3814  // volume that will came after and with a different alpha level
3815  // Good thing to do is to check and suppress doubles in changeDepthInSceneTree
3816  // and then check if last (transparents volumes) has to change alpha
3817 
3818  changeQColorForTreeWidgetItem(item,QColor((int)(color.GetRed()*255),
3819  (int)(color.GetGreen()*255),
3820  (int)(color.GetBlue()*255),
3821  (int)(transparencyLevel*255)));
3822  }
3823  }
3824  }
3825 
3826  for (int b=0;b< item->childCount();b++) {
3827  changeDepthOnSceneTreeItem(lookForDepth,currentDepth+1,item->child(b));
3828  }
3829 }
3830 
3831 
3832 void G4OpenGLQtViewer::clearTreeWidget(){
3833  // be careful about calling this twice
3834 
3835  if (fSceneTreeComponentTreeWidget) {
3836 
3837  if (fOldSceneTreeComponentTreeWidget == NULL) {
3838  fOldSceneTreeComponentTreeWidget = new QTreeWidget();
3839  }
3840  // clear old scene tree
3841  int tmp = fOldSceneTreeComponentTreeWidget->topLevelItemCount();
3842  while (tmp > 0) {
3843  delete fOldSceneTreeComponentTreeWidget->takeTopLevelItem (0);
3844  tmp = fOldSceneTreeComponentTreeWidget->topLevelItemCount();
3845  }
3846 
3847  if (fSceneTreeComponentTreeWidget->topLevelItemCount () > 0) {
3848 
3849  fPVRootNodeCreate = false;
3850 
3851  // reset all old
3852  fOldPositivePoIndexSceneTreeWidgetQuickMap.clear();
3853  fOldNullPoIndexSceneTreeWidgetQuickVector.clear();
3854  fOldTreeItemModels.clear();
3855 
3856  // Clone everything
3857  for (int b =0; b <fSceneTreeComponentTreeWidget->topLevelItemCount();b++) {
3858  // All tree widgets are in :
3859  // then we could get the old POindex and get
3860  // .visible/Hidden
3861  // .Check/Uncheck
3862  // .selected
3863  // .colour status from std::map
3864 
3865  // clone top level items
3866  int poIndex = fSceneTreeComponentTreeWidget->topLevelItem(b)->data(0,Qt::UserRole).toInt();
3867  if (poIndex != -1) {
3868  fOldPositivePoIndexSceneTreeWidgetQuickMap.insert(std::pair <int, QTreeWidgetItem*> (poIndex,cloneWidgetItem(fSceneTreeComponentTreeWidget->topLevelItem(b))));
3869  } else {
3870  fOldNullPoIndexSceneTreeWidgetQuickVector.push_back(cloneWidgetItem(fSceneTreeComponentTreeWidget->topLevelItem(b)));
3871  }
3872 
3873  // clone leaves
3874  cloneSceneTree(fSceneTreeComponentTreeWidget->topLevelItem(b));
3875  }
3876  // delete all elements
3877 
3878  fOldTreeItemModels.insert(fTreeItemModels.begin(), fTreeItemModels.end());
3879 
3880  // all is copy, then clear scene tree
3881  int tmp2 = fSceneTreeComponentTreeWidget->topLevelItemCount();
3882  while (tmp2 > 0) {
3883  delete fSceneTreeComponentTreeWidget->takeTopLevelItem (0);
3884  tmp2 = fSceneTreeComponentTreeWidget->topLevelItemCount();
3885  }
3886  fPositivePoIndexSceneTreeWidgetQuickMap.clear();
3887 
3888  // put correct value in paramaters
3889  fOldLastSceneTreeWidgetAskForIterator = fOldPositivePoIndexSceneTreeWidgetQuickMap.begin();
3890  fOldLastSceneTreeWidgetAskForIteratorEnd = fOldPositivePoIndexSceneTreeWidgetQuickMap.end();
3891  fSceneTreeDepth = 1;
3892  fModelShortNameItem = NULL;
3893  fMaxPOindexInserted = -1;
3894 
3895  }
3896  }
3897 }
3898 
3899 
3906 QTreeWidgetItem * G4OpenGLQtViewer::cloneWidgetItem(QTreeWidgetItem* item) {
3907 
3908  QTreeWidgetItem* cloneItem = new QTreeWidgetItem();
3909 
3910  // Clone what is create createTreeWidgetItem step
3911 
3912  cloneItem->setText(0,item->text(0));
3913  cloneItem->setData(1,Qt::UserRole,item->data(1,Qt::UserRole).toInt());
3914  cloneItem->setText(2,item->text(2));
3915  cloneItem->setData(0, Qt::UserRole,item->data(0,Qt::UserRole).toInt());
3916  cloneItem->setText(3,item->text(3));
3917  cloneItem->setFlags(item->flags());
3918  cloneItem->setToolTip(0,item->toolTip(0));
3919  cloneItem->setCheckState(0,item->checkState(0));
3920  cloneItem->setSelected(item->isSelected());
3921  cloneItem->setExpanded(item->isExpanded ());
3922 
3923  cloneItem->setData(2,Qt::UserRole,item->data(2,Qt::UserRole).value<QColor>());
3924 
3925  return cloneItem;
3926 }
3927 
3928 
3932 void G4OpenGLQtViewer::cloneSceneTree(
3933  QTreeWidgetItem* rootItem
3934 ) {
3935 
3936  for (int b=0;b< rootItem->childCount();b++) {
3937 
3938  QTreeWidgetItem *child = rootItem->child(b);
3939 
3940  // clone top level items
3941  int poIndex = child->data(0,Qt::UserRole).toInt();
3942  if (poIndex != -1) {
3943  fOldPositivePoIndexSceneTreeWidgetQuickMap.insert(std::pair <int, QTreeWidgetItem*> (poIndex,cloneWidgetItem(child)));
3944  } else {
3945  fOldNullPoIndexSceneTreeWidgetQuickVector.push_back(cloneWidgetItem(child));
3946  }
3947  cloneSceneTree(child);
3948  }
3949 }
3950 
3951 
3955  void G4OpenGLQtViewer::updatePositivePoIndexSceneTreeWidgetQuickMap(int POindex,QTreeWidgetItem* item) {
3956 
3957  // Check state
3958  std::map <int, QTreeWidgetItem*>::iterator i;
3959  i = fPositivePoIndexSceneTreeWidgetQuickMap.find(POindex);
3960 
3961  if (i == fPositivePoIndexSceneTreeWidgetQuickMap.end()) {
3962  fPositivePoIndexSceneTreeWidgetQuickMap.insert(std::pair <int, QTreeWidgetItem*> (POindex,item) );
3963  fLastSceneTreeWidgetAskForIterator = fPositivePoIndexSceneTreeWidgetQuickMap.end();
3964  fLastSceneTreeWidgetAskForIteratorEnd = fPositivePoIndexSceneTreeWidgetQuickMap.end();
3965  } else {
3966  i->second = item;
3967  }
3968  }
3969 
3970 
3971 
3972 void G4OpenGLQtViewer::changeQColorForTreeWidgetItem(QTreeWidgetItem* item,const QColor& qc) {
3973 
3974  int POIndex = item->data(0,Qt::UserRole).toInt();
3975  updatePositivePoIndexSceneTreeWidgetQuickMap(POIndex,item );
3976 
3977  QPixmap pixmap = QPixmap(QSize(16, 16));
3978  if (item->data(0,Qt::UserRole).toInt() != -1) {
3979  pixmap.fill (qc);
3980  } else {
3981  pixmap.fill (QColor(255,255,255,255));
3982  }
3983  QPainter painter(&pixmap);
3984  painter.setPen(Qt::black);
3985  painter.drawRect(0,0,15,15); // Draw contour
3986 
3987  item->setIcon(0,pixmap);
3988  item->setData(2,Qt::UserRole,qc);
3989 }
3990 
3991 
3992 
3997 QTreeWidgetItem* G4OpenGLQtViewer::getTreeWidgetItem(int POindex){
3998 
3999  // -1 is not a visible item
4000  if (POindex == -1) {
4001  return NULL;
4002  }
4003 
4004  if (fPositivePoIndexSceneTreeWidgetQuickMap.size() == 0){
4005  return NULL;
4006  }
4007 
4008  if (fLastSceneTreeWidgetAskForIterator != fLastSceneTreeWidgetAskForIteratorEnd) {
4009  if (POindex == fLastSceneTreeWidgetAskForIterator->first) {
4010  if (fLastSceneTreeWidgetAskForIterator->second != NULL) {
4011  return fLastSceneTreeWidgetAskForIterator->second;
4012  }
4013  }
4014  }
4015 
4016  // if not, use the "find" algorithm
4017  fLastSceneTreeWidgetAskForIterator = fPositivePoIndexSceneTreeWidgetQuickMap.find(POindex);
4018  fLastSceneTreeWidgetAskForIteratorEnd = fPositivePoIndexSceneTreeWidgetQuickMap.end();
4019 
4020  if (fLastSceneTreeWidgetAskForIterator != fPositivePoIndexSceneTreeWidgetQuickMap.end()) {
4021  return fLastSceneTreeWidgetAskForIterator->second;
4022  }
4023  return NULL;
4024 }
4025 
4030 QTreeWidgetItem* G4OpenGLQtViewer::getOldTreeWidgetItem(int POindex){
4031 
4032 
4033  // -1 is not a visible item
4034  if (POindex == -1) {
4035  return NULL;
4036  }
4037 
4038  if (fOldPositivePoIndexSceneTreeWidgetQuickMap.size() == 0){
4039  return NULL;
4040  }
4041 
4042  // Should be call only once by item addition
4043  // Prevent to get out the std::map
4044  if (fOldLastSceneTreeWidgetAskForIterator != fOldLastSceneTreeWidgetAskForIteratorEnd) {
4045  fOldLastSceneTreeWidgetAskForIterator++;
4046  }
4047 
4048  if (fOldLastSceneTreeWidgetAskForIterator != fOldPositivePoIndexSceneTreeWidgetQuickMap.end()) {
4049  if (POindex == fOldLastSceneTreeWidgetAskForIterator->first) {
4050  if (fOldLastSceneTreeWidgetAskForIterator->second != NULL) {
4051  return fOldLastSceneTreeWidgetAskForIterator->second;
4052  }
4053  }
4054  }
4055 
4056  // if not, use the "find" algorithm
4057  fOldLastSceneTreeWidgetAskForIterator = fOldPositivePoIndexSceneTreeWidgetQuickMap.find(POindex);
4058  fOldLastSceneTreeWidgetAskForIteratorEnd = fOldPositivePoIndexSceneTreeWidgetQuickMap.end();
4059 
4060  if (fOldLastSceneTreeWidgetAskForIterator != fOldPositivePoIndexSceneTreeWidgetQuickMap.end()) {
4061  return fOldLastSceneTreeWidgetAskForIterator->second;
4062  }
4063  return NULL;
4064 }
4065 
4066 
4067 
4072 void G4OpenGLQtViewer::displaySceneTreeComponent() {
4073  // no UI
4074  if (fUISceneTreeComponentsTBWidget == NULL) {
4075  return;
4076  }
4077  if (fSceneTreeComponentTreeWidget == NULL) {
4078  return;
4079  }
4080 
4081  // sort tree items
4082  fSceneTreeComponentTreeWidget->sortItems (0, Qt::AscendingOrder );
4083 
4084  return;
4085 }
4086 
4087 
4094 void G4OpenGLQtViewer::updateToolbarAndMouseContextMenu(){
4095  if (fBatchMode) {
4096  return;
4097  }
4098 
4100  d_style = fVP.GetDrawingStyle();
4101 
4102  // Surface style
4103  if (d_style == G4ViewParameters::wireframe) {
4104  if (fUiQt) fUiQt->SetIconWireframeSelected();
4105  if (fContextMenu) {
4106  fDrawingWireframe->setChecked(true);
4107  fDrawingLineRemoval->setChecked(false);
4108  fDrawingSurfaceRemoval->setChecked(false);
4109  fDrawingLineSurfaceRemoval->setChecked(false);
4110  }
4111  } else if (d_style == G4ViewParameters::hlr) {
4112  if (fUiQt) fUiQt->SetIconHLRSelected();
4113  if (fContextMenu) {
4114  fDrawingLineRemoval->setChecked(true);
4115  fDrawingWireframe->setChecked(false);
4116  fDrawingSurfaceRemoval->setChecked(false);
4117  fDrawingLineSurfaceRemoval->setChecked(false);
4118  }
4119  } else if (d_style == G4ViewParameters::hsr) {
4120  if (fUiQt) fUiQt->SetIconSolidSelected();
4121  if (fContextMenu) {
4122  fDrawingSurfaceRemoval->setChecked(true);
4123  fDrawingWireframe->setChecked(false);
4124  fDrawingLineRemoval->setChecked(false);
4125  fDrawingLineSurfaceRemoval->setChecked(false);
4126  }
4127  } else if (d_style == G4ViewParameters::hlhsr) {
4128  if (fUiQt) fUiQt->SetIconHLHSRSelected();
4129  if (fContextMenu) {
4130  fDrawingLineSurfaceRemoval->setChecked(true);
4131  fDrawingWireframe->setChecked(false);
4132  fDrawingLineRemoval->setChecked(false);
4133  fDrawingSurfaceRemoval->setChecked(false);
4134  fDrawingLineSurfaceRemoval->setChecked(false);
4135  }
4136  }
4137 
4138 
4139  // projection style
4140  G4double d_proj = fVP.GetFieldHalfAngle () ;
4141  if (d_proj == 0.) { // ortho
4142  if (fUiQt) fUiQt->SetIconOrthoSelected();
4143  if (fContextMenu) {
4144  fProjectionOrtho->setChecked(true);
4145  fProjectionPerspective->setChecked(false);
4146  }
4147  } else {
4148  if (fUiQt) fUiQt->SetIconPerspectiveSelected();
4149  if (fContextMenu) {
4150  fProjectionPerspective->setChecked(true);
4151  fProjectionOrtho->setChecked(false);
4152  }
4153  }
4154 
4155 
4156  // mouse style : They are controlled by UI !
4157  if (fUiQt && fContextMenu) {
4158  if (fUiQt->IsIconPickSelected()) {
4159  fMousePickAction->setChecked(true);
4160  fMouseZoomOutAction->setChecked(false);
4161  fMouseZoomInAction->setChecked(false);
4162  fMouseRotateAction->setChecked(false);
4163  fMouseMoveAction->setChecked(false);
4164  } else if (fUiQt->IsIconZoomOutSelected()) {
4165  fMouseZoomOutAction->setChecked(true);
4166  fMousePickAction->setChecked(false);
4167  fMouseZoomInAction->setChecked(false);
4168  fMouseRotateAction->setChecked(false);
4169  fMouseMoveAction->setChecked(false);
4170  } else if (fUiQt->IsIconZoomInSelected()) {
4171  fMouseZoomInAction->setChecked(true);
4172  fMousePickAction->setChecked(false);
4173  fMouseZoomOutAction->setChecked(false);
4174  fMouseRotateAction->setChecked(false);
4175  fMouseMoveAction->setChecked(false);
4176  } else if (fUiQt->IsIconRotateSelected()) {
4177  fMouseRotateAction->setChecked(true);
4178  fMousePickAction->setChecked(false);
4179  fMouseZoomOutAction->setChecked(false);
4180  fMouseZoomInAction->setChecked(false);
4181  fMouseMoveAction->setChecked(false);
4182  } else if (fUiQt->IsIconMoveSelected()) {
4183  fMouseMoveAction->setChecked(true);
4184  fMousePickAction->setChecked(false);
4185  fMouseZoomOutAction->setChecked(false);
4186  fMouseZoomInAction->setChecked(false);
4187  fMouseRotateAction->setChecked(false);
4188  }
4189  }
4190 }
4191 
4196 void G4OpenGLQtViewer::updateSceneTreeComponentTreeWidgetInfos() {
4197 
4198  if (!fSceneTreeComponentTreeWidgetInfos) {
4199  return;
4200  }
4201  int treeWidgetInfosIgnoredCommands = 0;
4203  G4UIcommandTree * commandTreeTop = UI->GetTree();
4204  G4UIcommandTree* path = commandTreeTop->FindCommandTree("/vis/viewer/set/");
4205 
4206  if (!path) {
4207  return;
4208  }
4209 
4210  // clear old table
4211  if ((path->GetCommandEntry()-fTreeWidgetInfosIgnoredCommands) != fSceneTreeComponentTreeWidgetInfos->rowCount()) {
4212  fSceneTreeComponentTreeWidgetInfos->clear();
4213  }
4214 
4215  fSceneTreeComponentTreeWidgetInfos->blockSignals(true);
4216  // TODO : Could be optimized by comparing current command to old commands. That should not change so much
4217 
4218  fSceneTreeComponentTreeWidgetInfos->setColumnCount (2);
4219  fSceneTreeComponentTreeWidgetInfos->setRowCount (path->GetCommandEntry()-fTreeWidgetInfosIgnoredCommands);
4220  fSceneTreeComponentTreeWidgetInfos->setHorizontalHeaderLabels(QStringList() << tr("Property")
4221  << tr("Value"));
4222  fSceneTreeComponentTreeWidgetInfos->verticalHeader()->setVisible(false);
4223  fSceneTreeComponentTreeWidgetInfos->setAlternatingRowColors (true);
4224 
4225  // For the moment, we do only command that have a "set" command in UI
4226 
4227  for (int a=0;a<path->GetCommandEntry();a++) {
4228  G4UIcommand* commandTmp = path->GetCommand(a+1);
4229 
4230  // get current parameters
4231  QString params = "";
4232 
4233  if(commandTmp->GetCommandName() == "autoRefresh") {
4234  if (fVP.IsAutoRefresh()) {
4235  params = "True";
4236  } else {
4237  params = "False";
4238  }
4239  } else if(commandTmp->GetCommandName() == "auxiliaryEdge") {
4240  if (fVP.IsAuxEdgeVisible()) {
4241  params = "True";
4242  } else {
4243  params = "False";
4244  }
4245  } else if(commandTmp->GetCommandName() == "background") {
4246  params = QString().number(fVP.GetBackgroundColour().GetRed()) + " "+
4247  QString().number(fVP.GetBackgroundColour().GetGreen()) + " "+
4248  QString().number(fVP.GetBackgroundColour().GetBlue()) + " "+
4249  QString().number(fVP.GetBackgroundColour().GetAlpha());
4250 
4251  } else if(commandTmp->GetCommandName() == "culling") {
4252  params = QString().number(fVP. IsCulling ());
4253  } else if(commandTmp->GetCommandName() == "cutawayMode") {
4254  if (fVP.GetCutawayMode() == G4ViewParameters::cutawayUnion) {
4255  params = "union";
4256  } else {
4257  params = "intersection";
4258  }
4259 
4260  } else if(commandTmp->GetCommandName() == "defaultColour") {
4261  params = QString().number(fVP.GetDefaultVisAttributes()->GetColor().GetRed()) + " "+
4262  QString().number(fVP.GetDefaultVisAttributes()->GetColor().GetGreen()) + " "+
4263  QString().number(fVP.GetDefaultVisAttributes()->GetColor().GetBlue()) + " "+
4264  QString().number(fVP.GetDefaultVisAttributes()->GetColor().GetAlpha());
4265 
4266  } else if(commandTmp->GetCommandName() == "defaultTextColour") {
4267  params = QString().number(fVP.GetDefaultTextVisAttributes()->GetColor().GetRed()) + " "+
4268  QString().number(fVP.GetDefaultTextVisAttributes()->GetColor().GetGreen()) + " "+
4269  QString().number(fVP.GetDefaultTextVisAttributes()->GetColor().GetBlue()) + " "+
4270  QString().number(fVP.GetDefaultTextVisAttributes()->GetColor().GetAlpha());
4271 
4272  } else if(commandTmp->GetCommandName() == "edge") {
4273  G4ViewParameters::DrawingStyle existingStyle = fVP.GetDrawingStyle();
4274  params = "False";
4275  if (existingStyle == G4ViewParameters::hsr) {
4276  params = "True";
4277  }
4278 
4279  } else if(commandTmp->GetCommandName() == "explodeFactor") {
4280  params = QString().number(fVP.GetExplodeFactor()) + " " + QString(G4String(G4BestUnit(fVP.GetExplodeFactor(),"Length")).data());
4281 
4282  } else if(commandTmp->GetCommandName() == "globalLineWidthScale") {
4283  params = QString().number(fVP.GetGlobalLineWidthScale());
4284 
4285  } else if(commandTmp->GetCommandName() == "globalMarkerScale") {
4286  params = QString().number(fVP.GetGlobalMarkerScale());
4287 
4288  } else if(commandTmp->GetCommandName() == "hiddenEdge") {
4289  G4ViewParameters::DrawingStyle style = fVP.GetDrawingStyle();
4290  if ((style == G4ViewParameters::hlr) ||
4291  (style == G4ViewParameters::hlhsr)) {
4292  params = "True";
4293  } else {
4294  params = "False";
4295  }
4296 
4297  } else if(commandTmp->GetCommandName() == "hiddenMarker") {
4298  if (fVP.IsMarkerNotHidden()) {
4299  params = "False";
4300  } else {
4301  params = "True";
4302  }
4303 
4304  } else if(commandTmp->GetCommandName() == "lightsMove") {
4305  if (fVP.GetLightsMoveWithCamera()) {
4306  params = "camera";
4307  } else {
4308  params = "object";
4309  }
4310  } else if(commandTmp->GetCommandName() == "lightsThetaPhi") {
4311  G4Vector3D direction = fVP.GetLightpointDirection();
4312  // degree
4313  params = QString().number(direction.theta()/CLHEP::degree)+ " "+ QString().number(direction.phi()/CLHEP::degree)+" deg";
4314  if (commandTmp->GetParameterEntries() == 3) {
4315  if (commandTmp->GetParameter(2)->GetDefaultValue() != "deg") {
4316  params = QString().number(direction.theta())+ " "+ QString().number(direction.phi())+" "+commandTmp->GetParameter(2)->GetDefaultValue().data();
4317  }
4318  }
4319  } else if(commandTmp->GetCommandName() == "lightsVector") {
4320  params = QString().number(fVP.GetLightpointDirection().x()) + " "+
4321  QString().number(fVP.GetLightpointDirection().y()) + " "+
4322  QString().number(fVP.GetLightpointDirection().z());
4323 
4324  } else if(commandTmp->GetCommandName() == "lineSegmentsPerCircle") {
4325  params = QString().number(fVP.GetNoOfSides());
4326 
4327  } else if(commandTmp->GetCommandName() == "picking") {
4328  if (fVP.IsPicking()) {
4329  params = "True";
4330  } else {
4331  params = "False";
4332  }
4333 
4334  } else if(commandTmp->GetCommandName() == "projection") {
4335  if (fVP.GetFieldHalfAngle() == 0.) {
4336  params = "orthogonal";
4337  } else {
4338  params = QString("perspective ") + QString().number(fVP.GetFieldHalfAngle()/CLHEP::degree) + " deg";
4339  }
4340 
4341  } else if(commandTmp->GetCommandName() == "rotationStyle") {
4342  if (fVP.GetRotationStyle() == G4ViewParameters::constrainUpDirection) {
4343  params = "constrainUpDirection";
4344  } else {
4345  params = "freeRotation";
4346  }
4347 
4348  } else if(commandTmp->GetCommandName() == "sectionPlane") {
4349  if (fVP.IsSection()) {
4350  params = QString("on ") +
4351  G4String(G4BestUnit(fVP.GetSectionPlane().point(),"Length")).data()+
4352  QString().number(fVP.GetSectionPlane().normal().x())
4353  + " " + QString().number(fVP.GetSectionPlane().normal().y())
4354  + " " + QString().number(fVP.GetSectionPlane().normal().z());
4355  } else {
4356  params = "off";
4357  }
4358 
4359  } else if(commandTmp->GetCommandName() == "style") {
4360  if (fVP.GetDrawingStyle() == G4ViewParameters::wireframe || fVP.GetDrawingStyle() == G4ViewParameters::hlr) {
4361  params = "wireframe";
4362  } else {
4363  params = "surface";
4364  }
4365 
4366 
4367  } else if(commandTmp->GetCommandName() == "targetPoint") {
4368  G4Point3D point = fVP.GetCurrentTargetPoint();
4369  if (fSceneHandler.GetScene()) {
4370  G4String b = G4BestUnit(fSceneHandler.GetScene()->GetStandardTargetPoint() + fVP.GetCurrentTargetPoint(),"Length");
4371  params = b.data();
4372  }
4373  } else if(commandTmp->GetCommandName() == "upThetaPhi") {
4374  G4Vector3D up = fVP.GetUpVector();
4375  // degree
4376  params = QString().number(up.theta()/CLHEP::degree)+ " "+ QString().number(up.phi()/CLHEP::degree)+" deg";
4377  if (commandTmp->GetParameterEntries() == 3) {
4378  if (commandTmp->GetParameter(2)->GetDefaultValue() != "deg") {
4379  params = QString().number(up.theta())+ " "+ QString().number(up.phi())+" "+commandTmp->GetParameter(2)->GetDefaultValue().data();
4380  }
4381  }
4382  } else if(commandTmp->GetCommandName() == "upVector") {
4383  G4Vector3D up = fVP.GetUpVector();
4384  params = QString().number(up.x())+ " "+ QString().number(up.y())+" "+QString().number(up.z())+ " ";
4385 
4386  } else if(commandTmp->GetCommandName() == "viewpointThetaPhi") {
4387  G4Vector3D direction = fVP.GetViewpointDirection();
4388  // degree
4389  params = QString().number(direction.theta()/CLHEP::degree)+ " "+ QString().number(direction.phi()/CLHEP::degree)+" deg";
4390  if (commandTmp->GetParameterEntries() == 3) {
4391  if (commandTmp->GetParameter(2)->GetDefaultValue() != "deg") {
4392  params = QString().number(direction.theta())+ " "+ QString().number(direction.phi())+" "+commandTmp->GetParameter(2)->GetDefaultValue().data();
4393  }
4394  }
4395  } else if(commandTmp->GetCommandName() == "viewpointVector") {
4396  G4Vector3D direction = fVP.GetViewpointDirection();
4397  params = QString().number(direction.x())+ " "+ QString().number(direction.y())+" "+QString().number(direction.z());
4398  } else {
4399  // No help
4400  }
4401 
4402  /* DO NOT DISPLAY COMMANDS WITHOUT ANY PARAMETERS SET
4403  if (params == "") {
4404  // TODO : display default parameters // should not be editable ?
4405 
4406  for( G4int i_thParameter=0; i_thParameter<commandTmp->GetParameterEntries(); i_thParameter++ ) {
4407  commandParam = commandTmp->GetParameter(i_thParameter);
4408 
4409  if (QString(QChar(commandParam->GetParameterType())) == "b") {
4410  if (commandParam->GetDefaultValue().data()) {
4411  params += "True";
4412  } else {
4413  params += "False";
4414  }
4415  } else {
4416  params += QString((char*)(commandParam->GetDefaultValue()).data());
4417  }
4418  if (i_thParameter<commandTmp->GetParameterEntries()-1) {
4419  params += " ";
4420  }
4421  }
4422  }
4423  */
4424 
4425  if (params != "") {
4426 
4427  QTableWidgetItem *nameItem;
4428  QTableWidgetItem *paramItem;
4429 
4430  // already present ?
4431  QList<QTableWidgetItem *> list = fSceneTreeComponentTreeWidgetInfos->findItems (commandTmp->GetCommandName().data(),Qt::MatchExactly);
4432  if (list.size() == 1) {
4433  nameItem = list.first();
4434  paramItem = fSceneTreeComponentTreeWidgetInfos->item(nameItem->row(),1);
4435 
4436  } else {
4437  nameItem = new QTableWidgetItem();
4438  paramItem = new QTableWidgetItem();
4439  fSceneTreeComponentTreeWidgetInfos->setItem(a-treeWidgetInfosIgnoredCommands, 0, nameItem);
4440  fSceneTreeComponentTreeWidgetInfos->setItem(a-treeWidgetInfosIgnoredCommands, 1, paramItem);
4441 
4442  // Set Guidance
4443  QString guidance;
4444  G4int n_guidanceEntry = commandTmp->GetGuidanceEntries();
4445  for( G4int i_thGuidance=0; i_thGuidance < n_guidanceEntry; i_thGuidance++ ) {
4446  guidance += QString((char*)(commandTmp->GetGuidanceLine(i_thGuidance)).data()) + "\n";
4447  }
4448 
4449  nameItem->setToolTip(guidance);
4450  paramItem->setToolTip(GetCommandParameterList(commandTmp));
4451 
4452  fSceneTreeComponentTreeWidgetInfos->setRowHeight(a-treeWidgetInfosIgnoredCommands,15);
4453  }
4454 
4455  // set current name and parameters
4456  nameItem->setText(commandTmp->GetCommandName().data());
4457  paramItem->setText(params);
4458 
4459  nameItem->setFlags(Qt::NoItemFlags);
4460  nameItem->setForeground(QBrush());
4461 
4462  } else {
4463  treeWidgetInfosIgnoredCommands++;
4464  }
4465  }
4466  // remove empty content row
4467  for (int i=0; i<treeWidgetInfosIgnoredCommands; i++) {
4468  fSceneTreeComponentTreeWidgetInfos->removeRow (fSceneTreeComponentTreeWidgetInfos->rowCount() - 1);
4469  }
4470 
4471  fSceneTreeComponentTreeWidgetInfos->resizeColumnToContents(0);
4472  fSceneTreeComponentTreeWidgetInfos->horizontalHeader()->setStretchLastSection(true);
4473  fSceneTreeComponentTreeWidgetInfos->blockSignals(false);
4474 
4475  fTreeWidgetInfosIgnoredCommands = treeWidgetInfosIgnoredCommands;
4476 }
4477 
4478 
4479 
4480 void G4OpenGLQtViewer::toggleSceneTreeViewerInfos() {
4481  if (! fSceneTreeViewerButton) {
4482  return;
4483  }
4484  fSceneTreeViewerInfos->setVisible(!fSceneTreeViewerInfos->isVisible());
4485  if (fSceneTreeViewerInfos->isVisible()) {
4486  fSceneTreeViewerButton->setIcon(*fTreeIconOpen);
4487  } else {
4488  fSceneTreeViewerButton->setIcon(*fTreeIconClosed);
4489  }
4490 }
4491 
4492 
4493 void G4OpenGLQtViewer::toggleSceneTreeComponentTreeWidgetInfos() {
4494  fSceneTreeComponentTreeWidgetInfos->setVisible(!fSceneTreeComponentTreeWidgetInfos->isVisible());
4495  if (fSceneTreeComponentTreeWidgetInfos->isVisible()) {
4496  fViewerPropertiesButton->setIcon(*fTreeIconOpen);
4497  } else {
4498  fViewerPropertiesButton->setIcon(*fTreeIconClosed);
4499  }
4500 }
4501 
4502 
4503 void G4OpenGLQtViewer::toggleSceneTreeComponentPickingInfos() {
4504  fSceneTreeComponentPickingScrollArea->setVisible(!fSceneTreeComponentPickingScrollArea->isVisible());
4505  if (fViewerPickingButton->isVisible()) {
4506  fViewerPickingButton->setIcon(*fTreeIconOpen);
4507  } else {
4508  fViewerPickingButton->setIcon(*fTreeIconClosed);
4509  }
4510 }
4511 
4512 
4513 void G4OpenGLQtViewer::toggleSceneTreeComponentPickingCout(int pickItem) {
4514 
4515  QWidget* w;
4516  // close other items, it could take too much space
4517 
4518  for (int a=0; a<fSceneTreeComponentPickingInfos->layout()->count(); a++) {
4519  w = fSceneTreeComponentPickingInfos->layout()->itemAt(a)->widget();
4520  QTextEdit* ed = dynamic_cast<QTextEdit*>(w);
4521  QPushButton* button;
4522  if (ed) {
4523  if (a == pickItem) {
4524  w->setVisible(!w->isVisible());
4525  } else {
4526  w->setVisible(false);
4527  }
4528  if (a >= 1) {
4529  button = dynamic_cast<QPushButton*>(fSceneTreeComponentPickingInfos->layout()->itemAt(a-1)->widget());
4530  if (button) {
4531  if (button->isVisible()) {
4532  button->setIcon(*fTreeIconOpen);
4533  } else {
4534  button->setIcon(*fTreeIconClosed);
4535  }
4536  }
4537  }
4538  }
4539  }
4540 }
4541 
4542 
4543 void G4OpenGLQtViewer::tableWidgetViewerSetItemChanged(QTableWidgetItem * item) {
4545  if(UI != NULL) {
4546  QTableWidgetItem* previous = fSceneTreeComponentTreeWidgetInfos->item(fSceneTreeComponentTreeWidgetInfos->row(item),0);
4547  if (previous) {
4548  fSceneTreeComponentTreeWidgetInfos->blockSignals(true);
4549  UI->ApplyCommand((std::string("/vis/viewer/set/")
4550  + previous->text().toStdString()
4551  + " "
4552  + item->text().toStdString()).c_str());
4553  fSceneTreeComponentTreeWidgetInfos->blockSignals(false);
4554  }
4555  }
4556 }
4557 
4558 
4566 QString G4OpenGLQtViewer::GetCommandParameterList (
4567  const G4UIcommand *aCommand
4568  )
4569 {
4570  G4int n_parameterEntry = aCommand->GetParameterEntries();
4571  QString txt;
4572 
4573  if( n_parameterEntry > 0 ) {
4574  G4UIparameter *param;
4575 
4576  // Re-implementation of G4UIparameter.cc
4577 
4578  for( G4int i_thParameter=0; i_thParameter<n_parameterEntry; i_thParameter++ ) {
4579  param = aCommand->GetParameter(i_thParameter);
4580  txt += "\nParameter : " + QString((char*)(param->GetParameterName()).data()) + "\n";
4581  if( ! param->GetParameterGuidance().isNull() )
4582  txt += QString((char*)(param->GetParameterGuidance()).data())+ "\n" ;
4583  txt += " Parameter type : " + QString(QChar(param->GetParameterType())) + "\n";
4584  if(param->IsOmittable()){
4585  txt += " Omittable : True\n";
4586  } else {
4587  txt += " Omittable : False\n";
4588  }
4589  if( param->GetCurrentAsDefault() ) {
4590  txt += " Default value : taken from the current value\n";
4591  } else if( ! param->GetDefaultValue().isNull() ) {
4592  txt += " Default value : " + QString((char*)(param->GetDefaultValue()).data())+ "\n";
4593  }
4594  if( ! param->GetParameterRange().isNull() ) {
4595  txt += " Parameter range : " + QString((char*)(param->GetParameterRange()).data())+ "\n";
4596  }
4597  if( ! param->GetParameterCandidates().isNull() ) {
4598  txt += " Candidates : " + QString((char*)(param->GetParameterCandidates()).data())+ "\n";
4599  }
4600  }
4601  }
4602  return txt;
4603 }
4604 
4605 #ifdef G4MULTITHREADED
4606 
4607 void G4OpenGLQtViewer::DoneWithMasterThread()
4608 {
4609  // Called by Main Thread !
4610 
4611  // Useful to avoid two vis thread at the same time
4612  G4MUTEXLOCK(&mWaitForVisSubThreadQtOpenGLContextInitialized);
4613 }
4614 
4615 void G4OpenGLQtViewer::SwitchToVisSubThread()
4616 {
4617  // Called by VisSub Thread !
4618 
4619  QGLWidget* qGLW = dynamic_cast<QGLWidget*> (fGLWidget) ;
4620  if (! qGLW) {
4621  return;
4622  }
4623 
4624  // Set the current QThread to its static variable
4625  SetQGLContextVisSubThread(QThread::currentThread());
4626 
4627  // - Wait for the vis thread to set its QThread
4628  G4CONDTIONBROADCAST(&c1_VisSubThreadQtOpenGLContextInitialized);
4629 
4630  // Unlock the vis thread if it is Qt Viewer
4631  G4CONDITIONWAIT(&c2_VisSubThreadQtOpenGLContextMoved, &mWaitForVisSubThreadQtOpenGLContextMoved);
4632 
4633  // make context current
4634  qGLW->makeCurrent();
4635 }
4636 
4637 void G4OpenGLQtViewer::DoneWithVisSubThread()
4638 {
4639  // Called by vis sub thread
4640  QGLWidget* qGLW = dynamic_cast<QGLWidget*> (fGLWidget) ;
4641  if (! qGLW) {
4642  return;
4643  }
4644 
4645  // finish with this vis sub thread context
4646  qGLW->doneCurrent();
4647 
4648 #if QT_VERSION > 0x050000
4649  // and move it back to the main thread
4650  qGLW->context()->moveToThread(fQGLContextMainThread);
4651 #endif
4652 }
4653 
4654 void G4OpenGLQtViewer::SwitchToMasterThread()
4655 {
4656  // Called by VisSub Thread !
4657 
4658  QGLWidget* qGLW = dynamic_cast<QGLWidget*> (fGLWidget) ;
4659  if (! qGLW) {
4660  return;
4661  }
4662 
4663  // Useful to avoid two vis thread at the same time
4664  G4MUTEXUNLOCK(&mWaitForVisSubThreadQtOpenGLContextInitialized);
4665  qGLW->makeCurrent();
4666 }
4667 
4668 
4669 void G4OpenGLQtViewer::MovingToVisSubThread(){
4670  // Called by Main Thread !
4671 
4672  QGLWidget* qGLW = dynamic_cast<QGLWidget*> (fGLWidget) ;
4673  if (! qGLW) {
4674  return;
4675  }
4676 
4677  // - Wait for the vis sub thread to set its QThread
4678  G4CONDITIONWAIT( &c1_VisSubThreadQtOpenGLContextInitialized, &mWaitForVisSubThreadQtOpenGLContextInitialized);
4679 
4680 
4681  // Set current QThread for the way back
4682  SetQGLContextMainThread(QThread::currentThread());
4683 
4684  // finish with this main thread context
4685  qGLW->doneCurrent();
4686 #if QT_VERSION > 0x050000
4687  qGLW->context()->moveToThread(fQGLContextVisSubThread);
4688 #endif
4689 
4690  G4CONDTIONBROADCAST(&c2_VisSubThreadQtOpenGLContextMoved);
4691 }
4692 
4693 #endif
4694 
4695 
4696 /*
4697 
4698 void MultiLayer::exportToSVG(const QString& fname)
4699 {
4700 QPicture picture;
4701 QPainter p(&picture);
4702 for (int i=0;i<(int)graphsList->count();i++)
4703 {
4704 Graph *gr=(Graph *)graphsList->at(i);
4705 Plot *myPlot= (Plot *)gr->plotWidget();
4706 
4707 QPoint pos=gr->pos();
4708 
4709 int width=int(myPlot->frameGeometry().width());
4710 int height=int(myPlot->frameGeometry().height());
4711 
4712 myPlot->print(&p, QRect(pos,QSize(width,height)));
4713 }
4714 
4715 p.end();
4716 picture.save(fname, "svg");
4717 }
4718 */
4719 #endif
#define G4MUTEXUNLOCK
Definition: G4Threading.hh:180
G4String GetText() const
G4int GetGuidanceEntries() const
Definition: G4UIcommand.hh:135
G4String GetDefaultValue() const
G4UIcommandTree * FindCommandTree(const char *commandPath)
void SetColour(const G4Colour &)
Float_t tmp
Definition: G4Text.hh:73
const G4String & GetCommandName() const
Definition: G4UIcommand.hh:141
G4String GetParameterRange() const
const char * data() const
Definition: test07.cc:36
Float_t d
Int_t index
G4bool GetCurrentAsDefault() const
#define G4CONDTIONBROADCAST(cond)
Definition: G4Threading.hh:192
G4Point3D GetPosition() const
Definition: G4UIGAG.hh:45
G4String name
Definition: TRTMaterials.hh:40
G4UIcommand * GetCommand(G4int i)
G4double GetAlpha() const
Definition: G4Colour.hh:142
const G4String GetParameterGuidance() const
const G4String & GetGuidanceLine(G4int i) const
Definition: G4UIcommand.hh:137
static G4bool GetColour(const G4String &key, G4Colour &result)
Definition: G4Colour.cc:126
#define width
G4bool IsOmittable() const
char GetParameterType() const
G4double GetXOffset() const
G4UIparameter * GetParameter(G4int i) const
Definition: G4UIcommand.hh:145
const G4Transform3D & GetTransformation() const
#define G4BestUnit(a, b)
#define G4_USE_G4BESTUNIT_FOR_VERBOSE 1
G4double GetGreen() const
Definition: G4Colour.hh:140
TDirectory * dir
Definition: test07.cc:36
TFile * file
Definition: test07.cc:36
int G4int
Definition: G4Types.hh:78
#define G4CONDITIONWAIT(cond, mutex)
Definition: G4Threading.hh:191
static const double degree
#define G4MUTEX_INITIALIZER
Definition: G4Threading.hh:175
G4double GetRed() const
Definition: G4Colour.hh:139
G4int GetCommandEntry() const
static G4UImanager * GetUIpointer()
Definition: G4UImanager.cc:58
const std::vector< G4PhysicalVolumeNodeID > & GetFullPVPath() const
Layout GetLayout() const
G4GLOB_DLL std::ostream G4cout
G4double GetBlue() const
Definition: G4Colour.hh:141
G4double GetYOffset() const
bool G4bool
Definition: G4Types.hh:79
G4String GetParameterName() const
std::vector< PVNodeID > PVPath
#define G4MUTEXLOCK
Definition: G4Threading.hh:179
G4Colour G4Color
Definition: G4Color.hh:42
G4UIcommandTree * GetTree() const
Definition: G4UImanager.hh:206
void print(G4double elem)
static const double gray
Definition: G4SIunits.hh:306
G4int G4Mutex
Definition: G4Threading.hh:173
G4String GetParameterCandidates() const
static const G4double factor
const G4String & GetName() const
G4int GetParameterEntries() const
Definition: G4UIcommand.hh:143
#define G4endl
Definition: G4ios.hh:61
static MCTruthManager * instance
static PROLOG_HANDLER error
Definition: xmlrole.cc:112
fclose(fp)
double G4double
Definition: G4Types.hh:76
static const G4double alpha
G4int G4Condition
Definition: G4Threading.hh:189
G4int G4GetThreadId()
Definition: G4Threading.cc:134
G4int ApplyCommand(const char *aCommand)
Definition: G4UImanager.cc:446
std::vector< G4PolyconeSideRZ > g4c
Definition: ExP02Classes.hh:79
G4GLOB_DLL std::ostream G4cerr
G4bool isNull() const
#define G4CONDITION_INITIALIZER
Definition: G4Threading.hh:190
const G4Colour & GetColour() const