diff --git a/src/Gui/Placement.cpp b/src/Gui/Placement.cpp index da94499696..819fa7473f 100644 --- a/src/Gui/Placement.cpp +++ b/src/Gui/Placement.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include "Placement.h" #include "ui_Placement.h" @@ -82,6 +83,7 @@ public: Placement::Placement(QWidget* parent, Qt::WindowFlags fl) : Gui::LocationDialog(parent, fl) + , changeProperty(false) { selectionObjects = Gui::Selection().getSelectionEx(); @@ -138,9 +140,28 @@ void Placement::showDefaultButtons(bool ok) ui->applyButton->setVisible(ok); } +void Placement::open() +{ + if (propertyName != "Placement") { + changeProperty = true; + openTransaction(); + } +} + void Placement::slotActiveDocument(const Gui::Document& doc) { documents.insert(doc.getDocument()->getName()); + + if (changeProperty) { + QMetaObject::invokeMethod(this, "openTransaction", Qt::QueuedConnection); + } +} + +void Placement::openTransaction() +{ + App::Document* activeDoc = App::GetApplication().getActiveDocument(); + if (activeDoc) + activeDoc->openTransaction("Placement"); } QWidget* Placement::getInvalidInput() const @@ -159,22 +180,28 @@ void Placement::revertTransformation() Gui::Document* document = Application::Instance->getDocument(it->c_str()); if (!document) continue; - std::vector obj = document->getDocument()-> - getObjectsOfType(App::DocumentObject::getClassTypeId()); - if (!obj.empty()) { - for (std::vector::iterator it=obj.begin();it!=obj.end();++it) { - std::map props; - (*it)->getPropertyMap(props); - // search for the placement property - std::map::iterator jt; - jt = std::find_if(props.begin(), props.end(), find_placement(this->propertyName)); - if (jt != props.end()) { - Base::Placement cur = static_cast(jt->second)->getValue(); - Gui::ViewProvider* vp = document->getViewProvider(*it); - if (vp) vp->setTransformation(cur.toMatrix()); + if (!changeProperty) { + std::vector obj = document->getDocument()-> + getObjectsOfType(App::DocumentObject::getClassTypeId()); + if (!obj.empty()) { + for (std::vector::iterator it=obj.begin();it!=obj.end();++it) { + std::map props; + (*it)->getPropertyMap(props); + // search for the placement property + std::map::iterator jt; + jt = std::find_if(props.begin(), props.end(), find_placement(this->propertyName)); + if (jt != props.end()) { + App::PropertyPlacement* property = static_cast(jt->second); + Base::Placement cur = property->getValue(); + Gui::ViewProvider* vp = document->getViewProvider(*it); + if (vp) vp->setTransformation(cur.toMatrix()); + } } } } + else { + document->abortCommand(); + } } } @@ -194,14 +221,20 @@ void Placement::applyPlacement(const Base::Placement& p, bool incremental) std::map::iterator jt; jt = std::find_if(props.begin(), props.end(), find_placement(this->propertyName)); if (jt != props.end()) { - Base::Placement cur = static_cast(jt->second)->getValue(); + App::PropertyPlacement* property = static_cast(jt->second); + Base::Placement cur = property->getValue(); if (incremental) cur = p * cur; else cur = p; - Gui::ViewProvider* vp = document->getViewProvider(*it); - if (vp) vp->setTransformation(cur.toMatrix()); + if (!changeProperty) { + Gui::ViewProvider* vp = document->getViewProvider(*it); + if (vp) vp->setTransformation(cur.toMatrix()); + } + else { + property->setValue(cur); + } } } } @@ -215,47 +248,60 @@ void Placement::applyPlacement(const QString& data, bool incremental) Gui::Document* document = Application::Instance->activeDocument(); if (!document) return; - std::vector sel = Gui::Selection().getObjectsOfType - (App::DocumentObject::getClassTypeId(), document->getDocument()->getName()); - if (!sel.empty()) { - document->openCommand("Placement"); - for (std::vector::iterator it=sel.begin();it!=sel.end();++it) { - std::map props; - (*it)->getPropertyMap(props); - // search for the placement property - std::map::iterator jt; - jt = std::find_if(props.begin(), props.end(), find_placement(this->propertyName)); - if (jt != props.end()) { - QString cmd; - if (incremental) - cmd = QString::fromLatin1( - "App.getDocument(\"%1\").%2.%3=%4.multiply(App.getDocument(\"%1\").%2.%3)") - .arg(QLatin1String((*it)->getDocument()->getName())) - .arg(QLatin1String((*it)->getNameInDocument())) - .arg(QLatin1String(this->propertyName.c_str())) - .arg(data); - else { - cmd = QString::fromLatin1( - "App.getDocument(\"%1\").%2.%3=%4") - .arg(QLatin1String((*it)->getDocument()->getName())) - .arg(QLatin1String((*it)->getNameInDocument())) - .arg(QLatin1String(this->propertyName.c_str())) - .arg(data); - } - - Gui::Command::runCommand(Gui::Command::App, cmd.toLatin1()); - } - } - + // 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(); try { document->getDocument()->recompute(); } catch (...) { } + document->openCommand("Placement"); } else { - Base::Console().Warning("No object selected.\n"); + std::vector sel = Gui::Selection().getObjectsOfType + (App::DocumentObject::getClassTypeId(), document->getDocument()->getName()); + if (!sel.empty()) { + document->openCommand("Placement"); + for (std::vector::iterator it=sel.begin();it!=sel.end();++it) { + std::map props; + (*it)->getPropertyMap(props); + // search for the placement property + std::map::iterator jt; + jt = std::find_if(props.begin(), props.end(), find_placement(this->propertyName)); + if (jt != props.end()) { + QString cmd; + if (incremental) + cmd = QString::fromLatin1( + "App.getDocument(\"%1\").%2.%3=%4.multiply(App.getDocument(\"%1\").%2.%3)") + .arg(QLatin1String((*it)->getDocument()->getName())) + .arg(QLatin1String((*it)->getNameInDocument())) + .arg(QLatin1String(this->propertyName.c_str())) + .arg(data); + else { + cmd = QString::fromLatin1( + "App.getDocument(\"%1\").%2.%3=%4") + .arg(QLatin1String((*it)->getDocument()->getName())) + .arg(QLatin1String((*it)->getNameInDocument())) + .arg(QLatin1String(this->propertyName.c_str())) + .arg(data); + } + + Gui::Command::runCommand(Gui::Command::App, cmd.toLatin1()); + } + } + + document->commitCommand(); + try { + document->getDocument()->recompute(); + } + catch (...) { + } + } + else { + Base::Console().Warning("No object selected.\n"); + } } } @@ -353,7 +399,8 @@ void Placement::on_selectedVertex_clicked() Base::Vector3d axis; if (firstSelected==picked[0]){ axis = Base::Vector3d(picked[1]-picked[0]); - } else { + } + else { axis = Base::Vector3d(picked[0]-picked[1]); } double length = axis.Length(); @@ -361,7 +408,8 @@ void Placement::on_selectedVertex_clicked() if (QApplication::keyboardModifiers() == Qt::ShiftModifier){ //copy to clipboard on Shift+click QLocale loc; QApplication::clipboard()->setText(loc.toString(length,'g',8)); - }else { + } + else { Base::Console().Message("(Shift + click Selected points button to copy distance to clipboard)\n"); } axis.Normalize(); @@ -371,7 +419,8 @@ void Placement::on_selectedVertex_clicked() ui->rotationInput->setCurrentIndex(0); //use rotation with axis instead of euler ui->stackedWidget->setCurrentIndex(0); success=true; - } else if (picked.size() == 3){ + } + else if (picked.size() == 3){ /* User selected 3 points, so we find the plane defined by those * and use the normal vector that contains the first point picked * as the axis of rotation. @@ -381,10 +430,12 @@ void Placement::on_selectedVertex_clicked() if (picked[0] == firstSelected){ a = picked[1]; c = picked[2]; - } else if (picked[1]==firstSelected){ + } + else if (picked[1]==firstSelected){ a = picked[0]; c = picked[2]; - } else if (picked[2] == firstSelected){ + } + else if (picked[2] == firstSelected){ a = picked[0]; c = picked[1]; } @@ -416,7 +467,8 @@ void Placement::on_selectedVertex_clicked() QLocale loc; QApplication::clipboard()->setText(loc.toString(targetAngle,'g',8)); Base::Console().Message("(Angle copied to clipboard, but you might need to use a negative (-) angle sometimes.)\n"); - } else { + } + else { Base::Console().Message("(Shift + click Selected points button to copy angle to clipboard)\n"); } rot.setValue(norm, angle); @@ -459,7 +511,8 @@ void Placement::on_applyAxial_clicked() Qt::KeyboardModifiers km = QApplication::keyboardModifiers(); if (km == Qt::ShiftModifier){ //go opposite direction on Shift+click newPos = Base::Vector3d(curPos.x-(axis.x*axPos),curPos.y-(axis.y*axPos),curPos.z-(axis.z*axPos)); - } else { + } + else { newPos = Base::Vector3d(curPos.x+(axis.x*axPos),curPos.y+(axis.y*axPos),curPos.z+(axis.z*axPos)); } ui->xPos->setValue(Base::Quantity(newPos.x,Base::Unit::Length)); @@ -772,6 +825,11 @@ TaskPlacement::~TaskPlacement() // automatically deleted in the sub-class } +void TaskPlacement::open() +{ + widget->open(); +} + void TaskPlacement::setPropertyName(const QString& name) { widget->propertyName = (const char*)name.toLatin1(); diff --git a/src/Gui/Placement.h b/src/Gui/Placement.h index b2b3ef61ee..bac88324db 100644 --- a/src/Gui/Placement.h +++ b/src/Gui/Placement.h @@ -57,10 +57,12 @@ public: void showDefaultButtons(bool); protected: + void open(); void changeEvent(QEvent *e); void keyPressEvent(QKeyEvent*); private Q_SLOTS: + void openTransaction(); void on_applyButton_clicked(); void on_applyIncrementalPlacement_toggled(bool); void onPlacementChanged(int); @@ -101,6 +103,10 @@ private: * after user selects points and clicks Selected point(s) */ std::vector selectionObjects; + /** If false apply the placement directly to the transform nodes, + * otherwise change the placement property. + */ + bool changeProperty; friend class TaskPlacement; }; @@ -132,6 +138,7 @@ public: bool reject(); void clicked(int id); + void open(); bool isAllowedAlterDocument(void) const { return true; } bool isAllowedAlterView(void) const