[TD]Cosmetic function overhaul (#14216)
* [TD]Cosmetic geometry and tools update - all cosmetics to store geometry in same form - all cosmetics to survive scaling and rotation - extension functions to survive scaling and rotation * [TD]overhaul leader point storage and editing - add py routine makeLeader(points) * [TD]add leader conversion utility * [TD]Set Leader RotateWithView default to true * [TD]fix intersection vertex position * [TD]add CosmeticEdge::makeLineFromCanonicalPoints * [TD]fix 2 Extension tools - positioning in DrawCosmeticCircle - mishandling of points in execLineParallelPerpendicular * [TD]Remove duplicate constexpr * [TD]fix 2x Cosmetic arc tools * [TD]refactor LineFormat out of Cosmetic * [TD]move cosmetic appearance settings to LineFormat * [TD]remove 2 unused methods * [TD]apply format to blue line & circle tools * [TD]fix ballon arrowhead does not rotate with view * [TD]fix CosmeticCircle3Points * [TD]allow multiple cosmetic object deletions * [TD]fix extend/shorten centerline
This commit is contained in:
@@ -31,11 +31,13 @@
|
||||
# include <QVector2D>
|
||||
#endif
|
||||
|
||||
#include <App/Document.h>
|
||||
#include <Base/Console.h>
|
||||
#include <Mod/TechDraw/App/ArrowPropEnum.h>
|
||||
#include <Mod/TechDraw/App/DrawLeaderLine.h>
|
||||
#include <Mod/TechDraw/App/DrawUtil.h>
|
||||
#include <Mod/TechDraw/App/LineGroup.h>
|
||||
#include <Mod/TechDraw/App/DrawViewPart.h>
|
||||
|
||||
#include "QGILeaderLine.h"
|
||||
#include "PreferencesGui.h"
|
||||
@@ -45,10 +47,14 @@
|
||||
#include "Rez.h"
|
||||
#include "ViewProviderLeader.h"
|
||||
#include "ZVALUE.h"
|
||||
#include "DrawGuiUtil.h"
|
||||
|
||||
|
||||
using namespace TechDrawGui;
|
||||
using namespace TechDraw;
|
||||
using DU = DrawUtil;
|
||||
using DGU = DrawGuiUtil;
|
||||
|
||||
|
||||
//**************************************************************
|
||||
QGILeaderLine::QGILeaderLine()
|
||||
@@ -75,7 +81,7 @@ QGILeaderLine::QGILeaderLine()
|
||||
m_line->setAcceptHoverEvents(false);
|
||||
m_line->setPos(0.0, 0.0);
|
||||
|
||||
m_editPath = new QGEPath(this);
|
||||
m_editPath = new QGEPath();
|
||||
addToGroup(m_editPath);
|
||||
m_editPath->setPos(0.0, 0.0);
|
||||
m_editPath->setFlag(QGraphicsItem::ItemIsSelectable, false);
|
||||
@@ -148,6 +154,21 @@ void QGILeaderLine::mouseReleaseEvent(QGraphicsSceneMouseEvent* event)
|
||||
QGraphicsItem::mouseReleaseEvent(event);
|
||||
}
|
||||
|
||||
//! start editor on double click
|
||||
void QGILeaderLine::mouseDoubleClickEvent(QGraphicsSceneMouseEvent* event)
|
||||
{
|
||||
// Base::Console().Message("QGILL::mouseDoubleClickEvent() - %s\n", getViewName());
|
||||
auto ViewProvider = dynamic_cast<ViewProviderLeader*>(getViewProvider(getLeaderFeature()));
|
||||
if (!ViewProvider) {
|
||||
qWarning() << "QGILeaderLine::mouseDoubleClickEvent: No valid view provider";
|
||||
return;
|
||||
}
|
||||
|
||||
ViewProvider->startDefaultEditMode();
|
||||
QGraphicsItem::mouseDoubleClickEvent(event);
|
||||
}
|
||||
|
||||
|
||||
void QGILeaderLine::hoverEnterEvent(QGraphicsSceneHoverEvent* event)
|
||||
{
|
||||
// Base::Console().Message("QGILL::hoverEnter() - selected; %d\n", isSelected());
|
||||
@@ -213,14 +234,17 @@ void QGILeaderLine::closeEdit()
|
||||
}
|
||||
}
|
||||
|
||||
//signaled from QEPath
|
||||
void QGILeaderLine::onLineEditFinished(QPointF tipDisplace, std::vector<QPointF> points)
|
||||
//! scene coordinates of leaderline points are converted to real page coordinates as deltas from first point.
|
||||
//! line start point (X,Y of leader feature) is recomputed as displacement from parent's (0,0).
|
||||
//! signaled from QEPath
|
||||
void QGILeaderLine::onLineEditFinished(QPointF tipDisplace, std::vector<QPointF> scenePoints)
|
||||
{
|
||||
// Base::Console().Message("QGILL::onLineEditFinished(%s, %d)\n",
|
||||
// TechDraw::DrawUtil::formatVector(tipDisplace).c_str(),
|
||||
// points.size());
|
||||
// Base::Console().Message("QGILL::onLineEditFinished(%s, %d)\n",
|
||||
// TechDraw::DrawUtil::formatVector(tipDisplace).c_str(),
|
||||
// scenePoints.size());
|
||||
|
||||
m_blockDraw = true;
|
||||
auto featLeader = getFeature();
|
||||
auto featLeader = getLeaderFeature();
|
||||
if (!featLeader) {
|
||||
return;
|
||||
}
|
||||
@@ -234,18 +258,18 @@ void QGILeaderLine::onLineEditFinished(QPointF tipDisplace, std::vector<QPointF>
|
||||
featLeader->setPosition(Rez::appX(newAttach.x()), Rez::appX(-newAttach.y()), true);
|
||||
}
|
||||
|
||||
std::vector<Base::Vector3d> waypoints;
|
||||
for (auto& p : points) {
|
||||
QPointF moved = p - tipDisplace;
|
||||
Base::Vector3d v(moved.x(), moved.y(), 0.0);
|
||||
waypoints.push_back(v);
|
||||
std::vector<Base::Vector3d> pageDeltas;
|
||||
for (auto& pt : scenePoints) {
|
||||
QPointF distFromP0 = pt - scenePoints.front();
|
||||
// convert deltas to mm and conventional Y axis from scene coords
|
||||
Base::Vector3d deltaInPageCoords = DGU::fromSceneCoords(DU::toVector3d(distFromP0));
|
||||
pageDeltas.push_back(deltaInPageCoords);
|
||||
}
|
||||
waypoints.at(0) = Base::Vector3d(0.0, 0.0, 0.0);
|
||||
pageDeltas.at(0) = Base::Vector3d(0.0, 0.0, 0.0);
|
||||
|
||||
featLeader->WayPoints.setValues(waypoints);
|
||||
if (featLeader->AutoHorizontal.getValue()) {
|
||||
featLeader->adjustLastSegment();
|
||||
}
|
||||
// to canonical form here
|
||||
auto temp = featLeader->makeCanonicalPointsInverted(pageDeltas);
|
||||
featLeader->WayPoints.setValues(temp);
|
||||
|
||||
Q_EMIT editComplete();//tell task editing is complete
|
||||
|
||||
@@ -272,7 +296,7 @@ void QGILeaderLine::startPathEdit()
|
||||
void QGILeaderLine::saveState()
|
||||
{
|
||||
// Base::Console().Message("QGILL::saveState()\n");
|
||||
auto featLeader = getFeature();
|
||||
auto featLeader = getLeaderFeature();
|
||||
if (featLeader) {
|
||||
m_savePoints = featLeader->WayPoints.getValues();
|
||||
m_saveX = featLeader->X.getValue();
|
||||
@@ -283,7 +307,7 @@ void QGILeaderLine::saveState()
|
||||
void QGILeaderLine::restoreState()
|
||||
{
|
||||
// Base::Console().Message("QGILL::restoreState()\n");
|
||||
auto featLeader = getFeature();
|
||||
auto featLeader = getLeaderFeature();
|
||||
if (featLeader) {
|
||||
featLeader->WayPoints.setValues(m_savePoints);
|
||||
featLeader->X.setValue(m_saveX);
|
||||
@@ -296,7 +320,7 @@ void QGILeaderLine::restoreState()
|
||||
|
||||
void QGILeaderLine::updateView(bool update)
|
||||
{
|
||||
// Base::Console().Message("QGIL::updateView() %s\n", getViewObject()->getNameInDocument());
|
||||
// Base::Console().Message("QGILL::updateView()\n");
|
||||
Q_UNUSED(update);
|
||||
auto featLeader(dynamic_cast<TechDraw::DrawLeaderLine*>(getViewObject()));
|
||||
if (!featLeader) {
|
||||
@@ -313,14 +337,14 @@ void QGILeaderLine::updateView(bool update)
|
||||
|
||||
void QGILeaderLine::draw()
|
||||
{
|
||||
// Base::Console().Message("QGILL::draw()- %s\n", getViewObject()->getNameInDocument());
|
||||
// Base::Console().Message("QGILL::draw()- %s\n", getViewObject()->getNameInDocument());
|
||||
if (m_blockDraw) {
|
||||
return;
|
||||
}
|
||||
if (!isVisible()) {
|
||||
return;
|
||||
}
|
||||
TechDraw::DrawLeaderLine* featLeader = getFeature();
|
||||
TechDraw::DrawLeaderLine* featLeader = getLeaderFeature();
|
||||
if (!featLeader) {
|
||||
return;
|
||||
}
|
||||
@@ -329,10 +353,10 @@ void QGILeaderLine::draw()
|
||||
return;
|
||||
}
|
||||
|
||||
double scale = 1.0;
|
||||
TechDraw::DrawView* parent = featLeader->getBaseView();
|
||||
if (parent) {
|
||||
scale = parent->getScale();
|
||||
|
||||
if (!parent) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_editPath->inEdit()) {
|
||||
@@ -347,25 +371,34 @@ void QGILeaderLine::draw()
|
||||
setFlag(QGraphicsItem::ItemIsMovable, true);
|
||||
}
|
||||
|
||||
// set the leader's Qt position from feature's X,Y and scale.
|
||||
// the feature's x,y is unscaled, unrotated and conventional Y
|
||||
// line style is standing in for line number here?
|
||||
m_lineStyle = static_cast<Qt::PenStyle>(vp->LineStyle.getValue());
|
||||
double baseScale = featLeader->getBaseScale();
|
||||
double x = Rez::guiX(featLeader->X.getValue());
|
||||
double y = -Rez::guiX(featLeader->Y.getValue());
|
||||
QPointF aPoint(x, y);
|
||||
aPoint *= baseScale;
|
||||
setPos(aPoint);
|
||||
double xPos = Rez::guiX(featLeader->X.getValue());
|
||||
double yPos = Rez::guiX(featLeader->Y.getValue());
|
||||
Base::Vector3d vAttachPoint{xPos, yPos};
|
||||
vAttachPoint = vAttachPoint * baseScale;
|
||||
double rotationRad = parent->Rotation.getValue() * M_PI / DegreesHalfCircle;
|
||||
if (rotationRad != 0.0) {
|
||||
vAttachPoint.RotateZ(rotationRad);
|
||||
}
|
||||
vAttachPoint = DU::invertY(vAttachPoint);
|
||||
QPointF qPoint = DU::toQPointF(vAttachPoint);
|
||||
// ???? why does the attach point not need Rez applied?
|
||||
setPos(qPoint);
|
||||
|
||||
m_line->setFillStyle(Qt::NoBrush);
|
||||
m_line->setStyle(m_lineStyle);
|
||||
m_line->setWidth(getLineWidth());
|
||||
|
||||
m_line->setPos(0, 0);//make m_line coords == leader coords
|
||||
m_line->setPos(0, 0); //make m_line coords == leader coords
|
||||
|
||||
std::vector<QPointF> qPoints = getWayPointsFromFeature();
|
||||
if (featLeader->Scalable.getValue()) {
|
||||
for (auto& p : qPoints) {
|
||||
p = p * scale;
|
||||
}
|
||||
if (qPoints.empty() ) {
|
||||
Base::Console().Message("QGILL::draw - no points\n");
|
||||
return;
|
||||
}
|
||||
|
||||
setNormalColorAll();
|
||||
@@ -388,9 +421,9 @@ QPainterPath QGILeaderLine::makeLeaderPath(std::vector<QPointF> qPoints)
|
||||
{
|
||||
// Base::Console().Message("QGILeaderLine::makeLeaderPath()\n");
|
||||
QPainterPath result;
|
||||
DrawLeaderLine* featLeader = getFeature();
|
||||
DrawLeaderLine* featLeader = getLeaderFeature();
|
||||
if (!featLeader) {
|
||||
Base::Console().Message("QGILL::makeLeaderPath - featLeader is nullptr\n");
|
||||
// Base::Console().Message("QGILL::makeLeaderPath - featLeader is nullptr\n");
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -431,37 +464,54 @@ QPainterPath QGILeaderLine::makeLeaderPath(std::vector<QPointF> qPoints)
|
||||
return result;
|
||||
}
|
||||
|
||||
//! returns the point (on the parent) to which the leader is attached.
|
||||
//! result is relative to the center of the unscaled, unrotated parent.
|
||||
//! result is is not inverted (Y grows upwards).
|
||||
QPointF QGILeaderLine::getAttachFromFeature()
|
||||
{
|
||||
// Base::Console().Message("QGILL::getAttachFromFeature()\n");
|
||||
TechDraw::DrawLeaderLine* featLeader = getFeature();
|
||||
// Base::Console().Message("QGILL::getAttachFromFeature()\n");
|
||||
TechDraw::DrawLeaderLine* featLeader = getLeaderFeature();
|
||||
if (!featLeader) {
|
||||
Base::Console().Message("QGIL::getAttachFromLeader - no feature\n");
|
||||
return QPointF();
|
||||
// Base::Console().Message("QGIL::getAttachFromLeader - no feature\n");
|
||||
return {};
|
||||
}
|
||||
double x = Rez::guiX(featLeader->X.getValue());
|
||||
double y = -Rez::guiX(featLeader->Y.getValue());
|
||||
return QPointF(x, y);
|
||||
// this is unrotated point. is it scaled?
|
||||
return {x, y};
|
||||
}
|
||||
|
||||
std::vector<QPointF> QGILeaderLine::getWayPointsFromFeature()
|
||||
{
|
||||
std::vector<QPointF> qPoints;
|
||||
|
||||
DrawLeaderLine* featLeader = getFeature();
|
||||
// Base::Console().Message("QGILL::getWayPointsFromFeature()\n");
|
||||
DrawLeaderLine* featLeader = getLeaderFeature();
|
||||
if (!featLeader) {
|
||||
Base::Console().Message("QGILL::getWayPointsFromFeature - featLeader is nullptr\n");
|
||||
return qPoints;
|
||||
// Base::Console().Message("QGILL::getWayPointsFromFeature - featLeader is nullptr\n");
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<Base::Vector3d> vPoints = featLeader->WayPoints.getValues();
|
||||
for (auto& d : vPoints) {
|
||||
QPointF temp(d.x, d.y);
|
||||
qPoints.push_back(temp);
|
||||
// vPoints are in mm with conventional Y axis
|
||||
auto doScale = featLeader->Scalable.getValue();
|
||||
auto doRotate = featLeader->RotatesWithParent.getValue();
|
||||
auto vPoints = featLeader->getScaledAndRotatedPoints(doScale, doRotate);
|
||||
|
||||
std::vector<QPointF> qPoints;
|
||||
qPoints.reserve(vPoints.size());
|
||||
// now convert to sceneUnits and Qt Y axis
|
||||
for (auto& entry : vPoints) {
|
||||
if (useOldCoords()) {
|
||||
// use points as saved in <= v0.21 (in Qt form, Rez'd and
|
||||
qPoints.push_back(DU::toQPointF(entry));
|
||||
} else {
|
||||
// use points as saved in >= v0.22
|
||||
qPoints.push_back(DU::toQPointF(DGU::toSceneCoords(entry, false)));
|
||||
}
|
||||
}
|
||||
|
||||
if (qPoints.empty()) {
|
||||
Base::Console().Warning("QGILeaderLine::getWayPointsFromFeature - no points\n");
|
||||
}
|
||||
|
||||
return qPoints;
|
||||
}
|
||||
|
||||
@@ -469,7 +519,7 @@ void QGILeaderLine::setArrows(std::vector<QPointF> pathPoints)
|
||||
{
|
||||
// Base::Console().Message("QGILL::setArrows()\n");
|
||||
Base::Vector3d stdX(1.0, 0.0, 0.0);
|
||||
TechDraw::DrawLeaderLine* featLeader = getFeature();
|
||||
TechDraw::DrawLeaderLine* featLeader = getLeaderFeature();
|
||||
|
||||
QPointF lastOffset = (pathPoints.back() - pathPoints.front());
|
||||
|
||||
@@ -544,7 +594,7 @@ double QGILeaderLine::getLineWidth()
|
||||
return Rez::guiX(vp->LineWidth.getValue());
|
||||
}
|
||||
|
||||
TechDraw::DrawLeaderLine* QGILeaderLine::getFeature()
|
||||
TechDraw::DrawLeaderLine* QGILeaderLine::getLeaderFeature()
|
||||
{
|
||||
TechDraw::DrawLeaderLine* result = static_cast<TechDraw::DrawLeaderLine*>(getViewObject());
|
||||
return result;
|
||||
@@ -585,4 +635,15 @@ void QGILeaderLine::paint(QPainter* painter, const QStyleOptionGraphicsItem* opt
|
||||
QGIView::paint(painter, &myOption, widget);
|
||||
}
|
||||
|
||||
bool QGILeaderLine::useOldCoords() const
|
||||
{
|
||||
bool result = false;
|
||||
auto vp = dynamic_cast<ViewProviderLeader*>(getViewProvider(getViewObject()));
|
||||
if (vp) {
|
||||
result = vp->UseOldCoords.getValue();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
#include <Mod/TechDraw/Gui/moc_QGILeaderLine.cpp>
|
||||
|
||||
Reference in New Issue
Block a user