| | |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | """Provides the viewprovider code for the base Draft object. |
| | |
| | Many viewprovider classes may inherit this class in order to have |
| | the same basic behavior.""" |
| | |
| | |
| | |
| |
|
| | |
| | |
| | import PySide.QtCore as QtCore |
| | import PySide.QtGui as QtGui |
| | from PySide.QtCore import QT_TRANSLATE_NOOP |
| |
|
| | import FreeCAD as App |
| | from draftutils import gui_utils |
| | from draftutils import params |
| | from draftutils import utils |
| | from draftutils.translate import translate |
| |
|
| | if App.GuiUp: |
| | from pivy import coin |
| | import FreeCADGui as Gui |
| | import Draft_rc |
| |
|
| | |
| | bool(Draft_rc.__name__) |
| |
|
| |
|
| | class ViewProviderDraft(object): |
| | """The base class for Draft view providers. |
| | |
| | Parameters |
| | ---------- |
| | vobj : a base C++ view provider |
| | The view provider of the scripted object (`obj.ViewObject`), |
| | which commonly may be of types `PartGui::ViewProvider2DObjectPython`, |
| | `PartGui::ViewProviderPython`, or `Gui::ViewProviderFeaturePython`. |
| | |
| | A basic view provider is instantiated during the creation |
| | of the base C++ object, for example, |
| | `Part::Part2DObjectPython`, `Part::FeaturePython`, |
| | or `App::FeaturePython`. |
| | |
| | >>> obj = App.ActiveDocument.addObject('Part::Part2DObjectPython') |
| | >>> vobj = obj.ViewObject |
| | >>> ViewProviderDraft(vobj) |
| | |
| | This view provider class instance is stored in the `Proxy` attribute |
| | of the base view provider. |
| | :: |
| | vobj.Proxy = self |
| | |
| | Attributes |
| | ---------- |
| | Object : the base C++ object |
| | The scripted document object that is associated |
| | with this view provider, which commonly may be of types |
| | `Part::Part2DObjectPython`, `Part::FeaturePython`, |
| | or `App::FeaturePython`. |
| | |
| | texture : coin.SoTexture2 |
| | A texture that could be added to this object. |
| | |
| | texcoords : coin.SoTextureCoordinatePlane |
| | The coordinates defining a plane to use for aligning the texture. |
| | |
| | These class attributes are accessible through the `Proxy` object: |
| | `vobj.Proxy.Object`, `vobj.Proxy.texture`, etc. |
| | """ |
| |
|
| | def __init__(self, vobj): |
| | self.Object = vobj.Object |
| | self.texture = None |
| | self.texcoords = None |
| |
|
| | self._set_properties(vobj) |
| | |
| | vobj.Proxy = self |
| |
|
| | def _set_properties(self, vobj): |
| | """Set the properties of objects if they don't exist.""" |
| | if not hasattr(vobj, "Pattern"): |
| | vobj.addProperty( |
| | "App::PropertyEnumeration", |
| | "Pattern", |
| | "Draft", |
| | QT_TRANSLATE_NOOP("App::Property", "Defines an SVG pattern."), |
| | locked=True, |
| | ) |
| | patterns = list(utils.svg_patterns()) |
| | patterns.sort() |
| | vobj.Pattern = ["None"] + patterns |
| |
|
| | if not hasattr(vobj, "PatternSize"): |
| | vobj.addProperty( |
| | "App::PropertyFloat", |
| | "PatternSize", |
| | "Draft", |
| | QT_TRANSLATE_NOOP("App::Property", "Defines the size of the SVG pattern."), |
| | locked=True, |
| | ) |
| | vobj.PatternSize = params.get_param("HatchPatternSize") |
| |
|
| | def dumps(self): |
| | """Return a tuple of all serializable objects or None. |
| | |
| | When saving the document this view provider object gets stored |
| | using Python's `json` module. |
| | |
| | Since we have some un-serializable objects (Coin objects) in here |
| | we must define this method to return a tuple of all serializable |
| | objects or `None`. |
| | |
| | Override this method to define the serializable objects to return. |
| | |
| | By default it returns `None`. |
| | |
| | Returns |
| | ------- |
| | None |
| | """ |
| | return None |
| |
|
| | def loads(self, state): |
| | """Set some internal properties for all restored objects. |
| | |
| | When a document is restored this method is used to set some properties |
| | for the objects stored with `json`. |
| | |
| | Override this method to define the properties to change for the |
| | restored serialized objects. |
| | |
| | By default no objects were serialized with `dumps`, |
| | so nothing needs to be done here, and it returns `None`. |
| | |
| | Parameters |
| | ---------- |
| | state : state |
| | A serialized object. |
| | |
| | Returns |
| | ------- |
| | None |
| | """ |
| | return None |
| |
|
| | def attach(self, vobj): |
| | """Set up the scene sub-graph of the view provider. |
| | |
| | This method should always be defined, even if it does nothing. |
| | |
| | Override this method to set up a custom scene. |
| | |
| | Parameters |
| | ---------- |
| | vobj : the view provider of the scripted object. |
| | This is `obj.ViewObject`. |
| | """ |
| | self.texture = None |
| | self.texcoords = None |
| | self.Object = vobj.Object |
| | self.onChanged(vobj, "Pattern") |
| | return |
| |
|
| | def updateData(self, obj, prop): |
| | """Run when an object property is changed. |
| | |
| | Override this method to handle the behavior of the view provider |
| | depending on changes that occur to the real object's properties. |
| | |
| | By default, no property is tested, and it does nothing. |
| | |
| | Parameters |
| | ---------- |
| | obj : the base C++ object |
| | The scripted document object that is associated |
| | with this view provider, which commonly may be of types |
| | `Part::Part2DObjectPython`, `Part::FeaturePython`, |
| | or `App::FeaturePython`. |
| | |
| | prop : str |
| | Name of the property that was modified. |
| | """ |
| | return |
| |
|
| | def getDisplayModes(self, vobj): |
| | """Return a list of display modes. |
| | |
| | Override this method to return a list of strings with |
| | display mode styles, such as `'Flat Lines'`, `'Shaded'`, |
| | `'Wireframe'`, `'Points'`. |
| | |
| | By default it returns an empty list. |
| | |
| | Parameters |
| | ---------- |
| | vobj : the view provider of the scripted object. |
| | This is `obj.ViewObject`. |
| | |
| | Returns |
| | ------- |
| | list |
| | Empty list `[ ]` |
| | """ |
| | modes = [] |
| | return modes |
| |
|
| | def getDefaultDisplayMode(self): |
| | """Return the default mode defined in getDisplayModes. |
| | |
| | Override this method to return a string with the default display mode. |
| | |
| | By default it returns `'Flat Lines'`. |
| | |
| | Returns |
| | ------- |
| | str |
| | `'Flat Lines'` |
| | |
| | """ |
| | return "Flat Lines" |
| |
|
| | def setDisplayMode(self, mode): |
| | """Map the modes defined in attach with those in getDisplayModes. |
| | |
| | This method is optional. |
| | |
| | By default since they have the same names nothing needs to be done, |
| | and it just returns the input `mode`. |
| | |
| | Parameters |
| | ---------- |
| | str |
| | A string defining a display mode such as |
| | `'Flat Lines'`, `'Shaded'`, `'Wireframe'`, `'Points'`. |
| | """ |
| | return mode |
| |
|
| | def onChanged(self, vobj, prop): |
| | """Run when a view property is changed. |
| | |
| | Override this method to handle the behavior |
| | of the view provider depending on changes that occur to its properties |
| | such as line color, line width, point color, point size, |
| | draw style, shape color, transparency, and others. |
| | |
| | This method updates the texture and pattern if |
| | the properties `TextureImage`, `Pattern`, `ShapeAppearance`, |
| | and `PatternSize` change. |
| | |
| | Parameters |
| | ---------- |
| | vobj : the view provider of the scripted object. |
| | This is `obj.ViewObject`. |
| | |
| | prop : str |
| | Name of the property that was modified. |
| | """ |
| | |
| | if prop in ("TextureImage", "Pattern", "ShapeAppearance"): |
| | if hasattr(self.Object, "Shape") and self.Object.Shape.Faces: |
| | path = None |
| | if hasattr(vobj, "TextureImage"): |
| | if vobj.TextureImage: |
| | path = vobj.TextureImage |
| | if not path: |
| | if hasattr(vobj, "Pattern"): |
| | if str(vobj.Pattern) in utils.svg_patterns(): |
| | path = utils.svg_patterns()[vobj.Pattern][1] |
| | else: |
| | path = "None" |
| | if path and vobj.RootNode: |
| | switch = gui_utils.find_coin_node(vobj.RootNode, coin.SoSwitch) |
| | if switch is not None and switch.getChildren().getLength() > 0: |
| | flat_lines_node = switch.getChild(0) |
| | |
| | |
| | shaded_node = gui_utils.find_coin_node_by_name(flat_lines_node, "FlatRoot") |
| | if shaded_node is not None: |
| | i = QtCore.QFileInfo(path) |
| | if self.texture: |
| | shaded_node.removeChild(self.texture) |
| | self.texture = None |
| | if self.texcoords: |
| | shaded_node.removeChild(self.texcoords) |
| | self.texcoords = None |
| | if i.exists(): |
| | size = None |
| | if ".SVG" in path.upper(): |
| | size = params.get_param("HatchPatternResolution") |
| | if not size: |
| | size = 128 |
| | im = gui_utils.load_texture(path, size) |
| | if im: |
| | self.texture = coin.SoTexture2() |
| | self.texture.image = im |
| | shaded_node.insertChild(self.texture, 1) |
| | if size: |
| | s = 1 |
| | if hasattr(vobj, "PatternSize"): |
| | if vobj.PatternSize: |
| | s = vobj.PatternSize |
| | self.texcoords = coin.SoTextureCoordinatePlane() |
| | self.texcoords.directionS.setValue(s, 0, 0) |
| | self.texcoords.directionT.setValue(0, s, 0) |
| | shaded_node.insertChild(self.texcoords, 2) |
| | elif prop == "PatternSize": |
| | if hasattr(self, "texcoords"): |
| | if self.texcoords: |
| | s = 1 |
| | if vobj.PatternSize: |
| | s = vobj.PatternSize |
| | vS = App.Vector(self.texcoords.directionS.getValue().getValue()) |
| | vT = App.Vector(self.texcoords.directionT.getValue().getValue()) |
| | vS.Length = s |
| | vT.Length = s |
| | self.texcoords.directionS.setValue(vS.x, vS.y, vS.z) |
| | self.texcoords.directionT.setValue(vT.x, vT.y, vT.z) |
| | return |
| |
|
| | def _update_pattern_size(self, vobj): |
| | """Update the pattern size. Helper method in onChanged.""" |
| | if hasattr(self, "texcoords") and self.texcoords: |
| | s = 1 |
| | if vobj.PatternSize: |
| | s = vobj.PatternSize |
| | vS = App.Vector(self.texcoords.directionS.getValue().getValue()) |
| | vT = App.Vector(self.texcoords.directionT.getValue().getValue()) |
| | vS.Length = s |
| | vT.Length = s |
| | self.texcoords.directionS.setValue(vS.x, vS.y, vS.z) |
| | self.texcoords.directionT.setValue(vT.x, vT.y, vT.z) |
| |
|
| | def execute(self, vobj): |
| | """Run when the object is created or recomputed. |
| | |
| | Override this method to produce effects when the object |
| | is newly created, and whenever the document is recomputed. |
| | |
| | By default it does nothing. |
| | |
| | Parameters |
| | ---------- |
| | vobj : the view provider of the scripted object. |
| | This is `obj.ViewObject`. |
| | """ |
| | return |
| |
|
| | def setEdit(self, vobj, mode): |
| | """Enter the edit mode of the object. |
| | |
| | Parameters |
| | ---------- |
| | vobj : the view provider of the scripted object. |
| | This is `obj.ViewObject`. |
| | |
| | mode : int |
| | 0, 1, 2 or 3. See the `Std_UserEditMode` command. |
| | |
| | Returns |
| | ------- |
| | bool or None |
| | `False`: NOT USED HERE. |
| | Do not enter edit mode (unsetEdit is not called). |
| | `True` : Handled edit mode. |
| | Handled modes are 0 and 3, and only for certain objects. |
| | The unsetEdit function should then also return `True`. |
| | `None` : Unhandled edit mode. |
| | Handling is left to Part::FeaturePython code. |
| | The unsetEdit function should then also return `None`. |
| | """ |
| | if mode == 1 or mode == 2: |
| | return None |
| |
|
| | |
| | |
| | |
| | |
| | |
| |
|
| | |
| | |
| |
|
| | if utils.get_type(vobj.Object) in ( |
| | "Wire", |
| | "Circle", |
| | "Ellipse", |
| | "Rectangle", |
| | "Polygon", |
| | "BSpline", |
| | "BezCurve", |
| | ): |
| | if not "Draft_Edit" in Gui.listCommands(): |
| | self.wb_before_edit = Gui.activeWorkbench() |
| | Gui.activateWorkbench("DraftWorkbench") |
| | Gui.runCommand("Draft_Edit") |
| | return True |
| |
|
| | return None |
| |
|
| | def unsetEdit(self, vobj, mode): |
| | """Terminate the edit mode of the object. |
| | |
| | See setEdit. |
| | """ |
| | if mode == 1 or mode == 2: |
| | return None |
| |
|
| | if utils.get_type(vobj.Object) in ( |
| | "Wire", |
| | "Circle", |
| | "Ellipse", |
| | "Rectangle", |
| | "Polygon", |
| | "BSpline", |
| | "BezCurve", |
| | ): |
| | if hasattr(App, "activeDraftCommand") and App.activeDraftCommand: |
| | App.activeDraftCommand.finish() |
| | Gui.Control.closeDialog() |
| | if hasattr(self, "wb_before_edit"): |
| | Gui.activateWorkbench(self.wb_before_edit.name()) |
| | delattr(self, "wb_before_edit") |
| | return True |
| |
|
| | return None |
| |
|
| | def setupContextMenu(self, vobj, menu): |
| | tp = utils.get_type(self.Object) |
| |
|
| | if tp in ( |
| | "Wire", |
| | "Circle", |
| | "Ellipse", |
| | "Rectangle", |
| | "Polygon", |
| | "BSpline", |
| | "BezCurve", |
| | "Facebinder", |
| | "ShapeString", |
| | "PanelSheet", |
| | "Profile", |
| | ): |
| | action_edit = QtGui.QAction(translate("draft", "Edit"), menu) |
| | QtCore.QObject.connect(action_edit, QtCore.SIGNAL("triggered()"), self.edit) |
| | menu.addAction(action_edit) |
| |
|
| | if tp == "Wire": |
| | action_flatten = QtGui.QAction(translate("draft", "Flatten"), menu) |
| | QtCore.QObject.connect( |
| | action_flatten, QtCore.SIGNAL("triggered()"), self.flatten |
| | ) |
| | menu.addAction(action_flatten) |
| |
|
| | |
| | |
| | |
| | |
| | |
| | if tp in ( |
| | "Wire", |
| | "Circle", |
| | "Ellipse", |
| | "Rectangle", |
| | "Polygon", |
| | "BSpline", |
| | "BezCurve", |
| | "Fillet", |
| | "Point", |
| | "Shape2DView", |
| | "PanelCut", |
| | "PanelSheet", |
| | "Profile", |
| | ): |
| | action_transform = QtGui.QAction( |
| | Gui.getIcon("Std_TransformManip.svg"), |
| | translate("Command", "Transform"), |
| | menu, |
| | ) |
| | QtCore.QObject.connect(action_transform, QtCore.SIGNAL("triggered()"), self.transform) |
| | menu.addAction(action_transform) |
| | return True |
| |
|
| | def edit(self): |
| | Gui.ActiveDocument.setEdit(self.Object, 0) |
| |
|
| | def transform(self): |
| | Gui.ActiveDocument.setEdit(self.Object, 1) |
| |
|
| | def getIcon(self): |
| | """Return the path to the icon used by the view provider. |
| | |
| | The path can be a full path in the system, or a relative path |
| | inside the compiled resource file. |
| | It can also be a string that defines the icon in XPM format. |
| | |
| | Override this method to provide a specific icon |
| | for the object in the tree view. |
| | |
| | By default it returns the path to the `Draft_Draft.svg` icon. |
| | |
| | Returns |
| | ------- |
| | str |
| | `':/icons/Draft_Draft.svg'` |
| | """ |
| | tp = utils.get_type(self.Object) |
| | if tp in ("Line", "Wire", "Polyline"): |
| | return ":/icons/Draft_N-Linear.svg" |
| | if tp in ("Rectangle", "Polygon"): |
| | return ":/icons/Draft_N-Polygon.svg" |
| | if tp in ("Circle", "Ellipse", "BSpline", "BezCurve", "Fillet"): |
| | return ":/icons/Draft_N-Curve.svg" |
| | if tp in ("ShapeString"): |
| | return ":/icons/Draft_ShapeString_tree.svg" |
| | if hasattr(self.Object, "AutoUpdate") and not self.Object.AutoUpdate: |
| | import TechDrawGui |
| |
|
| | return ":/icons/TechDraw_TreePageUnsync.svg" |
| | return ":/icons/Draft_Draft.svg" |
| |
|
| | def claimChildren(self): |
| | """Return objects that will be placed under it in the tree view. |
| | |
| | Override this method to return a list with objects |
| | that will appear under this object in the tree view. |
| | That is, this object becomes the `parent`, |
| | and all those under it are the `children`. |
| | |
| | By default the returned list is composed of objects from |
| | `Object.Base`, `Object.Objects`, `Object.Components`, |
| | and `Object.Group`, if they exist. |
| | |
| | Returns |
| | ------- |
| | list |
| | List of objects. |
| | """ |
| | objs = [] |
| | if hasattr(self.Object, "Base"): |
| | objs.append(self.Object.Base) |
| | if hasattr(self.Object, "Objects"): |
| | objs.extend(self.Object.Objects) |
| | if hasattr(self.Object, "Components"): |
| | objs.extend(self.Object.Components) |
| | if hasattr(self.Object, "Group"): |
| | objs.extend(self.Object.Group) |
| | return objs |
| |
|
| |
|
| | |
| | _ViewProviderDraft = ViewProviderDraft |
| |
|
| |
|
| | class ViewProviderDraftAlt(ViewProviderDraft): |
| | """A view provider that doesn't absorb its base object in the tree view. |
| | |
| | The `claimChildren` method is overridden to return an empty list. |
| | |
| | The `doubleClicked` method is defined. |
| | |
| | Only used by the `Shape2DView` object. |
| | """ |
| |
|
| | def __init__(self, vobj): |
| | super(ViewProviderDraftAlt, self).__init__(vobj) |
| |
|
| | def doubleClicked(self, vobj): |
| | |
| | Gui.runCommand("Std_TransformManip") |
| | return True |
| |
|
| | def claimChildren(self): |
| | return [] |
| |
|
| |
|
| | |
| | _ViewProviderDraftAlt = ViewProviderDraftAlt |
| |
|
| |
|
| | class ViewProviderDraftPart(ViewProviderDraftAlt): |
| | """A view provider that displays a Part icon instead of a Draft icon. |
| | |
| | The `getIcon` method is overridden to provide `Part_3D_object.svg`. |
| | |
| | Only used by the `Block` object. |
| | """ |
| |
|
| | def __init__(self, vobj): |
| | super(ViewProviderDraftPart, self).__init__(vobj) |
| |
|
| | def getIcon(self): |
| | return ":/icons/Part_3D_object.svg" |
| |
|
| | def setEdit(self, vobj, mode): |
| | return None |
| |
|
| | def unsetEdit(self, vobj, mode): |
| | return None |
| |
|
| |
|
| | |
| | _ViewProviderDraftPart = ViewProviderDraftPart |
| |
|
| | |
| |
|