From 6c9ad95a70bf60242826739c84579c62025d4a24 Mon Sep 17 00:00:00 2001 From: wmayer Date: Tue, 11 Mar 2025 00:16:37 +0100 Subject: [PATCH 1/6] App: Improve handling with freeze status * Do not raise an exception when saving a document and an object has 'freeze' status because this breaks the project file and may lead to loss of data. * Make 'freeze' state persistent * When toggling 'freeze' status only work directly on the selection. Do not use in-list or out-list of an object because this makes it quite inflexible and leads to unpredictable behaviour. This fixes issue with saving frozen files described in 18806. --- src/App/Document.cpp | 8 ++++++++ src/App/DocumentObject.cpp | 6 +----- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/App/Document.cpp b/src/App/Document.cpp index 14d2c51c58..b95e2c21b2 100644 --- a/src/App/Document.cpp +++ b/src/App/Document.cpp @@ -1317,6 +1317,9 @@ void Document::writeObjects(const std::vector& objs, writer.Stream() << "Error=\"" << Property::encodeAttribute(desc) << "\" "; } } + if ((*it)->isFreezed()) { + writer.Stream() << "Freeze=\"1\" "; + } writer.Stream() << "/>" << '\n'; } @@ -1514,6 +1517,11 @@ std::vector Document::readObjects(Base::XMLReader& reader) d->addRecomputeLog(reader.getAttribute("Error"), obj); } } + if (reader.hasAttribute("Freeze")) { + if (reader.getAttribute("Freeze") != 0) { + obj->freeze(); + } + } } } catch (const Base::Exception& e) { diff --git a/src/App/DocumentObject.cpp b/src/App/DocumentObject.cpp index fcecdf15f0..ed30d9db83 100644 --- a/src/App/DocumentObject.cpp +++ b/src/App/DocumentObject.cpp @@ -1170,11 +1170,7 @@ DocumentObject* DocumentObject::getLinkedObject(bool recursive, void DocumentObject::Save(Base::Writer& writer) const { - if (this->isFreezed()) { - throw Base::AbortException("At least one object is frozen, unable to save."); - } - - if (this->isAttachedToDocument()){ + if (this->isAttachedToDocument()) { writer.ObjectName = this->getNameInDocument(); } App::ExtensionContainer::Save(writer); From 2c2cdbfe7f94735a377c06f98389f507aed0d8c1 Mon Sep 17 00:00:00 2001 From: wmayer Date: Wed, 12 Mar 2025 16:31:42 +0100 Subject: [PATCH 2/6] App: Refactor Document::writeObjects --- src/App/Document.cpp | 182 ++++++++++++++++++++++++------------------- src/App/Document.h | 4 + 2 files changed, 107 insertions(+), 79 deletions(-) diff --git a/src/App/Document.cpp b/src/App/Document.cpp index b95e2c21b2..2d2bfa940e 100644 --- a/src/App/Document.cpp +++ b/src/App/Document.cpp @@ -93,7 +93,6 @@ using Base::Console; using Base::streq; using Base::Writer; using namespace App; -using namespace std; using namespace boost; using namespace zipios; @@ -1251,98 +1250,123 @@ constexpr auto fcAttrDepObjName {"Name"}; constexpr auto fcAttrDepAllowPartial {"AllowPartial"}; constexpr auto fcElementObjectDep {"Dep"}; -void Document::writeObjects(const std::vector& objs, - Base::Writer& writer) const +void Document::writeObjectDeps(const std::vector& objs, + Base::Writer& writer) const { - // writing the features types - writer.incInd(); // indentation for 'Objects count' - writer.Stream() << writer.ind() << "" << '\n'; + for (auto o : objs) { + // clang-format off + const auto& outList = o->getOutList(DocumentObject::OutListNoHidden | + DocumentObject::OutListNoXLinked); + // clang-format on - writer.incInd(); // indentation for 'Object type' - - if (isExporting(nullptr) == 0U) { - for (const auto o : objs) { - const auto& outList = - o->getOutList(DocumentObject::OutListNoHidden | DocumentObject::OutListNoXLinked); - writer.Stream() << writer.ind() - << "<" << fcElementObjectDeps << " " << fcAttrDepObjName << "=\"" - << o->getNameInDocument() << "\" " << fcAttrDepCount << "=\"" - << outList.size(); - if (outList.empty()) { - writer.Stream() << "\"/>" << '\n'; - continue; - } - const int partial = o->canLoadPartial(); - if (partial > 0) { - writer.Stream() << "\" " << fcAttrDepAllowPartial << "=\"" << partial; - } - writer.Stream() << "\">" << '\n'; - writer.incInd(); - for (const auto dep : outList) { - const auto name = dep ? dep->getNameInDocument() : ""; - writer.Stream() << writer.ind() - << "<" << fcElementObjectDep << " " << fcAttrDepObjName << "=\"" - << (name ? name : "") << "\"/>" << '\n'; - } - writer.decInd(); - writer.Stream() << writer.ind() << "" << '\n'; + writer.Stream() << writer.ind() + << "<" << fcElementObjectDeps + << " " << fcAttrDepObjName << "=\"" + << o->getNameInDocument() << "\" " + << fcAttrDepCount << "=\"" + << outList.size(); + if (outList.empty()) { + writer.Stream() << "\"/>\n"; + continue; } + int partial = o->canLoadPartial(); + if (partial > 0) { + writer.Stream() << "\" " << fcAttrDepAllowPartial << "=\"" << partial; + } + writer.Stream() << "\">\n"; + writer.incInd(); + for (auto dep : outList) { + auto name = dep ? dep->getNameInDocument() : ""; + writer.Stream() << writer.ind() + << "<" << fcElementObjectDep + << " " << fcAttrDepObjName << "=\"" + << (name ? name : "") << "\"/>\n"; + } + writer.decInd(); + writer.Stream() << writer.ind() << "\n"; } +} - std::vector::const_iterator it; - for (it = objs.begin(); it != objs.end(); ++it) { +void Document::writeObjectType(const std::vector& objs, + Base::Writer& writer) const +{ + for (auto it : objs) { writer.Stream() << writer.ind() << "getTypeId().getName() << "\" " - << "name=\"" << (*it)->getExportName() << "\" " - << "id=\"" << (*it)->getID() << "\" "; + << "type=\"" << it->getTypeId().getName() << "\" " + << "name=\"" << it->getExportName() << "\" " + << "id=\"" << it->getID() << "\" "; // Only write out custom view provider types - std::string viewType = (*it)->getViewProviderNameStored(); - if (viewType != (*it)->getViewProviderName()) { + std::string viewType = it->getViewProviderNameStored(); + if (viewType != it->getViewProviderName()) { writer.Stream() << "ViewType=\"" << viewType << "\" "; } // See DocumentObjectPy::getState - if ((*it)->testStatus(ObjectStatus::Touch)) { + if (it->testStatus(ObjectStatus::Touch)) { writer.Stream() << "Touched=\"1\" "; } - if ((*it)->testStatus(ObjectStatus::Error)) { + if (it->testStatus(ObjectStatus::Error)) { writer.Stream() << "Invalid=\"1\" "; - const auto desc = getErrorDescription(*it); + auto desc = getErrorDescription(it); if (desc) { writer.Stream() << "Error=\"" << Property::encodeAttribute(desc) << "\" "; } } - if ((*it)->isFreezed()) { + if (it->isFreezed()) { writer.Stream() << "Freeze=\"1\" "; } - writer.Stream() << "/>" << '\n'; + writer.Stream() << "/>\n"; } +} - writer.decInd(); // indentation for 'Object type' - writer.Stream() << writer.ind() << "" << '\n'; - +void Document::writeObjectData(const std::vector& objs, + Base::Writer& writer) const +{ // writing the features itself - writer.Stream() << writer.ind() << "" << '\n'; + writer.Stream() << writer.ind() << "\n"; writer.incInd(); // indentation for 'Object name' - for (it = objs.begin(); it != objs.end(); ++it) { - writer.Stream() << writer.ind() << "getExportName() << "\""; - if ((*it)->hasExtensions()) { + for (auto it : objs) { + writer.Stream() << writer.ind() << "getExportName() << "\""; + if (it->hasExtensions()) { writer.Stream() << " Extensions=\"True\""; } - writer.Stream() << ">" << '\n'; - (*it)->Save(writer); - writer.Stream() << writer.ind() << "" << '\n'; + writer.Stream() << ">\n"; + it->Save(writer); + writer.Stream() << writer.ind() << "\n"; + } + writer.decInd(); // indentation for 'Object name' + + writer.Stream() << writer.ind() << "\n"; +} + +void Document::writeObjects(const std::vector& objs, + Base::Writer& writer) const +{ + std::ostream& str = writer.Stream(); + + // writing the features types + writer.incInd(); // indentation for 'Objects count' + str << writer.ind() << "\n"; + + writer.incInd(); // indentation for 'Object type' + + if (!isExporting(nullptr)) { + writeObjectDeps(objs, writer); } - writer.decInd(); // indentation for 'Object name' - writer.Stream() << writer.ind() << "" << '\n'; + writeObjectType(objs, writer); + + writer.decInd(); // indentation for 'Object type' + str << writer.ind() << "\n"; + + writeObjectData(objs, writer); writer.decInd(); // indentation for 'Objects count' } @@ -2824,10 +2848,10 @@ int Document::recompute(const std::vector& objs, std::vector DocumentP::partialTopologicalSort(const std::vector& objects) { - vector ret; + std::vector ret; ret.reserve(objects.size()); // pairs of input and output degree - map> countMap; + std::map> countMap; for (auto objectIt : objects) { // we need inlist with unique entries @@ -2853,7 +2877,7 @@ DocumentP::partialTopologicalSort(const std::vector& objects) // try input degree auto degInIt = find_if(countMap.begin(), countMap.end(), - [](pair> vertex) -> bool { + [](std::pair> vertex) -> bool { return vertex.second.first == 0; }); @@ -2888,11 +2912,11 @@ DocumentP::partialTopologicalSort(const std::vector& objects) while (removeVertex) { removeVertex = false; - auto degOutIt = find_if(countMap.begin(), - countMap.end(), - [](pair> vertex) -> bool { - return vertex.second.second == 0; - }); + auto degOutIt = std::find_if(countMap.begin(), + countMap.end(), + [](std::pair> vertex) -> bool { + return vertex.second.second == 0; + }); if (degOutIt != countMap.end()) { removeVertex = true; @@ -2931,9 +2955,9 @@ DocumentP::topologicalSort(const std::vector& objects) const { // topological sort algorithm described here: // https://de.wikipedia.org/wiki/Topologische_Sortierung#Algorithmus_f.C3.BCr_das_Topologische_Sortieren - vector ret; + std::vector ret; ret.reserve(objects.size()); - map countMap; + std::map countMap; for (auto objectIt : objects) { // We now support externally linked objects @@ -2949,14 +2973,14 @@ DocumentP::topologicalSort(const std::vector& objects) const countMap[objectIt] = in.size(); } - auto rootObjeIt = find_if(countMap.begin(), - countMap.end(), - [](pair count) -> bool { - return count.second == 0; - }); + auto rootObjeIt = std::find_if(countMap.begin(), + countMap.end(), + [](std::pair count) -> bool { + return count.second == 0; + }); if (rootObjeIt == countMap.end()) { - cerr << "Document::topologicalSort: cyclic dependency detected (no root object)" << '\n'; + std::cerr << "Document::topologicalSort: cyclic dependency detected (no root object)" << '\n'; return ret; } @@ -2978,7 +3002,7 @@ DocumentP::topologicalSort(const std::vector& objects) const rootObjeIt = find_if(countMap.begin(), countMap.end(), - [](pair count) -> bool { + [](std::pair count) -> bool { return count.second == 0; }); } diff --git a/src/App/Document.h b/src/App/Document.h index 7347ff7513..8dd59b3023 100644 --- a/src/App/Document.h +++ b/src/App/Document.h @@ -1329,6 +1329,10 @@ protected: */ void writeObjects(const std::vector& objs, Base::Writer& writer) const; + void writeObjectDeps(const std::vector& objs, Base::Writer& writer) const; + void writeObjectType(const std::vector& objs, Base::Writer& writer) const; + void writeObjectData(const std::vector& objs, Base::Writer& writer) const; + /** * @brief Save the document to a file. * From 2c3d9e2bb702d35c8c0fe688f69682f614fb09f7 Mon Sep 17 00:00:00 2001 From: wmayer Date: Wed, 12 Mar 2025 18:47:50 +0100 Subject: [PATCH 3/6] Base: Add C++ iostate methods to Writer class --- src/Base/Writer.cpp | 25 +++++++++++++++++++++++++ src/Base/Writer.h | 28 ++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/src/Base/Writer.cpp b/src/Base/Writer.cpp index cd1126e945..90f0445891 100644 --- a/src/Base/Writer.cpp +++ b/src/Base/Writer.cpp @@ -92,6 +92,31 @@ Writer::Writer() Writer::~Writer() = default; +void Writer::clear() +{ + Stream().clear(); +} + +bool Writer::isGood() const +{ + return Stream().good(); +} + +bool Writer::hasFailed() const +{ + return Stream().fail(); +} + +bool Writer::isBad() const +{ + return Stream().bad(); +} + +bool Writer::isEof() const +{ + return Stream().eof(); +} + std::ostream& Writer::beginCharStream(CharStreamFormat format) { if (CharStream) { diff --git a/src/Base/Writer.h b/src/Base/Writer.h index 9ae1031f7b..9fb6823f1c 100644 --- a/src/Base/Writer.h +++ b/src/Base/Writer.h @@ -136,7 +136,22 @@ public: void decInd(); //@} + /** @name C++ streams */ + //@{ + /// get the current indentation virtual std::ostream& Stream() = 0; + virtual const std::ostream& Stream() const = 0; + /// Set error state flags + void clear(); + /// Check whether state of stream is good + bool isGood() const; + /// Check whether either failbit or badbit is set + bool hasFailed() const; + /// Check whether badbit is set + bool isBad() const; + /// Check whether eofbit is set + bool isEof() const; + //@} /** Create an output stream for storing character content * The input is assumed to be valid character with @@ -215,6 +230,11 @@ public: return ZipStream; } + const std::ostream& Stream() const override + { + return ZipStream; + } + void setComment(const char* str) { ZipStream.setComment(str); @@ -248,6 +268,10 @@ public: { return StrStream; } + const std::ostream& Stream() const override + { + return StrStream; + } std::string getString() const { return StrStream.str(); @@ -277,6 +301,10 @@ public: { return FileStream; } + const std::ostream& Stream() const override + { + return FileStream; + } void close() { FileStream.close(); From c97f6e5b3f29d9a4f698686ea63067596cf29236 Mon Sep 17 00:00:00 2001 From: wmayer Date: Wed, 12 Mar 2025 19:01:19 +0100 Subject: [PATCH 4/6] App: Improve Document::writeObjects Do not directly pass getNameInDocument() to the ostream as this will set the badbit in case it returns nullptr. As a result no further output is written to the stream and leads to loss of data. Instead the returned C string is stored in a local variable and in case it's nullptr an empty string is passed to the ostream. At the end of the function writeObjects() it's checked whether the failbit or badbit is set. If yes an error message is printed and the failbit or badbit are cleared. This is supposed to fix the issue 18044. In case this fix is not sufficient it can be also check for every object inside writeObjectData() --- src/App/Document.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/App/Document.cpp b/src/App/Document.cpp index 2d2bfa940e..fe186f3c41 100644 --- a/src/App/Document.cpp +++ b/src/App/Document.cpp @@ -1259,10 +1259,11 @@ void Document::writeObjectDeps(const std::vector& objs, DocumentObject::OutListNoXLinked); // clang-format on + auto objName = o->getNameInDocument(); writer.Stream() << writer.ind() << "<" << fcElementObjectDeps << " " << fcAttrDepObjName << "=\"" - << o->getNameInDocument() << "\" " + << (objName ? objName : "") << "\" " << fcAttrDepCount << "=\"" << outList.size(); if (outList.empty()) { @@ -1276,11 +1277,11 @@ void Document::writeObjectDeps(const std::vector& objs, writer.Stream() << "\">\n"; writer.incInd(); for (auto dep : outList) { - auto name = dep ? dep->getNameInDocument() : ""; + auto depName = dep ? dep->getNameInDocument() : ""; writer.Stream() << writer.ind() << "<" << fcElementObjectDep << " " << fcAttrDepObjName << "=\"" - << (name ? name : "") << "\"/>\n"; + << (depName ? depName : "") << "\"/>\n"; } writer.decInd(); writer.Stream() << writer.ind() << "\n"; @@ -1368,6 +1369,14 @@ void Document::writeObjects(const std::vector& objs, writeObjectData(objs, writer); writer.decInd(); // indentation for 'Objects count' + + // check for errors + if (writer.hasFailed()) { + std::cerr << "Output stream is in error state. As a result the " + "Document.xml file may be incomplete.\n"; + // reset the error flags to try to safe the data files + writer.clear(); + } } struct DepInfo From 4f116d8de36975ca220eaf4cd75e482062c139f6 Mon Sep 17 00:00:00 2001 From: wmayer Date: Sat, 26 Apr 2025 21:04:07 +0200 Subject: [PATCH 5/6] App: Move Python functions from Application to ApplicationPy This reduces build time when adding new Python functions because only one file must be compiled. --- src/App/Application.cpp | 5 +- src/App/Application.h | 53 ----------- src/App/ApplicationPy.cpp | 183 +++++++++++++++++++------------------- src/App/ApplicationPy.h | 95 ++++++++++++++++++++ 4 files changed, 190 insertions(+), 146 deletions(-) create mode 100644 src/App/ApplicationPy.h diff --git a/src/App/Application.cpp b/src/App/Application.cpp index 8c1851eabb..c212953f85 100644 --- a/src/App/Application.cpp +++ b/src/App/Application.cpp @@ -105,6 +105,7 @@ #include "Application.h" #include "ApplicationDirectories.h" #include "ApplicationDirectoriesPy.h" +#include "ApplicationPy.h" #include "CleanupProcess.h" #include "ComplexGeoData.h" #include "Services.h" @@ -276,7 +277,7 @@ void Application::setupPythonTypes() Base::PyGILStateLocker lock; PyObject* modules = PyImport_GetModuleDict(); - ApplicationMethods = Application::Methods; + ApplicationMethods = ApplicationPy::Methods; PyObject* pAppModule = PyImport_ImportModule ("FreeCAD"); if (!pAppModule) { PyErr_Clear(); @@ -2575,7 +2576,7 @@ void Application::initConfig(int argc, char ** argv) auto moduleName = "FreeCAD"; PyImport_AddModule(moduleName); - ApplicationMethods = Application::Methods; + ApplicationMethods = ApplicationPy::Methods; PyObject *pyModule = init_freecad_module(); PyDict_SetItemString(sysModules, moduleName, pyModule); Py_DECREF(pyModule); diff --git a/src/App/Application.h b/src/App/Application.h index 38d7adb39e..065760c4d3 100644 --- a/src/App/Application.h +++ b/src/App/Application.h @@ -953,59 +953,6 @@ private: static void setupPythonTypes(); static void setupPythonException(PyObject*); - // clang-format off - // static python wrapper of the exported functions - static PyObject* sGetParam (PyObject *self, PyObject *args); - static PyObject* sSaveParameter (PyObject *self, PyObject *args); - static PyObject* sGetVersion (PyObject *self, PyObject *args); - static PyObject* sGetConfig (PyObject *self, PyObject *args); - static PyObject* sSetConfig (PyObject *self, PyObject *args); - static PyObject* sDumpConfig (PyObject *self, PyObject *args); - static PyObject* sAddImportType (PyObject *self, PyObject *args); - static PyObject* sChangeImportModule(PyObject *self, PyObject *args); - static PyObject* sGetImportType (PyObject *self, PyObject *args); - static PyObject* sAddExportType (PyObject *self, PyObject *args); - static PyObject* sChangeExportModule(PyObject *self, PyObject *args); - static PyObject* sGetExportType (PyObject *self, PyObject *args); - static PyObject* sGetResourcePath (PyObject *self, PyObject *args); - static PyObject* sGetLibraryPath (PyObject *self, PyObject *args); - static PyObject* sGetTempPath (PyObject *self, PyObject *args); - static PyObject* sGetUserCachePath (PyObject *self, PyObject *args); - static PyObject* sGetUserConfigPath (PyObject *self, PyObject *args); - static PyObject* sGetUserAppDataPath(PyObject *self, PyObject *args); - static PyObject* sGetUserMacroPath (PyObject *self, PyObject *args); - static PyObject* sGetHelpPath (PyObject *self, PyObject *args); - static PyObject* sGetHomePath (PyObject *self, PyObject *args); - - static PyObject* sLoadFile (PyObject *self,PyObject *args); - static PyObject* sOpenDocument (PyObject *self,PyObject *args, PyObject *kwd); - static PyObject* sSaveDocument (PyObject *self,PyObject *args); - static PyObject* sSaveDocumentAs (PyObject *self,PyObject *args); - static PyObject* sNewDocument (PyObject *self,PyObject *args, PyObject *kwd); - static PyObject* sCloseDocument (PyObject *self,PyObject *args); - static PyObject* sActiveDocument (PyObject *self,PyObject *args); - static PyObject* sSetActiveDocument (PyObject *self,PyObject *args); - static PyObject* sGetDocument (PyObject *self,PyObject *args); - static PyObject* sListDocuments (PyObject *self,PyObject *args); - static PyObject* sAddDocObserver (PyObject *self,PyObject *args); - static PyObject* sRemoveDocObserver (PyObject *self,PyObject *args); - static PyObject *sIsRestoring (PyObject *self,PyObject *args); - - static PyObject *sSetLogLevel (PyObject *self,PyObject *args); - static PyObject *sGetLogLevel (PyObject *self,PyObject *args); - - static PyObject *sCheckLinkDepth (PyObject *self,PyObject *args); - static PyObject *sGetLinksTo (PyObject *self,PyObject *args); - - static PyObject *sGetDependentObjects(PyObject *self,PyObject *args); - - static PyObject *sSetActiveTransaction (PyObject *self,PyObject *args); - static PyObject *sGetActiveTransaction (PyObject *self,PyObject *args); - static PyObject *sCloseActiveTransaction(PyObject *self,PyObject *args); - static PyObject *sCheckAbort(PyObject *self,PyObject *args); - static PyMethodDef Methods[]; - // clang-format on - friend class ApplicationObserver; /* Private Init, Destruct, and Access methods */ diff --git a/src/App/ApplicationPy.cpp b/src/App/ApplicationPy.cpp index c1315679ae..c4500201e2 100644 --- a/src/App/ApplicationPy.cpp +++ b/src/App/ApplicationPy.cpp @@ -34,6 +34,7 @@ #include #include "Application.h" +#include "ApplicationPy.h" #include "DocumentPy.h" #include "DocumentObserverPython.h" #include "DocumentObjectPy.h" @@ -48,95 +49,95 @@ using namespace App; // Python stuff // Application methods structure -PyMethodDef Application::Methods[] = { - {"ParamGet", (PyCFunction)Application::sGetParam, METH_VARARGS, "Get parameters by path"}, +PyMethodDef ApplicationPy::Methods[] = { + {"ParamGet", (PyCFunction)ApplicationPy::sGetParam, METH_VARARGS, "Get parameters by path"}, {"saveParameter", - (PyCFunction)Application::sSaveParameter, + (PyCFunction)ApplicationPy::sSaveParameter, METH_VARARGS, "saveParameter(config='User parameter') -> None\n" "Save parameter set to file. The default set is 'User parameter'"}, {"Version", - (PyCFunction)Application::sGetVersion, + (PyCFunction)ApplicationPy::sGetVersion, METH_VARARGS, "Print the version to the output."}, {"ConfigGet", - (PyCFunction)Application::sGetConfig, + (PyCFunction)ApplicationPy::sGetConfig, METH_VARARGS, "ConfigGet(string) -- Get the value for the given key."}, {"ConfigSet", - (PyCFunction)Application::sSetConfig, + (PyCFunction)ApplicationPy::sSetConfig, METH_VARARGS, "ConfigSet(string, string) -- Set the given key to the given value."}, {"ConfigDump", - (PyCFunction)Application::sDumpConfig, + (PyCFunction)ApplicationPy::sDumpConfig, METH_VARARGS, "Dump the configuration to the output."}, {"addImportType", - (PyCFunction)Application::sAddImportType, + (PyCFunction)ApplicationPy::sAddImportType, METH_VARARGS, "Register filetype for import"}, {"changeImportModule", - (PyCFunction)Application::sChangeImportModule, + (PyCFunction)ApplicationPy::sChangeImportModule, METH_VARARGS, "Change the import module name of a registered filetype"}, {"getImportType", - (PyCFunction)Application::sGetImportType, + (PyCFunction)ApplicationPy::sGetImportType, METH_VARARGS, "Get the name of the module that can import the filetype"}, {"addExportType", - (PyCFunction)Application::sAddExportType, + (PyCFunction)ApplicationPy::sAddExportType, METH_VARARGS, "Register filetype for export"}, {"changeExportModule", - (PyCFunction)Application::sChangeExportModule, + (PyCFunction)ApplicationPy::sChangeExportModule, METH_VARARGS, "Change the export module name of a registered filetype"}, {"getExportType", - (PyCFunction)Application::sGetExportType, + (PyCFunction)ApplicationPy::sGetExportType, METH_VARARGS, "Get the name of the module that can export the filetype"}, {"getResourceDir", - (PyCFunction)Application::sGetResourcePath, + (PyCFunction)ApplicationPy::sGetResourcePath, METH_VARARGS, "Get the root directory of all resources"}, {"getLibraryDir", - (PyCFunction)Application::sGetLibraryPath, + (PyCFunction)ApplicationPy::sGetLibraryPath, METH_VARARGS, "Get the directory of all extension modules"}, {"getTempPath", - (PyCFunction)Application::sGetTempPath, + (PyCFunction)ApplicationPy::sGetTempPath, METH_VARARGS, "Get the root directory of cached files"}, {"getUserCachePath", - (PyCFunction)Application::sGetUserCachePath, + (PyCFunction)ApplicationPy::sGetUserCachePath, METH_VARARGS, "Get the root path of cached files"}, {"getUserConfigDir", - (PyCFunction)Application::sGetUserConfigPath, + (PyCFunction)ApplicationPy::sGetUserConfigPath, METH_VARARGS, "Get the root path of user config files"}, {"getUserAppDataDir", - (PyCFunction)Application::sGetUserAppDataPath, + (PyCFunction)ApplicationPy::sGetUserAppDataPath, METH_VARARGS, "Get the root directory of application data"}, {"getUserMacroDir", - (PyCFunction)Application::sGetUserMacroPath, + (PyCFunction)ApplicationPy::sGetUserMacroPath, METH_VARARGS, "getUserMacroDir(bool=False) -> str\n\n" "Get the directory of the user's macro directory\n" "If parameter is False (the default) it returns the standard path in the" "user's home directory, otherwise it returns the user-defined path."}, {"getHelpDir", - (PyCFunction)Application::sGetHelpPath, + (PyCFunction)ApplicationPy::sGetHelpPath, METH_VARARGS, "Get the directory of the documentation"}, {"getHomePath", - (PyCFunction)Application::sGetHomePath, + (PyCFunction)ApplicationPy::sGetHomePath, METH_VARARGS, "Get the home path, i.e. the parent directory of the executable"}, {"loadFile", - (PyCFunction)Application::sLoadFile, + (PyCFunction)ApplicationPy::sLoadFile, METH_VARARGS, "loadFile(string=filename,[string=module]) -> None\n\n" "Loads an arbitrary file by delegating to the given Python module:\n" @@ -144,11 +145,11 @@ PyMethodDef Application::Methods[] = { "* If more than one module can load a file the first one will be taken.\n" "* If no module exists to load the file an exception will be raised."}, {"open", - reinterpret_cast(reinterpret_cast(Application::sOpenDocument)), + reinterpret_cast(reinterpret_cast(ApplicationPy::sOpenDocument)), METH_VARARGS | METH_KEYWORDS, "See openDocument(string)"}, {"openDocument", - reinterpret_cast(reinterpret_cast(Application::sOpenDocument)), + reinterpret_cast(reinterpret_cast(ApplicationPy::sOpenDocument)), METH_VARARGS | METH_KEYWORDS, "openDocument(filepath,hidden=False,temporary=False) -> object\n" "Create a document and load the project file into the document.\n\n" @@ -157,11 +158,11 @@ PyMethodDef Application::Methods[] = { " In this case the document is kept alive.\n" "hidden: whether to hide document 3D view.\n" "temporary: whether to hide document in the tree view."}, - // {"saveDocument", (PyCFunction) Application::sSaveDocument, METH_VARARGS, + // {"saveDocument", (PyCFunction) ApplicationPy::sSaveDocument, METH_VARARGS, // "saveDocument(string) -- Save the document to a file."}, - // {"saveDocumentAs", (PyCFunction) Application::sSaveDocumentAs, METH_VARARGS}, + // {"saveDocumentAs", (PyCFunction) ApplicationPy::sSaveDocumentAs, METH_VARARGS}, {"newDocument", - reinterpret_cast(reinterpret_cast(Application::sNewDocument)), + reinterpret_cast(reinterpret_cast(ApplicationPy::sNewDocument)), METH_VARARGS | METH_KEYWORDS, "newDocument(name, label=None, hidden=False, temp=False) -> object\n" "Create a new document with a given name.\n\n" @@ -170,62 +171,62 @@ PyMethodDef Application::Methods[] = { "hidden: whether to hide document 3D view.\n" "temp: mark the document as temporary so that it will not be saved"}, {"closeDocument", - (PyCFunction)Application::sCloseDocument, + (PyCFunction)ApplicationPy::sCloseDocument, METH_VARARGS, "closeDocument(string) -> None\n\n" "Close the document with a given name."}, {"activeDocument", - (PyCFunction)Application::sActiveDocument, + (PyCFunction)ApplicationPy::sActiveDocument, METH_VARARGS, "activeDocument() -> object or None\n\n" "Return the active document or None if there is no one."}, {"setActiveDocument", - (PyCFunction)Application::sSetActiveDocument, + (PyCFunction)ApplicationPy::sSetActiveDocument, METH_VARARGS, "setActiveDocement(string) -> None\n\n" "Set the active document by its name."}, {"getDocument", - (PyCFunction)Application::sGetDocument, + (PyCFunction)ApplicationPy::sGetDocument, METH_VARARGS, "getDocument(string) -> object\n\n" "Get a document by its name or raise an exception\n" "if there is no document with the given name."}, {"listDocuments", - (PyCFunction)Application::sListDocuments, + (PyCFunction)ApplicationPy::sListDocuments, METH_VARARGS, "listDocuments(sort=False) -> list\n\n" "Return a list of names of all documents, optionally sort in dependency order."}, {"addDocumentObserver", - (PyCFunction)Application::sAddDocObserver, + (PyCFunction)ApplicationPy::sAddDocObserver, METH_VARARGS, "addDocumentObserver() -> None\n\n" "Add an observer to get notified about changes on documents."}, {"removeDocumentObserver", - (PyCFunction)Application::sRemoveDocObserver, + (PyCFunction)ApplicationPy::sRemoveDocObserver, METH_VARARGS, "removeDocumentObserver() -> None\n\n" "Remove an added document observer."}, {"setLogLevel", - (PyCFunction)Application::sSetLogLevel, + (PyCFunction)ApplicationPy::sSetLogLevel, METH_VARARGS, "setLogLevel(tag, level) -- Set the log level for a string tag.\n" "'level' can either be string 'Log', 'Msg', 'Wrn', 'Error', or an integer value"}, {"getLogLevel", - (PyCFunction)Application::sGetLogLevel, + (PyCFunction)ApplicationPy::sGetLogLevel, METH_VARARGS, "getLogLevel(tag) -- Get the log level of a string tag"}, {"checkLinkDepth", - (PyCFunction)Application::sCheckLinkDepth, + (PyCFunction)ApplicationPy::sCheckLinkDepth, METH_VARARGS, "checkLinkDepth(depth) -- check link recursion depth"}, {"getLinksTo", - (PyCFunction)Application::sGetLinksTo, + (PyCFunction)ApplicationPy::sGetLinksTo, METH_VARARGS, "getLinksTo(obj,options=0,maxCount=0) -- return the objects linked to 'obj'\n\n" "options: 1: recursive, 2: check link array. Options can combine.\n" "maxCount: to limit the number of links returned\n"}, {"getDependentObjects", - (PyCFunction)Application::sGetDependentObjects, + (PyCFunction)ApplicationPy::sGetDependentObjects, METH_VARARGS, "getDependentObjects(obj|[obj,...], options=0)\n" "Return a list of dependent objects including the given objects.\n\n" @@ -233,7 +234,7 @@ PyMethodDef Application::Methods[] = { " 1: to sort the list in topological order.\n" " 2: to exclude dependency of Link type object."}, {"setActiveTransaction", - (PyCFunction)Application::sSetActiveTransaction, + (PyCFunction)ApplicationPy::sSetActiveTransaction, METH_VARARGS, "setActiveTransaction(name, persist=False) -- setup active transaction with the given name\n\n" "name: the transaction name\n" @@ -244,21 +245,21 @@ PyMethodDef Application::Methods[] = { "active transaction causes any document changes to open a transaction with\n" "the given name and ID."}, {"getActiveTransaction", - (PyCFunction)Application::sGetActiveTransaction, + (PyCFunction)ApplicationPy::sGetActiveTransaction, METH_VARARGS, "getActiveTransaction() -> (name,id)\n\n" "return the current active transaction name and ID"}, {"closeActiveTransaction", - (PyCFunction)Application::sCloseActiveTransaction, + (PyCFunction)ApplicationPy::sCloseActiveTransaction, METH_VARARGS, "closeActiveTransaction(abort=False) -- commit or abort current active transaction"}, {"isRestoring", - (PyCFunction)Application::sIsRestoring, + (PyCFunction)ApplicationPy::sIsRestoring, METH_VARARGS, "isRestoring() -> bool\n\n" "Test if the application is opening some document"}, {"checkAbort", - (PyCFunction)Application::sCheckAbort, + (PyCFunction)ApplicationPy::sCheckAbort, METH_VARARGS, "checkAbort() -- check for user abort in length operation.\n\n" "This only works if there is an active sequencer (or ProgressIndicator in Python).\n" @@ -269,7 +270,7 @@ PyMethodDef Application::Methods[] = { }; -PyObject* Application::sLoadFile(PyObject* /*self*/, PyObject* args) +PyObject* ApplicationPy::sLoadFile(PyObject* /*self*/, PyObject* args) { const char* path; const char* doc = ""; @@ -329,7 +330,7 @@ PyObject* Application::sLoadFile(PyObject* /*self*/, PyObject* args) } } -PyObject* Application::sIsRestoring(PyObject* /*self*/, PyObject* args) +PyObject* ApplicationPy::sIsRestoring(PyObject* /*self*/, PyObject* args) { if (!PyArg_ParseTuple(args, "")) { return nullptr; @@ -337,7 +338,7 @@ PyObject* Application::sIsRestoring(PyObject* /*self*/, PyObject* args) return Py::new_reference_to(Py::Boolean(GetApplication().isRestoring())); } -PyObject* Application::sOpenDocument(PyObject* /*self*/, PyObject* args, PyObject* kwd) +PyObject* ApplicationPy::sOpenDocument(PyObject* /*self*/, PyObject* args, PyObject* kwd) { char* Name; PyObject* hidden = Py_False; @@ -379,7 +380,7 @@ PyObject* Application::sOpenDocument(PyObject* /*self*/, PyObject* args, PyObjec } } -PyObject* Application::sNewDocument(PyObject* /*self*/, PyObject* args, PyObject* kwd) +PyObject* ApplicationPy::sNewDocument(PyObject* /*self*/, PyObject* args, PyObject* kwd) { char* docName = nullptr; char* usrName = nullptr; @@ -417,7 +418,7 @@ PyObject* Application::sNewDocument(PyObject* /*self*/, PyObject* args, PyObject PY_CATCH; } -PyObject* Application::sSetActiveDocument(PyObject* /*self*/, PyObject* args) +PyObject* ApplicationPy::sSetActiveDocument(PyObject* /*self*/, PyObject* args) { char* pstr = nullptr; if (!PyArg_ParseTuple(args, "s", &pstr)) { @@ -435,7 +436,7 @@ PyObject* Application::sSetActiveDocument(PyObject* /*self*/, PyObject* args) Py_Return; } -PyObject* Application::sCloseDocument(PyObject* /*self*/, PyObject* args) +PyObject* ApplicationPy::sCloseDocument(PyObject* /*self*/, PyObject* args) { char* pstr = nullptr; if (!PyArg_ParseTuple(args, "s", &pstr)) { @@ -460,7 +461,7 @@ PyObject* Application::sCloseDocument(PyObject* /*self*/, PyObject* args) Py_Return; } -PyObject* Application::sSaveDocument(PyObject* /*self*/, PyObject* args) +PyObject* ApplicationPy::sSaveDocument(PyObject* /*self*/, PyObject* args) { char* pDoc; if (!PyArg_ParseTuple(args, "s", &pDoc)) { @@ -482,7 +483,7 @@ PyObject* Application::sSaveDocument(PyObject* /*self*/, PyObject* args) Py_Return; } -PyObject* Application::sActiveDocument(PyObject* /*self*/, PyObject* args) +PyObject* ApplicationPy::sActiveDocument(PyObject* /*self*/, PyObject* args) { if (!PyArg_ParseTuple(args, "")) { return nullptr; @@ -498,7 +499,7 @@ PyObject* Application::sActiveDocument(PyObject* /*self*/, PyObject* args) } } -PyObject* Application::sGetDocument(PyObject* /*self*/, PyObject* args) +PyObject* ApplicationPy::sGetDocument(PyObject* /*self*/, PyObject* args) { char* pstr = nullptr; if (!PyArg_ParseTuple(args, "s", &pstr)) { @@ -514,7 +515,7 @@ PyObject* Application::sGetDocument(PyObject* /*self*/, PyObject* args) return doc->getPyObject(); } -PyObject* Application::sGetParam(PyObject* /*self*/, PyObject* args) +PyObject* ApplicationPy::sGetParam(PyObject* /*self*/, PyObject* args) { char* pstr = nullptr; if (!PyArg_ParseTuple(args, "s", &pstr)) { @@ -528,7 +529,7 @@ PyObject* Application::sGetParam(PyObject* /*self*/, PyObject* args) PY_CATCH; } -PyObject* Application::sSaveParameter(PyObject* /*self*/, PyObject* args) +PyObject* ApplicationPy::sSaveParameter(PyObject* /*self*/, PyObject* args) { const char* pstr = "User parameter"; if (!PyArg_ParseTuple(args, "|s", &pstr)) { @@ -559,7 +560,7 @@ PyObject* Application::sSaveParameter(PyObject* /*self*/, PyObject* args) } -PyObject* Application::sGetConfig(PyObject* /*self*/, PyObject* args) +PyObject* ApplicationPy::sGetConfig(PyObject* /*self*/, PyObject* args) { char* pstr; @@ -578,20 +579,20 @@ PyObject* Application::sGetConfig(PyObject* /*self*/, PyObject* args) } } -PyObject* Application::sDumpConfig(PyObject* /*self*/, PyObject* args) +PyObject* ApplicationPy::sDumpConfig(PyObject* /*self*/, PyObject* args) { if (!PyArg_ParseTuple(args, "")) { return nullptr; } PyObject* dict = PyDict_New(); - for (const auto& It : GetApplication()._mConfig) { + for (const auto& It : GetApplication().Config()) { PyDict_SetItemString(dict, It.first.c_str(), PyUnicode_FromString(It.second.c_str())); } return dict; } -PyObject* Application::sSetConfig(PyObject* /*self*/, PyObject* args) +PyObject* ApplicationPy::sSetConfig(PyObject* /*self*/, PyObject* args) { char *pstr, *pstr2; @@ -599,13 +600,13 @@ PyObject* Application::sSetConfig(PyObject* /*self*/, PyObject* args) return nullptr; } - GetApplication()._mConfig[pstr] = pstr2; + GetApplication().Config()[pstr] = pstr2; Py_INCREF(Py_None); return Py_None; } -PyObject* Application::sGetVersion(PyObject* /*self*/, PyObject* args) +PyObject* ApplicationPy::sGetVersion(PyObject* /*self*/, PyObject* args) { if (!PyArg_ParseTuple(args, "")) { return nullptr; @@ -646,7 +647,7 @@ PyObject* Application::sGetVersion(PyObject* /*self*/, PyObject* args) return Py::new_reference_to(list); } -PyObject* Application::sAddImportType(PyObject* /*self*/, PyObject* args) +PyObject* ApplicationPy::sAddImportType(PyObject* /*self*/, PyObject* args) { char *psKey, *psMod; @@ -659,7 +660,7 @@ PyObject* Application::sAddImportType(PyObject* /*self*/, PyObject* args) Py_Return; } -PyObject* Application::sChangeImportModule(PyObject* /*self*/, PyObject* args) +PyObject* ApplicationPy::sChangeImportModule(PyObject* /*self*/, PyObject* args) { char *key, *oldMod, *newMod; @@ -672,7 +673,7 @@ PyObject* Application::sChangeImportModule(PyObject* /*self*/, PyObject* args) Py_Return; } -PyObject* Application::sGetImportType(PyObject* /*self*/, PyObject* args) +PyObject* ApplicationPy::sGetImportType(PyObject* /*self*/, PyObject* args) { char* psKey = nullptr; @@ -713,7 +714,7 @@ PyObject* Application::sGetImportType(PyObject* /*self*/, PyObject* args) } } -PyObject* Application::sAddExportType(PyObject* /*self*/, PyObject* args) +PyObject* ApplicationPy::sAddExportType(PyObject* /*self*/, PyObject* args) { char *psKey, *psMod; @@ -726,7 +727,7 @@ PyObject* Application::sAddExportType(PyObject* /*self*/, PyObject* args) Py_Return; } -PyObject* Application::sChangeExportModule(PyObject* /*self*/, PyObject* args) +PyObject* ApplicationPy::sChangeExportModule(PyObject* /*self*/, PyObject* args) { char *key, *oldMod, *newMod; @@ -739,7 +740,7 @@ PyObject* Application::sChangeExportModule(PyObject* /*self*/, PyObject* args) Py_Return; } -PyObject* Application::sGetExportType(PyObject* /*self*/, PyObject* args) +PyObject* ApplicationPy::sGetExportType(PyObject* /*self*/, PyObject* args) { char* psKey = nullptr; @@ -780,7 +781,7 @@ PyObject* Application::sGetExportType(PyObject* /*self*/, PyObject* args) } } -PyObject* Application::sGetResourcePath(PyObject* /*self*/, PyObject* args) +PyObject* ApplicationPy::sGetResourcePath(PyObject* /*self*/, PyObject* args) { if (!PyArg_ParseTuple(args, "")) { return nullptr; @@ -790,7 +791,7 @@ PyObject* Application::sGetResourcePath(PyObject* /*self*/, PyObject* args) return Py::new_reference_to(datadir); } -PyObject* Application::sGetLibraryPath(PyObject* /*self*/, PyObject* args) +PyObject* ApplicationPy::sGetLibraryPath(PyObject* /*self*/, PyObject* args) { if (!PyArg_ParseTuple(args, "")) { return nullptr; @@ -800,7 +801,7 @@ PyObject* Application::sGetLibraryPath(PyObject* /*self*/, PyObject* args) return Py::new_reference_to(datadir); } -PyObject* Application::sGetTempPath(PyObject* /*self*/, PyObject* args) +PyObject* ApplicationPy::sGetTempPath(PyObject* /*self*/, PyObject* args) { if (!PyArg_ParseTuple(args, "")) { return nullptr; @@ -810,7 +811,7 @@ PyObject* Application::sGetTempPath(PyObject* /*self*/, PyObject* args) return Py::new_reference_to(datadir); } -PyObject* Application::sGetUserCachePath(PyObject* /*self*/, PyObject* args) +PyObject* ApplicationPy::sGetUserCachePath(PyObject* /*self*/, PyObject* args) { if (!PyArg_ParseTuple(args, "")) { return nullptr; @@ -820,7 +821,7 @@ PyObject* Application::sGetUserCachePath(PyObject* /*self*/, PyObject* args) return Py::new_reference_to(datadir); } -PyObject* Application::sGetUserConfigPath(PyObject* /*self*/, PyObject* args) +PyObject* ApplicationPy::sGetUserConfigPath(PyObject* /*self*/, PyObject* args) { if (!PyArg_ParseTuple(args, "")) { return nullptr; @@ -830,7 +831,7 @@ PyObject* Application::sGetUserConfigPath(PyObject* /*self*/, PyObject* args) return Py::new_reference_to(datadir); } -PyObject* Application::sGetUserAppDataPath(PyObject* /*self*/, PyObject* args) +PyObject* ApplicationPy::sGetUserAppDataPath(PyObject* /*self*/, PyObject* args) { if (!PyArg_ParseTuple(args, "")) { return nullptr; @@ -840,7 +841,7 @@ PyObject* Application::sGetUserAppDataPath(PyObject* /*self*/, PyObject* args) return Py::new_reference_to(user_data_dir); } -PyObject* Application::sGetUserMacroPath(PyObject* /*self*/, PyObject* args) +PyObject* ApplicationPy::sGetUserMacroPath(PyObject* /*self*/, PyObject* args) { PyObject* actual = Py_False; if (!PyArg_ParseTuple(args, "|O!", &PyBool_Type, &actual)) { @@ -859,7 +860,7 @@ PyObject* Application::sGetUserMacroPath(PyObject* /*self*/, PyObject* args) return Py::new_reference_to(user_macro_dir); } -PyObject* Application::sGetHelpPath(PyObject* /*self*/, PyObject* args) +PyObject* ApplicationPy::sGetHelpPath(PyObject* /*self*/, PyObject* args) { if (!PyArg_ParseTuple(args, "")) { return nullptr; @@ -869,7 +870,7 @@ PyObject* Application::sGetHelpPath(PyObject* /*self*/, PyObject* args) return Py::new_reference_to(user_macro_dir); } -PyObject* Application::sGetHomePath(PyObject* /*self*/, PyObject* args) +PyObject* ApplicationPy::sGetHomePath(PyObject* /*self*/, PyObject* args) { if (!PyArg_ParseTuple(args, "")) { return nullptr; @@ -879,7 +880,7 @@ PyObject* Application::sGetHomePath(PyObject* /*self*/, PyObject* args) return Py::new_reference_to(homedir); } -PyObject* Application::sListDocuments(PyObject* /*self*/, PyObject* args) +PyObject* ApplicationPy::sListDocuments(PyObject* /*self*/, PyObject* args) { PyObject* sort = Py_False; if (!PyArg_ParseTuple(args, "|O!", &PyBool_Type, &sort)) { @@ -911,7 +912,7 @@ PyObject* Application::sListDocuments(PyObject* /*self*/, PyObject* args) PY_CATCH; } -PyObject* Application::sAddDocObserver(PyObject* /*self*/, PyObject* args) +PyObject* ApplicationPy::sAddDocObserver(PyObject* /*self*/, PyObject* args) { PyObject* o; if (!PyArg_ParseTuple(args, "O", &o)) { @@ -925,7 +926,7 @@ PyObject* Application::sAddDocObserver(PyObject* /*self*/, PyObject* args) PY_CATCH; } -PyObject* Application::sRemoveDocObserver(PyObject* /*self*/, PyObject* args) +PyObject* ApplicationPy::sRemoveDocObserver(PyObject* /*self*/, PyObject* args) { PyObject* o; if (!PyArg_ParseTuple(args, "O", &o)) { @@ -939,7 +940,7 @@ PyObject* Application::sRemoveDocObserver(PyObject* /*self*/, PyObject* args) PY_CATCH; } -PyObject* Application::sSetLogLevel(PyObject* /*self*/, PyObject* args) +PyObject* ApplicationPy::sSetLogLevel(PyObject* /*self*/, PyObject* args) { char* tag; PyObject* pcObj; @@ -1005,7 +1006,7 @@ PyObject* Application::sSetLogLevel(PyObject* /*self*/, PyObject* args) PY_CATCH; } -PyObject* Application::sGetLogLevel(PyObject* /*self*/, PyObject* args) +PyObject* ApplicationPy::sGetLogLevel(PyObject* /*self*/, PyObject* args) { char* tag; if (!PyArg_ParseTuple(args, "s", &tag)) { @@ -1017,12 +1018,12 @@ PyObject* Application::sGetLogLevel(PyObject* /*self*/, PyObject* args) int l = -1; if (strcmp(tag, "Default") == 0) { #ifdef FC_DEBUG - l = _pcUserParamMngr->GetGroup("BaseApp/LogLevels")->GetInt(tag, -1); + l = GetApplication().GetUserParameter().GetGroup("BaseApp/LogLevels")->GetInt(tag, -1); #endif } else if (strcmp(tag, "DebugDefault") == 0) { #ifndef FC_DEBUG - l = _pcUserParamMngr->GetGroup("BaseApp/LogLevels")->GetInt(tag, -1); + l = GetApplication().GetUserParameter().GetGroup("BaseApp/LogLevels")->GetInt(tag, -1); #endif } else { @@ -1035,7 +1036,7 @@ PyObject* Application::sGetLogLevel(PyObject* /*self*/, PyObject* args) PY_CATCH; } -PyObject* Application::sCheckLinkDepth(PyObject* /*self*/, PyObject* args) +PyObject* ApplicationPy::sCheckLinkDepth(PyObject* /*self*/, PyObject* args) { short depth = 0; if (!PyArg_ParseTuple(args, "h", &depth)) { @@ -1050,7 +1051,7 @@ PyObject* Application::sCheckLinkDepth(PyObject* /*self*/, PyObject* args) PY_CATCH; } -PyObject* Application::sGetLinksTo(PyObject* /*self*/, PyObject* args) +PyObject* ApplicationPy::sGetLinksTo(PyObject* /*self*/, PyObject* args) { PyObject* pyobj = Py_None; int options = 0; @@ -1081,7 +1082,7 @@ PyObject* Application::sGetLinksTo(PyObject* /*self*/, PyObject* args) PY_CATCH; } -PyObject* Application::sGetDependentObjects(PyObject* /*self*/, PyObject* args) +PyObject* ApplicationPy::sGetDependentObjects(PyObject* /*self*/, PyObject* args) { PyObject* obj; int options = 0; @@ -1125,7 +1126,7 @@ PyObject* Application::sGetDependentObjects(PyObject* /*self*/, PyObject* args) } -PyObject* Application::sSetActiveTransaction(PyObject* /*self*/, PyObject* args) +PyObject* ApplicationPy::sSetActiveTransaction(PyObject* /*self*/, PyObject* args) { char* name; PyObject* persist = Py_False; @@ -1141,7 +1142,7 @@ PyObject* Application::sSetActiveTransaction(PyObject* /*self*/, PyObject* args) PY_CATCH; } -PyObject* Application::sGetActiveTransaction(PyObject* /*self*/, PyObject* args) +PyObject* ApplicationPy::sGetActiveTransaction(PyObject* /*self*/, PyObject* args) { if (!PyArg_ParseTuple(args, "")) { return nullptr; @@ -1162,7 +1163,7 @@ PyObject* Application::sGetActiveTransaction(PyObject* /*self*/, PyObject* args) PY_CATCH; } -PyObject* Application::sCloseActiveTransaction(PyObject* /*self*/, PyObject* args) +PyObject* ApplicationPy::sCloseActiveTransaction(PyObject* /*self*/, PyObject* args) { PyObject* abort = Py_False; int id = 0; @@ -1178,7 +1179,7 @@ PyObject* Application::sCloseActiveTransaction(PyObject* /*self*/, PyObject* arg PY_CATCH; } -PyObject* Application::sCheckAbort(PyObject* /*self*/, PyObject* args) +PyObject* ApplicationPy::sCheckAbort(PyObject* /*self*/, PyObject* args) { if (!PyArg_ParseTuple(args, "")) { return nullptr; diff --git a/src/App/ApplicationPy.h b/src/App/ApplicationPy.h new file mode 100644 index 0000000000..a723bc6bba --- /dev/null +++ b/src/App/ApplicationPy.h @@ -0,0 +1,95 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later + +/*************************************************************************** + * Copyright (c) 2002 Jürgen Riegel * + * * + * This file is part of FreeCAD. * + * * + * FreeCAD is free software: you can redistribute it and/or modify it * + * under the terms of the GNU Lesser General Public License as * + * published by the Free Software Foundation, either version 2.1 of the * + * License, or (at your option) any later version. * + * * + * FreeCAD is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with FreeCAD. If not, see * + * . * + * * + **************************************************************************/ + +#ifndef APP_APPLICATIONPY_H +#define APP_APPLICATIONPY_H + +#include + +namespace App +{ + +/** The ApplicationPy class + * This is the Python wrapper class of Application. + * @author Jürgen Riegel, Werner Mayer + */ +class AppExport ApplicationPy +{ +public: + // clang-format off + // static python wrapper of the exported functions + static PyObject* sGetParam (PyObject *self, PyObject *args); + static PyObject* sSaveParameter (PyObject *self, PyObject *args); + static PyObject* sGetVersion (PyObject *self, PyObject *args); + static PyObject* sGetConfig (PyObject *self, PyObject *args); + static PyObject* sSetConfig (PyObject *self, PyObject *args); + static PyObject* sDumpConfig (PyObject *self, PyObject *args); + static PyObject* sAddImportType (PyObject *self, PyObject *args); + static PyObject* sChangeImportModule (PyObject *self, PyObject *args); + static PyObject* sGetImportType (PyObject *self, PyObject *args); + static PyObject* sAddExportType (PyObject *self, PyObject *args); + static PyObject* sChangeExportModule (PyObject *self, PyObject *args); + static PyObject* sGetExportType (PyObject *self, PyObject *args); + static PyObject* sGetResourcePath (PyObject *self, PyObject *args); + static PyObject* sGetLibraryPath (PyObject *self, PyObject *args); + static PyObject* sGetTempPath (PyObject *self, PyObject *args); + static PyObject* sGetUserCachePath (PyObject *self, PyObject *args); + static PyObject* sGetUserConfigPath (PyObject *self, PyObject *args); + static PyObject* sGetUserAppDataPath (PyObject *self, PyObject *args); + static PyObject* sGetUserMacroPath (PyObject *self, PyObject *args); + static PyObject* sGetHelpPath (PyObject *self, PyObject *args); + static PyObject* sGetHomePath (PyObject *self, PyObject *args); + + static PyObject* sLoadFile (PyObject *self,PyObject *args); + static PyObject* sOpenDocument (PyObject *self,PyObject *args, PyObject *kwd); + static PyObject* sSaveDocument (PyObject *self,PyObject *args); + static PyObject* sSaveDocumentAs (PyObject *self,PyObject *args); + static PyObject* sNewDocument (PyObject *self,PyObject *args, PyObject *kwd); + static PyObject* sCloseDocument (PyObject *self,PyObject *args); + static PyObject* sActiveDocument (PyObject *self,PyObject *args); + static PyObject* sSetActiveDocument (PyObject *self,PyObject *args); + static PyObject* sGetDocument (PyObject *self,PyObject *args); + static PyObject* sListDocuments (PyObject *self,PyObject *args); + static PyObject* sAddDocObserver (PyObject *self,PyObject *args); + static PyObject* sRemoveDocObserver (PyObject *self,PyObject *args); + static PyObject *sIsRestoring (PyObject *self,PyObject *args); + + static PyObject *sSetLogLevel (PyObject *self,PyObject *args); + static PyObject *sGetLogLevel (PyObject *self,PyObject *args); + + static PyObject *sCheckLinkDepth (PyObject *self,PyObject *args); + static PyObject *sGetLinksTo (PyObject *self,PyObject *args); + + static PyObject *sGetDependentObjects (PyObject *self,PyObject *args); + + static PyObject *sSetActiveTransaction (PyObject *self,PyObject *args); + static PyObject *sGetActiveTransaction (PyObject *self,PyObject *args); + static PyObject *sCloseActiveTransaction (PyObject *self,PyObject *args); + static PyObject *sCheckAbort (PyObject *self,PyObject *args); + static PyMethodDef Methods[]; + // clang-format on +}; + +} + +#endif // APP_APPLICATIONPY_H From cda2b8cbdbd9838335a9cef880d5f7fa8e81e99e Mon Sep 17 00:00:00 2001 From: wmayer Date: Sat, 10 May 2025 17:05:11 +0200 Subject: [PATCH 6/6] Use Application::getExecutableName() instead of Config()["ExeName"] --- src/App/Application.cpp | 4 ++-- src/Gui/MainWindow.cpp | 4 ++-- src/Main/MainCmd.cpp | 4 ++-- src/Main/MainGui.cpp | 12 ++++++------ src/Main/MainPy.cpp | 2 +- src/Mod/Material/App/Materials.cpp | 2 +- src/Mod/Mesh/App/AppMeshPy.cpp | 4 ++-- src/Mod/Start/Gui/FirstStartWidget.cpp | 3 +-- 8 files changed, 17 insertions(+), 18 deletions(-) diff --git a/src/App/Application.cpp b/src/App/Application.cpp index c212953f85..e534de2387 100644 --- a/src/App/Application.cpp +++ b/src/App/Application.cpp @@ -1320,7 +1320,7 @@ void Application::addImportType(const char* filter, const char* moduleName) // Due to branding stuff replace "FreeCAD" with the branded application name if (strncmp(filter, "FreeCAD", 7) == 0) { - std::string AppName = Config()["ExeName"]; + std::string AppName = getExecutableName(); AppName += item.filter.substr(7); item.filter = std::move(AppName); // put to the front of the array @@ -1436,7 +1436,7 @@ void Application::addExportType(const char* filter, const char* moduleName) // Due to branding stuff replace "FreeCAD" with the branded application name if (strncmp(filter, "FreeCAD", 7) == 0) { - std::string AppName = Config()["ExeName"]; + std::string AppName = getExecutableName(); AppName += item.filter.substr(7); item.filter = std::move(AppName); // put to the front of the array diff --git a/src/Gui/MainWindow.cpp b/src/Gui/MainWindow.cpp index 0bb8e02ddf..f2b11c80bc 100644 --- a/src/Gui/MainWindow.cpp +++ b/src/Gui/MainWindow.cpp @@ -1976,8 +1976,8 @@ void MainWindow::switchToDockedMode() void MainWindow::loadWindowSettings() { - QString vendor = QString::fromUtf8(App::Application::Config()["ExeVendor"].c_str()); - QString application = QString::fromUtf8(App::Application::Config()["ExeName"].c_str()); + QString vendor = QString::fromStdString(App::Application::Config()["ExeVendor"]); + QString application = QString::fromStdString(App::Application::getExecutableName()); int major = (QT_VERSION >> 0x10) & 0xff; int minor = (QT_VERSION >> 0x08) & 0xff; QString qtver = QStringLiteral("Qt%1.%2").arg(major).arg(minor); diff --git a/src/Main/MainCmd.cpp b/src/Main/MainCmd.cpp index faab6db67a..f12fb4d12b 100644 --- a/src/Main/MainCmd.cpp +++ b/src/Main/MainCmd.cpp @@ -104,7 +104,7 @@ int main(int argc, char** argv) exit(0); } catch (const Base::Exception& e) { - std::string appName = App::Application::Config()["ExeName"]; + std::string appName = App::Application::getExecutableName(); std::cout << "While initializing " << appName << " the following exception occurred: '" << e.what() << "'\n\n"; std::cout << "Python is searching for its runtime files in the following directories:\n" @@ -123,7 +123,7 @@ int main(int argc, char** argv) exit(100); } catch (...) { - std::string appName = App::Application::Config()["ExeName"]; + std::string appName = App::Application::getExecutableName(); std::cout << "Unknown runtime error occurred while initializing " << appName << ".\n\n"; std::cout << "Please contact the application's support team for more information."; std::cout << std::endl; diff --git a/src/Main/MainGui.cpp b/src/Main/MainGui.cpp index 16a2617273..43dd556818 100644 --- a/src/Main/MainGui.cpp +++ b/src/Main/MainGui.cpp @@ -104,7 +104,7 @@ static bool inGuiMode() static void displayInfo(const QString& msg, bool preformatted = true) { if (inGuiMode()) { - QString appName = QString::fromStdString(App::Application::Config()["ExeName"]); + QString appName = QString::fromStdString(App::Application::getExecutableName()); QMessageBox msgBox; msgBox.setIcon(QMessageBox::Information); msgBox.setWindowTitle(appName); @@ -120,7 +120,7 @@ static void displayInfo(const QString& msg, bool preformatted = true) static void displayCritical(const QString& msg, bool preformatted = true) { if (inGuiMode()) { - QString appName = QString::fromStdString(App::Application::Config()["ExeName"]); + QString appName = QString::fromStdString(App::Application::getExecutableName()); QString title = QObject::tr("Initialization of %1 failed").arg(appName); QString text = preformatted ? QStringLiteral("
%1
").arg(msg) : msg; QMessageBox::critical(nullptr, title, text); @@ -278,7 +278,7 @@ int main(int argc, char** argv) catch (const Base::Exception& e) { // Popup an own dialog box instead of that one of Windows QApplication app(argc, argv); - QString appName = QString::fromStdString(App::Application::Config()["ExeName"]); + QString appName = QString::fromStdString(App::Application::getExecutableName()); QString msg; msg = QObject::tr( "While initializing %1 the following exception occurred: '%2'\n\n" @@ -312,7 +312,7 @@ int main(int argc, char** argv) catch (...) { // Popup an own dialog box instead of that one of Windows QApplication app(argc, argv); - QString appName = QString::fromStdString(App::Application::Config()["ExeName"]); + QString appName = QString::fromStdString(App::Application::getExecutableName()); QString msg = QObject::tr( "Unknown runtime error occurred while initializing %1.\n\n" "Please contact the application's support team for more information.\n\n" @@ -359,12 +359,12 @@ int main(int argc, char** argv) std::cerr.rdbuf(oldcerr); // Destruction phase =========================================================== - Base::Console().log("%s terminating...\n", App::Application::Config()["ExeName"].c_str()); + Base::Console().log("%s terminating...\n", App::Application::getExecutableName().c_str()); // cleans up App::Application::destruct(); - Base::Console().log("%s completely terminated\n", App::Application::Config()["ExeName"].c_str()); + Base::Console().log("%s completely terminated\n", App::Application::getExecutableName().c_str()); return 0; } diff --git a/src/Main/MainPy.cpp b/src/Main/MainPy.cpp index c31802f405..1be1d0d364 100644 --- a/src/Main/MainPy.cpp +++ b/src/Main/MainPy.cpp @@ -167,7 +167,7 @@ PyMOD_INIT_FUNC(FreeCAD) App::Application::init(argc, argv.data()); } catch (const Base::Exception& e) { - std::string appName = App::Application::Config()["ExeName"]; + std::string appName = App::Application::getExecutableName(); std::cout << "While initializing " << appName << " the following exception occurred: '" << e.what() << "'\n\n"; std::cout << "Please contact the application's support team for more information." diff --git a/src/Mod/Material/App/Materials.cpp b/src/Mod/Material/App/Materials.cpp index 6b82b09f22..c0baa71841 100644 --- a/src/Mod/Material/App/Materials.cpp +++ b/src/Mod/Material/App/Materials.cpp @@ -1568,7 +1568,7 @@ void Material::save(QTextStream& stream, bool overwrite, bool saveAsCopy, bool s } stream << "---\n"; - stream << "# File created by " << QString::fromStdString(App::Application::Config()["ExeName"]) + stream << "# File created by " << QString::fromStdString(App::Application::getExecutableName()) << " " << QString::fromStdString(App::Application::Config()["ExeVersion"]) << " Revision: " << QString::fromStdString(App::Application::Config()["BuildRevision"]) << "\n"; diff --git a/src/Mod/Mesh/App/AppMeshPy.cpp b/src/Mod/Mesh/App/AppMeshPy.cpp index 85a0af0924..10ff1a4bd4 100644 --- a/src/Mod/Mesh/App/AppMeshPy.cpp +++ b/src/Mod/Mesh/App/AppMeshPy.cpp @@ -267,9 +267,9 @@ private: std::unique_ptr exporter; if (exportFormat == MeshIO::AMF) { std::map meta; - meta["cad"] = App::Application::Config()["ExeName"] + " " + meta["cad"] = App::Application::getExecutableName() + " " + App::Application::Config()["ExeVersion"]; - meta[App::Application::Config()["ExeName"] + "-buildRevisionHash"] + meta[App::Application::getExecutableName() + "-buildRevisionHash"] = App::Application::Config()["BuildRevisionHash"]; exporter = std::make_unique(outputFileName, meta, exportAmfCompressed); diff --git a/src/Mod/Start/Gui/FirstStartWidget.cpp b/src/Mod/Start/Gui/FirstStartWidget.cpp index 1ea0cf545c..114cba312c 100644 --- a/src/Mod/Start/Gui/FirstStartWidget.cpp +++ b/src/Mod/Start/Gui/FirstStartWidget.cpp @@ -57,7 +57,6 @@ void FirstStartWidget::setupUi() { auto outerLayout = gsl::owner(new QVBoxLayout(this)); outerLayout->setAlignment(Qt::AlignCenter); - QString application = QString::fromUtf8(App::Application::Config()["ExeName"].c_str()); _welcomeLabel = gsl::owner(new QLabel); outerLayout->addWidget(_welcomeLabel); _descriptionLabel = gsl::owner(new QLabel); @@ -90,7 +89,7 @@ bool FirstStartWidget::eventFilter(QObject* object, QEvent* event) void FirstStartWidget::retranslateUi() { _doneButton->setText(tr("Done")); - QString application = QString::fromUtf8(App::Application::Config()["ExeName"].c_str()); + QString application = QString::fromStdString(App::Application::getExecutableName()); _welcomeLabel->setText( QLatin1String("

") + tr("Welcome to %1").arg(application) + QLatin1String("

") );