/*************************************************************************** * Copyright (c) 2008 Werner Mayer * * * * 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 # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include #endif #include "DlgFilletEdges.h" #include "ui_DlgFilletEdges.h" #include "SoBrepFaceSet.h" #include "SoBrepEdgeSet.h" #include "SoBrepPointSet.h" #include "../App/PartFeature.h" #include "../App/FeatureFillet.h" #include "../App/FeatureChamfer.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace PartGui; FilletRadiusDelegate::FilletRadiusDelegate(QObject *parent) : QItemDelegate(parent) { } QWidget *FilletRadiusDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &/* option */, const QModelIndex & index) const { if (index.column() < 1) return 0; Gui::QuantitySpinBox *editor = new Gui::QuantitySpinBox(parent); editor->setUnit(Base::Unit::Length); editor->setMinimum(0.0); editor->setMaximum(INT_MAX); editor->setSingleStep(0.1); return editor; } void FilletRadiusDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const { Base::Quantity value = index.model()->data(index, Qt::EditRole).value(); Gui::QuantitySpinBox *spinBox = static_cast(editor); spinBox->setValue(value); } void FilletRadiusDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const { Gui::QuantitySpinBox *spinBox = static_cast(editor); spinBox->interpretText(); //double value = spinBox->value(); //QString value = QString::fromLatin1("%1").arg(spinBox->value(),0,'f',2); //QString value = QLocale::system().toString(spinBox->value().getValue(),'f',Base::UnitsApi::getDecimals()); Base::Quantity value = spinBox->value(); model->setData(index, QVariant::fromValue(value), Qt::EditRole); } void FilletRadiusDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &/* index */) const { editor->setGeometry(option.rect); } // -------------------------------------------------------------- FilletRadiusModel::FilletRadiusModel(QObject * parent) : QStandardItemModel(parent) { } void FilletRadiusModel::updateCheckStates() { // See http://www.qtcentre.org/threads/18856-Checkboxes-in-Treeview-do-not-get-refreshed?s=b0fea2bfc66da1098413ae9f2a651a68&p=93201#post93201 /*emit*/ layoutChanged(); } Qt::ItemFlags FilletRadiusModel::flags (const QModelIndex & index) const { Qt::ItemFlags fl = QStandardItemModel::flags(index); if (index.column() == 0) fl = fl | Qt::ItemIsUserCheckable; return fl; } bool FilletRadiusModel::setData (const QModelIndex & index, const QVariant & value, int role) { bool ok = QStandardItemModel::setData(index, value, role); if (role == Qt::CheckStateRole) { toggleCheckState(index); } return ok; } QVariant FilletRadiusModel::data(const QModelIndex& index, int role) const { QVariant value = QStandardItemModel::data(index, role); if (role == Qt::DisplayRole && index.column() >= 1) { Base::Quantity q = value.value(); QString str = q.getUserString(); return str; } return value; } // -------------------------------------------------------------- namespace PartGui { class EdgeFaceSelection : public Gui::SelectionFilterGate { bool allowEdge; App::DocumentObject*& object; public: EdgeFaceSelection(App::DocumentObject*& obj) : Gui::SelectionFilterGate((Gui::SelectionFilter*)0), allowEdge(true), object(obj) { } void selectEdges() { allowEdge = true; } void selectFaces() { allowEdge = false; } bool allow(App::Document* /*pDoc*/, App::DocumentObject*pObj, const char*sSubName) { if (pObj != this->object) return false; if (!sSubName || sSubName[0] == '\0') return false; std::string element(sSubName); if (allowEdge) return element.substr(0,4) == "Edge"; else return element.substr(0,4) == "Face"; } }; class DlgFilletEdges::Private { public: App::DocumentObject* object; EdgeFaceSelection* selection; Part::FilletBase* fillet; QTimer* highlighttimer; FilletType filletType; std::vector edge_ids; TopTools_IndexedMapOfShape all_edges; TopTools_IndexedMapOfShape all_faces; typedef boost::signals::connection Connection; Connection connectApplicationDeletedObject; Connection connectApplicationDeletedDocument; class SelectionObjectCompare { public: App::DocumentObject* obj; SelectionObjectCompare(App::DocumentObject* obj) : obj(obj) { } bool operator()(const Gui::SelectionObject& sel) const { return (sel.getObject() == obj); } }; }; }; /* TRANSLATOR PartGui::DlgFilletEdges */ DlgFilletEdges::DlgFilletEdges(FilletType type, Part::FilletBase* fillet, QWidget* parent, Qt::WindowFlags fl) : QWidget(parent, fl), ui(new Ui_DlgFilletEdges()), d(new Private()) { ui->setupUi(this); ui->filletStartRadius->setMaximum(INT_MAX); ui->filletStartRadius->setMinimum(0); ui->filletStartRadius->setUnit(Base::Unit::Length); ui->filletEndRadius->setMaximum(INT_MAX); ui->filletEndRadius->setMinimum(0); ui->filletEndRadius->setUnit(Base::Unit::Length); d->object = 0; d->selection = new EdgeFaceSelection(d->object); Gui::Selection().addSelectionGate(d->selection); d->fillet = fillet; d->connectApplicationDeletedObject = App::GetApplication().signalDeletedObject .connect(boost::bind(&DlgFilletEdges::onDeleteObject, this, _1)); d->connectApplicationDeletedDocument = App::GetApplication().signalDeleteDocument .connect(boost::bind(&DlgFilletEdges::onDeleteDocument, this, _1)); // set tree view with three columns QStandardItemModel* model = new FilletRadiusModel(this); connect(model, SIGNAL(toggleCheckState(const QModelIndex&)), this, SLOT(toggleCheckState(const QModelIndex&))); model->insertColumns(0,3); // timer for highlighting d->highlighttimer = new QTimer(this); d->highlighttimer->setSingleShot(true); connect(d->highlighttimer,SIGNAL(timeout()), this, SLOT(onHighlightEdges())); d->filletType = type; if (d->filletType == DlgFilletEdges::CHAMFER) { ui->labelRadius->setText(tr("Length:")); ui->filletType->setItemText(0, tr("Constant Length")); ui->filletType->setItemText(1, tr("Variable Length")); model->setHeaderData(0, Qt::Horizontal, tr("Edges to chamfer"), Qt::DisplayRole); model->setHeaderData(1, Qt::Horizontal, tr("Start length"), Qt::DisplayRole); model->setHeaderData(2, Qt::Horizontal, tr("End length"), Qt::DisplayRole); } else { model->setHeaderData(0, Qt::Horizontal, tr("Edges to fillet"), Qt::DisplayRole); model->setHeaderData(1, Qt::Horizontal, tr("Start radius"), Qt::DisplayRole); model->setHeaderData(2, Qt::Horizontal, tr("End radius"), Qt::DisplayRole); } ui->treeView->setRootIsDecorated(false); ui->treeView->setItemDelegate(new FilletRadiusDelegate(this)); ui->treeView->setModel(model); QHeaderView* header = ui->treeView->header(); header->setResizeMode(0, QHeaderView::Stretch); header->setDefaultAlignment(Qt::AlignLeft); header->setMovable(false); on_filletType_activated(0); findShapes(); } /* * Destroys the object and frees any allocated resources */ DlgFilletEdges::~DlgFilletEdges() { // no need to delete child widgets, Qt does it all for us d->connectApplicationDeletedDocument.disconnect(); d->connectApplicationDeletedObject.disconnect(); Gui::Selection().rmvSelectionGate(); } void DlgFilletEdges::onSelectionChanged(const Gui::SelectionChanges& msg) { // no object selected in the combobox or no sub-element was selected if (!d->object || !msg.pSubName) return; if (msg.Type == Gui::SelectionChanges::AddSelection || msg.Type == Gui::SelectionChanges::RmvSelection) { // when adding a sub-element to the selection check // whether this is the currently handled object App::Document* doc = d->object->getDocument(); std::string docname = doc->getName(); std::string objname = d->object->getNameInDocument(); if (docname==msg.pDocName && objname==msg.pObjectName) { QString subelement = QString::fromLatin1(msg.pSubName); if (subelement.startsWith(QLatin1String("Edge"))) { onSelectEdge(subelement, msg.Type); } else if (subelement.startsWith(QLatin1String("Face"))) { d->selection->selectEdges(); onSelectEdgesOfFace(subelement, msg.Type); d->selection->selectFaces(); } } } if (msg.Type != Gui::SelectionChanges::SetPreselect && msg.Type != Gui::SelectionChanges::RmvPreselect) d->highlighttimer->start(20); } void DlgFilletEdges::onHighlightEdges() { Gui::ViewProvider* view = Gui::Application::Instance->getViewProvider(d->object); if (view) { // deselect all faces { SoSearchAction searchAction; searchAction.setType(PartGui::SoBrepFaceSet::getClassTypeId()); searchAction.setInterest(SoSearchAction::FIRST); searchAction.apply(view->getRoot()); SoPath* selectionPath = searchAction.getPath(); if (selectionPath) { Gui::SoSelectionElementAction action(Gui::SoSelectionElementAction::None); action.apply(selectionPath); } } // deselect all points { SoSearchAction searchAction; searchAction.setType(PartGui::SoBrepPointSet::getClassTypeId()); searchAction.setInterest(SoSearchAction::FIRST); searchAction.apply(view->getRoot()); SoPath* selectionPath = searchAction.getPath(); if (selectionPath) { Gui::SoSelectionElementAction action(Gui::SoSelectionElementAction::None); action.apply(selectionPath); } } // select the edges { SoSearchAction searchAction; searchAction.setType(PartGui::SoBrepEdgeSet::getClassTypeId()); searchAction.setInterest(SoSearchAction::FIRST); searchAction.apply(view->getRoot()); SoPath* selectionPath = searchAction.getPath(); if (selectionPath) { ParameterGrp::handle hGrp = Gui::WindowParameter::getDefaultParameter()->GetGroup("View"); SbColor selectionColor(0.1f, 0.8f, 0.1f); unsigned long selection = (unsigned long)(selectionColor.getPackedValue()); selection = hGrp->GetUnsigned("SelectionColor", selection); float transparency; selectionColor.setPackedValue((uint32_t)selection, transparency); // clear the selection first Gui::SoSelectionElementAction clear(Gui::SoSelectionElementAction::None); clear.apply(selectionPath); Gui::SoSelectionElementAction action(Gui::SoSelectionElementAction::Append); action.setColor(selectionColor); action.apply(selectionPath); QAbstractItemModel* model = ui->treeView->model(); SoLineDetail detail; action.setElement(&detail); for (int i=0; irowCount(); ++i) { QVariant value = model->index(i,0).data(Qt::CheckStateRole); Qt::CheckState checkState = static_cast(value.toInt()); // is item checked if (checkState & Qt::Checked) { // the index value of the edge int id = model->index(i,0).data(Qt::UserRole).toInt(); detail.setLineIndex(id-1); action.apply(selectionPath); } } } } } } void DlgFilletEdges::onSelectEdge(const QString& subelement, int type) { Gui::SelectionChanges::MsgType msgType = Gui::SelectionChanges::MsgType(type); QAbstractItemModel* model = ui->treeView->model(); for (int i=0; irowCount(); ++i) { int id = model->data(model->index(i,0), Qt::UserRole).toInt(); QString name = QString::fromLatin1("Edge%1").arg(id); if (name == subelement) { // ok, check the selected sub-element Qt::CheckState checkState = (msgType == Gui::SelectionChanges::AddSelection ? Qt::Checked : Qt::Unchecked); QVariant value(static_cast(checkState)); QModelIndex index = model->index(i,0); model->setData(index, value, Qt::CheckStateRole); // select the item ui->treeView->selectionModel()->setCurrentIndex(index,QItemSelectionModel::NoUpdate); QItemSelection selection(index, model->index(i,1)); ui->treeView->selectionModel()->select(selection, QItemSelectionModel::ClearAndSelect); ui->treeView->update(); break; } } } void DlgFilletEdges::onSelectEdgesOfFace(const QString& subelement, int type) { bool ok; int index = subelement.mid(4).toInt(&ok); if (ok) { try { const TopoDS_Shape& face = d->all_faces.FindKey(index); TopTools_IndexedMapOfShape mapOfEdges; TopExp::MapShapes(face, TopAbs_EDGE, mapOfEdges); for(int j = 1; j <= mapOfEdges.Extent(); ++j) { TopoDS_Edge edge = TopoDS::Edge(mapOfEdges.FindKey(j)); int id = d->all_edges.FindIndex(edge); QString name = QString::fromLatin1("Edge%1").arg(id); onSelectEdge(name, type); Gui::SelectionChanges::MsgType msgType = Gui::SelectionChanges::MsgType(type); if (msgType == Gui::SelectionChanges::AddSelection) { Gui::Selection().addSelection(d->object->getDocument()->getName(), d->object->getNameInDocument(), (const char*)name.toLatin1()); } } } catch (Standard_Failure) { } } } void DlgFilletEdges::onDeleteObject(const App::DocumentObject& obj) { if (d->fillet == &obj) { d->fillet = 0; } else if (d->fillet && d->fillet->Base.getValue() == &obj) { d->fillet = 0; d->object = 0; ui->shapeObject->setCurrentIndex(0); on_shapeObject_activated(0); } else if (d->object == &obj) { d->object = 0; ui->shapeObject->removeItem(ui->shapeObject->currentIndex()); ui->shapeObject->setCurrentIndex(0); on_shapeObject_activated(0); } else { QString shape = QString::fromLatin1(obj.getNameInDocument()); // start from the second item for (int i=1; ishapeObject->count(); i++) { if (ui->shapeObject->itemData(i).toString() == shape) { ui->shapeObject->removeItem(i); break; } } } } void DlgFilletEdges::onDeleteDocument(const App::Document& doc) { if (d->object) { if (d->object->getDocument() == &doc) { ui->shapeObject->setCurrentIndex(0); on_shapeObject_activated(0); setEnabled(false); } } else if (App::GetApplication().getActiveDocument() == &doc) { ui->shapeObject->setCurrentIndex(0); on_shapeObject_activated(0); setEnabled(false); } } void DlgFilletEdges::toggleCheckState(const QModelIndex& index) { if (!d->object) return; QVariant check = index.data(Qt::CheckStateRole); int id = index.data(Qt::UserRole).toInt(); QString name = QString::fromLatin1("Edge%1").arg(id); Qt::CheckState checkState = static_cast(check.toInt()); bool block = this->blockConnection(true); // is item checked if (checkState & Qt::Checked) { App::Document* doc = d->object->getDocument(); Gui::Selection().addSelection(doc->getName(), d->object->getNameInDocument(), (const char*)name.toLatin1()); } else { App::Document* doc = d->object->getDocument(); Gui::Selection().rmvSelection(doc->getName(), d->object->getNameInDocument(), (const char*)name.toLatin1()); } this->blockConnection(block); } void DlgFilletEdges::findShapes() { App::Document* activeDoc = App::GetApplication().getActiveDocument(); if (!activeDoc) return; std::vector objs = activeDoc->getObjectsOfType (Part::Feature::getClassTypeId()); int index = 1; int current_index = 0; for (std::vector::iterator it = objs.begin(); it!=objs.end(); ++it, ++index) { ui->shapeObject->addItem(QString::fromUtf8((*it)->Label.getValue())); ui->shapeObject->setItemData(index, QString::fromLatin1((*it)->getNameInDocument())); if (current_index == 0) { if (Gui::Selection().isSelected(*it)) { current_index = index; } } } // if only one object is in the document then simply use that if (objs.size() == 1) current_index = 1; if (current_index > 0) { ui->shapeObject->setCurrentIndex(current_index); on_shapeObject_activated(current_index); } // if an existing fillet object is given start the edit mode if (d->fillet) { setupFillet(objs); } } void DlgFilletEdges::setupFillet(const std::vector& objs) { App::DocumentObject* base = d->fillet->Base.getValue(); const std::vector& e = d->fillet->Edges.getValues(); std::vector::const_iterator it = std::find(objs.begin(), objs.end(), base); if (it != objs.end()) { // toggle visibility Gui::ViewProvider* vp; vp = Gui::Application::Instance->getViewProvider(d->fillet); if (vp) vp->hide(); vp = Gui::Application::Instance->getViewProvider(base); if (vp) vp->show(); int current_index = (it - objs.begin()) + 1; ui->shapeObject->setCurrentIndex(current_index); on_shapeObject_activated(current_index); ui->shapeObject->setEnabled(false); double startRadius = 1; double endRadius = 1; bool twoRadii = false; std::vector subElements; QStandardItemModel *model = qobject_cast(ui->treeView->model()); bool block = model->blockSignals(true); // do not call toggleCheckState for (std::vector::const_iterator et = e.begin(); et != e.end(); ++et) { std::vector::iterator it = std::find(d->edge_ids.begin(), d->edge_ids.end(), et->edgeid); if (it != d->edge_ids.end()) { int index = it - d->edge_ids.begin(); model->setData(model->index(index, 0), Qt::Checked, Qt::CheckStateRole); //model->setData(model->index(index, 1), QVariant(QLocale::system().toString(et->radius1,'f',Base::UnitsApi::getDecimals()))); //model->setData(model->index(index, 2), QVariant(QLocale::system().toString(et->radius2,'f',Base::UnitsApi::getDecimals()))); model->setData(model->index(index, 1), QVariant::fromValue(Base::Quantity(et->radius1, Base::Unit::Length))); model->setData(model->index(index, 2), QVariant::fromValue(Base::Quantity(et->radius2, Base::Unit::Length))); startRadius = et->radius1; endRadius = et->radius2; if (startRadius != endRadius) twoRadii = true; int id = model->index(index, 0).data(Qt::UserRole).toInt(); std::stringstream str; str << "Edge" << id; subElements.push_back(str.str()); } } model->blockSignals(block); // #0002273 if (twoRadii) { ui->filletType->setCurrentIndex(1); on_filletType_activated(1); } // #0001746 ui->filletStartRadius->blockSignals(true); ui->filletStartRadius->setValue(startRadius); ui->filletStartRadius->blockSignals(false); ui->filletEndRadius->blockSignals(true); ui->filletEndRadius->setValue(endRadius); ui->filletEndRadius->blockSignals(false); App::Document* doc = d->object->getDocument(); // get current selection and their sub-elements std::vector selObj = Gui::Selection().getSelectionEx(doc->getName()); std::vector::iterator selIt = std::find_if(selObj.begin(), selObj.end(), Private::SelectionObjectCompare(d->object)); // If sub-objects are already selected then only add the un-selected parts. // This is impotant to avoid recursive calls of rmvSelection() which // invalidates the internal iterator (#0002200). if (selIt != selObj.end()) { std::vector selElements = selIt->getSubNames(); std::sort(selElements.begin(), selElements.end()); std::sort(subElements.begin(), subElements.end()); std::vector complementary; std::back_insert_iterator > biit(complementary); std::set_difference(subElements.begin(), subElements.end(), selElements.begin(), selElements.end(), biit); subElements = complementary; } if (!subElements.empty()) { Gui::Selection().addSelection(doc->getName(), d->object->getNameInDocument(), subElements); } } } /** * Sets the strings of the subwidgets using the current language. */ void DlgFilletEdges::changeEvent(QEvent *e) { if (e->type() == QEvent::LanguageChange) { int index = ui->shapeObject->currentIndex(); // only get the items from index 1 on since the first one will be added automatically int count = ui->shapeObject->count() - 1; QStringList text; QList data; for (int i=0; ishapeObject->itemText(i+1); data << ui->shapeObject->itemData(i+1); } ui->retranslateUi(this); for (int i=0; ishapeObject->addItem(text.at(i)); ui->shapeObject->setItemData(i+1, data.at(i)); } ui->shapeObject->setCurrentIndex(index); QStandardItemModel *model = qobject_cast(ui->treeView->model()); count = model->rowCount(); for (int i=0; idata(model->index(i, 0), Qt::UserRole).toInt(); model->setData(model->index(i, 0), QVariant(tr("Edge%1").arg(id))); } } else { QWidget::changeEvent(e); } } void DlgFilletEdges::on_shapeObject_activated(int index) { d->object = 0; QStandardItemModel *model = qobject_cast(ui->treeView->model()); model->removeRows(0, model->rowCount()); QByteArray name = ui->shapeObject->itemData(index).toByteArray(); App::Document* doc = App::GetApplication().getActiveDocument(); if (!doc) return; App::DocumentObject* part = doc->getObject((const char*)name); if (part && part->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) { d->object = part; TopoDS_Shape myShape = static_cast(part)->Shape.getValue(); d->all_edges.Clear(); TopExp::MapShapes(myShape, TopAbs_EDGE, d->all_edges); d->all_faces.Clear(); TopExp::MapShapes(myShape, TopAbs_FACE, d->all_faces); // build up map edge->face TopTools_IndexedDataMapOfShapeListOfShape edge2Face; TopExp::MapShapesAndAncestors(myShape, TopAbs_EDGE, TopAbs_FACE, edge2Face); TopTools_IndexedMapOfShape mapOfShape; TopExp::MapShapes(myShape, TopAbs_EDGE, mapOfShape); // populate the model d->edge_ids.clear(); for (int i=1; i<= edge2Face.Extent(); ++i) { // set the index value as user data to use it in accept() const TopTools_ListOfShape& los = edge2Face.FindFromIndex(i); if (los.Extent() == 2) { // set the index value as user data to use it in accept() const TopoDS_Shape& edge = edge2Face.FindKey(i); // Now check also the continuity to only allow C0-continious // faces const TopoDS_Shape& face1 = los.First(); const TopoDS_Shape& face2 = los.Last(); GeomAbs_Shape cont = BRep_Tool::Continuity(TopoDS::Edge(edge), TopoDS::Face(face1), TopoDS::Face(face2)); if (cont == GeomAbs_C0) { int id = mapOfShape.FindIndex(edge); d->edge_ids.push_back(id); } } } model->insertRows(0, d->edge_ids.size()); int index = 0; for (std::vector::iterator it = d->edge_ids.begin(); it != d->edge_ids.end(); ++it) { model->setData(model->index(index, 0), QVariant(tr("Edge%1").arg(*it))); model->setData(model->index(index, 0), QVariant(*it), Qt::UserRole); //model->setData(model->index(index, 1), QVariant(QLocale::system().toString(1.0,'f',Base::UnitsApi::getDecimals()))); //model->setData(model->index(index, 2), QVariant(QLocale::system().toString(1.0,'f',Base::UnitsApi::getDecimals()))); model->setData(model->index(index, 1), QVariant::fromValue(Base::Quantity(1.0,Base::Unit::Length))); model->setData(model->index(index, 2), QVariant::fromValue(Base::Quantity(1.0,Base::Unit::Length))); std::stringstream element; element << "Edge" << *it; if (Gui::Selection().isSelected(part, element.str().c_str())) model->setData(model->index(index, 0), Qt::Checked, Qt::CheckStateRole); else model->setData(model->index(index, 0), Qt::Unchecked, Qt::CheckStateRole); index++; } } } void DlgFilletEdges::on_selectEdges_toggled(bool on) { if (on) d->selection->selectEdges(); } void DlgFilletEdges::on_selectFaces_toggled(bool on) { if (on) d->selection->selectFaces(); } void DlgFilletEdges::on_selectAllButton_clicked() { std::vector subElements; FilletRadiusModel* model = static_cast(ui->treeView->model()); bool block = model->blockSignals(true); // do not call toggleCheckState for (int i=0; irowCount(); ++i) { QModelIndex index = model->index(i,0); // is not yet checked? QVariant check = index.data(Qt::CheckStateRole); Qt::CheckState state = static_cast(check.toInt()); if (state == Qt::Unchecked) { int id = index.data(Qt::UserRole).toInt(); std::stringstream str; str << "Edge" << id; subElements.push_back(str.str()); } Qt::CheckState checkState = Qt::Checked; QVariant value(static_cast(checkState)); model->setData(index, value, Qt::CheckStateRole); } model->blockSignals(block); model->updateCheckStates(); App::Document* doc = d->object->getDocument(); Gui::Selection().addSelection(doc->getName(), d->object->getNameInDocument(), subElements); } void DlgFilletEdges::on_selectNoneButton_clicked() { FilletRadiusModel* model = static_cast(ui->treeView->model()); bool block = model->blockSignals(true); // do not call toggleCheckState for (int i=0; irowCount(); ++i) { Qt::CheckState checkState = Qt::Unchecked; QVariant value(static_cast(checkState)); model->setData(model->index(i,0), value, Qt::CheckStateRole); } model->blockSignals(block); model->updateCheckStates(); App::Document* doc = d->object->getDocument(); Gui::Selection().clearSelection(doc->getName()); } void DlgFilletEdges::on_filletType_activated(int index) { QStandardItemModel *model = qobject_cast(ui->treeView->model()); if (index == 0) { if (d->filletType == DlgFilletEdges::CHAMFER) model->setHeaderData(1, Qt::Horizontal, tr("Length"), Qt::DisplayRole); else model->setHeaderData(1, Qt::Horizontal, tr("Radius"), Qt::DisplayRole); ui->treeView->hideColumn(2); ui->filletEndRadius->hide(); } else { if (d->filletType == DlgFilletEdges::CHAMFER) model->setHeaderData(1, Qt::Horizontal, tr("Start length"), Qt::DisplayRole); else model->setHeaderData(1, Qt::Horizontal, tr("Start radius"), Qt::DisplayRole); ui->treeView->showColumn(2); ui->filletEndRadius->show(); } ui->treeView->resizeColumnToContents(0); ui->treeView->resizeColumnToContents(1); ui->treeView->resizeColumnToContents(2); } void DlgFilletEdges::on_filletStartRadius_valueChanged(const Base::Quantity& radius) { QAbstractItemModel* model = ui->treeView->model(); for (int i=0; irowCount(); ++i) { QVariant value = model->index(i,0).data(Qt::CheckStateRole); Qt::CheckState checkState = static_cast(value.toInt()); // is item checked if (checkState & Qt::Checked) { model->setData(model->index(i, 1), QVariant::fromValue(radius)); } } } void DlgFilletEdges::on_filletEndRadius_valueChanged(const Base::Quantity& radius) { QAbstractItemModel* model = ui->treeView->model(); for (int i=0; irowCount(); ++i) { QVariant value = model->index(i,0).data(Qt::CheckStateRole); Qt::CheckState checkState = static_cast(value.toInt()); // is item checked if (checkState & Qt::Checked) { model->setData(model->index(i, 2), QVariant::fromValue(radius)); } } } const char* DlgFilletEdges::getFilletType() const { return "Fillet"; } bool DlgFilletEdges::accept() { if (!d->object) { QMessageBox::warning(this, tr("No shape selected"), tr("No valid shape is selected.\n" "Please select a valid shape in the drop-down box first.")); return false; } App::Document* activeDoc = App::GetApplication().getActiveDocument(); QAbstractItemModel* model = ui->treeView->model(); bool end_radius = !ui->treeView->isColumnHidden(2); bool todo = false; QString shape, type, name; std::string fillet = getFilletType(); int index = ui->shapeObject->currentIndex(); shape = ui->shapeObject->itemData(index).toString(); type = QString::fromLatin1("Part::%1").arg(QString::fromLatin1(fillet.c_str())); if (d->fillet) name = QString::fromLatin1(d->fillet->getNameInDocument()); else name = QString::fromLatin1(activeDoc->getUniqueObjectName(fillet.c_str()).c_str()); activeDoc->openTransaction(fillet.c_str()); QString code; if (!d->fillet) { code = QString::fromLatin1( "FreeCAD.ActiveDocument.addObject(\"%1\",\"%2\")\n" "FreeCAD.ActiveDocument.%2.Base = FreeCAD.ActiveDocument.%3\n") .arg(type).arg(name).arg(shape); } code += QString::fromLatin1("__fillets__ = []\n"); for (int i=0; irowCount(); ++i) { QVariant value = model->index(i,0).data(Qt::CheckStateRole); Qt::CheckState checkState = static_cast(value.toInt()); // is item checked if (checkState & Qt::Checked) { // the index value of the edge int id = model->index(i,0).data(Qt::UserRole).toInt(); Base::Quantity r1 = model->index(i,1).data(Qt::EditRole).value(); Base::Quantity r2 = r1; if (end_radius) r2 = model->index(i,2).data(Qt::EditRole).value(); code += QString::fromLatin1( "__fillets__.append((%1,%2,%3))\n") .arg(id) .arg(r1.getValue(),0,'f',Base::UnitsApi::getDecimals()) .arg(r2.getValue(),0,'f',Base::UnitsApi::getDecimals()); todo = true; } } if (!todo) { QMessageBox::warning(this, tr("No edge selected"), tr("No edge entity is checked to fillet.\n" "Please check one or more edge entities first.")); return false; } Gui::WaitCursor wc; code += QString::fromLatin1( "FreeCAD.ActiveDocument.%1.Edges = __fillets__\n" "del __fillets__\n" "FreeCADGui.ActiveDocument.%2.Visibility = False\n") .arg(name).arg(shape); Gui::Command::runCommand(Gui::Command::App, code.toLatin1()); activeDoc->commitTransaction(); activeDoc->recompute(); if (d->fillet) { Gui::ViewProvider* vp; vp = Gui::Application::Instance->getViewProvider(d->fillet); if (vp) vp->show(); } QByteArray to = name.toLatin1(); QByteArray from = shape.toLatin1(); Gui::Command::copyVisual(to, "LineColor", from); Gui::Command::copyVisual(to, "PointColor", from); return true; } // --------------------------------------- FilletEdgesDialog::FilletEdgesDialog(DlgFilletEdges::FilletType type, Part::FilletBase* fillet, QWidget* parent, Qt::WindowFlags fl) : QDialog(parent, fl) { widget = new DlgFilletEdges(type, fillet, this); this->setWindowTitle(widget->windowTitle()); QVBoxLayout* hboxLayout = new QVBoxLayout(this); QDialogButtonBox* buttonBox = new QDialogButtonBox(this); buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok); QObject::connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept())); QObject::connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject())); hboxLayout->addWidget(widget); hboxLayout->addWidget(buttonBox); } FilletEdgesDialog::~FilletEdgesDialog() { } void FilletEdgesDialog::accept() { if (widget->accept()) QDialog::accept(); } // --------------------------------------- TaskFilletEdges::TaskFilletEdges(Part::Fillet* fillet) { widget = new DlgFilletEdges(DlgFilletEdges::FILLET, fillet); taskbox = new Gui::TaskView::TaskBox( Gui::BitmapFactory().pixmap("Part_Fillet"), widget->windowTitle(), true, 0); taskbox->groupLayout()->addWidget(widget); Content.push_back(taskbox); } TaskFilletEdges::~TaskFilletEdges() { // automatically deleted in the sub-class } void TaskFilletEdges::open() { } void TaskFilletEdges::clicked(int) { } bool TaskFilletEdges::accept() { bool ok = widget->accept(); if (ok) Gui::Command::doCommand(Gui::Command::Gui,"Gui.activeDocument().resetEdit()"); return ok; } bool TaskFilletEdges::reject() { Gui::Command::doCommand(Gui::Command::Gui,"Gui.activeDocument().resetEdit()"); return true; } // -------------------------------------------------------------- /* TRANSLATOR PartGui::DlgChamferEdges */ DlgChamferEdges::DlgChamferEdges(Part::FilletBase* chamfer, QWidget* parent, Qt::WindowFlags fl) : DlgFilletEdges(DlgFilletEdges::CHAMFER, chamfer, parent, fl) { this->setWindowTitle(tr("Chamfer Edges")); } /* * Destroys the object and frees any allocated resources */ DlgChamferEdges::~DlgChamferEdges() { } const char* DlgChamferEdges::getFilletType() const { return "Chamfer"; } TaskChamferEdges::TaskChamferEdges(Part::Chamfer* chamfer) { widget = new DlgChamferEdges(chamfer); taskbox = new Gui::TaskView::TaskBox( Gui::BitmapFactory().pixmap("Part_Chamfer"), widget->windowTitle(), true, 0); taskbox->groupLayout()->addWidget(widget); Content.push_back(taskbox); } TaskChamferEdges::~TaskChamferEdges() { // automatically deleted in the sub-class } void TaskChamferEdges::open() { } void TaskChamferEdges::clicked(int) { } bool TaskChamferEdges::accept() { bool ok = widget->accept(); if (ok) Gui::Command::doCommand(Gui::Command::Gui,"Gui.activeDocument().resetEdit()"); return ok; } bool TaskChamferEdges::reject() { Gui::Command::doCommand(Gui::Command::Gui,"Gui.activeDocument().resetEdit()"); return true; } #include "moc_DlgFilletEdges.cpp"