From d810fea7c593f1adb4ae3979eb25d7ede615ce14 Mon Sep 17 00:00:00 2001 From: Krad Date: Wed, 23 Feb 2022 11:24:42 +0800 Subject: [PATCH] Remove myQVTKOpenGLNativeWidget --- .../measure/ActorDraggableInteractorStyle.h | 3 + src/include/view/dicomimageview.h | 4 +- src/include/view/myQVTKOpenGLNativeWidget.h | 289 ------ src/src/view/dicomimageview.cpp | 4 +- src/src/view/myQVTKOpenGLNativeWidget.cpp | 821 ------------------ src/src/view/viewcontainerwidget.cpp | 2 +- 6 files changed, 8 insertions(+), 1115 deletions(-) delete mode 100644 src/include/view/myQVTKOpenGLNativeWidget.h delete mode 100644 src/src/view/myQVTKOpenGLNativeWidget.cpp diff --git a/src/include/measure/ActorDraggableInteractorStyle.h b/src/include/measure/ActorDraggableInteractorStyle.h index 0105430..46bfc6f 100644 --- a/src/include/measure/ActorDraggableInteractorStyle.h +++ b/src/include/measure/ActorDraggableInteractorStyle.h @@ -66,6 +66,9 @@ public: */ void OnLeftButtonUp() override; + void OnMouseWheelForward() override{} + void OnMouseWheelBackward() override{} + void OnChar() override; void EndDolly() override; diff --git a/src/include/view/dicomimageview.h b/src/include/view/dicomimageview.h index 4941d1d..1233466 100644 --- a/src/include/view/dicomimageview.h +++ b/src/include/view/dicomimageview.h @@ -36,7 +36,7 @@ public: void ShowMetaData(); - myQVTKOpenGLNativeWidget* getGLWidget() + QVTKOpenGLNativeWidget* getGLWidget() { return _glWidt; } @@ -216,7 +216,7 @@ private: SeriesInstance* _Series =nullptr; QScrollBar* _scrollBar =nullptr; MyTitleBar *_titleBar =nullptr; - myQVTKOpenGLNativeWidget* _glWidt = nullptr; + QVTKOpenGLNativeWidget* _glWidt = nullptr; pqVCRToolbar* _vcr_toolbar = nullptr; pqVCRController *_vcr_ctrl = nullptr; QThread _thread; diff --git a/src/include/view/myQVTKOpenGLNativeWidget.h b/src/include/view/myQVTKOpenGLNativeWidget.h deleted file mode 100644 index 455f062..0000000 --- a/src/include/view/myQVTKOpenGLNativeWidget.h +++ /dev/null @@ -1,289 +0,0 @@ -/*========================================================================= - - Program: Visualization Toolkit - Module: myQVTKOpenGLNativeWidget.h - - Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen - All rights reserved. - See Copyright.txt or http://www.kitware.com/Copyright.htm for details. - - This software is distributed WITHOUT ANY WARRANTY; without even - the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - PURPOSE. See the above copyright notice for more information. - -=========================================================================*/ -/** - * @class myQVTKOpenGLNativeWidget - * @brief QOpenGLWidget subclass to house a vtkGenericOpenGLRenderWindow in a Qt - * application. - * - * myQVTKOpenGLNativeWidget extends QOpenGLWidget to make it work with a - * vtkGenericOpenGLRenderWindow. This is akin to QVTKWidget except it uses Qt to create and - * manage the OpenGL context using QOpenGLWidget (added in Qt 5.4). - * - * While myQVTKOpenGLNativeWidget is intended to be a replacement for QVTKWidget when - * using Qt 5, there are a few difference between myQVTKOpenGLNativeWidget and - * QVTKWidget. - * - * Unlike QVTKWidget, myQVTKOpenGLNativeWidget only works with vtkGenericOpenGLRenderWindow. - * This is necessary since QOpenGLWidget wants to take over the window management as - * well as the OpenGL context creation. Getting that to work reliably with - * vtkXRenderWindow or vtkWin32RenderWindow (and other platform specific - * vtkRenderWindow subclasses) was tricky and fraught with issues. - * - * Since myQVTKOpenGLNativeWidget uses QOpenGLWidget to create the OpenGL context, - * it uses QSurfaceFormat (set using `QOpenGLWidget::setFormat` or - * `QSurfaceFormat::setDefaultFormat`) to create appropriate window and context. - * You can use `myQVTKOpenGLNativeWidget::copyToFormat` to obtain a QSurfaceFormat - * appropriate for a vtkRenderWindow. - * - * A typical usage for myQVTKOpenGLNativeWidget is as follows: - * @code{.cpp} - * - * // before initializing QApplication, set the default surface format. - * QSurfaceFormat::setDefaultFormat(myQVTKOpenGLNativeWidget::defaultFormat()); - * - * vtkNew window; - * QPointer widget = new myQVTKOpenGLNativeWidget(...); - * widget->SetRenderWindow(window.Get()); - * - * // If using any of the standard view e.g. vtkContextView, then - * // you can do the following. - * vtkNew view; - * view->SetRenderWindow(window.Get()); - * - * // You can continue to use `window` as a regular vtkRenderWindow - * // including adding renderers, actors etc. - * - * @endcode - * - * @section OpenGLContext OpenGL Context - * - * In QOpenGLWidget (superclass for myQVTKOpenGLNativeWidget), all rendering happens in a - * framebuffer object. Thus, care must be taken in the rendering code to never - * directly re-bind the default framebuffer i.e. ID 0. - * - * myQVTKOpenGLNativeWidget creates an internal QOpenGLFramebufferObject, independent of the - * one created by superclass, for vtkRenderWindow to do the rendering in. This - * explicit double-buffering is useful in avoiding temporary back-buffer only - * renders done in VTK (e.g. when making selections) from destroying the results - * composed on screen. - * - * @section RenderAndPaint Handling Render and Paint. - * - * QWidget subclasses (including `QOpenGLWidget` and `myQVTKOpenGLNativeWidget`) display - * their contents on the screen in `QWidget::paint` in response to a paint event. - * `QOpenGLWidget` subclasses are expected to do OpenGL rendering in - * `QOpenGLWidget::paintGL`. QWidget can receive paint events for various - * reasons including widget getting focus/losing focus, some other widget on - * the UI e.g. QProgressBar in status bar updating, etc. - * - * In VTK applications, any time the vtkRenderWindow needs to be updated to - * render a new result, one call `vtkRenderWindow::Render` on it. - * vtkRenderWindowInteractor set on the render window ensures that as - * interactions happen that affect the rendered result, it calls `Render` on the - * render window. - * - * Since paint in Qt can be called more often then needed, we avoid potentially - * expensive `vtkRenderWindow::Render` calls each time that happens. Instead, - * myQVTKOpenGLNativeWidget relies on the VTK application calling - * `vtkRenderWindow::Render` on the render window when it needs to update the - * rendering. `paintGL` simply passes on the result rendered by the most render - * vtkRenderWindow::Render to Qt windowing system for composing on-screen. - * - * There may still be occasions when we may have to render in `paint` for - * example if the window was resized or Qt had to recreate the OpenGL context. - * In those cases, `myQVTKOpenGLNativeWidget::paintGL` can request a render by calling - * `myQVTKOpenGLNativeWidget::renderVTK`. - * - * @section Caveats - * myQVTKOpenGLNativeWidget only supports **OpenGL2** rendering backend. - * myQVTKOpenGLNativeWidget does not support stereo, - * please use QVTKOpenGLWidget if you need support for stereo rendering - * - * myQVTKOpenGLNativeWidget is targeted for Qt version 5.5 and above. - * - */ -#ifndef myQVTKOpenGLNativeWidget_h -#define myQVTKOpenGLNativeWidget_h - -#include - -#include "QVTKInteractor.h" // needed for QVTKInteractor -#include "vtkGUISupportQtModule.h" // for export macro -#include "vtkNew.h" // needed for vtkNew -#include "vtkSmartPointer.h" // needed for vtkSmartPointer - -class QOpenGLDebugLogger; -class QOpenGLFramebufferObject; -class QVTKInteractor; -class QVTKInteractorAdapter; -class QVTKOpenGLNativeWidgetObserver; -class vtkGenericOpenGLRenderWindow; -class DicomImageView; - -//class VTKGUISUPPORTQT_EXPORT myQVTKOpenGLNativeWidget : public QOpenGLWidget -class myQVTKOpenGLNativeWidget : public QOpenGLWidget -{ - Q_OBJECT - typedef QOpenGLWidget Superclass; -public: - myQVTKOpenGLNativeWidget(QWidget* parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags()); - ~myQVTKOpenGLNativeWidget() override; - - //@{ - /** - * Get/Set the currently used vtkGenericOpenGLRenderWindow. - * GetRenderWindow() creates and returns a new vtkGenericOpenGLRenderWindow - * if it is not already provided. - */ - void SetImageView(DicomImageView *v); - DicomImageView* GetImageView(); - - void SetRenderWindow(vtkGenericOpenGLRenderWindow* win); - void SetRenderWindow(vtkRenderWindow* win); - virtual vtkRenderWindow* GetRenderWindow(); - //@} - - /** - * Get the QEvent to VTK events translator. - */ - virtual QVTKInteractorAdapter* GetInteractorAdapter() { return this->InteractorAdapter; } - - /** - * Get the QVTKInteractor that was either created by default or set by the user. - */ - virtual QVTKInteractor* GetInteractor(); - - /** - * Sets up vtkRenderWindow ivars using QSurfaceFormat. - */ - static void copyFromFormat(const QSurfaceFormat& format, vtkRenderWindow* win); - - /** - * Using the vtkRenderWindow, setup QSurfaceFormat. - */ - static void copyToFormat(vtkRenderWindow* win, QSurfaceFormat& format); - - /** - * Returns a typical QSurfaceFormat suitable for most applications using - * myQVTKOpenGLNativeWidget. Note that this is not the QSurfaceFormat that gets used - * if none is specified. That is set using `QSurfaceFormat::setDefaultFormat`. - */ - static QSurfaceFormat defaultFormat(); - - /** - * Enable or disable support for HiDPI displays. - */ - virtual void setEnableHiDPI(bool enable); - virtual bool enableHiDPI() { return this->EnableHiDPI; } - - /** - * Set the cursor on this widget. - */ - void setQVTKCursor(const QCursor &cursor); - -signals: - /** - * This signal will be emitted whenever a mouse event occurs within the QVTK window. - */ - void mouseEvent(QMouseEvent* event); - -protected slots: - /** - * Called as a response to `QOpenGLContext::aboutToBeDestroyed`. This may be - * called anytime during the widget lifecycle. We need to release any OpenGL - * resources allocated in VTK work in this method. - */ - virtual void cleanupContext(); - -private slots: - /** - * recreates the FBO used for VTK rendering. - */ - void recreateFBO(); - - /** - * called before the render window starts to render. We ensure that this->FBO - * is bound and ready to use. - */ - void startEventCallback(); - - /** - * callback for changing the cursor. Called when vtkGenericOpenGLRenderWindow - * fires the CursorChangedEvent. - */ - void cursorChangedCallback(vtkObject* caller, unsigned long vtk_event, - void* client_data, void* call_data); - -protected: - //virtual void wheelEvent(QWheelEvent *event); - - bool event(QEvent* evt) Q_DECL_OVERRIDE; - void initializeGL() Q_DECL_OVERRIDE; - void resizeGL(int w, int h) Q_DECL_OVERRIDE; - void paintGL() Q_DECL_OVERRIDE; - - //void mousePressEvent(QMouseEvent* event) Q_DECL_OVERRIDE; - //void mouseMoveEvent(QMouseEvent* event) Q_DECL_OVERRIDE; - //void mouseReleaseEvent(QMouseEvent* event) Q_DECL_OVERRIDE; - //void mouseDoubleClickEvent(QMouseEvent* event) Q_DECL_OVERRIDE; - - /** - * This method is called to indicate that vtkRenderWindow needs to reinitialize - * itself before the next render (done in myQVTKOpenGLNativeWidget::paintGL). - * This is needed when the context gets recreated - * or the default FrameBufferObject gets recreated, for example. - */ - void requireRenderWindowInitialization(); - - /** - * This method may be called in `paintGL` to request VTK to do a render i.e. - * trigger render on the render window via its interactor. - * - * It will return true if render (or an equivalent action) was performed to - * update the frame buffer made available to VTK for rendering with latest - * rendering. - * - * Default implementation never returns false. However, subclasses can return - * false to indicate to myQVTKOpenGLNativeWidget that it cannot generate a reasonable - * image to be displayed in myQVTKOpenGLNativeWidget. In which case, the `paintGL` - * call will return leaving the `defaultFramebufferObject` untouched. - * - * Since by default `QOpenGLWidget::UpdateBehavior` is set to - * QOpenGLWidget::PartialUpdate, this means whatever was rendered in the frame - * buffer in most recent successful call will be preserved, unless the widget - * was forced to recreate the FBO as a result of resize or screen change. - * - * @sa Section @ref RenderAndPaint. - */ - virtual bool renderVTK(); - -protected: - vtkSmartPointer RenderWindow; - QVTKInteractorAdapter* InteractorAdapter; - - bool EnableHiDPI; - int OriginalDPI; - - static const double DevicePixelRatioTolerance; - -private: - Q_DISABLE_COPY(myQVTKOpenGLNativeWidget); - - /** - * Called when vtkCommand::WindowFrameEvent is fired by the - * vtkGenericOpenGLRenderWindow. - */ - void windowFrameEventCallback(); - - QOpenGLFramebufferObject* FBO; - bool InPaintGL; - bool DoVTKRenderInPaintGL; - vtkNew Observer; - friend class QVTKOpenGLNativeWidgetObserver; - QOpenGLDebugLogger* Logger; - DicomImageView *view; -}; - -#endif diff --git a/src/src/view/dicomimageview.cpp b/src/src/view/dicomimageview.cpp index e807395..ef4fe25 100644 --- a/src/src/view/dicomimageview.cpp +++ b/src/src/view/dicomimageview.cpp @@ -36,13 +36,13 @@ DicomImageView::DicomImageView(QWidget* parent) QGridLayout* controlLayout = new QGridLayout(wrapper); - _glWidt = new myQVTKOpenGLNativeWidget(wrapper); + _glWidt = new QVTKOpenGLNativeWidget(wrapper); m_glrenWin = vtkSmartPointer ::New(); //m_glrenWin->SetOffScreenRendering(1); //for offscreen rendering _glWidt->SetRenderWindow(m_glrenWin);//set up interacte //in order to visit in both way! - _glWidt->SetImageView(this); +// _glWidt->SetImageView(this); controlLayout->addWidget(_glWidt, 0, 0); diff --git a/src/src/view/myQVTKOpenGLNativeWidget.cpp b/src/src/view/myQVTKOpenGLNativeWidget.cpp deleted file mode 100644 index bb2b3f8..0000000 --- a/src/src/view/myQVTKOpenGLNativeWidget.cpp +++ /dev/null @@ -1,821 +0,0 @@ -/*========================================================================= - - Program: Visualization Toolkit - Module: myQVTKOpenGLNativeWidget.cxx - - Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen - All rights reserved. - See Copyright.txt or http://www.kitware.com/Copyright.htm for details. - - This software is distributed WITHOUT ANY WARRANTY; without even - the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - PURPOSE. See the above copyright notice for more information. - -=========================================================================*/ -#include "view/myQVTKOpenGLNativeWidget.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "QVTKInteractor.h" -#include "QVTKInteractorAdapter.h" -#include "vtkCommand.h" -#include "vtkGenericOpenGLRenderWindow.h" -#include "vtkInteractorStyleTrackballCamera.h" -#include "vtkNew.h" -#include "vtkObjectFactory.h" -#include "vtkOpenGLState.h" - -#ifdef __APPLE__ -#include "QVTKOpenGLWidget.h" -#include - -/** - * Unused except on MacOS. - * In an application using both QVTKOpenGLWidget - * and myQVTKOpenGLNativeWidget, this bug can appear: - * https://bugreports.qt.io/browse/QTBUG-69644 - */ -namespace -{ - /** - * It is needed to switch the visibility of currently visible QVTKOpenGLWidget - * back and forth (ie hide then show). Just after initialization of myQVTKOpenGLNativeWidget - * (ie when we receive WindowActivate event, or PolishRequest event) - * This method takes care of it. - */ - void QVTKOpenGLWidgetMacOSCheck(QWidget* window) - { - // Used a static to ensure the fix is done only once - static bool QVTKOpenGLWidgetMacOSFixed = false; - - if (QVTKOpenGLWidgetMacOSFixed || !window) - { - return; - } - - // Switch visibility back and forth of visible QVTKOpenGLWidgets - // that share the same window as this myQVTKOpenGLNativeWidget. - // This ensures they come back on the front after the Qt bug happens. - auto widgets = window->findChildren(); - for (auto qvglWidget : widgets) - { - if (qvglWidget->isVisible()) - { - qvglWidget->hide(); - qvglWidget->show(); - QVTKOpenGLWidgetMacOSFixed = true; - } - } - } -} -#endif // __APPLE__ - -// #define DEBUG_QVTKOPENGL_WIDGET -#ifdef DEBUG_QVTKOPENGL_WIDGET -#define vtkmyQVTKOpenGLNativeWidgetDebugMacro(msg) \ - cout << this << ": " msg << endl; \ - if (this->Logger) \ - { \ - this->Logger->logMessage( \ - QOpenGLDebugMessage::createApplicationMessage(QStringLiteral("myQVTKOpenGLNativeWidget::" msg))); \ - } -#else -#define vtkmyQVTKOpenGLNativeWidgetDebugMacro(x) -#endif - -class QVTKOpenGLNativeWidgetObserver : public vtkCommand -{ -public: - static QVTKOpenGLNativeWidgetObserver* New() { return new QVTKOpenGLNativeWidgetObserver(); } - vtkTypeMacro(QVTKOpenGLNativeWidgetObserver, vtkCommand); - - void SetTarget(myQVTKOpenGLNativeWidget* target) { this->Target = target; } - - void Execute(vtkObject* object, unsigned long eventId, void* callData) override - { - if (this->Target) - { - switch (eventId) - { - case vtkCommand::WindowMakeCurrentEvent: - { - // We do not call QOpenGLWidget::makeCurrent() as that also makes the - // frame buffer object used by QOpenGLWidget active. This can have - // unintended side effects when MakeCurrent gets called in a - // render-pass, for example. We should only be making the context - // active. To do that, we use this trick. We rely on the - // QOpenGLContext have been called makeCurrent() previously so we - // can get to the surface that was used to do that. We simply - // reactivate on that surface. - QOpenGLContext* ctxt = this->Target->context(); - QSurface* surface = ctxt ? ctxt->surface() : nullptr; - if (surface) - { - ctxt->makeCurrent(surface); - } - Q_ASSERT(ctxt == nullptr || surface != nullptr); - } - break; - - case vtkCommand::WindowIsCurrentEvent: - { - bool& cstatus = *reinterpret_cast(callData); - cstatus = (QOpenGLContext::currentContext() == this->Target->context()); - } - break; - - case vtkCommand::WindowFrameEvent: - this->Target->windowFrameEventCallback(); - break; - - case vtkCommand::StartEvent: - VTK_FALLTHROUGH; - case vtkCommand::StartPickEvent: - this->Target->startEventCallback(); - break; - case vtkCommand::CursorChangedEvent: - this->Target->cursorChangedCallback(object, eventId, nullptr, callData); - break; - } - } - } - -protected: - QVTKOpenGLNativeWidgetObserver() {} - ~QVTKOpenGLNativeWidgetObserver() override {} - QPointer Target; -}; - -// Tolerance used when truncating the device pixel ratio scaled -// window size in calls to SetSize / SetPosition. -const double myQVTKOpenGLNativeWidget::DevicePixelRatioTolerance = 1e-5; - -//----------------------------------------------------------------------------- -myQVTKOpenGLNativeWidget::myQVTKOpenGLNativeWidget(QWidget* parentWdg, Qt::WindowFlags f) - : Superclass(parentWdg, f) - , InteractorAdapter(nullptr) - , EnableHiDPI(false) - , OriginalDPI(0) - , FBO(nullptr) - , InPaintGL(false) - , DoVTKRenderInPaintGL(false) - , Logger(nullptr) -{ - this->Observer->SetTarget(this); - - // default to strong focus - this->setFocusPolicy(Qt::StrongFocus); - - this->setUpdateBehavior(QOpenGLWidget::PartialUpdate); - - this->InteractorAdapter = new QVTKInteractorAdapter(this); - this->InteractorAdapter->SetDevicePixelRatio(this->devicePixelRatio()); - - this->setMouseTracking(true); - - // QOpenGLWidget::resized() is triggered when the default FBO in QOpenGLWidget is recreated. - // We use the same signal to recreate our FBO. - this->connect(this, SIGNAL(resized()), SLOT(recreateFBO())); -} - -//----------------------------------------------------------------------------- -myQVTKOpenGLNativeWidget::~myQVTKOpenGLNativeWidget() -{ - vtkmyQVTKOpenGLNativeWidgetDebugMacro("~myQVTKOpenGLNativeWidget"); - // essential to cleanup context so that the render window finalizes and - // releases any graphics resources it may have allocated. - this->cleanupContext(); - this->SetRenderWindow(static_cast(nullptr)); - this->Observer->SetTarget(nullptr); - delete this->InteractorAdapter; - delete this->Logger; -} - -void myQVTKOpenGLNativeWidget::SetImageView(DicomImageView *v) -{ - this->view = v; -} - -DicomImageView* myQVTKOpenGLNativeWidget::GetImageView() -{ - return this->view; -} -//----------------------------------------------------------------------------- -void myQVTKOpenGLNativeWidget::SetRenderWindow(vtkRenderWindow* win) -{ - vtkGenericOpenGLRenderWindow* gwin = vtkGenericOpenGLRenderWindow::SafeDownCast(win); - this->SetRenderWindow(gwin); - if (gwin == nullptr && win != nullptr) - { - qDebug() << "myQVTKOpenGLNativeWidget requires a `vtkGenericOpenGLRenderWindow`. `" - << win->GetClassName() << "` is not supported."; - } -} - -//----------------------------------------------------------------------------- -void myQVTKOpenGLNativeWidget::SetRenderWindow(vtkGenericOpenGLRenderWindow* win) -{ - if (this->RenderWindow == win) - { - return; - } - - if (this->RenderWindow) - { - this->RenderWindow->RemoveObserver(this->Observer); - this->RenderWindow->SetReadyForRendering(false); - } - this->RenderWindow = win; - this->requireRenderWindowInitialization(); - if (this->RenderWindow) - { - // set this to 0 to reinitialize it before setting the RenderWindow DPI - this->OriginalDPI = 0; - - // if an interactor wasn't provided, we'll make one by default - if (!this->RenderWindow->GetInteractor()) - { - // create a default interactor - vtkNew iren; - // iren->SetUseTDx(this->UseTDx); - this->RenderWindow->SetInteractor(iren); - iren->Initialize(); - - // now set the default style - vtkNew style; - iren->SetInteractorStyle(style); - } - - this->RenderWindow->AddObserver(vtkCommand::WindowMakeCurrentEvent, this->Observer); - this->RenderWindow->AddObserver(vtkCommand::WindowIsCurrentEvent, this->Observer); - this->RenderWindow->AddObserver(vtkCommand::WindowFrameEvent, this->Observer); - this->RenderWindow->AddObserver(vtkCommand::StartEvent, this->Observer); - this->RenderWindow->AddObserver(vtkCommand::StartPickEvent, this->Observer); - this->RenderWindow->AddObserver(vtkCommand::StartPickEvent, this->Observer); - this->RenderWindow->AddObserver(vtkCommand::CursorChangedEvent, this->Observer); - - if (this->FBO) - { - this->makeCurrent(); - this->recreateFBO(); - } - } -} - -//----------------------------------------------------------------------------- -void myQVTKOpenGLNativeWidget::startEventCallback() -{ - vtkmyQVTKOpenGLNativeWidgetDebugMacro("startEventCallback"); - this->makeCurrent(); - if (this->FBO) - { - // ensure that before vtkRenderWindow starts to render, we activate the FBO - // to render into. VTK code can be a bit lax with it. This just ensures that - // we have the FBO activated. - this->FBO->bind(); - } -} - -//----------------------------------------------------------------------------- -vtkRenderWindow* myQVTKOpenGLNativeWidget::GetRenderWindow() -{ - if (!this->RenderWindow) - { - // create a default - vtkGenericOpenGLRenderWindow* win = vtkGenericOpenGLRenderWindow::New(); - this->SetRenderWindow(win); - win->Delete(); - } - return this->RenderWindow; -} - -//----------------------------------------------------------------------------- -QVTKInteractor* myQVTKOpenGLNativeWidget::GetInteractor() -{ - return QVTKInteractor::SafeDownCast(this->GetRenderWindow()->GetInteractor()); -} - -//----------------------------------------------------------------------------- -void myQVTKOpenGLNativeWidget::copyFromFormat(const QSurfaceFormat& format, vtkRenderWindow* win) -{ - if (vtkOpenGLRenderWindow* oglWin = vtkOpenGLRenderWindow::SafeDownCast(win)) - { - oglWin->SetStereoCapableWindow(format.stereo() ? 1 : 0); - // samples may not be correct if format is obtained from - // QOpenGLWidget::format() after the context is created. That's because - // QOpenGLWidget always created context to samples=0. - oglWin->SetMultiSamples(format.samples()); - oglWin->SetStencilCapable(format.stencilBufferSize() > 0); - } -} - -//----------------------------------------------------------------------------- -void myQVTKOpenGLNativeWidget::copyToFormat(vtkRenderWindow* win, QSurfaceFormat& format) -{ - if (vtkOpenGLRenderWindow* oglWin = vtkOpenGLRenderWindow::SafeDownCast(win)) - { - format.setStereo(oglWin->GetStereoCapableWindow()); - format.setSamples(oglWin->GetMultiSamples()); - format.setStencilBufferSize(oglWin->GetStencilCapable() ? 8 : 0); - } -} - -//----------------------------------------------------------------------------- -QSurfaceFormat myQVTKOpenGLNativeWidget::defaultFormat() -{ - QSurfaceFormat fmt; - fmt.setRenderableType(QSurfaceFormat::OpenGL); - fmt.setVersion(3, 2); - fmt.setProfile(QSurfaceFormat::CoreProfile); - fmt.setSwapBehavior(QSurfaceFormat::DoubleBuffer); - fmt.setRedBufferSize(1); - fmt.setGreenBufferSize(1); - fmt.setBlueBufferSize(1); - fmt.setDepthBufferSize(1); - fmt.setStencilBufferSize(0); - fmt.setAlphaBufferSize(1); - fmt.setStereo(false); - fmt.setSamples(vtkOpenGLRenderWindow::GetGlobalMaximumNumberOfMultiSamples()); -#ifdef DEBUG_QVTKOPENGL_WIDGET - fmt.setOption(QSurfaceFormat::DebugContext); -#endif - return fmt; -} - -//----------------------------------------------------------------------------- -void myQVTKOpenGLNativeWidget::setEnableHiDPI(bool enable) -{ - this->EnableHiDPI = enable; - - if (this->RenderWindow) - { - if (this->OriginalDPI == 0) - { - this->OriginalDPI = this->RenderWindow->GetDPI(); - } - if (this->EnableHiDPI) - { - this->RenderWindow->SetDPI(this->OriginalDPI * this->devicePixelRatio()); - } - else - { - this->RenderWindow->SetDPI(this->OriginalDPI); - } - } -} - -//----------------------------------------------------------------------------- -void myQVTKOpenGLNativeWidget::setQVTKCursor(const QCursor &cursor) -{ - this->setCursor(cursor); -} - -//----------------------------------------------------------------------------- -void myQVTKOpenGLNativeWidget::recreateFBO() -{ - vtkmyQVTKOpenGLNativeWidgetDebugMacro("recreateFBO"); - delete this->FBO; - this->FBO = nullptr; - if (!this->RenderWindow) - { - return; - } - - // Since myQVTKOpenGLNativeWidget::initializeGL() cannot set multi-samples - // state on the RenderWindow correctly, we do it here. - QOpenGLFunctions* f = QOpenGLContext::currentContext()->functions(); - GLint samples; - f->glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_SAMPLES, &samples); - - // Some graphics drivers report the number of samples as 1 when - // multisampling is off. Set the number of samples to 0 in this case. - samples = samples > 1 ? samples : 0; - this->RenderWindow->SetMultiSamples(static_cast(samples)); - - QOpenGLFramebufferObjectFormat format; - format.setAttachment(QOpenGLFramebufferObject::Depth); - format.setSamples(samples); - -#if QT_VERSION < QT_VERSION_CHECK(5, 6, 0) - // Qt < 5.6 only has an integer API for device pixel ratio. - const double devicePixelRatio_ = this->devicePixelRatio(); -#else - const double devicePixelRatio_ = this->devicePixelRatioF(); -#endif - const QSize widgetSize = this->size(); - const QSize deviceSize = QSize(static_cast(widgetSize.width() * devicePixelRatio_ + DevicePixelRatioTolerance), - static_cast(widgetSize.height() * devicePixelRatio_ + DevicePixelRatioTolerance)); - - // This is as good an opportunity as any to communicate size to the render - // window. - this->InteractorAdapter->SetDevicePixelRatio(devicePixelRatio_); - if (vtkRenderWindowInteractor* iren = this->RenderWindow->GetInteractor()) - { - iren->SetSize(deviceSize.width(), deviceSize.height()); - } - this->RenderWindow->SetSize(deviceSize.width(), deviceSize.height()); - this->RenderWindow->SetPosition(static_cast(this->x() * devicePixelRatio_ + DevicePixelRatioTolerance), - static_cast(this->y() * devicePixelRatio_ + DevicePixelRatioTolerance)); - - // Set screen size on render window. - const QRect screenGeometry = QApplication::desktop()->screenGeometry(this); - this->RenderWindow->SetScreenSize(screenGeometry.width(), screenGeometry.height()); - - this->FBO = new QOpenGLFramebufferObject(deviceSize, format); - this->FBO->bind(); - this->RenderWindow->SetForceMaximumHardwareLineWidth(1); - this->RenderWindow->SetReadyForRendering(true); - this->RenderWindow->InitializeFromCurrentContext(); - - this->setEnableHiDPI(this->EnableHiDPI); - - // Since the context or frame buffer was recreated, if a paintGL call ensues, - // we need to ensure we're requesting VTK to render. - this->DoVTKRenderInPaintGL = true; - - // Clear to ensure that an uninitialized framebuffer is never displayed. - vtkOpenGLState *ostate = this->RenderWindow->GetState(); - // have to keep vtk state up to date as well - ostate->vtkglDisable(GL_SCISSOR_TEST); - ostate->vtkglClearColor(0.0f, 0.0f, 0.0f, 1.0f); - ostate->vtkglViewport(0, 0, deviceSize.width(), deviceSize.height()); - f->glDisable(GL_SCISSOR_TEST); - f->glClearColor(0.0f, 0.0f, 0.0f, 1.0f); - f->glClear(GL_COLOR_BUFFER_BIT); -} - -//----------------------------------------------------------------------------- -void myQVTKOpenGLNativeWidget::initializeGL() -{ - this->Superclass::initializeGL(); - -#ifdef DEBUG_QVTKOPENGL_WIDGET - delete this->Logger; - this->Logger = new QOpenGLDebugLogger(this); - this->Logger->initialize(); // initializes in the current context. -#endif - - vtkmyQVTKOpenGLNativeWidgetDebugMacro("initializeGL"); - if (this->RenderWindow) - { - // use QSurfaceFormat for the widget, update ivars on the vtkRenderWindow. - myQVTKOpenGLNativeWidget::copyFromFormat(this->format(), this->RenderWindow); - // When a QOpenGLWidget is told to use a QSurfaceFormat with samples > 0, - // QOpenGLWidget doesn't actually create a context with multi-samples and - // internally changes the QSurfaceFormat to be samples=0. Thus, we can't - // rely on the QSurfaceFormat to indicate to us if multisampling is being - // used. We should use glGetRenderbufferParameteriv(..) to get - // GL_RENDERBUFFER_SAMPLES to determine the samples used. This is done by - // in recreateFBO(). - } - this->connect( - this->context(), SIGNAL(aboutToBeDestroyed()), SLOT(cleanupContext()), Qt::UniqueConnection); - this->requireRenderWindowInitialization(); -} - -//----------------------------------------------------------------------------- -void myQVTKOpenGLNativeWidget::requireRenderWindowInitialization() -{ - if (this->RenderWindow) - { - this->RenderWindow->SetReadyForRendering(false); - } -} - -//----------------------------------------------------------------------------- -void myQVTKOpenGLNativeWidget::resizeGL(int w, int h) -{ - vtkmyQVTKOpenGLNativeWidgetDebugMacro("resizeGL"); - this->Superclass::resizeGL(w, h); -} - -//----------------------------------------------------------------------------- -void myQVTKOpenGLNativeWidget::paintGL() -{ - if (this->InPaintGL) - { - return; - } - - if (!this->RenderWindow) - { - return; - } - - if (!this->FBO - || this->FBO->handle() != this->RenderWindow->GetDefaultFrameBufferId()) - { - this->recreateFBO(); - } - - QScopedValueRollback var(this->InPaintGL, true); - this->Superclass::paintGL(); - - if (this->DoVTKRenderInPaintGL && !this->renderVTK()) - { - vtkmyQVTKOpenGLNativeWidgetDebugMacro("paintGL:skipped-renderVTK"); - // This should be very rare, but it's conceivable that subclasses of - // myQVTKOpenGLNativeWidget are simply not ready to do a - // render on VTK render window when widget is being painted. - // Leave the buffer unchanged. - return; - } - - // We just did a render, if we needed it. Turn the flag off. - this->DoVTKRenderInPaintGL = false; - - // If render was triggered by above calls, that may change the current context - // due to things like progress events triggering updates on other widgets - // (e.g. progress bar). Hence we need to make sure to call makeCurrent() - // before proceeding with blit-ing. - this->makeCurrent(); - - // blit from this->FBO to QOpenGLWidget's FBO. - vtkmyQVTKOpenGLNativeWidgetDebugMacro("paintGL::blit-to-defaultFBO"); - QOpenGLFunctions_3_2_Core* f = - QOpenGLContext::currentContext()->versionFunctions(); - if (f) - { - vtkOpenGLState *ostate = this->RenderWindow->GetState(); - - f->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, this->defaultFramebufferObject()); - f->glDrawBuffer(GL_COLOR_ATTACHMENT0); - - f->glBindFramebuffer(GL_READ_FRAMEBUFFER, this->FBO->handle()); - f->glReadBuffer(GL_COLOR_ATTACHMENT0); - - // The viewport state may be modified outside the vtkOpenGLState mechanism, so reset the state here. - ostate->ResetGlViewportState(); - - // If you get a vtkOpenGLState warning from the call below, you can add - // a call to ostate->ResetEnumState(GL_SCISSOR_TEST); to reset the cache state - // to whatever the value in OpenGL is. - ostate->vtkglDisable(GL_SCISSOR_TEST); // Scissor affects glBindFramebuffer. - f->glBlitFramebuffer(0, 0, this->RenderWindow->GetSize()[0], this->RenderWindow->GetSize()[1], - 0, 0, this->RenderWindow->GetSize()[0], this->RenderWindow->GetSize()[1], GL_COLOR_BUFFER_BIT, - GL_NEAREST); - - // now clear alpha otherwise we end up blending the rendering with - // background windows in certain cases. It happens on OsX - // (if QSurfaceFormat::alphaBufferSize() > 0) or when using Mesa on Linux - // (see paraview/paraview#17159). - GLboolean colorMask[4]; - f->glGetBooleanv(GL_COLOR_WRITEMASK, colorMask); - f->glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE); - - GLfloat clearColor[4]; - f->glGetFloatv(GL_COLOR_CLEAR_VALUE, clearColor); - f->glClearColor(0.0f, 0.0f, 0.0f, 1.0f); - f->glClear(GL_COLOR_BUFFER_BIT); - - f->glColorMask(colorMask[0], colorMask[1], colorMask[2], colorMask[3]); - f->glClearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]); - } -} - -//----------------------------------------------------------------------------- -void myQVTKOpenGLNativeWidget::cleanupContext() -{ - // logger gets uninitialized when this gets called. We get errors from - // QOpenGLDebugLogger if logMessage is called here. So we just destroy the - // logger. - delete this->Logger; - this->Logger = nullptr; - - vtkmyQVTKOpenGLNativeWidgetDebugMacro("cleanupContext"); - - // QOpenGLWidget says when this slot is called, the context may not be current - // and hence is a good practice to make it so. - this->makeCurrent(); - if (this->RenderWindow) - { - if (this->FBO) - { - this->FBO->bind(); - } - this->RenderWindow->Finalize(); - this->RenderWindow->SetReadyForRendering(false); - } - delete this->FBO; - this->FBO = nullptr; - this->requireRenderWindowInitialization(); -} - -//----------------------------------------------------------------------------- -void myQVTKOpenGLNativeWidget::windowFrameEventCallback() -{ - Q_ASSERT(this->RenderWindow); - vtkmyQVTKOpenGLNativeWidgetDebugMacro("frame"); - - if (!this->InPaintGL) - { - // Handing vtkOpenGLRenderWindow::Frame is tricky. VTK code traditionally - // calls `Frame` to indicate that VTK is done rendering 1 frame. Now, when - // that happens, should we tell Qt to update the widget -- that's the - // question? In general, yes, but sometimes VTK does things in the - // background i.e. back buffer without wanting to update the front buffer - // e.g. when making selections. In that case, we don't want to update Qt - // widget either, since whatever it did was not meant to be visible. - // To handle that, we check if vtkOpenGLRenderWindow::SwapBuffers is true, - // and request an update only when it is. - if (this->RenderWindow->GetSwapBuffers() || this->RenderWindow->GetDoubleBuffer() == 0) - { - // Means that the vtkRenderWindow rendered outside a paintGL call. That can - // happen when application code call vtkRenderWindow::Render() directly, - // instead of calling myQVTKOpenGLNativeWidget::update() or letting Qt update the - // widget. In that case, since QOpenGLWidget rendering into an offscreen - // FBO, the result still needs to be composed by Qt widget stack. We request - // that using `update()`. - vtkmyQVTKOpenGLNativeWidgetDebugMacro("update"); - this->update(); - - this->DoVTKRenderInPaintGL = false; - } - else - { - vtkmyQVTKOpenGLNativeWidgetDebugMacro("buffer bad -- do not show"); - - // Since this->FBO right now is garbage, if paint event is received before - // a Render request is made on the render window, we will have to Render - // explicitly. - this->DoVTKRenderInPaintGL = true; - } - } -} - -//----------------------------------------------------------------------------- -bool myQVTKOpenGLNativeWidget::renderVTK() -{ - vtkmyQVTKOpenGLNativeWidgetDebugMacro("renderVTK"); - Q_ASSERT(this->FBO); - Q_ASSERT(this->FBO->handle() == this->RenderWindow->GetDefaultFrameBufferId()); - - // Bind the FBO we'll be rendering into. This may not be needed, since VTK will - // bind it anyways, but we'll be extra cautious. - this->FBO->bind(); - - vtkRenderWindowInteractor* iren = this->RenderWindow ? this->RenderWindow->GetInteractor() : nullptr; - if (iren) - { - iren->Render(); - } - else if (this->RenderWindow) - { - this->RenderWindow->Render(); - } - else - { - // no render window set, just fill with white. - QOpenGLFunctions* f = QOpenGLContext::currentContext()->functions(); - f->glClearColor(1.0f, 1.0f, 1.0f, 1.0f); - f->glClear(GL_COLOR_BUFFER_BIT); - } - return true; -} - -//----------------------------------------------------------------------------- -bool myQVTKOpenGLNativeWidget::event(QEvent* evt) -{ - switch (evt->type()) - { - //case QEvent::MouseMove: - //case QEvent::MouseButtonPress: - //case QEvent::MouseButtonRelease: - //case QEvent::MouseButtonDblClick: - // skip events that are explicitly handled by overrides to avoid duplicate - // calls to InteractorAdapter->ProcessEvent(). - //break; - - //case QEvent::Resize: - case QEvent::Wheel: - // we don't let QVTKInteractorAdapter process resize since we handle it - // in this->recreateFBO(). - break; - -#ifdef __APPLE__ - // On MacOS, because of https://bugreports.qt.io/browse/QTBUG-69644 - // It is needed to hide/show currently visible QVTKOpenGLWidget - // Just after initialization of myQVTKOpenGLNativeWidget - // This triggers a timer so as soon as Qt is able to process events, - // it will fix the broken QVTKOpenGLWidgets. - case QEvent::WindowActivate: - case QEvent::PolishRequest: - { - QWidget* window = this->window(); - QTimer::singleShot(1, [window]() {::QVTKOpenGLWidgetMacOSCheck(window); }); - } - break; -#endif // __APPLE__ - - default: - if (this->RenderWindow && this->RenderWindow->GetInteractor()) - { - this->InteractorAdapter->ProcessEvent(evt, this->RenderWindow->GetInteractor()); - } - } - return this->Superclass::event(evt); -} - -//----------------------------------------------------------------------------- -//void myQVTKOpenGLNativeWidget::wheelEvent(QWheelEvent *event) -//{ -// -// -//} -//----------------------------------------------------------------------------- -//void myQVTKOpenGLNativeWidget::mouseMoveEvent(QMouseEvent* event) -//{ -// //emit mouseEvent(event); -// -// //if (this->RenderWindow && this->RenderWindow->GetInteractor()) -// //{ -// // this->InteractorAdapter->ProcessEvent(event, -// // this->RenderWindow->GetInteractor()); -// //} -//} - -//----------------------------------------------------------------------------- -//void myQVTKOpenGLNativeWidget::mouseReleaseEvent(QMouseEvent* event) -//{ -// //emit mouseEvent(event); -// -// //if (this->RenderWindow && this->RenderWindow->GetInteractor()) -// //{ -// // this->InteractorAdapter->ProcessEvent(event, -// // this->RenderWindow->GetInteractor()); -// //} -//} - -//----------------------------------------------------------------------------- -//void myQVTKOpenGLNativeWidget::mouseDoubleClickEvent(QMouseEvent* event) -//{ -// //emit mouseEvent(event); -// -// //if (this->RenderWindow && this->RenderWindow->GetInteractor()) -// //{ -// // this->InteractorAdapter->ProcessEvent(event, -// // this->RenderWindow->GetInteractor()); -// //} -//} - -//----------------------------------------------------------------------------- -void myQVTKOpenGLNativeWidget::cursorChangedCallback(vtkObject*, unsigned long, - void*, void* call_data) -{ - if (!this->RenderWindow) - { - return; - } - - int* cShape = reinterpret_cast (call_data); - if (!cShape) - { - return; - } - - switch (*cShape) - { - case VTK_CURSOR_CROSSHAIR: - this->setCursor(QCursor(Qt::CrossCursor)); - break; - case VTK_CURSOR_SIZEALL: - this->setCursor(QCursor(Qt::SizeAllCursor)); - break; - case VTK_CURSOR_SIZENS: - this->setCursor(QCursor(Qt::SizeVerCursor)); - break; - case VTK_CURSOR_SIZEWE: - this->setCursor(QCursor(Qt::SizeHorCursor)); - break; - case VTK_CURSOR_SIZENE: - this->setCursor(QCursor(Qt::SizeBDiagCursor)); - break; - case VTK_CURSOR_SIZENW: - this->setCursor(QCursor(Qt::SizeFDiagCursor)); - break; - case VTK_CURSOR_SIZESE: - this->setCursor(QCursor(Qt::SizeFDiagCursor)); - break; - case VTK_CURSOR_SIZESW: - this->setCursor(QCursor(Qt::SizeBDiagCursor)); - break; - case VTK_CURSOR_HAND: - this->setCursor(QCursor(Qt::PointingHandCursor)); - break; - case VTK_CURSOR_ARROW: - default: - this->setCursor(QCursor(Qt::ArrowCursor)); - break; - } -} diff --git a/src/src/view/viewcontainerwidget.cpp b/src/src/view/viewcontainerwidget.cpp index 96ab8e7..8126cb3 100644 --- a/src/src/view/viewcontainerwidget.cpp +++ b/src/src/view/viewcontainerwidget.cpp @@ -207,7 +207,7 @@ void ViewContainerWidget::Slot_SyncEvent(DicomImageView *view, int interactionMo void ViewContainerWidget::SetInteractionMode(int InteractionMode) { for (auto *v : view_list_) { - myQVTKOpenGLNativeWidget*gl_w = v->getGLWidget(); + QVTKOpenGLNativeWidget*gl_w = v->getGLWidget(); if (gl_w->GetRenderWindow() && gl_w->GetRenderWindow()->GetInteractor() && v->HasSeries()) { infinitiViewer* viewer = v->getSeriesInstance()->getImageViewer2();