/*************************************************************************** * Copyright (c) 2019 WandererFan * * * * 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 # include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ui_TaskCosVertex.h" #include "TaskCosVertex.h" #include "MDIViewPage.h" #include "QGIView.h" #include "QGSPage.h" #include "QGTracker.h" #include "Rez.h" #include "ViewProviderPage.h" using namespace Gui; using namespace TechDraw; using namespace TechDrawGui; using DU = DrawUtil; TaskCosVertex::TaskCosVertex(TechDraw::DrawViewPart* baseFeat, TechDraw::DrawPage* page) : ui(new Ui_TaskCosVertex), blockUpdate(false), m_tracker(nullptr), m_baseFeat(baseFeat), m_basePage(page), m_qgParent(nullptr), m_trackerMode(QGTracker::TrackerMode::None), m_saveContextPolicy(Qt::DefaultContextMenu), m_inProgressLock(false), m_btnOK(nullptr), m_btnCancel(nullptr), m_pbTrackerState(TrackerAction::PICK), m_savePoint(QPointF(0.0, 0.0)) { //baseFeat and page existence checked in cosmetic vertex command (CommandAnnotate.cpp) ui->setupUi(this); Gui::Document* activeGui = Gui::Application::Instance->getDocument(m_basePage->getDocument()); Gui::ViewProvider* vp = activeGui->getViewProvider(m_basePage); m_vpp = static_cast(vp); setUiPrimary(); connect(ui->pbTracker, &QPushButton::clicked, this, &TaskCosVertex::onTrackerClicked); m_trackerMode = QGTracker::TrackerMode::Point; } void TaskCosVertex::updateTask() { // blockUpdate = true; // blockUpdate = false; } void TaskCosVertex::changeEvent(QEvent* event) { if (event->type() == QEvent::LanguageChange) { ui->retranslateUi(this); } } void TaskCosVertex::setUiPrimary() { // Base::Console().message("TCV::setUiPrimary()\n"); setWindowTitle(QObject::tr("New Cosmetic Vertex")); if (m_baseFeat) { std::string baseName = m_baseFeat->getNameInDocument(); ui->leBaseView->setText(QString::fromStdString(baseName)); } ui->pbTracker->setText(tr("Point Picker")); ui->pbTracker->setEnabled(true); ui->dsbX->setEnabled(true); ui->dsbY->setEnabled(true); int decimals = Base::UnitsApi::getDecimals(); ui->dsbX->setDecimals(decimals); ui->dsbY->setDecimals(decimals); ui->dsbX->setUnit(Base::Unit::Length); ui->dsbY->setUnit(Base::Unit::Length); } // set the ui x,y to apparent coords (ie invertY) void TaskCosVertex::updateUi() { double x = m_savePoint.x(); double y = - m_savePoint.y(); ui->dsbX->setValue(x); ui->dsbY->setValue(y); } //! create the cv as entered, addCosmeticVertex will invert it void TaskCosVertex::addCosVertex(QPointF qPos) { Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Add Cosmetic Vertex")); // Base::Vector3d pos = DU::invertY(DU::toVector3d(qPos)); // int idx = (void) m_baseFeat->addCosmeticVertex(DU::toVector3d(qPos)); m_baseFeat->requestPaint(); Gui::Command::commitCommand(); } //********** Tracker routines ******************************************************************* void TaskCosVertex::onTrackerClicked(bool clicked) { Q_UNUSED(clicked); // Base::Console().message("TCV::onTrackerClicked() m_pbTrackerState: %d\n", // m_pbTrackerState); removeTracker(); if (m_pbTrackerState == TrackerAction::CANCEL) { m_pbTrackerState = TrackerAction::PICK; ui->pbTracker->setText(tr("Pick points")); enableTaskButtons(true); setEditCursor(Qt::ArrowCursor); return; } m_inProgressLock = true; m_saveContextPolicy = m_vpp->getMDIViewPage()->contextMenuPolicy(); m_vpp->getMDIViewPage()->setContextMenuPolicy(Qt::PreventContextMenu); m_trackerMode = QGTracker::TrackerMode::Point; setEditCursor(Qt::CrossCursor); startTracker(); QString msg = tr("Pick a point for cosmetic vertex"); getMainWindow()->statusBar()->show(); Gui::getMainWindow()->showMessage(msg, 3000); ui->pbTracker->setText(tr("Escape picking")); ui->pbTracker->setEnabled(true); m_pbTrackerState = TrackerAction::CANCEL; enableTaskButtons(false); } void TaskCosVertex::startTracker() { // Base::Console().message("TCV::startTracker()\n"); if (m_trackerMode == QGTracker::TrackerMode::None) { return; } if (!m_tracker) { m_tracker = new QGTracker(m_vpp->getQGSPage(), m_trackerMode); std::string parentName = m_baseFeat->getNameInDocument(); QGIView* parentView = m_vpp->getQGSPage()->getQGIVByName(parentName); m_tracker->setOwnerQView(parentView); QObject::connect( m_tracker, &QGTracker::drawingFinished, this, &TaskCosVertex::onTrackerFinished ); } else { //this is too harsh. but need to avoid restarting process throw Base::RuntimeError("TechDrawNewLeader - tracker already active\n"); } setEditCursor(Qt::CrossCursor); QString msg = tr("Left click to set a point"); Gui::getMainWindow()->statusBar()->show(); Gui::getMainWindow()->showMessage(msg, 3000); } void TaskCosVertex::onTrackerFinished(std::vector pts, QGIView* qgParent) { (void)qgParent; if (pts.empty()) { Base::Console().error("TaskCosVertex - no points available\n"); return; } QPointF dragEnd = pts.front(); //scene pos of mouse click double x = Rez::guiX(m_baseFeat->X.getValue()); double y = Rez::guiX(m_baseFeat->Y.getValue()); DrawViewPart* dvp = m_baseFeat; DrawProjGroupItem* dpgi = freecad_cast(dvp); if (dpgi) { DrawProjGroup* dpg = dpgi->getPGroup(); if (dpg) { x += Rez::guiX(dpg->X.getValue()); y += Rez::guiX(dpg->Y.getValue()); } } //x, y are scene pos of dvp/dpgi QPointF basePosScene(x, -y); //base position in scene coords QPointF scenePosCV = dragEnd - basePosScene; // Invert Y value so the math works. // scenePosCV is effectively a scaled (and rotated), inverted value // Base::Vector3d posToRotate = DU::invertY(DU::toVector3d(scenePosCV)); // unscale and rotate the picked point Base::Vector3d posToRotate = CosmeticVertex::makeCanonicalPointInverted(m_baseFeat, DU::toVector3d(scenePosCV)); // now put Y value back to display form scenePosCV = DU::toQPointF(posToRotate); m_savePoint = Rez::appX(scenePosCV); updateUi(); m_tracker->sleep(true); m_inProgressLock = false; m_pbTrackerState = TrackerAction::PICK; ui->pbTracker->setText(tr("Pick points")); ui->pbTracker->setEnabled(true); enableTaskButtons(true); setEditCursor(Qt::ArrowCursor); m_vpp->getMDIViewPage()->setContextMenuPolicy(m_saveContextPolicy); } void TaskCosVertex::removeTracker() { // Base::Console().message("TCV::removeTracker()\n"); if (m_tracker && m_tracker->scene()) { m_vpp->getQGSPage()->removeItem(m_tracker); delete m_tracker; m_tracker = nullptr; } } void TaskCosVertex::setEditCursor(QCursor cursor) { if (m_baseFeat) { QGIView* qgivBase = m_vpp->getQGSPage()->findQViewForDocObj(m_baseFeat); qgivBase->setCursor(cursor); } } void TaskCosVertex::abandonEditSession() { QString msg = tr("In progress edit abandoned. Start over."); getMainWindow()->statusBar()->show(); Gui::getMainWindow()->showMessage(msg, 4000); ui->pbTracker->setEnabled(true); setEditCursor(Qt::ArrowCursor); } void TaskCosVertex::saveButtons(QPushButton* btnOK, QPushButton* btnCancel) { m_btnOK = btnOK; m_btnCancel = btnCancel; } void TaskCosVertex::enableTaskButtons(bool button) { m_btnOK->setEnabled(button); m_btnCancel->setEnabled(button); } //****************************************************************************** bool TaskCosVertex::accept() { Gui::Document* doc = Gui::Application::Instance->getDocument(m_basePage->getDocument()); if (!doc) return false; removeTracker(); // whatever is in the ui for x,y is treated as an unscaled, unrotated, conventional Y position. // the position from the tracker is unscaled & unrotated before updating the ui double x = ui->dsbX->value().getValue(); double y = ui->dsbY->value().getValue(); QPointF uiPoint(x, y); addCosVertex(uiPoint); m_baseFeat->recomputeFeature(); m_baseFeat->requestPaint(); m_vpp->getMDIViewPage()->setContextMenuPolicy(m_saveContextPolicy); m_trackerMode = QGTracker::TrackerMode::None; Gui::Command::doCommand(Gui::Command::Gui, "Gui.ActiveDocument.resetEdit()"); return true; } bool TaskCosVertex::reject() { Gui::Document* doc = Gui::Application::Instance->getDocument(m_basePage->getDocument()); if (!doc) return false; removeTracker(); m_trackerMode = QGTracker::TrackerMode::None; if (m_vpp->getMDIViewPage()) { m_vpp->getMDIViewPage()->setContextMenuPolicy(m_saveContextPolicy); } //make sure any dangling objects are cleaned up Gui::Command::doCommand(Gui::Command::Gui, "App.activeDocument().recompute()"); Gui::Command::doCommand(Gui::Command::Gui, "Gui.ActiveDocument.resetEdit()"); return false; } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// TaskDlgCosVertex::TaskDlgCosVertex(TechDraw::DrawViewPart* baseFeat, TechDraw::DrawPage* page) : TaskDialog() { widget = new TaskCosVertex(baseFeat, page); taskbox = new Gui::TaskView::TaskBox(Gui::BitmapFactory().pixmap("actions/TechDraw_CosmeticVertex"), widget->windowTitle(), true, nullptr); taskbox->groupLayout()->addWidget(widget); Content.push_back(taskbox); } TaskDlgCosVertex::~TaskDlgCosVertex() { } void TaskDlgCosVertex::update() { // widget->updateTask(); } void TaskDlgCosVertex::modifyStandardButtons(QDialogButtonBox* box) { QPushButton* btnOK = box->button(QDialogButtonBox::Ok); QPushButton* btnCancel = box->button(QDialogButtonBox::Cancel); widget->saveButtons(btnOK, btnCancel); } //==== calls from the TaskView =============================================================== void TaskDlgCosVertex::open() { } void TaskDlgCosVertex::clicked(int) { } bool TaskDlgCosVertex::accept() { widget->accept(); return true; } bool TaskDlgCosVertex::reject() { widget->reject(); return true; } #include