Merge branch 'master' into feature/suppress-warnings-preferences

This commit is contained in:
sliptonic
2020-12-18 11:12:48 -06:00
committed by GitHub
23 changed files with 1409 additions and 802 deletions

View File

@@ -1923,6 +1923,15 @@ void Application::runApplication(void)
QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
#endif
// Use software rendering for OpenGL
#if QT_VERSION >= 0x050400
ParameterGrp::handle hOpenGL = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/OpenGL");
bool useSoftwareOpenGL = hOpenGL->GetBool("UseSoftwareOpenGL", false);
if (useSoftwareOpenGL) {
QApplication::setAttribute(Qt::AA_UseSoftwareOpenGL);
}
#endif // QT_VERSION >= 0x050400
// A new QApplication
Base::Console().Log("Init: Creating Gui::Application and QApplication\n");

View File

@@ -108,6 +108,24 @@ will be shown at the lower left corner in opened files</string>
<string>Rendering</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="Gui::PrefCheckBox" name="CheckBox_use_SW_OpenGL">
<property name="toolTip">
<string>This option is useful for troubleshooting graphics card and driver problems.
Changing this option requires a restart of the application.</string>
</property>
<property name="text">
<string>Use software OpenGL</string>
</property>
<property name="prefEntry" stdset="0">
<cstring>UseSoftwareOpenGL</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>OpenGL</cstring>
</property>
</widget>
</item>
<item>
<widget class="Gui::PrefCheckBox" name="CheckBox_useVBO">
<property name="toolTip">

View File

@@ -93,6 +93,7 @@ void DlgSettings3DViewImp::saveSettings()
ui->CheckBox_WbByTab->onSave();
ui->CheckBox_ShowFPS->onSave();
ui->spinPickRadius->onSave();
ui->CheckBox_use_SW_OpenGL->onSave();
ui->CheckBox_useVBO->onSave();
ui->FloatSpinBox_EyeDistance->onSave();
ui->checkBoxBacklight->onSave();
@@ -109,6 +110,7 @@ void DlgSettings3DViewImp::loadSettings()
ui->CheckBox_WbByTab->onRestore();
ui->CheckBox_ShowFPS->onRestore();
ui->spinPickRadius->onRestore();
ui->CheckBox_use_SW_OpenGL->onRestore();
ui->CheckBox_useVBO->onRestore();
ui->FloatSpinBox_EyeDistance->onRestore();
ui->checkBoxBacklight->onRestore();

View File

@@ -1189,6 +1189,8 @@ bool Document::saveAs(void)
escapedstr = Base::Tools::escapeEncodeFilename(escapedstr);
Command::doCommand(Command::Doc,"App.getDocument(\"%s\").saveAs(u\"%s\")"
, DocName, escapedstr.c_str());
// App::Document::saveAs() may modify the passed file name
fi.setFile(QString::fromUtf8(d->_pcDocument->FileName.getValue()));
setModified(false);
getMainWindow()->appendRecentFile(fi.filePath());
}

View File

@@ -337,8 +337,20 @@ TaskDialogPython::~TaskDialogPython()
std::vector< QPointer<QWidget> > guarded;
guarded.insert(guarded.begin(), Content.begin(), Content.end());
Content.clear();
Base::PyGILStateLocker lock;
// The widgets stored in the 'form' attribute will be deleted.
// Thus, set this attribute to None to make sure that when using
// the same dialog instance for a task panel won't segfault.
if (this->dlg.hasAttr(std::string("form"))) {
this->dlg.setAttr(std::string("form"), Py::None());
}
this->dlg = Py::None();
// Assigning None to 'dlg' may destroy some of the stored widgets.
// By guarding them with QPointer their pointers will be set to null
// so that the destructor of the base class can reliably call 'delete'.
Content.insert(Content.begin(), guarded.begin(), guarded.end());
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -105,7 +105,7 @@ Py::Dict TooltablePy::getTools(void) const
{
Py::Dict dict;
for(std::map<int,Path::Tool*>::iterator i = getTooltablePtr()->Tools.begin(); i != getTooltablePtr()->Tools.end(); ++i) {
PyObject *tool = new Path::ToolPy(i->second);
PyObject *tool = new Path::ToolPy(new Tool(*i->second));
dict.setItem(Py::Long(i->first), Py::asObject(tool));
}
return dict;

View File

@@ -35,13 +35,8 @@ __doc__ = "A collection of helper and utility functions for the Path GUI."
def translate(context, text, disambig=None):
return PySide.QtCore.QCoreApplication.translate(context, text, disambig)
LOGLEVEL = False
if LOGLEVEL:
PathLog.setLevel(PathLog.Level.DEBUG, PathLog.thisModule())
PathLog.trackModule(PathLog.thisModule())
else:
PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule())
PathLog.setLevel(PathLog.Level.INFO, PathLog.thisModule())
# PathLog.trackModule(PathLog.thisModule())
def updateInputField(obj, prop, widget, onBeforeChange=None):
@@ -53,7 +48,7 @@ def updateInputField(obj, prop, widget, onBeforeChange=None):
If onBeforeChange is specified it is called before a new value is assigned to the property.
Returns True if a new value was assigned, False otherwise (new value is the same as the current).
'''
value = FreeCAD.Units.Quantity(widget.text()).Value
value = widget.property('rawValue')
attr = PathUtil.getProperty(obj, prop)
attrValue = attr.Value if hasattr(attr, 'Value') else attr
@@ -72,10 +67,10 @@ def updateInputField(obj, prop, widget, onBeforeChange=None):
isDiff = True
break
if noExpr:
widget.setReadOnly(False)
widget.setProperty('readonly', False)
widget.setStyleSheet("color: black")
else:
widget.setReadOnly(True)
widget.setProperty('readonly', True)
widget.setStyleSheet("color: gray")
widget.update()
@@ -100,19 +95,26 @@ class QuantitySpinBox:
'''
def __init__(self, widget, obj, prop, onBeforeChange=None):
self.obj = obj
PathLog.track(widget)
self.widget = widget
self.prop = prop
self.onBeforeChange = onBeforeChange
self.attachTo(obj, prop)
attr = PathUtil.getProperty(self.obj, self.prop)
if attr is not None:
if hasattr(attr, 'Value'):
widget.setProperty('unit', attr.getUserPreferred()[2])
widget.setProperty('binding', "%s.%s" % (obj.Name, prop))
self.valid = True
def attachTo(self, obj, prop = None):
'''attachTo(obj, prop=None) ... use an existing editor for the given object and property'''
self.obj = obj
self.prop = prop
if obj and prop:
attr = PathUtil.getProperty(obj, prop)
if attr is not None:
if hasattr(attr, 'Value'):
self.widget.setProperty('unit', attr.getUserPreferred()[2])
self.widget.setProperty('binding', "%s.%s" % (obj.Name, prop))
self.valid = True
else:
PathLog.warning(translate('PathGui', "Cannot find property %s of %s") % (prop, obj.Label))
self.valid = False
else:
PathLog.warning(translate('PathGui', "Cannot find property %s of %s") % (prop, obj.Label))
self.valid = False
def expression(self):
@@ -122,6 +124,7 @@ class QuantitySpinBox:
return ''
def setMinimum(self, quantity):
'''setMinimum(quantity) ... set the minimum'''
if self.valid:
value = quantity.Value if hasattr(quantity, 'Value') else quantity
self.widget.setProperty('setMinimum', value)

View File

@@ -200,7 +200,9 @@ class ToolBit(object):
return [prop for prop in obj.PropertiesList if obj.getGroupOfProperty(prop) == PropertyGroupAttribute]
def onDocumentRestored(self, obj):
obj.setEditorMode('BitShape', 1)
# when files are shared it is essential to be able to change/set the shape file,
# otherwise the file is hard to use
# obj.setEditorMode('BitShape', 1)
obj.setEditorMode('BitBody', 2)
obj.setEditorMode('File', 1)
obj.setEditorMode('Shape', 2)
@@ -252,7 +254,7 @@ class ToolBit(object):
p = findShape(p)
if not path and p != obj.BitShape:
obj.BitShape = p
doc = FreeCAD.open(p)
doc = FreeCAD.openDocument(p, True)
obj.ShapeName = doc.Name
docOpened = True
return (doc, docOpened)
@@ -286,21 +288,22 @@ class ToolBit(object):
self._removeBitBody(obj)
def _setupBitShape(self, obj, path=None):
PathLog.track(obj.Label)
activeDoc = FreeCAD.ActiveDocument
(doc, docOpened) = self._loadBitBody(obj, path)
obj.Label = doc.RootObjects[0].Label
self._deleteBitSetup(obj)
obj.BitBody = obj.Document.copyObject(doc.RootObjects[0], True)
bitBody = obj.Document.copyObject(doc.RootObjects[0], True)
if docOpened:
FreeCAD.setActiveDocument(activeDoc.Name)
FreeCAD.closeDocument(doc.Name)
if obj.BitBody.ViewObject:
obj.BitBody.ViewObject.Visibility = False
self._copyBitShape(obj)
if bitBody.ViewObject:
bitBody.ViewObject.Visibility = False
for sketch in [o for o in obj.BitBody.Group if o.TypeId == 'Sketcher::SketchObject']:
for sketch in [o for o in bitBody.Group if o.TypeId == 'Sketcher::SketchObject']:
for constraint in [c for c in sketch.Constraints if c.Name != '']:
typ = ParameterTypeConstraint.get(constraint.Type)
PathLog.track(constraint, typ)
@@ -316,6 +319,9 @@ class ToolBit(object):
if constraint.Type == 'Angle':
value = value * 180 / math.pi
PathUtil.setProperty(obj, prop, value)
# has to happen last because it could trigger op.execute evaluations
obj.BitBody = bitBody
self._copyBitShape(obj)
def getBitThumbnail(self, obj):
if obj.BitShape:

View File

@@ -62,24 +62,60 @@ class ToolBitEditor(object):
if self.loadbitbody:
self.tool.Proxy.loadBitBody(self.tool)
# remove example widgets
layout = self.form.bitParams.layout()
for i in range(layout.rowCount() - 1, -1, -1):
layout.removeRow(i)
# used to track property widgets and editors
self.widgets = []
self.setupTool(self.tool)
self.setupAttributes(self.tool)
def setupTool(self, tool):
PathLog.track()
# Can't delete and add fields to the form because of dangling references in case of
# a focus change. see https://forum.freecadweb.org/viewtopic.php?f=10&t=52246#p458583
# Instead we keep widgets once created and use them for new properties, and hide all
# which aren't being needed anymore.
def labelText(name):
return re.sub('([A-Z][a-z]+)', r' \1', re.sub('([A-Z]+)', r' \1', name))
layout = self.form.bitParams.layout()
for i in range(layout.rowCount() - 1, -1, -1):
layout.removeRow(i)
editor = {}
ui = FreeCADGui.UiLoader()
nr = 0
# for all properties either assign them to existing labels and editors
# or create additional ones for them if not enough have already been
# created.
for name in tool.PropertiesList:
if tool.getGroupOfProperty(name) == PathToolBit.PropertyGroupBit:
qsb = ui.createWidget('Gui::QuantitySpinBox')
editor[name] = PathGui.QuantitySpinBox(qsb, tool, name)
label = QtGui.QLabel(re.sub('([A-Z][a-z]+)', r' \1',
re.sub('([A-Z]+)', r' \1', name)))
layout.addRow(label, qsb)
self.bitEditor = editor
if nr < len(self.widgets):
PathLog.debug("re-use row: {} [{}]".format(nr, name))
label, qsb, editor = self.widgets[nr]
label.setText(labelText(name))
editor.attachTo(tool, name)
label.show()
qsb.show()
else:
qsb = ui.createWidget('Gui::QuantitySpinBox')
editor = PathGui.QuantitySpinBox(qsb, tool, name)
label = QtGui.QLabel(labelText(name))
self.widgets.append((label, qsb, editor))
PathLog.debug("create row: {} [{}]".format(nr, name))
if nr >= layout.rowCount():
layout.addRow(label, qsb)
nr = nr + 1
# hide all rows which aren't being used
for i in range(nr, len(self.widgets)):
label, qsb, editor = self.widgets[i]
label.hide()
qsb.hide()
editor.attachTo(None)
PathLog.debug(" hide row: {}".format(i))
img = tool.Proxy.getBitThumbnail(tool)
if img:
self.form.image.setPixmap(QtGui.QPixmap(QtGui.QImage.fromData(img)))
@@ -189,25 +225,28 @@ class ToolBitEditor(object):
self.form.toolName.setText(self.tool.Label)
self.form.shapePath.setText(self.tool.BitShape)
for editor in self.bitEditor:
self.bitEditor[editor].updateSpinBox()
for lbl, qsb, editor in self.widgets:
editor.updateSpinBox()
def updateShape(self):
PathLog.track()
self.tool.BitShape = str(self.form.shapePath.text())
self.setupTool(self.tool)
self.form.toolName.setText(self.tool.Label)
shapePath = str(self.form.shapePath.text())
# Only need to go through this exercise if the shape actually changed.
if self.tool.BitShape != shapePath:
self.tool.BitShape = shapePath
self.setupTool(self.tool)
self.form.toolName.setText(self.tool.Label)
for editor in self.bitEditor:
self.bitEditor[editor].updateSpinBox()
for lbl, qsb, editor in self.widgets:
editor.updateSpinBox()
def updateTool(self):
PathLog.track()
self.tool.Label = str(self.form.toolName.text())
self.tool.BitShape = str(self.form.shapePath.text())
for editor in self.bitEditor:
self.bitEditor[editor].updateProperty()
for lbl, qsb, editor in self.widgets:
editor.updateProperty()
# self.tool.Proxy._updateBitShape(self.tool)

View File

@@ -152,7 +152,9 @@ G0 Z0.500000
table.addTools(t2)
self.assertEqual(len(table.Tools), 2)
self.assertEqual(str(table.Tools), '{1: Tool 12.7mm Drill Bit, 2: Tool my other tool}' )
# gcc7 build needs some special treatment (makes 1L out of a 1) ...
if str(table.Tools) != '{1L: Tool 12.7mm Drill Bit, 2L: Tool my other tool}':
self.assertEqual(str(table.Tools), '{1: Tool 12.7mm Drill Bit, 2: Tool my other tool}')
def test50(self):
"""Test Path.Length calculation"""

View File

@@ -5987,7 +5987,7 @@ void CmdSketcherConstrainAngle::activated(int iMsg)
std::swap(PosId1,PosId2);
}
if(isBsplinePole(Obj, GeoId1) || isBsplinePole(Obj, GeoId2)) {
if(isBsplinePole(Obj, GeoId1) || (GeoId2 != Constraint::GeoUndef && isBsplinePole(Obj, GeoId2))) {
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
QObject::tr("Select an edge that is not a B-spline weight"));
return;
@@ -6538,14 +6538,14 @@ void CmdSketcherConstrainEqual::applyConstraint(std::vector<SelIdPair> &selSeq,
const Part::Geometry *geo1 = Obj->getGeometry(GeoId1);
const Part::Geometry *geo2 = Obj->getGeometry(GeoId2);
if ( (geo1->getTypeId() == Part::GeomLineSegment::getClassTypeId() && geo2->getTypeId() != Part::GeomLineSegment::getClassTypeId()) ||
(geo1->getTypeId() == Part::GeomHyperbola::getClassTypeId() && geo2->getTypeId() != Part::GeomHyperbola::getClassTypeId()) ||
(geo1->getTypeId() == Part::GeomParabola::getClassTypeId() && geo2->getTypeId() != Part::GeomParabola::getClassTypeId()) ||
(isBsplinePole(geo1) && !isBsplinePole(geo1)) ||
if ( (geo1->getTypeId() == Part::GeomLineSegment::getClassTypeId() && geo2->getTypeId() != Part::GeomLineSegment::getClassTypeId()) ||
(geo1->getTypeId() == Part::GeomArcOfHyperbola::getClassTypeId() && geo2->getTypeId() != Part::GeomArcOfHyperbola::getClassTypeId()) ||
(geo1->getTypeId() == Part::GeomArcOfParabola::getClassTypeId() && geo2->getTypeId() != Part::GeomArcOfParabola::getClassTypeId()) ||
(isBsplinePole(geo1) && !isBsplinePole(geo2)) ||
( (geo1->getTypeId() == Part::GeomCircle::getClassTypeId() || geo1->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) &&
(geo2->getTypeId() != Part::GeomCircle::getClassTypeId() || geo2->getTypeId() != Part::GeomArcOfCircle::getClassTypeId())) ||
!(geo2->getTypeId() == Part::GeomCircle::getClassTypeId() || geo2->getTypeId() == Part::GeomArcOfCircle::getClassTypeId())) ||
( (geo1->getTypeId() == Part::GeomEllipse::getClassTypeId() || geo1->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId()) &&
(geo2->getTypeId() != Part::GeomEllipse::getClassTypeId() || geo2->getTypeId() != Part::GeomArcOfEllipse::getClassTypeId())) ){
!(geo2->getTypeId() == Part::GeomEllipse::getClassTypeId() || geo2->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId())) ){
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
QObject::tr("Select two or more edges of similar type"));

View File

@@ -6106,9 +6106,9 @@ bool ViewProviderSketch::setEdit(int ModNum)
// is loaded into the solver, which ensures that any prospective draw using temporal
// geometry (draw with first parameter true) has the right ViewProvider geometry extensions
// set - This fixes Weight constraint dragging on a just opened sketch.
draw(false,true);
getSketchObject()->solve(false);
UpdateSolverInformation();
draw(false,true);
connectUndoDocument = getDocument()
->signalUndoDocument.connect(boost::bind(&ViewProviderSketch::slotUndoDocument, this, bp::_1));

View File

@@ -65,7 +65,7 @@ using namespace TechDraw;
App::PropertyFloatConstraint::Constraints DrawViewBalloon::SymbolScaleRange = { Precision::Confusion(),
std::numeric_limits<double>::max(),
(1.0) };
(0.1) };
//===========================================================================
// DrawViewBalloon
@@ -99,22 +99,20 @@ DrawViewBalloon::DrawViewBalloon(void)
EndType.setEnums(ArrowPropEnum::ArrowTypeEnums);
ADD_PROPERTY(EndType,(prefEnd()));
ADD_PROPERTY_TYPE(EndTypeScale,(1.0),"",(App::PropertyType)(App::Prop_None),"EndType shape scale");
EndTypeScale.setConstraints(&SymbolScaleRange);
BubbleShape.setEnums(balloonTypeEnums);
ADD_PROPERTY(BubbleShape,(prefShape()));
ADD_PROPERTY_TYPE(ShapeScale,(1.0),"",(App::PropertyType)(App::Prop_None),"Balloon shape scale");
ShapeScale.setConstraints(&SymbolScaleRange);
ADD_PROPERTY_TYPE(EndTypeScale,(1.0),"",(App::PropertyType)(App::Prop_None),"EndType shape scale");
ShapeScale.setConstraints(&SymbolScaleRange);
ADD_PROPERTY_TYPE(TextWrapLen,(-1),"",(App::PropertyType)(App::Prop_None),"Text wrap length; -1 means no wrap");
ADD_PROPERTY_TYPE(KinkLength,(prefKinkLength()),"",(App::PropertyType)(App::Prop_None),
"Distance from symbol to leader kink");
ADD_PROPERTY_TYPE(LineVisible,(true),"",(App::PropertyType)(App::Prop_None),"Balloon line visible or hidden");
SourceView.setScope(App::LinkScope::Global);
Rotation.setStatus(App::Property::Hidden,true);
Caption.setStatus(App::Property::Hidden,true);
@@ -130,8 +128,12 @@ void DrawViewBalloon::onChanged(const App::Property* prop)
if (!isRestoring()) {
if ( (prop == &EndType) ||
(prop == &BubbleShape) ||
(prop == &ShapeScale) ||
(prop == &Text) ||
(prop == &KinkLength) ) {
(prop == &KinkLength) ||
(prop == &EndTypeScale) ||
(prop == &OriginX) ||
(prop == &OriginY) ) {
requestPaint();
}
}

View File

@@ -59,7 +59,6 @@ public:
App::PropertyDistance OriginY;
App::PropertyFloat TextWrapLen;
App::PropertyDistance KinkLength;
App::PropertyBool LineVisible;
short mustExecute() const override;

View File

@@ -106,8 +106,8 @@ DrawViewDimension::DrawViewDimension(void)
References3D.setScope(App::LinkScope::Global);
ADD_PROPERTY_TYPE(FormatSpec,(getDefaultFormatSpec()) , "Format", App::Prop_Output,"Dimension Format");
ADD_PROPERTY_TYPE(FormatSpecOverTolerance,("%+g") , "Format", App::Prop_Output,"Dimension Overtolerance Format");
ADD_PROPERTY_TYPE(FormatSpecUnderTolerance,("%+g") , "Format", App::Prop_Output,"Dimension Undertolerance Format");
ADD_PROPERTY_TYPE(FormatSpecOverTolerance,(getDefaultFormatSpec(true)) , "Format", App::Prop_Output,"Dimension Overtolerance Format");
ADD_PROPERTY_TYPE(FormatSpecUnderTolerance,(getDefaultFormatSpec(true)) , "Format", App::Prop_Output,"Dimension Undertolerance Format");
ADD_PROPERTY_TYPE(Arbitrary,(false) ,"Format", App::Prop_Output,"Value overridden by user");
ADD_PROPERTY_TYPE(ArbitraryTolerances,(false) ,"Format", App::Prop_Output,"Tolerance values overridden by user");
@@ -1300,7 +1300,7 @@ std::string DrawViewDimension::getPrefix() const
return result;
}
std::string DrawViewDimension::getDefaultFormatSpec() const
std::string DrawViewDimension::getDefaultFormatSpec(bool isToleranceFormat) const
{
Base::Reference<ParameterGrp> hGrp = App::GetApplication().GetUserParameter()
.GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/TechDraw/Dimensions");
@@ -1333,6 +1333,10 @@ std::string DrawViewDimension::getDefaultFormatSpec() const
}
if (isToleranceFormat) {
formatSpec.replace(QString::fromUtf8("%"), QString::fromUtf8("%+"));
}
return Base::Tools::toStdString(formatSpec);
}

View File

@@ -171,7 +171,7 @@ protected:
virtual void onChanged(const App::Property* prop) override;
virtual void onDocumentRestored() override;
std::string getPrefix() const;
std::string getDefaultFormatSpec() const;
std::string getDefaultFormatSpec(bool isToleranceFormat = false) const;
virtual pointPair getPointsOneEdge();
virtual pointPair getPointsTwoEdges();
virtual pointPair getPointsTwoVerts();

View File

@@ -766,7 +766,7 @@ void QGIViewBalloon::draw()
balloonLines->setPath(dLinePath);
// This overwrites the previously created QPainterPath with empty one, in case it should be hidden. Should be refactored.
if (!balloon->LineVisible.getValue()) {
if (!vp->LineVisible.getValue()) {
arrow->hide();
balloonLines->setPath(QPainterPath());
}

View File

@@ -75,6 +75,7 @@ ViewProviderBalloon::ViewProviderBalloon()
double weight = lg->getWeight("Thin");
delete lg; //Coverity CID 174670
ADD_PROPERTY_TYPE(LineWidth,(weight),group,(App::PropertyType)(App::Prop_None),"Leader line width");
ADD_PROPERTY_TYPE(LineVisible,(true),group,(App::PropertyType)(App::Prop_None),"Balloon line visible or hidden");
ADD_PROPERTY_TYPE(Color,(PreferencesGui::dimColor()),
group,App::Prop_None,"Color of the balloon");
@@ -148,7 +149,8 @@ void ViewProviderBalloon::onChanged(const App::Property* p)
if ((p == &Font) ||
(p == &Fontsize) ||
(p == &Color) ||
(p == &LineWidth)) {
(p == &LineWidth) ||
(p == &LineVisible)) {
QGIView* qgiv = getQView();
if (qgiv) {
qgiv->updateView(true);

View File

@@ -48,6 +48,7 @@ public:
App::PropertyFont Font;
App::PropertyLength Fontsize;
App::PropertyLength LineWidth;
App::PropertyBool LineVisible;
App::PropertyColor Color;
virtual void attach(App::DocumentObject *);

View File

@@ -174,7 +174,7 @@ class FreeCADFileHandler(xml.sax.ContentHandler):
# Print all the contents of the document properties
items = self.contents.items()
items.sort()
items = sorted(items)
for key,value in items:
key = self.clean(key)
value = self.clean(value)
@@ -186,7 +186,7 @@ class FreeCADFileHandler(xml.sax.ContentHandler):
if (tag == "Document") and (self.short != 2):
items = self.contents.items()
items.sort()
items = sorted(items)
for key,value in items:
key = self.clean(key)
if "00000000::" in key: