diff --git a/src/Mod/Draft/Resources/Draft.qrc b/src/Mod/Draft/Resources/Draft.qrc
index 1df9126aaa..7907e7423e 100644
--- a/src/Mod/Draft/Resources/Draft.qrc
+++ b/src/Mod/Draft/Resources/Draft.qrc
@@ -49,6 +49,7 @@
icons/Draft_Join.svg
icons/Draft_Label.svg
icons/Draft_Layer.svg
+ icons/Draft_LayerManager.svg
icons/Draft_Line.svg
icons/Draft_LinkArray.svg
icons/Draft_Lock.svg
@@ -191,5 +192,6 @@
ui/dialog_AnnotationStyleEditor.ui
ui/TaskPanel_SetStyle.ui
ui/dialogHatch.ui
+ ui/dialogLayers.ui
diff --git a/src/Mod/Draft/Resources/icons/Draft_LayerManager.svg b/src/Mod/Draft/Resources/icons/Draft_LayerManager.svg
new file mode 100644
index 0000000000..34134c781f
--- /dev/null
+++ b/src/Mod/Draft/Resources/icons/Draft_LayerManager.svg
@@ -0,0 +1,515 @@
+
+
+
+
diff --git a/src/Mod/Draft/Resources/ui/dialogLayers.ui b/src/Mod/Draft/Resources/ui/dialogLayers.ui
new file mode 100644
index 0000000000..32c1468231
--- /dev/null
+++ b/src/Mod/Draft/Resources/ui/dialogLayers.ui
@@ -0,0 +1,94 @@
+
+
+ Dialog
+
+
+
+ 0
+ 0
+ 667
+ 320
+
+
+
+ Layers manager
+
+
+ -
+
+
+ true
+
+
+
+ -
+
+
-
+
+
+ New
+
+
+
+ -
+
+
+ Delete
+
+
+
+ -
+
+
+ Select all
+
+
+
+ -
+
+
+ Toggle on/off
+
+
+
+ -
+
+
+ Isolate
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Cancel
+
+
+
+ -
+
+
+ OK
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Mod/Draft/draftguitools/gui_layers.py b/src/Mod/Draft/draftguitools/gui_layers.py
index ab66fa7347..432e754c7f 100644
--- a/src/Mod/Draft/draftguitools/gui_layers.py
+++ b/src/Mod/Draft/draftguitools/gui_layers.py
@@ -30,7 +30,10 @@
# @{
from PySide.QtCore import QT_TRANSLATE_NOOP
+import os
+import FreeCAD
import FreeCADGui as Gui
+import Draft
import Draft_rc
import draftguitools.gui_base as gui_base
@@ -40,6 +43,18 @@ from draftutils.translate import translate
bool(Draft_rc.__name__)
+def getColorIcon(color):
+
+ "returns a QtGui.QIcon from a color 3-float tuple"
+
+ from PySide import QtCore,QtGui
+ c = QtGui.QColor(int(color[0]*255),int(color[1]*255),int(color[2]*255))
+ im = QtGui.QImage(48,48,QtGui.QImage.Format_ARGB32)
+ im.fill(c)
+ px = QtGui.QPixmap.fromImage(im)
+ return QtGui.QIcon(px)
+
+
class Layer(gui_base.GuiCommandSimplest):
"""GuiCommand to create a Layer object in the document."""
@@ -66,6 +81,435 @@ class Layer(gui_base.GuiCommandSimplest):
self.doc.commitTransaction()
+class LayerManager:
+
+ """GuiCommand that displays a Layers manager dialog"""
+
+ def GetResources(self):
+
+ return {'Pixmap' : 'Draft_LayerManager',
+ 'MenuText': QT_TRANSLATE_NOOP("Draft_LayerManager", "Manage layers..."),
+ 'ToolTip' : QT_TRANSLATE_NOOP("Draft_LayerManager", "Set/modify the different layers of this document")}
+
+ def Activated(self):
+
+ from PySide import QtCore, QtGui
+
+ # store changes to be committed
+ self.deleteList = []
+
+ # create the dialog
+ self.dialog = Gui.PySideUic.loadUi(":/ui/dialogLayers.ui")
+
+ # set nice icons
+ self.dialog.setWindowIcon(QtGui.QIcon(":/icons/Draft_Layer.svg"))
+ self.dialog.buttonNew.setIcon(QtGui.QIcon(":/icons/document-new.svg"))
+ self.dialog.buttonDelete.setIcon(QtGui.QIcon(":/icons/delete.svg"))
+ self.dialog.buttonSelectAll.setIcon(QtGui.QIcon(":/icons/edit-select-all.svg"))
+ self.dialog.buttonToggle.setIcon(QtGui.QIcon(":/icons/dagViewVisible.svg"))
+ self.dialog.buttonIsolate.setIcon(QtGui.QIcon(":/icons/view-refresh.svg"))
+ self.dialog.buttonCancel.setIcon(QtGui.QIcon(":/icons/edit_Cancel.svg"))
+ self.dialog.buttonOK.setIcon(QtGui.QIcon(":/icons/edit_OK.svg"))
+
+ # restore window geometry from stored state
+ pref = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft")
+ w = pref.GetInt("LayersManagerWidth",640)
+ h = pref.GetInt("LayersManagerHeight",320)
+ self.dialog.resize(w,h)
+
+ # center the dialog over FreeCAD window
+ mw = Gui.getMainWindow()
+ self.dialog.move(mw.frameGeometry().topLeft() + mw.rect().center() - self.dialog.rect().center())
+
+ # connect signals/slots
+ self.dialog.buttonNew.clicked.connect(self.addItem)
+ self.dialog.buttonDelete.clicked.connect(self.onDelete)
+ self.dialog.buttonSelectAll.clicked.connect(self.dialog.tree.selectAll)
+ self.dialog.buttonToggle.clicked.connect(self.onToggle)
+ self.dialog.buttonCancel.clicked.connect(self.dialog.reject)
+ self.dialog.buttonIsolate.clicked.connect(self.onIsolate)
+ self.dialog.buttonOK.clicked.connect(self.accept)
+ self.dialog.rejected.connect(self.reject)
+
+ # set the model up
+ self.model = QtGui.QStandardItemModel()
+ self.dialog.tree.setModel(self.model)
+ self.dialog.tree.setUniformRowHeights(True)
+ self.dialog.tree.setItemDelegate(Layers_Delegate())
+ self.dialog.tree.setItemsExpandable(False)
+ self.dialog.tree.setRootIsDecorated(False) # removes spacing in first column
+ self.dialog.tree.setSelectionMode(QtGui.QTreeView.ExtendedSelection) # allow to select many
+
+ # fill the tree view
+ self.update()
+
+ # rock 'n roll!!!
+ self.dialog.exec_()
+
+ def accept(self):
+
+ "when OK button is pressed"
+
+ changed = False
+
+ # delete layers
+ for name in self.deleteList:
+ if not changed:
+ FreeCAD.ActiveDocument.openTransaction("Layers change")
+ changed = True
+ FreeCAD.ActiveDocument.removeObject(name)
+
+ # apply changes
+ for row in range(self.model.rowCount()):
+
+ # get or create layer
+ name = self.model.item(row,1).toolTip()
+ obj = None
+ if name:
+ obj = FreeCAD.ActiveDocument.getObject(name)
+ if not obj:
+ if not changed:
+ FreeCAD.ActiveDocument.openTransaction("Layers change")
+ changed = True
+ obj = Draft.make_layer()
+
+ # visibility
+ checked = True if self.model.item(row,0).checkState() == QtCore.Qt.Checked else False
+ if checked != obj.ViewObject.Visibility:
+ if not changed:
+ FreeCAD.ActiveDocument.openTransaction("Layers change")
+ changed = True
+ obj.ViewObject.Visibility = checked
+
+ # label
+ label = self.model.item(row,1).text()
+ if label:
+ if obj.Label != label:
+ if not changed:
+ FreeCAD.ActiveDocument.openTransaction("Layers change")
+ changed = True
+ obj.Label = label
+
+ # line width
+ width = self.model.item(row,2).data(QtCore.Qt.DisplayRole)
+ if width:
+ if obj.ViewObject.LineWidth != width:
+ if not changed:
+ FreeCAD.ActiveDocument.openTransaction("Layers change")
+ changed = True
+ obj.ViewObject.LineWidth = width
+
+ # draw style
+ style = self.model.item(row,3).text()
+ if style:
+ if obj.ViewObject.DrawStyle != style:
+ if not changed:
+ FreeCAD.ActiveDocument.openTransaction("Layers change")
+ changed = True
+ obj.ViewObject.DrawStyle = style
+
+ # line color
+ color = self.model.item(row,4).data(QtCore.Qt.UserRole)
+ if color:
+ if obj.ViewObject.LineColor[3:] != color:
+ if not changed:
+ FreeCAD.ActiveDocument.openTransaction("Layers change")
+ changed = True
+ obj.ViewObject.LineColor = color
+
+ # shape color
+ color = self.model.item(row,5).data(QtCore.Qt.UserRole)
+ if color:
+ if obj.ViewObject.ShapeColor[3:] != color:
+ if not changed:
+ FreeCAD.ActiveDocument.openTransaction("Layers change")
+ changed = True
+ obj.ViewObject.ShapeColor = color
+
+ # transparency
+ transparency = self.model.item(row,6).data(QtCore.Qt.DisplayRole)
+ if transparency:
+ if obj.ViewObject.Transparency != transparency:
+ if not changed:
+ FreeCAD.ActiveDocument.openTransaction("Layers change")
+ changed = True
+ obj.ViewObject.Transparency = transparency
+
+ # line print color
+ color = self.model.item(row,7).data(QtCore.Qt.UserRole)
+ if color:
+ if not "LinePrintColor" in obj.ViewObject.PropertiesList:
+ if hasattr(obj.ViewObject.Proxy,"set_properties"):
+ obj.ViewObject.Proxy.set_properties(obj.ViewObject)
+ if "LinePrintColor" in obj.ViewObject.PropertiesList:
+ if obj.ViewObject.LinePrintColor[3:] != color:
+ if not changed:
+ FreeCAD.ActiveDocument.openTransaction("Layers change")
+ changed = True
+ obj.ViewObject.LinePrintColor = color
+
+ # recompute
+ if changed:
+ FreeCAD.ActiveDocument.commitTransaction()
+ FreeCAD.ActiveDocument.recompute()
+
+ # exit
+ self.dialog.reject()
+
+ def reject(self):
+
+ "when Cancel button is pressed or dialog is closed"
+
+ # save dialog size
+ pref = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft")
+ pref.SetInt("LayersManagerWidth",self.dialog.width())
+ pref.SetInt("LayersManagerHeight",self.dialog.height())
+
+ return True
+
+ def update(self):
+
+ "rebuild the model from document contents"
+
+ self.model.clear()
+
+ # set header
+ self.model.setHorizontalHeaderLabels([translate("Draft","On"),
+ translate("Draft","Name"),
+ translate("Draft","Line width"),
+ translate("Draft","Draw style"),
+ translate("Draft","Line color"),
+ translate("Draft","Face color"),
+ translate("Draft","Transparency"),
+ translate("Draft","Line print color")])
+ self.dialog.tree.header().setDefaultSectionSize(72)
+ self.dialog.tree.setColumnWidth(0,32) # on/off column
+ self.dialog.tree.setColumnWidth(1,128) # name column
+
+ # populate
+ objs = [obj for obj in FreeCAD.ActiveDocument.Objects if Draft.getType(obj) == "Layer"]
+ objs.sort(key=lambda o:o.Label)
+ for obj in objs:
+ self.addItem(obj)
+
+ def addItem(self,obj=None):
+
+ "adds a row to the model"
+
+ from PySide import QtCore, QtGui
+
+ # create row with default values
+ onItem = QtGui.QStandardItem()
+ onItem.setCheckable(True)
+ onItem.setCheckState(QtCore.Qt.Checked)
+ nameItem = QtGui.QStandardItem(translate("Draft","New Layer"))
+ widthItem = QtGui.QStandardItem()
+ widthItem.setData(self.getPref("DefaultShapeLineWidth",2,"Integer"),QtCore.Qt.DisplayRole)
+ styleItem = QtGui.QStandardItem("Solid")
+ lineColorItem = QtGui.QStandardItem()
+ lineColorItem.setData(self.getPref("DefaultShapeLineColor",421075455),QtCore.Qt.UserRole)
+ shapeColorItem = QtGui.QStandardItem()
+ shapeColorItem.setData(self.getPref("DefaultShapeColor",3435973887),QtCore.Qt.UserRole)
+ transparencyItem = QtGui.QStandardItem()
+ transparencyItem.setData(0,QtCore.Qt.DisplayRole)
+ linePrintColorItem = QtGui.QStandardItem()
+ linePrintColorItem.setData(self.getPref("DefaultPrintColor",0),QtCore.Qt.UserRole)
+
+ # populate with object data
+ if obj:
+ onItem.setCheckState(QtCore.Qt.Checked if obj.ViewObject.Visibility else QtCore.Qt.Unchecked)
+ nameItem.setText(obj.Label)
+ nameItem.setToolTip(obj.Name)
+ widthItem.setData(obj.ViewObject.LineWidth,QtCore.Qt.DisplayRole)
+ styleItem.setText(obj.ViewObject.DrawStyle)
+ lineColorItem.setData(obj.ViewObject.LineColor[:3],QtCore.Qt.UserRole)
+ shapeColorItem.setData(obj.ViewObject.ShapeColor[:3],QtCore.Qt.UserRole)
+ transparencyItem.setData(obj.ViewObject.Transparency,QtCore.Qt.DisplayRole)
+ if hasattr(obj.ViewObject,"LinePrintColor"):
+ linePrintColorItem.setData(obj.ViewObject.LinePrintColor[:3],QtCore.Qt.UserRole)
+ lineColorItem.setIcon(getColorIcon(lineColorItem.data(QtCore.Qt.UserRole)))
+ shapeColorItem.setIcon(getColorIcon(shapeColorItem.data(QtCore.Qt.UserRole)))
+ linePrintColorItem.setIcon(getColorIcon(linePrintColorItem.data(QtCore.Qt.UserRole)))
+
+ # append row
+ self.model.appendRow([onItem,
+ nameItem,
+ widthItem,
+ styleItem,
+ lineColorItem,
+ shapeColorItem,
+ transparencyItem,
+ linePrintColorItem])
+
+ def getPref(self,value,default,valuetype="Unsigned"):
+
+ "retrieves a view pref value"
+
+ p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/View")
+ if valuetype == "Unsigned":
+ c = p.GetUnsigned(value,default)
+ r = float((c>>24)&0xFF)/255.0
+ g = float((c>>16)&0xFF)/255.0
+ b = float((c>>8)&0xFF)/255.0
+ return (r,g,b,)
+ elif valuetype == "Integer":
+ return p.GetInt(value,default)
+
+ def onDelete(self):
+
+ "delete selected rows"
+
+ rows = []
+ for index in self.dialog.tree.selectedIndexes():
+ if not index.row() in rows:
+ rows.append(index.row())
+
+ # append layer name to the delete list
+ if index.column() == 1:
+ name = self.model.itemFromIndex(index).toolTip()
+ if name:
+ if not name in self.deleteList:
+ self.deleteList.append(name)
+
+ # delete rows starting from the lowest, to not alter row indexes while deleting
+ rows.sort()
+ rows.reverse()
+ for row in rows:
+ self.model.takeRow(row)
+
+ def onToggle(self):
+
+ "toggle selected layers on/off"
+
+ from PySide import QtCore, QtGui
+
+ state = None
+ for index in self.dialog.tree.selectedIndexes():
+ if index.column() == 0:
+ # get state from first selected row
+ if state is None:
+ if self.model.itemFromIndex(index).checkState() == QtCore.Qt.Checked:
+ state = QtCore.Qt.Unchecked
+ else:
+ state = QtCore.Qt.Checked
+ self.model.itemFromIndex(index).setCheckState(state)
+
+ def onIsolate(self):
+
+ "isolates the selected layers (turns all the others off"
+
+ from PySide import QtCore, QtGui
+
+ onrows = []
+ for index in self.dialog.tree.selectedIndexes():
+ if not index.row() in onrows:
+ onrows.append(index.row())
+ for row in range(self.model.rowCount()):
+ if not row in onrows:
+ self.model.item(row,0).setCheckState(QtCore.Qt.Unchecked)
+
+
+if FreeCAD.GuiUp:
+
+ from PySide import QtCore, QtGui
+
+ class Layers_Delegate(QtGui.QStyledItemDelegate):
+
+ "model delegate"
+
+ def __init__(self, parent=None, *args):
+
+ QtGui.QStyledItemDelegate.__init__(self, parent, *args)
+ # setEditorData() is triggered several times.
+ # But we want to show the color dialog only the first time
+ self.first = True
+
+ def createEditor(self,parent,option,index):
+
+ if index.column() == 0: # Layer on/off
+ editor = QtGui.QCheckBox(parent)
+ if index.column() == 1: # Layer name
+ editor = QtGui.QLineEdit(parent)
+ elif index.column() == 2: # Line width
+ editor = QtGui.QSpinBox(parent)
+ editor.setMaximum(99)
+ elif index.column() == 3: # Line style
+ editor = QtGui.QComboBox(parent)
+ editor.addItems(["Solid","Dashed","Dotted","Dashdot"])
+ elif index.column() == 4: # Line color
+ editor = QtGui.QLineEdit(parent)
+ self.first = True
+ elif index.column() == 5: # Shape color
+ editor = QtGui.QLineEdit(parent)
+ self.first = True
+ elif index.column() == 6: # Transparency
+ editor = QtGui.QSpinBox(parent)
+ editor.setMaximum(100)
+ elif index.column() == 7: # Line print color
+ editor = QtGui.QLineEdit(parent)
+ self.first = True
+ return editor
+
+ def setEditorData(self, editor, index):
+
+ if index.column() == 0: # Layer on/off
+ editor.setChecked(index.data())
+ elif index.column() == 1: # Layer name
+ editor.setText(index.data())
+ elif index.column() == 2: # Line width
+ editor.setValue(index.data())
+ elif index.column() == 3: # Line style
+ editor.setCurrentIndex(["Solid","Dashed","Dotted","Dashdot"].index(index.data()))
+ elif index.column() == 4: # Line color
+ editor.setText(str(index.data(QtCore.Qt.UserRole)))
+ if self.first:
+ c = index.data(QtCore.Qt.UserRole)
+ color = QtGui.QColorDialog.getColor(QtGui.QColor(int(c[0]*255),int(c[1]*255),int(c[2]*255)))
+ editor.setText(str(color.getRgbF()))
+ self.first = False
+ elif index.column() == 5: # Shape color
+ editor.setText(str(index.data(QtCore.Qt.UserRole)))
+ if self.first:
+ c = index.data(QtCore.Qt.UserRole)
+ color = QtGui.QColorDialog.getColor(QtGui.QColor(int(c[0]*255),int(c[1]*255),int(c[2]*255)))
+ editor.setText(str(color.getRgbF()))
+ self.first = False
+ elif index.column() == 6: # Transparency
+ editor.setValue(index.data())
+ elif index.column() == 7: # Line print color
+ editor.setText(str(index.data(QtCore.Qt.UserRole)))
+ if self.first:
+ c = index.data(QtCore.Qt.UserRole)
+ color = QtGui.QColorDialog.getColor(QtGui.QColor(int(c[0]*255),int(c[1]*255),int(c[2]*255)))
+ editor.setText(str(color.getRgbF()))
+ self.first = False
+
+ def setModelData(self, editor, model, index):
+
+ if index.column() == 0: # Layer on/off
+ model.setData(index,editor.isChecked())
+ elif index.column() == 1: # Layer name
+ model.setData(index,editor.text())
+ elif index.column() == 2: # Line width
+ model.setData(index,editor.value())
+ elif index.column() == 3: # Line style
+ model.setData(index,["Solid","Dashed","Dotted","Dashdot"][editor.currentIndex()])
+ elif index.column() == 4: # Line color
+ model.setData(index,eval(editor.text()),QtCore.Qt.UserRole)
+ model.itemFromIndex(index).setIcon(getColorIcon(eval(editor.text())))
+ elif index.column() == 5: # Shape color
+ model.setData(index,eval(editor.text()),QtCore.Qt.UserRole)
+ model.itemFromIndex(index).setIcon(getColorIcon(eval(editor.text())))
+ elif index.column() == 6: # Transparency
+ model.setData(index,editor.value())
+ elif index.column() == 7: # Line prin color
+ model.setData(index,eval(editor.text()),QtCore.Qt.UserRole)
+ model.itemFromIndex(index).setIcon(getColorIcon(eval(editor.text())))
+
+
+
+
Gui.addCommand('Draft_Layer', Layer())
+Gui.addCommand('Draft_LayerManager', LayerManager())
## @}
diff --git a/src/Mod/Draft/draftutils/init_tools.py b/src/Mod/Draft/draftutils/init_tools.py
index 49b401719c..82a7114f0c 100644
--- a/src/Mod/Draft/draftutils/init_tools.py
+++ b/src/Mod/Draft/draftutils/init_tools.py
@@ -112,6 +112,7 @@ def get_draft_utility_commands_menu():
"Draft_ApplyStyle",
"Separator",
"Draft_Layer",
+ "Draft_LayerManager",
"Draft_AddNamedGroup",
"Draft_AddToGroup",
"Draft_SelectGroup",
@@ -130,7 +131,7 @@ def get_draft_utility_commands_menu():
def get_draft_utility_commands_toolbar():
"""Return the utility commands list for the toolbar."""
- return ["Draft_Layer",
+ return ["Draft_LayerManager",
"Draft_AddNamedGroup",
"Draft_AddToGroup",
"Draft_SelectGroup",