Skip to content

Commit

Permalink
Gui: fix property editor crash on remove dynamic property
Browse files Browse the repository at this point in the history
The crash happens when the dynamic property is removed due changes of
the very same property.
  • Loading branch information
realthunder authored and wwmayer committed Mar 21, 2020
1 parent d441a9d commit 34c35f8
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 51 deletions.
95 changes: 45 additions & 50 deletions src/Gui/propertyeditor/PropertyItem.cpp
Expand Up @@ -395,38 +395,6 @@ void PropertyItem::setValue(const QVariant& /*value*/)
{
}

QString PropertyItem::pythonIdentifier(const App::Property* prop) const
{
App::PropertyContainer* parent = prop->getContainer();
QString propPrefix = QString::fromLatin1(parent->getPropertyPrefix());
if (parent->getTypeId() == App::Document::getClassTypeId()) {
App::Document* doc = static_cast<App::Document*>(parent);
QString docName = QString::fromLatin1(App::GetApplication().getDocumentName(doc));
QString propName = QString::fromLatin1(prop->getName());
return QString::fromLatin1("FreeCAD.getDocument(\"%1\").%3%2").arg(docName).arg(propName).arg(propPrefix);
}
if (parent->getTypeId().isDerivedFrom(App::DocumentObject::getClassTypeId())) {
App::DocumentObject* obj = static_cast<App::DocumentObject*>(parent);
App::Document* doc = obj->getDocument();
QString docName = QString::fromLatin1(App::GetApplication().getDocumentName(doc));
QString objName = QString::fromLatin1(obj->getNameInDocument());
QString propName = QString::fromLatin1(prop->getName());
return QString::fromLatin1("FreeCAD.getDocument(\"%1\").getObject(\"%2\").%4%3")
.arg(docName,objName,propName,propPrefix);
}
auto* vp = dynamic_cast<Gui::ViewProviderDocumentObject*>(parent);
if (vp) {
App::DocumentObject* obj = vp->getObject();
App::Document* doc = obj->getDocument();
QString docName = QString::fromLatin1(App::GetApplication().getDocumentName(doc));
QString objName = QString::fromLatin1(obj->getNameInDocument());
QString propName = QString::fromLatin1(prop->getName());
return QString::fromLatin1("FreeCADGui.getDocument(\"%1\").getObject(\"%2\").%4%3")
.arg(docName,objName,propName,propPrefix);
}
return QString();
}

QWidget* PropertyItem::createEditor(QWidget* /*parent*/, const QObject* /*receiver*/, const char* /*method*/) const
{
return 0;
Expand Down Expand Up @@ -502,25 +470,52 @@ void PropertyItem::setPropertyName(const QString& name)

void PropertyItem::setPropertyValue(const QString& value)
{
// Construct command for property assignment in one go, in case of any
// intermediate changes caused by property change that may potentially
// invalidate the current property array.
std::ostringstream ss;
for (std::vector<App::Property*>::const_iterator it = propertyItems.begin();
it != propertyItems.end(); ++it) {
App::PropertyContainer* parent = (*it)->getContainer();
if (parent && !parent->isReadOnly(*it) && !(*it)->testStatus(App::Property::ReadOnly)) {
QString cmd = QString::fromLatin1("%1 = %2").arg(pythonIdentifier(*it), value);
try {
Gui::Command::runCommand(Gui::Command::App, cmd.toUtf8());
}
catch (Base::PyException &e) {
e.ReportException();
Base::Console().Error("Stack Trace: %s\n",e.getStackTrace().c_str());
}
catch (Base::Exception &e) {
e.ReportException();
}
catch (...) {
Base::Console().Error("Unknown C++ exception in PropertyItem::setPropertyValue thrown\n");
}
}
it != propertyItems.end(); ++it)
{
auto prop = *it;
App::PropertyContainer* parent = prop->getContainer();
if (!parent || parent->isReadOnly(prop) || prop->testStatus(App::Property::ReadOnly))
continue;
if (parent->isDerivedFrom(App::Document::getClassTypeId())) {
App::Document* doc = static_cast<App::Document*>(parent);
ss << "FreeCAD.getDocument('" << doc->getName() << "').";
} else if (parent->isDerivedFrom(App::DocumentObject::getClassTypeId())) {
App::DocumentObject* obj = static_cast<App::DocumentObject*>(parent);
App::Document* doc = obj->getDocument();
ss << "FreeCAD.getDocument('" << doc->getName() << "').getObject('"
<< obj->getNameInDocument() << "').";
} else if (parent->isDerivedFrom(ViewProviderDocumentObject::getClassTypeId())) {
App::DocumentObject* obj = static_cast<ViewProviderDocumentObject*>(parent)->getObject();
App::Document* doc = obj->getDocument();
ss << "FreeCADGui.getDocument('" << doc->getName() << "').getObject('"
<< obj->getNameInDocument() << "').";
} else
continue;
ss << parent->getPropertyPrefix() << prop->getName()
<< " = " << value.toLatin1().constData() << '\n';
}

std::string cmd = ss.str();
if(cmd.empty())
return;

try {
Gui::Command::runCommand(Gui::Command::App, cmd.c_str());
}
catch (Base::PyException &e) {
e.ReportException();
Base::Console().Error("Stack Trace: %s\n",e.getStackTrace().c_str());
}
catch (Base::Exception &e) {
e.ReportException();
}
catch (...) {
Base::Console().Error("Unknown C++ exception in PropertyItem::setPropertyValue thrown\n");
}
}

Expand Down
1 change: 0 additions & 1 deletion src/Gui/propertyeditor/PropertyItem.h
Expand Up @@ -182,7 +182,6 @@ class GuiExport PropertyItem : public QObject, public ExpressionBinding
virtual QVariant value(const App::Property*) const;
virtual void setValue(const QVariant&);
virtual void initialize();
QString pythonIdentifier(const App::Property*) const;

//gets called when the bound expression is changed
virtual void onChange();
Expand Down

0 comments on commit 34c35f8

Please sign in to comment.