diff --git a/src/Mod/Arch/ArchCommands.py b/src/Mod/Arch/ArchCommands.py
index 858010f9b0..9917e375a1 100644
--- a/src/Mod/Arch/ArchCommands.py
+++ b/src/Mod/Arch/ArchCommands.py
@@ -765,7 +765,7 @@ def pruneIncluded(objectslist,strict=False):
if toplevel:
newlist.append(obj)
else:
- FreeCAD.Console.PrintLog("pruning "+obj.Label+"n")
+ FreeCAD.Console.PrintLog("pruning "+obj.Label+"\n")
return newlist
def getAllChildren(objectlist):
diff --git a/src/Mod/Arch/ArchSchedule.py b/src/Mod/Arch/ArchSchedule.py
index 298b849ed7..7afc975657 100644
--- a/src/Mod/Arch/ArchSchedule.py
+++ b/src/Mod/Arch/ArchSchedule.py
@@ -36,7 +36,7 @@ else:
def QT_TRANSLATE_NOOP(ctxt,txt):
return txt
# \endcond
-
+
## @package ArchSchedule
# \ingroup ARCH
# \brief The Schedule object and tools
@@ -53,7 +53,8 @@ __url__ = "http://www.freecadweb.org"
verbose = True # change this for silent recomputes
-class _CommandArchSchedule:
+
+class CommandArchSchedule:
"the Arch Schedule command definition"
@@ -63,7 +64,7 @@ class _CommandArchSchedule:
'ToolTip': QT_TRANSLATE_NOOP("Arch_Schedule","Creates a schedule to collect data from the model")}
def Activated(self):
- taskd = _ArchScheduleTaskPanel()
+ taskd = ArchScheduleTaskPanel()
FreeCADGui.Control.showDialog(taskd)
def IsActive(self):
@@ -73,53 +74,114 @@ class _CommandArchSchedule:
return False
+
class _ArchSchedule:
"the Arch Schedule object"
def __init__(self,obj):
- obj.addProperty("App::PropertyStringList","Description","Arch",QT_TRANSLATE_NOOP("App::Property","The description column"))
- obj.addProperty("App::PropertyStringList","Value", "Arch",QT_TRANSLATE_NOOP("App::Property","The values column"))
- obj.addProperty("App::PropertyStringList","Unit", "Arch",QT_TRANSLATE_NOOP("App::Property","The units column"))
- obj.addProperty("App::PropertyStringList","Objects", "Arch",QT_TRANSLATE_NOOP("App::Property","The objects column"))
- obj.addProperty("App::PropertyStringList","Filter", "Arch",QT_TRANSLATE_NOOP("App::Property","The filter column"))
- obj.addProperty("App::PropertyLink", "Result", "Arch",QT_TRANSLATE_NOOP("App::Property","The spreadsheet to print the results to"))
+
+ self.setProperties(obj)
obj.Proxy = self
self.Type = "Schedule"
+ def onDocumentRestored(self,obj):
+
+ self.setProperties(obj)
+
+ def setProperties(self,obj):
+
+ if not "Description" in obj.PropertiesList:
+ obj.addProperty("App::PropertyStringList","Description", "Arch",QT_TRANSLATE_NOOP("App::Property","The description column"))
+ if not "Value" in obj.PropertiesList:
+ obj.addProperty("App::PropertyStringList","Value", "Arch",QT_TRANSLATE_NOOP("App::Property","The values column"))
+ if not "Unit" in obj.PropertiesList:
+ obj.addProperty("App::PropertyStringList","Unit", "Arch",QT_TRANSLATE_NOOP("App::Property","The units column"))
+ if not "Objects" in obj.PropertiesList:
+ obj.addProperty("App::PropertyStringList","Objects", "Arch",QT_TRANSLATE_NOOP("App::Property","The objects column"))
+ if not "Filter" in obj.PropertiesList:
+ obj.addProperty("App::PropertyStringList","Filter", "Arch",QT_TRANSLATE_NOOP("App::Property","The filter column"))
+ if not "CreateSpreadsheet" in obj.PropertiesList:
+ obj.addProperty("App::PropertyBool", "CreateSpreadsheet", "Arch",QT_TRANSLATE_NOOP("App::Property","If True, a spreadsheet containing the results is recreated when needed"))
+ if not "Result" in obj.PropertiesList:
+ obj.addProperty("App::PropertyLink", "Result", "Arch",QT_TRANSLATE_NOOP("App::Property","The spreadsheet to print the results to"))
+ if not "DetailedResults" in obj.PropertiesList:
+ obj.addProperty("App::PropertyBool", "DetailedResults", "Arch",QT_TRANSLATE_NOOP("App::Property","If True, additional lines with each individual object are added to the results"))
+
+ def onChanged(self,obj,prop):
+
+ if (prop == "CreateSpreadsheet"):
+ if hasattr(obj,"CreateSpreadsheet") and obj.CreateSpreadsheet:
+ if not obj.Result:
+ import Spreadsheet
+ sp = FreeCAD.ActiveDocument.addObject("Spreadsheet::Sheet","Result")
+ obj.Result = sp
+
+ def setSpreadsheetData(self,obj):
+
+ """Fills a spreadsheet with the stored data"""
+
+ if not hasattr(self,"data"):
+ return
+ if not self.data:
+ return
+ if not obj.Result:
+ if obj.CreateSpreadsheet:
+ import Spreadsheet
+ sp = FreeCAD.ActiveDocument.addObject("Spreadsheet::Sheet","Result")
+ obj.Result = sp
+ else:
+ return
+ # clear spreadsheet
+ obj.Result.clearAll()
+ # set headers
+ obj.Result.set("A1","Description")
+ obj.Result.set("B1","Value")
+ obj.Result.set("C1","Unit")
+ obj.Result.setStyle('A1:C1', 'bold', 'add')
+ # write contents
+ for k,v in self.data.items():
+ obj.Result.set(k,v)
+ # recompute
+ obj.Result.recompute()
+
def execute(self,obj):
- # fills columns A, B and C of the spreadsheet
+
+ # verify the data
+
if not obj.Description:
+ # empty description column
return
for p in [obj.Value,obj.Unit,obj.Objects,obj.Filter]:
+ # different number of items in each column
if len(obj.Description) != len(p):
return
if not hasattr(obj,"Result"):
# silently fail on old schedule objects
return
- if not obj.Result:
- FreeCAD.Console.PrintError(translate("Arch","No spreadsheet attached to this schedule")+"\n")
- return
- obj.Result.clearAll()
- obj.Result.set("A1","Description")
- obj.Result.set("B1","Value")
- obj.Result.set("C1","Unit")
- obj.Result.setStyle('A1:C1', 'bold', 'add')
+
+ self.data = {} # store all results in self.data, so it lives even without spreadsheet
+ li = 1 # row index - starts at 2 to leave 2 blank rows for the title
+
for i in range(len(obj.Description)):
+ li += 1
if not obj.Description[i]:
# blank line
continue
# write description
if sys.version_info.major >= 3:
# use unicode for python3
- obj.Result.set("A"+str(i+2), obj.Description[i])
+ self.data["A"+str(li)] = obj.Description[i]
else:
- obj.Result.set("A"+str(i+2), obj.Description[i].encode("utf8"))
+ self.data["A"+str(li)] = obj.Description[i].encode("utf8")
if verbose:
l= "OPERATION: "+obj.Description[i]
+ print("")
print (l)
print (len(l)*"=")
- # get list of objects
+
+ # build set of valid objects
+
objs = obj.Objects[i]
val = obj.Value[i]
if val:
@@ -134,7 +196,7 @@ class _ArchSchedule:
# remove object itself if the object is a group
if objs[0].isDerivedFrom("App::DocumentObjectGroup"):
objs = objs[0].Group
- objs = Draft.getGroupContents(objs,walls=True,addgroups=True)
+ objs = Draft.getGroupContents(objs)
objs = Arch.pruneIncluded(objs,strict=True)
# remove the schedule object and its result from the list
objs = [o for o in objs if not o == obj]
@@ -159,59 +221,48 @@ class _ArchSchedule:
if args[1].upper() in o.Label.upper():
ok = False
elif args[0].upper() == "TYPE":
- if Draft.getType(o).upper() != args[1].upper():
- ok = False
- elif args[0].upper() == "!TYPE":
- if Draft.getType(o).upper() == args[1].upper():
- ok = False
- elif args[0].upper() == "IFCTYPE":
if hasattr(o,"IfcType"):
if o.IfcType.upper() != args[1].upper():
ok = False
else:
ok = False
- elif args[0].upper() == "!IFCTYPE":
+ elif args[0].upper() == "!TYPE":
if hasattr(o,"IfcType"):
if o.IfcType.upper() == args[1].upper():
ok = False
if ok:
nobjs.append(o)
objs = nobjs
- # perform operation
+
+ # perform operation: count or retrieve property
+
if val.upper() == "COUNT":
val = len(objs)
if verbose:
print (val, ",".join([o.Label for o in objs]))
- obj.Result.set("B"+str(i+2),str(val))
+ self.data["B"+str(li)] = str(val)
+ if obj.DetailedResults:
+ # additional blank line...
+ li += 1
+ self.data["A"+str(li)] = " "
else:
vals = val.split(".")
+ if vals[0][0].islower():
+ # old-style: first member is not a property
+ vals = vals[1:]
sumval = 0
- for o in objs:
- if verbose:
- l = o.Name+" ("+o.Label+"):"
- print (l+(40-len(l))*" ",)
- try:
- d = o
- for v in vals[1:]:
- d = getattr(d,v)
- if verbose:
- print (d)
- if hasattr(d,"Value"):
- d = d.Value
- except:
- FreeCAD.Console.PrintWarning(translate("Arch","Unable to retrieve value from object")+": "+o.Name+"."+".".join(vals)+"\n")
- else:
- if not sumval:
- sumval = d
- else:
- sumval += d
- val = sumval
+
# get unit
+ tp = None
+ unit = None
+ q = None
if obj.Unit[i]:
- ustr = obj.Unit[i]
+ unit = obj.Unit[i]
if sys.version_info.major < 3:
- ustr = ustr.encode("utf8")
- unit = ustr.replace("²","^2")
+ unit = unit.encode("utf8")
+ unit = unit.replace("2","^2")
+ unit = unit.replace("3","^3")
+ unit = unit.replace("²","^2")
unit = unit.replace("³","^3")
if "2" in unit:
tp = FreeCAD.Units.Area
@@ -221,19 +272,74 @@ class _ArchSchedule:
tp = FreeCAD.Units.Angle
else:
tp = FreeCAD.Units.Length
+
+ # format value
+ dv = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Units").GetInt("Decimals",2)
+ fs = "{:."+str(dv)+"f}" # format string
+ for o in objs:
+ if verbose:
+ l = o.Name+" ("+o.Label+"):"
+ print (l+(40-len(l))*" ",end="")
+ try:
+ d = o
+ for v in vals:
+ d = getattr(d,v)
+ if hasattr(d,"Value"):
+ d = d.Value
+ if verbose:
+ if tp and unit:
+ v = fs.format(FreeCAD.Units.Quantity(d,tp).getValueAs(unit).Value)
+ print(v,unit)
+ else:
+ print(fs.format(d))
+ if obj.DetailedResults:
+ li += 1
+ self.data["A"+str(li)] = o.Name+" ("+o.Label+")"
+ if tp and unit:
+ q = FreeCAD.Units.Quantity(d,tp)
+ self.data["B"+str(li)] = str(q.getValueAs(unit).Value)
+ self.data["C"+str(li)] = unit
+ else:
+ self.data["B"+str(li)] = str(d)
+ except:
+ FreeCAD.Console.PrintWarning(translate("Arch","Unable to retrieve value from object")+": "+o.Name+"."+".".join(vals)+"\n")
+ else:
+ if not sumval:
+ sumval = d
+ else:
+ sumval += d
+ val = sumval
+ if tp:
q = FreeCAD.Units.Quantity(val,tp)
- obj.Result.set("B"+str(i+2),str(q.getValueAs(unit).Value))
- obj.Result.set("C"+str(i+2),ustr)
+
+ # write data
+ if obj.DetailedResults:
+ li += 1
+ self.data["A"+str(li)] = "TOTAL"
+ if q and unit:
+ self.data["B"+str(li)] = str(q.getValueAs(unit).Value)
+ self.data["C"+str(li)] = unit
else:
- obj.Result.set("B"+str(i+2),str(val))
+ self.data["B"+str(li)] = str(val)
+ if obj.DetailedResults:
+ # additional blank line...
+ li += 1
+ self.data["A"+str(li)] = " "
if verbose:
- print ("TOTAL:"+34*" "+str(val))
- obj.Result.recompute()
+ if tp and unit:
+ v = fs.format(FreeCAD.Units.Quantity(val,tp).getValueAs(unit).Value)
+ print("TOTAL:"+34*" "+v+" "+unit)
+ else:
+ v = fs.format(val)
+ print("TOTAL:"+34*" "+v)
+ self.setSpreadsheetData(obj)
def __getstate__(self):
+
return self.Type
def __setstate__(self,state):
+
if state:
self.Type = state
@@ -249,16 +355,19 @@ class _ViewProviderArchSchedule:
import Arch_rc
return ":/icons/Arch_Schedule.svg"
+ def isShow(self):
+ return True
+
def attach(self, vobj):
self.Object = vobj.Object
def setEdit(self,vobj,mode):
- taskd = _ArchScheduleTaskPanel(vobj.Object)
+ taskd = ArchScheduleTaskPanel(vobj.Object)
FreeCADGui.Control.showDialog(taskd)
return True
def doubleClicked(self,vobj):
- taskd = _ArchScheduleTaskPanel(vobj.Object)
+ taskd = ArchScheduleTaskPanel(vobj.Object)
FreeCADGui.Control.showDialog(taskd)
return True
@@ -286,19 +395,43 @@ class _ViewProviderArchSchedule:
return mode
-class _ArchScheduleTaskPanel:
+class ArchScheduleTaskPanel:
'''The editmode TaskPanel for Schedules'''
def __init__(self,obj=None):
+
+ """Sets the panel up"""
+
self.obj = obj
self.form = FreeCADGui.PySideUic.loadUi(":/ui/ArchSchedule.ui")
self.form.setWindowIcon(QtGui.QIcon(":/icons/Arch_Schedule.svg"))
+
+ # set icons
+ self.form.buttonAdd.setIcon(QtGui.QIcon(":/icons/list-add.svg"))
+ self.form.buttonDel.setIcon(QtGui.QIcon(":/icons/list-remove.svg"))
+ self.form.buttonClear.setIcon(QtGui.QIcon(":/icons/delete.svg"))
+ self.form.buttonImport.setIcon(QtGui.QIcon(":/icons/document-open.svg"))
+ self.form.buttonExport.setIcon(QtGui.QIcon(":/icons/document-save.svg"))
+ self.form.buttonSelect.setIcon(QtGui.QIcon(":/icons/edit-select-all.svg"))
+
+ # restore widths
+ p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch")
+ self.form.list.setColumnWidth(0,p.GetInt("ScheduleColumnWidth0",100))
+ self.form.list.setColumnWidth(1,p.GetInt("ScheduleColumnWidth1",100))
+ self.form.list.setColumnWidth(2,p.GetInt("ScheduleColumnWidth2",50))
+ self.form.list.setColumnWidth(3,p.GetInt("ScheduleColumnWidth3",100))
+
+ # set delegate - Not using custom delegates for now...
+ #self.form.list.setItemDelegate(ScheduleDelegate())
+ #self.form.list.setEditTriggers(QtGui.QAbstractItemView.DoubleClicked)
+
+ # connect slots
QtCore.QObject.connect(self.form.buttonAdd, QtCore.SIGNAL("clicked()"), self.add)
QtCore.QObject.connect(self.form.buttonDel, QtCore.SIGNAL("clicked()"), self.remove)
QtCore.QObject.connect(self.form.buttonClear, QtCore.SIGNAL("clicked()"), self.clear)
QtCore.QObject.connect(self.form.buttonImport, QtCore.SIGNAL("clicked()"), self.importCSV)
- QtCore.QObject.connect(self.form.buttonExport, QtCore.SIGNAL("clicked()"), self.exportCSV)
+ QtCore.QObject.connect(self.form.buttonExport, QtCore.SIGNAL("clicked()"), self.export)
QtCore.QObject.connect(self.form.buttonSelect, QtCore.SIGNAL("clicked()"), self.select)
self.form.list.clearContents()
@@ -313,56 +446,146 @@ class _ArchScheduleTaskPanel:
for j in range(len(obj.Description)):
item = QtGui.QTableWidgetItem([obj.Description,obj.Value,obj.Unit,obj.Objects,obj.Filter][i][j])
self.form.list.setItem(j,i,item)
+ self.form.lineEditName.setText(self.obj.Label)
+ self.form.checkDetailed.setChecked(self.obj.DetailedResults)
+ self.form.checkSpreadsheet.setChecked(self.obj.CreateSpreadsheet)
def add(self):
+
+ """Adds a new row below the last one"""
+
self.form.list.insertRow(self.form.list.currentRow()+1)
def remove(self):
+
+ """Removes the current row"""
+
if self.form.list.currentRow() >= 0:
self.form.list.removeRow(self.form.list.currentRow())
def clear(self):
+
+ """Clears the list"""
+
self.form.list.clearContents()
self.form.list.setRowCount(0)
def importCSV(self):
+
+ """Imports a CSV file"""
+
filename = QtGui.QFileDialog.getOpenFileName(QtGui.QApplication.activeWindow(), translate("Arch","Import CSV File"), None, "CSV file (*.csv)");
if filename:
+ filename = filename[0]
+ if sys.version_info.major < 3:
+ filename = filename.encode("utf8")
self.form.list.clearContents()
import csv
- with open(filename[0], 'rb') as csvfile:
+ with open(filename,'r') as csvfile:
r = 0
for row in csv.reader(csvfile):
self.form.list.insertRow(r)
for i in range(5):
if len(row) > i:
t = row[i]
- t = t.replace("²","^2")
- t = t.replace("³","^3")
+ #t = t.replace("²","^2")
+ #t = t.replace("³","^3")
self.form.list.setItem(r,i,QtGui.QTableWidgetItem(t))
r += 1
- def exportCSV(self):
- if self.obj:
- if self.obj.Result:
- filename = QtGui.QFileDialog.getSaveFileName(QtGui.QApplication.activeWindow(), translate("Arch","Export CSV File"), None, "CSV file (*.csv)");
- if filename:
- # the following line crashes, couldn't fnid out why
- # self.obj.Result.exportFile(str(filename[0].encode("utf8")))
- import csv
- if not("Up-to-date" in self.obj.State):
- self.obj.Proxy.execute(self.obj)
- numrows = len(self.obj.Description)+1
- with open(filename[0].encode("utf8"), 'wb') as csvfile:
- csvfile = csv.writer(csvfile,delimiter="\t")
- for i in range(numrows):
- r = []
- for j in ["A","B","C"]:
- r.append(self.obj.Result.getContents(j+str(i+1)))
- csvfile.writerow(r)
- print("successfully exported ",filename[0])
+ def export(self):
+
+ """Exports the results as MD or CSV"""
+
+ # commit latest changes
+ self.writeValues()
+
+ # tests
+ if not("Up-to-date" in self.obj.State):
+ self.obj.Proxy.execute(self.obj)
+ if not hasattr(self.obj.Proxy,"data"):
+ return
+ if not self.obj.Proxy.data:
+ return
+
+ filename = QtGui.QFileDialog.getSaveFileName(QtGui.QApplication.activeWindow(), translate("Arch","Export CSV File"), None, "CSV (*.csv);;Markdown (*.md)");
+ if filename:
+ filt = filename[1]
+ filename = filename[0]
+ if sys.version_info.major < 3:
+ filename = filename.encode("utf8")
+ # add missing extension
+ if (not filename.lower().endswith(".csv")) and (not filename.lower().endswith(".md")):
+ if "csv" in filt:
+ filename += ".csv"
+ else:
+ filename += ".md"
+ if filename.lower().endswith(".csv"):
+ self.exportCSV(filename)
+ elif filename.lower().endswith(".md"):
+ self.exportMD(filename)
+ else:
+ FreeCAD.Console.PrintError(translate("Arch","Unable to recognize that file type")+":"+filename+"\n")
+
+ def getRows(self):
+
+ """get the rows that contain data"""
+
+ rows = []
+ if hasattr(self.obj.Proxy,"data") and self.obj.Proxy.data:
+ for key in self.obj.Proxy.data.keys():
+ n = key[1:]
+ if not n in rows:
+ rows.append(n)
+ rows.sort(key=int)
+ return rows
+
+ def exportCSV(self,filename):
+
+ """Exports the results as a CSV file"""
+
+ # use TAB to separate values
+ DELIMITER = "\t"
+
+ import csv
+ with open(filename, 'w') as csvfile:
+ csvfile = csv.writer(csvfile,delimiter=DELIMITER)
+ csvfile.writerow([translate("Arch","Description"),translate("Arch","Value"),translate("Arch","Unit")])
+ if self.obj.DetailedResults:
+ csvfile.writerow(["","",""])
+ for i in self.getRows():
+ r = []
+ for j in ["A","B","C"]:
+ if j+i in self.obj.Proxy.data:
+ r.append(str(self.obj.Proxy.data[j+i]))
+ else:
+ r.append("")
+ csvfile.writerow(r)
+ print("successfully exported ",filename)
+
+ def exportMD(self,filename):
+
+ """Exports the results as a Markdown file"""
+
+ with open(filename, 'w') as mdfile:
+ mdfile.write("| "+translate("Arch","Description")+" | "+translate("Arch","Value")+" | "+translate("Arch","Unit")+" |\n")
+ mdfile.write("| --- | --- | --- |\n")
+ if self.obj.DetailedResults:
+ mdfile.write("| | | |\n")
+ for i in self.getRows():
+ r = []
+ for j in ["A","B","C"]:
+ if j+i in self.obj.Proxy.data:
+ r.append(str(self.obj.Proxy.data[j+i]))
+ else:
+ r.append("")
+ mdfile.write("| "+" | ".join(r)+" |\n")
+ print("successfully exported ",filename)
def select(self):
+
+ """Adds selected objects to current row"""
+
if self.form.list.currentRow() >= 0:
sel = ""
for o in FreeCADGui.Selection.getSelection():
@@ -374,15 +597,34 @@ class _ArchScheduleTaskPanel:
self.form.list.setItem(self.form.list.currentRow(),3,QtGui.QTableWidgetItem(sel))
def accept(self):
+
+ """executes when OK button has been pressed"""
+
+ # store widths
+ p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch")
+ p.SetInt("ScheduleColumnWidth0",self.form.list.columnWidth(0))
+ p.SetInt("ScheduleColumnWidth1",self.form.list.columnWidth(1))
+ p.SetInt("ScheduleColumnWidth2",self.form.list.columnWidth(2))
+ p.SetInt("ScheduleColumnWidth3",self.form.list.columnWidth(3))
+
+ # commit values
+ self.writeValues()
+ return True
+
+ def writeValues(self):
+
+ """commits values and recalculate"""
+
if not self.obj:
- import Spreadsheet
self.obj = FreeCAD.ActiveDocument.addObject("App::FeaturePython","Schedule")
self.obj.Label = translate("Arch","Schedule")
_ArchSchedule(self.obj)
- sp = FreeCAD.ActiveDocument.addObject("Spreadsheet::Sheet","Result")
- self.obj.Result = sp
if FreeCAD.GuiUp:
_ViewProviderArchSchedule(self.obj.ViewObject)
+ if hasattr(self.obj,"CreateSpreadsheet") and self.obj.CreateSpreadsheet:
+ import Spreadsheet
+ sp = FreeCAD.ActiveDocument.addObject("Spreadsheet::Sheet","Result")
+ self.obj.Result = sp
lists = [ [], [], [], [], [] ]
for i in range(self.form.list.rowCount()):
for j in range(5):
@@ -391,14 +633,18 @@ class _ArchScheduleTaskPanel:
lists[j].append(cell.text())
else:
lists[j].append("")
+ FreeCAD.ActiveDocument.openTransaction("Edited Schedule")
self.obj.Description = lists[0]
self.obj.Value = lists[1]
self.obj.Unit = lists[2]
self.obj.Objects = lists[3]
self.obj.Filter = lists[4]
+ self.obj.Label = self.form.lineEditName.text()
+ self.obj.DetailedResults = self.form.checkDetailed.isChecked()
+ self.obj.CreateSpreadsheet = self.form.checkSpreadsheet.isChecked()
+ FreeCAD.ActiveDocument.commitTransaction()
FreeCAD.ActiveDocument.recompute()
- return True
if FreeCAD.GuiUp:
- FreeCADGui.addCommand('Arch_Schedule',_CommandArchSchedule())
+ FreeCADGui.addCommand('Arch_Schedule',CommandArchSchedule())
diff --git a/src/Mod/Arch/Resources/ui/ArchSchedule.ui b/src/Mod/Arch/Resources/ui/ArchSchedule.ui
index ab521dced7..4ff169edab 100644
--- a/src/Mod/Arch/Resources/ui/ArchSchedule.ui
+++ b/src/Mod/Arch/Resources/ui/ArchSchedule.ui
@@ -6,14 +6,28 @@
0
0
- 287
- 415
+ 554
+ 380
Schedule definition
+ -
+
+
-
+
+
+ Schedule name:
+
+
+
+ -
+
+
+
+
-
@@ -28,9 +42,15 @@
120
+
+ true
+
true
+
+ false
+
Description
@@ -41,10 +61,10 @@
- Value
+ Property
- The value to retrieve for each object. Can be "count" to count the objects, or object.Shape.Volume to retrieve a certain property.
+ The property to retrieve from each object. Can be "count" to count the objects, or property names like "Length" or "Shape.Volume" to retrieve a certain property.
@@ -52,7 +72,7 @@
Unit
- An optional unit to express the resulting value. Ex: m^3
+ An optional unit to express the resulting value. Ex: m^3 (you can also write m³ or m3)
@@ -60,7 +80,7 @@
Objects
- An optional semicolon (;) separated list of object names to be considered by this operation. If the list contains groups, children will be added
+ An optional semicolon (;) separated list of object names internal names, not labels) to be considered by this operation. If the list contains groups, children will be added. Leave blank to use all objects from the document
@@ -68,11 +88,35 @@
Filter
- A semicolon (;) separated list of type:value filters (see documentation for filters syntax)
+ <html><head/><body><p>An optional semicolon (;) separated list of type:value filters. Examples of valid filters (everything is case-insensitive):</p><p><span style=" font-weight:600;">Name:Wall</span> - Will only consider objects with "wall" in their name (internal name)</p><p><span style=" font-weight:600;">!Name:Wall</span> - Will only consider objects which DON'T have "wall" in their name (internal name)</p><p><span style=" font-weight:600;">Label:Win</span> - Will only consider objects with "win" in their label</p><p><span style=" font-weight:600;">!Label:Win</span> - Will only consider objects which DON't have "win" in their label</p><p><span style=" font-weight:600;">Type:Wall</span> - Will only consider objects which Ifc Type is "Wall"</p><p><span style=" font-weight:600;">!Type:Wall</span> - Will only consider objects which Ifc Type is NOT "Wall"</p><p>If you leave this field empty, no filtering is applied</p></body></html>
+ -
+
+
-
+
+
+ If this is enabled, an associated spreadsheet containing the results will be maintained together with this schedule object
+
+
+ Associate spreadsheet
+
+
+
+ -
+
+
+ If this is turned on, additional lines will be filled with each object considered. If not, only the totals.
+
+
+ Detailed results
+
+
+
+
+
-
-
@@ -81,7 +125,7 @@
Adds a line below the selected line/cell
- Add
+ Add row
@@ -96,7 +140,7 @@
Deletes the selected line
- Del
+ Del row
@@ -130,7 +174,7 @@
Put selected objects into the "Objects" column of the selected row
- Selection
+ Add selection
@@ -152,8 +196,7 @@
-
- This exports the contents of the "Result" spreadsheet to a CSV file. In Libreoffice, you can keep this CSV file linked by right-clicking the Sheets tab bar -> New sheet -> From file -> Link
- Note: as of LibreOffice v5.4.5.1 the correct path now is: Sheets tab bar -> Insert Sheet... -> From file -> Browse...
+ <html><head/><body><p>This exports the results to a CSV or Markdown file. </p><p><span style=" font-weight:600;">Note for CSV export:</span></p><p>In Libreoffice, you can keep this CSV file linked by right-clicking the Sheets tab bar -> New sheet -> From file -> Link (Note: as of LibreOffice v5.4.5.1 the correct path now is: Sheets tab bar -> Insert Sheet... -> From file -> Browse...)</p></body></html>
Export
@@ -169,6 +212,18 @@
+
+
+ Gui::PrefCheckBox
+ QCheckBox
+
+
+
+ Gui::PrefLineEdit
+ QLineEdit
+
+
+