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