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

Last change on this file since 857 was 857, checked in by garnier, 16 years ago

movie parameters imrovments

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