2.12.2021, 9:00 - 11:00: Due to updates GitLab may be unavailable for some minutes between 09:00 and 11:00.

Commit 7e5e44b1 authored by Artur Grunau's avatar Artur Grunau
Browse files

Refactor VisualizationPipelineWrapper and rename it MdiDockArea

VisualizationPipelineWrapper has been renamed MdiDockArea, and refactored
to make it easier to use it with arbitrary widgets. It now inherits from
QMdiArea, which removes an unnecessary layer of indirection. Moreover, it
creates MDI subwindows and floating windows only if necessary, i.e. when
a widget stored in it changes state.
parent 75d4690b
......@@ -36,9 +36,9 @@ SET(CampvisApplicationToBeMocced
gui/qtdatahandle.h
gui/logviewerwidget.h
gui/loghighlighter.h
gui/mdidockarea.h
gui/pipelinemdisubwindow.h
gui/visualizationpipelinewidget.h
gui/visualizationpipelinewrapper.h
gui/adjusterwidgets/doubleadjusterwidget.h
gui/adjusterwidgets/intadjusterwidget.h
gui/properties/abstractpropertywidget.h
......
......@@ -34,7 +34,6 @@
#include "application/gui/datacontainerinspectorwidget.h"
#include "application/gui/datacontainerinspectorcanvas.h"
#include "application/gui/qtdatahandle.h"
#include "application/gui/visualizationpipelinewrapper.h"
#include "core/datastructures/datacontainer.h"
#include "core/pipeline/abstractpipeline.h"
#include "core/pipeline/abstractprocessor.h"
......@@ -86,7 +85,7 @@ namespace campvis {
setTabPosition(Qt::TopDockWidgetArea, QTabWidget::North);
_mdiArea = new QMdiArea();
_mdiArea = new MdiDockArea();
_mdiArea->tileSubWindows();
setCentralWidget(_mdiArea);
......@@ -260,7 +259,9 @@ namespace campvis {
}
void MainWindow::addVisualizationPipelineWidget(const std::string& name, QWidget* canvas) {
VisualizationPipelineWrapper* widget = new VisualizationPipelineWrapper(name, canvas, _mdiArea, this);
QMdiSubWindow* mdiSubWindow = _mdiArea->addSubWindow(canvas);
const QString& windowTitle = QString::fromStdString(name);
mdiSubWindow->setWindowTitle(windowTitle);
}
QDockWidget* MainWindow::dockPrimaryWidget(const std::string& name, QWidget* widget) {
......
......@@ -32,6 +32,7 @@
#include "sigslot/sigslot.h"
#include "application/campvisapplication.h"
#include "application/gui/mdidockarea.h"
#include "application/gui/pipelinetreewidget.h"
#include "application/gui/properties/propertycollectionwidget.h"
#include "application/gui/logviewerwidget.h"
......@@ -43,7 +44,6 @@
#include <QHBoxLayout>
#include <QPushButton>
#include <QComboBox>
#include <QMdiArea>
#include <QScrollArea>
#include <vector>
......@@ -163,7 +163,7 @@ namespace campvis {
CampVisApplication* _application; ///< Pointer to the application hosting the whole stuff
QMdiArea* _mdiArea; ///< MDI area (the window's central widget)
MdiDockArea* _mdiArea; ///< MDI area (the window's central widget)
QWidget* _containerWidget; ///< Widget to manage the app's DataContainers and pipelines
QComboBox* _cbPipelineFactory; ///< Combobox for selecting the Pipelines from the PipelineFactory
QPushButton* _btnPipelineFactory; ///< Button to add a Pipeline from the factory
......
......@@ -27,71 +27,70 @@
//
// ================================================================================================
#include "visualizationpipelinewrapper.h"
#include "mdidockarea.h"
namespace campvis {
VisualizationPipelineWrapper::VisualizationPipelineWrapper(const std::string& name, QWidget* canvas,
QMdiArea* mdiArea, QObject* parent /*= 0*/)
: QObject(parent)
, _mdiArea(mdiArea)
{
_pipelineWidget = new VisualizationPipelineWidget(canvas);
_mdiSubWindow = new PipelineMdiSubWindow();
PipelineMdiSubWindow* MdiDockArea::addSubWindow(QWidget* widget, Qt::WindowFlags windowFlags /*= 0*/) {
PipelineMdiSubWindow* mdiSubWindow = new PipelineMdiSubWindow;
_mdiSubWindow->setWidget(_pipelineWidget);
mdiArea->addSubWindow(_mdiSubWindow);
mdiSubWindow->setWidget(widget);
QMdiArea::addSubWindow(mdiSubWindow, windowFlags);
widget->show();
this->tileSubWindows();
const QString& windowTitle = QString::fromStdString(name);
_mdiSubWindow->setWindowTitle(windowTitle);
_pipelineWidget->setWindowTitle(windowTitle);
_pipelineWidget->show();
_mdiArea->tileSubWindows();
connect(mdiSubWindow, SIGNAL(s_positionChanged(PipelineMdiSubWindow*, const QPoint&)),
this, SLOT(trackMdiSubWindowsPosition(PipelineMdiSubWindow*, const QPoint&)));
connect(_mdiSubWindow, SIGNAL(s_positionChanged(const QPoint&)),
this, SLOT(trackMdiSubWindowsPosition(const QPoint&)));
connect(_pipelineWidget, SIGNAL(s_positionChanged(const QPoint&)),
this, SLOT(trackFloatingWindowsPosition(const QPoint&)));
return mdiSubWindow;
}
void VisualizationPipelineWrapper::trackFloatingWindowsPosition(const QPoint& newPos) {
const QRect& widgetGeometry = _pipelineWidget->frameGeometry();
const QRect& mdiAreaRect = _mdiArea->contentsRect();
const QRect mdiAreaGeometry(_mdiArea->mapToGlobal(mdiAreaRect.topLeft()),
_mdiArea->mapToGlobal(mdiAreaRect.bottomRight()));
void MdiDockArea::trackFloatingWindowsPosition(VisualizationPipelineWidget* pipelineWidget, const QPoint& newPos) {
const QRect& widgetGeometry = pipelineWidget->frameGeometry();
const QRect& mdiAreaRect = this->contentsRect();
const QRect mdiAreaGeometry(this->mapToGlobal(mdiAreaRect.topLeft()),
this->mapToGlobal(mdiAreaRect.bottomRight()));
const QRect& intersection = widgetGeometry & mdiAreaGeometry;
// Dock the widget if at least 60% of it is over the MDI area
if (widgetGeometry.width() * widgetGeometry.height() * 3 <
intersection.width() * intersection.height() * 5) {
_pipelineWidget->stopWindowDrag();
pipelineWidget->stopWindowDrag();
_mdiSubWindow->setWidget(_pipelineWidget);
_mdiArea->addSubWindow(_mdiSubWindow);
_pipelineWidget->show();
QWidget* widget = pipelineWidget->canvas();
PipelineMdiSubWindow* mdiSubWindow = this->addSubWindow(widget);
mdiSubWindow->setWindowTitle(pipelineWidget->windowTitle());
widget->show();
pipelineWidget->deleteLater();
_mdiSubWindow->move(_mdiArea->mapFromGlobal(newPos));
_mdiSubWindow->grabMouse();
mdiSubWindow->move(this->mapFromGlobal(newPos));
mdiSubWindow->grabMouse();
}
}
void VisualizationPipelineWrapper::trackMdiSubWindowsPosition(const QPoint& newPos) {
const QRect& subWindowGeometry = _mdiSubWindow->frameGeometry();
const QRect& mdiAreaGeometry = _mdiArea->contentsRect();
void MdiDockArea::trackMdiSubWindowsPosition(PipelineMdiSubWindow *mdiSubWindow, const QPoint& newPos) {
const QRect& subWindowGeometry = mdiSubWindow->frameGeometry();
const QRect& mdiAreaGeometry = contentsRect();
const QRect& intersection = subWindowGeometry & mdiAreaGeometry;
// Detach the subwindow if at least 60% of it has left the MDI area
if (subWindowGeometry.width() * subWindowGeometry.height() * 2 >
intersection.width() * intersection.height() * 5) {
_mdiSubWindow->stopWindowDrag();
_mdiSubWindow->setWidget(0);
_mdiArea->removeSubWindow(_mdiSubWindow);
_mdiArea->tileSubWindows();
QWidget* widget = mdiSubWindow->widget();
mdiSubWindow->stopWindowDrag();
mdiSubWindow->setWidget(0);
removeSubWindow(mdiSubWindow);
mdiSubWindow->deleteLater();
tileSubWindows();
VisualizationPipelineWidget* pipelineWidget = new VisualizationPipelineWidget(widget);
pipelineWidget->setWindowTitle(mdiSubWindow->windowTitle());
pipelineWidget->move(this->mapToGlobal(newPos));
pipelineWidget->show();
pipelineWidget->forceWindowDrag();
_pipelineWidget->move(_mdiArea->mapToGlobal(newPos));
_pipelineWidget->show();
_pipelineWidget->forceWindowDrag();
connect(pipelineWidget, SIGNAL(s_positionChanged(VisualizationPipelineWidget*, const QPoint&)),
this, SLOT(trackFloatingWindowsPosition(VisualizationPipelineWidget*, const QPoint&)));
}
}
......
......@@ -27,8 +27,8 @@
//
// ================================================================================================
#ifndef VISUALIZATIONPIPELINEWRAPPER_H__
#define VISUALIZATIONPIPELINEWRAPPER_H__
#ifndef MDIDOCKAREA_H__
#define MDIDOCKAREA_H__
#include "pipelinemdisubwindow.h"
#include "visualizationpipelinewidget.h"
......@@ -38,30 +38,28 @@
namespace campvis {
/**
* Display wrapper for visualization pipelines.
* MDI area whose subwindows can be docked and undocked.
*
* VisualizationPipelineWrapper takes care of creating all necessary representations (widget,
* MDI subwindow) of a visualization pipeline and seamlessly switching between them in
* response to the user's actions (window dragging, key presses, etc).
* MdiDockArea takes care of creating all necessary representations (floating window, MDI
* subwindow) of the widgets passed to \ref addSubWindow and seamlessly switching between them
* in response to the user's actions (window dragging, key presses, etc).
*/
class VisualizationPipelineWrapper : public QObject {
class MdiDockArea : public QMdiArea {
Q_OBJECT
public:
/**
* Construct a wrapper for a visualization pipeline.
* Wrap \p widget in an MDI subwindow and dock it in the MDI area.
*
* This constructor creates a widget for the visualization pipeline it's passed. It then
* adds it to an MDI subwindow, and places it in the specified MDI area.
* This method creates a PipelineMdiSubWindow wrapping the widget it's passed, and adds it
* to the MDI area.
*
* \param name the name of the visualization pipeline
* \param canvas the pipeline's canvas
* \param mdiArea the MDI are to which the widget should be added
* \param parent the widget's parent
* \param widget the widget to add to the MDI area
* \param windowFlags flags used to customize the frame of the created subwindow
* \return the PipelineMdiSubWindow instance that was added to the MDI area
*/
VisualizationPipelineWrapper(const std::string& name, QWidget* canvas,
QMdiArea* mdiArea, QObject* parent = 0);
PipelineMdiSubWindow* addSubWindow(QWidget* widget, Qt::WindowFlags windowFlags = 0);
private slots:
/**
......@@ -69,21 +67,16 @@ namespace campvis {
*
* This slot is invoked when the pipeline's widget is floating and its position changes.
*/
void trackFloatingWindowsPosition(const QPoint& newPos);
void trackFloatingWindowsPosition(VisualizationPipelineWidget* pipelineWidget, const QPoint& newPos);
/**
* Track the position of the pipeline's MDI subwindow and detach it if necessary.
*
* This slot is invoked when the position of the pipeline's MDI subwindow changes.
*/
void trackMdiSubWindowsPosition(const QPoint& newPos);
private:
QMdiArea* _mdiArea; ///< The MDI area associated with the widget
PipelineMdiSubWindow* _mdiSubWindow; ///< An MDI subwindow for the pipeline
VisualizationPipelineWidget* _pipelineWidget; ///< A widget for the pipeline
void trackMdiSubWindowsPosition(PipelineMdiSubWindow* mdiSubWindow, const QPoint& newPos);
};
}
#endif // VISUALIZATIONPIPELINEWRAPPER_H__
#endif // MDIDOCKAREA_H__
......@@ -74,7 +74,7 @@ namespace campvis {
}
move(newPos);
emit s_positionChanged(newPos);
emit s_positionChanged(this, newPos);
}
else {
QMdiSubWindow::mouseMoveEvent(event);
......
......@@ -70,7 +70,7 @@ namespace campvis {
*
* \param newPos the subwindow's new position
*/
void s_positionChanged(const QPoint& newPos);
void s_positionChanged(PipelineMdiSubWindow* mdiSubWindow, const QPoint& newPos);
protected:
/**
......
......@@ -37,6 +37,7 @@ namespace campvis {
VisualizationPipelineWidget::VisualizationPipelineWidget(QWidget* canvas, QWidget* parent /*= 0*/)
: QWidget(parent)
, _canvas(canvas)
, _dragActive(false)
, _lastMousePos()
{
......@@ -62,6 +63,10 @@ namespace campvis {
}
}
QWidget* VisualizationPipelineWidget::canvas() {
return _canvas;
}
void VisualizationPipelineWidget::mouseMoveEvent(QMouseEvent* event) {
const QPoint& mousePos = event->globalPos();
const QPoint& newPos = pos() + (mousePos - _lastMousePos);
......@@ -77,7 +82,7 @@ namespace campvis {
}
void VisualizationPipelineWidget::moveEvent(QMoveEvent* /*event*/) {
emit s_positionChanged(frameGeometry().topLeft());
emit s_positionChanged(this, frameGeometry().topLeft());
}
}
......@@ -75,13 +75,18 @@ namespace campvis {
*/
void stopWindowDrag();
/**
* Return the canvas this widget wraps.
*/
QWidget* canvas();
signals:
/**
* Emitted when the widget's position changes.
*
* \param newPos the widget's new position
*/
void s_positionChanged(const QPoint& newPos);
void s_positionChanged(VisualizationPipelineWidget *pipelineWidget, const QPoint& newPos);
protected:
/**
......@@ -100,6 +105,7 @@ namespace campvis {
virtual void moveEvent(QMoveEvent* event);
private:
QWidget* _canvas; ///< The canvas this widget wraps
bool _dragActive; ///< Is the widget currently being dragged?
QPoint _lastMousePos; ///< Last reported mouse position
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment