Visualization Library 2.0.0

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-2020, 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  if ( info.majVersion() ) {
119  fmt.setVersion( info.majVersion(), info.minVersion() );
120  }
121  break;
122  case vl::GLP_Core:
123  fmt.setProfile( QGLFormat::CoreProfile );
124  if ( info.majVersion() ) {
125  fmt.setVersion( info.majVersion(), info.minVersion() );
126  }
127  break;
128  case vl::GLP_Default:
129  // Don't care
130  break;
131  }
132 
133  // double buffer
134  fmt.setDoubleBuffer( info.doubleBuffer() );
135 
136  // color buffer
137  fmt.setRedBufferSize( info.rgbaBits().r() );
138  fmt.setGreenBufferSize( info.rgbaBits().g() );
139  fmt.setBlueBufferSize( info.rgbaBits().b() );
140  // setAlpha == true makes the create() function alway fail
141  // even if the returned format has the requested alpha channel
142  fmt.setAlphaBufferSize( info.rgbaBits().a() );
143  fmt.setAlpha( info.rgbaBits().a() != 0 );
144 
145  // accumulation buffer
146  int accum = vl::max( info.accumRGBABits().r(), info.accumRGBABits().g() );
147  accum = vl::max( accum, info.accumRGBABits().b() );
148  accum = vl::max( accum, info.accumRGBABits().a() );
149  fmt.setAccumBufferSize( accum );
150  fmt.setAccum( accum != 0 );
151 
152  // multisampling
153  if (info.multisample())
154  fmt.setSamples( info.multisampleSamples() );
155  fmt.setSampleBuffers( info.multisample() );
156 
157  // depth buffer
158  fmt.setDepthBufferSize( info.depthBufferBits() );
159  fmt.setDepth( info.depthBufferBits() != 0 );
160 
161  // stencil buffer
162  fmt.setStencilBufferSize( info.stencilBufferBits() );
163  fmt.setStencil( info.stencilBufferBits() != 0 );
164 
165  // stereo
166  fmt.setStereo( info.stereo() );
167 
168  // swap interval / v-sync
169  fmt.setSwapInterval( info.vSync() ? 1 : 0 );
170 
171  glctx->setFormat(fmt);
172  // this function returns false when we request an alpha buffer
173  // even if the created context seem to have the alpha buffer
174  /*bool ok = */glctx->create(shareContext);
175  setContext(glctx);
176 
177  framebuffer()->setWidth(width);
178  framebuffer()->setHeight(height);
179 
180  #ifndef NDEBUG
181  printf("--------------------------------------------\n");
182  printf("REQUESTED OpenGL Format:\n");
183  printf("--------------------------------------------\n");
184  printf("rgba = %d %d %d %d\n", fmt.redBufferSize(), fmt.greenBufferSize(), fmt.blueBufferSize(), fmt.alphaBufferSize() );
185  printf("double buffer = %d\n", (int)fmt.doubleBuffer() );
186  printf("depth buffer size = %d\n", fmt.depthBufferSize() );
187  printf("depth buffer = %d\n", fmt.depth() );
188  printf("stencil buffer size = %d\n", fmt.stencilBufferSize() );
189  printf("stencil buffer = %d\n", fmt.stencil() );
190  printf("accum buffer size %d\n", fmt.accumBufferSize() );
191  printf("accum buffer %d\n", fmt.accum() );
192  printf("stereo = %d\n", (int)fmt.stereo() );
193  printf("swap interval = %d\n", fmt.swapInterval() );
194  printf("multisample = %d\n", (int)fmt.sampleBuffers() );
195  printf("multisample samples = %d\n", (int)fmt.samples() );
196 
197  fmt = format();
198 
199  printf("--------------------------------------------\n");
200  printf("OBTAINED OpenGL Format:\n");
201  printf("--------------------------------------------\n");
202  printf("rgba = %d %d %d %d\n", fmt.redBufferSize(), fmt.greenBufferSize(), fmt.blueBufferSize(), fmt.alphaBufferSize() );
203  printf("double buffer = %d\n", (int)fmt.doubleBuffer() );
204  printf("depth buffer size = %d\n", fmt.depthBufferSize() );
205  printf("depth buffer = %d\n", fmt.depth() );
206  printf("stencil buffer size = %d\n", fmt.stencilBufferSize() );
207  printf("stencil buffer = %d\n", fmt.stencil() );
208  printf("accum buffer size %d\n", fmt.accumBufferSize() );
209  printf("accum buffer %d\n", fmt.accum() );
210  printf("stereo = %d\n", (int)fmt.stereo() );
211  printf("swap interval = %d\n", fmt.swapInterval() );
212  printf("multisample = %d\n", (int)fmt.sampleBuffers() );
213  printf("multisample samples = %d\n", (int)fmt.samples() );
214  printf("--------------------------------------------\n");
215  #endif
216 
217  setWindowTitle(title);
218  move(x,y);
219  resize(width,height);
220 
221  if (info.fullscreen())
222  setFullscreen(true);
223 
224  return true;
225  }
226 
227  virtual void setContinuousUpdate(bool continuous)
228  {
229  mContinuousUpdate = continuous;
230  if (continuous)
231  {
232  disconnect(&mUpdateTimer, SIGNAL(timeout()), this, SLOT(updateGL()));
233  connect(&mUpdateTimer, SIGNAL(timeout()), this, SLOT(updateGL()));
234  mUpdateTimer.setSingleShot(false);
235  mUpdateTimer.setInterval(mRefresh);
236  mUpdateTimer.start(0);
237  }
238  else
239  {
240  disconnect(&mUpdateTimer, SIGNAL(timeout()), this, SLOT(updateGL()));
241  mUpdateTimer.stop();
242  }
243  }
244 
245  void setRefreshRate( int msec )
246  {
247  mRefresh = msec;
248  mUpdateTimer.setInterval(mRefresh);
249  }
250 
252  {
253  return mRefresh;
254  }
255 
257  {
258  // OpenGL extensions initialization
259  initGLContext();
260 
261  dispatchInitEvent();
262  }
263 
264  void resizeGL(int width, int height)
265  {
266  dispatchResizeEvent(width, height);
267  }
268 
269  void paintGL()
270  {
271  dispatchUpdateEvent();
272  }
273 
274  void update()
275  {
276  QGLWidget::update();
277  // QGLWidget::updateGL();
278  }
279 
280  virtual void setWindowTitle(const vl::String& title)
281  {
282  QGLWidget::setWindowTitle( QString::fromStdString(title.toStdString()) );
283  }
284 
285  virtual bool setFullscreen(bool fullscreen)
286  {
287  mFullscreen = fullscreen;
288  if (fullscreen)
289  QGLWidget::setWindowState(QGLWidget::windowState() | Qt::WindowFullScreen);
290  else
291  QGLWidget::setWindowState(QGLWidget::windowState() & (~Qt::WindowFullScreen));
292  return true;
293  }
294 
295  virtual void quitApplication()
296  {
297  eraseAllEventListeners();
298  QApplication::quit();
299  }
300 
301  virtual void show()
302  {
303  QGLWidget::show();
304  }
305 
306  virtual void hide()
307  {
308  QGLWidget::hide();
309  }
310 
311  virtual void setPosition(int x, int y)
312  {
313  QGLWidget::move(x,y);
314  }
315 
316  virtual vl::ivec2 position() const
317  {
318  return vl::ivec2(QGLWidget::pos().x(), QGLWidget::pos().y());
319  }
320 
321  virtual void setSize(int w, int h)
322  {
323  // this already excludes the window's frame so it's ok for Visualization Library standards
324  QGLWidget::resize(w,h);
325  }
326 
327  virtual vl::ivec2 size() const
328  {
329  // this already excludes the window's frame so it's ok for Visualization Library standards
330  return vl::ivec2(QGLWidget::size().width(), QGLWidget::size().height());
331  }
332 
333  void swapBuffers()
334  {
335  QGLWidget::swapBuffers();
336  }
337 
338  void makeCurrent()
339  {
340  QGLWidget::makeCurrent();
341  }
342 
343  void setMousePosition(int x, int y)
344  {
345  QCursor::setPos( mapToGlobal(QPoint(x,y)) );
346  }
347 
348  void mouseMoveEvent(QMouseEvent* ev)
349  {
350  if (!mIgnoreNextMouseMoveEvent)
351  dispatchMouseMoveEvent(ev->x(), ev->y());
352  mIgnoreNextMouseMoveEvent = false;
353  }
354 
355  void mousePressEvent(QMouseEvent* ev)
356  {
358  switch(ev->button())
359  {
360  case Qt::LeftButton: bt = vl::LeftButton; break;
361  case Qt::RightButton: bt = vl::RightButton; break;
362  case Qt::MidButton: bt = vl::MiddleButton; break;
363  default:
364  bt = vl::UnknownButton; break;
365  }
366  dispatchMouseDownEvent(bt, ev->x(), ev->y());
367  }
368 
369  void mouseReleaseEvent(QMouseEvent* ev)
370  {
372  switch(ev->button())
373  {
374  case Qt::LeftButton: bt = vl::LeftButton; break;
375  case Qt::RightButton: bt = vl::RightButton; break;
376  case Qt::MidButton: bt = vl::MiddleButton; break;
377  default:
378  bt = vl::UnknownButton; break;
379  }
380  dispatchMouseUpEvent(bt, ev->x(), ev->y());
381  }
382 
383  void wheelEvent(QWheelEvent* ev)
384  {
385  dispatchMouseWheelEvent(ev->delta() / 120);
386  }
387 
388  void keyPressEvent(QKeyEvent* ev)
389  {
390  unsigned short unicode_ch = 0;
391  vl::EKey key = vl::Key_None;
392  translateKeyEvent(ev, unicode_ch, key);
393  dispatchKeyPressEvent(unicode_ch, key);
394  }
395 
396  void keyReleaseEvent(QKeyEvent* ev)
397  {
398  unsigned short unicode_ch = 0;
399  vl::EKey key = vl::Key_None;
400  translateKeyEvent(ev, unicode_ch, key);
401  dispatchKeyReleaseEvent(unicode_ch, key);
402  }
403 
404  virtual void setMouseVisible(bool visible)
405  {
406  mMouseVisible=visible;
407  if (visible)
408  QGLWidget::setCursor(Qt::ArrowCursor);
409  else
410  QGLWidget::setCursor(Qt::BlankCursor);
411  }
412 
413  virtual void getFocus()
414  {
415  QGLWidget::setFocus(Qt::OtherFocusReason);
416  }
417 
418  protected:
419  void translateKeyEvent(QKeyEvent* ev, unsigned short& unicode_out, vl::EKey& key_out);
420 
421  protected:
422  int mRefresh;
423  QTimer mUpdateTimer;
424  };
425  //-----------------------------------------------------------------------------
426 }
427 
428 #endif
virtual void setWindowTitle(const vl::String &title)
If the OpenGL context is a top window this function sets its title.
Definition: Qt5Widget.hpp:280
void makeCurrent()
Sets the OpenGL context as current for the calling thread.
Definition: Qt5Widget.hpp:338
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:316
void resizeGL(int width, int height)
Definition: Qt5Widget.hpp:264
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:321
virtual void hide()
If the OpenGL context is a widget this function makes it invisible to the user.
Definition: Qt5Widget.hpp:306
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:327
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:301
void setRefreshRate(int msec)
Definition: Qt5Widget.hpp:245
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:343
void wheelEvent(QWheelEvent *ev)
Definition: Qt5Widget.hpp:383
void keyPressEvent(QKeyEvent *ev)
Definition: Qt5Widget.hpp:388
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:369
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:404
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:295
void swapBuffers()
Swaps the back and front buffers to present the last rendering.
Definition: Qt5Widget.hpp:333
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:285
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:227
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:348
virtual void setPosition(int x, int y)
If the OpenGL context is a widget this function sets its position.
Definition: Qt5Widget.hpp:311
void mousePressEvent(QMouseEvent *ev)
Definition: Qt5Widget.hpp:355
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:274
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:413
void keyReleaseEvent(QKeyEvent *ev)
Definition: Qt5Widget.hpp:396