diff --git a/src/App/Application.cpp b/src/App/Application.cpp index 8c1851eabb..e534de2387 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(); @@ -1319,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 @@ -1435,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 @@ -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 diff --git a/src/App/Document.cpp b/src/App/Document.cpp index 14d2c51c58..fe186f3c41 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,96 +1250,133 @@ 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'; + auto objName = o->getNameInDocument(); + writer.Stream() << writer.ind() + << "<" << fcElementObjectDeps + << " " << fcAttrDepObjName << "=\"" + << (objName ? objName : "") << "\" " + << 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 depName = dep ? dep->getNameInDocument() : ""; + writer.Stream() << writer.ind() + << "<" << fcElementObjectDep + << " " << fcAttrDepObjName << "=\"" + << (depName ? depName : "") << "\"/>\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) << "\" "; } } - writer.Stream() << "/>" << '\n'; + if (it->isFreezed()) { + writer.Stream() << "Freeze=\"1\" "; + } + 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' + + // 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 @@ -1514,6 +1550,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) { @@ -2816,10 +2857,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 @@ -2845,7 +2886,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; }); @@ -2880,11 +2921,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; @@ -2923,9 +2964,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 @@ -2941,14 +2982,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; } @@ -2970,7 +3011,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. * 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); 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(); 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("

") );