Geant4  9.6.p02
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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$
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 
35 #ifdef G4VIS_BUILD_OPENGLQT_DRIVER
36 
37 #include "G4OpenGLQtViewer.hh"
38 
39 #include "G4OpenGLSceneHandler.hh"
40 #include "G4VSolid.hh"
42 #include "G4OpenGLQtMovieDialog.hh"
43 #include "G4Qt.hh"
44 #include "G4UIQt.hh"
45 #include "G4UImanager.hh"
46 #include "G4UIcommandTree.hh"
47 #include "G4LogicalVolumeStore.hh"
48 #include "G4PhysicalVolumeStore.hh"
50 #include "G4PhysicalVolumeModel.hh"
51 #include "G4Text.hh"
52 
54 
55 #include <typeinfo>
56 
57 #include <qlayout.h>
58 #include <qlabel.h>
59 #include <qdialog.h>
60 #include <qpushbutton.h>
61 #include <qprocess.h>
62 #include <qapplication.h>
63 #include <qdesktopwidget.h>
64 
65 #include <qmenu.h>
66 #include <qimagewriter.h>
67 
68 #include <qtextedit.h>
69 #include <qtreewidget.h>
70 #include <qapplication.h>
71 #include <qmessagebox.h>
72 #include <qfiledialog.h>
73 #include <qprinter.h>
74 #include <qdatetime.h>
75 #include <qpainter.h>
76 #include <qgl.h> // include <qglwidget.h>
77 #include <qdialog.h>
78 #include <qcolordialog.h>
79 #include <qevent.h> //include <qcontextmenuevent.h>
80 #include <qobject.h>
81 #include <qgroupbox.h>
82 #include <qcombobox.h>
83 #include <qlineedit.h>
84 #include <qsignalmapper.h>
85 
87 void G4OpenGLQtViewer::CreateMainWindow (
88  QGLWidget* glWidget
89  ,const QString& name
90 )
91 {
94 
95  if(fWindow) return; //Done.
96 
97  fWindow = glWidget ;
98  // fWindow->makeCurrent();
99 
100  G4Qt* interactorManager = G4Qt::getInstance ();
101 
102  ResizeWindow(fVP.GetWindowSizeHintX(),fVP.GetWindowSizeHintY());
103 
104  // FIXME L.Garnier 9/11/09 Has to be check !!!
105  // Qt UI with Qt Vis
106  // Qt UI with X Vis
107  // X UI with Qt Vis
108  // X UI with X Vis
109  // Ne marche pas avec un UIBatch !! (ecran blanc)
110 
111  // return false if G4UIQt was not launch
112 
114  if (UI == NULL) return;
115 
116  if (! static_cast<G4UIQt*> (UI->GetG4UIWindow())) {
117  // NO UI, should be batch mode
118  fBatchMode = true;
119  return;
120  }
121  fUiQt = static_cast<G4UIQt*> (UI->GetG4UIWindow());
122 
123  bool isTabbedView = false;
124  if ( fUiQt) {
125  if (!fBatchMode) {
126  if (!interactorManager->IsExternalApp()) {
127  isTabbedView = fUiQt->AddTabWidget(fWindow,name,getWinWidth(),getWinHeight());
128  fUISceneTreeComponentsTBWidget = fUiQt->GetSceneTreeComponentsTBWidget();
129  isTabbedView = true;
130  }
131  }
132  }
133 #ifdef G4DEBUG_VIS_OGL
134  else {
135  printf("G4OpenGLQtViewer::CreateMainWindow :: UIQt NOt found \n");
136  }
137 #endif
138 
139  if (!isTabbedView) { // we have to do a dialog
140 
141  QWidget *myParent = getParentWidget();
142 #ifdef G4DEBUG_VIS_OGL
143  printf("G4OpenGLQtViewer::CreateMainWindow :: getParent OK \n");
144 #endif
145  if (myParent != NULL) {
146  glWidget->setParent(myParent);
147  }
148  QHBoxLayout *mainLayout = new QHBoxLayout(fGLWindow);
149 
150  mainLayout->setMargin(0);
151  mainLayout->setSpacing(0);
152  mainLayout->addWidget(fWindow);
153  if (fGLWindow->inherits("QMainWindow")) {
154  fGLWindow->setWindowTitle( name);
155  }
156  fGLWindow->setLayout(mainLayout);
157 
158 
159  //useful for MACOSX, we have to compt the menuBar height
160  int offset = QApplication::desktop()->height()
161  - QApplication::desktop()->availableGeometry().height();
162 
163  G4int YPos= fVP.GetWindowAbsoluteLocationHintY(QApplication::desktop()->height());
164  if (fVP.GetWindowAbsoluteLocationHintY(QApplication::desktop()->height())< offset) {
165  YPos = offset;
166  }
167  fGLWindow->resize(getWinWidth(), getWinHeight());
168 #ifdef G4DEBUG_VIS_OGL
169  printf("G4OpenGLQtViewer::CreateMainWindow :: resizing to %d %d \n",getWinWidth(), getWinHeight());
170 #endif
171  fGLWindow->move(fVP.GetWindowAbsoluteLocationHintX(QApplication::desktop()->width()),YPos);
172  fGLWindow->show();
173  } else {
174  fGLWindow = fWindow;
175  fGLWindow->resize(getWinWidth(), getWinHeight());
176  }
177 
178  if(!fWindow) return;
179 
180  if (!fContextMenu)
181  createPopupMenu();
182 
183 }
184 
185 
187 G4OpenGLQtViewer::G4OpenGLQtViewer (
188  G4OpenGLSceneHandler& scene
189 )
190  :G4VViewer (scene, -1)
191  ,G4OpenGLViewer (scene)
192  ,fWindow(0)
193  ,fRecordFrameNumber(0)
194  ,fContextMenu(0)
195  ,fDeltaDepth(0.01)
196  ,fDeltaZoom(0.05)
197  ,fHoldKeyEvent(false)
198  ,fHoldMoveEvent(false)
199  ,fHoldRotateEvent(false)
200  ,fAutoMove(false)
201  ,fEncoderPath("")
202  ,fTempFolderPath("")
203  ,fMovieTempFolderPath("")
204  ,fSaveFileName("")
205  ,fParameterFileName("ppmtompeg_encode_parameter_file.par")
206  ,fMovieParametersDialog(NULL)
207  ,fRecordingStep(WAIT)
208  ,fProcess(NULL)
209  ,fNbMaxFramesPerSec(100)
210  ,fNbMaxAnglePerSec(360)
211  ,fLaunchSpinDelay(100)
212  ,fUISceneTreeComponentsTBWidget(NULL)
213  ,fNoKeyPress(true)
214  ,fAltKeyPress(false)
215  ,fControlKeyPress(false)
216  ,fShiftKeyPress(false)
217  ,fBatchMode(false)
218  ,fCheckSceneTreeComponentSignalLock(false)
219  ,fSceneTreeComponentTreeWidget(NULL)
220  ,fOldSceneTreeComponentTreeWidget(NULL)
221  ,fSceneTreeWidget(NULL)
222  ,fPVRootNodeCreate(false)
223  ,fHelpLine(NULL)
224  ,fNbRotation(0)
225  ,fTimeRotation(0)
226  ,fTouchableVolumes("Touchables")
227  ,fShortcutsDialog(NULL)
228  ,fSceneTreeDepthSlider(NULL)
229  ,fSceneTreeDepth(1)
230  ,fModelShortNameItem(NULL)
231  ,fMaxPOindexInserted(-1)
232  ,fUiQt(NULL)
233  ,signalMapperMouse(NULL)
234  ,signalMapperSurface(NULL)
235 {
236 
237  // launch Qt if not
238  if (QCoreApplication::instance () == NULL) {
239  fBatchMode = true;
240  }
241  G4Qt::getInstance ();
242 
243  fLastPos3 = QPoint(-1,-1);
244  fLastPos2 = QPoint(-1,-1);
245  fLastPos1 = QPoint(-1,-1);
246 
247  initMovieParameters();
248 
249  fLastEventTime = new QTime();
250  signalMapperMouse = new QSignalMapper(this);
251  signalMapperSurface = new QSignalMapper(this);
252 
253 #ifdef G4DEBUG_VIS_OGL
254  printf("G4OpenGLQtViewer::G4OpenGLQtViewer END\n");
255 #endif
256 }
257 
259 G4OpenGLQtViewer::~G4OpenGLQtViewer (
260 )
261 {
264  // remove scene tree from layout
265  // Delete all the existing buttons in the layout
266  QLayoutItem *wItem;
267  if (fSceneTreeWidget != NULL) {
268  if (fSceneTreeWidget->layout() != NULL) {
269  while ((wItem = fSceneTreeWidget->layout()->takeAt(0)) != 0) {
270  delete wItem->widget();
271  delete wItem;
272  }
273  }
274  if (fUISceneTreeComponentsTBWidget != NULL) {
275  fUISceneTreeComponentsTBWidget->removeTab(fUISceneTreeComponentsTBWidget->indexOf(fSceneTreeWidget));
276  }
277  }
278  G4cout <<removeTempFolder().toStdString().c_str() <<G4endl;
279 }
280 
281 
282 //
283 // Create a popup menu for the widget. This menu is activated by right-mouse click
284 //
285 void G4OpenGLQtViewer::createPopupMenu() {
286 
287  fContextMenu = new QMenu("All");
288 
289  QMenu *mMouseAction = fContextMenu->addMenu("&Mouse actions");
290 
291  fMouseRotateAction = mMouseAction->addAction("Rotate", signalMapperMouse, SLOT(map()));
292  fMouseMoveAction = mMouseAction->addAction("Move", signalMapperMouse, SLOT(map()));
293  fMousePickAction = mMouseAction->addAction("Pick", signalMapperMouse, SLOT(map()));
294  fMouseZoomOutAction = mMouseAction->addAction("Zoom out", signalMapperMouse, SLOT(map()));
295  fMouseZoomInAction = mMouseAction->addAction("Zoom in", signalMapperMouse, SLOT(map()));
296  QAction *shortcutsAction = mMouseAction->addAction("Show shortcuts");
297 
298  fMouseRotateAction->setCheckable(true);
299  fMouseMoveAction->setCheckable(true);
300  fMousePickAction->setCheckable(true);
301  fMouseZoomOutAction->setCheckable(true);
302  fMouseZoomInAction->setCheckable(true);
303  shortcutsAction->setCheckable(false);
304 
305  connect(signalMapperMouse, SIGNAL(mapped(int)),this, SLOT(toggleMouseAction(int)));
306  signalMapperMouse->setMapping(fMouseRotateAction,1);
307  signalMapperMouse->setMapping(fMouseMoveAction,2);
308  signalMapperMouse->setMapping(fMousePickAction,3);
309  signalMapperMouse->setMapping(fMouseZoomOutAction,4);
310  signalMapperMouse->setMapping(fMouseZoomInAction,5);
311 
312  QObject::connect(shortcutsAction,
313  SIGNAL(triggered(bool)),
314  this,
315  SLOT(showShortcuts()));
316 
317  // === Style Menu ===
318  QMenu *mStyle = fContextMenu->addMenu("&Style");
319 
320  QMenu *mRepresentation = mStyle->addMenu("&Representation");
321  QMenu *mProjection = mStyle->addMenu("&Projection");
322  QAction *polyhedron = mRepresentation->addAction("Polyhedron");
323  QAction *nurbs = mRepresentation->addAction("NURBS");
324 
325  fProjectionOrtho = mProjection->addAction("Orthographic", signalMapperSurface, SLOT(map()));
326  fProjectionPerspective = mProjection->addAction("Persepective", signalMapperSurface, SLOT(map()));
327 
328  // INIT mRepresentation
330  style = fVP.GetRepStyle();
331  if (style == G4ViewParameters::polyhedron) {
332  createRadioAction(polyhedron,nurbs,SLOT(toggleRepresentation(bool)),1);
333  } else if (style == G4ViewParameters::nurbs) {
334  createRadioAction(polyhedron,nurbs,SLOT(toggleRepresentation(bool)),2);
335  } else {
336  mRepresentation->clear();
337  }
338 
339  // INIT mProjection
340  if (fVP.GetFieldHalfAngle() == 0) {
341  createRadioAction(fProjectionOrtho, fProjectionPerspective,SLOT(toggleProjection(bool)),1);
342  } else {
343  createRadioAction(fProjectionOrtho, fProjectionPerspective,SLOT(toggleProjection(bool)),2);
344  }
345 
346  // === Drawing Menu ===
347  QMenu *mDrawing = mStyle->addMenu("&Drawing");
348 
349  fDrawingWireframe = mDrawing->addAction("Wireframe", signalMapperSurface, SLOT(map()));
350 
351  fDrawingLineRemoval = mDrawing->addAction("Hidden line removal", signalMapperSurface, SLOT(map()));
352 
353  fDrawingSurfaceRemoval = mDrawing->addAction("Hidden Surface removal", signalMapperSurface, SLOT(map()));
354 
355  fDrawingLineSurfaceRemoval = mDrawing->addAction("Hidden line and surface removal", signalMapperSurface, SLOT(map()));
356 
357  fDrawingWireframe->setCheckable(true);
358  fDrawingLineRemoval->setCheckable(true);
359  fDrawingSurfaceRemoval->setCheckable(true);
360  fDrawingLineSurfaceRemoval->setCheckable(true);
361 
362  connect(signalMapperSurface, SIGNAL(mapped(int)),this, SLOT(toggleSurfaceAction(int)));
363  signalMapperSurface->setMapping(fDrawingWireframe,1);
364  signalMapperSurface->setMapping(fDrawingLineRemoval,2);
365  signalMapperSurface->setMapping(fDrawingSurfaceRemoval,3);
366  signalMapperSurface->setMapping(fDrawingLineSurfaceRemoval,4);
367 
368 
369  // Background Color
370 
371  QAction *backgroundColorChooser ;
372  // === Action Menu ===
373  backgroundColorChooser = mStyle->addAction("Background color");
374  QObject ::connect(backgroundColorChooser,
375  SIGNAL(triggered()),
376  this,
377  SLOT(actionChangeBackgroundColor()));
378 
379  // Text Color
380 
381  QAction *textColorChooser ;
382  // === Action Menu ===
383  textColorChooser = mStyle->addAction("Text color");
384  QObject ::connect(textColorChooser,
385  SIGNAL(triggered()),
386  this,
387  SLOT(actionChangeTextColor()));
388 
389  // Default Color
390 
391  QAction *defaultColorChooser ;
392  // === Action Menu ===
393  defaultColorChooser = mStyle->addAction("Default color");
394  QObject ::connect(defaultColorChooser,
395  SIGNAL(triggered()),
396  this,
397  SLOT(actionChangeDefaultColor()));
398 
399 
400  // === Action Menu ===
401  QMenu *mActions = fContextMenu->addMenu("&Actions");
402  QAction *createEPS = mActions->addAction("Save as ...");
403  QObject ::connect(createEPS,
404  SIGNAL(triggered()),
405  this,
406  SLOT(actionSaveImage()));
407 
408  // === Action Menu ===
409  QAction *movieParameters = mActions->addAction("Movie parameters...");
410  QObject ::connect(movieParameters,
411  SIGNAL(triggered()),
412  this,
413  SLOT(actionMovieParameters()));
414 
415 
416 
417 
418  // === Special Menu ===
419  QMenu *mSpecial = fContextMenu->addMenu("S&pecial");
420  QMenu *mTransparency = mSpecial->addMenu("Transparency");
421  QAction *transparencyOn = mTransparency->addAction("On");
422  QAction *transparencyOff = mTransparency->addAction("Off");
423 
424  if (transparency_enabled == false) {
425  createRadioAction(transparencyOn,transparencyOff,SLOT(toggleTransparency(bool)),2);
426  } else if (transparency_enabled == true) {
427  createRadioAction(transparencyOn,transparencyOff,SLOT(toggleTransparency(bool)),1);
428  } else {
429  mSpecial->clear();
430  }
431 
432 
433  QMenu *mAntialiasing = mSpecial->addMenu("Antialiasing");
434  QAction *antialiasingOn = mAntialiasing->addAction("On");
435  QAction *antialiasingOff = mAntialiasing->addAction("Off");
436 
437  if (antialiasing_enabled == false) {
438  createRadioAction(antialiasingOn,antialiasingOff,SLOT(toggleAntialiasing(bool)),2);
439  } else if (antialiasing_enabled == true) {
440  createRadioAction(antialiasingOn,antialiasingOff,SLOT(toggleAntialiasing(bool)),1);
441  } else {
442  mAntialiasing->clear();
443  }
444 
445  QMenu *mHaloing = mSpecial->addMenu("Haloing");
446  QAction *haloingOn = mHaloing->addAction("On");
447  QAction *haloingOff = mHaloing->addAction("Off");
448  if (haloing_enabled == false) {
449  createRadioAction(haloingOn,haloingOff,SLOT(toggleHaloing(bool)),2);
450  } else if (haloing_enabled == true) {
451  createRadioAction(haloingOn,haloingOff,SLOT(toggleHaloing(bool)),1);
452  } else {
453  mHaloing->clear();
454  }
455 
456  QMenu *mAux = mSpecial->addMenu("Auxiliary edges");
457  QAction *auxOn = mAux->addAction("On");
458  QAction *auxOff = mAux->addAction("Off");
459  if (!fVP.IsAuxEdgeVisible()) {
460  createRadioAction(auxOn,auxOff,SLOT(toggleAux(bool)),2);
461  } else {
462  createRadioAction(auxOn,auxOff,SLOT(toggleAux(bool)),1);
463  }
464 
465 
466  QMenu *mHiddenMarkers = mSpecial->addMenu("Hidden markers");
467  QAction *hiddenMarkersOn = mHiddenMarkers->addAction("On");
468  QAction *hiddenMarkersOff = mHiddenMarkers->addAction("Off");
469  if (fVP.IsMarkerNotHidden()) {
470  createRadioAction(hiddenMarkersOn,hiddenMarkersOff,SLOT(toggleHiddenMarkers(bool)),2);
471  } else {
472  createRadioAction(hiddenMarkersOn,hiddenMarkersOff,SLOT(toggleHiddenMarkers(bool)),1);
473  }
474 
475 
476 
477  QMenu *mFullScreen = mSpecial->addMenu("&Full screen");
478  fFullScreenOn = mFullScreen->addAction("On");
479  fFullScreenOff = mFullScreen->addAction("Off");
480  createRadioAction(fFullScreenOn,fFullScreenOff,SLOT(toggleFullScreen(bool)),2);
481 
482  // INIT All
483  updateToolbarAndMouseContextMenu();
484 }
485 
486 
487 void G4OpenGLQtViewer::G4manageContextMenuEvent(QContextMenuEvent *e)
488 {
489  if (!fGLWindow) {
490  G4cerr << "Visualization window not defined, please choose one before" << G4endl;
491  } else {
492 
493  if (!fContextMenu)
494  createPopupMenu();
495 
496  // launch menu
497  if ( fContextMenu ) {
498  fContextMenu->exec( e->globalPos() );
499  // delete fContextMenu;
500  }
501  }
502  e->accept();
503 }
504 
505 
514 void G4OpenGLQtViewer::createRadioAction(QAction *action1,QAction *action2, const std::string& method,unsigned int nCheck) {
515 
516  action1->setCheckable(true);
517  action2->setCheckable(true);
518 
519  if (nCheck ==1)
520  action1->setChecked (true);
521  else
522  action2->setChecked (true);
523 
524  QObject ::connect(action1, SIGNAL(triggered(bool)),action2, SLOT(toggle()));
525  QObject ::connect(action2, SIGNAL(triggered(bool)),action1, SLOT(toggle()));
526 
527  QObject ::connect(action1, SIGNAL(toggled(bool)),this, method.c_str());
528 
529 }
530 
531 
532 
536 void G4OpenGLQtViewer::showShortcuts() {
537  G4String text;
538 
539  text = "========= Mouse Shortcuts =========\n";
540  if (fUiQt != NULL) {
541  if (fUiQt->IsIconRotateSelected()) { // rotate
542  text += "Click and move mouse to rotate volume \n";
543  text += "ALT + Click and move mouse to rotate volume (Toggle View/Theta-Phi Direction) \n";
544  text += "CTRL + Click and zoom mouse to zoom in/out \n";
545  text += "SHIFT + Click and zoommove camera point of view \n";
546  } else if (fUiQt->IsIconMoveSelected()) { //move
547  text += "Move camera point of view with mouse \n";
548  } else if (fUiQt->IsIconPickSelected()) { //pick
549  text += "Click and pick \n";
550  }
551  } else {
552  text += "Click and move mouse to rotate volume \n";
553  text += "ALT + Click and move mouse to rotate volume (Toggle View/Theta-Phi Direction) \n";
554  text += "CTRL + Click and zoom mouse to zoom in/out \n";
555  text += "SHIFT + Click and zoommove camera point of view \n";
556  }
557  text += "========= Move Shortcuts ========= \n";
558  text += "Press left/right arrows to move volume left/right \n";
559  text += "Press up/down arrows to move volume up/down \n";
560  text += "Press '+'/'-' to move volume toward/forward \n";
561  text += "\n";
562  text += "========= Rotation (Theta/Phi) Shortcuts ========= \n";
563  text += "Press SHIFT + left/right arrows to rotate volume left/right \n";
564  text += "Press SHIFT + up/down arrows to rotate volume up/down \n";
565  text += "\n";
566  text += "========= Rotation (View Direction) Shortcuts ========= \n";
567  text += "Press ALT + left/right to rotate volume around vertical direction \n";
568  text += "Press ALT + up/down to rotate volume around horizontal direction \n";
569  text += "\n";
570  text += "========= Zoom View ========= \n";
571  text += "Press CTRL + '+'/'-' to zoom into volume \n";
572  text += "\n";
573  text += "========= Misc ========= \n";
574  text += "Press ALT +/- to slow/speed rotation/move \n";
575  text += "Press H to reset view \n";
576  text += "Press Esc to exit FullScreen \n";
577  text += "\n";
578  text += "========= Video ========= \n";
579  text += "In video mode : \n";
580  text += " Press SPACE to Start/Pause video recording \n";
581  text += " Press RETURN to Stop video recording \n";
582  text += "\n";
583 
584  G4cout << text;
585 
586  if ( fShortcutsDialog == NULL) {
587  fShortcutsDialog = new QDialog();
588  fShortcutsDialogInfos = new QTextEdit() ;
589  QVBoxLayout *mainLayout = new QVBoxLayout;
590  mainLayout->addWidget(fShortcutsDialogInfos);
591  fShortcutsDialog->setLayout(mainLayout);
592  fShortcutsDialog->setWindowTitle(tr("Shortcuts"));
593  }
594 
595  fShortcutsDialogInfos->setPlainText(text.data());
596  fShortcutsDialog->show();
597 }
598 
599 
600 
607 void G4OpenGLQtViewer::toggleMouseAction(int aAction) {
608 
609  if (aAction == 1) {
610  fUiQt->SetIconRotateSelected();
611  } else if (aAction == 2) {
612  fUiQt->SetIconMoveSelected();
613  } else if (aAction == 3) {
614  fUiQt->SetIconPickSelected();
615  } else if (aAction == 4) {
616  fUiQt->SetIconZoomOutSelected();
617  } else if (aAction == 5) {
618  fUiQt->SetIconZoomInSelected();
619  }
620 
621  updateToolbarAndMouseContextMenu();
622 }
623 
624 
635 void G4OpenGLQtViewer::toggleSurfaceAction(int aAction) {
636 
638 
639  if (aAction ==1) {
640  d_style = G4ViewParameters::wireframe;
641 
642  } else if (aAction ==2) {
643  d_style = G4ViewParameters::hlr;
644 
645  } else if (aAction ==3) {
646  d_style = G4ViewParameters::hsr;
647 
648  } else if (aAction ==4) {
649  d_style = G4ViewParameters::hlhsr;
650  }
651  fVP.SetDrawingStyle(d_style);
652 
653  updateToolbarAndMouseContextMenu();
654  updateQWidget();
655 }
656 
657 
668 void G4OpenGLQtViewer::toggleRepresentation(bool check) {
669 
671  if (check == 1) {
673  } else {
674  style = G4ViewParameters::nurbs;
675  }
676  fVP.SetRepStyle (style);
677 
678  updateToolbarAndMouseContextMenu();
679  updateQWidget();
680 }
681 
692 void G4OpenGLQtViewer::toggleProjection(bool check) {
693 
694  if (check == 1) {
695  fVP.SetOrthogonalProjection ();
696  } else {
697  fVP.SetPerspectiveProjection();
698  }
699  updateToolbarAndMouseContextMenu();
700  updateQWidget();
701 }
702 
703 
708 void G4OpenGLQtViewer::toggleTransparency(bool check) {
709 
710  if (check) {
711  transparency_enabled = true;
712  } else {
713  transparency_enabled = false;
714  }
715  SetNeedKernelVisit (true);
716  updateToolbarAndMouseContextMenu();
717  updateQWidget();
718 }
719 
724 void G4OpenGLQtViewer::toggleAntialiasing(bool check) {
725 
726  if (!check) {
727  antialiasing_enabled = false;
728  glDisable (GL_LINE_SMOOTH);
729  glDisable (GL_POLYGON_SMOOTH);
730  } else {
731  antialiasing_enabled = true;
732  glEnable (GL_LINE_SMOOTH);
733  glHint (GL_LINE_SMOOTH_HINT, GL_NICEST);
734  glEnable (GL_POLYGON_SMOOTH);
735  glHint (GL_POLYGON_SMOOTH_HINT, GL_NICEST);
736  }
737 
738  updateToolbarAndMouseContextMenu();
739  updateQWidget();
740 }
741 
746 //FIXME : I SEE NOTHING...
747 void G4OpenGLQtViewer::toggleHaloing(bool check) {
748  if (check) {
749  haloing_enabled = false;
750  } else {
751  haloing_enabled = true;
752  }
753 
754  updateToolbarAndMouseContextMenu();
755  updateQWidget();
756 
757 }
758 
763 void G4OpenGLQtViewer::toggleAux(bool check) {
764  if (check) {
765  fVP.SetAuxEdgeVisible(true);
766  } else {
767  fVP.SetAuxEdgeVisible(false);
768  }
769  SetNeedKernelVisit (true);
770  updateToolbarAndMouseContextMenu();
771  updateQWidget();
772 }
773 
778 void G4OpenGLQtViewer::toggleHiddenMarkers(bool check) {
779  if (check) {
780  fVP.SetMarkerHidden();
781  } else {
782  fVP.SetMarkerNotHidden();
783  }
784  // SetNeedKernelVisit (true);
785  updateToolbarAndMouseContextMenu();
786  updateQWidget();
787 }
788 
792 void G4OpenGLQtViewer::toggleFullScreen(bool check) {
793  if (check != fGLWindow->isFullScreen()) { //toggle
794  fGLWindow->setWindowState(fGLWindow->windowState() ^ Qt::WindowFullScreen);
795  }
796 }
797 
798 
799 void G4OpenGLQtViewer::savePPMToTemp() {
800  if (fMovieTempFolderPath == "") {
801  return;
802  }
803  QString fileName ="Test"+QString::number(fRecordFrameNumber)+".ppm";
804  QString filePath =fMovieTempFolderPath+fileName;
805 
806  QImage image;
807  image = fWindow->grabFrameBuffer();
808  bool res = false;
809 
810  res = image.save(filePath,0);
811  if (res == false) {
812  resetRecording();
813  setRecordingInfos("Can't save tmp file "+filePath);
814  return;
815  }
816 
817  setRecordingInfos("File "+fileName+" saved");
818  fRecordFrameNumber++;
819 }
820 
821 
822 
823 void G4OpenGLQtViewer::actionSaveImage() {
824  QString filters;
825  QList<QByteArray> formats = QImageWriter::supportedImageFormats ();
826  for (int i = 0; i < formats.size(); ++i) {
827  filters +=formats.at(i) + ";;";
828  }
829  filters += "eps;;";
830  filters += "ps;;";
831  filters += "pdf";
832  QString* selectedFormat = new QString();
833  std::string name;
834  name = QFileDialog::getSaveFileName ( fGLWindow,
835  tr("Save as ..."),
836  ".",
837  filters,
838  selectedFormat ).toStdString().c_str();
839  // bmp jpg jpeg png ppm xbm xpm
840  if (name.empty()) {
841  return;
842  }
843  name += "." + selectedFormat->toStdString();
844  QString format = selectedFormat->toLower();
845  setPrintFilename(name.c_str(),0);
846  G4OpenGLQtExportDialog* exportDialog= new G4OpenGLQtExportDialog(fGLWindow,format,fWindow->height(),fWindow->width());
847  if( exportDialog->exec()) {
848 
849  QImage image;
850  bool res = false;
851  if ((exportDialog->getWidth() !=fWindow->width()) ||
852  (exportDialog->getHeight() !=fWindow->height())) {
853  setPrintSize(exportDialog->getWidth(),exportDialog->getHeight());
854  if ((format != QString("eps")) && (format != QString("ps"))) {
855  G4cerr << "Export->Change Size : This function is not implemented, to export in another size, please resize your frame to what you need" << G4endl;
856 
857  // rescaleImage(exportDialog->getWidth(),exportDialog->getHeight());// re-scale image
858  // QGLWidget* glResized = fWindow;
859 
860  // FIXME :
861  // L.Garnier : I've try to implement change size function, but the problem is
862  // the renderPixmap function call the QGLWidget to resize and it doesn't draw
863  // the content of this widget... It only draw the background.
864 
865  // fWindow->renderPixmap (exportDialog->getWidth()*2,exportDialog->getHeight()*2,true );
866 
867  // QPixmap pixmap = fWindow->renderPixmap ();
868 
869  // image = pixmap->toImage();
870  // glResized->resize(exportDialog->getWidth()*2,exportDialog->getHeight()*2);
871  // image = glResized->grabFrameBuffer();
872  }
873  } else {
874  image = fWindow->grabFrameBuffer();
875  }
876  if (format == QString("eps")) {
877  fVectoredPs = exportDialog->getVectorEPS();
878  printEPS();
879  } else if (format == "ps") {
880  fVectoredPs = true;
881  printEPS();
882  } else if (format == "pdf") {
883 
884  res = printPDF(name,exportDialog->getNbColor(),image);
885 
886  } else if ((format == "tif") ||
887  (format == "tiff") ||
888  (format == "jpg") ||
889  (format == "jpeg") ||
890  (format == "png") ||
891  (format == "pbm") ||
892  (format == "pgm") ||
893  (format == "ppm") ||
894  (format == "bmp") ||
895  (format == "xbm") ||
896  (format == "xpm")) {
897  res = image.save(QString(name.c_str()),0,exportDialog->getSliderValue());
898  } else {
899  G4cerr << "This version of G4UI Could not generate the selected format" << G4endl;
900  }
901  if ((format == QString("eps")) && (format == QString("ps"))) {
902  if (res == false) {
903  G4cerr << "Error while saving file... "<<name.c_str()<< G4endl;
904  } else {
905  G4cout << "File "<<name.c_str()<<" has been saved " << G4endl;
906  }
907  }
908 
909  } else { // cancel selected
910  return;
911  }
912 
913 }
914 
915 
916 void G4OpenGLQtViewer::actionChangeBackgroundColor() {
917 
918  // //I need to revisit the kernel if the background colour changes and
919  // //hidden line removal is enabled, because hlr drawing utilises the
920  // //background colour in its drawing...
921  // // (Note added by JA 13/9/2005) Background now handled in view
922  // // parameters. A kernel visit is triggered on change of background.
923 
924 #if QT_VERSION < 0x040500
925  bool a;
926  const QColor color = QColor(QColorDialog::getRgba (QColor(Qt::black).rgba(),&a,fGLWindow));
927 #else
928  const QColor color =
929  QColorDialog::getColor(Qt::black,
930  fGLWindow,
931  " Get background color and transparency",
932  QColorDialog::ShowAlphaChannel);
933 #endif
934  if (color.isValid()) {
935  G4Colour colour(((G4double)color.red())/255,
936  ((G4double)color.green())/255,
937  ((G4double)color.blue())/255,
938  ((G4double)color.alpha())/255);
939  fVP.SetBackgroundColour(colour);
940 
941  updateToolbarAndMouseContextMenu();
942  updateQWidget();
943  }
944 }
945 
946 void G4OpenGLQtViewer::actionChangeTextColor() {
947 
948 #if QT_VERSION < 0x040500
949  bool a;
950  const QColor color = QColor(QColorDialog::getRgba (QColor(Qt::yellow).rgba(),&a,fGLWindow));
951 #else
952  const QColor& color =
953  QColorDialog::getColor(Qt::yellow,
954  fGLWindow,
955  " Get text color and transparency",
956  QColorDialog::ShowAlphaChannel);
957 #endif
958  if (color.isValid()) {
959  G4Colour colour(((G4double)color.red())/255,
960  ((G4double)color.green())/255,
961  ((G4double)color.blue())/255,
962  ((G4double)color.alpha())/255);
963 
964  fVP.SetDefaultTextColour(colour);
965 
966  updateToolbarAndMouseContextMenu();
967  updateQWidget();
968  }
969 }
970 
971 void G4OpenGLQtViewer::actionChangeDefaultColor() {
972 
973 #if QT_VERSION < 0x040500
974  bool a;
975  const QColor color = QColor(QColorDialog::getRgba (QColor(Qt::white).rgba(),&a,fGLWindow));
976 #else
977  const QColor& color =
978  QColorDialog::getColor(Qt::white,
979  fGLWindow,
980  " Get default color and transparency",
981  QColorDialog::ShowAlphaChannel);
982 #endif
983  if (color.isValid()) {
984  G4Colour colour(((G4double)color.red())/255,
985  ((G4double)color.green())/255,
986  ((G4double)color.blue())/255,
987  ((G4double)color.alpha())/255);
988 
989  fVP.SetDefaultColour(colour);
990 
991  updateToolbarAndMouseContextMenu();
992  updateQWidget();
993  }
994 }
995 
996 
997 void G4OpenGLQtViewer::actionMovieParameters() {
998  showMovieParametersDialog();
999 }
1000 
1001 
1002 void G4OpenGLQtViewer::showMovieParametersDialog() {
1003  if (!fMovieParametersDialog) {
1004  fMovieParametersDialog= new G4OpenGLQtMovieDialog(this,fGLWindow);
1005  displayRecordingStatus();
1006  fMovieParametersDialog->checkEncoderSwParameters();
1007  fMovieParametersDialog->checkSaveFileNameParameters();
1008  fMovieParametersDialog->checkTempFolderParameters();
1009  if (getEncoderPath() == "") {
1010  setRecordingInfos("ppmtompeg is needed to encode in video format. It is available here: http://netpbm.sourceforge.net ");
1011  }
1012  }
1013  fMovieParametersDialog->show();
1014 }
1015 
1016 
1017 /*
1018 // http://www.google.com/codesearch?hl=en&q=+jpg+Qt+quality+QDialog+show:FZkUoth8oiw:TONpW2mR-_c:tyTfrKMO-xI&sa=N&cd=2&ct=rc&cs_p=http://soft.proindependent.com/src/qtiplot-0.8.9.zip&cs_f=qtiplot-0.8.9/qtiplot/src/application.cpp#a0
1019 
1020 void Graph::exportToSVG(const QString& fname)
1021 {
1022 // enable workaround for Qt3 misalignments
1023 QwtPainter::setSVGMode(true);
1024 QPicture picture;
1025 QPainter p(&picture);
1026 d_plot->print(&p, d_plot->rect());
1027 p.end();
1028 
1029 picture.save(fname, "svg");
1030 }
1031 */
1032 
1033 
1034 
1035 void G4OpenGLQtViewer::FinishView()
1036 {
1037  glFlush ();
1038 
1039  // L. Garnier 10/2009 : Not necessary and cause problems on mac OS X 10.6
1040  // fWindow->swapBuffers ();
1041 }
1042 
1047 void G4OpenGLQtViewer::G4MousePressEvent(QMouseEvent *evnt)
1048 {
1049  if ((evnt->buttons() & Qt::LeftButton) && (! (evnt->modifiers() & Qt::ControlModifier ))){
1050  fWindow->setMouseTracking(true);
1051  fAutoMove = false; // stop automove
1052  fLastPos1 = evnt->pos();
1053  fLastPos2 = fLastPos1;
1054  fLastPos3 = fLastPos2;
1055  fLastEventTime->start();
1056  if (fUiQt != NULL) {
1057 
1058  if (fUiQt->IsIconPickSelected()){ // pick
1059  fVP.SetPicking(true);
1060  Pick(evnt->pos().x(),evnt->pos().y());
1061  fVP.SetPicking(false);
1062 
1063  } else if (fUiQt->IsIconZoomInSelected()) { // zoomIn
1064  // Move click point to center of OGL
1065 
1066  float deltaX = ((float)getWinWidth()/2-evnt->pos().x());
1067  float deltaY = ((float)getWinHeight()/2-evnt->pos().y());
1068 
1069  G4double coefTrans = 0;
1070  coefTrans = ((G4double)getSceneNearWidth())/((G4double)getWinWidth());
1071  if (getWinHeight() <getWinWidth()) {
1072  coefTrans = ((G4double)getSceneNearWidth())/((G4double)getWinHeight());
1073  }
1074  fVP.IncrementPan(-deltaX*coefTrans,deltaY*coefTrans,0);
1075  fVP.SetZoomFactor(1.5 * fVP.GetZoomFactor());
1076 
1077  updateQWidget();
1078 
1079  } else if (fUiQt->IsIconZoomOutSelected()) { // zoomOut
1080  // Move click point to center of OGL
1081  moveScene(((float)getWinWidth()/2-evnt->pos().x()),((float)getWinHeight()/2-evnt->pos().y()),0,true);
1082 
1083  fVP.SetZoomFactor(0.75 * fVP.GetZoomFactor());
1084  updateQWidget();
1085 
1086  }
1087  }
1088  }
1089 }
1090 
1093 void G4OpenGLQtViewer::G4MouseReleaseEvent()
1094 {
1095  fSpinningDelay = fLastEventTime->elapsed();
1096  QPoint delta = (fLastPos3-fLastPos1);
1097  if ((delta.x() == 0) && (delta.y() == 0)) {
1098  return;
1099  }
1100  if (fSpinningDelay < fLaunchSpinDelay ) {
1101  fAutoMove = true;
1102  QTime lastMoveTime;
1103  lastMoveTime.start();
1104  // try to addapt speed move/rotate looking to drawing speed
1105  float correctionFactor = 5;
1106  while (fAutoMove) {
1107  if ( lastMoveTime.elapsed() >= (int)(1000/fNbMaxFramesPerSec)) {
1108  float lTime = 1000/lastMoveTime.elapsed();
1109  if (((((float)delta.x())/correctionFactor)*lTime > fNbMaxAnglePerSec) ||
1110  ((((float)delta.x())/correctionFactor)*lTime < -fNbMaxAnglePerSec) ) {
1111  correctionFactor = (float)delta.x()*(lTime/fNbMaxAnglePerSec);
1112  if (delta.x() <0 ) {
1113  correctionFactor = -correctionFactor;
1114  }
1115  }
1116  if (((((float)delta.y())/correctionFactor)*lTime > fNbMaxAnglePerSec) ||
1117  ((((float)delta.y())/correctionFactor)*lTime < -fNbMaxAnglePerSec) ) {
1118  correctionFactor = (float)delta.y()*(lTime/fNbMaxAnglePerSec);
1119  if (delta.y() <0 ) {
1120  correctionFactor = -correctionFactor;
1121  }
1122  }
1123 
1124  // Check Qt Versions for META Keys
1125 
1126  // Click and move mouse to rotate volume
1127  // ALT + Click and move mouse to rotate volume (View Direction)
1128  // SHIFT + Click and move camera point of view
1129  // CTRL + Click and zoom mouse to zoom in/out
1130 
1131  lastMoveTime.start();
1132 
1133  bool rotate = false;
1134  bool move = false;
1135 
1136  if (fUiQt != NULL) {
1137  if (fUiQt->IsIconRotateSelected()) { // rotate
1138  rotate = true;
1139  } else if (fUiQt->IsIconMoveSelected()) { // move
1140  move = true;
1141  }
1142  } else {
1143  rotate = true;
1144  }
1145  if (rotate) { // rotate
1146  if (fNoKeyPress) {
1147  rotateQtScene(((float)delta.x())/correctionFactor,((float)delta.y())/correctionFactor);
1148  } else if (fAltKeyPress) {
1149  rotateQtSceneToggle(((float)delta.x())/correctionFactor,((float)delta.y())/correctionFactor);
1150  }
1151 #ifdef G4DEBUG_VIS_OGL
1152  fNbRotation ++;
1153  fTimeRotation += lastMoveTime.elapsed();
1154  printf("G4OpenGLQtViewer %f \n",fTimeRotation/(float)fNbRotation);
1155 #endif
1156 
1157  } else if (move) { // move
1158  moveScene(-((float)delta.x())/correctionFactor,-((float)delta.y())/correctionFactor,0,true);
1159  }
1160  }
1161  ((QApplication*)G4Qt::getInstance ())->processEvents();
1162  }
1163  }
1164  fWindow->setMouseTracking(false);
1165 
1166 }
1167 
1168 
1169 void G4OpenGLQtViewer::G4MouseDoubleClickEvent()
1170 {
1171  fWindow->setMouseTracking(true);
1172 }
1173 
1174 
1182 void G4OpenGLQtViewer::G4MouseMoveEvent(QMouseEvent *evnt)
1183 {
1184 
1185  Qt::MouseButtons mButtons = evnt->buttons();
1186 
1187  updateKeyModifierState(evnt->modifiers());
1188 
1189  if (fAutoMove) {
1190  return;
1191  }
1192 
1193  fLastPos3 = fLastPos2;
1194  fLastPos2 = fLastPos1;
1195  fLastPos1 = QPoint(evnt->x(), evnt->y());
1196 
1197  int deltaX = fLastPos2.x()-fLastPos1.x();
1198  int deltaY = fLastPos2.y()-fLastPos1.y();
1199 
1200  bool rotate = false;
1201  bool move = false;
1202  if (fUiQt != NULL) {
1203  if (fUiQt->IsIconRotateSelected()) { // rotate
1204  rotate = true;
1205  } else if (fUiQt->IsIconMoveSelected()) { // move
1206  move = true;
1207  }
1208  } else {
1209  rotate = true;
1210  }
1211  if (rotate) { // rotate
1212  if (mButtons & Qt::LeftButton) {
1213  if (fNoKeyPress) {
1214  rotateQtScene(((float)deltaX),((float)deltaY));
1215  } else if (fAltKeyPress) {
1216  rotateQtSceneToggle(((float)deltaX),((float)deltaY));
1217  } else if (fShiftKeyPress) {
1218  unsigned int sizeWin;
1219  sizeWin = getWinWidth();
1220  if (getWinHeight() < getWinWidth()) {
1221  sizeWin = getWinHeight();
1222  }
1223 
1224  // L.Garnier : 08/2010 100 is the good value, but don't ask me why !
1225  float factor = ((float)100/(float)sizeWin) ;
1226  moveScene(-(float)deltaX*factor,-(float)deltaY*factor,0,false);
1227  } else if (fControlKeyPress) {
1228  fVP.SetZoomFactor(fVP.GetZoomFactor()*(1+((float)deltaY)));
1229  }
1230  }
1231  } else if (move) { // move
1232  if (mButtons & Qt::LeftButton) {
1233  moveScene(-(float)deltaX,-(float)deltaY,0,true);
1234  }
1235  }
1236 
1237  fLastEventTime->start();
1238 }
1239 
1240 
1248 void G4OpenGLQtViewer::moveScene(float dx,float dy, float dz,bool mouseMove)
1249 {
1250  if (fHoldMoveEvent)
1251  return;
1252  fHoldMoveEvent = true;
1253 
1254  G4double coefTrans = 0;
1255  GLdouble coefDepth = 0;
1256  if(mouseMove) {
1257  coefTrans = ((G4double)getSceneNearWidth())/((G4double)getWinWidth());
1258  if (getWinHeight() <getWinWidth()) {
1259  coefTrans = ((G4double)getSceneNearWidth())/((G4double)getWinHeight());
1260  }
1261  } else {
1262  coefTrans = getSceneNearWidth()*fPan_sens;
1263  coefDepth = getSceneDepth()*fDeltaDepth;
1264  }
1265  fVP.IncrementPan(-dx*coefTrans,dy*coefTrans,dz*coefDepth);
1266 
1267  updateQWidget();
1268  if (fAutoMove)
1269  ((QApplication*)G4Qt::getInstance ())->processEvents();
1270 
1271  fHoldMoveEvent = false;
1272 }
1273 
1274 
1280 void G4OpenGLQtViewer::rotateQtScene(float dx, float dy)
1281 {
1282  if (fHoldRotateEvent)
1283  return;
1284  fHoldRotateEvent = true;
1285 
1286  rotateScene(dx,dy);
1287 
1288  updateQWidget();
1289 
1290  fHoldRotateEvent = false;
1291 }
1292 
1298 void G4OpenGLQtViewer::rotateQtSceneToggle(float dx, float dy)
1299 {
1300  if (fHoldRotateEvent)
1301  return;
1302  fHoldRotateEvent = true;
1303 
1304  rotateSceneToggle(dx,dy);
1305 
1306  updateQWidget();
1307 
1308  fHoldRotateEvent = false;
1309 }
1310 
1311 
1312 
1313 
1314 
1319 void G4OpenGLQtViewer::rescaleImage(
1320  int /* aWidth */
1321 ,int /* aHeight */
1322 ){
1323  // GLfloat* feedback_buffer;
1324  // GLint returned;
1325  // FILE* file;
1326 
1327  // feedback_buffer = new GLfloat[size];
1328  // glFeedbackBuffer (size, GL_3D_COLOR, feedback_buffer);
1329  // glRenderMode (GL_FEEDBACK);
1330 
1331  // DrawView();
1332  // returned = glRenderMode (GL_RENDER);
1333 
1334 }
1335 
1336 
1337 
1344 bool G4OpenGLQtViewer::printPDF (
1345  const std::string aFilename
1346  ,int aInColor
1347  ,QImage aImage
1348 )
1349 {
1350 
1351  QPrinter printer;
1352  // printer.setPageSize(pageSize);
1353 
1354  // FIXME : L. Garnier 4/12/07
1355  // This is not working, it does nothing. Image is staying in color mode
1356  // So I have desactivate the B/W button in GUI
1357  if ((!aImage.isGrayscale ()) &&(aInColor ==1 )) {
1358  aImage = aImage.convertToFormat ( aImage.format(), Qt::MonoOnly);
1359  }
1360 
1361 
1362  if (aFilename.substr(aFilename.size()-3) == ".ps") {
1363 #if QT_VERSION > 0x040200
1364  printer.setOutputFormat(QPrinter::PostScriptFormat);
1365 #endif
1366  } else {
1367 #if QT_VERSION > 0x040100
1368  printer.setOutputFormat(QPrinter::PdfFormat);
1369 #endif
1370  }
1371 #if QT_VERSION > 0x040100
1372  printer.setOutputFileName(QString(aFilename.c_str()));
1373 #endif
1374  // printer.setFullPage ( true);
1375  QPainter paint(&printer);
1376  paint.drawImage (0,0,aImage);
1377  paint.end();
1378  return true;
1379 }
1380 
1381 
1382 void G4OpenGLQtViewer::G4wheelEvent (QWheelEvent * evnt)
1383 {
1384  fVP.SetZoomFactor(fVP.GetZoomFactor()+(fVP.GetZoomFactor()*(evnt->delta())/1200));
1385  updateQWidget();
1386 }
1387 
1388 
1389 void G4OpenGLQtViewer::G4keyPressEvent (QKeyEvent * evnt)
1390 {
1391  if (fHoldKeyEvent)
1392  return;
1393 
1394  fHoldKeyEvent = true;
1395 
1396 
1397  // with no modifiers
1398  updateKeyModifierState(evnt->modifiers());
1399  if ((fNoKeyPress) || (evnt->modifiers() == Qt::KeypadModifier )) {
1400  if (evnt->key() == Qt::Key_Down) { // go down
1401  moveScene(0,1,0,false);
1402  }
1403  else if (evnt->key() == Qt::Key_Up) { // go up
1404  moveScene(0,-1,0,false);
1405  }
1406  if (evnt->key() == Qt::Key_Left) { // go left
1407  moveScene(-1,0,0,false);
1408  }
1409  else if (evnt->key() == Qt::Key_Right) { // go right
1410  moveScene(1,0,0,false);
1411  }
1412  if (evnt->key() == Qt::Key_Minus) { // go backward
1413  moveScene(0,0,1,false);
1414  }
1415  else if (evnt->key() == Qt::Key_Plus) { // go forward
1416  moveScene(0,0,-1,false);
1417  }
1418 
1419  // escaped from full screen
1420  if (evnt->key() == Qt::Key_Escape) {
1421  toggleFullScreen(false);
1422  }
1423  }
1424  // several case here : If return is pressed, in every case -> display the movie parameters dialog
1425  // If one parameter is wrong -> put it in red (only save filenam could be wrong..)
1426  // If encoder not found-> does nothing.Only display a message in status box
1427  // If all ok-> generate parameter file
1428  // If ok -> put encoder button enabled
1429 
1430  if ((evnt->key() == Qt::Key_Return) || (evnt->key() == Qt::Key_Enter)){ // end of video
1431  stopVideo();
1432  }
1433  if (evnt->key() == Qt::Key_Space){ // start/pause of video
1434  startPauseVideo();
1435  }
1436 
1437  // H : Return Home view
1438  if (evnt->key() == Qt::Key_H){ // go Home
1439  ResetView();
1440 
1441  updateQWidget();
1442  }
1443 
1444  // Shift Modifier
1445  if (fShiftKeyPress) {
1446  if (evnt->key() == Qt::Key_Down) { // rotate phi
1447  rotateQtScene(0,-fRot_sens);
1448  }
1449  else if (evnt->key() == Qt::Key_Up) { // rotate phi
1450  rotateQtScene(0,fRot_sens);
1451  }
1452  if (evnt->key() == Qt::Key_Left) { // rotate theta
1453  rotateQtScene(fRot_sens,0);
1454  }
1455  else if (evnt->key() == Qt::Key_Right) { // rotate theta
1456  rotateQtScene(-fRot_sens,0);
1457  }
1458  if (evnt->key() == Qt::Key_Plus) { // go forward ("Plus" imply
1459  // "Shift" on Mac French keyboard
1460  moveScene(0,0,-1,false);
1461  }
1462 
1463  // Alt Modifier
1464  }
1465  if ((fAltKeyPress)) {
1466  if (evnt->key() == Qt::Key_Down) { // rotate phi
1467  rotateQtSceneToggle(0,-fRot_sens);
1468  }
1469  else if (evnt->key() == Qt::Key_Up) { // rotate phi
1470  rotateQtSceneToggle(0,fRot_sens);
1471  }
1472  if (evnt->key() == Qt::Key_Left) { // rotate theta
1473  rotateQtSceneToggle(fRot_sens,0);
1474  }
1475  else if (evnt->key() == Qt::Key_Right) { // rotate theta
1476  rotateQtSceneToggle(-fRot_sens,0);
1477  }
1478 
1479  // Rotatio +/-
1480  if (evnt->key() == Qt::Key_Plus) {
1481  fRot_sens = fRot_sens/0.7;
1482  G4cout << "Auto-rotation set to : " << fRot_sens << G4endl;
1483  }
1484  else if (evnt->key() == Qt::Key_Minus) {
1485  fRot_sens = fRot_sens*0.7;
1486  G4cout << "Auto-rotation set to : " << fRot_sens << G4endl;
1487  }
1488 
1489  // Control Modifier OR Command on MAC
1490  }
1491  if ((fControlKeyPress)) {
1492  if (evnt->key() == Qt::Key_Plus) {
1493  fVP.SetZoomFactor(fVP.GetZoomFactor()*(1+fDeltaZoom));
1494  updateQWidget();
1495  }
1496  else if (evnt->key() == Qt::Key_Minus) {
1497  fVP.SetZoomFactor(fVP.GetZoomFactor()*(1-fDeltaZoom));
1498  updateQWidget();
1499  }
1500  }
1501 
1502  fHoldKeyEvent = false;
1503 }
1504 
1505 
1506 void G4OpenGLQtViewer::updateKeyModifierState(const Qt::KeyboardModifiers& modifier) {
1507  // Check Qt Versions for META Keys
1508 
1509  fNoKeyPress = true;
1510  fAltKeyPress = false;
1511  fShiftKeyPress = false;
1512  fControlKeyPress = false;
1513 
1514  if (modifier & Qt::AltModifier ) {
1515  fAltKeyPress = true;
1516  fNoKeyPress = false;
1517  }
1518  if (modifier & Qt::ShiftModifier ) {
1519  fShiftKeyPress = true;
1520  fNoKeyPress = false;
1521  }
1522  if (modifier & Qt::ControlModifier ) {
1523  fControlKeyPress = true;
1524  fNoKeyPress = false;
1525  }
1526 }
1527 
1528 
1531 void G4OpenGLQtViewer::stopVideo() {
1532 
1533  // if encoder parameter is wrong, display parameters dialog and return
1534  if (!fMovieParametersDialog) {
1535  showMovieParametersDialog();
1536  }
1537  setRecordingStatus(STOP);
1538 
1539  if (fRecordFrameNumber >0) {
1540  // check parameters if they were modified (Re APPLY them...)
1541  if (!(fMovieParametersDialog->checkEncoderSwParameters())) {
1542  setRecordingStatus(BAD_ENCODER);
1543  } else if (!(fMovieParametersDialog->checkSaveFileNameParameters())) {
1544  setRecordingStatus(BAD_OUTPUT);
1545  }
1546  } else {
1547  resetRecording();
1548  setRecordingInfos("No frame to encode.");
1549  }
1550 }
1551 
1554 void G4OpenGLQtViewer::saveVideo() {
1555 
1556  // if encoder parameter is wrong, display parameters dialog and return
1557  if (!fMovieParametersDialog) {
1558  showMovieParametersDialog();
1559  }
1560 
1561  fMovieParametersDialog->checkEncoderSwParameters();
1562  fMovieParametersDialog->checkSaveFileNameParameters();
1563 
1564  if (fRecordingStep == STOP) {
1565  setRecordingStatus(SAVE);
1566  generateMpegEncoderParameters();
1567  encodeVideo();
1568  }
1569 }
1570 
1571 
1574 void G4OpenGLQtViewer::startPauseVideo() {
1575 
1576  // first time, if temp parameter is wrong, display parameters dialog and return
1577 
1578  if ( fRecordingStep == WAIT) {
1579  if ( fRecordFrameNumber == 0) {
1580  if (getTempFolderPath() == "") { // BAD_OUTPUT
1581  showMovieParametersDialog();
1582  setRecordingInfos("You should specified the temp folder in order to make movie");
1583  return;
1584  } else {
1585  // remove temp folder if it was create
1586  QString tmp = removeTempFolder();
1587  if (tmp !="") {
1588  setRecordingInfos(tmp);
1589  return;
1590  }
1591  tmp = createTempFolder();
1592  if (tmp != "") {
1593  setRecordingInfos("Can't create temp folder."+tmp);
1594  return;
1595  }
1596  }
1597  }
1598  }
1599  if (fRecordingStep == WAIT) {
1600  setRecordingStatus(START);
1601  } else if (fRecordingStep == START) {
1602  setRecordingStatus(PAUSE);
1603  } else if (fRecordingStep == PAUSE) {
1604  setRecordingStatus(CONTINUE);
1605  } else if (fRecordingStep == CONTINUE) {
1606  setRecordingStatus(PAUSE);
1607  }
1608 }
1609 
1610 void G4OpenGLQtViewer::setRecordingStatus(RECORDING_STEP step) {
1611 
1612  fRecordingStep = step;
1613  displayRecordingStatus();
1614 }
1615 
1616 
1617 void G4OpenGLQtViewer::displayRecordingStatus() {
1618 
1619  QString txtStatus = "";
1620  if (fRecordingStep == WAIT) {
1621  txtStatus = "Waiting to start...";
1622  fRecordFrameNumber = 0; // reset the frame number
1623  } else if (fRecordingStep == START) {
1624  txtStatus = "Start Recording...";
1625  } else if (fRecordingStep == PAUSE) {
1626  txtStatus = "Pause Recording...";
1627  } else if (fRecordingStep == CONTINUE) {
1628  txtStatus = "Continue Recording...";
1629  } else if (fRecordingStep == STOP) {
1630  txtStatus = "Stop Recording...";
1631  } else if (fRecordingStep == READY_TO_ENCODE) {
1632  txtStatus = "Ready to Encode...";
1633  } else if (fRecordingStep == ENCODING) {
1634  txtStatus = "Encoding...";
1635  } else if (fRecordingStep == FAILED) {
1636  txtStatus = "Failed to encode...";
1637  } else if ((fRecordingStep == BAD_ENCODER)
1638  || (fRecordingStep == BAD_OUTPUT)
1639  || (fRecordingStep == BAD_TMP)) {
1640  txtStatus = "Correct above errors first";
1641  } else if (fRecordingStep == SUCCESS) {
1642  txtStatus = "File encoded successfully";
1643  } else {
1644  }
1645 
1646  if (fMovieParametersDialog) {
1647  fMovieParametersDialog->setRecordingStatus(txtStatus);
1648  } else {
1649  G4cout << txtStatus.toStdString().c_str() << G4endl;
1650  }
1651  setRecordingInfos("");
1652 }
1653 
1654 
1655 void G4OpenGLQtViewer::setRecordingInfos(const QString& txt) {
1656  if (fMovieParametersDialog) {
1657  fMovieParametersDialog->setRecordingInfos(txt);
1658  } else {
1659  G4cout << txt.toStdString().c_str() << G4endl;
1660  }
1661 }
1662 
1665 void G4OpenGLQtViewer::initMovieParameters() {
1666  //init encoder
1667 
1668  //look for encoderPath
1669  fProcess = new QProcess();
1670 
1671  QObject ::connect(fProcess,SIGNAL(finished ( int)),
1672  this,SLOT(processLookForFinished()));
1673  fProcess->setReadChannelMode(QProcess::MergedChannels);
1674  fProcess->start ("which ppmtompeg");
1675 
1676 }
1677 
1680 QString G4OpenGLQtViewer::getEncoderPath() {
1681  return fEncoderPath;
1682 }
1683 
1684 
1689 QString G4OpenGLQtViewer::setEncoderPath(QString path) {
1690  if (path == "") {
1691  return "File does not exist";
1692  }
1693 
1694  path = QDir::cleanPath(path);
1695  QFileInfo *f = new QFileInfo(path);
1696  if (!f->exists()) {
1697  return "File does not exist";
1698  } else if (f->isDir()) {
1699  return "This is a directory";
1700  } else if (!f->isExecutable()) {
1701  return "File exist but is not executable";
1702  } else if (!f->isFile()) {
1703  return "This is not a file";
1704  }
1705  fEncoderPath = path;
1706 
1707  if (fRecordingStep == BAD_ENCODER) {
1708  setRecordingStatus(STOP);
1709  }
1710  return "";
1711 }
1712 
1713 
1714 bool G4OpenGLQtViewer::isRecording(){
1715  if ((fRecordingStep == START) || (fRecordingStep == CONTINUE)) {
1716  return true;
1717  }
1718  return false;
1719 }
1720 
1721 bool G4OpenGLQtViewer::isPaused(){
1722  if (fRecordingStep == PAUSE) {
1723  return true;
1724  }
1725  return false;
1726 }
1727 
1728 bool G4OpenGLQtViewer::isEncoding(){
1729  if (fRecordingStep == ENCODING) {
1730  return true;
1731  }
1732  return false;
1733 }
1734 
1735 bool G4OpenGLQtViewer::isWaiting(){
1736  if (fRecordingStep == WAIT) {
1737  return true;
1738  }
1739  return false;
1740 }
1741 
1742 bool G4OpenGLQtViewer::isStopped(){
1743  if (fRecordingStep == STOP) {
1744  return true;
1745  }
1746  return false;
1747 }
1748 
1749 bool G4OpenGLQtViewer::isFailed(){
1750  if (fRecordingStep == FAILED) {
1751  return true;
1752  }
1753  return false;
1754 }
1755 
1756 bool G4OpenGLQtViewer::isSuccess(){
1757  if (fRecordingStep == SUCCESS) {
1758  return true;
1759  }
1760  return false;
1761 }
1762 
1763 bool G4OpenGLQtViewer::isBadEncoder(){
1764  if (fRecordingStep == BAD_ENCODER) {
1765  return true;
1766  }
1767  return false;
1768 }
1769 bool G4OpenGLQtViewer::isBadTmp(){
1770  if (fRecordingStep == BAD_TMP) {
1771  return true;
1772  }
1773  return false;
1774 }
1775 bool G4OpenGLQtViewer::isBadOutput(){
1776  if (fRecordingStep == BAD_OUTPUT) {
1777  return true;
1778  }
1779  return false;
1780 }
1781 
1782 void G4OpenGLQtViewer::setBadEncoder(){
1783  fRecordingStep = BAD_ENCODER;
1784  displayRecordingStatus();
1785 }
1786 void G4OpenGLQtViewer::setBadTmp(){
1787  fRecordingStep = BAD_TMP;
1788  displayRecordingStatus();
1789 }
1790 void G4OpenGLQtViewer::setBadOutput(){
1791  fRecordingStep = BAD_OUTPUT;
1792  displayRecordingStatus();
1793 }
1794 
1795 void G4OpenGLQtViewer::setWaiting(){
1796  fRecordingStep = WAIT;
1797  displayRecordingStatus();
1798 }
1799 
1800 
1801 bool G4OpenGLQtViewer::isReadyToEncode(){
1802  if (fRecordingStep == READY_TO_ENCODE) {
1803  return true;
1804  }
1805  return false;
1806 }
1807 
1808 void G4OpenGLQtViewer::resetRecording() {
1809  setRecordingStatus(WAIT);
1810 }
1811 
1816 QString G4OpenGLQtViewer::setTempFolderPath(QString path) {
1817 
1818  if (path == "") {
1819  return "Path does not exist";
1820  }
1821  path = QDir::cleanPath(path);
1822  QFileInfo *d = new QFileInfo(path);
1823  if (!d->exists()) {
1824  return "Path does not exist";
1825  } else if (!d->isDir()) {
1826  return "This is not a directory";
1827  } else if (!d->isReadable()) {
1828  return path +" is read protected";
1829  } else if (!d->isWritable()) {
1830  return path +" is write protected";
1831  }
1832 
1833  if (fRecordingStep == BAD_TMP) {
1834  setRecordingStatus(WAIT);
1835  }
1836  fTempFolderPath = path;
1837  return "";
1838 }
1839 
1842 QString G4OpenGLQtViewer::getTempFolderPath() {
1843  return fTempFolderPath;
1844 }
1845 
1850 QString G4OpenGLQtViewer::setSaveFileName(QString path) {
1851 
1852  if (path == "") {
1853  return "Path does not exist";
1854  }
1855 
1856  QFileInfo *file = new QFileInfo(path);
1857  QDir dir = file->dir();
1858  path = QDir::cleanPath(path);
1859  if (file->exists()) {
1860  return "File already exist, please choose a new one";
1861  } else if (!dir.exists()) {
1862  return "Dir does not exist";
1863  } else if (!dir.isReadable()) {
1864  return path +" is read protected";
1865  }
1866 
1867  if (fRecordingStep == BAD_OUTPUT) {
1868  setRecordingStatus(STOP);
1869  }
1870  fSaveFileName = path;
1871  return "";
1872 }
1873 
1876 QString G4OpenGLQtViewer::getSaveFileName() {
1877  return fSaveFileName ;
1878 }
1879 
1884 QString G4OpenGLQtViewer::createTempFolder() {
1885  fMovieTempFolderPath = "";
1886  //check
1887  QString tmp = setTempFolderPath(fTempFolderPath);
1888  if (tmp != "") {
1889  return tmp;
1890  }
1891  QString sep = QString(QDir::separator());
1892  QString path = sep+"QtMovie_"+QDateTime::currentDateTime ().toString("dd-MM-yyyy_hh-mm-ss")+sep;
1893  QDir *d = new QDir(QDir::cleanPath(fTempFolderPath));
1894  // check if it is already present
1895  if (d->exists(path)) {
1896  return "Folder "+path+" already exists.Please remove it first";
1897  }
1898  if (d->mkdir(fTempFolderPath+path)) {
1899  fMovieTempFolderPath = fTempFolderPath+path;
1900  return "";
1901  }
1902  return "Can't create "+fTempFolderPath+path;
1903 }
1904 
1907 QString G4OpenGLQtViewer::removeTempFolder() {
1908  // remove files in Qt_temp folder
1909  if (fMovieTempFolderPath == "") {
1910  return "";
1911  }
1912  QDir *d = new QDir(QDir::cleanPath(fMovieTempFolderPath));
1913  if (!d->exists()) {
1914  return ""; // already remove
1915  }
1916 
1917  d->setFilter( QDir::Files );
1918  QStringList subDirList = d->entryList();
1919  int res = true;
1920  QString error = "";
1921  for (QStringList::ConstIterator it = subDirList.begin() ;(it != subDirList.end()) ; it++) {
1922  const QString currentFile = *it;
1923  if (!d->remove(currentFile)) {
1924  res = false;
1925  QString file = fMovieTempFolderPath+currentFile;
1926  error +="Removing file failed : "+file;
1927  } else {
1928  }
1929  }
1930  if (res) {
1931  if (d->rmdir(fMovieTempFolderPath)) {
1932  fMovieTempFolderPath = "";
1933  return "";
1934  } else {
1935  return "Dir "+fMovieTempFolderPath+" should be empty, but could not remove it";
1936  }
1937 
1938  }
1939  return "Could not remove "+fMovieTempFolderPath+" because of the following errors :"+error;
1940 }
1941 
1942 
1943 
1944 bool G4OpenGLQtViewer::hasPendingEvents () {
1945  return ((QApplication*)G4Qt::getInstance ())->hasPendingEvents ();
1946 }
1947 
1948 bool G4OpenGLQtViewer::generateMpegEncoderParameters () {
1949 
1950  // save the parameter file
1951  FILE* fp;
1952  fp = fopen (QString(fMovieTempFolderPath+fParameterFileName).toStdString().c_str(), "w");
1953 
1954  if (fp == NULL) {
1955  setRecordingInfos("Generation of parameter file failed");
1956  return false;
1957  }
1958 
1959  fprintf (fp,"# Pattern affects speed, quality and compression. See the User's Guide\n");
1960  fprintf (fp,"# for more info.\n");
1961  fprintf (fp,"\n");
1962  fprintf (fp,"PATTERN IBBPBBPBBPBBPBBP\n");
1963  fprintf (fp,"OUTPUT %s\n",getSaveFileName().toStdString().c_str());
1964  fprintf (fp,"\n");
1965  fprintf (fp,"# You must specify the type of the input files. The choices are:\n");
1966  fprintf (fp,"# YUV, PPM, JMOVIE, Y, JPEG, PNM\n");
1967  fprintf (fp,"# (must be upper case)\n");
1968  fprintf (fp,"#\n");
1969  fprintf (fp,"BASE_FILE_FORMAT PPM\n");
1970  fprintf (fp,"\n");
1971  fprintf (fp,"#\n");
1972  fprintf (fp,"# if YUV format (or using parallel version), must provide width and height\n");
1973  fprintf (fp,"# YUV_SIZE widthxheight\n");
1974  fprintf (fp,"# this option is ignored if BASE_FILE_FORMAT is not YUV and you're running\n");
1975  fprintf (fp,"# on just one machine\n");
1976  fprintf (fp,"#\n");
1977  fprintf (fp,"YUV_SIZE 352x240\n");
1978  fprintf (fp,"\n");
1979  fprintf (fp,"# If you are using YUV, there are different supported file formats.\n");
1980  fprintf (fp,"# EYUV or UCB are the same as previous versions of this encoder.\n");
1981  fprintf (fp,"# (All the Y's, then U's then V's, in 4:2:0 subsampling.)\n");
1982  fprintf (fp,"# Other formats, such as Abekas, Phillips, or a general format are\n");
1983  fprintf (fp,"# permissible, the general format is a string of Y's, U's, and V's\n");
1984  fprintf (fp,"# to specify the file order.\n");
1985  fprintf (fp,"\n");
1986  fprintf (fp,"INPUT_FORMAT UCB\n");
1987  fprintf (fp,"\n");
1988  fprintf (fp,"# the conversion statement\n");
1989  fprintf (fp,"#\n");
1990  fprintf (fp,"# Each occurrence of '*' will be replaced by the input file\n");
1991  fprintf (fp,"#\n");
1992  fprintf (fp,"# e.g., if you have a bunch of GIF files, then this might be:\n");
1993  fprintf (fp,"# INPUT_CONVERT giftoppm *\n");
1994  fprintf (fp,"#\n");
1995  fprintf (fp,"# e.g., if you have a bunch of files like a.Y a.U a.V, etc., then:\n");
1996  fprintf (fp,"# INPUT_CONVERT cat *.Y *.U *.V\n");
1997  fprintf (fp,"#\n");
1998  fprintf (fp,"# e.g., if you are grabbing from laser disc you might have something like\n");
1999  fprintf (fp,"# INPUT_CONVERT goto frame *; grabppm\n");
2000  fprintf (fp,"# 'INPUT_CONVERT *' means the files are already in the base file format\n");
2001  fprintf (fp,"#\n");
2002  fprintf (fp,"INPUT_CONVERT * \n");
2003  fprintf (fp,"\n");
2004  fprintf (fp,"# number of frames in a GOP.\n");
2005  fprintf (fp,"#\n");
2006  fprintf (fp,"# since each GOP must have at least one I-frame, the encoder will find the\n");
2007  fprintf (fp,"# the first I-frame after GOP_SIZE frames to start the next GOP\n");
2008  fprintf (fp,"#\n");
2009  fprintf (fp,"# later, will add more flexible GOP signalling\n");
2010  fprintf (fp,"#\n");
2011  fprintf (fp,"GOP_SIZE 16\n");
2012  fprintf (fp,"\n");
2013  fprintf (fp,"# number of slices in a frame\n");
2014  fprintf (fp,"#\n");
2015  fprintf (fp,"# 1 is a good number. another possibility is the number of macroblock rows\n");
2016  fprintf (fp,"# (which is the height divided by 16)\n");
2017  fprintf (fp,"#\n");
2018  fprintf (fp,"SLICES_PER_FRAME 1\n");
2019  fprintf (fp,"\n");
2020  fprintf (fp,"# directory to get all input files from (makes this file easier to read)\n");
2021  fprintf (fp,"INPUT_DIR %s\n",fMovieTempFolderPath.toStdString().c_str());
2022  fprintf (fp,"\n");
2023  fprintf (fp,"# There are a bunch of ways to specify the input files.\n");
2024  fprintf (fp,"# from a simple one-per-line listing, to the following \n");
2025  fprintf (fp,"# way of numbering them. See the manual for more information.\n");
2026  fprintf (fp,"INPUT\n");
2027  fprintf (fp,"# '*' is replaced by the numbers 01, 02, 03, 04\n");
2028  fprintf (fp,"# if I instead do [01-11], it would be 01, 02, ..., 09, 10, 11\n");
2029  fprintf (fp,"# if I instead do [1-11], it would be 1, 2, 3, ..., 9, 10, 11\n");
2030  fprintf (fp,"# if I instead do [1-11+3], it would be 1, 4, 7, 10\n");
2031  fprintf (fp,"# the program assumes none of your input files has a name ending in ']'\n");
2032  fprintf (fp,"# if you do, too bad!!!\n");
2033  fprintf (fp,"#\n");
2034  fprintf (fp,"#\n");
2035  fprintf (fp,"Test*.ppm [0-%d]\n",fRecordFrameNumber-1);
2036  fprintf (fp,"# can have more files here if you want...there is no limit on the number\n");
2037  fprintf (fp,"# of files\n");
2038  fprintf (fp,"END_INPUT\n");
2039  fprintf (fp,"\n");
2040  fprintf (fp,"\n");
2041  fprintf (fp,"\n");
2042  fprintf (fp,"# Many of the remaining options have to do with the motion search and qscale\n");
2043  fprintf (fp,"\n");
2044  fprintf (fp,"# FULL or HALF -- must be upper case\n");
2045  fprintf (fp,"# Should be FULL for computer generated images\n");
2046  fprintf (fp,"PIXEL FULL\n");
2047  fprintf (fp,"\n");
2048  fprintf (fp,"# means +/- this many pixels for both P and B frame searches\n");
2049  fprintf (fp,"# specify two numbers if you wish to serc different ranges in the two.\n");
2050  fprintf (fp,"RANGE 10\n");
2051  fprintf (fp,"\n");
2052  fprintf (fp,"# The two search algorithm parameters below mostly affect speed,\n");
2053  fprintf (fp,"# with some affect on compression and almost none on quality.\n");
2054  fprintf (fp,"\n");
2055  fprintf (fp,"# this must be one of {EXHAUSTIVE, SUBSAMPLE, LOGARITHMIC}\n");
2056  fprintf (fp,"PSEARCH_ALG LOGARITHMIC\n");
2057  fprintf (fp,"\n");
2058  fprintf (fp,"# this must be one of {SIMPLE, CROSS2, EXHAUSTIVE}\n");
2059  fprintf (fp,"#\n");
2060  fprintf (fp,"# note that EXHAUSTIVE is really, really, really slow\n");
2061  fprintf (fp,"#\n");
2062  fprintf (fp,"BSEARCH_ALG SIMPLE\n");
2063  fprintf (fp,"\n");
2064  fprintf (fp,"#\n");
2065  fprintf (fp,"# these specify the q-scale for I, P, and B frames\n");
2066  fprintf (fp,"# (values must be between 1 and 31)\n");
2067  fprintf (fp,"# These are the Qscale values for the entire frame in variable bit-rate\n");
2068  fprintf (fp,"# mode, and starting points (but not important) for constant bit rate\n");
2069  fprintf (fp,"#\n");
2070  fprintf (fp,"\n");
2071  fprintf (fp,"# Qscale (Quantization scale) affects quality and compression,\n");
2072  fprintf (fp,"# but has very little effect on speed.\n");
2073  fprintf (fp,"\n");
2074  fprintf (fp,"IQSCALE 4\n");
2075  fprintf (fp,"PQSCALE 5\n");
2076  fprintf (fp,"BQSCALE 12\n");
2077  fprintf (fp,"\n");
2078  fprintf (fp,"# this must be ORIGINAL or DECODED\n");
2079  fprintf (fp,"REFERENCE_FRAME ORIGINAL\n");
2080  fprintf (fp,"\n");
2081  fprintf (fp,"# for parallel parameters see parallel.param in the exmaples subdirectory\n");
2082  fprintf (fp,"\n");
2083  fprintf (fp,"# if you want constant bit-rate mode, specify it as follows (number is bits/sec):\n");
2084  fprintf (fp,"#BIT_RATE 1000000\n");
2085  fprintf (fp,"\n");
2086  fprintf (fp,"# To specify the buffer size (327680 is default, measused in bits, for 16bit words)\n");
2087  fprintf (fp,"BUFFER_SIZE 327680\n");
2088  fprintf (fp,"\n");
2089  fprintf (fp,"# The frame rate is the number of frames/second (legal values:\n");
2090  fprintf (fp,"# 23.976, 24, 25, 29.97, 30, 50 ,59.94, 60\n");
2091  fprintf (fp,"FRAME_RATE 30\n");
2092  fprintf (fp,"\n");
2093  fprintf (fp,"# There are many more options, see the users manual for examples....\n");
2094  fprintf (fp,"# ASPECT_RATIO, USER_DATA, GAMMA, IQTABLE, etc.\n");
2095  fprintf (fp,"\n");
2096  fprintf (fp,"\n");
2097  fclose (fp);
2098 
2099  setRecordingInfos("Parameter file "+fParameterFileName+" generated in "+fMovieTempFolderPath);
2100  setRecordingStatus(READY_TO_ENCODE);
2101  return true;
2102 }
2103 
2104 void G4OpenGLQtViewer::encodeVideo()
2105 {
2106  if ((getEncoderPath() != "") && (getSaveFileName() != "")) {
2107  setRecordingStatus(ENCODING);
2108 
2109  fProcess = new QProcess();
2110 #if QT_VERSION > 0x040100
2111  QObject ::connect(fProcess,SIGNAL(finished ( int,QProcess::ExitStatus)),
2112  this,SLOT(processEncodeFinished()));
2113  QObject ::connect(fProcess,SIGNAL(readyReadStandardOutput ()),
2114  this,SLOT(processEncodeStdout()));
2115 #else
2116  QObject ::connect(fProcess,SIGNAL(finished ( int)),
2117  this,SLOT(processEncodeFinished()));
2118  QObject ::connect(fProcess,SIGNAL(readyReadStandardOutput ()),
2119  this,SLOT(processEncodeStdout()));
2120 #endif
2121  fProcess->setReadChannelMode(QProcess::MergedChannels);
2122  fProcess->start (fEncoderPath, QStringList(fMovieTempFolderPath+fParameterFileName));
2123  }
2124 }
2125 
2126 
2127 // FIXME : does not work on Qt3
2128 void G4OpenGLQtViewer::processEncodeStdout()
2129 {
2130  QString tmp = fProcess->readAllStandardOutput ().data();
2131  int start = tmp.lastIndexOf("ESTIMATED TIME");
2132  tmp = tmp.mid(start,tmp.indexOf("\n",start)-start);
2133  setRecordingInfos(tmp);
2134 }
2135 
2136 
2137 void G4OpenGLQtViewer::processEncodeFinished()
2138 {
2139 
2140  QString txt = "";
2141  txt = getProcessErrorMsg();
2142  if (txt == "") {
2143  setRecordingStatus(SUCCESS);
2144  } else {
2145  setRecordingStatus(FAILED);
2146  }
2147  // setRecordingInfos(txt+removeTempFolder());
2148 }
2149 
2150 
2151 void G4OpenGLQtViewer::processLookForFinished()
2152 {
2153 
2154  QString txt = getProcessErrorMsg();
2155  if (txt != "") {
2156  fEncoderPath = "";
2157  } else {
2158  fEncoderPath = QString(fProcess->readAllStandardOutput ().data()).trimmed();
2159  // if not found, return "not found"
2160  if (fEncoderPath.contains(" ")) {
2161  fEncoderPath = "";
2162  } else if (!fEncoderPath.contains("ppmtompeg")) {
2163  fEncoderPath = "";
2164  }
2165  setEncoderPath(fEncoderPath);
2166  }
2167  // init temp folder
2168  setTempFolderPath(QDir::temp ().absolutePath ());
2169 }
2170 
2171 
2172 QString G4OpenGLQtViewer::getProcessErrorMsg()
2173 {
2174  QString txt = "";
2175  if (fProcess->exitCode() != 0) {
2176  switch (fProcess->error()) {
2177  case QProcess::FailedToStart:
2178  txt = "The process failed to start. Either the invoked program is missing, or you may have insufficient permissions to invoke the program.\n";
2179  break;
2180  case QProcess::Crashed:
2181  txt = "The process crashed some time after starting successfully.\n";
2182  break;
2183  case QProcess::Timedout:
2184  txt = "The last waitFor...() function timed out. The state of QProcess is unchanged, and you can try calling waitFor...() again.\n";
2185  break;
2186  case QProcess::WriteError:
2187  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";
2188  break;
2189  case QProcess::ReadError:
2190  txt = "An error occurred when attempting to read from the process. For example, the process may not be running.\n";
2191  break;
2192  case QProcess::UnknownError:
2193  txt = "An unknown error occurred. This is the default return value of error().\n";
2194  break;
2195  }
2196  }
2197  return txt;
2198 }
2199 
2200 
2201 
2202 
2203 QWidget *G4OpenGLQtViewer::getParentWidget()
2204 {
2205  // launch Qt if not
2206  G4Qt* interactorManager = G4Qt::getInstance ();
2207  // G4UImanager* UI =
2208  // G4UImanager::GetUIpointer();
2209 
2210  bool found = false;
2211 
2212  // create window
2213  if (((QApplication*)interactorManager->GetMainInteractor())) {
2214  // look for the main window
2215  QWidgetList wl = QApplication::allWidgets();
2216  QWidget *widget = NULL;
2217  for (int i=0; i < wl.size(); i++) {
2218  widget = wl.at(i);
2219  if ((found== false) && (widget->inherits("QMainWindow"))) {
2220  fGLWindow = new QDialog(widget,Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowMinMaxButtonsHint);
2221  found = true;
2222  }
2223  }
2224 
2225  if (found==false) {
2226 #ifdef G4DEBUG_VIS_OGL
2227  printf("G4OpenGLQtViewer::CreateMainWindow case Qapp exist, but not found\n");
2228 #endif
2229  fGLWindow = new QDialog();
2230  }
2231  } else {
2232 #ifdef G4DEBUG_VIS_OGL
2233  printf("G4OpenGLQtViewer::CreateMainWindow case Qapp exist\n");
2234 #endif
2235  fGLWindow = new QDialog();
2236 #ifdef G4DEBUG_VIS_OGL
2237  printf("G4OpenGLQtViewer::GetParentWidget fGLWindow\n");
2238 #endif
2239  }
2240  if (found) {
2241  return fGLWindow;
2242  } else {
2243  return NULL;
2244  }
2245 }
2246 
2247 
2248 void G4OpenGLQtViewer::initSceneTreeComponent(){
2249 
2250  fSceneTreeWidget = new QWidget();
2251  fSceneTreeWidget->setLayout (new QVBoxLayout());
2252 
2253  if (fUISceneTreeComponentsTBWidget != NULL) {
2254  fUISceneTreeComponentsTBWidget->addTab(fSceneTreeWidget,QString(GetName().data()));
2255  }
2256 
2257  QLayout* layoutSceneTreeComponentsTBWidget = fSceneTreeWidget->layout();
2258 
2259 
2260  fSceneTreeComponentTreeWidget = new QTreeWidget();
2261  fSceneTreeComponentTreeWidget->setSelectionMode(QAbstractItemView::SingleSelection);
2262  fSceneTreeComponentTreeWidget->setHeaderLabel ("Scene tree : "+QString(GetName().data()));
2263  fSceneTreeComponentTreeWidget->setColumnHidden (1,true); // copy number
2264  fSceneTreeComponentTreeWidget->setColumnHidden (2,true); // PO index
2265  fSceneTreeComponentTreeWidget->setColumnHidden (3,true); // Informations
2266  // data(0) : POindex
2267  // data(1) : copy number
2268  // data(2) : g4color
2269 
2270  layoutSceneTreeComponentsTBWidget->addWidget(fSceneTreeComponentTreeWidget);
2271 
2272  connect(fSceneTreeComponentTreeWidget,SIGNAL(itemChanged(QTreeWidgetItem*, int)),SLOT(sceneTreeComponentItemChanged(QTreeWidgetItem*, int)));
2273  connect(fSceneTreeComponentTreeWidget,SIGNAL(itemSelectionChanged ()),SLOT(sceneTreeComponentSelected()));
2274  connect(fSceneTreeComponentTreeWidget,SIGNAL(itemDoubleClicked ( QTreeWidgetItem*, int)),SLOT(changeColorAndTransparency( QTreeWidgetItem*, int)));
2275 
2276 
2277  // Depth slider
2278  QLabel *depth = new QLabel();
2279  depth->setText("Depth :");
2280 
2281  QWidget* depthWidget = new QWidget();
2282  QGroupBox *groupBox = new QGroupBox(tr("Touchables slider"),depthWidget);
2283  QHBoxLayout *groupBoxLayout = new QHBoxLayout(groupBox);
2284 
2285  QLabel *zero = new QLabel();
2286  zero->setText("Show all");
2287  QLabel *one = new QLabel();
2288  one->setText("Hide all");
2289  fSceneTreeDepthSlider = new QSlider ( Qt::Horizontal, groupBox);
2290  fSceneTreeDepthSlider->setMaximum (1000);
2291  fSceneTreeDepthSlider->setMinimum (0);
2292  fSceneTreeDepthSlider->setTickPosition(QSlider::TicksAbove);
2293  groupBoxLayout->addWidget(zero);
2294  groupBoxLayout->addWidget(fSceneTreeDepthSlider);
2295  groupBoxLayout->addWidget(one);
2296 
2297  groupBox->setLayout(groupBoxLayout);
2298  layoutSceneTreeComponentsTBWidget->addWidget(groupBox);
2299 
2300  connect( fSceneTreeDepthSlider, SIGNAL( valueChanged(int) ), this, SLOT( changeDepthInSceneTree(int) ) );
2301 
2302  // Search line
2303  QWidget *helpWidget = new QWidget();
2304  QHBoxLayout *helpLayout = new QHBoxLayout();
2305  QPushButton* select = new QPushButton("select item(s)");
2306  fHelpLine = new QLineEdit();
2307  helpLayout->addWidget(new QLabel("Search :",helpWidget));
2308  helpLayout->addWidget(fHelpLine);
2309  helpLayout->addWidget(select);
2310  helpWidget->setLayout(helpLayout);
2311  layoutSceneTreeComponentsTBWidget->addWidget(helpWidget);
2312 
2313  connect( fHelpLine, SIGNAL( returnPressed () ), this, SLOT(changeSearchSelection()));
2314  connect( select, SIGNAL( clicked () ), this, SLOT(changeSearchSelection()));
2315 
2316 
2317  fTreeItemModels.clear();
2318 
2319  fPVRootNodeCreate = false;
2320 
2321  fMaxPOindexInserted = -1;
2322 }
2323 
2324 
2325 // set the component to check/unchecked, also go into its child
2326 // and set the same status to all his childs
2327 void G4OpenGLQtViewer::setCheckComponent(QTreeWidgetItem* item,bool check)
2328 {
2329  if (item != NULL) {
2330  if (check) {
2331  item->setCheckState(0,Qt::Checked);
2332  } else {
2333  item->setCheckState(0,Qt::Unchecked);
2334  }
2335  updatePositivePoIndexSceneTreeWidgetQuickMap(item->data(0,Qt::UserRole).toInt(),item);
2336  int nChildCount = item->childCount();
2337  for (int i = 0; i < nChildCount; i++) {
2338  setCheckComponent(item->child(i),check);
2339  }
2340  }
2341 }
2342 
2343 
2344 void G4OpenGLQtViewer::DrawText(const G4Text& g4text)
2345 {
2346  if (isGl2psWriting()) {
2347 
2348  G4OpenGLViewer::DrawText(g4text);
2349 
2350  } else {
2351 
2352  if (!fWindow) return;
2353 
2355  G4double size = fSceneHandler.GetMarkerSize(g4text,sizeType);
2356 
2357  QFont font = QFont();
2358  font.setPointSizeF(size);
2359 
2360  G4Point3D position = g4text.GetPosition();
2361 
2362  const G4String& textString = g4text.GetText();
2363  const char* textCString = textString.c_str();
2364 
2365  // Calculate move for centre and right adjustment
2366  QFontMetrics* f = new QFontMetrics (font);
2367  G4double span = f->width(textCString);
2368  G4double xmove = 0., ymove = 0.;
2369  switch (g4text.GetLayout()) {
2370  case G4Text::left: break;
2371  case G4Text::centre: xmove -= span / 2.; break;
2372  case G4Text::right: xmove -= span;
2373  }
2374 
2375  //Add offsets
2376  xmove += g4text.GetXOffset();
2377  ymove += g4text.GetYOffset();
2378 
2379  fWindow->renderText
2380  ((position.x()+(2*xmove)/getWinWidth()),
2381  (position.y()+(2*ymove)/getWinHeight()),
2382  position.z(),
2383  textCString,
2384  font);
2385 
2386  }
2387 }
2388 
2389 
2390 void G4OpenGLQtViewer::ResetView () {
2391  G4OpenGLViewer::ResetView();
2392  fDeltaDepth = 0.01;
2393  fDeltaZoom = 0.05;
2394 }
2395 
2396 
2397 
2398 
2399 void G4OpenGLQtViewer::addPVSceneTreeElement(const G4String& model, G4PhysicalVolumeModel* pPVModel, int currentPOIndex) {
2400 
2401  const QString& modelShortName = getModelShortName(model);
2402 
2403  if (modelShortName == "") {
2404  return ;
2405  }
2406  // try to init it
2407  if (fSceneTreeComponentTreeWidget == NULL) {
2408  initSceneTreeComponent();
2409  }
2410 
2411  // if no UI
2412  if (fSceneTreeComponentTreeWidget == NULL) {
2413  return;
2414  }
2415 
2416  fSceneTreeComponentTreeWidget->blockSignals(true);
2417 
2418  // Create the "volume" node if not
2419  // if (fSceneTreeComponentTreeWidget->topLevelItemCount () == 0) {
2420  if (!fPVRootNodeCreate) {
2421  const G4VisAttributes* visAttr = GetApplicableVisAttributes(pPVModel->GetFullPVPath().at(0).GetPhysicalVolume()->GetLogicalVolume()->GetVisAttributes());
2422  const G4Colour& color = visAttr->GetColour();
2423 
2424  fModelShortNameItem = createTreeWidgetItem(pPVModel->GetFullPVPath(),
2425  modelShortName,
2426  0, // currentPVCopyNb
2427  -1, // currentPVPOIndex
2428  "",
2429  Qt::Checked,
2430  NULL,
2431  color);
2432  fPVRootNodeCreate = true;
2433  }
2434 
2435  bool added = parseAndInsertInSceneTree(fModelShortNameItem,pPVModel,0,modelShortName,0,currentPOIndex);
2436  if (!added) {
2437  }
2438 
2439  fSceneTreeComponentTreeWidget->blockSignals(false);
2440 
2441 }
2442 
2443 
2448 QTreeWidgetItem* G4OpenGLQtViewer::createTreeWidgetItem(
2449  const PVPath& fullPath
2450  ,const QString& name
2451  ,int copyNb
2452  ,int POIndex
2453  ,const QString& logicalName
2454  ,Qt::CheckState state
2455  ,QTreeWidgetItem * parentTreeNode
2456  ,const G4Colour& color
2457 ) {
2458 
2459  // Set depth
2460  if (fullPath.size() > fSceneTreeDepth) {
2461  fSceneTreeDepth = fullPath.size();
2462  // Change slider value
2463  if (fSceneTreeDepthSlider) {
2464  fSceneTreeDepthSlider->setTickInterval(1000/(fSceneTreeDepth+1));
2465  }
2466  }
2467  QTreeWidgetItem * newItem = NULL;
2468  if (parentTreeNode == NULL) {
2469  newItem = new QTreeWidgetItem(fSceneTreeComponentTreeWidget);
2470  } else {
2471  newItem = new QTreeWidgetItem(parentTreeNode);
2472  }
2473 
2474 
2475  newItem->setText(0,name);
2476  newItem->setData(1,Qt::UserRole,copyNb);
2477  newItem->setText(2,QString::number(POIndex));
2478  newItem->setData(0, Qt::UserRole, POIndex);
2479  newItem->setText(3,logicalName);
2480  newItem->setFlags(newItem->flags()|Qt::ItemIsUserCheckable);
2481  newItem->setCheckState(0,state);
2482  updatePositivePoIndexSceneTreeWidgetQuickMap(POIndex,newItem);
2483 
2484  changeQColorForTreeWidgetItem(newItem,QColor((int)(color.GetRed()*255),
2485  (int)(color.GetGreen()*255),
2486  (int)(color.GetBlue()*255),
2487  (int)(color.GetAlpha()*255)));
2488 
2489  // If invisible
2490  if ((state == Qt::Unchecked) && (POIndex == -1)) {
2491  newItem->setForeground (0, QBrush( Qt::gray) );
2492 
2493  // Set a tootip
2494  newItem->setToolTip (0,QString(
2495  "This node exists in the geometry but has not been\n")+
2496  "drawn, perhaps because it has been set invisible. It \n"+
2497  "cannot be made visible with a click on the button.\n"+
2498  "To see it, change the visibility, for example, with \n"+
2499  "/vis/geometry/set/visibility " + logicalName + " 0 true\n"+
2500  "and rebuild the view with /vis/viewer/rebuild.\n"+
2501  "Click here will only show/hide all child components");
2502  }
2503 
2504  // special case: if alpha=0, it is a totally transparent objet,
2505  // then, do not redraw it
2506  if (color.GetAlpha() == 0) {
2507  state = Qt::Unchecked;
2508  newItem->setCheckState(0,state);
2509  updatePositivePoIndexSceneTreeWidgetQuickMap(POIndex,newItem);
2510  }
2511 
2512  fTreeItemModels.insert(std::pair <int, PVPath > (POIndex,fullPath) );
2513 
2514  // Check last status of this item and change if necessary
2515  // open/close/hidden/visible/selected
2516  changeOpenCloseVisibleHiddenSelectedColorSceneTreeElement(newItem);
2517  return newItem;
2518 }
2519 
2520 
2521 //
2522 // Recursive function.
2523 // Try to insert the given item :
2524 // - If not present and last item of the path: insert it and mark it CHECK
2525 // - If not present and NOT last item of the path: insert it and mark it UNCHECKED
2526 // - If already present and name/PO/Transformation identical, then it is a transparent
2527 // object : Change the PO number and transparency
2528 // - If already present and PO different, then it is an unvisible item : Have to
2529 // set it visible
2530 // - else : Create a new element
2531 // @return true if inserted, false if already present
2532 //
2533 bool G4OpenGLQtViewer::parseAndInsertInSceneTree(
2534  QTreeWidgetItem * parentItem
2535  ,G4PhysicalVolumeModel* pPVModel
2536  ,unsigned int fullPathIndex
2537  ,const QString& parentRoot
2538  ,unsigned int currentIndexInTreeSceneHandler
2539  ,int currentPVPOIndex
2540 ) {
2541 
2542  if (parentItem == NULL) {
2543  return false;
2544  }
2545 
2546  const PVPath& fullPath = pPVModel->GetFullPVPath();
2547 
2548  std::ostringstream oss;
2549  oss << fullPath.at(fullPathIndex).GetCopyNo();
2550  std::string currentPVName = G4String(fullPath.at(fullPathIndex).GetPhysicalVolume()->GetName()+" ["+oss.str()+"]").data();
2551 
2552  int currentPVCopyNb = fullPath.at(fullPathIndex).GetCopyNo();
2553 
2554  const G4VisAttributes* visAttr = GetApplicableVisAttributes(fullPath.at(fullPathIndex).GetPhysicalVolume()->GetLogicalVolume()->GetVisAttributes());
2555  const G4Colour& color = visAttr->GetColour();
2556 
2557  // look in all children in order to get if their is already a
2558  // child corresponding:
2559  // - if so, go into this child
2560  // - if not : create it as invisible
2561 
2562  // Realy quick check if the POindex is already there
2563  QTreeWidgetItem* subItem = NULL;
2564  QList<QTreeWidgetItem *> parentItemList;
2565 
2566 
2567  // first of all, very quick check if it was not the same as last one
2568 
2569  // Check only if it is a transparent object
2570  // If it is the last item and it is not transparent -> nothing to look for,
2571  // simply add it.
2572  if ((currentIndexInTreeSceneHandler == (fullPath.size()-1)) && ((color.GetAlpha() == 1.))) {
2573  } else {
2574  QString lookForString = QString(currentPVName.c_str());
2575  for (int i = 0;i < parentItem->childCount(); i++ ) {
2576  if (parentItem->child(i)->text(0) == lookForString) {
2577  parentItemList.push_back(parentItem->child(i));
2578  }
2579  }
2580  }
2581 
2582  for (int i = 0; i < parentItemList.size(); ++i) {
2583  const std::string& parentItemName = parentItemList.at(i)->text(0).toStdString();
2584  int parentItemCopyNb = parentItemList.at(i)->data(1,Qt::UserRole).toInt();
2585  int parentItemPOIndex = parentItemList.at(i)->data(0,Qt::UserRole).toInt();
2586 
2587  // if already inside
2588  // -> return true
2589  // special case, do not have to deal with hierarchy except for PhysicalVolume
2590 
2591 
2592  /* Physical Volume AND copy number equal AND name equal */
2593  if (((parentRoot == fTouchableVolumes) && (currentPVCopyNb == parentItemCopyNb)
2594  && (currentPVName == parentItemName)) ||
2595  /* NOT a Physical Volume AND copy number equal */
2596  ((parentRoot != fTouchableVolumes) && (currentPVCopyNb == parentItemCopyNb)
2597  /*AND name equal AND PO index equal*/
2598  && (currentPVName == parentItemName) && (currentPVPOIndex == parentItemPOIndex) )) {
2599 
2600  // then check for the Transform3D
2601  bool sameTransform = true;
2602  if (parentItemPOIndex >= 0) {
2603  const PVPath& fullPathTmp = fTreeItemModels[parentItemPOIndex];
2604  if (fullPathTmp.size() > 0) {
2605  if (fullPathTmp.at(fullPathTmp.size()-1).GetTransform () == pPVModel->GetTransformation ()) {
2606  sameTransform = true;
2607  } else {
2608  sameTransform = false;
2609  }
2610  }
2611  }
2612 
2613  // Same transformation, then try to change the PO index
2614  if (sameTransform == true) {
2615  // already exist in the tree, is it a transparent object ?
2616  // If so, then have to change the PO index ONLY if it is the last
2617  // and then change the state ONLY if POIndex has change
2618  // If not, then go deaper
2619 
2620  // last element
2621  if (currentIndexInTreeSceneHandler == (fullPath.size()-1)) {
2622 
2623  parentItemList.at(i)->setText(2,QString::number(currentPVPOIndex));
2624  parentItemList.at(i)->setData(0, Qt::UserRole,currentPVPOIndex);
2625 
2626  fTreeItemModels.insert(std::pair <int, PVPath >(currentPVPOIndex,fullPath) );
2627 
2628  // Then remove tooltip and special font
2629  QFont f = QFont();
2630  parentItemList.at(i)->setFont (0,f);
2631 
2632  // set foreground
2633  parentItemList.at(i)->setForeground (0,QBrush());
2634 
2635  // Set a tootip
2636  parentItemList.at(i)->setToolTip (0,"");
2637 
2638  changeQColorForTreeWidgetItem(parentItemList.at(i),QColor((int)(color.GetRed()*255),
2639  (int)(color.GetGreen()*255),
2640  (int)(color.GetBlue()*255),
2641  (int)(color.GetAlpha()*255)));
2642 
2643  // set check only if there is something to display
2644  if (color.GetAlpha() > 0) {
2645  parentItemList.at(i)->setCheckState(0,Qt::Checked);
2646  updatePositivePoIndexSceneTreeWidgetQuickMap(currentPVPOIndex,parentItemList.at(i));
2647  }
2648  return false;
2649  } else {
2650  subItem = parentItemList.at(i);
2651  }
2652 
2653  // Exists but not the end of path, then forget get it
2654  } else if (currentIndexInTreeSceneHandler < (fullPath.size()-1)) {
2655  subItem = parentItemList.at(i);
2656  }
2657  }
2658 
2659  } // end for
2660 
2661  // if it the last, then add it and set it checked
2662  if (currentIndexInTreeSceneHandler == (fullPath.size()-1)) {
2663  /* subItem =*/ createTreeWidgetItem(fullPath,
2664  QString(currentPVName.c_str()),
2665  currentPVCopyNb,
2666  currentPVPOIndex,
2667  QString(fullPath.at(fullPathIndex).GetPhysicalVolume()->GetLogicalVolume()->GetName().data()),
2668  Qt::Checked,
2669  parentItem,
2670  color);
2671 
2672  if (currentPVPOIndex > fMaxPOindexInserted) {
2673  fMaxPOindexInserted = currentPVPOIndex;
2674  }
2675 
2676  } else {
2677 
2678  // if no child found, then this child is create and marked as invisible, then go inside
2679  if (subItem == NULL) {
2680 
2681  if (currentIndexInTreeSceneHandler < (fullPath.size()-1)) {
2682  subItem = createTreeWidgetItem(fullPath,
2683  QString(currentPVName.c_str()),
2684  currentPVCopyNb,
2685  -1,
2686  QString(fullPath.at(fullPathIndex).GetPhysicalVolume()->GetLogicalVolume()->GetName().data()),
2687  Qt::Unchecked,
2688  parentItem,
2689  color);
2690  }
2691  }
2692 
2693  return parseAndInsertInSceneTree(subItem,pPVModel,fullPathIndex+1,parentRoot,currentIndexInTreeSceneHandler+1,currentPVPOIndex);
2694  }
2695  return true;
2696 }
2697 
2698 
2699 void G4OpenGLQtViewer::changeOpenCloseVisibleHiddenSelectedColorSceneTreeElement(
2700  QTreeWidgetItem* subItem
2701 )
2702 {
2703  // Check if object with the same POIndex is the same in old tree
2704  QTreeWidgetItem* oldItem = NULL;
2705 
2706  QTreeWidgetItem* foundItem = getOldTreeWidgetItem(subItem->data(0,Qt::UserRole).toInt());
2707 
2708  if (foundItem != NULL) {
2709  if (isSameSceneTreeElement(foundItem,subItem)) {
2710  oldItem = foundItem;
2711  }
2712  }
2713  if (foundItem == NULL) { // PO should have change, parse all
2714 
2715  // POindex > 0
2716  std::map <int, QTreeWidgetItem*>::const_iterator i;
2717  i = fOldPositivePoIndexSceneTreeWidgetQuickMap.begin();
2718  while (i != fOldPositivePoIndexSceneTreeWidgetQuickMap.end()) {
2719  if (isSameSceneTreeElement(i->second,subItem)) {
2720  oldItem = i->second;
2721  i = fOldPositivePoIndexSceneTreeWidgetQuickMap.end();
2722  } else {
2723  i++;
2724  }
2725  }
2726  // POindex == 0 ?
2727  if (oldItem == NULL) {
2728  unsigned int a = 0;
2729  while (a < fOldNullPoIndexSceneTreeWidgetQuickVector.size()) {
2730  if (isSameSceneTreeElement(fOldNullPoIndexSceneTreeWidgetQuickVector[a],subItem)) {
2731  oldItem = fOldNullPoIndexSceneTreeWidgetQuickVector[a];
2732  a = fOldNullPoIndexSceneTreeWidgetQuickVector.size();
2733  } else {
2734  a++;
2735  }
2736  }
2737  }
2738  }
2739 
2740  // if found : retore old state
2741  if (oldItem != NULL) {
2742  subItem->setFlags(oldItem->flags()); // flags
2743  subItem->setCheckState(0,oldItem->checkState(0)); // check state
2744  subItem->setSelected(oldItem->isSelected()); // selected
2745  subItem->setExpanded(oldItem->isExpanded ()); // expand
2746 
2747  // change color
2748  // when we call this function, the color in the item is the one of vis Attr
2749 
2750  std::map <int, QTreeWidgetItem* >::iterator it;
2751 
2752  // getOldPO
2753  int oldPOIndex = oldItem->data(0,Qt::UserRole).toInt();
2754  it = fOldPositivePoIndexSceneTreeWidgetQuickMap.find(oldPOIndex);
2755  QColor color;
2756 
2757  // get old Vis Attr Color
2758  std::map <int, QColor >::iterator itVis;
2759  itVis = fOldVisAttrColorMap.find(oldPOIndex);
2760 
2761  QColor oldVisAttrColor;
2762  const QColor& newVisAttrColor = subItem->data(2,Qt::UserRole).value<QColor>();
2763 
2764  bool visAttrChange = false;
2765  // if old vis attr color found
2766  if (itVis != fOldVisAttrColorMap.end()) {
2767  oldVisAttrColor = itVis->second;
2768  if (oldVisAttrColor != newVisAttrColor) {
2769  visAttrChange = true;
2770  }
2771  } else {
2772  visAttrChange = true;
2773  }
2774 
2775  if (visAttrChange) {
2776  fOldVisAttrColorMap.insert(std::pair <int, QColor > (subItem->data(0,Qt::UserRole).toInt(),newVisAttrColor) );
2777 
2778  } else { // if no changes, get old PO value
2779  // if old PO found
2780  if (it != fOldPositivePoIndexSceneTreeWidgetQuickMap.end()) {
2781  color = (it->second)->data(2,Qt::UserRole).value<QColor>();
2782  } else {
2783  color = oldItem->data(2,Qt::UserRole).value<QColor>();
2784  }
2785 #ifdef G4DEBUG_VIS_OGL
2786  printf("====color name:%s\n",color.name().toStdString().c_str());
2787 #endif
2788  changeQColorForTreeWidgetItem(subItem,color);
2789  }
2790  }
2791 
2792  return;
2793 }
2794 
2795 
2796 
2797 // Check if both items are identical.
2798 // For that, check name, copy number, transformation
2799 // special case for "non Touchables", do not check the PO index, check only the name
2800 bool G4OpenGLQtViewer::isSameSceneTreeElement(
2801  QTreeWidgetItem* parentOldItem
2802  ,QTreeWidgetItem* parentNewItem
2803 ) {
2804 
2805  int newPO = -1;
2806  int oldPO = -1;
2807 
2808  int newCpNumber = -1;
2809  int oldCpNumber = -1;
2810 
2811  bool firstWhile = true;
2812 
2813  while ((parentOldItem != NULL) && (parentNewItem != NULL)) {
2814 
2815  // check transform, optimize getting data(..,..) that consume lot of time
2816  if (!firstWhile) {
2817  oldPO = parentOldItem->data(0,Qt::UserRole).toInt();
2818  newPO = parentNewItem->data(0,Qt::UserRole).toInt();
2819  }
2820  firstWhile = false;
2821 
2822  if ((oldPO >= 0) &&
2823  (newPO >= 0)) {
2824  const PVPath& oldFullPath = fOldTreeItemModels[oldPO];
2825  const PVPath& newFullPath = fTreeItemModels[newPO];
2826  if ((oldFullPath.size() > 0) &&
2827  (newFullPath.size() > 0)) {
2828  if (oldFullPath.size() != newFullPath.size()) {
2829  return false;
2830  }
2831  if (oldFullPath.at(oldFullPath.size()-1).GetTransform () == newFullPath.at(newFullPath.size()-1).GetTransform ()) {
2832  newCpNumber = newFullPath.at(newFullPath.size()-1).GetCopyNo();
2833  oldCpNumber = oldFullPath.at(oldFullPath.size()-1).GetCopyNo();
2834  // ok
2835  } else {
2836  return false;
2837  }
2838  }
2839  }
2840 
2841  // Check copy Number
2842  if (oldCpNumber == -1) {
2843  oldCpNumber = parentOldItem->data(1,Qt::UserRole).toInt();
2844  }
2845  if (newCpNumber == -1) {
2846  newCpNumber = parentNewItem->data(1,Qt::UserRole).toInt();
2847  }
2848  if ((oldCpNumber != newCpNumber) ||
2849  // Check name
2850  (parentOldItem->text(0) != parentNewItem->text(0)) ) {
2851  // try to optimize
2852  return false;
2853  } else if ((parentOldItem->text(0) != parentNewItem->text(0)) || // Logical Name
2854  (parentOldItem->text(3) != parentNewItem->text(3))) { // Check logical name
2855  return false;
2856  } else {
2857  parentOldItem = parentOldItem->parent();
2858  parentNewItem = parentNewItem->parent();
2859  }
2860  } // end while
2861 
2862  return true;
2863 }
2864 
2865 
2866 void G4OpenGLQtViewer::addNonPVSceneTreeElement(
2867  const G4String& model
2868  ,int currentPOIndex
2869  ,const std::string& modelDescription
2870  ,const G4Visible& visible
2871 ) {
2872 
2873  QString modelShortName = getModelShortName(model);
2874  G4Colour color;
2875 
2876  // Special case for text
2877  try {
2878  const G4Text& g4Text = dynamic_cast<const G4Text&>(visible);
2879  color = fSceneHandler.GetTextColour(g4Text);
2880  }
2881  catch (std::bad_cast) {
2882  color = fSceneHandler.GetColour(visible);
2883  }
2884  if (modelShortName == "") {
2885  return ;
2886  }
2887  // try to init it
2888  if (fSceneTreeComponentTreeWidget == NULL) {
2889  initSceneTreeComponent();
2890  }
2891 
2892  // if no UI
2893  if (fSceneTreeComponentTreeWidget == NULL) {
2894  return;
2895  }
2896 
2897  fSceneTreeComponentTreeWidget->blockSignals(true);
2898 
2899  // Create the "Model" node if not
2900 
2901  QList<QTreeWidgetItem *> resItem;
2902  resItem = fSceneTreeComponentTreeWidget->findItems (modelShortName, Qt::MatchExactly, 0 );
2903  QTreeWidgetItem * currentItem = NULL;
2904  const PVPath tmpFullPath;
2905 
2906  if (resItem.empty()) {
2907  currentItem = createTreeWidgetItem(tmpFullPath,
2908  modelShortName,
2909  0, // currentPVCopyNb
2910  -1, // currentPVPOIndex
2911  "",
2912  Qt::Checked,
2913  NULL,
2914  color);
2915  } else {
2916  currentItem = resItem.first();
2917  }
2918 
2919  // Is this volume already in the tree AND PO is not the same?
2920  const QList<QTreeWidgetItem *>&
2921  resItems = fSceneTreeComponentTreeWidget->findItems (QString(modelDescription.c_str()), Qt::MatchFixedString| Qt::MatchCaseSensitive|Qt::MatchRecursive, 0 );
2922 
2923  bool alreadyPresent = false;
2924  for (int i = 0; i < resItems.size(); ++i) {
2925  if (currentPOIndex == resItems.at(i)->data(0,Qt::UserRole).toInt()) {
2926  alreadyPresent = true;
2927  }
2928  }
2929  if (!alreadyPresent) {
2930  createTreeWidgetItem(tmpFullPath,
2931  QString(modelDescription.c_str()),
2932  0, // currentPVCopyNb
2933  currentPOIndex,
2934  "",
2935  Qt::Checked,
2936  currentItem,
2937  color);
2938  }
2939  fSceneTreeComponentTreeWidget->blockSignals(false);
2940 
2941 }
2942 
2943 
2947 QString G4OpenGLQtViewer::getModelShortName(const G4String& model) {
2948 
2949  QString modelShortName = model.data();
2950  if (modelShortName.mid(0,modelShortName.indexOf(" ")) == "G4PhysicalVolumeModel") {
2951  modelShortName = fTouchableVolumes;
2952  } else {
2953  if (modelShortName.mid(0,2) == "G4") {
2954  modelShortName = modelShortName.mid(2);
2955  }
2956  if (modelShortName.indexOf("Model") != -1) {
2957  modelShortName = modelShortName.mid(0,modelShortName.indexOf("Model"));
2958  }
2959  }
2960  return modelShortName;
2961 }
2962 
2963 
2964 
2965 bool G4OpenGLQtViewer::isTouchableVisible(int POindex){
2966 
2967  // If no scene tree (Immediate viewer)
2968  if (fSceneTreeComponentTreeWidget == NULL) {
2969  return false;
2970  }
2971 
2972  // should be the next one
2973  fLastSceneTreeWidgetAskFor++;
2974 
2975  QTreeWidgetItem* item = getTreeWidgetItem(POindex);
2976 
2977  if (item != NULL) {
2978  if ( item->checkState(0) == Qt::Checked) {
2979  return true;
2980  }
2981  }
2982  return false;
2983 }
2984 
2985 
2986 bool G4OpenGLQtViewer::parseAndCheckVisibility(QTreeWidgetItem * treeNode,int POindex){
2987  bool isFound = false;
2988  for (int i = 0; i < treeNode->childCount() ; ++i) {
2989 
2990  if (treeNode->child(i)->data(0,Qt::UserRole).toInt() == POindex) {
2991  if (treeNode->child(i)->checkState(0) == Qt::Checked) {
2992  return true;
2993  }
2994  }
2995  isFound = parseAndCheckVisibility(treeNode->child(i),POindex);
2996  if (isFound) {
2997  return true;
2998  }
2999  } // end for
3000  return false;
3001 }
3002 
3003 
3004 void G4OpenGLQtViewer::sceneTreeComponentItemChanged(QTreeWidgetItem* item, int) {
3005 
3006  if (fCheckSceneTreeComponentSignalLock == false) {
3007  fCheckSceneTreeComponentSignalLock = true;
3008  G4bool checked = false;
3009  if (item->checkState(0) == Qt::Checked) {
3010  checked = true;
3011  }
3012  setCheckComponent(item,checked);
3013  updateQWidget();
3014 
3015  // change vis attributes to set new visibility
3016  G4int iPO = item->data(0,Qt::UserRole).toInt();
3017  if (iPO >= 0 && fTreeItemModels.find(iPO) != fTreeItemModels.end()) {
3018  const PVPath& fullPath = fTreeItemModels[iPO];
3019  // If a physical volume
3020  if (fullPath.size()) {
3021 
3022  // Instantiate a working copy of a G4VisAttributes object...
3023  G4VisAttributes workingVisAtts;
3024  // and set the visibility.
3025  workingVisAtts.SetVisibility(checked);
3026 
3027  // Add a vis atts modifier to the view parameters...
3028  fVP.AddVisAttributesModifier
3030  (workingVisAtts,
3032  fullPath));
3033  // G4ModelingParameters::VASVisibility tells G4PhysicalVolumeModel that
3034  // it is the visibility that should be picked out and merged with the
3035  // touchable's normal vis attributes.
3036  }
3037  }
3038 
3039  fCheckSceneTreeComponentSignalLock = false;
3040  }
3041 }
3042 
3043 
3044 void G4OpenGLQtViewer::sceneTreeComponentSelected() {
3045  /*
3046  if (fSceneTreeComponentTreeWidget) {
3047  if (! fSceneTreeComponentTreeWidget->selectedItems().isEmpty ()) {
3048  QTreeWidgetItem* item = fSceneTreeComponentTreeWidget->selectedItems ().first();
3049  if (item) {
3050 
3051  const PVPath& fullPath = fTreeItemModels[item->data(0,Qt::UserRole).toInt()];
3052  if (fullPath.size() > 0) {
3053  const G4VisAttributes* visAttr2 = GetApplicableVisAttributes(fullPath.at(fullPath.size()-1).GetPhysicalVolume()->GetLogicalVolume()->GetVisAttributes());
3054  }
3055  }
3056  }
3057  }
3058  */
3059 }
3060 
3061 
3062 void G4OpenGLQtViewer::changeDepthInSceneTree (int val){
3063 
3064  // If no scene tree (Immediate viewer)
3065  if (fSceneTreeComponentTreeWidget == NULL) {
3066  return;
3067  }
3068 
3069  // max depth : fSceneTreeDepth
3070  // val is between 0 and 1
3071  // 0 .1 .2 .3 .4 .5 .6 .7 .8 .9 1
3072  // 1 1.4 2
3073  // 1 2 3 4
3074 
3075  // Get the depth :
3076  double depth = 1 + ((double)val)/1000 * ((double)fSceneTreeDepth+1);
3077 
3078  // lock update on scene tree items
3079  fCheckSceneTreeComponentSignalLock = true;
3080 
3081  // Disable redraw each time !
3082  G4bool currentAutoRefresh = fVP.IsAutoRefresh();
3083  fVP.SetAutoRefresh(false);
3084 
3085  for (int b=0;b<fSceneTreeComponentTreeWidget->topLevelItemCount();b++) {
3086  changeDepthOnSceneTreeItem(depth,1.,fSceneTreeComponentTreeWidget->topLevelItem(b));
3087  }
3088 
3089  // Enable redraw !
3090  fVP.SetAutoRefresh(currentAutoRefresh);
3091  updateQWidget();
3092 
3093  // unlock update on scene tree items
3094  fCheckSceneTreeComponentSignalLock = false;
3095 
3096 }
3097 
3098 
3099 void G4OpenGLQtViewer::changeColorAndTransparency(QTreeWidgetItem* item,int) {
3100 
3101  if (item == NULL) {
3102  return;
3103  }
3104  const QColor& old = QColor(item->data(2,Qt::UserRole).value<QColor>());
3105 
3106 #if QT_VERSION < 0x040500
3107  bool a;
3108  const QColor& color = QColor(QColorDialog::getRgba (old.rgba(),&a,fSceneTreeComponentTreeWidget));
3109 #else
3110  const QColor& color = QColorDialog::getColor(old,
3111  fSceneTreeComponentTreeWidget,
3112  " Get color and transparency",
3113  QColorDialog::ShowAlphaChannel);
3114 #endif
3115 
3116  if (color.isValid()) {
3117 
3118  // change vis attributes to set new colour
3119  G4int iPO = item->data(0,Qt::UserRole).toInt();
3120  if (iPO >= 0 && fTreeItemModels.find(iPO) != fTreeItemModels.end()) {
3121  const PVPath& fullPath = fTreeItemModels[iPO];
3122  // If a physical volume
3123  if (fullPath.size()) {
3124 
3125  // Instantiate a working copy of a G4VisAttributes object...
3126  G4VisAttributes workingVisAtts;
3127  // and set the colour.
3128  G4Colour g4c(((G4double)color.red())/255,
3129  ((G4double)color.green())/255,
3130  ((G4double)color.blue())/255,
3131  ((G4double)color.alpha())/255);
3132  workingVisAtts.SetColour(g4c);
3133 
3134  // Add a vis atts modifier to the view parameters...
3135  fVP.AddVisAttributesModifier
3136  (G4ModelingParameters::VisAttributesModifier
3137  (workingVisAtts,
3138  G4ModelingParameters::VASColour,
3139  fullPath));
3140  // G4ModelingParameters::VASColour tells G4PhysicalVolumeModel that it is
3141  // the colour that should be picked out and merged with the touchable's
3142  // normal vis attributes.
3143  }
3144  }
3145 
3146  // set scene tree parameters
3147  changeQColorForTreeWidgetItem(item,color);
3148  }
3149 }
3150 
3151 
3152 G4Colour G4OpenGLQtViewer::getColorForPoIndex(int poIndex) {
3153 
3154  QTreeWidgetItem* item = getTreeWidgetItem(poIndex);
3155 
3156  if (item != NULL) {
3157 
3158  const QColor& color = item->data(2,Qt::UserRole).value<QColor>();
3159  G4Colour g4c(((G4double)color.red())/255,
3160  ((G4double)color.green())/255,
3161  ((G4double)color.blue())/255,
3162  ((G4double)color.alpha())/255);
3163 
3164  return g4c;
3165  }
3166  return G4Colour();
3167 }
3168 
3169 
3170 void G4OpenGLQtViewer::changeSearchSelection()
3171 {
3172  const QString& searchText = fHelpLine->text();
3173  if (fSceneTreeComponentTreeWidget == NULL) {
3174  return;
3175  }
3176 
3177  // unselect all
3178  for (int a=0; a<fSceneTreeComponentTreeWidget->topLevelItemCount(); a++) {
3179  fSceneTreeComponentTreeWidget->topLevelItem(a)->setExpanded(false);
3180  fSceneTreeComponentTreeWidget->topLevelItem(a)->setSelected(false);
3181  clearSceneTreeSelection(fSceneTreeComponentTreeWidget->topLevelItem(a));
3182  }
3183 
3184  QList<QTreeWidgetItem *> itemList = fSceneTreeComponentTreeWidget->findItems (searchText,Qt::MatchContains | Qt::MatchRecursive,0);
3185 
3186  for (int i = 0; i < itemList.size(); ++i) {
3187  QTreeWidgetItem* expandParentItem = itemList.at(i);
3188  while (expandParentItem->parent() != NULL) {
3189  expandParentItem->parent()->setExpanded(true);
3190  expandParentItem = expandParentItem->parent();
3191  }
3192  itemList.at(i)->setSelected(true);
3193  }
3194 
3195 }
3196 
3197 
3198 void G4OpenGLQtViewer::clearSceneTreeSelection(QTreeWidgetItem* item) {
3199  for (int a=0; a<item->childCount(); a++) {
3200  item->child(a)->setSelected(false);
3201  item->child(a)->setExpanded(false);
3202  clearSceneTreeSelection(item->child(a));
3203  }
3204 
3205 }
3206 
3207 
3208 bool G4OpenGLQtViewer::isPVVolume(QTreeWidgetItem* item) {
3209  QTreeWidgetItem* sParent = item;
3210  while (sParent->parent() != NULL) {
3211  sParent = sParent->parent();
3212  }
3213  if (sParent->text(0) != fTouchableVolumes) {
3214  return false;
3215  }
3216  // item is the "Touchable" node
3217  if (item->text(0) == fTouchableVolumes) {
3218  return false;
3219  }
3220  return true;
3221 }
3222 
3223 
3224 void G4OpenGLQtViewer::changeDepthOnSceneTreeItem(
3225  double lookForDepth
3226  ,double currentDepth
3227  ,QTreeWidgetItem* item
3228 ) {
3229  double transparencyLevel = 0.;
3230 
3231  // look for a 2.2 depth and we are at level 3
3232  // -> Set all theses items to Opaque
3233  // ONLY if it is a PV volume !
3234  if (isPVVolume(item)) {
3235  if ((lookForDepth-currentDepth) < 0) {
3236  item->setCheckState(0,Qt::Checked);
3237  updatePositivePoIndexSceneTreeWidgetQuickMap(item->data(0,Qt::UserRole).toInt(),item);
3238  transparencyLevel = 1;
3239  } else if ((lookForDepth-currentDepth) > 1 ){
3240  item->setCheckState(0,Qt::Unchecked);
3241  updatePositivePoIndexSceneTreeWidgetQuickMap(item->data(0,Qt::UserRole).toInt(),item);
3242  transparencyLevel = 0;
3243  } else {
3244  item->setCheckState(0,Qt::Checked);
3245  updatePositivePoIndexSceneTreeWidgetQuickMap(item->data(0,Qt::UserRole).toInt(),item);
3246  transparencyLevel = 1-(lookForDepth-currentDepth);
3247  }
3248  }
3249 
3250  if (item->data(0,Qt::UserRole).toInt() >= 0) {
3251  const G4Colour& color = getColorForPoIndex(item->data(0,Qt::UserRole).toInt());
3252 
3253  // We are less depper (ex:tree depth:2) than lookForDepth (ex:3.1)
3254  // -> Have to hide this level ONLY if it was not hidden before
3255 
3256  // Not on a top level item case
3257  // Do not set if it was already set
3258 
3259  // Should add them all the time in case of an older command has change transparency
3260  // before. Should be checked in changeDepthInSceneTree for duplicated commands
3261  // Do not change transparency if not visible by humain (and avoid precision value
3262  // problems..)
3263  if (((color.GetAlpha()-transparencyLevel) > 0.000001) ||
3264  ((color.GetAlpha()-transparencyLevel) < -0.000001)) {
3265  if ((item->text(3) != "")) {
3266  // FIXME : Should not test this here because of transparent
3267  // volume that will came after and with a different alpha level
3268  // Good thing to do is to check and suppress doubles in changeDepthInSceneTree
3269  // and then check if last (transparents volumes) has to change alpha
3270 
3271  changeQColorForTreeWidgetItem(item,QColor((int)(color.GetRed()*255),
3272  (int)(color.GetGreen()*255),
3273  (int)(color.GetBlue()*255),
3274  (int)(transparencyLevel*255)));
3275  }
3276  }
3277  }
3278 
3279  for (int b=0;b< item->childCount();b++) {
3280  changeDepthOnSceneTreeItem(lookForDepth,currentDepth+1,item->child(b));
3281  }
3282 }
3283 
3284 
3285 void G4OpenGLQtViewer::clearTreeWidget(){
3286  // be careful about calling this twice
3287 
3288  if (fSceneTreeComponentTreeWidget) {
3289 
3290  if (fOldSceneTreeComponentTreeWidget == NULL) {
3291  fOldSceneTreeComponentTreeWidget = new QTreeWidget();
3292  }
3293  // clear old scene tree
3294  int tmp = fOldSceneTreeComponentTreeWidget->topLevelItemCount();
3295  while (tmp > 0) {
3296  delete fOldSceneTreeComponentTreeWidget->takeTopLevelItem (0);
3297  tmp = fOldSceneTreeComponentTreeWidget->topLevelItemCount();
3298  }
3299 
3300  if (fSceneTreeComponentTreeWidget->topLevelItemCount () > 0) {
3301 
3302  fPVRootNodeCreate = false;
3303 
3304  // reset all old
3305  fOldPositivePoIndexSceneTreeWidgetQuickMap.clear();
3306  fOldNullPoIndexSceneTreeWidgetQuickVector.clear();
3307  fOldTreeItemModels.clear();
3308 
3309  // Clone everything
3310  for (int b =0; b <fSceneTreeComponentTreeWidget->topLevelItemCount();b++) {
3311  // All tree widgets are in :
3312  // then we could get the old POindex and get
3313  // .visible/Hidden
3314  // .Check/Uncheck
3315  // .selected
3316  // .colour status from std::map
3317 
3318  // clone top level items
3319  int poIndex = fSceneTreeComponentTreeWidget->topLevelItem(b)->data(0,Qt::UserRole).toInt();
3320  if (poIndex != -1) {
3321  fOldPositivePoIndexSceneTreeWidgetQuickMap.insert(std::pair <int, QTreeWidgetItem*> (poIndex,cloneWidgetItem(fSceneTreeComponentTreeWidget->topLevelItem(b))));
3322  } else {
3323  fOldNullPoIndexSceneTreeWidgetQuickVector.push_back(cloneWidgetItem(fSceneTreeComponentTreeWidget->topLevelItem(b)));
3324  }
3325 
3326  // clone leaves
3327  cloneSceneTree(fSceneTreeComponentTreeWidget->topLevelItem(b));
3328  }
3329  // delete all elements
3330 
3331  fOldTreeItemModels.insert(fTreeItemModels.begin(), fTreeItemModels.end());
3332 
3333  // all is copy, then clear scene tree
3334  int tmp2 = fSceneTreeComponentTreeWidget->topLevelItemCount();
3335  while (tmp2 > 0) {
3336  delete fSceneTreeComponentTreeWidget->takeTopLevelItem (0);
3337  tmp2 = fSceneTreeComponentTreeWidget->topLevelItemCount();
3338  }
3339  fPositivePoIndexSceneTreeWidgetQuickMap.clear();
3340 
3341  // put correct value in paramaters
3342  fOldLastSceneTreeWidgetAskFor = fOldPositivePoIndexSceneTreeWidgetQuickMap.begin();
3343  fSceneTreeDepth = 1;
3344  fModelShortNameItem = NULL;
3345  fMaxPOindexInserted = -1;
3346 
3347  }
3348  }
3349 }
3350 
3351 
3358 QTreeWidgetItem * G4OpenGLQtViewer::cloneWidgetItem(QTreeWidgetItem* item) {
3359 
3360  QTreeWidgetItem* cloneItem = new QTreeWidgetItem();
3361 
3362  // Clone what is create createTreeWidgetItem step
3363 
3364  cloneItem->setText(0,item->text(0));
3365  cloneItem->setData(1,Qt::UserRole,item->data(1,Qt::UserRole).toInt());
3366  cloneItem->setText(2,item->text(2));
3367  cloneItem->setData(0, Qt::UserRole,item->data(0,Qt::UserRole).toInt());
3368  cloneItem->setText(3,item->text(3));
3369  cloneItem->setFlags(item->flags());
3370  cloneItem->setToolTip(0,item->toolTip(0));
3371  cloneItem->setCheckState(0,item->checkState(0));
3372  cloneItem->setSelected(item->isSelected());
3373  cloneItem->setExpanded(item->isExpanded ());
3374 
3375  cloneItem->setData(2,Qt::UserRole,item->data(2,Qt::UserRole).value<QColor>());
3376 
3377  return cloneItem;
3378 }
3379 
3380 
3384 void G4OpenGLQtViewer::cloneSceneTree(
3385  QTreeWidgetItem* rootItem
3386 ) {
3387 
3388  for (int b=0;b< rootItem->childCount();b++) {
3389 
3390  QTreeWidgetItem *child = rootItem->child(b);
3391 
3392  // clone top level items
3393  int poIndex = child->data(0,Qt::UserRole).toInt();
3394  if (poIndex != -1) {
3395  fOldPositivePoIndexSceneTreeWidgetQuickMap.insert(std::pair <int, QTreeWidgetItem*> (poIndex,cloneWidgetItem(child)));
3396  } else {
3397  fOldNullPoIndexSceneTreeWidgetQuickVector.push_back(cloneWidgetItem(child));
3398  }
3399  cloneSceneTree(child);
3400  }
3401 }
3402 
3403 
3407  void G4OpenGLQtViewer::updatePositivePoIndexSceneTreeWidgetQuickMap(int POindex,QTreeWidgetItem* item) {
3408 
3409  // Check state
3410  std::map <int, QTreeWidgetItem*>::iterator i;
3411  i = fPositivePoIndexSceneTreeWidgetQuickMap.find(POindex);
3412 
3413  if (i == fPositivePoIndexSceneTreeWidgetQuickMap.end()) {
3414  fPositivePoIndexSceneTreeWidgetQuickMap.insert(std::pair <int, QTreeWidgetItem*> (POindex,item) );
3415  fLastSceneTreeWidgetAskFor = fPositivePoIndexSceneTreeWidgetQuickMap.end();
3416  } else {
3417  i->second = item;
3418  }
3419  }
3420 
3421 
3422 
3423 void G4OpenGLQtViewer::changeQColorForTreeWidgetItem(QTreeWidgetItem* item,const QColor& qc) {
3424 
3425  int POIndex = item->data(0,Qt::UserRole).toInt();
3426  updatePositivePoIndexSceneTreeWidgetQuickMap(POIndex,item );
3427 
3428  QPixmap pixmap = QPixmap(QSize(16, 16));
3429  if (item->data(0,Qt::UserRole).toInt() != -1) {
3430  pixmap.fill (qc);
3431  } else {
3432  pixmap.fill (QColor(255,255,255,255));
3433  }
3434  QPainter painter(&pixmap);
3435  painter.setPen(Qt::black);
3436  painter.drawRect(0,0,15,15); // Draw contour
3437 
3438  item->setIcon(0,pixmap);
3439  item->setData(2,Qt::UserRole,qc);
3440 }
3441 
3442 
3443 
3448 QTreeWidgetItem* G4OpenGLQtViewer::getTreeWidgetItem(int POindex){
3449 
3450  // -1 is not a visible item
3451  if (POindex == -1) {
3452  return NULL;
3453  }
3454 
3455  if (fPositivePoIndexSceneTreeWidgetQuickMap.size() == 0){
3456  return NULL;
3457  }
3458 
3459  if (POindex == fLastSceneTreeWidgetAskFor->first) {
3460  if (fLastSceneTreeWidgetAskFor->second != NULL) {
3461  return fLastSceneTreeWidgetAskFor->second;
3462  }
3463  }
3464 
3465  // if not, use the "find" algorithm
3466  fLastSceneTreeWidgetAskFor = fPositivePoIndexSceneTreeWidgetQuickMap.find(POindex);
3467 
3468  if (fLastSceneTreeWidgetAskFor != fPositivePoIndexSceneTreeWidgetQuickMap.end()) {
3469  return fLastSceneTreeWidgetAskFor->second;
3470  }
3471  return NULL;
3472 }
3473 
3478 QTreeWidgetItem* G4OpenGLQtViewer::getOldTreeWidgetItem(int POindex){
3479 
3480 
3481  // -1 is not a visible item
3482  if (POindex == -1) {
3483  return NULL;
3484  }
3485 
3486  if (fOldPositivePoIndexSceneTreeWidgetQuickMap.size() == 0){
3487  return NULL;
3488  }
3489 
3490  // Should be call only once by item addition
3491  fOldLastSceneTreeWidgetAskFor++;
3492 
3493  if (POindex == fOldLastSceneTreeWidgetAskFor->first) {
3494  if (fOldLastSceneTreeWidgetAskFor->second != NULL) {
3495  if (fOldLastSceneTreeWidgetAskFor != fOldPositivePoIndexSceneTreeWidgetQuickMap.end()) {
3496  return fOldLastSceneTreeWidgetAskFor->second;
3497  }
3498  }
3499  }
3500 
3501  // if not, use the "find" algorithm
3502  fOldLastSceneTreeWidgetAskFor = fOldPositivePoIndexSceneTreeWidgetQuickMap.find(POindex);
3503 
3504  if (fOldLastSceneTreeWidgetAskFor != fOldPositivePoIndexSceneTreeWidgetQuickMap.end()) {
3505  return fOldLastSceneTreeWidgetAskFor->second;
3506  }
3507  return NULL;
3508 }
3509 
3510 
3511 
3516 void G4OpenGLQtViewer::displaySceneTreeComponent() {
3517  // no UI
3518  if (fUISceneTreeComponentsTBWidget == NULL) {
3519  return;
3520  }
3521  if (fSceneTreeComponentTreeWidget == NULL) {
3522  return;
3523  }
3524 
3525  // sort tree items
3526  fSceneTreeComponentTreeWidget->sortItems (0, Qt::AscendingOrder );
3527 
3528  return;
3529 }
3530 
3531 
3538 void G4OpenGLQtViewer::updateToolbarAndMouseContextMenu(){
3539  if (fBatchMode) {
3540  return;
3541  }
3542 
3544  d_style = fVP.GetDrawingStyle();
3545 
3546  // Surface style
3547  if (d_style == G4ViewParameters::wireframe) {
3548  if (fUiQt) fUiQt->SetIconWireframeSelected();
3549  if (fContextMenu) {
3550  fDrawingWireframe->setChecked(true);
3551  fDrawingLineRemoval->setChecked(false);
3552  fDrawingSurfaceRemoval->setChecked(false);
3553  fDrawingLineSurfaceRemoval->setChecked(false);
3554  }
3555  } else if (d_style == G4ViewParameters::hlr) {
3556  if (fUiQt) fUiQt->SetIconHLRSelected();
3557  if (fContextMenu) {
3558  fDrawingLineRemoval->setChecked(true);
3559  fDrawingWireframe->setChecked(false);
3560  fDrawingSurfaceRemoval->setChecked(false);
3561  fDrawingLineSurfaceRemoval->setChecked(false);
3562  }
3563  } else if (d_style == G4ViewParameters::hsr) {
3564  if (fUiQt) fUiQt->SetIconSolidSelected();
3565  if (fContextMenu) {
3566  fDrawingSurfaceRemoval->setChecked(true);
3567  fDrawingWireframe->setChecked(false);
3568  fDrawingLineRemoval->setChecked(false);
3569  fDrawingLineSurfaceRemoval->setChecked(false);
3570  }
3571  } else if (d_style == G4ViewParameters::hlhsr) {
3572  if (fUiQt) fUiQt->SetIconHLHSRSelected();
3573  if (fContextMenu) {
3574  fDrawingLineSurfaceRemoval->setChecked(true);
3575  fDrawingWireframe->setChecked(false);
3576  fDrawingLineRemoval->setChecked(false);
3577  fDrawingSurfaceRemoval->setChecked(false);
3578  fDrawingLineSurfaceRemoval->setChecked(false);
3579  }
3580  }
3581 
3582 
3583  // projection style
3584  G4double d_proj = fVP.GetFieldHalfAngle () ;
3585  if (d_proj == 0.) { // ortho
3586  if (fUiQt) fUiQt->SetIconOrthoSelected();
3587  if (fContextMenu) {
3588  fProjectionOrtho->setChecked(true);
3589  fProjectionPerspective->setChecked(false);
3590  }
3591  } else {
3592  if (fUiQt) fUiQt->SetIconPerspectiveSelected();
3593  if (fContextMenu) {
3594  fProjectionPerspective->setChecked(true);
3595  fProjectionOrtho->setChecked(false);
3596  }
3597  }
3598 
3599 
3600  // mouse style : They are controlled by UI !
3601  if (fUiQt && fContextMenu) {
3602  if (fUiQt->IsIconPickSelected()) {
3603  fMousePickAction->setChecked(true);
3604  fMouseZoomOutAction->setChecked(false);
3605  fMouseZoomInAction->setChecked(false);
3606  fMouseRotateAction->setChecked(false);
3607  fMouseMoveAction->setChecked(false);
3608  } else if (fUiQt->IsIconZoomOutSelected()) {
3609  fMouseZoomOutAction->setChecked(true);
3610  fMousePickAction->setChecked(false);
3611  fMouseZoomInAction->setChecked(false);
3612  fMouseRotateAction->setChecked(false);
3613  fMouseMoveAction->setChecked(false);
3614  } else if (fUiQt->IsIconZoomInSelected()) {
3615  fMouseZoomInAction->setChecked(true);
3616  fMousePickAction->setChecked(false);
3617  fMouseZoomOutAction->setChecked(false);
3618  fMouseRotateAction->setChecked(false);
3619  fMouseMoveAction->setChecked(false);
3620  } else if (fUiQt->IsIconRotateSelected()) {
3621  fMouseRotateAction->setChecked(true);
3622  fMousePickAction->setChecked(false);
3623  fMouseZoomOutAction->setChecked(false);
3624  fMouseZoomInAction->setChecked(false);
3625  fMouseMoveAction->setChecked(false);
3626  } else if (fUiQt->IsIconMoveSelected()) {
3627  fMouseMoveAction->setChecked(true);
3628  fMousePickAction->setChecked(false);
3629  fMouseZoomOutAction->setChecked(false);
3630  fMouseZoomInAction->setChecked(false);
3631  fMouseRotateAction->setChecked(false);
3632  }
3633  }
3634 }
3635 
3636 
3637 /*
3638 
3639 void MultiLayer::exportToSVG(const QString& fname)
3640 {
3641 QPicture picture;
3642 QPainter p(&picture);
3643 for (int i=0;i<(int)graphsList->count();i++)
3644 {
3645 Graph *gr=(Graph *)graphsList->at(i);
3646 Plot *myPlot= (Plot *)gr->plotWidget();
3647 
3648 QPoint pos=gr->pos();
3649 
3650 int width=int(myPlot->frameGeometry().width());
3651 int height=int(myPlot->frameGeometry().height());
3652 
3653 myPlot->print(&p, QRect(pos,QSize(width,height)));
3654 }
3655 
3656 p.end();
3657 picture.save(fname, "svg");
3658 }
3659 */
3660 #endif