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

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

r836@wl-72126: garnier | 2008-05-15 14:34:32 +0200
en test

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