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