"Professional CMake" book suggest the following: "Targets should build successfully with or without compiler support for precompiled headers. It should be considered an optimization, not a requirement. In particular, do not explicitly include a precompile header (e.g. stdafx.h) in the source code, let CMake force-include an automatically generated precompile header on the compiler command line instead. This is more portable across the major compilers and is likely to be easier to maintain. It will also avoid warnings being generated from certain code checking tools like iwyu (include what you use)." Therefore, removed the "#include <PreCompiled.h>" from sources, also there is no need for the "#ifdef _PreComp_" anymore
1324 lines
47 KiB
C++
1324 lines
47 KiB
C++
/***************************************************************************
|
|
* Copyright (c) 2013 Luke Parry <l.parry@warwick.ac.uk> *
|
|
* *
|
|
* 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 <QPainterPath>
|
|
#include <QKeyEvent>
|
|
#include <cstdio>
|
|
#include <qmath.h>
|
|
|
|
#include <App/Application.h>
|
|
#include <App/Document.h>
|
|
#include <Base/Console.h>
|
|
#include <Base/Parameter.h>
|
|
#include <Base/Tools.h>
|
|
#include <Base/Vector3D.h>
|
|
#include <Gui/Selection/Selection.h>
|
|
#include <Mod/TechDraw/App/CenterLine.h>
|
|
#include <Mod/TechDraw/App/Cosmetic.h>
|
|
#include <Mod/TechDraw/App/DrawComplexSection.h>
|
|
#include <Mod/TechDraw/App/DrawGeomHatch.h>
|
|
#include <Mod/TechDraw/App/DrawHatch.h>
|
|
#include <Mod/TechDraw/App/DrawUtil.h>
|
|
#include <Mod/TechDraw/App/DrawViewDetail.h>
|
|
#include <Mod/TechDraw/App/DrawViewPart.h>
|
|
#include <Mod/TechDraw/App/DrawViewSection.h>
|
|
#include <Mod/TechDraw/App/Geometry.h>
|
|
#include <Mod/TechDraw/App/DrawBrokenView.h>
|
|
|
|
#include "DrawGuiUtil.h"
|
|
#include "MDIViewPage.h"
|
|
#include "PreferencesGui.h"
|
|
#include "QGICMark.h"
|
|
#include "QGICenterLine.h"
|
|
#include "QGIEdge.h"
|
|
#include "QGIFace.h"
|
|
#include "QGIHighlight.h"
|
|
#include "QGIMatting.h"
|
|
#include "QGISectionLine.h"
|
|
#include "QGIVertex.h"
|
|
#include "QGIViewPart.h"
|
|
#include "Rez.h"
|
|
#include "ViewProviderGeomHatch.h"
|
|
#include "ViewProviderHatch.h"
|
|
#include "ViewProviderViewPart.h"
|
|
#include "ZVALUE.h"
|
|
#include "PathBuilder.h"
|
|
#include "QGIBreakLine.h"
|
|
|
|
using namespace TechDraw;
|
|
using namespace TechDrawGui;
|
|
using namespace std;
|
|
using DU = DrawUtil;
|
|
using FillMode = QGIFace::FillMode;
|
|
|
|
const float lineScaleFactor = Rez::guiX(1.);// temp fiddle for devel
|
|
|
|
QGIViewPart::QGIViewPart()
|
|
{
|
|
setCacheMode(QGraphicsItem::NoCache);
|
|
setHandlesChildEvents(false);
|
|
setAcceptHoverEvents(true);
|
|
setFlag(QGraphicsItem::ItemIsSelectable, true);
|
|
setFlag(QGraphicsItem::ItemIsMovable, true);
|
|
setFlag(QGraphicsItem::ItemSendsScenePositionChanges, true);
|
|
setFlag(QGraphicsItem::ItemSendsGeometryChanges, true);
|
|
setFlag(QGraphicsItem::ItemIsFocusable, true);
|
|
|
|
showSection = false;
|
|
m_pathBuilder = new PathBuilder(this);
|
|
m_dashedLineGenerator = new LineGenerator();
|
|
}
|
|
|
|
QGIViewPart::~QGIViewPart()
|
|
{
|
|
tidy();
|
|
delete m_pathBuilder;
|
|
delete m_dashedLineGenerator;
|
|
}
|
|
|
|
QVariant QGIViewPart::itemChange(GraphicsItemChange change, const QVariant& value)
|
|
{
|
|
if (change == ItemSelectedHasChanged && scene()) {
|
|
bool selectState = value.toBool();
|
|
if (!selectState && !isUnderMouse()) {
|
|
// hide everything
|
|
for (auto& child : childItems()) {
|
|
if (child->type() == UserType::QGIVertex) {
|
|
child->hide();
|
|
}
|
|
}
|
|
return QGIView::itemChange(change, value);
|
|
}
|
|
// we are selected
|
|
}
|
|
else if (change == ItemSceneChange && scene()) {
|
|
// this is means we are finished?
|
|
tidy();
|
|
}
|
|
|
|
return QGIView::itemChange(change, value);
|
|
}
|
|
|
|
bool QGIViewPart::sceneEventFilter(QGraphicsItem *watched, QEvent *event)
|
|
{
|
|
if (event->type() == QEvent::ShortcutOverride) {
|
|
// if we accept this event, we should get a regular keystroke event next
|
|
// which will be processed by QGVPage/QGVNavStyle keypress logic, but not forwarded to
|
|
// Std_Delete
|
|
auto *keyEvent = static_cast<QKeyEvent*>(event);
|
|
if (keyEvent->matches(QKeySequence::Delete)) {
|
|
bool success = removeSelectedCosmetic();
|
|
if (success) {
|
|
updateView(true);
|
|
event->accept();
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return QGraphicsItem::sceneEventFilter(watched, event);
|
|
}
|
|
|
|
//! called when a DEL shortcut event is received. If a cosmetic edge or vertex is
|
|
//! selected, remove it from the view.
|
|
bool QGIViewPart::removeSelectedCosmetic() const
|
|
{
|
|
// Base::Console().message("QGIVP::removeSelectedCosmetic()\n");
|
|
auto dvp(dynamic_cast<TechDraw::DrawViewPart*>(getViewObject()));
|
|
if (!dvp) {
|
|
throw Base::RuntimeError("Graphic has no feature!");
|
|
}
|
|
char* defaultDocument{nullptr};
|
|
std::vector<Gui::SelectionObject> selectionAll = Gui::Selection().getSelectionEx(
|
|
defaultDocument, TechDraw::DrawViewPart::getClassTypeId(), Gui::ResolveMode::OldStyleElement);
|
|
if (selectionAll.empty()) {
|
|
return false;
|
|
}
|
|
std::vector<std::string> subElements = selectionAll.front().getSubNames();
|
|
if (subElements.empty()) {
|
|
return false;
|
|
}
|
|
|
|
dvp->deleteCosmeticElements(subElements);
|
|
dvp->refreshCEGeoms();
|
|
dvp->refreshCLGeoms();
|
|
dvp->refreshCVGeoms();
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
//obs?
|
|
void QGIViewPart::tidy()
|
|
{
|
|
//Delete any leftover items
|
|
for (QList<QGraphicsItem*>::iterator it = deleteItems.begin(); it != deleteItems.end(); ++it) {
|
|
delete *it;
|
|
}
|
|
deleteItems.clear();
|
|
}
|
|
|
|
void QGIViewPart::setViewPartFeature(TechDraw::DrawViewPart* obj)
|
|
{
|
|
if (!obj)
|
|
return;
|
|
|
|
setViewFeature(static_cast<TechDraw::DrawView*>(obj));
|
|
}
|
|
|
|
QPainterPath QGIViewPart::drawPainterPath(TechDraw::BaseGeomPtr baseGeom) const
|
|
{
|
|
double rot = getViewObject()->Rotation.getValue();
|
|
return m_pathBuilder->geomToPainterPath(baseGeom, rot);
|
|
}
|
|
void QGIViewPart::updateView(bool update)
|
|
{
|
|
// Base::Console().message("QGIVP::updateView() - %s\n", getViewObject()->getNameInDocument());
|
|
auto viewPart(dynamic_cast<TechDraw::DrawViewPart*>(getViewObject()));
|
|
if (!viewPart)
|
|
return;
|
|
auto vp = static_cast<ViewProviderViewPart*>(getViewProvider(getViewObject()));
|
|
if (!vp)
|
|
return;
|
|
|
|
if (update)
|
|
draw();
|
|
QGIView::updateView(update);
|
|
}
|
|
|
|
void QGIViewPart::draw()
|
|
{
|
|
auto viewPart(dynamic_cast<TechDraw::DrawViewPart*>(getViewObject()));
|
|
if (!viewPart) {
|
|
return;
|
|
}
|
|
|
|
auto doc = viewPart->getDocument();
|
|
if (!doc || doc->testStatus(App::Document::Status::Restoring)) {
|
|
// if the document is still restoring, we may not have all the information
|
|
// we need to draw the source objects, so we wait until restore is finished.
|
|
// Base::Console().message("QGIVP::draw - document is restoring, do not draw\n");
|
|
return;
|
|
}
|
|
|
|
if (!isVisible())
|
|
return;
|
|
|
|
drawViewPart();
|
|
drawAllHighlights();
|
|
drawBreakLines();
|
|
drawMatting();
|
|
//this is old C/L
|
|
drawCenterLines(true);//have to draw centerlines after border to get size correct.
|
|
drawAllSectionLines();//same for section lines
|
|
}
|
|
|
|
void QGIViewPart::drawViewPart()
|
|
{
|
|
auto viewPart(dynamic_cast<TechDraw::DrawViewPart*>(getViewObject()));
|
|
if (!viewPart)
|
|
return;
|
|
// Base::Console().message("QGIVP::DVP() - %s / %s\n", viewPart->getNameInDocument(), viewPart->Label.getValue());
|
|
if (!viewPart->hasGeometry()) {
|
|
removePrimitives();//clean the slate
|
|
removeDecorations();
|
|
return;
|
|
}
|
|
|
|
auto vp = static_cast<ViewProviderViewPart*>(getViewProvider(getViewObject()));
|
|
if (!vp)
|
|
return;
|
|
|
|
prepareGeometryChange();
|
|
removePrimitives();//clean the slate
|
|
removeDecorations();
|
|
|
|
if (viewPart->handleFaces() && !viewPart->CoarseView.getValue()) {
|
|
drawAllFaces();
|
|
}
|
|
|
|
drawAllEdges();
|
|
|
|
drawAllVertexes();
|
|
}
|
|
|
|
void QGIViewPart::drawAllFaces(void)
|
|
{
|
|
// dvp already validated
|
|
auto dvp(static_cast<TechDraw::DrawViewPart*>(getViewObject()));
|
|
|
|
QColor faceColor;
|
|
auto vpp = dynamic_cast<ViewProviderViewPart *>(getViewProvider(getViewObject()));
|
|
if (vpp) {
|
|
faceColor = vpp->FaceColor.getValue().asValue<QColor>();
|
|
faceColor.setAlpha((100 - vpp->FaceTransparency.getValue())*255/100);
|
|
}
|
|
|
|
std::vector<TechDraw::DrawHatch*> regularHatches = dvp->getHatches();
|
|
std::vector<TechDraw::DrawGeomHatch*> geomHatches = dvp->getGeomHatches();
|
|
const std::vector<TechDraw::FacePtr>& faceGeoms = dvp->getFaceGeometry();
|
|
int iFace(0);
|
|
for (auto& face : faceGeoms) {
|
|
QGIFace* newFace = drawFace(face, iFace);
|
|
if (faceColor.isValid()) {
|
|
newFace->setFillColor(faceColor);
|
|
newFace->setFillMode(faceColor.alpha() ? FillMode::PlainFill : FillMode::NoFill);
|
|
}
|
|
|
|
TechDraw::DrawHatch* fHatch = faceIsHatched(iFace, regularHatches);
|
|
TechDraw::DrawGeomHatch* fGeom = faceIsGeomHatched(iFace, geomHatches);
|
|
if (fGeom) {
|
|
// geometric hatch (from PAT hatch specification)
|
|
newFace->isHatched(true);
|
|
newFace->setFillMode(FillMode::GeomHatchFill);
|
|
std::vector<LineSet> lineSets = fGeom->getTrimmedLines(iFace);
|
|
if (!lineSets.empty()) {
|
|
// this face has geometric hatch lines
|
|
for (auto& ls : lineSets) {
|
|
newFace->addLineSet(ls);
|
|
}
|
|
}
|
|
double hatchScale = fGeom->ScalePattern.getValue();
|
|
if (hatchScale > 0.0) {
|
|
newFace->setHatchScale(fGeom->ScalePattern.getValue());
|
|
}
|
|
newFace->setHatchRotation(fGeom->PatternRotation.getValue());
|
|
newFace->setHatchOffset(fGeom->PatternOffset.getValue());
|
|
newFace->setHatchFile(fGeom->PatIncluded.getValue());
|
|
Gui::ViewProvider* gvp = QGIView::getViewProvider(fGeom);
|
|
ViewProviderGeomHatch* geomVp = freecad_cast<ViewProviderGeomHatch*>(gvp);
|
|
if (geomVp) {
|
|
newFace->setHatchColor(geomVp->ColorPattern.getValue());
|
|
newFace->setLineWeight(geomVp->WeightPattern.getValue());
|
|
}
|
|
} else if (fHatch) {
|
|
// svg or bitmap hatch
|
|
newFace->isHatched(true);
|
|
if (!fHatch->SvgIncluded.isEmpty()) {
|
|
newFace->setHatchFile(fHatch->SvgIncluded.getValue());
|
|
}
|
|
if (fHatch->isSvgHatch()) {
|
|
// svg tile hatch
|
|
newFace->setFillMode(FillMode::SvgFill);
|
|
} else {
|
|
//bitmap hatch
|
|
newFace->setFillMode(FillMode::BitmapFill);
|
|
}
|
|
|
|
// get the properties from the hatch viewprovider
|
|
Gui::ViewProvider* gvp = QGIView::getViewProvider(fHatch);
|
|
ViewProviderHatch* hatchVp = freecad_cast<ViewProviderHatch*>(gvp);
|
|
if (hatchVp) {
|
|
if (hatchVp->HatchScale.getValue() > 0.0) {
|
|
newFace->setHatchScale(hatchVp->HatchScale.getValue());
|
|
}
|
|
newFace->setHatchColor(hatchVp->HatchColor.getValue());
|
|
newFace->setHatchRotation(hatchVp->HatchRotation.getValue());
|
|
newFace->setHatchOffset(hatchVp->HatchOffset.getValue());
|
|
}
|
|
}
|
|
|
|
newFace->setDrawEdges(prefFaceEdges());
|
|
newFace->setZValue(ZVALUE::FACE);
|
|
newFace->setPrettyNormal();
|
|
newFace->draw();
|
|
iFace++;
|
|
}
|
|
}
|
|
|
|
void QGIViewPart::drawAllEdges()
|
|
{
|
|
// dvp and vp already validated
|
|
auto dvp(static_cast<TechDraw::DrawViewPart*>(getViewObject()));
|
|
auto vp = static_cast<ViewProviderViewPart*>(getViewProvider(getViewObject()));
|
|
|
|
const TechDraw::BaseGeomPtrVector& geoms = dvp->getEdgeGeometry();
|
|
TechDraw::BaseGeomPtrVector::const_iterator itGeom = geoms.begin();
|
|
QGIEdge* item;
|
|
for (int iEdge = 0; itGeom != geoms.end(); itGeom++, iEdge++) {
|
|
bool showItem = true;
|
|
if (!showThisEdge(*itGeom)) {
|
|
continue;
|
|
}
|
|
|
|
item = new QGIEdge(iEdge);
|
|
addToGroup(item); //item is created at scene(0, 0), not group(0, 0)
|
|
item->setPath(drawPainterPath(*itGeom));
|
|
item->setSource((*itGeom)->source());
|
|
|
|
item->setNormalColor(PreferencesGui::getAccessibleQColor(PreferencesGui::normalQColor()));
|
|
if ((*itGeom)->getCosmetic()) {
|
|
// cosmetic edge - format appropriately
|
|
TechDraw::SourceType source = (*itGeom)->source();
|
|
if (source == TechDraw::SourceType::COSMETICEDGE) {
|
|
std::string cTag = (*itGeom)->getCosmeticTag();
|
|
showItem = formatGeomFromCosmetic(cTag, item);
|
|
}
|
|
else if (source == TechDraw::SourceType::CENTERLINE) {
|
|
std::string cTag = (*itGeom)->getCosmeticTag();
|
|
showItem = formatGeomFromCenterLine(cTag, item);
|
|
}
|
|
else {
|
|
Base::Console().message("QGIVP::drawVP - cosmetic edge: %d is confused - source: %d\n",
|
|
iEdge, static_cast<int>(source));
|
|
}
|
|
} else {
|
|
// geometry edge - apply format if applicable
|
|
TechDraw::GeomFormat* gf = dvp->getGeomFormatBySelection(iEdge);
|
|
if (gf) {
|
|
Base::Color color = Preferences::getAccessibleColor(gf->m_format.getColor());
|
|
item->setNormalColor(color.asValue<QColor>());
|
|
int lineNumber = gf->m_format.getLineNumber();
|
|
int qtStyle = gf->m_format.getStyle();
|
|
item->setLinePen(m_dashedLineGenerator->getBestPen(lineNumber, (Qt::PenStyle)qtStyle,
|
|
gf->m_format.getWidth()));
|
|
// but we need to actually draw the lines in QGScene coords (0.1 mm).
|
|
item->setWidth(Rez::guiX(gf->m_format.getWidth()));
|
|
showItem = gf->m_format.getVisible();
|
|
} else {
|
|
if (!(*itGeom)->getHlrVisible()) {
|
|
// hidden line without a format
|
|
item->setLinePen(m_dashedLineGenerator->getLinePen(Preferences::HiddenLineStyle(),
|
|
vp->LineWidth.getValue()));
|
|
item->setHiddenEdge(true);
|
|
item->setWidth(Rez::guiX(vp->HiddenWidth.getValue())); //thin
|
|
item->setZValue(ZVALUE::HIDEDGE);
|
|
} else {
|
|
// unformatted visible line, draw as continuous line
|
|
item->setLinePen(m_dashedLineGenerator->getLinePen(1, vp->LineWidth.getValue()));
|
|
item->setWidth(Rez::guiX(vp->LineWidth.getValue()));
|
|
}
|
|
}
|
|
}
|
|
|
|
if ((*itGeom)->getClassOfEdge() == EdgeClass::UVISO) {
|
|
// we don't have a style option for iso-parametric lines so draw continuous
|
|
item->setLinePen(m_dashedLineGenerator->getLinePen(1, vp->IsoWidth.getValue()));
|
|
item->setWidth(Rez::guiX(vp->IsoWidth.getValue())); //graphic
|
|
}
|
|
|
|
item->setPos(0.0, 0.0);//now at group(0, 0)
|
|
item->setZValue(ZVALUE::EDGE);
|
|
item->setPrettyNormal();
|
|
|
|
if (!vp->ShowAllEdges.getValue() && !showItem) {
|
|
//view level "show" status && individual edge "show" status
|
|
item->hide();
|
|
}
|
|
|
|
//debug a path
|
|
// QPainterPath edgePath=drawPainterPath(*itGeom);
|
|
// std::stringstream edgeId;
|
|
// edgeId << "QGIVP.edgePath" << i;
|
|
// dumpPath(edgeId.str().c_str(), edgePath);
|
|
}
|
|
}
|
|
|
|
void QGIViewPart::drawAllVertexes()
|
|
{
|
|
// dvp and vp already validated
|
|
auto dvp(static_cast<TechDraw::DrawViewPart*>(getViewObject()));
|
|
auto vp(static_cast<ViewProviderViewPart*>(getViewProvider(getViewObject())));
|
|
QColor vertexColor = PreferencesGui::getAccessibleQColor(PreferencesGui::vertexQColor());
|
|
|
|
const std::vector<TechDraw::VertexPtr>& verts = dvp->getVertexGeometry();
|
|
std::vector<TechDraw::VertexPtr>::const_iterator vert = verts.begin();
|
|
for (int i = 0; vert != verts.end(); ++vert, i++) {
|
|
if ((*vert)->isCenter()) {
|
|
if (showCenterMarks()) {
|
|
auto* cmItem = new QGICMark(i);
|
|
addToGroup(cmItem);
|
|
cmItem->setPos(Rez::guiX((*vert)->x()), Rez::guiX((*vert)->y()));
|
|
cmItem->setThick(0.5F * getLineWidth());//need minimum?
|
|
cmItem->setSize(getVertexSize() * vp->CenterScale.getValue());
|
|
cmItem->setPrettyNormal();
|
|
cmItem->setZValue(ZVALUE::VERTEX);
|
|
cmItem->setVisible(false);
|
|
}
|
|
} else {
|
|
//regular Vertex
|
|
if (showVertices()) {
|
|
auto* item = new QGIVertex(i);
|
|
addToGroup(item);
|
|
item->setPos(Rez::guiX((*vert)->x()), Rez::guiX((*vert)->y()));
|
|
item->setNormalColor(vertexColor);
|
|
item->setFillColor(vertexColor);
|
|
item->setRadius(getVertexSize());
|
|
item->setPrettyNormal();
|
|
item->setZValue(ZVALUE::VERTEX);
|
|
item->setVisible(false);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool QGIViewPart::showThisEdge(BaseGeomPtr geom)
|
|
{
|
|
// dvp and vp already validated
|
|
auto dvp(static_cast<TechDraw::DrawViewPart*>(getViewObject()));
|
|
|
|
if (geom->getHlrVisible()) {
|
|
if ((geom->getClassOfEdge() == EdgeClass::HARD) || (geom->getClassOfEdge() == EdgeClass::OUTLINE)
|
|
|| ((geom->getClassOfEdge() == EdgeClass::SMOOTH) && dvp->SmoothVisible.getValue())
|
|
|| ((geom->getClassOfEdge() == EdgeClass::SEAM) && dvp->SeamVisible.getValue())
|
|
|| ((geom->getClassOfEdge() == EdgeClass::UVISO) && dvp->IsoVisible.getValue())) {
|
|
return true;
|
|
}
|
|
} else {
|
|
if (((geom->getClassOfEdge() == EdgeClass::HARD) && (dvp->HardHidden.getValue()))
|
|
|| ((geom->getClassOfEdge() == EdgeClass::OUTLINE) && (dvp->HardHidden.getValue()))
|
|
|| ((geom->getClassOfEdge() == EdgeClass::SMOOTH) && (dvp->SmoothHidden.getValue()))
|
|
|| ((geom->getClassOfEdge() == EdgeClass::SEAM) && (dvp->SeamHidden.getValue()))
|
|
|| ((geom->getClassOfEdge() == EdgeClass::UVISO) && (dvp->IsoHidden.getValue()))) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// returns true if vertex dots should be shown
|
|
bool QGIViewPart::showVertices()
|
|
{
|
|
// dvp and vp already validated
|
|
auto dvp(static_cast<TechDraw::DrawViewPart*>(getViewObject()));
|
|
|
|
if (dvp->CoarseView.getValue()) {
|
|
// never show vertices in CoarseView
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
// returns true if arc center marks should be shown
|
|
bool QGIViewPart::showCenterMarks()
|
|
{
|
|
// dvp and vp already validated
|
|
auto dvp(static_cast<TechDraw::DrawViewPart*>(getViewObject()));
|
|
auto vp(static_cast<ViewProviderViewPart*>(getViewProvider(dvp)));
|
|
|
|
if (!vp->ArcCenterMarks.getValue()) {
|
|
// no center marks if view property is false
|
|
return false;
|
|
}
|
|
if (prefPrintCenters()) {
|
|
// frames are off, view property is true and Print Center Marks is true
|
|
return true;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
bool QGIViewPart::formatGeomFromCosmetic(std::string cTag, QGIEdge* item)
|
|
{
|
|
// Base::Console().message("QGIVP::formatGeomFromCosmetic(%s)\n", cTag.c_str());
|
|
bool result = true;
|
|
auto partFeat(dynamic_cast<TechDraw::DrawViewPart*>(getViewObject()));
|
|
TechDraw::CosmeticEdge* ce = partFeat ? partFeat->getCosmeticEdge(cTag) : nullptr;
|
|
if (ce) {
|
|
Base::Color color = Preferences::getAccessibleColor(ce->m_format.getColor());
|
|
item->setNormalColor(color.asValue<QColor>());
|
|
item->setLinePen(m_dashedLineGenerator->getBestPen(ce->m_format.getLineNumber(),
|
|
(Qt::PenStyle)ce->m_format.getStyle(),
|
|
ce->m_format.getWidth()));
|
|
item->setWidth(Rez::guiX(ce->m_format.getWidth()));
|
|
result = ce->m_format.getVisible();
|
|
}
|
|
return result;
|
|
}
|
|
|
|
|
|
bool QGIViewPart::formatGeomFromCenterLine(std::string cTag, QGIEdge* item)
|
|
{
|
|
// Base::Console().message("QGIVP::formatGeomFromCenterLine()\n");
|
|
bool result = true;
|
|
auto partFeat(dynamic_cast<TechDraw::DrawViewPart*>(getViewObject()));
|
|
TechDraw::CenterLine* cl = partFeat ? partFeat->getCenterLine(cTag) : nullptr;
|
|
if (cl) {
|
|
Base::Color color = Preferences::getAccessibleColor(cl->m_format.getColor());
|
|
item->setNormalColor(color.asValue<QColor>());
|
|
item->setLinePen(m_dashedLineGenerator->getBestPen(cl->m_format.getLineNumber(),
|
|
(Qt::PenStyle)cl->m_format.getStyle(),
|
|
cl->m_format.getWidth()));
|
|
item->setWidth(Rez::guiX(cl->m_format.getWidth()));
|
|
result = cl->m_format.getVisible();
|
|
}
|
|
return result;
|
|
}
|
|
|
|
QGIFace* QGIViewPart::drawFace(TechDraw::FacePtr f, int idx)
|
|
{
|
|
// Base::Console().message("QGIVP::drawFace - %d\n", idx);
|
|
std::vector<TechDraw::Wire*> fWires = f->wires;
|
|
QPainterPath facePath;
|
|
for (std::vector<TechDraw::Wire*>::iterator wire = fWires.begin(); wire != fWires.end();
|
|
++wire) {
|
|
TechDraw::BaseGeomPtrVector geoms = (*wire)->geoms;
|
|
if (geoms.empty())
|
|
continue;
|
|
|
|
TechDraw::BaseGeomPtr firstGeom = geoms.front();
|
|
QPainterPath wirePath;
|
|
//QPointF startPoint(firstGeom->getStartPoint().x, firstGeom->getStartPoint().y);
|
|
//wirePath.moveTo(startPoint);
|
|
QPainterPath firstSeg = drawPainterPath(firstGeom);
|
|
wirePath.connectPath(firstSeg);
|
|
for (TechDraw::BaseGeomPtrVector::iterator edge = ((*wire)->geoms.begin()) + 1;
|
|
edge != (*wire)->geoms.end(); ++edge) {
|
|
QPainterPath edgePath = drawPainterPath(*edge);
|
|
//handle section faces differently
|
|
if (idx == -1) {
|
|
QPointF wEnd = wirePath.currentPosition();
|
|
auto element = edgePath.elementAt(0);
|
|
QPointF eStart(element.x, element.y);
|
|
QPointF eEnd = edgePath.currentPosition();
|
|
QPointF sVec = wEnd - eStart;
|
|
QPointF eVec = wEnd - eEnd;
|
|
double sDist2 = sVec.x() * sVec.x() + sVec.y() * sVec.y();
|
|
double eDist2 = eVec.x() * eVec.x() + eVec.y() * eVec.y();
|
|
if (sDist2 > eDist2) {
|
|
edgePath = edgePath.toReversed();
|
|
}
|
|
}
|
|
wirePath.connectPath(edgePath);
|
|
}
|
|
// dumpPath("wirePath:", wirePath);
|
|
facePath.addPath(wirePath);
|
|
}
|
|
facePath.setFillRule(Qt::OddEvenFill);
|
|
|
|
QGIFace* gFace = new QGIFace(idx);
|
|
addToGroup(gFace);
|
|
gFace->setPos(0.0, 0.0);
|
|
gFace->setOutline(facePath);
|
|
//debug a path
|
|
//std::stringstream faceId;
|
|
//faceId << "facePath " << idx;
|
|
//dumpPath(faceId.str().c_str(), facePath);
|
|
|
|
return gFace;
|
|
}
|
|
|
|
//! Remove all existing QGIPrimPath items(Vertex, Edge, Face)
|
|
//note this triggers scene selectionChanged signal if vertex/edge/face is selected
|
|
void QGIViewPart::removePrimitives()
|
|
{
|
|
QList<QGraphicsItem*> children = childItems();
|
|
MDIViewPage* mdi = getMDIViewPage();
|
|
if (mdi) {
|
|
getMDIViewPage()->blockSceneSelection(true);
|
|
}
|
|
for (auto& c : children) {
|
|
QGIPrimPath* prim = dynamic_cast<QGIPrimPath*>(c);
|
|
if (prim) {
|
|
prim->hide();
|
|
scene()->removeItem(prim);
|
|
delete prim;
|
|
}
|
|
}
|
|
if (mdi) {
|
|
getMDIViewPage()->blockSceneSelection(false);
|
|
}
|
|
}
|
|
|
|
//! Remove all existing QGIDecoration items(SectionLine, SectionMark, ...)
|
|
void QGIViewPart::removeDecorations()
|
|
{
|
|
QList<QGraphicsItem*> children = childItems();
|
|
for (auto& c : children) {
|
|
QGIDecoration* decor = dynamic_cast<QGIDecoration*>(c);
|
|
QGIMatting* mat = dynamic_cast<QGIMatting*>(c);
|
|
if (decor) {
|
|
decor->hide();
|
|
scene()->removeItem(decor);
|
|
delete decor;
|
|
}
|
|
else if (mat) {
|
|
mat->hide();
|
|
scene()->removeItem(mat);
|
|
delete mat;
|
|
}
|
|
}
|
|
}
|
|
|
|
void QGIViewPart::drawAllSectionLines()
|
|
{
|
|
TechDraw::DrawViewPart* viewPart = static_cast<TechDraw::DrawViewPart*>(getViewObject());
|
|
if (!viewPart)
|
|
return;
|
|
|
|
auto vp = static_cast<ViewProviderViewPart*>(getViewProvider(getViewObject()));
|
|
if (!vp) {
|
|
return;
|
|
}
|
|
|
|
if (vp->ShowSectionLine.getValue()) {
|
|
auto refs = viewPart->getSectionRefs();
|
|
for (auto& r : refs) {
|
|
if (r->isDerivedFrom<DrawComplexSection>()) {
|
|
drawComplexSectionLine(r, true);
|
|
}
|
|
else {
|
|
drawSectionLine(r, true);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void QGIViewPart::drawSectionLine(TechDraw::DrawViewSection* viewSection, bool b)
|
|
{
|
|
// Base::Console().message("QGIVP::drawSectionLine()\n");
|
|
TechDraw::DrawViewPart* viewPart = static_cast<TechDraw::DrawViewPart*>(getViewObject());
|
|
if (!viewPart)
|
|
return;
|
|
if (!viewSection)
|
|
return;
|
|
|
|
if (!viewSection->hasGeometry())
|
|
return;
|
|
|
|
auto vp = static_cast<ViewProviderViewPart*>(getViewProvider(getViewObject()));
|
|
if (!vp) {
|
|
return;
|
|
}
|
|
|
|
if (b) {
|
|
//find the ends of the section line
|
|
double scale = viewPart->getScale();
|
|
std::pair<Base::Vector3d, Base::Vector3d> sLineEnds = viewSection->sectionLineEnds();
|
|
Base::Vector3d l1 = Rez::guiX(sLineEnds.first) * scale;
|
|
Base::Vector3d l2 = Rez::guiX(sLineEnds.second) * scale;
|
|
if (l1.IsEqual(l2, EWTOLERANCE) ) {
|
|
Base::Console().message("QGIVP::drawSectionLine - line endpoints are equal. No section line created.\n");
|
|
return;
|
|
}
|
|
|
|
QGISectionLine* sectionLine = new QGISectionLine();
|
|
addToGroup(sectionLine);
|
|
sectionLine->setSymbol(const_cast<char*>(viewSection->SectionSymbol.getValue()));
|
|
Base::Color color = Preferences::getAccessibleColor(vp->SectionLineColor.getValue());
|
|
sectionLine->setSectionColor(color.asValue<QColor>());
|
|
sectionLine->setPathMode(false);
|
|
|
|
//make the section line a little longer
|
|
double fudge = 2.0 * Preferences::dimFontSizeMM();
|
|
Base::Vector3d lineDir = l2 - l1;
|
|
lineDir.Normalize();
|
|
sectionLine->setEnds(l1 - lineDir * Rez::guiX(fudge), l2 + lineDir * Rez::guiX(fudge));
|
|
|
|
//which way do the arrows point?
|
|
Base::Vector3d arrowDir = viewSection->SectionNormal.getValue();
|
|
arrowDir = -viewPart->projectPoint(arrowDir); //arrows point reverse of sectionNormal
|
|
sectionLine->setDirection(arrowDir.x, -arrowDir.y);//3d direction needs Y inversion
|
|
|
|
if (vp->SectionLineMarks.getValue()) {
|
|
ChangePointVector points = viewSection->getChangePointsFromSectionLine();
|
|
//extend the changePoint locations to match the fudged section line ends
|
|
QPointF location0 = points.front().getLocation() * scale;
|
|
location0 = location0 - DU::toQPointF(lineDir) * fudge;
|
|
QPointF location1 = points.back().getLocation() * scale;
|
|
location1 = location1 + DU::toQPointF(lineDir) * fudge;
|
|
//change points have Rez::guiX applied in sectionLine
|
|
points.front().setLocation(location0);
|
|
points.back().setLocation(location1);
|
|
sectionLine->setChangePoints(points);
|
|
}
|
|
else {
|
|
sectionLine->clearChangePoints();
|
|
}
|
|
|
|
//set the general parameters
|
|
sectionLine->setPos(0.0, 0.0);
|
|
|
|
if (vp->IncludeCutLine.getValue()) {
|
|
sectionLine->setShowLine(true);
|
|
// sectionLines are typically ISO 8 (long dash, short dash) or ISO 4 (long dash, dot)
|
|
sectionLine->setLinePen(
|
|
m_dashedLineGenerator->getLinePen((size_t)vp->SectionLineStyle.getValue(),
|
|
vp->HiddenWidth.getValue()));
|
|
sectionLine->setWidth(Rez::guiX(vp->HiddenWidth.getValue()));
|
|
} else {
|
|
sectionLine->setShowLine(false);
|
|
}
|
|
|
|
double fontSize = Preferences::dimFontSizeMM();
|
|
sectionLine->setFont(getFont(), fontSize);
|
|
sectionLine->setZValue(ZVALUE::SECTIONLINE);
|
|
sectionLine->setRotation(-viewPart->Rotation.getValue());
|
|
sectionLine->draw();
|
|
}
|
|
}
|
|
|
|
void QGIViewPart::drawComplexSectionLine(TechDraw::DrawViewSection* viewSection, bool b)
|
|
{
|
|
Q_UNUSED(b);
|
|
|
|
TechDraw::DrawViewPart* viewPart = static_cast<TechDraw::DrawViewPart*>(getViewObject());
|
|
if (!viewPart)
|
|
return;
|
|
if (!viewSection)
|
|
return;
|
|
auto vp = static_cast<ViewProviderViewPart*>(getViewProvider(getViewObject()));
|
|
if (!vp) {
|
|
return;
|
|
}
|
|
|
|
auto dcs = static_cast<DrawComplexSection*>(viewSection);
|
|
std::pair<Base::Vector3d, Base::Vector3d> ends = dcs->sectionLineEnds();
|
|
Base::Vector3d vStart = Rez::guiX(ends.first);//already scaled by dcs
|
|
Base::Vector3d vEnd = Rez::guiX(ends.second);
|
|
if (vStart.IsEqual(vEnd, EWTOLERANCE) ) {
|
|
Base::Console().message("QGIVP::drawComplexSectionLine - line endpoints are equal. No section line created.\n");
|
|
return;
|
|
}
|
|
|
|
|
|
BaseGeomPtrVector edges = dcs->makeSectionLineGeometry();
|
|
QPainterPath wirePath;
|
|
QPainterPath firstSeg = drawPainterPath(edges.front());
|
|
wirePath.connectPath(firstSeg);
|
|
int edgeCount = edges.size();
|
|
//NOTE: if the edges are not in nose to tail order, Qt will insert extra segments
|
|
//that will overlap the segments we add. for interrupted line styles, this
|
|
//will make the line look continuous. This is prevented in
|
|
//DrawComplexSection::makeSectionLineGeometry by calling makeNoseToTailWire
|
|
for (int i = 1; i < edgeCount; i++) {
|
|
QPainterPath edgePath = drawPainterPath(edges.at(i));
|
|
wirePath.connectPath(edgePath);
|
|
}
|
|
|
|
|
|
QGISectionLine* sectionLine = new QGISectionLine();
|
|
addToGroup(sectionLine);
|
|
sectionLine->setSymbol(const_cast<char*>(viewSection->SectionSymbol.getValue()));
|
|
Base::Color color = Preferences::getAccessibleColor(vp->SectionLineColor.getValue());
|
|
sectionLine->setSectionColor(color.asValue<QColor>());
|
|
sectionLine->setPathMode(true);
|
|
sectionLine->setPath(wirePath);
|
|
sectionLine->setEnds(vStart, vEnd);
|
|
if (vp->SectionLineMarks.getValue()) {
|
|
sectionLine->setChangePoints(dcs->getChangePointsFromSectionLine());
|
|
}
|
|
else {
|
|
sectionLine->clearChangePoints();
|
|
}
|
|
|
|
std::pair<Base::Vector3d, Base::Vector3d> dirsDCS = dcs->sectionLineArrowDirsMapped();
|
|
sectionLine->setArrowDirections(dirsDCS.first, dirsDCS.second);
|
|
|
|
//set the general parameters
|
|
sectionLine->setPos(0.0, 0.0);
|
|
|
|
if (vp->IncludeCutLine.getValue()) {
|
|
sectionLine->setShowLine(true);
|
|
// sectionLines are typically ISO 8 (long dash, short dash) or ISO 4 (long dash, dot)
|
|
sectionLine->setLinePen(
|
|
m_dashedLineGenerator->getLinePen((size_t)vp->SectionLineStyle.getValue(),
|
|
vp->HiddenWidth.getValue()));
|
|
sectionLine->setWidth(Rez::guiX(vp->HiddenWidth.getValue()));
|
|
} else {
|
|
sectionLine->setShowLine(false);
|
|
}
|
|
|
|
double fontSize = Preferences::dimFontSizeMM();
|
|
sectionLine->setFont(getFont(), fontSize);
|
|
sectionLine->setZValue(ZVALUE::SECTIONLINE);
|
|
sectionLine->setRotation(-viewPart->Rotation.getValue());
|
|
sectionLine->draw();
|
|
}
|
|
|
|
//TODO: use Cosmetic::CenterLine object for this to make it usable for dims.
|
|
// these are the view center lines (ie x,y axes)
|
|
void QGIViewPart::drawCenterLines(bool b)
|
|
{
|
|
TechDraw::DrawViewPart* viewPart = dynamic_cast<TechDraw::DrawViewPart*>(getViewObject());
|
|
if (!viewPart)
|
|
return;
|
|
|
|
auto vp = static_cast<ViewProviderViewPart*>(getViewProvider(getViewObject()));
|
|
if (!vp)
|
|
return;
|
|
|
|
if (b) {
|
|
bool horiz = vp->HorizCenterLine.getValue();
|
|
bool vert = vp->VertCenterLine.getValue();
|
|
|
|
QGICenterLine* centerLine;
|
|
double sectionSpan;
|
|
double sectionFudge = Rez::guiX(10.0);
|
|
double xVal, yVal;
|
|
if (horiz) {
|
|
centerLine = new QGICenterLine();
|
|
addToGroup(centerLine);
|
|
centerLine->setPos(0.0, 0.0);
|
|
double width = Rez::guiX(viewPart->getBoxX());
|
|
sectionSpan = width + sectionFudge;
|
|
xVal = sectionSpan / 2.0;
|
|
yVal = 0.0;
|
|
centerLine->setIntersection(horiz && vert);
|
|
centerLine->setBounds(-xVal, -yVal, xVal, yVal);
|
|
centerLine->setLinePen(m_dashedLineGenerator->getLinePen((size_t)Preferences::CenterLineStyle(),
|
|
vp->HiddenWidth.getValue()));
|
|
centerLine->setWidth(Rez::guiX(vp->HiddenWidth.getValue()));
|
|
centerLine->setColor(Qt::green);
|
|
centerLine->setZValue(ZVALUE::SECTIONLINE);
|
|
centerLine->draw();
|
|
}
|
|
if (vert) {
|
|
centerLine = new QGICenterLine();
|
|
addToGroup(centerLine);
|
|
centerLine->setPos(0.0, 0.0);
|
|
double height = Rez::guiX(viewPart->getBoxY());
|
|
sectionSpan = height + sectionFudge;
|
|
xVal = 0.0;
|
|
yVal = sectionSpan / 2.0;
|
|
centerLine->setIntersection(horiz && vert);
|
|
centerLine->setBounds(-xVal, -yVal, xVal, yVal);
|
|
centerLine->setLinePen(m_dashedLineGenerator->getLinePen((size_t)Preferences::CenterLineStyle(),
|
|
vp->HiddenWidth.getValue()));
|
|
centerLine->setWidth(Rez::guiX(vp->HiddenWidth.getValue()));
|
|
centerLine->setColor(Qt::red);
|
|
centerLine->setZValue(ZVALUE::SECTIONLINE);
|
|
centerLine->draw();
|
|
}
|
|
}
|
|
}
|
|
|
|
void QGIViewPart::drawAllHighlights()
|
|
{
|
|
// dvp and vp already validated
|
|
auto dvp(static_cast<TechDraw::DrawViewPart*>(getViewObject()));
|
|
|
|
auto drefs = dvp->getDetailRefs();
|
|
for (auto& r : drefs) {
|
|
drawHighlight(r, true);
|
|
}
|
|
}
|
|
|
|
void QGIViewPart::drawHighlight(TechDraw::DrawViewDetail* viewDetail, bool b)
|
|
{
|
|
auto* viewPart = static_cast<TechDraw::DrawViewPart*>(getViewObject());
|
|
if (!viewPart || !viewDetail) {
|
|
return;
|
|
}
|
|
|
|
auto vp = static_cast<ViewProviderViewPart*>(getViewProvider(getViewObject()));
|
|
if (!vp) {
|
|
return;
|
|
}
|
|
auto vpDetail = static_cast<ViewProviderViewPart*>(getViewProvider(viewDetail));
|
|
if (!vpDetail) {
|
|
return;
|
|
}
|
|
|
|
if (!viewDetail->ShowHighlight.getValue()) {
|
|
return;
|
|
}
|
|
|
|
if (b) {
|
|
double fontSize = Preferences::labelFontSizeMM();
|
|
auto* highlight = new QGIHighlight();
|
|
|
|
scene()->addItem(highlight);
|
|
highlight->setReference(viewDetail->Reference.getValue());
|
|
|
|
Base::Color color = Preferences::getAccessibleColor(vp->HighlightLineColor.getValue());
|
|
highlight->setColor(color.asValue<QColor>());
|
|
highlight->setFeatureName(viewDetail->getNameInDocument());
|
|
|
|
highlight->setInteractive(false);
|
|
|
|
addToGroup(highlight);
|
|
highlight->setPos(0.0, 0.0);//sb setPos(center.x, center.y)?
|
|
|
|
Base::Vector3d center = viewDetail->AnchorPoint.getValue() * viewPart->getScale();
|
|
double rotationRad = Base::toRadians(viewPart->Rotation.getValue());
|
|
center.RotateZ(rotationRad);
|
|
|
|
double radius = viewDetail->Radius.getValue() * viewPart->getScale();
|
|
highlight->setBounds(center.x - radius, center.y + radius, center.x + radius,
|
|
center.y - radius);
|
|
highlight->setLinePen(m_dashedLineGenerator->getLinePen((size_t)vp->HighlightLineStyle.getValue(),
|
|
vp->IsoWidth.getValue()));
|
|
highlight->setWidth(Rez::guiX(vp->IsoWidth.getValue()));
|
|
highlight->setFont(getFont(), fontSize);
|
|
highlight->setZValue(ZVALUE::HIGHLIGHT);
|
|
highlight->setReferenceAngle(vpDetail->HighlightAdjust.getValue());
|
|
|
|
//handle conversion of apparent X,Y to rotated
|
|
QPointF rotCenter = highlight->mapFromParent(transformOriginPoint());
|
|
highlight->setTransformOriginPoint(rotCenter);
|
|
|
|
double rotation = viewPart->Rotation.getValue();
|
|
highlight->setRotation(rotation);
|
|
highlight->draw();
|
|
}
|
|
}
|
|
|
|
//! this method is no longer used due to conflicts with TaskDetail dialog highlight drag
|
|
void QGIViewPart::highlightMoved(QGIHighlight* highlight, QPointF newPos)
|
|
{
|
|
std::string highlightName = highlight->getFeatureName();
|
|
App::Document* doc = getViewObject()->getDocument();
|
|
App::DocumentObject* docObj = doc->getObject(highlightName.c_str());
|
|
auto detail = freecad_cast<DrawViewDetail*>(docObj);
|
|
auto baseView = freecad_cast<DrawViewPart*>(getViewObject());
|
|
if (detail && baseView) {
|
|
auto oldAnchor = detail->AnchorPoint.getValue();
|
|
Base::Vector3d delta = Rez::appX(DrawUtil::toVector3d(newPos)) / getViewObject()->getScale();
|
|
delta = DrawUtil::invertY(delta);
|
|
Base::Vector3d newAnchorPoint = oldAnchor + delta;
|
|
newAnchorPoint = baseView->snapHighlightToVertex(newAnchorPoint,
|
|
detail->Radius.getValue());
|
|
detail->AnchorPoint.setValue(newAnchorPoint);
|
|
}
|
|
}
|
|
|
|
|
|
void QGIViewPart::drawMatting()
|
|
{
|
|
auto viewPart(dynamic_cast<TechDraw::DrawViewPart*>(getViewObject()));
|
|
TechDraw::DrawViewDetail* dvd = nullptr;
|
|
if (viewPart && viewPart->isDerivedFrom<TechDraw::DrawViewDetail>()) {
|
|
dvd = static_cast<TechDraw::DrawViewDetail*>(viewPart);
|
|
}
|
|
else {
|
|
return;
|
|
}
|
|
|
|
if (!dvd->ShowMatting.getValue()) {
|
|
return;
|
|
}
|
|
|
|
double scale = dvd->getScale();
|
|
double radius = dvd->Radius.getValue() * scale;
|
|
QGIMatting* mat = new QGIMatting();
|
|
addToGroup(mat);
|
|
mat->setRadius(Rez::guiX(radius));
|
|
mat->setPos(0.0, 0.0);
|
|
mat->draw();
|
|
mat->show();
|
|
}
|
|
|
|
|
|
//! if this is a broken view, draw the break lines.
|
|
void QGIViewPart::drawBreakLines()
|
|
{
|
|
// Base::Console().message("QGIVP::drawBreakLines()\n");
|
|
|
|
auto dbv = dynamic_cast<TechDraw::DrawBrokenView*>(getViewObject());
|
|
if (!dbv) {
|
|
return;
|
|
}
|
|
|
|
auto vp = static_cast<ViewProviderViewPart*>(getViewProvider(getViewObject()));
|
|
if (!vp) {
|
|
return;
|
|
}
|
|
|
|
DrawBrokenView::BreakType breakType = static_cast<DrawBrokenView::BreakType>(vp->BreakLineType.getValue());
|
|
auto breaks = dbv->Breaks.getValues();
|
|
for (auto& breakObj : breaks) {
|
|
QGIBreakLine* breakLine = new QGIBreakLine();
|
|
addToGroup(breakLine);
|
|
|
|
Base::Vector3d direction = dbv->guiDirectionFromObj(*breakObj);
|
|
breakLine->setDirection(direction);
|
|
// the bounds describe two corners of the removed area in the view
|
|
std::pair<Base::Vector3d, Base::Vector3d> bounds = dbv->breakBoundsFromObj(*breakObj);
|
|
// the bounds are in 3d form, so we need to invert & rez them
|
|
Base::Vector3d topLeft = Rez::guiX(DU::invertY(bounds.first));
|
|
Base::Vector3d bottomRight = Rez::guiX(DU::invertY(bounds.second));
|
|
breakLine->setBounds(topLeft, bottomRight);
|
|
breakLine->setPos(0.0, 0.0);
|
|
breakLine->setLinePen(
|
|
m_dashedLineGenerator->getLinePen(vp->BreakLineStyle.getValue(), vp->HiddenWidth.getValue()));
|
|
breakLine->setWidth(Rez::guiX(vp->HiddenWidth.getValue()));
|
|
breakLine->setBreakType(breakType);
|
|
breakLine->setZValue(ZVALUE::SECTIONLINE);
|
|
Base::Color color = prefBreaklineColor();
|
|
breakLine->setBreakColor(color.asValue<QColor>());
|
|
breakLine->setRotation(-dbv->Rotation.getValue());
|
|
breakLine->draw();
|
|
}
|
|
}
|
|
|
|
|
|
void QGIViewPart::toggleCache(bool state)
|
|
{
|
|
QList<QGraphicsItem*> items = childItems();
|
|
for (QList<QGraphicsItem*>::iterator it = items.begin(); it != items.end(); it++) {
|
|
//(*it)->setCacheMode((state)? DeviceCoordinateCache : NoCache); //TODO: fiddle cache settings if req'd for performance
|
|
Q_UNUSED(state);
|
|
(*it)->setCacheMode(NoCache);
|
|
(*it)->update();
|
|
}
|
|
}
|
|
|
|
void QGIViewPart::toggleCosmeticLines(bool state)
|
|
{
|
|
QList<QGraphicsItem*> items = childItems();
|
|
for (QList<QGraphicsItem*>::iterator it = items.begin(); it != items.end(); it++) {
|
|
QGIEdge* edge = dynamic_cast<QGIEdge*>(*it);
|
|
if (edge) {
|
|
edge->setCosmetic(state);
|
|
}
|
|
}
|
|
}
|
|
|
|
//get hatchObj for face i if it exists
|
|
TechDraw::DrawHatch* QGIViewPart::faceIsHatched(int i,
|
|
std::vector<TechDraw::DrawHatch*> hatchObjs) const
|
|
{
|
|
TechDraw::DrawHatch* result = nullptr;
|
|
bool found = false;
|
|
for (auto& h : hatchObjs) {
|
|
const std::vector<std::string>& sourceNames = h->Source.getSubValues();
|
|
for (auto& s : sourceNames) {
|
|
int fdx = TechDraw::DrawUtil::getIndexFromName(s);
|
|
if (fdx == i) {
|
|
result = h;
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
if (found) {
|
|
break;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TechDraw::DrawGeomHatch*
|
|
QGIViewPart::faceIsGeomHatched(int i, std::vector<TechDraw::DrawGeomHatch*> geomObjs) const
|
|
{
|
|
TechDraw::DrawGeomHatch* result = nullptr;
|
|
bool found = false;
|
|
for (auto& h : geomObjs) {
|
|
const std::vector<std::string>& sourceNames = h->Source.getSubValues();
|
|
for (auto& sn : sourceNames) {
|
|
int fdx = TechDraw::DrawUtil::getIndexFromName(sn);
|
|
if (fdx == i) {
|
|
result = h;
|
|
found = true;
|
|
break;
|
|
}
|
|
if (found) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
|
|
|
|
void QGIViewPart::dumpPath(const char* text, QPainterPath path)
|
|
{
|
|
QPainterPath::Element elem;
|
|
Base::Console().message(">>>%s has %d elements\n", text, path.elementCount());
|
|
const char* typeName;
|
|
for (int iElem = 0; iElem < path.elementCount(); iElem++) {
|
|
elem = path.elementAt(iElem);
|
|
if (elem.isMoveTo()) {
|
|
typeName = "MoveTo";
|
|
}
|
|
else if (elem.isLineTo()) {
|
|
typeName = "LineTo";
|
|
}
|
|
else if (elem.isCurveTo()) {
|
|
typeName = "CurveTo";
|
|
}
|
|
else {
|
|
typeName = "CurveData";
|
|
}
|
|
Base::Console().message(">>>>> element %d: type:%d/%s pos(%.3f, %.3f) M:%d L:%d C:%d\n",
|
|
iElem, static_cast<int>(elem.type), typeName, elem.x, elem.y, static_cast<int>(elem.isMoveTo()),
|
|
static_cast<int>(elem.isLineTo()), static_cast<int>(elem.isCurveTo()));
|
|
}
|
|
}
|
|
|
|
QRectF QGIViewPart::boundingRect() const
|
|
{
|
|
// return childrenBoundingRect();
|
|
// return customChildrenBoundingRect();
|
|
return QGIView::boundingRect();
|
|
}
|
|
void QGIViewPart::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
|
|
{
|
|
QStyleOptionGraphicsItem myOption(*option);
|
|
myOption.state &= ~QStyle::State_Selected;
|
|
|
|
// painter->drawRect(boundingRect()); //good for debugging
|
|
|
|
QGIView::paint(painter, &myOption, widget);
|
|
}
|
|
|
|
//QGIViewPart derived classes do not need a rotate view method as rotation is handled on App side.
|
|
void QGIViewPart::rotateView() {}
|
|
|
|
bool QGIViewPart::prefFaceEdges()
|
|
{
|
|
bool result = false;
|
|
result = Preferences::getPreferenceGroup("General")->GetBool("DrawFaceEdges", false);
|
|
return result;
|
|
}
|
|
|
|
bool QGIViewPart::prefPrintCenters()
|
|
{
|
|
bool printCenters = Preferences::getPreferenceGroup("Decorations")->GetBool("PrintCenterMarks", false);//true matches v0.18 behaviour
|
|
return printCenters;
|
|
}
|
|
|
|
Base::Color QGIViewPart::prefBreaklineColor()
|
|
{
|
|
return Preferences::getAccessibleColor(PreferencesGui::breaklineColor());
|
|
}
|
|
|
|
QGraphicsItem *QGIViewPart::getQGISubItemByName(const std::string &subName) const
|
|
{
|
|
int scanType = 0;
|
|
try {
|
|
const std::string &subType = TechDraw::DrawUtil::getGeomTypeFromName(subName);
|
|
if (subType == "Vertex") {
|
|
scanType = QGIVertex::Type;
|
|
}
|
|
else if (subType == "Edge") {
|
|
scanType = QGIEdge::Type;
|
|
}
|
|
else if (subType == "Face") {
|
|
scanType = QGIFace::Type;
|
|
}
|
|
}
|
|
catch (Base::ValueError&) {
|
|
// No action
|
|
}
|
|
if (!scanType) {
|
|
return nullptr;
|
|
}
|
|
|
|
int scanIndex = -1;
|
|
try {
|
|
scanIndex = TechDraw::DrawUtil::getIndexFromName(subName);
|
|
}
|
|
catch (Base::ValueError&) {
|
|
// No action
|
|
}
|
|
if (scanIndex < 0) {
|
|
return nullptr;
|
|
}
|
|
|
|
for (auto child : childItems()) {
|
|
if (child->type() != scanType) {
|
|
continue;
|
|
}
|
|
|
|
int projIndex;
|
|
switch (scanType) {
|
|
case QGIVertex::Type:
|
|
projIndex = static_cast<QGIVertex *>(child)->getProjIndex();
|
|
break;
|
|
case QGIEdge::Type:
|
|
projIndex = static_cast<QGIEdge *>(child)->getProjIndex();
|
|
break;
|
|
case QGIFace::Type:
|
|
projIndex = static_cast<QGIFace *>(child)->getProjIndex();
|
|
break;
|
|
default:
|
|
projIndex = -1;
|
|
break;
|
|
}
|
|
|
|
if (projIndex == scanIndex) {
|
|
return child;
|
|
}
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
bool QGIViewPart::getGroupSelection() {
|
|
return DrawGuiUtil::isSelectedInTree(this);
|
|
}
|
|
|
|
void QGIViewPart::setGroupSelection(bool isSelected) {
|
|
DrawGuiUtil::setSelectedTree(this, isSelected);
|
|
}
|
|
|
|
void QGIViewPart::setGroupSelection(bool isSelected, const std::vector<std::string> &subNames)
|
|
{
|
|
if (subNames.empty()) {
|
|
setSelected(isSelected);
|
|
return;
|
|
}
|
|
|
|
for (const std::string &subName : subNames) {
|
|
if (subName.empty()) {
|
|
setSelected(isSelected);
|
|
continue;
|
|
}
|
|
|
|
QGraphicsItem *subItem = getQGISubItemByName(subName);
|
|
if (subItem) {
|
|
subItem->setSelected(isSelected);
|
|
}
|
|
}
|
|
}
|
|
|
|
double QGIViewPart::getLineWidth() {
|
|
auto vp{static_cast<ViewProviderViewPart*>(getViewProvider(getViewObject()))};
|
|
|
|
return vp->LineWidth.getValue() * lineScaleFactor; // Thick
|
|
}
|
|
|
|
double QGIViewPart::getVertexSize() {
|
|
return getLineWidth() * Preferences::vertexScale();
|
|
}
|
|
|
|
void QGIViewPart::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
|
|
{
|
|
QGIView::hoverEnterEvent(event);
|
|
|
|
for (auto& child : childItems()) {
|
|
if (child->type() == UserType::QGIVertex) {
|
|
child->show();
|
|
}
|
|
}
|
|
|
|
update();
|
|
}
|
|
|
|
void QGIViewPart::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
|
|
{
|
|
QGIView::hoverLeaveEvent(event);
|
|
|
|
for (auto& child : childItems()) {
|
|
if (child->type() == UserType::QGIVertex &&
|
|
!child->isSelected()) {
|
|
child->hide();
|
|
}
|
|
}
|
|
update();
|
|
}
|