diff --git a/src/Mod/Material/CMakeLists.txt b/src/Mod/Material/CMakeLists.txt
index 4691095406..7b34903d94 100644
--- a/src/Mod/Material/CMakeLists.txt
+++ b/src/Mod/Material/CMakeLists.txt
@@ -9,6 +9,7 @@ SET(Material_SRCS
importFCMat.py
MaterialEditor.py
materials-editor.ui
+ MatPropDict.xml
)
SOURCE_GROUP("Module" FILES ${Material_SRCS})
diff --git a/src/Mod/Material/MatPropDict.xml b/src/Mod/Material/MatPropDict.xml
new file mode 100644
index 0000000000..6da8438595
--- /dev/null
+++ b/src/Mod/Material/MatPropDict.xml
@@ -0,0 +1,131 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ https://en.wikipedia.org/wiki/Young%27s_modulus
+
+
+ https://en.wikipedia.org/wiki/Poisson%27s_ratio
+
+
+ https://en.wikipedia.org/wiki/Ultimate_tensile_strength
+
+
+ https://en.wikipedia.org/wiki/Compressive_strength
+
+
+ https://en.wikipedia.org/wiki/Yield_Strength
+
+
+ https://en.wikipedia.org/wiki/Ultimate_tensile_strength
+
+
+ https://en.wikipedia.org/wiki/Fracture_toughness
+
+
+ https://en.wikipedia.org/wiki/Friction#Angle_of_friction
+ https://en.m.wikipedia.org/wiki/Mohr%E2%80%93Coulomb_theory
+
+
+
+
+
+ https://en.wikipedia.org/wiki/Thermal_conductivity
+
+
+ https://en.wikipedia.org/wiki/Volumetric_thermal_expansion_coefficient
+
+
+ https://en.wikipedia.org/wiki/Heat_capacity
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Mod/Material/Material.py b/src/Mod/Material/Material.py
index f712213993..98b33f99fd 100644
--- a/src/Mod/Material/Material.py
+++ b/src/Mod/Material/Material.py
@@ -94,87 +94,31 @@ def exportFCMat(fileName, matDict):
configfile.write(Preamble)
Config.write(configfile)
-
def getMaterialAttributeStructure(withSpaces=None):
+
+ ''''''
+
# material properties
- # see the following resources in the FreeCAD wiki for more information about the material specific properties:
+ # see the following resources in the FreeCAD wiki for more informations about the material specific properties:
# https://www.freecadweb.org/wiki/Material_data_model
# https://www.freecadweb.org/wiki/Material
- materialPropertyGroups = (
- ("Meta", (
- "CardName",
- "AuthorAndLicense",
- "Source"
- )),
- ("General", (
- "Name",
- "Father",
- "Description",
- "Density",
- "Vendor",
- "ProductURL",
- "SpecificPrice"
- )),
- ("Mechanical", (
- "YoungsModulus", # https://en.wikipedia.org/wiki/Young%27s_modulus
- "PoissonRatio", # https://en.wikipedia.org/wiki/Poisson%27s_ratio
- "UltimateTensileStrength", # https://en.wikipedia.org/wiki/Ultimate_tensile_strength
- "CompressiveStrength", # https://en.wikipedia.org/wiki/Compressive_strength
- "YieldStrength", # https://en.wikipedia.org/wiki/Yield_Strength
- "UltimateStrain", # https://en.wikipedia.org/wiki/Ultimate_tensile_strength
- "FractureToughness", # https://en.wikipedia.org/wiki/Fracture_toughness
- "AngleOfFriction" # https://en.wikipedia.org/wiki/Friction#Angle_of_friction and https://en.m.wikipedia.org/wiki/Mohr%E2%80%93Coulomb_theory
- )),
- ("Thermal", (
- "ThermalConductivity", # https://en.wikipedia.org/wiki/Thermal_conductivity
- "ThermalExpansionCoefficient", # https://en.wikipedia.org/wiki/Volumetric_thermal_expansion_coefficient
- "SpecificHeat" # https://en.wikipedia.org/wiki/Heat_capacity
- )),
- ("Architectural", (
- "Model",
- "ExecutionInstructions",
- "FireResistanceClass",
- "StandardCode",
- "SoundTransmissionClass",
- "Color",
- "Finish",
- "UnitsPerQuantity",
- "EnvironmentalEfficiencyClass"
- )),
- ("Rendering", (
- "DiffuseColor",
- "AmbientColor",
- "SpecularColor",
- "Shininess",
- "EmissiveColor",
- "Transparency",
- "VertexShader",
- "FragmentShader",
- "TexturePath",
- "TextureScaling"
- )),
- ("Vector rendering", (
- "ViewColor",
- "ViewFillPattern",
- "SectionFillPattern",
- "ViewLinewidth",
- "SectionLinewidth"
- )),
- ("User defined", (
- ))
- )
+
+ import os
+ import xml.etree.ElementTree as ElementTree
+
+ infile = os.path.dirname(__file__) + os.sep + "MatPropDict.xml"
+ tree = ElementTree.parse(infile)
+
if withSpaces:
# on attributes, add a space before a capital letter, will be used for better display in the ui
import re
- newMatProp = []
- for group in materialPropertyGroups:
- newAttr = []
- for attr in group[1]:
- newAttr.append(re.sub(r"(\w)([A-Z])", r"\1 \2", attr))
- newMatProp.append([group[0], newAttr])
- materialPropertyGroups = newMatProp
- # print(materialPropertyGroups)
- return materialPropertyGroups
+ root = tree.getroot()
+ for group in root.getchildren():
+ for proper in group.getchildren():
+ proper.set('Name', re.sub(r"(\w)([A-Z]+)", r"\1 \2",
+ proper.attrib['Name']))
+
+ return tree
if __name__ == '__main__':
diff --git a/src/Mod/Material/MaterialEditor.py b/src/Mod/Material/MaterialEditor.py
index ce2a8f2271..33a5d34c72 100644
--- a/src/Mod/Material/MaterialEditor.py
+++ b/src/Mod/Material/MaterialEditor.py
@@ -24,6 +24,8 @@
from __future__ import print_function
import FreeCAD
import FreeCADGui
+from Units import Unit
+from Units import Quantity
from Material import getMaterialAttributeStructure
import os
from PySide import QtCore, QtGui
@@ -41,42 +43,54 @@ __url__ = "http://www.freecadweb.org"
class MaterialEditor:
def __init__(self, obj=None, prop=None, material=None):
- """Initializes, optionally with an object name and a material property name to edit, or directly
- with a material dictionary."""
+
+ """Initializes, optionally with an object name and a material property
+ name to edit, or directly with a material dictionary."""
+
self.obj = obj
self.prop = prop
self.material = material
self.customprops = []
- # load the UI file from the same directory as this script
- self.widget = FreeCADGui.PySideUic.loadUi(os.path.dirname(__file__) + os.sep + "materials-editor.ui")
- # additional UI fixes and tweaks
- self.widget.ButtonURL.setIcon(QtGui.QIcon(":/icons/internet-web-browser.svg"))
- self.widget.ButtonDeleteProperty.setEnabled(False)
- self.widget.standardButtons.button(QtGui.QDialogButtonBox.Ok).setAutoDefault(False)
- self.widget.standardButtons.button(QtGui.QDialogButtonBox.Cancel).setAutoDefault(False)
- self.updateCards()
- self.widget.Editor.header().resizeSection(0, 200)
- self.widget.Editor.expandAll()
- self.widget.Editor.setFocus()
- # TODO allow to enter a custom property by pressing Enter in the lineedit (currently closes the dialog)
- self.widget.Editor.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers)
- QtCore.QObject.connect(self.widget.ComboMaterial, QtCore.SIGNAL("currentIndexChanged(QString)"), self.updateContents)
- QtCore.QObject.connect(self.widget.ButtonURL, QtCore.SIGNAL("clicked()"), self.openProductURL)
- QtCore.QObject.connect(self.widget.standardButtons, QtCore.SIGNAL("accepted()"), self.accept)
- QtCore.QObject.connect(self.widget.standardButtons, QtCore.SIGNAL("rejected()"), self.reject)
- QtCore.QObject.connect(self.widget.ButtonAddProperty, QtCore.SIGNAL("clicked()"), self.addCustomProperty)
- QtCore.QObject.connect(self.widget.EditProperty, QtCore.SIGNAL("returnPressed()"), self.addCustomProperty)
- QtCore.QObject.connect(self.widget.ButtonDeleteProperty, QtCore.SIGNAL("clicked()"), self.deleteCustomProperty)
- QtCore.QObject.connect(self.widget.Editor, QtCore.SIGNAL("itemDoubleClicked(QTreeWidgetItem*,int)"), self.itemClicked)
- QtCore.QObject.connect(self.widget.Editor, QtCore.SIGNAL("itemChanged(QTreeWidgetItem*,int)"), self.itemChanged)
- QtCore.QObject.connect(self.widget.Editor, QtCore.SIGNAL("currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)"), self.checkDeletable)
- QtCore.QObject.connect(self.widget.ButtonOpen, QtCore.SIGNAL("clicked()"), self.openfile)
- QtCore.QObject.connect(self.widget.ButtonSave, QtCore.SIGNAL("clicked()"), self.savefile)
+ self.internalprops = []
+ self.groups = []
- # add material properties (the keys) to the editor
- for group in getMaterialAttributeStructure(True): # get the mat file structure from material module, use Spaces for better ui
- # print(group)
- self.addPropertiesToGroup(group)
+ # load the UI file from the same directory as this script
+ self.widget =\
+ FreeCADGui.PySideUic.loadUi(os.path.dirname(__file__) +
+ os.sep + "materials-editor.ui")
+
+ # additional UI fixes and tweaks
+ widget = self.widget
+ buttonURL = widget.ButtonURL
+ buttonDeleteProperty = widget.ButtonDeleteProperty
+ buttonAddProperty = widget.ButtonAddProperty
+ standardButtons = widget.standardButtons
+ buttonOpen = widget.ButtonOpen
+ buttonSave = widget.ButtonSave
+ comboMaterial = widget.ComboMaterial
+ treeView = widget.treeView
+
+ buttonURL.setIcon(QtGui.QIcon(":/icons/internet-web-browser.svg"))
+ buttonDeleteProperty.setEnabled(False)
+ standardButtons.button(QtGui.QDialogButtonBox.Ok).setAutoDefault(False)
+ standardButtons.button(QtGui.QDialogButtonBox.Cancel).setAutoDefault(False)
+ self.updateCards()
+ # TODO allow to enter a custom property by pressing Enter in the lineedit (currently closes the dialog)
+
+ standardButtons.rejected.connect(self.reject)
+ standardButtons.accepted.connect(self.accept)
+ buttonOpen.clicked.connect(self.openfile)
+ buttonSave.clicked.connect(self.savefile)
+ buttonURL.clicked.connect(self.openProductURL)
+ comboMaterial.currentIndexChanged[str].connect(self.updateContents)
+ buttonAddProperty.clicked.connect(self.addCustomProperty)
+ buttonDeleteProperty.clicked.connect(self.deleteCustomProperty)
+ treeView.clicked.connect(self.checkDeletable)
+
+ model = QtGui.QStandardItemModel()
+ treeView.setModel(model)
+ treeView.setUniformRowHeights(True)
+ treeView.setItemDelegate(MaterialsDelegate())
# update the editor with the contents of the property, if we have one
d = None
@@ -84,29 +98,104 @@ class MaterialEditor:
d = FreeCAD.ActiveDocument.getObject(self.obj).getPropertyByName(self.prop)
elif self.material:
d = self.material
+
+ self.implementModel()
if d:
self.updateContents(d)
- def addPropertiesToGroup(self, propertygroup=None):
- "Adds property to a known group in Tree widges"
- if propertygroup:
- groupname = propertygroup[0]
- groupproperties = propertygroup[1]
- else:
- return
+ def implementModel(self):
- # parent
- self.widget.Editor.addTopLevelItem(QtGui.QTreeWidgetItem([groupname, ]))
- # how to expand it ?
+ '''implements the model with the material attribute structure.'''
- # childs
- for key in groupproperties:
- if not self.widget.Editor.findItems(key, QtCore.Qt.MatchRecursive, 0):
- top = self.widget.Editor.findItems(translate("Material", groupname), QtCore.Qt.MatchExactly, 0)
- if top:
- i = QtGui.QTreeWidgetItem(top[0])
- i.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEditable | QtCore.Qt.ItemIsDragEnabled | QtCore.Qt.ItemIsUserCheckable | QtCore.Qt.ItemIsEnabled)
- i.setText(0, key)
+ widget = self.widget
+ treeView = widget.treeView
+ model = treeView.model()
+ model.setHorizontalHeaderLabels(["Property", "Value",
+ "Type", "Units"])
+
+ treeView.setColumnWidth(0, 250)
+ treeView.setColumnWidth(1, 250)
+ treeView.setColumnHidden(2, True)
+ treeView.setColumnHidden(3, True)
+
+ tree = getMaterialAttributeStructure(True)
+ MatPropDict = tree.getroot()
+
+ for group in MatPropDict.getchildren():
+ gg = group.attrib['Name']
+ top = QtGui.QStandardItem(gg)
+ model.appendRow([top])
+ self.groups.append(gg)
+
+ for proper in group.getchildren():
+ properDict = proper.attrib
+
+ pp = properDict['Name']
+ item = QtGui.QStandardItem(pp)
+ self.internalprops.append(pp)
+
+ it = QtGui.QStandardItem()
+
+ tt = properDict['Type']
+ itType = QtGui.QStandardItem(tt)
+
+ try:
+ uu = properDict['Units']
+ itUnit = QtGui.QStandardItem(uu)
+ except KeyError:
+ itUnit = QtGui.QStandardItem()
+
+ top.appendRow([item, it, itType, itUnit])
+
+ top.sortChildren(0)
+
+ treeView.expandAll()
+
+ def updateContents(self, data):
+
+ '''updates the contents of the editor with the given data, can be:
+ - the name of a card, if material is changed in editors combo box
+ - a dictionary, if the editor was called with data.'''
+
+ if isinstance(data, dict):
+
+ model = self.widget.treeView.model()
+ root = model.invisibleRootItem()
+ for gg in range(root.rowCount() - 1):
+ group = root.child(gg, 0)
+ for pp in range(group.rowCount()):
+ item = group.child(pp, 0)
+ it = group.child(pp, 1)
+ kk = self.collapseKey(item.text())
+
+ try:
+ value = data[kk]
+ it.setText(value)
+ del data[kk]
+ except KeyError:
+ it.setText("")
+
+ userGroup = root.child(gg + 1, 0)
+ userGroup.setRowCount(0)
+ self.customprops = []
+
+ for k, i in data.items():
+ k = self.expandKey(k)
+ item = QtGui.QStandardItem(k)
+ it = QtGui.QStandardItem(i)
+ userGroup.appendRow([item, it])
+ self.customprops.append(k)
+
+ elif isinstance(data, unicode):
+
+ k = str(data)
+ if k:
+ if k in self.cards:
+
+ import importFCMat
+ d = importFCMat.read(self.cards[k])
+ if d:
+ self.updateContents(d)
def getMaterialResources(self):
self.fem_prefs = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Material/Resources")
@@ -145,11 +234,10 @@ class MaterialEditor:
self.getMaterialResources()
self.cards = {}
for p in self.resources:
- if os.path.exists(p):
- for f in os.listdir(p):
- b, e = os.path.splitext(f)
- if e.upper() == ".FCMAT":
- self.cards[b] = p + os.sep + f
+ for f in os.listdir(p):
+ b, e = os.path.splitext(f)
+ if e.upper() == ".FCMAT":
+ self.cards[b] = p + os.sep + f
# self.outputCards()
if self.cards:
self.widget.ComboMaterial.clear()
@@ -157,46 +245,26 @@ class MaterialEditor:
for k, i in self.cards.items():
self.widget.ComboMaterial.addItem(k)
- def updateContents(self, data):
- '''updates the contents of the editor with the given data, can be:
- - the name of a card, if material is changed in editors combo box
- - a dictionary, if the editor was called with data'''
- # print type(data)
- if isinstance(data, dict):
- self.clearEditor()
- for k, i in data.items():
- k = self.expandKey(k)
- # most material dict keys are added with addPropertiesToGroup, see tuple with all these properties at module end
- slot = self.widget.Editor.findItems(k, QtCore.Qt.MatchRecursive, 0)
- if len(slot) == 1:
- slot = slot[0]
- slot.setText(1, i)
- else:
- self.addCustomProperty(k, i)
- elif isinstance(data, unicode):
- k = str(data)
- if k:
- if k in self.cards:
- import importFCMat
- d = importFCMat.read(self.cards[k])
- if d:
- self.updateContents(d)
-
def openProductURL(self):
- "opens the contents of the ProductURL field in an external browser"
- url = str(self.widget.Editor.findItems(translate("Material", "Product URL"), QtCore.Qt.MatchRecursive, 0)[0].text(1))
+ "opens the contents of the ProductURL field in an external browser."
+
+ model = self.widget.treeView.model()
+ item = model.findItems(translate("Material", "Product URL"),
+ QtCore.Qt.MatchRecursive, 0)[0]
+ group = item.parent()
+ it = group.child(item.row(), 1)
+ url = it.text()
if url:
QtGui.QDesktopServices.openUrl(QtCore.QUrl(url, QtCore.QUrl.TolerantMode))
def accept(self):
- "if we are editing a property, set the property values"
- if self.prop and self.obj:
- d = self.getDict()
- o = FreeCAD.ActiveDocument.getObject(self.obj)
- setattr(o, self.prop, d)
+ ""
+
QtGui.QDialog.accept(self.widget)
def reject(self):
+ ""
+
QtGui.QDialog.reject(self.widget)
def expandKey(self, key):
@@ -219,94 +287,121 @@ class MaterialEditor:
nk += l
return nk
- def clearEditor(self):
- "Clears the contents of the editor"
- for i1 in range(self.widget.Editor.topLevelItemCount()):
- w = self.widget.Editor.topLevelItem(i1)
- for i2 in range(w.childCount()):
- c = w.child(i2)
- c.setText(1, "")
- for k in self.customprops:
- self.deleteCustomProperty(k)
-
def addCustomProperty(self, key=None, value=None):
- "Adds a custom property to the editor, optionally with a value"
+ "Adds a custom property to the editor, optionally with a value."
+
if not key:
- key = str(self.widget.EditProperty.text())
+ key = self.widget.EditProperty.text()
+
if key:
- if key not in self.customprops:
- if not self.widget.Editor.findItems(key, QtCore.Qt.MatchRecursive, 0):
- top = self.widget.Editor.findItems(translate("Material", "User defined"), QtCore.Qt.MatchExactly, 0)
- if top:
- i = QtGui.QTreeWidgetItem(top[0])
- i.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEditable | QtCore.Qt.ItemIsDragEnabled | QtCore.Qt.ItemIsUserCheckable | QtCore.Qt.ItemIsEnabled)
- i.setText(0, key)
- self.customprops.append(key)
- self.widget.EditProperty.setText("")
- if value:
- i.setText(1, value)
+ model = self.widget.treeView.model()
+ item = model.findItems(key, QtCore.Qt.MatchRecursive, 0)
+ if not item:
+
+ top = model.findItems(translate("Material", "User defined"),
+ QtCore.Qt.MatchExactly, 0)[0]
+ item = QtGui.QStandardItem(key)
+ it = QtGui.QStandardItem(value)
+ top.appendRow([item, it])
+ self.customprops.append(key)
def deleteCustomProperty(self, key=None):
- "Deletes a custom property from the editor"
+
+ '''Deletes a custom property from the editor,
+ or deletes the value of an internal property.'''
+
+ widget = self.widget
+ treeView = widget.treeView
+ model = treeView.model()
+ buttonDeleteProperty = widget.ButtonDeleteProperty
+
if not key:
- key = str(self.widget.Editor.currentItem().text(0))
+
+ index = treeView.selectedIndexes()[0]
+ item = model.itemFromIndex(index)
+ key = item.text()
+
if key:
- if key in self.customprops:
- i = self.widget.Editor.findItems(key, QtCore.Qt.MatchRecursive, 0)
- if i:
- top = self.widget.Editor.findItems(translate("Material", "User defined"), QtCore.Qt.MatchExactly, 0)
- if top:
- top = top[0]
- ii = top.indexOfChild(i[0])
- if ii >= 0:
- top.takeChild(ii)
- self.customprops.remove(key)
+ item = model.findItems(key, QtCore.Qt.MatchRecursive, 0)
+ if item:
- def itemClicked(self, item, column):
- "Edits an item if it is not in the first column"
- if column > 0:
- self.widget.Editor.editItem(item, column)
+ index = model.indexFromItem(item[0])
+ topIndex = index.parent()
+ top = model.itemFromIndex(topIndex)
+ row = item[0].row()
- def itemChanged(self, item, column):
- "Handles text changes"
- if item.text(0) == "Section Fill Pattern":
- if column == 1:
- self.setTexture(item.text(1))
+ if key in self.customprops:
+ top.takeRow(row)
+ self.customprops.remove(key)
+ buttonDeleteProperty.setProperty("text", "Delete property")
+
+ elif key in self.internalprops:
+ it = top.child(row, 1)
+ it.setText("")
+ buttonDeleteProperty.setProperty("text", "Delete value")
+
+ buttonDeleteProperty.setEnabled(False)
+
+ def checkDeletable(self, index):
+
+ '''Checks if the current item is a custom or an internal property,
+ and enable the delete property or delete value button.'''
+
+ widget = self.widget
+ buttonDeleteProperty = widget.ButtonDeleteProperty
+ treeView = widget.treeView
+ model = treeView.model()
+ ind = treeView.selectedIndexes()[0]
+ item = model.itemFromIndex(ind)
+ text = item.text()
+
+ if text in self.customprops:
+ buttonDeleteProperty.setEnabled(True)
+ buttonDeleteProperty.setProperty("text", "Delete property")
+
+ elif text in self.internalprops:
+ indParent = ind.parent()
+ group = model.itemFromIndex(indParent)
+ row = item.row()
+ it = group.child(row, 1)
+ buttonDeleteProperty.setProperty("text", "Delete value")
+ if it.text():
+ buttonDeleteProperty.setEnabled(True)
+ else:
+ buttonDeleteProperty.setEnabled(False)
- def checkDeletable(self, current, previous):
- "Checks if the current item is a custom property, if yes enable the delete button"
- if str(current.text(0)) in self.customprops:
- self.widget.ButtonDeleteProperty.setEnabled(True)
else:
- self.widget.ButtonDeleteProperty.setEnabled(False)
+ buttonDeleteProperty.setEnabled(False)
+ buttonDeleteProperty.setProperty("text", "Delete property")
def getDict(self):
- "returns a dictionary from the contents of the editor"
+ "returns a dictionary from the contents of the editor."
+
+ model = self.widget.treeView.model()
+ root = model.invisibleRootItem()
+
d = {}
- for i1 in range(self.widget.Editor.topLevelItemCount()):
- w = self.widget.Editor.topLevelItem(i1)
- for i2 in range(w.childCount()):
- c = w.child(i2)
- # TODO the following should be translated back to english, since text(0) could be translated
- matkey = self.collapseKey(str(c.text(0)))
- matvalue = unicode(c.text(1))
+ for gg in range(root.rowCount()):
+ group = root.child(gg)
+ for row in range(group.rowCount()):
+ kk = group.child(row, 0).text()
+ ii = group.child(row, 1).text()
+
+ # TODO the following should be translated back to english,since text(0) could be translated
+ matkey = self.collapseKey(str(kk))
+ matvalue = unicode(ii)
if matvalue or (matkey == 'Name'):
# use only keys which are not empty and the name even if empty
d[matkey] = matvalue
# self.outputDict(d)
return d
- # ??? after return ???
- if d:
- self.updateContents(d)
- self.widget.Editor.topLevelItem(6).child(4).setToolTip(1, self.getPatternsList())
-
def outputDict(self, d):
print('MaterialEditor dictionary')
for param in d:
print(' ' + param + ' : ' + d[param])
- def setTexture(self, pattern):
+ '''def setTexture(self, pattern):
"displays a texture preview if needed"
self.widget.PreviewVector.hide()
if pattern:
@@ -318,28 +413,36 @@ class MaterialEditor:
pattern = DrawingPatterns.buildFileSwatch(pattern, size=96, png=True)
if pattern:
self.widget.PreviewVector.setPixmap(QtGui.QPixmap(pattern))
- self.widget.PreviewVector.show()
+ self.widget.PreviewVector.show()'''
def openfile(self):
"Opens a FCMat file"
filetuple = QtGui.QFileDialog.getOpenFileName(QtGui.QApplication.activeWindow(), 'Open FreeCAD Material file', '*.FCMat')
filename = filetuple[0] # a tuple of two empty strings returns True, so use the filename directly
if filename:
- self.clearEditor()
import importFCMat
d = importFCMat.read(filename)
if d:
self.updateContents(d)
def savefile(self):
- "Saves a FCMat file"
- name = self.widget.Editor.findItems(translate("Material", "Name"), QtCore.Qt.MatchRecursive, 0)[0].text(1)
+ "Saves a FCMat file."
+
+ model = self.widget.treeView.model()
+ item = model.findItems(translate("Material", "Name"),
+ QtCore.Qt.MatchRecursive, 0)[0]
+ group = item.parent()
+ it = group.child(item.row(), 1)
+ name = it.text()
if sys.version_info.major < 3:
if isinstance(name,unicode):
name = name.encode("utf8")
if not name:
name = "Material"
- filetuple = QtGui.QFileDialog.getSaveFileName(QtGui.QApplication.activeWindow(), 'Save FreeCAD Material file', name + '.FCMat')
+ filetuple =\
+ QtGui.QFileDialog.getSaveFileName(QtGui.QApplication.activeWindow(),
+ 'Save FreeCAD Material file',
+ name + '.FCMat')
filename = filetuple[0] # a tuple of two empty strings returns True, so use the filename directly
if filename:
d = self.getDict()
@@ -347,6 +450,7 @@ class MaterialEditor:
if d:
import importFCMat
importFCMat.write(filename, d)
+ self.updateCards()
def show(self):
return self.widget.show()
@@ -355,6 +459,179 @@ class MaterialEditor:
return self.widget.exec_()
+class MaterialsDelegate(QtGui.QStyledItemDelegate):
+
+ '''provides display and editing facilities for data items from a model.'''
+
+ def __init__(self):
+ ""
+
+ super(MaterialsDelegate, self).__init__()
+
+ def createEditor(self, parent, option, index):
+
+ '''returns the widget used to change data from the model.'''
+
+ model = index.model()
+ column = index.column()
+
+ item = model.itemFromIndex(index)
+ group = item.parent()
+ if not group:
+ return
+
+ if column == 1:
+
+ row = index.row()
+ TT = group.child(row, 2)
+
+ if TT:
+ Type = TT.text()
+ UU = group.child(row, 3)
+ if UU:
+ Units = UU.text()
+ else:
+ Units = None
+
+ else:
+ Type = "String"
+ Units = None
+
+ VV = group.child(row, 1)
+ Value = VV.text()
+
+ editor = matProperWidget(parent, Type, Units, Value)
+
+ elif column == 0:
+
+ if group.text() == "User defined":
+ editor = matProperWidget(parent)
+
+ else:
+ return
+
+ else:
+
+ return
+
+ return editor
+
+ def setEditorData(self, editor, index):
+
+ '''provides the widget with data to manipulate.'''
+
+ Type = editor.property('Type')
+ model = index.model()
+ item = model.itemFromIndex(index)
+
+ if Type == "Color":
+
+ color = editor.property('color')
+ color = color.getRgb()
+ item.setText(str(color))
+
+ elif Type == "File":
+
+ lineEdit = editor.children()[1]
+ item.setText(lineEdit.text())
+
+ else:
+
+ super(MaterialsDelegate, self).setEditorData(editor, index)
+
+
+ui = FreeCADGui.UiLoader()
+
+
+def matProperWidget(parent=None, Type="String", Units=None, Value=None,
+ minimum=None, maximum=None, stepsize=None, precision=None):
+
+ '''customs widgets for the material stuff.'''
+
+ if Type == "String":
+
+ widget = ui.createWidget("Gui::PrefLineEdit")
+
+ elif Type == "URL":
+
+ widget = ui.createWidget("Gui::PrefLineEdit")
+
+ elif Type == "File":
+
+ widget = ui.createWidget("Gui::FileChooser")
+ if Value:
+ lineEdit = widget.children()[1]
+ lineEdit.setText(Value)
+
+ elif Type == "Quantity":
+
+ widget = ui.createWidget("Gui::InputField")
+ if Units:
+ vv = string2tuple(Units)
+ unit = Unit(vv[0], vv[1], vv[2], vv[3],
+ vv[4], vv[5], vv[6], vv[7])
+ quantity = Quantity(1, unit)
+ widget.setProperty('unit', quantity.getUserPreferred()[2])
+
+ elif Type == "Integer":
+
+ widget = ui.createWidget("Gui::UIntSpinBox")
+
+ elif Type == "Float":
+
+ widget = ui.createWidget("Gui::PrefDoubleSpinBox")
+
+ elif Type == "Enumerator":
+
+ widget = ui.createWidget("Gui::PrefComboBox")
+
+ elif Type == "Boolean":
+
+ widget = ui.createWidget("Gui::PrefComboBox")
+ widget.insertItems(0, ['', 'False', 'True'])
+
+ elif Type == "Vector":
+
+ widget = ui.createWidget("Gui::PrefLineEdit")
+
+ elif Type == "Color":
+
+ widget = ui.createWidget("Gui::PrefColorButton")
+ if Value:
+ value = string2tuple(Value)
+ color = QtGui.QColor()
+ color.setRgb(value[0], value[1], value[2], value[3])
+ widget.setProperty('color', color)
+
+ else:
+
+ widget = QtGui.QLineEdit()
+
+ if minimum is not None:
+ widget.setProperty('minimum', minimum)
+ if maximum is not None:
+ widget.setProperty('maximum', maximum)
+ if stepsize is not None:
+ widget.setProperty('stepsize', stepsize)
+ if precision is not None:
+ widget.setProperty('precision', precision)
+
+ widget.setProperty('Type', Type)
+
+ widget.setParent(parent)
+
+ return widget
+
+
+def string2tuple(string):
+ "provisionally"
+ value = string[1:-1]
+ value = value.split(',')
+ value = [int(v) for v in value]
+ value = tuple(value)
+ return value
+
+
def translate(context, text):
"translates text"
return text # TODO use Qt translation mechanism here
diff --git a/src/Mod/Material/importFCMat.py b/src/Mod/Material/importFCMat.py
index f139ec56c7..6fcbccf338 100644
--- a/src/Mod/Material/importFCMat.py
+++ b/src/Mod/Material/importFCMat.py
@@ -22,8 +22,7 @@
import FreeCAD
-# import Material
-from Material import getMaterialAttributeStructure
+import Material
import os
import sys
if sys.version_info.major >= 3:
@@ -105,15 +104,19 @@ def write(filename, dictionary):
"writes the given dictionary to the given file"
# sort the data into sections
contents = []
- for key in getMaterialAttributeStructure(): # get the mat file structure from material module
- contents.append({"keyname": key[0]})
- if key[0] == "Meta":
+ tree = Material.getMaterialAttributeStructure()
+ MatPropDict = tree.getroot()
+ for group in MatPropDict.getchildren():
+ groupName = group.attrib['Name']
+ contents.append({"keyname": groupName})
+ if groupName == "Meta":
header = contents[-1]
- elif key[0] == "User defined":
+ elif groupName == "User defined":
user = contents[-1]
- for p in key[1]:
- contents[-1][p] = ""
- for k, i in dictionary.items():
+ for proper in group.getchildren():
+ properName = proper.attrib['Name']
+ contents[-1][properName] = ""
+ for k, i in dictionary.iteritems():
found = False
for group in contents:
if not found:
diff --git a/src/Mod/Material/materials-editor.ui b/src/Mod/Material/materials-editor.ui
index 4ef6dde150..1b2058ca47 100644
--- a/src/Mod/Material/materials-editor.ui
+++ b/src/Mod/Material/materials-editor.ui
@@ -143,44 +143,7 @@
QLayout::SetMaximumSize
-
-
-
-
- 0
- 0
-
-
-
-
- 0
- 300
-
-
-
- true
-
-
- 2
-
-
- true
-
-
- 150
-
-
- true
-
-
-
- Property
-
-
-
-
- Value
-
-
+