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

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

suppres des debug et modif des WinSize

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