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 # include <sstream>
00028 # include <QFileInfo>
00029 # include <QPixmap>
00030 # include <boost/signals.hpp>
00031 # include <boost/bind.hpp>
00032 # include <Inventor/nodes/SoDrawStyle.h>
00033 # include <Inventor/nodes/SoMaterial.h>
00034 # include <Inventor/nodes/SoSeparator.h>
00035 # include <Inventor/actions/SoSearchAction.h>
00036 # include <Inventor/draggers/SoDragger.h>
00037 # include <Inventor/manips/SoCenterballManip.h>
00038 # include <Inventor/nodes/SoBaseColor.h>
00039 # include <Inventor/nodes/SoCamera.h>
00040 # include <Inventor/nodes/SoDrawStyle.h>
00041 # include <Inventor/nodes/SoMaterial.h>
00042 # include <Inventor/nodes/SoSeparator.h>
00043 # include <Inventor/nodes/SoSwitch.h>
00044 # include <Inventor/nodes/SoDirectionalLight.h>
00045 # include <Inventor/sensors/SoNodeSensor.h>
00046 # include <Inventor/SoPickedPoint.h>
00047 # include <Inventor/actions/SoRayPickAction.h>
00048 #endif
00049
00050 #include "ViewProviderPythonFeature.h"
00051 #include "ViewProviderPythonFeaturePy.h"
00052 #include "SoFCSelection.h"
00053 #include "SoFCBoundingBox.h"
00054 #include "Tree.h"
00055 #include "Window.h"
00056 #include "Application.h"
00057 #include "BitmapFactory.h"
00058 #include "Document.h"
00059 #include <App/DocumentObjectPy.h>
00060 #include <App/GeoFeature.h>
00061 #include <App/PropertyGeo.h>
00062 #include <Base/Console.h>
00063 #include <Base/Reader.h>
00064 #include <Base/Interpreter.h>
00065
00066
00067 using namespace Gui;
00068
00069 namespace Gui {
00070
00071 class ViewProviderPythonFeatureObserver
00072 {
00073 public:
00075 static ViewProviderPythonFeatureObserver* instance();
00077 static void destruct ();
00078 void slotAppendObject(const Gui::ViewProvider&);
00079 void slotDeleteObject(const Gui::ViewProvider&);
00080 void slotDeleteDocument(const Gui::Document&);
00081
00082 private:
00083 static ViewProviderPythonFeatureObserver* _singleton;
00084
00085 ViewProviderPythonFeatureObserver();
00086 ~ViewProviderPythonFeatureObserver();
00087 typedef std::map<
00088 const App::DocumentObject*,
00089 std::string
00090 > ObjectProxy;
00091
00092 std::map<const App::Document*, ObjectProxy> proxyMap;
00093 };
00094
00095 }
00096
00097 ViewProviderPythonFeatureObserver* ViewProviderPythonFeatureObserver::_singleton = 0;
00098
00099 ViewProviderPythonFeatureObserver* ViewProviderPythonFeatureObserver::instance()
00100 {
00101 if (!_singleton)
00102 _singleton = new ViewProviderPythonFeatureObserver;
00103 return _singleton;
00104 }
00105
00106 void ViewProviderPythonFeatureObserver::destruct ()
00107 {
00108 delete _singleton;
00109 _singleton = 0;
00110 }
00111
00112 void ViewProviderPythonFeatureObserver::slotDeleteDocument(const Gui::Document& d)
00113 {
00114 App::Document* doc = d.getDocument();
00115 std::map<const App::Document*, ObjectProxy>::iterator it = proxyMap.find(doc);
00116 if (it != proxyMap.end()) {
00117 proxyMap.erase(it);
00118 }
00119 }
00120
00121 void ViewProviderPythonFeatureObserver::slotAppendObject(const Gui::ViewProvider& obj)
00122 {
00123 if (!obj.isDerivedFrom(Gui::ViewProviderDocumentObject::getClassTypeId()))
00124 return;
00125 const Gui::ViewProviderDocumentObject& vp = static_cast<const Gui::ViewProviderDocumentObject&>(obj);
00126 const App::DocumentObject* docobj = vp.getObject();
00127 App::Document* doc = docobj->getDocument();
00128 std::map<const App::Document*, ObjectProxy>::iterator it = proxyMap.find(doc);
00129 if (it != proxyMap.end()) {
00130 ObjectProxy::iterator jt = it->second.find(docobj);
00131 if (jt != it->second.end()) {
00132 Base::PyGILStateLocker lock;
00133 try {
00134 App::Property* prop = vp.getPropertyByName("Proxy");
00135 if (prop && prop->isDerivedFrom(App::PropertyPythonObject::getClassTypeId())) {
00136 static_cast<App::PropertyPythonObject*>(prop)->fromString(jt->second);
00137 static_cast<App::PropertyPythonObject*>(prop)->touch();
00138 it->second.erase(jt);
00139 }
00140 }
00141 catch (Py::Exception& e) {
00142 e.clear();
00143 }
00144 }
00145
00146 else {
00147 it->second.clear();
00148 }
00149 }
00150 }
00151
00152 void ViewProviderPythonFeatureObserver::slotDeleteObject(const Gui::ViewProvider& obj)
00153 {
00154 if (!obj.isDerivedFrom(Gui::ViewProviderDocumentObject::getClassTypeId()))
00155 return;
00156 const Gui::ViewProviderDocumentObject& vp = static_cast<const Gui::ViewProviderDocumentObject&>(obj);
00157 const App::DocumentObject* docobj = vp.getObject();
00158 App::Document* doc = docobj->getDocument();
00159 if (!doc->getUndoMode())
00160 return;
00161 Base::PyGILStateLocker lock;
00162 try {
00163 App::Property* prop = vp.getPropertyByName("Proxy");
00164 if (prop && prop->isDerivedFrom(App::PropertyPythonObject::getClassTypeId())) {
00165 std::string proxy = static_cast<App::PropertyPythonObject*>(prop)->toString();
00166 proxyMap[doc][docobj] = proxy;
00167 }
00168 }
00169 catch (Py::Exception& e) {
00170 e.clear();
00171 }
00172 }
00173
00174 ViewProviderPythonFeatureObserver::ViewProviderPythonFeatureObserver()
00175 {
00176 Gui::Application::Instance->signalDeletedObject.connect(boost::bind
00177 (&ViewProviderPythonFeatureObserver::slotDeleteObject, this, _1));
00178 Gui::Application::Instance->signalNewObject.connect(boost::bind
00179 (&ViewProviderPythonFeatureObserver::slotAppendObject, this, _1));
00180 Gui::Application::Instance->signalDeleteDocument.connect(boost::bind
00181 (&ViewProviderPythonFeatureObserver::slotDeleteDocument, this, _1));
00182 }
00183
00184 ViewProviderPythonFeatureObserver::~ViewProviderPythonFeatureObserver()
00185 {
00186 }
00187
00188
00189
00190 ViewProviderPythonFeatureImp::ViewProviderPythonFeatureImp(ViewProviderDocumentObject* vp)
00191 : object(vp)
00192 {
00193 (void)ViewProviderPythonFeatureObserver::instance();
00194 }
00195
00196 ViewProviderPythonFeatureImp::~ViewProviderPythonFeatureImp()
00197 {
00198 }
00199
00200 QIcon ViewProviderPythonFeatureImp::getIcon() const
00201 {
00202
00203
00204
00205
00206 Base::PyGILStateLocker lock;
00207 try {
00208 App::Property* proxy = object->getPropertyByName("Proxy");
00209 if (proxy && proxy->getTypeId() == App::PropertyPythonObject::getClassTypeId()) {
00210 Py::Object vp = static_cast<App::PropertyPythonObject*>(proxy)->getValue();
00211 if (vp.hasAttr(std::string("getIcon"))) {
00212 Py::Callable method(vp.getAttr(std::string("getIcon")));
00213 Py::Tuple args(0);
00214 Py::String str(method.apply(args));
00215 std::string content = str.as_std_string();
00216 QPixmap icon;
00217
00218 QFileInfo fi(QString::fromAscii(content.c_str()));
00219 if (fi.isFile() && fi.exists()) {
00220 icon.load(fi.absoluteFilePath());
00221 } else {
00222 QByteArray ary;
00223 int strlen = (int)content.size();
00224 ary.resize(strlen);
00225 for (int j=0; j<strlen; j++)
00226 ary[j]=content[j];
00227
00228 QList<QByteArray> lines = ary.split('\n');
00229 QByteArray buffer;
00230 buffer.reserve(ary.size()+lines.size());
00231 for (QList<QByteArray>::iterator it = lines.begin(); it != lines.end(); ++it) {
00232 QByteArray trim = it->trimmed();
00233 if (!trim.isEmpty()) {
00234 buffer.append(trim);
00235 buffer.append('\n');
00236 }
00237 }
00238 icon.loadFromData(buffer, "XPM");
00239 }
00240 if (!icon.isNull()) {
00241 return icon;
00242 }
00243 }
00244 }
00245 }
00246 catch (Py::Exception&) {
00247 Base::PyException e;
00248 Base::Console().Error("ViewProviderPythonFeature::getIcon: %s\n", e.what());
00249 }
00250
00251 return QIcon();
00252 }
00253
00254 std::vector<App::DocumentObject*> ViewProviderPythonFeatureImp::claimChildren() const
00255 {
00256 std::vector<App::DocumentObject*> children;
00257 Base::PyGILStateLocker lock;
00258 try {
00259 App::Property* proxy = object->getPropertyByName("Proxy");
00260 if (proxy && proxy->getTypeId() == App::PropertyPythonObject::getClassTypeId()) {
00261 Py::Object vp = static_cast<App::PropertyPythonObject*>(proxy)->getValue();
00262 if (vp.hasAttr(std::string("claimChildren"))) {
00263 Py::Callable method(vp.getAttr(std::string("claimChildren")));
00264 Py::Tuple args(0);
00265 Py::Sequence list(method.apply(args));
00266 for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
00267 PyObject* item = (*it).ptr();
00268 if (PyObject_TypeCheck(item, &(App::DocumentObjectPy::Type))) {
00269 App::DocumentObject* obj = static_cast<App::DocumentObjectPy*>(item)->getDocumentObjectPtr();
00270 children.push_back(obj);
00271 }
00272 }
00273 }
00274 }
00275 }
00276 catch (Py::Exception&) {
00277 Base::PyException e;
00278 Base::Console().Error("ViewProviderPythonFeature::claimChildren: %s\n", e.what());
00279 }
00280
00281 return children;
00282 }
00283
00284 std::string ViewProviderPythonFeatureImp::getElement(const SoPickedPoint *pp) const
00285 {
00286 return "";
00287 }
00288
00289 std::vector<Base::Vector3d> ViewProviderPythonFeatureImp::getSelectionShape(const char* Element) const
00290 {
00291 return std::vector<Base::Vector3d>();
00292 }
00293
00294 bool ViewProviderPythonFeatureImp::setEdit(int ModNum)
00295 {
00296
00297 Base::PyGILStateLocker lock;
00298 try {
00299 App::Property* proxy = object->getPropertyByName("Proxy");
00300 if (proxy && proxy->getTypeId() == App::PropertyPythonObject::getClassTypeId()) {
00301 Py::Object vp = static_cast<App::PropertyPythonObject*>(proxy)->getValue();
00302 if (vp.hasAttr(std::string("setEdit"))) {
00303 if (vp.hasAttr("__object__")) {
00304 Py::Callable method(vp.getAttr(std::string("setEdit")));
00305 Py::Tuple args(1);
00306 args.setItem(0, Py::Int(ModNum));
00307 Py::Boolean ok(method.apply(args));
00308 return (bool)ok;
00309 }
00310 else {
00311 Py::Callable method(vp.getAttr(std::string("setEdit")));
00312 Py::Tuple args(2);
00313 args.setItem(0, Py::Object(object->getPyObject(), true));
00314 args.setItem(1, Py::Int(ModNum));
00315 Py::Boolean ok(method.apply(args));
00316 return (bool)ok;
00317 }
00318 }
00319 }
00320 }
00321 catch (Py::Exception&) {
00322 Base::PyException e;
00323 const char* name = object->getObject()->Label.getValue();
00324 Base::Console().Error("ViewProviderPythonFeature::setEdit (%s): %s\n", name, e.what());
00325 }
00326
00327 return false;
00328 }
00329
00330 bool ViewProviderPythonFeatureImp::unsetEdit(int ModNum)
00331 {
00332
00333 Base::PyGILStateLocker lock;
00334 try {
00335 App::Property* proxy = object->getPropertyByName("Proxy");
00336 if (proxy && proxy->getTypeId() == App::PropertyPythonObject::getClassTypeId()) {
00337 Py::Object vp = static_cast<App::PropertyPythonObject*>(proxy)->getValue();
00338 if (vp.hasAttr(std::string("unsetEdit"))) {
00339 if (vp.hasAttr("__object__")) {
00340 Py::Callable method(vp.getAttr(std::string("unsetEdit")));
00341 Py::Tuple args(1);
00342 args.setItem(0, Py::Int(ModNum));
00343 Py::Boolean ok(method.apply(args));
00344 return (bool)ok;
00345 }
00346 else {
00347 Py::Callable method(vp.getAttr(std::string("unsetEdit")));
00348 Py::Tuple args(2);
00349 args.setItem(0, Py::Object(object->getPyObject(), true));
00350 args.setItem(1, Py::Int(ModNum));
00351 Py::Boolean ok(method.apply(args));
00352 return (bool)ok;
00353 }
00354 }
00355 }
00356 }
00357 catch (Py::Exception&) {
00358 Base::PyException e;
00359 const char* name = object->getObject()->Label.getValue();
00360 Base::Console().Error("ViewProviderPythonFeature::unsetEdit (%s): %s\n", name, e.what());
00361 }
00362
00363 return false;
00364 }
00365
00366 void ViewProviderPythonFeatureImp::attach(App::DocumentObject *pcObject)
00367 {
00368
00369 Base::PyGILStateLocker lock;
00370 try {
00371 App::Property* proxy = object->getPropertyByName("Proxy");
00372 if (proxy && proxy->getTypeId() == App::PropertyPythonObject::getClassTypeId()) {
00373 Py::Object vp = static_cast<App::PropertyPythonObject*>(proxy)->getValue();
00374 if (vp.hasAttr(std::string("attach"))) {
00375 if (vp.hasAttr("__object__")) {
00376 Py::Callable method(vp.getAttr(std::string("attach")));
00377 Py::Tuple args(0);
00378 method.apply(args);
00379 }
00380 else {
00381 Py::Callable method(vp.getAttr(std::string("attach")));
00382 Py::Tuple args(1);
00383 args.setItem(0, Py::Object(object->getPyObject(), true));
00384 method.apply(args);
00385 }
00386 }
00387 }
00388 }
00389 catch (Py::Exception&) {
00390 Base::PyException e;
00391 const char* name = object->getObject()->Label.getValue();
00392 Base::Console().Error("ViewProviderPythonFeature::attach (%s): %s\n", name, e.what());
00393 }
00394 }
00395
00396 void ViewProviderPythonFeatureImp::updateData(const App::Property* prop)
00397 {
00398
00399 Base::PyGILStateLocker lock;
00400 try {
00401 App::Property* proxy = object->getPropertyByName("Proxy");
00402 if (proxy && proxy->getTypeId() == App::PropertyPythonObject::getClassTypeId()) {
00403 Py::Object vp = static_cast<App::PropertyPythonObject*>(proxy)->getValue();
00404 if (vp.hasAttr(std::string("updateData"))) {
00405 if (vp.hasAttr("__object__")) {
00406 Py::Callable method(vp.getAttr(std::string("updateData")));
00407 Py::Tuple args(1);
00408 const char* prop_name = object->getObject()->getName(prop);
00409 if (prop_name) {
00410 args.setItem(0, Py::String(prop_name));
00411 method.apply(args);
00412 }
00413 }
00414 else {
00415 Py::Callable method(vp.getAttr(std::string("updateData")));
00416 Py::Tuple args(2);
00417 args.setItem(0, Py::Object(object->getObject()->getPyObject(), true));
00418 const char* prop_name = object->getObject()->getName(prop);
00419 if (prop_name) {
00420 args.setItem(1, Py::String(prop_name));
00421 method.apply(args);
00422 }
00423 }
00424 }
00425 }
00426 }
00427 catch (Py::Exception&) {
00428 Base::PyException e;
00429 const char* name = object->getObject()->Label.getValue();
00430 Base::Console().Error("ViewProviderPythonFeature::updateData (%s): %s\n", name, e.what());
00431 }
00432 }
00433
00434 void ViewProviderPythonFeatureImp::onChanged(const App::Property* prop)
00435 {
00436
00437 Base::PyGILStateLocker lock;
00438 try {
00439 App::Property* proxy = object->getPropertyByName("Proxy");
00440 if (proxy && proxy->getTypeId() == App::PropertyPythonObject::getClassTypeId()) {
00441 Py::Object vp = static_cast<App::PropertyPythonObject*>(proxy)->getValue();
00442 if (vp.hasAttr(std::string("onChanged"))) {
00443 if (vp.hasAttr("__object__")) {
00444 Py::Callable method(vp.getAttr(std::string("onChanged")));
00445 Py::Tuple args(1);
00446 std::string prop_name = object->getName(prop);
00447 args.setItem(0, Py::String(prop_name));
00448 method.apply(args);
00449 }
00450 else {
00451 Py::Callable method(vp.getAttr(std::string("onChanged")));
00452 Py::Tuple args(2);
00453 args.setItem(0, Py::Object(object->getPyObject(), true));
00454 std::string prop_name = object->getName(prop);
00455 args.setItem(1, Py::String(prop_name));
00456 method.apply(args);
00457 }
00458 }
00459 }
00460 }
00461 catch (Py::Exception&) {
00462 Base::PyException e;
00463 const char* name = object->getObject()->Label.getValue();
00464 Base::Console().Error("ViewProviderPythonFeature::onChanged (%s): %s\n", name, e.what());
00465 }
00466 }
00467
00468 void ViewProviderPythonFeatureImp::startRestoring()
00469 {
00470 }
00471
00472 void ViewProviderPythonFeatureImp::finishRestoring()
00473 {
00474 App::Property* proxy = object->getPropertyByName("Proxy");
00475 if (proxy && proxy->getTypeId() == App::PropertyPythonObject::getClassTypeId()) {
00476 Py::Object vp = static_cast<App::PropertyPythonObject*>(proxy)->getValue();
00477 if (vp.ptr() == Py::_None()) {
00478 object->show();
00479 static_cast<App::PropertyPythonObject*>(proxy)->setValue(Py::Int(1));
00480 }
00481 }
00482 }
00483
00484 const char* ViewProviderPythonFeatureImp::getDefaultDisplayMode() const
00485 {
00486
00487 Base::PyGILStateLocker lock;
00488 static std::string mode;
00489 try {
00490 App::Property* proxy = object->getPropertyByName("Proxy");
00491 if (proxy && proxy->getTypeId() == App::PropertyPythonObject::getClassTypeId()) {
00492 Py::Object vp = static_cast<App::PropertyPythonObject*>(proxy)->getValue();
00493 if (vp.hasAttr(std::string("getDefaultDisplayMode"))) {
00494 Py::Callable method(vp.getAttr(std::string("getDefaultDisplayMode")));
00495 Py::Tuple args(0);
00496 Py::String str(method.apply(args));
00497 mode = str.as_std_string();
00498 return mode.c_str();
00499 }
00500 }
00501 }
00502 catch (Py::Exception&) {
00503 Base::PyException e;
00504 const char* name = object->getObject()->Label.getValue();
00505 Base::Console().Error("ViewProviderPythonFeature::getDefaultDisplayMode (%s): %s\n", name, e.what());
00506 }
00507
00508 return 0;
00509 }
00510
00511 std::vector<std::string> ViewProviderPythonFeatureImp::getDisplayModes(void) const
00512 {
00513
00514 Base::PyGILStateLocker lock;
00515 std::vector<std::string> modes;
00516 try {
00517 App::Property* proxy = object->getPropertyByName("Proxy");
00518 if (proxy && proxy->getTypeId() == App::PropertyPythonObject::getClassTypeId()) {
00519 Py::Object vp = static_cast<App::PropertyPythonObject*>(proxy)->getValue();
00520 if (vp.hasAttr(std::string("getDisplayModes"))) {
00521 if (vp.hasAttr("__object__")) {
00522 Py::Callable method(vp.getAttr(std::string("getDisplayModes")));
00523 Py::Tuple args(0);
00524 Py::List list(method.apply(args));
00525 for (Py::List::iterator it = list.begin(); it != list.end(); ++it) {
00526 Py::String str(*it);
00527 modes.push_back(str.as_std_string());
00528 }
00529 }
00530 else {
00531 Py::Callable method(vp.getAttr(std::string("getDisplayModes")));
00532 Py::Tuple args(1);
00533 args.setItem(0, Py::Object(object->getPyObject(), true));
00534 Py::List list(method.apply(args));
00535 for (Py::List::iterator it = list.begin(); it != list.end(); ++it) {
00536 Py::String str(*it);
00537 modes.push_back(str.as_std_string());
00538 }
00539 }
00540 }
00541 }
00542 }
00543 catch (Py::Exception&) {
00544 Base::PyException e;
00545 const char* name = object->getObject()->Label.getValue();
00546 Base::Console().Error("ViewProviderPythonFeature::getDisplayModes (%s): %s\n", name, e.what());
00547 }
00548
00549 return modes;
00550 }
00551
00552 std::string ViewProviderPythonFeatureImp::setDisplayMode(const char* ModeName)
00553 {
00554
00555 Base::PyGILStateLocker lock;
00556 try {
00557 App::Property* proxy = object->getPropertyByName("Proxy");
00558 if (proxy && proxy->getTypeId() == App::PropertyPythonObject::getClassTypeId()) {
00559 Py::Object vp = static_cast<App::PropertyPythonObject*>(proxy)->getValue();
00560 if (vp.hasAttr(std::string("setDisplayMode"))) {
00561 Py::Callable method(vp.getAttr(std::string("setDisplayMode")));
00562 Py::Tuple args(1);
00563 args.setItem(0, Py::String(ModeName));
00564 Py::String str(method.apply(args));
00565 return str.as_std_string();
00566 }
00567 }
00568 }
00569 catch (Py::Exception&) {
00570 Base::PyException e;
00571 const char* name = object->getObject()->Label.getValue();
00572 Base::Console().Error("ViewProviderPythonFeature::setDisplayMode (%s): %s\n", name, e.what());
00573 }
00574
00575 return ModeName;
00576 }
00577
00578
00579
00580 namespace Gui {
00581 PROPERTY_SOURCE_TEMPLATE(Gui::ViewProviderPythonFeature, Gui::ViewProviderDocumentObject)
00582
00583 template class GuiExport ViewProviderPythonFeatureT<ViewProviderDocumentObject>;
00584 }
00585
00586
00587
00588 namespace Gui {
00589 PROPERTY_SOURCE_TEMPLATE(Gui::ViewProviderPythonGeometry, Gui::ViewProviderGeometryObject)
00590
00591 template class GuiExport ViewProviderPythonFeatureT<ViewProviderGeometryObject>;
00592 }
00593
00594