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