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

Last change on this file since 843 was 843, checked in by garnier, 17 years ago

Add some signals

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