diff --git a/MakeBoxPanel.py b/MakeBoxPanel.py index ab7bc6a..b7faae5 100644 --- a/MakeBoxPanel.py +++ b/MakeBoxPanel.py @@ -43,17 +43,17 @@ def __init__(self, obj): obj.addProperty("App::PropertyPythonObject", "box_properties").box_properties = BoxProperties() # supported https://www.freecadweb.org/wiki/Scripted_objects obj.addProperty("App::PropertyPythonObject", "top_properties").top_properties = TopBottomProperties() obj.addProperty("App::PropertyPythonObject", "bottom_properties").bottom_properties = TopBottomProperties() - obj.addProperty('App::PropertyPythonObject', 'recompute').recompute = False + obj.addProperty('App::PropertyPythonObject', 'need_recompute').need_recompute = False obj.addProperty('App::PropertyLinkList', 'parts').parts = [] obj.Proxy = self def onChanged(self, fp, prop): - if prop == "recompute": + if prop == "need_recompute": self.execute(fp) def execute(self, fp): - if fp.recompute: - fp.recompute = False + if fp.need_recompute: + fp.need_recompute = False document = fp.Document computed_parts = makebox.make_box(fp.box_properties, fp.top_properties, fp.bottom_properties) @@ -161,7 +161,7 @@ def reject(self): self.obj_box.box_properties = self.box_properties_origin self.obj_box.bottom_properties = self.bottom_properties_origin self.obj_box.top_properties = self.top_properties_origin - self.obj_box.recompute = True + self.obj_box.need_recompute = True return True def preview(self): @@ -169,7 +169,7 @@ def preview(self): self.dim_box_param.get_properties() self.top_box_param.get_properties() self.bottom_box_param.get_properties() - self.obj_box.recompute = True + self.obj_box.need_recompute = True class MakeBoxCommand: diff --git a/MakeRoundedBoxPanel.py b/MakeRoundedBoxPanel.py index 8e17498..390d37a 100644 --- a/MakeRoundedBoxPanel.py +++ b/MakeRoundedBoxPanel.py @@ -1,204 +1,204 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -# *************************************************************************** -# * * -# * Copyright (c) 2016 execuc * -# * * -# * This file is part of LCInterlocking module. * -# * LCInterlocking module is free software; you can redistribute it and/or* -# * modify it under the terms of the GNU Lesser General Public * -# * License as published by the Free Software Foundation; either * -# * version 2.1 of the License, or (at your option) any later version. * -# * * -# * This module 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 * -# * Lesser General Public License for more details. * -# * * -# * You should have received a copy of the GNU Lesser General Public * -# * License along with this library; if not, write to the Free Software * -# * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * -# * MA 02110-1301 USA * -# * * -# *************************************************************************** - -from FreeCAD import Gui -import FreeCAD -import FreeCADGui -import Part -import os -import math -import Draft -import copy -from panel.roundedbox import RoundedBoxProperties, TopBottomRoundedProperties, DimensionRoundedBoxParam, BottomRoundedBoxParam, TopBoxRoundedParam -from lasercut import makeroundedbox - - -__dir__ = os.path.dirname(__file__) -iconPath = os.path.join(__dir__, 'icons') -from PySide import QtCore, QtGui - - -class GroupRoundedBox: - def __init__(self, obj): - obj.addProperty("App::PropertyPythonObject", "box_properties").box_properties = RoundedBoxProperties() - obj.addProperty("App::PropertyPythonObject", "top_properties").top_properties = TopBottomRoundedProperties() - obj.addProperty("App::PropertyPythonObject", "bottom_properties").bottom_properties = TopBottomRoundedProperties() - obj.addProperty('App::PropertyPythonObject', 'recompute').recompute = False - obj.addProperty('App::PropertyLinkList', 'parts').parts= [] - obj.Proxy = self - - def onChanged(self, fp, prop): - if prop == "recompute": - self.execute(fp) - - def execute(self, fp): - if fp.recompute: - fp.recompute = False - - document = fp.Document - computed_parts = makeroundedbox.make_rounded_box(fp.box_properties, fp.top_properties, fp.bottom_properties) - - object_list = fp.parts - if len(computed_parts) != len(object_list): - for part in object_list: - document.removeObject(part.Name) - - object_list = [] - for part in computed_parts: - new_shape = document.addObject("Part::Feature", part['name']) - object_list.append(new_shape) - - for index in range(len(computed_parts)): - object_list[index].Shape = computed_parts[index]['shape'] - - fp.parts = object_list - FreeCADGui.getDocument(document.Name).ActiveView.fitAll() - document.recompute() - - -class ViewProviderGroupRoundedBox: - def __init__(self, vobj): - vobj.Proxy = self - - def setEdit(self, vobj=None, mode=0): - if mode == 0: - FreeCADGui.Control.showDialog(MakeRoundedBox(self.Object)) - return True - - def setupContextMenu(self, obj, menu): - action = menu.addAction("Edit") - action.triggered.connect(self.setEdit) - - def onChanged(self, vp, prop): - pass - - def __getstate__(self): - ''' When saving the document this object gets stored using Python's cPickle module. - Since we have some un-pickable here -- the Coin stuff -- we must define this method - to return a tuple of all pickable objects or None. - ''' - return None - - def __setstate__(self, state): - ''' When restoring the pickled object from document we have the chance to set some - internals here. Since no data were pickled nothing needs to be done here. - ''' - return None - - def attach(self, vobj): - self.ViewObject = vobj - self.Object = vobj.Object - - def claimChildren(self): - return self.Object.parts - - - -class MakeRoundedBox: - - def __init__(self, obj_box): - self.form = [] - self.main_widget = QtGui.QWidget() - self.main_widget.setWindowTitle("Make rounded box") - self.parts_vbox = QtGui.QGridLayout(self.main_widget) - self.form.append(self.main_widget) - - self.preview_button = QtGui.QPushButton('Preview', self.main_widget) - self.parts_vbox.addWidget(self.preview_button, 0, 0, 1, 2) - self.preview_button.clicked.connect(self.preview) - - self.obj_box = obj_box - self.box_properties_origin = copy.deepcopy(self.obj_box.box_properties) - self.bottom_properties_origin = copy.deepcopy(self.obj_box.bottom_properties) - self.top_properties_origin = copy.deepcopy(self.obj_box.top_properties) - - self.box_properties = DimensionRoundedBoxParam(self.obj_box.box_properties) - self.bottom_box_param = BottomRoundedBoxParam(self.obj_box.bottom_properties) - self.top_box_param = TopBoxRoundedParam(self.obj_box.top_properties) - - self.param_widget = QtGui.QWidget() - self.param_widget.setWindowTitle("Parameters") - self.form.append(self.param_widget) - self.params_vlayout = QtGui.QVBoxLayout(self.param_widget) - - dim_group_box, grid = self.box_properties.get_group_box(self.param_widget) - top_group_box, grid = self.top_box_param.get_group_box(self.param_widget) - bottom_group_box, grid = self.bottom_box_param.get_group_box(self.param_widget) - - self.params_vlayout.addWidget(dim_group_box) - self.params_vlayout.addWidget(top_group_box) - self.params_vlayout.addWidget(bottom_group_box) - - radius_widget = self.box_properties.get_widget("inradius") - radius_widget.valueChanged.connect(self.preview) - nb_face_widget = self.box_properties.get_widget("nb_face") - nb_face_widget.valueChanged.connect(self.preview) - - self.actual_parts = [] - self.document = FreeCAD.ActiveDocument - self.preview() - return - - def accept(self): - self.preview() - return True - - def reject(self): - self.obj_box.box_properties = self.box_properties_origin - self.obj_box.bottom_properties = self.bottom_properties_origin - self.obj_box.top_properties = self.top_properties_origin - self.obj_box.recompute = True - return True - - def preview(self): - self.box_properties.get_properties().compute_information() - self.box_properties.update_information() - self.bottom_box_param.get_properties() - self.top_box_param.get_properties() - self.obj_box.recompute = True - - -class MakeRoundedBoxCommand: - - def __init__(self): - return - - def GetResources(self): - return {'Pixmap': os.path.join(iconPath, 'roundbox.xpm'), # the name of a svg file available in the resources - 'MenuText': "Rounded box", - 'ToolTip': "Make rounded box without tab"} - - def IsActive(self): - return FreeCAD.ActiveDocument is not None - - def Activated(self): - groupRoundedBox = FreeCAD.ActiveDocument.addObject("Part::FeaturePython", "RoundedBox") - GroupRoundedBox(groupRoundedBox) - vp = ViewProviderGroupRoundedBox(groupRoundedBox.ViewObject) - vp.setEdit(ViewProviderGroupRoundedBox) - return - - -Gui.addCommand('make_rounded_box_command', MakeRoundedBoxCommand()) +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# *************************************************************************** +# * * +# * Copyright (c) 2016 execuc * +# * * +# * This file is part of LCInterlocking module. * +# * LCInterlocking module is free software; you can redistribute it and/or* +# * modify it under the terms of the GNU Lesser General Public * +# * License as published by the Free Software Foundation; either * +# * version 2.1 of the License, or (at your option) any later version. * +# * * +# * This module 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 * +# * Lesser General Public License for more details. * +# * * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with this library; if not, write to the Free Software * +# * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * +# * MA 02110-1301 USA * +# * * +# *************************************************************************** + +from FreeCAD import Gui +import FreeCAD +import FreeCADGui +import Part +import os +import math +import Draft +import copy +from panel.roundedbox import RoundedBoxProperties, TopBottomRoundedProperties, DimensionRoundedBoxParam, BottomRoundedBoxParam, TopBoxRoundedParam +from lasercut import makeroundedbox + + +__dir__ = os.path.dirname(__file__) +iconPath = os.path.join(__dir__, 'icons') +from PySide import QtCore, QtGui + + +class GroupRoundedBox: + def __init__(self, obj): + obj.addProperty("App::PropertyPythonObject", "box_properties").box_properties = RoundedBoxProperties() + obj.addProperty("App::PropertyPythonObject", "top_properties").top_properties = TopBottomRoundedProperties() + obj.addProperty("App::PropertyPythonObject", "bottom_properties").bottom_properties = TopBottomRoundedProperties() + obj.addProperty('App::PropertyPythonObject', 'need_recompute').need_recompute = False + obj.addProperty('App::PropertyLinkList', 'parts').parts= [] + obj.Proxy = self + + def onChanged(self, fp, prop): + if prop == "need_recompute": + self.execute(fp) + + def execute(self, fp): + if fp.need_recompute: + fp.need_recompute = False + + document = fp.Document + computed_parts = makeroundedbox.make_rounded_box(fp.box_properties, fp.top_properties, fp.bottom_properties) + + object_list = fp.parts + if len(computed_parts) != len(object_list): + for part in object_list: + document.removeObject(part.Name) + + object_list = [] + for part in computed_parts: + new_shape = document.addObject("Part::Feature", part['name']) + object_list.append(new_shape) + + for index in range(len(computed_parts)): + object_list[index].Shape = computed_parts[index]['shape'] + + fp.parts = object_list + FreeCADGui.getDocument(document.Name).ActiveView.fitAll() + document.recompute() + + +class ViewProviderGroupRoundedBox: + def __init__(self, vobj): + vobj.Proxy = self + + def setEdit(self, vobj=None, mode=0): + if mode == 0: + FreeCADGui.Control.showDialog(MakeRoundedBox(self.Object)) + return True + + def setupContextMenu(self, obj, menu): + action = menu.addAction("Edit") + action.triggered.connect(self.setEdit) + + def onChanged(self, vp, prop): + pass + + def __getstate__(self): + ''' When saving the document this object gets stored using Python's cPickle module. + Since we have some un-pickable here -- the Coin stuff -- we must define this method + to return a tuple of all pickable objects or None. + ''' + return None + + def __setstate__(self, state): + ''' When restoring the pickled object from document we have the chance to set some + internals here. Since no data were pickled nothing needs to be done here. + ''' + return None + + def attach(self, vobj): + self.ViewObject = vobj + self.Object = vobj.Object + + def claimChildren(self): + return self.Object.parts + + + +class MakeRoundedBox: + + def __init__(self, obj_box): + self.form = [] + self.main_widget = QtGui.QWidget() + self.main_widget.setWindowTitle("Make rounded box") + self.parts_vbox = QtGui.QGridLayout(self.main_widget) + self.form.append(self.main_widget) + + self.preview_button = QtGui.QPushButton('Preview', self.main_widget) + self.parts_vbox.addWidget(self.preview_button, 0, 0, 1, 2) + self.preview_button.clicked.connect(self.preview) + + self.obj_box = obj_box + self.box_properties_origin = copy.deepcopy(self.obj_box.box_properties) + self.bottom_properties_origin = copy.deepcopy(self.obj_box.bottom_properties) + self.top_properties_origin = copy.deepcopy(self.obj_box.top_properties) + + self.box_properties = DimensionRoundedBoxParam(self.obj_box.box_properties) + self.bottom_box_param = BottomRoundedBoxParam(self.obj_box.bottom_properties) + self.top_box_param = TopBoxRoundedParam(self.obj_box.top_properties) + + self.param_widget = QtGui.QWidget() + self.param_widget.setWindowTitle("Parameters") + self.form.append(self.param_widget) + self.params_vlayout = QtGui.QVBoxLayout(self.param_widget) + + dim_group_box, grid = self.box_properties.get_group_box(self.param_widget) + top_group_box, grid = self.top_box_param.get_group_box(self.param_widget) + bottom_group_box, grid = self.bottom_box_param.get_group_box(self.param_widget) + + self.params_vlayout.addWidget(dim_group_box) + self.params_vlayout.addWidget(top_group_box) + self.params_vlayout.addWidget(bottom_group_box) + + radius_widget = self.box_properties.get_widget("inradius") + radius_widget.valueChanged.connect(self.preview) + nb_face_widget = self.box_properties.get_widget("nb_face") + nb_face_widget.valueChanged.connect(self.preview) + + self.actual_parts = [] + self.document = FreeCAD.ActiveDocument + self.preview() + return + + def accept(self): + self.preview() + return True + + def reject(self): + self.obj_box.box_properties = self.box_properties_origin + self.obj_box.bottom_properties = self.bottom_properties_origin + self.obj_box.top_properties = self.top_properties_origin + self.obj_box.need_recompute = True + return True + + def preview(self): + self.box_properties.get_properties().compute_information() + self.box_properties.update_information() + self.bottom_box_param.get_properties() + self.top_box_param.get_properties() + self.obj_box.need_recompute = True + + +class MakeRoundedBoxCommand: + + def __init__(self): + return + + def GetResources(self): + return {'Pixmap': os.path.join(iconPath, 'roundbox.xpm'), # the name of a svg file available in the resources + 'MenuText': "Rounded box", + 'ToolTip': "Make rounded box without tab"} + + def IsActive(self): + return FreeCAD.ActiveDocument is not None + + def Activated(self): + groupRoundedBox = FreeCAD.ActiveDocument.addObject("Part::FeaturePython", "RoundedBox") + GroupRoundedBox(groupRoundedBox) + vp = ViewProviderGroupRoundedBox(groupRoundedBox.ViewObject) + vp.setEdit(ViewProviderGroupRoundedBox) + return + + +Gui.addCommand('make_rounded_box_command', MakeRoundedBoxCommand()) diff --git a/README.md b/README.md index 2ac7112..507de75 100644 --- a/README.md +++ b/README.md @@ -62,7 +62,10 @@ If you encounter a bug please participate in the [dedicated FreeCAD discussion t * Rounded corner: https://www.youtube.com/watch?v=KSnMxqjA_-Q ## Changelog -**v1.3: In progress** +**v1.4: In progress** + * Fix for FreeCAD 0.19. + +**v1.3:** * Fix tab link widget not displayed. **v1.2:** diff --git a/panel/crosspiece.py b/panel/crosspiece.py index 4e39282..98363fc 100644 --- a/panel/crosspiece.py +++ b/panel/crosspiece.py @@ -41,7 +41,7 @@ class CrossPieceGroup: def __init__(self, obj): obj.addProperty('App::PropertyPythonObject', 'parts').parts = PropertiesList() - obj.addProperty('App::PropertyPythonObject', 'recompute').recompute = False + obj.addProperty('App::PropertyPythonObject', 'need_recompute').need_recompute = False obj.addProperty('App::PropertyPythonObject', 'preview').preview = PREVIEW_NONE obj.addProperty('App::PropertyLinkList', 'generatedParts').generatedParts = [] obj.addProperty('App::PropertyLinkList', 'fromParts').fromParts = [] @@ -50,7 +50,7 @@ def __init__(self, obj): obj.Proxy = self def onChanged(self, fp, prop): - if prop == "recompute": + if prop == "need_recompute": self.execute(fp) elif prop == "preview": self.preview(fp) @@ -107,8 +107,8 @@ def preview(self, fp): def execute(self, fp): - if fp.recompute: - fp.recompute = False + if fp.need_recompute: + fp.need_recompute = False document = fp.Document if len(fp.fromParts) > 0: @@ -221,7 +221,7 @@ def compute(self, preview): self.save_items_properties() self.save_link_properties() if not preview: - self.obj_join.recompute = True + self.obj_join.need_recompute = True else: self.obj_join.preview = PREVIEW_NORMAL diff --git a/panel/livinghinge.py b/panel/livinghinge.py index 398be18..78f4752 100644 --- a/panel/livinghinge.py +++ b/panel/livinghinge.py @@ -107,7 +107,7 @@ def compute_parts(self): for conn in self.connection_widget_list: conn.get_properties() - self.obj.recompute = True + self.obj.need_recompute = True def create_object(self, document, flat_part, solid_part): if self.global_properties_widget.get_properties().generate_solid is True: @@ -183,18 +183,18 @@ class LivingHinges: def __init__(self, obj, freecad_obj): obj.addProperty('App::PropertyPythonObject', 'globalProperties').globalProperties = GlobalLivingMaterialProperties(freecad_object=freecad_obj) obj.addProperty('App::PropertyPythonObject', 'hinges').hinges = PropertiesList() - obj.addProperty('App::PropertyPythonObject', 'recompute').recompute = False + obj.addProperty('App::PropertyPythonObject', 'need_recompute').need_recompute = False obj.addProperty('App::PropertyLink', 'solid').solid = None obj.addProperty('App::PropertyLink', 'obj').obj = None obj.Proxy = self def onChanged(self, fp, prop): - if prop == "recompute": + if prop == "need_recompute": self.execute(fp) def execute(self, fp): - if fp.recompute: - fp.recompute = False + if fp.need_recompute: + fp.need_recompute = False document = fp.Document diff --git a/panel/multiplejoins.py b/panel/multiplejoins.py index 9303d20..cc97b18 100644 --- a/panel/multiplejoins.py +++ b/panel/multiplejoins.py @@ -41,7 +41,7 @@ class MultipleJoinGroup: def __init__(self, obj): obj.addProperty('App::PropertyPythonObject', 'parts').parts = PropertiesList() obj.addProperty('App::PropertyPythonObject', 'faces').faces = PropertiesList() - obj.addProperty('App::PropertyPythonObject', 'recompute').recompute = False + obj.addProperty('App::PropertyPythonObject', 'need_recompute').need_recompute = False obj.addProperty('App::PropertyPythonObject', 'preview').preview = PREVIEW_NONE obj.addProperty('App::PropertyLinkList', 'generatedParts').generatedParts = [] obj.addProperty('App::PropertyLinkList', 'fromParts').fromParts = [] @@ -50,7 +50,7 @@ def __init__(self, obj): obj.Proxy = self def onChanged(self, fp, prop): - if prop == "recompute": + if prop == "need_recompute": self.execute(fp) elif prop == "preview": self.preview(fp) @@ -117,8 +117,8 @@ def preview(self, fp): def execute(self, fp): - if fp.recompute: - fp.recompute = False + if fp.need_recompute: + fp.need_recompute = False document = fp.Document if len(fp.fromParts) > 0: @@ -247,7 +247,7 @@ def compute(self, preview, fast=False): self.save_items_properties() self.save_link_properties() if not preview: - self.obj_join.recompute = True + self.obj_join.need_recompute = True elif not fast: self.obj_join.preview = PREVIEW_NORMAL else: diff --git a/panel/treepanel.py b/panel/treepanel.py index 586b035..38533b7 100644 --- a/panel/treepanel.py +++ b/panel/treepanel.py @@ -28,6 +28,11 @@ from FreeCAD import Gui import os, copy from PySide import QtCore, QtGui +try: + from PySide.QtGui import QItemSelectionModel +except ImportError: + from PySide.QtCore import QItemSelectionModel + from panel.partmat import PartsList, CrossPartWidget, Part from panel.tab import TabsList from panel import selection @@ -277,7 +282,7 @@ def add_same_tabs(self): def force_selection(self, index): self.selection_model.clearSelection() - self.selection_model.select(index, QtGui.QItemSelectionModel.ClearAndSelect | QtGui.QItemSelectionModel.Rows) + self.selection_model.select(index, QItemSelectionModel.ClearAndSelect | QItemSelectionModel.Rows) def selection_changed(self, selected, deselected): FreeCADGui.Selection.clearSelection()