コード例 #1
0
void PropertyFileIncluded::Save (Base::Writer &writer) const
{
    if (writer.isForceXML()) {
        if (!_cValue.empty()) {
            Base::FileInfo file(_cValue.c_str());
            writer.Stream() << writer.ind() << "<FileIncluded data=\"" << 
            file.fileName() << "\">" << std::endl;
            // write the file in the XML stream
            writer.incInd();
            writer.insertBinFile(_cValue.c_str());
            writer.decInd();
            writer.Stream() << writer.ind() <<"</FileIncluded>" << endl;
        }
        else
            writer.Stream() << writer.ind() << "<FileIncluded data=\"\"/>" << std::endl;
    }
    else {
        // instead initiate an extra file 
        if (!_cValue.empty()) {
            Base::FileInfo file(_cValue.c_str());
            writer.Stream() << writer.ind() << "<FileIncluded file=\"" << 
            writer.addFile(file.fileName().c_str(), this) << "\"/>" << std::endl;
        }
        else
            writer.Stream() << writer.ind() << "<FileIncluded file=\"\"/>" << std::endl;
    }
}
コード例 #2
0
void PropertyLinkList::Save (Base::Writer &writer) const
{
    writer.Stream() << writer.ind() << "<LinkList count=\"" <<  getSize() <<"\">" << endl;
    writer.incInd();
    for(int i = 0;i<getSize(); i++)
        writer.Stream() << writer.ind() << "<Link value=\"" <<  _lValueList[i]->getNameInDocument() <<"\"/>" << endl; ;
    writer.decInd();
    writer.Stream() << writer.ind() << "</LinkList>" << endl ;
}
コード例 #3
0
void DynamicProperty::Save (Base::Writer &writer) const 
{
    std::map<std::string,Property*> Map;
    getPropertyMap(Map);

    writer.incInd(); // indentation for 'Properties Count'
    writer.Stream() << writer.ind() << "<Properties Count=\"" << Map.size() << "\">" << std::endl;
    std::map<std::string,Property*>::iterator it;
    for (it = Map.begin(); it != Map.end(); ++it)
    {
        writer.incInd(); // indentation for 'Property name'
        // check whether a static or dynamic property
        std::map<std::string,PropData>::const_iterator pt = props.find(it->first);
        if (pt == props.end()) {
            writer.Stream() << writer.ind() << "<Property name=\"" << it->first << "\" type=\"" 
                            << it->second->getTypeId().getName() << "\">" << std::endl;
        }
        else {
            writer.Stream() << writer.ind() << "<Property name=\"" << it->first
                            << "\" type=\"" << it->second->getTypeId().getName()
                            << "\" group=\"" << encodeAttribute(pt->second.group)
                            << "\" doc=\"" << encodeAttribute(pt->second.doc)
                            << "\" attr=\"" << pt->second.attr << "\" ro=\"" << pt->second.readonly
                            << "\" hide=\"" << pt->second.hidden << "\">" << std::endl;
        }

        writer.incInd(); // indentation for the actual property
        try {
            // We must make sure to handle all exceptions accordingly so that
            // the project file doesn't get invalidated. In the error case this
            // means to proceed instead of aborting the write operation.

            // Don't write transient properties 
            if (!(getPropertyType(it->second) & Prop_Transient))
                it->second->Save(writer);
        }
        catch (const Base::Exception &e) {
            Base::Console().Error("%s\n", e.what());
        }
        catch (const std::exception &e) {
            Base::Console().Error("%s\n", e.what());
        }
        catch (const char* e) {
            Base::Console().Error("%s\n", e);
        }
#ifndef FC_DEBUG
        catch (...) {
            Base::Console().Error("DynamicProperty::Save: Unknown C++ exception thrown. Try to continue...\n");
        }
#endif
        writer.decInd(); // indentation for the actual property
        writer.Stream() << writer.ind() << "</Property>" << std::endl;
        writer.decInd(); // indentation for 'Property name'
    }
    writer.Stream() << writer.ind() << "</Properties>" << std::endl;
    writer.decInd(); // indentation for 'Properties Count'
}
コード例 #4
0
void PropertyIntegerList::Save (Base::Writer &writer) const
{
    writer.Stream() << writer.ind() << "<IntegerList count=\"" <<  getSize() <<"\">" << endl;
    writer.incInd();
    for(int i = 0;i<getSize(); i++)
        writer.Stream() << writer.ind() << "<I v=\"" <<  _lValueList[i] <<"\"/>" << endl; ;
    writer.decInd();
    writer.Stream() << writer.ind() << "</IntegerList>" << endl ;
}
コード例 #5
0
void PropertyBool::Save (Base::Writer &writer) const
{
    writer.Stream() << writer.ind() << "<Bool value=\"" ;
    if (_lValue)
        writer.Stream() << "true" <<"\"/>" ;
    else
        writer.Stream() << "false" <<"\"/>" ;
    writer.Stream() << std::endl;
}
コード例 #6
0
void PropertyStringList::Save (Base::Writer &writer) const
{
    writer.Stream() << writer.ind() << "<StringList count=\"" <<  getSize() <<"\">" << endl;
    writer.incInd();
    for(int i = 0;i<getSize(); i++) {
        std::string val = encodeAttribute(_lValueList[i]);
        writer.Stream() << writer.ind() << "<String value=\"" <<  val <<"\"/>" << endl;
    }
    writer.decInd();
    writer.Stream() << writer.ind() << "</StringList>" << endl ;
}
コード例 #7
0
void PropertyMeshKernel::Save (Base::Writer &writer) const
{
    if (writer.isForceXML()) {
        writer.Stream() << writer.ind() << "<Mesh>" << std::endl;
        MeshCore::MeshOutput saver(_meshObject->getKernel());
        saver.SaveXML(writer);
    }
    else {
        writer.Stream() << writer.ind() << "<Mesh file=\"" << 
        writer.addFile("MeshKernel.bms", this) << "\"/>" << std::endl;
    }
}
コード例 #8
0
void PropertyColumnWidths::Save(Base::Writer &writer) const
{
        // Save column information
    writer.Stream() << writer.ind() << "<ColumnInfo Count=\"" << size() << "\">" << std::endl;
    writer.incInd(); // indention for 'ColumnInfo'
    std::map<int, int>::const_iterator coli = begin();
    while (coli != end()) {
        writer.Stream() << writer.ind() << "<Column name=\"" << columnName(coli->first) << "\" width=\"" << coli->second << "\" />" << std::endl;
        ++coli;
    }
    writer.decInd(); // indention for 'ColumnInfo'
    writer.Stream() << writer.ind() << "</ColumnInfo>" << std::endl;
}
コード例 #9
0
void PropertyContainer::Save (Base::Writer &writer) const
{
    std::map<std::string,Property*> Map;
    getPropertyMap(Map);

    // ignore the properties we won't store
    size_t ct = std::count_if(Map.begin(), Map.end(), std::bind2nd(PropertyAttribute
        <std::pair<std::string,Property*> >(this), Prop_Transient));
    size_t size = Map.size() - ct;

    writer.incInd(); // indentation for 'Properties Count'
    writer.Stream() << writer.ind() << "<Properties Count=\"" << size << "\">" << endl;
    std::map<std::string,Property*>::iterator it;
    for (it = Map.begin(); it != Map.end(); ++it)
    {
        // Don't write transient properties
        if (!(getPropertyType(it->second) & Prop_Transient))
        {
            writer.incInd(); // indentation for 'Property name'
            writer.Stream() << writer.ind() << "<Property name=\"" << it->first << "\" type=\""
                            << it->second->getTypeId().getName() << "\">" << endl;;
            writer.incInd(); // indentation for the actual property
            try {
                // We must make sure to handle all exceptions accordingly so that
                // the project file doesn't get invalidated. In the error case this
                // means to proceed instead of aborting the write operation.
                it->second->Save(writer);
            }
            catch (const Base::Exception &e) {
                Base::Console().Error("%s\n", e.what());
            }
            catch (const std::exception &e) {
                Base::Console().Error("%s\n", e.what());
            }
            catch (const char* e) {
                Base::Console().Error("%s\n", e);
            }
#ifndef FC_DEBUG
            catch (...) {
                Base::Console().Error("PropertyContainer::Save: Unknown C++ exception thrown. Try to continue...\n");
            }
#endif
            writer.decInd(); // indentation for the actual property
            writer.Stream() << writer.ind() << "</Property>" << endl;
            writer.decInd(); // indentation for 'Property name'
        }
    }
    writer.Stream() << writer.ind() << "</Properties>" << endl;
    writer.decInd(); // indentation for 'Properties Count'
}
コード例 #10
0
void PropertyExpressionEngine::Save(Base::Writer &writer) const
{
    writer.Stream() << writer.ind() << "<ExpressionEngine count=\"" <<  expressions.size() <<"\">" << std::endl;
    writer.incInd();
    for (ExpressionMap::const_iterator it = expressions.begin(); it != expressions.end(); ++it) {
        writer.Stream() << writer.ind() << "<Expression path=\"" <<  Property::encodeAttribute(it->first.toString()) <<"\"" <<
                           " expression=\"" << Property::encodeAttribute(it->second.expression->toString()) << "\"";
        if (it->second.comment.size() > 0)
            writer.Stream() << " comment=\"" << Property::encodeAttribute(it->second.comment) << "\"";
        writer.Stream() << "/>" << std::endl;
    }
    writer.decInd();
    writer.Stream() << writer.ind() << "</ExpressionEngine>" << std::endl;
}
コード例 #11
0
void PropertyRowHeights::Save(Base::Writer &writer) const
{
    // Save row information
    writer.Stream() << writer.ind() << "<RowInfo Count=\"" << size() << "\">" << std::endl;
    writer.incInd(); // indention for 'RowInfo'

    std::map<int, int>::const_iterator ri = begin();
    while (ri != end()) {
        writer.Stream() << writer.ind() << "<Row name=\"" << rowName(ri->first) << "\"  height=\"" << ri->second << "\" />" << std::endl;
        ++ri;
    }
    writer.decInd(); // indention for 'RowInfo'
    writer.Stream() << writer.ind() << "</RowInfo>" << std::endl;
}
コード例 #12
0
void PropertyLinkSub::Save (Base::Writer &writer) const
{
    const char* internal_name = "";
    // it can happen that the object is still alive but is not part of the document anymore and thus
    // returns 0
    if (_pcLinkSub && _pcLinkSub->getNameInDocument())
        internal_name = _pcLinkSub->getNameInDocument();
    writer.Stream() << writer.ind() << "<LinkSub value=\"" <<  internal_name <<"\" count=\"" <<  _cSubList.size() <<"\">" << std::endl;
    writer.incInd();
    for(unsigned int i = 0;i<_cSubList.size(); i++)
        writer.Stream() << writer.ind() << "<Sub value=\"" <<  _cSubList[i]<<"\"/>" << endl;
    writer.decInd();
    writer.Stream() << writer.ind() << "</LinkSub>" << endl ;
}
コード例 #13
0
ファイル: Properties.cpp プロジェクト: 3DPrinterGuy/FreeCAD
void PropertyGreyValueList::Save (Base::Writer &writer) const
{
    if (writer.isForceXML()) {
        writer.Stream() << writer.ind() << "<FloatList count=\"" <<  getSize() <<"\">" << endl;
        writer.incInd();
        for(int i = 0;i<getSize(); i++)
            writer.Stream() << writer.ind() << "<F v=\"" <<  _lValueList[i] <<"\"/>" << endl; ;
        writer.decInd();
        writer.Stream() << writer.ind() <<"</FloatList>" << endl ;
    }
    else {
        writer.Stream() << writer.ind() << "<FloatList file=\"" << 
        writer.addFile(getName(), this) << "\"/>" << std::endl;
    }
}
コード例 #14
0
void PropertyLinkList::Save(Base::Writer &writer) const
{
    writer.Stream() << writer.ind() << "<LinkList count=\"" << getSize() << "\">" << endl;
    writer.incInd();
    for (int i = 0; i<getSize(); i++) {
        DocumentObject* obj = _lValueList[i];
        if (obj)
            writer.Stream() << writer.ind() << "<Link value=\"" << obj->getNameInDocument() << "\"/>" << endl;
        else
            writer.Stream() << writer.ind() << "<Link value=\"\"/>" << endl;
    }

    writer.decInd();
    writer.Stream() << writer.ind() << "</LinkList>" << endl;
}
コード例 #15
0
void PropertyCurvatureList::Save (Base::Writer &writer) const
{
    if (!writer.isForceXML()) {
        writer.Stream() << writer.ind() << "<CurvatureList file=\"" << 
        writer.addFile(getName(), this) << "\"/>" << std::endl;
    }
}
コード例 #16
0
void PropertyPartShape::Save (Base::Writer &writer) const
{
    if(!writer.isForceXML()) {
        //See SaveDocFile(), RestoreDocFile()
        if (writer.getMode("BinaryBrep")) {
            writer.Stream() << writer.ind() << "<Part file=\"" 
                            << writer.addFile("PartShape.bin", this)
                            << "\"/>" << std::endl;
        }
        else {
            writer.Stream() << writer.ind() << "<Part file=\"" 
                            << writer.addFile("PartShape.brp", this)
                            << "\"/>" << std::endl;
        }
    }
}
コード例 #17
0
ファイル: Thumbnail.cpp プロジェクト: lainegates/FreeCAD
void Thumbnail::SaveDocFile (Base::Writer &writer) const
{
    if (!this->viewer)
        return;
    QImage img;
    try {
        this->viewer->savePicture(this->size, this->size, View3DInventorViewer::Current, img);
    }
    catch (...) {
        return; // offscreen rendering failed
    }

    QPixmap px = Gui::BitmapFactory().pixmap(App::Application::Config()["AppIcon"].c_str());
    px = BitmapFactory().merge(QPixmap::fromImage(img),px,BitmapFactoryInst::BottomRight);

    // according to specification add some meta-information to the image
    uint mt = QDateTime::currentDateTime().toTime_t();
    QString mtime = QString::fromAscii("%1").arg(mt);
    img.setText(QLatin1String("Software"), qApp->applicationName());
    img.setText(QLatin1String("Thumb::Mimetype"), QLatin1String("application/x-extension-fcstd"));
    img.setText(QLatin1String("Thumb::MTime"), mtime);
    img.setText(QLatin1String("Thumb::URI"), this->uri.toString());

    QByteArray ba;
    QBuffer buffer(&ba);
    buffer.open(QIODevice::WriteOnly);
    px.save(&buffer, "PNG");
    writer.Stream().write(ba.constData(), ba.length());
}
コード例 #18
0
ファイル: Points.cpp プロジェクト: pgilfernandez/FreeCAD
void PointKernel::Save (Base::Writer &writer) const
{
    if (!writer.isForceXML()) {
        writer.Stream() << writer.ind()
            << "<Points file=\"" << writer.addFile(writer.ObjectName.c_str(), this) << "\" " 
            << "mtrx=\"" << _Mtrx.toString() << "\"/>" << std::endl;
    }
}
コード例 #19
0
/**
 * Saves the properties of the view providers.
 */
void Document::SaveDocFile (Base::Writer &writer) const
{
    writer.Stream() << "<?xml version='1.0' encoding='utf-8'?>" << std::endl
                    << "<!--" << std::endl
                    << " FreeCAD Document, see http://free-cad.sourceforge.net for more information..."
                    << std::endl << "-->" << std::endl;

    writer.Stream() << "<Document SchemaVersion=\"1\">" << std::endl;

    std::map<const App::DocumentObject*,ViewProviderDocumentObject*>::const_iterator it;

    // writing the view provider names itself
    writer.incInd(); // indention for 'ViewProviderData Count'
    writer.Stream() << writer.ind() << "<ViewProviderData Count=\"" 
                    << d->_ViewProviderMap.size() <<"\">" << std::endl;

    bool xml = writer.isForceXML();
    //writer.setForceXML(true);
    writer.incInd(); // indention for 'ViewProvider name'
    for(it = d->_ViewProviderMap.begin(); it != d->_ViewProviderMap.end(); ++it) {
        const App::DocumentObject* doc = it->first;
        ViewProvider* obj = it->second;
        writer.Stream() << writer.ind() << "<ViewProvider name=\""
                        << doc->getNameInDocument() << "\" "
                        << "expanded=\"" << (doc->testStatus(App::Expand) ? 1:0)
                        << "\">" << std::endl;
        obj->Save(writer);
        writer.Stream() << writer.ind() << "</ViewProvider>" << std::endl;
    }
    writer.setForceXML(xml);

    writer.decInd(); // indention for 'ViewProvider name'
    writer.Stream() << writer.ind() << "</ViewProviderData>" << std::endl;
    writer.decInd();  // indention for 'ViewProviderData Count'

    // set camera settings
    QString viewPos;
    if (d->_pcAppWnd->sendHasMsgToActiveView("GetCamera")) {
        const char* ppReturn=0;
        d->_pcAppWnd->sendMsgToActiveView("GetCamera",&ppReturn);
  
        // remove the first line because it's a comment like '#Inventor V2.1 ascii'
        QStringList lines = QString(QString::fromAscii(ppReturn)).split(QLatin1String("\n"));
        if (lines.size() > 1) {
            lines.pop_front();
            viewPos = lines.join(QLatin1String(" "));
        }
    }

    writer.incInd(); // indention for camera settings
    writer.Stream() << writer.ind() << "<Camera settings=\"" 
                    << (const char*)viewPos.toAscii() <<"\"/>" << std::endl;
    writer.decInd(); // indention for camera settings
    writer.Stream() << "</Document>" << std::endl;
}
コード例 #20
0
void PropertyColorList::SaveDocFile (Base::Writer &writer) const
{
    Base::OutputStream str(writer.Stream());
    uint32_t uCt = (uint32_t)getSize();
    str << uCt;
    for (std::vector<App::Color>::const_iterator it = _lValueList.begin(); it != _lValueList.end(); ++it) {
        str << it->getPackedValue();
    }
}
コード例 #21
0
void PropertyFilletEdges::SaveDocFile (Base::Writer &writer) const
{
    Base::OutputStream str(writer.Stream());
    uint32_t uCt = (uint32_t)getSize();
    str << uCt;
    for (std::vector<FilletElement>::const_iterator it = _lValueList.begin(); it != _lValueList.end(); ++it) {
        str << it->edgeid << it->radius1 << it->radius2;
    }
}
コード例 #22
0
ファイル: Properties.cpp プロジェクト: 3DPrinterGuy/FreeCAD
void PropertyGreyValueList::SaveDocFile (Base::Writer &writer) const
{
    Base::OutputStream str(writer.Stream());
    uint32_t uCt = (uint32_t)getSize();
    str << uCt;
    for (std::vector<float>::const_iterator it = _lValueList.begin(); it != _lValueList.end(); ++it) {
        str << *it;
    }
}
コード例 #23
0
void PropertyNormalList::SaveDocFile (Base::Writer &writer) const
{
    Base::OutputStream str(writer.Stream());
    uint32_t uCt = (uint32_t)getSize();
    str << uCt;
    for (std::vector<Base::Vector3f>::const_iterator it = _lValueList.begin(); it != _lValueList.end(); ++it) {
        str << it->x << it->y << it->z;
    }
}
コード例 #24
0
void PropertyMaterial::Save (Base::Writer &writer) const
{
    writer.Stream() << writer.ind() << "<PropertyMaterial ambientColor=\"" 
        <<  _cMat.ambientColor.getPackedValue() 
        << "\" diffuseColor=\"" <<  _cMat.diffuseColor.getPackedValue() 
        << "\" specularColor=\"" <<  _cMat.specularColor.getPackedValue()
        << "\" emissiveColor=\"" <<  _cMat.emissiveColor.getPackedValue()
        << "\" shininess=\"" <<  _cMat.shininess << "\" transparency=\"" 
        <<  _cMat.transparency << "\"/>" << endl;
}
コード例 #25
0
ファイル: Points.cpp プロジェクト: pgilfernandez/FreeCAD
void PointKernel::SaveDocFile (Base::Writer &writer) const
{
    Base::OutputStream str(writer.Stream());
    uint32_t uCt = (uint32_t)size();
    str << uCt;
    // store the data without transforming it
    for (std::vector<value_type>::const_iterator it = _Points.begin(); it != _Points.end(); ++it) {
        str << it->x << it->y << it->z;
    }
}
コード例 #26
0
void PropertyPythonObject::saveObject(Base::Writer &writer) const
{
    Base::PyGILStateLocker lock;
    try {
        PropertyContainer* parent = this->getContainer();
        if (parent->isDerivedFrom(Base::Type::fromName("App::DocumentObject"))) {
            if (this->object.hasAttr("__object__")) {
                writer.Stream() << " object=\"yes\"";
            }
        }
        if (parent->isDerivedFrom(Base::Type::fromName("Gui::ViewProvider"))) {
            if (this->object.hasAttr("__vobject__")) {
                writer.Stream() << " vobject=\"yes\"";
            }
        }
    }
    catch (Py::Exception& e) {
        e.clear();
    }
}
コード例 #27
0
void PropertyPartShape::SaveDocFile (Base::Writer &writer) const
{
    // If the shape is empty we simply store nothing. The file size will be 0 which
    // can be checked when reading in the data.
    if (_Shape._Shape.IsNull())
        return;
    // NOTE: Cleaning the triangulation may cause problems on some algorithms like BOP
    // Before writing to the project we clean all triangulation data to save memory
    BRepBuilderAPI_Copy copy(_Shape._Shape);
    const TopoDS_Shape& myShape = copy.Shape();
    BRepTools::Clean(myShape); // remove triangulation

    // create a temporary file and copy the content to the zip stream
    // once the tmp. filename is known use always the same because otherwise
    // we may run into some problems on the Linux platform
    static Base::FileInfo fi(Base::FileInfo::getTempFileName());

    if (!BRepTools::Write(myShape,(const Standard_CString)fi.filePath().c_str())) {
        // Note: Do NOT throw an exception here because if the tmp. file could
        // not be created we should not abort.
        // We only print an error message but continue writing the next files to the
        // stream...
        App::PropertyContainer* father = this->getContainer();
        if (father && father->isDerivedFrom(App::DocumentObject::getClassTypeId())) {
            App::DocumentObject* obj = static_cast<App::DocumentObject*>(father);
            Base::Console().Error("Shape of '%s' cannot be written to BRep file '%s'\n", 
                obj->Label.getValue(),fi.filePath().c_str());
        }
        else {
            Base::Console().Error("Cannot save BRep file '%s'\n", fi.filePath().c_str());
        }
    }

    Base::ifstream file(fi, std::ios::in | std::ios::binary);
    if (file){
        unsigned long ulSize = 0; 
        std::streambuf* buf = file.rdbuf();
        if (buf) {
            unsigned long ulCurr;
            ulCurr = buf->pubseekoff(0, std::ios::cur, std::ios::in);
            ulSize = buf->pubseekoff(0, std::ios::end, std::ios::in);
            buf->pubseekoff(ulCurr, std::ios::beg, std::ios::in);
        }

        // read in the ASCII file and write back to the stream
        std::strstreambuf sbuf(ulSize);
        file >> &sbuf;
        writer.Stream() << &sbuf;
    }

    file.close();
    // remove temp file
    fi.deleteFile();
}
コード例 #28
0
void PropertyCurvatureList::SaveDocFile (Base::Writer &writer) const
{
    Base::OutputStream str(writer.Stream());
    uint32_t uCt = (uint32_t)getSize();
    str << uCt;
    for (std::vector<CurvatureInfo>::const_iterator it = _lValueList.begin(); it != _lValueList.end(); ++it) {
        str << it->fMaxCurvature << it->fMinCurvature;
        str << it->cMaxCurvDir.x << it->cMaxCurvDir.y << it->cMaxCurvDir.z;
        str << it->cMinCurvDir.x << it->cMinCurvDir.y << it->cMinCurvDir.z;
    }
}
コード例 #29
0
void PropertyFileIncluded::SaveDocFile (Base::Writer &writer) const
{
    Base::ifstream from(Base::FileInfo(_cValue.c_str()));
    if (!from)
        throw Base::Exception("PropertyFileIncluded::SaveDocFile() "
        "File in document transient dir deleted");

    // copy plain data
    unsigned char c;
    std::ostream& to = writer.Stream();
    while (from.get((char&)c)) {
        to.put((const char)c);
    }
}
コード例 #30
0
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;
    //}
}