App: Provide temporary document creation flag to Python App.loadDocument.

This commit is contained in:
tritao
2025-01-19 16:05:29 +00:00
committed by Chris Hennes
parent 299123b9de
commit ff8e99f385
6 changed files with 57 additions and 35 deletions

View File

@@ -453,7 +453,7 @@ void Application::renameDocument(const char *OldName, const char *NewName)
throw Base::RuntimeError("Renaming document internal name is no longer allowed!");
}
Document* Application::newDocument(const char * Name, const char * UserName, bool createView, bool tempDoc)
Document* Application::newDocument(const char * Name, const char * UserName, DocumentCreateFlags CreateFlags)
{
auto getNameAndLabel = [this](const char * Name, const char * UserName) -> std::tuple<std::string, std::string> {
bool defaultName = (!Name || Name[0] == '\0');
@@ -487,10 +487,10 @@ Document* Application::newDocument(const char * Name, const char * UserName, boo
auto tuple = getNameAndLabel(Name, UserName);
std::string name = std::get<0>(tuple);
std::string userName = std::get<1>(tuple);
name = getUniqueDocumentName(name.c_str(), tempDoc);
name = getUniqueDocumentName(name.c_str(), CreateFlags.temporary);
// return the temporary document if it exists
if (tempDoc) {
if (CreateFlags.temporary) {
auto it = DocMap.find(name);
if (it != DocMap.end() && it->second->testStatus(Document::TempDoc))
return it->second;
@@ -498,7 +498,7 @@ Document* Application::newDocument(const char * Name, const char * UserName, boo
// create the FreeCAD document
std::unique_ptr<Document> newDoc(new Document(name.c_str()));
newDoc->setStatus(Document::TempDoc, tempDoc);
newDoc->setStatus(Document::TempDoc, CreateFlags.temporary);
auto oldActiveDoc = _pActiveDoc;
auto doc = newDoc.release(); // now owned by the Application
@@ -539,13 +539,13 @@ Document* Application::newDocument(const char * Name, const char * UserName, boo
Py::Module("FreeCAD").setAttr(std::string("ActiveDocument"), active);
}
signalNewDocument(*_pActiveDoc, createView);
signalNewDocument(*_pActiveDoc, CreateFlags.createView);
// set the UserName after notifying all observers
_pActiveDoc->Label.setValue(userName);
// set the old document active again if the new is temporary
if (tempDoc && oldActiveDoc)
if (CreateFlags.temporary && oldActiveDoc)
setActiveDocument(oldActiveDoc);
return doc;
@@ -701,9 +701,9 @@ public:
}
};
Document* Application::openDocument(const char * FileName, bool createView) {
Document* Application::openDocument(const char * FileName, DocumentCreateFlags createFlags) {
std::vector<std::string> filenames(1,FileName);
auto docs = openDocuments(filenames, nullptr, nullptr, nullptr, createView);
auto docs = openDocuments(filenames, nullptr, nullptr, nullptr, createFlags);
if(!docs.empty())
return docs.front();
return nullptr;
@@ -748,7 +748,7 @@ std::vector<Document*> Application::openDocuments(const std::vector<std::string>
const std::vector<std::string> *paths,
const std::vector<std::string> *labels,
std::vector<std::string> *errs,
bool createView)
DocumentCreateFlags createFlags)
{
std::vector<Document*> res(filenames.size(), nullptr);
if (filenames.empty())
@@ -812,7 +812,7 @@ std::vector<Document*> Application::openDocuments(const std::vector<std::string>
label = (*labels)[count].c_str();
}
auto doc = openDocumentPrivate(path, name.c_str(), label, isMainDoc, createView, std::move(objNames));
auto doc = openDocumentPrivate(path, name.c_str(), label, isMainDoc, createFlags, std::move(objNames));
FC_DURATION_PLUS(timing.d1,t1);
if (doc) {
timings[doc].d1 += timing.d1;
@@ -951,7 +951,7 @@ std::vector<Document*> Application::openDocuments(const std::vector<std::string>
Document* Application::openDocumentPrivate(const char * FileName,
const char *propFileName, const char *label,
bool isMainDoc, bool createView,
bool isMainDoc, DocumentCreateFlags createFlags,
std::vector<std::string> &&objNames)
{
FileInfo File(FileName);
@@ -1022,8 +1022,8 @@ Document* Application::openDocumentPrivate(const char * FileName,
// to only contain valid ASCII characters but the user name will be kept.
if(!label)
label = name.c_str();
Document* newDoc = newDocument(name.c_str(),label,isMainDoc && createView);
Document* newDoc = newDocument(name.c_str(), label, createFlags);
newDoc->FileName.setValue(propFileName==FileName?File.filePath():propFileName);
try {

View File

@@ -69,6 +69,10 @@ enum class MessageOption {
Throw, /**< Throw an exception. */
};
struct DocumentCreateFlags {
bool createView {true};
bool temporary {false};
};
/** The Application
* The root of the whole application
@@ -94,13 +98,13 @@ public:
* the user and stored in the App::Document::Name property.
*/
App::Document* newDocument(const char * Name=nullptr, const char * UserName=nullptr,
bool createView=true, bool tempDoc=false);
DocumentCreateFlags CreateFlags=DocumentCreateFlags());
/// Closes the document \a name and removes it from the application.
bool closeDocument(const char* name);
/// find a unique document name
std::string getUniqueDocumentName(const char *Name, bool tempDoc=false) const;
/// Open an existing document from a file
App::Document* openDocument(const char * FileName=nullptr, bool createView=true);
App::Document* openDocument(const char * FileName=nullptr, DocumentCreateFlags createFlags = DocumentCreateFlags{});
/** Open multiple documents
*
* @param filenames: input file names
@@ -122,7 +126,7 @@ public:
const std::vector<std::string> *paths=nullptr,
const std::vector<std::string> *labels=nullptr,
std::vector<std::string> *errs=nullptr,
bool createView = true);
DocumentCreateFlags createFlags = DocumentCreateFlags{});
/// Retrieve the active document
App::Document* getActiveDocument() const;
/// Retrieve a named document
@@ -486,7 +490,7 @@ protected:
/// open single document only
App::Document* openDocumentPrivate(const char * FileName, const char *propFileName,
const char *label, bool isMainDoc, bool createView, std::vector<std::string> &&objNames);
const char *label, bool isMainDoc, DocumentCreateFlags createFlags, std::vector<std::string> &&objNames);
/// Helper class for App::Document to signal on close/abort transaction
class AppExport TransactionSignaller {

View File

@@ -149,12 +149,13 @@ PyMethodDef Application::Methods[] = {
{"openDocument",
reinterpret_cast<PyCFunction>(reinterpret_cast<void (*)()>(Application::sOpenDocument)),
METH_VARARGS | METH_KEYWORDS,
"openDocument(filepath,hidden=False) -> object\n"
"openDocument(filepath,hidden=False,temporary=False) -> object\n"
"Create a document and load the project file into the document.\n\n"
"filepath: file path to an existing file. If the file doesn't exist\n"
" or the file cannot be loaded an I/O exception is thrown.\n"
" In this case the document is kept alive.\n"
"hidden: whether to hide document 3D view."},
"hidden: whether to hide document 3D view.\n"
"temporary: whether to hide document in the tree view."},
// {"saveDocument", (PyCFunction) Application::sSaveDocument, METH_VARARGS,
// "saveDocument(string) -- Save the document to a file."},
// {"saveDocumentAs", (PyCFunction) Application::sSaveDocumentAs, METH_VARARGS},
@@ -339,23 +340,30 @@ PyObject* Application::sOpenDocument(PyObject* /*self*/, PyObject* args, PyObjec
{
char* Name;
PyObject* hidden = Py_False;
static const std::array<const char*, 3> kwlist {"name", "hidden", nullptr};
PyObject* temporary = Py_False;
static const std::array<const char*, 4> kwlist {"name", "hidden", "temporary", nullptr};
if (!Base::Wrapped_ParseTupleAndKeywords(args,
kwd,
"et|O!",
"et|O!O!",
kwlist,
"utf-8",
&Name,
&PyBool_Type,
&hidden)) {
&hidden,
&PyBool_Type,
&temporary)) {
return nullptr;
}
std::string EncodedName = std::string(Name);
PyMem_Free(Name);
try {
DocumentCreateFlags createFlags;
createFlags.createView = !Base::asBoolean(hidden);
createFlags.temporary = Base::asBoolean(temporary);
// return new document
return (GetApplication()
.openDocument(EncodedName.c_str(), !Base::asBoolean(hidden))
.openDocument(EncodedName.c_str(), createFlags)
->getPyObject());
}
catch (const Base::Exception& e) {
@@ -393,11 +401,13 @@ PyObject* Application::sNewDocument(PyObject* /*self*/, PyObject* args, PyObject
PY_TRY
{
DocumentCreateFlags createFlags;
createFlags.createView = !Base::asBoolean(hidden);
createFlags.temporary = Base::asBoolean(temp);
App::Document* doc = GetApplication().newDocument(docName,
usrName,
!Base::asBoolean(hidden),
Base::asBoolean(temp));
PyMem_Free(docName);
createFlags);
PyMem_Free(usrName);
return doc->getPyObject();
}

View File

@@ -2562,7 +2562,9 @@ App::Document* Application::reopen(App::Document* doc)
}
for (auto& file : docs) {
App::GetApplication().openDocument(file.c_str(), false);
App::DocumentCreateFlags createFlags;
createFlags.createView = false;
App::GetApplication().openDocument(file.c_str(), createFlags);
}
}

View File

@@ -411,7 +411,10 @@ App::Document* ImportOCAF2::getDocument(App::Document* doc, TDF_Label label)
return doc;
}
auto newDoc = App::GetApplication().newDocument(name.c_str(), name.c_str(), false);
App::DocumentCreateFlags createFlags;
createFlags.createView = false;
auto newDoc = App::GetApplication().newDocument(name.c_str(), name.c_str(), createFlags);
std::ostringstream ss;
Base::FileInfo fi(doc->FileName.getValue());
std::string path = fi.dirPath();

View File

@@ -597,8 +597,11 @@ void SubShapeBinder::update(SubShapeBinder::UpdateOption options) {
recomputeCopy = true;
clearCopiedObjects();
auto tmpDoc = App::GetApplication().newDocument(
"_tmp_binder", nullptr, false, true);
App::DocumentCreateFlags createFlags;
createFlags.createView = false;
createFlags.temporary = true;
auto tmpDoc = App::GetApplication().newDocument("_tmp_binder", nullptr, createFlags);
tmpDoc->setUndoMode(0);
auto objs = tmpDoc->copyObject({ obj }, true, true);
if (!objs.empty()) {
@@ -618,21 +621,21 @@ void SubShapeBinder::update(SubShapeBinder::UpdateOption options) {
std::vector<App::Property*> props;
getPropertyList(props);
// lambda for copying values of copy-on-change properties
const auto copyPropertyValues = [this, &recomputeCopy, &props, copied](const bool to_support) {
const auto copyPropertyValues = [this, &recomputeCopy, &props, copied](const bool to_support) {
for (auto prop : props) {
if (!App::LinkBaseExtension::isCopyOnChangeProperty(this, *prop))
continue;
// we only copy read-only and output properties from support to binder
if (!to_support && !(prop->testStatus(App::Property::Output) && prop->testStatus(App::Property::ReadOnly)))
continue;
// we only copy read-only and output properties from support to binder
if (!to_support && !(prop->testStatus(App::Property::Output) && prop->testStatus(App::Property::ReadOnly)))
continue;
auto p = copied->getPropertyByName(prop->getName());
if (p && p->getContainer() == copied
&& p->getTypeId() == prop->getTypeId()
&& !p->isSame(*prop))
{
recomputeCopy = true;
auto* const from = to_support ? prop : p;
auto* const to = to_support ? p : prop;
auto* const from = to_support ? prop : p;
auto* const to = to_support ? p : prop;
std::unique_ptr<App::Property> pcopy(from->Copy());
to->Paste(*pcopy);