Merge pull request #22712 from PaddleStroke/asm_watcher
Assembly: TaskWatcher
This commit is contained in:
@@ -40,6 +40,7 @@
|
||||
#include <Gui/Application.h>
|
||||
#include <Gui/Document.h>
|
||||
#include <Gui/MainWindow.h>
|
||||
#include <Gui/ViewProviderDocumentObject.h>
|
||||
|
||||
#include "TaskView.h"
|
||||
#include "TaskDialog.h"
|
||||
@@ -317,6 +318,9 @@ TaskView::TaskView(QWidget *parent)
|
||||
connectApplicationRedoDocument =
|
||||
App::GetApplication().signalRedoDocument.connect
|
||||
(std::bind(&Gui::TaskView::TaskView::slotRedoDocument, this, sp::_1));
|
||||
connectApplicationInEdit =
|
||||
Gui::Application::Instance->signalInEdit.connect(
|
||||
std::bind(&Gui::TaskView::TaskView::slotInEdit, this, sp::_1));
|
||||
//NOLINTEND
|
||||
|
||||
updateWatcher();
|
||||
@@ -329,6 +333,7 @@ TaskView::~TaskView()
|
||||
connectApplicationClosedView.disconnect();
|
||||
connectApplicationUndoDocument.disconnect();
|
||||
connectApplicationRedoDocument.disconnect();
|
||||
connectApplicationInEdit.disconnect();
|
||||
Gui::Selection().Detach(this);
|
||||
|
||||
for (QWidget* panel : contextualPanels) {
|
||||
@@ -474,8 +479,20 @@ QSize TaskView::minimumSizeHint() const
|
||||
void TaskView::slotActiveDocument(const App::Document& doc)
|
||||
{
|
||||
Q_UNUSED(doc);
|
||||
if (!ActiveDialog)
|
||||
if (!ActiveDialog) {
|
||||
// at this point, active object of the active view returns None.
|
||||
// which is a problem if shouldShow of a watcher rely on the presence
|
||||
// of an active object (example Assembly).
|
||||
QTimer::singleShot(100, this, &TaskView::updateWatcher);
|
||||
}
|
||||
}
|
||||
|
||||
void TaskView::slotInEdit(const Gui::ViewProviderDocumentObject& vp)
|
||||
{
|
||||
Q_UNUSED(vp);
|
||||
if (!ActiveDialog) {
|
||||
updateWatcher();
|
||||
}
|
||||
}
|
||||
|
||||
void TaskView::slotDeletedDocument(const App::Document& doc)
|
||||
|
||||
@@ -39,6 +39,7 @@ class Property;
|
||||
namespace Gui {
|
||||
class MDIView;
|
||||
class ControlSingleton;
|
||||
class ViewProviderDocumentObject;
|
||||
namespace DockWnd{
|
||||
class ComboView;
|
||||
}
|
||||
@@ -187,6 +188,7 @@ private:
|
||||
void saveCurrentWidth();
|
||||
void tryRestoreWidth();
|
||||
void slotActiveDocument(const App::Document&);
|
||||
void slotInEdit(const Gui::ViewProviderDocumentObject&);
|
||||
void slotDeletedDocument(const App::Document&);
|
||||
void slotViewClosed(const Gui::MDIView*);
|
||||
void slotUndoDocument(const App::Document&);
|
||||
@@ -224,6 +226,7 @@ protected:
|
||||
Connection connectApplicationClosedView;
|
||||
Connection connectApplicationUndoDocument;
|
||||
Connection connectApplicationRedoDocument;
|
||||
Connection connectApplicationInEdit;
|
||||
};
|
||||
|
||||
} //namespace TaskView
|
||||
|
||||
@@ -27,11 +27,12 @@ from PySide.QtCore import QT_TRANSLATE_NOOP
|
||||
|
||||
if App.GuiUp:
|
||||
import FreeCADGui as Gui
|
||||
from PySide import QtCore, QtGui, QtWidgets
|
||||
|
||||
import UtilsAssembly
|
||||
import Preferences
|
||||
|
||||
# translate = App.Qt.translate
|
||||
translate = App.Qt.translate
|
||||
|
||||
__title__ = "Assembly Command Create Assembly"
|
||||
__author__ = "Ondsel"
|
||||
@@ -91,5 +92,81 @@ class CommandCreateAssembly:
|
||||
App.closeActiveTransaction()
|
||||
|
||||
|
||||
class ActivateAssemblyTaskPanel:
|
||||
"""A basic TaskPanel to select an assembly to activate."""
|
||||
|
||||
def __init__(self, assemblies):
|
||||
self.assemblies = assemblies
|
||||
self.form = QtWidgets.QWidget()
|
||||
self.form.setWindowTitle(translate("Assembly_ActivateAssembly", "Activate Assembly"))
|
||||
|
||||
layout = QtWidgets.QVBoxLayout(self.form)
|
||||
label = QtWidgets.QLabel(
|
||||
translate("Assembly_ActivateAssembly", "Select an assembly to activate:")
|
||||
)
|
||||
self.combo = QtWidgets.QComboBox()
|
||||
|
||||
for asm in self.assemblies:
|
||||
# Store the user-friendly Label for display, and the internal Name for activation
|
||||
self.combo.addItem(asm.Label, asm.Name)
|
||||
|
||||
layout.addWidget(label)
|
||||
layout.addWidget(self.combo)
|
||||
|
||||
def accept(self):
|
||||
"""Called when the user clicks OK."""
|
||||
selected_name = self.combo.currentData()
|
||||
if selected_name:
|
||||
Gui.doCommand(f"Gui.ActiveDocument.setEdit('{selected_name}')")
|
||||
return True
|
||||
|
||||
def reject(self):
|
||||
"""Called when the user clicks Cancel or closes the panel."""
|
||||
return True
|
||||
|
||||
|
||||
class CommandActivateAssembly:
|
||||
def __init__(self):
|
||||
self.task_panel = None
|
||||
|
||||
def GetResources(self):
|
||||
return {
|
||||
"Pixmap": "Assembly_ActivateAssembly",
|
||||
"MenuText": QT_TRANSLATE_NOOP("Assembly_ActivateAssembly", "Activate Assembly"),
|
||||
"ToolTip": QT_TRANSLATE_NOOP(
|
||||
"Assembly_ActivateAssembly", "Sets an assembly as the active one for editing."
|
||||
),
|
||||
"CmdType": "ForEdit",
|
||||
}
|
||||
|
||||
def IsActive(self):
|
||||
if Gui.Control.activeDialog() or App.ActiveDocument is None:
|
||||
return False
|
||||
|
||||
# Command is only active if no assembly is currently active
|
||||
if UtilsAssembly.activeAssembly() is not None:
|
||||
return False
|
||||
|
||||
# And if there is at least one assembly in the document to activate
|
||||
for obj in App.ActiveDocument.Objects:
|
||||
if obj.isDerivedFrom("Assembly::AssemblyObject"):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def Activated(self):
|
||||
doc = App.ActiveDocument
|
||||
assemblies = [o for o in doc.Objects if o.isDerivedFrom("Assembly::AssemblyObject")]
|
||||
|
||||
if len(assemblies) == 1:
|
||||
# If there's only one, activate it directly without showing a dialog
|
||||
Gui.doCommand(f"Gui.ActiveDocument.setEdit('{assemblies[0].Name}')")
|
||||
elif len(assemblies) > 1:
|
||||
# If there are multiple, show a task panel to let the user choose
|
||||
self.task_panel = ActivateAssemblyTaskPanel(assemblies)
|
||||
Gui.Control.showDialog(self.task_panel)
|
||||
|
||||
|
||||
if App.GuiUp:
|
||||
Gui.addCommand("Assembly_CreateAssembly", CommandCreateAssembly())
|
||||
Gui.addCommand("Assembly_ActivateAssembly", CommandActivateAssembly())
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<RCC>
|
||||
<qresource prefix="/">
|
||||
<file>icons/Assembly_ActivateAssembly.svg</file>
|
||||
<file>icons/Assembly_AssemblyLink.svg</file>
|
||||
<file>icons/Assembly_AssemblyLinkRigid.svg</file>
|
||||
<file>icons/Assembly_InsertLink.svg</file>
|
||||
|
||||
@@ -0,0 +1,388 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="64"
|
||||
height="64"
|
||||
version="1.1"
|
||||
viewBox="0 0 64 64"
|
||||
id="svg96"
|
||||
sodipodi:docname="Assembly_ActivateAssembly.svg"
|
||||
inkscape:version="1.4 (86a8ad7, 2024-10-11)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="3840"
|
||||
inkscape:window-height="1571"
|
||||
id="namedview98"
|
||||
showgrid="false"
|
||||
inkscape:zoom="7.375"
|
||||
inkscape:cx="19.186441"
|
||||
inkscape:cy="33.152542"
|
||||
inkscape:window-x="-9"
|
||||
inkscape:window-y="-9"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg96"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1" />
|
||||
<defs
|
||||
id="defs26">
|
||||
<linearGradient
|
||||
id="linearGradient4383">
|
||||
<stop
|
||||
stop-color="#3465a4"
|
||||
offset="0"
|
||||
id="stop2" />
|
||||
<stop
|
||||
stop-color="#729fcf"
|
||||
offset="1"
|
||||
id="stop4" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient4389"
|
||||
x1="20.244"
|
||||
x2="17.244"
|
||||
y1="37.588"
|
||||
y2="27.588"
|
||||
gradientTransform="translate(-1.2435,-2.5881)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
xlink:href="#linearGradient3774" />
|
||||
<linearGradient
|
||||
id="linearGradient4399"
|
||||
x1="48.714"
|
||||
x2="44.714"
|
||||
y1="45.586"
|
||||
y2="34.586"
|
||||
gradientTransform="translate(1.2856,1.4142)"
|
||||
gradientUnits="userSpaceOnUse">
|
||||
<stop
|
||||
stop-color="#c4a000"
|
||||
offset="0"
|
||||
id="stop8" />
|
||||
<stop
|
||||
stop-color="#edd400"
|
||||
offset="1"
|
||||
id="stop10" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient69042"
|
||||
x1="48.714"
|
||||
x2="44.714"
|
||||
y1="45.586"
|
||||
y2="34.586"
|
||||
gradientTransform="translate(-12.714,-17.586)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
xlink:href="#linearGradient3774" />
|
||||
<linearGradient
|
||||
id="linearGradient69056"
|
||||
x1="27.244"
|
||||
x2="22.244"
|
||||
y1="54.588"
|
||||
y2="40.588"
|
||||
gradientTransform="translate(-1.2435,-2.5881)"
|
||||
gradientUnits="userSpaceOnUse">
|
||||
<stop
|
||||
stop-color="#c4a000"
|
||||
offset="0"
|
||||
id="stop14" />
|
||||
<stop
|
||||
stop-color="#fce94f"
|
||||
offset="1"
|
||||
id="stop16" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient69709"
|
||||
x1="20.244"
|
||||
x2="17.244"
|
||||
y1="37.588"
|
||||
y2="27.588"
|
||||
gradientTransform="matrix(1,-0.026667,0,1,81.696,-5.3735)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
xlink:href="#linearGradient4383" />
|
||||
<linearGradient
|
||||
id="linearGradient69717"
|
||||
x1="50.714"
|
||||
x2="48.714"
|
||||
y1="25.586"
|
||||
y2="20.586"
|
||||
gradientTransform="translate(61.2256,1.0356)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
xlink:href="#linearGradient4383" />
|
||||
<linearGradient
|
||||
id="linearGradient3774">
|
||||
<stop
|
||||
stop-color="#4e9a06"
|
||||
offset="0"
|
||||
id="stop21" />
|
||||
<stop
|
||||
stop-color="#8ae234"
|
||||
offset="1"
|
||||
id="stop23" />
|
||||
</linearGradient>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath1">
|
||||
<path
|
||||
style="fill:none;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;-inkscape-stroke:none"
|
||||
d="m 1128.2358,1230.7769 47.3569,-44.8156 90.1392,-7.1378 98.3518,-93.074 -122.4881,-129.43385 -196.8251,186.26295 z"
|
||||
id="path2" />
|
||||
</clipPath>
|
||||
<linearGradient
|
||||
xlink:href="#linearGradient3774"
|
||||
id="linearGradient5137"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(-0.51964051,0,0,0.50042191,1386.3532,982.21378)"
|
||||
x1="288.11227"
|
||||
y1="358.15811"
|
||||
x2="372.52457"
|
||||
y2="7.5416322" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4383"
|
||||
id="linearGradient1"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1,-0.026667,0,1,81.696,-5.3735)"
|
||||
x1="20.244"
|
||||
y1="37.588"
|
||||
x2="17.244"
|
||||
y2="27.588" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3774"
|
||||
id="linearGradient2"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(-1.2435,-2.5881)"
|
||||
x1="20.244"
|
||||
y1="37.588"
|
||||
x2="17.244"
|
||||
y2="27.588" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient3774"
|
||||
id="linearGradient3"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(-12.714,-17.586)"
|
||||
x1="48.714"
|
||||
y1="45.586"
|
||||
x2="44.714"
|
||||
y2="34.586" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4399"
|
||||
id="linearGradient4"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(-52.714,-17.586)"
|
||||
x1="48.714001"
|
||||
y1="45.585999"
|
||||
x2="44.714001"
|
||||
y2="34.585999" />
|
||||
</defs>
|
||||
<metadata
|
||||
id="metadata28">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
<dc:title>Path-Stock</dc:title>
|
||||
<dc:date>2015-07-04</dc:date>
|
||||
<dc:relation>https://www.freecad.org/wiki/index.php?title=Artwork</dc:relation>
|
||||
<dc:publisher>
|
||||
<cc:Agent>
|
||||
<dc:title>FreeCAD</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:publisher>
|
||||
<dc:identifier>FreeCAD/src/Mod/Path/Gui/Resources/icons/Path-Stock.svg</dc:identifier>
|
||||
<dc:rights>
|
||||
<cc:Agent>
|
||||
<dc:title>FreeCAD LGPL2+</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:rights>
|
||||
<cc:license>https://www.gnu.org/copyleft/lesser.html</cc:license>
|
||||
<dc:contributor>
|
||||
<cc:Agent>
|
||||
<dc:title>[agryson] Alexander Gryson</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:contributor>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="layer1"
|
||||
transform="translate(0.19522715,0.27982587)">
|
||||
<g
|
||||
id="g1124"
|
||||
transform="matrix(1.0964113,0,0,1.0964113,-13.226965,60.643745)"
|
||||
style="opacity:1">
|
||||
<g
|
||||
id="g40-8"
|
||||
style="stroke-width:2"
|
||||
transform="translate(9.249999,-58.229485)">
|
||||
<path
|
||||
d="M 9,49 V 35 l 28,10 v 14 z"
|
||||
id="path30-8"
|
||||
style="fill:#babdb6;stroke:#0b1e23;stroke-linejoin:round;stroke-opacity:1" />
|
||||
<path
|
||||
d="M 37,59 V 45 L 55,28 v 13 z"
|
||||
id="path32-2"
|
||||
style="fill:#babdb6;stroke:#0b1e23;stroke-linejoin:round;stroke-opacity:1" />
|
||||
<path
|
||||
d="M 11.008,47.606 11,37.9997 l 24,8 0.0081,10.185 z"
|
||||
id="path34-4"
|
||||
style="fill:#888a85;stroke:#babdb6" />
|
||||
<path
|
||||
d="M 39.005,54.168 39,45.9998 l 14,-13 0.0021,7.1768 z"
|
||||
id="path36-5"
|
||||
style="fill:#888a85;stroke:#babdb6" />
|
||||
<path
|
||||
d="M 23,40 42,23 55,28 37,45 Z"
|
||||
id="path38-5"
|
||||
style="fill:#d3d7cf;stroke:#0b1e23;stroke-linejoin:round;stroke-opacity:1" />
|
||||
</g>
|
||||
<g
|
||||
id="g943-1"
|
||||
transform="translate(-50.750001,-58.229485)">
|
||||
<path
|
||||
d="m 91,33.5 -0.02739,-14.214 12.967,4.3352 v 14.5 z"
|
||||
id="path54-7"
|
||||
style="fill:url(#linearGradient1);stroke:#0b1e23;stroke-width:2;stroke-linejoin:round;stroke-opacity:1" />
|
||||
<path
|
||||
d="m 92.927,32.029 0.04731,-10.141 8.9272,3.29 0.0781,10.042 z"
|
||||
id="path56-1"
|
||||
style="fill:#888a85;stroke:#babdb6;stroke-width:2" />
|
||||
<path
|
||||
d="m 103.94,38.121 v -14.5 l 11,-9 L 115,28 Z"
|
||||
id="path58-1"
|
||||
style="fill:#edd400;stroke:#0b1e23;stroke-width:2;stroke-linejoin:round;stroke-opacity:1" />
|
||||
<path
|
||||
d="m 105.94,33.621 v -9 l 7,-6 -0.0122,8.5816 z"
|
||||
id="path60-5"
|
||||
style="fill:#888a85;stroke:#babdb6;stroke-width:2" />
|
||||
<path
|
||||
d="M 90.973,19.286 102,9.9998 l 12.94,4.6214 -11,9 z"
|
||||
id="path62-2"
|
||||
style="fill:#d3d7cf;stroke:#0b1e23;stroke-width:2;stroke-linejoin:round;stroke-opacity:1" />
|
||||
</g>
|
||||
<g
|
||||
id="g963-7"
|
||||
transform="translate(49.249999,-58.229485)">
|
||||
<g
|
||||
style="stroke:#172a04;stroke-width:2;stroke-linejoin:round"
|
||||
transform="translate(-40)"
|
||||
id="g48-6">
|
||||
<path
|
||||
style="fill:url(#linearGradient2)"
|
||||
id="path42-1"
|
||||
d="M 9,35 V 21 l 14,5 v 14 z" />
|
||||
<path
|
||||
style="fill:#8ae234"
|
||||
id="path44-4"
|
||||
d="M 9,21 28.585,5.209 42,10.0001 l -19,16 z" />
|
||||
<path
|
||||
style="fill:url(#linearGradient3)"
|
||||
id="path46-2"
|
||||
d="M 23,40 V 26 l 7.9726,-6.7138 0.02739,13.714 z" />
|
||||
</g>
|
||||
<path
|
||||
style="fill:#888a85;fill-opacity:1;stroke:#0b1e23;stroke-width:2;stroke-linejoin:round;stroke-opacity:1"
|
||||
id="path912-3"
|
||||
d="M -31,35 V 21 l 14,5 v 14 z" />
|
||||
<path
|
||||
style="fill:#d3d7cf;fill-opacity:1;stroke:#0b1e23;stroke-width:2;stroke-linejoin:round;stroke-opacity:1"
|
||||
id="path914-2"
|
||||
d="M -31,21 -11.415,5.209 2,10.0001 l -19,16 z" />
|
||||
<path
|
||||
style="fill:url(#linearGradient4);fill-opacity:1;stroke:#0b1e23;stroke-width:2;stroke-linejoin:round;stroke-opacity:1"
|
||||
id="path916-2"
|
||||
d="M -17,40 V 26 l 7.9726,-6.7138 0.02739,13.714 z" />
|
||||
<path
|
||||
d="m -15,36 v -9 l 4,-3.5 v 9 z"
|
||||
id="path50-1"
|
||||
style="fill:#888a85;stroke:#babdb6;stroke-width:2;stroke-opacity:1" />
|
||||
<path
|
||||
d="m -29.049,33.746 0.08695,-9.9796 9.9568,3.5229 -0.02105,9.9613 z"
|
||||
id="path52-6"
|
||||
style="fill:none;stroke:#babdb6;stroke-width:2;stroke-opacity:1" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
display="none"
|
||||
fill="#ef2929"
|
||||
fill-rule="evenodd"
|
||||
opacity=".588"
|
||||
stroke="#ef2929"
|
||||
stroke-width="1px"
|
||||
id="g94">
|
||||
<path
|
||||
d="m9 35v14"
|
||||
id="path66" />
|
||||
<path
|
||||
d="m9 35 28 10"
|
||||
id="path68" />
|
||||
<path
|
||||
d="m55 28v13"
|
||||
id="path70" />
|
||||
<path
|
||||
d="m37 45 18-17"
|
||||
id="path72" />
|
||||
<path
|
||||
d="m23 40v-14"
|
||||
id="path74" />
|
||||
<path
|
||||
d="m29 5 13 5"
|
||||
id="path76" />
|
||||
<path
|
||||
d="m23 26 19-16"
|
||||
id="path78" />
|
||||
<path
|
||||
d="m19 13 10-8"
|
||||
id="path80" />
|
||||
<path
|
||||
d="m55 15-9 8"
|
||||
id="path82" />
|
||||
<path
|
||||
d="m42 23v-13"
|
||||
id="path84" />
|
||||
<path
|
||||
d="m42 23 14 5"
|
||||
id="path86" />
|
||||
<path
|
||||
d="m23 40 19-17"
|
||||
id="path88" />
|
||||
<path
|
||||
d="m23 10h19"
|
||||
id="path90" />
|
||||
<path
|
||||
d="m34 17v13"
|
||||
id="path92" />
|
||||
</g>
|
||||
<g
|
||||
transform="matrix(0.12325184,0.1166378,-0.1166378,0.12325184,11.596839,-245.60194)"
|
||||
id="g4218"
|
||||
clip-path="url(#clipPath1)">
|
||||
<path
|
||||
style="opacity:1;fill:#8ae234;fill-opacity:1;stroke:#172a04;stroke-width:14.7326;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 1145.5648,1074.1543 c 18.5937,-18.383 48.2169,-28.9064 88.8688,-31.5737 v -37.4326 c 0,-4.0003 1.9294,-6.80966 5.7868,-8.43006 4.0547,-1.61639 7.5171,-0.95178 10.3849,2.00121 l 75.9581,73.15065 c 1.8799,1.8121 2.8184,3.9543 2.8184,6.4303 0,2.4767 -0.9389,4.6185 -2.8184,6.429 l -75.9602,73.1502 c -1.7833,1.81 -4.0064,2.7148 -6.6772,2.7148 -1.1865,0 -2.4222,-0.2382 -3.7083,-0.7141 -3.8572,-1.6204 -5.7882,-4.4273 -5.7882,-8.4296 v -35.8618 c -15.9228,1.2386 -29.1503,3.7387 -39.6881,7.5008 -10.5331,3.7627 -18.9637,9.0247 -25.2946,15.7879 -14.738,15.7158 -19.9806,42.6214 -15.7274,80.7237 0.1953,2.4775 -0.9389,4.0963 -3.4125,4.858 -0.2967,0.097 -0.7414,0.142 -1.3349,0.142 -1.9778,0 -3.361,-0.8095 -4.154,-2.4285 l -2.9667,-5.7148 c -1.3832,-2.6676 -3.3858,-6.9784 -6.007,-12.9313 -2.6194,-5.9556 -4.9969,-11.9071 -7.1237,-17.8612 -2.1269,-5.9515 -4.0298,-12.5235 -5.7119,-19.7147 -1.6805,-7.194 -2.5219,-13.5508 -2.5219,-19.074 0,-32.0039 8.3606,-56.2428 25.078,-72.7222 z"
|
||||
id="path4228" />
|
||||
<path
|
||||
id="path5135"
|
||||
d="m 1252.6459,1025.0625 c 18.4441,17.7617 37.1632,35.1962 55.3062,53.3235 -19.0906,18.0067 -37.542,36.7844 -56.7747,54.6184 -0.018,-12.2743 -0.087,-24.5491 0.032,-36.8231 -26.4463,1.6409 -53.9694,3.575 -77.8197,17.2303 -17.0095,9.5803 -28.4884,27.8106 -34.5388,47.088 -3.5743,-21.5969 -1.2897,-45.3408 10.607,-63.6609 11.0273,-16.9013 29.5358,-25.7267 47.629,-30.3404 14.7839,-4.3279 30.2561,-4.0127 45.1276,-7.7257 7.8392,-4.3982 10.4187,-14.9284 9.2176,-23.8416 -0.062,-3.7919 -0.2886,-7.6325 -0.4323,-11.451 0.5488,0.5275 1.0977,1.055 1.6465,1.5825 z"
|
||||
style="opacity:1;fill:url(#linearGradient5137);fill-opacity:1;stroke:none;stroke-width:34.7533;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 13 KiB |
+152
-1
@@ -118,11 +118,162 @@ class AssemblyWorkbench(Workbench):
|
||||
# update the translation engine
|
||||
FreeCADGui.updateLocale()
|
||||
|
||||
# Add task watchers to provide contextual tools in the task panel
|
||||
self.setWatchers()
|
||||
|
||||
def Deactivated(self):
|
||||
pass
|
||||
FreeCADGui.Control.clearTaskWatcher()
|
||||
|
||||
def ContextMenu(self, recipient):
|
||||
pass
|
||||
|
||||
def setWatchers(self):
|
||||
import UtilsAssembly
|
||||
|
||||
translate = FreeCAD.Qt.translate
|
||||
|
||||
class AssemblyCreateWatcher:
|
||||
"""Shows 'Create Assembly' when no assembly exists in the document."""
|
||||
|
||||
def __init__(self):
|
||||
self.commands = ["Assembly_CreateAssembly"]
|
||||
self.title = translate("Assembly", "Create")
|
||||
|
||||
def shouldShow(self):
|
||||
doc = FreeCAD.ActiveDocument
|
||||
|
||||
if hasattr(doc, "RootObjects"):
|
||||
for obj in doc.RootObjects:
|
||||
if obj.isDerivedFrom("Assembly::AssemblyObject"):
|
||||
return False
|
||||
return True
|
||||
|
||||
class AssemblyActivateWatcher:
|
||||
"""Shows 'Activate Assembly' when an assembly exists but is not active."""
|
||||
|
||||
def __init__(self):
|
||||
self.commands = ["Assembly_ActivateAssembly"]
|
||||
self.title = translate("Assembly", "Activate")
|
||||
|
||||
def shouldShow(self):
|
||||
doc = FreeCAD.ActiveDocument
|
||||
|
||||
has_assembly = False
|
||||
if hasattr(doc, "RootObjects"):
|
||||
for obj in doc.RootObjects:
|
||||
if obj.isDerivedFrom("Assembly::AssemblyObject"):
|
||||
has_assembly = True
|
||||
break
|
||||
|
||||
assembly = UtilsAssembly.activeAssembly()
|
||||
|
||||
return has_assembly and (assembly is None or assembly.Document != doc)
|
||||
|
||||
class AssemblyBaseWatcher:
|
||||
"""Base class for watchers that require an active assembly."""
|
||||
|
||||
def __init__(self):
|
||||
self.assembly = None
|
||||
|
||||
def shouldShow(self):
|
||||
doc = FreeCAD.ActiveDocument
|
||||
|
||||
self.assembly = UtilsAssembly.activeAssembly()
|
||||
return self.assembly is not None and self.assembly.Document == doc
|
||||
|
||||
class AssemblyInsertWatcher(AssemblyBaseWatcher):
|
||||
"""Shows 'Insert Component' when an assembly is active."""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.commands = ["Assembly_Insert"]
|
||||
self.title = translate("Assembly", "Insert")
|
||||
|
||||
def shouldShow(self):
|
||||
return super().shouldShow()
|
||||
|
||||
class AssemblyGroundWatcher(AssemblyBaseWatcher):
|
||||
"""Shows 'Ground' when the active assembly has no grounded parts."""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.commands = ["Assembly_ToggleGrounded"]
|
||||
self.title = translate("Assembly", "Grounding")
|
||||
|
||||
def shouldShow(self):
|
||||
if not super().shouldShow():
|
||||
return False
|
||||
return (
|
||||
UtilsAssembly.assembly_has_at_least_n_parts(1)
|
||||
and not UtilsAssembly.isAssemblyGrounded()
|
||||
)
|
||||
|
||||
class AssemblyJointsWatcher(AssemblyBaseWatcher):
|
||||
"""Shows Joint, View, and BOM tools when there are enough parts."""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.commands = [
|
||||
"Assembly_CreateJointFixed",
|
||||
"Assembly_CreateJointRevolute",
|
||||
"Assembly_CreateJointCylindrical",
|
||||
"Assembly_CreateJointSlider",
|
||||
"Assembly_CreateJointBall",
|
||||
"Separator",
|
||||
"Assembly_CreateJointDistance",
|
||||
"Assembly_CreateJointParallel",
|
||||
"Assembly_CreateJointPerpendicular",
|
||||
"Assembly_CreateJointAngle",
|
||||
]
|
||||
self.title = translate("Assembly", "Constraints")
|
||||
|
||||
def shouldShow(self):
|
||||
if not super().shouldShow():
|
||||
return False
|
||||
return UtilsAssembly.assembly_has_at_least_n_parts(2)
|
||||
|
||||
class AssemblyToolsWatcher(AssemblyBaseWatcher):
|
||||
"""Shows Joint, View, and BOM tools when there are enough parts."""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.commands = [
|
||||
"Assembly_CreateView",
|
||||
"Assembly_CreateBom",
|
||||
]
|
||||
self.title = translate("Assembly", "Tools")
|
||||
|
||||
def shouldShow(self):
|
||||
if not super().shouldShow():
|
||||
return False
|
||||
return UtilsAssembly.assembly_has_at_least_n_parts(1)
|
||||
|
||||
class AssemblySimulationWatcher(AssemblyBaseWatcher):
|
||||
"""Shows 'Create Simulation' when specific motional joints exist."""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.commands = ["Assembly_CreateSimulation"]
|
||||
self.title = translate("Assembly", "Simulation")
|
||||
|
||||
def shouldShow(self):
|
||||
if not super().shouldShow():
|
||||
return False
|
||||
|
||||
joint_types = ["Revolute", "Slider", "Cylindrical"]
|
||||
joints = UtilsAssembly.getJointsOfType(self.assembly, joint_types)
|
||||
return len(joints) > 0
|
||||
|
||||
watchers = [
|
||||
AssemblyCreateWatcher(),
|
||||
AssemblyActivateWatcher(),
|
||||
AssemblyInsertWatcher(),
|
||||
AssemblyGroundWatcher(),
|
||||
AssemblyJointsWatcher(),
|
||||
AssemblyToolsWatcher(),
|
||||
AssemblySimulationWatcher(),
|
||||
]
|
||||
FreeCADGui.Control.addTaskWatcher(watchers)
|
||||
|
||||
|
||||
Gui.addWorkbench(AssemblyWorkbench())
|
||||
|
||||
Reference in New Issue
Block a user