[MeasureGui] Use temporary measure object creation (#15122)
* MeasureGui: Store measure type in TaskMeasure * MeasureGui: Avoid adding measurement to document during command interaction * [Gui] Add check for document in VPDocumentObject::getActiveView * MeasureGui: Track the document when adding objects * MeasureGui: Cleanup python measurement creation * [Gui] Add isAnnotationViewProvider method * [Gui] Check if viewprovider is added as an annotation in getActiveView * [Gui] Add takeAnnotationViewprovider method to Gui::Document * [Gui] Make addViewProvider public * [MeasureGui] Add existing view provider to document when storing measurement * [MeasureGui] Fix invocation of initial label placement * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
@@ -30,13 +30,13 @@
|
||||
|
||||
#include "TaskMeasure.h"
|
||||
|
||||
#include <App/Document.h>
|
||||
#include <App/DocumentObjectGroup.h>
|
||||
#include <App/Link.h>
|
||||
#include <Gui/MainWindow.h>
|
||||
#include <Gui/Application.h>
|
||||
#include <Gui/BitmapFactory.h>
|
||||
#include <Gui/Control.h>
|
||||
#include <Gui/ViewProviderDocumentObject.h>
|
||||
|
||||
#include <QFormLayout>
|
||||
#include <QPushButton>
|
||||
@@ -162,6 +162,81 @@ void TaskMeasure::setMeasureObject(Measure::MeasureBase* obj)
|
||||
}
|
||||
|
||||
|
||||
App::DocumentObject* TaskMeasure::createObject(const App::MeasureType* measureType)
|
||||
{
|
||||
auto measureClass =
|
||||
measureType->isPython ? "Measure::MeasurePython" : measureType->measureObject;
|
||||
auto type = Base::Type::getTypeIfDerivedFrom(measureClass.c_str(),
|
||||
App::DocumentObject::getClassTypeId(),
|
||||
true);
|
||||
|
||||
if (type.isBad()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
_mMeasureObject = static_cast<Measure::MeasureBase*>(type.createInstance());
|
||||
|
||||
// Create an instance of the python measure class, the classe's
|
||||
// initializer sets the object as proxy
|
||||
if (measureType->isPython) {
|
||||
Base::PyGILStateLocker lock;
|
||||
Py::Tuple args(1);
|
||||
args.setItem(0, Py::asObject(_mMeasureObject->getPyObject()));
|
||||
PyObject* result = PyObject_CallObject(measureType->pythonClass, args.ptr());
|
||||
Py_XDECREF(result);
|
||||
}
|
||||
|
||||
return static_cast<App::DocumentObject*>(_mMeasureObject);
|
||||
}
|
||||
|
||||
|
||||
Gui::ViewProviderDocumentObject* TaskMeasure::createViewObject(App::DocumentObject* measureObj)
|
||||
{
|
||||
// Add view object
|
||||
auto vpName = measureObj->getViewProviderName();
|
||||
if ((vpName == nullptr) || (vpName[0] == '\0')) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto vpType =
|
||||
Base::Type::getTypeIfDerivedFrom(vpName,
|
||||
Gui::ViewProviderDocumentObject::getClassTypeId(),
|
||||
true);
|
||||
if (vpType.isBad()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto vp = static_cast<Gui::ViewProviderDocumentObject*>(vpType.createInstance());
|
||||
|
||||
_mGuiDocument = Gui::Application::Instance->activeDocument();
|
||||
_mGuiDocument->setAnnotationViewProvider(vp->getTypeId().getName(), vp);
|
||||
vp->attach(measureObj);
|
||||
|
||||
// Init the position of the annotation
|
||||
static_cast<MeasureGui::ViewProviderMeasureBase*>(vp)->positionAnno(_mMeasureObject);
|
||||
|
||||
vp->updateView();
|
||||
vp->setActiveMode();
|
||||
|
||||
_mViewObject = vp;
|
||||
return vp;
|
||||
}
|
||||
|
||||
|
||||
void TaskMeasure::saveObject()
|
||||
{
|
||||
if (_mViewObject && _mGuiDocument) {
|
||||
_mGuiDocument->addViewProvider(_mViewObject);
|
||||
_mGuiDocument->takeAnnotationViewProvider(_mViewObject->getTypeId().getName());
|
||||
_mViewObject = nullptr;
|
||||
}
|
||||
|
||||
_mDocument = App::GetApplication().getActiveDocument();
|
||||
_mDocument->addObject(_mMeasureObject, _mMeasureType->label.c_str());
|
||||
_mMeasureObject = nullptr;
|
||||
}
|
||||
|
||||
|
||||
void TaskMeasure::update()
|
||||
{
|
||||
App::Document* doc = App::GetApplication().getActiveDocument();
|
||||
@@ -189,8 +264,6 @@ void TaskMeasure::update()
|
||||
valueResult->setText(QString::asprintf("-"));
|
||||
|
||||
// Get valid measure type
|
||||
App::MeasureType* measureType(nullptr);
|
||||
|
||||
|
||||
std::string mode = explicitMode ? modeSwitch->currentText().toStdString() : "";
|
||||
|
||||
@@ -204,10 +277,11 @@ void TaskMeasure::update()
|
||||
|
||||
auto measureTypes = App::MeasureManager::getValidMeasureTypes(selection, mode);
|
||||
if (measureTypes.size() > 0) {
|
||||
measureType = measureTypes.front();
|
||||
_mMeasureType = measureTypes.front();
|
||||
}
|
||||
|
||||
if (!measureType) {
|
||||
|
||||
if (!_mMeasureType) {
|
||||
|
||||
// Note: If there's no valid measure type we might just restart the selection,
|
||||
// however this requires enough coverage of measuretypes that we can access all of them
|
||||
@@ -226,34 +300,13 @@ void TaskMeasure::update()
|
||||
}
|
||||
|
||||
// Update tool mode display
|
||||
setModeSilent(measureType);
|
||||
setModeSilent(_mMeasureType);
|
||||
|
||||
if (!_mMeasureObject || measureType->measureObject != _mMeasureObject->getTypeId().getName()) {
|
||||
if (!_mMeasureObject
|
||||
|| _mMeasureType->measureObject != _mMeasureObject->getTypeId().getName()) {
|
||||
// we don't already have a measureobject or it isn't the same type as the new one
|
||||
removeObject();
|
||||
|
||||
if (measureType->isPython) {
|
||||
Base::PyGILStateLocker lock;
|
||||
auto pyMeasureClass = measureType->pythonClass;
|
||||
|
||||
// Create a MeasurePython instance
|
||||
auto featurePython =
|
||||
doc->addObject("Measure::MeasurePython", measureType->label.c_str());
|
||||
setMeasureObject((Measure::MeasureBase*)featurePython);
|
||||
|
||||
// Create an instance of the pyMeasureClass, the classe's initializer sets the object as
|
||||
// proxy
|
||||
Py::Tuple args(1);
|
||||
args.setItem(0, Py::asObject(featurePython->getPyObject()));
|
||||
PyObject* result = PyObject_CallObject(pyMeasureClass, args.ptr());
|
||||
Py_XDECREF(result);
|
||||
}
|
||||
else {
|
||||
// Create measure object
|
||||
setMeasureObject(
|
||||
(Measure::MeasureBase*)doc->addObject(measureType->measureObject.c_str(),
|
||||
measureType->label.c_str()));
|
||||
}
|
||||
createObject(_mMeasureType);
|
||||
}
|
||||
|
||||
// we have a valid measure object so we can enable the annotate button
|
||||
@@ -262,14 +315,10 @@ void TaskMeasure::update()
|
||||
// Fill measure object's properties from selection
|
||||
_mMeasureObject->parseSelection(selection);
|
||||
|
||||
// Init the view object
|
||||
Gui::ViewProvider* viewObj = Gui::Application::Instance->getViewProvider(_mMeasureObject);
|
||||
if (viewObj) {
|
||||
static_cast<MeasureGui::ViewProviderMeasureBase*>(viewObj)->positionAnno(_mMeasureObject);
|
||||
}
|
||||
|
||||
// Get result
|
||||
valueResult->setText(_mMeasureObject->getResultString());
|
||||
|
||||
createViewObject(_mMeasureObject);
|
||||
}
|
||||
|
||||
void TaskMeasure::close()
|
||||
@@ -278,7 +327,7 @@ void TaskMeasure::close()
|
||||
}
|
||||
|
||||
|
||||
void ensureGroup(Measure::MeasureBase* measurement)
|
||||
void TaskMeasure::ensureGroup(Measure::MeasureBase* measurement)
|
||||
{
|
||||
// Ensure measurement object is part of the measurements group
|
||||
|
||||
@@ -287,7 +336,7 @@ void ensureGroup(Measure::MeasureBase* measurement)
|
||||
return;
|
||||
}
|
||||
|
||||
App::Document* doc = App::GetApplication().getActiveDocument();
|
||||
App::Document* doc = measurement->getDocument();
|
||||
App::DocumentObject* obj = doc->getObject(measurementGroupName);
|
||||
if (!obj || !obj->isValid()) {
|
||||
obj = doc->addObject("App::DocumentObjectGroup",
|
||||
@@ -309,7 +358,9 @@ void TaskMeasure::invoke()
|
||||
|
||||
bool TaskMeasure::apply()
|
||||
{
|
||||
saveObject();
|
||||
ensureGroup(_mMeasureObject);
|
||||
_mMeasureType = nullptr;
|
||||
_mMeasureObject = nullptr;
|
||||
reset();
|
||||
|
||||
@@ -332,6 +383,7 @@ bool TaskMeasure::reject()
|
||||
void TaskMeasure::reset()
|
||||
{
|
||||
// Reset tool state
|
||||
_mMeasureType = nullptr;
|
||||
this->clearSelection();
|
||||
|
||||
// Should the explicit mode also be reset?
|
||||
@@ -350,7 +402,13 @@ void TaskMeasure::removeObject()
|
||||
if (_mMeasureObject->isRemoving()) {
|
||||
return;
|
||||
}
|
||||
_mMeasureObject->getDocument()->removeObject(_mMeasureObject->getNameInDocument());
|
||||
|
||||
if (_mViewObject && _mGuiDocument) {
|
||||
_mGuiDocument->removeAnnotationViewProvider(_mViewObject->getTypeId().getName());
|
||||
_mViewObject = nullptr;
|
||||
}
|
||||
|
||||
delete _mMeasureObject;
|
||||
setMeasureObject(nullptr);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user