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