/****************************************************************************** * Copyright (c) 2012 Jan Rheinländer * * * * 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 #endif #include #include #include #include #include #include #include #include #include #include #include #include #include "ui_TaskLinearPatternParameters.h" #include "TaskLinearPatternParameters.h" #include "ReferenceSelection.h" #include "TaskMultiTransformParameters.h" using namespace PartDesignGui; using namespace Gui; /* TRANSLATOR PartDesignGui::TaskLinearPatternParameters */ TaskLinearPatternParameters::TaskLinearPatternParameters(ViewProviderTransformed* TransformedView, QWidget* parent) : TaskTransformedParameters(TransformedView, parent) , ui(new Ui_TaskLinearPatternParameters) { setupUI(); } TaskLinearPatternParameters::TaskLinearPatternParameters(TaskMultiTransformParameters* parentTask, QWidget* parameterWidget) : TaskTransformedParameters(parentTask) , ui(new Ui_TaskLinearPatternParameters) { setupParameterUI(parameterWidget); } void TaskLinearPatternParameters::setupParameterUI(QWidget* widget) { ui->setupUi(widget); QMetaObject::connectSlotsByName(this); // Get the feature data auto pcLinearPattern = static_cast(getObject()); ui->spinLength->bind(pcLinearPattern->Length); ui->spinOffset->bind(pcLinearPattern->Offset); ui->spinOccurrences->bind(pcLinearPattern->Occurrences); ui->spinOccurrences->setMaximum(pcLinearPattern->Occurrences.getMaximum()); ui->spinOccurrences->setMinimum(pcLinearPattern->Occurrences.getMinimum()); ui->comboDirection->setEnabled(true); ui->checkReverse->setEnabled(true); ui->comboMode->setEnabled(true); ui->spinLength->blockSignals(true); ui->spinLength->setEnabled(true); ui->spinLength->setUnit(Base::Unit::Length); ui->spinLength->blockSignals(false); ui->spinOffset->blockSignals(true); ui->spinOffset->setEnabled(true); ui->spinOffset->setUnit(Base::Unit::Length); ui->spinOffset->blockSignals(false); ui->spinOccurrences->setEnabled(true); dirLinks.setCombo(*(ui->comboDirection)); App::DocumentObject* sketch = getSketchObject(); if (sketch && sketch->isDerivedFrom()) { this->fillAxisCombo(dirLinks, static_cast(sketch)); } else { this->fillAxisCombo(dirLinks, nullptr); } // show the parts coordinate system axis for selection PartDesign::Body* body = PartDesign::Body::findBodyOf(getObject()); if (body) { try { App::Origin* origin = body->getOrigin(); auto vpOrigin = static_cast( Gui::Application::Instance->getViewProvider(origin)); vpOrigin->setTemporaryVisibility(true, false); } catch (const Base::Exception& ex) { Base::Console().Error("%s\n", ex.what()); } } adaptVisibilityToMode(); updateViewTimer = new QTimer(this); updateViewTimer->setSingleShot(true); updateViewTimer->setInterval(getUpdateViewTimeout()); connect(updateViewTimer, &QTimer::timeout, this, &TaskLinearPatternParameters::onUpdateViewTimer); connect(ui->comboDirection, qOverload(&QComboBox::activated), this, &TaskLinearPatternParameters::onDirectionChanged); connect(ui->checkReverse, &QCheckBox::toggled, this, &TaskLinearPatternParameters::onCheckReverse); connect(ui->comboMode, qOverload(&QComboBox::activated), this, &TaskLinearPatternParameters::onModeChanged); connect(ui->spinLength, qOverload(&Gui::QuantitySpinBox::valueChanged), this, &TaskLinearPatternParameters::onLength); connect(ui->spinOffset, qOverload(&Gui::QuantitySpinBox::valueChanged), this, &TaskLinearPatternParameters::onOffset); connect(ui->spinOccurrences, &Gui::UIntSpinBox::unsignedChanged, this, &TaskLinearPatternParameters::onOccurrences); } void TaskLinearPatternParameters::retranslateParameterUI(QWidget* widget) { ui->retranslateUi(widget); } void TaskLinearPatternParameters::updateUI() { if (blockUpdate) { return; } blockUpdate = true; auto pcLinearPattern = static_cast(getObject()); auto mode = static_cast(pcLinearPattern->Mode.getValue()); bool reverse = pcLinearPattern->Reversed.getValue(); double length = pcLinearPattern->Length.getValue(); double offset = pcLinearPattern->Offset.getValue(); unsigned occurrences = pcLinearPattern->Occurrences.getValue(); if (dirLinks.setCurrentLink(pcLinearPattern->Direction) == -1) { // failed to set current, because the link isn't in the list yet dirLinks.addLink(pcLinearPattern->Direction, getRefStr(pcLinearPattern->Direction.getValue(), pcLinearPattern->Direction.getSubValues())); dirLinks.setCurrentLink(pcLinearPattern->Direction); } // Note: This block of code would trigger change signal handlers (e.g. onOccurrences()) // and another updateUI() if we didn't check for blockUpdate ui->checkReverse->setChecked(reverse); ui->comboMode->setCurrentIndex(static_cast(mode)); ui->spinLength->setValue(length); ui->spinOffset->setValue(offset); ui->spinOccurrences->setValue(occurrences); blockUpdate = false; } void TaskLinearPatternParameters::adaptVisibilityToMode() { auto pcLinearPattern = static_cast(getObject()); auto mode = static_cast(pcLinearPattern->Mode.getValue()); ui->lengthWrapper->setVisible(mode == PartDesign::LinearPatternMode::length); ui->offsetWrapper->setVisible(mode == PartDesign::LinearPatternMode::offset); updateUI(); } void TaskLinearPatternParameters::onUpdateViewTimer() { setupTransaction(); recomputeFeature(); } void TaskLinearPatternParameters::kickUpdateViewTimer() const { updateViewTimer->start(); } void TaskLinearPatternParameters::onSelectionChanged(const Gui::SelectionChanges& msg) { if (selectionMode != SelectionMode::None && msg.Type == Gui::SelectionChanges::AddSelection) { if (originalSelected(msg)) { exitSelectionMode(); } else if (selectionMode == SelectionMode::Reference) { auto pcLinearPattern = static_cast(getObject()); std::vector directions; App::DocumentObject* selObj = nullptr; getReferencedSelection(pcLinearPattern, msg, selObj, directions); if (!selObj) { return; } // Note: ReferenceSelection has already checked the selection for validity if (selObj->isDerivedFrom() || selObj->isDerivedFrom() || selObj->isDerivedFrom() || selObj->isDerivedFrom()) { setupTransaction(); pcLinearPattern->Direction.setValue(selObj, directions); recomputeFeature(); updateUI(); } exitSelectionMode(); } } } void TaskLinearPatternParameters::onCheckReverse(const bool on) { if (blockUpdate) { return; } auto pcLinearPattern = static_cast(getObject()); pcLinearPattern->Reversed.setValue(on); exitSelectionMode(); kickUpdateViewTimer(); } void TaskLinearPatternParameters::onModeChanged(const int mode) { if (blockUpdate) { return; } auto pcLinearPattern = static_cast(getObject()); pcLinearPattern->Mode.setValue(mode); adaptVisibilityToMode(); exitSelectionMode(); kickUpdateViewTimer(); } void TaskLinearPatternParameters::onLength(const double length) { if (blockUpdate) { return; } auto pcLinearPattern = static_cast(getObject()); pcLinearPattern->Length.setValue(length); exitSelectionMode(); kickUpdateViewTimer(); } void TaskLinearPatternParameters::onOffset(const double offset) { if (blockUpdate) { return; } auto pcLinearPattern = static_cast(getObject()); pcLinearPattern->Offset.setValue(offset); exitSelectionMode(); kickUpdateViewTimer(); } void TaskLinearPatternParameters::onOccurrences(const uint number) { if (blockUpdate) { return; } auto pcLinearPattern = static_cast(getObject()); pcLinearPattern->Occurrences.setValue(number); exitSelectionMode(); kickUpdateViewTimer(); } void TaskLinearPatternParameters::onDirectionChanged(int /*num*/) { if (blockUpdate) { return; } auto pcLinearPattern = static_cast(getObject()); try { if (!dirLinks.getCurrentLink().getValue()) { // enter reference selection mode hideObject(); showBase(); selectionMode = SelectionMode::Reference; Gui::Selection().clearSelection(); addReferenceSelectionGate(AllowSelection::EDGE | AllowSelection::FACE | AllowSelection::PLANAR); } else { exitSelectionMode(); pcLinearPattern->Direction.Paste(dirLinks.getCurrentLink()); } } catch (Base::Exception& e) { QMessageBox::warning(nullptr, tr("Error"), QApplication::translate("Exception", e.what())); } kickUpdateViewTimer(); } void TaskLinearPatternParameters::onUpdateView(bool on) { blockUpdate = !on; if (on) { // Do the same like in TaskDlgLinearPatternParameters::accept() but without doCommand auto pcLinearPattern = static_cast(getObject()); std::vector directions; App::DocumentObject* obj = nullptr; setupTransaction(); getDirection(obj, directions); pcLinearPattern->Direction.setValue(obj, directions); pcLinearPattern->Reversed.setValue(getReverse()); pcLinearPattern->Length.setValue(getLength()); pcLinearPattern->Offset.setValue(getOffset()); pcLinearPattern->Occurrences.setValue(getOccurrences()); recomputeFeature(); } } void TaskLinearPatternParameters::getDirection(App::DocumentObject*& obj, std::vector& sub) const { const App::PropertyLinkSub& lnk = dirLinks.getCurrentLink(); obj = lnk.getValue(); sub = lnk.getSubValues(); } bool TaskLinearPatternParameters::getReverse() const { return ui->checkReverse->isChecked(); } int TaskLinearPatternParameters::getMode() const { return ui->comboMode->currentIndex(); } double TaskLinearPatternParameters::getLength() const { return ui->spinLength->value().getValue(); } double TaskLinearPatternParameters::getOffset() const { return ui->spinOffset->value().getValue(); } unsigned TaskLinearPatternParameters::getOccurrences() const { return ui->spinOccurrences->value(); } TaskLinearPatternParameters::~TaskLinearPatternParameters() { try { // hide the parts coordinate system axis for selection PartDesign::Body* body = PartDesign::Body::findBodyOf(getObject()); if (body) { App::Origin* origin = body->getOrigin(); auto vpOrigin = static_cast( Gui::Application::Instance->getViewProvider(origin)); vpOrigin->resetTemporaryVisibility(); } } catch (const Base::Exception& ex) { Base::Console().Error("%s\n", ex.what()); } } void TaskLinearPatternParameters::apply() { std::vector directions; App::DocumentObject* obj = nullptr; getDirection(obj, directions); std::string direction = buildLinkSingleSubPythonStr(obj, directions); auto tobj = getObject(); FCMD_OBJ_CMD(tobj, "Direction = " << direction); FCMD_OBJ_CMD(tobj, "Reversed = " << getReverse()); FCMD_OBJ_CMD(tobj, "Mode = " << getMode()); ui->spinLength->apply(); ui->spinOffset->apply(); ui->spinOccurrences->apply(); } //************************************************************************** //************************************************************************** // TaskDialog //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ TaskDlgLinearPatternParameters::TaskDlgLinearPatternParameters( ViewProviderLinearPattern* LinearPatternView) : TaskDlgTransformedParameters(LinearPatternView) { parameter = new TaskLinearPatternParameters(LinearPatternView); Content.push_back(parameter); } #include "moc_TaskLinearPatternParameters.cpp"