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

Last change on this file since 908 was 908, checked in by garnier, 15 years ago

update with CVS

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