From 7323d8ae5c0a06b72095ef3cb7f1f5edfca98d67 Mon Sep 17 00:00:00 2001 From: Thomas-Alexandre Moreau Date: Thu, 15 May 2025 17:39:09 +0200 Subject: [PATCH 1/3] modified import from PySide2 to PySide --- MultiExport.FCMacro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MultiExport.FCMacro b/MultiExport.FCMacro index 665a47f..3d1387c 100755 --- a/MultiExport.FCMacro +++ b/MultiExport.FCMacro @@ -4,7 +4,7 @@ import FreeCADGui import Draft import os import Mesh -from PySide2.QtWidgets import QWidget, QLabel, QSpinBox, QHBoxLayout, QListWidgetItem +from PySide.QtWidgets import QWidget, QLabel, QSpinBox, QHBoxLayout, QListWidgetItem from datetime import datetime From d1e0f260fc46ebb82d98ad0cf955236696925f7a Mon Sep 17 00:00:00 2001 From: Thomas-Alexandre Moreau Date: Wed, 11 Jun 2025 16:37:10 +0200 Subject: [PATCH 2/3] added refresh button (temp fix) --- MultiExport.FCMacro | 83 +++++++++++++++++++++----------------- MultiExport/MultiExport.ui | 24 ++++++++++- 2 files changed, 69 insertions(+), 38 deletions(-) diff --git a/MultiExport.FCMacro b/MultiExport.FCMacro index 3d1387c..6996f19 100755 --- a/MultiExport.FCMacro +++ b/MultiExport.FCMacro @@ -36,14 +36,28 @@ class WindowDialog(): self._connect_widgets() self._populate_selector_list() - # Connect the selection change signal to keep the list in sync FreeCADGui.Selection.addObserver(self._on_selection_changed) self.form.show() + def refresh(self): + for index in range(self.form.listWidgetSelector.count()): + item = self.form.listWidgetSelector.item(index) + widget = self.form.listWidgetSelector.itemWidget(item) + item.setSelected(False) + + for obj in FreeCADGui.Selection.getSelection(): + for index in range(self.form.listWidgetSelector.count()): + item = self.form.listWidgetSelector.item(index) + widget = self.form.listWidgetSelector.itemWidget(item) + if widget.obj == obj: + item.setSelected(True) + break def _connect_widgets(self): self.form.pushButtonExport.pressed.connect(self.export) + self.form.pushButtonSave.pressed.connect(self.saveVarSet) + self.form.pushButtonRefresh.pressed.connect(self.refresh) self.form.listWidgetSelector.itemClicked.connect(self._on_list_item_clicked) def _populate_selector_list(self): @@ -59,7 +73,6 @@ class WindowDialog(): self.form.listWidgetSelector.addItem(item) self.form.listWidgetSelector.setItemWidget(item, widget) - # Sync selection: add the object to the selection and select the item in the list item.setSelected(True) FreeCADGui.Selection.addSelection(obj) @@ -74,19 +87,17 @@ class WindowDialog(): FreeCADGui.Selection.addSelection(obj) def _on_selection_changed(self, doc, objects): - # Clear current selection in the list for index in range(self.form.listWidgetSelector.count()): item = self.form.listWidgetSelector.item(index) widget = self.form.listWidgetSelector.itemWidget(item) - item.setSelected(False) # Deselect in the list + item.setSelected(False) - # Sync the list selection with FreeCAD's current selection for obj in FreeCADGui.Selection.getSelection(): for index in range(self.form.listWidgetSelector.count()): item = self.form.listWidgetSelector.item(index) widget = self.form.listWidgetSelector.itemWidget(item) if widget.obj == obj: - item.setSelected(True) # Select the corresponding item in the list + item.setSelected(True) break @@ -224,38 +235,13 @@ class WindowDialog(): largestFace = face if largestFace: - # Get normal at center of face (parametric center) u, v = largestFace.Surface.parameter(largestFace.CenterOfMass) normal = largestFace.normalAt(u, v) return normal.normalize() return None - # def searchDir(self, obj, xres, yres, zres): - # x, y, z = xres, yres, zres - - # if hasattr(obj, "Dir"): - # if obj.Dir.x != 0.0: - # x = obj.Dir.x - # if obj.Dir.y != 0.0: - # y = obj.Dir.y - # if obj.Dir.z != 0.0: - # z = obj.Dir.z - - # if not hasattr(obj, "Objects"): - # return FreeCAD.Vector(x, y, z) - # else: - # res = FreeCAD.Vector(x, y, z) - # for i in obj.Objects: - # res = self.searchDir(i, x, y, z) - # return res - - # elif hasattr(obj, "Objects"): - # res = FreeCAD.Vector(x, y, z) - # for i in obj.Objects: - # res = self.searchDir(i, x, y, z) - # return res - + def exportSVG(self, isCalepinage): plateLength = self.form.doubleSpinBoxLength.value() plateWidth = self.form.doubleSpinBoxWidth.value() @@ -266,8 +252,7 @@ class WindowDialog(): if not obj.Label.endswith("-SVG"): continue - count = 1 # default if not using spinboxes (or fetch from list if desired) - # Optional: match count from list + count = 1 for index in range(self.form.listWidgetSelector.count()): item = self.form.listWidgetSelector.item(index) widget = self.form.listWidgetSelector.itemWidget(item) @@ -281,7 +266,6 @@ class WindowDialog(): else: vector = self.getLargestFaceDir(obj) - # vector = self.searchDir(obj, 0, 0, 0) sv0 = Draft.make_shape2dview(obj, vector) FreeCAD.ActiveDocument.recompute() @@ -298,7 +282,9 @@ class WindowDialog(): else: self._exportSketchBasic(sketchList) - self._populate_selector_list() + for obj in FreeCAD.ActiveDocument.Objects: + if obj.Label.endswith("-SVG") or obj.Label.endswith("-STL"): + FreeCADGui.Selection.addSelection(obj) @@ -340,7 +326,9 @@ class WindowDialog(): FreeCAD.ActiveDocument.removeObject(obj.Name) FreeCAD.ActiveDocument.recompute() - self._populate_selector_list() + for obj in FreeCAD.ActiveDocument.Objects: + if obj.Label.endswith("-SVG") or obj.Label.endswith("-STL"): + FreeCADGui.Selection.addSelection(obj) def export(self): @@ -351,6 +339,27 @@ class WindowDialog(): self.exportSVG(isCalepinage) self.exportSTL(isCombine) + + + def saveVarSet(self, varSetName = "TestVarSet"): + varSet = FreeCAD.ActiveDocument.addObject("App::VarSet", varSetName) + + for obj in FreeCADGui.Selection.getSelection(): + count = 1 + for index in range(self.form.listWidgetSelector.count()): + item = self.form.listWidgetSelector.item(index) + widget = self.form.listWidgetSelector.itemWidget(item) + if widget.obj == obj: + count = widget.get_value() + break + + varSet.addProperty("App::PropertyStringList", obj.Name) + if obj.Label.endswith("-SVG"): + setattr(varSet, obj.Name, ("SVG", str(count))) + else: + setattr(varSet, obj.Name, ("STL", str(count))) + + FreeCAD.ActiveDocument.recompute() if __name__ == '__main__': diff --git a/MultiExport/MultiExport.ui b/MultiExport/MultiExport.ui index 7cd9bef..1773030 100644 --- a/MultiExport/MultiExport.ui +++ b/MultiExport/MultiExport.ui @@ -17,7 +17,7 @@ Multi Export - + @@ -45,6 +45,21 @@ + + + + 🔄 + + + + 12 + + + + Refresh + + + @@ -187,6 +202,13 @@ + + + + Save + + + From 9cc8cd49c06e0422bef78be79c54bca71f286b21 Mon Sep 17 00:00:00 2001 From: Thomas-Alexandre Moreau Date: Tue, 8 Jul 2025 12:43:55 +0200 Subject: [PATCH 3/3] reworked code - no longer depends on document selection but only on macro selection for exports --- MultiExport.FCMacro | 128 +++++++++++++++---------------------- MultiExport/MultiExport.ui | 15 ----- 2 files changed, 50 insertions(+), 93 deletions(-) diff --git a/MultiExport.FCMacro b/MultiExport.FCMacro index 6996f19..baa959b 100755 --- a/MultiExport.FCMacro +++ b/MultiExport.FCMacro @@ -14,7 +14,7 @@ class ObjectListItem(QWidget): self.obj = obj self.label = QLabel(obj.Label) self.spinbox = QSpinBox() - self.spinbox.setRange(0, 9999) + self.spinbox.setRange(1, 9999) self.spinbox.setValue(1) layout = QHBoxLayout() @@ -33,34 +33,20 @@ class WindowDialog(): self.outputRacine = "" self.ui_file = os.path.join(FreeCAD.getUserMacroDir(True), 'MultiExport/MultiExport.ui') self.form = FreeCADGui.PySideUic.loadUi(self.ui_file) - self._connect_widgets() - self._populate_selector_list() + self.connect_widgets() + self.populate_selector_list() - FreeCADGui.Selection.addObserver(self._on_selection_changed) + FreeCADGui.Selection.addObserver(self.on_selection_changed) self.form.show() - def refresh(self): - for index in range(self.form.listWidgetSelector.count()): - item = self.form.listWidgetSelector.item(index) - widget = self.form.listWidgetSelector.itemWidget(item) - item.setSelected(False) - for obj in FreeCADGui.Selection.getSelection(): - for index in range(self.form.listWidgetSelector.count()): - item = self.form.listWidgetSelector.item(index) - widget = self.form.listWidgetSelector.itemWidget(item) - if widget.obj == obj: - item.setSelected(True) - break - - def _connect_widgets(self): + def connect_widgets(self): self.form.pushButtonExport.pressed.connect(self.export) self.form.pushButtonSave.pressed.connect(self.saveVarSet) - self.form.pushButtonRefresh.pressed.connect(self.refresh) - self.form.listWidgetSelector.itemClicked.connect(self._on_list_item_clicked) - def _populate_selector_list(self): + + def populate_selector_list(self): self.form.listWidgetSelector.clear() FreeCADGui.Selection.clearSelection() @@ -74,19 +60,9 @@ class WindowDialog(): self.form.listWidgetSelector.setItemWidget(item, widget) item.setSelected(True) - FreeCADGui.Selection.addSelection(obj) - - def _on_list_item_clicked(self, item): - widget = self.form.listWidgetSelector.itemWidget(item) - obj = widget.obj - if obj in FreeCADGui.Selection.getSelection(): - FreeCADGui.Selection.removeSelection(obj) - else: - FreeCADGui.Selection.addSelection(obj) - - def _on_selection_changed(self, doc, objects): + def on_selection_changed(self, doc, objects): for index in range(self.form.listWidgetSelector.count()): item = self.form.listWidgetSelector.item(index) widget = self.form.listWidgetSelector.itemWidget(item) @@ -101,7 +77,7 @@ class WindowDialog(): break - def _createFolder(self): + def createFolder(self): date = datetime.today().strftime('%Y-%m-%d') time = datetime.today().strftime('%H:%M:%S') @@ -120,7 +96,7 @@ class WindowDialog(): # -------- MODIFICATION DE LA MACRO "exportSketchEnMasse-SVG" de Gauthier Brière -------- # - def _exportSketchBasic(self, sketchList): + def exportSketchBasic(self, sketchList): for __O__ in sketchList: __obj__ = [] __obj__.append(__O__) @@ -133,7 +109,7 @@ class WindowDialog(): FreeCAD.activeDocument().recompute() - def _exportSketchCalepinage(self, sketchList, plateLength, plateWidth, spacing): + def exportSketchCalepinage(self, sketchList, plateLength, plateWidth, spacing): copy_sketchList = sketchList[:] __obj__ = [] currentX = 0.0 @@ -197,8 +173,8 @@ class WindowDialog(): FreeCAD.activeDocument().recompute() if listSize <= 0 or isSVGFull: - fichierSVG = u"" + self.outputRacine + 'CALEPINAGE-' + str(SVGNameCounter) + '-' + '.svg' - print('Export SVG de : ' + u"" + str(os.path.basename(self.outputRacine)) + 'CALEPINAGE-' + str(SVGNameCounter) + '-' + '.svg') + fichierSVG = u"" + self.outputRacine + 'CALEPINAGE-(' + str(SVGNameCounter) + ')' + '.svg' + print('Export SVG de : ' + u"" + str(os.path.basename(self.outputRacine)) + 'CALEPINAGE-(' + str(SVGNameCounter) + ')' + '.svg') importSVG.export(__obj__, fichierSVG) for __i__ in __obj__: FreeCAD.ActiveDocument.removeObject(__i__.Label) @@ -242,25 +218,14 @@ class WindowDialog(): return None - def exportSVG(self, isCalepinage): + def exportSVG(self, isCalepinage, svgList): plateLength = self.form.doubleSpinBoxLength.value() plateWidth = self.form.doubleSpinBoxWidth.value() spacing = self.form.doubleSpinBoxSpacing.value() sketchList = [] - for obj in FreeCADGui.Selection.getSelection(): - if not obj.Label.endswith("-SVG"): - continue - - count = 1 - for index in range(self.form.listWidgetSelector.count()): - item = self.form.listWidgetSelector.item(index) - widget = self.form.listWidgetSelector.itemWidget(item) - if widget.obj == obj: - count = widget.get_value() - break - - for _ in range(count): + for _, obj, objCount in svgList: + for _ in range(objCount): if hasattr(obj, "Dir"): vector = FreeCAD.Vector(obj.Dir.x, obj.Dir.y, obj.Dir.z) else: @@ -278,34 +243,19 @@ class WindowDialog(): FreeCAD.ActiveDocument.removeObject(sv0.Name) if isCalepinage: - self._exportSketchCalepinage(sketchList, plateLength, plateWidth, spacing) + self.exportSketchCalepinage(sketchList, plateLength, plateWidth, spacing) else: - self._exportSketchBasic(sketchList) - - for obj in FreeCAD.ActiveDocument.Objects: - if obj.Label.endswith("-SVG") or obj.Label.endswith("-STL"): - FreeCADGui.Selection.addSelection(obj) + self.exportSketchBasic(sketchList) - def exportSTL(self, singleMode): + def exportSTL(self, singleMode, stlList): objects_to_export = [] - for obj in FreeCADGui.Selection.getSelection(): - if not obj.Label.endswith("-STL"): - continue - - count = 1 - for index in range(self.form.listWidgetSelector.count()): - item = self.form.listWidgetSelector.item(index) - widget = self.form.listWidgetSelector.itemWidget(item) - if widget.obj == obj: - count = widget.get_value() - break - - for i in range(count): + for objLabel, obj, objCount in stlList: + for i in range(objCount): clone = Draft.clone(obj) - objects_to_export.append((clone, obj.Label, i + 1)) + objects_to_export.append((clone, objLabel, i + 1)) FreeCAD.ActiveDocument.recompute() @@ -326,19 +276,38 @@ class WindowDialog(): FreeCAD.ActiveDocument.removeObject(obj.Name) FreeCAD.ActiveDocument.recompute() - for obj in FreeCAD.ActiveDocument.Objects: - if obj.Label.endswith("-SVG") or obj.Label.endswith("-STL"): - FreeCADGui.Selection.addSelection(obj) def export(self): isCalepinage = self.form.checkBoxCalepinage.isChecked() isCombine = self.form.checkBoxCombine.isChecked() - self.outputRacine = self._createFolder() + svgList = [] + stlList = [] - self.exportSVG(isCalepinage) - self.exportSTL(isCombine) + for obj in FreeCAD.ActiveDocument.Objects: + count = 1 + + for index in range(self.form.listWidgetSelector.count()): + item = self.form.listWidgetSelector.item(index) + widget = self.form.listWidgetSelector.itemWidget(item) + + if not item.isSelected(): + continue + + if widget.obj == obj: + count = widget.get_value() + if obj.Label.endswith("-SVG"): + svgList.append((obj.Label, obj, count)) + elif obj.Label.endswith("-STL"): + stlList.append((obj.Label, obj, count)) + break + + if not svgList == [] or not stlList == []: + self.outputRacine = self.createFolder() + + self.exportSVG(isCalepinage, svgList) + self.exportSTL(isCombine, stlList) def saveVarSet(self, varSetName = "TestVarSet"): @@ -360,6 +329,9 @@ class WindowDialog(): setattr(varSet, obj.Name, ("STL", str(count))) FreeCAD.ActiveDocument.recompute() + + + # def loadVarSet(self, varSetName = "TestVarSet", count = 1): if __name__ == '__main__': diff --git a/MultiExport/MultiExport.ui b/MultiExport/MultiExport.ui index 1773030..f76e2b3 100644 --- a/MultiExport/MultiExport.ui +++ b/MultiExport/MultiExport.ui @@ -45,21 +45,6 @@ - - - - 🔄 - - - - 12 - - - - Refresh - - -