FreeCAD
291 строка · 11.2 Кб
1# ***************************************************************************
2# * Copyright (c) 2019 Yorik van Havre <yorik@uncreated.net> *
3# * Copyright (c) 2023 FreeCAD Project Association *
4# * *
5# * This program is free software; you can redistribute it and/or modify *
6# * it under the terms of the GNU Lesser General Public License (LGPL) *
7# * as published by the Free Software Foundation; either version 2 of *
8# * the License, or (at your option) any later version. *
9# * for detail see the LICENCE text file. *
10# * *
11# * This program is distributed in the hope that it will be useful, *
12# * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14# * GNU Library General Public License for more details. *
15# * *
16# * You should have received a copy of the GNU Library General Public *
17# * License along with this program; if not, write to the Free Software *
18# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
19# * USA *
20# * *
21# ***************************************************************************
22"""Provides GUI tools to set up the working plane and its grid."""
23## @package gui_selectplane
24# \ingroup draftguitools
25# \brief Provides GUI tools to set up the working plane and its grid.
26
27## \addtogroup draftguitools
28# @{
29from PySide import QtGui
30from PySide.QtCore import QT_TRANSLATE_NOOP
31
32import FreeCAD as App
33import FreeCADGui as Gui
34import Part
35import WorkingPlane
36
37from FreeCAD import Units
38from drafttaskpanels import task_selectplane
39from draftutils import params
40from draftutils import utils
41from draftutils.messages import _msg
42from draftutils.todo import todo
43from draftutils.translate import translate
44
45__title__ = "FreeCAD Draft Workbench GUI Tools - Working plane-related tools"
46__author__ = ("Yorik van Havre, Werner Mayer, Martin Burbaum, Ken Cline, "
47"Dmitry Chigrin")
48__url__ = "https://www.freecad.org"
49
50
51class Draft_SelectPlane:
52"""The Draft_SelectPlane FreeCAD command definition."""
53
54def GetResources(self):
55"""Set icon, menu and tooltip."""
56return {"Pixmap": "Draft_SelectPlane",
57"Accel": "W, P",
58"MenuText": QT_TRANSLATE_NOOP("Draft_SelectPlane", "Select plane"),
59"ToolTip": QT_TRANSLATE_NOOP("Draft_SelectPlane", "Select 3 vertices, one or more shapes or an object to define a working plane.")}
60
61def IsActive(self):
62"""Return True when this command should be available."""
63if Gui.ActiveDocument:
64return True
65else:
66return False
67
68def Activated(self):
69"""Execute when the command is called."""
70# Finish active Draft command if any
71if App.activeDraftCommand is not None:
72App.activeDraftCommand.finish()
73
74App.activeDraftCommand = self
75self.call = None
76
77# Set variables
78self.wp = WorkingPlane.get_working_plane()
79self.view = self.wp._view
80self.grid = None
81if hasattr(Gui, "Snapper"):
82Gui.Snapper.setTrackers()
83self.grid = Gui.Snapper.grid
84self.offset = 0
85self.center = params.get_param("CenterPlaneOnView")
86
87# Create task panel
88self.taskd = task_selectplane.SelectPlaneTaskPanel()
89self.taskd.reject = self.reject
90form = self.taskd.form
91
92# Fill values
93form.fieldOffset.setText(Units.Quantity(self.offset, Units.Length).UserString)
94form.checkCenter.setChecked(self.center)
95try:
96q = Units.Quantity(params.get_param("gridSpacing"))
97except ValueError:
98q = Units.Quantity("1 mm")
99form.fieldGridSpacing.setText(q.UserString)
100form.fieldGridMainLine.setValue(params.get_param("gridEvery"))
101form.fieldGridExtension.setValue(params.get_param("gridSize"))
102form.fieldSnapRadius.setValue(params.get_param("snapRange"))
103
104# Set icons
105form.setWindowIcon(QtGui.QIcon(":/icons/Draft_SelectPlane.svg"))
106form.buttonTop.setIcon(QtGui.QIcon(":/icons/view-top.svg"))
107form.buttonFront.setIcon(QtGui.QIcon(":/icons/view-front.svg"))
108form.buttonSide.setIcon(QtGui.QIcon(":/icons/view-right.svg"))
109form.buttonAlign.setIcon(QtGui.QIcon(":/icons/view-isometric.svg"))
110form.buttonAuto.setIcon(QtGui.QIcon(":/icons/view-axonometric.svg"))
111form.buttonMove.setIcon(QtGui.QIcon(":/icons/Draft_Move.svg"))
112form.buttonCenter.setIcon(QtGui.QIcon(":/icons/view-fullscreen.svg"))
113form.buttonPrevious.setIcon(QtGui.QIcon(":/icons/sel-back.svg"))
114form.buttonNext.setIcon(QtGui.QIcon(":/icons/sel-forward.svg"))
115
116# Grid color
117color = params.get_param("gridColor")
118form.buttonColor.setProperty("color", QtGui.QColor(utils.rgba_to_argb(color)))
119
120# Connect slots
121form.buttonTop.clicked.connect(self.on_click_top)
122form.buttonFront.clicked.connect(self.on_click_front)
123form.buttonSide.clicked.connect(self.on_click_side)
124form.buttonAlign.clicked.connect(self.on_click_align)
125form.buttonAuto.clicked.connect(self.on_click_auto)
126form.buttonMove.clicked.connect(self.on_click_move)
127form.buttonCenter.clicked.connect(self.on_click_center)
128form.buttonPrevious.clicked.connect(self.on_click_previous)
129form.buttonNext.clicked.connect(self.on_click_next)
130form.fieldOffset.textEdited.connect(self.on_set_offset)
131form.checkCenter.stateChanged.connect(self.on_set_center)
132form.fieldGridSpacing.textEdited.connect(self.on_set_grid_size)
133form.fieldGridMainLine.valueChanged.connect(self.on_set_main_line)
134form.fieldGridExtension.valueChanged.connect(self.on_set_extension)
135form.fieldSnapRadius.valueChanged.connect(self.on_set_snap_radius)
136form.buttonColor.changed.connect(self.on_color_changed)
137
138# Enable/disable buttons.
139form.buttonPrevious.setEnabled(self.wp._has_previous())
140form.buttonNext.setEnabled(self.wp._has_next())
141
142# Try to find a WP from the current selection
143if Gui.Selection.hasSelection():
144if self.wp.align_to_selection(self.offset):
145Gui.Selection.clearSelection()
146self.finish()
147return
148
149# Execute the actual task panel delayed to catch possible active Draft command
150todo.delay(Gui.Control.showDialog, self.taskd)
151todo.delay(form.setFocus, None)
152_msg(translate(
153"draft",
154"Select 3 vertices, one or more shapes or an object to define a working plane"))
155self.call = self.view.addEventCallback("SoEvent", self.action)
156
157def finish(self):
158"""Execute when the command is terminated."""
159App.activeDraftCommand = None
160Gui.Control.closeDialog()
161if hasattr(Gui, "Snapper"):
162Gui.Snapper.off()
163# Terminate coin callbacks
164if self.call:
165try:
166self.view.removeEventCallback("SoEvent", self.call)
167except RuntimeError:
168# The view has been deleted already
169pass
170self.call = None
171
172def reject(self):
173"""Execute when clicking the Cancel button."""
174self.finish()
175
176def action(self, arg):
177"""Set the callbacks for the view."""
178if arg["Type"] == "SoKeyboardEvent" and arg["Key"] == "ESCAPE":
179self.reject()
180if arg["Type"] == "SoMouseButtonEvent" \
181and (arg["State"] == "DOWN") \
182and (arg["Button"] == "BUTTON1"):
183self.check_selection()
184
185def check_selection(self):
186"""Check the selection, if it is usable, finish the command."""
187if self.wp.align_to_selection(self.offset):
188Gui.Selection.clearSelection()
189self.finish()
190
191def on_click_top(self):
192self.wp.set_to_top(self.offset, self.center)
193self.finish()
194
195def on_click_front(self):
196self.wp.set_to_front(self.offset, self.center)
197self.finish()
198
199def on_click_side(self):
200self.wp.set_to_side(self.offset, self.center)
201self.finish()
202
203def on_click_align(self):
204self.wp.set_to_view(self.offset, self.center)
205self.finish()
206
207def on_click_auto(self):
208self.wp.set_to_auto()
209self.finish()
210
211def on_click_move(self):
212sels = Gui.Selection.getSelectionEx("", 0)
213if len(sels) == 1 \
214and len(sels[0].SubObjects) == 1 \
215and sels[0].SubObjects[0].ShapeType == "Vertex":
216vert = Part.getShape(sels[0].Object,
217sels[0].SubElementNames[0],
218needSubElement=True,
219retType=0)
220self.wp.set_to_position(vert.Point)
221Gui.Selection.clearSelection()
222self.finish()
223else:
224# Move the WP to the center of the current view
225self.wp.center_on_view()
226self.finish()
227
228def on_click_center(self):
229self.wp.align_view()
230self.finish()
231
232def on_click_previous(self):
233self.wp._previous()
234self.finish()
235
236def on_click_next(self):
237self.wp._next()
238self.finish()
239
240def on_set_offset(self, text):
241try:
242q = Units.Quantity(text)
243except Exception:
244pass
245else:
246self.offset = q.Value
247
248def on_set_center(self, val):
249self.center = bool(val)
250params.set_param("CenterPlaneOnView", self.center)
251
252def on_set_grid_size(self, text):
253try:
254q = Units.Quantity(text)
255except Exception:
256pass
257else:
258params.set_param("gridSpacing", q.UserString)
259# ParamObserver handles grid changes. See params.py.
260if self.grid is not None:
261self.grid.show_during_command = True
262self.grid.on()
263
264def on_set_main_line(self, i):
265if i > 1:
266params.set_param("gridEvery", i)
267# ParamObserver handles grid changes. See params.py.
268if self.grid is not None:
269self.grid.show_during_command = True
270self.grid.on()
271
272def on_set_extension(self, i):
273if i > 1:
274params.set_param("gridSize", i)
275# ParamObserver handles grid changes. See params.py.
276if self.grid is not None:
277self.grid.show_during_command = True
278self.grid.on()
279
280def on_set_snap_radius(self, i):
281params.set_param("snapRange", i)
282if hasattr(Gui, "Snapper"):
283Gui.Snapper.showradius()
284
285def on_color_changed(self):
286color = utils.argb_to_rgba(self.taskd.form.buttonColor.property("color").rgba())
287params.set_param("gridColor", color)
288
289Gui.addCommand('Draft_SelectPlane', Draft_SelectPlane())
290
291## @}
292