Merge pull request #16220 from wwmayer/placementpy
Core: Expose Placement dialog to Python
This commit is contained in:
@@ -81,6 +81,7 @@
|
||||
#include "PythonDebugger.h"
|
||||
#include "MainWindowPy.h"
|
||||
#include "MDIViewPy.h"
|
||||
#include "Placement.h"
|
||||
#include "SoFCDB.h"
|
||||
#include "Selection.h"
|
||||
#include "SelectionFilterPy.h"
|
||||
@@ -359,6 +360,7 @@ struct PyMethodDef FreeCADGui_methods[] = {
|
||||
|
||||
} // namespace Gui
|
||||
|
||||
// clang-format off
|
||||
Application::Application(bool GUIenabled)
|
||||
{
|
||||
// App::GetApplication().Attach(this);
|
||||
@@ -452,6 +454,10 @@ Application::Application(bool GUIenabled)
|
||||
Base::Interpreter().addType(UiLoaderPy::type_object(), module, "UiLoader");
|
||||
PyResource::init_type();
|
||||
|
||||
Gui::Dialog::TaskPlacementPy::init_type();
|
||||
Base::Interpreter().addType(Gui::Dialog::TaskPlacementPy::type_object(),
|
||||
module, "TaskPlacement");
|
||||
|
||||
// PySide additions
|
||||
PyModule_AddObject(module, "PySideUic", Base::Interpreter().addModule(new PySideUicModule));
|
||||
|
||||
@@ -555,6 +561,7 @@ Application::Application(bool GUIenabled)
|
||||
MacroCommand::load();
|
||||
}
|
||||
}
|
||||
// clang-format on
|
||||
|
||||
Application::~Application()
|
||||
{
|
||||
|
||||
@@ -1562,6 +1562,7 @@ void StdCmdPlacement::activated(int iMsg)
|
||||
plm->setPropertyName(QLatin1String("Placement"));
|
||||
plm->setSelection(selection);
|
||||
plm->bindObject();
|
||||
plm->clearSelection();
|
||||
}
|
||||
}
|
||||
Gui::Control().showDialog(plm);
|
||||
|
||||
@@ -32,13 +32,16 @@
|
||||
|
||||
#include <App/ComplexGeoData.h>
|
||||
#include <App/Document.h>
|
||||
#include <App/DocumentObjectPy.h>
|
||||
#include <App/GeoFeature.h>
|
||||
#include <Base/Console.h>
|
||||
#include <Base/PlacementPy.h>
|
||||
#include <Base/Tools.h>
|
||||
#include <Gui/Application.h>
|
||||
#include <Gui/Command.h>
|
||||
#include <Gui/DockWindowManager.h>
|
||||
#include <Gui/Document.h>
|
||||
#include <Gui/PythonWrapper.h>
|
||||
#include <Gui/Selection.h>
|
||||
#include <Gui/ViewProvider.h>
|
||||
#include <Gui/Window.h>
|
||||
@@ -77,7 +80,8 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
static App::PropertyPlacement* getProperty(App::DocumentObject* obj, const std::string& propertyName)
|
||||
static App::PropertyPlacement* getProperty(const App::DocumentObject* obj,
|
||||
const std::string& propertyName)
|
||||
{
|
||||
std::map<std::string,App::Property*> props;
|
||||
obj->getPropertyMap(props);
|
||||
@@ -101,8 +105,9 @@ public:
|
||||
PlacementHandler::PlacementHandler()
|
||||
: propertyName{"Placement"}
|
||||
, changeProperty{false}
|
||||
, ignoreTransaction{false}
|
||||
{
|
||||
|
||||
setupDocument();
|
||||
}
|
||||
|
||||
void PlacementHandler::openTransactionIfNeeded()
|
||||
@@ -120,6 +125,38 @@ void PlacementHandler::setPropertyName(const std::string& name)
|
||||
changeProperty = (propertyName != "Placement");
|
||||
}
|
||||
|
||||
void PlacementHandler::setIgnoreTransactions(bool value)
|
||||
{
|
||||
ignoreTransaction = value;
|
||||
}
|
||||
|
||||
void PlacementHandler::setSelection(const std::vector<Gui::SelectionObject>& selection)
|
||||
{
|
||||
selectionObjects = selection;
|
||||
}
|
||||
|
||||
void PlacementHandler::reselectObjects()
|
||||
{
|
||||
//we have to clear selection and reselect original object(s)
|
||||
//else later on the rotation is applied twice because there will
|
||||
//be 2 (vertex) objects in the selection, and even if both are subobjects
|
||||
//of the same object the rotation still gets applied twice
|
||||
Gui::Selection().clearSelection();
|
||||
//reselect original object that was selected when placement dlg first opened
|
||||
for (const auto& it : selectionObjects) {
|
||||
Gui::Selection().addSelection(it);
|
||||
}
|
||||
}
|
||||
|
||||
const App::DocumentObject* PlacementHandler::getFirstOfSelection() const
|
||||
{
|
||||
if (!selectionObjects.empty()) {
|
||||
return selectionObjects.front().getObject();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const std::string& PlacementHandler::getPropertyName() const
|
||||
{
|
||||
return propertyName;
|
||||
@@ -155,25 +192,43 @@ void PlacementHandler::revertTransformation()
|
||||
revertTransformationOfViewProviders(document);
|
||||
}
|
||||
else {
|
||||
document->abortCommand();
|
||||
abortCommandIfActive(document);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<App::DocumentObject*> PlacementHandler::getObjects(Gui::Document* document) const
|
||||
std::vector<const App::DocumentObject*> PlacementHandler::getObjects(const Gui::Document* document) const
|
||||
{
|
||||
return document->getDocument()->getObjectsOfType(App::DocumentObject::getClassTypeId());
|
||||
auto objs = document->getDocument()->getObjectsOfType(App::DocumentObject::getClassTypeId());
|
||||
std::vector<const App::DocumentObject*> list;
|
||||
list.insert(list.begin(), objs.begin(), objs.end());
|
||||
return list;
|
||||
}
|
||||
|
||||
std::vector<App::DocumentObject*> PlacementHandler::getSelectedObjects(Gui::Document* document) const
|
||||
std::vector<const App::DocumentObject*> PlacementHandler::getSelectedObjects(const Gui::Document* document) const
|
||||
{
|
||||
return Gui::Selection().getObjectsOfType(App::DocumentObject::getClassTypeId(), document->getDocument()->getName());
|
||||
App::Document* doc = document->getDocument();
|
||||
std::vector<const App::DocumentObject*> list;
|
||||
list.reserve(selectionObjects.size());
|
||||
for (const auto& it : selectionObjects) {
|
||||
const App::DocumentObject* obj = it.getObject();
|
||||
if (obj && obj->getDocument() == doc) {
|
||||
list.push_back(obj);
|
||||
}
|
||||
}
|
||||
|
||||
if (list.empty()) {
|
||||
auto objs = Gui::Selection().getObjectsOfType(App::DocumentObject::getClassTypeId(), doc->getName());
|
||||
list.insert(list.begin(), objs.begin(), objs.end());
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
void PlacementHandler::revertTransformationOfViewProviders(Gui::Document* document)
|
||||
{
|
||||
std::vector<App::DocumentObject*> obj = getObjects(document);
|
||||
std::vector<const App::DocumentObject*> obj = getObjects(document);
|
||||
for (const auto & it : obj) {
|
||||
auto property = find_placement::getProperty(it, this->propertyName);
|
||||
if (property) {
|
||||
@@ -186,13 +241,23 @@ void PlacementHandler::revertTransformationOfViewProviders(Gui::Document* docume
|
||||
}
|
||||
}
|
||||
|
||||
void PlacementHandler::setRefPlacement(const Base::Placement& plm)
|
||||
{
|
||||
ref = plm;
|
||||
}
|
||||
|
||||
const Base::Placement& PlacementHandler::getRefPlacement() const
|
||||
{
|
||||
return ref;
|
||||
}
|
||||
|
||||
void PlacementHandler::applyPlacement(const Base::Placement& p, bool incremental)
|
||||
{
|
||||
Gui::Document* document = Application::Instance->activeDocument();
|
||||
if (!document)
|
||||
return;
|
||||
|
||||
std::vector<App::DocumentObject*> sel = getSelectedObjects(document);
|
||||
std::vector<const App::DocumentObject*> sel = getSelectedObjects(document);
|
||||
if (!sel.empty()) {
|
||||
for (const auto & it : sel) {
|
||||
applyPlacement(document, it, p, incremental);
|
||||
@@ -203,7 +268,8 @@ void PlacementHandler::applyPlacement(const Base::Placement& p, bool incremental
|
||||
}
|
||||
}
|
||||
|
||||
void PlacementHandler::applyPlacement(Gui::Document* document, App::DocumentObject* obj, const Base::Placement& p, bool incremental)
|
||||
void PlacementHandler::applyPlacement(const Gui::Document* document, const App::DocumentObject* obj,
|
||||
const Base::Placement& p, bool incremental)
|
||||
{
|
||||
auto property = find_placement::getProperty(obj, this->propertyName);
|
||||
if (property) {
|
||||
@@ -234,19 +300,18 @@ void PlacementHandler::applyPlacement(const QString& data, bool incremental)
|
||||
// When directly changing the property we now only have to commit the transaction,
|
||||
// do a recompute and open a new transaction
|
||||
if (changeProperty) {
|
||||
document->commitCommand();
|
||||
commitCommandIfActive(document);
|
||||
tryRecompute(document);
|
||||
document->openCommand(QT_TRANSLATE_NOOP("Command", "Placement"));
|
||||
openCommandIfActive(document);
|
||||
}
|
||||
else {
|
||||
std::vector<App::DocumentObject*> sel = getSelectedObjects(document);
|
||||
std::vector<const App::DocumentObject*> sel = getSelectedObjects(document);
|
||||
if (!sel.empty()) {
|
||||
document->openCommand(QT_TRANSLATE_NOOP("Command", "Placement"));
|
||||
openCommandIfActive(document);
|
||||
for (const auto & it : sel) {
|
||||
applyPlacement(it, data, incremental);
|
||||
}
|
||||
|
||||
document->commitCommand();
|
||||
commitCommandIfActive(document);
|
||||
tryRecompute(document);
|
||||
}
|
||||
else {
|
||||
@@ -255,7 +320,7 @@ void PlacementHandler::applyPlacement(const QString& data, bool incremental)
|
||||
}
|
||||
}
|
||||
|
||||
void PlacementHandler::applyPlacement(App::DocumentObject* obj, const QString& data, bool incremental)
|
||||
void PlacementHandler::applyPlacement(const App::DocumentObject* obj, const QString& data, bool incremental)
|
||||
{
|
||||
auto property = find_placement::getProperty(obj, this->propertyName);
|
||||
if (property) {
|
||||
@@ -271,7 +336,7 @@ void PlacementHandler::applyPlacement(App::DocumentObject* obj, const QString& d
|
||||
}
|
||||
}
|
||||
|
||||
QString PlacementHandler::getIncrementalPlacement(App::DocumentObject* obj, const QString& data) const
|
||||
QString PlacementHandler::getIncrementalPlacement(const App::DocumentObject* obj, const QString& data) const
|
||||
{
|
||||
return QString::fromLatin1(
|
||||
R"(App.getDocument("%1").%2.%3=%4.multiply(App.getDocument("%1").%2.%3))")
|
||||
@@ -281,7 +346,7 @@ QString PlacementHandler::getIncrementalPlacement(App::DocumentObject* obj, cons
|
||||
data);
|
||||
}
|
||||
|
||||
QString PlacementHandler::getSimplePlacement(App::DocumentObject* obj, const QString& data) const
|
||||
QString PlacementHandler::getSimplePlacement(const App::DocumentObject* obj, const QString& data) const
|
||||
{
|
||||
return QString::fromLatin1(
|
||||
"App.getDocument(\"%1\").%2.%3=%4")
|
||||
@@ -291,6 +356,52 @@ QString PlacementHandler::getSimplePlacement(App::DocumentObject* obj, const QSt
|
||||
data);
|
||||
}
|
||||
|
||||
Base::Vector3d PlacementHandler::computeCenterOfMass() const
|
||||
{
|
||||
Base::Vector3d centerOfMass;
|
||||
std::vector<App::DocumentObject*> sel = Gui::Selection().getObjectsOfType
|
||||
(App::GeoFeature::getClassTypeId());
|
||||
if (!sel.empty()) {
|
||||
for (auto it : sel) {
|
||||
const App::PropertyComplexGeoData* propgeo = static_cast<App::GeoFeature*>(it)->getPropertyOfGeometry();
|
||||
const Data::ComplexGeoData* geodata = propgeo ? propgeo->getComplexData() : nullptr;
|
||||
if (geodata && geodata->getCenterOfGravity(centerOfMass)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return centerOfMass;
|
||||
}
|
||||
|
||||
void PlacementHandler::setCenterOfMass(const Base::Vector3d& pnt)
|
||||
{
|
||||
cntOfMass = pnt;
|
||||
}
|
||||
|
||||
Base::Vector3d PlacementHandler::getCenterOfMass() const
|
||||
{
|
||||
return cntOfMass;
|
||||
}
|
||||
|
||||
std::tuple<Base::Vector3d, std::vector<Base::Vector3d>> PlacementHandler::getSelectedPoints() const
|
||||
{
|
||||
std::vector<Gui::SelectionObject> selection = Gui::Selection().getSelectionEx();
|
||||
std::vector<Base::Vector3d> picked;
|
||||
//combine all pickedpoints into single vector
|
||||
//even if points are from separate objects
|
||||
Base::Vector3d firstSelected; //first selected will be central point when 3 points picked
|
||||
for (auto it = selection.begin(); it != selection.end(); ++it) {
|
||||
std::vector<Base::Vector3d> points = it->getPickedPoints();
|
||||
if (it == selection.begin() && !points.empty()) {
|
||||
firstSelected = points[0];
|
||||
}
|
||||
|
||||
picked.insert(picked.begin(), points.begin(), points.end());
|
||||
}
|
||||
|
||||
return std::make_tuple(firstSelected, picked);
|
||||
}
|
||||
|
||||
void PlacementHandler::tryRecompute(Gui::Document* document)
|
||||
{
|
||||
try {
|
||||
@@ -300,6 +411,44 @@ void PlacementHandler::tryRecompute(Gui::Document* document)
|
||||
}
|
||||
}
|
||||
|
||||
void PlacementHandler::setupDocument()
|
||||
{
|
||||
//NOLINTBEGIN
|
||||
connectAct = Application::Instance->signalActiveDocument.connect
|
||||
(std::bind(&PlacementHandler::slotActiveDocument, this, sp::_1));
|
||||
//NOLINTEND
|
||||
App::Document* activeDoc = App::GetApplication().getActiveDocument();
|
||||
if (activeDoc) {
|
||||
appendDocument(activeDoc->getName());
|
||||
}
|
||||
}
|
||||
|
||||
void PlacementHandler::slotActiveDocument(const Gui::Document& doc)
|
||||
{
|
||||
activatedDocument(doc.getDocument()->getName());
|
||||
}
|
||||
|
||||
void PlacementHandler::openCommandIfActive(Gui::Document* doc)
|
||||
{
|
||||
if (!ignoreTransaction) {
|
||||
doc->openCommand(QT_TRANSLATE_NOOP("Command", "Placement"));
|
||||
}
|
||||
}
|
||||
|
||||
void PlacementHandler::commitCommandIfActive(Gui::Document* doc)
|
||||
{
|
||||
if (!ignoreTransaction) {
|
||||
doc->commitCommand();
|
||||
}
|
||||
}
|
||||
|
||||
void PlacementHandler::abortCommandIfActive(Gui::Document* doc)
|
||||
{
|
||||
if (!ignoreTransaction) {
|
||||
doc->abortCommand();
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/* TRANSLATOR Gui::Dialog::Placement */
|
||||
@@ -312,13 +461,11 @@ Placement::Placement(QWidget* parent, Qt::WindowFlags fl)
|
||||
setupConnections();
|
||||
setupUnits();
|
||||
setupSignalMapper();
|
||||
setupDocument();
|
||||
setupRotationMethod();
|
||||
}
|
||||
|
||||
Placement::~Placement()
|
||||
{
|
||||
connectAct.disconnect();
|
||||
delete ui;
|
||||
}
|
||||
|
||||
@@ -331,7 +478,8 @@ void Placement::setupUi()
|
||||
|
||||
void Placement::setupConnections()
|
||||
{
|
||||
connect(ui->applyButton, &QPushButton::clicked,
|
||||
QPushButton* applyButton = ui->buttonBox->button(QDialogButtonBox::Apply);
|
||||
connect(applyButton, &QPushButton::clicked,
|
||||
this, &Placement::onApplyButtonClicked);
|
||||
connect(ui->applyIncrementalPlacement, &QCheckBox::toggled,
|
||||
this, &Placement::onApplyIncrementalPlacementToggled);
|
||||
@@ -391,18 +539,6 @@ void Placement::setupSignalMapper()
|
||||
#endif
|
||||
}
|
||||
|
||||
void Placement::setupDocument()
|
||||
{
|
||||
//NOLINTBEGIN
|
||||
connectAct = Application::Instance->signalActiveDocument.connect
|
||||
(std::bind(&Placement::slotActiveDocument, this, sp::_1));
|
||||
//NOLINTEND
|
||||
App::Document* activeDoc = App::GetApplication().getActiveDocument();
|
||||
if (activeDoc) {
|
||||
handler.appendDocument(activeDoc->getName());
|
||||
}
|
||||
}
|
||||
|
||||
void Placement::setupRotationMethod()
|
||||
{
|
||||
ParameterGrp::handle hGrp = WindowParameter::getDefaultParameter()->GetGroup("Placement");
|
||||
@@ -413,9 +549,7 @@ void Placement::setupRotationMethod()
|
||||
|
||||
void Placement::showDefaultButtons(bool ok)
|
||||
{
|
||||
ui->oKButton->setVisible(ok);
|
||||
ui->closeButton->setVisible(ok);
|
||||
ui->applyButton->setVisible(ok);
|
||||
ui->buttonBox->setVisible(ok);
|
||||
ui->buttonBoxLayout->invalidate();
|
||||
if (ok) {
|
||||
ui->buttonBoxLayout->insertSpacerItem(0, ui->buttonBoxSpacer);
|
||||
@@ -430,11 +564,6 @@ void Placement::open()
|
||||
handler.openTransactionIfNeeded();
|
||||
}
|
||||
|
||||
void Placement::slotActiveDocument(const Gui::Document& doc)
|
||||
{
|
||||
handler.activatedDocument(doc.getDocument()->getName());
|
||||
}
|
||||
|
||||
QWidget* Placement::getInvalidInput() const
|
||||
{
|
||||
QList<Gui::QuantitySpinBox*> sb = this->findChildren<Gui::QuantitySpinBox*>();
|
||||
@@ -466,57 +595,31 @@ void Placement::onCenterOfMassToggled(bool on)
|
||||
ui->zCnt->setDisabled(on);
|
||||
|
||||
if (on) {
|
||||
cntOfMass = getCenterOfMass();
|
||||
ui->xCnt->setValue(cntOfMass.x);
|
||||
ui->yCnt->setValue(cntOfMass.y);
|
||||
ui->zCnt->setValue(cntOfMass.z);
|
||||
Base::Vector3d pnt = handler.computeCenterOfMass();
|
||||
handler.setCenterOfMass(pnt);
|
||||
ui->xCnt->setValue(pnt.x);
|
||||
ui->yCnt->setValue(pnt.y);
|
||||
ui->zCnt->setValue(pnt.z);
|
||||
}
|
||||
}
|
||||
|
||||
void Placement::onSelectedVertexClicked()
|
||||
{
|
||||
cntOfMass.Set(0,0,0);
|
||||
ui->centerOfMass->setChecked(false);
|
||||
|
||||
bool success=false;
|
||||
std::vector<Gui::SelectionObject> selection = Gui::Selection().getSelectionEx();
|
||||
std::vector<Base::Vector3d> picked;
|
||||
//combine all pickedpoints into single vector
|
||||
//even if points are from separate objects
|
||||
Base::Vector3d firstSelected; //first selected will be central point when 3 points picked
|
||||
for (auto it=selection.begin(); it!=selection.end(); ++it){
|
||||
std::vector<Base::Vector3d> points = it->getPickedPoints();
|
||||
if (it==selection.begin() && !points.empty()){
|
||||
firstSelected=points[0];
|
||||
}
|
||||
picked.insert(picked.begin(),points.begin(),points.end());
|
||||
}
|
||||
//we have to clear selection and reselect original object(s)
|
||||
//else later on the rotation is applied twice because there will
|
||||
//be 2 (vertex) objects in the selection, and even if both are subobjects
|
||||
//of the same object the rotation still gets applied twice
|
||||
Gui::Selection().clearSelection();
|
||||
//reselect original object that was selected when placement dlg first opened
|
||||
for (const auto& it : selectionObjects)
|
||||
Gui::Selection().addSelection(it);
|
||||
Base::Vector3d center;
|
||||
bool success = false;
|
||||
auto [firstSelected, picked] = handler.getSelectedPoints();
|
||||
handler.reselectObjects();
|
||||
|
||||
if (picked.size() == 1) {
|
||||
ui->xCnt->setValue(picked[0].x);
|
||||
ui->yCnt->setValue(picked[0].y);
|
||||
ui->zCnt->setValue(picked[0].z);
|
||||
cntOfMass.x=picked[0].x;
|
||||
cntOfMass.y=picked[0].y;
|
||||
cntOfMass.z=picked[0].z;
|
||||
success=true;
|
||||
center = picked[0];
|
||||
success = true;
|
||||
}
|
||||
else if (picked.size() == 2) {
|
||||
//average the coords to get center of rotation
|
||||
ui->xCnt->setValue((picked[0].x+picked[1].x)/2.0);
|
||||
ui->yCnt->setValue((picked[0].y+picked[1].y)/2.0);
|
||||
ui->zCnt->setValue((picked[0].z+picked[1].z)/2.0);
|
||||
cntOfMass.x=(picked[0].x+picked[1].x)/2.0;
|
||||
cntOfMass.y=(picked[0].y+picked[1].y)/2.0;
|
||||
cntOfMass.z=(picked[0].z+picked[1].z)/2.0;
|
||||
center = (picked[0] + picked[1]) / 2.0;
|
||||
|
||||
//setup a customized axis since the user selected 2 points
|
||||
//keep any existing angle, but setup our own axis
|
||||
Base::Placement plm = getPlacement();
|
||||
@@ -525,11 +628,11 @@ void Placement::onSelectedVertexClicked()
|
||||
double angle;
|
||||
rot.getRawValue(tmp, angle);
|
||||
Base::Vector3d axis;
|
||||
if (firstSelected==picked[0]){
|
||||
axis = Base::Vector3d(picked[1]-picked[0]);
|
||||
if (firstSelected == picked[0]){
|
||||
axis = Base::Vector3d(picked[1] - picked[0]);
|
||||
}
|
||||
else {
|
||||
axis = Base::Vector3d(picked[0]-picked[1]);
|
||||
axis = Base::Vector3d(picked[0] - picked[1]);
|
||||
}
|
||||
double length = axis.Length();
|
||||
Base::Console().Message("Distance: %.8f\n",length);
|
||||
@@ -546,7 +649,7 @@ void Placement::onSelectedVertexClicked()
|
||||
setPlacementData(plm); //creates custom axis, if needed
|
||||
ui->rotationInput->setCurrentIndex(0); //use rotation with axis instead of euler
|
||||
ui->stackedWidget->setCurrentIndex(0);
|
||||
success=true;
|
||||
success = true;
|
||||
}
|
||||
else if (picked.size() == 3){
|
||||
/* User selected 3 points, so we find the plane defined by those
|
||||
@@ -559,7 +662,7 @@ void Placement::onSelectedVertexClicked()
|
||||
a = picked[1];
|
||||
c = picked[2];
|
||||
}
|
||||
else if (picked[1]==firstSelected){
|
||||
else if (picked[1] == firstSelected){
|
||||
a = picked[0];
|
||||
c = picked[2];
|
||||
}
|
||||
@@ -570,12 +673,8 @@ void Placement::onSelectedVertexClicked()
|
||||
|
||||
Base::Vector3d norm((a-b).Cross(c-b));
|
||||
norm.Normalize();
|
||||
ui->xCnt->setValue(b.x);
|
||||
ui->yCnt->setValue(b.y);
|
||||
ui->zCnt->setValue(b.z);
|
||||
cntOfMass.x=b.x;
|
||||
cntOfMass.y=b.y;
|
||||
cntOfMass.z=b.z;
|
||||
center = b;
|
||||
|
||||
//setup a customized axis normal to the plane
|
||||
//keep any existing angle, but setup our own axis
|
||||
Base::Placement plm = getPlacement();
|
||||
@@ -604,10 +703,15 @@ void Placement::onSelectedVertexClicked()
|
||||
setPlacementData(plm); //creates custom axis, if needed
|
||||
ui->rotationInput->setCurrentIndex(0); //use rotation with axis instead of euler
|
||||
ui->stackedWidget->setCurrentIndex(0);
|
||||
success=true;
|
||||
success = true;
|
||||
}
|
||||
|
||||
if (!success){
|
||||
handler.setCenterOfMass(center);
|
||||
ui->xCnt->setValue(center.x);
|
||||
ui->yCnt->setValue(center.y);
|
||||
ui->zCnt->setValue(center.z);
|
||||
|
||||
if (!success) {
|
||||
Base::Console().Warning("Placement selection error. Select either 1 or 2 points.\n");
|
||||
QMessageBox msgBox;
|
||||
msgBox.setText(tr("Please select 1, 2, or 3 points before clicking this button. A point may be on a vertex, \
|
||||
@@ -619,10 +723,6 @@ lies on the vector that is normal to the plane defined by the 3 points. Some di
|
||||
information is provided in the report view, which can be useful when aligning objects. For your \
|
||||
convenience when Shift + click is used the appropriate distance or angle is copied to the clipboard."));
|
||||
msgBox.exec();
|
||||
ui->xCnt->setValue(0);
|
||||
ui->yCnt->setValue(0);
|
||||
ui->zCnt->setValue(0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -653,12 +753,12 @@ void Placement::onApplyAxialClicked()
|
||||
void Placement::onApplyIncrementalPlacementToggled(bool on)
|
||||
{
|
||||
if (on) {
|
||||
this->ref = getPlacementData();
|
||||
handler.setRefPlacement(getPlacementData());
|
||||
onResetButtonClicked();
|
||||
}
|
||||
else {
|
||||
Base::Placement p = getPlacementData();
|
||||
p = p * this->ref;
|
||||
p = p * handler.getRefPlacement();
|
||||
setPlacementData(p);
|
||||
onPlacementChanged(0);
|
||||
}
|
||||
@@ -767,14 +867,19 @@ void Placement::onResetButtonClicked()
|
||||
*/
|
||||
void Placement::setSelection(const std::vector<Gui::SelectionObject>& selection)
|
||||
{
|
||||
selectionObjects = selection;
|
||||
handler.setSelection(selection);
|
||||
}
|
||||
|
||||
void Placement::setPropertyName(const std::string& name)
|
||||
void Placement::setPropertyName(const std::string& name)
|
||||
{
|
||||
handler.setPropertyName(name);
|
||||
}
|
||||
|
||||
void Placement::setIgnoreTransactions(bool value)
|
||||
{
|
||||
handler.setIgnoreTransactions(value);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Placement::bindObject
|
||||
* Binds the spin boxes to the placement components of the first object of the selection.
|
||||
@@ -782,10 +887,34 @@ void Placement::setPropertyName(const std::string& name)
|
||||
*/
|
||||
void Placement::bindObject()
|
||||
{
|
||||
if (!selectionObjects.empty()) {
|
||||
App::DocumentObject* obj = selectionObjects.front().getObject();
|
||||
|
||||
if (const App::DocumentObject* obj = handler.getFirstOfSelection()) {
|
||||
std::string propertyName = handler.getPropertyName();
|
||||
bindProperty(obj, propertyName);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Placement::setPlacementAndBindObject
|
||||
* Sets the placement, binds the spin boxes to the placement components of the passed object and
|
||||
* sets the name of the placement property.
|
||||
*/
|
||||
void Placement::setPlacementAndBindObject(const App::DocumentObject* obj, const std::string& propertyName)
|
||||
{
|
||||
if (obj) {
|
||||
App::PropertyPlacement* prop = find_placement::getProperty(obj, propertyName);
|
||||
if (prop) {
|
||||
setPlacement(prop->getValue());
|
||||
handler.setPropertyName(propertyName);
|
||||
bindProperty(obj, propertyName);
|
||||
handler.setSelection({SelectionObject{obj}});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Placement::bindProperty(const App::DocumentObject* obj, const std::string& propertyName)
|
||||
{
|
||||
// clang-format off
|
||||
if (obj) {
|
||||
App::ObjectIdentifier path = App::ObjectIdentifier::parse(obj, propertyName);
|
||||
if (path.getProperty()) {
|
||||
ui->xPos->bind(App::ObjectIdentifier::parse(obj, propertyName + std::string(".Base.x")));
|
||||
@@ -806,6 +935,7 @@ void Placement::bindObject()
|
||||
ui->rollAngle->evaluateExpression();
|
||||
}
|
||||
}
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
Base::Vector3d Placement::getDirection() const
|
||||
@@ -883,30 +1013,14 @@ Base::Vector3d Placement::getAnglesData() const
|
||||
|
||||
Base::Vector3d Placement::getCenterData() const
|
||||
{
|
||||
if (ui->centerOfMass->isChecked())
|
||||
return this->cntOfMass;
|
||||
if (ui->centerOfMass->isChecked()) {
|
||||
return handler.getCenterOfMass();
|
||||
}
|
||||
return Base::Vector3d(ui->xCnt->value().getValue(),
|
||||
ui->yCnt->value().getValue(),
|
||||
ui->zCnt->value().getValue());
|
||||
}
|
||||
|
||||
Base::Vector3d Placement::getCenterOfMass() const
|
||||
{
|
||||
Base::Vector3d centerOfMass;
|
||||
std::vector<App::DocumentObject*> sel = Gui::Selection().getObjectsOfType
|
||||
(App::GeoFeature::getClassTypeId());
|
||||
if (!sel.empty()) {
|
||||
for (auto it : sel) {
|
||||
const App::PropertyComplexGeoData* propgeo = static_cast<App::GeoFeature*>(it)->getPropertyOfGeometry();
|
||||
const Data::ComplexGeoData* geodata = propgeo ? propgeo->getComplexData() : nullptr;
|
||||
if (geodata && geodata->getCenterOfGravity(centerOfMass)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return centerOfMass;
|
||||
}
|
||||
|
||||
Base::Placement Placement::getPlacementData() const
|
||||
{
|
||||
Base::Rotation rot = getRotationData();
|
||||
@@ -1037,6 +1151,15 @@ void TaskPlacement::setSelection(const std::vector<Gui::SelectionObject>& select
|
||||
widget->setSelection(selection);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief TaskPlacement::clearSelection
|
||||
* Clears the array of selection objects.
|
||||
*/
|
||||
void TaskPlacement::clearSelection()
|
||||
{
|
||||
widget->setSelection({});
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief TaskPlacement::bindObject
|
||||
* Binds the spin boxes to the placement components of the first object of the selection.
|
||||
@@ -1047,6 +1170,12 @@ void TaskPlacement::bindObject()
|
||||
widget->bindObject();
|
||||
}
|
||||
|
||||
void TaskPlacement::setPlacementAndBindObject(const App::DocumentObject* obj,
|
||||
const std::string& propertyName)
|
||||
{
|
||||
widget->setPlacementAndBindObject(obj, propertyName);
|
||||
}
|
||||
|
||||
void TaskPlacement::open()
|
||||
{
|
||||
widget->open();
|
||||
@@ -1093,4 +1222,270 @@ void TaskPlacement::clicked(int id)
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------
|
||||
|
||||
void TaskPlacementPy::init_type()
|
||||
{
|
||||
behaviors().name("TaskPlacement");
|
||||
behaviors().doc("TaskPlacement");
|
||||
behaviors().set_tp_new(PyMake);
|
||||
// you must have overwritten the virtual functions
|
||||
behaviors().supportRepr();
|
||||
behaviors().supportGetattr();
|
||||
behaviors().supportSetattr();
|
||||
// clang-format off
|
||||
add_varargs_method("setPropertyName", &TaskPlacementPy::setPropertyName,
|
||||
"setPropertyName(string)");
|
||||
add_varargs_method("setPlacement", &TaskPlacementPy::setPlacement,
|
||||
"setPlacement(Placement)");
|
||||
add_varargs_method("setSelection", &TaskPlacementPy::setSelection,
|
||||
"setSelection(list)");
|
||||
add_varargs_method("bindObject", &TaskPlacementPy::bindObject,
|
||||
"bindObject()");
|
||||
add_varargs_method("setPlacementAndBindObject", &TaskPlacementPy::setPlacementAndBindObject,
|
||||
"setPlacementAndBindObject(obj, string)");
|
||||
add_varargs_method("setIgnoreTransactions", &TaskPlacementPy::setIgnoreTransactions,
|
||||
"setIgnoreTransactions(bool)");
|
||||
add_varargs_method("showDefaultButtons", &TaskPlacementPy::showDefaultButtons,
|
||||
"showDefaultButtons(bool)");
|
||||
add_varargs_method("accept", &TaskPlacementPy::accept,
|
||||
"accept()");
|
||||
add_varargs_method("reject", &TaskPlacementPy::reject,
|
||||
"reject()");
|
||||
add_varargs_method("clicked", &TaskPlacementPy::clicked,
|
||||
"clicked()");
|
||||
add_varargs_method("open", &TaskPlacementPy::open,
|
||||
"open()");
|
||||
add_varargs_method("isAllowedAlterDocument", &TaskPlacementPy::isAllowedAlterDocument,
|
||||
"isAllowedAlterDocument()");
|
||||
add_varargs_method("isAllowedAlterView", &TaskPlacementPy::isAllowedAlterView,
|
||||
"isAllowedAlterView()");
|
||||
add_varargs_method("isAllowedAlterSelection", &TaskPlacementPy::isAllowedAlterSelection,
|
||||
"isAllowedAlterSelection()");
|
||||
add_varargs_method("getStandardButtons", &TaskPlacementPy::getStandardButtons,
|
||||
"getStandardButtons()");
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
PyObject* TaskPlacementPy::PyMake(struct _typeobject * type, PyObject * args, PyObject * kwds)
|
||||
{
|
||||
Q_UNUSED(type)
|
||||
Q_UNUSED(kwds)
|
||||
if (!PyArg_ParseTuple(args, "")) {
|
||||
return nullptr;
|
||||
}
|
||||
return new TaskPlacementPy();
|
||||
}
|
||||
|
||||
TaskPlacementPy::TaskPlacementPy()
|
||||
: widget{new Placement}
|
||||
{
|
||||
}
|
||||
|
||||
TaskPlacementPy::~TaskPlacementPy() = default;
|
||||
|
||||
Py::Object TaskPlacementPy::repr()
|
||||
{
|
||||
return Py::String("TaskPlacement");
|
||||
}
|
||||
|
||||
Py::Object TaskPlacementPy::getattr(const char * name)
|
||||
{
|
||||
if (strcmp(name, "form") == 0) {
|
||||
Gui::PythonWrapper wrap;
|
||||
wrap.loadWidgetsModule();
|
||||
return wrap.fromQWidget(widget, "QDialog");
|
||||
}
|
||||
return BaseType::getattr(name);
|
||||
}
|
||||
|
||||
int TaskPlacementPy::setattr(const char* name, const Py::Object& attr)
|
||||
{
|
||||
if (strcmp(name, "form") == 0 && attr.isNone()) {
|
||||
delete widget;
|
||||
widget = nullptr;
|
||||
return {};
|
||||
}
|
||||
return BaseType::setattr(name, attr);
|
||||
}
|
||||
|
||||
Py::Object TaskPlacementPy::setPropertyName(const Py::Tuple& args)
|
||||
{
|
||||
const char* propname {};
|
||||
if (!PyArg_ParseTuple(args.ptr(), "s", &propname)) {
|
||||
throw Py::Exception();
|
||||
}
|
||||
|
||||
if (widget) {
|
||||
widget->setPropertyName(propname);
|
||||
}
|
||||
return Py::None();
|
||||
}
|
||||
|
||||
Py::Object TaskPlacementPy::setPlacement(const Py::Tuple& args)
|
||||
{
|
||||
PyObject* plm {};
|
||||
if (!PyArg_ParseTuple(args.ptr(), "O!", &Base::PlacementPy::Type, &plm)) {
|
||||
throw Py::Exception();
|
||||
}
|
||||
|
||||
if (widget) {
|
||||
widget->setPlacement(*static_cast<Base::PlacementPy*>(plm)->getPlacementPtr());
|
||||
}
|
||||
return Py::None();
|
||||
}
|
||||
|
||||
Py::Object TaskPlacementPy::setSelection(const Py::Tuple& args)
|
||||
{
|
||||
std::vector<Gui::SelectionObject> sel;
|
||||
Py::Sequence list(args[0]);
|
||||
|
||||
for (const auto& obj : list) {
|
||||
if (PyObject_TypeCheck(obj.ptr(), &App::DocumentObjectPy::Type)) {
|
||||
auto doc = static_cast<App::DocumentObjectPy*>(obj.ptr());
|
||||
sel.emplace_back(doc->getDocumentObjectPtr());
|
||||
}
|
||||
}
|
||||
|
||||
if (widget) {
|
||||
widget->setSelection(sel);
|
||||
}
|
||||
return Py::None();
|
||||
}
|
||||
|
||||
Py::Object TaskPlacementPy::bindObject(const Py::Tuple& args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args.ptr(), "")) {
|
||||
throw Py::Exception();
|
||||
}
|
||||
|
||||
if (widget) {
|
||||
widget->bindObject();
|
||||
}
|
||||
|
||||
return Py::None();
|
||||
}
|
||||
|
||||
Py::Object TaskPlacementPy::setPlacementAndBindObject(const Py::Tuple& args)
|
||||
{
|
||||
Py::Object object = args[0];
|
||||
Py::String name = args[1];
|
||||
std::string propName = static_cast<std::string>(name);
|
||||
|
||||
if (PyObject_TypeCheck(object.ptr(), &App::DocumentObjectPy::Type)) {
|
||||
auto py = static_cast<App::DocumentObjectPy*>(object.ptr());
|
||||
auto obj = py->getDocumentObjectPtr();
|
||||
|
||||
if (widget) {
|
||||
widget->setPlacementAndBindObject(obj, propName);
|
||||
}
|
||||
}
|
||||
|
||||
return Py::None();
|
||||
}
|
||||
|
||||
Py::Object TaskPlacementPy::setIgnoreTransactions(const Py::Tuple& args)
|
||||
{
|
||||
if (widget) {
|
||||
widget->setIgnoreTransactions(Py::Boolean(args[0]));
|
||||
}
|
||||
return Py::None();
|
||||
}
|
||||
|
||||
Py::Object TaskPlacementPy::showDefaultButtons(const Py::Tuple& args)
|
||||
{
|
||||
if (widget) {
|
||||
widget->showDefaultButtons(Py::Boolean(args[0]));
|
||||
}
|
||||
return Py::None();
|
||||
}
|
||||
|
||||
Py::Object TaskPlacementPy::accept(const Py::Tuple& args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args.ptr(), "")) {
|
||||
throw Py::Exception();
|
||||
}
|
||||
|
||||
bool res = true;
|
||||
if (widget) {
|
||||
widget->accept();
|
||||
res = widget->result() == QDialog::Accepted;
|
||||
}
|
||||
return Py::Boolean(res);
|
||||
}
|
||||
|
||||
Py::Object TaskPlacementPy::reject(const Py::Tuple& args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args.ptr(), "")) {
|
||||
throw Py::Exception();
|
||||
}
|
||||
|
||||
bool res = true;
|
||||
if (widget) {
|
||||
widget->reject();
|
||||
res = widget->result() == QDialog::Rejected;
|
||||
}
|
||||
return Py::Boolean(res);
|
||||
}
|
||||
|
||||
Py::Object TaskPlacementPy::clicked(const Py::Tuple& args)
|
||||
{
|
||||
int index {};
|
||||
if (!PyArg_ParseTuple(args.ptr(), "i", &index)) {
|
||||
throw Py::Exception();
|
||||
}
|
||||
|
||||
if (widget && index == QDialogButtonBox::Apply) {
|
||||
widget->onApplyButtonClicked();
|
||||
}
|
||||
return Py::None();
|
||||
}
|
||||
|
||||
Py::Object TaskPlacementPy::open(const Py::Tuple& args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args.ptr(), "")) {
|
||||
throw Py::Exception();
|
||||
}
|
||||
|
||||
if (widget) {
|
||||
widget->open();
|
||||
}
|
||||
return Py::None();
|
||||
}
|
||||
|
||||
Py::Object TaskPlacementPy::isAllowedAlterDocument(const Py::Tuple& args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args.ptr(), "")) {
|
||||
throw Py::Exception();
|
||||
}
|
||||
return Py::Boolean(true);
|
||||
}
|
||||
|
||||
Py::Object TaskPlacementPy::isAllowedAlterView(const Py::Tuple& args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args.ptr(), "")) {
|
||||
throw Py::Exception();
|
||||
}
|
||||
return Py::Boolean(true);
|
||||
}
|
||||
|
||||
Py::Object TaskPlacementPy::isAllowedAlterSelection(const Py::Tuple& args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args.ptr(), "")) {
|
||||
throw Py::Exception();
|
||||
}
|
||||
return Py::Boolean(true);
|
||||
}
|
||||
|
||||
Py::Object TaskPlacementPy::getStandardButtons(const Py::Tuple& args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args.ptr(), "")) {
|
||||
throw Py::Exception();
|
||||
}
|
||||
auto buttons = QDialogButtonBox::Ok|
|
||||
QDialogButtonBox::Cancel|
|
||||
QDialogButtonBox::Apply;
|
||||
return Py::Long(static_cast<int>(buttons));
|
||||
}
|
||||
|
||||
#include "moc_Placement.cpp"
|
||||
|
||||
@@ -51,33 +51,62 @@ public:
|
||||
PlacementHandler();
|
||||
void openTransactionIfNeeded();
|
||||
void setPropertyName(const std::string&);
|
||||
void setIgnoreTransactions(bool value);
|
||||
void setSelection(const std::vector<SelectionObject>&);
|
||||
void reselectObjects();
|
||||
const App::DocumentObject* getFirstOfSelection() const;
|
||||
const std::string& getPropertyName() const;
|
||||
void appendDocument(const std::string&);
|
||||
void activatedDocument(const std::string&);
|
||||
void revertTransformation();
|
||||
void setRefPlacement(const Base::Placement& plm);
|
||||
const Base::Placement& getRefPlacement() const;
|
||||
void applyPlacement(const Base::Placement& p, bool incremental);
|
||||
void applyPlacement(const QString& p, bool incremental);
|
||||
Base::Vector3d computeCenterOfMass() const;
|
||||
void setCenterOfMass(const Base::Vector3d& pnt);
|
||||
Base::Vector3d getCenterOfMass() const;
|
||||
std::tuple<Base::Vector3d, std::vector<Base::Vector3d>> getSelectedPoints() const;
|
||||
|
||||
private:
|
||||
std::vector<App::DocumentObject*> getObjects(Gui::Document*) const;
|
||||
std::vector<App::DocumentObject*> getSelectedObjects(Gui::Document*) const;
|
||||
std::vector<const App::DocumentObject*> getObjects(const Gui::Document*) const;
|
||||
std::vector<const App::DocumentObject*> getSelectedObjects(const Gui::Document*) const;
|
||||
void revertTransformationOfViewProviders(Gui::Document*);
|
||||
void tryRecompute(Gui::Document*);
|
||||
void applyPlacement(Gui::Document*, App::DocumentObject*, const Base::Placement& p, bool incremental);
|
||||
void applyPlacement(App::DocumentObject*, const QString& p, bool incremental);
|
||||
QString getIncrementalPlacement(App::DocumentObject*, const QString&) const;
|
||||
QString getSimplePlacement(App::DocumentObject*, const QString&) const;
|
||||
void applyPlacement(const Gui::Document*, const App::DocumentObject*,
|
||||
const Base::Placement& p, bool incremental);
|
||||
void applyPlacement(const App::DocumentObject*, const QString& p, bool incremental);
|
||||
QString getIncrementalPlacement(const App::DocumentObject*, const QString&) const;
|
||||
QString getSimplePlacement(const App::DocumentObject*, const QString&) const;
|
||||
void setupDocument();
|
||||
void slotActiveDocument(const Gui::Document&);
|
||||
void openCommandIfActive(Gui::Document*);
|
||||
void commitCommandIfActive(Gui::Document*);
|
||||
void abortCommandIfActive(Gui::Document*);
|
||||
|
||||
private Q_SLOTS:
|
||||
void openTransaction();
|
||||
|
||||
private:
|
||||
using Connection = boost::signals2::scoped_connection;
|
||||
std::string propertyName; // the name of the placement property
|
||||
std::set<std::string> documents;
|
||||
/** If false apply the placement directly to the transform nodes,
|
||||
* otherwise change the placement property.
|
||||
*/
|
||||
bool changeProperty;
|
||||
/** If true do not open or commit transactions. In this case it's expected
|
||||
* that it's done by the calling instance.
|
||||
*/
|
||||
bool ignoreTransaction;
|
||||
Connection connectAct;
|
||||
/**
|
||||
* store these so we can reselect original object
|
||||
* after user selects points and clicks Selected point(s)
|
||||
*/
|
||||
std::vector<SelectionObject> selectionObjects;
|
||||
Base::Placement ref;
|
||||
Base::Vector3d cntOfMass;
|
||||
};
|
||||
|
||||
class GuiExport Placement : public QDialog
|
||||
@@ -94,6 +123,9 @@ public:
|
||||
void setPropertyName(const std::string&);
|
||||
void setSelection(const std::vector<SelectionObject>&);
|
||||
void bindObject();
|
||||
void setPlacementAndBindObject(const App::DocumentObject* obj,
|
||||
const std::string& propertyName);
|
||||
void setIgnoreTransactions(bool value);
|
||||
Base::Vector3d getDirection() const;
|
||||
void setPlacement(const Base::Placement&);
|
||||
Base::Placement getPlacement() const;
|
||||
@@ -119,8 +151,8 @@ private:
|
||||
void setupConnections();
|
||||
void setupUnits();
|
||||
void setupSignalMapper();
|
||||
void setupDocument();
|
||||
void setupRotationMethod();
|
||||
void bindProperty(const App::DocumentObject* obj, const std::string& propertyName);
|
||||
|
||||
bool onApply();
|
||||
void setPlacementData(const Base::Placement&);
|
||||
@@ -129,11 +161,9 @@ private:
|
||||
Base::Vector3d getPositionData() const;
|
||||
Base::Vector3d getAnglesData() const;
|
||||
Base::Vector3d getCenterData() const;
|
||||
Base::Vector3d getCenterOfMass() const;
|
||||
QString getPlacementString() const;
|
||||
QString getPlacementFromEulerAngles() const;
|
||||
QString getPlacementFromAxisWithAngle() const;
|
||||
void slotActiveDocument(const Gui::Document&);
|
||||
QWidget* getInvalidInput() const;
|
||||
void showErrorMessage();
|
||||
|
||||
@@ -141,18 +171,9 @@ Q_SIGNALS:
|
||||
void placementChanged(const QVariant &, bool, bool);
|
||||
|
||||
private:
|
||||
using Connection = boost::signals2::connection;
|
||||
Ui_Placement* ui;
|
||||
QSignalMapper* signalMapper;
|
||||
Connection connectAct;
|
||||
PlacementHandler handler;
|
||||
Base::Placement ref;
|
||||
Base::Vector3d cntOfMass;
|
||||
/**
|
||||
* store these so we can reselect original object
|
||||
* after user selects points and clicks Selected point(s)
|
||||
*/
|
||||
std::vector<SelectionObject> selectionObjects;
|
||||
};
|
||||
|
||||
class GuiExport DockablePlacement : public Placement
|
||||
@@ -179,7 +200,10 @@ public:
|
||||
void setPropertyName(const QString&);
|
||||
void setPlacement(const Base::Placement&);
|
||||
void setSelection(const std::vector<SelectionObject>&);
|
||||
void clearSelection();
|
||||
void bindObject();
|
||||
void setPlacementAndBindObject(const App::DocumentObject* obj,
|
||||
const std::string& propertyName);
|
||||
bool accept() override;
|
||||
bool reject() override;
|
||||
void clicked(int id) override;
|
||||
@@ -203,6 +227,43 @@ private:
|
||||
Placement* widget;
|
||||
};
|
||||
|
||||
class TaskPlacementPy: public Py::PythonExtension<TaskPlacementPy>
|
||||
{
|
||||
public:
|
||||
using BaseType = Py::PythonExtension<TaskPlacementPy>;
|
||||
static void init_type();
|
||||
|
||||
TaskPlacementPy();
|
||||
~TaskPlacementPy() override;
|
||||
|
||||
Py::Object repr() override;
|
||||
Py::Object getattr(const char* name) override;
|
||||
int setattr(const char* name, const Py::Object&) override;
|
||||
|
||||
Py::Object setPropertyName(const Py::Tuple&);
|
||||
Py::Object setPlacement(const Py::Tuple&);
|
||||
Py::Object setSelection(const Py::Tuple&);
|
||||
Py::Object bindObject(const Py::Tuple&);
|
||||
Py::Object setPlacementAndBindObject(const Py::Tuple&);
|
||||
Py::Object setIgnoreTransactions(const Py::Tuple&);
|
||||
|
||||
Py::Object showDefaultButtons(const Py::Tuple&);
|
||||
Py::Object accept(const Py::Tuple&);
|
||||
Py::Object reject(const Py::Tuple&);
|
||||
Py::Object clicked(const Py::Tuple&);
|
||||
Py::Object open(const Py::Tuple&);
|
||||
Py::Object isAllowedAlterDocument(const Py::Tuple&);
|
||||
Py::Object isAllowedAlterView(const Py::Tuple&);
|
||||
Py::Object isAllowedAlterSelection(const Py::Tuple&);
|
||||
Py::Object getStandardButtons(const Py::Tuple&);
|
||||
|
||||
private:
|
||||
static PyObject* PyMake(struct _typeobject*, PyObject*, PyObject*);
|
||||
|
||||
private:
|
||||
QPointer<Placement> widget;
|
||||
};
|
||||
|
||||
} // namespace Dialog
|
||||
} // namespace Gui
|
||||
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>277</width>
|
||||
<height>394</height>
|
||||
<width>456</width>
|
||||
<height>492</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@@ -233,7 +233,7 @@
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<item row="1" column="0">
|
||||
<widget class="QStackedWidget" name="stackedWidget">
|
||||
<property name="currentIndex">
|
||||
<number>1</number>
|
||||
@@ -415,7 +415,7 @@
|
||||
<widget class="QWidget" name="page_2"/>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
@@ -487,23 +487,9 @@
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="oKButton">
|
||||
<property name="text">
|
||||
<string>OK</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="closeButton">
|
||||
<property name="text">
|
||||
<string>Close</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="applyButton">
|
||||
<property name="text">
|
||||
<string>Apply</string>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -525,44 +511,9 @@
|
||||
<tabstop>yAxis</tabstop>
|
||||
<tabstop>zAxis</tabstop>
|
||||
<tabstop>applyIncrementalPlacement</tabstop>
|
||||
<tabstop>oKButton</tabstop>
|
||||
<tabstop>applyButton</tabstop>
|
||||
<tabstop>closeButton</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>oKButton</sender>
|
||||
<signal>clicked()</signal>
|
||||
<receiver>Gui::Dialog::Placement</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>164</x>
|
||||
<y>252</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>8</x>
|
||||
<y>28</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>closeButton</sender>
|
||||
<signal>clicked()</signal>
|
||||
<receiver>Gui::Dialog::Placement</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>354</x>
|
||||
<y>252</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>291</x>
|
||||
<y>179</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>rotationInput</sender>
|
||||
<signal>activated(int)</signal>
|
||||
@@ -579,5 +530,37 @@
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>Gui::Dialog::Placement</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>310</x>
|
||||
<y>469</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>227</x>
|
||||
<y>245</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>Gui::Dialog::Placement</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>310</x>
|
||||
<y>469</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>227</x>
|
||||
<y>245</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
|
||||
@@ -53,7 +53,7 @@ SelectionObject::SelectionObject(const Gui::SelectionChanges& msg)
|
||||
}
|
||||
}
|
||||
|
||||
SelectionObject::SelectionObject(App::DocumentObject* obj)
|
||||
SelectionObject::SelectionObject(const App::DocumentObject* obj)
|
||||
{
|
||||
FeatName = obj->getNameInDocument();
|
||||
DocName = obj->getDocument()->getName();
|
||||
|
||||
@@ -50,7 +50,7 @@ public:
|
||||
/*! Constructs a SelectionObject from the SelectionChanges structure.
|
||||
*/
|
||||
explicit SelectionObject(const SelectionChanges& msg);
|
||||
explicit SelectionObject(App::DocumentObject*);
|
||||
explicit SelectionObject(const App::DocumentObject*);
|
||||
~SelectionObject() override;
|
||||
/**
|
||||
* The default implementation returns an instance of @ref SelectionObjectPy.
|
||||
|
||||
@@ -279,13 +279,12 @@ Transform::Transform(QWidget* parent, Qt::WindowFlags fl)
|
||||
{
|
||||
ui = new Ui_Placement();
|
||||
ui->setupUi(this);
|
||||
connect(ui->applyButton, &QPushButton::clicked,
|
||||
QPushButton* applyButton = ui->buttonBox->button(QDialogButtonBox::Apply);
|
||||
connect(applyButton, &QPushButton::clicked,
|
||||
this, &Transform::onApplyButtonClicked);
|
||||
|
||||
ui->resetButton->hide();
|
||||
ui->applyIncrementalPlacement->hide();
|
||||
|
||||
ui->closeButton->setText(tr("Cancel"));
|
||||
this->setWindowTitle(tr("Transform"));
|
||||
|
||||
// create a signal mapper in order to have one slot to perform the change
|
||||
@@ -332,9 +331,7 @@ void Transform::setTransformStrategy(TransformStrategy* ts)
|
||||
|
||||
void Transform::showStandardButtons(bool b)
|
||||
{
|
||||
ui->closeButton->setVisible(b);
|
||||
ui->oKButton->setVisible(b);
|
||||
ui->applyButton->setVisible(b);
|
||||
ui->buttonBox->setVisible(b);
|
||||
}
|
||||
|
||||
void Transform::onTransformChanged(int)
|
||||
@@ -413,7 +410,6 @@ void Transform::changeEvent(QEvent *e)
|
||||
{
|
||||
if (e->type() == QEvent::LanguageChange) {
|
||||
ui->retranslateUi(this);
|
||||
ui->closeButton->setText(tr("Cancel"));
|
||||
this->setWindowTitle(tr("Transform"));
|
||||
}
|
||||
else {
|
||||
|
||||
Reference in New Issue
Block a user