Visualization Library 2.0.0-b3

A lightweight C++ OpenGL middleware for 2D/3D graphics

VL     Star     Watch     Fork     Issue

[Download] [Tutorials] [All Classes] [Grouped Classes]
Qt5Widget.hpp
Go to the documentation of this file.
1 /**************************************************************************************/
2 /* */
3 /* Visualization Library */
4 /* http://visualizationlibrary.org */
5 /* */
6 /* Copyright (c) 2005-2017, Michele Bosi */
7 /* All rights reserved. */
8 /* */
9 /* Redistribution and use in source and binary forms, with or without modification, */
10 /* are permitted provided that the following conditions are met: */
11 /* */
12 /* - Redistributions of source code must retain the above copyright notice, this */
13 /* list of conditions and the following disclaimer. */
14 /* */
15 /* - Redistributions in binary form must reproduce the above copyright notice, this */
16 /* list of conditions and the following disclaimer in the documentation and/or */
17 /* other materials provided with the distribution. */
18 /* */
19 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND */
20 /* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED */
21 /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */
22 /* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR */
23 /* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES */
24 /* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */
25 /* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON */
26 /* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */
27 /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */
28 /* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
29 /* */
30 /**************************************************************************************/
31 
32 #ifndef Qt5Window_INCLUDE_ONCE
33 #define Qt5Window_INCLUDE_ONCE
34 
35 #include <vlQt5/link_config.hpp>
38 #include <QApplication>
39 #include <QMouseEvent>
40 #include <QWidget>
41 #include <QUrl>
42 #include <QTimer>
43 #include <QObject>
44 #include <QMimeData>
45 #include <QGLWidget>
46 #include <QGLFormat>
47 
48 namespace vlQt5
49 {
50 //-----------------------------------------------------------------------------
51 // Qt5Widget
52 //-----------------------------------------------------------------------------
54  class VLQT5_EXPORT Qt5Widget : public QGLWidget, public vl::OpenGLContext
55  {
56  Q_OBJECT
57 
58  public:
60  using QObject::setObjectName;
61 
62  Qt5Widget(QWidget* parent=NULL, const QGLWidget* shareWidget=NULL, Qt::WindowFlags f=0)
63  :QGLWidget(parent,shareWidget,f),
64  mRefresh(10) // 100 fps
65  {
66  setContinuousUpdate(true);
67  setMouseTracking(true);
68  setAutoBufferSwap(false);
69  setAcceptDrops(true);
70  // let Qt take care of object destruction.
72  }
73 
75  {
76  dispatchDestroyEvent();
77  }
78 
79  void dragEnterEvent(QDragEnterEvent *ev)
80  {
81  if (ev->mimeData()->hasUrls())
82  ev->acceptProposedAction();
83  }
84 
85  void dropEvent(QDropEvent* ev)
86  {
87  if ( ev->mimeData()->hasUrls() )
88  {
89  std::vector<vl::String> files;
90  QList<QUrl> list = ev->mimeData()->urls();
91  for(int i=0; i<list.size(); ++i)
92  {
93  if (list[i].path().isEmpty())
94  continue;
95  #ifdef WIN32
96  if (list[i].path()[0] == '/')
97  files.push_back( list[i].path().toStdString().c_str()+1 );
98  else
99  files.push_back( list[i].path().toStdString().c_str() );
100  #else
101  files.push_back( list[i].path().toStdString().c_str() );
102  #endif
103  }
104  dispatchFileDroppedEvent(files);
105  }
106  }
107 
108  bool initQt5Widget(const vl::String& title, const vl::OpenGLContextFormat& info, const QGLContext* shareContext=0, int x=0, int y=0, int width=640, int height=480)
109  {
110  // setFormat(fmt) is marked as deprecated so we use this other method
111  QGLContext* glctx = new QGLContext(context()->format(), this);
112  QGLFormat fmt = context()->format();
113 
114  switch( info.openGLProfile() )
115  {
117  fmt.setProfile( QGLFormat::CompatibilityProfile );
118  fmt.setVersion( info.majVersion(), info.minVersion() );
119  break;
120  case vl::GLP_Core:
121  fmt.setProfile( QGLFormat::CoreProfile );
122  fmt.setVersion( info.majVersion(), info.minVersion() );
123  break;
124  case vl::GLP_Default:
125  // Don't care
126  break;
127  }
128 
129  // double buffer
130  fmt.setDoubleBuffer( info.doubleBuffer() );
131 
132  // color buffer
133  fmt.setRedBufferSize( info.rgbaBits().r() );
134  fmt.setGreenBufferSize( info.rgbaBits().g() );
135  fmt.setBlueBufferSize( info.rgbaBits().b() );
136  // setAlpha == true makes the create() function alway fail
137  // even if the returned format has the requested alpha channel
138  fmt.setAlphaBufferSize( info.rgbaBits().a() );
139  fmt.setAlpha( info.rgbaBits().a() != 0 );
140 
141  // accumulation buffer
142  int accum = vl::max( info.accumRGBABits().r(), info.accumRGBABits().g() );
143  accum = vl::max( accum, info.accumRGBABits().b() );
144  accum = vl::max( accum, info.accumRGBABits().a() );
145  fmt.setAccumBufferSize( accum );
146  fmt.setAccum( accum != 0 );
147 
148  // multisampling
149  if (info.multisample())
150  fmt.setSamples( info.multisampleSamples() );
151  fmt.setSampleBuffers( info.multisample() );
152 
153  // depth buffer
154  fmt.setDepthBufferSize( info.depthBufferBits() );
155  fmt.setDepth( info.depthBufferBits() != 0 );
156 
157  // stencil buffer
158  fmt.setStencilBufferSize( info.stencilBufferBits() );
159  fmt.setStencil( info.stencilBufferBits() != 0 );
160 
161  // stereo
162  fmt.setStereo( info.stereo() );
163 
164  // swap interval / v-sync
165  fmt.setSwapInterval( info.vSync() ? 1 : 0 );
166 
167  glctx->setFormat(fmt);
168  // this function returns false when we request an alpha buffer
169  // even if the created context seem to have the alpha buffer
170  /*bool ok = */glctx->create(shareContext);
171  setContext(glctx);
172 
173  framebuffer()->setWidth(width);
174  framebuffer()->setHeight(height);
175 
176  #ifndef NDEBUG
177  printf("--------------------------------------------\n");
178  printf("REQUESTED OpenGL Format:\n");
179  printf("--------------------------------------------\n");
180  printf("rgba = %d %d %d %d\n", fmt.redBufferSize(), fmt.greenBufferSize(), fmt.blueBufferSize(), fmt.alphaBufferSize() );
181  printf("double buffer = %d\n", (int)fmt.doubleBuffer() );
182  printf("depth buffer size = %d\n", fmt.depthBufferSize() );
183  printf("depth buffer = %d\n", fmt.depth() );
184  printf("stencil buffer size = %d\n", fmt.stencilBufferSize() );
185  printf("stencil buffer = %d\n", fmt.stencil() );
186  printf("accum buffer size %d\n", fmt.accumBufferSize() );
187  printf("accum buffer %d\n", fmt.accum() );
188  printf("stereo = %d\n", (int)fmt.stereo() );
189  printf("swap interval = %d\n", fmt.swapInterval() );
190  printf("multisample = %d\n", (int)fmt.sampleBuffers() );
191  printf("multisample samples = %d\n", (int)fmt.samples() );
192 
193  fmt = format();
194 
195  printf("--------------------------------------------\n");
196  printf("OBTAINED OpenGL Format:\n");
197  printf("--------------------------------------------\n");
198  printf("rgba = %d %d %d %d\n", fmt.redBufferSize(), fmt.greenBufferSize(), fmt.blueBufferSize(), fmt.alphaBufferSize() );
199  printf("double buffer = %d\n", (int)fmt.doubleBuffer() );
200  printf("depth buffer size = %d\n", fmt.depthBufferSize() );
201  printf("depth buffer = %d\n", fmt.depth() );
202  printf("stencil buffer size = %d\n", fmt.stencilBufferSize() );
203  printf("stencil buffer = %d\n", fmt.stencil() );
204  printf("accum buffer size %d\n", fmt.accumBufferSize() );
205  printf("accum buffer %d\n", fmt.accum() );
206  printf("stereo = %d\n", (int)fmt.stereo() );
207  printf("swap interval = %d\n", fmt.swapInterval() );
208  printf("multisample = %d\n", (int)fmt.sampleBuffers() );
209  printf("multisample samples = %d\n", (int)fmt.samples() );
210  printf("--------------------------------------------\n");
211  #endif
212 
213  setWindowTitle(title);
214  move(x,y);
215  resize(width,height);
216 
217  if (info.fullscreen())
218  setFullscreen(true);
219 
220  return true;
221  }
222 
223  virtual void setContinuousUpdate(bool continuous)
224  {
225  mContinuousUpdate = continuous;
226  if (continuous)
227  {
228  disconnect(&mUpdateTimer, SIGNAL(timeout()), this, SLOT(updateGL()));
229  connect(&mUpdateTimer, SIGNAL(timeout()), this, SLOT(updateGL()));
230  mUpdateTimer.setSingleShot(false);
231  mUpdateTimer.setInterval(mRefresh);
232  mUpdateTimer.start(0);
233  }
234  else
235  {
236  disconnect(&mUpdateTimer, SIGNAL(timeout()), this, SLOT(updateGL()));
237  mUpdateTimer.stop();
238  }
239  }
240 
241  void setRefreshRate( int msec )
242  {
243  mRefresh = msec;
244  mUpdateTimer.setInterval(mRefresh);
245  }
246 
248  {
249  return mRefresh;
250  }
251 
253  {
254  // OpenGL extensions initialization
255  initGLContext();
256 
257  dispatchInitEvent();
258  }
259 
260  void resizeGL(int width, int height)
261  {
262  dispatchResizeEvent(width, height);
263  }
264 
265  void paintGL()
266  {
267  dispatchUpdateEvent();
268  }
269 
270  void update()
271  {
272  QGLWidget::update();
273  // QGLWidget::updateGL();
274  }
275 
276  virtual void setWindowTitle(const vl::String& title)
277  {
278  QGLWidget::setWindowTitle( QString::fromStdString(title.toStdString()) );
279  }
280 
281  virtual bool setFullscreen(bool fullscreen)
282  {
283  mFullscreen = fullscreen;
284  if (fullscreen)
285  QGLWidget::setWindowState(QGLWidget::windowState() | Qt::WindowFullScreen);
286  else
287  QGLWidget::setWindowState(QGLWidget::windowState() & (~Qt::WindowFullScreen));
288  return true;
289  }
290 
291  virtual void quitApplication()
292  {
293  eraseAllEventListeners();
294  QApplication::quit();
295  }
296 
297  virtual void show()
298  {
299  QGLWidget::show();
300  }
301 
302  virtual void hide()
303  {
304  QGLWidget::hide();
305  }
306 
307  virtual void setPosition(int x, int y)
308  {
309  QGLWidget::move(x,y);
310  }
311 
312  virtual vl::ivec2 position() const
313  {
314  return vl::ivec2(QGLWidget::pos().x(), QGLWidget::pos().y());
315  }
316 
317  virtual void setSize(int w, int h)
318  {
319  // this already excludes the window's frame so it's ok for Visualization Library standards
320  QGLWidget::resize(w,h);
321  }
322 
323  virtual vl::ivec2 size() const
324  {
325  // this already excludes the window's frame so it's ok for Visualization Library standards
326  return vl::ivec2(QGLWidget::size().width(), QGLWidget::size().height());
327  }
328 
329  void swapBuffers()
330  {
331  QGLWidget::swapBuffers();
332  }
333 
334  void makeCurrent()
335  {
336  QGLWidget::makeCurrent();
337  }
338 
339  void setMousePosition(int x, int y)
340  {
341  QCursor::setPos( mapToGlobal(QPoint(x,y)) );
342  }
343 
344  void mouseMoveEvent(QMouseEvent* ev)
345  {
346  if (!mIgnoreNextMouseMoveEvent)
347  dispatchMouseMoveEvent(ev->x(), ev->y());
348  mIgnoreNextMouseMoveEvent = false;
349  }
350 
351  void mousePressEvent(QMouseEvent* ev)
352  {
354  switch(ev->button())
355  {
356  case Qt::LeftButton: bt = vl::LeftButton; break;
357  case Qt::RightButton: bt = vl::RightButton; break;
358  case Qt::MidButton: bt = vl::MiddleButton; break;
359  default:
360  bt = vl::UnknownButton; break;
361  }
362  dispatchMouseDownEvent(bt, ev->x(), ev->y());
363  }
364 
365  void mouseReleaseEvent(QMouseEvent* ev)
366  {
368  switch(ev->button())
369  {
370  case Qt::LeftButton: bt = vl::LeftButton; break;
371  case Qt::RightButton: bt = vl::RightButton; break;
372  case Qt::MidButton: bt = vl::MiddleButton; break;
373  default:
374  bt = vl::UnknownButton; break;
375  }
376  dispatchMouseUpEvent(bt, ev->x(), ev->y());
377  }
378 
379  void wheelEvent(QWheelEvent* ev)
380  {
381  dispatchMouseWheelEvent(ev->delta() / 120);
382  }
383 
384  void keyPressEvent(QKeyEvent* ev)
385  {
386  unsigned short unicode_ch = 0;
387  vl::EKey key = vl::Key_None;
388  translateKeyEvent(ev, unicode_ch, key);
389  dispatchKeyPressEvent(unicode_ch, key);
390  }
391 
392  void keyReleaseEvent(QKeyEvent* ev)
393  {
394  unsigned short unicode_ch = 0;
395  vl::EKey key = vl::Key_None;
396  translateKeyEvent(ev, unicode_ch, key);
397  dispatchKeyReleaseEvent(unicode_ch, key);
398  }
399 
400  virtual void setMouseVisible(bool visible)
401  {
402  mMouseVisible=visible;
403  if (visible)
404  QGLWidget::setCursor(Qt::ArrowCursor);
405  else
406  QGLWidget::setCursor(Qt::BlankCursor);
407  }
408 
409  virtual void getFocus()
410  {
411  QGLWidget::setFocus(Qt::OtherFocusReason);
412  }
413 
414  protected:
415  void translateKeyEvent(QKeyEvent* ev, unsigned short& unicode_out, vl::EKey& key_out);
416 
417  protected:
418  int mRefresh;
419  QTimer mUpdateTimer;
420  };
421  //-----------------------------------------------------------------------------
422 }
423 
424 #endif
virtual void setWindowTitle(const vl::String &title)
If the OpenGL context is a top window this function sets its title.
Definition: Qt5Widget.hpp:276
void makeCurrent()
Sets the OpenGL context as current for the calling thread.
Definition: Qt5Widget.hpp:334
Vector2< int > ivec2
A 2 components vector with int precision.
Definition: Vector2.hpp:278
virtual vl::ivec2 position() const
If the OpenGL context is a widget this function returns its position.
Definition: Qt5Widget.hpp:312
void resizeGL(int width, int height)
Definition: Qt5Widget.hpp:260
void setAutomaticDelete(bool autodel_on)
If set to true the Object is deleted when its reference count reaches 0.
Definition: Object.hpp:275
virtual void setSize(int w, int h)
If the OpenGL context is a widget this function sets its size.
Definition: Qt5Widget.hpp:317
virtual void hide()
If the OpenGL context is a widget this function makes it invisible to the user.
Definition: Qt5Widget.hpp:302
void setObjectName(const char *name)
The name of the object, by default set to the object&#39;s class name in debug builds.
Definition: Object.hpp:220
virtual vl::ivec2 size() const
Definition: Qt5Widget.hpp:323
The String class implements an advanced UTF16 (Unicode BMP) string manipulation engine.
Definition: String.hpp:62
int multisampleSamples() const
const T_Scalar & r() const
Definition: Vector4.hpp:111
Represents an OpenGL context, possibly a widget or a pbuffer, which can also respond to keyboard...
virtual void show()
If the OpenGL context is a widget this function makes it visible to the user.
Definition: Qt5Widget.hpp:297
void setRefreshRate(int msec)
Definition: Qt5Widget.hpp:241
Qt5Widget(QWidget *parent=NULL, const QGLWidget *shareWidget=NULL, Qt::WindowFlags f=0)
Definition: Qt5Widget.hpp:62
void setMousePosition(int x, int y)
If the OpenGL context is a widget this function sets the mouse position.
Definition: Qt5Widget.hpp:339
void wheelEvent(QWheelEvent *ev)
Definition: Qt5Widget.hpp:379
void keyPressEvent(QKeyEvent *ev)
Definition: Qt5Widget.hpp:384
const T_Scalar & g() const
Definition: Vector4.hpp:112
The OpenGLContextFormat class encapsulates the settings of an OpenGL rendering context.
const ivec4 & rgbaBits() const
void mouseReleaseEvent(QMouseEvent *ev)
Definition: Qt5Widget.hpp:365
The Qt5Widget class implements an OpenGLContext using the Qt5 API.
Definition: Qt5Widget.hpp:54
float max(float a, float b)
Definition: Vector2.hpp:311
const ivec4 & accumRGBABits() const
virtual void setMouseVisible(bool visible)
If the OpenGL context is a widget this function sets whether the mouse is visible over it or not...
Definition: Qt5Widget.hpp:400
void dropEvent(QDropEvent *ev)
Definition: Qt5Widget.hpp:85
EMouseButton
virtual void quitApplication()
Asks to the windowing system that is managing the OpenGLContext to quit the application.
Definition: Qt5Widget.hpp:291
void swapBuffers()
Swaps the back and front buffers to present the last rendering.
Definition: Qt5Widget.hpp:329
const T_Scalar & b() const
Definition: Vector4.hpp:113
#define NULL
Definition: OpenGLDefs.hpp:81
virtual bool setFullscreen(bool fullscreen)
If the OpenGL context is a widget this function requests a maximization to fullscreen.
Definition: Qt5Widget.hpp:281
EOpenGLProfile openGLProfile() const
virtual void setContinuousUpdate(bool continuous)
If the OpenGL context is a widget this function sets whether its area is continuously updated at each...
Definition: Qt5Widget.hpp:223
VLEGL_EXPORT void translateKeyEvent(WPARAM wParam, LPARAM lParam, unsigned short &unicode_out, vl::EKey &key_out)
Definition: EGLWindow.cpp:584
bool initQt5Widget(const vl::String &title, const vl::OpenGLContextFormat &info, const QGLContext *shareContext=0, int x=0, int y=0, int width=640, int height=480)
Definition: Qt5Widget.hpp:108
void dragEnterEvent(QDragEnterEvent *ev)
Definition: Qt5Widget.hpp:79
void mouseMoveEvent(QMouseEvent *ev)
Definition: Qt5Widget.hpp:344
virtual void setPosition(int x, int y)
If the OpenGL context is a widget this function sets its position.
Definition: Qt5Widget.hpp:307
void mousePressEvent(QMouseEvent *ev)
Definition: Qt5Widget.hpp:351
The Qt5 bindings namespace.
std::string toStdString() const
Returns a UTF8 encoded std::string.
Definition: String.cpp:1156
void update()
If the OpenGLContext is a widget this function requests a redraw and generates an updateEvent()...
Definition: Qt5Widget.hpp:270
const T_Scalar & a() const
Definition: Vector4.hpp:114
virtual void getFocus()
If the OpenGL context is a widget this function requests the mouse focus on it.
Definition: Qt5Widget.hpp:409
void keyReleaseEvent(QKeyEvent *ev)
Definition: Qt5Widget.hpp:392