diff --git a/src/Mod/Spreadsheet/InitGui.py b/src/Mod/Spreadsheet/InitGui.py index 7bd9f81091c4..13de247fef21 100644 --- a/src/Mod/Spreadsheet/InitGui.py +++ b/src/Mod/Spreadsheet/InitGui.py @@ -54,7 +54,7 @@ class SpreadsheetWorkbench(Workbench): def Initialize(self): import Spreadsheet,Spreadsheet_rc from DraftTools import translate - commands = ["Spreadsheet_Create","Spreadsheet_Controller"] + commands = ["Spreadsheet_Create","Spreadsheet_Controller","Spreadsheet_PropertyController"] self.appendToolbar(str(translate("Spreadsheet","Spreadsheet tools")),commands) self.appendMenu(str(translate("Spreadsheet","&Spreadsheet")),commands) FreeCADGui.addIconPath(":/icons") diff --git a/src/Mod/Spreadsheet/Resources/Spreadsheet.qrc b/src/Mod/Spreadsheet/Resources/Spreadsheet.qrc index 1ef25a0d43d8..4ad2c81fd8b6 100644 --- a/src/Mod/Spreadsheet/Resources/Spreadsheet.qrc +++ b/src/Mod/Spreadsheet/Resources/Spreadsheet.qrc @@ -2,5 +2,6 @@ icons/Spreadsheet.svg icons/SpreadsheetController.svg + icons/SpreadsheetPropertyController.svg diff --git a/src/Mod/Spreadsheet/Resources/icons/SpreadsheetPropertyController.svg b/src/Mod/Spreadsheet/Resources/icons/SpreadsheetPropertyController.svg new file mode 100644 index 000000000000..94988cb08e6b --- /dev/null +++ b/src/Mod/Spreadsheet/Resources/icons/SpreadsheetPropertyController.svg @@ -0,0 +1,198 @@ + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + diff --git a/src/Mod/Spreadsheet/Spreadsheet.py b/src/Mod/Spreadsheet/Spreadsheet.py index 75b90b571f81..58c99181bf17 100644 --- a/src/Mod/Spreadsheet/Spreadsheet.py +++ b/src/Mod/Spreadsheet/Spreadsheet.py @@ -215,6 +215,7 @@ def __init__(self,obj=None): if obj: obj.Proxy = self obj.addProperty("App::PropertyLinkList","Controllers","Base","Cell controllers of this object") + self.Object = obj.Name self._cells = {} # this stores cell contents self._relations = {} # this stores relations - currently not used self.cols = [] # this stores filled columns @@ -245,6 +246,7 @@ def __setattr__(self, key, value): if not r in self.rows: self.rows.append(r) self.rows.sort() + self.updateControlledProperties(key) else: self.__dict__.__setitem__(key,value) @@ -266,6 +268,8 @@ def __getattr__(self, key): def __getstate__(self): self._cells["Type"] = self.Type + if hasattr(self,"Object"): + self._cells["Object"] = self.Object return self._cells def __setstate__(self,state): @@ -275,6 +279,9 @@ def __setstate__(self,state): if "Type" in self._cells.keys(): self.Type = self._cells["Type"] del self._cells["Type"] + if "Object" in self._cells.keys(): + self.Object = self._cells["Object"] + del self._cells["Object"] # updating relation tables self.rows = [] self.cols = [] @@ -423,16 +430,57 @@ def setControlledCells(self,obj): if obj: if hasattr(obj,"Controllers"): for co in obj.Controllers: - co.Proxy.setCells(co,obj) + import Draft + if Draft.getType(co) == "SpreadsheetController": + co.Proxy.setCells(co,obj) def getControlledCells(self,obj): "returns a list of cells managed by controllers" cells = [] if hasattr(obj,"Controllers"): - for c in obj.Controllers: - cells.extend(c.Proxy.getCells(c,obj)) + for co in obj.Controllers: + import Draft + if Draft.getType(co) == "SpreadsheetController": + cells.extend(co.Proxy.getCells(co,obj)) return cells + def getControllingCells(self,obj): + "returns a list of controlling cells managed by controllers" + cells = [] + if hasattr(obj,"Controllers"): + for co in obj.Controllers: + import Draft + if Draft.getType(co) == "SpreadsheetPropertyController": + if co.Cell: + cells.append(co.Cell.lower()) + return cells + + def updateControlledProperties(self,key): + "updates the properties of controlled objects" + if hasattr(self,"Object"): + obj = FreeCAD.ActiveDocument.getObject(self.Object) + if obj: + import Draft + if Draft.getType(obj) == "Spreadsheet": + if hasattr(obj,"Controllers"): + for co in obj.Controllers: + if Draft.getType(co) == "SpreadsheetPropertyController": + if co.Cell.upper() == key.upper(): + if co.TargetObject and co.TargetProperty: + b = co.TargetObject + props = co.TargetProperty.split(".") + for p in props: + if hasattr(b,p): + if p != props[-1]: + b = getattr(b,p) + else: + return + try: + setattr(b,p,self._cells[key]) + if DEBUG: print "setting property ",co.TargetProperty, " of object ",co.TargetObject.Name, " to ",self._cells[key] + except: + if DEBUG: print "unable to set property ",co.TargetProperty, " of object ",co.TargetObject.Name, " to ",self._cells[key] + class ViewProviderSpreadsheet(object): def __init__(self, vobj): @@ -454,6 +502,7 @@ def setEdit(self,vobj,mode): return True def unsetEdit(self,vobj,mode): + del self.editor return False def claimChildren(self): @@ -590,6 +639,39 @@ def getIcon(self): return ":/icons/SpreadsheetController.svg" +class SpreadsheetPropertyController: + "A spreadsheet property controller object" + def __init__(self,obj): + obj.Proxy = self + self.Type = "SpreadsheetPropertyController" + obj.addProperty("App::PropertyLink","TargetObject","Base","The object that must be controlled") + obj.addProperty("App::PropertyString","TargetProperty","Base","The property of the target object to control") + obj.addProperty("App::PropertyString","Cell","Base","The cell that contains the value to apply to the property") + + def execute(self,obj): + pass + + def __getstate__(self): + return self.Type + + def __setstate__(self,state): + if state: + self.Type = state + + def onChanged(self,obj,prop): + pass + + +class ViewProviderSpreadsheetPropertyController: + "A view provider for the spreadsheet property controller" + def __init__(self,vobj): + vobj.Proxy = self + + def getIcon(self): + import Spreadsheet_rc + return ":/icons/SpreadsheetPropertyController.svg" + + class SpreadsheetView(QtGui.QWidget): "A spreadsheet viewer for FreeCAD" @@ -643,6 +725,7 @@ def update(self): "updates the cells with the contents of the spreadsheet" if self.spreadsheet: controlled = self.spreadsheet.Proxy.getControlledCells(self.spreadsheet) + controlling = self.spreadsheet.Proxy.getControllingCells(self.spreadsheet) for cell in self.spreadsheet.Proxy._cells.keys(): if cell != "Type": c,r = self.spreadsheet.Proxy.splitKey(cell) @@ -663,6 +746,11 @@ def update(self): brush.setStyle(QtCore.Qt.Dense6Pattern) if self.table.item(r,c): self.table.item(r,c).setBackground(brush) + elif cell in controlling: + brush = QtGui.QBrush(QtGui.QColor(0, 0, 255)) + brush.setStyle(QtCore.Qt.Dense6Pattern) + if self.table.item(r,c): + self.table.item(r,c).setBackground(brush) def changeCell(self,r,c,value=None): "changes the contens of a cell" @@ -755,6 +843,46 @@ def Activated(self): FreeCAD.ActiveDocument.recompute() +class _Command_Spreadsheet_PropertyController: + "the Spreadsheet_Controller FreeCAD command" + def GetResources(self): + return {'Pixmap' : 'SpreadsheetPropertyController', + 'MenuText': QtCore.QT_TRANSLATE_NOOP("Spreadsheet_PropertyController","Add property controller"), + 'ToolTip': QtCore.QT_TRANSLATE_NOOP("Spreadsheet_PropertyController","Adds a property controller to a selected spreadsheet")} + + def IsActive(self): + if FreeCADGui.Selection.getSelection(): + return True + else: + return False + + def Activated(self): + import Draft + from DraftTools import translate + sel = FreeCADGui.Selection.getSelection() + if (len(sel) == 1) and Draft.getType(sel[0]) == "Spreadsheet": + n = FreeCADGui.Selection.getSelection()[0].Name + FreeCAD.ActiveDocument.openTransaction(str(translate("Spreadsheet","Add property controller"))) + FreeCADGui.doCommand("import Spreadsheet") + FreeCADGui.doCommand("Spreadsheet.makeSpreadsheetPropertyController(FreeCAD.ActiveDocument."+n+")") + FreeCAD.ActiveDocument.commitTransaction() + FreeCAD.ActiveDocument.recompute() + elif (len(sel) == 2): + if (Draft.getType(sel[0]) == "Spreadsheet") and (Draft.getType(sel[1]) == "SpreadsheetPropertyController"): + s = sel[0].Name + o = sel[1].Name + elif (Draft.getType(sel[1]) == "Spreadsheet") and (Draft.getType(sel[0]) == "SpreadsheetPropertyController"): + s = sel[1].Name + o = sel[0].Name + else: + return + FreeCAD.ActiveDocument.openTransaction(str(translate("Spreadsheet","Add property controller"))) + FreeCADGui.doCommand("import Spreadsheet") + FreeCADGui.doCommand("Spreadsheet.makeSpreadsheetPropertyController(FreeCAD.ActiveDocument."+s+",FreeCAD.ActiveDocument."+o+")") + FreeCAD.ActiveDocument.commitTransaction() + FreeCAD.ActiveDocument.recompute() + + def makeSpreadsheet(): "makeSpreadsheet(): adds a spreadsheet object to the active document" obj = FreeCAD.ActiveDocument.addObject("App::FeaturePython","Spreadsheet") @@ -782,6 +910,25 @@ def makeSpreadsheetController(spreadsheet,cell=None,direction=None): return obj +def makeSpreadsheetPropertyController(spreadsheet,object=None,prop=None,cell=None): + """makeSpreadsheetPropertyController(spreadsheet,[object,prop,cell]): adds a + property controller, targetting the given object if any, to the given spreadsheet. + You can give a property (such as "Length" or "Proxy.Length") and a cell address + (such as "B6").""" + obj = FreeCAD.ActiveDocument.addObject("App::FeaturePython","PropertyController") + SpreadsheetPropertyController(obj) + if FreeCAD.GuiUp: + ViewProviderSpreadsheetPropertyController(obj.ViewObject) + conts = spreadsheet.Controllers + conts.append(obj) + spreadsheet.Controllers = conts + if cell: + obj.Cell = cell + if prop: + obj.Property = prop + return obj + + def addSpreadsheetView(view): "addSpreadsheetView(view): adds the given spreadsheet view to the FreeCAD MDI area" if FreeCAD.GuiUp: @@ -873,3 +1020,4 @@ def export(exportList,filename): FreeCADGui.addCommand('Spreadsheet_Create',_Command_Spreadsheet_Create()) FreeCADGui.addCommand('Spreadsheet_Controller',_Command_Spreadsheet_Controller()) +FreeCADGui.addCommand('Spreadsheet_PropertyController',_Command_Spreadsheet_PropertyController()) diff --git a/src/Mod/Spreadsheet/Spreadsheet_rc.py b/src/Mod/Spreadsheet/Spreadsheet_rc.py index 2ca5227c9866..05df8fcca59a 100644 --- a/src/Mod/Spreadsheet/Spreadsheet_rc.py +++ b/src/Mod/Spreadsheet/Spreadsheet_rc.py @@ -2,16 +2,16 @@ # Resource object code # -# Created: Thu Jan 9 18:21:34 2014 +# Created: Sat Mar 29 14:56:48 2014 # by: The Resource Compiler for PySide (Qt v4.8.6) # # WARNING! All changes made in this file will be lost! from PySide import QtCore -qt_resource_data = "\x00\x00\x18S\x0a\x0a\x0a\x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a image/svg+xml\x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a\x0a\x00\x00\x14w\x0a\x0a\x0a\x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a image/svg+xml\x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a\x0a" -qt_resource_name = "\x00\x05\x00o\xa6S\x00i\x00c\x00o\x00n\x00s\x00\x19\x02\x18\xed\xa7\x00S\x00p\x00r\x00e\x00a\x00d\x00s\x00h\x00e\x00e\x00t\x00C\x00o\x00n\x00t\x00r\x00o\x00l\x00l\x00e\x00r\x00.\x00s\x00v\x00g\x00\x0f\x0a\xa9@\xe7\x00S\x00p\x00r\x00e\x00a\x00d\x00s\x00h\x00e\x00e\x00t\x00.\x00s\x00v\x00g" -qt_resource_struct = "\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x10\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00H\x00\x00\x00\x00\x00\x01\x00\x00\x18W" +qt_resource_data = "\x00\x00\x18S\x0a\x0a\x0a\x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a image/svg+xml\x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a\x0a\x00\x00\x1f\x01\x0a\x0a\x0a\x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a image/svg+xml\x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a\x0a\x00\x00\x14w\x0a\x0a\x0a\x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a image/svg+xml\x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a \x0a\x0a" +qt_resource_name = "\x00\x05\x00o\xa6S\x00i\x00c\x00o\x00n\x00s\x00\x19\x02\x18\xed\xa7\x00S\x00p\x00r\x00e\x00a\x00d\x00s\x00h\x00e\x00e\x00t\x00C\x00o\x00n\x00t\x00r\x00o\x00l\x00l\x00e\x00r\x00.\x00s\x00v\x00g\x00!\x08o\x93\xa7\x00S\x00p\x00r\x00e\x00a\x00d\x00s\x00h\x00e\x00e\x00t\x00P\x00r\x00o\x00p\x00e\x00r\x00t\x00y\x00C\x00o\x00n\x00t\x00r\x00o\x00l\x00l\x00e\x00r\x00.\x00s\x00v\x00g\x00\x0f\x0a\xa9@\xe7\x00S\x00p\x00r\x00e\x00a\x00d\x00s\x00h\x00e\x00e\x00t\x00.\x00s\x00v\x00g" +qt_resource_struct = "\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\x02\x00\x00\x00\x10\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00H\x00\x00\x00\x00\x00\x01\x00\x00\x18W\x00\x00\x00\x90\x00\x00\x00\x00\x00\x01\x00\x007\x5c" def qInitResources(): QtCore.qRegisterResourceData(0x01, qt_resource_struct, qt_resource_name, qt_resource_data)