From e014c29bb3d18be0d1ea993f346efb82597a2e4f Mon Sep 17 00:00:00 2001 From: tomate44 Date: Wed, 29 Nov 2017 09:46:37 +0100 Subject: [PATCH] Surface WB: add a Gui widget for unbound edges to the Filling tool. --- src/Mod/Surface/Gui/CMakeLists.txt | 4 + src/Mod/Surface/Gui/TaskFilling.cpp | 14 +- src/Mod/Surface/Gui/TaskFilling.h | 4 +- src/Mod/Surface/Gui/TaskFillingUnbound.cpp | 593 +++++++++++++++++++++ src/Mod/Surface/Gui/TaskFillingUnbound.h | 93 ++++ src/Mod/Surface/Gui/TaskFillingUnbound.ui | 159 ++++++ 6 files changed, 865 insertions(+), 2 deletions(-) create mode 100644 src/Mod/Surface/Gui/TaskFillingUnbound.cpp create mode 100644 src/Mod/Surface/Gui/TaskFillingUnbound.h create mode 100644 src/Mod/Surface/Gui/TaskFillingUnbound.ui diff --git a/src/Mod/Surface/Gui/CMakeLists.txt b/src/Mod/Surface/Gui/CMakeLists.txt index 36bb016d40..7e20fd3d61 100644 --- a/src/Mod/Surface/Gui/CMakeLists.txt +++ b/src/Mod/Surface/Gui/CMakeLists.txt @@ -25,6 +25,7 @@ set(SurfaceGui_LIBS set(SurfaceGui_MOC_HDRS TaskFilling.h + TaskFillingUnbound.h TaskFillingVertex.h TaskGeomFillSurface.h ) @@ -39,6 +40,7 @@ endif() SET(SurfaceGui_UIC_SRCS TaskFilling.ui + TaskFillingUnbound.ui TaskFillingVertex.ui TaskGeomFillSurface.ui ) @@ -54,6 +56,8 @@ SET(SurfaceGui_SRCS ${SurfaceGui_UIC_HDRS} TaskFilling.cpp TaskFilling.h + TaskFillingUnbound.cpp + TaskFillingUnbound.h TaskFillingVertex.cpp TaskFillingVertex.h TaskGeomFillSurface.cpp diff --git a/src/Mod/Surface/Gui/TaskFilling.cpp b/src/Mod/Surface/Gui/TaskFilling.cpp index 7f7b82b26c..9f47ef62b0 100644 --- a/src/Mod/Surface/Gui/TaskFilling.cpp +++ b/src/Mod/Surface/Gui/TaskFilling.cpp @@ -42,6 +42,7 @@ #include #include "TaskFilling.h" +#include "TaskFillingUnbound.h" #include "TaskFillingVertex.h" #include "ui_TaskFilling.h" @@ -823,12 +824,20 @@ TaskFilling::TaskFilling(ViewProviderFilling* vp, Surface::Filling* obj) Content.push_back(taskbox1); // second task box - widget2 = new FillingVertexPanel(vp, obj); + widget2 = new FillingUnboundPanel(vp, obj); Gui::TaskView::TaskBox* taskbox2 = new Gui::TaskView::TaskBox( QPixmap(), widget2->windowTitle(), true, 0); taskbox2->groupLayout()->addWidget(widget2); Content.push_back(taskbox2); taskbox2->hideGroupBox(); + + // third task box + widget3 = new FillingVertexPanel(vp, obj); + Gui::TaskView::TaskBox* taskbox3 = new Gui::TaskView::TaskBox( + QPixmap(), widget3->windowTitle(), true, 0); + taskbox3->groupLayout()->addWidget(widget3); + Content.push_back(taskbox3); + taskbox3->hideGroupBox(); } TaskFilling::~TaskFilling() @@ -845,6 +854,7 @@ void TaskFilling::open() { widget1->open(); widget2->open(); + widget3->open(); } bool TaskFilling::accept() @@ -852,6 +862,7 @@ bool TaskFilling::accept() bool ok = widget1->accept(); if (ok) { widget2->reject(); + widget3->reject(); Gui::Command::commitCommand(); Gui::Command::doCommand(Gui::Command::Gui,"Gui.ActiveDocument.resetEdit()"); Gui::Command::updateActive(); @@ -865,6 +876,7 @@ bool TaskFilling::reject() bool ok = widget1->reject(); if (ok) { widget2->reject(); + widget3->reject(); Gui::Command::abortCommand(); Gui::Command::doCommand(Gui::Command::Gui,"Gui.ActiveDocument.resetEdit()"); Gui::Command::updateActive(); diff --git a/src/Mod/Surface/Gui/TaskFilling.h b/src/Mod/Surface/Gui/TaskFilling.h index 157c2172c5..31f7175e7c 100644 --- a/src/Mod/Surface/Gui/TaskFilling.h +++ b/src/Mod/Surface/Gui/TaskFilling.h @@ -37,6 +37,7 @@ namespace SurfaceGui { class FillingVertexPanel; +class FillingUnboundPanel; class Ui_TaskFilling; class ViewProviderFilling : public PartGui::ViewProviderSpline @@ -122,7 +123,8 @@ public: private: FillingPanel* widget1; - FillingVertexPanel* widget2; + FillingUnboundPanel* widget2; + FillingVertexPanel* widget3; }; } //namespace SurfaceGui diff --git a/src/Mod/Surface/Gui/TaskFillingUnbound.cpp b/src/Mod/Surface/Gui/TaskFillingUnbound.cpp new file mode 100644 index 0000000000..5ee64ff84c --- /dev/null +++ b/src/Mod/Surface/Gui/TaskFillingUnbound.cpp @@ -0,0 +1,593 @@ +/*************************************************************************** + * Copyright (c) 2017 Werner Mayer * + * Christophe Grellier * + * * + * 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" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "TaskFillingUnbound.h" +#include "ui_TaskFillingUnbound.h" +#include "TaskFilling.h" + + +using namespace SurfaceGui; + +namespace SurfaceGui { + +class FillingUnboundPanel::ShapeSelection : public Gui::SelectionFilterGate +{ +public: + ShapeSelection(FillingUnboundPanel::SelectionMode& mode, Surface::Filling* editedObject) + : Gui::SelectionFilterGate(static_cast(nullptr)) + , mode(mode) + , editedObject(editedObject) + { + } + ~ShapeSelection() + { + mode = FillingUnboundPanel::None; + } + /** + * Allow the user to pick only edges. + */ + bool allow(App::Document*, App::DocumentObject* pObj, const char* sSubName) + { + // don't allow references to itself + if (pObj == editedObject) + return false; + if (!pObj->isDerivedFrom(Part::Feature::getClassTypeId())) + return false; + + if (!sSubName || sSubName[0] == '\0') + return false; + + switch (mode) { + case FillingUnboundPanel::AppendEdge: + return allowEdge(true, pObj, sSubName); + case FillingUnboundPanel::RemoveEdge: + return allowEdge(false, pObj, sSubName); + default: + return false; + } + } + +private: + bool allowEdge(bool appendEdges, App::DocumentObject* pObj, const char* sSubName) + { + std::string element(sSubName); + if (element.substr(0,4) != "Edge") + return false; + + auto links = editedObject->UnboundEdges.getSubListValues(); + for (auto it : links) { + if (it.first == pObj) { + for (auto jt : it.second) { + if (jt == sSubName) + return !appendEdges; + } + } + } + + return appendEdges; + } + +private: + FillingUnboundPanel::SelectionMode& mode; + Surface::Filling* editedObject; +}; + +// ---------------------------------------------------------------------------- + +FillingUnboundPanel::FillingUnboundPanel(ViewProviderFilling* vp, Surface::Filling* obj) +{ + ui = new Ui_TaskFillingUnbound(); + ui->setupUi(this); + + selectionMode = None; + this->vp = vp; + checkCommand = true; + setEditedObject(obj); + + // Create context menu + QAction* action = new QAction(tr("Remove"), this); + action->setShortcut(QString::fromLatin1("Del")); + ui->listUnbound->addAction(action); + connect(action, SIGNAL(triggered()), this, SLOT(onDeleteUnboundEdge())); + ui->listUnbound->setContextMenuPolicy(Qt::ActionsContextMenu); +} + +/* + * Destroys the object and frees any allocated resources + */ +FillingUnboundPanel::~FillingUnboundPanel() +{ + // no need to delete child widgets, Qt does it all for us + delete ui; + Gui::Selection().rmvSelectionGate(); +} + +// stores object pointer, its old fill type and adjusts radio buttons according to it. +void FillingUnboundPanel::setEditedObject(Surface::Filling* obj) +{ + editedObject = obj; + + // get the unbound edges, if set their adjacent faces and continuities + auto objects = editedObject->UnboundEdges.getValues(); + auto edges = editedObject->UnboundEdges.getSubValues(); + auto count = objects.size(); + + // fill up faces if wrong size + auto faces = editedObject->UnboundFaces.getValues(); + if (faces.size() != edges.size()) { + faces.resize(edges.size()); + std::fill(faces.begin(), faces.end(), std::string()); + } + + // fill up continuities if wrong size + auto conts = editedObject->UnboundOrder.getValues(); + if (edges.size() != conts.size()) { + conts.resize(edges.size()); + std::fill(conts.begin(), conts.end(), static_cast(GeomAbs_C0)); + } + + App::Document* doc = editedObject->getDocument(); + for (std::size_t i=0; ilistUnbound); + ui->listUnbound->addItem(item); + + QString text = QString::fromLatin1("%1.%2") + .arg(QString::fromUtf8(obj->Label.getValue())) + .arg(QString::fromStdString(edge)); + item->setText(text); + + // The user data field of a list widget item + // is a list of five elementa: + // 1. document name + // 2. object name + // 3. sub-element name of the edge + // 4. sub-element of an adjacent face or empty string + // 5. the continuity as int + QList data; + data << QByteArray(doc->getName()); + data << QByteArray(obj->getNameInDocument()); + data << QByteArray(edge.c_str()); + data << QByteArray(face.c_str()); + data << static_cast(conts[i]); + item->setData(Qt::UserRole, data); + } + + // attach this document observer + attachDocument(Gui::Application::Instance->getDocument(doc)); +} + +void FillingUnboundPanel::changeEvent(QEvent *e) +{ + if (e->type() == QEvent::LanguageChange) { + ui->retranslateUi(this); + } + else { + QWidget::changeEvent(e); + } +} + +void FillingUnboundPanel::open() +{ + checkOpenCommand(); + + // highlight the boundary edges + this->vp->highlightReferences(ViewProviderFilling::Edge, + editedObject->UnboundEdges.getSubListValues(), true); + + Gui::Selection().clearSelection(); +} + +void FillingUnboundPanel::clearSelection() +{ + Gui::Selection().clearSelection(); +} + +void FillingUnboundPanel::checkOpenCommand() +{ + if (checkCommand && !Gui::Command::hasPendingCommand()) { + std::string Msg("Edit "); + Msg += editedObject->Label.getValue(); + Gui::Command::openCommand(Msg.c_str()); + checkCommand = false; + } +} + +void FillingUnboundPanel::slotUndoDocument(const Gui::Document&) +{ + checkCommand = true; +} + +void FillingUnboundPanel::slotRedoDocument(const Gui::Document&) +{ + checkCommand = true; +} + +void FillingUnboundPanel::slotDeletedObject(const Gui::ViewProviderDocumentObject& Obj) +{ + // If this view provider is being deleted then reset the colors of + // referenced part objects. The dialog will be deleted later. + if (this->vp == &Obj) { + this->vp->highlightReferences(ViewProviderFilling::Edge, + editedObject->UnboundEdges.getSubListValues(), false); + } +} + +bool FillingUnboundPanel::accept() +{ + selectionMode = None; + Gui::Selection().rmvSelectionGate(); + + if (editedObject->mustExecute()) + editedObject->recomputeFeature(); + if (!editedObject->isValid()) { + QMessageBox::warning(this, tr("Invalid object"), + QString::fromLatin1(editedObject->getStatusString())); + return false; + } + + this->vp->highlightReferences(ViewProviderFilling::Edge, + editedObject->UnboundEdges.getSubListValues(), false); + return true; +} + +bool FillingUnboundPanel::reject() +{ + this->vp->highlightReferences(ViewProviderFilling::Edge, + editedObject->UnboundEdges.getSubListValues(), false); + + selectionMode = None; + Gui::Selection().rmvSelectionGate(); + + return true; +} + +void FillingUnboundPanel::on_buttonUnboundEdgeAdd_clicked() +{ + // 'selectionMode' is passed by reference and changed when the filter is deleted + Gui::Selection().addSelectionGate(new ShapeSelection(selectionMode, editedObject)); + selectionMode = AppendEdge; +} + +void FillingUnboundPanel::on_buttonUnboundEdgeRemove_clicked() +{ + // 'selectionMode' is passed by reference and changed when the filter is deleted + Gui::Selection().addSelectionGate(new ShapeSelection(selectionMode, editedObject)); + selectionMode = RemoveEdge; +} + +void FillingUnboundPanel::on_listUnbound_itemDoubleClicked(QListWidgetItem* item) +{ + Gui::Selection().clearSelection(); + Gui::Selection().rmvSelectionGate(); + selectionMode = None; + + ui->comboBoxUnboundFaces->clear(); + ui->comboBoxUnboundCont->clear(); + + if (item) { + QList data; + data = item->data(Qt::UserRole).toList(); + + try { + App::Document* doc = App::GetApplication().getDocument(data[0].toByteArray()); + App::DocumentObject* obj = doc ? doc->getObject(data[1].toByteArray()) : nullptr; + if (obj && obj->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) { + const Part::TopoShape& shape = static_cast(obj)->Shape.getShape(); + TopoDS_Shape edge = shape.getSubShape(data[2].toByteArray()); + + // build up map edge->face + TopTools_IndexedMapOfShape faces; + TopExp::MapShapes(shape.getShape(), TopAbs_FACE, faces); + TopTools_IndexedDataMapOfShapeListOfShape edge2Face; + TopExp::MapShapesAndAncestors(shape.getShape(), TopAbs_EDGE, TopAbs_FACE, edge2Face); + const TopTools_ListOfShape& adj_faces = edge2Face.FindFromKey(edge); + if (adj_faces.Extent() > 0) { + int n = adj_faces.Extent(); + ui->statusLabel->setText(tr("Edge has %n adjacent face(s)", 0, n)); + + // fill up the combo boxes + modifyBoundary(true); + ui->comboBoxUnboundFaces->addItem(tr("None"), QByteArray("")); + ui->comboBoxUnboundCont->addItem(QString::fromLatin1("C0"), static_cast(GeomAbs_C0)); + ui->comboBoxUnboundCont->addItem(QString::fromLatin1("G1"), static_cast(GeomAbs_G1)); + ui->comboBoxUnboundCont->addItem(QString::fromLatin1("G2"), static_cast(GeomAbs_G2)); + TopTools_ListIteratorOfListOfShape it(adj_faces); + for (; it.More(); it.Next()) { + const TopoDS_Shape& F = it.Value(); + int index = faces.FindIndex(F); + QString text = QString::fromLatin1("Face%1").arg(index); + ui->comboBoxUnboundFaces->addItem(text, text.toLatin1()); + } + + // activate face and continuity + if (data.size() == 5) { + int index = ui->comboBoxUnboundFaces->findData(data[3]); + ui->comboBoxUnboundFaces->setCurrentIndex(index); + index = ui->comboBoxUnboundCont->findData(data[4]); + ui->comboBoxUnboundCont->setCurrentIndex(index); + } + } + else { + ui->statusLabel->setText(tr("Edge has no adjacent faces")); + } + } + + Gui::Selection().addSelection(data[0].toByteArray(), + data[1].toByteArray(), + data[2].toByteArray()); + } + catch (...) { + } + } +} + +void FillingUnboundPanel::onSelectionChanged(const Gui::SelectionChanges& msg) +{ + if (selectionMode == None) + return; + + if (msg.Type == Gui::SelectionChanges::AddSelection) { + checkOpenCommand(); + if (selectionMode == AppendEdge) { + QListWidgetItem* item = new QListWidgetItem(ui->listUnbound); + ui->listUnbound->addItem(item); + + Gui::SelectionObject sel(msg); + QString text = QString::fromLatin1("%1.%2") + .arg(QString::fromUtf8(sel.getObject()->Label.getValue())) + .arg(QString::fromLatin1(msg.pSubName)); + item->setText(text); + + QList data; + data << QByteArray(msg.pDocName); + data << QByteArray(msg.pObjectName); + data << QByteArray(msg.pSubName); + data << QByteArray(""); + data << static_cast(GeomAbs_C0); + item->setData(Qt::UserRole, data); + + auto objects = editedObject->UnboundEdges.getValues(); + std::size_t count = objects.size(); + objects.push_back(sel.getObject()); + auto element = editedObject->UnboundEdges.getSubValues(); + element.push_back(msg.pSubName); + editedObject->UnboundEdges.setValues(objects, element); + + // extend faces and continuities lists if needed + auto faces = editedObject->UnboundFaces.getValues(); + if (count == faces.size()) { + faces.push_back(std::string()); + editedObject->UnboundFaces.setValues(faces); + } + auto conts = editedObject->UnboundOrder.getValues(); + if (count == conts.size()) { + conts.push_back(static_cast(GeomAbs_C0)); + editedObject->UnboundOrder.setValues(conts); + } + + this->vp->highlightReferences(ViewProviderFilling::Edge, + editedObject->UnboundEdges.getSubListValues(), true); + } + else if (selectionMode == RemoveEdge) { + Gui::SelectionObject sel(msg); + QList data; + data << QByteArray(msg.pDocName); + data << QByteArray(msg.pObjectName); + data << QByteArray(msg.pSubName); + + // only the three first elements must match + for (int i=0; ilistUnbound->count(); i++) { + QListWidgetItem* item = ui->listUnbound->item(i); + QList userdata = item->data(Qt::UserRole).toList(); + if (userdata.mid(0,3) == data) { + ui->listUnbound->takeItem(i); + delete item; + break; + } + } + + this->vp->highlightReferences(ViewProviderFilling::Edge, + editedObject->UnboundEdges.getSubListValues(), false); + App::DocumentObject* obj = sel.getObject(); + std::string sub = msg.pSubName; + auto objects = editedObject->UnboundEdges.getValues(); + auto element = editedObject->UnboundEdges.getSubValues(); + auto it = objects.begin(); + auto jt = element.begin(); + + for (; it != objects.end() && jt != element.end(); ++it, ++jt) { + if (*it == obj && *jt == sub) { + std::size_t index = std::distance(objects.begin(), it); + + objects.erase(it); + element.erase(jt); + editedObject->UnboundEdges.setValues(objects, element); + + // try to remove the item also from the faces + auto faces = editedObject->UnboundFaces.getValues(); + if (index < faces.size()) { + faces.erase(faces.begin() + index); + editedObject->UnboundFaces.setValues(faces); + } + + // try to remove the item also from the orders + auto order = editedObject->UnboundOrder.getValues(); + if (index < order.size()) { + order.erase(order.begin() + index); + editedObject->UnboundOrder.setValues(order); + } + break; + } + } + this->vp->highlightReferences(ViewProviderFilling::Edge, + editedObject->UnboundEdges.getSubListValues(), true); + } + + editedObject->recomputeFeature(); + QTimer::singleShot(50, this, SLOT(clearSelection())); + } +} + +void FillingUnboundPanel::onDeleteUnboundEdge() +{ + int row = ui->listUnbound->currentRow(); + QListWidgetItem* item = ui->listUnbound->item(row); + if (item) { + checkOpenCommand(); + QList data; + data = item->data(Qt::UserRole).toList(); + ui->listUnbound->takeItem(row); + delete item; + + App::Document* doc = App::GetApplication().getDocument(data[0].toByteArray()); + App::DocumentObject* obj = doc ? doc->getObject(data[1].toByteArray()) : nullptr; + std::string sub = data[2].toByteArray().constData(); + auto objects = editedObject->UnboundEdges.getValues(); + auto element = editedObject->UnboundEdges.getSubValues(); + auto it = objects.begin(); + auto jt = element.begin(); + this->vp->highlightReferences(ViewProviderFilling::Edge, + editedObject->UnboundEdges.getSubListValues(), false); + for (; it != objects.end() && jt != element.end(); ++it, ++jt) { + if (*it == obj && *jt == sub) { + std::size_t index = std::distance(objects.begin(), it); + + objects.erase(it); + element.erase(jt); + editedObject->UnboundEdges.setValues(objects, element); + + // try to remove the item also from the faces + auto faces = editedObject->UnboundFaces.getValues(); + if (index < faces.size()) { + faces.erase(faces.begin() + index); + editedObject->UnboundFaces.setValues(faces); + } + + // try to remove the item also from the orders + auto order = editedObject->UnboundOrder.getValues(); + if (index < order.size()) { + order.erase(order.begin() + index); + editedObject->UnboundOrder.setValues(order); + } + break; + } + } + this->vp->highlightReferences(ViewProviderFilling::Edge, + editedObject->UnboundEdges.getSubListValues(), true); + + editedObject->recomputeFeature(); + } +} + +void FillingUnboundPanel::on_buttonUnboundAccept_clicked() +{ + QListWidgetItem* item = ui->listUnbound->currentItem(); + if (item) { + QList data; + data = item->data(Qt::UserRole).toList(); + + QVariant face = ui->comboBoxUnboundFaces->itemData(ui->comboBoxUnboundFaces->currentIndex()); + QVariant cont = ui->comboBoxUnboundCont->itemData(ui->comboBoxUnboundCont->currentIndex()); + if (data.size() == 5) { + data[3] = face; + data[4] = cont; + } + else { + data << face; + data << cont; + } + + item->setData(Qt::UserRole, data); + + std::size_t index = ui->listUnbound->row(item); + + // try to set the item of the faces + auto faces = editedObject->UnboundFaces.getValues(); + if (index < faces.size()) { + faces[index] = face.toByteArray().data(); + editedObject->UnboundFaces.setValues(faces); + } + + // try to set the item of the orders + auto order = editedObject->UnboundOrder.getValues(); + if (index < order.size()) { + order[index] = cont.toInt(); + editedObject->UnboundOrder.setValues(order); + } + } + + modifyBoundary(false); + ui->comboBoxUnboundFaces->clear(); + ui->comboBoxUnboundCont->clear(); + ui->statusLabel->clear(); + + editedObject->recomputeFeature(); +} + +void FillingUnboundPanel::on_buttonUnboundIgnore_clicked() +{ + modifyBoundary(false); + ui->comboBoxUnboundFaces->clear(); + ui->comboBoxUnboundCont->clear(); + ui->statusLabel->clear(); +} + +void FillingUnboundPanel::modifyBoundary(bool on) +{ + ui->buttonUnboundEdgeAdd->setDisabled(on); + ui->buttonUnboundEdgeRemove->setDisabled(on); + ui->listUnbound->setDisabled(on); + + ui->comboBoxUnboundFaces->setEnabled(on); + ui->comboBoxUnboundCont->setEnabled(on); + ui->buttonUnboundAccept->setEnabled(on); + ui->buttonUnboundIgnore->setEnabled(on); +} +} + +#include "moc_TaskFillingUnbound.cpp" diff --git a/src/Mod/Surface/Gui/TaskFillingUnbound.h b/src/Mod/Surface/Gui/TaskFillingUnbound.h new file mode 100644 index 0000000000..7901fa1cf7 --- /dev/null +++ b/src/Mod/Surface/Gui/TaskFillingUnbound.h @@ -0,0 +1,93 @@ +/*************************************************************************** + * Copyright (c) 2017 Werner Mayer * + * Christophe Grellier * + * * + * 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 SURFACEGUI_TASKFILLINGUNBOUND_H +#define SURFACEGUI_TASKFILLINGUNBOUND_H + +#include +#include +#include +#include +#include +#include +#include + +class QListWidgetItem; + +namespace SurfaceGui +{ + +class ViewProviderFilling; +class Ui_TaskFillingUnbound; + +class FillingUnboundPanel : public QWidget, + public Gui::SelectionObserver, + public Gui::DocumentObserver +{ + Q_OBJECT + +protected: + class ShapeSelection; + enum SelectionMode { None, AppendEdge, RemoveEdge }; + SelectionMode selectionMode; + Surface::Filling* editedObject; + bool checkCommand; + +private: + Ui_TaskFillingUnbound* ui; + ViewProviderFilling* vp; + +public: + FillingUnboundPanel(ViewProviderFilling* vp, Surface::Filling* obj); + ~FillingUnboundPanel(); + + void open(); + void checkOpenCommand(); + bool accept(); + bool reject(); + void setEditedObject(Surface::Filling* obj); + +protected: + void changeEvent(QEvent *e); + virtual void onSelectionChanged(const Gui::SelectionChanges& msg); + /** Notifies on undo */ + virtual void slotUndoDocument(const Gui::Document& Doc); + /** Notifies on redo */ + virtual void slotRedoDocument(const Gui::Document& Doc); + /** Notifies when the object is about to be removed. */ + virtual void slotDeletedObject(const Gui::ViewProviderDocumentObject& Obj); + void modifyBoundary(bool); + +private Q_SLOTS: + void on_buttonUnboundEdgeAdd_clicked(); + void on_buttonUnboundEdgeRemove_clicked(); + void on_listUnbound_itemDoubleClicked(QListWidgetItem*); + void on_buttonUnboundAccept_clicked(); + void on_buttonUnboundIgnore_clicked(); + void onDeleteUnboundEdge(void); + void clearSelection(); +}; + +} //namespace SurfaceGui + +#endif // SURFACEGUI_TASKFILLINGUNBOUND_H diff --git a/src/Mod/Surface/Gui/TaskFillingUnbound.ui b/src/Mod/Surface/Gui/TaskFillingUnbound.ui new file mode 100644 index 0000000000..70dd94f755 --- /dev/null +++ b/src/Mod/Surface/Gui/TaskFillingUnbound.ui @@ -0,0 +1,159 @@ + + + SurfaceGui::TaskFillingUnbound + + + + 0 + 0 + 360 + 400 + + + + + 0 + 0 + + + + Unbound Edges + + + + + + Unbound Edges + + + + + + + + + + 0 + 0 + + + + Faces: + + + + + + + false + + + + + + + + 0 + 0 + + + + Continuity: + + + + + + + false + + + + + + + Qt::Horizontal + + + QSizePolicy::Maximum + + + + 74 + 20 + + + + + + + + false + + + Accept + + + + + + + false + + + Ignore + + + + + + + + + true + + + + 0 + 0 + + + + Add Edge + + + false + + + + + + + + 0 + 0 + + + + Remove Edge + + + + + + + + + Status messages + + + + + + + + + + + +