Merge pull request #19917 from tritao/refactor-document-recompute

Core: Refactor code around document and feature recompute
This commit is contained in:
Chris Hennes
2025-03-16 23:59:12 -05:00
committed by GitHub
13 changed files with 73 additions and 79 deletions

View File

@@ -3370,7 +3370,7 @@ int Document::_recomputeFeature(DocumentObject* Feat)
return 1;
}
catch (std::exception& e) {
FC_ERR("exception in " << Feat->getFullName() << " thrown: " << e.what());
FC_ERR("Exception in " << Feat->getFullName() << " thrown: " << e.what());
d->addRecomputeLog(e.what(), Feat);
return 1;
}
@@ -3394,26 +3394,25 @@ int Document::_recomputeFeature(DocumentObject* Feat)
return 0;
}
bool Document::recomputeFeature(DocumentObject* Feat, bool recursive)
bool Document::recomputeFeature(DocumentObject* feature, bool recursive)
{
// delete recompute log
d->clearRecomputeLog(Feat);
d->clearRecomputeLog(feature);
// verify that the feature is (active) part of the document
if (Feat->isAttachedToDocument()) {
if (recursive) {
bool hasError = false;
recompute({Feat}, true, &hasError);
return !hasError;
}
else {
_recomputeFeature(Feat);
signalRecomputedObject(*Feat);
return Feat->isValid();
}
if (!feature->isAttachedToDocument()) {
return false;
}
if (recursive) {
bool hasError = false;
recompute({feature}, true, &hasError);
return !hasError;
}
else {
return false;
_recomputeFeature(feature);
signalRecomputedObject(*feature);
return feature->isValid();
}
}

View File

@@ -31,17 +31,18 @@
#include <string>
#include <memory>
#include <vector>
#include <unordered_map>
#include <unordered_set>
#include <boost/bimap.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <CXX/Objects.hxx>
#include <App/DocumentObject.h>
#include <App/DocumentObserver.h>
#include <App/StringHasher.h>
#include <Base/UniqueNameManager.h>
#include <CXX/Objects.hxx>
#include <boost/bimap.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <unordered_map>
#include <unordered_set>
// using VertexProperty = boost::property<boost::vertex_root_t, DocumentObject* >;
using DependencyList = boost::adjacency_list<

View File

@@ -853,18 +853,6 @@ bool Command::isActiveObjectValid()
return object->isValid();
}
/// Updates the (all or listed) documents (propagate changes)
void Command::updateAll(std::list<Gui::Document*> cList)
{
if (!cList.empty()) {
for (auto & it : cList)
it->onUpdate();
}
else {
Gui::Application::Instance->onUpdate();
}
}
//--------------------------------------------------------------------------
// Online help handling
//--------------------------------------------------------------------------

View File

@@ -418,8 +418,6 @@ public:
static bool hasPendingCommand();
/// Updates the (active) document (propagate changes)
static void updateActive();
/// Updates the (all or listed) documents (propagate changes)
static void updateAll(std::list<Gui::Document*> cList);
/// Checks if the active object of the active document is valid
static bool isActiveObjectValid();
/// Translate command

View File

@@ -1487,24 +1487,25 @@ StdCmdRefresh::StdCmdRefresh()
eType = eType | NoTransaction;
}
void StdCmdRefresh::activated(int iMsg)
void StdCmdRefresh::activated([[maybe_unused]] int iMsg)
{
Q_UNUSED(iMsg);
if (getActiveGuiDocument()) {
App::AutoTransaction trans((eType & NoTransaction) ? nullptr : "Recompute");
try {
doCommand(Doc,"App.activeDocument().recompute(None,True,True)");
}
catch (Base::Exception& /*e*/) {
auto ret = QMessageBox::warning(getMainWindow(), QObject::tr("Dependency error"),
qApp->translate("Std_Refresh", "The document contains dependency cycles.\n"
"Please check the Report View for more details.\n\n"
"Do you still want to proceed?"),
QMessageBox::Yes, QMessageBox::No);
if(ret == QMessageBox::No)
return;
doCommand(Doc,"App.activeDocument().recompute(None,True)");
}
if (!getActiveGuiDocument()) {
return;
}
App::AutoTransaction trans((eType & NoTransaction) ? nullptr : "Recompute");
try {
doCommand(Doc,"App.activeDocument().recompute(None,True,True)");
}
catch (Base::Exception& /*e*/) {
auto ret = QMessageBox::warning(getMainWindow(), QObject::tr("Dependency error"),
qApp->translate("Std_Refresh", "The document contains dependency cycles.\n"
"Please check the Report View for more details.\n\n"
"Do you still want to proceed?"),
QMessageBox::Yes, QMessageBox::No);
if(ret == QMessageBox::No)
return;
doCommand(Doc,"App.activeDocument().recompute(None,True)");
}
}

View File

@@ -676,7 +676,7 @@ void TaskAttacher::onCheckFlip(bool on)
Part::AttachExtension* pcAttach = ViewProvider->getObject()->getExtensionByType<Part::AttachExtension>();
pcAttach->MapReversed.setValue(on);
ViewProvider->getObject()->getDocument()->recomputeFeature(ViewProvider->getObject());
ViewProvider->getObject()->recomputeFeature();
}
void TaskAttacher::onButtonRef(const bool checked, unsigned idx)

View File

@@ -528,17 +528,18 @@ bool CmdPartDesignNewSketch::isActive()
// Common utility functions for all features creating solids
//===========================================================================
void finishFeature(const Gui::Command* cmd, App::DocumentObject *Feat,
static void finishFeature(const Gui::Command* cmd, App::DocumentObject *feature,
App::DocumentObject* prevSolidFeature = nullptr,
const bool hidePrevSolid = true,
const bool updateDocument = true)
{
PartDesign::Body *pcActiveBody;
PartDesign::Body *activeBody;
if (prevSolidFeature) {
pcActiveBody = PartDesignGui::getBodyFor(prevSolidFeature, /*messageIfNot = */false);
} else { // insert into the same body as the given previous one
pcActiveBody = PartDesignGui::getBody(/*messageIfNot = */false);
// insert into the same body as the given previous one
activeBody = PartDesignGui::getBodyFor(prevSolidFeature, /*messageIfNot = */false);
} else {
activeBody = PartDesignGui::getBody(/*messageIfNot = */false);
}
if (hidePrevSolid && prevSolidFeature)
@@ -547,27 +548,24 @@ void finishFeature(const Gui::Command* cmd, App::DocumentObject *Feat,
if (updateDocument)
cmd->updateActive();
auto base = dynamic_cast<PartDesign::Feature*>(Feat);
auto base = dynamic_cast<PartDesign::Feature*>(feature);
if (base)
base = dynamic_cast<PartDesign::Feature*>(base->getBaseObject(true));
App::DocumentObject *obj = base;
if (!obj)
obj = pcActiveBody;
obj = activeBody;
// Do this before calling setEdit to avoid to override the 'Shape preview' mode (#0003621)
if (obj) {
cmd->copyVisual(Feat, "ShapeAppearance", obj);
cmd->copyVisual(Feat, "LineColor", obj);
cmd->copyVisual(Feat, "PointColor", obj);
cmd->copyVisual(Feat, "Transparency", obj);
cmd->copyVisual(Feat, "DisplayMode", obj);
cmd->copyVisual(feature, "ShapeAppearance", obj);
cmd->copyVisual(feature, "LineColor", obj);
cmd->copyVisual(feature, "PointColor", obj);
cmd->copyVisual(feature, "Transparency", obj);
cmd->copyVisual(feature, "DisplayMode", obj);
}
// #0001721: use '0' as edit value to avoid switching off selection in
// ViewProviderGeometryObject::setEditViewer
PartDesignGui::setEdit(Feat,pcActiveBody);
PartDesignGui::setEdit(feature, activeBody);
cmd->doCommand(cmd->Gui,"Gui.Selection.clearSelection()");
//cmd->doCommand(cmd->Gui,"Gui.Selection.addSelection(App.ActiveDocument.ActiveObject)");
}
//===========================================================================

View File

@@ -72,7 +72,7 @@ void TaskFeatureParameters::recomputeFeature()
if (!blockUpdate) {
App::DocumentObject* obj = getObject();
assert (obj);
obj->getDocument()->recomputeFeature (obj);
obj->recomputeFeature();
}
}

View File

@@ -158,12 +158,7 @@ bool ViewProviderTransformed::onDelete(const std::vector<std::string> &s)
return ViewProvider::onDelete(s);
}
void ViewProviderTransformed::recomputeFeature(bool recompute)
{
PartDesign::Transformed* pcTransformed = getObject<PartDesign::Transformed>();
if(recompute || (pcTransformed->isError() || pcTransformed->mustExecute()))
pcTransformed->recomputeFeature(true);
void ViewProviderTransformed::handleTranformedResult(PartDesign::Transformed* pcTransformed) {
unsigned rejected = 0;
TopoDS_Shape cShape = pcTransformed->rejected;
TopExp_Explorer xp;
@@ -209,6 +204,15 @@ void ViewProviderTransformed::recomputeFeature(bool recompute)
}
}
void ViewProviderTransformed::recomputeFeature(bool recompute)
{
PartDesign::Transformed* pcTransformed = getObject<PartDesign::Transformed>();
if(recompute || (pcTransformed->isError() || pcTransformed->mustExecute()))
pcTransformed->recomputeFeature(true);
handleTranformedResult(pcTransformed);
}
void ViewProviderTransformed::showRejectedShape(TopoDS_Shape shape)
{
try {

View File

@@ -26,6 +26,10 @@
#include "ViewProvider.h"
namespace PartDesign {
class Transformed;
}
namespace PartDesignGui {
class TaskDlgTransformedParameters;
@@ -58,6 +62,7 @@ protected:
void unsetEdit(int ModNum) override;
bool checkDlgOpen(TaskDlgTransformedParameters* transformedDlg);
void handleTranformedResult(PartDesign::Transformed* transformed);
// node for the representation of rejected repetitions
SoGroup * pcRejectedRoot{nullptr};

View File

@@ -157,7 +157,7 @@ void TaskBalloon::recomputeFeature()
{
App::DocumentObject* objVP = m_balloonVP->getObject();
assert(objVP);
objVP->getDocument()->recomputeFeature(objVP);
objVP->recomputeFeature();
}
void TaskBalloon::onTextChanged()

View File

@@ -180,7 +180,7 @@ void TaskDimension::recomputeFeature()
}
App::DocumentObject* objVP = m_dimensionVP->getObject();
assert(objVP);
objVP->getDocument()->recomputeFeature(objVP);
objVP->recomputeFeature();
}
void TaskDimension::onTheoreticallyExactChanged()

View File

@@ -296,7 +296,7 @@ void TaskLeaderLine::recomputeFeature()
{
App::DocumentObject* objVP = m_lineVP->getObject();
assert(objVP);
objVP->getDocument()->recomputeFeature(objVP);
objVP->recomputeFeature();
}
void TaskLeaderLine::onStartSymbolChanged()