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