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