source: trunk/source/visualization/OpenGL/src/G4OpenGLQtViewer.cc @ 1333

Last change on this file since 1333 was 1333, checked in by garnier, 14 years ago

shorcuts better implementation, Mouse move volume follow mouse position

  • Property svn:mime-type set to text/cpp
File size: 87.4 KB
Line 
1//
2// ********************************************************************
3// * License and Disclaimer                                           *
4// *                                                                  *
5// * The  Geant4 software  is  copyright of the Copyright Holders  of *
6// * the Geant4 Collaboration.  It is provided  under  the terms  and *
7// * conditions of the Geant4 Software License,  included in the file *
8// * LICENSE and available at  http://cern.ch/geant4/license .  These *
9// * include a list of copyright holders.                             *
10// *                                                                  *
11// * Neither the authors of this software system, nor their employing *
12// * institutes,nor the agencies providing financial support for this *
13// * work  make  any representation or  warranty, express or implied, *
14// * regarding  this  software system or assume any liability for its *
15// * use.  Please see the license in the file  LICENSE  and URL above *
16// * for the full disclaimer and the limitation of liability.         *
17// *                                                                  *
18// * This  code  implementation is the result of  the  scientific and *
19// * technical work of the GEANT4 collaboration.                      *
20// * By using,  copying,  modifying or  distributing the software (or *
21// * any work based  on the software)  you  agree  to acknowledge its *
22// * use  in  resulting  scientific  publications,  and indicate your *
23// * acceptance of all terms of the Geant4 Software license.          *
24// ********************************************************************
25//
26//
27// $Id: G4OpenGLQtViewer.cc,v 1.52 2010/06/23 13:29:23 lgarnier Exp $
28// GEANT4 tag $Name:  $
29//
30//
31// G4OpenGLQtViewer : Class to provide Qt specific
32//                     functionality for OpenGL in GEANT4
33//
34// 27/06/2003 : G.Barrand : implementation (at last !).
35
36#ifdef G4VIS_BUILD_OPENGLQT_DRIVER
37
38#include "G4OpenGLQtViewer.hh"
39#include "G4VViewer.hh"
40#include "G4VSceneHandler.hh"
41#include "G4OpenGLSceneHandler.hh"
42
43#include "G4ios.hh"
44#include "G4VisExtent.hh"
45#include "G4LogicalVolume.hh"
46#include "G4VSolid.hh"
47#include "G4Point3D.hh"
48#include "G4Normal3D.hh"
49#include "G4Scene.hh"
50#include "G4OpenGLQtExportDialog.hh"
51#include "G4OpenGLQtMovieDialog.hh"
52#include "G4UnitsTable.hh"
53#include "G4Qt.hh"
54#include "G4UIQt.hh"
55#include "G4UImanager.hh"
56#include "G4UIcommandTree.hh"
57#include <qlayout.h>
58#include <qdialog.h>
59#include <qprocess.h>
60#include <qapplication.h>
61#include <qdesktopwidget.h>
62
63#if QT_VERSION >= 0x040000
64#include <qmenu.h>
65#include <qimagewriter.h>
66#else
67#include <qaction.h>
68#include <qwidgetlist.h>
69#include <qpopupmenu.h>
70#include <qimage.h>
71#endif
72
73#include <qapplication.h>
74#include <qmessagebox.h>
75#include <qfiledialog.h>
76#include <qprinter.h>
77#include <qdatetime.h>
78#include <qpainter.h>
79#include <qgl.h> // include <qglwidget.h>
80#include <qdialog.h>
81#include <qevent.h> //include <qcontextmenuevent.h>
82
83
84//////////////////////////////////////////////////////////////////////////////
85/**
86   Implementation of virtual method of G4VViewer
87*/
88void G4OpenGLQtViewer::SetView (
89)
90//////////////////////////////////////////////////////////////////////////////
91//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!//
92{
93  G4OpenGLViewer::SetView ();
94}
95
96
97
98
99//////////////////////////////////////////////////////////////////////////////
100void G4OpenGLQtViewer::CreateMainWindow (
101 QGLWidget* glWidget
102 ,QString name
103)
104//////////////////////////////////////////////////////////////////////////////
105//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!//
106{
107
108  if(fWindow) return; //Done.
109
110  fWindow = glWidget ;
111  //  fWindow->makeCurrent();
112
113#ifdef G4DEBUG_VIS_OGL
114#if QT_VERSION < 0x040000
115  printf("G4OpenGLQtViewer::CreateMainWindow :: ++++++++++++++ add new TAB %s  W:%d H:%d SizeHinX:%d SizeHintY:%d\n",name.ascii(),getWinWidth(),getWinHeight(),fVP.GetWindowSizeHintX(),fVP.GetWindowSizeHintY());
116#else
117  printf("G4OpenGLQtViewer::CreateMainWindow :: ++++++++++++++ add new TAB %s  W:%d H:%d SizeHinX:%d SizeHintY:%d\n",name.toStdString().c_str(),getWinWidth(),getWinHeight(),fVP.GetWindowSizeHintX(),fVP.GetWindowSizeHintY());
118#endif
119#endif
120  //G4Qt* interactorManager = G4Qt::getInstance ();
121
122  ResizeWindow(fVP.GetWindowSizeHintX(),fVP.GetWindowSizeHintY());
123   
124  // FIXME L.Garnier 9/11/09 Has to be check !!!
125  // Qt UI with Qt Vis
126  // Qt UI with X Vis
127  // X UI with Qt Vis
128  // X UI with X Vis
129  // Ne marche pas avec un UIBatch !! (ecran blanc)
130
131  // return false if G4UIQt was not launch
132
133  G4UImanager* UI = G4UImanager::GetUIpointer();
134  if (UI == NULL) return;
135
136  if (! static_cast<G4UIQt*> (UI->GetG4UIWindow())) return;
137
138  G4UIQt * uiQt = static_cast<G4UIQt*> (UI->GetG4UIWindow());
139 
140  bool isTabbedView = false;
141  if ( uiQt) {
142    isTabbedView = uiQt->AddTabWidget(fWindow,name,getWinWidth(),getWinHeight());
143  }
144#ifdef G4DEBUG_VIS_OGL
145  else {
146    printf("G4OpenGLQtViewer::CreateMainWindow :: UIQt NOt found \n");
147  }
148#endif
149
150  if (!isTabbedView) { // we have to do a dialog
151
152    QWidget *myParent = getParentWidget();
153#ifdef G4DEBUG_VIS_OGL
154    printf("G4OpenGLQtViewer::CreateMainWindow :: getParent OK \n");
155#endif
156    if (myParent != NULL) {
157#if QT_VERSION < 0x040000
158      glWidget->reparent(myParent,0,QPoint(0,0)); 
159#else
160      glWidget->setParent(myParent); 
161#endif
162    }
163    QHBoxLayout *mainLayout = new QHBoxLayout(fGLWindow);
164   
165    mainLayout->setMargin(0);
166    mainLayout->setSpacing(0);   
167    mainLayout->addWidget(fWindow);
168    if (fGLWindow->inherits("QMainWindow")) {
169#if QT_VERSION < 0x040000
170      fGLWindow->setCaption(name );
171#else
172      fGLWindow->setWindowTitle( name);
173#endif
174    }
175#if QT_VERSION >= 0x040000
176    fGLWindow->setLayout(mainLayout);
177#endif
178
179   
180    //useful for MACOSX, we have to compt the menuBar height
181    int offset = QApplication::desktop()->height()
182      - QApplication::desktop()->availableGeometry().height();
183   
184    G4int YPos= fVP.GetWindowAbsoluteLocationHintY(QApplication::desktop()->height());
185    if (fVP.GetWindowAbsoluteLocationHintY(QApplication::desktop()->height())< offset) {
186      YPos = offset;
187    }
188    fGLWindow->resize(getWinWidth(), getWinHeight());
189#ifdef G4DEBUG_VIS_OGL
190    printf("G4OpenGLQtViewer::CreateMainWindow :: resizing to %d %d \n",getWinWidth(), getWinHeight());
191#endif
192    fGLWindow->move(fVP.GetWindowAbsoluteLocationHintX(QApplication::desktop()->width()),YPos);
193    fGLWindow->show();
194  } else {
195    fGLWindow = fWindow;
196    fGLWindow->resize(getWinWidth(), getWinHeight());
197  }
198
199  if(!fWindow) return;
200 
201  if (!fContextMenu)
202    createPopupMenu();
203
204}
205
206#if QT_VERSION >= 0x040000
207/**  Close the dialog and set the pointer to NULL
208 */
209// void G4OpenGLQtViewer::dialogClosed() {
210//   //  fGLWindow = NULL;
211// }
212#endif
213
214//////////////////////////////////////////////////////////////////////////////
215G4OpenGLQtViewer::G4OpenGLQtViewer (
216                                    G4OpenGLSceneHandler& scene
217                                    )
218  :G4VViewer (scene, -1)
219  ,G4OpenGLViewer (scene)
220  ,fWindow(0)
221  ,fRecordFrameNumber(0)
222  ,fContextMenu(0)
223  ,fMouseAction(STYLE1)
224  ,fDeltaRotation(1)
225  ,fDeltaSceneTranslation(0.01)
226  ,fDeltaDepth(0.01)
227  ,fDeltaZoom(0.05)
228  ,fDeltaMove(0.05)
229  ,fHoldKeyEvent(false)
230  ,fHoldMoveEvent(false)
231  ,fHoldRotateEvent(false)
232  ,fAutoMove(false)
233  ,fEncoderPath("")
234  ,fTempFolderPath("")
235  ,fMovieTempFolderPath("")
236  ,fSaveFileName("")
237  ,fParameterFileName("mpeg_encode_parameter_file.par")
238  ,fMovieParametersDialog(NULL)
239  ,fRecordingStep(WAIT)
240  ,fProcess(NULL)
241  ,fNbMaxFramesPerSec(100)
242  ,fNbMaxAnglePerSec(360)
243  ,fLaunchSpinDelay(100)
244  ,fXRot(0)
245  ,fYRot(0)
246  ,fNoKeyPress(true)
247  ,fAltKeyPress(false)
248  ,fControlKeyPress(false)
249  ,fShiftKeyPress(false)
250{
251
252  // launch Qt if not
253  G4Qt::getInstance ();
254
255  fLastPos3 = QPoint(-1,-1);   
256  fLastPos2 = QPoint(-1,-1);   
257  fLastPos1 = QPoint(-1,-1);   
258 
259  initMovieParameters();
260
261  fLastEventTime = new QTime();
262
263#ifdef G4DEBUG_VIS_OGL
264  printf("G4OpenGLQtViewer::G4OpenGLQtViewer END\n");
265#endif
266}
267
268//////////////////////////////////////////////////////////////////////////////
269G4OpenGLQtViewer::~G4OpenGLQtViewer (
270)
271//////////////////////////////////////////////////////////////////////////////
272//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!//
273{
274#if QT_VERSION < 0x040000
275  G4cout <<removeTempFolder().ascii() <<G4endl;
276#else
277  G4cout <<removeTempFolder().toStdString().c_str() <<G4endl;
278#endif
279}
280
281
282/**
283   Create a popup menu for the widget. This menu is activated by right-mouse click
284*/
285void G4OpenGLQtViewer::createPopupMenu()    {
286
287#if QT_VERSION < 0x040000
288  fContextMenu = new QPopupMenu( fGLWindow,"All" );
289#else
290  fContextMenu = new QMenu("All");
291#endif
292
293#if QT_VERSION < 0x040000
294  QPopupMenu *mMouseAction = new QPopupMenu( fContextMenu );
295  fContextMenu->insertItem("&Mouse actions",mMouseAction);
296#if QT_VERSION < 0x030200
297  fRotateAction =  new QAction("&Rotate","&Rotate",CTRL+Key_R,mMouseAction,0,true);
298  fMoveAction =  new QAction("&Move","&Move",CTRL+Key_M,mMouseAction,0,true);
299  fPickAction =  new QAction("&Pick","&Pick",CTRL+Key_P,mMouseAction,0,true);
300  QAction * shortcutsAction =  new QAction("&Show shortcuts","&Show shortcuts",CTRL+Key_S,mMouseAction,0,true);
301#else
302  fRotateAction =  new QAction("&Rotate",CTRL+Key_R,mMouseAction);
303  fMoveAction =  new QAction("&Move",CTRL+Key_M,mMouseAction);
304  fPickAction =  new QAction("&Pick",CTRL+Key_P,mMouseAction);
305  QAction *shortcutsAction =  new QAction("&Show shortcuts",CTRL+Key_S,mMouseAction);
306#endif
307  fRotateAction->addTo(mMouseAction);
308  fMoveAction->addTo(mMouseAction);
309  fPickAction->addTo(mMouseAction);
310  shortcutsAction->addTo(mMouseAction);
311
312  fRotateAction->setToggleAction(true);
313  fMoveAction->setToggleAction(true);
314  fPickAction->setToggleAction(true);
315  shortcutsAction->setToggleAction(true);
316
317  fRotateAction->setOn(true);
318  fMoveAction->setOn(false);
319  fPickAction->setOn(false);
320  shortcutsAction->setOn(false);
321
322
323  QObject ::connect(fRotateAction,
324                    SIGNAL(activated()),
325                    this,
326                    SLOT(actionMouseRotate()));
327
328  QObject ::connect(fMoveAction,
329                    SIGNAL(activated()),
330                    this,
331                    SLOT(actionMouseMove()));
332
333  QObject ::connect(fPickAction,
334                    SIGNAL(activated()),
335                    this,
336                    SLOT(actionMousePick()));
337
338  QObject ::connect(shortcutsAction,
339                    SIGNAL(activated()),
340                    this,
341                    SLOT(showShortcuts()));
342
343#else
344  QMenu *mMouseAction = fContextMenu->addMenu("&Mouse actions");
345
346  fRotateAction = mMouseAction->addAction("Rotate");
347  fMoveAction = mMouseAction->addAction("Move");
348  fPickAction = mMouseAction->addAction("Pick");
349  QAction *shortcutsAction = mMouseAction->addAction("Show shortcuts");
350
351  fRotateAction->setCheckable(true);
352  fMoveAction->setCheckable(false);
353  fPickAction->setCheckable(false);
354  shortcutsAction->setCheckable(false);
355
356  fRotateAction->setChecked(true);
357  fMoveAction->setChecked(false);
358  fPickAction->setChecked(false);
359  shortcutsAction->setChecked(false);
360
361  QObject ::connect(fRotateAction,
362                    SIGNAL(triggered(bool)),
363                    this,
364                    SLOT(actionMouseRotate()));
365
366  QObject ::connect(fMoveAction,
367                    SIGNAL(triggered(bool)),
368                    this,
369                    SLOT(actionMouseMove()));
370
371  QObject ::connect(fPickAction,
372                    SIGNAL(triggered(bool)),
373                    this,
374                    SLOT(actionMousePick()));
375
376  QObject ::connect(shortcutsAction,
377                    SIGNAL(triggered(bool)),
378                    this,
379                    SLOT(showShortcuts()));
380#endif
381
382#if QT_VERSION < 0x040000
383  // === Style Menu ===
384  QPopupMenu *mStyle = new QPopupMenu(fContextMenu);
385
386  QPopupMenu *mRepresentation = new QPopupMenu(fContextMenu);
387
388  QPopupMenu *mProjection = new QPopupMenu(fContextMenu);
389
390#if QT_VERSION < 0x030200
391  QAction *polyhedron = new QAction("&Polyhedron","&Polyhedron",CTRL+Key_P,mRepresentation,0,true);
392  QAction *nurbs = new QAction("&NURBS","&NURBS",CTRL+Key_N,mRepresentation,0,true);
393
394  QAction *ortho = new QAction("&Orthographic","&Orthographic",CTRL+Key_O,mProjection,0,true);
395  QAction *perspective = new QAction("&Perspective","&Perspective",CTRL+Key_P,mProjection,0,true);
396#else
397  QAction *polyhedron = new QAction("&Polyhedron",CTRL+Key_P,mRepresentation);
398  QAction *nurbs = new QAction("&NURBS",CTRL+Key_N,mRepresentation);
399
400  QAction *ortho = new QAction("&Orthographic",CTRL+Key_O,mProjection);
401  QAction *perspective = new QAction("&Perspective",CTRL+Key_P,mProjection);
402  polyhedron->setToggleAction(true);
403  nurbs->setToggleAction(true);
404  ortho->setToggleAction(true);
405  perspective->setToggleAction(true);
406#endif
407  polyhedron->addTo(mRepresentation);
408  nurbs->addTo(mRepresentation);
409
410  ortho->addTo(mProjection);
411  perspective->addTo(mProjection);
412
413  mStyle->insertItem("&Representation",mRepresentation);
414  mStyle->insertItem("&Projection",mProjection);
415  fContextMenu->insertItem("&Style",mStyle);
416
417
418#else
419  // === Style Menu ===
420  QMenu *mStyle = fContextMenu->addMenu("&Style");
421
422  QMenu *mRepresentation = mStyle->addMenu("&Representation");
423  QMenu *mProjection = mStyle->addMenu("&Projection");
424  QAction *polyhedron = mRepresentation->addAction("Polyhedron");
425  QAction *nurbs = mRepresentation->addAction("NURBS");
426
427  QAction *ortho = mProjection->addAction("Orthographic");
428  QAction *perspective = mProjection->addAction("Persepective");
429#endif
430
431  // INIT mRepresentation
432  G4ViewParameters::RepStyle style;
433  style = fVP.GetRepStyle();
434  if (style == G4ViewParameters::polyhedron) {
435    createRadioAction(polyhedron,nurbs,SLOT(toggleRepresentation(bool)),1);
436  } else if (style == G4ViewParameters::nurbs) {
437    createRadioAction(polyhedron,nurbs,SLOT(toggleRepresentation(bool)),2);
438  } else {
439    mRepresentation->clear();
440  }
441
442  // INIT mProjection
443  if (fVP.GetFieldHalfAngle() == 0) {
444    createRadioAction(ortho, perspective,SLOT(toggleProjection(bool)),1);
445  } else {
446    createRadioAction(ortho, perspective,SLOT(toggleProjection(bool)),2);
447  }
448
449#if QT_VERSION < 0x040000
450  // === Drawing Menu ===
451  QPopupMenu *mDrawing = new QPopupMenu(fContextMenu);
452  fContextMenu->insertItem("&Drawing",mDrawing);
453
454#if QT_VERSION < 0x030200
455  fDrawingWireframe = new QAction("&Wireframe","&Wireframe",CTRL+Key_W,mDrawing,0,true);
456  fDrawingLineRemoval = new QAction("&Hidden line removal","&Hidden line removal",CTRL+Key_L,mDrawing,0,true);
457  fDrawingSurfaceRemoval = new QAction("&Hidden surface removal","&Hidden surface removal",CTRL+Key_S,mDrawing,0,true);
458  fDrawingLineSurfaceRemoval = new QAction("&Hidden line and surface removal","&Hidden line and surface removal",CTRL+Key_R,mDrawing,0,true);
459#else
460  fDrawingWireframe = new QAction("&Wireframe",CTRL+Key_W,mDrawing);
461  fDrawingLineRemoval = new QAction("&Hidden line removal",CTRL+Key_L,mDrawing);
462  fDrawingSurfaceRemoval = new QAction("&Hidden surface removal",CTRL+Key_S,mDrawing);
463  fDrawingLineSurfaceRemoval = new QAction("&Hidden line and surface removal",CTRL+Key_R,mDrawing);
464#endif
465  fDrawingWireframe->setToggleAction(true);
466  fDrawingLineRemoval->setToggleAction(true);
467  fDrawingSurfaceRemoval->setToggleAction(true);
468  fDrawingLineSurfaceRemoval->setToggleAction(true);
469
470  fDrawingWireframe->addTo(mDrawing);
471  fDrawingLineRemoval->addTo(mDrawing);
472  fDrawingSurfaceRemoval->addTo(mDrawing);
473  fDrawingLineSurfaceRemoval->addTo(mDrawing);
474
475
476#else
477  // === Drawing Menu ===
478  QMenu *mDrawing = mStyle->addMenu("&Drawing");
479
480  fDrawingWireframe = mDrawing->addAction("Wireframe");
481  fDrawingWireframe->setCheckable(true);
482
483  fDrawingLineRemoval = mDrawing->addAction("Hidden line removal");
484  fDrawingLineRemoval->setCheckable(true);
485
486  fDrawingSurfaceRemoval = mDrawing->addAction("Hidden Surface removal");
487  fDrawingSurfaceRemoval->setCheckable(true);
488
489  fDrawingLineSurfaceRemoval = mDrawing->addAction("Hidden line and surface removal");
490  fDrawingLineSurfaceRemoval->setCheckable(true);
491#endif
492  // INIT Drawing
493  G4ViewParameters::DrawingStyle d_style;
494  d_style = fVP.GetDrawingStyle();
495 
496#if QT_VERSION < 0x040000
497  if (d_style == G4ViewParameters::wireframe) {
498    fDrawingWireframe->setOn(true);
499  } else if (d_style == G4ViewParameters::hlr) {
500    fDrawingLineRemoval->setOn(true);
501  } else if (d_style == G4ViewParameters::hsr) {
502    fDrawingSurfaceRemoval->setOn(true);
503  } else if (d_style == G4ViewParameters::hlhsr) {
504    fDrawingLineSurfaceRemoval->setOn(true);
505  } else {
506    mDrawing->clear();
507  }
508  QObject ::connect(fDrawingWireframe,
509                    SIGNAL(activated()),
510                    this,
511                    SLOT(actionDrawingWireframe()));
512  QObject ::connect(fDrawingLineRemoval,
513                    SIGNAL(activated()),
514                    this,
515                    SLOT(actionDrawingLineRemoval()));
516  QObject ::connect(fDrawingSurfaceRemoval,
517                    SIGNAL(activated()),
518                    this,
519                    SLOT(actionDrawingSurfaceRemoval()));
520  QObject ::connect(fDrawingLineSurfaceRemoval,
521                    SIGNAL(activated()),
522                    this,
523                    SLOT(actionDrawingLineSurfaceRemoval()));
524#else
525  if (d_style == G4ViewParameters::wireframe) {
526    fDrawingWireframe->setChecked(true);
527  } else if (d_style == G4ViewParameters::hlr) {
528    fDrawingLineRemoval->setChecked(true);
529  } else if (d_style == G4ViewParameters::hsr) {
530    fDrawingSurfaceRemoval->setChecked(true);
531  } else if (d_style == G4ViewParameters::hlhsr) {
532    fDrawingLineSurfaceRemoval->setChecked(true);
533  } else {
534    mDrawing->clear();
535  }
536  QObject ::connect(fDrawingWireframe,
537                    SIGNAL(triggered(bool)),
538                    this,
539                    SLOT(actionDrawingWireframe()));
540  QObject ::connect(fDrawingLineRemoval,
541                    SIGNAL(triggered(bool)),
542                    this,
543                    SLOT(actionDrawingLineRemoval()));
544  QObject ::connect(fDrawingSurfaceRemoval,
545                    SIGNAL(triggered(bool)),
546                    this,
547                    SLOT(actionDrawingSurfaceRemoval()));
548  QObject ::connect(fDrawingLineSurfaceRemoval,
549                    SIGNAL(triggered(bool)),
550                    this,
551                    SLOT(actionDrawingLineSurfaceRemoval()));
552#endif
553
554
555
556#if QT_VERSION < 0x040000
557  QPopupMenu *mBackground = new QPopupMenu(mStyle);
558  mStyle->insertItem("&Background color",mBackground);
559
560#if QT_VERSION < 0x030200
561  QAction *white = new QAction("&White","&White",CTRL+Key_W,mBackground,0,true);
562  QAction *black =  new QAction("&Black","&Black",CTRL+Key_B,mBackground,0,true);
563#else
564  QAction *white = new QAction("&White",CTRL+Key_W,mBackground);
565  QAction *black =  new QAction("&Black",CTRL+Key_B,mBackground);
566  white->setToggleAction(true);
567  black->setToggleAction(true);
568#endif
569  white->addTo(mBackground);
570  black->addTo(mBackground);
571
572#else
573  QMenu *mBackground = mStyle->addMenu("&Background color");
574  QAction *white = mBackground->addAction("White");
575  QAction *black = mBackground->addAction("Black");
576
577#endif
578  if (background.GetRed() == 1. &&
579      background.GetGreen() == 1. &&
580      background.GetBlue() == 1.) {
581    createRadioAction(white,black,SLOT(toggleBackground(bool)),1);
582  } else {
583    createRadioAction(white,black,SLOT(toggleBackground(bool)),2);
584  }
585
586
587#if QT_VERSION < 0x040000
588  // === Action Menu ===
589  QPopupMenu *mActions = new QPopupMenu(fContextMenu);
590  fContextMenu->insertItem("&Actions",mActions);
591
592#if QT_VERSION < 0x030200
593  QAction *createEPS =  new QAction("&Save as ...","&Save as ...",CTRL+Key_S,mActions,0,true);
594#else
595  QAction *createEPS =  new QAction("&Save as ...",CTRL+Key_S,mActions);
596#endif
597  createEPS->addTo(mActions);
598  QObject ::connect(createEPS,
599                    SIGNAL(activated()),
600                    this,
601                    SLOT(actionSaveImage()));
602
603#else
604  // === Action Menu ===
605  QMenu *mActions = fContextMenu->addMenu("&Actions");
606  QAction *createEPS = mActions->addAction("Save as ...");
607  QObject ::connect(createEPS,
608                    SIGNAL(triggered()),
609                    this,
610                    SLOT(actionSaveImage()));
611#endif
612
613#if QT_VERSION < 0x040000
614#if QT_VERSION < 0x030200
615  QAction *movieParameters =  new QAction("&Make Movie...","&Make movie ...",CTRL+Key_M,mActions,0,true);
616#else
617  QAction *movieParameters =  new QAction("&Make Movie...",CTRL+Key_M,mActions);
618#endif
619  movieParameters->addTo(mActions);
620  QObject ::connect(movieParameters,
621                    SIGNAL(activated()),
622                    this,
623                    SLOT(actionMovieParameters()));
624
625#else
626  // === Action Menu ===
627  QAction *movieParameters = mActions->addAction("Movie parameters...");
628  QObject ::connect(movieParameters,
629                    SIGNAL(triggered()),
630                    this,
631                    SLOT(actionMovieParameters()));
632#endif
633
634
635
636
637#if QT_VERSION < 0x040000
638  // === Special Menu ===
639  QPopupMenu *mSpecial = new QPopupMenu(fContextMenu);
640  fContextMenu->insertItem("S&pecial",mSpecial);
641
642  QPopupMenu *mTransparency = new QPopupMenu(mSpecial);
643  mSpecial->insertItem("Transparency",mTransparency);
644
645#if QT_VERSION < 0x030200
646  QAction *transparencyOn = new QAction("&On","&On",CTRL+Key_O,mTransparency,0,true);
647  QAction *transparencyOff = new QAction("&Off","&Off",CTRL+Key_F,mTransparency,0,true);
648#else
649  QAction *transparencyOn = new QAction("&On",CTRL+Key_O,mTransparency);
650  QAction *transparencyOff = new QAction("&Off",CTRL+Key_F,mTransparency);
651  transparencyOn->setToggleAction(true);
652  transparencyOff->setToggleAction(true);
653#endif
654  transparencyOn->addTo(mTransparency);
655  transparencyOff->addTo(mTransparency);
656
657#else
658  // === Special Menu ===
659  QMenu *mSpecial = fContextMenu->addMenu("S&pecial");
660  QMenu *mTransparency = mSpecial->addMenu("Transparency");
661  QAction *transparencyOn = mTransparency->addAction("On");
662  QAction *transparencyOff = mTransparency->addAction("Off");
663#endif
664
665  if (transparency_enabled == false) {
666    createRadioAction(transparencyOn,transparencyOff,SLOT(toggleTransparency(bool)),2);
667  } else if (transparency_enabled == true) {
668    createRadioAction(transparencyOn,transparencyOff,SLOT(toggleTransparency(bool)),1);
669  } else {
670    mSpecial->clear();
671  }
672
673
674#if QT_VERSION < 0x040000
675  QPopupMenu *mAntialiasing = new QPopupMenu(mSpecial);
676  mSpecial->insertItem("Antialiasing",mAntialiasing);
677
678#if QT_VERSION < 0x030200
679  QAction *antialiasingOn = new QAction("&On","&On",CTRL+Key_O,mAntialiasing,0,true);
680  QAction *antialiasingOff = new QAction("&Off","&Off",CTRL+Key_F,mAntialiasing,0,true);
681#else
682  QAction *antialiasingOn = new QAction("&On",CTRL+Key_O,mAntialiasing);
683  QAction *antialiasingOff = new QAction("&Off",CTRL+Key_F,mAntialiasing);
684  antialiasingOn->setToggleAction(true);
685  antialiasingOff->setToggleAction(true);
686#endif
687  antialiasingOn->addTo(mAntialiasing);
688  antialiasingOff->addTo(mAntialiasing);
689
690#else
691  QMenu *mAntialiasing = mSpecial->addMenu("Antialiasing");
692  QAction *antialiasingOn = mAntialiasing->addAction("On");
693  QAction *antialiasingOff = mAntialiasing->addAction("Off");
694#endif
695
696  if (antialiasing_enabled == false) {
697    createRadioAction(antialiasingOn,antialiasingOff,SLOT(toggleAntialiasing(bool)),2);
698  } else if (antialiasing_enabled == true) {
699    createRadioAction(antialiasingOn,antialiasingOff,SLOT(toggleAntialiasing(bool)),1);
700  } else {
701    mAntialiasing->clear();
702  }
703
704#if QT_VERSION < 0x040000
705  QPopupMenu *mHaloing = new QPopupMenu(mSpecial);
706  mSpecial->insertItem("Haloing",mHaloing);
707
708#if QT_VERSION < 0x030200
709  QAction *haloingOn = new QAction("&On","&On",CTRL+Key_O,mHaloing,0,true);
710  QAction *haloingOff = new QAction("&Off","&Off",CTRL+Key_F,mHaloing,0,true);
711#else
712  QAction *haloingOn = new QAction("&On",CTRL+Key_O,mHaloing);
713  QAction *haloingOff = new QAction("&Off",CTRL+Key_F,mHaloing);
714  haloingOn->setToggleAction(true);
715  haloingOff->setToggleAction(true);
716#endif
717  haloingOn->addTo(mHaloing);
718  haloingOff->addTo(mHaloing);
719#else
720  QMenu *mHaloing = mSpecial->addMenu("Haloing");
721  QAction *haloingOn = mHaloing->addAction("On");
722  QAction *haloingOff = mHaloing->addAction("Off");
723#endif
724  if (haloing_enabled == false) {
725    createRadioAction(haloingOn,haloingOff,SLOT(toggleHaloing(bool)),2);
726  } else if (haloing_enabled == true) {
727    createRadioAction(haloingOn,haloingOff,SLOT(toggleHaloing(bool)),1);
728  } else {
729    mHaloing->clear();
730  }
731
732#if QT_VERSION < 0x040000
733  QPopupMenu *mAux = new QPopupMenu(mSpecial);
734  mSpecial->insertItem("Auxiliairy edges",mAux);
735
736#if QT_VERSION < 0x030200
737  QAction *auxOn = new QAction("&On","&On",CTRL+Key_O,mAux,0,true);
738  QAction *auxOff = new QAction("&Off","&Off",CTRL+Key_F,mAux,0,true);
739#else
740  QAction *auxOn = new QAction("&On",CTRL+Key_O,mAux);
741  QAction *auxOff = new QAction("&Off",CTRL+Key_F,mAux);
742  auxOn->setToggleAction(true);
743  auxOff->setToggleAction(true);
744#endif
745  auxOn->addTo(mAux);
746  auxOff->addTo(mAux);
747
748#else
749  QMenu *mAux = mSpecial->addMenu("Auxiliary edges");
750  QAction *auxOn = mAux->addAction("On");
751  QAction *auxOff = mAux->addAction("Off");
752#endif
753  if (!fVP.IsAuxEdgeVisible()) {
754    createRadioAction(auxOn,auxOff,SLOT(toggleAux(bool)),1);
755  } else {
756    createRadioAction(auxOn,auxOff,SLOT(toggleAux(bool)),2);
757  }
758
759
760
761#if QT_VERSION < 0x040000
762  QPopupMenu *mFullScreen = new QPopupMenu(mSpecial);
763  mSpecial->insertItem("Full screen",mFullScreen);
764
765#if QT_VERSION < 0x030200
766  fFullScreenOn = new QAction("&On","&On",CTRL+Key_O,mFullScreen,0,true);
767  fFullScreenOff = new QAction("&Off","&Off",CTRL+Key_F,mFullScreen,0,true);
768#else
769  fFullScreenOn = new QAction("&On",CTRL+Key_O,mFullScreen);
770  fFullScreenOff = new QAction("&Off",CTRL+Key_F,mFullScreen);
771  fFullScreenOn->setToggleAction(true);
772  fFullScreenOff->setToggleAction(true);
773#endif
774  fFullScreenOn->addTo(mFullScreen);
775  fFullScreenOff->addTo(mFullScreen);
776#else
777  QMenu *mFullScreen = mSpecial->addMenu("&Full screen");
778  fFullScreenOn = mFullScreen->addAction("On");
779  fFullScreenOff = mFullScreen->addAction("Off");
780#endif
781  createRadioAction(fFullScreenOn,fFullScreenOff,SLOT(toggleFullScreen(bool)),2);
782
783}
784
785
786void G4OpenGLQtViewer::G4manageContextMenuEvent(QContextMenuEvent *e)
787{
788  if (!fGLWindow) {
789    G4cerr << "Visualization window not defined, please choose one before" << G4endl;
790  } else {
791 
792    if (!fContextMenu)
793      createPopupMenu();
794   
795    // launch menu
796    if ( fContextMenu ) {
797      fContextMenu->exec( e->globalPos() );
798      //    delete fContextMenu;
799    }
800  }
801  e->accept();
802}
803
804
805/**
806   Create a radio button menu. The two menu will be connected. When click on one,
807   eatch state will be invert and callback method will be called.
808   @param action1 first action to connect
809   @param action2 second action to connect
810   @param method callback method
811   @param nCheck: 1 : first action will be set true. 2 : second action will be set true
812*/
813#if QT_VERSION < 0x040000
814void G4OpenGLQtViewer::createRadioAction(QAction *action1,QAction *action2, const std::string& method,unsigned int nCheck) {
815
816  if (action1->parent()->inherits("QPopupMenu")){
817    ((QPopupMenu*)action1->parent())->setCheckable(true);
818    ((QPopupMenu*)action2->parent())->setCheckable(true);
819  }
820  action1->setOn(false);
821   action2->setOn(false);
822
823  if (nCheck ==1)
824    action1->setOn(true);
825  else
826    action2->setOn(true);
827   
828  //FIXME : Should not work on Qt3
829  QObject ::connect(action1, SIGNAL(activated()),action2, SLOT(toggle()));
830  QObject ::connect(action2, SIGNAL(activated()),action1, SLOT(toggle()));
831
832  QObject ::connect(action1, SIGNAL(toggled(bool)),this, method.c_str());
833}
834
835#else
836void G4OpenGLQtViewer::createRadioAction(QAction *action1,QAction *action2, const std::string& method,unsigned int nCheck) {
837
838  action1->setCheckable(true);
839  action2->setCheckable(true);
840
841  if (nCheck ==1)
842    action1->setChecked (true);
843  else
844    action2->setChecked (true);
845   
846  QObject ::connect(action1, SIGNAL(triggered(bool)),action2, SLOT(toggle()));
847  QObject ::connect(action2, SIGNAL(triggered(bool)),action1, SLOT(toggle()));
848
849  QObject ::connect(action1, SIGNAL(toggled(bool)),this, method.c_str());
850
851}
852#endif
853
854/**
855   Slot activate when mouseAction->rotate menu is set
856 */
857void G4OpenGLQtViewer::actionMouseRotate() {
858  emit toggleMouseAction(STYLE1);
859}
860
861
862/**
863   Slot activate when mouseAction->rotate menu is set
864 */
865void G4OpenGLQtViewer::actionMouseMove() {
866  emit toggleMouseAction(STYLE2);
867}
868
869
870/**
871   Slot activate when mouseAction->zoom menu is set
872 */
873void G4OpenGLQtViewer::actionMousePick() {
874  emit toggleMouseAction(STYLE3);
875}
876
877
878/**
879   Slot activate when drawing->wireframe menu is set
880 */
881void G4OpenGLQtViewer::actionDrawingWireframe() {
882  emit toggleDrawingAction(1);
883}
884
885/**
886   Slot activate when drawing->line removal menu is set
887 */
888void G4OpenGLQtViewer::actionDrawingLineRemoval() {
889  emit toggleDrawingAction(2);
890}
891
892/**
893   Slot activate when drawing->surface removal menu is set
894 */
895void G4OpenGLQtViewer::actionDrawingSurfaceRemoval() {
896  emit toggleDrawingAction(3);
897}
898
899/**
900   Slot activate when drawing->wireframe menu is set
901 */
902void G4OpenGLQtViewer::actionDrawingLineSurfaceRemoval() {
903  emit toggleDrawingAction(4);
904}
905
906
907/**
908   Slot activated when mouse action is toggle
909   @param aAction : STYLE1, STYLE2, STYLE3
910 */
911void G4OpenGLQtViewer::toggleMouseAction(mouseActions aAction) {
912 
913  if ((aAction == STYLE1) || //initialize all
914      (aAction == STYLE2) ||
915      (aAction == STYLE3))  {
916#if QT_VERSION < 0x040000
917    fRotateAction->setOn (false);
918    fMoveAction->setOn (false);
919    fPickAction->setOn (false);
920#else
921    fRotateAction->setChecked (false);
922    fMoveAction->setChecked (false);
923    fPickAction->setChecked (false);
924#endif
925    fVP.SetPicking(false);
926    fMouseAction = aAction;
927  }
928  // rotate
929  if (aAction == STYLE1) {  // rotate
930    showShortcuts();
931#if QT_VERSION < 0x040000
932    fRotateAction->setOn (true);
933#else
934    fRotateAction->setChecked (true);
935#endif
936  } else  if (aAction == STYLE2) { //move
937#if QT_VERSION < 0x040000
938    fMoveAction->setOn (true);
939#else
940    fMoveAction->setChecked (true);
941#endif
942  } else  if (aAction == STYLE3) { //pick
943#if QT_VERSION < 0x040000
944    fPickAction->setOn (true);
945#else
946    fPickAction->setChecked (true);
947#endif
948    fVP.SetPicking(true);
949  }
950}
951
952/**
953   Show shortcuts for this mouse action
954 */
955void G4OpenGLQtViewer::showShortcuts() {
956  G4cout << "========= Mouse Shortcuts =========" << G4endl;
957  if (fMouseAction == STYLE1) {  // rotate
958    G4cout << "Click and move mouse to rotate volume " << G4endl;
959    G4cout << "ALT + Click and move mouse to rotate volume (View Direction)" << G4endl;
960    G4cout << "CTRL + Click and zoom mouse to zoom in/out" << G4endl;
961    G4cout << "SHIFT + Click and zoommove camera point of view" << G4endl;
962  } else  if (fMouseAction == STYLE2) { //move
963    G4cout << "Move camera point of view with mouse" << G4endl;
964  } else  if (fMouseAction == STYLE3) { //pick
965    G4cout << "Click and pick " << G4endl;
966  }
967  G4cout << "========= Move Shortcuts =========" << G4endl;
968  G4cout << "Press left/right arrows to move volume left/right" << G4endl;
969  G4cout << "Press up/down arrows to move volume up/down" << G4endl;
970  G4cout << "Press '+'/'-' to move volume toward/forward" << G4endl;
971  G4cout <<  G4endl;
972  G4cout << "========= Rotation (Theta/Phi) Shortcuts =========" << G4endl;
973  G4cout << "Press SHIFT + left/right arrows to rotate volume left/right" << G4endl;
974  G4cout << "Press SHIFT + up/down arrows to rotate volume up/down" << G4endl;
975  G4cout <<  G4endl;
976  G4cout << "========= Rotation (View Direction) Shortcuts =========" << G4endl;
977  G4cout << "Press ALT + left/right to rotate volume around vertical direction" << G4endl;
978  G4cout << "Press ALT + up/down to rotate volume around horizontal direction" << G4endl;
979  G4cout <<  G4endl;
980  G4cout << "========= Zoom View =========" << G4endl;
981  G4cout << "Press CTRL + '+'/'-' to zoom into volume" << G4endl;
982  G4cout <<  G4endl;
983  G4cout << "========= Misc =========" << G4endl;
984  G4cout << "Press ALT +/- to slow/speed auto rotation/move" << G4endl;
985  G4cout << "Press H to reset view" << G4endl;
986  G4cout << "Press Esc to exit FullScreen" << G4endl;
987  G4cout <<  G4endl;
988  G4cout << "========= Video =========" << G4endl;
989  G4cout << "In video mode : " << G4endl;
990  G4cout << " Press SPACE to Start/Pause video recording " << G4endl;
991  G4cout << " Press RETURN to Stop video recording " << G4endl;
992  G4cout <<  G4endl;
993}
994
995
996
997/**
998   Slot activated when drawing menu is toggle
999   Warning : When G4OpenGLStoredQtViewer::DrawView() method call,
1000   KernelVisitDecision () will be call and will set the fNeedKernelVisit
1001   to 1. See G4XXXStoredViewer::CompareForKernelVisit for explanations.
1002   It will cause a redraw of the view
1003   @param aAction : 1 wireframe, 2 line removal, 3 surface removal, 4 line & surface removal
1004   @see G4OpenGLStoredQtViewer::DrawView
1005   @see G4XXXStoredViewer::CompareForKernelVisit
1006 */
1007void G4OpenGLQtViewer::toggleDrawingAction(int aAction) {
1008
1009  G4ViewParameters::DrawingStyle d_style = G4ViewParameters::wireframe;
1010 
1011
1012  // initialize
1013  if ((aAction >0) && (aAction <5)) {
1014#if QT_VERSION < 0x040000
1015    fDrawingWireframe->setOn(false);
1016    fDrawingLineRemoval->setOn(false);
1017    fDrawingSurfaceRemoval->setOn(false);
1018    fDrawingLineSurfaceRemoval->setOn(false);
1019#else
1020    fDrawingWireframe->setChecked (false);
1021    fDrawingLineRemoval->setChecked (false);
1022    fDrawingSurfaceRemoval->setChecked (false);
1023    fDrawingLineSurfaceRemoval->setChecked (false);
1024#endif
1025  }
1026  if (aAction ==1) {
1027#if QT_VERSION < 0x040000
1028    fDrawingWireframe->setOn(true);
1029#else
1030    fDrawingWireframe->setChecked (true);
1031#endif
1032
1033    d_style = G4ViewParameters::wireframe;
1034
1035  } else  if (aAction ==2) {
1036#if QT_VERSION < 0x040000
1037    fDrawingLineRemoval->setOn(true);
1038#else
1039    fDrawingLineRemoval->setChecked (true);
1040#endif
1041
1042    d_style = G4ViewParameters::hlr;
1043
1044  } else  if (aAction ==3) {
1045#if QT_VERSION < 0x040000
1046    fDrawingSurfaceRemoval->setOn(true);
1047#else
1048    fDrawingSurfaceRemoval->setChecked (true);
1049#endif
1050
1051    d_style = G4ViewParameters::hsr;
1052
1053  } else  if (aAction ==4) {
1054#if QT_VERSION < 0x040000
1055    fDrawingLineSurfaceRemoval->setOn(true);
1056#else
1057    fDrawingLineSurfaceRemoval->setChecked (true);
1058#endif
1059    d_style = G4ViewParameters::hlhsr;
1060  }
1061  fVP.SetDrawingStyle(d_style);
1062
1063  updateQWidget();
1064}
1065
1066
1067/**
1068   SLOT Activate by a click on the representation menu
1069   Warning : When G4OpenGLStoredQtViewer::DrawView() method call,
1070   KernelVisitDecision () will be call and will set the fNeedKernelVisit
1071   to 1. See G4XXXStoredViewer::CompareForKernelVisit for explanations.
1072   It will cause a redraw of the view
1073   @param check : 1 polyhedron, 0 nurbs
1074   @see G4OpenGLStoredQtViewer::DrawView
1075   @see G4XXXStoredViewer::CompareForKernelVisit
1076*/
1077void G4OpenGLQtViewer::toggleRepresentation(bool check) {
1078
1079  G4ViewParameters::RepStyle style;
1080  if (check == 1) {
1081    style = G4ViewParameters::polyhedron;
1082  } else {
1083    style = G4ViewParameters::nurbs;
1084  }
1085  fVP.SetRepStyle (style);
1086
1087  updateQWidget();
1088}
1089
1090/**
1091   SLOT Activate by a click on the projection menu
1092   Warning : When G4OpenGLStoredQtViewer::DrawView() method call,
1093   KernelVisitDecision () will be call and will set the fNeedKernelVisit
1094   to 1. See G4XXXStoredViewer::CompareForKernelVisit for explanations.
1095   It will cause a redraw of the view
1096   @param check : 1 orthographic, 2 perspective
1097   @see G4OpenGLStoredQtViewer::DrawView
1098   @see G4XXXStoredViewer::CompareForKernelVisit
1099*/
1100void G4OpenGLQtViewer::toggleProjection(bool check) {
1101
1102  if (check == 1) {
1103    fVP.SetFieldHalfAngle (0);
1104  } else {
1105
1106    // look for the default parameter hidden in G4UIcommand parameters
1107    G4UImanager* UI = G4UImanager::GetUIpointer();
1108    if(UI==NULL)
1109      return;
1110    G4UIcommandTree * treeTop = UI->GetTree();
1111
1112    // find command
1113    G4UIcommand* command = treeTop->FindPath("/vis/viewer/set/projection");
1114    if (!command)
1115      return;
1116
1117    // find param
1118    G4UIparameter * angleParam = NULL;
1119    for(G4int i=0;  i<command->GetParameterEntries(); i++)
1120    {
1121      if( command->GetParameter(i)->GetParameterName() == "field-half-angle" ) {
1122        angleParam = command->GetParameter(i);
1123      }
1124    }
1125    if (!angleParam)
1126      return;
1127
1128    // find unit
1129    G4UIparameter * unitParam = NULL;
1130    for(G4int i=0;  i<command->GetParameterEntries(); i++)
1131    {
1132      if( command->GetParameter(i)->GetParameterName() == "unit" ) {
1133        unitParam = command->GetParameter(i);
1134      }
1135    }
1136    if (!unitParam)
1137      return;
1138
1139    G4double defaultValue = command->ConvertToDouble(angleParam->GetDefaultValue())
1140                            * G4UnitDefinition::GetValueOf(unitParam->GetDefaultValue());
1141    if (defaultValue > 89.5 || defaultValue <= 0.0) {
1142      G4cerr << "Field half angle should be 0 < angle <= 89.5 degrees. Check your default Field half angle parameter";
1143    } else {
1144      G4cout << "Perspective view has been set to default value. Field half angle="<<angleParam->GetDefaultValue() <<" " << G4endl;
1145      fVP.SetFieldHalfAngle (defaultValue);
1146      SetView ();
1147    }
1148  } 
1149  updateQWidget();
1150}
1151
1152
1153/**
1154   SLOT Activate by a click on the background menu
1155@param check : 1 white, 0 black
1156*/
1157void G4OpenGLQtViewer::toggleBackground(bool check) {
1158
1159  //   //I need to revisit the kernel if the background colour changes and
1160  //   //hidden line removal is enabled, because hlr drawing utilises the
1161  //   //background colour in its drawing...
1162  //   // (Note added by JA 13/9/2005) Background now handled in view
1163  //   // parameters.  A kernel visit is triggered on change of background.
1164  if (check == 1) {
1165    ((G4ViewParameters&)this->GetViewParameters()).
1166      SetBackgroundColour(G4Colour(1.,1.,1.));  // White
1167  } else {
1168    ((G4ViewParameters&)this->GetViewParameters()).
1169      SetBackgroundColour(G4Colour(0.,0.,0.));  // Black
1170  }
1171  updateQWidget();
1172}
1173
1174/**
1175   SLOT Activate by a click on the transparency menu
1176@param check : 1 , 0
1177*/
1178void G4OpenGLQtViewer::toggleTransparency(bool check) {
1179 
1180  if (check) {
1181    transparency_enabled = false;
1182  } else {
1183    transparency_enabled = true;
1184  }
1185  SetNeedKernelVisit (true);
1186  updateQWidget();
1187}
1188
1189/**
1190   SLOT Activate by a click on the antialiasing menu
1191@param check : 1 , 0
1192*/
1193void G4OpenGLQtViewer::toggleAntialiasing(bool check) {
1194
1195  if (!check) {
1196    antialiasing_enabled = false;
1197    glDisable (GL_LINE_SMOOTH);
1198    glDisable (GL_POLYGON_SMOOTH);
1199  } else {
1200    antialiasing_enabled = true;
1201    glEnable (GL_LINE_SMOOTH);
1202    glHint (GL_LINE_SMOOTH_HINT, GL_NICEST);
1203    glEnable (GL_POLYGON_SMOOTH);
1204    glHint (GL_POLYGON_SMOOTH_HINT, GL_NICEST);
1205  }
1206
1207  updateQWidget();
1208}
1209
1210/**
1211   SLOT Activate by a click on the haloing menu
1212@param check : 1 , 0
1213*/
1214//FIXME : I SEE NOTHING...
1215void G4OpenGLQtViewer::toggleHaloing(bool check) {
1216  if (check) {
1217    haloing_enabled = false;
1218  } else {
1219    haloing_enabled = true;
1220  }
1221
1222  updateQWidget();
1223
1224}
1225
1226/**
1227   SLOT Activate by a click on the auxiliaire edges menu
1228@param check : 1 , 0
1229*/
1230void G4OpenGLQtViewer::toggleAux(bool check) {
1231  if (check) {
1232    fVP.SetAuxEdgeVisible(false);
1233  } else {
1234    fVP.SetAuxEdgeVisible(true);
1235  }
1236  SetNeedKernelVisit (true);
1237  updateQWidget();
1238}
1239
1240/**
1241   SLOT Activate by a click on the full screen menu
1242*/
1243void G4OpenGLQtViewer::toggleFullScreen(bool check) {
1244  if (check != fGLWindow->isFullScreen()) { //toggle
1245#if QT_VERSION >= 0x030200
1246    fGLWindow->setWindowState(fGLWindow->windowState() ^ Qt::WindowFullScreen);
1247#else
1248    G4cerr << "This version of Qt could not do fullScreen. Resizing the widget is the only solution available." << G4endl;
1249#endif
1250  }
1251}
1252
1253
1254void G4OpenGLQtViewer::savePPMToTemp() {
1255  if (fMovieTempFolderPath == "") {
1256    return;
1257  }
1258  QString fileName ="Test"+QString::number(fRecordFrameNumber)+".ppm";
1259  QString filePath =fMovieTempFolderPath+fileName;
1260
1261  QImage image;
1262  image = fWindow->grabFrameBuffer();
1263  bool res = false;
1264 
1265#if QT_VERSION < 0x040000
1266  res = image.save(filePath,"PPM");
1267#else
1268  res = image.save(filePath,0);
1269#endif
1270  if (res == false) {
1271    resetRecording();
1272    setRecordingInfos("Can't save tmp file "+filePath);
1273    return;
1274  }
1275 
1276  setRecordingInfos("File "+fileName+" saved");
1277  fRecordFrameNumber++;
1278}
1279
1280
1281
1282void G4OpenGLQtViewer::actionSaveImage() {
1283  QString filters;
1284#if QT_VERSION < 0x040000
1285  QStrList listFormat=QImageIO::outputFormats();
1286  char *tmp=listFormat.first();
1287  while (tmp!=0) {
1288    filters += QString(tmp) + ";;";
1289    tmp=listFormat.next();
1290  }
1291#else
1292  QList<QByteArray> formats =  QImageWriter::supportedImageFormats ();
1293  for (int i = 0; i < formats.size(); ++i) {
1294    filters +=formats.at(i) + ";;";
1295  }
1296#endif
1297  filters += "eps;;";
1298  filters += "ps;;";
1299  filters += "pdf";
1300  QString* selectedFormat = new QString();
1301  std::string name;
1302#if QT_VERSION < 0x040000
1303  name =  QFileDialog::getSaveFileName ( ".",
1304                                                    filters,
1305                                                    fGLWindow,
1306                                                    "Save file dialog",
1307                                                    tr("Save as ..."),
1308                                                    selectedFormat ).ascii();
1309#else
1310  name =  QFileDialog::getSaveFileName ( fGLWindow,
1311                                                    tr("Save as ..."),
1312                                                    ".",
1313                                                    filters,
1314                                                    selectedFormat ).toStdString().c_str();
1315#endif
1316  // bmp jpg jpeg png ppm xbm xpm
1317  if (name.empty()) {
1318    return;
1319  }
1320#if QT_VERSION < 0x040000
1321  name += "." + std::string(selectedFormat->ascii());
1322  QString format = selectedFormat->lower();
1323#else
1324  name += "." + selectedFormat->toStdString();
1325  QString format = selectedFormat->toLower();
1326#endif
1327  setPrintFilename(name.c_str(),0);
1328  G4OpenGLQtExportDialog* exportDialog= new G4OpenGLQtExportDialog(fGLWindow,format,fWindow->height(),fWindow->width());
1329  if(  exportDialog->exec()) {
1330
1331    QImage image;
1332    bool res = false;
1333    if ((exportDialog->getWidth() !=fWindow->width()) ||
1334        (exportDialog->getHeight() !=fWindow->height())) {
1335      setPrintSize(exportDialog->getWidth(),exportDialog->getHeight());
1336      if ((format != QString("eps")) && (format != QString("ps"))) {
1337      G4cerr << "Export->Change Size : This function is not implemented, to export in another size, please resize your frame to what you need" << G4endl;
1338     
1339      //    rescaleImage(exportDialog->getWidth(),exportDialog->getHeight());// re-scale image
1340      //      QGLWidget* glResized = fWindow;
1341
1342      // FIXME :
1343      // L.Garnier : I've try to implement change size function, but the problem is
1344      // the renderPixmap function call the QGLWidget to resize and it doesn't draw
1345      // the content of this widget... It only draw the background.
1346
1347      //      fWindow->renderPixmap (exportDialog->getWidth()*2,exportDialog->getHeight()*2,true );
1348
1349      //      QPixmap pixmap = fWindow->renderPixmap ();
1350     
1351      //      image = pixmap->toImage();
1352      //      glResized->resize(exportDialog->getWidth()*2,exportDialog->getHeight()*2);
1353      //      image = glResized->grabFrameBuffer();
1354      }     
1355    } else {
1356      image = fWindow->grabFrameBuffer();
1357    }   
1358    if (format == QString("eps")) {
1359      fVectoredPs = exportDialog->getVectorEPS();
1360      printEPS();
1361    } else if (format == "ps") {
1362      fVectoredPs = true;
1363      printEPS();
1364    } else if (format == "pdf") {
1365
1366      res = printPDF(name,exportDialog->getNbColor(),image);
1367
1368    } else if ((format == "tif") ||
1369               (format == "tiff") ||
1370               (format == "jpg") ||
1371               (format == "jpeg") ||
1372               (format == "png") ||
1373               (format == "pbm") ||
1374               (format == "pgm") ||
1375               (format == "ppm") ||
1376               (format == "bmp") ||
1377               (format == "xbm") ||
1378               (format == "xpm")) {
1379#if QT_VERSION < 0x040000
1380      res = image.save(QString(name.c_str()),selectedFormat->ascii(),exportDialog->getSliderValue());
1381#else
1382      res = image.save(QString(name.c_str()),0,exportDialog->getSliderValue());
1383#endif
1384    } else {
1385      G4cerr << "This version of G4UI Could not generate the selected format" << G4endl;
1386    }
1387    if ((format == QString("eps")) && (format == QString("ps"))) {
1388      if (res == false) {
1389        G4cerr << "Error while saving file... "<<name.c_str()<< G4endl;
1390      } else {
1391        G4cout << "File "<<name.c_str()<<" has been saved " << G4endl;
1392      }
1393    }
1394   
1395  } else { // cancel selected
1396    return;
1397  }
1398 
1399}
1400
1401
1402void G4OpenGLQtViewer::actionMovieParameters() {
1403  showMovieParametersDialog();
1404}
1405
1406
1407void G4OpenGLQtViewer::showMovieParametersDialog() {
1408  if (!fMovieParametersDialog) {
1409    fMovieParametersDialog= new G4OpenGLQtMovieDialog(this,fGLWindow);
1410    displayRecordingStatus();
1411    fMovieParametersDialog->checkEncoderSwParameters();
1412    fMovieParametersDialog->checkSaveFileNameParameters();
1413    fMovieParametersDialog->checkTempFolderParameters();
1414    if (getEncoderPath() == "") {
1415      setRecordingInfos("mpeg_encode is needed to encode in video format. It is available here: http://bmrc.berkeley.edu/frame/research/mpeg/");
1416    }
1417  }
1418  fMovieParametersDialog->show();
1419}
1420
1421
1422/*
1423// 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
1424
1425void Graph::exportToSVG(const QString& fname)
1426{
1427  // enable workaround for Qt3 misalignments
1428  QwtPainter::setSVGMode(true);
1429  QPicture picture;
1430  QPainter p(&picture);
1431  d_plot->print(&p, d_plot->rect());
1432  p.end();
1433
1434  picture.save(fname, "svg");
1435}
1436*/
1437
1438
1439
1440void G4OpenGLQtViewer::FinishView()
1441{
1442  glFlush ();
1443
1444  // L. Garnier 10/2009 : Not necessary and cause problems on mac OS X 10.6
1445  //  fWindow->swapBuffers ();
1446}
1447
1448/**
1449   Save the current mouse press point
1450   @param p mouse click point
1451*/
1452void G4OpenGLQtViewer::G4MousePressEvent(QMouseEvent *event)
1453{
1454#if QT_VERSION < 0x040000
1455  if (event->button() & Qt::LeftButton) {
1456#else
1457  if (event->buttons() & Qt::LeftButton) {
1458#endif
1459    fWindow->setMouseTracking(true);
1460    fAutoMove = false; // stop automove
1461    fLastPos1 = event->pos();
1462    fLastPos2 = fLastPos1;
1463    fLastPos3 = fLastPos2;
1464    fLastEventTime->start();
1465    if (fMouseAction == STYLE3){  // pick
1466      Pick(event->pos().x(),event->pos().y());
1467    }
1468  }
1469}
1470
1471/**
1472*/
1473void G4OpenGLQtViewer::G4MouseReleaseEvent()
1474{
1475  fSpinningDelay = fLastEventTime->elapsed();
1476  QPoint delta = (fLastPos3-fLastPos1);
1477  if ((delta.x() == 0) && (delta.y() == 0)) {
1478    return;
1479  }
1480  if (fSpinningDelay < fLaunchSpinDelay ) {
1481    fAutoMove = true;
1482    QTime lastMoveTime;
1483    lastMoveTime.start();
1484    // try to addapt speed move/rotate looking to drawing speed
1485    float correctionFactor = 5;
1486    while (fAutoMove) {
1487      if ( lastMoveTime.elapsed () >= (int)(1000/fNbMaxFramesPerSec)) {
1488        float lTime = 1000/((float)lastMoveTime.elapsed ());
1489        if (((((float)delta.x())/correctionFactor)*lTime > fNbMaxAnglePerSec) ||
1490            ((((float)delta.x())/correctionFactor)*lTime < -fNbMaxAnglePerSec) ) {
1491          correctionFactor = (float)delta.x()*(lTime/fNbMaxAnglePerSec);
1492          if (delta.x() <0 ) {
1493            correctionFactor = -correctionFactor;
1494          }
1495        }
1496        if (((((float)delta.y())/correctionFactor)*lTime > fNbMaxAnglePerSec) ||
1497            ((((float)delta.y())/correctionFactor)*lTime < -fNbMaxAnglePerSec) ) {
1498          correctionFactor = (float)delta.y()*(lTime/fNbMaxAnglePerSec);
1499          if (delta.y() <0 ) {
1500            correctionFactor = -correctionFactor;
1501          }
1502        }
1503               
1504        // Check Qt Versions for META Keys
1505               
1506        // Click and move mouse to rotate volume
1507        // ALT + Click and move mouse to rotate volume (View Direction)
1508        // SHIFT + Click and move camera point of view
1509        // CTRL + Click and zoom mouse to zoom in/out
1510
1511        if (fMouseAction == STYLE1) {  // rotate
1512#ifdef G4DEBUG_VIS_OGL
1513          printf("G4OpenGLQtViewer:: ___________________________________\n");
1514          printf("G4OpenGLQtViewer:: mouse move\n");
1515#endif
1516          if (fNoKeyPress) {
1517#ifdef G4DEBUG_VIS_OGL
1518            printf("G4OpenGLQtViewer:: rotate normal\n");
1519#endif
1520            rotateQtScene(((float)delta.x())/correctionFactor,((float)delta.y())/correctionFactor);
1521          } else if (fAltKeyPress) {
1522#ifdef G4DEBUG_VIS_OGL
1523            printf("G4OpenGLQtViewer:: rotate view\n");
1524#endif
1525            rotateQtSceneInViewDirection(((float)delta.x())/correctionFactor,((float)delta.y())/correctionFactor);
1526          }
1527         
1528        } else if (fMouseAction == STYLE2) {  // move
1529          moveScene(-((float)delta.x())/correctionFactor,-((float)delta.y())/correctionFactor,0,true);
1530        }
1531#ifdef G4DEBUG_VIS_OGL
1532        printf("G4OpenGLQtViewer::G4MouseReleaseEvent Fps:%f x:%d y:%d cycle:%f\n",(float)1000/lastMoveTime.elapsed(),delta.x(),delta.y(),correctionFactor);
1533#endif
1534        lastMoveTime.start();
1535      }
1536      ((QApplication*)G4Qt::getInstance ())->processEvents();
1537    }
1538  }
1539  fWindow->setMouseTracking(false);
1540
1541}
1542
1543
1544void G4OpenGLQtViewer::G4MouseDoubleClickEvent()
1545{
1546  fWindow->setMouseTracking(true);
1547}
1548
1549
1550/**
1551   @param pos_x mouse x position
1552   @param pos_y mouse y position
1553   @param mButtons mouse button active
1554   @param mAutoMove true: apply this move till another evnt came, false :one time move
1555*/
1556
1557void G4OpenGLQtViewer::G4MouseMoveEvent(QMouseEvent *event)
1558{
1559 
1560#if QT_VERSION < 0x040000
1561  Qt::ButtonState mButtons = event->state();
1562#else
1563  Qt::MouseButtons mButtons = event->buttons();
1564#endif
1565
1566#if QT_VERSION < 0x040000
1567  updateKeyModifierState(event->state());
1568#else
1569  updateKeyModifierState(event->modifiers());
1570#endif
1571
1572  if (fAutoMove) {
1573    return;
1574  }
1575
1576  fLastPos3 = fLastPos2;
1577  fLastPos2 = fLastPos1;
1578  fLastPos1 = QPoint(event->x(), event->y());
1579
1580  int deltaX = fLastPos2.x()-fLastPos1.x();
1581  int deltaY = fLastPos2.y()-fLastPos1.y();
1582
1583  if (fMouseAction == STYLE1) {  // rotate
1584    if (mButtons & Qt::LeftButton) {
1585#ifdef G4DEBUG_VIS_OGL
1586      printf("G4OpenGLQtViewer:: ___________________________________\n");
1587      printf("G4OpenGLQtViewer:: mouse move %f %f\n",((float)deltaX),((float)deltaY));
1588#endif
1589      if (fNoKeyPress) {
1590#ifdef G4DEBUG_VIS_OGL
1591        printf("G4OpenGLQtViewer:: rotate normal\n");
1592#endif
1593        rotateQtScene(((float)deltaX),((float)deltaY));
1594      } else if (fAltKeyPress) {
1595#ifdef G4DEBUG_VIS_OGL
1596        printf("G4OpenGLQtViewer:: rotate view\n");
1597#endif
1598        rotateQtSceneInViewDirection(((float)deltaX),((float)deltaY));
1599      } else if (fShiftKeyPress) {
1600        unsigned int sizeWin;
1601        sizeWin = getWinWidth();
1602        if (getWinHeight() < getWinWidth()) {
1603          sizeWin = getWinHeight();
1604        }
1605
1606        // L.Garnier : 08/2010 100 is the good value, but don't ask me why !
1607        float factor = ((float)100/(float)sizeWin) ;
1608        moveScene(-(float)deltaX*factor,-(float)deltaY*factor,0,false);
1609      } else if (fControlKeyPress) {
1610#ifdef G4DEBUG_VIS_OGL
1611        printf("G4OpenGLQtViewer:: zoom\n");
1612#endif
1613        fVP.SetZoomFactor(fVP.GetZoomFactor()*(1+((float)deltaY)));
1614      }
1615    }
1616  } else if (fMouseAction == STYLE2) {  // move
1617    if (mButtons & Qt::LeftButton) {
1618      moveScene(-deltaX,-deltaY,0,true);
1619    }
1620  }
1621
1622  fLastEventTime->start();
1623}
1624
1625
1626/**
1627   Move the scene of dx, dy, dz values.
1628   @param dx delta mouse x position
1629   @param dy delta mouse y position
1630   @param mouseMove : true if even comes from a mouse move, false if even comes from key action
1631*/
1632
1633void G4OpenGLQtViewer::moveScene(float dx,float dy, float dz,bool mouseMove)
1634{
1635  if (fHoldMoveEvent)
1636    return;
1637  fHoldMoveEvent = true;
1638
1639  G4double coefTrans = 0;
1640  GLdouble coefDepth = 0;
1641  if(mouseMove) {
1642    coefTrans = ((G4double)getSceneNearWidth())/((G4double)getWinWidth());
1643    if (getWinHeight() <getWinWidth()) {
1644      coefTrans = ((G4double)getSceneNearWidth())/((G4double)getWinHeight());
1645    }
1646  } else {
1647    coefTrans = getSceneNearWidth()*fDeltaSceneTranslation;
1648    coefDepth = getSceneDepth()*fDeltaDepth;
1649  }
1650  fVP.IncrementPan(-dx*coefTrans,dy*coefTrans,dz*coefDepth);
1651  emit moveX(-static_cast<int>(dx*coefTrans));
1652  emit moveY(static_cast<int>(dy*coefTrans));
1653  emit moveZ(static_cast<int>(dz*coefTrans));
1654 
1655  updateQWidget();
1656  if (fAutoMove)
1657    ((QApplication*)G4Qt::getInstance ())->processEvents();
1658 
1659  fHoldMoveEvent = false;
1660}
1661
1662
1663/**
1664   @param dx delta mouse x position
1665   @param dy delta mouse y position
1666*/
1667
1668void G4OpenGLQtViewer::rotateQtScene(float dx, float dy)
1669{
1670  if (fHoldRotateEvent)
1671    return;
1672  fHoldRotateEvent = true;
1673 
1674  if( dx != 0) {
1675    rotateScene(dx,0,fDeltaRotation);
1676    emit rotateTheta(static_cast<int>(dx));
1677  }
1678  if( dy != 0) {
1679    rotateScene(0,dy,fDeltaRotation);
1680    emit rotatePhi(static_cast<int>(dy));
1681  }
1682  updateQWidget();
1683 
1684  fHoldRotateEvent = false;
1685}
1686
1687/**
1688   @param dx delta mouse x position
1689   @param dy delta mouse y position
1690*/
1691
1692void G4OpenGLQtViewer::rotateQtSceneInViewDirection(float dx, float dy)
1693{
1694  if (fHoldRotateEvent)
1695    return;
1696  fHoldRotateEvent = true;
1697 
1698  fXRot +=dx;
1699  fYRot +=dy;
1700 
1701  rotateSceneInViewDirection(dx,dy,fDeltaRotation/100);
1702 
1703  emit rotateTheta(static_cast<int>(dx));
1704  emit rotatePhi(static_cast<int>(dy));
1705  updateQWidget();
1706 
1707  fHoldRotateEvent = false;
1708}
1709
1710/**
1711   @param dx delta mouse x position
1712   @param dy delta mouse y position
1713*/
1714
1715void G4OpenGLQtViewer::rotateQtCamera(float dx, float dy)
1716{
1717  if (fHoldRotateEvent)
1718    return;
1719  fHoldRotateEvent = true;
1720
1721  rotateScene(dx,dy,fDeltaRotation);
1722  emit rotateTheta(static_cast<int>(dx));
1723  emit rotatePhi(static_cast<int>(dy));
1724  updateQWidget();
1725 
1726  fHoldRotateEvent = false;
1727}
1728
1729/**
1730   @param dx delta mouse x position
1731   @param dy delta mouse y position
1732*/
1733
1734void G4OpenGLQtViewer::rotateQtCameraInViewDirection(float dx, float dy)
1735{
1736  if (fHoldRotateEvent)
1737    return;
1738  fHoldRotateEvent = true;
1739
1740  fVP.SetUpVector(G4Vector3D(0.0, 1.0, 0.0));
1741  fVP.SetViewAndLights (G4Vector3D(0.0, 0.0, 1.0));
1742
1743
1744  fXRot +=dx;
1745  fYRot +=dy;
1746
1747  rotateSceneInViewDirection(fXRot,fYRot,fDeltaRotation/100);
1748
1749  emit rotateTheta(static_cast<int>(dx));
1750  emit rotatePhi(static_cast<int>(dy));
1751  updateQWidget();
1752 
1753  fHoldRotateEvent = false;
1754}
1755
1756
1757
1758
1759
1760/** This is the benning of a rescale function. It does nothing for the moment
1761    @param aWidth : new width
1762    @param aHeight : new height
1763*/
1764void G4OpenGLQtViewer::rescaleImage(
1765 int /* aWidth */
1766,int /* aHeight */
1767){
1768  //  GLfloat* feedback_buffer;
1769  //  GLint returned;
1770  //  FILE* file;
1771 
1772//   feedback_buffer = new GLfloat[size];
1773//   glFeedbackBuffer (size, GL_3D_COLOR, feedback_buffer);
1774//   glRenderMode (GL_FEEDBACK);
1775 
1776//   DrawView();
1777//   returned = glRenderMode (GL_RENDER);
1778
1779}
1780
1781
1782
1783/**
1784   Generate Postscript or PDF form image
1785   @param aFilename : name of file
1786   @param aInColor : numbers of colors : 1->BW 2->RGB
1787   @param aImage : Image to print
1788*/
1789bool G4OpenGLQtViewer::printPDF (
1790 const std::string aFilename
1791,int aInColor
1792,QImage aImage
1793)
1794{
1795
1796#if QT_VERSION < 0x040000
1797#if defined(Q_WS_MAC) || defined(Q_WS_X11)
1798  QPrinter printer;
1799  //  printer.setPageSize(pageSize);
1800  if (aInColor == 1) {
1801    printer.setColorMode(QPrinter::GrayScale);
1802  } else {
1803    printer.setColorMode(QPrinter::Color);
1804  }
1805
1806  /* FIXME : I don't know which format it will save...
1807     if (aFilename.endsWith(".ps")) {
1808     printer.setOutputFormat(QPrinter::PostScriptFormat);
1809     } else {
1810     printer.setOutputFormat(QPrinter::PdfFormat);
1811     }
1812  */
1813  printer.setOutputFileName(QString(aFilename.c_str()));
1814  //  printer.setFullPage ( true);
1815  QPainter paint(&printer);
1816  paint.drawImage (0,0,aImage );
1817  paint.end();
1818#else
1819  G4cerr << "This fonction is only supported on Mac OsX or X11 with Qt3. Full platform supported with Qt4" << G4endl;
1820  // FIXME
1821  // L.Garnier 6 May 2009 : Only to fix compilation warnings
1822  if (aFilename.empty()) {
1823    aInColor = 0;
1824    aImage = 0;
1825  }
1826  // END_OF FIXME
1827#endif
1828#else
1829  QPrinter printer;
1830  //  printer.setPageSize(pageSize);
1831
1832  // FIXME : L. Garnier 4/12/07
1833  // This is not working, it does nothing. Image is staying in color mode
1834  // So I have desactivate the B/W button in GUI
1835  if ((!aImage.isGrayscale ()) &&(aInColor ==1 )) {
1836#if QT_VERSION < 0x040000
1837    aImage = aImage.convertDepth(1,Qt::MonoOnly);
1838#else
1839    aImage = aImage.convertToFormat ( aImage.format(), Qt::MonoOnly);
1840#endif
1841  }
1842
1843
1844  if (aFilename.substr(aFilename.size()-3) == ".ps") {
1845#if QT_VERSION > 0x040200
1846    printer.setOutputFormat(QPrinter::PostScriptFormat);
1847#endif
1848  } else {
1849#if QT_VERSION > 0x040100
1850    printer.setOutputFormat(QPrinter::PdfFormat);
1851#endif
1852  }
1853#if QT_VERSION > 0x040100
1854  printer.setOutputFileName(QString(aFilename.c_str()));
1855#endif
1856  //  printer.setFullPage ( true);
1857  QPainter paint(&printer);
1858  paint.drawImage (0,0,aImage);
1859  paint.end();
1860#endif
1861  return true;
1862}
1863
1864
1865void G4OpenGLQtViewer::G4wheelEvent (QWheelEvent * event)
1866{
1867  fVP.SetZoomFactor(fVP.GetZoomFactor()+(fVP.GetZoomFactor()*(event->delta())/1200));
1868  updateQWidget();
1869}
1870
1871
1872 void G4OpenGLQtViewer::G4keyPressEvent (QKeyEvent * event)
1873{
1874  if (fHoldKeyEvent)
1875    return;
1876
1877  fHoldKeyEvent = true;
1878
1879 
1880  // with no modifiers
1881#if QT_VERSION < 0x040000
1882  updateKeyModifierState(event->state());
1883  if (fNoKeyPress) {
1884#else
1885  updateKeyModifierState(event->modifiers());
1886  if ((fNoKeyPress) || (event->modifiers() == Qt::KeypadModifier )) {
1887#endif
1888    if (event->key() == Qt::Key_Down) { // go down
1889      moveScene(0,1,0,false);
1890    }
1891    else if (event->key() == Qt::Key_Up) {  // go up
1892      moveScene(0,-1,0,false);
1893    }
1894    if (event->key() == Qt::Key_Left) { // go left
1895      moveScene(-1,0,0,false);
1896    }
1897    else if (event->key() == Qt::Key_Right) { // go right
1898      moveScene(1,0,0,false);
1899    }
1900    if (event->key() == Qt::Key_Minus) { // go backward
1901      moveScene(0,0,1,false);
1902    }
1903    else if (event->key() == Qt::Key_Plus) { // go forward
1904      moveScene(0,0,-1,false);
1905    }
1906
1907    // escaped from full screen
1908    if (event->key() == Qt::Key_Escape) {
1909#if QT_VERSION >= 0x030200
1910      toggleFullScreen(false);
1911#endif
1912    }
1913  }   
1914  // several case here : If return is pressed, in every case -> display the movie parameters dialog
1915  // If one parameter is wrong -> put it in red (only save filenam could be wrong..)
1916  // If encoder not found-> does nothing.Only display a message in status box
1917  // If all ok-> generate parameter file
1918  // If ok -> put encoder button enabled
1919 
1920  if ((event->key() == Qt::Key_Return) || (event->key() == Qt::Key_Enter)){ // end of video
1921    stopVideo();
1922  }
1923  if (event->key() == Qt::Key_Space){ // start/pause of video
1924    startPauseVideo();
1925  }
1926 
1927  // H : Return Home view
1928  if (event->key() == Qt::Key_H){ // go Home
1929    fDeltaRotation = 1;
1930    fDeltaSceneTranslation = 0.01;
1931    fDeltaDepth = 0.01;
1932    fDeltaZoom = 0.05;
1933    fDeltaMove = 0.05;
1934   
1935    fVP.SetZoomFactor(1.);
1936    fVP.SetUpVector(G4Vector3D (0., 1., 0.));
1937    fVP.SetViewAndLights (G4Vector3D (0., 0., 1.));
1938
1939    updateQWidget();
1940  }
1941
1942  // Shift Modifier
1943  if (fShiftKeyPress) {
1944    if (event->key() == Qt::Key_Down) { // rotate phi
1945      rotateQtScene(0,-fDeltaRotation);
1946    }
1947    else if (event->key() == Qt::Key_Up) { // rotate phi
1948      rotateQtScene(0,fDeltaRotation);
1949    }
1950    if (event->key() == Qt::Key_Left) { // rotate theta
1951      rotateQtScene(fDeltaRotation,0);
1952    }
1953    else if (event->key() == Qt::Key_Right) { // rotate theta
1954      rotateQtScene(-fDeltaRotation,0);
1955    }
1956
1957  // Alt Modifier
1958  }
1959  if ((fAltKeyPress)) {
1960    if (event->key() == Qt::Key_Down) { // rotate phi
1961      rotateQtSceneInViewDirection(0,-fDeltaRotation);
1962    }
1963    else if (event->key() == Qt::Key_Up) { // rotate phi
1964      rotateQtSceneInViewDirection(0,fDeltaRotation);
1965    }
1966    if (event->key() == Qt::Key_Left) { // rotate theta
1967      rotateQtSceneInViewDirection(fDeltaRotation,0);
1968    }
1969    else if (event->key() == Qt::Key_Right) { // rotate theta
1970      rotateQtSceneInViewDirection(-fDeltaRotation,0);
1971    }
1972
1973    // Rotatio +/-
1974    if (event->key() == Qt::Key_Plus) {
1975      fDeltaRotation = fDeltaRotation/0.7;
1976      G4cout << "Auto-rotation set to : " << fDeltaRotation << G4endl;
1977    }
1978    else if (event->key() == Qt::Key_Minus) {
1979      fDeltaRotation = fDeltaRotation*0.7;
1980      G4cout << "Auto-rotation set to : " << fDeltaRotation << G4endl;
1981    }
1982
1983  // Control Modifier OR Command on MAC
1984  }
1985  if ((fControlKeyPress)) {
1986    if (event->key() == Qt::Key_Plus) {
1987      fVP.SetZoomFactor(fVP.GetZoomFactor()*(1+fDeltaZoom));
1988      updateQWidget();
1989    }
1990    else if (event->key() == Qt::Key_Minus) {
1991      fVP.SetZoomFactor(fVP.GetZoomFactor()*(1-fDeltaZoom));
1992      updateQWidget();
1993    }
1994  } 
1995 
1996  fHoldKeyEvent = false;
1997}
1998 
1999
2000#if QT_VERSION < 0x040000
2001void  G4OpenGLQtViewer::updateKeyModifierState(Qt::ButtonState modifier) {
2002#else
2003void  G4OpenGLQtViewer::updateKeyModifierState(Qt::KeyboardModifiers modifier) {
2004#endif
2005  // Check Qt Versions for META Keys
2006   
2007  fNoKeyPress = true;
2008  fAltKeyPress = false;
2009  fShiftKeyPress = false;
2010  fControlKeyPress = false;
2011 
2012#if QT_VERSION < 0x040000
2013  if (modifier & Qt::AltButton ) {
2014    fAltKeyPress = true;
2015    fNoKeyPress = false;
2016  }
2017  if (modifier & Qt::ShiftButton ) {
2018    fShiftKeyPress = true;
2019    fNoKeyPress = false;
2020  }
2021  if (modifier & Qt::ControlButton ) {
2022    fControlKeyPress = true;
2023    fNoKeyPress = false;
2024  }
2025#else
2026#ifdef G4DEBUG_VIS_OGL
2027  printf("G4OpenGLQtViewer:: ________________Key Press\n");
2028#endif
2029  if (modifier & Qt::AltModifier ) {
2030    fAltKeyPress = true;
2031    fNoKeyPress = false;
2032#ifdef G4DEBUG_VIS_OGL
2033    printf("G4OpenGLQtViewer:: ________________ALT\n");
2034#endif
2035  }
2036  if (modifier & Qt::ShiftModifier ) {
2037    fShiftKeyPress = true;
2038    fNoKeyPress = false;
2039#ifdef G4DEBUG_VIS_OGL
2040    printf("G4OpenGLQtViewer:: ________________Shift\n");
2041#endif
2042  }
2043  if (modifier & Qt::ControlModifier ) {
2044    fControlKeyPress = true;
2045    fNoKeyPress = false;
2046#ifdef G4DEBUG_VIS_OGL
2047    printf("G4OpenGLQtViewer:: ________________Control\n");
2048#endif
2049  }
2050#endif
2051}
2052
2053
2054/** Stop the video. Check all parameters and enable encoder button if all is ok.
2055*/
2056void G4OpenGLQtViewer::stopVideo() {
2057
2058 // if encoder parameter is wrong, display parameters dialog and return
2059  if (!fMovieParametersDialog) {
2060    showMovieParametersDialog();
2061  }
2062  setRecordingStatus(STOP);
2063
2064  if (fRecordFrameNumber >0) {
2065    // check parameters if they were modified (Re APPLY them...)
2066    if (!(fMovieParametersDialog->checkEncoderSwParameters())) {
2067      setRecordingStatus(BAD_ENCODER);
2068    }  else if (!(fMovieParametersDialog->checkSaveFileNameParameters())) {
2069      setRecordingStatus(BAD_OUTPUT);
2070    }
2071  } else {
2072    resetRecording();
2073    setRecordingInfos("No frame to encode.");
2074  }
2075}
2076
2077/** Stop the video. Check all parameters and enable encoder button if all is ok.
2078*/
2079void G4OpenGLQtViewer::saveVideo() {
2080
2081  // if encoder parameter is wrong, display parameters dialog and return
2082  if (!fMovieParametersDialog) {
2083    showMovieParametersDialog();
2084  }
2085
2086  fMovieParametersDialog->checkEncoderSwParameters();
2087  fMovieParametersDialog->checkSaveFileNameParameters();
2088 
2089  if (fRecordingStep == STOP) {
2090    setRecordingStatus(SAVE);
2091    generateMpegEncoderParameters();
2092    encodeVideo();
2093  }
2094}
2095
2096
2097/** Start/Pause the video..
2098*/
2099void G4OpenGLQtViewer::startPauseVideo() {
2100   
2101  // first time, if temp parameter is wrong, display parameters dialog and return
2102
2103  if (( fRecordingStep == WAIT)) {
2104    if ( fRecordFrameNumber == 0) {
2105      if (getTempFolderPath() == "") { // BAD_OUTPUT
2106        showMovieParametersDialog();
2107        setRecordingInfos("You should specified the temp folder in order to make movie");
2108        return;
2109      } else  {
2110        // remove temp folder if it was create
2111        QString tmp = removeTempFolder();
2112        if (tmp !="") {
2113          setRecordingInfos(tmp);
2114          return;
2115        }
2116        tmp = createTempFolder();
2117        if (tmp != "") {
2118          setRecordingInfos("Can't create temp folder."+tmp);
2119          return;
2120        }
2121      }
2122    }
2123  }
2124  if ((fRecordingStep == WAIT)) {
2125    setRecordingStatus(START);
2126  } else if (fRecordingStep == START) {
2127    setRecordingStatus(PAUSE);
2128  } else if (fRecordingStep == PAUSE) {
2129    setRecordingStatus(CONTINUE);
2130  } else if (fRecordingStep == CONTINUE) {
2131    setRecordingStatus(PAUSE);
2132  }
2133}
2134
2135void G4OpenGLQtViewer::setRecordingStatus(RECORDING_STEP step) {
2136
2137  fRecordingStep = step;
2138  displayRecordingStatus();
2139}
2140
2141
2142void G4OpenGLQtViewer::displayRecordingStatus() {
2143 
2144  QString txtStatus = "";
2145  if (fRecordingStep == WAIT) {
2146    txtStatus  = "Waiting to start...";
2147    fRecordFrameNumber = 0; // reset the frame number
2148  } else if (fRecordingStep == START) {
2149    txtStatus  = "Start Recording...";
2150  } else if (fRecordingStep == PAUSE) {
2151    txtStatus  = "Pause Recording...";
2152  } else if (fRecordingStep == CONTINUE) {
2153    txtStatus  = "Continue Recording...";
2154  } else if (fRecordingStep == STOP) {
2155    txtStatus  = "Stop Recording...";
2156  } else if (fRecordingStep == READY_TO_ENCODE) {
2157    txtStatus  = "Ready to Encode...";
2158  } else if (fRecordingStep == ENCODING) {
2159    txtStatus  = "Encoding...";
2160  } else if (fRecordingStep == FAILED) {
2161    txtStatus  = "Failed to encode...";
2162  } else if ((fRecordingStep == BAD_ENCODER)
2163         || (fRecordingStep == BAD_OUTPUT)
2164             || (fRecordingStep == BAD_TMP)) {
2165    txtStatus  = "Correct above errors first";
2166  } else if (fRecordingStep == SUCCESS) {
2167    txtStatus  = "File encoded successfully";
2168  } else {
2169  }
2170
2171  if (fMovieParametersDialog) {
2172    fMovieParametersDialog->setRecordingStatus(txtStatus);
2173  } else {
2174#if QT_VERSION < 0x040000
2175    G4cout << txtStatus.ascii() << G4endl;
2176#else
2177    G4cout << txtStatus.toStdString().c_str() << G4endl;
2178#endif
2179  }
2180  setRecordingInfos("");
2181}
2182
2183
2184void G4OpenGLQtViewer::setRecordingInfos(QString txt) {
2185  if (fMovieParametersDialog) {
2186    fMovieParametersDialog->setRecordingInfos(txt);
2187  } else {
2188#if QT_VERSION < 0x040000
2189    G4cout << txt.ascii() << G4endl;
2190#else
2191    G4cout << txt.toStdString().c_str() << G4endl;
2192#endif
2193  }
2194}
2195
2196/** Init the movie parameters. Temp dir and encoder path
2197*/
2198void G4OpenGLQtViewer::initMovieParameters() {
2199  //init encoder
2200 
2201   //look for encoderPath
2202     fProcess = new QProcess();
2203     
2204#if QT_VERSION < 0x040000
2205     QObject ::connect(fProcess,SIGNAL(processExited ()),
2206                       this,SLOT(processLookForFinished()));
2207     fProcess->setCommunication(QProcess::DupStderr);
2208     fProcess->setArguments(QStringList("which mpeg_encode"));
2209     fProcess->start();
2210#else
2211     QObject ::connect(fProcess,SIGNAL(finished ( int)),
2212                       this,SLOT(processLookForFinished()));
2213     fProcess->setReadChannelMode(QProcess::MergedChannels);
2214     fProcess->start ("which mpeg_encode");
2215#endif
2216 
2217}
2218
2219/** @return encoder path or "" if it does not exist
2220 */
2221QString G4OpenGLQtViewer::getEncoderPath() {
2222  return fEncoderPath;
2223}
2224 
2225
2226/**
2227 * set the new encoder path
2228 * @return "" if correct. The error otherwise
2229*/
2230QString G4OpenGLQtViewer::setEncoderPath(QString path) {
2231  if (path == "") {
2232    return "File does not exist";
2233  }
2234
2235#if QT_VERSION < 0x040000
2236  path =  QDir::cleanDirPath(path);
2237#else
2238  path =  QDir::cleanPath(path);
2239#endif
2240  QFileInfo *f = new QFileInfo(path);
2241  if (!f->exists()) {
2242    return "File does not exist";
2243  } else if (f->isDir()) {
2244    return "This is a directory";
2245  } else if (!f->isExecutable()) {
2246    return "File exist but is not executable";
2247  } else if (!f->isFile()) {
2248    return "This is not a file";
2249  }
2250  fEncoderPath = path;
2251
2252  if ((fRecordingStep == BAD_ENCODER)) {
2253    setRecordingStatus(STOP);
2254  }
2255  return "";
2256}
2257
2258
2259bool G4OpenGLQtViewer::isRecording(){
2260  if ((fRecordingStep == START) || (fRecordingStep == CONTINUE)) {
2261    return true;
2262  }
2263  return false;
2264}
2265
2266bool G4OpenGLQtViewer::isPaused(){
2267  if (fRecordingStep == PAUSE) {
2268    return true;
2269  }
2270  return false;
2271}
2272
2273bool G4OpenGLQtViewer::isEncoding(){
2274  if (fRecordingStep == ENCODING) {
2275    return true;
2276  }
2277  return false;
2278}
2279
2280bool G4OpenGLQtViewer::isWaiting(){
2281  if (fRecordingStep == WAIT) {
2282    return true;
2283  }
2284  return false;
2285}
2286
2287bool G4OpenGLQtViewer::isStopped(){
2288  if (fRecordingStep == STOP) {
2289    return true;
2290  }
2291  return false;
2292}
2293
2294bool G4OpenGLQtViewer::isFailed(){
2295  if (fRecordingStep == FAILED) {
2296    return true;
2297  }
2298  return false;
2299}
2300
2301bool G4OpenGLQtViewer::isSuccess(){
2302  if (fRecordingStep == SUCCESS) {
2303    return true;
2304  }
2305  return false;
2306}
2307
2308bool G4OpenGLQtViewer::isBadEncoder(){
2309  if (fRecordingStep == BAD_ENCODER) {
2310    return true;
2311  }
2312  return false;
2313}
2314bool G4OpenGLQtViewer::isBadTmp(){
2315  if (fRecordingStep == BAD_TMP) {
2316    return true;
2317  }
2318  return false;
2319}
2320bool G4OpenGLQtViewer::isBadOutput(){
2321  if (fRecordingStep == BAD_OUTPUT) {
2322    return true;
2323  }
2324  return false;
2325}
2326
2327void G4OpenGLQtViewer::setBadEncoder(){
2328  fRecordingStep = BAD_ENCODER;
2329  displayRecordingStatus();
2330}
2331void G4OpenGLQtViewer::setBadTmp(){
2332  fRecordingStep = BAD_TMP;
2333  displayRecordingStatus();
2334}
2335void G4OpenGLQtViewer::setBadOutput(){
2336  fRecordingStep = BAD_OUTPUT;
2337  displayRecordingStatus();
2338}
2339
2340void G4OpenGLQtViewer::setWaiting(){
2341  fRecordingStep = WAIT;
2342  displayRecordingStatus();
2343}
2344
2345
2346bool G4OpenGLQtViewer::isReadyToEncode(){
2347  if (fRecordingStep == READY_TO_ENCODE) {
2348    return true;
2349  }
2350  return false;
2351}
2352
2353void G4OpenGLQtViewer::resetRecording() {
2354    setRecordingStatus(WAIT);
2355}
2356
2357/**
2358 * set the temp folder path
2359 * @return "" if correct. The error otherwise
2360*/
2361QString G4OpenGLQtViewer::setTempFolderPath(QString path) {
2362
2363  if (path == "") {
2364    return "Path does not exist";
2365  }
2366#if QT_VERSION < 0x040000
2367  path =  QDir::cleanDirPath(path);
2368#else
2369  path =  QDir::cleanPath(path);
2370#endif
2371  QFileInfo *d = new QFileInfo(path);
2372  if (!d->exists()) {
2373    return "Path does not exist";
2374  } else if (!d->isDir()) {
2375    return "This is not a directory";
2376  } else if (!d->isReadable()) {
2377    return path +" is read protected";
2378  } else if (!d->isWritable()) {
2379    return path +" is write protected";
2380  }
2381 
2382  if ((fRecordingStep == BAD_TMP)) {
2383    setRecordingStatus(WAIT);
2384  }
2385  fTempFolderPath = path;
2386  return "";
2387}
2388
2389/** @return the temp folder path or "" if it does not exist
2390 */
2391QString G4OpenGLQtViewer::getTempFolderPath() {
2392  return fTempFolderPath;
2393}
2394 
2395/**
2396 * set the save file name path
2397 * @return "" if correct. The error otherwise
2398*/
2399QString G4OpenGLQtViewer::setSaveFileName(QString path) {
2400
2401  if (path == "") {
2402    return "Path does not exist";
2403  }
2404 
2405  QFileInfo *file = new QFileInfo(path);
2406  QDir dir = file->dir();
2407#if QT_VERSION < 0x040000
2408  path =  QDir::cleanDirPath(path);
2409#else
2410  path =  QDir::cleanPath(path);
2411#endif
2412  if (file->exists()) {
2413    return "File already exist, please choose a new one";
2414  } else if (!dir.exists()) {
2415    return "Dir does not exist";
2416  } else if (!dir.isReadable()) {
2417    return path +" is read protected";
2418  }
2419 
2420  if ((fRecordingStep == BAD_OUTPUT)) {
2421    setRecordingStatus(STOP);
2422  }
2423  fSaveFileName = path;
2424  return "";
2425}
2426
2427/** @return the save file path
2428 */
2429QString G4OpenGLQtViewer::getSaveFileName() {
2430  return fSaveFileName ;
2431}
2432
2433/** Create a Qt_temp folder in the temp folder given
2434* The temp folder will be like this /tmp/QtMovie_12-02-2008_12_12_58/
2435* @return "" if success. Error message if not.
2436*/
2437QString G4OpenGLQtViewer::createTempFolder() {
2438  fMovieTempFolderPath = "";
2439  //check
2440  QString tmp = setTempFolderPath(fTempFolderPath);
2441  if (tmp != "") {
2442    return tmp;
2443  }
2444#if QT_VERSION < 0x040000
2445  QString sep = QChar(QDir::separator());
2446#else
2447  QString sep = QString(QDir::separator());
2448#endif
2449  QString path = sep+"QtMovie_"+QDateTime::currentDateTime ().toString("dd-MM-yyyy_hh-mm-ss")+sep;
2450#if QT_VERSION < 0x040000
2451  QDir *d = new QDir(QDir::cleanDirPath(fTempFolderPath));
2452#else
2453  QDir *d = new QDir(QDir::cleanPath(fTempFolderPath));
2454#endif
2455  // check if it is already present
2456  if (d->exists(path)) {
2457    return "Folder "+path+" already exists.Please remove it first";
2458  }
2459  if (d->mkdir(fTempFolderPath+path)) {
2460    fMovieTempFolderPath = fTempFolderPath+path;
2461    return "";
2462  } else {
2463    return "Can't create "+fTempFolderPath+path;
2464  }
2465  return "-";
2466}
2467
2468/** Remove the Qt_temp folder in the temp folder
2469*/
2470QString G4OpenGLQtViewer::removeTempFolder() {
2471        // remove files in Qt_temp folder
2472  if (fMovieTempFolderPath == "") {
2473    return "";
2474  }
2475#if QT_VERSION < 0x040000
2476  QDir *d = new QDir(QDir::cleanDirPath(fMovieTempFolderPath));
2477#else
2478  QDir *d = new QDir(QDir::cleanPath(fMovieTempFolderPath));
2479#endif
2480  if (!d->exists()) {
2481    return "";  // already remove
2482  }
2483
2484  d->setFilter( QDir::Files );
2485  QStringList subDirList = d->entryList();
2486  int res = true;
2487  QString error = "";
2488  for (QStringList::ConstIterator it = subDirList.begin() ;(it != subDirList.end()) ; it++) {
2489    const QString currentFile = *it;
2490      if (!d->remove(currentFile)) {
2491        res = false;
2492        QString file = fMovieTempFolderPath+currentFile;
2493        error +="Removing file failed : "+file;
2494      } else {
2495      }
2496  }
2497  if (res) {
2498    if (d->rmdir(fMovieTempFolderPath)) {
2499      fMovieTempFolderPath = "";
2500      return "";
2501    } else {
2502      return "Dir "+fMovieTempFolderPath+" should be empty, but could not remove it";
2503    }
2504
2505  }
2506  return "Could not remove "+fMovieTempFolderPath+" because of the following errors :"+error;
2507}
2508
2509
2510
2511bool G4OpenGLQtViewer::hasPendingEvents () {
2512  return ((QApplication*)G4Qt::getInstance ())->hasPendingEvents ();
2513}
2514
2515bool G4OpenGLQtViewer::generateMpegEncoderParameters () {
2516
2517                // save the parameter file
2518  FILE* fp;
2519#if QT_VERSION < 0x040000
2520  fp = fopen (QString(fMovieTempFolderPath+fParameterFileName).ascii(), "w");
2521#else
2522  fp = fopen (QString(fMovieTempFolderPath+fParameterFileName).toStdString().c_str(), "w");
2523#endif
2524
2525  if (fp == NULL) {
2526    setRecordingInfos("Generation of parameter file failed");
2527    return false;
2528  }
2529
2530  fprintf (fp,"# parameter file template with lots of comments to assist you\n");
2531  fprintf (fp,"#\n");
2532  fprintf (fp,"# you can use this as a template, copying it to a separate file then modifying\n");
2533  fprintf (fp,"# the copy\n");
2534  fprintf (fp,"#\n");
2535  fprintf (fp,"#\n");
2536  fprintf (fp,"# any line beginning with '#' is a comment\n");
2537  fprintf (fp,"#\n");
2538  fprintf (fp,"# no line should be longer than 255 characters\n");
2539  fprintf (fp,"#\n");
2540  fprintf (fp,"#\n");
2541  fprintf (fp,"# general format of each line is:\n");
2542  fprintf (fp,"#          \n");
2543  fprintf (fp,"#\n");
2544  fprintf (fp,"# lines can generally be in any order\n");
2545  fprintf (fp,"#\n");
2546  fprintf (fp,"# an exception is the option 'INPUT' which must be followed by input\n");
2547  fprintf (fp,"# files in the order in which they must appear, followed by 'END_INPUT'\n");
2548  fprintf (fp,"#\n");
2549  fprintf (fp,"# Also, if you use the `command` method of generating input file names,\n");
2550  fprintf (fp,"# the command will only be executed in the INPUT_DIR if INPUT_DIR preceeds\n");
2551  fprintf (fp,"# the INPUT parameter.\n");
2552  fprintf (fp,"#\n");
2553  fprintf (fp,"#  MUST be in UPPER CASE\n");
2554  fprintf (fp,"#\n");
2555  fprintf (fp,"\n");
2556  fprintf (fp,"# Pattern affects speed, quality and compression. See the User's Guide\n");
2557  fprintf (fp,"# for more info.\n");
2558  fprintf (fp,"\n");
2559  fprintf (fp,"PATTERN          IBBPBBPBBPBBPBBP\n");
2560#if QT_VERSION < 0x040000
2561  fprintf (fp,"OUTPUT           %s\n",getSaveFileName().ascii());
2562#else
2563  fprintf (fp,"OUTPUT           %s\n",getSaveFileName().toStdString().c_str());
2564#endif
2565  fprintf (fp,"\n");
2566  fprintf (fp,"# mpeg_encode really only accepts 3 different file formats, but using a\n");
2567  fprintf (fp,"# conversion statement it can effectively handle ANY file format\n");
2568  fprintf (fp,"#\n");
2569  fprintf (fp,"# You must specify the type of the input files.  The choices are:\n");
2570  fprintf (fp,"#    YUV, PPM, JMOVIE, Y, JPEG, PNM\n");
2571  fprintf (fp,"#        (must be upper case)\n");
2572  fprintf (fp,"#\n");
2573  fprintf (fp,"BASE_FILE_FORMAT PPM\n");
2574  fprintf (fp,"\n");
2575  fprintf (fp,"#\n");
2576  fprintf (fp,"# if YUV format (or using parallel version), must provide width and height\n");
2577  fprintf (fp,"# YUV_SIZE       widthxheight\n");
2578  fprintf (fp,"# this option is ignored if BASE_FILE_FORMAT is not YUV and you're running\n");
2579  fprintf (fp,"# on just one machine\n");
2580  fprintf (fp,"#\n");
2581  fprintf (fp,"YUV_SIZE 352x240\n");
2582  fprintf (fp,"\n");
2583  fprintf (fp,"# If you are using YUV, there are different supported file formats.\n");
2584  fprintf (fp,"# EYUV or UCB are the same as previous versions of this encoder.\n");
2585  fprintf (fp,"# (All the Y's, then U's then V's, in 4:2:0 subsampling.)\n");
2586  fprintf (fp,"# Other formats, such as Abekas, Phillips, or a general format are\n");
2587  fprintf (fp,"# permissible, the general format is a string of Y's, U's, and V's\n");
2588  fprintf (fp,"# to specify the file order.\n");
2589  fprintf (fp,"\n");
2590  fprintf (fp,"INPUT_FORMAT UCB\n");
2591  fprintf (fp,"\n");
2592  fprintf (fp,"# the conversion statement\n");
2593  fprintf (fp,"#\n");
2594  fprintf (fp,"# Each occurrence of '*' will be replaced by the input file\n");
2595  fprintf (fp,"#\n");
2596  fprintf (fp,"# e.g., if you have a bunch of GIF files, then this might be:\n");
2597  fprintf (fp,"#        INPUT_CONVERT   giftoppm *\n");
2598  fprintf (fp,"#\n");
2599  fprintf (fp,"# e.g., if you have a bunch of files like a.Y a.U a.V, etc., then:\n");
2600  fprintf (fp,"#        INPUT_CONVERT   cat *.Y *.U *.V\n");
2601  fprintf (fp,"#\n");
2602  fprintf (fp,"# e.g., if you are grabbing from laser disc you might have something like\n");
2603  fprintf (fp,"#        INPUT_CONVERT   goto frame *; grabppm\n");
2604  fprintf (fp,"# 'INPUT_CONVERT *' means the files are already in the base file format\n");
2605  fprintf (fp,"#\n");
2606  fprintf (fp,"INPUT_CONVERT    * \n");
2607  fprintf (fp,"\n");
2608  fprintf (fp,"# number of frames in a GOP.\n");
2609  fprintf (fp,"#\n");
2610  fprintf (fp,"# since each GOP must have at least one I-frame, the encoder will find the\n");
2611  fprintf (fp,"# the first I-frame after GOP_SIZE frames to start the next GOP\n");
2612  fprintf (fp,"#\n");
2613  fprintf (fp,"# later, will add more flexible GOP signalling\n");
2614  fprintf (fp,"#\n");
2615  fprintf (fp,"GOP_SIZE 16\n");
2616  fprintf (fp,"\n");
2617  fprintf (fp,"# number of slices in a frame\n");
2618  fprintf (fp,"#\n");
2619  fprintf (fp,"# 1 is a good number.  another possibility is the number of macroblock rows\n");
2620  fprintf (fp,"# (which is the height divided by 16)\n");
2621  fprintf (fp,"#\n");
2622  fprintf (fp,"SLICES_PER_FRAME 1\n");
2623  fprintf (fp,"\n");
2624  fprintf (fp,"# directory to get all input files from (makes this file easier to read)\n");
2625#if QT_VERSION < 0x040000
2626  fprintf (fp,"INPUT_DIR        %s\n",fMovieTempFolderPath.ascii());
2627#else
2628  fprintf (fp,"INPUT_DIR        %s\n",fMovieTempFolderPath.toStdString().c_str());
2629#endif
2630  fprintf (fp,"\n");
2631  fprintf (fp,"# There are a bunch of ways to specify the input files.\n");
2632  fprintf (fp,"# from a simple one-per-line listing, to the following \n");
2633  fprintf (fp,"# way of numbering them.  See the manual for more information.\n");
2634  fprintf (fp,"INPUT\n");
2635  fprintf (fp,"# '*' is replaced by the numbers 01, 02, 03, 04\n");
2636  fprintf (fp,"# if I instead do [01-11], it would be 01, 02, ..., 09, 10, 11\n");
2637  fprintf (fp,"# if I instead do [1-11], it would be 1, 2, 3, ..., 9, 10, 11\n");
2638  fprintf (fp,"# if I instead do [1-11+3], it would be 1, 4, 7, 10\n");
2639  fprintf (fp,"# the program assumes none of your input files has a name ending in ']'\n");
2640  fprintf (fp,"# if you do, too bad!!!\n");
2641  fprintf (fp,"#\n");
2642  fprintf (fp,"#\n");
2643  fprintf (fp,"Test*.ppm        [0-%d]\n",fRecordFrameNumber-1);
2644  fprintf (fp,"# can have more files here if you want...there is no limit on the number\n");
2645  fprintf (fp,"# of files\n");
2646  fprintf (fp,"END_INPUT\n");
2647  fprintf (fp,"\n");
2648  fprintf (fp,"\n");
2649  fprintf (fp,"\n");
2650  fprintf (fp,"# Many of the remaining options have to do with the motion search and qscale\n");
2651  fprintf (fp,"\n");
2652  fprintf (fp,"# FULL or HALF -- must be upper case\n");
2653  fprintf (fp,"# Should be FULL for computer generated images\n");
2654  fprintf (fp,"PIXEL            FULL\n");
2655  fprintf (fp,"\n");
2656  fprintf (fp,"# means +/- this many pixels for both P and B frame searches\n");
2657  fprintf (fp,"# specify two numbers if you wish to serc different ranges in the two.\n");
2658  fprintf (fp,"RANGE            10\n");
2659  fprintf (fp,"\n");
2660  fprintf (fp,"# The two search algorithm parameters below mostly affect speed,\n");
2661  fprintf (fp,"# with some affect on compression and almost none on quality.\n");
2662  fprintf (fp,"\n");
2663  fprintf (fp,"# this must be one of {EXHAUSTIVE, SUBSAMPLE, LOGARITHMIC}\n");
2664  fprintf (fp,"PSEARCH_ALG      LOGARITHMIC\n");
2665  fprintf (fp,"\n");
2666  fprintf (fp,"# this must be one of {SIMPLE, CROSS2, EXHAUSTIVE}\n");
2667  fprintf (fp,"#\n");
2668  fprintf (fp,"# note that EXHAUSTIVE is really, really, really slow\n");
2669  fprintf (fp,"#\n");
2670  fprintf (fp,"BSEARCH_ALG      SIMPLE\n");
2671  fprintf (fp,"\n");
2672  fprintf (fp,"#\n");
2673  fprintf (fp,"# these specify the q-scale for I, P, and B frames\n");
2674  fprintf (fp,"# (values must be between 1 and 31)\n");
2675  fprintf (fp,"# These are the Qscale values for the entire frame in variable bit-rate\n");
2676  fprintf (fp,"# mode, and starting points (but not important) for constant bit rate\n");
2677  fprintf (fp,"#\n");
2678  fprintf (fp,"\n");
2679  fprintf (fp,"# Qscale (Quantization scale) affects quality and compression,\n");
2680  fprintf (fp,"# but has very little effect on speed.\n");
2681  fprintf (fp,"\n");
2682  fprintf (fp,"IQSCALE          4\n");
2683  fprintf (fp,"PQSCALE          5\n");
2684  fprintf (fp,"BQSCALE          12\n");
2685  fprintf (fp,"\n");
2686  fprintf (fp,"# this must be ORIGINAL or DECODED\n");
2687  fprintf (fp,"REFERENCE_FRAME  ORIGINAL\n");
2688  fprintf (fp,"\n");
2689  fprintf (fp,"# for parallel parameters see parallel.param in the exmaples subdirectory\n");
2690  fprintf (fp,"\n");
2691  fprintf (fp,"# if you want constant bit-rate mode, specify it as follows (number is bits/sec):\n");
2692  fprintf (fp,"#BIT_RATE  1000000\n");
2693  fprintf (fp,"\n");
2694  fprintf (fp,"# To specify the buffer size (327680 is default, measused in bits, for 16bit words)\n");
2695  fprintf (fp,"BUFFER_SIZE 327680\n");
2696  fprintf (fp,"\n");
2697  fprintf (fp,"# The frame rate is the number of frames/second (legal values:\n");
2698  fprintf (fp,"# 23.976, 24, 25, 29.97, 30, 50 ,59.94, 60\n");
2699  fprintf (fp,"FRAME_RATE 30\n");
2700  fprintf (fp,"\n");
2701  fprintf (fp,"# There are many more options, see the users manual for examples....\n");
2702  fprintf (fp,"# ASPECT_RATIO, USER_DATA, GAMMA, IQTABLE, etc.\n");
2703  fprintf (fp,"\n");
2704  fprintf (fp,"\n");
2705  fclose (fp);
2706
2707  setRecordingInfos("Parameter file "+fParameterFileName+" generated in "+fMovieTempFolderPath);
2708  setRecordingStatus(READY_TO_ENCODE);
2709  return true;
2710}
2711
2712void G4OpenGLQtViewer::encodeVideo()
2713{
2714  if ((getEncoderPath() != "") && (getSaveFileName() != "")) {
2715    setRecordingStatus(ENCODING);
2716   
2717#if QT_VERSION < 0x040000
2718    QStringList args = QStringList(fEncoderPath);
2719    args.push_back(fMovieTempFolderPath+fParameterFileName);
2720    fProcess = new QProcess(args);
2721    QObject ::connect(fProcess,SIGNAL(processExited ()),
2722                      this,SLOT(processEncodeFinished()));
2723    QObject ::connect(fProcess,SIGNAL(readyReadStdout ()),
2724                      this,SLOT(processEncodeStdout()));
2725    fProcess->setCommunication(QProcess::DupStderr);
2726    fProcess->launch("");
2727#else
2728    fProcess = new QProcess();
2729#if QT_VERSION > 0x040100
2730    QObject ::connect(fProcess,SIGNAL(finished ( int,QProcess::ExitStatus)),
2731                      this,SLOT(processEncodeFinished()));
2732    QObject ::connect(fProcess,SIGNAL(readyReadStandardOutput ()),
2733                      this,SLOT(processEncodeStdout()));
2734#else
2735    QObject ::connect(fProcess,SIGNAL(finished ( int)),
2736                      this,SLOT(processEncodeFinished()));
2737    QObject ::connect(fProcess,SIGNAL(readyReadStandardOutput ()),
2738                      this,SLOT(processEncodeStdout()));
2739#endif
2740    fProcess->setReadChannelMode(QProcess::MergedChannels);
2741    fProcess->start (fEncoderPath, QStringList(fMovieTempFolderPath+fParameterFileName));
2742#endif
2743  }
2744}
2745
2746
2747// FIXME : does not work on Qt3
2748void G4OpenGLQtViewer::processEncodeStdout()
2749{
2750#if QT_VERSION > 0x040000
2751  QString tmp = fProcess->readAllStandardOutput ().data();
2752  int start = tmp.lastIndexOf("ESTIMATED TIME");
2753  tmp = tmp.mid(start,tmp.indexOf("\n",start)-start);
2754#else
2755  QString tmp = fProcess->readStdout ().data();
2756  int start = tmp.findRev("ESTIMATED TIME");
2757  tmp = tmp.mid(start,tmp.find("\n",start)-start);
2758#endif
2759  setRecordingInfos(tmp);
2760}
2761
2762
2763void G4OpenGLQtViewer::processEncodeFinished()
2764{
2765
2766  QString txt = "";
2767  txt = getProcessErrorMsg();
2768  if (txt == "") {
2769    setRecordingStatus(SUCCESS);
2770  } else {
2771    setRecordingStatus(FAILED);
2772  }
2773  //  setRecordingInfos(txt+removeTempFolder());
2774}
2775
2776
2777void G4OpenGLQtViewer::processLookForFinished()
2778 {
2779
2780  QString txt = getProcessErrorMsg();
2781  if (txt != "") {
2782    fEncoderPath = "";
2783  } else {
2784#if QT_VERSION > 0x040000
2785    fEncoderPath = QString(fProcess->readAllStandardOutput ().data()).trimmed();
2786#else
2787    fEncoderPath = QString(fProcess->readStdout ().data()).simplifyWhiteSpace();
2788#endif
2789    // if not found, return "not found"
2790    if (fEncoderPath.contains(" ")) {
2791      fEncoderPath = "";
2792    } else if (!fEncoderPath.contains("mpeg_encode")) {
2793      fEncoderPath = "";
2794    }
2795    setEncoderPath(fEncoderPath);
2796  }
2797  // init temp folder
2798#if QT_VERSION > 0x040000
2799  setTempFolderPath(QDir::temp ().absolutePath ());
2800#else
2801  // Let's have a try
2802  setTempFolderPath("/tmp/");
2803#endif
2804}
2805
2806
2807QString G4OpenGLQtViewer::getProcessErrorMsg()
2808{
2809  QString txt = "";
2810#if QT_VERSION < 0x040000
2811  if (!fProcess->normalExit ()) {
2812    txt = "Exist status "+ fProcess->exitStatus ();
2813  }
2814#else
2815  if (fProcess->exitCode() != 0) {
2816    switch (fProcess->error()) {
2817    case QProcess::FailedToStart:
2818      txt = "The process failed to start. Either the invoked program is missing, or you may have insufficient permissions to invoke the program.\n";
2819      break;
2820    case QProcess::Crashed:
2821      txt = "The process crashed some time after starting successfully.\n";
2822      break;
2823    case QProcess::Timedout:
2824      txt = "The last waitFor...() function timed out. The state of QProcess is unchanged, and you can try calling waitFor...() again.\n";
2825      break;
2826    case QProcess::WriteError:
2827      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";
2828      break;
2829    case QProcess::ReadError:
2830      txt = "An error occurred when attempting to read from the process. For example, the process may not be running.\n";
2831      break;
2832    case QProcess::UnknownError:
2833      txt = "An unknown error occurred. This is the default return value of error().\n";
2834      break;
2835    }
2836  }
2837#endif
2838   return txt;
2839}
2840
2841
2842
2843
2844QWidget *G4OpenGLQtViewer::getParentWidget()
2845{
2846  // launch Qt if not
2847  G4Qt* interactorManager = G4Qt::getInstance ();
2848  // G4UImanager* UI =
2849  G4UImanager::GetUIpointer();
2850#ifdef G4DEBUG_VIS_OGL
2851  //  printf("G4OpenGLQtViewer::getParentWidget :: UImanager %d  G4Qt:%d et via GetUIQt:%d---------------------\n",UI,UI->GetSession(),interactorManager,interactorManager->GetUIVisWidget());
2852#endif
2853 
2854  bool found = false;
2855 
2856  // create window
2857  if (((QApplication*)interactorManager->GetMainInteractor())) {
2858    // look for the main window
2859#if QT_VERSION < 0x040000
2860    // theses lines does nothing exept this one "GLWindow = new QDialog(0..."
2861    // but if I comment them, it doesn't work...
2862    QWidgetList  *list = QApplication::allWidgets();
2863    QWidgetListIt it( *list );         // iterate over the widgets
2864    QWidget * widget;
2865    while ( (widget=it.current()) != 0 ) {  // for each widget...
2866      ++it;
2867      if ((found== false) && (widget->inherits("QMainWindow"))) {
2868        fGLWindow = new QDialog(0,0,FALSE,Qt::WStyle_Title | Qt::WStyle_SysMenu | Qt::WStyle_MinMax );
2869        found = true;
2870      }
2871    }
2872    delete list;                      // delete the list, not the widgets
2873#else
2874    foreach (QWidget *widget, QApplication::allWidgets()) {
2875      if ((found== false) && (widget->inherits("QMainWindow"))) {
2876        fGLWindow = new QDialog(widget,Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowMinMaxButtonsHint);
2877        found = true;
2878      }
2879    }
2880#endif
2881   
2882    if (found==false) {
2883#ifdef G4DEBUG_VIS_OGL
2884      printf("G4OpenGLQtViewer::CreateMainWindow case Qapp exist, but not found\n");
2885#endif
2886      fGLWindow = new QDialog();
2887    }
2888  } else {
2889#ifdef G4DEBUG_VIS_OGL
2890    printf("G4OpenGLQtViewer::CreateMainWindow case Qapp exist\n");
2891#endif
2892    fGLWindow = new QDialog();
2893#ifdef G4DEBUG_VIS_OGL
2894    printf("G4OpenGLQtViewer::GetParentWidget fGLWindow\n");
2895#endif
2896  }
2897  if (found) {
2898    return fGLWindow;
2899  } else {
2900    return NULL;
2901  }
2902}
2903
2904/*
2905 
2906void MultiLayer::exportToSVG(const QString& fname)
2907{
2908  QPicture picture;
2909  QPainter p(&picture);
2910  for (int i=0;i<(int)graphsList->count();i++)
2911    {
2912      Graph *gr=(Graph *)graphsList->at(i);
2913      Plot *myPlot= (Plot *)gr->plotWidget();
2914     
2915      QPoint pos=gr->pos();
2916     
2917      int width=int(myPlot->frameGeometry().width());
2918      int height=int(myPlot->frameGeometry().height());
2919     
2920      myPlot->print(&p, QRect(pos,QSize(width,height)));
2921    }
2922 
2923  p.end();
2924  picture.save(fname, "svg");
2925}
2926*/
2927#endif
Note: See TracBrowser for help on using the repository browser.