- at the moment some NaviCube parameters are in the general View group, some in the dedicated NaviCube group
1047 lines
39 KiB
C++
1047 lines
39 KiB
C++
/***************************************************************************
|
|
* Copyright (c) 2004 Jürgen Riegel <juergen.riegel@web.de> *
|
|
* *
|
|
* This file is part of the FreeCAD CAx development system. *
|
|
* *
|
|
* This library is free software; you can redistribute it and/or *
|
|
* modify it under the terms of the GNU Library General Public *
|
|
* License as published by the Free Software Foundation; either *
|
|
* version 2 of the License, or (at your option) any later version. *
|
|
* *
|
|
* This library is distributed in the hope that it will be useful, *
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
* GNU Library General Public License for more details. *
|
|
* *
|
|
* You should have received a copy of the GNU Library General Public *
|
|
* License along with this library; see the file COPYING.LIB. If not, *
|
|
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
|
* Suite 330, Boston, MA 02111-1307, USA *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
#include "PreCompiled.h"
|
|
|
|
#ifndef _PreComp_
|
|
# include <string>
|
|
# include <QAction>
|
|
# include <QApplication>
|
|
# include <QKeyEvent>
|
|
# include <QEvent>
|
|
# include <QDropEvent>
|
|
# include <QDragEnterEvent>
|
|
# include <QLayout>
|
|
# include <QMdiSubWindow>
|
|
# include <QMessageBox>
|
|
# include <QMimeData>
|
|
# include <QPainter>
|
|
# include <QPrinter>
|
|
# include <QPrintDialog>
|
|
# include <QPrintPreviewDialog>
|
|
# include <QStackedWidget>
|
|
# include <QTimer>
|
|
# include <QUrl>
|
|
# include <QWindow>
|
|
# include <Inventor/actions/SoGetPrimitiveCountAction.h>
|
|
# include <Inventor/fields/SoSFColor.h>
|
|
# include <Inventor/fields/SoSFString.h>
|
|
# include <Inventor/nodes/SoDirectionalLight.h>
|
|
# include <Inventor/nodes/SoOrthographicCamera.h>
|
|
# include <Inventor/nodes/SoPerspectiveCamera.h>
|
|
# include <Inventor/nodes/SoSeparator.h>
|
|
#endif
|
|
|
|
#include <App/Document.h>
|
|
#include <Base/Console.h>
|
|
#include <Base/Interpreter.h>
|
|
|
|
#include "View3DInventor.h"
|
|
#include "Application.h"
|
|
#include "Document.h"
|
|
#include "FileDialog.h"
|
|
#include "MainWindow.h"
|
|
#include "NavigationStyle.h"
|
|
#include "SoFCDB.h"
|
|
#include "SoFCSelectionAction.h"
|
|
#include "SoFCVectorizeSVGAction.h"
|
|
#include "View3DInventorExamples.h"
|
|
#include "View3DInventorViewer.h"
|
|
#include "View3DPy.h"
|
|
#include "ViewProvider.h"
|
|
#include "WaitCursor.h"
|
|
|
|
|
|
using namespace Gui;
|
|
|
|
void GLOverlayWidget::paintEvent(QPaintEvent*)
|
|
{
|
|
QPainter paint(this);
|
|
paint.drawImage(0,0,image);
|
|
paint.end();
|
|
}
|
|
|
|
/* TRANSLATOR Gui::View3DInventor */
|
|
|
|
TYPESYSTEM_SOURCE_ABSTRACT(Gui::View3DInventor,Gui::MDIView)
|
|
|
|
View3DInventor::View3DInventor(Gui::Document* pcDocument, QWidget* parent,
|
|
const QtGLWidget* sharewidget, Qt::WindowFlags wflags)
|
|
: MDIView(pcDocument, parent, wflags), _viewerPy(nullptr)
|
|
{
|
|
stack = new QStackedWidget(this);
|
|
// important for highlighting
|
|
setMouseTracking(true);
|
|
// accept drops on the window, get handled in dropEvent, dragEnterEvent
|
|
setAcceptDrops(true);
|
|
|
|
// attach parameter Observer
|
|
hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/View");
|
|
hGrp->Attach(this);
|
|
|
|
hGrpNavi =
|
|
App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/NaviCube");
|
|
hGrpNavi->Attach(this);
|
|
|
|
//anti-aliasing settings
|
|
bool smoothing = false;
|
|
bool glformat = false;
|
|
int samples = View3DInventorViewer::getNumSamples();
|
|
QtGLFormat f;
|
|
|
|
if (samples > 1) {
|
|
glformat = true;
|
|
f.setSamples(samples);
|
|
}
|
|
else if (samples > 0) {
|
|
smoothing = true;
|
|
}
|
|
|
|
if (glformat)
|
|
_viewer = new View3DInventorViewer(f, this, sharewidget);
|
|
else
|
|
_viewer = new View3DInventorViewer(this, sharewidget);
|
|
|
|
if (smoothing)
|
|
_viewer->getSoRenderManager()->getGLRenderAction()->setSmoothing(true);
|
|
|
|
// create the inventor widget and set the defaults
|
|
_viewer->setDocument(this->_pcDocument);
|
|
stack->addWidget(_viewer->getWidget());
|
|
// http://forum.freecadweb.org/viewtopic.php?f=3&t=6055&sid=150ed90cbefba50f1e2ad4b4e6684eba
|
|
// describes a minor error but trying to fix it leads to a major issue
|
|
// http://forum.freecadweb.org/viewtopic.php?f=3&t=6085&sid=3f4bcab8007b96aaf31928b564190fd7
|
|
// so the change is commented out
|
|
// By default, the wheel events are processed by the 3d view AND the mdi area.
|
|
//_viewer->getGLWidget()->setAttribute(Qt::WA_NoMousePropagation);
|
|
setCentralWidget(stack);
|
|
|
|
// apply the user settings
|
|
OnChange(*hGrp,"EyeDistance");
|
|
OnChange(*hGrp,"CornerCoordSystem");
|
|
OnChange(*hGrp,"CornerCoordSystemSize");
|
|
OnChange(*hGrp,"ShowAxisCross");
|
|
OnChange(*hGrp,"UseAutoRotation");
|
|
OnChange(*hGrp,"Gradient");
|
|
OnChange(*hGrp,"BackgroundColor");
|
|
OnChange(*hGrp,"BackgroundColor2");
|
|
OnChange(*hGrp,"BackgroundColor3");
|
|
OnChange(*hGrp,"BackgroundColor4");
|
|
OnChange(*hGrp,"UseBackgroundColorMid");
|
|
OnChange(*hGrp,"ShowFPS");
|
|
OnChange(*hGrp,"ShowNaviCube");
|
|
OnChange(*hGrpNavi, "CornerNaviCube");
|
|
OnChange(*hGrp,"UseVBO");
|
|
OnChange(*hGrp,"RenderCache");
|
|
OnChange(*hGrp,"Orthographic");
|
|
OnChange(*hGrp,"HeadlightColor");
|
|
OnChange(*hGrp,"HeadlightDirection");
|
|
OnChange(*hGrp,"HeadlightIntensity");
|
|
OnChange(*hGrp,"EnableBacklight");
|
|
OnChange(*hGrp,"BacklightColor");
|
|
OnChange(*hGrp,"BacklightDirection");
|
|
OnChange(*hGrp,"BacklightIntensity");
|
|
OnChange(*hGrp,"NavigationStyle");
|
|
OnChange(*hGrp,"OrbitStyle");
|
|
OnChange(*hGrp,"Sensitivity");
|
|
OnChange(*hGrp,"ResetCursorPosition");
|
|
OnChange(*hGrp,"DimensionsVisible");
|
|
OnChange(*hGrp,"Dimensions3dVisible");
|
|
OnChange(*hGrp,"DimensionsDeltaVisible");
|
|
OnChange(*hGrp,"PickRadius");
|
|
OnChange(*hGrp,"TransparentObjectRenderType");
|
|
|
|
stopSpinTimer = new QTimer(this);
|
|
connect(stopSpinTimer, SIGNAL(timeout()), this, SLOT(stopAnimating()));
|
|
}
|
|
|
|
View3DInventor::~View3DInventor()
|
|
{
|
|
if(_pcDocument) {
|
|
SoCamera * Cam = _viewer->getSoRenderManager()->getCamera();
|
|
if (Cam)
|
|
_pcDocument->saveCameraSettings(SoFCDB::writeNodesToString(Cam).c_str());
|
|
}
|
|
hGrp->Detach(this);
|
|
hGrpNavi->Detach(this);
|
|
|
|
//If we destroy this viewer by calling 'delete' directly the focus proxy widget which is defined
|
|
//by a widget in SoQtViewer isn't reset. This widget becomes a dangling pointer and makes
|
|
//the application crash. (Probably it's better to destroy this viewer by calling close().)
|
|
//See also Gui::Document::~Document().
|
|
QWidget* foc = qApp->focusWidget();
|
|
if (foc) {
|
|
QWidget* par = foc->parentWidget();
|
|
while (par) {
|
|
if (par == this) {
|
|
foc->setFocusProxy(nullptr);
|
|
foc->clearFocus();
|
|
break;
|
|
}
|
|
par = par->parentWidget();
|
|
}
|
|
}
|
|
|
|
if (_viewerPy) {
|
|
Base::PyGILStateLocker lock;
|
|
Py_DECREF(_viewerPy);
|
|
}
|
|
|
|
// here is from time to time trouble!!!
|
|
delete _viewer;
|
|
}
|
|
|
|
void View3DInventor::deleteSelf()
|
|
{
|
|
_viewer->setSceneGraph(nullptr);
|
|
_viewer->setDocument(nullptr);
|
|
MDIView::deleteSelf();
|
|
}
|
|
|
|
PyObject *View3DInventor::getPyObject(void)
|
|
{
|
|
if (!_viewerPy)
|
|
_viewerPy = new View3DInventorPy(this);
|
|
|
|
Py_INCREF(_viewerPy);
|
|
return _viewerPy;
|
|
}
|
|
|
|
void View3DInventor::OnChange(ParameterGrp::SubjectType &rCaller,ParameterGrp::MessageType Reason)
|
|
{
|
|
const ParameterGrp& rGrp = static_cast<ParameterGrp&>(rCaller);
|
|
if (strcmp(Reason,"HeadlightColor") == 0) {
|
|
unsigned long headlight = rGrp.GetUnsigned("HeadlightColor",ULONG_MAX); // default color (white)
|
|
float transparency;
|
|
SbColor headlightColor;
|
|
headlightColor.setPackedValue((uint32_t)headlight, transparency);
|
|
_viewer->getHeadlight()->color.setValue(headlightColor);
|
|
}
|
|
else if (strcmp(Reason,"HeadlightDirection") == 0) {
|
|
std::string pos = rGrp.GetASCII("HeadlightDirection");
|
|
QString flt = QString::fromLatin1("([-+]?[0-9]+\\.?[0-9]+)");
|
|
QRegExp rx(QString::fromLatin1("^\\(%1,%1,%1\\)$").arg(flt));
|
|
if (rx.indexIn(QLatin1String(pos.c_str())) > -1) {
|
|
float x = rx.cap(1).toFloat();
|
|
float y = rx.cap(2).toFloat();
|
|
float z = rx.cap(3).toFloat();
|
|
_viewer->getHeadlight()->direction.setValue(x,y,z);
|
|
}
|
|
}
|
|
else if (strcmp(Reason,"HeadlightIntensity") == 0) {
|
|
long value = rGrp.GetInt("HeadlightIntensity", 100);
|
|
_viewer->getHeadlight()->intensity.setValue((float)value/100.0f);
|
|
}
|
|
else if (strcmp(Reason,"EnableBacklight") == 0) {
|
|
_viewer->setBacklight(rGrp.GetBool("EnableBacklight", false));
|
|
}
|
|
else if (strcmp(Reason,"BacklightColor") == 0) {
|
|
unsigned long backlight = rGrp.GetUnsigned("BacklightColor",ULONG_MAX); // default color (white)
|
|
float transparency;
|
|
SbColor backlightColor;
|
|
backlightColor.setPackedValue((uint32_t)backlight, transparency);
|
|
_viewer->getBacklight()->color.setValue(backlightColor);
|
|
}
|
|
else if (strcmp(Reason,"BacklightDirection") == 0) {
|
|
std::string pos = rGrp.GetASCII("BacklightDirection");
|
|
QString flt = QString::fromLatin1("([-+]?[0-9]+\\.?[0-9]+)");
|
|
QRegExp rx(QString::fromLatin1("^\\(%1,%1,%1\\)$").arg(flt));
|
|
if (rx.indexIn(QLatin1String(pos.c_str())) > -1) {
|
|
float x = rx.cap(1).toFloat();
|
|
float y = rx.cap(2).toFloat();
|
|
float z = rx.cap(3).toFloat();
|
|
_viewer->getBacklight()->direction.setValue(x,y,z);
|
|
}
|
|
}
|
|
else if (strcmp(Reason,"BacklightIntensity") == 0) {
|
|
long value = rGrp.GetInt("BacklightIntensity", 100);
|
|
_viewer->getBacklight()->intensity.setValue((float)value/100.0f);
|
|
}
|
|
else if (strcmp(Reason,"EnablePreselection") == 0) {
|
|
const ParameterGrp& rclGrp = ((ParameterGrp&)rCaller);
|
|
SoFCEnableHighlightAction cAct(rclGrp.GetBool("EnablePreselection", true));
|
|
cAct.apply(_viewer->getSceneGraph());
|
|
}
|
|
else if (strcmp(Reason,"EnableSelection") == 0) {
|
|
const ParameterGrp& rclGrp = ((ParameterGrp&)rCaller);
|
|
SoFCEnableSelectionAction cAct(rclGrp.GetBool("EnableSelection", true));
|
|
cAct.apply(_viewer->getSceneGraph());
|
|
}
|
|
else if (strcmp(Reason,"HighlightColor") == 0) {
|
|
float transparency;
|
|
SbColor highlightColor(0.8f, 0.1f, 0.1f);
|
|
unsigned long highlight = (unsigned long)(highlightColor.getPackedValue());
|
|
highlight = rGrp.GetUnsigned("HighlightColor", highlight);
|
|
highlightColor.setPackedValue((uint32_t)highlight, transparency);
|
|
SoSFColor col; col.setValue(highlightColor);
|
|
SoFCHighlightColorAction cAct(col);
|
|
cAct.apply(_viewer->getSceneGraph());
|
|
}
|
|
else if (strcmp(Reason,"SelectionColor") == 0) {
|
|
float transparency;
|
|
SbColor selectionColor(0.1f, 0.8f, 0.1f);
|
|
unsigned long selection = (unsigned long)(selectionColor.getPackedValue());
|
|
selection = rGrp.GetUnsigned("SelectionColor", selection);
|
|
selectionColor.setPackedValue((uint32_t)selection, transparency);
|
|
SoSFColor col; col.setValue(selectionColor);
|
|
SoFCSelectionColorAction cAct(col);
|
|
cAct.apply(_viewer->getSceneGraph());
|
|
}
|
|
else if (strcmp(Reason,"NavigationStyle") == 0) {
|
|
// check whether the simple or the full mouse model is used
|
|
std::string model = rGrp.GetASCII("NavigationStyle",CADNavigationStyle::getClassTypeId().getName());
|
|
Base::Type type = Base::Type::fromName(model.c_str());
|
|
_viewer->setNavigationType(type);
|
|
}
|
|
else if (strcmp(Reason,"OrbitStyle") == 0) {
|
|
int style = rGrp.GetInt("OrbitStyle",1);
|
|
_viewer->navigationStyle()->setOrbitStyle(NavigationStyle::OrbitStyle(style));
|
|
}
|
|
else if (strcmp(Reason,"Sensitivity") == 0) {
|
|
float val = rGrp.GetFloat("Sensitivity",2.0f);
|
|
_viewer->navigationStyle()->setSensitivity(val);
|
|
}
|
|
else if (strcmp(Reason,"ResetCursorPosition") == 0) {
|
|
bool on = rGrp.GetBool("ResetCursorPosition",false);
|
|
_viewer->navigationStyle()->setResetCursorPosition(on);
|
|
}
|
|
else if (strcmp(Reason,"InvertZoom") == 0) {
|
|
bool on = rGrp.GetBool("InvertZoom", true);
|
|
_viewer->navigationStyle()->setZoomInverted(on);
|
|
}
|
|
else if (strcmp(Reason,"ZoomAtCursor") == 0) {
|
|
bool on = rGrp.GetBool("ZoomAtCursor", true);
|
|
_viewer->navigationStyle()->setZoomAtCursor(on);
|
|
}
|
|
else if (strcmp(Reason,"ZoomStep") == 0) {
|
|
float val = rGrp.GetFloat("ZoomStep", 0.0f);
|
|
_viewer->navigationStyle()->setZoomStep(val);
|
|
}
|
|
else if (strcmp(Reason,"RotationMode") == 0) {
|
|
long mode = rGrp.GetInt("RotationMode", 1);
|
|
if (mode == 0) {
|
|
_viewer->navigationStyle()->setRotationCenterMode(NavigationStyle::RotationCenterMode::WindowCenter);
|
|
}
|
|
else if (mode == 1) {
|
|
_viewer->navigationStyle()->setRotationCenterMode(NavigationStyle::RotationCenterMode::ScenePointAtCursor |
|
|
NavigationStyle::RotationCenterMode::FocalPointAtCursor);
|
|
}
|
|
else if (mode == 2) {
|
|
_viewer->navigationStyle()->setRotationCenterMode(NavigationStyle::RotationCenterMode::ScenePointAtCursor |
|
|
NavigationStyle::RotationCenterMode::BoundingBoxCenter);
|
|
}
|
|
}
|
|
else if (strcmp(Reason,"EyeDistance") == 0) {
|
|
_viewer->getSoRenderManager()->setStereoOffset(rGrp.GetFloat("EyeDistance",5.0));
|
|
}
|
|
else if (strcmp(Reason,"CornerCoordSystem") == 0) {
|
|
_viewer->setFeedbackVisibility(rGrp.GetBool("CornerCoordSystem",true));
|
|
}
|
|
else if (strcmp(Reason,"CornerCoordSystemSize") == 0) {
|
|
_viewer->setFeedbackSize(rGrp.GetInt("CornerCoordSystemSize",10));
|
|
}
|
|
else if (strcmp(Reason,"ShowAxisCross") == 0) {
|
|
_viewer->setAxisCross(rGrp.GetBool("ShowAxisCross",false));
|
|
}
|
|
else if (strcmp(Reason,"UseAutoRotation") == 0) {
|
|
_viewer->setAnimationEnabled(rGrp.GetBool("UseAutoRotation",false));
|
|
}
|
|
else if (strcmp(Reason,"Gradient") == 0) {
|
|
_viewer->setGradientBackground((rGrp.GetBool("Gradient",true)));
|
|
}
|
|
else if (strcmp(Reason,"ShowFPS") == 0) {
|
|
_viewer->setEnabledFPSCounter(rGrp.GetBool("ShowFPS",false));
|
|
}
|
|
else if (strcmp(Reason,"ShowNaviCube") == 0) {
|
|
_viewer->setEnabledNaviCube(rGrp.GetBool("ShowNaviCube",true));
|
|
}
|
|
else if (strcmp(Reason, "CornerNaviCube") == 0) {
|
|
_viewer->setNaviCubeCorner(rGrp.GetInt("CornerNaviCube", 1));
|
|
}
|
|
else if (strcmp(Reason,"UseVBO") == 0) {
|
|
_viewer->setEnabledVBO(rGrp.GetBool("UseVBO",false));
|
|
}
|
|
else if (strcmp(Reason,"RenderCache") == 0) {
|
|
_viewer->setRenderCache(rGrp.GetInt("RenderCache",0));
|
|
}
|
|
else if (strcmp(Reason,"Orthographic") == 0) {
|
|
// check whether a perspective or orthogrphic camera should be set
|
|
if (rGrp.GetBool("Orthographic", true))
|
|
_viewer->setCameraType(SoOrthographicCamera::getClassTypeId());
|
|
else
|
|
_viewer->setCameraType(SoPerspectiveCamera::getClassTypeId());
|
|
}
|
|
else if (strcmp(Reason, "DimensionsVisible") == 0) {
|
|
if (rGrp.GetBool("DimensionsVisible", true))
|
|
_viewer->turnAllDimensionsOn();
|
|
else
|
|
_viewer->turnAllDimensionsOff();
|
|
}
|
|
else if (strcmp(Reason, "Dimensions3dVisible") == 0) {
|
|
if (rGrp.GetBool("Dimensions3dVisible", true))
|
|
_viewer->turn3dDimensionsOn();
|
|
else
|
|
_viewer->turn3dDimensionsOff();
|
|
}
|
|
else if (strcmp(Reason, "DimensionsDeltaVisible") == 0) {
|
|
if (rGrp.GetBool("DimensionsDeltaVisible", true))
|
|
_viewer->turnDeltaDimensionsOn();
|
|
else
|
|
_viewer->turnDeltaDimensionsOff();
|
|
}
|
|
else if (strcmp(Reason, "PickRadius") == 0) {
|
|
_viewer->setPickRadius(rGrp.GetFloat("PickRadius", 5.0f));
|
|
}
|
|
else if (strcmp(Reason, "TransparentObjectRenderType") == 0) {
|
|
long renderType = rGrp.GetInt("TransparentObjectRenderType", 0);
|
|
if (renderType == 0) {
|
|
_viewer->getSoRenderManager()->getGLRenderAction()
|
|
->setTransparentDelayedObjectRenderType(SoGLRenderAction::ONE_PASS);
|
|
}
|
|
else if (renderType == 1) {
|
|
_viewer->getSoRenderManager()->getGLRenderAction()
|
|
->setTransparentDelayedObjectRenderType(SoGLRenderAction::NONSOLID_SEPARATE_BACKFACE_PASS);
|
|
}
|
|
}
|
|
else {
|
|
unsigned long col1 = rGrp.GetUnsigned("BackgroundColor",3940932863UL);
|
|
unsigned long col2 = rGrp.GetUnsigned("BackgroundColor2",859006463UL); // default color (dark blue)
|
|
unsigned long col3 = rGrp.GetUnsigned("BackgroundColor3",2880160255UL); // default color (blue/grey)
|
|
unsigned long col4 = rGrp.GetUnsigned("BackgroundColor4",1869583359UL); // default color (blue/grey)
|
|
float r1,g1,b1,r2,g2,b2,r3,g3,b3,r4,g4,b4;
|
|
r1 = ((col1 >> 24) & 0xff) / 255.0; g1 = ((col1 >> 16) & 0xff) / 255.0; b1 = ((col1 >> 8) & 0xff) / 255.0;
|
|
r2 = ((col2 >> 24) & 0xff) / 255.0; g2 = ((col2 >> 16) & 0xff) / 255.0; b2 = ((col2 >> 8) & 0xff) / 255.0;
|
|
r3 = ((col3 >> 24) & 0xff) / 255.0; g3 = ((col3 >> 16) & 0xff) / 255.0; b3 = ((col3 >> 8) & 0xff) / 255.0;
|
|
r4 = ((col4 >> 24) & 0xff) / 255.0; g4 = ((col4 >> 16) & 0xff) / 255.0; b4 = ((col4 >> 8) & 0xff) / 255.0;
|
|
_viewer->setBackgroundColor(QColor::fromRgbF(r1, g1, b1));
|
|
if (!rGrp.GetBool("UseBackgroundColorMid",false))
|
|
_viewer->setGradientBackgroundColor(SbColor(r2, g2, b2), SbColor(r3, g3, b3));
|
|
else
|
|
_viewer->setGradientBackgroundColor(SbColor(r2, g2, b2), SbColor(r3, g3, b3), SbColor(r4, g4, b4));
|
|
}
|
|
}
|
|
|
|
void View3DInventor::onRename(Gui::Document *pDoc)
|
|
{
|
|
SoSFString name;
|
|
name.setValue(pDoc->getDocument()->getName());
|
|
SoFCDocumentAction cAct(name);
|
|
cAct.apply(_viewer->getSceneGraph());
|
|
}
|
|
|
|
void View3DInventor::onUpdate(void)
|
|
{
|
|
#ifdef FC_LOGUPDATECHAIN
|
|
Base::Console().Log("Acti: Gui::View3DInventor::onUpdate()");
|
|
#endif
|
|
update();
|
|
_viewer->redraw();
|
|
}
|
|
|
|
void View3DInventor::viewAll()
|
|
{
|
|
_viewer->viewAll();
|
|
}
|
|
|
|
const char *View3DInventor::getName(void) const
|
|
{
|
|
return "View3DInventor";
|
|
}
|
|
|
|
void View3DInventor::print()
|
|
{
|
|
QPrinter printer(QPrinter::ScreenResolution);
|
|
printer.setFullPage(true);
|
|
restorePrinterSettings(&printer);
|
|
|
|
QPrintDialog dlg(&printer, this);
|
|
if (dlg.exec() == QDialog::Accepted) {
|
|
Gui::WaitCursor wc;
|
|
print(&printer);
|
|
savePrinterSettings(&printer);
|
|
}
|
|
}
|
|
|
|
void View3DInventor::printPdf()
|
|
{
|
|
QString filename = FileDialog::getSaveFileName(this, tr("Export PDF"), QString(),
|
|
QString::fromLatin1("%1 (*.pdf)").arg(tr("PDF file")));
|
|
if (!filename.isEmpty()) {
|
|
Gui::WaitCursor wc;
|
|
QPrinter printer(QPrinter::ScreenResolution);
|
|
printer.setOutputFormat(QPrinter::PdfFormat);
|
|
printer.setPageOrientation(QPageLayout::Landscape);
|
|
printer.setOutputFileName(filename);
|
|
print(&printer);
|
|
}
|
|
}
|
|
|
|
void View3DInventor::printPreview()
|
|
{
|
|
QPrinter printer(QPrinter::ScreenResolution);
|
|
printer.setFullPage(true);
|
|
restorePrinterSettings(&printer);
|
|
|
|
QPrintPreviewDialog dlg(&printer, this);
|
|
connect(&dlg, SIGNAL(paintRequested (QPrinter *)),
|
|
this, SLOT(print(QPrinter *)));
|
|
dlg.exec();
|
|
savePrinterSettings(&printer);
|
|
}
|
|
|
|
void View3DInventor::print(QPrinter* printer)
|
|
{
|
|
QPainter p(printer);
|
|
p.setRenderHints(QPainter::Antialiasing);
|
|
if (!p.isActive() && !printer->outputFileName().isEmpty()) {
|
|
qApp->setOverrideCursor(Qt::ArrowCursor);
|
|
QMessageBox::critical(this, tr("Opening file failed"),
|
|
tr("Can't open file '%1' for writing.").arg(printer->outputFileName()));
|
|
qApp->restoreOverrideCursor();
|
|
return;
|
|
}
|
|
|
|
QRect rect = printer->pageLayout().paintRectPixels(printer->resolution());
|
|
QImage img;
|
|
_viewer->imageFromFramebuffer(rect.width(), rect.height(), 8, QColor(255,255,255), img);
|
|
p.drawImage(0,0,img);
|
|
p.end();
|
|
}
|
|
|
|
bool View3DInventor::containsViewProvider(const ViewProvider* vp) const
|
|
{
|
|
return _viewer->containsViewProvider(vp);
|
|
}
|
|
|
|
// **********************************************************************************
|
|
|
|
bool View3DInventor::onMsg(const char* pMsg, const char** ppReturn)
|
|
{
|
|
if (strcmp("ViewFit",pMsg) == 0) {
|
|
_viewer->viewAll();
|
|
return true;
|
|
}
|
|
else if (strcmp("ViewVR",pMsg) == 0) {
|
|
// call the VR portion of the viewer
|
|
_viewer->viewVR();
|
|
return true;
|
|
}
|
|
else if(strcmp("ViewSelection",pMsg) == 0) {
|
|
_viewer->viewSelection();
|
|
return true;
|
|
}
|
|
else if(strcmp("SetStereoRedGreen",pMsg) == 0 ) {
|
|
_viewer->setStereoMode(Quarter::SoQTQuarterAdaptor::ANAGLYPH);
|
|
return true;
|
|
}
|
|
else if(strcmp("SetStereoQuadBuff",pMsg) == 0 ) {
|
|
_viewer->setStereoMode(Quarter::SoQTQuarterAdaptor::QUAD_BUFFER );
|
|
return true;
|
|
}
|
|
else if(strcmp("SetStereoInterleavedRows",pMsg) == 0 ) {
|
|
_viewer->setStereoMode(Quarter::SoQTQuarterAdaptor::INTERLEAVED_ROWS );
|
|
return true;
|
|
}
|
|
else if(strcmp("SetStereoInterleavedColumns",pMsg) == 0 ) {
|
|
_viewer->setStereoMode(Quarter::SoQTQuarterAdaptor::INTERLEAVED_COLUMNS );
|
|
return true;
|
|
}
|
|
else if(strcmp("SetStereoOff",pMsg) == 0 ) {
|
|
_viewer->setStereoMode(Quarter::SoQTQuarterAdaptor::MONO );
|
|
return true;
|
|
}
|
|
else if(strcmp("Example1",pMsg) == 0 ) {
|
|
SoSeparator * root = new SoSeparator;
|
|
Texture3D(root);
|
|
_viewer->setSceneGraph(root);
|
|
return true;
|
|
}
|
|
else if(strcmp("Example2",pMsg) == 0 ) {
|
|
SoSeparator * root = new SoSeparator;
|
|
LightManip(root);
|
|
_viewer->setSceneGraph(root);
|
|
return true;
|
|
}
|
|
else if(strcmp("Example3",pMsg) == 0 ) {
|
|
SoSeparator * root = new SoSeparator;
|
|
AnimationTexture(root);
|
|
_viewer->setSceneGraph(root);
|
|
return true;
|
|
}
|
|
else if(strcmp("GetCamera",pMsg) == 0 ) {
|
|
SoCamera * Cam = _viewer->getSoRenderManager()->getCamera();
|
|
if (!Cam)
|
|
return false;
|
|
*ppReturn = SoFCDB::writeNodesToString(Cam).c_str();
|
|
return true;
|
|
}
|
|
else if(strncmp("SetCamera",pMsg,9) == 0 ) {
|
|
return setCamera(pMsg+10);
|
|
}
|
|
else if(strncmp("Dump",pMsg,4) == 0 ) {
|
|
dump(pMsg+5);
|
|
return true;
|
|
}
|
|
else if(strcmp("ViewBottom",pMsg) == 0 ) {
|
|
_viewer->setCameraOrientation(Camera::rotation(Camera::Bottom));
|
|
_viewer->viewAll();
|
|
return true;
|
|
}
|
|
else if(strcmp("ViewFront",pMsg) == 0 ) {
|
|
_viewer->setCameraOrientation(Camera::rotation(Camera::Front));
|
|
_viewer->viewAll();
|
|
return true;
|
|
}
|
|
else if(strcmp("ViewLeft",pMsg) == 0 ) {
|
|
_viewer->setCameraOrientation(Camera::rotation(Camera::Left));
|
|
_viewer->viewAll();
|
|
return true;
|
|
}
|
|
else if(strcmp("ViewRear",pMsg) == 0 ) {
|
|
_viewer->setCameraOrientation(Camera::rotation(Camera::Rear));
|
|
_viewer->viewAll();
|
|
return true;
|
|
}
|
|
else if(strcmp("ViewRight",pMsg) == 0 ) {
|
|
_viewer->setCameraOrientation(Camera::rotation(Camera::Right));
|
|
_viewer->viewAll();
|
|
return true;
|
|
}
|
|
else if(strcmp("ViewTop",pMsg) == 0 ) {
|
|
_viewer->setCameraOrientation(Camera::rotation(Camera::Top));
|
|
_viewer->viewAll();
|
|
return true;
|
|
}
|
|
else if(strcmp("ViewAxo",pMsg) == 0 ) {
|
|
_viewer->setCameraOrientation(Camera::rotation(Camera::Isometric));
|
|
_viewer->viewAll();
|
|
return true;
|
|
}
|
|
else if(strcmp("OrthographicCamera",pMsg) == 0 ) {
|
|
_viewer->setCameraType(SoOrthographicCamera::getClassTypeId());
|
|
return true;
|
|
}
|
|
else if(strcmp("PerspectiveCamera",pMsg) == 0 ) {
|
|
_viewer->setCameraType(SoPerspectiveCamera::getClassTypeId());
|
|
return true;
|
|
}
|
|
else if(strcmp("Undo",pMsg) == 0 ) {
|
|
getGuiDocument()->undo(1);
|
|
return true;
|
|
}
|
|
else if(strcmp("Redo",pMsg) == 0 ) {
|
|
getGuiDocument()->redo(1);
|
|
return true;
|
|
}
|
|
else if (strcmp("Save",pMsg) == 0) {
|
|
getGuiDocument()->save();
|
|
return true;
|
|
}
|
|
else if (strcmp("SaveAs",pMsg) == 0) {
|
|
getGuiDocument()->saveAs();
|
|
return true;
|
|
}
|
|
else if (strcmp("SaveCopy",pMsg) == 0) {
|
|
getGuiDocument()->saveCopy();
|
|
return true;
|
|
}
|
|
else
|
|
return false;
|
|
}
|
|
|
|
bool View3DInventor::onHasMsg(const char* pMsg) const
|
|
{
|
|
if (strcmp("Save",pMsg) == 0)
|
|
return true;
|
|
else if (strcmp("SaveAs",pMsg) == 0)
|
|
return true;
|
|
else if (strcmp("SaveCopy",pMsg) == 0)
|
|
return true;
|
|
else if (strcmp("Undo",pMsg) == 0) {
|
|
App::Document* doc = getAppDocument();
|
|
return doc && doc->getAvailableUndos() > 0;
|
|
}
|
|
else if (strcmp("Redo",pMsg) == 0) {
|
|
App::Document* doc = getAppDocument();
|
|
return doc && doc->getAvailableRedos() > 0;
|
|
}
|
|
else if (strcmp("Print",pMsg) == 0)
|
|
return true;
|
|
else if (strcmp("PrintPreview",pMsg) == 0)
|
|
return true;
|
|
else if (strcmp("PrintPdf",pMsg) == 0)
|
|
return true;
|
|
else if(strcmp("SetStereoRedGreen",pMsg) == 0)
|
|
return true;
|
|
else if(strcmp("SetStereoQuadBuff",pMsg) == 0)
|
|
return true;
|
|
else if(strcmp("SetStereoInterleavedRows",pMsg) == 0)
|
|
return true;
|
|
else if(strcmp("SetStereoInterleavedColumns",pMsg) == 0)
|
|
return true;
|
|
else if(strcmp("SetStereoOff",pMsg) == 0)
|
|
return true;
|
|
else if(strcmp("Example1",pMsg) == 0)
|
|
return true;
|
|
else if(strcmp("Example2",pMsg) == 0)
|
|
return true;
|
|
else if(strcmp("Example3",pMsg) == 0)
|
|
return true;
|
|
else if(strcmp("ViewFit",pMsg) == 0)
|
|
return true;
|
|
else if(strcmp("ViewVR",pMsg) == 0)
|
|
#ifdef BUILD_VR
|
|
return true;
|
|
#else
|
|
return false;
|
|
#endif
|
|
else if(strcmp("ViewSelection",pMsg) == 0)
|
|
return true;
|
|
else if(strcmp("ViewBottom",pMsg) == 0)
|
|
return true;
|
|
else if(strcmp("ViewFront",pMsg) == 0)
|
|
return true;
|
|
else if(strcmp("ViewLeft",pMsg) == 0)
|
|
return true;
|
|
else if(strcmp("ViewRear",pMsg) == 0)
|
|
return true;
|
|
else if(strcmp("ViewRight",pMsg) == 0)
|
|
return true;
|
|
else if(strcmp("ViewTop",pMsg) == 0)
|
|
return true;
|
|
else if(strcmp("ViewAxo",pMsg) == 0)
|
|
return true;
|
|
else if(strcmp("GetCamera",pMsg) == 0)
|
|
return true;
|
|
else if(strncmp("SetCamera",pMsg,9) == 0)
|
|
return true;
|
|
else if(strncmp("Dump",pMsg,4) == 0)
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
bool View3DInventor::setCamera(const char* pCamera)
|
|
{
|
|
SoCamera * CamViewer = _viewer->getSoRenderManager()->getCamera();
|
|
if (!CamViewer) {
|
|
throw Base::RuntimeError("No camera set so far...");
|
|
}
|
|
|
|
SoInput in;
|
|
in.setBuffer((void*)pCamera,std::strlen(pCamera));
|
|
|
|
SoNode * Cam;
|
|
SoDB::read(&in,Cam);
|
|
|
|
if (!Cam || !Cam->isOfType(SoCamera::getClassTypeId())) {
|
|
throw Base::RuntimeError("Camera settings failed to read");
|
|
}
|
|
|
|
// this is to make sure to reliably delete the node
|
|
CoinPtr<SoNode> camPtr(Cam, true);
|
|
|
|
// toggle between perspective and orthographic camera
|
|
if (Cam->getTypeId() != CamViewer->getTypeId()) {
|
|
_viewer->setCameraType(Cam->getTypeId());
|
|
CamViewer = _viewer->getSoRenderManager()->getCamera();
|
|
}
|
|
|
|
SoPerspectiveCamera * CamViewerP = nullptr;
|
|
SoOrthographicCamera * CamViewerO = nullptr;
|
|
|
|
if (CamViewer->getTypeId() == SoPerspectiveCamera::getClassTypeId()) {
|
|
CamViewerP = static_cast<SoPerspectiveCamera *>(CamViewer); // safe downward cast, knows the type
|
|
}
|
|
else if (CamViewer->getTypeId() == SoOrthographicCamera::getClassTypeId()) {
|
|
CamViewerO = static_cast<SoOrthographicCamera *>(CamViewer); // safe downward cast, knows the type
|
|
}
|
|
|
|
if (Cam->getTypeId() == SoPerspectiveCamera::getClassTypeId()) {
|
|
if (CamViewerP){
|
|
CamViewerP->position = static_cast<SoPerspectiveCamera *>(Cam)->position;
|
|
CamViewerP->orientation = static_cast<SoPerspectiveCamera *>(Cam)->orientation;
|
|
CamViewerP->nearDistance = static_cast<SoPerspectiveCamera *>(Cam)->nearDistance;
|
|
CamViewerP->farDistance = static_cast<SoPerspectiveCamera *>(Cam)->farDistance;
|
|
CamViewerP->focalDistance = static_cast<SoPerspectiveCamera *>(Cam)->focalDistance;
|
|
}
|
|
else {
|
|
throw Base::TypeError("Camera type mismatch");
|
|
}
|
|
}
|
|
else if (Cam->getTypeId() == SoOrthographicCamera::getClassTypeId()) {
|
|
if (CamViewerO){
|
|
CamViewerO->viewportMapping = static_cast<SoOrthographicCamera *>(Cam)->viewportMapping;
|
|
CamViewerO->position = static_cast<SoOrthographicCamera *>(Cam)->position;
|
|
CamViewerO->orientation = static_cast<SoOrthographicCamera *>(Cam)->orientation;
|
|
CamViewerO->nearDistance = static_cast<SoOrthographicCamera *>(Cam)->nearDistance;
|
|
CamViewerO->farDistance = static_cast<SoOrthographicCamera *>(Cam)->farDistance;
|
|
CamViewerO->focalDistance = static_cast<SoOrthographicCamera *>(Cam)->focalDistance;
|
|
CamViewerO->aspectRatio = static_cast<SoOrthographicCamera *>(Cam)->aspectRatio ;
|
|
CamViewerO->height = static_cast<SoOrthographicCamera *>(Cam)->height;
|
|
}
|
|
else {
|
|
throw Base::TypeError("Camera type mismatch");
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void View3DInventor::toggleClippingPlane()
|
|
{
|
|
_viewer->toggleClippingPlane();
|
|
}
|
|
|
|
bool View3DInventor::hasClippingPlane() const
|
|
{
|
|
return _viewer->hasClippingPlane();
|
|
}
|
|
|
|
void View3DInventor::setOverlayWidget(QWidget* widget)
|
|
{
|
|
removeOverlayWidget();
|
|
stack->addWidget(widget);
|
|
stack->setCurrentIndex(1);
|
|
}
|
|
|
|
void View3DInventor::removeOverlayWidget()
|
|
{
|
|
stack->setCurrentIndex(0);
|
|
QWidget* overlay = stack->widget(1);
|
|
if (overlay) stack->removeWidget(overlay);
|
|
}
|
|
|
|
void View3DInventor::setOverrideCursor(const QCursor& aCursor)
|
|
{
|
|
_viewer->getWidget()->setCursor(aCursor);
|
|
}
|
|
|
|
void View3DInventor::restoreOverrideCursor()
|
|
{
|
|
_viewer->getWidget()->setCursor(QCursor(Qt::ArrowCursor));
|
|
}
|
|
|
|
// defined in SoFCDB.cpp
|
|
extern SoNode* replaceSwitchesInSceneGraph(SoNode*);
|
|
|
|
void View3DInventor::dump(const char* filename, bool onlyVisible)
|
|
{
|
|
SoGetPrimitiveCountAction action;
|
|
action.setCanApproximate(true);
|
|
action.apply(_viewer->getSceneGraph());
|
|
|
|
SoNode* node = _viewer->getSceneGraph();
|
|
if (onlyVisible) {
|
|
node = replaceSwitchesInSceneGraph(node);
|
|
node->ref();
|
|
}
|
|
|
|
if ( action.getTriangleCount() > 100000 || action.getPointCount() > 30000 || action.getLineCount() > 10000 )
|
|
_viewer->dumpToFile(node, filename, true);
|
|
else
|
|
_viewer->dumpToFile(node, filename, false);
|
|
|
|
if (onlyVisible) {
|
|
node->unref();
|
|
}
|
|
}
|
|
|
|
void View3DInventor::windowStateChanged(MDIView* view)
|
|
{
|
|
bool canStartTimer = false;
|
|
if (this != view) {
|
|
// If both views are child widgets of the workspace and view is maximized this view
|
|
// must be hidden, hence we can start the timer.
|
|
// Note: If view is top-level or fullscreen it doesn't necessarily hide the other view
|
|
// e.g. if it is on a second monitor.
|
|
canStartTimer = (!this->isTopLevel() && !view->isTopLevel() && view->isMaximized());
|
|
} else if (isMinimized()) {
|
|
// I am the active view but minimized
|
|
canStartTimer = true;
|
|
}
|
|
|
|
if (canStartTimer) {
|
|
// do a single shot event (maybe insert a checkbox in viewer settings)
|
|
int msecs = hGrp->GetInt("stopAnimatingIfDeactivated", 3000);
|
|
if (!stopSpinTimer->isActive() && msecs >= 0) { // if < 0 do not stop rotation
|
|
stopSpinTimer->setSingleShot(true);
|
|
stopSpinTimer->start(msecs);
|
|
}
|
|
} else if (stopSpinTimer->isActive()) {
|
|
// If this view may be visible again we can stop the timer
|
|
stopSpinTimer->stop();
|
|
}
|
|
}
|
|
|
|
void View3DInventor::stopAnimating()
|
|
{
|
|
_viewer->stopAnimating();
|
|
}
|
|
|
|
/**
|
|
* Drops the event \a e and writes the right Python command.
|
|
*/
|
|
void View3DInventor::dropEvent (QDropEvent * e)
|
|
{
|
|
const QMimeData* data = e->mimeData();
|
|
if (data->hasUrls()) {
|
|
getMainWindow()->loadUrls(getAppDocument(), data->urls());
|
|
}
|
|
else {
|
|
MDIView::dropEvent(e);
|
|
}
|
|
}
|
|
|
|
void View3DInventor::dragEnterEvent (QDragEnterEvent * e)
|
|
{
|
|
// Here we must allow uri drags and check them in dropEvent
|
|
const QMimeData* data = e->mimeData();
|
|
if (data->hasUrls())
|
|
e->accept();
|
|
else
|
|
e->ignore();
|
|
}
|
|
|
|
void View3DInventor::setCurrentViewMode(ViewMode newmode)
|
|
{
|
|
ViewMode oldmode = MDIView::currentViewMode();
|
|
if (oldmode == newmode)
|
|
return;
|
|
|
|
if (newmode == Child) {
|
|
// Fix in two steps:
|
|
// The mdi view got a QWindow when it became a top-level widget and when resetting it to a child widget
|
|
// the QWindow must be deleted because it has an impact on resize events and may break the layout of
|
|
// mdi view inside the QMdiSubWindow.
|
|
// In the second step below the layout must be invalidated after it's again a child widget to make sure
|
|
// the mdi view fits into the QMdiSubWindow.
|
|
QWindow* winHandle = this->windowHandle();
|
|
if (winHandle)
|
|
winHandle->destroy();
|
|
}
|
|
|
|
MDIView::setCurrentViewMode(newmode);
|
|
|
|
// Internally the QOpenGLWidget switches of the multi-sampling and there is no
|
|
// way to switch it on again. So as a workaround we just re-create a new viewport
|
|
// The method is private but defined as slot to avoid to call it by accident.
|
|
//int index = _viewer->metaObject()->indexOfMethod("replaceViewport()");
|
|
//if (index >= 0) {
|
|
// _viewer->qt_metacall(QMetaObject::InvokeMetaMethod, index, 0);
|
|
//}
|
|
|
|
// This widget becomes the focus proxy of the embedded GL widget if we leave
|
|
// the 'Child' mode. If we reenter 'Child' mode the focus proxy is reset to 0.
|
|
// If we change from 'TopLevel' mode to 'Fullscreen' mode or vice versa nothing
|
|
// happens.
|
|
// Grabbing keyboard when leaving 'Child' mode (as done in a recent version) should
|
|
// be avoided because when two or more windows are either in 'TopLevel' or 'Fullscreen'
|
|
// mode only the last window gets all key event even if it is not the active one.
|
|
//
|
|
// It is important to set the focus proxy to get all key events otherwise we would lose
|
|
// control after redirecting the first key event to the GL widget.
|
|
if (oldmode == Child) {
|
|
// To make a global shortcut working from this window we need to add
|
|
// all existing actions from the mainwindow and its sub-widgets
|
|
QList<QAction*> acts = getMainWindow()->findChildren<QAction*>();
|
|
this->addActions(acts);
|
|
_viewer->getGLWidget()->setFocusProxy(this);
|
|
// To be notfified for new actions
|
|
qApp->installEventFilter(this);
|
|
}
|
|
else if (newmode == Child) {
|
|
_viewer->getGLWidget()->setFocusProxy(nullptr);
|
|
qApp->removeEventFilter(this);
|
|
QList<QAction*> acts = this->actions();
|
|
for (QList<QAction*>::Iterator it = acts.begin(); it != acts.end(); ++it)
|
|
this->removeAction(*it);
|
|
|
|
// Step two
|
|
QMdiSubWindow* mdi = qobject_cast<QMdiSubWindow*>(parentWidget());
|
|
if (mdi && mdi->layout())
|
|
mdi->layout()->invalidate();
|
|
}
|
|
}
|
|
|
|
bool View3DInventor::eventFilter(QObject* watched, QEvent* e)
|
|
{
|
|
// As long as this widget is a top-level window (either in 'TopLevel' or 'FullScreen' mode) we
|
|
// need to be notified when an action is added to a widget. This action must also be added to
|
|
// this window to allow to make use of its shortcut (if defined).
|
|
// Note: We don't need to care about removing an action if its parent widget gets destroyed.
|
|
// This does the action itself for us.
|
|
if (watched != this && e->type() == QEvent::ActionAdded) {
|
|
QActionEvent* a = static_cast<QActionEvent*>(e);
|
|
QAction* action = a->action();
|
|
|
|
if (!action->isSeparator()) {
|
|
QList<QAction*> actions = this->actions();
|
|
if (!actions.contains(action))
|
|
this->addAction(action);
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void View3DInventor::keyPressEvent (QKeyEvent* e)
|
|
{
|
|
// See StdViewDockUndockFullscreen::activated()
|
|
// With Qt5 one cannot directly use 'setCurrentViewMode'
|
|
// of an MDI view because it causes rendering problems.
|
|
// The only reliable solution is to clone the MDI view,
|
|
// set its view mode and close the original MDI view.
|
|
|
|
QMainWindow::keyPressEvent(e);
|
|
}
|
|
|
|
void View3DInventor::keyReleaseEvent (QKeyEvent* e)
|
|
{
|
|
QMainWindow::keyReleaseEvent(e);
|
|
}
|
|
|
|
void View3DInventor::focusInEvent (QFocusEvent *)
|
|
{
|
|
_viewer->getGLWidget()->setFocus();
|
|
}
|
|
|
|
void View3DInventor::contextMenuEvent (QContextMenuEvent*e)
|
|
{
|
|
MDIView::contextMenuEvent(e);
|
|
}
|
|
|
|
void View3DInventor::customEvent(QEvent * e)
|
|
{
|
|
if (e->type() == QEvent::User) {
|
|
NavigationStyleEvent* se = static_cast<NavigationStyleEvent*>(e);
|
|
ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath
|
|
("User parameter:BaseApp/Preferences/View");
|
|
if (hGrp->GetBool("SameStyleForAllViews", true))
|
|
hGrp->SetASCII("NavigationStyle", se->style().getName());
|
|
else
|
|
_viewer->setNavigationType(se->style());
|
|
}
|
|
}
|
|
|
|
|
|
#include "moc_View3DInventor.cpp"
|