Skip to content

Commit

Permalink
Material: Fixed the material editor dialog, thanks to rockn
Browse files Browse the repository at this point in the history
  • Loading branch information
yorikvanhavre committed Nov 25, 2015
1 parent a029d90 commit a5852dd
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 67 deletions.
115 changes: 51 additions & 64 deletions src/Mod/Material/MaterialEditor.py
Expand Up @@ -20,68 +20,47 @@
#* *
#***************************************************************************

import FreeCAD, os
import FreeCAD, FreeCADGui, os
from PySide import QtCore, QtGui, QtUiTools

__title__="FreeCAD material editor"
__author__ = "Yorik van Havre"
__url__ = "http://www.freecadweb.org"

# pyside dynamic ui loader from
# from https://github.com/lunaryorn/snippets/blob/master/qt4/designer/pyside_dynamic.py
class UiLoader(QtUiTools.QUiLoader):
def __init__(self, baseinstance):
QtUiTools.QUiLoader.__init__(self, baseinstance)
self.baseinstance = baseinstance

def createWidget(self, class_name, parent=None, name=''):
if parent is None and self.baseinstance:
return self.baseinstance
else:
widget = QtUiTools.QUiLoader.createWidget(self, class_name, parent, name)
if self.baseinstance:
setattr(self.baseinstance, name, widget)
return widget

class MaterialEditor(QtGui.QDialog):
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."""
QtGui.QDialog.__init__(self)
self.obj = obj
self.prop = prop
self.material = material
self.customprops = []
# load the UI file from the same directory as this script
loader = UiLoader(self)
widget = loader.load(os.path.dirname(__file__)+os.sep+"materials-editor.ui")
#QtCore.QMetaObject.connectSlotsByName(widget)
self.ui = self
#print self.ui
#print dir(self.ui)
self.widget = FreeCADGui.PySideUic.loadUi(os.path.dirname(__file__)+os.sep+"materials-editor.ui")
# additional UI fixes and tweaks
self.ButtonURL.setIcon(QtGui.QIcon(":/icons/internet-web-browser.svg"))
self.ButtonDeleteProperty.setEnabled(False)
self.standardButtons.button(QtGui.QDialogButtonBox.Ok).setAutoDefault(False)
self.standardButtons.button(QtGui.QDialogButtonBox.Cancel).setAutoDefault(False)
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.Editor.header().resizeSection(0,200)
self.Editor.expandAll()
self.Editor.setFocus()
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.Editor.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers)
QtCore.QObject.connect(self.ComboMaterial, QtCore.SIGNAL("currentIndexChanged(QString)"), self.updateContents)
QtCore.QObject.connect(self.ButtonURL, QtCore.SIGNAL("clicked()"), self.openProductURL)
QtCore.QObject.connect(self.standardButtons, QtCore.SIGNAL("accepted()"), self.accept)
QtCore.QObject.connect(self.standardButtons, QtCore.SIGNAL("rejected()"), self.reject)
QtCore.QObject.connect(self.ButtonAddProperty, QtCore.SIGNAL("clicked()"), self.addCustomProperty)
QtCore.QObject.connect(self.EditProperty, QtCore.SIGNAL("returnPressed()"), self.addCustomProperty)
QtCore.QObject.connect(self.ButtonDeleteProperty, QtCore.SIGNAL("clicked()"), self.deleteCustomProperty)
QtCore.QObject.connect(self.Editor, QtCore.SIGNAL("itemDoubleClicked(QTreeWidgetItem*,int)"), self.itemClicked)
QtCore.QObject.connect(self.Editor, QtCore.SIGNAL("currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)"), self.checkDeletable)
QtCore.QObject.connect(self.ButtonOpen, QtCore.SIGNAL("clicked()"), self.openfile)
QtCore.QObject.connect(self.ButtonSave, QtCore.SIGNAL("clicked()"), self.savefile)
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("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)
# update the editor with the contents of the property, if we have one
d = None
if self.prop and self.obj:
Expand All @@ -106,10 +85,10 @@ def updateCards(self):
if e.upper() == ".FCMAT":
self.cards[b] = p + os.sep + f
if self.cards:
self.ComboMaterial.clear()
self.ComboMaterial.addItem("") # add a blank item first
self.widget.ComboMaterial.clear()
self.widget.ComboMaterial.addItem("") # add a blank item first
for k,i in self.cards.items():
self.ComboMaterial.addItem(k)
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 or a dictionary)"
Expand All @@ -118,7 +97,7 @@ def updateContents(self,data):
self.clearEditor()
for k,i in data.items():
k = self.expandKey(k)
slot = self.Editor.findItems(k,QtCore.Qt.MatchRecursive,0)
slot = self.widget.Editor.findItems(k,QtCore.Qt.MatchRecursive,0)
if len(slot) == 1:
slot = slot[0]
slot.setText(1,i)
Expand All @@ -135,7 +114,7 @@ def updateContents(self,data):

def openProductURL(self):
"opens the contents of the ProductURL field in an external browser"
url = str(self.Editor.findItems(translate("Material","Product URL"),QtCore.Qt.MatchRecursive,0)[0].text(1))
url = str(self.widget.Editor.findItems(translate("Material","Product URL"),QtCore.Qt.MatchRecursive,0)[0].text(1))
if url:
QtGui.QDesktopServices.openUrl(QtCore.QUrl(url, QtCore.QUrl.TolerantMode))

Expand All @@ -145,7 +124,10 @@ def accept(self):
d = self.getDict()
o = FreeCAD.ActiveDocument.getObject(self.obj)
setattr(o,self.prop,d)
QtGui.QDialog.accept(self)
QtGui.QDialog.accept(self.widget)

def reject(self):
QtGui.QDialog.reject(self.widget)

def expandKey(self, key):
"adds spaces before caps in a KeyName"
Expand All @@ -169,8 +151,8 @@ def collapseKey(self, key):

def clearEditor(self):
"Clears the contents of the editor"
for i1 in range(self.Editor.topLevelItemCount()):
w = self.Editor.topLevelItem(i1)
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,"")
Expand All @@ -180,29 +162,29 @@ def clearEditor(self):
def addCustomProperty(self, key = None, value = None):
"Adds a custom property to the editor, optionally with a value"
if not key:
key = str(self.EditProperty.text())
key = str(self.widget.EditProperty.text())
if key:
if not key in self.customprops:
if not self.Editor.findItems(key,QtCore.Qt.MatchRecursive,0):
top = self.Editor.findItems(translate("Material","User defined"),QtCore.Qt.MatchExactly,0)
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.EditProperty.setText("")
self.widget.EditProperty.setText("")
if value:
i.setText(1,value)

def deleteCustomProperty(self, key = None):
"Deletes a custom property from the editor"
if not key:
key = str(self.Editor.currentItem().text(0))
key = str(self.widget.Editor.currentItem().text(0))
if key:
if key in self.customprops:
i = self.Editor.findItems(key,QtCore.Qt.MatchRecursive,0)
i = self.widget.Editor.findItems(key,QtCore.Qt.MatchRecursive,0)
if i:
top = self.Editor.findItems(translate("Material","User defined"),QtCore.Qt.MatchExactly,0)
top = self.widget.Editor.findItems(translate("Material","User defined"),QtCore.Qt.MatchExactly,0)
if top:
top = top[0]
ii = top.indexOfChild(i[0])
Expand All @@ -213,20 +195,20 @@ def deleteCustomProperty(self, key = None):
def itemClicked(self, item, column):
"Edits an item if it is not in the first column"
if column > 0:
self.Editor.editItem(item, column)
self.widget.Editor.editItem(item, column)

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.ButtonDeleteProperty.setEnabled(True)
self.widget.ButtonDeleteProperty.setEnabled(True)
else:
self.ButtonDeleteProperty.setEnabled(False)
self.widget.ButtonDeleteProperty.setEnabled(False)

def getDict(self):
"returns a dictionnary from the contents of the editor"
d = {}
for i1 in range(self.Editor.topLevelItemCount()):
w = self.Editor.topLevelItem(i1)
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
Expand All @@ -245,7 +227,7 @@ def openfile(self):

def savefile(self):
"Saves a FCMat file"
name = str(self.Editor.findItems(translate("Material","Name"),QtCore.Qt.MatchRecursive,0)[0].text(1))
name = str(self.widget.Editor.findItems(translate("Material","Name"),QtCore.Qt.MatchRecursive,0)[0].text(1))
if not name:
name = "Material"
filename = QtGui.QFileDialog.getSaveFileName(QtGui.qApp.activeWindow(),'Save FreeCAD Material file',name+'.FCMat')
Expand All @@ -255,6 +237,11 @@ def savefile(self):
import importFCMat
importFCMat.write(filename,d)

def show(self):
self.widget.show()

def exec_(self):
self.widget.exec_()

def translate(context,text):
"translates text"
Expand Down
14 changes: 11 additions & 3 deletions src/Mod/Material/importFCMat.py
Expand Up @@ -79,6 +79,9 @@ def decode(name):

def read(filename):
"reads a FCMat file and returns a dictionary from it"
if isinstance(filename,unicode):
import sys
filename = filename.encode(sys.getfilesystemencoding())
f = pythonopen(filename)
d = {}
l = 0
Expand Down Expand Up @@ -118,16 +121,21 @@ def write(filename,dictionary):
user[k] = i
# write header
rev = FreeCAD.ConfigGet("BuildVersionMajor")+"."+FreeCAD.ConfigGet("BuildVersionMinor")+" "+FreeCAD.ConfigGet("BuildRevision")
filename = filename[0]
if isinstance(filename,unicode):
import sys
filename = filename.encode(sys.getfilesystemencoding())
print filename
f = pythonopen(filename,"wb")
f.write("; " + header["CardName"] + "\n")
f.write("; " + header["AuthorAndLicense"] + "\n")
f.write("; " + header["CardName"].encode("utf8") + "\n")
f.write("; " + header["AuthorAndLicense"].encode("utf8") + "\n")
f.write("; file produced by FreeCAD " + rev + "\n")
f.write("; information about the content of this card can be found here:\n")
f.write("; http://www.freecadweb.org/wiki/index.php?title=Material\n")
f.write("\n")
if header["Source"]:
f.write("; source of the data provided in this card:\n")
f.write("; " + header["Source"] + "\n")
f.write("; " + header["Source"].encode("utf8") + "\n")
f.write("\n")
# write sections
for s in contents:
Expand Down

0 comments on commit a5852dd

Please sign in to comment.