From f3953a45e3c073c97fe05a10c5871abd25ea1d30 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Fri, 22 Sep 2017 16:10:51 -0300 Subject: [PATCH] Arch: New UI for the survey tool --- src/Mod/Arch/ArchCommands.py | 292 ++++++++++++++++++++++++++++++----- 1 file changed, 254 insertions(+), 38 deletions(-) diff --git a/src/Mod/Arch/ArchCommands.py b/src/Mod/Arch/ArchCommands.py index 230152f451..a4116aa58d 100644 --- a/src/Mod/Arch/ArchCommands.py +++ b/src/Mod/Arch/ArchCommands.py @@ -188,7 +188,7 @@ def removeComponents(objectsList,host=None): if o in a: a.remove(o) h.Objects = a - + def makeComponent(baseobj=None,name="Component",delete=False): '''makeComponent([baseobj]): creates an undefined, non-parametric Arch component from the given base object''' @@ -212,7 +212,7 @@ def makeComponent(baseobj=None,name="Component",delete=False): obj.Shape = baseobj Draft.select(obj) return obj - + def cloneComponent(obj): '''cloneComponent(obj): Creates a clone of an object as an undefined component''' c = makeComponent() @@ -455,7 +455,7 @@ def getShapeFromMesh(mesh,fast=True,tolerance=0.001,flat=False,cut=True): print("getShapeFromMesh: error removing splitter") #pass return solid - + #if not mesh.isSolid(): # print "getShapeFromMesh: non-solid mesh, using slow method" faces = [] @@ -725,55 +725,51 @@ def getAllChildren(objectlist): obs.append(c) return obs -class _SurveyObserver: - "an observer for the survey() function" - def __init__(self,callback): - self.callback = callback - self.cancellable = False - self.selection = [] - self.labels = [] - - def addSelection(self,document, object, element, position): - self.cancellable = False - self.callback(True) - - def clearSelection(self,document): - if self.cancellable: - self.callback(True) - else: - self.cancellable = True def survey(callback=False): """survey(): starts survey mode, where you can click edges and faces to get their lengths or area. - Clicking on no object (on an empty area) stops survey mode.""" + Clicking on no object (on an empty area) resets the count.""" if not callback: if hasattr(FreeCAD,"SurveyObserver"): for label in FreeCAD.SurveyObserver.labels: FreeCAD.ActiveDocument.removeObject(label) FreeCADGui.Selection.removeObserver(FreeCAD.SurveyObserver) del FreeCAD.SurveyObserver - if FreeCAD.GuiUp: - if hasattr(FreeCADGui,"draftToolBar"): - FreeCADGui.draftToolBar.offUi() + FreeCADGui.Control.closeDialog() + if hasattr(FreeCAD,"SurveyDialog"): + del FreeCAD.SurveyDialog else: FreeCAD.SurveyObserver = _SurveyObserver(callback=survey) FreeCADGui.Selection.addObserver(FreeCAD.SurveyObserver) - if FreeCAD.GuiUp: - if hasattr(FreeCADGui,"draftToolBar"): - FreeCADGui.draftToolBar.selectUi(callback=survey) + FreeCAD.SurveyDialog = SurveyTaskPanel() + FreeCADGui.Control.showDialog(FreeCAD.SurveyDialog) else: sel = FreeCADGui.Selection.getSelectionEx() - if not sel: - if hasattr(FreeCAD,"SurveyObserver"): - for label in FreeCAD.SurveyObserver.labels: - FreeCAD.ActiveDocument.removeObject(label) - FreeCADGui.Selection.removeObserver(FreeCAD.SurveyObserver) - del FreeCAD.SurveyObserver - if FreeCAD.GuiUp: - if hasattr(FreeCADGui,"draftToolBar"): - FreeCADGui.draftToolBar.offUi() - else: - if hasattr(FreeCAD,"SurveyObserver"): + if hasattr(FreeCAD,"SurveyObserver"): + if not sel: + if FreeCAD.SurveyObserver.labels: + for label in FreeCAD.SurveyObserver.labels: + FreeCAD.ActiveDocument.removeObject(label) + tl = FreeCAD.SurveyObserver.totalLength + ta = FreeCAD.SurveyObserver.totalArea + FreeCAD.SurveyObserver.labels = [] + FreeCAD.SurveyObserver.selection = [] + FreeCAD.SurveyObserver.totalLength = 0 + FreeCAD.SurveyObserver.totalArea = 0 + FreeCAD.SurveyObserver.totalVolume = 0 + if not FreeCAD.SurveyObserver.cancellable: + FreeCAD.Console.PrintMessage("\n---- Reset ----\n\n") + FreeCAD.SurveyObserver.cancellable = True + if hasattr(FreeCAD,"SurveyDialog"): + FreeCAD.SurveyDialog.newline(tl,ta) + else: + FreeCADGui.Selection.removeObserver(FreeCAD.SurveyObserver) + del FreeCAD.SurveyObserver + FreeCADGui.Control.closeDialog() + if hasattr(FreeCAD,"SurveyDialog"): + del FreeCAD.SurveyDialog + else: + FreeCAD.SurveyObserver.cancellable = False basesel = FreeCAD.SurveyObserver.selection newsels = [] for o in sel: @@ -805,18 +801,25 @@ def survey(callback=False): t = t.encode("utf8").replace("^3","³") anno.LabelText = "v " + t FreeCAD.Console.PrintMessage("Object: " + n + ", Element: Whole, Volume: " + utf8_decode(t) + "\n") + FreeCAD.SurveyObserver.totalVolume += u.Value elif o.Object.Shape.Faces: u = FreeCAD.Units.Quantity(o.Object.Shape.Area,FreeCAD.Units.Area) t = u.getUserPreferred()[0] t = t.encode("utf8").replace("^2","²") anno.LabelText = "a " + t FreeCAD.Console.PrintMessage("Object: " + n + ", Element: Whole, Area: " + utf8_decode(t) + "\n") + FreeCAD.SurveyObserver.totalArea += u.Value + if hasattr(FreeCAD,"SurveyDialog"): + FreeCAD.SurveyDialog.update(2,t) else: u = FreeCAD.Units.Quantity(o.Object.Shape.Length,FreeCAD.Units.Length) t = u.getUserPreferred()[0] t = t.encode("utf8") anno.LabelText = "l " + t FreeCAD.Console.PrintMessage("Object: " + n + ", Element: Whole, Length: " + utf8_decode(t) + "\n") + FreeCAD.SurveyObserver.totalLength += u.Value + if hasattr(FreeCAD,"SurveyDialog"): + FreeCAD.SurveyDialog.update(1,t) if FreeCAD.GuiUp and t: if showUnit: QtGui.qApp.clipboard().setText(t) @@ -841,12 +844,18 @@ def survey(callback=False): t = t.encode("utf8").replace("^2","²") anno.LabelText = "a " + t FreeCAD.Console.PrintMessage("Object: " + n + ", Element: " + el + ", Area: "+ utf8_decode(t) + "\n") + FreeCAD.SurveyObserver.totalArea += u.Value + if hasattr(FreeCAD,"SurveyDialog"): + FreeCAD.SurveyDialog.update(2,t) elif "Edge" in el: u= FreeCAD.Units.Quantity(e.Length,FreeCAD.Units.Length) t = u.getUserPreferred()[0] t = t.encode("utf8") anno.LabelText = "l " + t FreeCAD.Console.PrintMessage("Object: " + n + ", Element: " + el + ", Length: " + utf8_decode(t) + "\n") + FreeCAD.SurveyObserver.totalLength += u.Value + if hasattr(FreeCAD,"SurveyDialog"): + FreeCAD.SurveyDialog.update(1,t) elif "Vertex" in el: u = FreeCAD.Units.Quantity(e.Z,FreeCAD.Units.Length) t = u.getUserPreferred()[0] @@ -860,6 +869,213 @@ def survey(callback=False): QtGui.qApp.clipboard().setText(str(u.Value)) FreeCAD.SurveyObserver.selection.extend(newsels) + if hasattr(FreeCAD,"SurveyObserver"): + if FreeCAD.SurveyObserver.totalLength or FreeCAD.SurveyObserver.totalArea or FreeCAD.SurveyObserver.totalVolume: + msg = " Total:" + if FreeCAD.SurveyObserver.totalLength: + u = FreeCAD.Units.Quantity(FreeCAD.SurveyObserver.totalLength,FreeCAD.Units.Length) + t = u.getUserPreferred()[0] + t = t.encode("utf8") + msg += " Length: " + t + if FreeCAD.SurveyObserver.totalArea: + u = FreeCAD.Units.Quantity(FreeCAD.SurveyObserver.totalArea,FreeCAD.Units.Area) + t = u.getUserPreferred()[0] + t = t.encode("utf8").replace("^2","²") + msg += " Area: " + t + if FreeCAD.SurveyObserver.totalVolume: + u = FreeCAD.Units.Quantity(FreeCAD.SurveyObserver.totalVolume,FreeCAD.Units.Volume) + t = u.getUserPreferred()[0] + t = t.encode("utf8").replace("^3","³") + msg += " Volume: " + t + FreeCAD.Console.PrintMessage(msg+"\n") + +class _SurveyObserver: + "an observer for the survey() function" + def __init__(self,callback): + self.callback = callback + self.selection = [] + self.labels = [] + self.totalLength = 0 + self.totalArea = 0 + self.totalVolume = 0 + self.cancellable = False + self.doubleclear = False + + def addSelection(self,document, object, element, position): + self.doubleclear = False + self.callback(True) + + def clearSelection(self,document): + if not self.doubleclear: + self.doubleclear = True + else: + self.callback(True) + +class SurveyTaskPanel: + "A task panel for the survey tool" + + def __init__(self): + self.form = QtGui.QWidget() + self.form.setWindowIcon(QtGui.QIcon(":/icons/Arch_Survey.svg")) + layout = QtGui.QVBoxLayout(self.form) + llayout = QtGui.QHBoxLayout() + self.descr = QtGui.QLineEdit() + llayout.addWidget(self.descr) + self.addButton = QtGui.QPushButton() + llayout.addWidget(self.addButton) + layout.addLayout(llayout) + self.tree = QtGui.QTreeWidget() + self.tree.setColumnCount(3) + layout.addWidget(self.tree) + blayout = QtGui.QHBoxLayout() + self.clearButton = QtGui.QPushButton() + blayout.addWidget(self.clearButton) + self.copyLength = QtGui.QPushButton() + blayout.addWidget(self.copyLength) + self.copyArea = QtGui.QPushButton() + blayout.addWidget(self.copyArea) + layout.addLayout(blayout) + self.export = QtGui.QPushButton() + layout.addWidget(self.export) + QtCore.QObject.connect(self.addButton, QtCore.SIGNAL("clicked()"), self.setText) + QtCore.QObject.connect(self.clearButton, QtCore.SIGNAL("clicked()"), self.clear) + QtCore.QObject.connect(self.copyLength, QtCore.SIGNAL("clicked()"), self.clipLength) + QtCore.QObject.connect(self.copyArea, QtCore.SIGNAL("clicked()"), self.clipArea) + QtCore.QObject.connect(self.export, QtCore.SIGNAL("clicked()"), self.exportCSV) + QtCore.QObject.connect(self.tree, QtCore.SIGNAL("itemClicked(QTreeWidgetItem*,int)"), self.setDescr) + self.retranslateUi(self) + item = QtGui.QTreeWidgetItem(self.tree) + self.tree.setCurrentItem(item) + + def retranslateUi(self,dlg): + self.form.setWindowTitle(QtGui.QApplication.translate("Arch", "Survey", None)) + self.addButton.setText(QtGui.QApplication.translate("Arch", "Set description", None)) + self.clearButton.setText(QtGui.QApplication.translate("Arch", "Clear", None)) + self.copyLength.setText(QtGui.QApplication.translate("Arch", "Copy Length", None)) + self.copyArea.setText(QtGui.QApplication.translate("Arch", "Copy Area", None)) + self.export.setText(QtGui.QApplication.translate("Arch", "Export CSV", None)) + self.tree.setHeaderLabels([QtGui.QApplication.translate("Arch", "Description", None), + QtGui.QApplication.translate("Arch", "Length", None), + QtGui.QApplication.translate("Arch", "Area", None)]) + + def isAllowedAlterSelection(self): + return True + + def isAllowedAlterView(self): + return True + + def getStandardButtons(self): + return int(QtGui.QDialogButtonBox.Close) + + def reject(self): + if hasattr(FreeCAD,"SurveyObserver"): + for label in FreeCAD.SurveyObserver.labels: + FreeCAD.ActiveDocument.removeObject(label) + FreeCADGui.Selection.removeObserver(FreeCAD.SurveyObserver) + del FreeCAD.SurveyObserver + return True + + def clear(self): + FreeCADGui.Selection.clearSelection() + + def clipLength(self): + if hasattr(FreeCAD,"SurveyObserver"): + u = FreeCAD.Units.Quantity(FreeCAD.SurveyObserver.totalLength,FreeCAD.Units.Length) + t = u.getUserPreferred()[0] + t = t.encode("utf8") + if FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch").GetBool("surveyUnits",True): + QtGui.qApp.clipboard().setText(t) + else: + QtGui.qApp.clipboard().setText(str(u.Value/u.getUserPreferred()[1])) + + def clipArea(self): + if hasattr(FreeCAD,"SurveyObserver"): + u = FreeCAD.Units.Quantity(FreeCAD.SurveyObserver.totalArea,FreeCAD.Units.Area) + t = u.getUserPreferred()[0] + t = t.encode("utf8").replace("^2","²") + if FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch").GetBool("surveyUnits",True): + QtGui.qApp.clipboard().setText(t) + else: + QtGui.qApp.clipboard().setText(str(u.Value/u.getUserPreferred()[1])) + + def newline(self,length=0,area=0): + FreeCADGui.Selection.clearSelection() + item = QtGui.QTreeWidgetItem(self.tree) + if length or area: + item.setText(0,QtGui.QApplication.translate("Arch", "Total", None)) + item.setToolTip(0,"total") + f = QtGui.QFont() + f.setBold(True) + item.setFont(0,f) + item.setFont(1,f) + item.setFont(2,f) + else: + item.setText(0,self.descr.text()) + self.descr.setText("") + self.tree.setCurrentItem(item) + if length: + u = FreeCAD.Units.Quantity(length,FreeCAD.Units.Length) + t = u.getUserPreferred()[0] + item.setText(1,t) + if area: + u = FreeCAD.Units.Quantity(area,FreeCAD.Units.Area) + t = u.getUserPreferred()[0] + t = t.replace(u"^2",u"²") + item.setText(2,t) + if length or area: + item = QtGui.QTreeWidgetItem(self.tree) + self.tree.setCurrentItem(item) + + def update(self,column,txt): + item = QtGui.QTreeWidgetItem(self.tree) + self.tree.setCurrentItem(item) + item.setText(column,txt.decode("utf8")) + + def setDescr(self,item,col): + self.descr.setText(item.text(0)) + + def setText(self): + item = self.tree.currentItem() + if item: + item.setText(0,self.descr.text()) + self.descr.setText("") + + def exportCSV(self): + import csv + rows = self.tree.topLevelItemCount() + if rows: + filename = QtGui.QFileDialog.getSaveFileName(QtGui.qApp.activeWindow(), translate("Arch","Export CSV File"), None, "CSV file (*.csv)"); + if filename: + with open(filename[0].encode("utf8"), 'wb') as csvfile: + csvfile = csv.writer(csvfile,delimiter="\t") + suml = 0 + for i in range(rows): + item = self.tree.topLevelItem(i) + row = [] + row.append(item.text(0)) + if item.text(1): + u = FreeCAD.Units.Quantity(item.text(1)) + if item.toolTip(0) == "total": + row.append("=SUM(B"+str(suml+1)+":B"+str(i)+")") + else: + row.append(u.Value/u.getUserPreferred()[1]) + row.append(u.getUserPreferred()[2]) + else: + row.extend(["",""]) + if item.text(2): + t = item.text(2).replace(u"²",u"^2") + u = FreeCAD.Units.Quantity(t) + if item.toolTip(0) == "total": + row.append("=SUM(D"+str(suml+1)+":D"+str(i)+")") + else: + row.append(u.Value/u.getUserPreferred()[1]) + row.append(u.getUserPreferred()[2]) + else: + row.extend(["",""]) + csvfile.writerow(row) + if item.toolTip(0) == "total": + suml = i+1 + print("successfully exported ",filename[0]) def toggleIfcBrepFlag(obj):