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

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

update before commit to cvs

  • Property svn:mime-type set to text/cpp
File size: 84.5 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.23 2008/04/29 16:58:04 lgarnier Exp $
28// GEANT4 tag $Name:  $
29//
30//
31// G4OpenGLQtViewer : Class to provide Qt specific
32//                     functionality for OpenGL in GEANT4
33//
34// 27/06/2003 : G.Barrand : implementation (at last !).
35
36#ifdef G4VIS_BUILD_OPENGLQT_DRIVER
37
38//#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    if (getEncoderPath() == "") {
1489      setRecordingInfos("mpeg_encode is needed to encode in video format. It is available here: http://bmrc.berkeley.edu/frame/research/mpeg/");
1490    }
1491  }
1492  fMovieParametersDialog->show();
1493}
1494
1495
1496/*
1497// 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
1498
1499void Graph::exportToSVG(const QString& fname)
1500{
1501  // enable workaround for Qt3 misalignments
1502  QwtPainter::setSVGMode(true);
1503  QPicture picture;
1504  QPainter p(&picture);
1505  d_plot->print(&p, d_plot->rect());
1506  p.end();
1507
1508  picture.save(fname, "svg");
1509}
1510*/
1511
1512
1513
1514
1515/**
1516   Save the current mouse press point
1517   @param p mouse click point
1518*/
1519#if QT_VERSION < 0x040000
1520void G4OpenGLQtViewer::G4MousePressEvent(QPoint p)
1521#else
1522void G4OpenGLQtViewer::G4MousePressEvent(QPoint p)
1523#endif
1524{
1525  fAutoMove = false; // stop automove
1526  fLastPos1 = p;
1527  fLastPos2 = fLastPos1;
1528  fLastPos3 = fLastPos2;
1529  fLastEventTime->start();
1530  if (fMouseAction == STYLE2){  // pick
1531    Pick(p.x(),p.y());
1532  }
1533}
1534
1535/**
1536*/
1537void G4OpenGLQtViewer::G4MouseReleaseEvent()
1538{
1539#ifdef GEANT4_QT_DEBUG
1540  printf("G4OpenGLQtViewer::mouseRealease() %d,%d  %d,%d  %d,%d\n",fLastPos1.x(),fLastPos1.y(),fLastPos2.x(),fLastPos2.y(),fLastPos3.x(),fLastPos3.y());
1541#endif
1542  fSpinningDelay = fLastEventTime->elapsed();
1543  QPoint delta = (fLastPos3-fLastPos1);
1544  if ((delta.x() == 0) && (delta.y() == 0)) {
1545#ifdef GEANT4_QT_DEBUG
1546  printf("G4OpenGLQtViewer::mouseRealease() EXIT 1 \n");
1547#endif
1548    return;
1549  }
1550  if (fSpinningDelay < fLaunchSpinDelay ) {
1551    fAutoMove = true;
1552    QTime lastMoveTime;
1553    lastMoveTime.start();
1554    // try to addapt speed move/rotate looking to drawing speed
1555    int cycles = 4;
1556    while (fAutoMove) {
1557      //      if ( lastMoveTime.elapsed() > (fSpinningDelay / (cycles/2))) {
1558        if (fMouseAction == STYLE1) {  // rotate
1559          rotateQtScene(((float)delta.x())/cycles,((float)delta.y())/cycles);
1560        } else if (fMouseAction == STYLE2) {  // move
1561          moveScene(-((float)delta.x())/cycles,-((float)delta.y())/cycles,0,true);
1562        }
1563        lastMoveTime.start();
1564        cycles = 1 ;
1565        //      }
1566      ((QApplication*)G4Qt::getInstance ())->processEvents();
1567#ifdef GEANT4_QT_DEBUG
1568        printf("G4OpenGLQtViewer::mouseRealease() cycle :%d \n",lastMoveTime.elapsed());
1569#endif
1570      cycles ++ ;
1571    }
1572  }
1573}
1574
1575
1576/**
1577   @param pos_x mouse x position
1578   @param pos_y mouse y position
1579   @param mButtons mouse button active
1580   @param mAutoMove true: apply this move till another evnt came, false :one time move
1581*/
1582
1583#if QT_VERSION < 0x040000
1584void G4OpenGLQtViewer::G4MouseMoveEvent(int pos_x, int pos_y,Qt::ButtonState mButtons)
1585#else
1586  void G4OpenGLQtViewer::G4MouseMoveEvent(int pos_x, int pos_y,Qt::MouseButtons mButtons)
1587#endif
1588{
1589
1590  if (fAutoMove) {
1591    return;
1592  }
1593
1594  fLastPos3 = fLastPos2;
1595  fLastPos2 = fLastPos1;
1596  fLastPos1 = QPoint(pos_x, pos_y);
1597
1598  int deltaX = fLastPos2.x()-fLastPos1.x();
1599  int deltaY = fLastPos2.y()-fLastPos1.y();
1600
1601  if (fMouseAction == STYLE1) {  // rotate
1602    if (mButtons & Qt::LeftButton) {
1603      rotateQtScene(deltaX,deltaY);
1604    }
1605  } else if (fMouseAction == STYLE2) {  // move
1606    if (mButtons & Qt::LeftButton) {
1607      moveScene(-deltaX,-deltaY,0,true);
1608    }
1609  }
1610
1611  fLastEventTime->start();
1612}
1613
1614
1615/**
1616   Move the scene of dx, dy, dz values.
1617   @param dx delta mouse x position
1618   @param dy delta mouse y position
1619   @param mouseMove : true if even comes from a mouse move, false if even comes from key action
1620*/
1621
1622void G4OpenGLQtViewer::moveScene(float dx,float dy, float dz,bool mouseMove)
1623{
1624  if (fHoldMoveEvent)
1625    return;
1626  fHoldMoveEvent = true;
1627
1628  G4double coefTrans = 0;
1629  GLdouble coefDepth = 0;
1630  if(mouseMove) {
1631    coefTrans = ((G4double)getSceneNearWidth())/((G4double)WinSize_x);
1632    if (WinSize_y <WinSize_x) {
1633      coefTrans = ((G4double)getSceneNearWidth())/((G4double)WinSize_y);
1634    }
1635  } else {
1636    coefTrans = getSceneNearWidth()*fDeltaSceneTranslation;
1637    coefDepth = getSceneDepth()*fDeltaDepth;
1638  }
1639  fVP.IncrementPan(-dx*coefTrans,dy*coefTrans,dz*coefDepth);
1640  emit moveX(-dx*coefTrans);
1641  emit moveY(dy*coefTrans);
1642  emit moveZ(dz*coefTrans);
1643 
1644  updateQWidget();
1645  if (fAutoMove)
1646    ((QApplication*)G4Qt::getInstance ())->processEvents();
1647 
1648  fHoldMoveEvent = false;
1649}
1650
1651
1652/**
1653   @param dx delta mouse x position
1654   @param dy delta mouse y position
1655*/
1656
1657void G4OpenGLQtViewer::rotateQtScene(float dx, float dy)
1658{
1659  if (fHoldRotateEvent)
1660    return;
1661  fHoldRotateEvent = true;
1662 
1663  if( dx != 0) {
1664    rotateScene(dx,0,fDeltaRotation);
1665    emit rotateTheta(dx);
1666  }
1667  if( dy != 0) {
1668    rotateScene(0,dy,fDeltaRotation);
1669    emit rotatePhi(dy);
1670  }
1671  updateQWidget();
1672 
1673  fHoldRotateEvent = false;
1674}
1675
1676/**
1677   @param dx delta mouse x position
1678   @param dy delta mouse y position
1679*/
1680
1681void G4OpenGLQtViewer::rotateQtCamera(float dx, float dy)
1682{
1683  if (fHoldRotateEvent)
1684    return;
1685  fHoldRotateEvent = true;
1686
1687  rotateScene(dx,dy,fDeltaRotation);
1688  emit rotateTheta(dx);
1689  emit rotatePhi(dy);
1690  updateQWidget();
1691 
1692  fHoldRotateEvent = false;
1693}
1694
1695
1696
1697
1698/** This is the benning of a rescale function. It does nothing for the moment
1699    @param aWidth : new width
1700    @param aHeight : new height
1701*/
1702void G4OpenGLQtViewer::rescaleImage(
1703 int aWidth
1704,int aHeight
1705){
1706#ifdef GEANT4_QT_DEBUG
1707  printf("should rescale \n");
1708#endif
1709  GLfloat* feedback_buffer;
1710  GLint returned;
1711  FILE* file;
1712 
1713//   feedback_buffer = new GLfloat[size];
1714//   glFeedbackBuffer (size, GL_3D_COLOR, feedback_buffer);
1715//   glRenderMode (GL_FEEDBACK);
1716 
1717//   glViewport (0, 0, aWidth, aHeight);
1718//   DrawView();
1719//   returned = glRenderMode (GL_RENDER);
1720
1721}
1722
1723/**
1724   Generate Vectorial Encapsulated Postscript form image
1725   @param aFilename : name of file
1726   @param aInColor : numbers of colors : 1->BW 2->RGB 3->RGB+Alpha
1727   @param aImage : Image to print
1728*/
1729bool G4OpenGLQtViewer::generateVectorEPS (
1730 QString aFilename
1731,int aWidth
1732,int aHeight
1733,QImage aImage
1734)
1735{
1736  // Print vectored PostScript
1737 
1738  G4int size = 5000000;
1739
1740  GLfloat* feedback_buffer;
1741  GLint returned;
1742  FILE* file;
1743 
1744  feedback_buffer = new GLfloat[size];
1745  glFeedbackBuffer (size, GL_3D_COLOR, feedback_buffer);
1746  glRenderMode (GL_FEEDBACK);
1747 
1748  int side = aWidth;
1749  if (aHeight < aWidth) side = aHeight;
1750  glViewport((aWidth - side) / 2, (aHeight - side) / 2, side, side);
1751  DrawView();
1752
1753  returned = glRenderMode (GL_RENDER);
1754 
1755 
1756#if QT_VERSION < 0x040000
1757  file = fopen (aFilename.ascii(), "w");
1758#else
1759  file = fopen (aFilename.toStdString().c_str(), "w");
1760#endif
1761  if (file) {
1762    spewWireframeEPS (file, returned, feedback_buffer, "rendereps");
1763  } else {
1764#if QT_VERSION < 0x040000
1765    G4cerr << "Could not open "<< aFilename.ascii() << G4endl;
1766#else
1767    G4cerr << "Could not open "<< aFilename.toStdString().c_str() << G4endl;
1768#endif
1769  }
1770 
1771  delete[] feedback_buffer;
1772
1773  return true;
1774}
1775
1776/**
1777   Generate Encapsulated Postscript form image
1778   @param aFilename : name of file
1779   @param aInColor : numbers of colors : 1->BW 2->RGB 3->RGB+Alpha
1780   @param aImage : Image to print
1781*/
1782bool G4OpenGLQtViewer::generateEPS (
1783 QString aFilename
1784,int aInColor
1785,QImage aImage
1786)
1787{
1788  // FIXME
1789#ifdef GEANT4_QT_DEBUG
1790  printf("saving EPS\n");
1791#endif
1792
1793  FILE* fp;
1794
1795  if (aImage.bits () == NULL)
1796    return false;
1797 
1798#if QT_VERSION < 0x040000
1799  fp = fopen (aFilename.ascii(), "w");
1800#else
1801  fp = fopen (aFilename.toStdString().c_str(), "w");
1802#endif
1803  if (fp == NULL) {
1804    return false;
1805  }
1806 
1807  fprintf (fp, "%%!PS-Adobe-2.0 EPSF-1.2\n");
1808#if QT_VERSION < 0x040000
1809  fprintf (fp, "%%%%Title: %s\n", aFilename.ascii());
1810#else
1811  fprintf (fp, "%%%%Title: %s\n", aFilename.toStdString().c_str());
1812#endif
1813  fprintf (fp, "%%%%Creator: OpenGL pixmap render output\n");
1814  fprintf (fp, "%%%%BoundingBox: 0 0 %d %d\n", aImage.width(), aImage.height());
1815  fprintf (fp, "%%%%EndComments\n");
1816  fprintf (fp, "gsave\n");
1817  fprintf (fp, "/bwproc {\n");
1818  fprintf (fp, "    rgbproc\n");
1819  fprintf (fp, "    dup length 3 idiv string 0 3 0 \n");
1820  fprintf (fp, "    5 -1 roll {\n");
1821  fprintf (fp, "    add 2 1 roll 1 sub dup 0 eq\n");
1822  fprintf (fp, "    { pop 3 idiv 3 -1 roll dup 4 -1 roll dup\n");
1823  fprintf (fp, "       3 1 roll 5 -1 roll } put 1 add 3 0 \n");
1824  fprintf (fp, "    { 2 1 roll } ifelse\n");
1825  fprintf (fp, "    }forall\n");
1826  fprintf (fp, "    pop pop pop\n");
1827  fprintf (fp, "} def\n");
1828  fprintf (fp, "systemdict /colorimage known not {\n");
1829  fprintf (fp, "   /colorimage {\n");
1830  fprintf (fp, "       pop\n");
1831  fprintf (fp, "       pop\n");
1832  fprintf (fp, "       /rgbproc exch def\n");
1833  fprintf (fp, "       { bwproc } image\n");
1834  fprintf (fp, "   }  def\n");
1835  fprintf (fp, "} if\n");
1836  fprintf (fp, "/picstr %d string def\n", aImage.width() * aInColor);
1837  fprintf (fp, "%d %d scale\n", aImage.width(), aImage.height());
1838  fprintf (fp, "%d %d %d\n", aImage.width(), aImage.height(), 8);
1839  fprintf (fp, "[%d 0 0 %d 0 0]\n", aImage.width(), aImage.height());
1840  fprintf (fp, "{currentfile picstr readhexstring pop}\n");
1841  fprintf (fp, "false %d\n", aInColor);
1842  fprintf (fp, "colorimage\n");
1843 
1844
1845  int width = aImage.width();
1846  int height = aImage.height();
1847  int depth = aImage.depth();
1848  int size = width*height;
1849 
1850  if (depth == 1)
1851    size = (width+7)/8*height;
1852  else if (aInColor == 1)
1853    size = size*3;
1854 
1855  int i = 0;
1856  //  if ( aInColor ==1 ) {
1857  // FIXME : L. Garnier. For the moment 10 dec 2007, I could not find a way
1858  // to save correctly grayscale Image. I mean that color or grayscale image
1859  // have the same file save size !
1860 
1861  /* } else*/ if (depth == 8) {
1862    for(int y=height-1; y >=0 ; y--) {
1863      const uchar * s = aImage.scanLine(y);
1864      for(int x=0; x <width; x++) {
1865        QRgb rgb = aImage.color(s[x]);
1866        if (aInColor == 1) {
1867          fprintf (fp, " %02hx ",(unsigned char)qGray(rgb));
1868          i++;
1869        } else {
1870          fprintf (fp, " %02hx %02hx %02hx",
1871                   (unsigned char) qRed(rgb),
1872                   (unsigned char) qGreen(rgb),
1873                   (unsigned char) qBlue(rgb));
1874          i += 3;
1875        }
1876      }
1877      fprintf (fp, "\n");
1878    }
1879  } else {
1880#if QT_VERSION < 0x040000
1881    bool alpha = aImage.hasAlphaBuffer();
1882#else
1883    bool alpha = aImage.hasAlphaChannel();
1884    for(int y=height-1; y >=0 ; y--) {
1885      QRgb * s = (QRgb*)(aImage.scanLine(y));
1886      for(int x=0; x <width; x++) {
1887        QRgb rgb = (*s++);
1888        if (alpha && qAlpha(rgb) < 0x40) // 25% alpha, convert to white -
1889          rgb = qRgb(0xff, 0xff, 0xff);
1890        if (aInColor == 1) {
1891          fprintf (fp, " %02hx ",(unsigned char)qGray(rgb));
1892          i++;
1893        } else {
1894          fprintf (fp, " %02hx %02hx %02hx",
1895                   (unsigned char) qRed(rgb),
1896                   (unsigned char) qGreen(rgb),
1897                   (unsigned char) qBlue(rgb));
1898          i += 3;
1899        }
1900      }
1901      fprintf (fp, "\n");
1902    }
1903#endif
1904
1905  }
1906
1907  fprintf (fp, "grestore\n");
1908  fprintf (fp, "showpage\n");
1909  fclose (fp);
1910
1911  return true;
1912}
1913/**
1914   Generate Postscript or PDF form image
1915   @param aFilename : name of file
1916   @param aInColor : numbers of colors : 1->BW 2->RGB
1917   @param aImage : Image to print
1918*/
1919bool G4OpenGLQtViewer::generatePS_PDF (
1920 QString aFilename
1921,int aInColor
1922,QImage aImage
1923)
1924{
1925
1926#if QT_VERSION < 0x040000
1927#ifdef Q_WS_MAC || Q_WS_X11
1928  QPrinter printer;
1929  //  printer.setPageSize(pageSize);
1930  if (aInColor == 1) {
1931    printer.setColorMode(QPrinter::GrayScale);
1932  } else {
1933    printer.setColorMode(QPrinter::Color);
1934  }
1935
1936  /* FIXME : I don't know which format it will save...
1937     if (aFilename.endsWith(".ps")) {
1938     printer.setOutputFormat(QPrinter::PostScriptFormat);
1939     } else {
1940     printer.setOutputFormat(QPrinter::PdfFormat);
1941     }
1942  */
1943  printer.setOutputFileName(aFilename);
1944  //  printer.setFullPage ( true);
1945  QPainter paint(&printer);
1946  paint.drawImage (0,0,aImage );
1947  paint.end();
1948#else
1949  G4cerr << "This fonction is only supported on Mac OsX or X11 with Qt3. Full platform supported with Qt4" << G4endl;
1950#endif
1951#else
1952  QPrinter printer;
1953  //  printer.setPageSize(pageSize);
1954
1955  // FIXME : L. Garnier 4/12/07
1956  // This is not working, it does nothing. Image is staying in color mode
1957  // So I have desactivate the B/W button in GUI
1958  if ((!aImage.isGrayscale ()) &&(aInColor ==1 )) {
1959#if QT_VERSION < 0x040000
1960    aImage = aImage.convertDepth(1,Qt::MonoOnly);
1961#else
1962    aImage = aImage.convertToFormat ( aImage.format(), Qt::MonoOnly);
1963#endif
1964  }
1965
1966
1967  if (aFilename.endsWith(".ps")) {
1968#if QT_VERSION > 0x040200
1969    printer.setOutputFormat(QPrinter::PostScriptFormat);
1970#endif
1971  } else {
1972#if QT_VERSION > 0x040100
1973    printer.setOutputFormat(QPrinter::PdfFormat);
1974#endif
1975  }
1976#if QT_VERSION > 0x040100
1977  printer.setOutputFileName(aFilename);
1978#endif
1979  //  printer.setFullPage ( true);
1980  QPainter paint(&printer);
1981  paint.drawImage (0,0,aImage);
1982  paint.end();
1983#endif
1984  return true;
1985}
1986
1987
1988void G4OpenGLQtViewer::G4wheelEvent (QWheelEvent * event)
1989{
1990  fVP.SetZoomFactor(fVP.GetZoomFactor()+(fVP.GetZoomFactor()*(event->delta())/1200));
1991  updateQWidget();
1992
1993#ifdef GEANT4_QT_DEBUG
1994  printf("G4OpenGLQtViewer::wheel event  +++++++++++++++++++++ %f %d\n",fVP.GetZoomFactor(),event->delta());
1995#endif
1996}
1997
1998
1999void G4OpenGLQtViewer::G4keyPressEvent (QKeyEvent * event)
2000{
2001  if (fHoldKeyEvent)
2002    return;
2003
2004  fHoldKeyEvent = true;
2005
2006#if QT_VERSION < 0x040000
2007  if ((event->key() == Qt::Key_Down) && (event->state() & Qt::AltButton )) { // go backward
2008#else
2009  if ((event->key() == Qt::Key_Down) && (event->modifiers() & Qt::AltModifier )) { // go backward
2010#endif
2011   
2012    moveScene(0,0,1,false);
2013  }
2014#if QT_VERSION < 0x040000
2015  else if ((event->key() == Qt::Key_Up) && (event->state() & Qt::AltButton)) { // go forward
2016#else
2017  else if ((event->key() == Qt::Key_Up) && (event->modifiers() & Qt::AltModifier)) { // go forward
2018#endif
2019    moveScene(0,0,-1,false);
2020  }
2021#if QT_VERSION < 0x040000
2022  if ((event->key() == Qt::Key_Down) && (event->state() & Qt::ShiftButton)) { // rotate phi
2023#else
2024  if ((event->key() == Qt::Key_Down) && (event->modifiers() & Qt::ShiftModifier)) { // rotate phi
2025#endif
2026    rotateQtCamera(0,-1);
2027  }
2028#if QT_VERSION < 0x040000
2029  else if ((event->key() == Qt::Key_Up) && (event->state() & Qt::ShiftButton)) { // rotate phi
2030#else
2031  else if ((event->key() == Qt::Key_Up) && (event->modifiers() & Qt::ShiftModifier)) { // rotate phi
2032#endif
2033    rotateQtCamera(0,1);
2034  }
2035#if QT_VERSION < 0x040000
2036  if ((event->key() == Qt::Key_Left) && (event->state() & Qt::ShiftButton)) { // rotate theta
2037#else
2038  if ((event->key() == Qt::Key_Left) && (event->modifiers() & Qt::ShiftModifier)) { // rotate theta
2039#endif
2040    rotateQtCamera(1,0);
2041  }
2042#if QT_VERSION < 0x040000
2043  else if ((event->key() == Qt::Key_Right) && (event->state() & Qt::ShiftButton)) { // rotate theta
2044#else
2045  else if ((event->key() == Qt::Key_Right) && (event->modifiers() & Qt::ShiftModifier)) { // rotate theta
2046#endif
2047    rotateQtCamera(-1,0);
2048  }
2049
2050#if QT_VERSION < 0x040000
2051  if ((event->state() & Qt::AltButton)) {
2052#else
2053  if ((event->modifiers() & Qt::AltModifier)) {
2054#endif
2055    if (event->key() == Qt::Key_Plus) {
2056      fDeltaRotation = fDeltaRotation/0.7;
2057    }
2058    else if (event->key() == Qt::Key_Minus) {
2059      fDeltaRotation = fDeltaRotation*0.7;
2060    }
2061  } else {
2062    if (event->key() == Qt::Key_Plus) {
2063      fVP.SetZoomFactor(fVP.GetZoomFactor()*(1+fDeltaZoom));
2064      updateQWidget();
2065    }
2066    else if (event->key() == Qt::Key_Minus) {
2067      fVP.SetZoomFactor(fVP.GetZoomFactor()*(1-fDeltaZoom));
2068      updateQWidget();
2069    }
2070  }
2071 
2072 
2073  if (event->key() == Qt::Key_Escape) { // escaped from full screen
2074#if QT_VERSION >= 0x030200
2075      toggleFullScreen(false);
2076#endif
2077  }
2078  // several case here : If return is pressed, in every case -> display the movie parameters dialog
2079  // If one parameter is wrong -> put it in red (only save filenam could be wrong..)
2080  // If encoder not found-> does nothing.Only display a message in status box
2081  // If all ok-> generate parameter file
2082  // If ok -> put encoder button enabled
2083 
2084  if ((event->key() == Qt::Key_Return) || (event->key() == Qt::Key_Enter)){ // end of video
2085   stopVideo();
2086  }
2087  if (event->key() == Qt::Key_Space){ // start/pause of video
2088   startPauseVideo();
2089  }
2090
2091  // with no modifiers
2092#if QT_VERSION < 0x040000
2093  if (event->state() == Qt::NoButton) {
2094#else
2095  if ((event->modifiers() == Qt::NoModifier) || (event->modifiers() == Qt::KeypadModifier )) {
2096#endif
2097    if (event->key() == Qt::Key_Down) { // go down
2098      moveScene(0,1,0,false);
2099    }
2100    else if (event->key() == Qt::Key_Up) {  // go up
2101      moveScene(0,-1,0,false);
2102    }
2103    if (event->key() == Qt::Key_Left) { // go left
2104      moveScene(-1,0,0,false);
2105    }
2106    else if (event->key() == Qt::Key_Right) { // go right
2107      moveScene(1,0,0,false);
2108    }
2109  }
2110  fHoldKeyEvent = false;
2111}
2112 
2113
2114/** Stop the video. Check all parameters and enable encoder button if all is ok.
2115*/
2116void G4OpenGLQtViewer::stopVideo() {
2117
2118 // if encoder parameter is wrong, display parameters dialog and return
2119  if (!fMovieParametersDialog) {
2120    showMovieParametersDialog();
2121  }
2122  setRecordingStatus(STOP);
2123
2124  if (fRecordFrameNumber >0) {
2125    // check parameters if they were modified (Re APPLY them...)
2126    // It will enable/disable encode button
2127    fMovieParametersDialog->checkAllParameters();
2128  } else {
2129    resetRecording();
2130    setRecordingInfos("No frame to encode.");
2131  }
2132}
2133
2134
2135/** Start/Pause the video..
2136*/
2137void G4OpenGLQtViewer::startPauseVideo() {
2138   
2139  // first time, if temp parameter is wrong, display parameters dialog and return
2140  if ( fRecordingStep == WAIT) {
2141    if ( fRecordFrameNumber == 0) {
2142      if (getTempFolderPath() == "") {
2143        showMovieParametersDialog();
2144        setRecordingInfos("You should specified the temp folder in order to make movie");
2145        return;
2146      } else  {
2147        // remove temp folder if it was create
2148        QString tmp = removeTempFolder();
2149        if (tmp !="") {
2150          setRecordingInfos(tmp);
2151          return;
2152        }
2153        tmp = createTempFolder();
2154        if (tmp != "") {
2155          setRecordingInfos("Can't create temp folder."+tmp);
2156          return;
2157        }
2158      }
2159    }
2160  }
2161  if (fRecordingStep == WAIT) {
2162    setRecordingStatus(START);
2163  } else if (fRecordingStep == START) {
2164    setRecordingStatus(PAUSE);
2165  } else if (fRecordingStep == PAUSE) {
2166    setRecordingStatus(CONTINUE);
2167  } else if (fRecordingStep == CONTINUE) {
2168    setRecordingStatus(PAUSE);
2169  }
2170}
2171
2172
2173void G4OpenGLQtViewer::setRecordingStatus(RECORDING_STEP step) {
2174
2175  fRecordingStep = step;
2176  displayRecordingStatus();
2177}
2178
2179
2180void G4OpenGLQtViewer::displayRecordingStatus() {
2181 
2182  QString txt = "";
2183  if (fRecordingStep == WAIT) {
2184    txt  = "Waiting to start...";
2185    fRecordFrameNumber = 0; // reset the frame number
2186  } else if (fRecordingStep == START) {
2187    txt  = "Start Recording...";
2188  } else if (fRecordingStep == PAUSE) {
2189    txt  = "Pause Recording...";
2190  } else if (fRecordingStep == CONTINUE) {
2191    txt  = "Continue Recording...";
2192  } else if (fRecordingStep == STOP) {
2193    txt  = "Stop Recording...";
2194  } else if (fRecordingStep == READY_TO_ENCODE) {
2195    txt  = "Ready to Encode...";
2196  } else if (fRecordingStep == ENCODING) {
2197    txt  = "Encoding...";
2198  } else if (fRecordingStep == FAILED) {
2199    txt  = "Failed to encode...";
2200  } else if (fRecordingStep == SUCCESS) {
2201    txt  = "File encoded successfully";
2202  } else {
2203  }
2204
2205  if (fMovieParametersDialog) {
2206    fMovieParametersDialog->setRecordingStatus(txt);
2207  } else {
2208#if QT_VERSION < 0x040000
2209    G4cout << txt.ascii() << G4endl;
2210#else
2211    G4cout << txt.toStdString().c_str() << G4endl;
2212#endif
2213  }
2214  setRecordingInfos("");
2215}
2216
2217
2218void G4OpenGLQtViewer::setRecordingInfos(QString txt) {
2219  if (fMovieParametersDialog) {
2220    fMovieParametersDialog->setRecordingInfos(txt);
2221  } else {
2222#if QT_VERSION < 0x040000
2223    G4cout << txt.ascii() << G4endl;
2224#else
2225    G4cout << txt.toStdString().c_str() << G4endl;
2226#endif
2227  }
2228}
2229
2230/** Init the movie parameters. Temp dir and encoder path
2231*/
2232void G4OpenGLQtViewer::initMovieParameters() {
2233  //init encoder
2234 
2235   //look for encoderPath
2236     fProcess = new QProcess();
2237     
2238#if QT_VERSION < 0x040000
2239     QObject ::connect(fProcess,SIGNAL(processExited ()),
2240                       this,SLOT(processLookForFinished()));
2241     fProcess->setCommunication(QProcess::DupStderr);
2242     fProcess->setArguments(QStringList("which mpeg_encode"));
2243     fProcess->start();
2244#else
2245     QObject ::connect(fProcess,SIGNAL(finished ( int)),
2246                       this,SLOT(processLookForFinished()));
2247     fProcess->setReadChannelMode(QProcess::MergedChannels);
2248     fProcess->start ("which mpeg_encode");
2249#endif
2250 
2251}
2252
2253/** @return encoder path or "" if it does not exist
2254 */
2255QString G4OpenGLQtViewer::getEncoderPath() {
2256  return fEncoderPath;
2257}
2258 
2259
2260/**
2261 * set the new encoder path
2262 * @return "" if correct. The error otherwise
2263*/
2264QString G4OpenGLQtViewer::setEncoderPath(QString path) {
2265  if (path == "") {
2266    return "File does not exist";
2267  }
2268
2269#if QT_VERSION < 0x040000
2270  path =  QDir::cleanDirPath(path);
2271#else
2272  path =  QDir::cleanPath(path);
2273#endif
2274  QFileInfo *f = new QFileInfo(path);
2275  if (!f->exists()) {
2276    return "File does not exist";
2277  } else if (f->isDir()) {
2278    return "This is a directory";
2279  } else if (!f->isExecutable()) {
2280    return "File exist but is not executable";
2281  } else if (!f->isFile()) {
2282    return "This is not a file";
2283  }
2284  fEncoderPath = path;
2285  return "";
2286}
2287
2288
2289bool G4OpenGLQtViewer::isRecording(){
2290  if ((fRecordingStep == START) || (fRecordingStep == CONTINUE)) {
2291    return true;
2292  }
2293  return false;
2294}
2295
2296bool G4OpenGLQtViewer::isStopped(){
2297  if (fRecordingStep == STOP) {
2298    return true;
2299  }
2300  return false;
2301}
2302
2303
2304bool G4OpenGLQtViewer::isReadyToEncode(){
2305  if (fRecordingStep == READY_TO_ENCODE) {
2306    return true;
2307  }
2308  return false;
2309}
2310
2311void G4OpenGLQtViewer::resetRecording() {
2312    setRecordingStatus(WAIT);
2313}
2314
2315/**
2316 * set the temp folder path
2317 * @return "" if correct. The error otherwise
2318*/
2319QString G4OpenGLQtViewer::setTempFolderPath(QString path) {
2320
2321  if (path == "") {
2322    return "Path does not exist";
2323  }
2324#if QT_VERSION < 0x040000
2325  path =  QDir::cleanDirPath(path);
2326#else
2327  path =  QDir::cleanPath(path);
2328#endif
2329  QFileInfo *d = new QFileInfo(path);
2330  if (!d->exists()) {
2331    return "Path does not exist";
2332  } else if (!d->isDir()) {
2333    return "This is not a directory";
2334  } else if (!d->isReadable()) {
2335    return path +" is read protected";
2336  } else if (!d->isWritable()) {
2337    return path +" is write protected";
2338  }
2339 
2340  fTempFolderPath = path;
2341  return "";
2342}
2343
2344/** @return the temp folder path or "" if it does not exist
2345 */
2346QString G4OpenGLQtViewer::getTempFolderPath() {
2347  return fTempFolderPath;
2348}
2349 
2350/**
2351 * set the save file name path
2352 * @return "" if correct. The error otherwise
2353*/
2354QString G4OpenGLQtViewer::setSaveFileName(QString path) {
2355
2356  if (path == "") {
2357    return "Path does not exist";
2358  }
2359 
2360  QFileInfo *file = new QFileInfo(path);
2361  QDir dir = file->dir();
2362#if QT_VERSION < 0x040000
2363  path =  QDir::cleanDirPath(path);
2364#else
2365  path =  QDir::cleanPath(path);
2366#endif
2367  if (file->exists()) {
2368    return "File already exist, please choose a new one";
2369  } else if (!dir.exists()) {
2370    return "Dir does not exist";
2371  } else if (!dir.isReadable()) {
2372    return path +" is read protected";
2373  }
2374 
2375  fSaveFileName = path;
2376  return "";
2377}
2378
2379/** @return the save file path
2380 */
2381QString G4OpenGLQtViewer::getSaveFileName() {
2382  return fSaveFileName ;
2383}
2384
2385/** Create a Qt_temp folder in the temp folder given
2386* The temp folder will be like this /tmp/QtMovie_12-02-2008_12_12_58/
2387* @return "" if success. Error message if not.
2388*/
2389QString G4OpenGLQtViewer::createTempFolder() {
2390  fMovieTempFolderPath = "";
2391
2392  //check
2393  QString tmp = setTempFolderPath(fTempFolderPath);
2394  if (tmp != "") {
2395    return tmp;
2396  }
2397#if QT_VERSION < 0x040000
2398  QString sep = QChar(QDir::separator());
2399#else
2400  QString sep = QString(QDir::separator());
2401#endif
2402  QString path = sep+"QtMovie_"+QDateTime::currentDateTime ().toString("dd-MM-yyyy_hh-mm-ss")+sep;
2403#if QT_VERSION < 0x040000
2404  QDir *d = new QDir(QDir::cleanDirPath(fTempFolderPath));
2405#else
2406  QDir *d = new QDir(QDir::cleanPath(fTempFolderPath));
2407#endif
2408  // check if it is already present
2409  if (d->exists(path)) {
2410    return "Folder "+path+" already exists.Please remove it first";
2411  }
2412  if (d->mkdir(fTempFolderPath+path)) {
2413    fMovieTempFolderPath = fTempFolderPath+path;
2414    return "";
2415  } else {
2416    return "Can't create "+fTempFolderPath+path;
2417  }
2418  return "-";
2419}
2420
2421/** Remove the Qt_temp folder in the temp folder
2422*/
2423QString G4OpenGLQtViewer::removeTempFolder() {
2424        // remove files in Qt_temp folder
2425  if (fMovieTempFolderPath == "") {
2426    return "";
2427  }
2428#if QT_VERSION < 0x040000
2429  QDir *d = new QDir(QDir::cleanDirPath(fMovieTempFolderPath));
2430#else
2431  QDir *d = new QDir(QDir::cleanPath(fMovieTempFolderPath));
2432#endif
2433  if (!d->exists()) {
2434    return "";  // already remove
2435  }
2436
2437  d->setFilter( QDir::Files );
2438  QStringList subDirList = d->entryList();
2439  int res = true;
2440  QString error = "";
2441  for (QStringList::ConstIterator it = subDirList.begin() ;(it != subDirList.end()) ; it++) {
2442    const QString currentFile = *it;
2443      if (!d->remove(currentFile)) {
2444        res = false;
2445        QString file = fMovieTempFolderPath+currentFile;
2446        error +="Removing file failed : "+file;
2447      } else {
2448      }
2449  }
2450  if (res) {
2451    if (d->rmdir(fMovieTempFolderPath)) {
2452      fMovieTempFolderPath = "";
2453      return "";
2454    } else {
2455      return "Dir "+fMovieTempFolderPath+" should be empty, but could not remove it";
2456    }
2457
2458  }
2459  return "Could not remove "+fMovieTempFolderPath+" because of the following errors :"+error;
2460}
2461
2462
2463
2464bool G4OpenGLQtViewer::hasPendingEvents () {
2465  return ((QApplication*)G4Qt::getInstance ())->hasPendingEvents ();
2466}
2467
2468bool G4OpenGLQtViewer::generateMpegEncoderParameters () {
2469
2470                // save the parameter file
2471  FILE* fp;
2472#if QT_VERSION < 0x040000
2473  fp = fopen (QString(fMovieTempFolderPath+fParameterFileName).ascii(), "w");
2474#else
2475  fp = fopen (QString(fMovieTempFolderPath+fParameterFileName).toStdString().c_str(), "w");
2476#endif
2477
2478  if (fp == NULL) {
2479    setRecordingInfos("Generation of parameter file failed");
2480    return false;
2481  }
2482
2483  fprintf (fp,"# parameter file template with lots of comments to assist you\n");
2484  fprintf (fp,"#\n");
2485  fprintf (fp,"# you can use this as a template, copying it to a separate file then modifying\n");
2486  fprintf (fp,"# the copy\n");
2487  fprintf (fp,"#\n");
2488  fprintf (fp,"#\n");
2489  fprintf (fp,"# any line beginning with '#' is a comment\n");
2490  fprintf (fp,"#\n");
2491  fprintf (fp,"# no line should be longer than 255 characters\n");
2492  fprintf (fp,"#\n");
2493  fprintf (fp,"#\n");
2494  fprintf (fp,"# general format of each line is:\n");
2495  fprintf (fp,"#          \n");
2496  fprintf (fp,"#\n");
2497  fprintf (fp,"# lines can generally be in any order\n");
2498  fprintf (fp,"#\n");
2499  fprintf (fp,"# an exception is the option 'INPUT' which must be followed by input\n");
2500  fprintf (fp,"# files in the order in which they must appear, followed by 'END_INPUT'\n");
2501  fprintf (fp,"#\n");
2502  fprintf (fp,"# Also, if you use the `command` method of generating input file names,\n");
2503  fprintf (fp,"# the command will only be executed in the INPUT_DIR if INPUT_DIR preceeds\n");
2504  fprintf (fp,"# the INPUT parameter.\n");
2505  fprintf (fp,"#\n");
2506  fprintf (fp,"#  MUST be in UPPER CASE\n");
2507  fprintf (fp,"#\n");
2508  fprintf (fp,"\n");
2509  fprintf (fp,"# Pattern affects speed, quality and compression. See the User's Guide\n");
2510  fprintf (fp,"# for more info.\n");
2511  fprintf (fp,"\n");
2512  fprintf (fp,"PATTERN          IBBPBBPBBPBBPBBP\n");
2513#if QT_VERSION < 0x040000
2514  fprintf (fp,"OUTPUT           %s\n",getSaveFileName().ascii());
2515#else
2516  fprintf (fp,"OUTPUT           %s\n",getSaveFileName().toStdString().c_str());
2517#endif
2518  fprintf (fp,"\n");
2519  fprintf (fp,"# mpeg_encode really only accepts 3 different file formats, but using a\n");
2520  fprintf (fp,"# conversion statement it can effectively handle ANY file format\n");
2521  fprintf (fp,"#\n");
2522  fprintf (fp,"# You must specify the type of the input files.  The choices are:\n");
2523  fprintf (fp,"#    YUV, PPM, JMOVIE, Y, JPEG, PNM\n");
2524  fprintf (fp,"#        (must be upper case)\n");
2525  fprintf (fp,"#\n");
2526  fprintf (fp,"BASE_FILE_FORMAT PPM\n");
2527  fprintf (fp,"\n");
2528  fprintf (fp,"#\n");
2529  fprintf (fp,"# if YUV format (or using parallel version), must provide width and height\n");
2530  fprintf (fp,"# YUV_SIZE       widthxheight\n");
2531  fprintf (fp,"# this option is ignored if BASE_FILE_FORMAT is not YUV and you're running\n");
2532  fprintf (fp,"# on just one machine\n");
2533  fprintf (fp,"#\n");
2534  fprintf (fp,"YUV_SIZE 352x240\n");
2535  fprintf (fp,"\n");
2536  fprintf (fp,"# If you are using YUV, there are different supported file formats.\n");
2537  fprintf (fp,"# EYUV or UCB are the same as previous versions of this encoder.\n");
2538  fprintf (fp,"# (All the Y's, then U's then V's, in 4:2:0 subsampling.)\n");
2539  fprintf (fp,"# Other formats, such as Abekas, Phillips, or a general format are\n");
2540  fprintf (fp,"# permissible, the general format is a string of Y's, U's, and V's\n");
2541  fprintf (fp,"# to specify the file order.\n");
2542  fprintf (fp,"\n");
2543  fprintf (fp,"INPUT_FORMAT UCB\n");
2544  fprintf (fp,"\n");
2545  fprintf (fp,"# the conversion statement\n");
2546  fprintf (fp,"#\n");
2547  fprintf (fp,"# Each occurrence of '*' will be replaced by the input file\n");
2548  fprintf (fp,"#\n");
2549  fprintf (fp,"# e.g., if you have a bunch of GIF files, then this might be:\n");
2550  fprintf (fp,"#        INPUT_CONVERT   giftoppm *\n");
2551  fprintf (fp,"#\n");
2552  fprintf (fp,"# e.g., if you have a bunch of files like a.Y a.U a.V, etc., then:\n");
2553  fprintf (fp,"#        INPUT_CONVERT   cat *.Y *.U *.V\n");
2554  fprintf (fp,"#\n");
2555  fprintf (fp,"# e.g., if you are grabbing from laser disc you might have something like\n");
2556  fprintf (fp,"#        INPUT_CONVERT   goto frame *; grabppm\n");
2557  fprintf (fp,"# 'INPUT_CONVERT *' means the files are already in the base file format\n");
2558  fprintf (fp,"#\n");
2559  fprintf (fp,"INPUT_CONVERT    * \n");
2560  fprintf (fp,"\n");
2561  fprintf (fp,"# number of frames in a GOP.\n");
2562  fprintf (fp,"#\n");
2563  fprintf (fp,"# since each GOP must have at least one I-frame, the encoder will find the\n");
2564  fprintf (fp,"# the first I-frame after GOP_SIZE frames to start the next GOP\n");
2565  fprintf (fp,"#\n");
2566  fprintf (fp,"# later, will add more flexible GOP signalling\n");
2567  fprintf (fp,"#\n");
2568  fprintf (fp,"GOP_SIZE 16\n");
2569  fprintf (fp,"\n");
2570  fprintf (fp,"# number of slices in a frame\n");
2571  fprintf (fp,"#\n");
2572  fprintf (fp,"# 1 is a good number.  another possibility is the number of macroblock rows\n");
2573  fprintf (fp,"# (which is the height divided by 16)\n");
2574  fprintf (fp,"#\n");
2575  fprintf (fp,"SLICES_PER_FRAME 1\n");
2576  fprintf (fp,"\n");
2577  fprintf (fp,"# directory to get all input files from (makes this file easier to read)\n");
2578#if QT_VERSION < 0x040000
2579  fprintf (fp,"INPUT_DIR        %s\n",fMovieTempFolderPath.ascii());
2580#else
2581  fprintf (fp,"INPUT_DIR        %s\n",fMovieTempFolderPath.toStdString().c_str());
2582#endif
2583  fprintf (fp,"\n");
2584  fprintf (fp,"# There are a bunch of ways to specify the input files.\n");
2585  fprintf (fp,"# from a simple one-per-line listing, to the following \n");
2586  fprintf (fp,"# way of numbering them.  See the manual for more information.\n");
2587  fprintf (fp,"INPUT\n");
2588  fprintf (fp,"# '*' is replaced by the numbers 01, 02, 03, 04\n");
2589  fprintf (fp,"# if I instead do [01-11], it would be 01, 02, ..., 09, 10, 11\n");
2590  fprintf (fp,"# if I instead do [1-11], it would be 1, 2, 3, ..., 9, 10, 11\n");
2591  fprintf (fp,"# if I instead do [1-11+3], it would be 1, 4, 7, 10\n");
2592  fprintf (fp,"# the program assumes none of your input files has a name ending in ']'\n");
2593  fprintf (fp,"# if you do, too bad!!!\n");
2594  fprintf (fp,"#\n");
2595  fprintf (fp,"#\n");
2596  fprintf (fp,"Test*.ppm        [0-%d]\n",fRecordFrameNumber-1);
2597  fprintf (fp,"# can have more files here if you want...there is no limit on the number\n");
2598  fprintf (fp,"# of files\n");
2599  fprintf (fp,"END_INPUT\n");
2600  fprintf (fp,"\n");
2601  fprintf (fp,"\n");
2602  fprintf (fp,"\n");
2603  fprintf (fp,"# Many of the remaining options have to do with the motion search and qscale\n");
2604  fprintf (fp,"\n");
2605  fprintf (fp,"# FULL or HALF -- must be upper case\n");
2606  fprintf (fp,"# Should be FULL for computer generated images\n");
2607  fprintf (fp,"PIXEL            FULL\n");
2608  fprintf (fp,"\n");
2609  fprintf (fp,"# means +/- this many pixels for both P and B frame searches\n");
2610  fprintf (fp,"# specify two numbers if you wish to serc different ranges in the two.\n");
2611  fprintf (fp,"RANGE            10\n");
2612  fprintf (fp,"\n");
2613  fprintf (fp,"# The two search algorithm parameters below mostly affect speed,\n");
2614  fprintf (fp,"# with some affect on compression and almost none on quality.\n");
2615  fprintf (fp,"\n");
2616  fprintf (fp,"# this must be one of {EXHAUSTIVE, SUBSAMPLE, LOGARITHMIC}\n");
2617  fprintf (fp,"PSEARCH_ALG      LOGARITHMIC\n");
2618  fprintf (fp,"\n");
2619  fprintf (fp,"# this must be one of {SIMPLE, CROSS2, EXHAUSTIVE}\n");
2620  fprintf (fp,"#\n");
2621  fprintf (fp,"# note that EXHAUSTIVE is really, really, really slow\n");
2622  fprintf (fp,"#\n");
2623  fprintf (fp,"BSEARCH_ALG      SIMPLE\n");
2624  fprintf (fp,"\n");
2625  fprintf (fp,"#\n");
2626  fprintf (fp,"# these specify the q-scale for I, P, and B frames\n");
2627  fprintf (fp,"# (values must be between 1 and 31)\n");
2628  fprintf (fp,"# These are the Qscale values for the entire frame in variable bit-rate\n");
2629  fprintf (fp,"# mode, and starting points (but not important) for constant bit rate\n");
2630  fprintf (fp,"#\n");
2631  fprintf (fp,"\n");
2632  fprintf (fp,"# Qscale (Quantization scale) affects quality and compression,\n");
2633  fprintf (fp,"# but has very little effect on speed.\n");
2634  fprintf (fp,"\n");
2635  fprintf (fp,"IQSCALE          4\n");
2636  fprintf (fp,"PQSCALE          5\n");
2637  fprintf (fp,"BQSCALE          12\n");
2638  fprintf (fp,"\n");
2639  fprintf (fp,"# this must be ORIGINAL or DECODED\n");
2640  fprintf (fp,"REFERENCE_FRAME  ORIGINAL\n");
2641  fprintf (fp,"\n");
2642  fprintf (fp,"# for parallel parameters see parallel.param in the exmaples subdirectory\n");
2643  fprintf (fp,"\n");
2644  fprintf (fp,"# if you want constant bit-rate mode, specify it as follows (number is bits/sec):\n");
2645  fprintf (fp,"#BIT_RATE  1000000\n");
2646  fprintf (fp,"\n");
2647  fprintf (fp,"# To specify the buffer size (327680 is default, measused in bits, for 16bit words)\n");
2648  fprintf (fp,"BUFFER_SIZE 327680\n");
2649  fprintf (fp,"\n");
2650  fprintf (fp,"# The frame rate is the number of frames/second (legal values:\n");
2651  fprintf (fp,"# 23.976, 24, 25, 29.97, 30, 50 ,59.94, 60\n");
2652  fprintf (fp,"FRAME_RATE 30\n");
2653  fprintf (fp,"\n");
2654  fprintf (fp,"# There are many more options, see the users manual for examples....\n");
2655  fprintf (fp,"# ASPECT_RATIO, USER_DATA, GAMMA, IQTABLE, etc.\n");
2656  fprintf (fp,"\n");
2657  fprintf (fp,"\n");
2658  fclose (fp);
2659
2660  setRecordingInfos("Parameter file "+fParameterFileName+" generated in "+fMovieTempFolderPath);
2661  setRecordingStatus(READY_TO_ENCODE);
2662  return true;
2663}
2664
2665void G4OpenGLQtViewer::encodeVideo()
2666{
2667  if ((getEncoderPath() != "") && (getSaveFileName() != "")) {
2668    setRecordingStatus(ENCODING);
2669   
2670#if QT_VERSION < 0x040000
2671    QStringList args = QStringList(fEncoderPath);
2672    args.push_back(fMovieTempFolderPath+fParameterFileName);
2673    fProcess = new QProcess(args);
2674    QObject ::connect(fProcess,SIGNAL(processExited ()),
2675                      this,SLOT(processEncodeFinished()));
2676    QObject ::connect(fProcess,SIGNAL(readyReadStdout ()),
2677                      this,SLOT(processEncodeStdout()));
2678    fProcess->setCommunication(QProcess::DupStderr);
2679    fProcess->launch("");
2680#else
2681    fProcess = new QProcess();
2682#if QT_VERSION > 0x040100
2683    QObject ::connect(fProcess,SIGNAL(finished ( int,QProcess::ExitStatus)),
2684                      this,SLOT(processEncodeFinished()));
2685    QObject ::connect(fProcess,SIGNAL(readyReadStandardOutput ()),
2686                      this,SLOT(processEncodeStdout()));
2687#else
2688    QObject ::connect(fProcess,SIGNAL(finished ( int)),
2689                      this,SLOT(processEncodeFinished()));
2690    QObject ::connect(fProcess,SIGNAL(readyReadStandardOutput ()),
2691                      this,SLOT(processEncodeStdout()));
2692#endif
2693    fProcess->setReadChannelMode(QProcess::MergedChannels);
2694    fProcess->start (fEncoderPath, QStringList(fMovieTempFolderPath+fParameterFileName));
2695#endif
2696  }
2697}
2698
2699
2700// FIXME : does not work on Qt3
2701void G4OpenGLQtViewer::processEncodeStdout()
2702{
2703#if QT_VERSION > 0x040000
2704  QString tmp = fProcess->readAllStandardOutput ().data();
2705  int start = tmp.lastIndexOf("ESTIMATED TIME");
2706  tmp = tmp.mid(start,tmp.indexOf("\n",start)-start);
2707#else
2708  QString tmp = fProcess->readStdout ().data();
2709  int start = tmp.findRev("ESTIMATED TIME");
2710  tmp = tmp.mid(start,tmp.find("\n",start)-start);
2711#endif
2712  setRecordingInfos(tmp);
2713}
2714
2715
2716void G4OpenGLQtViewer::processEncodeFinished()
2717{
2718
2719  QString txt = "";
2720  txt = getProcessErrorMsg();
2721  if (txt == "") {
2722    setRecordingStatus(SUCCESS);
2723  } else {
2724    setRecordingStatus(FAILED);
2725  }
2726  setRecordingInfos(txt+removeTempFolder());
2727}
2728
2729
2730void G4OpenGLQtViewer::processLookForFinished()
2731 {
2732
2733  QString txt = getProcessErrorMsg();
2734  if (txt != "") {
2735    fEncoderPath = "";
2736  } else {
2737#if QT_VERSION > 0x040000
2738    fEncoderPath = QString(fProcess->readAllStandardOutput ().data()).trimmed();
2739#else
2740    fEncoderPath = QString(fProcess->readStdout ().data()).simplifyWhiteSpace();
2741#endif
2742    // if not found, return "not found"
2743    if (fEncoderPath.contains(" ")) {
2744      fEncoderPath = "";
2745    } else if (!fEncoderPath.contains("mpeg_encode")) {
2746      fEncoderPath = "";
2747    }
2748    setEncoderPath(fEncoderPath);
2749  }
2750  // init temp folder
2751#if QT_VERSION > 0x040000
2752  setTempFolderPath(QDir::temp ().absolutePath ());
2753#else
2754  // Let's have a try
2755  setTempFolderPath("/tmp/");
2756#endif
2757}
2758
2759
2760QString G4OpenGLQtViewer::getProcessErrorMsg()
2761{
2762  QString txt = "";
2763#if QT_VERSION < 0x040000
2764  if (!fProcess->normalExit ()) {
2765    txt = "Exist status "+ fProcess->exitStatus ();
2766  }
2767#else
2768  if (fProcess->exitCode() != 0) {
2769    switch (fProcess->error()) {
2770    case QProcess::FailedToStart:
2771      txt = "The process failed to start. Either the invoked program is missing, or you may have insufficient permissions to invoke the program.\n";
2772      break;
2773    case QProcess::Crashed:
2774      txt = "The process crashed some time after starting successfully.\n";
2775      break;
2776    case QProcess::Timedout:
2777      txt = "The last waitFor...() function timed out. The state of QProcess is unchanged, and you can try calling waitFor...() again.\n";
2778      break;
2779    case QProcess::WriteError:
2780      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";
2781      break;
2782    case QProcess::ReadError:
2783      txt = "An error occurred when attempting to read from the process. For example, the process may not be running.\n";
2784      break;
2785    case QProcess::UnknownError:
2786      txt = "An unknown error occurred. This is the default return value of error().\n";
2787      break;
2788    }
2789  }
2790#endif
2791   return txt;
2792}
2793
2794/*
2795 
2796void MultiLayer::exportToSVG(const QString& fname)
2797{
2798  QPicture picture;
2799  QPainter p(&picture);
2800  for (int i=0;i<(int)graphsList->count();i++)
2801    {
2802      Graph *gr=(Graph *)graphsList->at(i);
2803      Plot *myPlot= (Plot *)gr->plotWidget();
2804     
2805      QPoint pos=gr->pos();
2806     
2807      int width=int(myPlot->frameGeometry().width());
2808      int height=int(myPlot->frameGeometry().height());
2809     
2810      myPlot->print(&p, QRect(pos,QSize(width,height)));
2811    }
2812 
2813  p.end();
2814  picture.save(fname, "svg");
2815}
2816*/
2817#endif
Note: See TracBrowser for help on using the repository browser.