big updates on UI and macro

This commit is contained in:
Thomas-Alexandre Moreau 2025-04-23 15:26:41 +02:00
parent f6e39d597a
commit f847a7c91b
2 changed files with 228 additions and 203 deletions

View file

@ -5,6 +5,7 @@ import Draft
import os import os
import Mesh import Mesh
from PySide2.QtWidgets import QWidget, QLabel, QSpinBox, QHBoxLayout, QListWidgetItem from PySide2.QtWidgets import QWidget, QLabel, QSpinBox, QHBoxLayout, QListWidgetItem
from datetime import datetime
class ObjectListItem(QWidget): class ObjectListItem(QWidget):
@ -34,18 +35,21 @@ class WindowDialog():
self.form = FreeCADGui.PySideUic.loadUi(self.ui_file) self.form = FreeCADGui.PySideUic.loadUi(self.ui_file)
self._connect_widgets() self._connect_widgets()
self._populate_selector_list() 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() self.form.show()
def _connect_widgets(self):
self.form.pushButtonSVG.pressed.connect(lambda: self.exportSVG(False))
self.form.pushButtonCalepinage.pressed.connect(lambda: self.exportSVG(True))
self.form.pushButtonSTLSingle.pressed.connect(lambda: self.exportSTL(True))
self.form.pushButtonSTLMulti.pressed.connect(lambda: self.exportSTL(False))
self.form.listWidgetSelector.itemSelectionChanged.connect(self._on_selector_item_changed)
def _connect_widgets(self):
self.form.pushButtonExport.pressed.connect(self.export)
self.form.listWidgetSelector.itemClicked.connect(self._on_list_item_clicked)
def _populate_selector_list(self): def _populate_selector_list(self):
self.form.listWidgetSelector.clear() self.form.listWidgetSelector.clear()
FreeCADGui.Selection.clearSelection()
for obj in FreeCAD.ActiveDocument.Objects: for obj in FreeCAD.ActiveDocument.Objects:
if obj.Label.startswith("SVG-") or obj.Label.startswith("STL-"): if obj.Label.startswith("SVG-") or obj.Label.startswith("STL-"):
item = QListWidgetItem() item = QListWidgetItem()
@ -55,19 +59,39 @@ class WindowDialog():
self.form.listWidgetSelector.addItem(item) self.form.listWidgetSelector.addItem(item)
self.form.listWidgetSelector.setItemWidget(item, widget) self.form.listWidgetSelector.setItemWidget(item, widget)
def _on_selector_item_changed(self): # Sync selection: add the object to the selection and select the item in the list
self.selectedItems = [] item.setSelected(True)
FreeCADGui.Selection.clearSelection() 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):
# Clear current selection in the list
for index in range(self.form.listWidgetSelector.count()): for index in range(self.form.listWidgetSelector.count()):
item = self.form.listWidgetSelector.item(index) item = self.form.listWidgetSelector.item(index)
widget = self.form.listWidgetSelector.itemWidget(item) widget = self.form.listWidgetSelector.itemWidget(item)
if item.isSelected(): item.setSelected(False) # Deselect in the list
FreeCADGui.Selection.addSelection(widget.obj)
self.selectedItems.append((widget.obj, widget.get_value())) # 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
break
def _createFolder(self): def _createFolder(self):
folderPath = f"{FreeCAD.activeDocument().getFileName().rpartition('.')[0]}-Exports/" folderPath = f"{FreeCAD.activeDocument().getFileName().rpartition('.')[0]}-{datetime.today().strftime('%Y-%m-%d')}-Exports/"
if not os.path.exists(folderPath): if not os.path.exists(folderPath):
os.makedirs(folderPath) os.makedirs(folderPath)
@ -184,16 +208,20 @@ class WindowDialog():
spacing = self.form.doubleSpinBoxSpacing.value() spacing = self.form.doubleSpinBoxSpacing.value()
sketchList = [] sketchList = []
# Loop over all selected items in list widget, not GUI selection for obj in FreeCADGui.Selection.getSelection():
if not obj.Label.startswith("SVG-"):
continue
count = 1 # default if not using spinboxes (or fetch from list if desired)
# Optional: match count from list
for index in range(self.form.listWidgetSelector.count()): for index in range(self.form.listWidgetSelector.count()):
item = self.form.listWidgetSelector.item(index) item = self.form.listWidgetSelector.item(index)
widget = self.form.listWidgetSelector.itemWidget(item) widget = self.form.listWidgetSelector.itemWidget(item)
if item.isSelected(): if widget.obj == obj:
count = widget.get_value() count = widget.get_value()
obj = widget.obj break
for _ in range(count): for _ in range(count):
# Create 2D view and sketch for each instance
if hasattr(obj, 'Dir'): if hasattr(obj, 'Dir'):
sv0 = Draft.make_shape2dview(obj, FreeCAD.Vector(obj.Dir)) sv0 = Draft.make_shape2dview(obj, FreeCAD.Vector(obj.Dir))
elif hasattr(obj, 'Objects'): elif hasattr(obj, 'Objects'):
@ -216,19 +244,25 @@ class WindowDialog():
else: else:
self._exportSketchBasic(sketchList) self._exportSketchBasic(sketchList)
FreeCADGui.Selection.clearSelection()
self._populate_selector_list() self._populate_selector_list()
def exportSTL(self, singleMode): def exportSTL(self, singleMode):
objects_to_export = [] objects_to_export = []
for obj in FreeCADGui.Selection.getSelection():
if not obj.Label.startswith("STL-"):
continue
count = 1
for index in range(self.form.listWidgetSelector.count()): for index in range(self.form.listWidgetSelector.count()):
item = self.form.listWidgetSelector.item(index) item = self.form.listWidgetSelector.item(index)
widget = self.form.listWidgetSelector.itemWidget(item) widget = self.form.listWidgetSelector.itemWidget(item)
if item.isSelected(): if widget.obj == obj:
count = widget.get_value() count = widget.get_value()
obj = widget.obj break
for i in range(count): for i in range(count):
clone = Draft.clone(obj) clone = Draft.clone(obj)
objects_to_export.append((clone, obj.Label, i + 1)) objects_to_export.append((clone, obj.Label, i + 1))
@ -242,7 +276,6 @@ class WindowDialog():
print(f"Exported STL: {filename}") print(f"Exported STL: {filename}")
FreeCAD.ActiveDocument.removeObject(obj.Name) FreeCAD.ActiveDocument.removeObject(obj.Name)
else: else:
# Combine all into one STL
export_objs = [obj for obj, _, _ in objects_to_export] export_objs = [obj for obj, _, _ in objects_to_export]
if export_objs: if export_objs:
label = FreeCAD.activeDocument().Name label = FreeCAD.activeDocument().Name
@ -253,12 +286,19 @@ class WindowDialog():
FreeCAD.ActiveDocument.removeObject(obj.Name) FreeCAD.ActiveDocument.removeObject(obj.Name)
FreeCAD.ActiveDocument.recompute() FreeCAD.ActiveDocument.recompute()
FreeCADGui.Selection.clearSelection()
self._populate_selector_list() self._populate_selector_list()
def export(self):
isCalepinage = self.form.checkBoxCalepinage.isChecked()
isCombine = self.form.checkBoxCombine.isChecked()
self.exportSVG(isCalepinage)
self.exportSTL(isCombine)
if __name__ == '__main__': if __name__ == '__main__':
try: try:
WindowDialog() mainWindow = WindowDialog()
except Exception as e: except Exception as e:
print(e) print(e)

View file

@ -9,31 +9,49 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>600</width> <width>500</width>
<height>500</height> <height>400</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
<string notr="true">Multi Exporting</string> <string notr="true">Multi Export</string>
</property> </property>
<layout class="QGridLayout" name="gridLayout"> <layout class="QGridLayout" name="gridLayout">
<item row="10" column="0" colspan="3"> <item row="0" column="0" colspan="3">
<widget class="QListWidget" name="listWidgetSelector"> <widget class="QListWidget" name="listWidgetSelector">
<property name="selectionMode"> <property name="selectionMode">
<enum>QAbstractItemView::MultiSelection</enum> <enum>QAbstractItemView::MultiSelection</enum>
</property> </property>
</widget> </widget>
</item> </item>
<item row="16" column="0" colspan="3"> <item row="1" column="0">
<widget class="QTabWidget" name="tabWidget"> <spacer name="verticalSpacer1">
<property name="currentIndex"> <property name="orientation">
<number>0</number> <enum>Qt::Vertical</enum>
</property> </property>
<widget class="QWidget" name="tab"> <property name="sizeHint" stdset="0">
<attribute name="title"> <size>
<string notr="true">Exportation SVG</string> <width>20</width>
</attribute> <height>40</height>
<layout class="QGridLayout" name="gridLayout_4"> </size>
</property>
</spacer>
</item>
<item row="2" column="0" colspan="2">
<widget class="QLabel" name="labelDecoupe">
<property name="text">
<string notr="true">Dimensions du plateau de découpe</string>
</property>
<property name="font">
<font>
<pointsize>12</pointsize>
</font>
</property>
</widget>
</item>
<item row="3" column="0" colspan="2">
<widget class="QWidget" name="containerWidget">
<layout class="QGridLayout" name="gridLayout2">
<item row="0" column="0"> <item row="0" column="0">
<widget class="QLabel" name="label"> <widget class="QLabel" name="label">
<property name="locale"> <property name="locale">
@ -88,8 +106,8 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="4" column="0"> <item row="3" column="0">
<spacer name="verticalSpacer"> <spacer name="verticalSpacer2">
<property name="orientation"> <property name="orientation">
<enum>Qt::Vertical</enum> <enum>Qt::Vertical</enum>
</property> </property>
@ -101,67 +119,28 @@
</property> </property>
</spacer> </spacer>
</item> </item>
<item row="4" column="0">
<widget class="QCheckBox" name="checkBoxCalepinage">
<property name="text">
<string notr="true">SVG : Calepinage</string>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
<item row="5" column="0"> <item row="5" column="0">
<widget class="QPushButton" name="pushButtonCalepinage"> <widget class="QCheckBox" name="checkBoxCombine">
<property name="text"> <property name="text">
<string>Export en .svg (calepinage)</string> <string notr="true">STL : Combiné</string>
</property> </property>
<property name="minimumSize"> <property name="checked">
<size> <bool>false</bool>
<width>0</width>
<height>50</height>
</size>
</property> </property>
</widget> </widget>
</item> </item>
<item row="5" column="1"> <item row="5" column="0">
<widget class="QPushButton" name="pushButtonSVG"> <spacer name="verticalSpacer3">
<property name="text">
<string>Export en .svg (sans calepinage)</string>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>50</height>
</size>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="tab_2">
<attribute name="title">
<string notr="true">Exportation STL</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_2">
<item row="1" column="0">
<widget class="QPushButton" name="pushButtonSTLSingle">
<property name="text">
<string>Export en .stl (combiné)</string>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>50</height>
</size>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="pushButtonSTLMulti">
<property name="text">
<string>Export en .stl (séparé)</string>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>50</height>
</size>
</property>
</widget>
</item>
<item row="0" column="0">
<spacer name="verticalSpacer">
<property name="orientation"> <property name="orientation">
<enum>Qt::Vertical</enum> <enum>Qt::Vertical</enum>
</property> </property>
@ -173,8 +152,14 @@
</property> </property>
</spacer> </spacer>
</item> </item>
</layout> <item row="6" column="1" colspan="2">
<widget class="QPushButton" name="pushButtonExport">
<property name="text">
<string notr="true">Exporter</string>
</property>
</widget> </widget>
</item>
</layout>
</widget> </widget>
</item> </item>
</layout> </layout>