App: fix external document loading

The problem happens when partial loading is enabled. If document A
contains a link to some object in document B, it will load B as partial
document with only that object and its necessary dependencies. But if
document A contains another link to some object in document C which also
has a link to some object in document B, the link in document C may not
be restored, because document B is partially loaded without the linked
object. This patch will check for this case and reload document B for
more objects.

See an example reported in
https://forum.freecadweb.org/viewtopic.php?p=495078#p495078
This commit is contained in:
Zheng, Lei
2021-08-02 11:38:01 +08:00
parent 414ea71a28
commit fc9d3547ad
7 changed files with 311 additions and 166 deletions

View File

@@ -1866,7 +1866,6 @@ void Document::exportObjects(const std::vector<App::DocumentObject*>& obj, std::
#define FC_ELEMENT_OBJECT_DEPS "ObjectDeps"
#define FC_ATTR_DEP_COUNT "Count"
#define FC_ATTR_DEP_OBJ_NAME "Name"
#define FC_ATTR_DEP_COUNT "Count"
#define FC_ATTR_DEP_ALLOW_PARTIAL "AllowPartial"
#define FC_ELEMENT_OBJECT_DEP "Dep"
@@ -2693,7 +2692,7 @@ bool Document::isAnyRestoring() {
// Open the document
void Document::restore (const char *filename,
bool delaySignal, const std::set<std::string> &objNames)
bool delaySignal, const std::vector<std::string> &objNames)
{
clearUndos();
d->activeObject = 0;
@@ -2752,8 +2751,7 @@ void Document::restore (const char *filename,
d->partialLoadObjects.emplace(name,true);
try {
Document::Restore(reader);
}
catch (const Base::Exception& e) {
} catch (const Base::Exception& e) {
Base::Console().Error("Invalid Document.xml: %s\n", e.what());
setStatus(Document::RestoreError, true);
}
@@ -2777,15 +2775,16 @@ void Document::restore (const char *filename,
afterRestore(true);
}
void Document::afterRestore(bool checkPartial) {
bool Document::afterRestore(bool checkPartial) {
Base::FlagToggler<> flag(_IsRestoring,false);
if(!afterRestore(d->objectArray,checkPartial)) {
FC_WARN("Reload partial document " << getName());
restore();
return;
GetApplication().signalPendingReloadDocument(*this);
return false;
}
GetApplication().signalFinishRestoreDocument(*this);
setStatus(Document::Restoring, false);
return true;
}
bool Document::afterRestore(const std::vector<DocumentObject *> &objArray, bool checkPartial)
@@ -2861,9 +2860,12 @@ bool Document::afterRestore(const std::vector<DocumentObject *> &objArray, bool
std::string errMsg;
if(link && (res=link->checkRestore(&errMsg))) {
d->touchedObjs.insert(obj);
if(res==1)
if(res==1 || checkPartial) {
FC_WARN(obj->getFullName() << '.' << prop->getName() << ": " << errMsg);
else {
setStatus(Document::LinkStampChanged, true);
if(checkPartial)
return false;
} else {
FC_ERR(obj->getFullName() << '.' << prop->getName() << ": " << errMsg);
d->addRecomputeLog(errMsg,obj);
setStatus(Document::PartialRestore, true);