Core: Fixed a bug where an empty document disappears (#20554)
* Core: Fixed a bug where an empty document disappears Created a flag named autoCreated to distinguish an autoCreated document created in the startup from a manually document. Implemented a setter and a getter for this new flag. Added a codition that verifies if a document is autoCreated when opening another document to close it in the correct case. Implemented unit tests for theses cases. Fixes #19868. Signed-off-by: João Neves <joao.antonio.neves@tecnico.ulisboa.pt> * Tests: Fix failing auto-created document tests Signed-off-by: João Neves <joao.antonio.neves@tecnico.ulisboa.pt> * Tests: moved created tests to the existing Document test framework. Signed-off-by: João Neves <joao.antonio.neves@tecnico.ulisboa.pt> --------- Signed-off-by: João Neves <joao.antonio.neves@tecnico.ulisboa.pt>
This commit is contained in:
@@ -840,6 +840,7 @@ Document::Document(const char* documentName)
|
||||
// So, we must increment only if the interpreter gets a reference.
|
||||
// Remark: We force the document Python object to own the DocumentPy instance, thus we don't
|
||||
// have to care about ref counting any more.
|
||||
setAutoCreated(false);
|
||||
d = new DocumentP;
|
||||
Base::PyGILStateLocker lock;
|
||||
d->DocumentPythonObject = Py::Object(new DocumentPy(this), true);
|
||||
@@ -2505,6 +2506,14 @@ std::string Document::getFullName() const
|
||||
return myName;
|
||||
}
|
||||
|
||||
void Document::setAutoCreated(bool value) {
|
||||
autoCreated = value;
|
||||
}
|
||||
|
||||
bool Document::isAutoCreated() const {
|
||||
return autoCreated;
|
||||
}
|
||||
|
||||
const char* Document::getProgramVersion() const
|
||||
{
|
||||
return d->programVersion.c_str();
|
||||
|
||||
@@ -389,6 +389,10 @@ public:
|
||||
void setClosable(bool);
|
||||
/// check whether the document can be closed
|
||||
bool isClosable() const;
|
||||
/// set the document to autoCreated, this is off by default.
|
||||
void setAutoCreated(bool);
|
||||
/// check whether the document is autoCreated.
|
||||
bool isAutoCreated() const;
|
||||
/** Recompute touched features and return the number of recalculated features
|
||||
*
|
||||
* @param objs: specify a sub set of objects to recompute. If empty, then
|
||||
@@ -674,6 +678,7 @@ private:
|
||||
|
||||
std::string oldLabel;
|
||||
std::string myName;
|
||||
bool autoCreated; // Flag to know if the document was automatically created at startup
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
|
||||
@@ -314,6 +314,18 @@ class Document(PropertyContainer):
|
||||
"""
|
||||
...
|
||||
|
||||
def setAutoCreated(self, autoCreated: bool) -> None:
|
||||
"""
|
||||
Set a flag that indicates if a document is autoCreated
|
||||
"""
|
||||
...
|
||||
|
||||
def isAutoCreated(self) -> bool:
|
||||
"""
|
||||
Check if the document is autoCreated. The default value is False
|
||||
"""
|
||||
...
|
||||
|
||||
def recompute(self, objs: Sequence[DocumentObject] = None) -> int:
|
||||
"""
|
||||
recompute(objs=None): Recompute the document and returns the amount of recomputed features
|
||||
|
||||
@@ -660,6 +660,27 @@ PyObject* DocumentPy::isClosable(PyObject* args)
|
||||
return Py::new_reference_to(Py::Boolean(ok));
|
||||
}
|
||||
|
||||
PyObject *DocumentPy::setAutoCreated(PyObject *args)
|
||||
{
|
||||
PyObject *autoCreated;
|
||||
if (!PyArg_ParseTuple(args, "O!", &PyBool_Type, &autoCreated)) {
|
||||
return nullptr;
|
||||
}
|
||||
bool value = (autoCreated == Py_True);
|
||||
getDocumentPtr()->setAutoCreated(value);
|
||||
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
PyObject *DocumentPy::isAutoCreated(PyObject *args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, "")) {
|
||||
return nullptr;
|
||||
}
|
||||
bool ok = getDocumentPtr()->isAutoCreated();
|
||||
return Py::new_reference_to(Py::Boolean(ok));
|
||||
}
|
||||
|
||||
PyObject* DocumentPy::recompute(PyObject* args)
|
||||
{
|
||||
PyObject* pyobjs = Py_None;
|
||||
|
||||
@@ -631,7 +631,7 @@ void Application::open(const char* FileName, const char* Module)
|
||||
// in case of an automatically created empty document at startup
|
||||
App::Document* act = App::GetApplication().getActiveDocument();
|
||||
Gui::Document* gui = this->getDocument(act);
|
||||
if (act && act->countObjects() == 0 && gui && !gui->isModified()) {
|
||||
if (act && act->countObjects() == 0 && gui && !gui->isModified() && act->isAutoCreated()) {
|
||||
Command::doCommand(Command::App, "App.closeDocument('%s')", act->getName());
|
||||
qApp->processEvents(); // an update is needed otherwise the new view isn't shown
|
||||
}
|
||||
|
||||
@@ -1564,6 +1564,9 @@ void MainWindow::delayedStartup()
|
||||
if (hGrp->GetBool("CreateNewDoc", false)) {
|
||||
if (App::GetApplication().getDocuments().empty()){
|
||||
Application::Instance->commandManager().runCommandByName("Std_New");
|
||||
// This document is autoCreated
|
||||
App::Document* newDoc = App::GetApplication().getActiveDocument();
|
||||
newDoc->setAutoCreated(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2664,3 +2664,46 @@ class FeatureTestAttribute(unittest.TestCase):
|
||||
|
||||
def tearDown(self):
|
||||
FreeCAD.closeDocument("TestAttribute")
|
||||
|
||||
|
||||
class DocumentAutoCreatedCases(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.doc = FreeCAD.newDocument("TestDoc")
|
||||
|
||||
def tearDown(self):
|
||||
for doc_name in FreeCAD.listDocuments().keys():
|
||||
FreeCAD.closeDocument(doc_name)
|
||||
|
||||
def test_set_get_auto_created(self):
|
||||
self.doc.setAutoCreated(True)
|
||||
self.assertTrue(self.doc.isAutoCreated(), "autoCreated flag should be True")
|
||||
|
||||
self.doc.setAutoCreated(False)
|
||||
self.assertFalse(self.doc.isAutoCreated(), "autoCreated flag should be False")
|
||||
|
||||
def test_auto_created_document_closes_on_opening_existing_document(self):
|
||||
self.doc.setAutoCreated(True)
|
||||
self.assertEqual(len(self.doc.Objects), 0)
|
||||
saved_doc = FreeCAD.newDocument("SavedDoc")
|
||||
file_path = tempfile.gettempdir() + os.sep + "SavedDoc.FCStd"
|
||||
saved_doc.saveAs(file_path)
|
||||
FreeCAD.closeDocument("SavedDoc")
|
||||
FreeCAD.setActiveDocument("TestDoc")
|
||||
FreeCAD.open(file_path)
|
||||
if self.doc.isAutoCreated() and len(self.doc.Objects) == 0:
|
||||
FreeCAD.closeDocument("TestDoc")
|
||||
self.assertNotIn("TestDoc", FreeCAD.listDocuments())
|
||||
|
||||
def test_manual_document_does_not_close_on_opening_existing_document(self):
|
||||
self.assertFalse(self.doc.isAutoCreated())
|
||||
self.assertEqual(len(self.doc.Objects), 0)
|
||||
saved_doc = FreeCAD.newDocument("SavedDoc")
|
||||
file_path = tempfile.gettempdir() + os.sep + "SavedDoc.FCStd"
|
||||
saved_doc.saveAs(file_path)
|
||||
FreeCAD.closeDocument("SavedDoc")
|
||||
FreeCAD.setActiveDocument("TestDoc")
|
||||
FreeCAD.open(file_path)
|
||||
if self.doc.isAutoCreated() and len(self.doc.Objects) == 0:
|
||||
FreeCAD.closeDocument("TestDoc")
|
||||
self.assertIn("TestDoc", FreeCAD.listDocuments())
|
||||
self.assertIn("SavedDoc", FreeCAD.listDocuments())
|
||||
|
||||
Reference in New Issue
Block a user