G4OpenGLQtViewer.cc

Go to the documentation of this file.
00001 //
00002 // ********************************************************************
00003 // * License and Disclaimer                                           *
00004 // *                                                                  *
00005 // * The  Geant4 software  is  copyright of the Copyright Holders  of *
00006 // * the Geant4 Collaboration.  It is provided  under  the terms  and *
00007 // * conditions of the Geant4 Software License,  included in the file *
00008 // * LICENSE and available at  http://cern.ch/geant4/license .  These *
00009 // * include a list of copyright holders.                             *
00010 // *                                                                  *
00011 // * Neither the authors of this software system, nor their employing *
00012 // * institutes,nor the agencies providing financial support for this *
00013 // * work  make  any representation or  warranty, express or implied, *
00014 // * regarding  this  software system or assume any liability for its *
00015 // * use.  Please see the license in the file  LICENSE  and URL above *
00016 // * for the full disclaimer and the limitation of liability.         *
00017 // *                                                                  *
00018 // * This  code  implementation is the result of  the  scientific and *
00019 // * technical work of the GEANT4 collaboration.                      *
00020 // * By using,  copying,  modifying or  distributing the software (or *
00021 // * any work based  on the software)  you  agree  to acknowledge its *
00022 // * use  in  resulting  scientific  publications,  and indicate your *
00023 // * acceptance of all terms of the Geant4 Software license.          *
00024 // ********************************************************************
00025 //
00026 //
00027 // $Id$
00028 //
00029 // 
00030 // G4OpenGLQtViewer : Class to provide Qt specific
00031 //                     functionality for OpenGL in GEANT4
00032 //
00033 // 27/06/2003 : G.Barrand : implementation (at last !).
00034 
00035 #ifdef G4VIS_BUILD_OPENGLQT_DRIVER
00036 
00037 #include "G4OpenGLQtViewer.hh"
00038 
00039 #include "G4OpenGLSceneHandler.hh"
00040 #include "G4VSolid.hh"
00041 #include "G4OpenGLQtExportDialog.hh"
00042 #include "G4OpenGLQtMovieDialog.hh"
00043 #include "G4Qt.hh"
00044 #include "G4UIQt.hh"
00045 #include "G4UImanager.hh"
00046 #include "G4UIcommandTree.hh"
00047 #include "G4LogicalVolumeStore.hh"
00048 #include "G4PhysicalVolumeStore.hh"
00049 #include "G4VisCommandsGeometrySet.hh"
00050 #include "G4PhysicalVolumeModel.hh"
00051 #include "G4Text.hh"
00052 
00053 #include <CLHEP/Units/SystemOfUnits.h>
00054 
00055 #include <typeinfo>
00056 
00057 #include <qlayout.h>
00058 #include <qlabel.h>
00059 #include <qdialog.h>
00060 #include <qpushbutton.h>
00061 #include <qprocess.h>
00062 #include <qapplication.h>
00063 #include <qdesktopwidget.h>
00064 
00065 #include <qmenu.h>
00066 #include <qimagewriter.h>
00067 
00068 #include <qtextedit.h>
00069 #include <qtreewidget.h>
00070 #include <qapplication.h>
00071 #include <qmessagebox.h>
00072 #include <qfiledialog.h>
00073 #include <qprinter.h>
00074 #include <qdatetime.h>
00075 #include <qpainter.h>
00076 #include <qgl.h> // include <qglwidget.h>
00077 #include <qdialog.h>
00078 #include <qcolordialog.h>
00079 #include <qevent.h> //include <qcontextmenuevent.h>
00080 #include <qobject.h>
00081 #include <qgroupbox.h>
00082 #include <qcombobox.h>
00083 #include <qlineedit.h>
00084 #include <qsignalmapper.h>
00085 
00087 void G4OpenGLQtViewer::CreateMainWindow (
00088  QGLWidget* glWidget
00089  ,const QString& name
00090 ) 
00091 
00092 
00093 {
00094 
00095   if(fWindow) return; //Done.
00096 
00097   fWindow = glWidget ;
00098   //  fWindow->makeCurrent();
00099 
00100   G4Qt* interactorManager = G4Qt::getInstance ();
00101 
00102   ResizeWindow(fVP.GetWindowSizeHintX(),fVP.GetWindowSizeHintY());
00103     
00104   // FIXME L.Garnier 9/11/09 Has to be check !!! 
00105   // Qt UI with Qt Vis
00106   // Qt UI with X Vis
00107   // X UI with Qt Vis
00108   // X UI with X Vis
00109   // Ne marche pas avec un UIBatch !! (ecran blanc)
00110 
00111   // return false if G4UIQt was not launch
00112 
00113   G4UImanager* UI = G4UImanager::GetUIpointer();
00114   if (UI == NULL) return;
00115 
00116   if (! static_cast<G4UIQt*> (UI->GetG4UIWindow())) {
00117     // NO UI, should be batch mode
00118     fBatchMode = true;
00119     return;
00120   }
00121   fUiQt = static_cast<G4UIQt*> (UI->GetG4UIWindow());
00122   
00123   bool isTabbedView = false;
00124   if ( fUiQt) {
00125     if (!fBatchMode) {
00126       if (!interactorManager->IsExternalApp()) {
00127         isTabbedView = fUiQt->AddTabWidget(fWindow,name,getWinWidth(),getWinHeight());
00128         fUISceneTreeComponentsTBWidget = fUiQt->GetSceneTreeComponentsTBWidget();
00129         isTabbedView = true;
00130       }
00131     }
00132   }
00133 #ifdef G4DEBUG_VIS_OGL
00134   else {
00135     printf("G4OpenGLQtViewer::CreateMainWindow :: UIQt NOt found \n");
00136   }
00137 #endif
00138 
00139   if (!isTabbedView) { // we have to do a dialog
00140 
00141     QWidget *myParent = getParentWidget();
00142 #ifdef G4DEBUG_VIS_OGL
00143     printf("G4OpenGLQtViewer::CreateMainWindow :: getParent OK \n");
00144 #endif
00145     if (myParent != NULL) {
00146       glWidget->setParent(myParent);  
00147     }
00148     QHBoxLayout *mainLayout = new QHBoxLayout(fGLWindow);
00149     
00150     mainLayout->setMargin(0);
00151     mainLayout->setSpacing(0);   
00152     mainLayout->addWidget(fWindow);
00153     if (fGLWindow->inherits("QMainWindow")) {
00154       fGLWindow->setWindowTitle( name);
00155     }
00156     fGLWindow->setLayout(mainLayout);
00157 
00158     
00159     //useful for MACOSX, we have to compt the menuBar height
00160     int offset = QApplication::desktop()->height() 
00161       - QApplication::desktop()->availableGeometry().height();
00162     
00163     G4int YPos= fVP.GetWindowAbsoluteLocationHintY(QApplication::desktop()->height());
00164     if (fVP.GetWindowAbsoluteLocationHintY(QApplication::desktop()->height())< offset) {
00165       YPos = offset;
00166     }
00167     fGLWindow->resize(getWinWidth(), getWinHeight());
00168 #ifdef G4DEBUG_VIS_OGL
00169     printf("G4OpenGLQtViewer::CreateMainWindow :: resizing to %d %d \n",getWinWidth(), getWinHeight());
00170 #endif
00171     fGLWindow->move(fVP.GetWindowAbsoluteLocationHintX(QApplication::desktop()->width()),YPos);
00172     fGLWindow->show();
00173   } else {
00174     fGLWindow = fWindow;
00175     fGLWindow->resize(getWinWidth(), getWinHeight());
00176   }
00177 
00178   if(!fWindow) return;
00179   
00180   if (!fContextMenu) 
00181     createPopupMenu();
00182 
00183 }
00184 
00185 
00187 G4OpenGLQtViewer::G4OpenGLQtViewer (
00188  G4OpenGLSceneHandler& scene
00189 )
00190   :G4VViewer (scene, -1)
00191   ,G4OpenGLViewer (scene)
00192   ,fWindow(0)
00193   ,fRecordFrameNumber(0)
00194   ,fContextMenu(0)
00195   ,fDeltaDepth(0.01)
00196   ,fDeltaZoom(0.05)
00197   ,fHoldKeyEvent(false)
00198   ,fHoldMoveEvent(false)
00199   ,fHoldRotateEvent(false)
00200   ,fAutoMove(false)
00201   ,fEncoderPath("")
00202   ,fTempFolderPath("")
00203   ,fMovieTempFolderPath("")
00204   ,fSaveFileName("")
00205   ,fParameterFileName("ppmtompeg_encode_parameter_file.par")
00206   ,fMovieParametersDialog(NULL)
00207   ,fRecordingStep(WAIT)
00208   ,fProcess(NULL)
00209   ,fNbMaxFramesPerSec(100)
00210   ,fNbMaxAnglePerSec(360)
00211   ,fLaunchSpinDelay(100)
00212   ,fUISceneTreeComponentsTBWidget(NULL)
00213   ,fNoKeyPress(true)
00214   ,fAltKeyPress(false)
00215   ,fControlKeyPress(false)
00216   ,fShiftKeyPress(false)
00217   ,fBatchMode(false)
00218   ,fCheckSceneTreeComponentSignalLock(false)
00219   ,fSceneTreeComponentTreeWidget(NULL)
00220   ,fOldSceneTreeComponentTreeWidget(NULL)
00221   ,fSceneTreeWidget(NULL)
00222   ,fPVRootNodeCreate(false)
00223   ,fHelpLine(NULL)
00224   ,fNbRotation(0)
00225   ,fTimeRotation(0)
00226   ,fTouchableVolumes("Touchables")
00227   ,fShortcutsDialog(NULL)
00228   ,fSceneTreeDepthSlider(NULL)
00229   ,fSceneTreeDepth(1)
00230   ,fModelShortNameItem(NULL)
00231   ,fMaxPOindexInserted(-1)
00232   ,fUiQt(NULL)
00233   ,signalMapperMouse(NULL)
00234   ,signalMapperSurface(NULL)
00235 {
00236 
00237   // launch Qt if not
00238   if (QCoreApplication::instance () == NULL) {
00239     fBatchMode = true;
00240   }
00241   G4Qt::getInstance ();
00242 
00243   fLastPos3 = QPoint(-1,-1);    
00244   fLastPos2 = QPoint(-1,-1);    
00245   fLastPos1 = QPoint(-1,-1);    
00246   
00247   initMovieParameters();
00248 
00249   fLastEventTime = new QTime();
00250   signalMapperMouse = new QSignalMapper(this);
00251   signalMapperSurface = new QSignalMapper(this);
00252 
00253 #ifdef G4DEBUG_VIS_OGL
00254   printf("G4OpenGLQtViewer::G4OpenGLQtViewer END\n");
00255 #endif
00256 }
00257 
00259 G4OpenGLQtViewer::~G4OpenGLQtViewer (
00260 ) 
00261 
00262 
00263 {
00264   // remove scene tree from layout
00265   // Delete all the existing buttons in the layout
00266   QLayoutItem *wItem;
00267   if (fSceneTreeWidget != NULL) {
00268     if (fSceneTreeWidget->layout() != NULL) {
00269       while ((wItem = fSceneTreeWidget->layout()->takeAt(0)) != 0) {
00270         delete wItem->widget();
00271         delete wItem;
00272       }
00273     }
00274     if (fUISceneTreeComponentsTBWidget != NULL) {
00275       fUISceneTreeComponentsTBWidget->removeTab(fUISceneTreeComponentsTBWidget->indexOf(fSceneTreeWidget));
00276     }
00277   }
00278   G4cout <<removeTempFolder().toStdString().c_str() <<G4endl;
00279 }
00280 
00281 
00282 //
00283 //   Create a popup menu for the widget. This menu is activated by right-mouse click
00284 //
00285 void G4OpenGLQtViewer::createPopupMenu()    {
00286 
00287   fContextMenu = new QMenu("All");
00288 
00289   QMenu *mMouseAction = fContextMenu->addMenu("&Mouse actions");
00290 
00291   fMouseRotateAction = mMouseAction->addAction("Rotate", signalMapperMouse, SLOT(map()));
00292   fMouseMoveAction = mMouseAction->addAction("Move", signalMapperMouse, SLOT(map()));
00293   fMousePickAction = mMouseAction->addAction("Pick", signalMapperMouse, SLOT(map()));
00294   fMouseZoomOutAction = mMouseAction->addAction("Zoom out", signalMapperMouse, SLOT(map()));
00295   fMouseZoomInAction = mMouseAction->addAction("Zoom in", signalMapperMouse, SLOT(map()));
00296   QAction *shortcutsAction = mMouseAction->addAction("Show shortcuts");
00297 
00298   fMouseRotateAction->setCheckable(true);
00299   fMouseMoveAction->setCheckable(true);
00300   fMousePickAction->setCheckable(true);
00301   fMouseZoomOutAction->setCheckable(true);
00302   fMouseZoomInAction->setCheckable(true);
00303   shortcutsAction->setCheckable(false);
00304 
00305   connect(signalMapperMouse, SIGNAL(mapped(int)),this, SLOT(toggleMouseAction(int)));
00306   signalMapperMouse->setMapping(fMouseRotateAction,1);
00307   signalMapperMouse->setMapping(fMouseMoveAction,2);
00308   signalMapperMouse->setMapping(fMousePickAction,3);
00309   signalMapperMouse->setMapping(fMouseZoomOutAction,4);
00310   signalMapperMouse->setMapping(fMouseZoomInAction,5);
00311 
00312   QObject::connect(shortcutsAction, 
00313                     SIGNAL(triggered(bool)),
00314                     this, 
00315                     SLOT(showShortcuts()));
00316 
00317   // === Style Menu ===
00318   QMenu *mStyle = fContextMenu->addMenu("&Style");
00319 
00320   QMenu *mRepresentation = mStyle->addMenu("&Representation");
00321   QMenu *mProjection = mStyle->addMenu("&Projection");
00322   QAction *polyhedron = mRepresentation->addAction("Polyhedron");
00323   QAction *nurbs = mRepresentation->addAction("NURBS");
00324 
00325   fProjectionOrtho = mProjection->addAction("Orthographic", signalMapperSurface, SLOT(map()));
00326   fProjectionPerspective = mProjection->addAction("Persepective", signalMapperSurface, SLOT(map()));
00327 
00328   // INIT mRepresentation
00329   G4ViewParameters::RepStyle style;
00330   style = fVP.GetRepStyle();
00331   if (style == G4ViewParameters::polyhedron) {
00332     createRadioAction(polyhedron,nurbs,SLOT(toggleRepresentation(bool)),1);
00333   } else if (style == G4ViewParameters::nurbs) {
00334     createRadioAction(polyhedron,nurbs,SLOT(toggleRepresentation(bool)),2);
00335   } else {
00336     mRepresentation->clear();
00337   }
00338 
00339   // INIT mProjection
00340   if (fVP.GetFieldHalfAngle() == 0) {
00341     createRadioAction(fProjectionOrtho, fProjectionPerspective,SLOT(toggleProjection(bool)),1);
00342   } else {
00343     createRadioAction(fProjectionOrtho, fProjectionPerspective,SLOT(toggleProjection(bool)),2);
00344   }
00345 
00346   // === Drawing Menu ===
00347   QMenu *mDrawing = mStyle->addMenu("&Drawing");
00348 
00349   fDrawingWireframe = mDrawing->addAction("Wireframe", signalMapperSurface, SLOT(map()));
00350 
00351   fDrawingLineRemoval = mDrawing->addAction("Hidden line removal", signalMapperSurface, SLOT(map()));
00352 
00353   fDrawingSurfaceRemoval = mDrawing->addAction("Hidden Surface removal", signalMapperSurface, SLOT(map()));
00354 
00355   fDrawingLineSurfaceRemoval = mDrawing->addAction("Hidden line and surface removal", signalMapperSurface, SLOT(map()));
00356 
00357   fDrawingWireframe->setCheckable(true);
00358   fDrawingLineRemoval->setCheckable(true);
00359   fDrawingSurfaceRemoval->setCheckable(true);
00360   fDrawingLineSurfaceRemoval->setCheckable(true);
00361 
00362   connect(signalMapperSurface, SIGNAL(mapped(int)),this, SLOT(toggleSurfaceAction(int)));
00363   signalMapperSurface->setMapping(fDrawingWireframe,1);
00364   signalMapperSurface->setMapping(fDrawingLineRemoval,2);
00365   signalMapperSurface->setMapping(fDrawingSurfaceRemoval,3);
00366   signalMapperSurface->setMapping(fDrawingLineSurfaceRemoval,4);
00367 
00368 
00369   // Background Color
00370 
00371   QAction *backgroundColorChooser ;
00372   // === Action Menu ===
00373   backgroundColorChooser = mStyle->addAction("Background color");
00374   QObject ::connect(backgroundColorChooser, 
00375                     SIGNAL(triggered()),
00376                     this,
00377                     SLOT(actionChangeBackgroundColor()));
00378 
00379   // Text Color
00380 
00381   QAction *textColorChooser ;
00382   // === Action Menu ===
00383   textColorChooser = mStyle->addAction("Text color");
00384   QObject ::connect(textColorChooser, 
00385                     SIGNAL(triggered()),
00386                     this,
00387                     SLOT(actionChangeTextColor()));
00388 
00389   // Default Color
00390 
00391   QAction *defaultColorChooser ;
00392   // === Action Menu ===
00393   defaultColorChooser = mStyle->addAction("Default color");
00394   QObject ::connect(defaultColorChooser, 
00395                     SIGNAL(triggered()),
00396                     this,
00397                     SLOT(actionChangeDefaultColor()));
00398 
00399 
00400   // === Action Menu ===
00401   QMenu *mActions = fContextMenu->addMenu("&Actions");
00402   QAction *createEPS = mActions->addAction("Save as ...");
00403   QObject ::connect(createEPS, 
00404                     SIGNAL(triggered()),
00405                     this,
00406                     SLOT(actionSaveImage()));
00407 
00408   // === Action Menu ===
00409   QAction *movieParameters = mActions->addAction("Movie parameters...");
00410   QObject ::connect(movieParameters, 
00411                     SIGNAL(triggered()),
00412                     this,
00413                     SLOT(actionMovieParameters()));
00414 
00415 
00416 
00417 
00418   // === Special Menu ===
00419   QMenu *mSpecial = fContextMenu->addMenu("S&pecial");
00420   QMenu *mTransparency = mSpecial->addMenu("Transparency");
00421   QAction *transparencyOn = mTransparency->addAction("On");
00422   QAction *transparencyOff = mTransparency->addAction("Off");
00423 
00424   if (transparency_enabled == false) {
00425     createRadioAction(transparencyOn,transparencyOff,SLOT(toggleTransparency(bool)),2);
00426   } else if (transparency_enabled == true) {
00427     createRadioAction(transparencyOn,transparencyOff,SLOT(toggleTransparency(bool)),1);
00428   } else {
00429     mSpecial->clear();
00430   }
00431 
00432 
00433   QMenu *mAntialiasing = mSpecial->addMenu("Antialiasing");
00434   QAction *antialiasingOn = mAntialiasing->addAction("On");
00435   QAction *antialiasingOff = mAntialiasing->addAction("Off");
00436 
00437   if (antialiasing_enabled == false) {
00438     createRadioAction(antialiasingOn,antialiasingOff,SLOT(toggleAntialiasing(bool)),2);
00439   } else if (antialiasing_enabled == true) {
00440     createRadioAction(antialiasingOn,antialiasingOff,SLOT(toggleAntialiasing(bool)),1);
00441   } else {
00442     mAntialiasing->clear();
00443   }
00444 
00445   QMenu *mHaloing = mSpecial->addMenu("Haloing");
00446   QAction *haloingOn = mHaloing->addAction("On");
00447   QAction *haloingOff = mHaloing->addAction("Off");
00448   if (haloing_enabled == false) {
00449     createRadioAction(haloingOn,haloingOff,SLOT(toggleHaloing(bool)),2);
00450   } else if (haloing_enabled == true) {
00451     createRadioAction(haloingOn,haloingOff,SLOT(toggleHaloing(bool)),1);
00452   } else {
00453     mHaloing->clear();
00454   }
00455 
00456   QMenu *mAux = mSpecial->addMenu("Auxiliary edges");
00457   QAction *auxOn = mAux->addAction("On");
00458   QAction *auxOff = mAux->addAction("Off");
00459   if (!fVP.IsAuxEdgeVisible()) {
00460     createRadioAction(auxOn,auxOff,SLOT(toggleAux(bool)),2);
00461   } else {
00462     createRadioAction(auxOn,auxOff,SLOT(toggleAux(bool)),1);
00463   }
00464 
00465 
00466   QMenu *mHiddenMarkers = mSpecial->addMenu("Hidden markers");
00467   QAction *hiddenMarkersOn = mHiddenMarkers->addAction("On");
00468   QAction *hiddenMarkersOff = mHiddenMarkers->addAction("Off");
00469   if (fVP.IsMarkerNotHidden()) {
00470     createRadioAction(hiddenMarkersOn,hiddenMarkersOff,SLOT(toggleHiddenMarkers(bool)),2);
00471   } else {
00472     createRadioAction(hiddenMarkersOn,hiddenMarkersOff,SLOT(toggleHiddenMarkers(bool)),1);
00473   }
00474 
00475 
00476 
00477   QMenu *mFullScreen = mSpecial->addMenu("&Full screen");
00478   fFullScreenOn = mFullScreen->addAction("On");
00479   fFullScreenOff = mFullScreen->addAction("Off");
00480   createRadioAction(fFullScreenOn,fFullScreenOff,SLOT(toggleFullScreen(bool)),2);
00481 
00482   // INIT All
00483   updateToolbarAndMouseContextMenu();
00484 }
00485 
00486 
00487 void G4OpenGLQtViewer::G4manageContextMenuEvent(QContextMenuEvent *e)
00488 {
00489   if (!fGLWindow) {
00490     G4cerr << "Visualization window not defined, please choose one before" << G4endl;
00491   } else {
00492   
00493     if (!fContextMenu) 
00494       createPopupMenu();
00495     
00496     // launch menu
00497     if ( fContextMenu ) {
00498       fContextMenu->exec( e->globalPos() );
00499       //    delete fContextMenu;
00500     }
00501   }
00502   e->accept();
00503 }
00504 
00505 
00514 void G4OpenGLQtViewer::createRadioAction(QAction *action1,QAction *action2, const std::string& method,unsigned int nCheck) {
00515 
00516   action1->setCheckable(true);
00517   action2->setCheckable(true);
00518 
00519   if (nCheck ==1)
00520     action1->setChecked (true);
00521   else
00522     action2->setChecked (true);
00523    
00524   QObject ::connect(action1, SIGNAL(triggered(bool)),action2, SLOT(toggle()));
00525   QObject ::connect(action2, SIGNAL(triggered(bool)),action1, SLOT(toggle()));
00526 
00527   QObject ::connect(action1, SIGNAL(toggled(bool)),this, method.c_str());
00528 
00529 }
00530 
00531 
00532 
00536 void G4OpenGLQtViewer::showShortcuts() {
00537   G4String text;
00538 
00539   text = "========= Mouse Shortcuts =========\n";
00540   if (fUiQt != NULL) {
00541     if (fUiQt->IsIconRotateSelected()) {  // rotate
00542       text += "Click and move mouse to rotate volume \n";
00543       text += "ALT + Click and move mouse to rotate volume (Toggle View/Theta-Phi Direction) \n";
00544       text += "CTRL + Click and zoom mouse to zoom in/out \n";
00545       text += "SHIFT + Click and zoommove camera point of view \n";
00546     } else  if (fUiQt->IsIconMoveSelected()) { //move
00547       text += "Move camera point of view with mouse \n";
00548     } else  if (fUiQt->IsIconPickSelected()) { //pick
00549       text += "Click and pick \n";
00550     }
00551   } else {
00552     text += "Click and move mouse to rotate volume \n";
00553     text += "ALT + Click and move mouse to rotate volume (Toggle View/Theta-Phi Direction) \n";
00554     text += "CTRL + Click and zoom mouse to zoom in/out \n";
00555     text += "SHIFT + Click and zoommove camera point of view \n";
00556   }
00557   text += "========= Move Shortcuts ========= \n";
00558   text += "Press left/right arrows to move volume left/right \n";
00559   text += "Press up/down arrows to move volume up/down \n";
00560   text += "Press '+'/'-' to move volume toward/forward \n";
00561   text += "\n";
00562   text += "========= Rotation (Theta/Phi) Shortcuts ========= \n";
00563   text += "Press SHIFT + left/right arrows to rotate volume left/right \n";
00564   text += "Press SHIFT + up/down arrows to rotate volume up/down \n";
00565   text += "\n";
00566   text += "========= Rotation (View Direction) Shortcuts ========= \n";
00567   text += "Press ALT + left/right to rotate volume around vertical direction \n";
00568   text += "Press ALT + up/down to rotate volume around horizontal direction \n";
00569   text += "\n";
00570   text += "========= Zoom View ========= \n";
00571   text += "Press CTRL + '+'/'-' to zoom into volume \n";
00572   text += "\n";
00573   text += "========= Misc ========= \n";
00574   text += "Press ALT +/- to slow/speed rotation/move \n";
00575   text += "Press H to reset view \n";
00576   text += "Press Esc to exit FullScreen \n";
00577   text += "\n";
00578   text += "========= Video ========= \n";
00579   text += "In video mode : \n";
00580   text += " Press SPACE to Start/Pause video recording \n";
00581   text += " Press RETURN to Stop video recording \n";
00582   text += "\n";
00583 
00584   G4cout << text;
00585 
00586   if (  fShortcutsDialog == NULL) {
00587     fShortcutsDialog = new QDialog();
00588     fShortcutsDialogInfos = new QTextEdit() ;
00589     QVBoxLayout *mainLayout = new QVBoxLayout;
00590     mainLayout->addWidget(fShortcutsDialogInfos);
00591     fShortcutsDialog->setLayout(mainLayout);
00592     fShortcutsDialog->setWindowTitle(tr("Shortcuts"));
00593   }
00594   
00595   fShortcutsDialogInfos->setPlainText(text.data());
00596   fShortcutsDialog->show();      
00597 }
00598 
00599 
00600 
00607 void G4OpenGLQtViewer::toggleMouseAction(int aAction) {
00608 
00609   if (aAction == 1) {
00610     fUiQt->SetIconRotateSelected();
00611   } else  if (aAction == 2) {
00612     fUiQt->SetIconMoveSelected();
00613   } else  if (aAction == 3) {
00614     fUiQt->SetIconPickSelected();
00615   } else  if (aAction == 4) {
00616     fUiQt->SetIconZoomOutSelected();
00617   } else  if (aAction == 5) {
00618     fUiQt->SetIconZoomInSelected();
00619   }
00620 
00621   updateToolbarAndMouseContextMenu();
00622 }
00623 
00624 
00635 void G4OpenGLQtViewer::toggleSurfaceAction(int aAction) {
00636 
00637   G4ViewParameters::DrawingStyle d_style = G4ViewParameters::wireframe;
00638   
00639   if (aAction ==1) {
00640     d_style = G4ViewParameters::wireframe;
00641 
00642   } else  if (aAction ==2) {
00643     d_style = G4ViewParameters::hlr;
00644 
00645   } else  if (aAction ==3) {
00646     d_style = G4ViewParameters::hsr;
00647 
00648   } else  if (aAction ==4) {
00649     d_style = G4ViewParameters::hlhsr;
00650   }
00651   fVP.SetDrawingStyle(d_style);
00652 
00653   updateToolbarAndMouseContextMenu();
00654   updateQWidget();
00655 }
00656 
00657 
00668 void G4OpenGLQtViewer::toggleRepresentation(bool check) {
00669 
00670   G4ViewParameters::RepStyle style;
00671   if (check == 1) {
00672     style = G4ViewParameters::polyhedron;
00673   } else {
00674     style = G4ViewParameters::nurbs;
00675   }
00676   fVP.SetRepStyle (style);
00677 
00678   updateToolbarAndMouseContextMenu();
00679   updateQWidget();
00680 }
00681 
00692 void G4OpenGLQtViewer::toggleProjection(bool check) {
00693 
00694   if (check == 1) {
00695     fVP.SetOrthogonalProjection ();
00696   } else {
00697     fVP.SetPerspectiveProjection();
00698   }  
00699   updateToolbarAndMouseContextMenu();
00700   updateQWidget();
00701 }
00702 
00703 
00708 void G4OpenGLQtViewer::toggleTransparency(bool check) {
00709   
00710   if (check) {
00711     transparency_enabled = true;
00712   } else {
00713     transparency_enabled = false;
00714   }
00715   SetNeedKernelVisit (true);
00716   updateToolbarAndMouseContextMenu();
00717   updateQWidget();
00718 }
00719 
00724 void G4OpenGLQtViewer::toggleAntialiasing(bool check) {
00725 
00726   if (!check) {
00727     antialiasing_enabled = false;
00728     glDisable (GL_LINE_SMOOTH);
00729     glDisable (GL_POLYGON_SMOOTH);
00730   } else {
00731     antialiasing_enabled = true;
00732     glEnable (GL_LINE_SMOOTH);
00733     glHint (GL_LINE_SMOOTH_HINT, GL_NICEST);
00734     glEnable (GL_POLYGON_SMOOTH);
00735     glHint (GL_POLYGON_SMOOTH_HINT, GL_NICEST);
00736   }
00737 
00738   updateToolbarAndMouseContextMenu();
00739   updateQWidget();
00740 }
00741 
00746 //FIXME : I SEE NOTHING...
00747 void G4OpenGLQtViewer::toggleHaloing(bool check) {
00748   if (check) {
00749     haloing_enabled = false;
00750   } else {
00751     haloing_enabled = true;
00752   }
00753 
00754   updateToolbarAndMouseContextMenu();
00755   updateQWidget();
00756 
00757 }
00758 
00763 void G4OpenGLQtViewer::toggleAux(bool check) {
00764   if (check) {
00765     fVP.SetAuxEdgeVisible(true);
00766   } else {
00767     fVP.SetAuxEdgeVisible(false);
00768   }
00769   SetNeedKernelVisit (true);
00770   updateToolbarAndMouseContextMenu();
00771   updateQWidget();
00772 }
00773 
00778 void G4OpenGLQtViewer::toggleHiddenMarkers(bool check) {
00779   if (check) {
00780     fVP.SetMarkerHidden();
00781   } else {
00782     fVP.SetMarkerNotHidden();
00783   }
00784   //  SetNeedKernelVisit (true);
00785   updateToolbarAndMouseContextMenu();
00786   updateQWidget();
00787 }
00788 
00792 void G4OpenGLQtViewer::toggleFullScreen(bool check) {
00793   if (check != fGLWindow->isFullScreen()) { //toggle
00794     fGLWindow->setWindowState(fGLWindow->windowState() ^ Qt::WindowFullScreen);
00795   }
00796 }
00797 
00798 
00799 void G4OpenGLQtViewer::savePPMToTemp() {
00800   if (fMovieTempFolderPath == "") {
00801     return;
00802   }
00803   QString fileName ="Test"+QString::number(fRecordFrameNumber)+".ppm";
00804   QString filePath =fMovieTempFolderPath+fileName;
00805 
00806   QImage image;
00807   image = fWindow->grabFrameBuffer();
00808   bool res = false;
00809   
00810   res = image.save(filePath,0);
00811   if (res == false) { 
00812     resetRecording();
00813     setRecordingInfos("Can't save tmp file "+filePath);
00814     return;
00815   }
00816   
00817   setRecordingInfos("File "+fileName+" saved");
00818   fRecordFrameNumber++;
00819 }
00820 
00821 
00822 
00823 void G4OpenGLQtViewer::actionSaveImage() {
00824   QString filters;
00825   QList<QByteArray> formats =  QImageWriter::supportedImageFormats ();
00826   for (int i = 0; i < formats.size(); ++i) {
00827     filters +=formats.at(i) + ";;";
00828   }
00829   filters += "eps;;";
00830   filters += "ps;;";
00831   filters += "pdf";
00832   QString* selectedFormat = new QString();
00833   std::string name;
00834   name =  QFileDialog::getSaveFileName ( fGLWindow,
00835                                          tr("Save as ..."),
00836                                          ".",
00837                                          filters,
00838                                          selectedFormat ).toStdString().c_str(); 
00839   // bmp jpg jpeg png ppm xbm xpm
00840   if (name.empty()) {
00841     return;
00842   }
00843   name += "." + selectedFormat->toStdString();
00844   QString format = selectedFormat->toLower();
00845   setPrintFilename(name.c_str(),0);
00846   G4OpenGLQtExportDialog* exportDialog= new G4OpenGLQtExportDialog(fGLWindow,format,fWindow->height(),fWindow->width());
00847   if(  exportDialog->exec()) {
00848 
00849     QImage image;
00850     bool res = false;
00851     if ((exportDialog->getWidth() !=fWindow->width()) ||
00852         (exportDialog->getHeight() !=fWindow->height())) {
00853       setPrintSize(exportDialog->getWidth(),exportDialog->getHeight());
00854       if ((format != QString("eps")) && (format != QString("ps"))) {
00855         G4cerr << "Export->Change Size : This function is not implemented, to export in another size, please resize your frame to what you need" << G4endl;
00856       
00857         //    rescaleImage(exportDialog->getWidth(),exportDialog->getHeight());// re-scale image
00858         //      QGLWidget* glResized = fWindow;
00859 
00860         // FIXME :
00861         // L.Garnier : I've try to implement change size function, but the problem is 
00862         // the renderPixmap function call the QGLWidget to resize and it doesn't draw
00863         // the content of this widget... It only draw the background.
00864 
00865         //      fWindow->renderPixmap (exportDialog->getWidth()*2,exportDialog->getHeight()*2,true );
00866 
00867         //      QPixmap pixmap = fWindow->renderPixmap ();
00868       
00869         //      image = pixmap->toImage();
00870         //      glResized->resize(exportDialog->getWidth()*2,exportDialog->getHeight()*2);
00871         //      image = glResized->grabFrameBuffer();
00872       }      
00873     } else {
00874       image = fWindow->grabFrameBuffer();
00875     }    
00876     if (format == QString("eps")) {
00877       fVectoredPs = exportDialog->getVectorEPS();
00878       printEPS();
00879     } else if (format == "ps") {
00880       fVectoredPs = true;
00881       printEPS();
00882     } else if (format == "pdf") {
00883 
00884       res = printPDF(name,exportDialog->getNbColor(),image);
00885 
00886     } else if ((format == "tif") ||
00887                (format == "tiff") ||
00888                (format == "jpg") ||
00889                (format == "jpeg") ||
00890                (format == "png") ||
00891                (format == "pbm") ||
00892                (format == "pgm") ||
00893                (format == "ppm") ||
00894                (format == "bmp") ||
00895                (format == "xbm") ||
00896                (format == "xpm")) {
00897       res = image.save(QString(name.c_str()),0,exportDialog->getSliderValue());
00898     } else {
00899       G4cerr << "This version of G4UI Could not generate the selected format" << G4endl;
00900     }
00901     if ((format == QString("eps")) && (format == QString("ps"))) {
00902       if (res == false) {
00903         G4cerr << "Error while saving file... "<<name.c_str()<< G4endl;
00904       } else {
00905         G4cout << "File "<<name.c_str()<<" has been saved " << G4endl;
00906       }
00907     }
00908     
00909   } else { // cancel selected
00910     return;
00911   }
00912   
00913 }
00914 
00915 
00916 void G4OpenGLQtViewer::actionChangeBackgroundColor() {
00917 
00918   //   //I need to revisit the kernel if the background colour changes and
00919   //   //hidden line removal is enabled, because hlr drawing utilises the
00920   //   //background colour in its drawing...
00921   //   // (Note added by JA 13/9/2005) Background now handled in view
00922   //   // parameters.  A kernel visit is triggered on change of background.
00923 
00924 #if QT_VERSION < 0x040500
00925   bool a;
00926   const QColor color = QColor(QColorDialog::getRgba (QColor(Qt::black).rgba(),&a,fGLWindow));
00927 #else
00928   const QColor color =
00929     QColorDialog::getColor(Qt::black,
00930                            fGLWindow,
00931                            " Get background color and transparency",
00932                            QColorDialog::ShowAlphaChannel);
00933 #endif
00934   if (color.isValid()) {
00935     G4Colour colour(((G4double)color.red())/255,
00936                     ((G4double)color.green())/255,
00937                     ((G4double)color.blue())/255,
00938                     ((G4double)color.alpha())/255);
00939     fVP.SetBackgroundColour(colour);
00940 
00941     updateToolbarAndMouseContextMenu();
00942     updateQWidget();
00943   }
00944 }
00945 
00946 void G4OpenGLQtViewer::actionChangeTextColor() {
00947 
00948 #if QT_VERSION < 0x040500
00949   bool a;
00950   const QColor color = QColor(QColorDialog::getRgba (QColor(Qt::yellow).rgba(),&a,fGLWindow));
00951 #else
00952   const QColor& color =
00953     QColorDialog::getColor(Qt::yellow,
00954                            fGLWindow,
00955                            " Get text color and transparency",
00956                            QColorDialog::ShowAlphaChannel);
00957 #endif
00958   if (color.isValid()) {
00959     G4Colour colour(((G4double)color.red())/255,
00960                     ((G4double)color.green())/255,
00961                     ((G4double)color.blue())/255,
00962                     ((G4double)color.alpha())/255);
00963 
00964     fVP.SetDefaultTextColour(colour);
00965 
00966     updateToolbarAndMouseContextMenu();
00967     updateQWidget();
00968   }
00969 }
00970 
00971 void G4OpenGLQtViewer::actionChangeDefaultColor() {
00972 
00973 #if QT_VERSION < 0x040500
00974   bool a;
00975   const QColor color = QColor(QColorDialog::getRgba (QColor(Qt::white).rgba(),&a,fGLWindow));
00976 #else
00977   const QColor& color =
00978     QColorDialog::getColor(Qt::white,
00979                            fGLWindow,
00980                            " Get default color and transparency",
00981                            QColorDialog::ShowAlphaChannel);
00982 #endif
00983   if (color.isValid()) {
00984     G4Colour colour(((G4double)color.red())/255,
00985                     ((G4double)color.green())/255,
00986                     ((G4double)color.blue())/255,
00987                     ((G4double)color.alpha())/255);
00988 
00989     fVP.SetDefaultColour(colour);
00990 
00991     updateToolbarAndMouseContextMenu();
00992     updateQWidget();
00993   }
00994 }
00995 
00996 
00997 void G4OpenGLQtViewer::actionMovieParameters() {
00998   showMovieParametersDialog();
00999 }
01000 
01001 
01002 void G4OpenGLQtViewer::showMovieParametersDialog() {
01003   if (!fMovieParametersDialog) {
01004     fMovieParametersDialog= new G4OpenGLQtMovieDialog(this,fGLWindow);
01005     displayRecordingStatus();
01006     fMovieParametersDialog->checkEncoderSwParameters();
01007     fMovieParametersDialog->checkSaveFileNameParameters();
01008     fMovieParametersDialog->checkTempFolderParameters();
01009     if (getEncoderPath() == "") {
01010       setRecordingInfos("ppmtompeg is needed to encode in video format. It is available here: http://netpbm.sourceforge.net ");
01011     }
01012   }
01013   fMovieParametersDialog->show();
01014 }
01015 
01016 
01017 /*
01018 // 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
01019 
01020 void Graph::exportToSVG(const QString& fname)
01021 {
01022 // enable workaround for Qt3 misalignments
01023 QwtPainter::setSVGMode(true);
01024 QPicture picture;
01025 QPainter p(&picture);
01026 d_plot->print(&p, d_plot->rect());
01027 p.end();
01028 
01029 picture.save(fname, "svg");
01030 }
01031 */
01032 
01033 
01034 
01035 void G4OpenGLQtViewer::FinishView()
01036 {
01037   glFlush ();
01038 
01039   // L. Garnier 10/2009 : Not necessary and cause problems on mac OS X 10.6
01040   //  fWindow->swapBuffers ();
01041 }
01042 
01047 void G4OpenGLQtViewer::G4MousePressEvent(QMouseEvent *evnt)
01048 {
01049   if ((evnt->buttons() & Qt::LeftButton) && (! (evnt->modifiers() & Qt::ControlModifier ))){
01050     fWindow->setMouseTracking(true);
01051     fAutoMove = false; // stop automove
01052     fLastPos1 = evnt->pos();
01053     fLastPos2 = fLastPos1;
01054     fLastPos3 = fLastPos2;
01055     fLastEventTime->start();
01056     if (fUiQt != NULL) {
01057 
01058       if (fUiQt->IsIconPickSelected()){  // pick
01059         fVP.SetPicking(true);
01060         Pick(evnt->pos().x(),evnt->pos().y());
01061         fVP.SetPicking(false);
01062  
01063       } else if (fUiQt->IsIconZoomInSelected()) {  // zoomIn
01064         // Move click point to center of OGL
01065 
01066         float deltaX = ((float)getWinWidth()/2-evnt->pos().x());
01067         float deltaY = ((float)getWinHeight()/2-evnt->pos().y());
01068 
01069         G4double coefTrans = 0;
01070         coefTrans = ((G4double)getSceneNearWidth())/((G4double)getWinWidth());
01071         if (getWinHeight() <getWinWidth()) {
01072           coefTrans = ((G4double)getSceneNearWidth())/((G4double)getWinHeight());
01073         }
01074         fVP.IncrementPan(-deltaX*coefTrans,deltaY*coefTrans,0);
01075         fVP.SetZoomFactor(1.5 * fVP.GetZoomFactor());
01076   
01077         updateQWidget();
01078         
01079       } else if (fUiQt->IsIconZoomOutSelected()) {  // zoomOut
01080         // Move click point to center of OGL
01081         moveScene(((float)getWinWidth()/2-evnt->pos().x()),((float)getWinHeight()/2-evnt->pos().y()),0,true);
01082 
01083         fVP.SetZoomFactor(0.75 * fVP.GetZoomFactor());
01084         updateQWidget();
01085 
01086       }
01087     }
01088   }
01089 }
01090 
01093 void G4OpenGLQtViewer::G4MouseReleaseEvent()
01094 {
01095   fSpinningDelay = fLastEventTime->elapsed();
01096   QPoint delta = (fLastPos3-fLastPos1);
01097   if ((delta.x() == 0) && (delta.y() == 0)) {
01098     return;
01099   }
01100   if (fSpinningDelay < fLaunchSpinDelay ) {
01101     fAutoMove = true;
01102     QTime lastMoveTime;
01103     lastMoveTime.start();
01104     // try to addapt speed move/rotate looking to drawing speed
01105     float correctionFactor = 5;
01106     while (fAutoMove) {
01107       if ( lastMoveTime.elapsed() >= (int)(1000/fNbMaxFramesPerSec)) {
01108         float lTime = 1000/lastMoveTime.elapsed();
01109         if (((((float)delta.x())/correctionFactor)*lTime > fNbMaxAnglePerSec) ||
01110             ((((float)delta.x())/correctionFactor)*lTime < -fNbMaxAnglePerSec) ) {
01111           correctionFactor = (float)delta.x()*(lTime/fNbMaxAnglePerSec);
01112           if (delta.x() <0 ) {
01113             correctionFactor = -correctionFactor;
01114           }
01115         }
01116         if (((((float)delta.y())/correctionFactor)*lTime > fNbMaxAnglePerSec) ||
01117             ((((float)delta.y())/correctionFactor)*lTime < -fNbMaxAnglePerSec) ) {
01118           correctionFactor = (float)delta.y()*(lTime/fNbMaxAnglePerSec);
01119           if (delta.y() <0 ) {
01120             correctionFactor = -correctionFactor;
01121           }
01122         }
01123                 
01124         // Check Qt Versions for META Keys
01125                 
01126         // Click and move mouse to rotate volume
01127         // ALT + Click and move mouse to rotate volume (View Direction)
01128         // SHIFT + Click and move camera point of view
01129         // CTRL + Click and zoom mouse to zoom in/out
01130 
01131         lastMoveTime.start();
01132 
01133         bool rotate = false;
01134         bool move = false;
01135 
01136         if (fUiQt != NULL) {
01137           if (fUiQt->IsIconRotateSelected()) {  // rotate
01138             rotate = true;
01139           } else if (fUiQt->IsIconMoveSelected()) {  // move
01140             move = true;
01141           }
01142         } else {
01143           rotate = true;
01144         }
01145         if (rotate) {  // rotate
01146           if (fNoKeyPress) {
01147             rotateQtScene(((float)delta.x())/correctionFactor,((float)delta.y())/correctionFactor);
01148           } else if (fAltKeyPress) {
01149             rotateQtSceneToggle(((float)delta.x())/correctionFactor,((float)delta.y())/correctionFactor);
01150           }
01151 #ifdef G4DEBUG_VIS_OGL
01152           fNbRotation ++;
01153           fTimeRotation += lastMoveTime.elapsed();
01154           printf("G4OpenGLQtViewer %f \n",fTimeRotation/(float)fNbRotation);
01155 #endif
01156           
01157         } else if (move) {  // move
01158           moveScene(-((float)delta.x())/correctionFactor,-((float)delta.y())/correctionFactor,0,true);
01159         }
01160       }
01161       ((QApplication*)G4Qt::getInstance ())->processEvents();
01162     }
01163   }
01164   fWindow->setMouseTracking(false);
01165 
01166 }
01167 
01168 
01169 void G4OpenGLQtViewer::G4MouseDoubleClickEvent()
01170 {
01171   fWindow->setMouseTracking(true);
01172 }
01173 
01174 
01182 void G4OpenGLQtViewer::G4MouseMoveEvent(QMouseEvent *evnt)
01183 {
01184 
01185   Qt::MouseButtons mButtons = evnt->buttons();
01186 
01187   updateKeyModifierState(evnt->modifiers());
01188 
01189   if (fAutoMove) {
01190     return;
01191   }
01192 
01193   fLastPos3 = fLastPos2;
01194   fLastPos2 = fLastPos1;
01195   fLastPos1 = QPoint(evnt->x(), evnt->y());
01196 
01197   int deltaX = fLastPos2.x()-fLastPos1.x();
01198   int deltaY = fLastPos2.y()-fLastPos1.y();
01199 
01200   bool rotate = false;
01201   bool move = false;
01202   if (fUiQt != NULL) {
01203     if (fUiQt->IsIconRotateSelected()) {  // rotate
01204       rotate = true;
01205     } else if (fUiQt->IsIconMoveSelected()) {  // move
01206       move = true;
01207     }
01208   } else {
01209     rotate = true;
01210   }
01211   if (rotate) {  // rotate
01212     if (mButtons & Qt::LeftButton) {
01213       if (fNoKeyPress) {
01214         rotateQtScene(((float)deltaX),((float)deltaY));
01215       } else if (fAltKeyPress) {
01216         rotateQtSceneToggle(((float)deltaX),((float)deltaY));
01217       } else if (fShiftKeyPress) {
01218         unsigned int sizeWin;
01219         sizeWin = getWinWidth();
01220         if (getWinHeight() < getWinWidth()) {
01221           sizeWin = getWinHeight();
01222         }
01223 
01224         // L.Garnier : 08/2010 100 is the good value, but don't ask me why !
01225         float factor = ((float)100/(float)sizeWin) ;
01226         moveScene(-(float)deltaX*factor,-(float)deltaY*factor,0,false);
01227       } else if (fControlKeyPress) {
01228         fVP.SetZoomFactor(fVP.GetZoomFactor()*(1+((float)deltaY))); 
01229       }
01230     }
01231   } else if (move) {  // move
01232     if (mButtons & Qt::LeftButton) {
01233       moveScene(-(float)deltaX,-(float)deltaY,0,true);
01234     }
01235   }
01236 
01237   fLastEventTime->start();
01238 }
01239 
01240 
01248 void G4OpenGLQtViewer::moveScene(float dx,float dy, float dz,bool mouseMove)
01249 {
01250   if (fHoldMoveEvent)
01251     return;
01252   fHoldMoveEvent = true;
01253 
01254   G4double coefTrans = 0;
01255   GLdouble coefDepth = 0;
01256   if(mouseMove) {
01257     coefTrans = ((G4double)getSceneNearWidth())/((G4double)getWinWidth());
01258     if (getWinHeight() <getWinWidth()) {
01259       coefTrans = ((G4double)getSceneNearWidth())/((G4double)getWinHeight());
01260     }
01261   } else {
01262     coefTrans = getSceneNearWidth()*fPan_sens;
01263     coefDepth = getSceneDepth()*fDeltaDepth;
01264   }
01265   fVP.IncrementPan(-dx*coefTrans,dy*coefTrans,dz*coefDepth);
01266   
01267   updateQWidget();
01268   if (fAutoMove)
01269     ((QApplication*)G4Qt::getInstance ())->processEvents();
01270   
01271   fHoldMoveEvent = false;
01272 }
01273 
01274 
01280 void G4OpenGLQtViewer::rotateQtScene(float dx, float dy)
01281 {
01282   if (fHoldRotateEvent)
01283     return;
01284   fHoldRotateEvent = true;
01285   
01286   rotateScene(dx,dy);
01287 
01288   updateQWidget();
01289   
01290   fHoldRotateEvent = false;
01291 }
01292 
01298 void G4OpenGLQtViewer::rotateQtSceneToggle(float dx, float dy)
01299 {
01300   if (fHoldRotateEvent)
01301     return;
01302   fHoldRotateEvent = true;
01303   
01304   rotateSceneToggle(dx,dy);
01305 
01306   updateQWidget();
01307   
01308   fHoldRotateEvent = false;
01309 }
01310 
01311 
01312 
01313 
01314 
01319 void G4OpenGLQtViewer::rescaleImage(
01320  int /* aWidth */
01321 ,int /* aHeight */
01322 ){
01323   //  GLfloat* feedback_buffer;
01324   //  GLint returned;
01325   //  FILE* file;
01326   
01327   //   feedback_buffer = new GLfloat[size];
01328   //   glFeedbackBuffer (size, GL_3D_COLOR, feedback_buffer);
01329   //   glRenderMode (GL_FEEDBACK);
01330   
01331   //   DrawView();
01332   //   returned = glRenderMode (GL_RENDER);
01333 
01334 }
01335 
01336 
01337 
01344 bool G4OpenGLQtViewer::printPDF (
01345  const std::string aFilename
01346  ,int aInColor
01347  ,QImage aImage
01348 )
01349 {
01350 
01351   QPrinter printer;
01352   //  printer.setPageSize(pageSize);
01353 
01354   // FIXME : L. Garnier 4/12/07
01355   // This is not working, it does nothing. Image is staying in color mode
01356   // So I have desactivate the B/W button in GUI
01357   if ((!aImage.isGrayscale ()) &&(aInColor ==1 )) {
01358     aImage = aImage.convertToFormat ( aImage.format(), Qt::MonoOnly);
01359   }
01360 
01361 
01362   if (aFilename.substr(aFilename.size()-3) == ".ps") {
01363 #if QT_VERSION > 0x040200
01364     printer.setOutputFormat(QPrinter::PostScriptFormat);
01365 #endif
01366   } else {
01367 #if QT_VERSION > 0x040100
01368     printer.setOutputFormat(QPrinter::PdfFormat);
01369 #endif
01370   }
01371 #if QT_VERSION > 0x040100
01372   printer.setOutputFileName(QString(aFilename.c_str()));
01373 #endif
01374   //  printer.setFullPage ( true);
01375   QPainter paint(&printer);
01376   paint.drawImage (0,0,aImage);
01377   paint.end();
01378   return true;
01379 }
01380 
01381 
01382 void G4OpenGLQtViewer::G4wheelEvent (QWheelEvent * evnt) 
01383 {
01384   fVP.SetZoomFactor(fVP.GetZoomFactor()+(fVP.GetZoomFactor()*(evnt->delta())/1200)); 
01385   updateQWidget();
01386 }
01387 
01388 
01389 void G4OpenGLQtViewer::G4keyPressEvent (QKeyEvent * evnt) 
01390 {
01391   if (fHoldKeyEvent)
01392     return;
01393 
01394   fHoldKeyEvent = true;
01395 
01396   
01397   // with no modifiers
01398   updateKeyModifierState(evnt->modifiers());
01399   if ((fNoKeyPress) || (evnt->modifiers() == Qt::KeypadModifier )) {
01400     if (evnt->key() == Qt::Key_Down) { // go down
01401       moveScene(0,1,0,false);
01402     }
01403     else if (evnt->key() == Qt::Key_Up) {  // go up
01404       moveScene(0,-1,0,false);
01405     }
01406     if (evnt->key() == Qt::Key_Left) { // go left
01407       moveScene(-1,0,0,false);
01408     }
01409     else if (evnt->key() == Qt::Key_Right) { // go right
01410       moveScene(1,0,0,false);
01411     }
01412     if (evnt->key() == Qt::Key_Minus) { // go backward
01413       moveScene(0,0,1,false);
01414     }
01415     else if (evnt->key() == Qt::Key_Plus) { // go forward
01416       moveScene(0,0,-1,false);
01417     }
01418 
01419     // escaped from full screen
01420     if (evnt->key() == Qt::Key_Escape) {
01421       toggleFullScreen(false);
01422     }
01423   }    
01424   // several case here : If return is pressed, in every case -> display the movie parameters dialog
01425   // If one parameter is wrong -> put it in red (only save filenam could be wrong..)
01426   // If encoder not found-> does nothing.Only display a message in status box
01427   // If all ok-> generate parameter file
01428   // If ok -> put encoder button enabled
01429   
01430   if ((evnt->key() == Qt::Key_Return) || (evnt->key() == Qt::Key_Enter)){ // end of video
01431     stopVideo();
01432   }
01433   if (evnt->key() == Qt::Key_Space){ // start/pause of video
01434     startPauseVideo();
01435   }
01436   
01437   // H : Return Home view
01438   if (evnt->key() == Qt::Key_H){ // go Home
01439     ResetView();
01440 
01441     updateQWidget();
01442   }
01443 
01444   // Shift Modifier
01445   if (fShiftKeyPress) {
01446     if (evnt->key() == Qt::Key_Down) { // rotate phi
01447       rotateQtScene(0,-fRot_sens);
01448     }
01449     else if (evnt->key() == Qt::Key_Up) { // rotate phi
01450       rotateQtScene(0,fRot_sens);
01451     }
01452     if (evnt->key() == Qt::Key_Left) { // rotate theta
01453       rotateQtScene(fRot_sens,0);
01454     }
01455     else if (evnt->key() == Qt::Key_Right) { // rotate theta
01456       rotateQtScene(-fRot_sens,0);
01457     }
01458     if (evnt->key() == Qt::Key_Plus) { // go forward  ("Plus" imply 
01459       // "Shift" on Mac French keyboard
01460       moveScene(0,0,-1,false);
01461     }
01462 
01463     // Alt Modifier
01464   }
01465   if ((fAltKeyPress)) {
01466     if (evnt->key() == Qt::Key_Down) { // rotate phi
01467       rotateQtSceneToggle(0,-fRot_sens);
01468     }
01469     else if (evnt->key() == Qt::Key_Up) { // rotate phi
01470       rotateQtSceneToggle(0,fRot_sens);
01471     }
01472     if (evnt->key() == Qt::Key_Left) { // rotate theta
01473       rotateQtSceneToggle(fRot_sens,0);
01474     }
01475     else if (evnt->key() == Qt::Key_Right) { // rotate theta
01476       rotateQtSceneToggle(-fRot_sens,0);
01477     }
01478 
01479     // Rotatio +/-
01480     if (evnt->key() == Qt::Key_Plus) {
01481       fRot_sens = fRot_sens/0.7;
01482       G4cout << "Auto-rotation set to : " << fRot_sens << G4endl;
01483     }
01484     else if (evnt->key() == Qt::Key_Minus) {
01485       fRot_sens = fRot_sens*0.7;
01486       G4cout << "Auto-rotation set to : " << fRot_sens << G4endl;
01487     }
01488 
01489     // Control Modifier OR Command on MAC
01490   }
01491   if ((fControlKeyPress)) {
01492     if (evnt->key() == Qt::Key_Plus) {
01493       fVP.SetZoomFactor(fVP.GetZoomFactor()*(1+fDeltaZoom)); 
01494       updateQWidget();
01495     }
01496     else if (evnt->key() == Qt::Key_Minus) {
01497       fVP.SetZoomFactor(fVP.GetZoomFactor()*(1-fDeltaZoom)); 
01498       updateQWidget();
01499     }
01500   }  
01501   
01502   fHoldKeyEvent = false;
01503 }
01504   
01505 
01506 void  G4OpenGLQtViewer::updateKeyModifierState(const Qt::KeyboardModifiers& modifier) {
01507   // Check Qt Versions for META Keys
01508     
01509   fNoKeyPress = true;
01510   fAltKeyPress = false;
01511   fShiftKeyPress = false;
01512   fControlKeyPress = false;
01513   
01514   if (modifier & Qt::AltModifier ) {
01515     fAltKeyPress = true;
01516     fNoKeyPress = false;
01517   }
01518   if (modifier & Qt::ShiftModifier ) {
01519     fShiftKeyPress = true;
01520     fNoKeyPress = false;
01521   }
01522   if (modifier & Qt::ControlModifier ) {
01523     fControlKeyPress = true;
01524     fNoKeyPress = false;
01525   }
01526 }
01527 
01528 
01531 void G4OpenGLQtViewer::stopVideo() {
01532 
01533   // if encoder parameter is wrong, display parameters dialog and return
01534   if (!fMovieParametersDialog) {
01535     showMovieParametersDialog();
01536   }
01537   setRecordingStatus(STOP);
01538 
01539   if (fRecordFrameNumber >0) {
01540     // check parameters if they were modified (Re APPLY them...)
01541     if (!(fMovieParametersDialog->checkEncoderSwParameters())) {
01542       setRecordingStatus(BAD_ENCODER);
01543     }  else if (!(fMovieParametersDialog->checkSaveFileNameParameters())) {
01544       setRecordingStatus(BAD_OUTPUT);
01545     }
01546   } else {
01547     resetRecording();
01548     setRecordingInfos("No frame to encode.");
01549   }
01550 }
01551 
01554 void G4OpenGLQtViewer::saveVideo() {
01555 
01556   // if encoder parameter is wrong, display parameters dialog and return
01557   if (!fMovieParametersDialog) {
01558     showMovieParametersDialog();
01559   }
01560 
01561   fMovieParametersDialog->checkEncoderSwParameters();
01562   fMovieParametersDialog->checkSaveFileNameParameters();
01563   
01564   if (fRecordingStep == STOP) {
01565     setRecordingStatus(SAVE);
01566     generateMpegEncoderParameters();
01567     encodeVideo();
01568   }
01569 }
01570 
01571 
01574 void G4OpenGLQtViewer::startPauseVideo() {
01575    
01576   // first time, if temp parameter is wrong, display parameters dialog and return
01577 
01578   if ( fRecordingStep == WAIT) {
01579     if ( fRecordFrameNumber == 0) {
01580       if (getTempFolderPath() == "") { // BAD_OUTPUT
01581         showMovieParametersDialog();
01582         setRecordingInfos("You should specified the temp folder in order to make movie");
01583         return;
01584       } else  {
01585         // remove temp folder if it was create
01586         QString tmp = removeTempFolder();
01587         if (tmp !="") {
01588           setRecordingInfos(tmp);
01589           return;
01590         }
01591         tmp = createTempFolder();
01592         if (tmp != "") {
01593           setRecordingInfos("Can't create temp folder."+tmp);
01594           return;
01595         }
01596       }
01597     }
01598   }
01599   if (fRecordingStep == WAIT) {
01600     setRecordingStatus(START); 
01601   } else if (fRecordingStep == START) {
01602     setRecordingStatus(PAUSE);
01603   } else if (fRecordingStep == PAUSE) {
01604     setRecordingStatus(CONTINUE);
01605   } else if (fRecordingStep == CONTINUE) {
01606     setRecordingStatus(PAUSE);
01607   }
01608 }
01609 
01610 void G4OpenGLQtViewer::setRecordingStatus(RECORDING_STEP step) {
01611 
01612   fRecordingStep = step;
01613   displayRecordingStatus();
01614 }
01615 
01616 
01617 void G4OpenGLQtViewer::displayRecordingStatus() {
01618   
01619   QString txtStatus = "";
01620   if (fRecordingStep == WAIT) {
01621     txtStatus  = "Waiting to start...";
01622     fRecordFrameNumber = 0; // reset the frame number
01623   } else if (fRecordingStep == START) {
01624     txtStatus  = "Start Recording...";
01625   } else if (fRecordingStep == PAUSE) {
01626     txtStatus  = "Pause Recording...";
01627   } else if (fRecordingStep == CONTINUE) {
01628     txtStatus  = "Continue Recording...";
01629   } else if (fRecordingStep == STOP) {
01630     txtStatus  = "Stop Recording...";
01631   } else if (fRecordingStep == READY_TO_ENCODE) {
01632     txtStatus  = "Ready to Encode...";
01633   } else if (fRecordingStep == ENCODING) {
01634     txtStatus  = "Encoding...";
01635   } else if (fRecordingStep == FAILED) {
01636     txtStatus  = "Failed to encode...";
01637   } else if ((fRecordingStep == BAD_ENCODER)
01638              || (fRecordingStep == BAD_OUTPUT)
01639              || (fRecordingStep == BAD_TMP)) {
01640     txtStatus  = "Correct above errors first";
01641   } else if (fRecordingStep == SUCCESS) {
01642     txtStatus  = "File encoded successfully";
01643   } else {
01644   }
01645 
01646   if (fMovieParametersDialog) {
01647     fMovieParametersDialog->setRecordingStatus(txtStatus);
01648   } else {
01649     G4cout << txtStatus.toStdString().c_str() << G4endl;
01650   }
01651   setRecordingInfos("");
01652 }
01653 
01654 
01655 void G4OpenGLQtViewer::setRecordingInfos(const QString& txt) {
01656   if (fMovieParametersDialog) {
01657     fMovieParametersDialog->setRecordingInfos(txt);
01658   } else {
01659     G4cout << txt.toStdString().c_str() << G4endl;
01660   }
01661 }
01662 
01665 void G4OpenGLQtViewer::initMovieParameters() {
01666   //init encoder
01667   
01668   //look for encoderPath
01669   fProcess = new QProcess();
01670      
01671   QObject ::connect(fProcess,SIGNAL(finished ( int)),
01672                     this,SLOT(processLookForFinished()));
01673   fProcess->setReadChannelMode(QProcess::MergedChannels);
01674   fProcess->start ("which ppmtompeg");
01675   
01676 }
01677 
01680 QString G4OpenGLQtViewer::getEncoderPath() {
01681   return fEncoderPath;
01682 }
01683  
01684 
01689 QString G4OpenGLQtViewer::setEncoderPath(QString path) {
01690   if (path == "") {
01691     return "File does not exist";
01692   }
01693 
01694   path =  QDir::cleanPath(path);
01695   QFileInfo *f = new QFileInfo(path);
01696   if (!f->exists()) {
01697     return "File does not exist";
01698   } else if (f->isDir()) {
01699     return "This is a directory";
01700   } else if (!f->isExecutable()) {
01701     return "File exist but is not executable";
01702   } else if (!f->isFile()) {
01703     return "This is not a file";
01704   }
01705   fEncoderPath = path;
01706 
01707   if (fRecordingStep == BAD_ENCODER) {
01708     setRecordingStatus(STOP);
01709   } 
01710   return "";
01711 }
01712 
01713 
01714 bool G4OpenGLQtViewer::isRecording(){
01715   if ((fRecordingStep == START) || (fRecordingStep == CONTINUE)) {
01716     return true;
01717   }
01718   return false;
01719 }
01720 
01721 bool G4OpenGLQtViewer::isPaused(){
01722   if (fRecordingStep == PAUSE) {
01723     return true;
01724   }
01725   return false;
01726 }
01727 
01728 bool G4OpenGLQtViewer::isEncoding(){
01729   if (fRecordingStep == ENCODING) {
01730     return true;
01731   }
01732   return false;
01733 }
01734 
01735 bool G4OpenGLQtViewer::isWaiting(){
01736   if (fRecordingStep == WAIT) {
01737     return true;
01738   }
01739   return false;
01740 }
01741 
01742 bool G4OpenGLQtViewer::isStopped(){
01743   if (fRecordingStep == STOP) {
01744     return true;
01745   }
01746   return false;
01747 }
01748 
01749 bool G4OpenGLQtViewer::isFailed(){
01750   if (fRecordingStep == FAILED) {
01751     return true;
01752   }
01753   return false;
01754 }
01755 
01756 bool G4OpenGLQtViewer::isSuccess(){
01757   if (fRecordingStep == SUCCESS) {
01758     return true;
01759   }
01760   return false;
01761 }
01762 
01763 bool G4OpenGLQtViewer::isBadEncoder(){
01764   if (fRecordingStep == BAD_ENCODER) {
01765     return true;
01766   }
01767   return false;
01768 }
01769 bool G4OpenGLQtViewer::isBadTmp(){
01770   if (fRecordingStep == BAD_TMP) {
01771     return true;
01772   }
01773   return false;
01774 }
01775 bool G4OpenGLQtViewer::isBadOutput(){
01776   if (fRecordingStep == BAD_OUTPUT) {
01777     return true;
01778   }
01779   return false;
01780 }
01781 
01782 void G4OpenGLQtViewer::setBadEncoder(){
01783   fRecordingStep = BAD_ENCODER;
01784   displayRecordingStatus();
01785 }
01786 void G4OpenGLQtViewer::setBadTmp(){
01787   fRecordingStep = BAD_TMP;
01788   displayRecordingStatus();
01789 }
01790 void G4OpenGLQtViewer::setBadOutput(){
01791   fRecordingStep = BAD_OUTPUT;
01792   displayRecordingStatus();
01793 }
01794 
01795 void G4OpenGLQtViewer::setWaiting(){
01796   fRecordingStep = WAIT;
01797   displayRecordingStatus();
01798 }
01799 
01800 
01801 bool G4OpenGLQtViewer::isReadyToEncode(){
01802   if (fRecordingStep == READY_TO_ENCODE) {
01803     return true;
01804   }
01805   return false;
01806 }
01807 
01808 void G4OpenGLQtViewer::resetRecording() {
01809   setRecordingStatus(WAIT);
01810 }
01811 
01816 QString G4OpenGLQtViewer::setTempFolderPath(QString path) {
01817 
01818   if (path == "") {
01819     return "Path does not exist";
01820   }
01821   path =  QDir::cleanPath(path);
01822   QFileInfo *d = new QFileInfo(path);
01823   if (!d->exists()) {
01824     return "Path does not exist";
01825   } else if (!d->isDir()) {
01826     return "This is not a directory";
01827   } else if (!d->isReadable()) {
01828     return path +" is read protected";
01829   } else if (!d->isWritable()) {
01830     return path +" is write protected";
01831   }
01832   
01833   if (fRecordingStep == BAD_TMP) {
01834     setRecordingStatus(WAIT); 
01835   }
01836   fTempFolderPath = path;
01837   return "";
01838 }
01839 
01842 QString G4OpenGLQtViewer::getTempFolderPath() {
01843   return fTempFolderPath;
01844 }
01845  
01850 QString G4OpenGLQtViewer::setSaveFileName(QString path) {
01851 
01852   if (path == "") {
01853     return "Path does not exist";
01854   }
01855   
01856   QFileInfo *file = new QFileInfo(path);
01857   QDir dir = file->dir();
01858   path =  QDir::cleanPath(path);
01859   if (file->exists()) {
01860     return "File already exist, please choose a new one";
01861   } else if (!dir.exists()) {
01862     return "Dir does not exist";
01863   } else if (!dir.isReadable()) {
01864     return path +" is read protected";
01865   }
01866   
01867   if (fRecordingStep == BAD_OUTPUT) {
01868     setRecordingStatus(STOP); 
01869   }
01870   fSaveFileName = path;
01871   return "";
01872 }
01873 
01876 QString G4OpenGLQtViewer::getSaveFileName() {
01877   return fSaveFileName ;
01878 }
01879 
01884 QString G4OpenGLQtViewer::createTempFolder() {
01885   fMovieTempFolderPath = "";
01886   //check
01887   QString tmp = setTempFolderPath(fTempFolderPath);
01888   if (tmp != "") {
01889     return tmp;
01890   }
01891   QString sep = QString(QDir::separator());
01892   QString path = sep+"QtMovie_"+QDateTime::currentDateTime ().toString("dd-MM-yyyy_hh-mm-ss")+sep; 
01893   QDir *d = new QDir(QDir::cleanPath(fTempFolderPath));
01894   // check if it is already present
01895   if (d->exists(path)) {
01896     return "Folder "+path+" already exists.Please remove it first";
01897   }
01898   if (d->mkdir(fTempFolderPath+path)) {
01899     fMovieTempFolderPath = fTempFolderPath+path;
01900     return "";
01901   }
01902   return "Can't create "+fTempFolderPath+path;
01903 }
01904 
01907 QString G4OpenGLQtViewer::removeTempFolder() {
01908   // remove files in Qt_temp folder
01909   if (fMovieTempFolderPath == "") {
01910     return "";
01911   }
01912   QDir *d = new QDir(QDir::cleanPath(fMovieTempFolderPath));
01913   if (!d->exists()) {
01914     return "";  // already remove
01915   }
01916 
01917   d->setFilter( QDir::Files );
01918   QStringList subDirList = d->entryList();
01919   int res = true;
01920   QString error = "";
01921   for (QStringList::ConstIterator it = subDirList.begin() ;(it != subDirList.end()) ; it++) {
01922     const QString currentFile = *it;
01923     if (!d->remove(currentFile)) {
01924       res = false;
01925       QString file = fMovieTempFolderPath+currentFile;
01926       error +="Removing file failed : "+file;
01927     } else {
01928     }
01929   }
01930   if (res) {
01931     if (d->rmdir(fMovieTempFolderPath)) {
01932       fMovieTempFolderPath = "";
01933       return "";
01934     } else {
01935       return "Dir "+fMovieTempFolderPath+" should be empty, but could not remove it";
01936     }
01937 
01938   }
01939   return "Could not remove "+fMovieTempFolderPath+" because of the following errors :"+error;
01940 }
01941 
01942 
01943 
01944 bool G4OpenGLQtViewer::hasPendingEvents () {
01945   return ((QApplication*)G4Qt::getInstance ())->hasPendingEvents ();
01946 }
01947 
01948 bool G4OpenGLQtViewer::generateMpegEncoderParameters () {
01949 
01950   // save the parameter file
01951   FILE* fp;
01952   fp = fopen (QString(fMovieTempFolderPath+fParameterFileName).toStdString().c_str(), "w");
01953 
01954   if (fp == NULL) {
01955     setRecordingInfos("Generation of parameter file failed");
01956     return false;
01957   }
01958 
01959   fprintf (fp,"# Pattern affects speed, quality and compression. See the User's Guide\n");
01960   fprintf (fp,"# for more info.\n");
01961   fprintf (fp,"\n");
01962   fprintf (fp,"PATTERN          IBBPBBPBBPBBPBBP\n");
01963   fprintf (fp,"OUTPUT           %s\n",getSaveFileName().toStdString().c_str());
01964   fprintf (fp,"\n");
01965   fprintf (fp,"# You must specify the type of the input files.  The choices are:\n");
01966   fprintf (fp,"#    YUV, PPM, JMOVIE, Y, JPEG, PNM\n");
01967   fprintf (fp,"#        (must be upper case)\n");
01968   fprintf (fp,"#\n");
01969   fprintf (fp,"BASE_FILE_FORMAT PPM\n");
01970   fprintf (fp,"\n");
01971   fprintf (fp,"#\n");
01972   fprintf (fp,"# if YUV format (or using parallel version), must provide width and height\n");
01973   fprintf (fp,"# YUV_SIZE       widthxheight\n");
01974   fprintf (fp,"# this option is ignored if BASE_FILE_FORMAT is not YUV and you're running\n");
01975   fprintf (fp,"# on just one machine\n");
01976   fprintf (fp,"#\n");
01977   fprintf (fp,"YUV_SIZE 352x240\n");
01978   fprintf (fp,"\n");
01979   fprintf (fp,"# If you are using YUV, there are different supported file formats.\n");
01980   fprintf (fp,"# EYUV or UCB are the same as previous versions of this encoder.\n");
01981   fprintf (fp,"# (All the Y's, then U's then V's, in 4:2:0 subsampling.)\n");
01982   fprintf (fp,"# Other formats, such as Abekas, Phillips, or a general format are\n");
01983   fprintf (fp,"# permissible, the general format is a string of Y's, U's, and V's\n");
01984   fprintf (fp,"# to specify the file order.\n");
01985   fprintf (fp,"\n");
01986   fprintf (fp,"INPUT_FORMAT UCB\n");
01987   fprintf (fp,"\n");
01988   fprintf (fp,"# the conversion statement\n");
01989   fprintf (fp,"#\n");
01990   fprintf (fp,"# Each occurrence of '*' will be replaced by the input file\n");
01991   fprintf (fp,"#\n");
01992   fprintf (fp,"# e.g., if you have a bunch of GIF files, then this might be:\n");
01993   fprintf (fp,"#        INPUT_CONVERT   giftoppm *\n");
01994   fprintf (fp,"#\n");
01995   fprintf (fp,"# e.g., if you have a bunch of files like a.Y a.U a.V, etc., then:\n");
01996   fprintf (fp,"#        INPUT_CONVERT   cat *.Y *.U *.V\n");
01997   fprintf (fp,"#\n");
01998   fprintf (fp,"# e.g., if you are grabbing from laser disc you might have something like\n");
01999   fprintf (fp,"#        INPUT_CONVERT   goto frame *; grabppm\n");
02000   fprintf (fp,"# 'INPUT_CONVERT *' means the files are already in the base file format\n");
02001   fprintf (fp,"#\n");
02002   fprintf (fp,"INPUT_CONVERT    * \n");
02003   fprintf (fp,"\n");
02004   fprintf (fp,"# number of frames in a GOP.\n");
02005   fprintf (fp,"#\n");
02006   fprintf (fp,"# since each GOP must have at least one I-frame, the encoder will find the\n");
02007   fprintf (fp,"# the first I-frame after GOP_SIZE frames to start the next GOP\n");
02008   fprintf (fp,"#\n");
02009   fprintf (fp,"# later, will add more flexible GOP signalling\n");
02010   fprintf (fp,"#\n");
02011   fprintf (fp,"GOP_SIZE 16\n");
02012   fprintf (fp,"\n");
02013   fprintf (fp,"# number of slices in a frame\n");
02014   fprintf (fp,"#\n");
02015   fprintf (fp,"# 1 is a good number.  another possibility is the number of macroblock rows\n");
02016   fprintf (fp,"# (which is the height divided by 16)\n");
02017   fprintf (fp,"#\n");
02018   fprintf (fp,"SLICES_PER_FRAME 1\n");
02019   fprintf (fp,"\n");
02020   fprintf (fp,"# directory to get all input files from (makes this file easier to read)\n");
02021   fprintf (fp,"INPUT_DIR        %s\n",fMovieTempFolderPath.toStdString().c_str());
02022   fprintf (fp,"\n");
02023   fprintf (fp,"# There are a bunch of ways to specify the input files.\n");
02024   fprintf (fp,"# from a simple one-per-line listing, to the following \n");
02025   fprintf (fp,"# way of numbering them.  See the manual for more information.\n");
02026   fprintf (fp,"INPUT\n");
02027   fprintf (fp,"# '*' is replaced by the numbers 01, 02, 03, 04\n");
02028   fprintf (fp,"# if I instead do [01-11], it would be 01, 02, ..., 09, 10, 11\n");
02029   fprintf (fp,"# if I instead do [1-11], it would be 1, 2, 3, ..., 9, 10, 11\n");
02030   fprintf (fp,"# if I instead do [1-11+3], it would be 1, 4, 7, 10\n");
02031   fprintf (fp,"# the program assumes none of your input files has a name ending in ']'\n");
02032   fprintf (fp,"# if you do, too bad!!!\n");
02033   fprintf (fp,"#\n");
02034   fprintf (fp,"#\n");
02035   fprintf (fp,"Test*.ppm        [0-%d]\n",fRecordFrameNumber-1);
02036   fprintf (fp,"# can have more files here if you want...there is no limit on the number\n");
02037   fprintf (fp,"# of files\n");
02038   fprintf (fp,"END_INPUT\n");
02039   fprintf (fp,"\n");
02040   fprintf (fp,"\n");
02041   fprintf (fp,"\n");
02042   fprintf (fp,"# Many of the remaining options have to do with the motion search and qscale\n");
02043   fprintf (fp,"\n");
02044   fprintf (fp,"# FULL or HALF -- must be upper case\n");
02045   fprintf (fp,"# Should be FULL for computer generated images\n");
02046   fprintf (fp,"PIXEL            FULL\n");
02047   fprintf (fp,"\n");
02048   fprintf (fp,"# means +/- this many pixels for both P and B frame searches\n");
02049   fprintf (fp,"# specify two numbers if you wish to serc different ranges in the two.\n");
02050   fprintf (fp,"RANGE            10\n");
02051   fprintf (fp,"\n");
02052   fprintf (fp,"# The two search algorithm parameters below mostly affect speed,\n");
02053   fprintf (fp,"# with some affect on compression and almost none on quality.\n");
02054   fprintf (fp,"\n");
02055   fprintf (fp,"# this must be one of {EXHAUSTIVE, SUBSAMPLE, LOGARITHMIC}\n");
02056   fprintf (fp,"PSEARCH_ALG      LOGARITHMIC\n");
02057   fprintf (fp,"\n");
02058   fprintf (fp,"# this must be one of {SIMPLE, CROSS2, EXHAUSTIVE}\n");
02059   fprintf (fp,"#\n");
02060   fprintf (fp,"# note that EXHAUSTIVE is really, really, really slow\n");
02061   fprintf (fp,"#\n");
02062   fprintf (fp,"BSEARCH_ALG      SIMPLE\n");
02063   fprintf (fp,"\n");
02064   fprintf (fp,"#\n");
02065   fprintf (fp,"# these specify the q-scale for I, P, and B frames\n");
02066   fprintf (fp,"# (values must be between 1 and 31)\n");
02067   fprintf (fp,"# These are the Qscale values for the entire frame in variable bit-rate\n");
02068   fprintf (fp,"# mode, and starting points (but not important) for constant bit rate\n");
02069   fprintf (fp,"#\n");
02070   fprintf (fp,"\n");
02071   fprintf (fp,"# Qscale (Quantization scale) affects quality and compression,\n");
02072   fprintf (fp,"# but has very little effect on speed.\n");
02073   fprintf (fp,"\n");
02074   fprintf (fp,"IQSCALE          4\n");
02075   fprintf (fp,"PQSCALE          5\n");
02076   fprintf (fp,"BQSCALE          12\n");
02077   fprintf (fp,"\n");
02078   fprintf (fp,"# this must be ORIGINAL or DECODED\n");
02079   fprintf (fp,"REFERENCE_FRAME  ORIGINAL\n");
02080   fprintf (fp,"\n");
02081   fprintf (fp,"# for parallel parameters see parallel.param in the exmaples subdirectory\n");
02082   fprintf (fp,"\n");
02083   fprintf (fp,"# if you want constant bit-rate mode, specify it as follows (number is bits/sec):\n");
02084   fprintf (fp,"#BIT_RATE  1000000\n");
02085   fprintf (fp,"\n");
02086   fprintf (fp,"# To specify the buffer size (327680 is default, measused in bits, for 16bit words)\n");
02087   fprintf (fp,"BUFFER_SIZE 327680\n");
02088   fprintf (fp,"\n");
02089   fprintf (fp,"# The frame rate is the number of frames/second (legal values:\n");
02090   fprintf (fp,"# 23.976, 24, 25, 29.97, 30, 50 ,59.94, 60\n");
02091   fprintf (fp,"FRAME_RATE 30\n");
02092   fprintf (fp,"\n");
02093   fprintf (fp,"# There are many more options, see the users manual for examples....\n");
02094   fprintf (fp,"# ASPECT_RATIO, USER_DATA, GAMMA, IQTABLE, etc.\n");
02095   fprintf (fp,"\n");
02096   fprintf (fp,"\n");
02097   fclose (fp);
02098 
02099   setRecordingInfos("Parameter file "+fParameterFileName+" generated in "+fMovieTempFolderPath);
02100   setRecordingStatus(READY_TO_ENCODE);
02101   return true;
02102 }
02103 
02104 void G4OpenGLQtViewer::encodeVideo()
02105 {
02106   if ((getEncoderPath() != "") && (getSaveFileName() != "")) {
02107     setRecordingStatus(ENCODING);
02108     
02109     fProcess = new QProcess();
02110 #if QT_VERSION > 0x040100
02111     QObject ::connect(fProcess,SIGNAL(finished ( int,QProcess::ExitStatus)),
02112                       this,SLOT(processEncodeFinished()));
02113     QObject ::connect(fProcess,SIGNAL(readyReadStandardOutput ()),
02114                       this,SLOT(processEncodeStdout()));
02115 #else
02116     QObject ::connect(fProcess,SIGNAL(finished ( int)),
02117                       this,SLOT(processEncodeFinished()));
02118     QObject ::connect(fProcess,SIGNAL(readyReadStandardOutput ()),
02119                       this,SLOT(processEncodeStdout()));
02120 #endif
02121     fProcess->setReadChannelMode(QProcess::MergedChannels);
02122     fProcess->start (fEncoderPath, QStringList(fMovieTempFolderPath+fParameterFileName));
02123   }
02124 }
02125 
02126 
02127 // FIXME : does not work on Qt3
02128 void G4OpenGLQtViewer::processEncodeStdout()
02129 {
02130   QString tmp = fProcess->readAllStandardOutput ().data();
02131   int start = tmp.lastIndexOf("ESTIMATED TIME");
02132   tmp = tmp.mid(start,tmp.indexOf("\n",start)-start);
02133   setRecordingInfos(tmp);
02134 }
02135 
02136 
02137 void G4OpenGLQtViewer::processEncodeFinished()
02138 {
02139 
02140   QString txt = "";
02141   txt = getProcessErrorMsg();
02142   if (txt == "") {
02143     setRecordingStatus(SUCCESS);
02144   } else {
02145     setRecordingStatus(FAILED);
02146   }
02147   //  setRecordingInfos(txt+removeTempFolder());
02148 }
02149 
02150 
02151 void G4OpenGLQtViewer::processLookForFinished() 
02152 {
02153 
02154   QString txt = getProcessErrorMsg();
02155   if (txt != "") {
02156     fEncoderPath = "";
02157   } else {
02158     fEncoderPath = QString(fProcess->readAllStandardOutput ().data()).trimmed();
02159     // if not found, return "not found"
02160     if (fEncoderPath.contains(" ")) {
02161       fEncoderPath = "";
02162     } else if (!fEncoderPath.contains("ppmtompeg")) {
02163       fEncoderPath = "";
02164     }
02165     setEncoderPath(fEncoderPath);
02166   }
02167   // init temp folder
02168   setTempFolderPath(QDir::temp ().absolutePath ());
02169 }
02170 
02171 
02172 QString G4OpenGLQtViewer::getProcessErrorMsg()
02173 {
02174   QString txt = "";
02175   if (fProcess->exitCode() != 0) {
02176     switch (fProcess->error()) {
02177     case QProcess::FailedToStart:
02178       txt = "The process failed to start. Either the invoked program is missing, or you may have insufficient permissions to invoke the program.\n";
02179       break;
02180     case QProcess::Crashed:
02181       txt = "The process crashed some time after starting successfully.\n";
02182       break;
02183     case QProcess::Timedout:
02184       txt = "The last waitFor...() function timed out. The state of QProcess is unchanged, and you can try calling waitFor...() again.\n";
02185       break;
02186     case QProcess::WriteError:
02187       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";
02188       break;
02189     case QProcess::ReadError:
02190       txt = "An error occurred when attempting to read from the process. For example, the process may not be running.\n";
02191       break;
02192     case QProcess::UnknownError:
02193       txt = "An unknown error occurred. This is the default return value of error().\n";
02194       break;
02195     }
02196   }
02197   return txt;
02198 }
02199 
02200 
02201 
02202 
02203 QWidget *G4OpenGLQtViewer::getParentWidget() 
02204 {
02205   // launch Qt if not
02206   G4Qt* interactorManager = G4Qt::getInstance ();
02207   // G4UImanager* UI = 
02208   // G4UImanager::GetUIpointer();
02209   
02210   bool found = false;
02211   
02212   // create window
02213   if (((QApplication*)interactorManager->GetMainInteractor())) {
02214     // look for the main window
02215     QWidgetList wl = QApplication::allWidgets();
02216     QWidget *widget = NULL;
02217     for (int i=0; i < wl.size(); i++) {
02218       widget = wl.at(i);
02219       if ((found== false) && (widget->inherits("QMainWindow"))) {
02220         fGLWindow = new QDialog(widget,Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowMinMaxButtonsHint);
02221         found = true;
02222       }
02223     }
02224     
02225     if (found==false) {
02226 #ifdef G4DEBUG_VIS_OGL
02227       printf("G4OpenGLQtViewer::CreateMainWindow case Qapp exist, but not found\n");
02228 #endif
02229       fGLWindow = new QDialog();
02230     }
02231   } else {
02232 #ifdef G4DEBUG_VIS_OGL
02233     printf("G4OpenGLQtViewer::CreateMainWindow case Qapp exist\n");
02234 #endif
02235     fGLWindow = new QDialog();
02236 #ifdef G4DEBUG_VIS_OGL
02237     printf("G4OpenGLQtViewer::GetParentWidget fGLWindow\n");
02238 #endif
02239   }
02240   if (found) {
02241     return fGLWindow;
02242   } else {
02243     return NULL;
02244   }
02245 }
02246 
02247 
02248 void G4OpenGLQtViewer::initSceneTreeComponent(){
02249 
02250   fSceneTreeWidget = new QWidget();
02251   fSceneTreeWidget->setLayout (new QVBoxLayout());
02252 
02253   if (fUISceneTreeComponentsTBWidget != NULL) {
02254     fUISceneTreeComponentsTBWidget->addTab(fSceneTreeWidget,QString(GetName().data()));
02255   }
02256 
02257   QLayout* layoutSceneTreeComponentsTBWidget = fSceneTreeWidget->layout();
02258 
02259 
02260   fSceneTreeComponentTreeWidget = new QTreeWidget();
02261   fSceneTreeComponentTreeWidget->setSelectionMode(QAbstractItemView::SingleSelection);
02262   fSceneTreeComponentTreeWidget->setHeaderLabel ("Scene tree : "+QString(GetName().data()));
02263   fSceneTreeComponentTreeWidget->setColumnHidden (1,true);  // copy number
02264   fSceneTreeComponentTreeWidget->setColumnHidden (2,true);  // PO index
02265   fSceneTreeComponentTreeWidget->setColumnHidden (3,true);  // Informations
02266   //   data(0) : POindex
02267   //   data(1) : copy number
02268   //   data(2) : g4color
02269 
02270   layoutSceneTreeComponentsTBWidget->addWidget(fSceneTreeComponentTreeWidget);
02271 
02272   connect(fSceneTreeComponentTreeWidget,SIGNAL(itemChanged(QTreeWidgetItem*, int)),SLOT(sceneTreeComponentItemChanged(QTreeWidgetItem*, int)));
02273   connect(fSceneTreeComponentTreeWidget,SIGNAL(itemSelectionChanged ()),SLOT(sceneTreeComponentSelected()));
02274   connect(fSceneTreeComponentTreeWidget,SIGNAL(itemDoubleClicked ( QTreeWidgetItem*, int)),SLOT(changeColorAndTransparency( QTreeWidgetItem*, int)));
02275 
02276 
02277   // Depth slider
02278   QLabel *depth = new QLabel();
02279   depth->setText("Depth :");
02280 
02281   QWidget* depthWidget = new QWidget();
02282   QGroupBox *groupBox = new QGroupBox(tr("Touchables slider"),depthWidget);
02283   QHBoxLayout *groupBoxLayout = new QHBoxLayout(groupBox);
02284 
02285   QLabel *zero = new QLabel();
02286   zero->setText("Show all");          
02287   QLabel *one = new QLabel();
02288   one->setText("Hide all");
02289   fSceneTreeDepthSlider = new QSlider ( Qt::Horizontal, groupBox);
02290   fSceneTreeDepthSlider->setMaximum (1000);
02291   fSceneTreeDepthSlider->setMinimum (0);
02292   fSceneTreeDepthSlider->setTickPosition(QSlider::TicksAbove);
02293   groupBoxLayout->addWidget(zero);
02294   groupBoxLayout->addWidget(fSceneTreeDepthSlider);
02295   groupBoxLayout->addWidget(one);
02296 
02297   groupBox->setLayout(groupBoxLayout);
02298   layoutSceneTreeComponentsTBWidget->addWidget(groupBox);
02299 
02300   connect( fSceneTreeDepthSlider, SIGNAL( valueChanged(int) ), this, SLOT( changeDepthInSceneTree(int) ) );
02301 
02302   // Search line
02303   QWidget *helpWidget = new QWidget();
02304   QHBoxLayout *helpLayout = new QHBoxLayout();
02305   QPushButton* select = new QPushButton("select item(s)");
02306   fHelpLine = new QLineEdit();
02307   helpLayout->addWidget(new QLabel("Search :",helpWidget));
02308   helpLayout->addWidget(fHelpLine);
02309   helpLayout->addWidget(select);
02310   helpWidget->setLayout(helpLayout);
02311   layoutSceneTreeComponentsTBWidget->addWidget(helpWidget);
02312 
02313   connect( fHelpLine, SIGNAL( returnPressed () ), this, SLOT(changeSearchSelection()));
02314   connect( select, SIGNAL( clicked () ), this, SLOT(changeSearchSelection()));
02315 
02316 
02317   fTreeItemModels.clear();
02318 
02319   fPVRootNodeCreate = false;
02320 
02321   fMaxPOindexInserted = -1;
02322 }
02323 
02324 
02325 // set the component to check/unchecked, also go into its child
02326 // and set the same status to all his childs
02327 void G4OpenGLQtViewer::setCheckComponent(QTreeWidgetItem* item,bool check)
02328 {
02329   if (item != NULL) {
02330     if (check) {
02331       item->setCheckState(0,Qt::Checked);
02332     } else {
02333       item->setCheckState(0,Qt::Unchecked);
02334     }
02335       updatePositivePoIndexSceneTreeWidgetQuickMap(item->data(0,Qt::UserRole).toInt(),item);
02336     int nChildCount = item->childCount();
02337     for (int i = 0; i < nChildCount; i++) {
02338       setCheckComponent(item->child(i),check);
02339     }
02340   }
02341 }
02342 
02343 
02344 void G4OpenGLQtViewer::DrawText(const G4Text& g4text)
02345 {
02346   if (isGl2psWriting()) {
02347 
02348     G4OpenGLViewer::DrawText(g4text);
02349 
02350   } else {
02351 
02352     if (!fWindow) return;
02353 
02354     G4VSceneHandler::MarkerSizeType sizeType;
02355     G4double size = fSceneHandler.GetMarkerSize(g4text,sizeType);
02356 
02357     QFont font = QFont();
02358     font.setPointSizeF(size);
02359 
02360     G4Point3D position = g4text.GetPosition();
02361 
02362     const G4String& textString = g4text.GetText();
02363     const char* textCString = textString.c_str();
02364   
02365     // Calculate move for centre and right adjustment
02366     QFontMetrics* f = new QFontMetrics (font);
02367     G4double span = f->width(textCString);
02368     G4double xmove = 0., ymove = 0.;
02369     switch (g4text.GetLayout()) {
02370     case G4Text::left: break;
02371     case G4Text::centre: xmove -= span / 2.; break;
02372     case G4Text::right: xmove -= span;
02373     }
02374     
02375     //Add offsets
02376     xmove += g4text.GetXOffset();
02377     ymove += g4text.GetYOffset();
02378 
02379     fWindow->renderText
02380       ((position.x()+(2*xmove)/getWinWidth()),
02381        (position.y()+(2*ymove)/getWinHeight()),
02382        position.z(),
02383        textCString,
02384        font);
02385 
02386   }
02387 }
02388 
02389 
02390 void G4OpenGLQtViewer::ResetView () {
02391   G4OpenGLViewer::ResetView();
02392   fDeltaDepth = 0.01;
02393   fDeltaZoom = 0.05;
02394 }
02395 
02396 
02397 
02398 
02399 void G4OpenGLQtViewer::addPVSceneTreeElement(const G4String& model, G4PhysicalVolumeModel* pPVModel, int currentPOIndex) {
02400 
02401   const QString& modelShortName = getModelShortName(model);
02402 
02403   if (modelShortName == "") {
02404     return ;
02405   }
02406   // try to init it
02407   if (fSceneTreeComponentTreeWidget == NULL) {
02408     initSceneTreeComponent();
02409   }
02410 
02411   // if no UI
02412   if (fSceneTreeComponentTreeWidget == NULL) {
02413     return;
02414   }
02415 
02416   fSceneTreeComponentTreeWidget->blockSignals(true);
02417 
02418   // Create the "volume" node if not
02419   //  if (fSceneTreeComponentTreeWidget->topLevelItemCount () == 0) {
02420   if (!fPVRootNodeCreate) {
02421     const G4VisAttributes* visAttr = GetApplicableVisAttributes(pPVModel->GetFullPVPath().at(0).GetPhysicalVolume()->GetLogicalVolume()->GetVisAttributes());
02422     const G4Colour& color = visAttr->GetColour();
02423     
02424     fModelShortNameItem = createTreeWidgetItem(pPVModel->GetFullPVPath(),
02425                                                modelShortName,
02426                                                0, // currentPVCopyNb
02427                                                -1, // currentPVPOIndex
02428                                                "",
02429                                                Qt::Checked,
02430                                                NULL,
02431                                                color);
02432     fPVRootNodeCreate = true;
02433   }
02434 
02435   bool added = parseAndInsertInSceneTree(fModelShortNameItem,pPVModel,0,modelShortName,0,currentPOIndex);
02436   if (!added) {
02437   }
02438   
02439   fSceneTreeComponentTreeWidget->blockSignals(false);
02440   
02441 }
02442 
02443 
02448 QTreeWidgetItem* G4OpenGLQtViewer::createTreeWidgetItem(
02449  const PVPath& fullPath
02450  ,const QString& name
02451  ,int copyNb
02452  ,int POIndex
02453  ,const QString& logicalName
02454  ,Qt::CheckState state
02455  ,QTreeWidgetItem * parentTreeNode
02456  ,const G4Colour& color
02457 ) {
02458 
02459   // Set depth
02460   if (fullPath.size() > fSceneTreeDepth) {
02461     fSceneTreeDepth = fullPath.size();
02462     // Change slider value
02463     if (fSceneTreeDepthSlider) {
02464       fSceneTreeDepthSlider->setTickInterval(1000/(fSceneTreeDepth+1));
02465     }
02466   }
02467   QTreeWidgetItem * newItem = NULL;
02468   if (parentTreeNode == NULL) {
02469     newItem = new QTreeWidgetItem(fSceneTreeComponentTreeWidget);
02470   } else {
02471     newItem = new QTreeWidgetItem(parentTreeNode);
02472   }
02473 
02474 
02475   newItem->setText(0,name);
02476   newItem->setData(1,Qt::UserRole,copyNb);
02477   newItem->setText(2,QString::number(POIndex));
02478   newItem->setData(0, Qt::UserRole, POIndex);
02479   newItem->setText(3,logicalName);
02480   newItem->setFlags(newItem->flags()|Qt::ItemIsUserCheckable);
02481   newItem->setCheckState(0,state);
02482   updatePositivePoIndexSceneTreeWidgetQuickMap(POIndex,newItem);
02483 
02484   changeQColorForTreeWidgetItem(newItem,QColor((int)(color.GetRed()*255),
02485                                                (int)(color.GetGreen()*255),
02486                                                (int)(color.GetBlue()*255),
02487                                                (int)(color.GetAlpha()*255)));
02488 
02489   // If invisible
02490   if ((state == Qt::Unchecked) && (POIndex == -1)) {
02491     newItem->setForeground (0, QBrush( Qt::gray) );
02492     
02493     // Set a tootip
02494     newItem->setToolTip (0,QString(
02495                                    "This node exists in the geometry but has not been\n")+
02496                          "drawn, perhaps because it has been set invisible. It \n"+
02497                          "cannot be made visible with a click on the button.\n"+
02498                          "To see it, change the visibility, for example, with \n"+
02499                          "/vis/geometry/set/visibility " + logicalName + " 0 true\n"+
02500                          "and rebuild the view with /vis/viewer/rebuild.\n"+
02501                          "Click here will only show/hide all child components");
02502   }
02503 
02504   // special case: if alpha=0, it is a totally transparent objet,
02505   // then, do not redraw it
02506   if (color.GetAlpha() == 0) {
02507     state = Qt::Unchecked;
02508     newItem->setCheckState(0,state);
02509     updatePositivePoIndexSceneTreeWidgetQuickMap(POIndex,newItem);
02510   }
02511 
02512   fTreeItemModels.insert(std::pair <int, PVPath > (POIndex,fullPath) );
02513 
02514   // Check last status of this item and change if necessary 
02515   // open/close/hidden/visible/selected
02516   changeOpenCloseVisibleHiddenSelectedColorSceneTreeElement(newItem);
02517   return newItem;
02518 }
02519 
02520 
02521 //
02522 //   Recursive function.
02523 //   Try to insert the given item :
02524 //   - If not present and last item of the path: insert it and mark it CHECK
02525 //   - If not present and NOT last item of the path: insert it and mark it UNCHECKED
02526 //   - If already present and name/PO/Transformation identical, then it is a transparent
02527 //     object : Change the PO number and transparency
02528 //   - If already present and PO different, then it is an unvisible item : Have to
02529 //     set it visible
02530 //   - else : Create a new element
02531 //   @return true if inserted, false if already present
02532 //
02533 bool G4OpenGLQtViewer::parseAndInsertInSceneTree(
02534  QTreeWidgetItem * parentItem
02535  ,G4PhysicalVolumeModel* pPVModel
02536  ,unsigned int fullPathIndex
02537  ,const QString& parentRoot
02538  ,unsigned int currentIndexInTreeSceneHandler
02539  ,int currentPVPOIndex
02540 ) {
02541 
02542   if (parentItem == NULL) {
02543     return false;
02544   }
02545 
02546   const PVPath& fullPath = pPVModel->GetFullPVPath();
02547 
02548   std::ostringstream oss;
02549   oss << fullPath.at(fullPathIndex).GetCopyNo();
02550   std::string currentPVName = G4String(fullPath.at(fullPathIndex).GetPhysicalVolume()->GetName()+" ["+oss.str()+"]").data();
02551 
02552   int currentPVCopyNb = fullPath.at(fullPathIndex).GetCopyNo();
02553 
02554   const G4VisAttributes* visAttr = GetApplicableVisAttributes(fullPath.at(fullPathIndex).GetPhysicalVolume()->GetLogicalVolume()->GetVisAttributes());
02555   const G4Colour& color = visAttr->GetColour();
02556 
02557   // look in all children in order to get if their is already a
02558   // child corresponding:
02559   // - if so, go into this child
02560   // - if not : create it as invisible
02561 
02562   // Realy quick check if the POindex is already there
02563   QTreeWidgetItem* subItem = NULL;
02564   QList<QTreeWidgetItem *> parentItemList;
02565   
02566     
02567   // first of all, very quick check if it was not the same as last one
02568 
02569   // Check only if it is a transparent object
02570   // If it is the last item and it is not transparent -> nothing to look for, 
02571   // simply add it.
02572   if ((currentIndexInTreeSceneHandler == (fullPath.size()-1)) && ((color.GetAlpha() == 1.))) {
02573   } else {
02574     QString lookForString = QString(currentPVName.c_str());
02575     for (int i = 0;i < parentItem->childCount(); i++ ) {
02576       if (parentItem->child(i)->text(0) == lookForString) {
02577         parentItemList.push_back(parentItem->child(i));
02578       }
02579     }
02580   }
02581    
02582   for (int i = 0; i < parentItemList.size(); ++i) {
02583     const std::string& parentItemName = parentItemList.at(i)->text(0).toStdString();
02584     int parentItemCopyNb = parentItemList.at(i)->data(1,Qt::UserRole).toInt();
02585     int parentItemPOIndex = parentItemList.at(i)->data(0,Qt::UserRole).toInt();
02586         
02587     // if already inside
02588     // -> return true
02589     // special case, do not have to deal with hierarchy except for PhysicalVolume
02590 
02591     
02592     /* Physical Volume AND copy number equal AND  name equal */
02593     if (((parentRoot == fTouchableVolumes) &&  (currentPVCopyNb == parentItemCopyNb)
02594          && (currentPVName == parentItemName))        ||
02595         /* NOT a Physical Volume AND  copy number equal */
02596         ((parentRoot != fTouchableVolumes) && (currentPVCopyNb == parentItemCopyNb) 
02597          /*AND  name equal AND  PO index equal*/
02598          && (currentPVName == parentItemName) && (currentPVPOIndex == parentItemPOIndex) )) {
02599       
02600       // then check for the Transform3D
02601       bool sameTransform = true;
02602       if (parentItemPOIndex >= 0) {
02603         const PVPath& fullPathTmp = fTreeItemModels[parentItemPOIndex];
02604         if (fullPathTmp.size() > 0) {
02605           if (fullPathTmp.at(fullPathTmp.size()-1).GetTransform () == pPVModel->GetTransformation ()) {
02606             sameTransform = true;
02607           } else {
02608             sameTransform = false;
02609           }
02610         }
02611       }
02612 
02613       // Same transformation, then try to change the PO index
02614       if (sameTransform == true) {
02615         // already exist in the tree, is it a transparent object ?
02616         // If so, then have to change the PO index ONLY if it is the last
02617         // and then change the state ONLY if POIndex has change
02618         // If not, then go deaper
02619         
02620         // last element
02621         if (currentIndexInTreeSceneHandler == (fullPath.size()-1)) {
02622           
02623           parentItemList.at(i)->setText(2,QString::number(currentPVPOIndex));
02624           parentItemList.at(i)->setData(0, Qt::UserRole,currentPVPOIndex);
02625           
02626           fTreeItemModels.insert(std::pair <int, PVPath >(currentPVPOIndex,fullPath) );
02627           
02628           // Then remove tooltip and special font
02629           QFont f = QFont();
02630           parentItemList.at(i)->setFont (0,f);
02631           
02632           // set foreground
02633           parentItemList.at(i)->setForeground (0,QBrush());
02634           
02635           // Set a tootip
02636           parentItemList.at(i)->setToolTip (0,"");
02637           
02638           changeQColorForTreeWidgetItem(parentItemList.at(i),QColor((int)(color.GetRed()*255),
02639                                                                     (int)(color.GetGreen()*255),
02640                                                                     (int)(color.GetBlue()*255),
02641                                                                     (int)(color.GetAlpha()*255)));
02642           
02643           // set check only if there is something to display
02644           if (color.GetAlpha() > 0) {
02645             parentItemList.at(i)->setCheckState(0,Qt::Checked);
02646             updatePositivePoIndexSceneTreeWidgetQuickMap(currentPVPOIndex,parentItemList.at(i));
02647           }
02648           return false;
02649         } else {
02650           subItem = parentItemList.at(i);        
02651         }
02652         
02653         // Exists but not the end of path, then forget get it
02654       } else if (currentIndexInTreeSceneHandler < (fullPath.size()-1))  {
02655         subItem = parentItemList.at(i);
02656       }
02657     }
02658 
02659   } // end for
02660   
02661   // if it the last, then add it and set it checked
02662   if (currentIndexInTreeSceneHandler == (fullPath.size()-1)) {
02663     /* subItem =*/ createTreeWidgetItem(fullPath,
02664                                    QString(currentPVName.c_str()),
02665                                    currentPVCopyNb,
02666                                    currentPVPOIndex,
02667                                    QString(fullPath.at(fullPathIndex).GetPhysicalVolume()->GetLogicalVolume()->GetName().data()),
02668                                    Qt::Checked,
02669                                    parentItem,
02670                                    color);
02671 
02672     if (currentPVPOIndex > fMaxPOindexInserted) {
02673       fMaxPOindexInserted = currentPVPOIndex;
02674     }
02675 
02676   } else {
02677     
02678     // if no child found, then this child is create and marked as invisible, then go inside
02679     if (subItem == NULL) {
02680       
02681       if (currentIndexInTreeSceneHandler < (fullPath.size()-1))  {
02682         subItem = createTreeWidgetItem(fullPath,
02683                                        QString(currentPVName.c_str()),
02684                                        currentPVCopyNb,
02685                                        -1,
02686                                        QString(fullPath.at(fullPathIndex).GetPhysicalVolume()->GetLogicalVolume()->GetName().data()),
02687                                        Qt::Unchecked,
02688                                        parentItem,
02689                                        color);
02690       }
02691     }
02692     
02693     return parseAndInsertInSceneTree(subItem,pPVModel,fullPathIndex+1,parentRoot,currentIndexInTreeSceneHandler+1,currentPVPOIndex);
02694   }
02695   return true;
02696 }
02697 
02698 
02699 void G4OpenGLQtViewer::changeOpenCloseVisibleHiddenSelectedColorSceneTreeElement(
02700  QTreeWidgetItem* subItem
02701 )
02702 {
02703   // Check if object with the same POIndex is the same in old tree
02704   QTreeWidgetItem* oldItem = NULL;
02705 
02706   QTreeWidgetItem* foundItem = getOldTreeWidgetItem(subItem->data(0,Qt::UserRole).toInt());
02707 
02708   if (foundItem != NULL) {
02709     if (isSameSceneTreeElement(foundItem,subItem)) {
02710       oldItem = foundItem;
02711     }
02712   }
02713   if (foundItem == NULL) {  // PO should have change, parse all
02714 
02715     // POindex > 0
02716     std::map <int, QTreeWidgetItem*>::const_iterator i;
02717     i = fOldPositivePoIndexSceneTreeWidgetQuickMap.begin();
02718     while (i != fOldPositivePoIndexSceneTreeWidgetQuickMap.end()) {
02719       if (isSameSceneTreeElement(i->second,subItem)) {
02720         oldItem = i->second;
02721         i = fOldPositivePoIndexSceneTreeWidgetQuickMap.end();
02722       } else {
02723         i++;
02724       }
02725     }
02726     // POindex == 0 ?
02727     if (oldItem == NULL) {
02728       unsigned int a = 0;
02729       while (a < fOldNullPoIndexSceneTreeWidgetQuickVector.size()) {
02730         if (isSameSceneTreeElement(fOldNullPoIndexSceneTreeWidgetQuickVector[a],subItem)) {
02731           oldItem = fOldNullPoIndexSceneTreeWidgetQuickVector[a];
02732           a = fOldNullPoIndexSceneTreeWidgetQuickVector.size();
02733         } else {
02734           a++;
02735         }
02736       }
02737     }
02738   }
02739 
02740   // if found : retore old state
02741   if (oldItem != NULL) {
02742     subItem->setFlags(oldItem->flags());   // flags
02743     subItem->setCheckState(0,oldItem->checkState(0)); // check state
02744     subItem->setSelected(oldItem->isSelected());  // selected
02745     subItem->setExpanded(oldItem->isExpanded ());  // expand
02746 
02747     // change color
02748     // when we call this function, the color in the item is the one of vis Attr
02749 
02750     std::map <int, QTreeWidgetItem* >::iterator it;
02751     
02752     // getOldPO
02753     int oldPOIndex = oldItem->data(0,Qt::UserRole).toInt();
02754     it = fOldPositivePoIndexSceneTreeWidgetQuickMap.find(oldPOIndex);
02755     QColor color;
02756 
02757     // get old Vis Attr Color
02758     std::map <int, QColor >::iterator itVis;
02759     itVis = fOldVisAttrColorMap.find(oldPOIndex);
02760 
02761     QColor oldVisAttrColor;
02762     const QColor& newVisAttrColor = subItem->data(2,Qt::UserRole).value<QColor>();
02763 
02764     bool visAttrChange = false;
02765     // if old vis attr color found
02766     if (itVis != fOldVisAttrColorMap.end()) {
02767       oldVisAttrColor = itVis->second;
02768       if (oldVisAttrColor != newVisAttrColor) {
02769         visAttrChange = true;
02770       }
02771     } else {
02772       visAttrChange = true;
02773     }
02774     
02775     if (visAttrChange) {
02776       fOldVisAttrColorMap.insert(std::pair <int, QColor > (subItem->data(0,Qt::UserRole).toInt(),newVisAttrColor) );
02777 
02778     } else { // if no changes, get old PO value
02779       // if old PO found
02780       if (it != fOldPositivePoIndexSceneTreeWidgetQuickMap.end()) {
02781         color = (it->second)->data(2,Qt::UserRole).value<QColor>(); 
02782       } else {
02783         color = oldItem->data(2,Qt::UserRole).value<QColor>(); 
02784       }
02785 #ifdef G4DEBUG_VIS_OGL
02786       printf("====color name:%s\n",color.name().toStdString().c_str());
02787 #endif
02788       changeQColorForTreeWidgetItem(subItem,color);
02789     }
02790   }
02791 
02792   return;
02793 }
02794 
02795 
02796 
02797 // Check if both items are identical.
02798 // For that, check name, copy number, transformation
02799 // special case for "non Touchables", do not check the PO index, check only the name
02800 bool G4OpenGLQtViewer::isSameSceneTreeElement(
02801  QTreeWidgetItem* parentOldItem
02802  ,QTreeWidgetItem* parentNewItem
02803 ) {
02804 
02805   int newPO = -1;
02806   int oldPO = -1;
02807   
02808   int newCpNumber = -1;
02809   int oldCpNumber = -1;
02810 
02811   bool firstWhile = true;
02812 
02813   while ((parentOldItem != NULL) && (parentNewItem != NULL)) {
02814 
02815     // check transform, optimize getting data(..,..) that consume lot of time
02816     if (!firstWhile) {
02817       oldPO = parentOldItem->data(0,Qt::UserRole).toInt();
02818       newPO = parentNewItem->data(0,Qt::UserRole).toInt();
02819     }
02820     firstWhile = false;
02821     
02822     if ((oldPO >= 0) &&
02823         (newPO >= 0)) {
02824       const PVPath& oldFullPath = fOldTreeItemModels[oldPO];
02825       const PVPath& newFullPath = fTreeItemModels[newPO];
02826       if ((oldFullPath.size() > 0) &&
02827           (newFullPath.size() > 0)) {
02828         if (oldFullPath.size() != newFullPath.size()) {
02829           return false;
02830         }
02831         if (oldFullPath.at(oldFullPath.size()-1).GetTransform () == newFullPath.at(newFullPath.size()-1).GetTransform ()) {
02832           newCpNumber = newFullPath.at(newFullPath.size()-1).GetCopyNo();
02833           oldCpNumber = oldFullPath.at(oldFullPath.size()-1).GetCopyNo();
02834           // ok
02835         } else {
02836           return false;
02837         }
02838       }
02839     }
02840     
02841     // Check copy Number
02842     if (oldCpNumber == -1) {
02843       oldCpNumber = parentOldItem->data(1,Qt::UserRole).toInt();
02844     }
02845     if (newCpNumber == -1) {
02846       newCpNumber = parentNewItem->data(1,Qt::UserRole).toInt();
02847     }
02848     if ((oldCpNumber != newCpNumber) ||
02849         // Check name
02850         (parentOldItem->text(0) != parentNewItem->text(0)) ) { 
02851       // try to optimize
02852       return false;  
02853     } else if ((parentOldItem->text(0) != parentNewItem->text(0)) || // Logical Name
02854                (parentOldItem->text(3) != parentNewItem->text(3))) {   // Check logical name
02855       return false;
02856     } else {
02857       parentOldItem = parentOldItem->parent();
02858       parentNewItem = parentNewItem->parent();
02859     }
02860   } // end while
02861 
02862   return true;
02863 }
02864 
02865 
02866 void G4OpenGLQtViewer::addNonPVSceneTreeElement(
02867  const G4String& model
02868  ,int currentPOIndex
02869  ,const std::string& modelDescription
02870  ,const G4Visible& visible
02871 ) {
02872 
02873   QString modelShortName = getModelShortName(model);
02874   G4Colour color;
02875 
02876   // Special case for text
02877   try {
02878     const G4Text& g4Text = dynamic_cast<const G4Text&>(visible);
02879     color = fSceneHandler.GetTextColour(g4Text);
02880   }
02881   catch (std::bad_cast) {
02882     color = fSceneHandler.GetColour(visible);
02883   }
02884   if (modelShortName == "") {
02885     return ;
02886   }
02887   // try to init it
02888   if (fSceneTreeComponentTreeWidget == NULL) {
02889     initSceneTreeComponent();
02890   }
02891 
02892   // if no UI
02893   if (fSceneTreeComponentTreeWidget == NULL) {
02894     return;
02895   }
02896 
02897   fSceneTreeComponentTreeWidget->blockSignals(true);
02898 
02899   // Create the "Model" node if not
02900 
02901   QList<QTreeWidgetItem *> resItem;
02902   resItem =  fSceneTreeComponentTreeWidget->findItems (modelShortName, Qt::MatchExactly, 0 );
02903   QTreeWidgetItem * currentItem = NULL;
02904   const PVPath tmpFullPath;
02905 
02906   if (resItem.empty()) {
02907     currentItem = createTreeWidgetItem(tmpFullPath,
02908                                        modelShortName,
02909                                        0, // currentPVCopyNb
02910                                        -1, // currentPVPOIndex
02911                                        "",
02912                                        Qt::Checked,
02913                                        NULL,
02914                                        color);
02915   } else {
02916     currentItem = resItem.first();
02917   }
02918 
02919   // Is this volume already in the tree AND PO is not the same?
02920   const QList<QTreeWidgetItem *>&
02921   resItems =  fSceneTreeComponentTreeWidget->findItems (QString(modelDescription.c_str()), Qt::MatchFixedString| Qt::MatchCaseSensitive|Qt::MatchRecursive, 0 );
02922   
02923   bool alreadyPresent = false;
02924   for (int i = 0; i < resItems.size(); ++i) {
02925     if (currentPOIndex == resItems.at(i)->data(0,Qt::UserRole).toInt()) {
02926       alreadyPresent = true;
02927     }
02928   }
02929   if (!alreadyPresent) {
02930     createTreeWidgetItem(tmpFullPath,
02931                          QString(modelDescription.c_str()),
02932                          0, // currentPVCopyNb
02933                          currentPOIndex,
02934                          "",
02935                          Qt::Checked,
02936                          currentItem,
02937                          color);
02938   }
02939   fSceneTreeComponentTreeWidget->blockSignals(false);
02940   
02941 }
02942 
02943 
02947 QString G4OpenGLQtViewer::getModelShortName(const G4String& model) {
02948 
02949   QString modelShortName = model.data();
02950   if (modelShortName.mid(0,modelShortName.indexOf(" ")) == "G4PhysicalVolumeModel") {
02951     modelShortName = fTouchableVolumes;
02952   } else {
02953     if (modelShortName.mid(0,2) == "G4") {
02954       modelShortName = modelShortName.mid(2);
02955     }
02956     if (modelShortName.indexOf("Model") != -1) {
02957       modelShortName = modelShortName.mid(0,modelShortName.indexOf("Model"));
02958     }
02959   }
02960   return modelShortName;
02961 }
02962 
02963 
02964 
02965 bool G4OpenGLQtViewer::isTouchableVisible(int POindex){
02966 
02967   // If no scene tree (Immediate viewer)
02968   if (fSceneTreeComponentTreeWidget == NULL) {
02969     return false;
02970   }
02971   
02972   // should be the next one
02973   fLastSceneTreeWidgetAskFor++;
02974 
02975   QTreeWidgetItem* item = getTreeWidgetItem(POindex);
02976   
02977   if (item != NULL) {
02978     if ( item->checkState(0) == Qt::Checked) {
02979       return true;
02980     }
02981   }  
02982   return false;
02983 }
02984 
02985 
02986 bool G4OpenGLQtViewer::parseAndCheckVisibility(QTreeWidgetItem * treeNode,int POindex){
02987   bool isFound = false;
02988   for (int i = 0; i < treeNode->childCount() ; ++i) {
02989 
02990     if (treeNode->child(i)->data(0,Qt::UserRole).toInt() == POindex) {
02991       if (treeNode->child(i)->checkState(0) == Qt::Checked) {
02992         return true;
02993       }
02994     }
02995     isFound = parseAndCheckVisibility(treeNode->child(i),POindex);
02996     if (isFound) {
02997       return true;
02998     }
02999   } // end for
03000   return false;
03001 }
03002 
03003 
03004 void G4OpenGLQtViewer::sceneTreeComponentItemChanged(QTreeWidgetItem* item, int) {
03005 
03006   if (fCheckSceneTreeComponentSignalLock == false) {
03007     fCheckSceneTreeComponentSignalLock = true;
03008     G4bool checked = false;
03009     if (item->checkState(0) == Qt::Checked) {
03010       checked = true;
03011     }
03012     setCheckComponent(item,checked);
03013     updateQWidget();
03014 
03015     // change vis attributes to set new visibility
03016     G4int iPO = item->data(0,Qt::UserRole).toInt();
03017     if (iPO >= 0 && fTreeItemModels.find(iPO) != fTreeItemModels.end()) {
03018       const PVPath& fullPath = fTreeItemModels[iPO];
03019       // If a physical volume
03020       if (fullPath.size()) {
03021 
03022         // Instantiate a working copy of a G4VisAttributes object...
03023         G4VisAttributes workingVisAtts;
03024         // and set the visibility.
03025         workingVisAtts.SetVisibility(checked);
03026 
03027         // Add a vis atts modifier to the view parameters...
03028         fVP.AddVisAttributesModifier
03029         (G4ModelingParameters::VisAttributesModifier
03030          (workingVisAtts,
03031           G4ModelingParameters::VASVisibility,
03032           fullPath));
03033         // G4ModelingParameters::VASVisibility tells G4PhysicalVolumeModel that
03034         // it is the visibility that should be picked out and merged with the
03035         // touchable's normal vis attributes.
03036       }
03037     }
03038 
03039     fCheckSceneTreeComponentSignalLock = false;
03040   }
03041 }
03042 
03043 
03044 void G4OpenGLQtViewer::sceneTreeComponentSelected() {
03045   /*
03046   if (fSceneTreeComponentTreeWidget) {
03047     if (! fSceneTreeComponentTreeWidget->selectedItems().isEmpty ()) {
03048       QTreeWidgetItem* item = fSceneTreeComponentTreeWidget->selectedItems ().first();
03049       if (item) {
03050 
03051         const PVPath& fullPath = fTreeItemModels[item->data(0,Qt::UserRole).toInt()];
03052         if (fullPath.size() > 0) {
03053           const G4VisAttributes* visAttr2 = GetApplicableVisAttributes(fullPath.at(fullPath.size()-1).GetPhysicalVolume()->GetLogicalVolume()->GetVisAttributes());
03054         }
03055       }
03056     }
03057   }
03058   */
03059 }
03060 
03061 
03062 void G4OpenGLQtViewer::changeDepthInSceneTree (int val){
03063 
03064   // If no scene tree (Immediate viewer)
03065   if (fSceneTreeComponentTreeWidget == NULL) {
03066     return;
03067   }
03068 
03069   // max depth :   fSceneTreeDepth
03070   // val is between 0 and 1
03071   // 0  .1  .2  .3  .4  .5  .6  .7  .8  .9  1
03072   // 1      1.4          2                  
03073   // 1         2         3         4
03074 
03075   // Get the depth :
03076   double depth = 1 + ((double)val)/1000 * ((double)fSceneTreeDepth+1);
03077   
03078   // lock update on scene tree items
03079   fCheckSceneTreeComponentSignalLock = true;
03080   
03081   // Disable redraw each time !
03082   G4bool currentAutoRefresh = fVP.IsAutoRefresh();
03083   fVP.SetAutoRefresh(false);
03084 
03085   for (int b=0;b<fSceneTreeComponentTreeWidget->topLevelItemCount();b++) {
03086     changeDepthOnSceneTreeItem(depth,1.,fSceneTreeComponentTreeWidget->topLevelItem(b));
03087   }
03088 
03089   // Enable redraw !
03090   fVP.SetAutoRefresh(currentAutoRefresh);
03091   updateQWidget();
03092 
03093   // unlock update on scene tree items
03094   fCheckSceneTreeComponentSignalLock = false;
03095 
03096 }
03097 
03098 
03099 void G4OpenGLQtViewer::changeColorAndTransparency(QTreeWidgetItem* item,int) {
03100 
03101   if (item == NULL) {
03102     return;
03103   }
03104   const QColor& old = QColor(item->data(2,Qt::UserRole).value<QColor>());
03105 
03106 #if QT_VERSION < 0x040500
03107   bool a;
03108   const QColor& color = QColor(QColorDialog::getRgba (old.rgba(),&a,fSceneTreeComponentTreeWidget));
03109 #else
03110   const QColor& color = QColorDialog::getColor(old,
03111                                         fSceneTreeComponentTreeWidget,
03112                                         " Get color and transparency",
03113                                         QColorDialog::ShowAlphaChannel);
03114 #endif
03115   
03116   if (color.isValid()) {
03117 
03118     // change vis attributes to set new colour
03119     G4int iPO = item->data(0,Qt::UserRole).toInt();
03120     if (iPO >= 0 && fTreeItemModels.find(iPO) != fTreeItemModels.end()) {
03121       const PVPath& fullPath = fTreeItemModels[iPO];
03122       // If a physical volume
03123       if (fullPath.size()) {
03124       
03125         // Instantiate a working copy of a G4VisAttributes object...
03126         G4VisAttributes workingVisAtts;
03127         // and set the colour.
03128         G4Colour g4c(((G4double)color.red())/255,
03129                      ((G4double)color.green())/255,
03130                      ((G4double)color.blue())/255,
03131                      ((G4double)color.alpha())/255);
03132         workingVisAtts.SetColour(g4c);
03133         
03134         // Add a vis atts modifier to the view parameters...
03135         fVP.AddVisAttributesModifier
03136         (G4ModelingParameters::VisAttributesModifier
03137          (workingVisAtts,
03138           G4ModelingParameters::VASColour,
03139           fullPath));
03140         // G4ModelingParameters::VASColour tells G4PhysicalVolumeModel that it is
03141         // the colour that should be picked out and merged with the touchable's
03142         // normal vis attributes.
03143       }
03144     }
03145     
03146     // set scene tree parameters
03147     changeQColorForTreeWidgetItem(item,color);
03148   }
03149 }
03150 
03151 
03152 G4Colour G4OpenGLQtViewer::getColorForPoIndex(int poIndex) {
03153 
03154   QTreeWidgetItem* item = getTreeWidgetItem(poIndex);
03155 
03156   if (item != NULL) {
03157     
03158     const QColor& color = item->data(2,Qt::UserRole).value<QColor>();
03159     G4Colour g4c(((G4double)color.red())/255,
03160                  ((G4double)color.green())/255,
03161                  ((G4double)color.blue())/255,
03162                  ((G4double)color.alpha())/255);
03163 
03164     return g4c;
03165   }
03166   return G4Colour();
03167 }
03168 
03169 
03170 void G4OpenGLQtViewer::changeSearchSelection()
03171 {
03172   const QString& searchText = fHelpLine->text();
03173   if (fSceneTreeComponentTreeWidget == NULL) {
03174     return;
03175   }
03176 
03177   // unselect all
03178   for (int a=0; a<fSceneTreeComponentTreeWidget->topLevelItemCount(); a++) {
03179     fSceneTreeComponentTreeWidget->topLevelItem(a)->setExpanded(false);
03180     fSceneTreeComponentTreeWidget->topLevelItem(a)->setSelected(false);
03181     clearSceneTreeSelection(fSceneTreeComponentTreeWidget->topLevelItem(a));
03182   }
03183 
03184   QList<QTreeWidgetItem *> itemList = fSceneTreeComponentTreeWidget->findItems (searchText,Qt::MatchContains | Qt::MatchRecursive,0);
03185 
03186   for (int i = 0; i < itemList.size(); ++i) {
03187     QTreeWidgetItem* expandParentItem = itemList.at(i);
03188     while (expandParentItem->parent() != NULL) {
03189       expandParentItem->parent()->setExpanded(true);
03190       expandParentItem = expandParentItem->parent();
03191     }
03192     itemList.at(i)->setSelected(true);
03193   }    
03194 
03195 }
03196 
03197 
03198 void G4OpenGLQtViewer::clearSceneTreeSelection(QTreeWidgetItem* item) {
03199   for (int a=0; a<item->childCount(); a++) {
03200     item->child(a)->setSelected(false);
03201     item->child(a)->setExpanded(false);
03202     clearSceneTreeSelection(item->child(a));
03203   }
03204 
03205 }
03206 
03207 
03208 bool G4OpenGLQtViewer::isPVVolume(QTreeWidgetItem* item) {
03209   QTreeWidgetItem* sParent = item;
03210   while (sParent->parent() != NULL) {
03211     sParent = sParent->parent();
03212   }
03213   if (sParent->text(0) != fTouchableVolumes) {
03214     return false;
03215   }
03216   // item is the "Touchable" node
03217   if (item->text(0) == fTouchableVolumes) {
03218     return false;
03219   }
03220   return true;
03221 }
03222 
03223 
03224 void G4OpenGLQtViewer::changeDepthOnSceneTreeItem(
03225  double lookForDepth
03226  ,double currentDepth
03227  ,QTreeWidgetItem* item
03228 ) {
03229   double transparencyLevel = 0.;
03230   
03231   // look for a 2.2 depth and we are at level 3 
03232   // -> Set all theses items to Opaque
03233   // ONLY if it is a PV volume !
03234   if (isPVVolume(item)) {
03235     if ((lookForDepth-currentDepth) < 0) {
03236       item->setCheckState(0,Qt::Checked);
03237       updatePositivePoIndexSceneTreeWidgetQuickMap(item->data(0,Qt::UserRole).toInt(),item);
03238       transparencyLevel = 1;
03239     } else if ((lookForDepth-currentDepth) > 1 ){
03240       item->setCheckState(0,Qt::Unchecked);
03241       updatePositivePoIndexSceneTreeWidgetQuickMap(item->data(0,Qt::UserRole).toInt(),item);
03242       transparencyLevel = 0;
03243     } else {
03244       item->setCheckState(0,Qt::Checked);
03245       updatePositivePoIndexSceneTreeWidgetQuickMap(item->data(0,Qt::UserRole).toInt(),item);
03246       transparencyLevel = 1-(lookForDepth-currentDepth);
03247     }
03248   }
03249   
03250   if (item->data(0,Qt::UserRole).toInt() >= 0) {
03251     const G4Colour& color = getColorForPoIndex(item->data(0,Qt::UserRole).toInt());
03252     
03253     // We are less depper (ex:tree depth:2) than lookForDepth (ex:3.1)
03254     // -> Have to hide this level ONLY if it was not hidden before
03255     
03256     // Not on a top level item case
03257     // Do not set if it was already set
03258 
03259     // Should add them all the time in case of an older command has change transparency
03260     // before. Should be checked in changeDepthInSceneTree for duplicated commands
03261     // Do not change transparency if not visible by humain (and avoid precision value
03262     // problems..)
03263     if (((color.GetAlpha()-transparencyLevel) >  0.000001) ||
03264         ((color.GetAlpha()-transparencyLevel) < -0.000001))  {
03265       if ((item->text(3) != "")) {
03266         // FIXME : Should not test this here because of transparent
03267         // volume that will came after and with a different alpha level
03268         // Good thing to do is to check and suppress doubles in changeDepthInSceneTree
03269         // and then check if last (transparents volumes) has to change alpha
03270 
03271         changeQColorForTreeWidgetItem(item,QColor((int)(color.GetRed()*255),
03272                                                   (int)(color.GetGreen()*255),
03273                                                   (int)(color.GetBlue()*255),
03274                                                   (int)(transparencyLevel*255)));
03275       }
03276     }
03277   }
03278 
03279   for (int b=0;b< item->childCount();b++) {
03280     changeDepthOnSceneTreeItem(lookForDepth,currentDepth+1,item->child(b));
03281   }
03282 }
03283 
03284 
03285 void G4OpenGLQtViewer::clearTreeWidget(){
03286   // be careful about calling this twice
03287 
03288   if (fSceneTreeComponentTreeWidget) {
03289 
03290     if (fOldSceneTreeComponentTreeWidget == NULL) {
03291       fOldSceneTreeComponentTreeWidget = new QTreeWidget();
03292     }
03293     // clear old scene tree
03294     int tmp = fOldSceneTreeComponentTreeWidget->topLevelItemCount();
03295     while (tmp > 0) {
03296       delete fOldSceneTreeComponentTreeWidget->takeTopLevelItem (0);
03297       tmp = fOldSceneTreeComponentTreeWidget->topLevelItemCount();
03298     }
03299 
03300     if (fSceneTreeComponentTreeWidget->topLevelItemCount () > 0) {
03301 
03302       fPVRootNodeCreate = false;
03303 
03304       // reset all old
03305       fOldPositivePoIndexSceneTreeWidgetQuickMap.clear();
03306       fOldNullPoIndexSceneTreeWidgetQuickVector.clear();
03307       fOldTreeItemModels.clear();
03308 
03309       // Clone everything  
03310       for (int b =0; b <fSceneTreeComponentTreeWidget->topLevelItemCount();b++) {
03311         // All tree widgets are in :
03312         // then we could get the old POindex and get 
03313         // .visible/Hidden
03314         // .Check/Uncheck
03315         // .selected
03316         // .colour status from std::map
03317 
03318         // clone top level items
03319         int poIndex = fSceneTreeComponentTreeWidget->topLevelItem(b)->data(0,Qt::UserRole).toInt();
03320         if (poIndex != -1) {
03321           fOldPositivePoIndexSceneTreeWidgetQuickMap.insert(std::pair <int, QTreeWidgetItem*> (poIndex,cloneWidgetItem(fSceneTreeComponentTreeWidget->topLevelItem(b))));
03322         } else {
03323           fOldNullPoIndexSceneTreeWidgetQuickVector.push_back(cloneWidgetItem(fSceneTreeComponentTreeWidget->topLevelItem(b)));
03324         }
03325 
03326         // clone leaves
03327         cloneSceneTree(fSceneTreeComponentTreeWidget->topLevelItem(b));
03328       }
03329       // delete all elements
03330 
03331       fOldTreeItemModels.insert(fTreeItemModels.begin(), fTreeItemModels.end());  
03332 
03333       // all is copy, then clear scene tree
03334       int tmp2 = fSceneTreeComponentTreeWidget->topLevelItemCount();
03335       while (tmp2 > 0) {
03336         delete fSceneTreeComponentTreeWidget->takeTopLevelItem (0);
03337         tmp2 = fSceneTreeComponentTreeWidget->topLevelItemCount();
03338       }
03339       fPositivePoIndexSceneTreeWidgetQuickMap.clear();
03340 
03341       // put correct value in paramaters
03342       fOldLastSceneTreeWidgetAskFor = fOldPositivePoIndexSceneTreeWidgetQuickMap.begin();
03343       fSceneTreeDepth = 1;
03344       fModelShortNameItem = NULL;
03345       fMaxPOindexInserted = -1;
03346 
03347     }
03348   }
03349 }
03350 
03351 
03358 QTreeWidgetItem * G4OpenGLQtViewer::cloneWidgetItem(QTreeWidgetItem* item) {
03359 
03360   QTreeWidgetItem* cloneItem = new QTreeWidgetItem();
03361 
03362   // Clone what is create createTreeWidgetItem step
03363 
03364   cloneItem->setText(0,item->text(0));
03365   cloneItem->setData(1,Qt::UserRole,item->data(1,Qt::UserRole).toInt());
03366   cloneItem->setText(2,item->text(2));
03367   cloneItem->setData(0, Qt::UserRole,item->data(0,Qt::UserRole).toInt());
03368   cloneItem->setText(3,item->text(3));
03369   cloneItem->setFlags(item->flags());
03370   cloneItem->setToolTip(0,item->toolTip(0));        
03371   cloneItem->setCheckState(0,item->checkState(0));
03372   cloneItem->setSelected(item->isSelected()); 
03373   cloneItem->setExpanded(item->isExpanded ());
03374 
03375   cloneItem->setData(2,Qt::UserRole,item->data(2,Qt::UserRole).value<QColor>());
03376 
03377   return cloneItem;
03378 }
03379 
03380 
03384 void G4OpenGLQtViewer::cloneSceneTree(
03385  QTreeWidgetItem* rootItem
03386 ) {
03387   
03388   for (int b=0;b< rootItem->childCount();b++) {
03389 
03390     QTreeWidgetItem *child = rootItem->child(b);
03391 
03392     // clone top level items
03393     int poIndex = child->data(0,Qt::UserRole).toInt();
03394     if (poIndex != -1) {
03395       fOldPositivePoIndexSceneTreeWidgetQuickMap.insert(std::pair <int, QTreeWidgetItem*> (poIndex,cloneWidgetItem(child)));
03396     } else {
03397       fOldNullPoIndexSceneTreeWidgetQuickVector.push_back(cloneWidgetItem(child));
03398     }
03399     cloneSceneTree(child);
03400   }
03401 }
03402 
03403 
03407  void G4OpenGLQtViewer::updatePositivePoIndexSceneTreeWidgetQuickMap(int POindex,QTreeWidgetItem* item) {
03408 
03409    // Check state
03410    std::map <int, QTreeWidgetItem*>::iterator i;
03411    i = fPositivePoIndexSceneTreeWidgetQuickMap.find(POindex);
03412 
03413    if (i == fPositivePoIndexSceneTreeWidgetQuickMap.end()) {
03414      fPositivePoIndexSceneTreeWidgetQuickMap.insert(std::pair <int, QTreeWidgetItem*> (POindex,item) );
03415      fLastSceneTreeWidgetAskFor = fPositivePoIndexSceneTreeWidgetQuickMap.end();
03416    } else {
03417      i->second = item;
03418    }
03419  }
03420 
03421 
03422 
03423 void G4OpenGLQtViewer::changeQColorForTreeWidgetItem(QTreeWidgetItem* item,const QColor& qc) {
03424 
03425   int POIndex = item->data(0,Qt::UserRole).toInt();
03426   updatePositivePoIndexSceneTreeWidgetQuickMap(POIndex,item );
03427 
03428   QPixmap pixmap = QPixmap(QSize(16, 16));
03429   if (item->data(0,Qt::UserRole).toInt() != -1) {
03430     pixmap.fill (qc);
03431   } else {
03432     pixmap.fill (QColor(255,255,255,255));
03433   }
03434   QPainter painter(&pixmap);
03435   painter.setPen(Qt::black);
03436   painter.drawRect(0,0,15,15); // Draw contour
03437 
03438   item->setIcon(0,pixmap);
03439   item->setData(2,Qt::UserRole,qc);
03440 }
03441 
03442 
03443 
03448 QTreeWidgetItem* G4OpenGLQtViewer::getTreeWidgetItem(int POindex){
03449 
03450   // -1 is not a visible item
03451   if (POindex == -1) {
03452     return NULL;
03453   }
03454 
03455   if (fPositivePoIndexSceneTreeWidgetQuickMap.size() == 0){
03456     return NULL;
03457   }
03458 
03459   if (POindex == fLastSceneTreeWidgetAskFor->first) {
03460     if (fLastSceneTreeWidgetAskFor->second != NULL) {
03461       return fLastSceneTreeWidgetAskFor->second;
03462     }
03463   }
03464   
03465   // if not, use the "find" algorithm
03466   fLastSceneTreeWidgetAskFor = fPositivePoIndexSceneTreeWidgetQuickMap.find(POindex);
03467   
03468   if (fLastSceneTreeWidgetAskFor != fPositivePoIndexSceneTreeWidgetQuickMap.end()) {
03469     return fLastSceneTreeWidgetAskFor->second;
03470   }
03471   return NULL;
03472 }
03473 
03478 QTreeWidgetItem* G4OpenGLQtViewer::getOldTreeWidgetItem(int POindex){
03479 
03480 
03481   // -1 is not a visible item
03482   if (POindex == -1) {
03483     return NULL;
03484   }
03485 
03486   if (fOldPositivePoIndexSceneTreeWidgetQuickMap.size() == 0){
03487     return NULL;
03488   }
03489 
03490   // Should be call only once by item addition
03491   fOldLastSceneTreeWidgetAskFor++;
03492 
03493   if (POindex == fOldLastSceneTreeWidgetAskFor->first) {
03494     if (fOldLastSceneTreeWidgetAskFor->second != NULL) {
03495       if (fOldLastSceneTreeWidgetAskFor != fOldPositivePoIndexSceneTreeWidgetQuickMap.end()) {
03496         return fOldLastSceneTreeWidgetAskFor->second;
03497       }
03498     }
03499   }
03500   
03501   // if not, use the "find" algorithm
03502   fOldLastSceneTreeWidgetAskFor = fOldPositivePoIndexSceneTreeWidgetQuickMap.find(POindex);
03503   
03504   if (fOldLastSceneTreeWidgetAskFor != fOldPositivePoIndexSceneTreeWidgetQuickMap.end()) {
03505     return fOldLastSceneTreeWidgetAskFor->second;
03506   }
03507   return NULL;
03508 }
03509 
03510 
03511 
03516 void G4OpenGLQtViewer::displaySceneTreeComponent() {
03517   // no UI
03518   if (fUISceneTreeComponentsTBWidget == NULL) {
03519     return; 
03520   }
03521   if (fSceneTreeComponentTreeWidget == NULL) {
03522     return; 
03523   }
03524 
03525   // sort tree items
03526   fSceneTreeComponentTreeWidget->sortItems (0, Qt::AscendingOrder );
03527 
03528   return;
03529 }
03530 
03531 
03538 void G4OpenGLQtViewer::updateToolbarAndMouseContextMenu(){
03539    if (fBatchMode) {
03540      return;
03541    }
03542 
03543   G4ViewParameters::DrawingStyle
03544   d_style = fVP.GetDrawingStyle();
03545   
03546   // Surface style
03547   if (d_style == G4ViewParameters::wireframe) {
03548     if (fUiQt) fUiQt->SetIconWireframeSelected();
03549     if (fContextMenu) {
03550       fDrawingWireframe->setChecked(true);
03551       fDrawingLineRemoval->setChecked(false);
03552       fDrawingSurfaceRemoval->setChecked(false);
03553       fDrawingLineSurfaceRemoval->setChecked(false);
03554     }    
03555   } else if (d_style == G4ViewParameters::hlr) {
03556     if (fUiQt) fUiQt->SetIconHLRSelected();
03557     if (fContextMenu) {
03558       fDrawingLineRemoval->setChecked(true);
03559       fDrawingWireframe->setChecked(false);
03560       fDrawingSurfaceRemoval->setChecked(false);
03561       fDrawingLineSurfaceRemoval->setChecked(false);
03562     }    
03563   } else if (d_style == G4ViewParameters::hsr) {
03564     if (fUiQt) fUiQt->SetIconSolidSelected();
03565     if (fContextMenu) {
03566       fDrawingSurfaceRemoval->setChecked(true);
03567       fDrawingWireframe->setChecked(false);
03568       fDrawingLineRemoval->setChecked(false);
03569       fDrawingLineSurfaceRemoval->setChecked(false);
03570     }
03571   } else if (d_style == G4ViewParameters::hlhsr) {
03572     if (fUiQt) fUiQt->SetIconHLHSRSelected();
03573     if (fContextMenu) {
03574       fDrawingLineSurfaceRemoval->setChecked(true);
03575       fDrawingWireframe->setChecked(false);
03576       fDrawingLineRemoval->setChecked(false);
03577       fDrawingSurfaceRemoval->setChecked(false);
03578       fDrawingLineSurfaceRemoval->setChecked(false);
03579     }
03580   }
03581   
03582   
03583   // projection style
03584   G4double d_proj = fVP.GetFieldHalfAngle () ;
03585   if (d_proj == 0.) { // ortho
03586     if (fUiQt) fUiQt->SetIconOrthoSelected();
03587     if (fContextMenu) {
03588       fProjectionOrtho->setChecked(true);
03589       fProjectionPerspective->setChecked(false);
03590     }    
03591   } else {
03592     if (fUiQt) fUiQt->SetIconPerspectiveSelected();
03593       if (fContextMenu) {
03594         fProjectionPerspective->setChecked(true);
03595         fProjectionOrtho->setChecked(false);
03596       }
03597   }
03598   
03599   
03600   // mouse style : They are controlled by UI !
03601   if (fUiQt && fContextMenu) {
03602     if (fUiQt->IsIconPickSelected()) {
03603       fMousePickAction->setChecked(true);
03604       fMouseZoomOutAction->setChecked(false);
03605       fMouseZoomInAction->setChecked(false);
03606       fMouseRotateAction->setChecked(false);
03607       fMouseMoveAction->setChecked(false);
03608     } else if (fUiQt->IsIconZoomOutSelected()) {
03609       fMouseZoomOutAction->setChecked(true);
03610       fMousePickAction->setChecked(false);
03611       fMouseZoomInAction->setChecked(false);
03612       fMouseRotateAction->setChecked(false);
03613       fMouseMoveAction->setChecked(false);
03614     } else if (fUiQt->IsIconZoomInSelected()) {
03615       fMouseZoomInAction->setChecked(true);
03616       fMousePickAction->setChecked(false);
03617       fMouseZoomOutAction->setChecked(false);
03618       fMouseRotateAction->setChecked(false);
03619       fMouseMoveAction->setChecked(false);
03620     } else if (fUiQt->IsIconRotateSelected()) {
03621       fMouseRotateAction->setChecked(true);
03622       fMousePickAction->setChecked(false);
03623       fMouseZoomOutAction->setChecked(false);
03624       fMouseZoomInAction->setChecked(false);
03625       fMouseMoveAction->setChecked(false);
03626     } else if (fUiQt->IsIconMoveSelected()) {
03627       fMouseMoveAction->setChecked(true);
03628       fMousePickAction->setChecked(false);
03629       fMouseZoomOutAction->setChecked(false);
03630       fMouseZoomInAction->setChecked(false);
03631       fMouseRotateAction->setChecked(false);
03632     }
03633   }
03634 }
03635 
03636 
03637 /*
03638   
03639 void MultiLayer::exportToSVG(const QString& fname)
03640 {
03641 QPicture picture;
03642 QPainter p(&picture);
03643 for (int i=0;i<(int)graphsList->count();i++)
03644 {
03645 Graph *gr=(Graph *)graphsList->at(i);
03646 Plot *myPlot= (Plot *)gr->plotWidget();
03647       
03648 QPoint pos=gr->pos();
03649       
03650 int width=int(myPlot->frameGeometry().width());
03651 int height=int(myPlot->frameGeometry().height());
03652       
03653 myPlot->print(&p, QRect(pos,QSize(width,height)));
03654 }
03655   
03656 p.end();
03657 picture.save(fname, "svg");
03658 }
03659 */
03660 #endif

Generated on Mon May 27 17:49:10 2013 for Geant4 by  doxygen 1.4.7