Removes unused imports as reported by LGTM. There are exceptions: `import Arch_rc` is shown as an alert, but has side effects. It's not clear what the best thing to do in those cases is, so I've left them for now.
692 lines
27 KiB
Python
692 lines
27 KiB
Python
# -*- coding: utf8 -*-
|
|
#***************************************************************************
|
|
#* Copyright (c) 2015 Yorik van Havre <yorik@uncreated.net> *
|
|
#* *
|
|
#* This program is free software; you can redistribute it and/or modify *
|
|
#* it under the terms of the GNU Lesser General Public License (LGPL) *
|
|
#* as published by the Free Software Foundation; either version 2 of *
|
|
#* the License, or (at your option) any later version. *
|
|
#* for detail see the LICENCE text file. *
|
|
#* *
|
|
#* This program is distributed in the hope that it will be useful, *
|
|
#* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
#* GNU Library General Public License for more details. *
|
|
#* *
|
|
#* You should have received a copy of the GNU Library General Public *
|
|
#* License along with this program; if not, write to the Free Software *
|
|
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
|
#* USA *
|
|
#* *
|
|
#***************************************************************************
|
|
|
|
from __future__ import print_function
|
|
import sys
|
|
import FreeCAD
|
|
if FreeCAD.GuiUp:
|
|
import FreeCADGui
|
|
from PySide import QtCore, QtGui
|
|
from DraftTools import translate
|
|
from PySide.QtCore import QT_TRANSLATE_NOOP
|
|
else:
|
|
# \cond
|
|
def translate(ctxt,txt):
|
|
return txt
|
|
def QT_TRANSLATE_NOOP(ctxt,txt):
|
|
return txt
|
|
# \endcond
|
|
|
|
## @package ArchSchedule
|
|
# \ingroup ARCH
|
|
# \brief The Schedule object and tools
|
|
#
|
|
# This module provides tools to build Schedule objects.
|
|
# Schedules are objects that can count and gather information
|
|
# about objects in the document, and fill a spreadsheet with the result
|
|
|
|
__title__ = "Arch Schedule"
|
|
__author__ = "Yorik van Havre"
|
|
__url__ = "https://www.freecadweb.org"
|
|
|
|
|
|
verbose = True # change this for silent recomputes
|
|
|
|
|
|
|
|
class CommandArchSchedule:
|
|
|
|
"the Arch Schedule command definition"
|
|
|
|
def GetResources(self):
|
|
return {'Pixmap': 'Arch_Schedule',
|
|
'MenuText': QT_TRANSLATE_NOOP("Arch_Schedule","Schedule"),
|
|
'ToolTip': QT_TRANSLATE_NOOP("Arch_Schedule","Creates a schedule to collect data from the model")}
|
|
|
|
def Activated(self):
|
|
if hasattr(self,"taskd"):
|
|
if self.taskd:
|
|
self.taskd.form.hide()
|
|
self.taskd = ArchScheduleTaskPanel()
|
|
|
|
def IsActive(self):
|
|
if FreeCAD.ActiveDocument:
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
|
|
|
|
class _ArchSchedule:
|
|
|
|
"the Arch Schedule object"
|
|
|
|
def __init__(self,obj):
|
|
|
|
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,force=False):
|
|
|
|
"""Fills a spreadsheet with the stored data"""
|
|
|
|
if not hasattr(self,"data"):
|
|
self.execute(obj)
|
|
if not hasattr(self,"data"):
|
|
return
|
|
if not self.data:
|
|
return
|
|
if not obj.Result:
|
|
if obj.CreateSpreadsheet or force:
|
|
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):
|
|
|
|
# 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
|
|
|
|
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
|
|
self.data["A"+str(li)] = obj.Description[i]
|
|
else:
|
|
self.data["A"+str(li)] = obj.Description[i].encode("utf8")
|
|
if verbose:
|
|
l= "OPERATION: "+obj.Description[i]
|
|
print("")
|
|
print (l)
|
|
print (len(l)*"=")
|
|
|
|
# build set of valid objects
|
|
|
|
objs = obj.Objects[i]
|
|
val = obj.Value[i]
|
|
if val:
|
|
import Draft,Arch
|
|
if objs:
|
|
objs = objs.split(";")
|
|
objs = [FreeCAD.ActiveDocument.getObject(o) for o in objs]
|
|
objs = [o for o in objs if o != None]
|
|
else:
|
|
objs = FreeCAD.ActiveDocument.Objects
|
|
if len(objs) == 1:
|
|
# remove object itself if the object is a group
|
|
if objs[0].isDerivedFrom("App::DocumentObjectGroup"):
|
|
objs = objs[0].Group
|
|
objs = Draft.get_group_contents(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]
|
|
objs = [o for o in objs if not o == obj.Result]
|
|
if obj.Filter[i]:
|
|
# apply filters
|
|
nobjs = []
|
|
for o in objs:
|
|
props = [p.upper() for p in o.PropertiesList]
|
|
ok = True
|
|
for f in obj.Filter[i].split(";"):
|
|
args = [a.strip() for a in f.strip().split(":")]
|
|
if args[0][0] == "!":
|
|
inv = True
|
|
prop = args[0][1:].upper()
|
|
else:
|
|
inv = False
|
|
prop = args[0].upper()
|
|
fval = args[1].upper()
|
|
if prop == "TYPE":
|
|
prop = "IFCTYPE"
|
|
if inv:
|
|
if prop in props:
|
|
csprop = o.PropertiesList[props.index(prop)]
|
|
if fval in getattr(o,csprop).upper():
|
|
ok = False
|
|
else:
|
|
if not (prop in props):
|
|
ok = False
|
|
else:
|
|
csprop = o.PropertiesList[props.index(prop)]
|
|
if not (fval in getattr(o,csprop).upper()):
|
|
ok = False
|
|
if ok:
|
|
nobjs.append(o)
|
|
objs = nobjs
|
|
|
|
# perform operation: count or retrieve property
|
|
|
|
if val.upper() == "COUNT":
|
|
val = len(objs)
|
|
if verbose:
|
|
print (val, ",".join([o.Label for o in objs]))
|
|
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
|
|
|
|
# get unit
|
|
tp = None
|
|
unit = None
|
|
q = None
|
|
if obj.Unit[i]:
|
|
unit = obj.Unit[i]
|
|
if sys.version_info.major < 3:
|
|
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
|
|
elif "3" in unit:
|
|
tp = FreeCAD.Units.Volume
|
|
elif "deg" in unit:
|
|
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
|
|
except Exception:
|
|
FreeCAD.Console.PrintWarning(translate("Arch","Unable to retrieve value from object")+": "+o.Name+"."+".".join(vals)+"\n")
|
|
else:
|
|
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)
|
|
|
|
if not sumval:
|
|
sumval = d
|
|
else:
|
|
sumval += d
|
|
val = sumval
|
|
if tp:
|
|
q = FreeCAD.Units.Quantity(val,tp)
|
|
|
|
# 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:
|
|
self.data["B"+str(li)] = str(val)
|
|
if obj.DetailedResults:
|
|
# additional blank line...
|
|
li += 1
|
|
self.data["A"+str(li)] = " "
|
|
if verbose:
|
|
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
|
|
|
|
|
|
class _ViewProviderArchSchedule:
|
|
|
|
"A View Provider for Schedules"
|
|
|
|
def __init__(self,vobj):
|
|
vobj.Proxy = self
|
|
|
|
def getIcon(self):
|
|
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=0):
|
|
if hasattr(self,"taskd"):
|
|
if self.taskd:
|
|
self.taskd.form.hide()
|
|
self.taskd = ArchScheduleTaskPanel(vobj.Object)
|
|
return True
|
|
|
|
def doubleClicked(self,vobj):
|
|
self.setEdit(vobj)
|
|
|
|
def unsetEdit(self,vobj,mode):
|
|
return True
|
|
|
|
def claimChildren(self):
|
|
if hasattr(self,"Object"):
|
|
return [self.Object.Result]
|
|
|
|
def __getstate__(self):
|
|
return None
|
|
|
|
def __setstate__(self,state):
|
|
return None
|
|
|
|
def getDisplayModes(self,vobj):
|
|
return ["Default"]
|
|
|
|
def getDefaultDisplayMode(self):
|
|
return "Default"
|
|
|
|
def setDisplayMode(self,mode):
|
|
return mode
|
|
|
|
def setupContextMenu(self,vobj,menu):
|
|
action1 = QtGui.QAction(QtGui.QIcon(":/icons/Arch_Schedule.svg"),"Attach spreadsheet",menu)
|
|
QtCore.QObject.connect(action1,QtCore.SIGNAL("triggered()"),self.attachSpreadsheet)
|
|
menu.addAction(action1)
|
|
|
|
def attachSpreadsheet(self):
|
|
if hasattr(self,"Object"):
|
|
self.Object.Proxy.setSpreadsheetData(self.Object,force=True)
|
|
|
|
|
|
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))
|
|
w = p.GetInt("ScheduleDialogWidth",300)
|
|
h = p.GetInt("ScheduleDialogHeight",200)
|
|
self.form.resize(w,h)
|
|
|
|
# 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.export)
|
|
QtCore.QObject.connect(self.form.buttonSelect, QtCore.SIGNAL("clicked()"), self.select)
|
|
QtCore.QObject.connect(self.form.buttonBox, QtCore.SIGNAL("accepted()"), self.accept)
|
|
QtCore.QObject.connect(self.form.buttonBox, QtCore.SIGNAL("rejected()"), self.reject)
|
|
QtCore.QObject.connect(self.form, QtCore.SIGNAL("rejected()"), self.reject)
|
|
self.form.list.clearContents()
|
|
|
|
if self.obj:
|
|
if not obj.Description:
|
|
return
|
|
for p in [obj.Value,obj.Unit,obj.Objects,obj.Filter]:
|
|
if len(obj.Description) != len(p):
|
|
return
|
|
self.form.list.setRowCount(len(obj.Description))
|
|
for i in range(5):
|
|
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)
|
|
|
|
# center over FreeCAD window
|
|
mw = FreeCADGui.getMainWindow()
|
|
self.form.move(mw.frameGeometry().topLeft() + mw.rect().center() - self.form.rect().center())
|
|
|
|
# maintain above FreeCAD window
|
|
self.form.setWindowFlags(self.form.windowFlags() | QtCore.Qt.WindowStaysOnTopHint)
|
|
|
|
self.form.show()
|
|
|
|
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,'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")
|
|
self.form.list.setItem(r,i,QtGui.QTableWidgetItem(t))
|
|
r += 1
|
|
|
|
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,
|
|
"Comma-separated values (*.csv);;TAB-separated values (*.tsv);;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(".tsv")) and (not filename.lower().endswith(".md")):
|
|
if "csv" in filt:
|
|
filename += ".csv"
|
|
elif "tsv" in filt:
|
|
filename += ".tsv"
|
|
else:
|
|
filename += ".md"
|
|
if filename.lower().endswith(".csv"):
|
|
self.exportCSV(filename,delimiter=",")
|
|
elif filename.lower().endswith(".tsv"):
|
|
self.exportCSV(filename,delimiter="\t")
|
|
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,delimiter="\t"):
|
|
|
|
"""Exports the results as a CSV/TSV file"""
|
|
|
|
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():
|
|
if o != self.obj:
|
|
if sel:
|
|
sel += ";"
|
|
sel += o.Name
|
|
if sel:
|
|
self.form.list.setItem(self.form.list.currentRow(),3,QtGui.QTableWidgetItem(sel))
|
|
|
|
def accept(self):
|
|
|
|
"""Saves the changes and closes the dialog"""
|
|
|
|
# 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))
|
|
p.SetInt("ScheduleDialogWidth",self.form.width())
|
|
p.SetInt("ScheduleDialogHeight",self.form.height())
|
|
|
|
# commit values
|
|
self.writeValues()
|
|
self.form.hide()
|
|
return True
|
|
|
|
def reject(self):
|
|
|
|
"""Close dialog without saving"""
|
|
|
|
self.form.hide()
|
|
return True
|
|
|
|
def writeValues(self):
|
|
|
|
"""commits values and recalculate"""
|
|
|
|
if not self.obj:
|
|
self.obj = FreeCAD.ActiveDocument.addObject("App::FeaturePython","Schedule")
|
|
self.obj.Label = translate("Arch","Schedule")
|
|
_ArchSchedule(self.obj)
|
|
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):
|
|
cell = self.form.list.item(i,j)
|
|
if cell:
|
|
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()
|
|
|
|
|
|
if FreeCAD.GuiUp:
|
|
FreeCADGui.addCommand('Arch_Schedule',CommandArchSchedule())
|