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

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

print improvments begin, see History file

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