source: trunk/source/visualization/OpenGL/src/G4OpenGLQtViewer.cc~ @ 1350

Last change on this file since 1350 was 1350, checked in by garnier, 13 years ago

update to last version 4.9.4

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