24
#include "PreCompiled.h"
31
#include <TopTools_IndexedMapOfShape.hxx>
34
#include <App/Document.h>
35
#include <Base/Console.h>
36
#include <Gui/Application.h>
37
#include <Gui/BitmapFactory.h>
38
#include <Gui/Command.h>
39
#include <Gui/Control.h>
40
#include <Gui/Document.h>
41
#include <Gui/SelectionObject.h>
42
#include <Gui/Widgets.h>
43
#include <Mod/Part/Gui/ViewProvider.h>
45
#include "TaskGeomFillSurface.h"
46
#include "ui_TaskGeomFillSurface.h"
49
using namespace SurfaceGui;
51
PROPERTY_SOURCE(SurfaceGui::ViewProviderGeomFillSurface, PartGui::ViewProviderSpline)
56
void ViewProviderGeomFillSurface::setupContextMenu(QMenu* menu,
61
act = menu->addAction(QObject::tr("Edit filling"), receiver, member);
62
act->setData(QVariant((int)ViewProvider::Default));
63
PartGui::ViewProviderSpline::setupContextMenu(menu, receiver, member);
66
bool ViewProviderGeomFillSurface::setEdit(int ModNum)
68
if (ModNum == ViewProvider::Default) {
73
Surface::GeomFillSurface* obj = static_cast<Surface::GeomFillSurface*>(this->getObject());
75
Gui::TaskView::TaskDialog* dlg = Gui::Control().activeDialog();
79
TaskGeomFillSurface* tDlg = qobject_cast<TaskGeomFillSurface*>(dlg);
81
tDlg->setEditedObject(obj);
83
Gui::Control().showDialog(dlg);
86
Gui::Control().showDialog(new TaskGeomFillSurface(this, obj));
91
return ViewProviderSpline::setEdit(ModNum);
95
void ViewProviderGeomFillSurface::unsetEdit(int ModNum)
97
if (ModNum == ViewProvider::Default) {
99
QTimer::singleShot(0, &Gui::Control(), &Gui::ControlSingleton::closeDialog);
102
PartGui::ViewProviderSpline::unsetEdit(ModNum);
106
QIcon ViewProviderGeomFillSurface::getIcon() const
108
return Gui::BitmapFactory().pixmap("Surface_BSplineSurface");
111
void ViewProviderGeomFillSurface::highlightReferences(bool on)
113
Surface::GeomFillSurface* surface = static_cast<Surface::GeomFillSurface*>(getObject());
114
auto bounds = surface->BoundaryList.getSubListValues();
115
for (const auto& it : bounds) {
116
Part::Feature* base = dynamic_cast<Part::Feature*>(it.first);
118
PartGui::ViewProviderPartExt* svp = dynamic_cast<PartGui::ViewProviderPartExt*>(
119
Gui::Application::Instance->getViewProvider(base));
122
std::vector<App::Color> colors;
123
TopTools_IndexedMapOfShape eMap;
124
TopExp::MapShapes(base->Shape.getValue(), TopAbs_EDGE, eMap);
125
colors.resize(eMap.Extent(), svp->LineColor.getValue());
127
for (const auto& jt : it.second) {
128
std::size_t idx = static_cast<std::size_t>(std::stoi(jt.substr(4)) - 1);
129
assert(idx < colors.size());
130
colors[idx] = App::Color(1.0, 0.0, 1.0);
133
svp->setHighlightedEdges(colors);
136
svp->unsetHighlightedEdges();
145
class GeomFillSurface::EdgeSelection: public Gui::SelectionFilterGate
148
EdgeSelection(bool appendEdges, Surface::GeomFillSurface* editedObject)
149
: Gui::SelectionFilterGate(nullPointer())
150
, appendEdges(appendEdges)
151
, editedObject(editedObject)
156
bool allow(App::Document* pDoc, App::DocumentObject* pObj, const char* sSubName) override;
160
Surface::GeomFillSurface* editedObject;
163
bool GeomFillSurface::EdgeSelection::allow(App::Document*,
164
App::DocumentObject* pObj,
165
const char* sSubName)
168
if (pObj == editedObject) {
171
if (!pObj->isDerivedFrom(Part::Feature::getClassTypeId())) {
175
if (!sSubName || sSubName[0] == '\0') {
179
std::string element(sSubName);
180
if (element.substr(0, 4) != "Edge") {
184
auto links = editedObject->BoundaryList.getSubListValues();
185
for (const auto& it : links) {
186
if (it.first == pObj) {
187
for (const auto& jt : it.second) {
188
if (jt == sSubName) {
200
GeomFillSurface::GeomFillSurface(ViewProviderGeomFillSurface* vp, Surface::GeomFillSurface* obj)
202
ui = new Ui_GeomFillSurface();
206
selectionMode = None;
209
setEditedObject(obj);
212
buttonGroup = new Gui::ButtonGroup(this);
213
buttonGroup->setExclusive(true);
214
buttonGroup->addButton(ui->buttonEdgeAdd, (int)SelectionMode::Append);
215
buttonGroup->addButton(ui->buttonEdgeRemove, (int)SelectionMode::Remove);
218
QAction* remove = new QAction(tr("Remove"), this);
219
remove->setShortcut(QString::fromLatin1("Del"));
220
ui->listWidget->addAction(remove);
221
connect(remove, &QAction::triggered, this, &GeomFillSurface::onDeleteEdge);
223
QAction* orientation = new QAction(tr("Flip orientation"), this);
224
ui->listWidget->addAction(orientation);
225
connect(orientation, &QAction::triggered, this, &GeomFillSurface::onFlipOrientation);
227
ui->listWidget->setContextMenuPolicy(Qt::ActionsContextMenu);
233
GeomFillSurface::~GeomFillSurface()
239
void GeomFillSurface::setupConnections()
241
connect(ui->fillType_stretch,
242
&QRadioButton::clicked,
244
&GeomFillSurface::onFillTypeStretchClicked);
245
connect(ui->fillType_coons,
246
&QRadioButton::clicked,
248
&GeomFillSurface::onFillTypeCoonsClicked);
249
connect(ui->fillType_curved,
250
&QRadioButton::clicked,
252
&GeomFillSurface::onFillTypeCurvedClicked);
253
connect(ui->buttonEdgeAdd,
254
&QToolButton::toggled,
256
&GeomFillSurface::onButtonEdgeAddToggled);
257
connect(ui->buttonEdgeRemove,
258
&QToolButton::toggled,
260
&GeomFillSurface::onButtonEdgeRemoveToggled);
261
connect(ui->listWidget,
262
&QListWidget::itemDoubleClicked,
264
&GeomFillSurface::onListWidgetItemDoubleClicked);
268
void GeomFillSurface::setEditedObject(Surface::GeomFillSurface* obj)
271
GeomFill_FillingStyle curtype =
272
static_cast<GeomFill_FillingStyle>(editedObject->FillType.getValue());
274
case GeomFill_StretchStyle:
275
ui->fillType_stretch->setChecked(true);
277
case GeomFill_CoonsStyle:
278
ui->fillType_coons->setChecked(true);
280
case GeomFill_CurvedStyle:
281
ui->fillType_curved->setChecked(true);
287
auto objects = editedObject->BoundaryList.getValues();
288
auto element = editedObject->BoundaryList.getSubValues();
289
auto boolean = editedObject->ReversedList.getValues();
290
auto it = objects.begin();
291
auto jt = element.begin();
292
std::size_t index = 0;
294
QPixmap rotateLeft = Gui::BitmapFactory().pixmap("view-rotate-left");
295
QPixmap rotateRight = Gui::BitmapFactory().pixmap("view-rotate-right");
297
App::Document* doc = editedObject->getDocument();
298
for (; it != objects.end() && jt != element.end(); ++it, ++jt, ++index) {
299
QListWidgetItem* item = new QListWidgetItem(ui->listWidget);
300
if (index < boolean.size()) {
301
if (boolean[index]) {
302
item->setIcon(rotateLeft);
305
item->setIcon(rotateRight);
308
ui->listWidget->addItem(item);
310
QString text = QString::fromLatin1("%1.%2").arg(QString::fromUtf8((*it)->Label.getValue()),
311
QString::fromStdString(*jt));
314
QList<QVariant> data;
315
data << QByteArray(doc->getName());
316
data << QByteArray((*it)->getNameInDocument());
317
data << QByteArray(jt->c_str());
318
item->setData(Qt::UserRole, data);
321
attachDocument(Gui::Application::Instance->getDocument(doc));
324
void GeomFillSurface::changeEvent(QEvent* e)
326
if (e->type() == QEvent::LanguageChange) {
327
ui->retranslateUi(this);
330
QWidget::changeEvent(e);
334
void GeomFillSurface::open()
337
this->vp->highlightReferences(true);
338
Gui::Selection().clearSelection();
341
void GeomFillSurface::clearSelection()
343
Gui::Selection().clearSelection();
346
void GeomFillSurface::checkOpenCommand()
348
if (checkCommand && !Gui::Command::hasPendingCommand()) {
349
std::string Msg("Edit ");
350
Msg += editedObject->Label.getValue();
351
Gui::Command::openCommand(Msg.c_str());
352
checkCommand = false;
356
void GeomFillSurface::slotUndoDocument(const Gui::Document&)
361
void GeomFillSurface::slotRedoDocument(const Gui::Document&)
366
void GeomFillSurface::slotDeletedObject(const Gui::ViewProviderDocumentObject& Obj)
370
if (this->vp == &Obj) {
371
this->vp->highlightReferences(false);
375
bool GeomFillSurface::accept()
377
selectionMode = None;
378
Gui::Selection().rmvSelectionGate();
380
int count = ui->listWidget->count();
382
QMessageBox::warning(this,
383
tr("Too many edges"),
384
tr("The tool requires two, three or four edges"));
387
else if (count < 2) {
388
QMessageBox::warning(this,
389
tr("Too less edges"),
390
tr("The tool requires two, three or four edges"));
394
if (editedObject->mustExecute()) {
395
editedObject->recomputeFeature();
397
if (!editedObject->isValid()) {
398
QMessageBox::warning(this,
399
tr("Invalid object"),
400
QString::fromLatin1(editedObject->getStatusString()));
404
this->vp->highlightReferences(false);
406
Gui::Command::commitCommand();
407
Gui::Command::doCommand(Gui::Command::Gui, "Gui.ActiveDocument.resetEdit()");
408
Gui::Command::updateActive();
412
bool GeomFillSurface::reject()
414
this->vp->highlightReferences(false);
415
selectionMode = None;
416
Gui::Selection().rmvSelectionGate();
418
Gui::Command::abortCommand();
419
Gui::Command::doCommand(Gui::Command::Gui, "Gui.ActiveDocument.resetEdit()");
420
Gui::Command::updateActive();
424
void GeomFillSurface::onFillTypeStretchClicked()
426
changeFillType(GeomFill_StretchStyle);
429
void GeomFillSurface::onFillTypeCoonsClicked()
431
changeFillType(GeomFill_CoonsStyle);
434
void GeomFillSurface::onFillTypeCurvedClicked()
436
changeFillType(GeomFill_CurvedStyle);
439
void GeomFillSurface::changeFillType(GeomFill_FillingStyle fillType)
441
GeomFill_FillingStyle curtype =
442
static_cast<GeomFill_FillingStyle>(editedObject->FillType.getValue());
443
if (curtype != fillType) {
445
editedObject->FillType.setValue(static_cast<long>(fillType));
446
editedObject->recomputeFeature();
447
if (!editedObject->isValid()) {
448
Base::Console().Error("Surface filling: %s", editedObject->getStatusString());
453
void GeomFillSurface::onButtonEdgeAddToggled(bool checked)
456
selectionMode = Append;
457
Gui::Selection().addSelectionGate(new EdgeSelection(true, editedObject));
459
else if (selectionMode == Append) {
464
void GeomFillSurface::onButtonEdgeRemoveToggled(bool checked)
467
selectionMode = Remove;
468
Gui::Selection().addSelectionGate(new EdgeSelection(false, editedObject));
470
else if (selectionMode == Remove) {
475
void GeomFillSurface::onSelectionChanged(const Gui::SelectionChanges& msg)
477
if (selectionMode == None) {
481
if (msg.Type == Gui::SelectionChanges::AddSelection) {
483
if (selectionMode == Append) {
484
QListWidgetItem* item = new QListWidgetItem(ui->listWidget);
485
item->setIcon(Gui::BitmapFactory().pixmap("view-rotate-right"));
486
ui->listWidget->addItem(item);
488
Gui::SelectionObject sel(msg);
489
QString text = QString::fromLatin1("%1.%2").arg(
490
QString::fromUtf8(sel.getObject()->Label.getValue()),
491
QString::fromLatin1(msg.pSubName));
494
QList<QVariant> data;
495
data << QByteArray(msg.pDocName);
496
data << QByteArray(msg.pObjectName);
497
data << QByteArray(msg.pSubName);
498
item->setData(Qt::UserRole, data);
500
auto objects = editedObject->BoundaryList.getValues();
501
objects.push_back(sel.getObject());
502
auto element = editedObject->BoundaryList.getSubValues();
503
element.emplace_back(msg.pSubName);
504
editedObject->BoundaryList.setValues(objects, element);
505
auto booleans = editedObject->ReversedList.getValues();
506
booleans.push_back(false);
507
editedObject->ReversedList.setValues(booleans);
508
this->vp->highlightReferences(true);
511
Gui::SelectionObject sel(msg);
512
QList<QVariant> data;
514
data << QByteArray(msg.pDocName);
515
data << QByteArray(msg.pObjectName);
516
data << QByteArray(msg.pSubName);
517
for (int i = 0; i < ui->listWidget->count(); i++) {
518
QListWidgetItem* item = ui->listWidget->item(i);
519
if (item && item->data(Qt::UserRole) == data) {
521
ui->listWidget->takeItem(i);
526
this->vp->highlightReferences(false);
527
App::DocumentObject* obj = sel.getObject();
528
std::string sub = msg.pSubName;
529
auto objects = editedObject->BoundaryList.getValues();
530
auto element = editedObject->BoundaryList.getSubValues();
531
auto it = objects.begin();
532
auto jt = element.begin();
535
const boost::dynamic_bitset<>& old_booleans = editedObject->ReversedList.getValues();
536
boost::dynamic_bitset<> new_booleans = old_booleans >> 1;
537
new_booleans.resize(objects.size() - 1);
540
if (new_booleans.size() < old_booleans.size()) {
541
for (int i = 0; i < row; i++) {
542
new_booleans[i] = old_booleans[i];
546
for (; it != objects.end() && jt != element.end(); ++it, ++jt) {
547
if (*it == obj && *jt == sub) {
550
editedObject->BoundaryList.setValues(objects, element);
551
editedObject->ReversedList.setValues(new_booleans);
555
this->vp->highlightReferences(true);
558
editedObject->recomputeFeature();
559
QTimer::singleShot(50, this, &GeomFillSurface::clearSelection);
563
void GeomFillSurface::onDeleteEdge()
565
int row = ui->listWidget->currentRow();
566
QListWidgetItem* item = ui->listWidget->item(row);
569
QList<QVariant> data;
570
data = item->data(Qt::UserRole).toList();
571
ui->listWidget->takeItem(row);
574
App::Document* doc = App::GetApplication().getDocument(data[0].toByteArray());
575
App::DocumentObject* obj = doc ? doc->getObject(data[1].toByteArray()) : nullptr;
576
std::string sub = data[2].toByteArray().constData();
577
auto objects = editedObject->BoundaryList.getValues();
578
auto element = editedObject->BoundaryList.getSubValues();
579
auto it = objects.begin();
580
auto jt = element.begin();
581
this->vp->highlightReferences(false);
584
const boost::dynamic_bitset<>& old_booleans = editedObject->ReversedList.getValues();
585
boost::dynamic_bitset<> new_booleans = old_booleans >> 1;
586
new_booleans.resize(objects.size() - 1);
589
if (new_booleans.size() < old_booleans.size()) {
590
for (int i = 0; i < row; i++) {
591
new_booleans[i] = old_booleans[i];
595
for (; it != objects.end() && jt != element.end(); ++it, ++jt) {
596
if (*it == obj && *jt == sub) {
599
editedObject->BoundaryList.setValues(objects, element);
600
editedObject->ReversedList.setValues(new_booleans);
604
this->vp->highlightReferences(true);
608
void GeomFillSurface::flipOrientation(QListWidgetItem* item)
612
QPixmap rotateLeft = Gui::BitmapFactory().pixmap("view-rotate-left");
613
QPixmap rotateRight = Gui::BitmapFactory().pixmap("view-rotate-right");
615
int row = ui->listWidget->row(item);
616
if (row < editedObject->ReversedList.getSize()) {
617
auto booleans = editedObject->ReversedList.getValues();
618
bool reversed = !booleans[row];
619
booleans[row] = reversed;
621
item->setIcon(rotateLeft);
624
item->setIcon(rotateRight);
627
editedObject->ReversedList.setValues(booleans);
628
editedObject->recomputeFeature();
632
void GeomFillSurface::onListWidgetItemDoubleClicked(QListWidgetItem* item)
635
flipOrientation(item);
639
void GeomFillSurface::onFlipOrientation()
641
QListWidgetItem* item = ui->listWidget->currentItem();
643
flipOrientation(item);
647
void GeomFillSurface::exitSelectionMode()
649
selectionMode = None;
650
Gui::Selection().clearSelection();
651
Gui::Selection().rmvSelectionGate();
656
TaskGeomFillSurface::TaskGeomFillSurface(ViewProviderGeomFillSurface* vp,
657
Surface::GeomFillSurface* obj)
659
widget = new GeomFillSurface(vp, obj);
660
widget->setWindowTitle(QObject::tr("Surface"));
661
addTaskBox(Gui::BitmapFactory().pixmap("Surface_BSplineSurface"), widget);
664
void TaskGeomFillSurface::setEditedObject(Surface::GeomFillSurface* obj)
666
widget->setEditedObject(obj);
669
void TaskGeomFillSurface::open()
674
bool TaskGeomFillSurface::accept()
676
return widget->accept();
679
bool TaskGeomFillSurface::reject()
681
return widget->reject();
686
#include "moc_TaskGeomFillSurface.cpp"