Developer Documentation
QtBaseViewer_qt.cc
1 /*===========================================================================*\
2  * *
3  * OpenFlipper *
4  * Copyright (c) 2001-2015, RWTH-Aachen University *
5  * Department of Computer Graphics and Multimedia *
6  * All rights reserved. *
7  * www.openflipper.org *
8  * *
9  *---------------------------------------------------------------------------*
10  * This file is part of OpenFlipper. *
11  *---------------------------------------------------------------------------*
12  * *
13  * Redistribution and use in source and binary forms, with or without *
14  * modification, are permitted provided that the following conditions *
15  * are met: *
16  * *
17  * 1. Redistributions of source code must retain the above copyright notice, *
18  * this list of conditions and the following disclaimer. *
19  * *
20  * 2. Redistributions in binary form must reproduce the above copyright *
21  * notice, this list of conditions and the following disclaimer in the *
22  * documentation and/or other materials provided with the distribution. *
23  * *
24  * 3. Neither the name of the copyright holder nor the names of its *
25  * contributors may be used to endorse or promote products derived from *
26  * this software without specific prior written permission. *
27  * *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39  * *
40 \*===========================================================================*/
41 
42 
43 
44 
45 
46 //=============================================================================
47 //
48 // CLASS QtBaseViewer - IMPLEMENTATION
49 //
50 //=============================================================================
51 
52 
53 //== INCLUDES =================================================================
54 
55 #include "QtBaseViewer.hh"
56 #include "QtGLGraphicsScene.hh"
57 #include "QtGLGraphicsView.hh"
58 //#include "QtSceneGraphWidget.hh"
59 #include "QtWheel.hh"
60 
61 #include <QMimeData>
62 #include <QToolButton>
63 
64 #include <QClipboard>
65 #include <QApplication>
66 #include <QPushButton>
67 #include <QStatusBar>
68 #include <QColorDialog>
69 #include <QFileDialog>
70 #include <QTimer>
71 
72 #include <QGLFormat>
73 #include <QGLWidget>
74 
75 #include <QDesktopWidget>
76 #include <QButtonGroup>
77 
78 #include <QGraphicsWidget>
79 #include <QGraphicsGridLayout>
80 #include <QGraphicsProxyWidget>
81 
82 #include "move.xpm"
83 #include "light.xpm"
84 #include "info.xpm"
85 #include "home.xpm"
86 #include "set_home.xpm"
87 #include "viewall.xpm"
88 #include "pick.xpm"
89 #include "persp.xpm"
90 #include "ortho.xpm"
91 #include "scenegraph.xpm"
92 #include "mono.xpm"
93 
94 
95 #define homeIcon home_xpm
96 #define sethomeIcon set_home_xpm
97 #define moveIcon move_xpm
98 #define lightIcon light_xpm
99 #define questionIcon info_xpm
100 #define viewallIcon viewall_xpm
101 #define pickIcon pick_xpm
102 #define perspectiveIcon persp_xpm
103 #define orthoIcon ortho_xpm
104 #define sceneGraphIcon scenegraph_xpm
105 #define monoIcon mono_xpm
106 
107 
108 #ifdef max
109 # undef max
110 #endif
111 
112 #ifdef min
113 # undef min
114 #endif
115 
116 
117 //== NAMESPACES ===============================================================
118 
119 namespace ACG {
120 namespace QtWidgets {
121 
122 
123 //== IMPLEMENTATION ==========================================================
124 
125 static const char VIEW_MAGIC[] =
126  "ACG::QtWidgets::QGLViewerWidget encoded view";
127 
128 //== IMPLEMENTATION ==========================================================
129 
130 
132  glWidget_->makeCurrent();
133 }
134 
136  glWidget_->swapBuffers();
137 }
138 
139 
140 
141 void
143  unsigned int /* _l */ , unsigned int /* _t */ ,
144  unsigned int /* _w */ , unsigned int /* _h */ ,
145  GLenum /* _buffer */ )
146 {
147  makeCurrent();
148  _image = glWidget_->grabFrameBuffer(true);
149 }
150 
151 
152 void
153 QtBaseViewer::createWidgets(const QGLFormat* _format,
154  QStatusBar* _sb,
155  const QtBaseViewer* _share)
156 {
157  statusbar_=privateStatusBar_=0;
158  setStatusBar(_sb);
159  drawMenu_=0;
160  funcMenu_=0;
161  pickMenu_=0;
162 
163 
164  // contains splitter and eventually status bar
165  // QT3: Q3VBoxLayout* layout=new Q3VBoxLayout(this,0,0,"toplevel layout");
166  QVBoxLayout* layout=new QVBoxLayout(this);
167  layout->setSpacing( 0 );
168  layout->setMargin( 0 );
169 
170  // contains glarea and buttons
171 
172  // QT3: Q3Frame* work=new Q3Frame(this,"box-glarea-buttons");
173  QFrame* work=new QFrame(this);
174 
175  layout->addWidget(work,1); // gets all stretch
176 
177 
178  // private status bar
179  assert(statusbar_!=0);
180  if (privateStatusBar_!=0)
181  layout->addWidget(privateStatusBar_,0); // no stretch
182 
183 
184  // Construct GL context & widget
185  QGLWidget* share = 0;
186  if (_share) share = _share->glWidget_;
187 
188  QGLFormat format;
189  format.setAlpha(true);
190  if (_format!=0) format = *_format;
191 
192  glWidget_ = new QGLWidget(format, 0, share);
193  glView_ = new QtGLGraphicsView(this, work);
194  glScene_ = new QtGLGraphicsScene (this);
195 
196  glView_->setViewport(glWidget_);
197  glView_->setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
198  glView_->setScene(glScene_);
199  glView_->setFrameStyle(QFrame::NoFrame);
200 
201  wheelZ_=new QtWheel( 0,"wheel-z",QtWheel::Vertical);
202  wheelZ_->setMinimumSize(wheelZ_->sizeHint());
203  wheelZ_->setMaximumSize(wheelZ_->sizeHint());
204  connect(wheelZ_,SIGNAL(angleChangedBy(double)),
205  this,SLOT(slotWheelZ(double)));
206  wheelZ_->setToolTip( "Translate along <b>z-axis</b>.");
207  wheelZ_->setWhatsThis( "Translate along <b>z-axis</b>.");
208  if ((options_&ShowWheelZ)==0)
209  wheelZ_->hide();
210 
211  wheelY_=new QtWheel( 0,"wheel-y",QtWheel::Horizontal);
212  wheelY_->setMinimumSize(wheelY_->sizeHint());
213  wheelY_->setMaximumSize(wheelY_->sizeHint());
214  connect(wheelY_,SIGNAL(angleChangedBy(double)),
215  this,SLOT(slotWheelY(double)));
216  wheelY_->setToolTip("Rotate around <b>y-axis</b>.");
217  wheelY_->setWhatsThis( "Rotate around <b>y-axis</b>.");
218  if ((options_&ShowWheelY)==0)
219  wheelY_->hide();
220 
221  wheelX_=new QtWheel( 0,"wheel-x",QtWheel::Vertical);
222  wheelX_->setMinimumSize(wheelX_->sizeHint());
223  wheelX_->setMaximumSize(wheelX_->sizeHint());
224  connect(wheelX_,SIGNAL(angleChangedBy(double)),
225  this,SLOT(slotWheelX(double)));
226  wheelX_->setToolTip("Rotate around <b>x-axis</b>.");
227  wheelX_->setWhatsThis( "Rotate around <b>x-axis</b>.");
228  if ((options_&ShowWheelX)==0)
229  wheelX_->hide();
230 
231 
232  QGraphicsWidget *wheelX = glScene_->addWidget (wheelX_);
233  QGraphicsWidget *wheelY = glScene_->addWidget (wheelY_);
234  QGraphicsWidget *wheelZ = glScene_->addWidget (wheelZ_);
235 
236  wheelX_->setWindowOpacity (0.5);
237  wheelY_->setWindowOpacity (0.5);
238  wheelZ_->setWindowOpacity (0.5);
239 
240  wheelX->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
241  wheelY->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
242  wheelZ->setCacheMode(QGraphicsItem::DeviceCoordinateCache);
243 
244  glBaseLayout_ = new QGraphicsGridLayout;
245  glBaseLayout_->addItem(wheelX, 1, 0);
246  glBaseLayout_->addItem(wheelY, 2, 1);
247  glBaseLayout_->addItem(wheelZ, 1, 3);
248 
249  glBaseLayout_->setColumnStretchFactor(0,0);
250  glBaseLayout_->setColumnStretchFactor(1,0);
251  glBaseLayout_->setColumnStretchFactor(2,1);
252  glBaseLayout_->setColumnStretchFactor(3,0);
253 
254  glBaseLayout_->setRowStretchFactor(0,1);
255  glBaseLayout_->setRowStretchFactor(1,0);
256  glBaseLayout_->setRowStretchFactor(2,0);
257 
258  glBase_ = new QGraphicsWidget;
259  glBase_->setLayout(glBaseLayout_);
260  glScene_->addItem(glBase_);
261  glBase_->setGeometry (glScene_->sceneRect ());
262  //QRectF r = glScene_->sceneRect ();
263 
264  connect ( glScene_, SIGNAL( sceneRectChanged( const QRectF & ) ),
265  this, SLOT( sceneRectChanged( const QRectF & ) ) );
266 
267  // If popupEnabled_ this signal will not be emitted!
268  // If popupEnabled_ is set to false the Contextmenu Mode will be set to customContextMenuRequested
269  // and this signal will be emitted on right click
270  connect( glView_ , SIGNAL( customContextMenuRequested( const QPoint& ) ) ,
271  this , SIGNAL( signalCustomContextMenuRequested( const QPoint& ) ) );
272 
273  // is stereo possible ?
274  if (format.stereo())
275  std::cerr << "Stereo buffer requested: "
276  << (glWidget_->format().stereo() ? "ok\n" : "failed\n");
277 
278 
279  // toolbar
280  buttonBar_= new QToolBar( "Viewer Toolbar", work );
281  buttonBar_->setOrientation(Qt::Vertical);
282 
283  moveButton_ = new QToolButton( buttonBar_ );
284  moveButton_->setIcon( QPixmap(moveIcon) );
285  moveButton_->setMinimumSize( 16, 16 );
286  moveButton_->setMaximumSize( 32, 32 );
287  moveButton_->setToolTip( "Switch to <b>move</b> mode." );
288  moveButton_->setWhatsThis(
289  "Switch to <b>move</b> mode.<br>"
290  "<ul><li><b>Rotate</b> using <b>left</b> mouse button.</li>"
291  "<li><b>Translate</b> using <b>middle</b> mouse button.</li>"
292  "<li><b>Zoom</b> using <b>left+middle</b> mouse buttons.</li></ul>" );
293  QObject::connect( moveButton_, SIGNAL( clicked() ),
294  this, SLOT( examineMode() ) );
295 
296  buttonBar_->addWidget( moveButton_)->setText("Move");
297 
298  lightButton_ = new QToolButton( buttonBar_ );
299  lightButton_->setIcon( QPixmap(lightIcon) );
300  lightButton_->setMinimumSize( 16, 16 );
301  lightButton_->setMaximumSize( 32, 32 );
302  lightButton_->setToolTip("Switch to <b>light</b> mode.");
303  lightButton_->setWhatsThis(
304  "Switch to <b>light</b> mode.<br>"
305  "Rotate lights using left mouse button.");
306  QObject::connect( lightButton_, SIGNAL( clicked() ),
307  this, SLOT( lightMode() ) );
308  buttonBar_->addWidget( lightButton_)->setText("Light");
309 
310 
311  pickButton_ = new QToolButton( buttonBar_ );
312  pickButton_->setIcon( QPixmap(pickIcon) );
313  pickButton_->setMinimumSize( 16, 16 );
314  pickButton_->setMaximumSize( 32, 32 );
315  pickButton_->setToolTip("Switch to <b>picking</b> mode.");
316  pickButton_->setWhatsThis(
317  "Switch to <b>picking</b> mode.<br>"
318  "Use picking functions like flipping edges.<br>"
319  "To change the mode use the right click<br>"
320  "context menu in the viewer.");
321  QObject::connect( pickButton_, SIGNAL( clicked() ),
322  this, SLOT( pickingMode() ) );
323  buttonBar_->addWidget( pickButton_)->setText("Pick");
324 
325 
326  questionButton_ = new QToolButton( buttonBar_ );
327  questionButton_->setIcon( QPixmap(questionIcon) );
328  questionButton_->setMinimumSize( 16, 16 );
329  questionButton_->setMaximumSize( 32, 32 );
330  questionButton_->setToolTip("Switch to <b>identification</b> mode.");
331  questionButton_->setWhatsThis(
332  "Switch to <b>identification</b> mode.<br>"
333  "Use identification mode to get information "
334  "about objects. Click on an object and see "
335  "the log output for information about the "
336  "object.");
337  QObject::connect( questionButton_, SIGNAL( clicked() ),
338  this, SLOT( questionMode() ) );
339  buttonBar_->addWidget( questionButton_)->setText("Question");
340 
341  buttonBar_->addSeparator();
342 
343  homeButton_ = new QToolButton( buttonBar_ );
344  homeButton_->setIcon( QPixmap(homeIcon) );
345  homeButton_->setMinimumSize( 16, 16 );
346  homeButton_->setMaximumSize( 32, 32 );
347  homeButton_->setCheckable( false );
348  homeButton_->setToolTip("Restore <b>home</b> view.");
349  homeButton_->setWhatsThis(
350  "Restore home view<br><br>"
351  "Resets the view to the home view");
352  QObject::connect( homeButton_, SIGNAL( clicked() ),
353  this, SLOT( home() ) );
354  buttonBar_->addWidget( homeButton_)->setText("Home");
355 
356 
357  setHomeButton_ = new QToolButton( buttonBar_ );
358  setHomeButton_->setIcon( QPixmap(sethomeIcon) );
359  setHomeButton_->setMinimumSize( 16, 16 );
360  setHomeButton_->setMaximumSize( 32, 32 );
361  setHomeButton_->setCheckable( false );
362  setHomeButton_->setToolTip("Set <b>home</b> view");
363  setHomeButton_->setWhatsThis(
364  "Store home view<br><br>"
365  "Stores the current view as the home view");
366  QObject::connect( setHomeButton_, SIGNAL( clicked() ),
367  this, SLOT( setHome() ) );
368  buttonBar_->addWidget( setHomeButton_)->setText("Set Home");
369 
370 
371  viewAllButton_ = new QToolButton( buttonBar_ );
372  viewAllButton_->setIcon( QPixmap(viewallIcon) );
373  viewAllButton_->setMinimumSize( 16, 16 );
374  viewAllButton_->setMaximumSize( 32, 32 );
375  viewAllButton_->setCheckable( false );
376  viewAllButton_->setToolTip("View all.");
377  viewAllButton_->setWhatsThis(
378  "View all<br><br>"
379  "Move the objects in the scene so that"
380  " the whole scene is visible.");
381  QObject::connect( viewAllButton_, SIGNAL( clicked() ),
382  this, SLOT( viewAll() ) );
383  buttonBar_->addWidget( viewAllButton_)->setText("View all");
384 
385 
386  projectionButton_ = new QToolButton( buttonBar_ );
387  projectionButton_->setIcon( QPixmap(perspectiveIcon) );
388  projectionButton_->setMinimumSize( 16, 16 );
389  projectionButton_->setMaximumSize( 32, 32 );
390  projectionButton_->setCheckable( false );
391  projectionButton_->setToolTip(
392  "Switch between <b>perspective</b> and "
393  "<b>parrallel</b> projection mode.");
394  projectionButton_->setWhatsThis(
395  "Switch projection modes<br><br>"
396  "Switch between <b>perspective</b> and "
397  "<b>parrallel</b> projection mode.");
398  QObject::connect( projectionButton_, SIGNAL( clicked() ),
399  this, SLOT( toggleProjectionMode() ) );
400  buttonBar_->addWidget( projectionButton_)->setText( "Projection" );
401 
402 
403  if (glWidget_->format().stereo())
404  {
405  stereoButton_ = new QToolButton( buttonBar_ );
406  stereoButton_->setIcon( QPixmap(monoIcon) );
407  stereoButton_->setMinimumSize( 16, 16 );
408  stereoButton_->setMaximumSize( 32, 32 );
409  stereoButton_->setCheckable( true );
410  stereoButton_->setToolTip( "Toggle stereo viewing");
411  stereoButton_->setWhatsThis(
412  "Toggle stereo mode<br><br>"
413  "Use this button to switch between stereo "
414  "and mono view. To use this feature you need "
415  "a stereo capable graphics card and a stereo "
416  "display/projection system.");
417  QObject::connect( stereoButton_, SIGNAL( clicked() ),
418  this, SLOT( toggleStereoMode() ) );
419  buttonBar_->addWidget( stereoButton_)->setText( "Stereo");
420  }
421 
422  buttonBar_->addSeparator();
423 
424  sceneGraphButton_ = new QToolButton( buttonBar_ );
425  sceneGraphButton_->setIcon( QPixmap(sceneGraphIcon) );
426  sceneGraphButton_->setMinimumSize( 16, 16 );
427  sceneGraphButton_->setMaximumSize( 32, 32 );
428  sceneGraphButton_->setCheckable( false );
429  sceneGraphButton_->setToolTip("Toggle scene graph viewer.");
430  sceneGraphButton_->setWhatsThis(
431  "Toggle scene graph viewer<br><br>"
432  "The scene graph viewer enables you to examine the "
433  "displayed scene graph and to modify certain nodes.<br><br>"
434  "There are three modi for the scene graph viewer:"
435  "<ul><li><b>hidden</b></li>"
436  "<li><b>split</b>: share space</li>"
437  "<li><b>dialog</b>: own dialog window</li></ul>"
438  "This button toggles between these modi.");
439  QObject::connect( sceneGraphButton_, SIGNAL( clicked() ),
440  this, SLOT( showSceneGraphDialog() ) );
441  buttonBar_->addWidget( sceneGraphButton_)->setText( "SceneGraph" );
442 
443  glLayout_ = new QGridLayout(work);
444  glLayout_->setSpacing( 0 );
445  glLayout_->setMargin( 0 );
446 
447  glLayout_->addWidget(glView_, 0,0);
448  glLayout_->addWidget(buttonBar_, 0,1);
449 
450  glLayout_->setColumnStretch(0,1);
451  glLayout_->setColumnStretch(1,0);
452 
453  if (!(options_ & ShowToolBar))
454  buttonBar_->hide();
455 
456 }
457 
458 bool QtBaseViewer::hasOpenGL()
459 {
460  return QGLFormat::hasOpenGL();
461 }
462 
463 //=============================================================================
464 } // namespace QtWidgets
465 } // namespace ACG
466 //=============================================================================
virtual void showSceneGraphDialog()
show scenegraph widget
Namespace providing different geometric functions concerning angles.
Show wheel for rotation around y-axis (bottom)?
virtual QSize sizeHint() const
reimplemented
Definition: QtWheel.cc:425
virtual void slotWheelX(double _dAngle)
process signals from wheelX_
void signalCustomContextMenuRequested(const QPoint &)
virtual void swapBuffers()
Swaps the screen contents with the off-screen buffer.
Show wheel for rotation around x-axis (left)?
virtual void toggleProjectionMode()
toggle projection mode
virtual void slotWheelZ(double _dist)
process signals from wheelZ_
virtual void viewAll()
view the whole scene
void copyToImage(QImage &_image, GLenum _buffer=GL_BACK)
copy current framebuffer to an QImage
virtual void questionMode()
calls actionMode() with QuestionMode (cf. ActionMode)
virtual void lightMode()
calls actionMode() with LightMode (cf. ActionMode)
virtual void setHome()
set home position
virtual void makeCurrent()
Makes this widget the current widget for OpenGL operations.
virtual void toggleStereoMode()
toggle stereo mode
virtual void examineMode()
calls actionMode() with ExamineMode (cf. ActionMode)
virtual void sceneRectChanged(const QRectF &rect)
process graphics scene size changes
virtual void home()
go to home pos
void setStatusBar(QStatusBar *_sb)
virtual void slotWheelY(double _dAngle)
process signals from wheelX_