void ViewProviderPythonFeatureObserver::slotAppendObject(const Gui::ViewProvider& obj) { if (!obj.isDerivedFrom(Gui::ViewProviderDocumentObject::getClassTypeId())) return; const Gui::ViewProviderDocumentObject& vp = static_cast<const Gui::ViewProviderDocumentObject&>(obj); const App::DocumentObject* docobj = vp.getObject(); App::Document* doc = docobj->getDocument(); std::map<const App::Document*, ObjectProxy>::iterator it = proxyMap.find(doc); if (it != proxyMap.end()) { ObjectProxy::iterator jt = it->second.find(docobj); if (jt != it->second.end()) { Base::PyGILStateLocker lock; try { App::Property* prop = vp.getPropertyByName("Proxy"); if (prop && prop->isDerivedFrom(App::PropertyPythonObject::getClassTypeId())) { // make this delayed so that the corresponding item in the tree view is accessible QApplication::postEvent(this, new PropertyEvent(prop, jt->second)); it->second.erase(jt); } } catch (Py::Exception& e) { e.clear(); } } // all cached objects of the documents are already destroyed else { it->second.clear(); } } }
void ViewProviderPythonFeatureObserver::slotAppendObject(const Gui::ViewProvider& obj) { if (!obj.isDerivedFrom(Gui::ViewProviderDocumentObject::getClassTypeId())) return; const Gui::ViewProviderDocumentObject& vp = static_cast<const Gui::ViewProviderDocumentObject&>(obj); const App::DocumentObject* docobj = vp.getObject(); App::Document* doc = docobj->getDocument(); std::map<const App::Document*, ObjectProxy>::iterator it = proxyMap.find(doc); if (it != proxyMap.end()) { ObjectProxy::iterator jt = it->second.find(docobj); if (jt != it->second.end()) { Base::PyGILStateLocker lock; try { App::Property* prop = vp.getPropertyByName("Proxy"); if (prop && prop->isDerivedFrom(App::PropertyPythonObject::getClassTypeId())) { static_cast<App::PropertyPythonObject*>(prop)->fromString(jt->second); static_cast<App::PropertyPythonObject*>(prop)->touch(); it->second.erase(jt); } } catch (Py::Exception& e) { e.clear(); } } // all cached objects of the documents are already destroyed else { it->second.clear(); } } }
void Part2DObject::Restore(Base::XMLReader &reader) { //override generic restoration to convert Support property from PropertyLinkSub to PropertyLinkSubList reader.readElement("Properties"); int Cnt = reader.getAttributeAsInteger("Count"); for (int i=0 ;i<Cnt ;i++) { reader.readElement("Property"); const char* PropName = reader.getAttribute("name"); const char* TypeName = reader.getAttribute("type"); App::Property* prop = getPropertyByName(PropName); // NOTE: We must also check the type of the current property because a // subclass of PropertyContainer might change the type of a property but // not its name. In this case we would force to read-in a wrong property // type and the behaviour would be undefined. try { if(prop){ if (strcmp(prop->getTypeId().getName(), TypeName) == 0){ prop->Restore(reader); } else if (prop->isDerivedFrom(App::PropertyLinkSubList::getClassTypeId())){ //reading legacy Support - when the Support could only be a single flat face. App::PropertyLinkSub tmp; if (0 == strcmp(tmp.getTypeId().getName(),TypeName)) { tmp.setContainer(this); tmp.Restore(reader); static_cast<App::PropertyLinkSubList*>(prop)->setValue(tmp.getValue(), tmp.getSubValues()); } this->MapMode.setValue(Attacher::mmFlatFace); } } } catch (const Base::XMLParseException&) { throw; // re-throw } 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::Restore: Unknown C++ exception thrown"); } #endif reader.readEndElement("Property"); } reader.readEndElement("Properties"); }
void customEvent(QEvent* e) { PropertyEvent* pe = static_cast<PropertyEvent*>(e); std::set<const Gui::ViewProvider*>::iterator it = viewMap.find(pe->view); // Make sure that the object hasn't been deleted in the meantime (#0001522) if (it != viewMap.end()) { viewMap.erase(it); App::Property* prop = pe->view->getPropertyByName("Proxy"); if (prop && prop->isDerivedFrom(App::PropertyPythonObject::getClassTypeId())) { prop->Paste(*pe->prop); } } delete pe->prop; }
void ViewProviderPythonFeatureObserver::slotDeleteObject(const Gui::ViewProvider& obj) { if (!obj.isDerivedFrom(Gui::ViewProviderDocumentObject::getClassTypeId())) return; const Gui::ViewProviderDocumentObject& vp = static_cast<const Gui::ViewProviderDocumentObject&>(obj); const App::DocumentObject* docobj = vp.getObject(); App::Document* doc = docobj->getDocument(); if (!doc->getUndoMode()) return; // object will be deleted immediately, thus we don't need to store anything Base::PyGILStateLocker lock; try { App::Property* prop = vp.getPropertyByName("Proxy"); if (prop && prop->isDerivedFrom(App::PropertyPythonObject::getClassTypeId())) { proxyMap[doc][docobj] = prop->Copy(); } } catch (Py::Exception& e) { e.clear(); } }
std::string DrawViewSpreadsheet::getSheetImage(void) { std::stringstream result; App::DocumentObject* link = Source.getValue(); std::string scellstart = CellStart.getValue(); std::string scellend = CellEnd.getValue(); std::vector<std::string> availcolumns = getAvailColumns(); // build rows range and columns range std::vector<std::string> columns; std::vector<int> rows; try { for (unsigned int i=0; i<scellstart.length(); ++i) { if (isdigit(scellstart[i])) { columns.push_back(scellstart.substr(0,i)); rows.push_back(std::atoi(scellstart.substr(i,scellstart.length()-1).c_str())); } } for (unsigned int i=0; i<scellend.length(); ++i) { if (isdigit(scellend[i])) { std::string startcol = columns.back(); std::string endcol = scellend.substr(0,i); bool valid = false; for (std::vector<std::string>::const_iterator j = availcolumns.begin(); j != availcolumns.end(); ++j) { if ( (*j) == startcol) { if ( (*j) != endcol) { valid = true; } } else { if (valid) { if ( (*j) == endcol) { columns.push_back((*j)); valid = false; } else { columns.push_back((*j)); } } } } int endrow = std::atoi(scellend.substr(i,scellend.length()-1).c_str()); for (int j=rows.back()+1; j<=endrow; ++j) { rows.push_back(j); } } } } catch (std::exception) { Base::Console().Error("Invalid cell range for %s\n",getNameInDocument()); return result.str(); } // create the containing group std::string ViewName = Label.getValue(); result << getSVGHead(); App::Color c = TextColor.getValue(); result << "<g id=\"" << ViewName << "\">" << endl; // fill the cells float rowoffset = 0.0; float coloffset = 0.0; float cellheight = 100; float cellwidth = 100; std::string celltext; Spreadsheet::Sheet* sheet = static_cast<Spreadsheet::Sheet*>(link); std::vector<std::string> skiplist; for (std::vector<std::string>::const_iterator col = columns.begin(); col != columns.end(); ++col) { // create a group for each column result << " <g id=\"" << ViewName << "_col" << (*col) << "\">" << endl; for (std::vector<int>::const_iterator row = rows.begin(); row != rows.end(); ++row) { // get cell size std::stringstream srow; srow << (*row); App::CellAddress address((*col) + srow.str()); cellwidth = sheet->getColumnWidth(address.col()); cellheight = sheet->getRowHeight(address.row()); celltext = ""; // get the text App::Property* prop = sheet->getPropertyByName(address.toString().c_str()); std::stringstream field; if (prop != 0) { if (prop->isDerivedFrom((App::PropertyQuantity::getClassTypeId()))) field << static_cast<App::PropertyQuantity*>(prop)->getValue(); else if (prop->isDerivedFrom((App::PropertyFloat::getClassTypeId()))) field << static_cast<App::PropertyFloat*>(prop)->getValue(); else if (prop->isDerivedFrom((App::PropertyString::getClassTypeId()))) field << static_cast<App::PropertyString*>(prop)->getValue(); else assert(0); celltext = field.str(); } // get colors, style, alignment and span int alignment; std::string bcolor = "none"; std::string fcolor = c.asCSSString(); std::string textstyle = ""; Spreadsheet::Cell* cell = sheet->getCell(address); if (cell) { App::Color f,b; std::set<std::string> st; int colspan, rowspan; if (cell->getBackground(b)) { bcolor = b.asCSSString(); } if (cell->getForeground(f)) { fcolor = f.asCSSString(); } if (cell->getStyle(st)) { for (std::set<std::string>::const_iterator i = st.begin(); i != st.end(); ++i) { if ((*i) == "bold") textstyle = textstyle + "font-weight: bold; "; else if ((*i) == "italic") textstyle = textstyle + "font-style: italic; "; else if ((*i) == "underline") textstyle = textstyle + "text-decoration: underline; "; } } if (cell->getSpans(rowspan,colspan)) { for (int i=0; i<colspan; ++i) { for (int j=0; j<rowspan; ++j) { App::CellAddress nextcell(address.row()+j,address.col()+i); if (i > 0) cellwidth = cellwidth + sheet->getColumnWidth(nextcell.col()); if (j > 0) cellheight = cellheight + sheet->getRowHeight(nextcell.row()); if ( (i > 0) || (j > 0) ) skiplist.push_back(nextcell.toString()); } } } cell->getAlignment(alignment); } // skip cell if found in skiplist if (std::find(skiplist.begin(), skiplist.end(), address.toString()) == skiplist.end()) { result << " <rect x=\"" << coloffset << "\" y=\"" << rowoffset << "\" width=\"" << cellwidth << "\" height=\"" << cellheight << "\" style=\"fill:" << bcolor << ";stroke-width:" << LineWidth.getValue()/Scale.getValue() << ";stroke:" << c.asCSSString() << ";\" />" << endl; if (alignment & Spreadsheet::Cell::ALIGNMENT_LEFT) result << " <text style=\"" << textstyle << "\" x=\"" << coloffset + TextSize.getValue()/2 << "\" y=\"" << rowoffset + 0.75 * cellheight << "\" font-family=\"" ; if (alignment & Spreadsheet::Cell::ALIGNMENT_HCENTER) result << " <text text-anchor=\"middle\" style=\"" << textstyle << "\" x=\"" << coloffset + cellwidth/2 << "\" y=\"" << rowoffset + 0.75 * cellheight << "\" font-family=\"" ; if (alignment & Spreadsheet::Cell::ALIGNMENT_RIGHT) result << " <text text-anchor=\"end\" style=\"" << textstyle << "\" x=\"" << coloffset + (cellwidth - TextSize.getValue()/2) << "\" y=\"" << rowoffset + 0.75 * cellheight << "\" font-family=\"" ; result << Font.getValue() << "\"" << " font-size=\"" << TextSize.getValue() << "\"" << " fill=\"" << fcolor << "\">" << celltext << "</text>" << endl; } rowoffset = rowoffset + cellheight; } result << " </g>" << endl; rowoffset = 0.0; coloffset = coloffset + cellwidth; } // close the containing group result << "</g>" << endl; result << getSVGTail(); return result.str(); }
App::DocumentObjectExecReturn *FeatureViewSpreadsheet::execute(void) { // quick tests App::DocumentObject* link = Source.getValue(); std::string scellstart = CellStart.getValue(); std::string scellend = CellEnd.getValue(); if (!link) return new App::DocumentObjectExecReturn("No spreadsheet linked"); if (!link->getTypeId().isDerivedFrom(Spreadsheet::Sheet::getClassTypeId())) return new App::DocumentObjectExecReturn("The linked object is not a spreadsheet"); if ( (scellstart.empty()) || (scellend.empty()) ) return new App::DocumentObjectExecReturn("Empty cell value"); // build a list of available colums: A, B, C, ... AA, AB, ... ZY, ZZ. std::string alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; std::vector<std::string> availcolumns; for (int i=0; i<26; ++i) { std::stringstream s; s << alphabet[i]; availcolumns.push_back(s.str()); } for (int i=0; i<26; ++i) { for (int j=0; i<26; ++i) { std::stringstream s; s << alphabet[i] << alphabet[j]; availcolumns.push_back(s.str()); } } // build rows range and columns range std::vector<std::string> columns; std::vector<int> rows; try { for (unsigned int i=0; i<scellstart.length(); ++i) { if (isdigit(scellstart[i])) { columns.push_back(scellstart.substr(0,i)); rows.push_back(std::atoi(scellstart.substr(i,scellstart.length()-1).c_str())); } } for (unsigned int i=0; i<scellend.length(); ++i) { if (isdigit(scellend[i])) { std::string startcol = columns.back(); std::string endcol = scellend.substr(0,i); bool valid = false; for (std::vector<std::string>::const_iterator j = availcolumns.begin(); j != availcolumns.end(); ++j) { if ( (*j) == startcol) { if ( (*j) != endcol) { valid = true; } } else { if (valid) { if ( (*j) == endcol) { columns.push_back((*j)); valid = false; } else { columns.push_back((*j)); } } } } int endrow = std::atoi(scellend.substr(i,scellend.length()-1).c_str()); for (int j=rows.back()+1; j<=endrow; ++j) { rows.push_back(j); } } } } catch (std::exception) { return new App::DocumentObjectExecReturn("Invalid cell range"); } // create the containing group std::string ViewName = Label.getValue(); std::stringstream result,hr,hg,hb; const App::Color& c = Color.getValue(); hr << hex << setfill('0') << setw(2) << (int)(255.0*c.r); hg << hex << setfill('0') << setw(2) << (int)(255.0*c.g); hb << hex << setfill('0') << setw(2) << (int)(255.0*c.b); result << "<g id=\"" << ViewName << "\" transform=\"translate(" << X.getValue() << "," << Y.getValue() << ")" << " rotate(" << Rotation.getValue() << ")" << " scale(" << Scale.getValue() << ")\">" << endl; // fill the cells float rowoffset = 0.0; float coloffset = 0.0; float cellheight = 100; float cellwidth = 100; std::string celltext; Spreadsheet::Sheet* sheet = static_cast<Spreadsheet::Sheet*>(link); std::vector<std::string> skiplist; for (std::vector<std::string>::const_iterator col = columns.begin(); col != columns.end(); ++col) { // create a group for each column result << " <g id=\"" << ViewName << "_col" << (*col) << "\">" << endl; for (std::vector<int>::const_iterator row = rows.begin(); row != rows.end(); ++row) { // get cell size std::stringstream srow; srow << (*row); App::CellAddress address((*col) + srow.str()); cellwidth = sheet->getColumnWidth(address.col()); cellheight = sheet->getRowHeight(address.row()); celltext = ""; // get the text App::Property* prop = sheet->getPropertyByName(address.toString().c_str()); std::stringstream field; if (prop != 0) { if (prop->isDerivedFrom((App::PropertyQuantity::getClassTypeId()))) field << static_cast<App::PropertyQuantity*>(prop)->getValue(); else if (prop->isDerivedFrom((App::PropertyFloat::getClassTypeId()))) field << static_cast<App::PropertyFloat*>(prop)->getValue(); else if (prop->isDerivedFrom((App::PropertyString::getClassTypeId()))) field << static_cast<App::PropertyString*>(prop)->getValue(); else assert(0); celltext = field.str(); } // get colors, style, alignment and span int alignment; std::string bcolor = "none"; std::string fcolor = "#" + hr.str() + hg.str() + hb.str(); std::string textstyle = ""; Spreadsheet::Cell* cell = sheet->getCell(address); if (cell) { App::Color f,b; std::set<std::string> st; int colspan, rowspan; if (cell->getBackground(b)) { std::stringstream br,bg,bb; br << hex << setfill('0') << setw(2) << (int)(255.0*b.r); bg << hex << setfill('0') << setw(2) << (int)(255.0*b.g); bb << hex << setfill('0') << setw(2) << (int)(255.0*b.b); bcolor = "#" + br.str() + bg.str() + bb.str(); } if (cell->getForeground(f)) { std::stringstream fr,fg,fb; fr << hex << setfill('0') << setw(2) << (int)(255.0*f.r); fg << hex << setfill('0') << setw(2) << (int)(255.0*f.g); fb << hex << setfill('0') << setw(2) << (int)(255.0*f.b); fcolor = "#" + fr.str() + fg.str() + fb.str(); } if (cell->getStyle(st)) { for (std::set<std::string>::const_iterator i = st.begin(); i != st.end(); ++i) { if ((*i) == "bold") textstyle = textstyle + "font-weight: bold; "; else if ((*i) == "italic") textstyle = textstyle + "font-style: italic; "; else if ((*i) == "underline") textstyle = textstyle + "text-decoration: underline; "; } } if (cell->getSpans(rowspan,colspan)) { for (int i=0; i<colspan; ++i) { for (int j=0; j<rowspan; ++j) { App::CellAddress nextcell(address.row()+j,address.col()+i); if (i > 0) cellwidth = cellwidth + sheet->getColumnWidth(nextcell.col()); if (j > 0) cellheight = cellheight + sheet->getRowHeight(nextcell.row()); if ( (i > 0) || (j > 0) ) skiplist.push_back(nextcell.toString()); } } } cell->getAlignment(alignment); } // skip cell if found in skiplist if (std::find(skiplist.begin(), skiplist.end(), address.toString()) == skiplist.end()) { result << " <rect x=\"" << coloffset << "\" y=\"" << rowoffset << "\" width=\"" << cellwidth << "\" height=\"" << cellheight << "\" style=\"fill:" << bcolor << ";stroke-width:" << LineWidth.getValue()/Scale.getValue() << ";stroke:#" << hr.str() << hg.str() << hb.str() << ";\" />" << endl; if (alignment & Spreadsheet::Cell::ALIGNMENT_LEFT) result << " <text style=\"" << textstyle << "\" x=\"" << coloffset + FontSize.getValue()/2 << "\" y=\"" << rowoffset + 0.75 * cellheight << "\" font-family=\"" ; if (alignment & Spreadsheet::Cell::ALIGNMENT_HCENTER) result << " <text text-anchor=\"middle\" style=\"" << textstyle << "\" x=\"" << coloffset + cellwidth/2 << "\" y=\"" << rowoffset + 0.75 * cellheight << "\" font-family=\"" ; if (alignment & Spreadsheet::Cell::ALIGNMENT_RIGHT) result << " <text text-anchor=\"end\" style=\"" << textstyle << "\" x=\"" << coloffset + (cellwidth - FontSize.getValue()/2) << "\" y=\"" << rowoffset + 0.75 * cellheight << "\" font-family=\"" ; result << Font.getValue() << "\"" << " font-size=\"" << FontSize.getValue() << "\"" << " fill=\"" << fcolor << "\">" << celltext << "</text>" << endl; } rowoffset = rowoffset + cellheight; } result << " </g>" << endl; rowoffset = 0.0; coloffset = coloffset + cellwidth; } // close the containing group result << "</g>" << endl; // Apply the resulting fragment ViewResult.setValue(result.str().c_str()); return App::DocumentObject::StdReturn; }
void DrawView::Restore(Base::XMLReader &reader) { // this is temporary code for backwards compat (within v0.17). can probably be deleted once there are no development // fcstd files with old property types in use. reader.readElement("Properties"); int Cnt = reader.getAttributeAsInteger("Count"); for (int i=0 ;i<Cnt ;i++) { reader.readElement("Property"); const char* PropName = reader.getAttribute("name"); const char* TypeName = reader.getAttribute("type"); App::Property* schemaProp = getPropertyByName(PropName); try { if(schemaProp){ if (strcmp(schemaProp->getTypeId().getName(), TypeName) == 0){ //if the property type in obj == type in schema schemaProp->Restore(reader); //nothing special to do } else { if (strcmp(PropName, "Scale") == 0) { if (schemaProp->isDerivedFrom(App::PropertyFloatConstraint::getClassTypeId())){ //right property type schemaProp->Restore(reader); //nothing special to do (redundant) } else { //Scale, but not PropertyFloatConstraint App::PropertyFloat tmp; if (strcmp(tmp.getTypeId().getName(),TypeName)) { //property in file is Float tmp.setContainer(this); tmp.Restore(reader); double tmpValue = tmp.getValue(); if (tmpValue > 0.0) { static_cast<App::PropertyFloatConstraint*>(schemaProp)->setValue(tmpValue); } else { static_cast<App::PropertyFloatConstraint*>(schemaProp)->setValue(1.0); } } else { // has Scale prop that isn't Float! Base::Console().Log("DrawView::Restore - old Document Scale is Not Float!\n"); // no idea } } } else if (strcmp(PropName, "Source") == 0) { App::PropertyLinkGlobal glink; App::PropertyLink link; if (strcmp(glink.getTypeId().getName(),TypeName) == 0) { //property in file is plg glink.setContainer(this); glink.Restore(reader); if (glink.getValue() != nullptr) { static_cast<App::PropertyLinkList*>(schemaProp)->setScope(App::LinkScope::Global); static_cast<App::PropertyLinkList*>(schemaProp)->setValue(glink.getValue()); } } else if (strcmp(link.getTypeId().getName(),TypeName) == 0) { //property in file is pl link.setContainer(this); link.Restore(reader); if (link.getValue() != nullptr) { static_cast<App::PropertyLinkList*>(schemaProp)->setScope(App::LinkScope::Global); static_cast<App::PropertyLinkList*>(schemaProp)->setValue(link.getValue()); } } else { // has Source prop isn't PropertyLink or PropertyLinkGlobal! Base::Console().Log("DrawView::Restore - old Document Source is weird: %s\n", TypeName); // no idea } } else { Base::Console().Log("DrawView::Restore - old Document has unknown Property\n"); } } } } catch (const Base::XMLParseException&) { throw; // re-throw } 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::Restore: Unknown C++ exception thrown\n"); } #endif reader.readEndElement("Property"); } reader.readEndElement("Properties"); }