Added check in Tree.cpp DocumentItem::slotChangeObject to check for invalid pointers returned by claimChildren()

This commit is contained in:
jrheinlaender 2013-04-17 19:49:55 +04:30 committed by Stefan Tröger
parent 4f80b72508
commit efd33c8465
3 changed files with 37 additions and 19 deletions

View File

@ -2294,6 +2294,16 @@ DocumentObject * Document::getObject(const char *Name) const
return 0;
}
// Note: This method is only used in Tree.cpp slotChangeObject(), see explanation there
const bool Document::isIn(const DocumentObject *pFeat) const
{
for (std::map<std::string,DocumentObject*>::const_iterator o = d->objectMap.begin(); o != d->objectMap.end(); o++)
if (o->second == pFeat)
return true;
return false;
}
const char * Document::getObjectName(DocumentObject *pFeat) const
{
std::map<std::string,DocumentObject*>::const_iterator pos;

View File

@ -192,6 +192,8 @@ public:
DocumentObject *getActiveObject(void) const;
/// Returns a Object of this document
DocumentObject *getObject(const char *Name) const;
/// Returns true if the DocumentObject is contained in this document
const bool isIn(const DocumentObject *pFeat) const;
/// Returns a Name of an Object or 0
const char *getObjectName(DocumentObject *pFeat) const;
/// Returns a Name of an Object or 0

View File

@ -943,25 +943,31 @@ void DocumentItem::slotChangeObject(const Gui::ViewProviderDocumentObject& view)
std::string objectName = obj->getNameInDocument();
std::map<std::string, DocumentObjectItem*>::iterator it = ObjectMap.find(objectName);
if (it != ObjectMap.end()) {
// use new grouping style
std::set<QTreeWidgetItem*> children;
std::vector<App::DocumentObject*> group = view.claimChildren();
for (std::vector<App::DocumentObject*>::iterator jt = group.begin(); jt != group.end(); ++jt) {
if (*jt) {
const char* internalName = (*jt)->getNameInDocument();
if (internalName) {
std::map<std::string, DocumentObjectItem*>::iterator kt = ObjectMap.find(internalName);
if (kt != ObjectMap.end()) {
children.insert(kt->second);
QTreeWidgetItem* parent = kt->second->parent();
if (parent && parent != it->second) {
if (it->second != kt->second) {
int index = parent->indexOfChild(kt->second);
parent->takeChild(index);
it->second->addChild(kt->second);
}
else {
Base::Console().Warning("Gui::DocumentItem::slotChangedObject(): Object references to itself.\n");
// use new grouping style
std::set<QTreeWidgetItem*> children;
std::vector<App::DocumentObject*> group = view.claimChildren();
for (std::vector<App::DocumentObject*>::iterator jt = group.begin(); jt != group.end(); ++jt) {
if ((*jt) && view.getObject()->getDocument()->isIn(*jt)){
// Note: It is possible that we receive an invalid pointer from claimChildren(), e.g. if multiple properties
// were changed in a transaction and slotChangedObject() is triggered by one property being reset
// before the invalid pointer has been removed from another. Currently this happens for PartDesign::Body
// when cancelling a new feature in the dialog. First the new feature is deleted, then the Tip property is
// reset, but claimChildren() accesses the Model property which still contains the pointer to the deleted feature
const char* internalName = (*jt)->getNameInDocument();
if (internalName) {
std::map<std::string, DocumentObjectItem*>::iterator kt = ObjectMap.find(internalName);
if (kt != ObjectMap.end()) {
children.insert(kt->second);
QTreeWidgetItem* parent = kt->second->parent();
if (parent && parent != it->second) {
if (it->second != kt->second) {
int index = parent->indexOfChild(kt->second);
parent->takeChild(index);
it->second->addChild(kt->second);
}
else {
Base::Console().Warning("Gui::DocumentItem::slotChangedObject(): Object references to itself.\n");
}
}
}
}