// SPDX-License-Identifier: LGPL-2.1-or-later /*************************************************************************** * Copyright (c) 2002 Jürgen Riegel * * * * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "DlgMaterialImp.h" #include "ui_DlgMaterial.h" using namespace MatGui; using namespace std; namespace sp = std::placeholders; /* TRANSLATOR Gui::Dialog::DlgMaterialImp */ #if 0 // needed for Qt's lupdate utility qApp->translate("QDockWidget", "Material"); #endif class DlgMaterialImp::Private { using DlgMaterialImp_Connection = fastsignals::connection; public: Ui::DlgMaterial ui; bool floating; DlgMaterialImp_Connection connectChangedObject; }; /** * Constructs a DlgMaterialImp which is a child of 'parent', with the * name 'name' and widget flags set to 'f' * * The dialog will by default be modeless, unless you set 'modal' to * true to construct a modal dialog. */ DlgMaterialImp::DlgMaterialImp(bool floating, QWidget* parent, Qt::WindowFlags fl) : QDialog(parent, fl) , d(new Private) { d->ui.setupUi(this); setupConnections(); d->floating = floating; // Create a filter to only include current format materials // that contain physical properties. Materials::MaterialFilter filter; filter.requirePhysical(true); d->ui.widgetMaterial->setFilter(filter); std::vector objects = getSelectionObjects(); setMaterial(objects); // embed this dialog into a dockable widget container if (floating) { Gui::DockWindowManager* pDockMgr = Gui::DockWindowManager::instance(); QDockWidget* dw = pDockMgr->addDockWindow("Display Properties", this, Qt::AllDockWidgetAreas); dw->setFeatures(QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable); dw->setFloating(true); dw->show(); } Gui::Selection().Attach(this); // NOLINTBEGIN d->connectChangedObject = Gui::Application::Instance->signalChangedObject.connect( std::bind(&DlgMaterialImp::slotChangedObject, this, sp::_1, sp::_2)); // NOLINTEND } /** * Destroys the object and frees any allocated resources */ DlgMaterialImp::~DlgMaterialImp() { // no need to delete child widgets, Qt does it all for us d->connectChangedObject.disconnect(); Gui::Selection().Detach(this); } void DlgMaterialImp::setupConnections() { connect(d->ui.widgetMaterial, &MaterialTreeWidget::materialSelected, this, &DlgMaterialImp::onMaterialSelected); } void DlgMaterialImp::changeEvent(QEvent* e) { if (e->type() == QEvent::LanguageChange) { d->ui.retranslateUi(this); } QDialog::changeEvent(e); } /// @cond DOXERR void DlgMaterialImp::OnChange(Gui::SelectionSingleton::SubjectType& rCaller, Gui::SelectionSingleton::MessageType Reason) { Q_UNUSED(rCaller); if (Reason.Type == Gui::SelectionChanges::AddSelection || Reason.Type == Gui::SelectionChanges::RmvSelection || Reason.Type == Gui::SelectionChanges::SetSelection || Reason.Type == Gui::SelectionChanges::ClrSelection) { std::vector objects = getSelectionObjects(); setMaterial(objects); } } /// @endcond void DlgMaterialImp::slotChangedObject(const Gui::ViewProvider& obj, const App::Property& prop) { // This method gets called if a property of any view provider is changed. // We pick out all the properties for which we need to update this dialog. std::vector Provider = getSelection(); auto vp = std::find_if(Provider.begin(), Provider.end(), [&obj](Gui::ViewProvider* v) { return v == &obj; }); if (vp != Provider.end()) { const char* name = obj.getPropertyName(&prop); // this is not a property of the view provider but of the document object if (!name) { return; } std::string prop_name = name; if (prop.isDerivedFrom()) { //auto& value = static_cast(prop).getValue(); if (prop_name == "ShapeMaterial") { // bool blocked = d->ui.buttonColor->blockSignals(true); // auto color = value.diffuseColor; // d->ui.buttonColor->setColor(QColor((int)(255.0f * color.r), // (int)(255.0f * color.g), // (int)(255.0f * color.b))); // d->ui.buttonColor->blockSignals(blocked); } } } } /** * Destroys the dock window this object is embedded into without destroying itself. */ void DlgMaterialImp::reject() { if (d->floating) { // closes the dock window Gui::DockWindowManager* pDockMgr = Gui::DockWindowManager::instance(); pDockMgr->removeDockWindow(this); } QDialog::reject(); } void DlgMaterialImp::setMaterial(const std::vector& objects) { for (auto it : objects) { if (auto prop = dynamic_cast(it->getPropertyByName("ShapeMaterial"))) { try { const auto& material = prop->getValue(); d->ui.widgetMaterial->setMaterial(material.getUUID()); return; } catch (const Materials::MaterialNotFound&) { } } } d->ui.widgetMaterial->setMaterial(Materials::MaterialManager::defaultMaterialUUID()); } std::vector DlgMaterialImp::getSelection() const { std::vector views; // get the complete selection std::vector sel = Gui::Selection().getCompleteSelection(); for (const auto& it : sel) { Gui::ViewProvider* view = Gui::Application::Instance->getDocument(it.pDoc)->getViewProvider(it.pObject); views.push_back(view); } return views; } std::vector DlgMaterialImp::getSelectionObjects() const { std::vector objects; // get the complete selection std::vector sel = Gui::Selection().getCompleteSelection(); for (const auto& it : sel) { objects.push_back(it.pObject); } return objects; } void DlgMaterialImp::onMaterialSelected(const std::shared_ptr& material) { std::vector objects = getSelectionObjects(); for (auto it : objects) { if (auto prop = dynamic_cast(it->getPropertyByName("ShapeMaterial"))) { prop->setValue(*material); } } } // ---------------------------------------------------------------------------- /* TRANSLATOR Gui::Dialog::TaskMaterial */ TaskMaterial::TaskMaterial() { this->setButtonPosition(TaskMaterial::North); widget = new DlgMaterialImp(false); taskbox = new Gui::TaskView::TaskBox(QPixmap(), widget->windowTitle(), true, nullptr); taskbox->groupLayout()->addWidget(widget); Content.push_back(taskbox); } TaskMaterial::~TaskMaterial() = default; QDialogButtonBox::StandardButtons TaskMaterial::getStandardButtons() const { return QDialogButtonBox::Close; } bool TaskMaterial::reject() { widget->reject(); return (widget->result() == QDialog::Rejected); } #include "moc_DlgMaterialImp.cpp"