From bc3578cf1619a33307528b27bb157398c5dcb3fb Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Thu, 8 Jul 2010 10:51:37 +0000 Subject: [PATCH] From Jean-Sebastien Guay and Martin Scheffler, "First are Martin's changes: * Added support for floating windows and context menus in QMDIAreas. * Protected the size (_width and _height) by a mutex to prevent threading problems. Then my own: * Made sure the embedded widget's size follows the graphicsView's size at all times so that window resizes will resize the widget as expected in fullscreen mode." --- include/osgQt/QGraphicsViewAdapter | 3 + src/osgQt/QGraphicsViewAdapter.cpp | 113 +++++++++++++++++++++-------- 2 files changed, 84 insertions(+), 32 deletions(-) diff --git a/include/osgQt/QGraphicsViewAdapter b/include/osgQt/QGraphicsViewAdapter index faf0a21af..805ac5007 100644 --- a/include/osgQt/QGraphicsViewAdapter +++ b/include/osgQt/QGraphicsViewAdapter @@ -66,6 +66,7 @@ class OSGQT_EXPORT QGraphicsViewAdapter : public QObject bool handlePointerEvent(int x, int y, int buttonMask); bool handleKeyEvent(int key, bool keyDown); + QWidget* getWidgetAt(const QPoint& pos); osg::observer_ptr _image; @@ -86,8 +87,10 @@ class OSGQT_EXPORT QGraphicsViewAdapter : public QObject QColor _backgroundColor; QPointer _graphicsView; QPointer _graphicsScene; + QPointer _widget; OpenThreads::Mutex _qimagesMutex; + OpenThreads::Mutex _qresizeMutex; int _previousFrameNumber; bool _newImageAvailable; unsigned int _currentRead; diff --git a/src/osgQt/QGraphicsViewAdapter.cpp b/src/osgQt/QGraphicsViewAdapter.cpp index a545f6f4e..8ee033cd8 100644 --- a/src/osgQt/QGraphicsViewAdapter.cpp +++ b/src/osgQt/QGraphicsViewAdapter.cpp @@ -16,9 +16,12 @@ #include +#include #include #include +#include +#include #define MYQKEYEVENT 2000 #define MYQPOINTEREVENT 2001 @@ -67,7 +70,8 @@ QGraphicsViewAdapter::QGraphicsViewAdapter(osg::Image* image, QWidget* widget): _previousQtMouseY(-1), _previousSentEvent(false), _qtKeyModifiers(Qt::NoModifier), - _backgroundColor(255, 255, 255) + _backgroundColor(255, 255, 255), + _widget(widget) { // make sure we have a valid QApplication before we start creating widgets. getOrCreateQApplication(); @@ -267,15 +271,40 @@ void QGraphicsViewAdapter::setUpKeyMap() } +QWidget* QGraphicsViewAdapter::getWidgetAt(const QPoint& pos) +{ + QWidget* childAt = _graphicsView->childAt(pos); + if(childAt) + { + return childAt; + } + + QGraphicsItem* item = _graphicsView->itemAt(pos); + if(item && item->contains(item->mapFromScene(pos))) + { + QGraphicsProxyWidget* p = dynamic_cast(item); + if(p) + { + childAt = p->widget(); + QWidget* c; + while( (c = childAt->childAt(childAt->mapFromGlobal(pos)))!=0 ) + { + childAt = c; + } + return childAt; + } + } + return NULL; +} + bool QGraphicsViewAdapter::sendPointerEvent(int x, int y, int buttonMask) { _previousQtMouseX = x; _previousQtMouseY = _graphicsView->size().height() - y; - + QPoint pos(_previousQtMouseX, _previousQtMouseY); - if (_graphicsView->itemAt(pos) || - _graphicsView->childAt(pos) || - (_previousSentEvent && buttonMask != 0)) + + if (getWidgetAt(pos) != NULL || (_previousSentEvent && buttonMask != 0)) { QCoreApplication::postEvent(this, new MyQPointerEvent(x,y,buttonMask)); OSG_INFO<<"sendPointerEvent("<viewport()->geometry(); - const QPoint pos(x, y); + const QPoint globalPos(x, y); + + if (buttonMask != _previousButtonMask) { Qt::MouseButton qtButton = Qt::NoButton; @@ -332,21 +363,31 @@ bool QGraphicsViewAdapter::handlePointerEvent(int x, int y, int buttonMask) { qtButton = Qt::RightButton; eventType = rightButtonPressed ? QEvent::MouseButtonPress : QEvent::MouseButtonRelease ; + if(!rightButtonPressed) + { + QWidget* targetWidget = getWidgetAt(globalPos); + if(targetWidget) + { + QPoint localPos = targetWidget->mapFromGlobal(globalPos); + QContextMenuEvent* cme = new QContextMenuEvent(QContextMenuEvent::Mouse, localPos, globalPos); + QCoreApplication::postEvent(targetWidget, cme); + } + } } - + if (eventType==QEvent::MouseButtonPress) { _image->sendFocusHint(true); } - QMouseEvent event(eventType, pos, qtButton, qtMouseButtons, 0); + QMouseEvent event(eventType, globalPos, qtButton, qtMouseButtons, 0); QCoreApplication::sendEvent(_graphicsView->viewport(), &event ); _previousButtonMask = buttonMask; } else if (x != _previousMouseX || y != _previousMouseY) { - QMouseEvent event(QEvent::MouseMove, pos, Qt::NoButton, qtMouseButtons, 0); + QMouseEvent event(QEvent::MouseMove, globalPos, Qt::NoButton, qtMouseButtons, 0); QCoreApplication::sendEvent(_graphicsView->viewport(), &event); _previousMouseX = x; @@ -359,8 +400,7 @@ bool QGraphicsViewAdapter::handlePointerEvent(int x, int y, int buttonMask) bool QGraphicsViewAdapter::sendKeyEvent(int key, bool keyDown) { QPoint pos(_previousQtMouseX, _previousQtMouseY); - if (_graphicsView->itemAt(pos) || - _graphicsView->childAt(pos)) + if (getWidgetAt(pos) != NULL) { QCoreApplication::postEvent(this, new MyQKeyEvent(key,keyDown)); return true; @@ -453,45 +493,50 @@ void QGraphicsViewAdapter::render() QImage& image = _qimages[_currentWrite]; // If we got a resize, act on it, first by resizing the view, then the current image - if (_graphicsView->size().width() != _width || _graphicsView->size().height() != _height) + { - _graphicsView->setGeometry(0, 0, _width, _height); - _graphicsView->viewport()->setGeometry(0, 0, _width, _height); + OpenThreads::ScopedLock lock(_qresizeMutex); + if (_graphicsView->size().width() != _width || _graphicsView->size().height() != _height) + { + _graphicsView->setGeometry(0, 0, _width, _height); + _graphicsView->viewport()->setGeometry(0, 0, _width, _height); + + _widget->setGeometry(0, 0, _width, _height); + } + + if (image.width() != _width || image.height() != _height) + { + _qimages[_currentWrite] = QImage(_width, _height, s_imageFormat); + image = _qimages[_currentWrite]; + } + OSG_INFO << "render image " << _currentWrite << " with size (" << _width << "," << _height << ")" <render(&painter, destinationRect, sourceRect, Qt::IgnoreAspectRatio); painter.end(); #elif 0 - QPixmap pixmap(QPixmap::grabWidget(_graphicsView.data(), QRect(0, 0, _width, _height))); + QPixmap pixmap(QPixmap::grabWidget(_graphicsView.data(), QRect(0, 0, image.width(), image.height()))); image = pixmap.toImage(); #else // paint the image with the graphics view - QPixmap pixmap(_width, _height); + QPixmap pixmap(image.width(), image.height()); // Clear the image otherwise there are artifacts for some widgets that overpaint. pixmap.fill(Qt::transparent); QPainter painter(&pixmap); - QRectF destinationRect(0, 0, _width, _height); - QRect sourceRect(0, 0, _width, _height); + QRectF destinationRect(0, 0, image.width(), image.height()); + QRect sourceRect(0, 0, image.width(), image.height()); _graphicsView->render(&painter, destinationRect, _graphicsView->viewport()->rect()); painter.end(); @@ -524,8 +569,12 @@ void QGraphicsViewAdapter::resize(int width, int height) OSG_INFO << "resize to (" << width << "," << height << ")" < lock(_qresizeMutex); + _width = width; + _height = height; + } // Force an update so render() will be called. _graphicsScene->update(_graphicsScene->sceneRect());