From 3a5555f67a71e1354d8030ae225ccffb2745609b Mon Sep 17 00:00:00 2001 From: David Daish Date: Sun, 5 Apr 2020 17:59:26 +1200 Subject: [PATCH] Finished arch component docstrings --- src/Mod/Arch/ArchComponent.py | 293 ++++++++++++++++++++++++++++++++-- 1 file changed, 281 insertions(+), 12 deletions(-) diff --git a/src/Mod/Arch/ArchComponent.py b/src/Mod/Arch/ArchComponent.py index e0b41ddea4..8914ce7d59 100644 --- a/src/Mod/Arch/ArchComponent.py +++ b/src/Mod/Arch/ArchComponent.py @@ -22,6 +22,13 @@ __title__="FreeCAD Arch Component" __author__ = "Yorik van Havre" __url__ = "http://www.freecadweb.org" +__doc__ = """This module provides the base Arch component class, that is shared +by all of the Arch BIM objects. + +Examples +-------- +TODO put examples here. +""" import FreeCAD,Draft,ArchCommands,math,sys,json,os,ArchIFC,ArchIFCSchema from FreeCAD import Vector @@ -46,12 +53,22 @@ else: # is shared by all of the Arch BIM objects def addToComponent(compobject,addobject,mod=None): + """Adds an object to a component's properties. - '''addToComponent(compobject,addobject,mod): adds addobject - to the given component. Default is in "Additions", "Objects" or - "Components", the first one that exists in the component. Mod - can be set to one of those attributes ("Objects", Base", etc...) - to override the default.''' + Does not run if the addobject already exists in the component's properties. Adds + the object to the first property found of Base, Group, or Hosts. + + If mod is provided, adds the object to that property instead. + + Parameters + ---------- + compobject: + The component object to add the object to. + addobject: + The object to add to the component. + mod: str, optional + The property to add the object to. + """ import Draft if compobject == addobject: return @@ -96,11 +113,20 @@ def addToComponent(compobject,addobject,mod=None): def removeFromComponent(compobject,subobject): + """Removes the object from the given component. - '''removeFromComponent(compobject,subobject): subtracts subobject - from the given component. If the subobject is already part of the - component (as addition, subtraction, etc... it is removed. Otherwise, - it is added as a subtraction.''' + Tries to find the object in the component's properties. If it finds it, + removes the object. + + If the object is not found, adds the object in the component's Subtractions property. + + Parameters + ---------- + compobject: + The component to remove the object from. + subobject: + The object to remove from the component. + """ if compobject == subobject: return found = False @@ -1446,6 +1472,10 @@ class ArchSelectionObserver: When a watched object is specified, the observer will only fire when this watched object is selected. + + TODO: This could probably use a rework. Most of the functionality isn't + used. It does not work correctly to reset the appearance of parent object + in ComponentTaskPanel.editObject(), for example. """ def __init__(self,origin=None,watched=None,hide=True,nextCommand=None): @@ -1526,14 +1556,23 @@ class SelectionTaskPanel: """ def __init__(self): - """Initialises""" + """Initialises the task panel. + + Adds a label. + + TODO: Label does not seem to appear? + """ + self.baseform = QtGui.QLabel() self.baseform.setText(QtGui.QApplication.translate("Arch", "Please select a base object", None)) def getStandardButtons(self): + """Adds the cancel button.""" return int(QtGui.QDialogButtonBox.Cancel) def reject(self): + """The method run when the user selects the cancel button.""" + if hasattr(FreeCAD,"ArchObserver"): FreeCADGui.Selection.removeObserver(FreeCAD.ArchObserver) del FreeCAD.ArchObserver @@ -1541,10 +1580,18 @@ class SelectionTaskPanel: class ComponentTaskPanel: + """The default TaskPanel for all Arch components. - '''The default TaskPanel for all Arch components''' + TODO: outline the purpose of this taskpanel. + + """ def __init__(self): + """Initialises the task panel. + + Defines the layout of the task panel, and setups callbacks for when + buttons and menu items are clicked. + """ # the panel has a tree widget that contains categories # for the subcomponents, such as additions, subtractions. @@ -1605,18 +1652,54 @@ class ComponentTaskPanel: self.update() def isAllowedAlterSelection(self): + """This method indicates whether this task dialog allows other commands to + modify the selection while it is open. + + Returns + ------- + bool + If alteration of the selection should be allowed. + """ return True def isAllowedAlterView(self): + """This method indicates whether this task dialog allows other commands + to modify the 3D view while it is open. + + Returns + ------- + bool + If alteration of the 3D view should be allowed. + """ return True def getStandardButtons(self): + """Adds the standard ok button.""" return int(QtGui.QDialogButtonBox.Ok) def check(self,wid,col): + """This method is run as the callback when the user selects an item in the tree. + + This method enables and disables the add and remove buttons depending on what + the user has selected. + + If they have selected one of the root attribute folders, it disables + the remove button. If they have seperately selected an object in the 3D + view, the add button is enabled, allowing the user to add that object + to the root attribute folder. + + If they have selected one of the items inside a root attribute folder, + it enables the remove button, allowing the user to remove the object + from that attribute. + + Parameters + ---------- + wid: + Qt object the user has selected in the tree widget. + """ if not wid.parent(): self.delButton.setEnabled(False) @@ -1630,6 +1713,8 @@ class ComponentTaskPanel: self.addButton.setEnabled(False) def getIcon(self,obj): + """Gets the path to the icons, of the items that fill the tree widget. + """ if hasattr(obj.ViewObject,"Proxy"): if hasattr(obj.ViewObject.Proxy,"getIcon"): @@ -1641,8 +1726,17 @@ class ComponentTaskPanel: return QtGui.QIcon(":/icons/Tree_Part.svg") def update(self): + """Populates the treewidget with it's various items. + + Checks if the object being edited has attributes relevant to + subobjects. IE: Additions, Subtractions, etc. + + Populates the tree with these subobjects, under folders named after the + attributes they are listed in. + + Finally, runs method .retranslateUi(). + """ - 'fills the treewidget' self.tree.clear() dirIcon = QtGui.QApplication.style().standardIcon(QtGui.QStyle.SP_DirIcon) for a in self.attribs: @@ -1676,6 +1770,14 @@ class ComponentTaskPanel: self.retranslateUi(self.baseform) def addElement(self): + """This method is run as a callback when the user selects the add button. + + Gets the object selected in the 3D view, and gets the attribute folder + selected in the tree widget. + + Adds the object selected in the 3D view to the attribute associated + with the selected folder, by using function addToComponent(). + """ it = self.tree.currentItem() if it: @@ -1688,6 +1790,13 @@ class ComponentTaskPanel: self.update() def removeElement(self): + """This method is run as a callback when the user selects the remove button. + + Gets the object selected in the tree widget. If there is an object in + the document with the same Name as the selected item in the tree, it is + removed from the object being edited, with the removeFromComponent() + function. + """ it = self.tree.currentItem() if it: @@ -1696,12 +1805,29 @@ class ComponentTaskPanel: self.update() def accept(self): + """This method runs as a callback when the user selects the ok button. + + It recomputes the document, and leaves edit mode. + """ FreeCAD.ActiveDocument.recompute() FreeCADGui.ActiveDocument.resetEdit() return True def editObject(self,wid,col): + """This method is run when the user double clicks on an item in the tree widget. + + If the item in the tree has a corresponding object in the document, + it enters edit mode for that associated object. + + At the same time, it makes the object this task panel was opened for + transparent and unselectable. + + Parameters + ---------- + wid: + Qt object the user has selected in the tree widget. + """ if wid.parent(): obj = FreeCAD.ActiveDocument.getObject(str(wid.toolTip(0))) @@ -1717,6 +1843,8 @@ class ComponentTaskPanel: FreeCADGui.ActiveDocument.setEdit(obj.Name,0) def retranslateUi(self, TaskPanel): + """Adds the text of the task panel, in translated form. + """ self.baseform.setWindowTitle(QtGui.QApplication.translate("Arch", "Component", None)) self.delButton.setText(QtGui.QApplication.translate("Arch", "Remove", None)) @@ -1735,6 +1863,14 @@ class ComponentTaskPanel: self.classButton.setText(QtGui.QApplication.translate("Arch", "Edit standard code", None)) def editIfcProperties(self): + """Opens the IFC editor dialog box. + + This is the method that runs as a callback when the Edit IFC properties + button is selected by the user. + + It defines the editor's structure, fills it with data, adds callback + for the buttons and other interactions, and shows it. + """ if hasattr(self,"ifcEditor"): if self.ifcEditor: @@ -1761,6 +1897,7 @@ class ComponentTaskPanel: self.psetkeys = [''.join(map(lambda x: x if x.islower() else " "+x, t[5:]))[1:] for t in self.psetdefs.keys()] self.psetkeys.sort() self.ifcEditor = FreeCADGui.PySideUic.loadUi(":/ui/DialogIfcProperties.ui") + # center the dialog over FreeCAD window mw = FreeCADGui.getMainWindow() self.ifcEditor.move(mw.frameGeometry().topLeft() + mw.rect().center() - self.ifcEditor.rect().center()) @@ -1772,13 +1909,16 @@ class ComponentTaskPanel: self.ifcModel.setHorizontalHeaderLabels([QtGui.QApplication.translate("Arch", "Property", None), QtGui.QApplication.translate("Arch", "Type", None), QtGui.QApplication.translate("Arch", "Value", None)]) + # set combos self.ifcEditor.comboProperty.addItems([QtGui.QApplication.translate("Arch", "Add property...", None)]+self.plabels) self.ifcEditor.comboPset.addItems([QtGui.QApplication.translate("Arch", "Add property set...", None), QtGui.QApplication.translate("Arch", "New...", None)]+self.psetkeys) + # set UUID if "IfcUID" in self.obj.IfcData: self.ifcEditor.labelUUID.setText(self.obj.IfcData["IfcUID"]) + # fill the tree psets = {} for pname,value in self.obj.IfcProperties.items(): @@ -1812,17 +1952,21 @@ class ComponentTaskPanel: it3.setDropEnabled(False) top.appendRow([it1,it2,it3]) top.sortChildren(0) + # span top levels idx = self.ifcModel.invisibleRootItem().index() for i in range(self.ifcModel.rowCount()): if self.ifcModel.item(i,0).hasChildren(): self.ifcEditor.treeProperties.setFirstColumnSpanned(i, idx, True) self.ifcEditor.treeProperties.expandAll() + + # Add callbacks QtCore.QObject.connect(self.ifcEditor.buttonBox, QtCore.SIGNAL("accepted()"), self.acceptIfcProperties) QtCore.QObject.connect(self.ifcEditor.comboProperty, QtCore.SIGNAL("currentIndexChanged(int)"), self.addIfcProperty) QtCore.QObject.connect(self.ifcEditor.comboPset, QtCore.SIGNAL("currentIndexChanged(int)"), self.addIfcPset) QtCore.QObject.connect(self.ifcEditor.buttonDelete, QtCore.SIGNAL("clicked()"), self.removeIfcProperty) self.ifcEditor.treeProperties.setSortingEnabled(True) + # set checkboxes if "FlagForceBrep" in self.obj.IfcData: self.ifcEditor.checkBrep.setChecked(self.obj.IfcData["FlagForceBrep"] == "True") @@ -1831,6 +1975,13 @@ class ComponentTaskPanel: self.ifcEditor.show() def acceptIfcProperties(self): + """This method runs as a callback when the user selects the ok button in the IFC editor. + + This method scrapes through the rows of the IFC editor's items, and + compares them to the object being edited's .IfcData. If the two are + different, it changes the object's .IfcData to match the editor's + items. + """ if hasattr(self,"ifcEditor") and self.ifcEditor: self.ifcEditor.hide() @@ -1863,6 +2014,36 @@ class ComponentTaskPanel: del self.ifcEditor def addIfcProperty(self,idx=0,pset=None,prop=None,ptype=None): + """Adds an IFC property to the object, within the IFC editor. + + This method runs as a callback when the user selects an option in the + Add Property dropdown box in the IFC editor. When used via the + dropdown, it adds a property with the property type selected in the + dropdown. + + This method can also be run standalone, outside it's function as a + callback. + + Unless otherwise specified, the property will be called "New property". + The property will have no value assigned. + + Parameters + ---------- + idx: int, optional + The index number of the property type selected in the dropdown. If + idx is not specified, the property's type must be specified in the + ptype parameter. + pset: str, optional + The name of the property set this property will be assigned to. If + not provided, the pset will be determined by which property set has + been selected within the IFC editor widget. + prop: str, optional + The name of the property to be created. If left blank, will be set to + "New Property". + ptype: str, optional + The name of the property type the new property will be set as. If not + specified, the the property's type will be determined using the idx parameter. + """ if hasattr(self,"ifcEditor") and self.ifcEditor: if not pset: @@ -1891,6 +2072,21 @@ class ComponentTaskPanel: self.ifcEditor.comboProperty.setCurrentIndex(0) def addIfcPset(self,idx=0): + """Adds a IFC property set to the object, within the IFC editor. + + This method runs as a callback when the user selects a property set + within the Add property set dropdown. + + Adds the property set selected in the dropdown, then checks the + property set definitions for the property set's standard properties, + and adds them with blank values to the new property set. + + Parameters + ---------- + idx: int + The index of the options selected from the Add property set + dropdown. + """ if hasattr(self,"ifcEditor") and self.ifcEditor: if idx == 1: @@ -1918,6 +2114,14 @@ class ComponentTaskPanel: self.ifcEditor.comboPset.setCurrentIndex(0) def removeIfcProperty(self): + """Removes an IFC property or property set from the object, within the IFC editor. + + This method runs as a callback when the user selects the Delete + selected property/set button within the IFC editor. + + It finds the selected property, and deletes it. If it's a property set, + it deletes the children properties as well. + """ if hasattr(self,"ifcEditor") and self.ifcEditor: sel = self.ifcEditor.treeProperties.selectedIndexes() @@ -1929,6 +2133,11 @@ class ComponentTaskPanel: pset.takeRow(sel[0].row()) def editClass(self): + """Simple wrapper for BIM_Classification Gui command. + + This method is called when the Edit class button is selected + in the IFC editor. It relies on the presence of the BIM module. + """ FreeCADGui.Selection.clearSelection() FreeCADGui.Selection.addSelection(self.obj) @@ -1937,9 +2146,24 @@ class ComponentTaskPanel: if FreeCAD.GuiUp: class IfcEditorDelegate(QtGui.QStyledItemDelegate): + """This class manages the editing of the individual table cells in the IFC editor. + """ def __init__(self, parent=None, dialog=None, ptypes=[], plabels=[], *args): + """This method initalises the class. + + Parameters + ---------- + parent: + Unclear. + dialog: + The dialog box this delegate was created in. + ptypes: list of str + A list of the names of IFC property types. + plables: list of str + A list of the human readable names of IFC property types. + """ self.dialog = dialog QtGui.QStyledItemDelegate.__init__(self, parent, *args) @@ -1947,6 +2171,27 @@ if FreeCAD.GuiUp: self.plabels = plabels def createEditor(self,parent,option,index): + """Returns the widget used to change data. + + Returns a text line editor if editing the property name. Returns a + dropdown to change property type if editing property type. If + editing the property's value, returns an appropriate widget + depending on the datatype of the value. + + Parameters + ---------- + parent: + The table cell that is being edited. + option: + Unused? + index: + The index object of the table of the IFC editor. + + Returns + ------- + + The editor widget this method has created. + """ if index.column() == 0: # property name editor = QtGui.QLineEdit(parent) @@ -1971,6 +2216,19 @@ if FreeCAD.GuiUp: return editor def setEditorData(self, editor, index): + """Gives data to the edit widget. + + This method extracts the data already present in the table, and + writes it to the editor. This means the user starts the editor with + their previous data already present, instead of a blank slate. + + Parameters + ---------- + editor: + The editor widget. + index: + The index object of the table, of the IFC editor + """ if index.column() == 0: editor.setText(index.data()) @@ -2004,6 +2262,17 @@ if FreeCAD.GuiUp: editor.setText(index.data()) def setModelData(self, editor, model, index): + """Writes the data in the editor to the IFC editor's table. + + Parameters + ---------- + editor: + The editor widget. + model: + The table object of the IFC editor. + index: + The index object of the table, of the IFC editor + """ if index.column() == 0: model.setData(index,editor.text())