diff --git a/Modules/Overlays/QmitkOverlayController.cpp b/Modules/Overlays/QmitkOverlayController.cpp index 94c4b189a1..ab8261eee0 100644 --- a/Modules/Overlays/QmitkOverlayController.cpp +++ b/Modules/Overlays/QmitkOverlayController.cpp @@ -1,468 +1,460 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkOverlayController.h" #include "QmitkRenderWindow.h" #include "QmitkOverlay.h" #include #include #include QmitkOverlayController::QmitkOverlayController( QmitkRenderWindow* rw, mitk::PropertyList* pl ) : QObject(), m_RenderWindow( rw ), m_PropertyList( pl ) { if ( m_RenderWindow == NULL ) { MITK_ERROR << "invalid QmitkRenderWindow"; return; } - qRegisterMetaType( "QmitkOverlay::DisplayPosition" ); - - connect( this, SIGNAL( InternalAdjustOverlayPosition( QmitkOverlay::DisplayPosition ) ), - this, SLOT( AdjustOverlayPosition( QmitkOverlay::DisplayPosition ) ), Qt::QueuedConnection ); - connect( rw, SIGNAL( moved() ), this, SLOT( AdjustAllOverlayPosition() ) ); this->InitializeOverlayLayout(); this->AdjustAllOverlayPosition(); this->SetOverlayVisibility( true ); if ( m_PropertyList.IsNull() ) m_PropertyList = mitk::PropertyList::New(); } QmitkOverlayController::~QmitkOverlayController() { } void QmitkOverlayController::InitializeOverlayLayout() { // setup widget for each position this->InitializeWidget( QmitkOverlay::top_Left ); this->InitializeWidget( QmitkOverlay::top_Center ); this->InitializeWidget( QmitkOverlay::top_Right ); this->InitializeWidget( QmitkOverlay::middle_Left ); this->InitializeWidget( QmitkOverlay::middle_Right ); this->InitializeWidget( QmitkOverlay::bottom_Left ); this->InitializeWidget( QmitkOverlay::bottom_Center ); this->InitializeWidget( QmitkOverlay::bottom_Right ); } void QmitkOverlayController::InitializeWidget( QmitkOverlay::DisplayPosition pos ) { // create a new QWidget as Tool & FramelessWindowHint m_PositionedOverlays[ pos ] = new QWidget( m_RenderWindow, Qt::Tool | Qt::FramelessWindowHint ); // autoFillBackGround(false) and WA_TranslucentBackground = true are needed to have a translucent background // transparency does NOT work under Win-XP 32-Bit --> paint black background #if !defined(_WIN32) || defined(_WIN64) m_PositionedOverlays[ pos ]->setAttribute( Qt::WA_TranslucentBackground, true ); #else m_PositionedOverlays[ pos ]->setStyleSheet( "QWidget { background: black }" ); m_PositionedOverlays[ pos ]->setAttribute( Qt::WA_TranslucentBackground, false ); #endif // X11 specific attributes m_PositionedOverlays[ pos ]->setAttribute( Qt::WA_X11NetWmWindowTypeUtility, true ); // mac-specific attributes: // making sure overlays are even visible if RenderWindow does not have the focus (not default for Qt::Tool on mac) m_PositionedOverlays[ pos ]->setAttribute( Qt::WA_MacAlwaysShowToolWindow, true ); // testing something m_PositionedOverlays[ pos ]->setAttribute( Qt::WA_MacShowFocusRect, false ); // overlays should not get the focus m_PositionedOverlays[ pos ]->setFocusPolicy( Qt::NoFocus ); // setting the color of the background to transparent - not sure it's needed after the attributes have been set above QPalette p = QPalette(); p.setColor( QPalette::Window, Qt::transparent ); m_PositionedOverlays[ pos ]->setPalette( p ); // setting position-specific properties switch ( pos ) { case QmitkOverlay::top_Left : { // adding left-aligned top-to-bottom layout QVBoxLayout* layout = new QVBoxLayout( m_PositionedOverlays[ pos ] ); layout->setDirection( QBoxLayout::TopToBottom ); layout->setAlignment( Qt::AlignLeft ); m_PositionedOverlays[ pos ]->layout()->setSpacing( 0 ); break; } case QmitkOverlay::top_Center : { // adding center-aligned top-to-bottom layout QVBoxLayout* layout = new QVBoxLayout( m_PositionedOverlays[ pos ] ); layout->setDirection( QBoxLayout::TopToBottom ); layout->setAlignment( Qt::AlignCenter ); layout->setAlignment( Qt::AlignLeft ); m_PositionedOverlays[ pos ]->layout()->setSpacing( 0 ); break; } case QmitkOverlay::top_Right : { // adding right-aligned top-to-bottom layout QVBoxLayout* layout = new QVBoxLayout( m_PositionedOverlays[ pos ] ); layout->setDirection( QBoxLayout::TopToBottom ); layout->setAlignment( Qt::AlignRight ); m_PositionedOverlays[ pos ]->layout()->setSpacing( 0 ); break; } case QmitkOverlay::middle_Left : { // adding left-aligned left-to-right layout QHBoxLayout* layout = new QHBoxLayout( m_PositionedOverlays[ pos ] ); layout->setDirection( QBoxLayout::LeftToRight ); layout->setAlignment( Qt::AlignLeft ); layout->setSpacing( 3 ); break; } case QmitkOverlay::middle_Right : { // adding right-aligned right-to-left layout QHBoxLayout* layout = new QHBoxLayout( m_PositionedOverlays[ pos ] ); layout->setDirection( QBoxLayout::RightToLeft ); layout->setAlignment( Qt::AlignRight ); layout->setSpacing( 3 ); break; } case QmitkOverlay::bottom_Left : { // adding left-aligned bottom-to-top layout QVBoxLayout* layout = new QVBoxLayout( m_PositionedOverlays[ pos ] ); layout->setDirection( QBoxLayout::BottomToTop ); layout->setAlignment( Qt::AlignLeft ); m_PositionedOverlays[ pos ]->layout()->setSpacing( 0 ); break; } case QmitkOverlay::bottom_Center : { QVBoxLayout* layout = new QVBoxLayout( m_PositionedOverlays[ pos ] ); layout->setDirection( QBoxLayout::BottomToTop ); layout->setAlignment( Qt::AlignCenter ); m_PositionedOverlays[ pos ]->layout()->setSpacing( 0 ); break; } case QmitkOverlay::bottom_Right : { QVBoxLayout* layout = new QVBoxLayout( m_PositionedOverlays[ pos ] ); layout->setDirection( QBoxLayout::BottomToTop ); layout->setAlignment( Qt::AlignRight ); m_PositionedOverlays[ pos ]->layout()->setSpacing( 0 ); break; } } } void QmitkOverlayController::AdjustAllOverlayPosition() { AdjustOverlayPosition( QmitkOverlay::top_Left ); AdjustOverlayPosition( QmitkOverlay::top_Center ); AdjustOverlayPosition( QmitkOverlay::top_Right ); AdjustOverlayPosition( QmitkOverlay::middle_Left ); AdjustOverlayPosition( QmitkOverlay::middle_Right ); AdjustOverlayPosition( QmitkOverlay::bottom_Left ); AdjustOverlayPosition( QmitkOverlay::bottom_Center ); AdjustOverlayPosition( QmitkOverlay::bottom_Right ); } void QmitkOverlayController::AdjustOverlayPosition( QmitkOverlay::DisplayPosition displayPosition ) { QWidget* widget; QPoint pos; switch (displayPosition) { case QmitkOverlay::top_Left: { // setting position of top-left overlay-container pos = m_RenderWindow->mapToGlobal( QPoint(0,0) ); m_PositionedOverlays[ QmitkOverlay::top_Left ]->move( pos.x(), pos.y() ); break; } case QmitkOverlay::top_Center: { // setting position of top-center overlay-container widget = m_PositionedOverlays[ QmitkOverlay::top_Center ]; pos = m_RenderWindow->mapToGlobal( QPoint( m_RenderWindow->size().width()/2, 0 ) ) ; widget->move( pos.x() - widget->size().width()/2, pos.y() ); break; } case QmitkOverlay::top_Right: { // setting position of top-right overlay-container widget = m_PositionedOverlays[ QmitkOverlay::top_Right ]; pos = m_RenderWindow->mapToGlobal( QPoint( m_RenderWindow->size().width(), 0 ) ) ; widget->move( pos.x() - widget->size().width(), pos.y() ); break; } case QmitkOverlay::middle_Left: { // setting position of middle-left overlay-container widget = m_PositionedOverlays[ QmitkOverlay::middle_Left ]; pos = m_RenderWindow->mapToGlobal( QPoint( 0, m_RenderWindow->size().height()/2 ) ) ; widget->move( pos.x(), pos.y() - widget->size().height()/2 ); break; } case QmitkOverlay::middle_Right: { // setting position of middle-right overlay-container widget = m_PositionedOverlays[ QmitkOverlay::middle_Right ]; pos = m_RenderWindow->mapToGlobal( QPoint( m_RenderWindow->size().width(), m_RenderWindow->size().height()/2 ) ) ; widget->move( pos.x() - widget->size().width(), pos.y() - widget->size().height()/2 ); break; } case QmitkOverlay::bottom_Left: { // setting position of bottom-left overlay-container widget = m_PositionedOverlays[ QmitkOverlay::bottom_Left ]; pos = m_RenderWindow->mapToGlobal( QPoint( 0, m_RenderWindow->size().height() ) ) ; widget->move( pos.x(), pos.y() - widget->size().height() ); break; } case QmitkOverlay::bottom_Center: { // setting position of bottom-center overlay-container widget = m_PositionedOverlays[ QmitkOverlay::bottom_Center ]; pos = m_RenderWindow->mapToGlobal( QPoint( m_RenderWindow->size().width()/2, m_RenderWindow->size().height() ) ) ; widget->move( pos.x() - widget->size().width()/2, pos.y() - widget->size().height() ); break; } case QmitkOverlay::bottom_Right: { // setting position of bottom-right overlay-container widget = m_PositionedOverlays[ QmitkOverlay::bottom_Right ]; pos = m_RenderWindow->mapToGlobal( QPoint( m_RenderWindow->size().width(), m_RenderWindow->size().height() ) ) ; widget->move( pos.x() - widget->size().width(), pos.y() - widget->size().height() ); break; } } } void QmitkOverlayController::SetOverlayVisibility( bool visible ) { OverlayPositionMap::iterator overlayIter; for ( overlayIter=m_PositionedOverlays.begin(); overlayIter!=m_PositionedOverlays.end(); overlayIter++ ) { if ( visible ) { (overlayIter->second)->show(); } else { (overlayIter->second)->hide(); } } OverlayVector::iterator allOverlaysIter; for( allOverlaysIter=m_AllOverlays.begin(); allOverlaysIter!=m_AllOverlays.end(); allOverlaysIter++ ) { if ( visible ) { (*allOverlaysIter)->GetWidget()->show(); } else { (*allOverlaysIter)->GetWidget()->hide(); } } } void QmitkOverlayController::AddOverlay( QmitkOverlay* overlay ) { // if no renderwindow has been set, it's not possible to add overlays... if ( m_RenderWindow == NULL ) { MITK_ERROR << "invalid QmitkRenderWindow"; return; } if ( overlay != NULL ) { // get desired position and layer of the overlay QmitkOverlay::DisplayPosition pos = overlay->GetPosition(); // concatenate local propertyList and propertyList of the RenderingManager // local properties have priority as they are not overwritten if preset in both m_PropertyList->ConcatenatePropertyList( m_RenderWindow->GetRenderer()->GetRenderingManager()->GetPropertyList(), false ); // add the overlay to the OverlayContainer in the RenderWindow ... overlay->GetWidget()->setParent( m_PositionedOverlays[ pos ] ); // ... and set it up with the correct properties this->UpdateOverlayData( overlay ); // add overlay to list of all overlays and correctly put it into the layering m_AllOverlays.push_back( overlay ); this->RestackOverlays( pos ); // ... and reset the position of the widgets this->AdjustOverlayPosition( pos ); } } void QmitkOverlayController::UpdateOverlayData( QmitkOverlay* overlay ) { if ( overlay != NULL) { overlay->GenerateData( m_PropertyList ); + AdjustOverlayPosition( overlay->GetPosition() ); - // We trigger the re-adjusting of the overlay-positions - // by emitting this signal. It's a QueuedConnection, - // so Qt will have enough time to get the geometries right. - emit InternalAdjustOverlayPosition( overlay->GetPosition() ); } } void QmitkOverlayController::RemoveOverlay( QmitkOverlay* overlay ) { if ( overlay != NULL ) { // get desired position and layer of the overlay QmitkOverlay::DisplayPosition pos = overlay->GetPosition(); OverlayVector::iterator iter = std::find( m_AllOverlays.begin(), m_AllOverlays.end(), overlay ); if ( iter != m_AllOverlays.end() ) { m_AllOverlays.erase( iter ); overlay->GetWidget()->setParent( NULL ); overlay->GetWidget()->hide(); if ( m_PositionedOverlays[ pos ]->layout()->isEmpty() ) { m_PositionedOverlays[ pos ]->hide(); } else { this->RestackOverlays( pos ); // reset the position of the widgets this->AdjustOverlayPosition( pos ); } } overlay->deleteLater(); } } void QmitkOverlayController::AlignOverlays() { //OverlayVector::iterator overlayIter; //for ( overlayIter=m_AllOverlays.begin(); overlayIter!=m_AllOverlays.end(); overlayIter++ ) //{ // int stackLayer = dynamic_cast( m_PositionedOverlays[ (*overlayIter)->GetPosition() ]->layout() )->isEmpty() ? 0 : layer; // dynamic_cast( m_PositionedOverlays[ (*overlayIter)->GetPosition() ]->layout() )->addWidget( (*overlayIter)->GetWidget(), stackLayer, Qt::AlignLeft ); //} } void QmitkOverlayController::RestackOverlays( QmitkOverlay::DisplayPosition pos ) { OverlayVector::iterator overlayIter; QBoxLayout* layout = dynamic_cast( m_PositionedOverlays[ pos ]->layout() ); std::sort( m_AllOverlays.begin(), m_AllOverlays.end() ); for ( overlayIter=m_AllOverlays.begin(); overlayIter!=m_AllOverlays.end(); overlayIter++ ) { // do nothing if the overlay is not in the right position if ( (*overlayIter)->GetPosition() != pos ) { continue; } // determine the desired stacking layer // if the overlay-container is empty, simply append the overlay to the list // if it's not empty, use the layer of the overlay unsigned int layer = (*overlayIter)->GetLayer(); int stackLayer = 0; if ( !layout->isEmpty() ) { stackLayer = layer; } switch ( pos ) { // same alignment for all lefts, ... case QmitkOverlay::top_Left : {} case QmitkOverlay::middle_Left : {} case QmitkOverlay::bottom_Left : { layout->insertWidget( stackLayer, (*overlayIter)->GetWidget(), 0, Qt::AlignLeft ); break; } // ... for all centers, ... case QmitkOverlay::top_Center : {} case QmitkOverlay::bottom_Center : { layout->insertWidget( stackLayer, (*overlayIter)->GetWidget(), 0, Qt::AlignCenter ); break; } // ... and for all rights case QmitkOverlay::top_Right : {} case QmitkOverlay::middle_Right : {} case QmitkOverlay::bottom_Right : { layout->insertWidget( stackLayer, (*overlayIter)->GetWidget(), 0, Qt::AlignRight ); break; } } } } void QmitkOverlayController::UpdateAllOverlays() { foreach( QmitkOverlay* overlay, m_AllOverlays ) { this->UpdateOverlayData( overlay ); } } diff --git a/Modules/Overlays/QmitkOverlayController.h b/Modules/Overlays/QmitkOverlayController.h index 4c9e760eaa..974ab0805a 100644 --- a/Modules/Overlays/QmitkOverlayController.h +++ b/Modules/Overlays/QmitkOverlayController.h @@ -1,169 +1,164 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKOVERLAYCONTROLLER_H_HEADER_INCLUDED_C1E77191 #define MITKOVERLAYCONTROLLER_H_HEADER_INCLUDED_C1E77191 // MITK-Stuff #include "mitkCommon.h" #include "mitkPropertyList.h" #include "QmitkOverlay.h" #include #include #include "OverlaysExports.h" class QmitkRenderWindow; /** \class QmitkOverlayController * \brief controller that manages the positioning and stacking of QmitkOverlays * * This controller manages all QmitkOverlays of one QmitkRenderWindow. * * When constructed, it creates one QWidget for each possible display-position and sets the * appropriate attributes and layouts. * * It is possible to add new Overlays using AddOverlay( QmitkOverlay ). * This overlay will be added to the correct Widget according to its destined position (stored in QmitkOverlay). * If this widget already holds an overlay, the layer-property is taken into account. If no layer has been set, * the overlay will be appended at the end. * * It is possible to set the visibility of all overlays at a time using SetOverlayVisibility(bool). * * RenderWindow specific properties can be set using the internal mitk::PropertyList. This propertyList and the * 'default' propertyList of the RenderingManager will be concatenated before the overlay is set up. * If one property exists in both propertyLists, the one in the QmitkOverlayController will be used! * * \sa QmitkOverlay * \sa QmitkRenderWindow * \ingroup Qmitk */ class Overlays_EXPORT QmitkOverlayController : public QObject { Q_OBJECT public: /** * \brief constructor with mandatory QmitkRenderWindow and optional mitk::PropertyList */ QmitkOverlayController( QmitkRenderWindow* rw, mitk::PropertyList* pl = NULL ); virtual ~QmitkOverlayController(); /** * \brief adds an instance of QmitkOverlay to the RenderWindow * * This method adds the given QmitkOverlay as a sub-widget to the registered RenderWindow. * It will be added to the correct position in the RenderWindow as it's defined by the overlays * position-variable. The layer-property will only be considered if necessary. */ void AddOverlay( QmitkOverlay* ); void RemoveOverlay( QmitkOverlay* ); /** * \brief setting the visibility of all overlays */ void SetOverlayVisibility( bool visible ); /** * \brief getter for the RenderWindow-specific PropertyList */ mitk::PropertyList* GetPropertyList(); /** * \brief setter for the RenderWindow-specific PropertyList */ void SetPropertyList( mitk::PropertyList* ); public slots : /** * \brief adjusts the position of all overlays to the position of the RenderWindow * * This method updates the position of all Widgets according to the position of the RenderWindow * and the extend of the overlays. */ void AdjustAllOverlayPosition(); void AdjustOverlayPosition( QmitkOverlay::DisplayPosition displayPosition ); void UpdateAllOverlays(); void UpdateOverlayData( QmitkOverlay* overlay ); -signals: - - void InternalAdjustOverlayPosition( QmitkOverlay::DisplayPosition ); - - protected: /** * \brief setting up the widgets that will hold all overlays * * This method sets up the 8 QWidgets that will later hold all QmitkOverlays. * This includes the correct setting of layouts, alignments and the widget * attributes necessary to achieve a translucent background and correct rendering * on all platforms. */ void InitializeOverlayLayout(); /** * \brief re-aligning the overlays - not implemented yet */ virtual void AlignOverlays(); /** * \brief initializes one QWidget - internally used by InitializeOverlayLayout() */ void InitializeWidget( QmitkOverlay::DisplayPosition pos ); void RestackOverlays( QmitkOverlay::DisplayPosition pos ); typedef std::map< QmitkOverlay::DisplayPosition, QWidget* > OverlayPositionMap; typedef std::vector< QmitkOverlay* > OverlayVector; /** * \brief all QmitkOverlays that are currently added */ OverlayVector m_AllOverlays; /** * \brief all possible positions and the QWidgets representing the corresponding QmitkOverlays */ OverlayPositionMap m_PositionedOverlays; /** * \brief RenderWindow that all Overlays will be added to */ QmitkRenderWindow* m_RenderWindow; /** * \brief PropertyList for RenderWindow-specific properties */ mitk::PropertyList::Pointer m_PropertyList; }; #endif /* MITKOVERLAYCONTROLLER_H_HEADER_INCLUDED_C1E77191 */