PartDesign: Add new need active body dialog with option to choose body (#4949)
* [PD] Add new need active body dialog Intended for use wherever an active body is needed but none exists. The dialog contains a list with the bodies present in the document, with an extra option to make a new body. Custom text can be provided if needed. This commit also replaces the warnings used by "new sketch" and "primitive" command with this new dialog. Addresses issue #4288.
This commit is contained in:
@@ -59,6 +59,7 @@ set(PartDesignGui_UIC_SRCS
|
||||
TaskPipeScaling.ui
|
||||
TaskLoftParameters.ui
|
||||
DlgReference.ui
|
||||
DlgActiveBody.ui
|
||||
TaskHelixParameters.ui
|
||||
)
|
||||
|
||||
@@ -213,6 +214,8 @@ SET(PartDesignGuiTaskDlgs_SRCS
|
||||
TaskHelixParameters.ui
|
||||
TaskHelixParameters.h
|
||||
TaskHelixParameters.cpp
|
||||
DlgActiveBody.h
|
||||
DlgActiveBody.cpp
|
||||
)
|
||||
SOURCE_GROUP("TaskDialogs" FILES ${PartDesignGuiTaskDlgs_SRCS})
|
||||
|
||||
|
||||
@@ -70,6 +70,7 @@
|
||||
#include "WorkflowManager.h"
|
||||
#include "ViewProvider.h"
|
||||
#include "ViewProviderBody.h"
|
||||
#include "DlgActiveBody.h"
|
||||
|
||||
// TODO Remove this header after fixing code so it won;t be needed here (2015-10-20, Fat-Zer)
|
||||
#include "ui_DlgReference.h"
|
||||
@@ -505,12 +506,15 @@ void CmdPartDesignNewSketch::activated(int iMsg)
|
||||
// objects (in which case, just make one) to make a new sketch.
|
||||
|
||||
pcActiveBody = PartDesignGui::getBody( /* messageIfNot = */ false );
|
||||
if (pcActiveBody == nullptr) {
|
||||
if ( doc->getObjectsOfType(PartDesign::Body::getClassTypeId()).empty() ) {
|
||||
if (!pcActiveBody) {
|
||||
if ( doc->countObjectsOfType(PartDesign::Body::getClassTypeId()) == 0 ) {
|
||||
shouldMakeBody = true;
|
||||
} else {
|
||||
PartDesignGui::needActiveBodyError();
|
||||
return;
|
||||
PartDesignGui::DlgActiveBody dia(Gui::getMainWindow(), doc);
|
||||
if (dia.exec() == QDialog::DialogCode::Accepted)
|
||||
pcActiveBody = dia.getActiveBody();
|
||||
if (!pcActiveBody)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
|
||||
#include "Utils.h"
|
||||
#include "WorkflowManager.h"
|
||||
#include "DlgActiveBody.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
@@ -85,12 +86,15 @@ void CmdPrimtiveCompAdditive::activated(int iMsg)
|
||||
PartDesign::Body *pcActiveBody = PartDesignGui::getBody( /* messageIfNot = */ false );
|
||||
|
||||
auto shouldMakeBody( false );
|
||||
if (pcActiveBody == nullptr) {
|
||||
if (!pcActiveBody) {
|
||||
if ( doc->getObjectsOfType(PartDesign::Body::getClassTypeId()).empty() ) {
|
||||
shouldMakeBody = true;
|
||||
} else {
|
||||
PartDesignGui::needActiveBodyError();
|
||||
return;
|
||||
PartDesignGui::DlgActiveBody dia(Gui::getMainWindow(), doc);
|
||||
if (dia.exec() == QDialog::DialogCode::Accepted)
|
||||
pcActiveBody = dia.getActiveBody();
|
||||
if (!pcActiveBody)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,7 +108,7 @@ void CmdPrimtiveCompAdditive::activated(int iMsg)
|
||||
pcActiveBody = PartDesignGui::makeBody(doc);
|
||||
}
|
||||
|
||||
if (pcActiveBody == nullptr) {
|
||||
if (!pcActiveBody) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
95
src/Mod/PartDesign/Gui/DlgActiveBody.cpp
Normal file
95
src/Mod/PartDesign/Gui/DlgActiveBody.cpp
Normal file
@@ -0,0 +1,95 @@
|
||||
/**************************************************************************
|
||||
* Copyright (c) 2021 FreeCAD Developers *
|
||||
* Author: Ajinkya Dahale *
|
||||
* Based on src/Gui/DlgAddProperty.cpp *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#include "PreCompiled.h"
|
||||
#ifndef _PreComp_
|
||||
# include <QMessageBox>
|
||||
#endif
|
||||
|
||||
#include <Gui/Application.h>
|
||||
|
||||
#include "DlgActiveBody.h"
|
||||
#include "ReferenceSelection.h"
|
||||
#include "Utils.h"
|
||||
|
||||
Q_DECLARE_METATYPE(App::DocumentObject*);
|
||||
|
||||
using namespace PartDesignGui;
|
||||
|
||||
DlgActiveBody::DlgActiveBody(QWidget *parent, App::Document*& doc,
|
||||
const QString& infoText)
|
||||
: QDialog(parent),
|
||||
ui(new Ui_DlgActiveBody),
|
||||
_doc(doc),
|
||||
activeBody(nullptr)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
QObject::connect(ui->bodySelect, SIGNAL(itemDoubleClicked(QListWidgetItem *)),
|
||||
this, SLOT(accept()));
|
||||
|
||||
if(!infoText.isEmpty()) {
|
||||
ui->label->setText(infoText + QString::fromUtf8("\n\n") +
|
||||
QObject::tr("Please select"));
|
||||
}
|
||||
|
||||
auto bodies = _doc->getObjectsOfType(PartDesign::Body::getClassTypeId());
|
||||
|
||||
PartDesign::Body* bodyOfActiveObject = nullptr;
|
||||
for (const auto &obj : Gui::Selection().getSelection()) {
|
||||
bodyOfActiveObject = PartDesign::Body::findBodyOf(obj.pObject);
|
||||
break; // Just get the body for first selected object
|
||||
}
|
||||
|
||||
for (const auto &body : bodies) {
|
||||
auto item = new QListWidgetItem(QString::fromUtf8(body->Label.getValue()));
|
||||
item->setData(Qt::UserRole, QVariant::fromValue(body));
|
||||
ui->bodySelect->addItem(item);
|
||||
|
||||
if (body == bodyOfActiveObject) {
|
||||
item->setSelected(true);
|
||||
}
|
||||
|
||||
// TODO: Any other logic (hover, select effects on view etc.)
|
||||
}
|
||||
}
|
||||
|
||||
void DlgActiveBody::accept()
|
||||
{
|
||||
auto selectedItems = ui->bodySelect->selectedItems();
|
||||
if (selectedItems.empty())
|
||||
return;
|
||||
|
||||
App::DocumentObject* selectedBody =
|
||||
selectedItems[0]->data(Qt::UserRole).value<App::DocumentObject*>();
|
||||
if (selectedBody)
|
||||
activeBody = makeBodyActive(selectedBody, _doc);
|
||||
else
|
||||
activeBody = makeBody(_doc);
|
||||
|
||||
QDialog::accept();
|
||||
}
|
||||
|
||||
#include "moc_DlgActiveBody.cpp"
|
||||
59
src/Mod/PartDesign/Gui/DlgActiveBody.h
Normal file
59
src/Mod/PartDesign/Gui/DlgActiveBody.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/**************************************************************************
|
||||
* Copyright (c) 2021 FreeCAD Developers *
|
||||
* Author: Ajinkya Dahale *
|
||||
* Based on src/Gui/DlgAddProperty.h *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#ifndef PARTDESIGNGUI_DLGACTIVEBODY_H
|
||||
#define PARTDESIGNGUI_DLGACTIVEBODY_H
|
||||
|
||||
#include <App/Document.h>
|
||||
#include <Mod/PartDesign/App/Body.h>
|
||||
|
||||
// TODO: Apparently this header can be avoided. See ./Command.cpp:74.
|
||||
#include "ui_DlgActiveBody.h"
|
||||
|
||||
namespace PartDesignGui {
|
||||
|
||||
/** Dialog box to ask user to pick a Part Design body to make active
|
||||
* or make a new one
|
||||
*/
|
||||
class PartDesignGuiExport DlgActiveBody : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
DlgActiveBody(QWidget* parent, App::Document*& doc,
|
||||
const QString& infoText=QString());
|
||||
|
||||
void accept() override;
|
||||
PartDesign::Body* getActiveBody() { return activeBody; };
|
||||
|
||||
private:
|
||||
std::unique_ptr<Ui_DlgActiveBody> ui;
|
||||
App::Document* _doc;
|
||||
PartDesign::Body* activeBody;
|
||||
};
|
||||
|
||||
} // namespace PartDesignGui
|
||||
|
||||
#endif // PARTDESIGNGUI_DLGACTIVEBODY_H
|
||||
88
src/Mod/PartDesign/Gui/DlgActiveBody.ui
Normal file
88
src/Mod/PartDesign/Gui/DlgActiveBody.ui
Normal file
@@ -0,0 +1,88 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>PartDesignGui::DlgActiveBody</class>
|
||||
<widget class="QDialog" name="PartDesignGui::DlgActiveBody">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>480</width>
|
||||
<height>270</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Active Body Required</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>To create a new PartDesign object, there must be an active Body object in the document.
|
||||
|
||||
Please select a body from below, or create a new body.</string>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QListWidget" name="bodySelect">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Create new body</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>PartDesignGui::DlgActiveBody</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>PartDesignGui::DlgActiveBody</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
@@ -52,6 +52,8 @@
|
||||
#include "ReferenceSelection.h"
|
||||
#include "Utils.h"
|
||||
#include "WorkflowManager.h"
|
||||
#include "DlgActiveBody.h"
|
||||
|
||||
|
||||
FC_LOG_LEVEL_INIT("PartDesignGui",true,true)
|
||||
|
||||
@@ -108,44 +110,30 @@ PartDesign::Body *getBody(bool messageIfNot, bool autoActivate, bool assertModer
|
||||
Gui::MDIView *activeView = Gui::Application::Instance->activeView();
|
||||
|
||||
if (activeView) {
|
||||
bool singleBodyDocument = activeView->getAppDocument()->
|
||||
countObjectsOfType(PartDesign::Body::getClassTypeId()) == 1;
|
||||
if (assertModern && PartDesignGui::assureModernWorkflow ( activeView->getAppDocument() ) ) {
|
||||
auto doc = activeView->getAppDocument();
|
||||
bool singleBodyDocument = doc->countObjectsOfType(PartDesign::Body::getClassTypeId()) == 1;
|
||||
if (assertModern && PartDesignGui::assureModernWorkflow (doc) ) {
|
||||
activeBody = activeView->getActiveObject<PartDesign::Body*>(PDBODYKEY,topParent,subname);
|
||||
|
||||
if (!activeBody && singleBodyDocument && autoActivate) {
|
||||
auto doc = activeView->getAppDocument();
|
||||
auto bodies = doc->getObjectsOfType(PartDesign::Body::getClassTypeId());
|
||||
App::DocumentObject *parent = 0;
|
||||
App::DocumentObject *body = 0;
|
||||
std::string sub;
|
||||
if(bodies.size()==1) {
|
||||
body = bodies[0];
|
||||
for(auto &v : body->getParents()) {
|
||||
if(v.first->getDocument()!=doc)
|
||||
continue;
|
||||
if(parent) {
|
||||
body = 0;
|
||||
break;
|
||||
}
|
||||
parent = v.first;
|
||||
sub = v.second;
|
||||
}
|
||||
}
|
||||
if(body) {
|
||||
auto doc = parent?parent->getDocument():body->getDocument();
|
||||
_FCMD_DOC_CMD(Gui,doc,"ActiveView.setActiveObject('" << PDBODYKEY << "',"
|
||||
<< Gui::Command::getObjectCmd(parent?parent:body) << ",'" << sub << "')");
|
||||
return activeView->getActiveObject<PartDesign::Body*>(PDBODYKEY,topParent,subname);
|
||||
activeBody = makeBodyActive(body, doc, topParent, subname);
|
||||
}
|
||||
}
|
||||
if (!activeBody && messageIfNot) {
|
||||
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("No active Body"),
|
||||
DlgActiveBody dia(
|
||||
Gui::getMainWindow(),
|
||||
doc,
|
||||
QObject::tr("In order to use PartDesign you need an active Body object in the document. "
|
||||
"Please make one active (double click) or create one.\n\nIf you have a legacy document "
|
||||
"with PartDesign objects without Body, use the migrate function in "
|
||||
"PartDesign to put them into a Body."
|
||||
));
|
||||
"Please make one active (double click) or create one."
|
||||
"\n\nIf you have a legacy document with PartDesign objects without Body, "
|
||||
"use the migrate function in PartDesign to put them into a Body."
|
||||
));
|
||||
if (dia.exec() == QDialog::DialogCode::Accepted)
|
||||
activeBody = dia.getActiveBody();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -153,6 +141,36 @@ PartDesign::Body *getBody(bool messageIfNot, bool autoActivate, bool assertModer
|
||||
return activeBody;
|
||||
}
|
||||
|
||||
PartDesign::Body * makeBodyActive(App::DocumentObject *body, App::Document *doc,
|
||||
App::DocumentObject **topParent,
|
||||
std::string *subname)
|
||||
{
|
||||
App::DocumentObject *parent = 0;
|
||||
std::string sub;
|
||||
|
||||
for(auto &v : body->getParents()) {
|
||||
if(v.first->getDocument()!=doc)
|
||||
continue;
|
||||
if(parent) {
|
||||
body = 0;
|
||||
break;
|
||||
}
|
||||
parent = v.first;
|
||||
sub = v.second;
|
||||
}
|
||||
|
||||
if(body) {
|
||||
auto _doc = parent?parent->getDocument():body->getDocument();
|
||||
_FCMD_DOC_CMD(Gui, _doc, "ActiveView.setActiveObject('" << PDBODYKEY
|
||||
<< "'," << Gui::Command::getObjectCmd(parent?parent:body)
|
||||
<< ",'" << sub << "')");
|
||||
return Gui::Application::Instance->activeView()->
|
||||
getActiveObject<PartDesign::Body*>(PDBODYKEY,topParent,subname);
|
||||
}
|
||||
|
||||
return dynamic_cast<PartDesign::Body*>(body);
|
||||
}
|
||||
|
||||
void needActiveBodyError(void)
|
||||
{
|
||||
QMessageBox::warning( Gui::getMainWindow(),
|
||||
@@ -170,13 +188,8 @@ PartDesign::Body * makeBody(App::Document *doc)
|
||||
"App.getDocument('%s').addObject('PartDesign::Body','%s')",
|
||||
doc->getName(), bodyName.c_str() );
|
||||
auto body = dynamic_cast<PartDesign::Body*>(doc->getObject(bodyName.c_str()));
|
||||
if(body) {
|
||||
auto vp = Gui::Application::Instance->getViewProvider(body);
|
||||
if(vp) {
|
||||
// make the new body active
|
||||
vp->doubleClicked();
|
||||
}
|
||||
}
|
||||
if(body)
|
||||
makeBodyActive(body, doc);
|
||||
return body;
|
||||
}
|
||||
|
||||
|
||||
@@ -50,6 +50,22 @@ bool setEdit(App::DocumentObject *obj, PartDesign::Body *body = 0);
|
||||
PartDesign::Body *getBody(bool messageIfNot, bool autoActivate=true, bool assertModern=true,
|
||||
App::DocumentObject **topParent=0, std::string *subname=0);
|
||||
|
||||
/// Display a dialog to select or create a Body object when none is active
|
||||
PartDesign::Body * needActiveBodyMessage(App::Document *doc,
|
||||
const QString& infoText=QString());
|
||||
|
||||
/**
|
||||
* Set given body active, and return pointer to it.
|
||||
* \param body the pointer to the body
|
||||
* \param doc the pointer to the document in question
|
||||
* \param topParent and
|
||||
* \param subname to be passed under certain circumstances
|
||||
* (currently only subshapebinder)
|
||||
*/
|
||||
PartDesign::Body * makeBodyActive(App::DocumentObject *body, App::Document *doc,
|
||||
App::DocumentObject **topParent=0,
|
||||
std::string *subname=0);
|
||||
|
||||
/// Display error when there are existing Body objects, but none are active
|
||||
void needActiveBodyError(void);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user