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

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

Update in code, try to mutualise everything between Stored and immediate Qt Viewers

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