void PropertyPythonObject::fromString(const std::string& repr)
{
    Base::PyGILStateLocker lock;
    try {
        Py::Module pickle(PyImport_ImportModule("json"),true);
        Py::Callable method(pickle.getAttr(std::string("loads")));
        Py::Tuple args(1);
        args.setItem(0, Py::String(repr));
        Py::Object res = method.apply(args);

        if (this->object.hasAttr("__setstate__")) {
            Py::Tuple args(1);
            args.setItem(0, res);
            Py::Callable state(this->object.getAttr("__setstate__"));
            state.apply(args);
        }
        else if (this->object.hasAttr("__dict__")) {
            this->object.setAttr("__dict__", res);
        }
        else {
            this->object = res;
        }
    }
    catch (Py::Exception&) {
        Base::PyException e; // extract the Python error text
        e.ReportException();
    }
}
const char* ViewProviderPythonFeatureImp::getDefaultDisplayMode() const
{
    // Run the getDefaultDisplayMode method of the proxy object.
    Base::PyGILStateLocker lock;
    static std::string mode;
    try {
        App::Property* proxy = object->getPropertyByName("Proxy");
        if (proxy && proxy->getTypeId() == App::PropertyPythonObject::getClassTypeId()) {
            Py::Object vp = static_cast<App::PropertyPythonObject*>(proxy)->getValue();
            if (vp.hasAttr(std::string("getDefaultDisplayMode"))) {
                Py::Callable method(vp.getAttr(std::string("getDefaultDisplayMode")));
                Py::Tuple args;
                Py::String str(method.apply(args));
                //if (str.isUnicode())
                //    str = str.encode("ascii"); // json converts strings into unicode
                mode = str.as_std_string("ascii");
                return mode.c_str();
            }
        }
    }
    catch (Py::Exception&) {
        Base::PyException e; // extract the Python error text
        e.ReportException();
    }

    return 0;
}
void ViewProviderPythonFeatureImp::attach(App::DocumentObject *pcObject)
{
    // Run the attach method of the proxy object.
    Base::PyGILStateLocker lock;
    try {
        App::Property* proxy = object->getPropertyByName("Proxy");
        if (proxy && proxy->getTypeId() == App::PropertyPythonObject::getClassTypeId()) {
            Py::Object vp = static_cast<App::PropertyPythonObject*>(proxy)->getValue();
            if (vp.hasAttr(std::string("attach"))) {
                if (vp.hasAttr("__object__")) {
                    Py::Callable method(vp.getAttr(std::string("attach")));
                    Py::Tuple args;
                    method.apply(args);
                }
                else {
                    Py::Callable method(vp.getAttr(std::string("attach")));
                    Py::Tuple args(1);
                    args.setItem(0, Py::Object(object->getPyObject(), true));
                    method.apply(args);
                }

                // #0000415: Now simulate a property change event to call
                // claimChildren if implemented.
                pcObject->Label.touch();
            }
        }
    }
    catch (Py::Exception&) {
        Base::PyException e; // extract the Python error text
        e.ReportException();
    }
}
std::vector<App::DocumentObject*> ViewProviderPythonFeatureImp::claimChildren(const std::vector<App::DocumentObject*>& base) const 
{
    std::vector<App::DocumentObject*> children;
    Base::PyGILStateLocker lock;
    try {
        App::Property* proxy = object->getPropertyByName("Proxy");
        if (proxy && proxy->getTypeId() == App::PropertyPythonObject::getClassTypeId()) {
            Py::Object vp = static_cast<App::PropertyPythonObject*>(proxy)->getValue();
            if (vp.hasAttr(std::string("claimChildren"))) {
                Py::Callable method(vp.getAttr(std::string("claimChildren")));
                Py::Tuple args;
                Py::Sequence list(method.apply(args));
                for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
                    PyObject* item = (*it).ptr();
                    if (PyObject_TypeCheck(item, &(App::DocumentObjectPy::Type))) {
                        App::DocumentObject* obj = static_cast<App::DocumentObjectPy*>(item)->getDocumentObjectPtr();
                        children.push_back(obj);
                    }
                }
            }
            else {
                children = base;
            }
        }
    }
    catch (Py::Exception&) {
        Base::PyException e; // extract the Python error text
        e.ReportException();
    }

    return children;
}
DocumentObjectExecReturn *FeaturePythonImp::execute()
{
    // Run the execute method of the proxy object.
    Base::PyGILStateLocker lock;
    try {
        Property* proxy = object->getPropertyByName("Proxy");
        if (proxy && proxy->getTypeId() == PropertyPythonObject::getClassTypeId()) {
            Py::Object feature = static_cast<PropertyPythonObject*>(proxy)->getValue();
            if (feature.hasAttr("__object__")) {
                Py::Callable method(feature.getAttr(std::string("execute")));
                Py::Tuple args(0);
                method.apply(args);
            }
            else {
                Py::Callable method(feature.getAttr(std::string("execute")));
                Py::Tuple args(1);
                args.setItem(0, Py::Object(object->getPyObject(), true));
                method.apply(args);
            }
        }
    }
    catch (Py::Exception&) {
        Base::PyException e; // extract the Python error text
        e.ReportException();
        std::stringstream str;
        str << object->Label.getValue() << ": " << e.what();
        return new App::DocumentObjectExecReturn(str.str());
    }

    return DocumentObject::StdReturn;
}
std::string PropertyPythonObject::toString() const
{
    std::string repr;
    Base::PyGILStateLocker lock;
    try {
        Py::Module pickle(PyImport_ImportModule("json"),true);
        Py::Callable method(pickle.getAttr(std::string("dumps")));
        Py::Object dump;
        if (this->object.hasAttr("__getstate__")) {
            Py::Tuple args;
            Py::Callable state(this->object.getAttr("__getstate__"));
            dump = state.apply(args);
        }
        else if (this->object.hasAttr("__dict__")) {
            dump = this->object.getAttr("__dict__");
        }
        else {
            dump = this->object;
        }

        Py::Tuple args(1);
        args.setItem(0, dump);
        Py::Object res = method.apply(args);
        Py::String str(res);
        repr = str.as_std_string("ascii");
    }
    catch (Py::Exception&) {
        Base::PyException e; // extract the Python error text
        e.ReportException();
    }

    return repr;
}
SoDetail* ViewProviderPythonFeatureImp::getDetail(const char* name) const
{
    // Run the onChanged method of the proxy object.
    Base::PyGILStateLocker lock;
    try {
        App::Property* proxy = object->getPropertyByName("Proxy");
        if (proxy && proxy->getTypeId() == App::PropertyPythonObject::getClassTypeId()) {
            Py::Object vp = static_cast<App::PropertyPythonObject*>(proxy)->getValue();
            if (vp.hasAttr(std::string("getDetail"))) {
                Py::Callable method(vp.getAttr(std::string("getDetail")));
                Py::Tuple args(1);
                args.setItem(0, Py::String(name));
                Py::Object det(method.apply(args));
                void* ptr = 0;
                Base::Interpreter().convertSWIGPointerObj("pivy.coin", "SoDetail *", det.ptr(), &ptr, 0);
                SoDetail* detail = reinterpret_cast<SoDetail*>(ptr);
                return detail ? detail->copy() : 0;
            }
        }
    }
    catch (const Base::Exception& e) {
        e.ReportException();
    }
    catch (Py::Exception&) {
        Base::PyException e; // extract the Python error text
        e.ReportException();
    }

    return 0;
}
std::string ViewProviderPythonFeatureImp::getElement(const SoDetail *det) const
{
    // Run the onChanged method of the proxy object.
    Base::PyGILStateLocker lock;
    try {
        App::Property* proxy = object->getPropertyByName("Proxy");
        if (proxy && proxy->getTypeId() == App::PropertyPythonObject::getClassTypeId()) {
            Py::Object vp = static_cast<App::PropertyPythonObject*>(proxy)->getValue();
            if (vp.hasAttr(std::string("getElement"))) {
                PyObject* pivy = 0;
                // Note: As there is no ref'counting mechanism for the SoDetail class we must
                // pass '0' as the last parameter so that the Python object does not 'own'
                // the detail object.
                pivy = Base::Interpreter().createSWIGPointerObj("pivy.coin", "SoDetail *", (void*)det, 0);
                Py::Callable method(vp.getAttr(std::string("getElement")));
                Py::Tuple args(1);
                args.setItem(0, Py::Object(pivy, true));
                Py::String name(method.apply(args));
                return (std::string)name;
            }
        }
    }
    catch (const Base::Exception& e) {
        e.ReportException();
    }
    catch (Py::Exception&) {
        Base::PyException e; // extract the Python error text
        e.ReportException();
    }

    return "";
}
void FeaturePythonImp::onChanged(const Property* prop)
{
    // Run the execute method of the proxy object.
    Base::PyGILStateLocker lock;
    try {
        Property* proxy = object->getPropertyByName("Proxy");
        if (proxy && proxy->getTypeId() == PropertyPythonObject::getClassTypeId()) {
            Py::Object feature = static_cast<PropertyPythonObject*>(proxy)->getValue();
            if (feature.hasAttr(std::string("onChanged"))) {
                if (feature.hasAttr("__object__")) {
                    Py::Callable method(feature.getAttr(std::string("onChanged")));
                    Py::Tuple args(1);
                    std::string prop_name = object->getName(prop);
                    args.setItem(0, Py::String(prop_name));
                    method.apply(args);
                }
                else {
                    Py::Callable method(feature.getAttr(std::string("onChanged")));
                    Py::Tuple args(2);
                    args.setItem(0, Py::Object(object->getPyObject(), true));
                    std::string prop_name = object->getName(prop);
                    args.setItem(1, Py::String(prop_name));
                    method.apply(args);
                }
            }
        }
    }
    catch (Py::Exception&) {
        Base::PyException e; // extract the Python error text
        e.ReportException();
    }
}
ViewProviderPythonFeatureImp::ValueT
ViewProviderPythonFeatureImp::canDropObject(App::DocumentObject* obj) const
{
    // Run the onChanged method of the proxy object.
    Base::PyGILStateLocker lock;
    try {
        App::Property* proxy = object->getPropertyByName("Proxy");
        if (proxy && proxy->getTypeId() == App::PropertyPythonObject::getClassTypeId()) {
            Py::Object vp = static_cast<App::PropertyPythonObject*>(proxy)->getValue();
            if (vp.hasAttr(std::string("canDropObject"))) {
                Py::Callable method(vp.getAttr(std::string("canDropObject")));
                Py::Tuple args(1);
                args.setItem(0, Py::Object(obj->getPyObject(), true));
                Py::Boolean ok(method.apply(args));
                return static_cast<bool>(ok) ? Accepted : Rejected;
            }
            else {
                return NotImplemented;
            }
        }
    }
    catch (Py::Exception&) {
        Base::PyException e; // extract the Python error text
        e.ReportException();
    }

    return Rejected;
}
void PropertyPythonObject::loadPickle(const std::string& str)
{
    // find the custom attributes and restore them
    Base::PyGILStateLocker lock;
    try {
        std::string buffer = str;
        boost::regex pickle("S'(\\w+)'.+S'(\\w+)'\\n");
        boost::match_results<std::string::const_iterator> what;
        std::string::const_iterator start, end;
        start = buffer.begin();
        end = buffer.end();
        while (boost::regex_search(start, end, what, pickle)) {
            std::string key = std::string(what[1].first, what[1].second);
            std::string val = std::string(what[2].first, what[2].second);
            this->object.setAttr(key, Py::String(val));
            buffer = std::string(what[2].second, end);
            start = buffer.begin();
            end = buffer.end();
        }
    }
    catch (Py::Exception&) {
        Base::PyException e; // extract the Python error text
        e.ReportException();
    }
}
QIcon ViewProviderPythonFeatureImp::getIcon() const
{
    // default icon
    //static QPixmap px = BitmapFactory().pixmap("Tree_Python");

    // Run the getIcon method of the proxy object.
    Base::PyGILStateLocker lock;
    try {
        App::Property* proxy = object->getPropertyByName("Proxy");
        if (proxy && proxy->getTypeId() == App::PropertyPythonObject::getClassTypeId()) {
            Py::Object vp = static_cast<App::PropertyPythonObject*>(proxy)->getValue();
            if (vp.hasAttr(std::string("getIcon"))) {
                Py::Callable method(vp.getAttr(std::string("getIcon")));
                Py::Tuple args;
                Py::String str(method.apply(args));
                std::string content = str.as_std_string("utf-8");
                QPixmap icon;
                // Check if the passed string is a filename, otherwise treat as xpm data
                QFileInfo fi(QString::fromUtf8(content.c_str()));
                if (fi.isFile() && fi.exists()) {
                    icon.load(fi.absoluteFilePath());
                } else {
                    QByteArray ary;
                    int strlen = (int)content.size();
                    ary.resize(strlen);
                    for (int j=0; j<strlen; j++)
                        ary[j]=content[j];
                    // Make sure to remove crap around the XPM data
                    QList<QByteArray> lines = ary.split('\n');
                    QByteArray buffer;
                    buffer.reserve(ary.size()+lines.size());
                    for (QList<QByteArray>::iterator it = lines.begin(); it != lines.end(); ++it) {
                        QByteArray trim = it->trimmed();
                        if (!trim.isEmpty()) {
                            buffer.append(trim);
                            buffer.append('\n');
                        }
                    }
                    icon.loadFromData(buffer, "XPM");
                }
                if (!icon.isNull()) {
                    return icon;
                }
            }
        }
    }
    catch (Py::Exception&) {
        Base::PyException e; // extract the Python error text
        e.ReportException();
    }

    return QIcon();
}
void TaskDialogPython::helpRequested()
{
    Base::PyGILStateLocker lock;
    try {
        if (dlg.hasAttr(std::string("helpRequested"))) {
            Py::Callable method(dlg.getAttr(std::string("helpRequested")));
            Py::Tuple args;
            method.apply(args);
        }
    }
    catch (Py::Exception&) {
        Base::PyException e; // extract the Python error text
        e.ReportException();
    }
}
void SelectionObserverPython::clearSelection(const SelectionChanges& msg)
{
    Base::PyGILStateLocker lock;
    try {
        if (this->inst.hasAttr(std::string("clearSelection"))) {
            Py::Callable method(this->inst.getAttr(std::string("clearSelection")));
            Py::Tuple args(1);
            args.setItem(0, Py::String(msg.pDocName ? msg.pDocName : ""));
            method.apply(args);
        }
    }
    catch (Py::Exception&) {
        Base::PyException e; // extract the Python error text
        e.ReportException();
    }
}
void TaskDialogPython::clicked(int i)
{
    Base::PyGILStateLocker lock;
    try {
        if (dlg.hasAttr(std::string("clicked"))) {
            Py::Callable method(dlg.getAttr(std::string("clicked")));
            Py::Tuple args(1);
            args.setItem(0, Py::Int(i));
            method.apply(args);
        }
    }
    catch (Py::Exception&) {
        Base::PyException e; // extract the Python error text
        e.ReportException();
    }
}
bool TaskDialogPython::needsFullSpace() const
{
    Base::PyGILStateLocker lock;
    try {
        if (dlg.hasAttr(std::string("needsFullSpace"))) {
            Py::Callable method(dlg.getAttr(std::string("needsFullSpace")));
            Py::Tuple args;
            Py::Boolean ret(method.apply(args));
            return (bool)ret;
        }
    }
    catch (Py::Exception&) {
        Base::PyException e; // extract the Python error text
        e.ReportException();
    }

    return TaskDialog::needsFullSpace();
}
/**
 * Executes the selected macro file.
 */
void DlgMacroExecuteImp::accept()
{
    QTreeWidgetItem* item;

    int index = tabMacroWidget->currentIndex();
    if (index == 0) { //user-specific
        item = userMacroListBox->currentItem();
    }
    else {
        //index == 1 system-wide
        item = systemMacroListBox->currentItem();
    }
    if (!item)
        return;

    QDialog::accept();

    MacroItem * mitem = static_cast<MacroItem *>(item);

    QDir dir;

    if (!mitem->systemWide){
        dir =QDir(this->macroPath);
    }
    else {
        QString dirstr = QString::fromUtf8(App::GetApplication().getHomePath()) + QString::fromUtf8("Macro");
        dir = QDir(dirstr);
    }

    QFileInfo fi(dir, item->text(0));
    try {
        Application::Instance->macroManager()->run(Gui::MacroManager::File, fi.filePath().toUtf8());
        // after macro run recalculate the document
        if (Application::Instance->activeDocument())
            Application::Instance->activeDocument()->getDocument()->recompute();
    }
    catch (const Base::SystemExitException&) {
        // handle SystemExit exceptions
        Base::PyGILStateLocker locker;
        Base::PyException e;
        e.ReportException();
    }
}
Exemple #18
0
void Command::invoke(int i)
{
    // Do not query _pcAction since it isn't created necessarily
#ifdef FC_LOGUSERACTION
    Base::Console().Log("CmdG: %s\n",sName);
#endif
    // set the application module type for the macro
    getGuiApplication()->macroManager()->setModule(sAppModule);
    try {
        // check if it really works NOW (could be a delay between click deactivation of the button)
        if (isActive())
            activated( i );
    }
    catch (const Base::SystemExitException&) {
        throw;
    }
    catch (Base::PyException &e) {
        e.ReportException();
    }
    catch (Py::Exception&) {
        Base::PyGILStateLocker lock;
        Base::PyException e;
        e.ReportException();
    }
    catch (Base::AbortException&) {
    }
    catch (Base::Exception &e) {
        e.ReportException();
        // Pop-up a dialog for FreeCAD-specific exceptions
        QMessageBox::critical(Gui::getMainWindow(), QObject::tr("Exception"), QLatin1String(e.what()));
    }
    catch (std::exception &e) {
        Base::Console().Error("C++ exception thrown (%s)\n", e.what());
    }
    catch (const char* e) {
        Base::Console().Error("%s\n", e);
    }
#ifndef FC_DEBUG
    catch (...) {
        Base::Console().Error("Gui::Command::activated(%d): Unknown C++ exception thrown\n", i);
    }
#endif
}
void TaskDialogPython::modifyStandardButtons(QDialogButtonBox *buttonBox)
{
    Base::PyGILStateLocker lock;
    try {
        if (dlg.hasAttr(std::string("modifyStandardButtons"))) {
            Gui::PythonWrapper wrap;
            wrap.loadGuiModule();
            wrap.loadWidgetsModule();
            Py::Callable method(dlg.getAttr(std::string("modifyStandardButtons")));
            Py::Tuple args(1);
            args.setItem(0, wrap.fromQWidget(buttonBox, "QDialogButtonBox"));
            method.apply(args);
        }
    }
    catch (Py::Exception&) {
        Base::PyException e; // extract the Python error text
        e.ReportException();
    }
}
QDialogButtonBox::StandardButtons TaskDialogPython::getStandardButtons(void) const
{
    Base::PyGILStateLocker lock;
    try {
        if (dlg.hasAttr(std::string("getStandardButtons"))) {
            Py::Callable method(dlg.getAttr(std::string("getStandardButtons")));
            Py::Tuple args;
            Py::Int ret(method.apply(args));
            int value = (int)ret;
            return QDialogButtonBox::StandardButtons(value);
        }
    }
    catch (Py::Exception&) {
        Base::PyException e; // extract the Python error text
        e.ReportException();
    }

    return TaskDialog::getStandardButtons();
}
bool TaskWatcherPython::shouldShow()
{
    Base::PyGILStateLocker lock;
    try {
        if (watcher.hasAttr(std::string("shouldShow"))) {
            Py::Callable method(watcher.getAttr(std::string("shouldShow")));
            Py::Tuple args;
            Py::Boolean ret(method.apply(args));
            return (bool)ret;
        }
    }
    catch (Py::Exception&) {
        Base::PyException e; // extract the Python error text
        e.ReportException();
    }

    if (!this->Filter.empty())
        return match();
    else
        return TaskWatcher::shouldShow();
}
bool ViewProviderPythonFeatureImp::onDelete(const std::vector<std::string> & sub)
{
    Base::PyGILStateLocker lock;
    try {
        App::Property* proxy = object->getPropertyByName("Proxy");
        if (proxy && proxy->getTypeId() == App::PropertyPythonObject::getClassTypeId()) {
            Py::Object vp = static_cast<App::PropertyPythonObject*>(proxy)->getValue();
            if (vp.hasAttr(std::string("onDelete"))) {
                Py::Tuple seq(sub.size());
                int index=0;
                for (std::vector<std::string>::const_iterator it = sub.begin(); it != sub.end(); ++it) {
                    seq.setItem(index++, Py::String(*it));
                }

                if (vp.hasAttr("__object__")) {
                    Py::Callable method(vp.getAttr(std::string("onDelete")));
                    Py::Tuple args(1);
                    args.setItem(0, seq);
                    Py::Boolean ok(method.apply(args));
                    return (bool)ok;
                }
                else {
                    Py::Callable method(vp.getAttr(std::string("onDelete")));
                    Py::Tuple args(2);
                    args.setItem(0, Py::Object(object->getPyObject(), true));
                    args.setItem(1, seq);
                    Py::Boolean ok(method.apply(args));
                    return (bool)ok;
                }
            }
        }
    }
    catch (Py::Exception&) {
        Base::PyException e; // extract the Python error text
        e.ReportException();
    }

    return true;
}
std::vector<std::string> ViewProviderPythonFeatureImp::getDisplayModes(void) const
{
    // Run the getDisplayModes method of the proxy object.
    Base::PyGILStateLocker lock;
    std::vector<std::string> modes;
    try {
        App::Property* proxy = object->getPropertyByName("Proxy");
        if (proxy && proxy->getTypeId() == App::PropertyPythonObject::getClassTypeId()) {
            Py::Object vp = static_cast<App::PropertyPythonObject*>(proxy)->getValue();
            if (vp.hasAttr(std::string("getDisplayModes"))) {
                if (vp.hasAttr("__object__")) {
                    Py::Callable method(vp.getAttr(std::string("getDisplayModes")));
                    Py::Tuple args;
                    Py::Sequence list(method.apply(args));
                    for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
                        Py::String str(*it);
                        modes.push_back(str.as_std_string("ascii"));
                    }
                }
                else {
                    Py::Callable method(vp.getAttr(std::string("getDisplayModes")));
                    Py::Tuple args(1);
                    args.setItem(0, Py::Object(object->getPyObject(), true));
                    Py::Sequence list(method.apply(args));
                    for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
                        Py::String str(*it);
                        modes.push_back(str.as_std_string("ascii"));
                    }
                }
            }
        }
    }
    catch (Py::Exception&) {
        Base::PyException e; // extract the Python error text
        e.ReportException();
    }

    return modes;
}
void SelectionObserverPython::addSelection(const SelectionChanges& msg)
{
    Base::PyGILStateLocker lock;
    try {
        if (this->inst.hasAttr(std::string("addSelection"))) {
            Py::Callable method(this->inst.getAttr(std::string("addSelection")));
            Py::Tuple args(4);
            args.setItem(0, Py::String(msg.pDocName ? msg.pDocName : ""));
            args.setItem(1, Py::String(msg.pObjectName ? msg.pObjectName : ""));
            args.setItem(2, Py::String(msg.pSubName ? msg.pSubName : ""));
            Py::Tuple tuple(3);
            tuple[0] = Py::Float(msg.x);
            tuple[1] = Py::Float(msg.y);
            tuple[2] = Py::Float(msg.z);
            args.setItem(3, tuple);
            method.apply(args);
        }
    }
    catch (Py::Exception&) {
        Base::PyException e; // extract the Python error text
        e.ReportException();
    }
}
bool ViewProviderPythonFeatureImp::useNewSelectionModel() const
{
    // Run the useNewSelectionModel method of the proxy object.
    Base::PyGILStateLocker lock;
    try {
        App::Property* proxy = object->getPropertyByName("Proxy");
        if (proxy && proxy->getTypeId() == App::PropertyPythonObject::getClassTypeId()) {
            Py::Object vp = static_cast<App::PropertyPythonObject*>(proxy)->getValue();
            if (vp.hasAttr(std::string("useNewSelectionModel"))) {
                Py::Callable method(vp.getAttr(std::string("useNewSelectionModel")));
                Py::Tuple args;
                Py::Boolean ok(method.apply(args));
                return (bool)ok;
            }
        }
    }
    catch (Py::Exception&) {
        Base::PyException e; // extract the Python error text
        e.ReportException();
    }

    return true;
}
ViewProviderPythonFeatureImp::ValueT
ViewProviderPythonFeatureImp::unsetEdit(int ModNum)
{
    // Run the onChanged method of the proxy object.
    Base::PyGILStateLocker lock;
    try {
        App::Property* proxy = object->getPropertyByName("Proxy");
        if (proxy && proxy->getTypeId() == App::PropertyPythonObject::getClassTypeId()) {
            Py::Object vp = static_cast<App::PropertyPythonObject*>(proxy)->getValue();
            if (vp.hasAttr(std::string("unsetEdit"))) {
                if (vp.hasAttr("__object__")) {
                    Py::Callable method(vp.getAttr(std::string("unsetEdit")));
                    Py::Tuple args(1);
                    args.setItem(0, Py::Int(ModNum));
                    Py::Boolean ok(method.apply(args));
                    bool value = (bool)ok;
                    return value ? Accepted : Rejected;
                }
                else {
                    Py::Callable method(vp.getAttr(std::string("unsetEdit")));
                    Py::Tuple args(2);
                    args.setItem(0, Py::Object(object->getPyObject(), true));
                    args.setItem(1, Py::Int(ModNum));
                    Py::Boolean ok(method.apply(args));
                    bool value = (bool)ok;
                    return value ? Accepted : Rejected;
                }
            }
        }
    }
    catch (Py::Exception&) {
        Base::PyException e; // extract the Python error text
        e.ReportException();
    }

    return NotImplemented;
}
void PropertyPythonObject::Save (Base::Writer &writer) const
{
    //if (writer.isForceXML()) {
        std::string repr = this->toString();
        repr = Base::base64_encode((const unsigned char*)repr.c_str(), repr.size());
        std::string val = /*encodeValue*/(repr);
        writer.Stream() << writer.ind() << "<Python value=\"" << val
                        << "\" encoded=\"yes\"";

        Base::PyGILStateLocker lock;
        try {
            if (this->object.hasAttr("__module__") && this->object.hasAttr("__class__")) {
                Py::String mod(this->object.getAttr("__module__"));
                Py::Object cls(this->object.getAttr("__class__"));
                if (cls.hasAttr("__name__")) {
                    Py::String name(cls.getAttr("__name__"));
                    writer.Stream() << " module=\"" << (std::string)mod << "\""
                                    << " class=\"" << (std::string)name << "\"";
                }
            }
            else {
                writer.Stream() << " json=\"yes\"";
            }
        }
        catch (Py::Exception&) {
            Base::PyException e; // extract the Python error text
            e.ReportException();
        }

        saveObject(writer);
        writer.Stream() << "/>" << std::endl;
    //}
    //else {
    //    writer.Stream() << writer.ind() << "<Python file=\"" << 
    //    writer.addFile("pickle", this) << "\"/>" << std::endl;
    //}
}
void ViewProviderPythonFeatureImp::setupContextMenu(QMenu* menu)
{
    // Run the attach method of the proxy object.
    Base::PyGILStateLocker lock;
    try {
        App::Property* proxy = object->getPropertyByName("Proxy");
        if (proxy && proxy->getTypeId() == App::PropertyPythonObject::getClassTypeId()) {
            Py::Object vp = static_cast<App::PropertyPythonObject*>(proxy)->getValue();
            if (vp.hasAttr(std::string("setupContextMenu"))) {
                if (vp.hasAttr("__object__")) {
                    PythonWrapper wrap;
                    wrap.loadGuiModule();
                    wrap.loadWidgetsModule();
                    Py::Callable method(vp.getAttr(std::string("setupContextMenu")));
                    Py::Tuple args(1);
                    args.setItem(0, wrap.fromQWidget(menu, "QMenu"));
                    method.apply(args);
                }
                else {
                    PythonWrapper wrap;
                    wrap.loadGuiModule();
                    wrap.loadWidgetsModule();
                    Py::Callable method(vp.getAttr(std::string("setupContextMenu")));
                    Py::Tuple args(2);
                    args.setItem(0, Py::Object(object->getPyObject(), true));
                    args.setItem(1, wrap.fromQWidget(menu, "QMenu"));
                    method.apply(args);
                }
            }
        }
    }
    catch (Py::Exception&) {
        Base::PyException e; // extract the Python error text
        e.ReportException();
    }
}
void ViewProviderPythonFeatureImp::updateData(const App::Property* prop)
{
    // Run the updateData method of the proxy object.
    Base::PyGILStateLocker lock;
    try {
        App::Property* proxy = object->getPropertyByName("Proxy");
        if (proxy && proxy->getTypeId() == App::PropertyPythonObject::getClassTypeId()) {
            Py::Object vp = static_cast<App::PropertyPythonObject*>(proxy)->getValue();
            if (vp.hasAttr(std::string("updateData"))) {
                if (vp.hasAttr("__object__")) {
                    Py::Callable method(vp.getAttr(std::string("updateData")));
                    Py::Tuple args(1);
                    const char* prop_name = object->getObject()->getPropertyName(prop);
                    if (prop_name) {
                        args.setItem(0, Py::String(prop_name));
                        method.apply(args);
                    }
                }
                else {
                    Py::Callable method(vp.getAttr(std::string("updateData")));
                    Py::Tuple args(2);
                    args.setItem(0, Py::Object(object->getObject()->getPyObject(), true));
                    const char* prop_name = object->getObject()->getPropertyName(prop);
                    if (prop_name) {
                        args.setItem(1, Py::String(prop_name));
                        method.apply(args);
                    }
                }
            }
        }
    }
    catch (Py::Exception&) {
        Base::PyException e; // extract the Python error text
        e.ReportException();
    }
}
std::string ViewProviderPythonFeatureImp::setDisplayMode(const char* ModeName)
{
    // Run the setDisplayMode method of the proxy object.
    Base::PyGILStateLocker lock;
    try {
        App::Property* proxy = object->getPropertyByName("Proxy");
        if (proxy && proxy->getTypeId() == App::PropertyPythonObject::getClassTypeId()) {
            Py::Object vp = static_cast<App::PropertyPythonObject*>(proxy)->getValue();
            if (vp.hasAttr(std::string("setDisplayMode"))) {
                Py::Callable method(vp.getAttr(std::string("setDisplayMode")));
                Py::Tuple args(1);
                args.setItem(0, Py::String(ModeName));
                Py::String str(method.apply(args));
                return str.as_std_string("ascii");
            }
        }
    }
    catch (Py::Exception&) {
        Base::PyException e; // extract the Python error text
        e.ReportException();
    }

    return ModeName;
}