source: trunk/geant4/visualization/OpenGL/src/G4OpenGLQtViewer.cc @ 804

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

r846@wl-72126: garnier | 2008-05-29 12:20:22 +0200
prise en compte de la roulette de souris

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