| |
|
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| |
|
| | #include <Base/FileInfo.h>
|
| | #include <Base/Interpreter.h>
|
| | #include <Base/Stream.h>
|
| |
|
| | #include "Document.h"
|
| | #include "DocumentObject.h"
|
| | #include "DocumentObjectPy.h"
|
| | #include "MergeDocuments.h"
|
| |
|
| |
|
| | #include "DocumentPy.h"
|
| | #include "DocumentPy.cpp"
|
| | #include <boost/regex.hpp>
|
| | #include <Base/PyWrapParseTupleAndKeywords.h>
|
| |
|
| | using namespace App;
|
| |
|
| |
|
| | PyObject* DocumentPy::addProperty(PyObject* args, PyObject* kwd)
|
| | {
|
| | char* sType {nullptr};
|
| | char* sName {nullptr};
|
| | char* sGroup {nullptr};
|
| | char* sDoc {nullptr};
|
| | short attr = 0;
|
| | std::string sDocStr;
|
| | PyObject *ro = Py_False, *hd = Py_False, *lk = Py_False;
|
| | PyObject* enumVals = nullptr;
|
| | static const std::array<const char*, 10> kwlist {"type",
|
| | "name",
|
| | "group",
|
| | "doc",
|
| | "attr",
|
| | "read_only",
|
| | "hidden",
|
| | "locked",
|
| | "enum_vals",
|
| | nullptr};
|
| | if (!Base::Wrapped_ParseTupleAndKeywords(args,
|
| | kwd,
|
| | "ss|sethO!O!O!O",
|
| | kwlist,
|
| | &sType,
|
| | &sName,
|
| | &sGroup,
|
| | "utf-8",
|
| | &sDoc,
|
| | &attr,
|
| | &PyBool_Type,
|
| | &ro,
|
| | &PyBool_Type,
|
| | &hd,
|
| | &PyBool_Type,
|
| | &lk,
|
| | &enumVals)) {
|
| | return nullptr;
|
| | }
|
| |
|
| | if (sDoc) {
|
| | sDocStr = sDoc;
|
| | PyMem_Free(sDoc);
|
| | }
|
| |
|
| | Property* prop = getDocumentPtr()->addDynamicProperty(sType,
|
| | sName,
|
| | sGroup,
|
| | sDocStr.c_str(),
|
| | attr,
|
| | Base::asBoolean(ro),
|
| | Base::asBoolean(hd));
|
| | prop->setStatus(Property::LockDynamic, Base::asBoolean(lk));
|
| |
|
| |
|
| | auto* propEnum = dynamic_cast<App::PropertyEnumeration*>(prop);
|
| | if (propEnum && enumVals) {
|
| | propEnum->setPyObject(enumVals);
|
| | }
|
| |
|
| | return Py::new_reference_to(this);
|
| | }
|
| |
|
| | PyObject* DocumentPy::removeProperty(PyObject* args)
|
| | {
|
| | char* sName;
|
| | if (!PyArg_ParseTuple(args, "s", &sName)) {
|
| | return nullptr;
|
| | }
|
| |
|
| | bool ok = getDocumentPtr()->removeDynamicProperty(sName);
|
| | return Py_BuildValue("O", (ok ? Py_True : Py_False));
|
| | }
|
| |
|
| |
|
| | std::string DocumentPy::representation() const
|
| | {
|
| | std::stringstream str;
|
| | str << "<Document '" << getDocumentPtr()->getName() << "' (" << getDocumentPtr()->Label.getValue() << ") >";
|
| |
|
| | return str.str();
|
| | }
|
| |
|
| | PyObject* DocumentPy::save(PyObject* args)
|
| | {
|
| | if (!PyArg_ParseTuple(args, "")) {
|
| | return nullptr;
|
| | }
|
| |
|
| | PY_TRY
|
| | {
|
| | if (!getDocumentPtr()->save()) {
|
| | PyErr_SetString(PyExc_ValueError, "Object attribute 'FileName' is not set");
|
| | return nullptr;
|
| | }
|
| | }
|
| | PY_CATCH;
|
| |
|
| | const char* filename = getDocumentPtr()->FileName.getValue();
|
| | Base::FileInfo fi(filename);
|
| | if (!fi.isReadable()) {
|
| | PyErr_Format(PyExc_IOError, "No such file or directory: '%s'", filename);
|
| | return nullptr;
|
| | }
|
| |
|
| | Py_Return;
|
| | }
|
| |
|
| | PyObject* DocumentPy::saveAs(PyObject* args)
|
| | {
|
| | char* fn;
|
| | if (!PyArg_ParseTuple(args, "et", "utf-8", &fn)) {
|
| | return nullptr;
|
| | }
|
| |
|
| | std::string utf8Name = fn;
|
| | PyMem_Free(fn);
|
| |
|
| | PY_TRY
|
| | {
|
| | getDocumentPtr()->saveAs(utf8Name.c_str());
|
| | Py_Return;
|
| | }
|
| | PY_CATCH
|
| | }
|
| |
|
| | PyObject* DocumentPy::saveCopy(PyObject* args)
|
| | {
|
| | char* fn;
|
| | if (!PyArg_ParseTuple(args, "s", &fn)) {
|
| | return nullptr;
|
| | }
|
| |
|
| | PY_TRY
|
| | {
|
| | getDocumentPtr()->saveCopy(fn);
|
| | Py_Return;
|
| | }
|
| | PY_CATCH
|
| | }
|
| |
|
| | PyObject* DocumentPy::load(PyObject* args)
|
| | {
|
| | char* filename = nullptr;
|
| | if (!PyArg_ParseTuple(args, "s", &filename)) {
|
| | return nullptr;
|
| | }
|
| | if (!filename || *filename == '\0') {
|
| | PyErr_Format(PyExc_ValueError, "Path is empty");
|
| | return nullptr;
|
| | }
|
| |
|
| | getDocumentPtr()->FileName.setValue(filename);
|
| | Base::FileInfo fi(filename);
|
| | if (!fi.isReadable()) {
|
| | PyErr_Format(PyExc_IOError, "No such file or directory: '%s'", filename);
|
| | return nullptr;
|
| | }
|
| | try {
|
| | getDocumentPtr()->restore();
|
| | }
|
| | catch (...) {
|
| | PyErr_Format(PyExc_IOError, "Reading from file '%s' failed", filename);
|
| | return nullptr;
|
| | }
|
| | Py_Return;
|
| | }
|
| |
|
| | PyObject* DocumentPy::restore(PyObject* args)
|
| | {
|
| | if (!PyArg_ParseTuple(args, "")) {
|
| | return nullptr;
|
| | }
|
| | const char* filename = getDocumentPtr()->FileName.getValue();
|
| | if (!filename || *filename == '\0') {
|
| | PyErr_Format(PyExc_ValueError, "Object attribute 'FileName' is not set");
|
| | return nullptr;
|
| | }
|
| | Base::FileInfo fi(filename);
|
| | if (!fi.isReadable()) {
|
| | PyErr_Format(PyExc_IOError, "No such file or directory: '%s'", filename);
|
| | return nullptr;
|
| | }
|
| | try {
|
| | getDocumentPtr()->restore();
|
| | }
|
| | catch (...) {
|
| | PyErr_Format(PyExc_IOError, "Reading from file '%s' failed", filename);
|
| | return nullptr;
|
| | }
|
| | Py_Return;
|
| | }
|
| |
|
| | PyObject* DocumentPy::isSaved(PyObject* args)
|
| | {
|
| | if (!PyArg_ParseTuple(args, "")) {
|
| | return nullptr;
|
| | }
|
| | bool ok = getDocumentPtr()->isSaved();
|
| | return Py::new_reference_to(Py::Boolean(ok));
|
| | }
|
| |
|
| | PyObject* DocumentPy::getProgramVersion(PyObject* args)
|
| | {
|
| | if (!PyArg_ParseTuple(args, "")) {
|
| | return nullptr;
|
| | }
|
| | const char* version = getDocumentPtr()->getProgramVersion();
|
| | return Py::new_reference_to(Py::String(version));
|
| | }
|
| |
|
| | PyObject* DocumentPy::getFileName(PyObject* args)
|
| | {
|
| | if (!PyArg_ParseTuple(args, "")) {
|
| | return nullptr;
|
| | }
|
| | const char* fn = getDocumentPtr()->getFileName();
|
| | return Py::new_reference_to(Py::String(fn));
|
| | }
|
| |
|
| | PyObject* DocumentPy::getUniqueObjectName(PyObject* args)
|
| | {
|
| | char* sName;
|
| | if (!PyArg_ParseTuple(args, "s", &sName)) {
|
| | return nullptr;
|
| | }
|
| | PY_TRY
|
| | {
|
| | auto newName = getDocumentPtr()->getUniqueObjectName(sName);
|
| | return Py::new_reference_to(Py::String(newName));
|
| | }
|
| | PY_CATCH;
|
| | }
|
| |
|
| | PyObject* DocumentPy::mergeProject(PyObject* args)
|
| | {
|
| | char* filename;
|
| | if (!PyArg_ParseTuple(args, "s", &filename)) {
|
| | return nullptr;
|
| | }
|
| |
|
| | PY_TRY
|
| | {
|
| | Base::FileInfo fi(filename);
|
| | Base::ifstream str(fi, std::ios::in | std::ios::binary);
|
| | App::Document* doc = getDocumentPtr();
|
| | MergeDocuments md(doc);
|
| | md.importObjects(str);
|
| | Py_Return;
|
| | }
|
| | PY_CATCH;
|
| | }
|
| |
|
| | PyObject* DocumentPy::exportGraphviz(PyObject* args)
|
| | {
|
| | char* fn = nullptr;
|
| | if (!PyArg_ParseTuple(args, "|s", &fn)) {
|
| | return nullptr;
|
| | }
|
| | if (fn) {
|
| | Base::FileInfo fi(fn);
|
| | Base::ofstream str(fi);
|
| | getDocumentPtr()->exportGraphviz(str);
|
| | str.close();
|
| | Py_Return;
|
| | }
|
| | else {
|
| | std::stringstream str;
|
| | getDocumentPtr()->exportGraphviz(str);
|
| | return PyUnicode_FromString(str.str().c_str());
|
| | }
|
| | }
|
| |
|
| | PyObject* DocumentPy::addObject(PyObject* args, PyObject* kwd)
|
| | {
|
| | char *sType, *sName = nullptr, *sViewType = nullptr;
|
| | PyObject* obj = nullptr;
|
| | PyObject* view = nullptr;
|
| | PyObject* attach = Py_False;
|
| | static const std::array<const char*, 7>
|
| | kwlist {"type", "name", "objProxy", "viewProxy", "attach", "viewType", nullptr};
|
| | if (!Base::Wrapped_ParseTupleAndKeywords(args,
|
| | kwd,
|
| | "s|sOOO!s",
|
| | kwlist,
|
| | &sType,
|
| | &sName,
|
| | &obj,
|
| | &view,
|
| | &PyBool_Type,
|
| | &attach,
|
| | &sViewType)) {
|
| | return nullptr;
|
| | }
|
| |
|
| | DocumentObject* pcFtr = nullptr;
|
| |
|
| | if (!obj || !Base::asBoolean(attach)) {
|
| | pcFtr = getDocumentPtr()->addObject(sType, sName, true, sViewType);
|
| | }
|
| | else {
|
| | Base::Type type =
|
| | Base::Type::getTypeIfDerivedFrom(sType, DocumentObject::getClassTypeId(), true);
|
| | if (type.isBad()) {
|
| | std::stringstream str;
|
| | str << "'" << sType << "' is not a document object type";
|
| | throw Base::TypeError(str.str());
|
| | }
|
| | pcFtr = static_cast<DocumentObject*>(type.createInstance());
|
| | }
|
| |
|
| | if (!pcFtr) {
|
| | std::stringstream str;
|
| | str << "No document object found of type '" << sType << "'" << std::ends;
|
| | throw Py::TypeError(str.str());
|
| | }
|
| |
|
| | if (obj) {
|
| | try {
|
| |
|
| | Py::Object pyftr = Py::asObject(pcFtr->getPyObject());
|
| |
|
| | Py::Object pyobj(obj);
|
| | if (pyobj.hasAttr("__object__")) {
|
| | pyobj.setAttr("__object__", pyftr);
|
| | }
|
| | pyftr.setAttr("Proxy", pyobj);
|
| |
|
| | if (Base::asBoolean(attach)) {
|
| | getDocumentPtr()->addObject(pcFtr, sName);
|
| |
|
| | try {
|
| | Py::Callable method(pyobj.getAttr("attach"));
|
| | if (!method.isNone()) {
|
| | Py::TupleN arg(pyftr);
|
| | method.apply(arg);
|
| | }
|
| | }
|
| | catch (Py::Exception&) {
|
| | Base::PyException e;
|
| | e.reportException();
|
| | }
|
| | }
|
| |
|
| |
|
| |
|
| | Py::Object pyvp;
|
| | if (view) {
|
| | pyvp = Py::Object(view);
|
| | }
|
| | if (pyvp.isNone()) {
|
| | pyvp = Py::Long(1);
|
| | }
|
| |
|
| | if (pyvp.hasAttr("__vobject__")) {
|
| | pyvp.setAttr("__vobject__", pyftr.getAttr("ViewObject"));
|
| | }
|
| |
|
| | Py::Object pyprx(pyftr.getAttr("ViewObject"));
|
| | pyprx.setAttr("Proxy", pyvp);
|
| | return Py::new_reference_to(pyftr);
|
| | }
|
| | catch (Py::Exception& e) {
|
| | e.clear();
|
| | }
|
| | }
|
| | return pcFtr->getPyObject();
|
| | }
|
| |
|
| | PyObject* DocumentPy::removeObject(PyObject* args)
|
| | {
|
| | char* sName;
|
| | if (!PyArg_ParseTuple(args, "s", &sName)) {
|
| | return nullptr;
|
| | }
|
| |
|
| |
|
| | DocumentObject* pcFtr = getDocumentPtr()->getObject(sName);
|
| | if (pcFtr) {
|
| | getDocumentPtr()->removeObject(sName);
|
| | Py_Return;
|
| | }
|
| | else {
|
| | std::stringstream str;
|
| | str << "No document object found with name '" << sName << "'" << std::ends;
|
| | throw Py::ValueError(str.str());
|
| | }
|
| | }
|
| |
|
| | PyObject* DocumentPy::copyObject(PyObject* args, PyObject* kwd)
|
| | {
|
| | PyObject* obj;
|
| | PyObject* rec = Py_False;
|
| | PyObject* retAll = Py_False;
|
| | static constexpr std::array<const char*, 4> kwlist {"object", "recursive", "return_all", nullptr};
|
| | if (!Base::Wrapped_ParseTupleAndKeywords(args,
|
| | kwd,
|
| | "O|O!O!",
|
| | kwlist,
|
| | &obj,
|
| | &PyBool_Type,
|
| | &rec,
|
| | &PyBool_Type,
|
| | &retAll)) {
|
| | return nullptr;
|
| | }
|
| |
|
| | std::vector<App::DocumentObject*> objs;
|
| | bool single = false;
|
| | if (PySequence_Check(obj)) {
|
| | Py::Sequence seq(obj);
|
| | for (Py_ssize_t i = 0; i < seq.size(); ++i) {
|
| | if (!PyObject_TypeCheck(seq[i].ptr(), &DocumentObjectPy::Type)) {
|
| | PyErr_SetString(PyExc_TypeError,
|
| | "Expect element in sequence to be of type document object");
|
| | return nullptr;
|
| | }
|
| | objs.push_back(static_cast<DocumentObjectPy*>(seq[i].ptr())->getDocumentObjectPtr());
|
| | }
|
| | }
|
| | else if (!PyObject_TypeCheck(obj, &DocumentObjectPy::Type)) {
|
| | PyErr_SetString(
|
| | PyExc_TypeError,
|
| | "Expect first argument to be either a document object or sequence of document objects");
|
| | return nullptr;
|
| | }
|
| | else {
|
| | objs.push_back(static_cast<DocumentObjectPy*>(obj)->getDocumentObjectPtr());
|
| | single = true;
|
| | }
|
| |
|
| | PY_TRY
|
| | {
|
| | auto ret =
|
| | getDocumentPtr()->copyObject(objs, Base::asBoolean(rec), Base::asBoolean(retAll));
|
| | if (ret.size() == 1 && single) {
|
| | return ret[0]->getPyObject();
|
| | }
|
| |
|
| | Py::Tuple tuple(ret.size());
|
| | for (size_t i = 0; i < ret.size(); ++i) {
|
| | tuple.setItem(i, Py::Object(ret[i]->getPyObject(), true));
|
| | }
|
| | return Py::new_reference_to(tuple);
|
| | }
|
| | PY_CATCH
|
| | }
|
| |
|
| | PyObject* DocumentPy::importLinks(PyObject* args)
|
| | {
|
| | PyObject* obj = Py_None;
|
| | if (!PyArg_ParseTuple(args, "|O", &obj)) {
|
| | return nullptr;
|
| | }
|
| |
|
| | std::vector<App::DocumentObject*> objs;
|
| | if (PySequence_Check(obj)) {
|
| | Py::Sequence seq(obj);
|
| | for (Py_ssize_t i = 0; i < seq.size(); ++i) {
|
| | if (!PyObject_TypeCheck(seq[i].ptr(), &DocumentObjectPy::Type)) {
|
| | PyErr_SetString(PyExc_TypeError,
|
| | "Expect element in sequence to be of type document object");
|
| | return nullptr;
|
| | }
|
| | objs.push_back(static_cast<DocumentObjectPy*>(seq[i].ptr())->getDocumentObjectPtr());
|
| | }
|
| | }
|
| | else {
|
| | Base::PyTypeCheck(&obj,
|
| | &DocumentObjectPy::Type,
|
| | "Expect first argument to be either a document object, sequence of "
|
| | "document objects or None");
|
| | if (obj) {
|
| | objs.push_back(static_cast<DocumentObjectPy*>(obj)->getDocumentObjectPtr());
|
| | }
|
| | }
|
| |
|
| | if (objs.empty()) {
|
| | objs = getDocumentPtr()->getObjects();
|
| | }
|
| |
|
| | PY_TRY
|
| | {
|
| | auto ret = getDocumentPtr()->importLinks(objs);
|
| |
|
| | Py::Tuple tuple(ret.size());
|
| | for (size_t i = 0; i < ret.size(); ++i) {
|
| | tuple.setItem(i, Py::Object(ret[i]->getPyObject(), true));
|
| | }
|
| | return Py::new_reference_to(tuple);
|
| | }
|
| | PY_CATCH
|
| | }
|
| |
|
| | PyObject* DocumentPy::moveObject(PyObject* args)
|
| | {
|
| | PyObject *obj, *rec = Py_False;
|
| | if (!PyArg_ParseTuple(args, "O!|O!", &(DocumentObjectPy::Type), &obj, &PyBool_Type, &rec)) {
|
| | return nullptr;
|
| | }
|
| |
|
| | DocumentObjectPy* docObj = static_cast<DocumentObjectPy*>(obj);
|
| | DocumentObject* move =
|
| | getDocumentPtr()->moveObject(docObj->getDocumentObjectPtr(), Base::asBoolean(rec));
|
| | if (move) {
|
| | return move->getPyObject();
|
| | }
|
| | else {
|
| | std::string str("Failed to move the object");
|
| | throw Py::ValueError(str);
|
| | }
|
| | }
|
| |
|
| | PyObject* DocumentPy::openTransaction(PyObject* args)
|
| | {
|
| | PyObject* value = nullptr;
|
| | if (!PyArg_ParseTuple(args, "|O", &value)) {
|
| | return nullptr;
|
| | }
|
| | std::string cmd;
|
| |
|
| |
|
| | if (!value) {
|
| | cmd = "<empty>";
|
| | }
|
| | else if (PyUnicode_Check(value)) {
|
| | cmd = PyUnicode_AsUTF8(value);
|
| | }
|
| | else {
|
| | PyErr_SetString(PyExc_TypeError, "string or unicode expected");
|
| | return nullptr;
|
| | }
|
| |
|
| | getDocumentPtr()->openTransaction(cmd.c_str());
|
| | Py_Return;
|
| | }
|
| |
|
| | PyObject* DocumentPy::abortTransaction(PyObject* args)
|
| | {
|
| | if (!PyArg_ParseTuple(args, "")) {
|
| | return nullptr;
|
| | }
|
| | getDocumentPtr()->abortTransaction();
|
| | Py_Return;
|
| | }
|
| |
|
| | PyObject* DocumentPy::commitTransaction(PyObject* args)
|
| | {
|
| | if (!PyArg_ParseTuple(args, "")) {
|
| | return nullptr;
|
| | }
|
| | getDocumentPtr()->commitTransaction();
|
| | Py_Return;
|
| | }
|
| |
|
| | Py::Boolean DocumentPy::getHasPendingTransaction() const
|
| | {
|
| | return {getDocumentPtr()->hasPendingTransaction()};
|
| | }
|
| |
|
| | PyObject* DocumentPy::undo(PyObject* args)
|
| | {
|
| | if (!PyArg_ParseTuple(args, "")) {
|
| | return nullptr;
|
| | }
|
| | if (getDocumentPtr()->getAvailableUndos()) {
|
| | getDocumentPtr()->undo();
|
| | }
|
| | Py_Return;
|
| | }
|
| |
|
| | PyObject* DocumentPy::redo(PyObject* args)
|
| | {
|
| | if (!PyArg_ParseTuple(args, "")) {
|
| | return nullptr;
|
| | }
|
| | if (getDocumentPtr()->getAvailableRedos()) {
|
| | getDocumentPtr()->redo();
|
| | }
|
| | Py_Return;
|
| | }
|
| |
|
| | PyObject* DocumentPy::clearUndos(PyObject* args)
|
| | {
|
| | if (!PyArg_ParseTuple(args, "")) {
|
| | return nullptr;
|
| | }
|
| | getDocumentPtr()->clearUndos();
|
| | Py_Return;
|
| | }
|
| |
|
| | PyObject* DocumentPy::clearDocument(PyObject* args)
|
| | {
|
| | if (!PyArg_ParseTuple(args, "")) {
|
| | return nullptr;
|
| | }
|
| | getDocumentPtr()->clearDocument();
|
| | Py_Return;
|
| | }
|
| |
|
| | PyObject* DocumentPy::setClosable(PyObject* args)
|
| | {
|
| | PyObject* close;
|
| | if (!PyArg_ParseTuple(args, "O!", &PyBool_Type, &close)) {
|
| | return nullptr;
|
| | }
|
| | getDocumentPtr()->setClosable(Base::asBoolean(close));
|
| | Py_Return;
|
| | }
|
| |
|
| | PyObject* DocumentPy::isClosable(PyObject* args)
|
| | {
|
| | if (!PyArg_ParseTuple(args, "")) {
|
| | return nullptr;
|
| | }
|
| | bool ok = getDocumentPtr()->isClosable();
|
| | return Py::new_reference_to(Py::Boolean(ok));
|
| | }
|
| |
|
| | PyObject *DocumentPy::setAutoCreated(PyObject *args)
|
| | {
|
| | PyObject *autoCreated;
|
| | if (!PyArg_ParseTuple(args, "O!", &PyBool_Type, &autoCreated)) {
|
| | return nullptr;
|
| | }
|
| | bool value = (autoCreated == Py_True);
|
| | getDocumentPtr()->setAutoCreated(value);
|
| |
|
| | Py_RETURN_NONE;
|
| | }
|
| |
|
| | PyObject *DocumentPy::isAutoCreated(PyObject *args)
|
| | {
|
| | if (!PyArg_ParseTuple(args, "")) {
|
| | return nullptr;
|
| | }
|
| | bool ok = getDocumentPtr()->isAutoCreated();
|
| | return Py::new_reference_to(Py::Boolean(ok));
|
| | }
|
| |
|
| | PyObject* DocumentPy::recompute(PyObject* args)
|
| | {
|
| | PyObject* pyobjs = Py_None;
|
| | PyObject* force = Py_False;
|
| | PyObject* checkCycle = Py_False;
|
| | if (!PyArg_ParseTuple(args,
|
| | "|OO!O!",
|
| | &pyobjs,
|
| | &PyBool_Type,
|
| | &force,
|
| | &PyBool_Type,
|
| | &checkCycle)) {
|
| | return nullptr;
|
| | }
|
| |
|
| | PY_TRY
|
| | {
|
| | std::vector<App::DocumentObject*> objs;
|
| | if (pyobjs != Py_None) {
|
| | if (!PySequence_Check(pyobjs)) {
|
| | PyErr_SetString(PyExc_TypeError, "expect input of sequence of document objects");
|
| | return nullptr;
|
| | }
|
| |
|
| | Py::Sequence seq(pyobjs);
|
| | for (Py_ssize_t i = 0; i < seq.size(); ++i) {
|
| | if (!PyObject_TypeCheck(seq[i].ptr(), &DocumentObjectPy::Type)) {
|
| | PyErr_SetString(PyExc_TypeError,
|
| | "Expect element in sequence to be of type document object");
|
| | return nullptr;
|
| | }
|
| | objs.push_back(
|
| | static_cast<DocumentObjectPy*>(seq[i].ptr())->getDocumentObjectPtr());
|
| | }
|
| | }
|
| |
|
| | int options = 0;
|
| | if (Base::asBoolean(checkCycle)) {
|
| | options = Document::DepNoCycle;
|
| | }
|
| |
|
| | int objectCount =
|
| | getDocumentPtr()->recompute(objs, Base::asBoolean(force), nullptr, options);
|
| |
|
| |
|
| |
|
| | if (PyErr_Occurred()) {
|
| | return nullptr;
|
| | }
|
| |
|
| | return Py::new_reference_to(Py::Long(objectCount));
|
| | }
|
| | PY_CATCH;
|
| | }
|
| |
|
| | PyObject* DocumentPy::mustExecute(PyObject* args)
|
| | {
|
| | if (!PyArg_ParseTuple(args, "")) {
|
| | return nullptr;
|
| | }
|
| | bool ok = getDocumentPtr()->mustExecute();
|
| | return Py::new_reference_to(Py::Boolean(ok));
|
| | }
|
| |
|
| | PyObject* DocumentPy::isTouched(PyObject* args)
|
| | {
|
| | if (!PyArg_ParseTuple(args, "")) {
|
| | return nullptr;
|
| | }
|
| | bool ok = getDocumentPtr()->isTouched();
|
| | return Py::new_reference_to(Py::Boolean(ok));
|
| | }
|
| |
|
| | PyObject* DocumentPy::purgeTouched(PyObject* args)
|
| | {
|
| | if (!PyArg_ParseTuple(args, "")) {
|
| | return nullptr;
|
| | }
|
| | getDocumentPtr()->purgeTouched();
|
| | Py_Return;
|
| | }
|
| |
|
| | PyObject* DocumentPy::getObject(PyObject* args)
|
| | {
|
| | DocumentObject* obj = nullptr;
|
| |
|
| | do {
|
| | char* name = nullptr;
|
| | if (PyArg_ParseTuple(args, "s", &name)) {
|
| | obj = getDocumentPtr()->getObject(name);
|
| | break;
|
| | }
|
| |
|
| | PyErr_Clear();
|
| | long id = -1;
|
| | if (PyArg_ParseTuple(args, "l", &id)) {
|
| | obj = getDocumentPtr()->getObjectByID(id);
|
| | break;
|
| | }
|
| |
|
| | PyErr_SetString(PyExc_TypeError, "a string or integer is required");
|
| | return nullptr;
|
| | } while (false);
|
| |
|
| | if (obj) {
|
| | return obj->getPyObject();
|
| | }
|
| |
|
| | Py_Return;
|
| | }
|
| |
|
| | PyObject* DocumentPy::getObjectsByLabel(PyObject* args)
|
| | {
|
| | char* sName;
|
| | if (!PyArg_ParseTuple(args, "s", &sName)) {
|
| | return nullptr;
|
| | }
|
| |
|
| | Py::List list;
|
| | std::string name = sName;
|
| | std::vector<DocumentObject*> objs = getDocumentPtr()->getObjects();
|
| | for (auto obj : objs) {
|
| | if (name == obj->Label.getValue()) {
|
| | list.append(Py::asObject(obj->getPyObject()));
|
| | }
|
| | }
|
| |
|
| | return Py::new_reference_to(list);
|
| | }
|
| |
|
| | PyObject* DocumentPy::findObjects(PyObject* args, PyObject* kwds)
|
| | {
|
| | const char *sType = "App::DocumentObject", *sName = nullptr, *sLabel = nullptr;
|
| | static const std::array<const char*, 4> kwlist {"Type", "Name", "Label", nullptr};
|
| | if (!Base::Wrapped_ParseTupleAndKeywords(args, kwds, "|sss", kwlist, &sType, &sName, &sLabel)) {
|
| | return nullptr;
|
| | }
|
| |
|
| | Base::Type type =
|
| | Base::Type::getTypeIfDerivedFrom(sType, App::DocumentObject::getClassTypeId(), true);
|
| | if (type.isBad()) {
|
| | std::stringstream str;
|
| | str << "'" << sType << "' is not a document object type";
|
| | throw Base::TypeError(str.str());
|
| | }
|
| |
|
| | std::vector<DocumentObject*> res;
|
| |
|
| | try {
|
| | res = getDocumentPtr()->findObjects(type, sName, sLabel);
|
| | }
|
| | catch (const boost::regex_error& e) {
|
| | PyErr_SetString(PyExc_RuntimeError, e.what());
|
| | return nullptr;
|
| | }
|
| |
|
| | Py_ssize_t index = 0;
|
| | PyObject* list = PyList_New((Py_ssize_t)res.size());
|
| | for (std::vector<DocumentObject*>::const_iterator It = res.begin(); It != res.end();
|
| | ++It, index++) {
|
| | PyList_SetItem(list, index, (*It)->getPyObject());
|
| | }
|
| | return list;
|
| | }
|
| |
|
| | Py::Object DocumentPy::getActiveObject() const
|
| | {
|
| | DocumentObject* pcFtr = getDocumentPtr()->getActiveObject();
|
| | if (pcFtr) {
|
| | return Py::Object(pcFtr->getPyObject(), true);
|
| | }
|
| | return Py::None();
|
| | }
|
| |
|
| | PyObject* DocumentPy::supportedTypes(PyObject* args)
|
| | {
|
| | if (!PyArg_ParseTuple(args, "")) {
|
| | return nullptr;
|
| | }
|
| |
|
| | std::vector<Base::Type> ary;
|
| | Base::Type::getAllDerivedFrom(App::DocumentObject::getClassTypeId(), ary);
|
| | Py::List res;
|
| | for (const auto& it : ary) {
|
| | res.append(Py::String(it.getName()));
|
| | }
|
| | return Py::new_reference_to(res);
|
| | }
|
| |
|
| | Py::List DocumentPy::getObjects() const
|
| | {
|
| | std::vector<DocumentObject*> objs = getDocumentPtr()->getObjects();
|
| | Py::List res;
|
| |
|
| | for (auto obj : objs) {
|
| |
|
| |
|
| | res.append(Py::Object(obj->getPyObject(), true));
|
| | }
|
| |
|
| | return res;
|
| | }
|
| |
|
| | Py::List DocumentPy::getTopologicalSortedObjects() const
|
| | {
|
| | std::vector<DocumentObject*> objs = getDocumentPtr()->topologicalSort();
|
| | Py::List res;
|
| |
|
| | for (auto obj : objs) {
|
| |
|
| |
|
| | res.append(Py::Object(obj->getPyObject(), true));
|
| | }
|
| |
|
| | return res;
|
| | }
|
| |
|
| | Py::List DocumentPy::getRootObjects() const
|
| | {
|
| | std::vector<DocumentObject*> objs = getDocumentPtr()->getRootObjects();
|
| | Py::List res;
|
| |
|
| | for (auto obj : objs) {
|
| |
|
| |
|
| | res.append(Py::Object(obj->getPyObject(), true));
|
| | }
|
| |
|
| | return res;
|
| | }
|
| |
|
| | Py::List DocumentPy::getRootObjectsIgnoreLinks() const
|
| | {
|
| | std::vector<App::DocumentObject*> objs = getDocumentPtr()->getRootObjectsIgnoreLinks();
|
| | Py::List res;
|
| |
|
| | for (auto obj : objs) {
|
| |
|
| |
|
| | res.append(Py::Object(obj->getPyObject(), true));
|
| | }
|
| |
|
| | return res;
|
| | }
|
| |
|
| | Py::Long DocumentPy::getUndoMode() const
|
| | {
|
| | return Py::Long(getDocumentPtr()->getUndoMode());
|
| | }
|
| |
|
| | void DocumentPy::setUndoMode(Py::Long arg)
|
| | {
|
| | getDocumentPtr()->setUndoMode(arg);
|
| | }
|
| |
|
| |
|
| | Py::Long DocumentPy::getUndoRedoMemSize() const
|
| | {
|
| | return Py::Long((long)getDocumentPtr()->getUndoMemSize());
|
| | }
|
| |
|
| | Py::Long DocumentPy::getUndoCount() const
|
| | {
|
| | return Py::Long((long)getDocumentPtr()->getAvailableUndos());
|
| | }
|
| |
|
| | Py::Long DocumentPy::getRedoCount() const
|
| | {
|
| | return Py::Long((long)getDocumentPtr()->getAvailableRedos());
|
| | }
|
| |
|
| | Py::List DocumentPy::getUndoNames() const
|
| | {
|
| | std::vector<std::string> vList = getDocumentPtr()->getAvailableUndoNames();
|
| | Py::List res;
|
| |
|
| | for (const auto& It : vList) {
|
| | res.append(Py::String(It));
|
| | }
|
| |
|
| | return res;
|
| | }
|
| |
|
| | Py::List DocumentPy::getRedoNames() const
|
| | {
|
| | std::vector<std::string> vList = getDocumentPtr()->getAvailableRedoNames();
|
| | Py::List res;
|
| |
|
| | for (const auto& It : vList) {
|
| | res.append(Py::String(It));
|
| | }
|
| |
|
| | return res;
|
| | }
|
| |
|
| | Py::String DocumentPy::getDependencyGraph() const
|
| | {
|
| | std::stringstream out;
|
| | getDocumentPtr()->exportGraphviz(out);
|
| | return {out.str()};
|
| | }
|
| |
|
| | Py::String DocumentPy::getName() const
|
| | {
|
| | return {getDocumentPtr()->getName()};
|
| | }
|
| |
|
| | Py::Boolean DocumentPy::getRecomputesFrozen() const
|
| | {
|
| | return {getDocumentPtr()->testStatus(Document::Status::SkipRecompute)};
|
| | }
|
| |
|
| | void DocumentPy::setRecomputesFrozen(Py::Boolean arg)
|
| | {
|
| | getDocumentPtr()->setStatus(Document::Status::SkipRecompute, arg.isTrue());
|
| | }
|
| |
|
| | PyObject* DocumentPy::getTempFileName(PyObject* args)
|
| | {
|
| | PyObject* value;
|
| | if (!PyArg_ParseTuple(args, "O", &value)) {
|
| | return nullptr;
|
| | }
|
| |
|
| | std::string string;
|
| | if (PyUnicode_Check(value)) {
|
| | string = PyUnicode_AsUTF8(value);
|
| | }
|
| | else {
|
| | std::string error = std::string("type must be a string!");
|
| | error += value->ob_type->tp_name;
|
| | throw Py::TypeError(error);
|
| | }
|
| |
|
| |
|
| | Base::FileInfo fileName(
|
| | Base::FileInfo::getTempFileName(string.c_str(), getDocumentPtr()->TransientDir.getValue()));
|
| |
|
| | fileName.deleteFile();
|
| |
|
| | PyObject* p =
|
| | PyUnicode_DecodeUTF8(fileName.filePath().c_str(), fileName.filePath().size(), nullptr);
|
| | if (!p) {
|
| | throw Base::UnicodeError("UTF8 conversion failure at PropertyString::getPyObject()");
|
| | }
|
| | return p;
|
| | }
|
| |
|
| | PyObject* DocumentPy::getCustomAttributes(const char* attr) const
|
| | {
|
| |
|
| |
|
| |
|
| |
|
| |
|
| | App::Property* prop = getPropertyContainerPtr()->getPropertyByName(attr);
|
| | if (prop) {
|
| | return nullptr;
|
| | }
|
| | if (!this->ob_type->tp_dict) {
|
| | if (PyType_Ready(this->ob_type) < 0) {
|
| | return nullptr;
|
| | }
|
| | }
|
| | PyObject* item = PyDict_GetItemString(this->ob_type->tp_dict, attr);
|
| | if (item) {
|
| | return nullptr;
|
| | }
|
| |
|
| | DocumentObject* obj = getDocumentPtr()->getObject(attr);
|
| | return (obj ? obj->getPyObject() : nullptr);
|
| | }
|
| |
|
| | int DocumentPy::setCustomAttributes(const char* attr, PyObject*)
|
| | {
|
| |
|
| |
|
| |
|
| |
|
| |
|
| | App::Property* prop = getPropertyContainerPtr()->getPropertyByName(attr);
|
| | if (prop) {
|
| | return 0;
|
| | }
|
| | if (!this->ob_type->tp_dict) {
|
| | if (PyType_Ready(this->ob_type) < 0) {
|
| | return 0;
|
| | }
|
| | }
|
| | PyObject* item = PyDict_GetItemString(this->ob_type->tp_dict, attr);
|
| | if (item) {
|
| | return 0;
|
| | }
|
| | DocumentObject* obj = getDocumentPtr()->getObject(attr);
|
| | if (obj) {
|
| | std::stringstream str;
|
| | str << "'Document' object attribute '" << attr << "' must not be set this way" << std::ends;
|
| | PyErr_SetString(PyExc_RuntimeError, str.str().c_str());
|
| | return -1;
|
| | }
|
| |
|
| | return 0;
|
| | }
|
| |
|
| | PyObject* DocumentPy::getLinksTo(PyObject* args)
|
| | {
|
| | PyObject* pyobj = Py_None;
|
| | int options = 0;
|
| | short count = 0;
|
| | if (!PyArg_ParseTuple(args, "|Oih", &pyobj, &options, &count)) {
|
| | return nullptr;
|
| | }
|
| |
|
| | PY_TRY
|
| | {
|
| | Base::PyTypeCheck(&pyobj,
|
| | &DocumentObjectPy::Type,
|
| | "Expect the first argument of type document object");
|
| | DocumentObject* obj = nullptr;
|
| | if (pyobj) {
|
| | obj = static_cast<DocumentObjectPy*>(pyobj)->getDocumentObjectPtr();
|
| | }
|
| |
|
| | std::set<DocumentObject*> links;
|
| | getDocumentPtr()->getLinksTo(links, obj, options, count);
|
| | Py::Tuple ret(links.size());
|
| | int i = 0;
|
| | for (auto o : links) {
|
| | ret.setItem(i++, Py::Object(o->getPyObject(), true));
|
| | }
|
| |
|
| | return Py::new_reference_to(ret);
|
| | }
|
| | PY_CATCH
|
| | }
|
| |
|
| | Py::List DocumentPy::getInList() const
|
| | {
|
| | Py::List ret;
|
| | auto lists = PropertyXLink::getDocumentInList(getDocumentPtr());
|
| | if (lists.size() == 1) {
|
| | for (auto doc : lists.begin()->second) {
|
| | ret.append(Py::Object(doc->getPyObject(), true));
|
| | }
|
| | }
|
| | return ret;
|
| | }
|
| |
|
| | Py::List DocumentPy::getOutList() const
|
| | {
|
| | Py::List ret;
|
| | auto lists = PropertyXLink::getDocumentOutList(getDocumentPtr());
|
| | if (lists.size() == 1) {
|
| | for (auto doc : lists.begin()->second) {
|
| | ret.append(Py::Object(doc->getPyObject(), true));
|
| | }
|
| | }
|
| | return ret;
|
| | }
|
| |
|
| | PyObject* DocumentPy::getDependentDocuments(PyObject* args)
|
| | {
|
| | PyObject* sort = Py_True;
|
| | if (!PyArg_ParseTuple(args, "|O!", &PyBool_Type, &sort)) {
|
| | return nullptr;
|
| | }
|
| | PY_TRY
|
| | {
|
| | auto docs = getDocumentPtr()->getDependentDocuments(Base::asBoolean(sort));
|
| | Py::List ret;
|
| | for (auto doc : docs) {
|
| | ret.append(Py::Object(doc->getPyObject(), true));
|
| | }
|
| | return Py::new_reference_to(ret);
|
| | }
|
| | PY_CATCH;
|
| | }
|
| |
|
| | Py::Boolean DocumentPy::getRestoring() const
|
| | {
|
| | return {getDocumentPtr()->testStatus(Document::Status::Restoring)};
|
| | }
|
| |
|
| | Py::Boolean DocumentPy::getPartial() const
|
| | {
|
| | return {getDocumentPtr()->testStatus(Document::Status::PartialDoc)};
|
| | }
|
| |
|
| | Py::Boolean DocumentPy::getImporting() const
|
| | {
|
| | return {getDocumentPtr()->testStatus(Document::Status::Importing)};
|
| | }
|
| |
|
| | Py::Boolean DocumentPy::getRecomputing() const
|
| | {
|
| | return {getDocumentPtr()->testStatus(Document::Status::Recomputing)};
|
| | }
|
| |
|
| | Py::Boolean DocumentPy::getTransacting() const
|
| | {
|
| | return {getDocumentPtr()->isPerformingTransaction()};
|
| | }
|
| |
|
| | Py::String DocumentPy::getOldLabel() const
|
| | {
|
| | return {getDocumentPtr()->getOldLabel()};
|
| | }
|
| |
|
| | Py::Boolean DocumentPy::getTemporary() const
|
| | {
|
| | return {getDocumentPtr()->testStatus(Document::TempDoc)};
|
| | }
|
| |
|