[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:
WandererFan
2024-05-23 09:41:42 -04:00
committed by GitHub
parent a8d093280e
commit 50f970efd7
56 changed files with 1812 additions and 1076 deletions

View File

@@ -22,7 +22,6 @@
#include "PreCompiled.h"
#ifndef _PreComp_
# include <cmath>
# include <QStatusBar>
#endif
@@ -40,6 +39,7 @@
#include <Mod/TechDraw/App/DrawPage.h>
#include <Mod/TechDraw/App/DrawView.h>
#include <Mod/TechDraw/App/LineGroup.h>
#include <Mod/TechDraw/App/DrawUtil.h>
#include "TaskLeaderLine.h"
#include "ui_TaskLeaderLine.h"
@@ -58,21 +58,24 @@
using namespace Gui;
using namespace TechDraw;
using namespace TechDrawGui;
using DU = DrawUtil;
using DGU = DrawGuiUtil;
constexpr int MessageDisplayTime{3000};
//ctor for edit
TaskLeaderLine::TaskLeaderLine(TechDrawGui::ViewProviderLeader* leadVP) :
ui(new Ui_TaskLeaderLine),
m_tracker(nullptr),
m_lineVP(leadVP),
m_baseFeat(nullptr),
m_basePage(nullptr),
m_lineFeat(nullptr),
m_lineFeat(m_lineVP->getFeature()),
m_qgParent(nullptr),
m_createMode(false),
m_trackerMode(QGTracker::None),
m_saveContextPolicy(Qt::DefaultContextMenu),
m_inProgressLock(false),
m_qgLine(nullptr),
m_qgLeader(nullptr),
m_btnOK(nullptr),
m_btnCancel(nullptr),
m_pbTrackerState(TrackerAction::EDIT),
@@ -81,7 +84,6 @@ TaskLeaderLine::TaskLeaderLine(TechDrawGui::ViewProviderLeader* leadVP) :
{
//existence of leadVP is guaranteed by caller being ViewProviderLeaderLine.setEdit
m_lineFeat = m_lineVP->getFeature();
m_basePage = m_lineFeat->findParentPage();
if (!m_basePage) {
@@ -127,8 +129,9 @@ TaskLeaderLine::TaskLeaderLine(TechDrawGui::ViewProviderLeader* leadVP) :
saveState();
m_trackerMode = QGTracker::TrackerMode::Line;
if (m_vpp->getMDIViewPage())
if (m_vpp->getMDIViewPage()) {
m_saveContextPolicy = m_vpp->getMDIViewPage()->contextMenuPolicy();
}
}
//ctor for creation
@@ -145,7 +148,7 @@ TaskLeaderLine::TaskLeaderLine(TechDraw::DrawView* baseFeat,
m_trackerMode(QGTracker::None),
m_saveContextPolicy(Qt::DefaultContextMenu),
m_inProgressLock(false),
m_qgLine(nullptr),
m_qgLeader(nullptr),
m_btnOK(nullptr),
m_btnCancel(nullptr),
m_pbTrackerState(TrackerAction::PICK),
@@ -158,7 +161,6 @@ TaskLeaderLine::TaskLeaderLine(TechDraw::DrawView* baseFeat,
Gui::ViewProvider* vp = activeGui->getViewProvider(m_basePage);
m_vpp = static_cast<ViewProviderPage*>(vp);
m_qgParent = nullptr;
if (m_baseFeat) {
m_qgParent = m_vpp->getQGSPage()->findQViewForDocObj(baseFeat);
}
@@ -174,8 +176,9 @@ TaskLeaderLine::TaskLeaderLine(TechDraw::DrawView* baseFeat,
ui->pbCancelEdit->setEnabled(false);
m_trackerMode = QGTracker::TrackerMode::Line;
if (m_vpp->getMDIViewPage())
if (m_vpp->getMDIViewPage()) {
m_saveContextPolicy = m_vpp->getMDIViewPage()->contextMenuPolicy();
}
}
void TaskLeaderLine::saveState()
@@ -231,7 +234,7 @@ void TaskLeaderLine::setUiPrimary()
}
DrawGuiUtil::loadArrowBox(ui->cboxStartSym);
int aStyle = getPrefArrowStyle();
int aStyle = PreferencesGui::dimArrowStyle();
ui->cboxStartSym->setCurrentIndex(aStyle);
DrawGuiUtil::loadArrowBox(ui->cboxEndSym);
@@ -239,9 +242,9 @@ void TaskLeaderLine::setUiPrimary()
ui->dsbWeight->setUnit(Base::Unit::Length);
ui->dsbWeight->setMinimum(0);
ui->dsbWeight->setValue(prefWeight());
ui->dsbWeight->setValue(TechDraw::LineGroup::getDefaultWidth("Graphic"));
ui->cpLineColor->setColor(prefLineColor().asValue<QColor>());
ui->cpLineColor->setColor(PreferencesGui::leaderColor().asValue<QColor>());
}
//switch widgets related to ViewProvider on/off
@@ -332,9 +335,11 @@ void TaskLeaderLine::onLineStyleChanged()
//******************************************************************************
void TaskLeaderLine::createLeaderFeature(std::vector<Base::Vector3d> converted)
//! sceneDeltas are vector from first picked scene point (0,0) to the ith point.
//! sceneDeltas are in Qt scene coords (Rez and inverted Y).
void TaskLeaderLine::createLeaderFeature(std::vector<Base::Vector3d> sceneDeltas)
{
// Base::Console().Message("TTL::createLeaderFeature()\n");
// Base::Console().Message("TTL::createLeaderFeature()\n");
const std::string objectName{"LeaderLine"};
std::string m_leaderName = m_basePage->getDocument()->getUniqueObjectName(objectName.c_str());
m_leaderType = "TechDraw::DrawLeaderLine";
@@ -355,16 +360,29 @@ void TaskLeaderLine::createLeaderFeature(std::vector<Base::Vector3d> converted)
}
App::DocumentObject* obj = m_basePage->getDocument()->getObject(m_leaderName.c_str());
if (!obj)
if (!obj) {
throw Base::RuntimeError("TaskLeaderLine - new markup object not found");
}
if (obj->isDerivedFrom(TechDraw::DrawLeaderLine::getClassTypeId())) {
m_lineFeat = static_cast<TechDraw::DrawLeaderLine*>(obj);
m_lineFeat->setPosition(Rez::appX(m_attachPoint.x), Rez::appX(- m_attachPoint.y), true);
if (!converted.empty()) {
m_lineFeat->WayPoints.setValues(converted);
if (m_lineFeat->AutoHorizontal.getValue()) {
m_lineFeat->adjustLastSegment();
if (!sceneDeltas.empty()) {
std::vector<Base::Vector3d> pageDeltas;
// convert deltas to mm. leader points are stored inverted, so we do not convert to conventional Y axis
for (auto& delta : sceneDeltas) {
Base::Vector3d deltaInPageCoords = DGU::fromSceneCoords(delta, false);
pageDeltas.push_back(deltaInPageCoords);
}
// should just do this in place.
if (m_lineFeat->AutoHorizontal.getValue()) {
pageDeltas = DrawLeaderLine::horizLastSegment(pageDeltas);
// m_lineFeat->horizLastSegment();
}
// convert to unscaled, unrotated but inverted
auto temp = m_lineFeat->makeCanonicalPointsInverted(pageDeltas);
m_lineFeat->WayPoints.setValues(temp);
}
commonFeatureUpdate();
}
@@ -396,6 +414,15 @@ void TaskLeaderLine::createLeaderFeature(std::vector<Base::Vector3d> converted)
}
}
void TaskLeaderLine::dumpTrackerPoints(std::vector<Base::Vector3d>& tPoints) const
{
Base::Console().Message("TTL::dumpTrackerPoints(%d)\n", tPoints.size());
Base::Console().Message("TTL::dumpTrackerPoints - attach point: %s\n", DU::formatVector(m_attachPoint).c_str());
for (auto& point : tPoints) {
Base::Console().Message("TTL::dumpTrackerPoints - a point: %s\n", DU::formatVector(point).c_str());
}
}
void TaskLeaderLine::updateLeaderFeature()
{
// Base::Console().Message("TTL::updateLeaderFeature()\n");
@@ -428,8 +455,9 @@ void TaskLeaderLine::commonFeatureUpdate()
void TaskLeaderLine::removeFeature()
{
// Base::Console().Message("TTL::removeFeature()\n");
if (!m_lineFeat)
if (!m_lineFeat) {
return;
}
if (m_createMode) {
try {
@@ -462,8 +490,8 @@ void TaskLeaderLine::onTrackerClicked(bool clicked)
return;
}
if ( (m_pbTrackerState == TrackerAction::SAVE) &&
(getCreateMode()) ){
if ( m_pbTrackerState == TrackerAction::SAVE &&
getCreateMode() ){
if (m_tracker) {
m_tracker->terminateDrawing();
}
@@ -474,10 +502,12 @@ void TaskLeaderLine::onTrackerClicked(bool clicked)
setEditCursor(Qt::ArrowCursor);
return;
} else if ( (m_pbTrackerState == TrackerAction::SAVE) &&
(!getCreateMode()) ) { //edit mode
if (m_qgLine) {
m_qgLine->closeEdit();
}
if ( m_pbTrackerState == TrackerAction::SAVE &&
!getCreateMode() ) { //edit mode
if (m_qgLeader) {
m_qgLeader->closeEdit();
}
m_pbTrackerState = TrackerAction::PICK;
ui->pbTracker->setText(tr("Edit Points"));
@@ -499,33 +529,42 @@ void TaskLeaderLine::onTrackerClicked(bool clicked)
QString msg = tr("Pick a starting point for leader line");
getMainWindow()->statusBar()->show();
Gui::getMainWindow()->showMessage(msg, 3000);
Gui::getMainWindow()->showMessage(msg, MessageDisplayTime);
ui->pbTracker->setText(tr("Save Points"));
ui->pbTracker->setEnabled(true);
ui->pbCancelEdit->setEnabled(true);
m_pbTrackerState = TrackerAction::SAVE;
enableTaskButtons(false);
} else { //edit mode
m_trackerPoints = m_lineFeat->WayPoints.getValues();
if (!m_trackerPoints.empty()) { //regular edit session
// pageDeltas are in mm with conventional Y axis
auto pageDeltas = m_lineFeat->getScaledAndRotatedPoints();
m_sceneDeltas.clear();
m_sceneDeltas.reserve(pageDeltas.size());
// now convert to sceneUnits and Qt Y axis
for (auto& entry : pageDeltas) {
m_sceneDeltas.push_back(DGU::toSceneCoords(entry, false));
}
if (!m_sceneDeltas.empty()) { //regular edit session
m_inProgressLock = true;
m_saveContextPolicy = m_vpp->getMDIViewPage()->contextMenuPolicy();
m_vpp->getMDIViewPage()->setContextMenuPolicy(Qt::PreventContextMenu);
QGIView* qgiv = m_vpp->getQGSPage()->findQViewForDocObj(m_lineFeat);
QGILeaderLine* qgLead = dynamic_cast<QGILeaderLine*>(qgiv);
auto qgLead = dynamic_cast<QGILeaderLine*>(qgiv);
if (!qgLead) {
//tarfu
Base::Console().Error("TaskLeaderLine - can't find leader graphic\n");
//now what? throw will generate "unknown unhandled exception"
} else {
m_qgLine = qgLead;
m_qgLeader = qgLead;
connect(qgLead, &QGILeaderLine::editComplete,
this, &TaskLeaderLine::onPointEditComplete);
this, &TaskLeaderLine::onPointEditComplete);
qgLead->startPathEdit();
QString msg = tr("Click and drag markers to adjust leader line");
getMainWindow()->statusBar()->show();
Gui::getMainWindow()->showMessage(msg, 3000);
Gui::getMainWindow()->showMessage(msg, MessageDisplayTime);
ui->pbTracker->setText(tr("Save changes"));
ui->pbTracker->setEnabled(true);
ui->pbCancelEdit->setEnabled(true);
@@ -542,7 +581,7 @@ void TaskLeaderLine::onTrackerClicked(bool clicked)
QString msg = tr("Pick a starting point for leader line");
getMainWindow()->statusBar()->show();
Gui::getMainWindow()->showMessage(msg, 3000);
Gui::getMainWindow()->showMessage(msg, MessageDisplayTime);
ui->pbTracker->setText(tr("Save changes"));
ui->pbTracker->setEnabled(true);
ui->pbCancelEdit->setEnabled(true);
@@ -555,10 +594,13 @@ void TaskLeaderLine::onTrackerClicked(bool clicked)
void TaskLeaderLine::startTracker()
{
// Base::Console().Message("TTL::startTracker()\n");
if (!m_vpp->getQGSPage())
if (!m_vpp->getQGSPage()) {
return;
if (m_trackerMode == QGTracker::TrackerMode::None)
}
if (m_trackerMode == QGTracker::TrackerMode::None) {
return;
}
if (!m_tracker) {
m_tracker = new QGTracker(m_vpp->getQGSPage(), m_trackerMode);
@@ -573,24 +615,24 @@ void TaskLeaderLine::startTracker()
setEditCursor(Qt::CrossCursor);
QString msg = tr("Left click to set a point");
Gui::getMainWindow()->statusBar()->show();
Gui::getMainWindow()->showMessage(msg, 3000);
Gui::getMainWindow()->showMessage(msg, MessageDisplayTime);
}
void TaskLeaderLine::onTrackerFinished(std::vector<QPointF> pts, QGIView* qgParent)
void TaskLeaderLine::onTrackerFinished(std::vector<QPointF> trackerScenePoints, QGIView* qgParent)
{
//in this case, we already know who the parent is. We don't need QGTracker to tell us.
(void) qgParent;
// Base::Console().Message("TTL::onTrackerFinished() - parent: %X\n", qgParent);
if (pts.empty()) {
// Base::Console().Message("TTL::onTrackerFinished() - parent: %X\n", qgParent);
if (trackerScenePoints.empty()) {
Base::Console().Error("TaskLeaderLine - no points available\n");
return;
}
if (m_qgParent) {
double scale = m_qgParent->getScale();
QPointF mapped = m_qgParent->mapFromScene(pts.front()) / scale;
QPointF mapped = m_qgParent->mapFromScene(trackerScenePoints.front()) / scale;
m_attachPoint = Base::Vector3d(mapped.x(), mapped.y(), 0.0);
trackerPointsFromQPoints(pts);
m_sceneDeltas = scenePointsToDeltas(trackerScenePoints);
} else {
Base::Console().Message("TTL::onTrackerFinished - can't find parent graphic!\n");
//blow up!?
@@ -599,22 +641,30 @@ void TaskLeaderLine::onTrackerFinished(std::vector<QPointF> pts, QGIView* qgPare
QString msg = tr("Press OK or Cancel to continue");
getMainWindow()->statusBar()->show();
Gui::getMainWindow()->showMessage(msg, 3000);
Gui::getMainWindow()->showMessage(msg, MessageDisplayTime);
enableTaskButtons(true);
// ??? why does the tracker go to sleep when we are finished with it? why not removeTracker
m_tracker->sleep(true);
m_inProgressLock = false;
// can not pick points any more?
ui->pbTracker->setEnabled(false);
ui->pbCancelEdit->setEnabled(false);
// only option available to user is accept/reject?
enableTaskButtons(true);
setEditCursor(Qt::ArrowCursor);
setEditCursor(Qt::ArrowCursor); // already done by m_tracker->sleep()?
}
// this is called at every possible exit path?
void TaskLeaderLine::removeTracker()
{
// Base::Console().Message("TTL::removeTracker()\n");
if (!m_vpp->getQGSPage())
if (!m_vpp->getQGSPage()) {
return;
}
if (m_tracker && m_tracker->scene()) {
m_vpp->getQGSPage()->removeItem(m_tracker);
delete m_tracker;
@@ -643,13 +693,15 @@ void TaskLeaderLine::onCancelEditClicked(bool clicked)
QGIView* TaskLeaderLine::findParentQGIV()
{
if (!m_baseFeat)
if (!m_baseFeat) {
return nullptr;
}
Gui::ViewProvider* gvp = QGIView::getViewProvider(m_baseFeat);
ViewProviderDrawingView* vpdv = dynamic_cast<ViewProviderDrawingView*>(gvp);
if (!vpdv)
if (!vpdv) {
return nullptr;
}
return vpdv->getQView();;
}
@@ -665,20 +717,23 @@ void TaskLeaderLine::setEditCursor(QCursor cursor)
}
}
//from 1:1 scale scene QPointF to zero origin Vector3d points
void TaskLeaderLine::trackerPointsFromQPoints(std::vector<QPointF> pts)
//from scene QPointF to zero origin (delta from p0) Vector3d points
std::vector<Base::Vector3d> TaskLeaderLine::scenePointsToDeltas(std::vector<QPointF> scenePoints)
{
// Base::Console().Message("TTL::trackerPointsFromQPoints(%d)\n", pts.size());
m_trackerPoints.clear();
for (auto& p: pts) {
QPointF mapped = p - pts.front();
Base::Vector3d convert(mapped.x(), mapped.y(), 0.0);
m_trackerPoints.push_back(convert);
// Base::Console().Message("TTL::scenePointsToDeltas(%d)\n", pts.size());
std::vector<Base::Vector3d> result;
result.reserve(scenePoints.size());
for (auto& point: scenePoints) {
QPointF delta = point - scenePoints.front();
result.push_back(DU::toVector3d(delta));
}
return result;
}
//******************************************************************************
//void TaskLeaderLine::onPointEditComplete(std::vector<QPointF> pts, QGIView* parent)
//! point edit session completed. reset ui to initial state.
void TaskLeaderLine::onPointEditComplete()
{
// Base::Console().Message("TTL::onPointEditComplete()\n");
@@ -691,15 +746,20 @@ void TaskLeaderLine::onPointEditComplete()
enableTaskButtons(true);
}
//! give up on the current point editing session. reset the ui so we are in a state to
//! start editing points again. leave the existing tracker instance in place.
void TaskLeaderLine::abandonEditSession()
{
// Base::Console().Message("TTL::abandonEditSession()\n");
if (m_qgLine) {
m_qgLine->abandonEdit();
constexpr int MessageDuration{4000};
if (m_qgLeader) {
// tell the graphics item that we are giving up so it should do any clean up it needs.
m_qgLeader->abandonEdit();
}
QString msg = tr("In progress edit abandoned. Start over.");
getMainWindow()->statusBar()->show();
Gui::getMainWindow()->showMessage(msg, 4000);
Gui::getMainWindow()->showMessage(msg, MessageDuration);
m_pbTrackerState = TrackerAction::EDIT;
ui->pbTracker->setText(tr("Edit points"));
@@ -723,21 +783,6 @@ void TaskLeaderLine::enableTaskButtons(bool enable)
m_btnCancel->setEnabled(enable);
}
int TaskLeaderLine::getPrefArrowStyle()
{
return PreferencesGui::dimArrowStyle();
}
double TaskLeaderLine::prefWeight() const
{
return TechDraw::LineGroup::getDefaultWidth("Thin");
}
App::Color TaskLeaderLine::prefLineColor()
{
return PreferencesGui::leaderColor();
}
//******************************************************************************
bool TaskLeaderLine::accept()
@@ -759,7 +804,7 @@ bool TaskLeaderLine::accept()
updateLeaderFeature();
} else {
// removeTracker();
createLeaderFeature(m_trackerPoints);
createLeaderFeature(m_sceneDeltas);
}
m_trackerMode = QGTracker::TrackerMode::None;
removeTracker();