mirror of
https://github.com/OpenFOAM/ThirdParty-6.git
synced 2025-12-08 06:57:43 +00:00
900 lines
27 KiB
C++
900 lines
27 KiB
C++
/*=========================================================================
|
|
|
|
Program: ParaView
|
|
Module: $RCSfile$
|
|
|
|
Copyright (c) 2005,2006 Sandia Corporation, Kitware Inc.
|
|
All rights reserved.
|
|
|
|
ParaView is a free software; you can redistribute it and/or modify it
|
|
under the terms of the ParaView license version 1.2.
|
|
|
|
See License_v1.2.txt for the full ParaView license.
|
|
A copy of this license can be obtained by contacting
|
|
Kitware Inc.
|
|
28 Corporate Drive
|
|
Clifton Park, NY 12065
|
|
USA
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR
|
|
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
========================================================================*/
|
|
#include "pqMultiViewWidget.h"
|
|
|
|
#include "pqActiveObjects.h"
|
|
#include "pqApplicationCore.h"
|
|
#include "pqEventDispatcher.h"
|
|
#include "pqInterfaceTracker.h"
|
|
#include "pqObjectBuilder.h"
|
|
#include "pqServerManagerModel.h"
|
|
#include "pqUndoStack.h"
|
|
#include "pqViewFrameActionsInterface.h"
|
|
#include "pqViewFrame.h"
|
|
#include "pqView.h"
|
|
#include "vtkCommand.h"
|
|
#include "vtkNew.h"
|
|
#include "vtkSMParaViewPipelineControllerWithRendering.h"
|
|
#include "vtkSMProperty.h"
|
|
#include "vtkSMViewLayoutProxy.h"
|
|
#include "vtkSMViewProxy.h"
|
|
#include "vtkWeakPointer.h"
|
|
|
|
#include <QVariant>
|
|
#include <QApplication>
|
|
#include <QFrame>
|
|
#include <QHBoxLayout>
|
|
#include <QMap>
|
|
#include <QPointer>
|
|
#include <QSplitter>
|
|
#include <QVBoxLayout>
|
|
#include <QVector>
|
|
|
|
class pqMultiViewWidget::pqInternals
|
|
{
|
|
public:
|
|
QVector<QPointer<QWidget> > Widgets;
|
|
|
|
// This map is used to avoid reassigning frames. Once a view is assigned a
|
|
// frame, we preserve that frame as long as possible.
|
|
QMap<vtkSMViewProxy*, QPointer<pqViewFrame> > ViewFrames;
|
|
|
|
unsigned long ObserverId;
|
|
vtkWeakPointer<vtkSMViewLayoutProxy> LayoutManager;
|
|
QPointer<pqViewFrame> ActiveFrame;
|
|
|
|
// Set to true to place views in a separate popout widget.
|
|
bool Popout;
|
|
QWidget PopoutFrame;
|
|
bool DecorationsVisibleBeforeCapture;
|
|
|
|
pqInternals(QWidget* self) :
|
|
ObserverId(0),
|
|
Popout(false),
|
|
PopoutFrame(self),
|
|
SavedButtons(pqViewFrame::NoButton)
|
|
{
|
|
this->PopoutFrame.setWindowFlags(Qt::Window|
|
|
Qt::CustomizeWindowHint|
|
|
Qt::WindowTitleHint|
|
|
Qt::WindowMaximizeButtonHint|
|
|
Qt::WindowCloseButtonHint);
|
|
this->DecorationsVisibleBeforeCapture = false;
|
|
}
|
|
|
|
~pqInternals()
|
|
{
|
|
if (this->LayoutManager && this->ObserverId)
|
|
{
|
|
this->LayoutManager->RemoveObserver(this->ObserverId);
|
|
}
|
|
}
|
|
|
|
void setMaximizedWidget(QWidget* wdg)
|
|
{
|
|
pqViewFrame* frame = qobject_cast<pqViewFrame*>(wdg);
|
|
if (frame)
|
|
{
|
|
this->SavedButtons = frame->standardButtons();
|
|
frame->setStandardButtons(pqViewFrame::Restore);
|
|
}
|
|
if (this->MaximizedWidget)
|
|
{
|
|
this->MaximizedWidget->setStandardButtons(
|
|
this->SavedButtons);
|
|
this->SavedButtons = pqViewFrame::NoButton;
|
|
}
|
|
this->MaximizedWidget = frame;
|
|
}
|
|
|
|
private:
|
|
QPointer<pqViewFrame> MaximizedWidget;
|
|
pqViewFrame::StandardButtons SavedButtons;
|
|
};
|
|
|
|
//-----------------------------------------------------------------------------
|
|
namespace
|
|
{
|
|
pqView* getPQView(vtkSMProxy* view)
|
|
{
|
|
if (view)
|
|
{
|
|
pqServerManagerModel* smmodel =
|
|
pqApplicationCore::instance()->getServerManagerModel();
|
|
return smmodel->findItem<pqView*>(view);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void ConnectFrameToView(pqViewFrame* frame, pqView* pqview)
|
|
{
|
|
Q_ASSERT(frame);
|
|
// if pqview == NULL, then the frame is either being assigned to a empty
|
|
// view, or pqview for a view-proxy just isn't present yet.
|
|
// it's possible that pqview is NULL, if the view proxy hasnt been registered
|
|
// yet. This happens often when initialization state is being loaded in
|
|
// collaborative sessions.
|
|
if (pqview != NULL)
|
|
{
|
|
QWidget* viewWidget = pqview->widget();
|
|
frame->setCentralWidget(viewWidget);
|
|
}
|
|
}
|
|
|
|
/// A simple subclass of QBoxLayout mimicking the layout style of a QSplitter
|
|
/// with just 2 widgets.
|
|
class pqSplitterLayout : public QBoxLayout
|
|
{
|
|
double SplitFraction;
|
|
public:
|
|
|
|
pqSplitterLayout(QBoxLayout::Direction dir, QWidget* parentWdg)
|
|
: QBoxLayout(dir, parentWdg), SplitFraction(0.5)
|
|
{
|
|
this->setContentsMargins(0, 0, 0,0);
|
|
this->setSpacing(0);
|
|
};
|
|
|
|
virtual ~pqSplitterLayout()
|
|
{
|
|
}
|
|
|
|
void setSplitFraction(double val) { this->SplitFraction = val; }
|
|
|
|
virtual void setGeometry(const QRect& rect)
|
|
{
|
|
this->QLayout::setGeometry(rect);
|
|
|
|
Q_ASSERT(this->count() <= 2);
|
|
|
|
int offset = 0;
|
|
double fractions[2] = { this->SplitFraction, 1.0 - this->SplitFraction };
|
|
for (int cc=0; cc < this->count(); cc++)
|
|
{
|
|
QLayoutItem* item = this->itemAt(cc);
|
|
if (this->direction() == LeftToRight)
|
|
{
|
|
item->setGeometry(
|
|
QRect(offset + rect.x(), rect.y(),
|
|
static_cast<int>(fractions[cc] * rect.width()), rect.height()));
|
|
offset += static_cast<int>(fractions[cc] * rect.width());
|
|
}
|
|
else if (this->direction() == TopToBottom)
|
|
{
|
|
item->setGeometry(
|
|
QRect(rect.x(), offset + rect.y(),
|
|
rect.width(), static_cast<int>(fractions[cc] * rect.height())));
|
|
offset += static_cast<int>(fractions[cc] * rect.height());
|
|
}
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
pqMultiViewWidget::pqMultiViewWidget(QWidget * parentObject, Qt::WindowFlags f)
|
|
: Superclass(parentObject, f),
|
|
Internals( new pqInternals(this)),
|
|
DecorationsVisible(true)
|
|
{
|
|
qApp->installEventFilter(this);
|
|
|
|
QObject::connect(&pqActiveObjects::instance(),
|
|
SIGNAL(viewChanged(pqView*)), this, SLOT(markActive(pqView*)));
|
|
|
|
pqApplicationCore* core = pqApplicationCore::instance();
|
|
pqServerManagerModel* smmodel = core->getServerManagerModel();
|
|
QObject::connect(smmodel, SIGNAL(proxyRemoved(pqProxy*)),
|
|
this, SLOT(proxyRemoved(pqProxy*)));
|
|
QObject::connect(smmodel, SIGNAL(viewAdded(pqView*)),
|
|
this, SLOT(viewAdded(pqView*)));
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
pqMultiViewWidget::~pqMultiViewWidget()
|
|
{
|
|
delete this->Internals;
|
|
this->Internals = NULL;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
bool pqMultiViewWidget::isViewAssigned(pqView* view) const
|
|
{
|
|
return (view && this->Internals->LayoutManager &&
|
|
this->Internals->LayoutManager->GetViewLocation(
|
|
view->getViewProxy()) != -1);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void pqMultiViewWidget::viewAdded(pqView* view)
|
|
{
|
|
if (view && this->Internals->LayoutManager &&
|
|
this->Internals->LayoutManager->GetViewLocation(
|
|
view->getViewProxy()) != -1)
|
|
{
|
|
// a pqview was created for a view that this layout knows about. we have to
|
|
// reload the layout to ensure that the view gets placed correctly.
|
|
pqViewFrame* frame = this->Internals->ViewFrames[view->getViewProxy()];
|
|
if (frame)
|
|
{
|
|
ConnectFrameToView(frame, view);
|
|
}
|
|
else
|
|
{
|
|
this->reload();
|
|
}
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void pqMultiViewWidget::setLayoutManager(vtkSMViewLayoutProxy* vlayout)
|
|
{
|
|
if (this->Internals->LayoutManager != vlayout)
|
|
{
|
|
if (this->Internals->LayoutManager)
|
|
{
|
|
this->Internals->LayoutManager->RemoveObserver(
|
|
this->Internals->ObserverId);
|
|
}
|
|
this->Internals->ObserverId = 0;
|
|
this->Internals->LayoutManager = vlayout;
|
|
if (vlayout)
|
|
{
|
|
this->Internals->ObserverId =
|
|
vlayout->AddObserver(vtkCommand::ConfigureEvent,
|
|
this, &pqMultiViewWidget::reload);
|
|
}
|
|
this->reload();
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
vtkSMViewLayoutProxy* pqMultiViewWidget::layoutManager() const
|
|
{
|
|
return this->Internals->LayoutManager;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
bool pqMultiViewWidget::eventFilter(QObject* caller, QEvent* evt)
|
|
{
|
|
if (evt->type() == QEvent::MouseButtonPress)
|
|
{
|
|
QWidget* wdg = qobject_cast<QWidget*>(caller);
|
|
if (wdg &&
|
|
( (!this->Internals->Popout && this->isAncestorOf(wdg)) ||
|
|
(this->Internals->Popout && this->Internals->PopoutFrame.isAncestorOf(wdg)))
|
|
)
|
|
{
|
|
// If the new widget that is getting the focus is a child widget of any of the
|
|
// frames, then the frame should be made active.
|
|
foreach (QWidget* frame_or_splitter, this->Internals->Widgets)
|
|
{
|
|
pqViewFrame* frame =
|
|
qobject_cast<pqViewFrame*>(frame_or_splitter);
|
|
if (frame && frame->isAncestorOf(wdg))
|
|
{
|
|
this->makeActive(frame);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (evt->type() == QEvent::Close &&
|
|
caller == &this->Internals->PopoutFrame)
|
|
{
|
|
// the popout-frame is being closed. We interpret that as "un-popping" the
|
|
// frame.
|
|
this->togglePopout();
|
|
}
|
|
|
|
return this->Superclass::eventFilter(caller, evt);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void pqMultiViewWidget::proxyRemoved(pqProxy* proxy)
|
|
{
|
|
vtkSMViewProxy* view = vtkSMViewProxy::SafeDownCast(proxy->getProxy());
|
|
if (view && this->Internals->ViewFrames.contains(view) && this->layoutManager())
|
|
{
|
|
this->layoutManager()->RemoveView(view);
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void pqMultiViewWidget::assignToFrame(pqView* view)
|
|
{
|
|
if (this->layoutManager() && view)
|
|
{
|
|
int active_index = 0;
|
|
if (this->Internals->ActiveFrame)
|
|
{
|
|
active_index =
|
|
this->Internals->ActiveFrame->property("FRAME_INDEX").toInt();
|
|
}
|
|
this->layoutManager()->AssignViewToAnyCell(view->getViewProxy(), active_index);
|
|
}
|
|
pqActiveObjects::instance().setActiveView(view);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void pqMultiViewWidget::makeFrameActive()
|
|
{
|
|
/// note pqMultiViewWidget::markActive(pqViewFrame*) fires a signal that
|
|
/// results in this method being called. So we need to ensure that we don't
|
|
/// do anything silly here that could cause infinite recursion.
|
|
if (!this->Internals->ActiveFrame)
|
|
{
|
|
foreach (QWidget* wdg, this->Internals->Widgets)
|
|
{
|
|
pqViewFrame* frame = qobject_cast<pqViewFrame*>(wdg);
|
|
if (frame)
|
|
{
|
|
this->makeActive(frame);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (this->layoutManager())
|
|
{
|
|
this->layoutManager()->ShowViewsOnTileDisplay();
|
|
}
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void pqMultiViewWidget::markActive(pqView* view)
|
|
{
|
|
if (view &&
|
|
this->Internals->ViewFrames.contains(view->getViewProxy()))
|
|
{
|
|
this->markActive(this->Internals->ViewFrames[view->getViewProxy()]);
|
|
}
|
|
else
|
|
{
|
|
this->markActive(static_cast<pqViewFrame*>(NULL));
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void pqMultiViewWidget::markActive(pqViewFrame* frame)
|
|
{
|
|
if (this->Internals->ActiveFrame)
|
|
{
|
|
this->Internals->ActiveFrame->setBorderVisibility(false);
|
|
}
|
|
this->Internals->ActiveFrame = frame;
|
|
if (frame)
|
|
{
|
|
frame->setBorderVisibility(true);
|
|
// indicate to the world that a frame on this widget has been activated.
|
|
// pqTabbedMultiViewWidget listens to this signal to raise that tab.
|
|
emit this->frameActivated();
|
|
// NOTE: this signal will result in call to makeFrameActive().
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void pqMultiViewWidget::makeActive(pqViewFrame* frame)
|
|
{
|
|
if (this->Internals->ActiveFrame != frame)
|
|
{
|
|
pqView* view = NULL;
|
|
if (frame)
|
|
{
|
|
int index = frame->property("FRAME_INDEX").toInt();
|
|
view = getPQView(this->layoutManager()->GetView(index));
|
|
}
|
|
pqActiveObjects::instance().setActiveView(view);
|
|
// this needs to called only when view == null since in that case when
|
|
// markActive(pqView*) slot is called, we have no idea what frame is really
|
|
// to be made active.
|
|
this->markActive(frame);
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void pqMultiViewWidget::lockViewSize(const QSize& viewSize)
|
|
{
|
|
if (this->LockViewSize != viewSize)
|
|
{
|
|
this->LockViewSize = viewSize;
|
|
this->reload();
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
pqViewFrame* pqMultiViewWidget::newFrame(vtkSMProxy* view)
|
|
{
|
|
pqViewFrame* frame = new pqViewFrame(this);
|
|
QObject::connect(frame, SIGNAL(buttonPressed(int)),
|
|
this, SLOT(standardButtonPressed(int)));
|
|
QObject::connect(frame, SIGNAL(swapPositions(const QString&)),
|
|
this, SLOT(swapPositions(const QString&)), Qt::QueuedConnection);
|
|
|
|
pqServerManagerModel* smmodel =
|
|
pqApplicationCore::instance()->getServerManagerModel();
|
|
pqView* pqview = smmodel->findItem<pqView*>(view);
|
|
// it's possible that pqview is NULL, if the view proxy hasnt been registered
|
|
// yet. This happens often when initialization state is being loaded in
|
|
// collaborative sessions.
|
|
ConnectFrameToView(frame, pqview);
|
|
|
|
// Search for view frame actions plugins and allow them to decide
|
|
// whether to add their actions to this view type's frame or not.
|
|
pqInterfaceTracker* tracker =
|
|
pqApplicationCore::instance()->interfaceTracker();
|
|
foreach (pqViewFrameActionsInterface* vfai,
|
|
tracker->interfaces<pqViewFrameActionsInterface*>())
|
|
{
|
|
vfai->frameConnected(frame, pqview);
|
|
}
|
|
return frame;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
QWidget* pqMultiViewWidget::createWidget(
|
|
int index, vtkSMViewLayoutProxy* vlayout, QWidget* parentWdg,
|
|
int& max_index)
|
|
{
|
|
if (this->Internals->Widgets.size() <= static_cast<int>(index))
|
|
{
|
|
this->Internals->Widgets.resize(index+1);
|
|
}
|
|
|
|
vtkSMViewLayoutProxy::Direction direction = vlayout->GetSplitDirection(index);
|
|
switch (direction)
|
|
{
|
|
case vtkSMViewLayoutProxy::NONE:
|
|
{
|
|
vtkSMViewProxy* view = vlayout->GetView(index);
|
|
pqViewFrame* frame = view?
|
|
this->Internals->ViewFrames[view] : NULL;
|
|
if (!frame)
|
|
{
|
|
frame = this->newFrame(view);
|
|
if (view)
|
|
{
|
|
this->Internals->ViewFrames[view] = frame;
|
|
}
|
|
}
|
|
Q_ASSERT(frame != NULL);
|
|
|
|
frame->setParent(parentWdg);
|
|
this->Internals->Widgets[index] = frame;
|
|
frame->setObjectName(QString("Frame.%1").arg(index));
|
|
frame->setProperty("FRAME_INDEX", QVariant(index));
|
|
frame->setDecorationsVisibility(this->DecorationsVisible);
|
|
if (this->LockViewSize.isEmpty())
|
|
{
|
|
frame->centralWidget()->setMaximumSize(
|
|
QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX));
|
|
}
|
|
else
|
|
{
|
|
frame->centralWidget()->setMaximumSize(this->LockViewSize);
|
|
}
|
|
if (max_index < index) { max_index = index; }
|
|
return frame;
|
|
}
|
|
|
|
case vtkSMViewLayoutProxy::VERTICAL:
|
|
case vtkSMViewLayoutProxy::HORIZONTAL:
|
|
if (this->DecorationsVisible)
|
|
{
|
|
QSplitter* splitter = qobject_cast<QSplitter*>(
|
|
this->Internals->Widgets[index]);
|
|
if (!splitter)
|
|
{
|
|
splitter = new QSplitter(parentWdg);
|
|
}
|
|
Q_ASSERT(splitter);
|
|
splitter->setParent(parentWdg);
|
|
splitter->setHandleWidth(this->DecorationsVisible? 3 : 1);
|
|
this->Internals->Widgets[index] = splitter;
|
|
splitter->setObjectName(QString("Splitter.%1").arg(index));
|
|
splitter->setProperty("FRAME_INDEX", QVariant(index));
|
|
splitter->setOpaqueResize(false);
|
|
splitter->setOrientation(
|
|
direction == vtkSMViewLayoutProxy::VERTICAL?
|
|
Qt::Vertical : Qt::Horizontal);
|
|
splitter->addWidget(
|
|
this->createWidget(vlayout->GetFirstChild(index), vlayout, splitter,
|
|
max_index));
|
|
splitter->addWidget(
|
|
this->createWidget(vlayout->GetSecondChild(index), vlayout, splitter,
|
|
max_index));
|
|
|
|
// set the sizes are percentage. QSplitter uses the initially specified
|
|
// sizes as reference.
|
|
QList<int> sizes;
|
|
sizes << static_cast<int>(vlayout->GetSplitFraction(index) * 10000);
|
|
sizes << static_cast<int>((1.0 - vlayout->GetSplitFraction(index)) * 10000);
|
|
splitter->setSizes(sizes);
|
|
|
|
// FIXME: Don't like this as this QueuedConnection may cause multiple
|
|
// renders.
|
|
QObject::disconnect(splitter, SIGNAL(splitterMoved(int, int)),
|
|
this, SLOT(splitterMoved()));
|
|
QObject::connect(splitter, SIGNAL(splitterMoved(int, int)),
|
|
this, SLOT(splitterMoved()), Qt::QueuedConnection);
|
|
if (max_index < index) { max_index = index; }
|
|
return splitter;
|
|
}
|
|
else
|
|
{
|
|
QWidget* container = new QWidget(parentWdg);
|
|
pqSplitterLayout* slayout = new pqSplitterLayout(
|
|
direction == vtkSMViewLayoutProxy::VERTICAL?
|
|
pqSplitterLayout::TopToBottom :
|
|
pqSplitterLayout::LeftToRight,
|
|
container);
|
|
slayout->setSplitFraction(vlayout->GetSplitFraction(index));
|
|
container->setLayout(slayout);
|
|
container->setObjectName(QString("Container.%1").arg(index));
|
|
slayout->addWidget(
|
|
this->createWidget(vlayout->GetFirstChild(index), vlayout, container,
|
|
max_index));
|
|
slayout->addWidget(
|
|
this->createWidget(vlayout->GetSecondChild(index), vlayout, container,
|
|
max_index));
|
|
if (max_index < index) { max_index = index; }
|
|
return container;
|
|
}
|
|
break;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void pqMultiViewWidget::reload()
|
|
{
|
|
vtkSMViewLayoutProxy* vlayout = this->layoutManager();
|
|
if (!vlayout)
|
|
{
|
|
return;
|
|
}
|
|
|
|
QWidget *cleaner = new QWidget();
|
|
foreach (QWidget* widget, this->Internals->Widgets)
|
|
{
|
|
if (widget)
|
|
{
|
|
widget->setParent(cleaner);
|
|
}
|
|
}
|
|
|
|
// if popout is true, we add the widgets to the PopoutFrame, rather that
|
|
// ourselves.
|
|
QWidget* parentWdg = this->Internals->Popout?
|
|
&this->Internals->PopoutFrame : this;
|
|
|
|
int max_index=0;
|
|
QWidget* child = this->createWidget(0, vlayout, parentWdg, max_index);
|
|
delete cleaner;
|
|
cleaner = NULL;
|
|
|
|
// resize Widgets to remove any obsolete indices. These indices weren't
|
|
// touched at all during the last call to createWidget().
|
|
this->Internals->Widgets.resize(max_index+1);
|
|
|
|
delete parentWdg->layout();
|
|
QVBoxLayout* vbox = new QVBoxLayout(parentWdg);
|
|
vbox->setContentsMargins(0, 0, 0, 0);
|
|
vbox->addWidget(child);
|
|
|
|
if (this->Internals->Popout)
|
|
{
|
|
// if the PopoutFrame is being shown for the first time, we resize it to
|
|
// match this widgets size so that it doesn't end up too small.
|
|
if (!this->Internals->PopoutFrame.property(
|
|
"pqMultiViewWidget::SizeInitialized").isValid())
|
|
{
|
|
this->Internals->PopoutFrame.setProperty(
|
|
"pqMultiViewWidget::SizeInitialized", true);
|
|
this->Internals->PopoutFrame.resize(this->size());
|
|
}
|
|
this->Internals->PopoutFrame.show();
|
|
}
|
|
else
|
|
{
|
|
this->Internals->PopoutFrame.hide();
|
|
}
|
|
|
|
int maximized_cell = vlayout->GetMaximizedCell();
|
|
this->Internals->setMaximizedWidget(NULL);
|
|
for (int cc = 0; cc < this->Internals->Widgets.size(); cc++)
|
|
{
|
|
pqViewFrame* frame = qobject_cast<pqViewFrame*>(
|
|
this->Internals->Widgets[cc]);
|
|
if (frame)
|
|
{
|
|
bool visibility = true;
|
|
if (cc == maximized_cell)
|
|
{
|
|
this->Internals->setMaximizedWidget(frame);
|
|
}
|
|
else if (maximized_cell != -1)
|
|
{
|
|
visibility = false;
|
|
}
|
|
frame->setVisible(visibility);
|
|
}
|
|
}
|
|
|
|
// ensure the active view is marked appropriately.
|
|
this->markActive(pqActiveObjects::instance().activeView());
|
|
|
|
// Cleanup deleted objects. "cleaner" helps us avoid any dangling widgets and
|
|
// deletes them whwn delete cleaner is called. Now we prune internal
|
|
// datastructures to get rid of these NULL ptrs.
|
|
|
|
// remove any deleted view frames.
|
|
QMutableMapIterator<vtkSMViewProxy*, QPointer<pqViewFrame> > iter(
|
|
this->Internals->ViewFrames);
|
|
while (iter.hasNext())
|
|
{
|
|
iter.next();
|
|
if (iter.value() == NULL)
|
|
{
|
|
// since we are in the process of destroying the view, cancel any pending
|
|
// render requests. This addresses a Windows issue where the view would
|
|
// occassionally popout and render when undoing the creation of the view
|
|
// or closing it.
|
|
pqView* view = getPQView(iter.key());
|
|
if (view)
|
|
{
|
|
view->cancelPendingRenders();
|
|
}
|
|
iter.remove();
|
|
}
|
|
}
|
|
|
|
// we let the GUI updated immediately. This is needed since when a new view is
|
|
// created (for example), it may depend on the size of the view during its
|
|
// initialization to ensure camera is reset correctly.
|
|
QCoreApplication::sendPostedEvents();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void pqMultiViewWidget::standardButtonPressed(int button)
|
|
{
|
|
QWidget* frame = qobject_cast<QWidget*>(this->sender());
|
|
QVariant index = frame? frame->property("FRAME_INDEX") : QVariant();
|
|
if (!index.isValid() || this->layoutManager() == NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
switch (button)
|
|
{
|
|
case pqViewFrame::SplitVertical:
|
|
case pqViewFrame::SplitHorizontal:
|
|
{
|
|
BEGIN_UNDO_SET("Split View");
|
|
int new_index = this->layoutManager()->Split(index.toInt(),
|
|
(button == pqViewFrame::SplitVertical?
|
|
vtkSMViewLayoutProxy::VERTICAL : vtkSMViewLayoutProxy::HORIZONTAL),
|
|
0.5);
|
|
this->makeActive(qobject_cast<pqViewFrame*>(
|
|
this->Internals->Widgets[new_index + 1]));
|
|
END_UNDO_SET();
|
|
}
|
|
break;
|
|
|
|
case pqViewFrame::Maximize:
|
|
this->layoutManager()->MaximizeCell(index.toInt());
|
|
break;
|
|
|
|
case pqViewFrame::Restore:
|
|
this->layoutManager()->RestoreMaximizedState();
|
|
break;
|
|
|
|
case pqViewFrame::Close:
|
|
{
|
|
BEGIN_UNDO_SET("Close View");
|
|
vtkSMViewProxy* viewProxy =
|
|
this->layoutManager()->GetView(index.toInt());
|
|
if (viewProxy)
|
|
{
|
|
this->layoutManager()->RemoveView(viewProxy);
|
|
pqObjectBuilder* builder =
|
|
pqApplicationCore::instance()->getObjectBuilder();
|
|
builder->destroy(getPQView(viewProxy));
|
|
}
|
|
if (index.toInt() != 0)
|
|
{
|
|
int location = index.toInt();
|
|
int parent_idx = vtkSMViewLayoutProxy::GetParent(location);
|
|
this->layoutManager()->Collapse(location);
|
|
this->makeActive(qobject_cast<pqViewFrame*>(
|
|
this->Internals->Widgets[parent_idx]));
|
|
}
|
|
END_UNDO_SET();
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void pqMultiViewWidget::destroyAllViews()
|
|
{
|
|
BEGIN_UNDO_SET("Destroy all views");
|
|
pqObjectBuilder* builder =
|
|
pqApplicationCore::instance()->getObjectBuilder();
|
|
QList<vtkSMViewProxy*> views = this->viewProxies();
|
|
foreach (vtkSMViewProxy* view, views)
|
|
{
|
|
if (view)
|
|
{
|
|
builder->destroy(getPQView(view));
|
|
}
|
|
}
|
|
END_UNDO_SET();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void pqMultiViewWidget::splitterMoved()
|
|
{
|
|
QSplitter* splitter = qobject_cast<QSplitter*>(this->sender());
|
|
QVariant index = splitter? splitter->property("FRAME_INDEX") : QVariant();
|
|
if (index.isValid() && this->layoutManager())
|
|
{
|
|
QList<int> sizes = splitter->sizes();
|
|
if (sizes.size() == 2)
|
|
{
|
|
BEGIN_UNDO_SET("Resize Frame");
|
|
double fraction = sizes[0] * 1.0 / (sizes[0] + sizes[1]);
|
|
this->layoutManager()->SetSplitFraction(index.toInt(), fraction);
|
|
END_UNDO_SET();
|
|
}
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void pqMultiViewWidget::setDecorationsVisible(bool val)
|
|
{
|
|
if (this->DecorationsVisible == val)
|
|
{
|
|
return;
|
|
}
|
|
|
|
this->DecorationsVisible = val;
|
|
this->reload();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
int pqMultiViewWidget::prepareForCapture(int dx, int dy)
|
|
{
|
|
QSize requestedSize(dx, dy);
|
|
QSize mySize = this->size();
|
|
|
|
int magnification = pqView::computeMagnification(requestedSize, mySize);
|
|
this->setMaximumSize(mySize);
|
|
this->resize(mySize);
|
|
this->Internals->DecorationsVisibleBeforeCapture = this->isDecorationsVisible();
|
|
this->setDecorationsVisible(false);
|
|
pqEventDispatcher::processEventsAndWait(1);
|
|
return magnification;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void pqMultiViewWidget::cleanupAfterCapture()
|
|
{
|
|
this->setMaximumSize(QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX));
|
|
this->setDecorationsVisible(this->Internals->DecorationsVisibleBeforeCapture);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
vtkImageData* pqMultiViewWidget::captureImage(int dx, int dy)
|
|
{
|
|
int magnification = this->prepareForCapture(dx, dy);
|
|
vtkImageData* image = this->layoutManager()->CaptureWindow(magnification);
|
|
this->cleanupAfterCapture();
|
|
return image;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
bool pqMultiViewWidget::writeImage(
|
|
const QString& filename, int dx, int dy, int quality)
|
|
{
|
|
int magnification = this->prepareForCapture(dx, dy);
|
|
vtkNew<vtkSMParaViewPipelineControllerWithRendering> controller;
|
|
bool status = controller->WriteImage(this->layoutManager(),
|
|
filename.toLatin1().data(), magnification, quality);
|
|
this->cleanupAfterCapture();
|
|
return status;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void pqMultiViewWidget::swapPositions(const QString& uid_str)
|
|
{
|
|
QUuid other (uid_str);
|
|
|
|
vtkSMViewLayoutProxy* vlayout = this->layoutManager();
|
|
pqViewFrame* senderFrame = qobject_cast<pqViewFrame*>(this->sender());
|
|
if (!senderFrame || !vlayout)
|
|
{
|
|
return;
|
|
}
|
|
|
|
pqViewFrame* swapWith = NULL;
|
|
foreach (QWidget* wdg, this->Internals->Widgets)
|
|
{
|
|
pqViewFrame* frame = qobject_cast<pqViewFrame*>(wdg);
|
|
if (frame && frame->uniqueID() == other)
|
|
{
|
|
swapWith = frame;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!swapWith)
|
|
{
|
|
return;
|
|
}
|
|
|
|
int id1 = senderFrame->property("FRAME_INDEX").toInt();
|
|
int id2 = swapWith->property("FRAME_INDEX").toInt();
|
|
vtkSMViewProxy* view1 = vlayout->GetView(id1);
|
|
vtkSMViewProxy* view2 = vlayout->GetView(id2);
|
|
|
|
if (view1 == NULL && view2 == NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
BEGIN_UNDO_SET("Swap Views");
|
|
vlayout->SwapCells(id1, id2);
|
|
END_UNDO_SET();
|
|
this->reload();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void pqMultiViewWidget::reset()
|
|
{
|
|
this->layoutManager()->Reset();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
QList<vtkSMViewProxy*> pqMultiViewWidget::viewProxies() const
|
|
{
|
|
return this->Internals->ViewFrames.keys();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
bool pqMultiViewWidget::togglePopout()
|
|
{
|
|
this->Internals->Popout = this->Internals->Popout? false: true;
|
|
this->reload();
|
|
return this->Internals->Popout;
|
|
}
|