PropertyPythonObject.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "PreCompiled.h"
00025
00026 #ifndef _PreComp_
00027 #endif
00028
00029 #include "PropertyPythonObject.h"
00030 #include "DocumentObjectPy.h"
00031 #include "DocumentObject.h"
00032 #include <Base/Base64.h>
00033 #include <Base/Writer.h>
00034 #include <Base/Reader.h>
00035 #include <Base/Console.h>
00036 #include <Base/Interpreter.h>
00037 #include <iostream>
00038
00039 using namespace App;
00040
00041
00042 TYPESYSTEM_SOURCE(App::PropertyPythonObject , App::Property);
00043
00044 PropertyPythonObject::PropertyPythonObject()
00045 {
00046 }
00047
00048 PropertyPythonObject::~PropertyPythonObject()
00049 {
00050
00051
00052 Base::PyGILStateLocker lock;
00053 this->object = Py::Object();
00054 }
00055
00056 void PropertyPythonObject::setValue(Py::Object o)
00057 {
00058 aboutToSetValue();
00059 this->object = o;
00060 hasSetValue();
00061 }
00062
00063 Py::Object PropertyPythonObject::getValue() const
00064 {
00065 return object;
00066 }
00067
00068 PyObject *PropertyPythonObject::getPyObject(void)
00069 {
00070 return Py::new_reference_to(this->object);
00071 }
00072
00073 void PropertyPythonObject::setPyObject(PyObject * obj)
00074 {
00075 aboutToSetValue();
00076 this->object = obj;
00077 hasSetValue();
00078 }
00079
00080 std::string PropertyPythonObject::toString() const
00081 {
00082 std::string repr;
00083 Base::PyGILStateLocker lock;
00084 try {
00085 Py::Module pickle(PyImport_ImportModule("cPickle"),true);
00086 Py::Callable method(pickle.getAttr(std::string("dumps")));
00087 Py::Tuple args(1);
00088 args.setItem(0, this->object);
00089 Py::Object res = method.apply(args);
00090 Py::String str(res);
00091 repr = str.as_std_string();
00092 }
00093 catch (Py::Exception&) {
00094 Base::PyException e;
00095 Base::Console().Warning("PropertyPythonObject::toString: %s\n", e.what());
00096 }
00097
00098 return repr;
00099 }
00100
00101 void PropertyPythonObject::fromString(const std::string& repr)
00102 {
00103 Base::PyGILStateLocker lock;
00104 try {
00105 Py::Module pickle(PyImport_ImportModule("cPickle"),true);
00106 Py::Callable method(pickle.getAttr(std::string("loads")));
00107 Py::Tuple args(1);
00108 args.setItem(0, Py::String(repr));
00109 Py::Object res = method.apply(args);
00110 this->object = res;
00111 }
00112 catch (Py::Exception&) {
00113 Base::PyException e;
00114 Base::Console().Warning("PropertyPythonObject::fromString: %s\n", e.what());
00115 }
00116 }
00117
00118 std::string PropertyPythonObject::encodeValue(const std::string& str) const
00119 {
00120 std::string tmp;
00121 for (std::string::const_iterator it = str.begin(); it != str.end(); ++it) {
00122 if (*it == '<')
00123 tmp += "<";
00124 else if (*it == '"')
00125 tmp += """;
00126 else if (*it == '&')
00127 tmp += "&";
00128 else if (*it == '>')
00129 tmp += ">";
00130 else if (*it == '\n')
00131 tmp += "\\n";
00132 else
00133 tmp += *it;
00134 }
00135
00136 return tmp;
00137 }
00138
00139 std::string PropertyPythonObject::decodeValue(const std::string& str) const
00140 {
00141 std::string tmp;
00142 for (std::string::const_iterator it = str.begin(); it != str.end(); ++it) {
00143 if (*it == '\\') {
00144 ++it;
00145 if (it != str.end() && *it == 'n') {
00146 tmp += '\n';
00147 }
00148 }
00149 else
00150 tmp += *it;
00151 }
00152
00153 return tmp;
00154 }
00155
00156 void PropertyPythonObject::saveObject(Base::Writer &writer) const
00157 {
00158 Base::PyGILStateLocker lock;
00159 try {
00160 PropertyContainer* parent = this->getContainer();
00161 if (parent->isDerivedFrom(Base::Type::fromName("App::DocumentObject"))) {
00162 if (this->object.hasAttr("__object__")) {
00163 writer.Stream() << " object=\"yes\"";
00164 }
00165 }
00166 if (parent->isDerivedFrom(Base::Type::fromName("Gui::ViewProvider"))) {
00167 if (this->object.hasAttr("__vobject__")) {
00168 writer.Stream() << " vobject=\"yes\"";
00169 }
00170 }
00171 }
00172 catch (Py::Exception& e) {
00173 e.clear();
00174 }
00175 }
00176
00177 void PropertyPythonObject::restoreObject(Base::XMLReader &reader)
00178 {
00179 Base::PyGILStateLocker lock;
00180 try {
00181 PropertyContainer* parent = this->getContainer();
00182 if (reader.hasAttribute("object")) {
00183 if (strcmp(reader.getAttribute("object"),"yes") == 0) {
00184 Py::Object obj = Py::asObject(parent->getPyObject());
00185 this->object.setAttr("__object__", obj);
00186 }
00187 }
00188 if (reader.hasAttribute("vobject")) {
00189 if (strcmp(reader.getAttribute("vobject"),"yes") == 0) {
00190 Py::Object obj = Py::asObject(parent->getPyObject());
00191 this->object.setAttr("__vobject__", obj);
00192 }
00193 }
00194 }
00195 catch (Py::Exception& e) {
00196 e.clear();
00197 }
00198 catch (const Base::Exception& e) {
00199 Base::Console().Error("%s\n",e.what());
00200 }
00201 catch (...) {
00202 Base::Console().Error("Critical error in PropertyPythonObject::restoreObject\n");
00203 }
00204 }
00205
00206 void PropertyPythonObject::Save (Base::Writer &writer) const
00207 {
00208
00209 std::string repr = this->toString();
00210 repr = Base::base64_encode((const unsigned char*)repr.c_str(), repr.size());
00211 std::string val = (repr);
00212 writer.Stream() << writer.ind() << "<Python value=\"" << val
00213 <<"\" encoded=\"yes\"";
00214 saveObject(writer);
00215 writer.Stream() << "/>" << std::endl;
00216
00217
00218
00219
00220
00221 }
00222
00223 void PropertyPythonObject::Restore(Base::XMLReader &reader)
00224 {
00225 reader.readElement("Python");
00226 if (reader.hasAttribute("file")) {
00227 std::string file(reader.getAttribute("file"));
00228 reader.addFile(file.c_str(),this);
00229 }
00230 else {
00231 std::string buffer = reader.getAttribute("value");
00232 if (reader.hasAttribute("encoded") &&
00233 strcmp(reader.getAttribute("encoded"),"yes") == 0) {
00234 buffer = Base::base64_decode(buffer);
00235 }
00236 else {
00237 buffer = decodeValue(buffer);
00238 }
00239
00240 aboutToSetValue();
00241 this->fromString(buffer);
00242 restoreObject(reader);
00243 hasSetValue();
00244 }
00245 }
00246
00247 void PropertyPythonObject::SaveDocFile (Base::Writer &writer) const
00248 {
00249 std::string buffer = this->toString();
00250 for (std::string::iterator it = buffer.begin(); it != buffer.end(); ++it)
00251 writer.Stream().put(*it);
00252 }
00253
00254 void PropertyPythonObject::RestoreDocFile(Base::Reader &reader)
00255 {
00256 aboutToSetValue();
00257 std::string buffer;
00258 char c;
00259 while (reader.get(c)) {
00260 buffer.push_back(c);
00261 }
00262 this->fromString(buffer);
00263 hasSetValue();
00264 }
00265
00266 unsigned int PropertyPythonObject::getMemSize (void) const
00267 {
00268 return sizeof(Py::Object);
00269 }
00270
00271 Property *PropertyPythonObject::Copy(void) const
00272 {
00273 PropertyPythonObject *p = new PropertyPythonObject();
00274 p->object = this->object;
00275 return p;
00276 }
00277
00278 void PropertyPythonObject::Paste(const Property &from)
00279 {
00280 if (from.getTypeId() == PropertyPythonObject::getClassTypeId()) {
00281 aboutToSetValue();
00282 this->object = static_cast<const PropertyPythonObject&>(from).object;
00283 hasSetValue();
00284 }
00285 }