diff --git a/src/Mod/Material/App/Materials.cpp b/src/Mod/Material/App/Materials.cpp index 5c199240ca..5192328211 100644 --- a/src/Mod/Material/App/Materials.cpp +++ b/src/Mod/Material/App/Materials.cpp @@ -50,14 +50,15 @@ MaterialProperty::MaterialProperty() _valuePtr = std::make_shared(MaterialValue::None); } -MaterialProperty::MaterialProperty(const ModelProperty& other) +MaterialProperty::MaterialProperty(const ModelProperty& other, QString modelUUID) : ModelProperty(other) + , _modelUUID(modelUUID) , _valuePtr(nullptr) { setType(getPropertyType()); auto columns = other.getColumns(); for (auto& it : columns) { - MaterialProperty prop(it); + MaterialProperty prop(it, modelUUID); addColumn(prop); } } @@ -657,7 +658,7 @@ void Material::addPhysical(const QString& uuid) ModelProperty property = static_cast(it.second); try { - _physical[propertyName] = std::make_shared(property); + _physical[propertyName] = std::make_shared(property, uuid); } catch (const UnknownValueType&) { Base::Console().Error("Property '%s' has unknown type '%s'. Ignoring\n", @@ -733,7 +734,7 @@ void Material::addAppearance(const QString& uuid) if (!hasAppearanceProperty(propertyName)) { ModelProperty property = static_cast(it.second); - _appearance[propertyName] = std::make_shared(property); + _appearance[propertyName] = std::make_shared(property, uuid); } } } diff --git a/src/Mod/Material/App/Materials.h b/src/Mod/Material/App/Materials.h index 33de6ae629..1b5630d2b1 100644 --- a/src/Mod/Material/App/Materials.h +++ b/src/Mod/Material/App/Materials.h @@ -52,7 +52,7 @@ class MaterialsExport MaterialProperty: public ModelProperty public: MaterialProperty(); MaterialProperty(const MaterialProperty& other); - explicit MaterialProperty(const ModelProperty& other); + explicit MaterialProperty(const ModelProperty& other, QString modelUUID); explicit MaterialProperty(const std::shared_ptr& other); ~MaterialProperty() override = default; @@ -61,7 +61,11 @@ public: return _valuePtr->getType(); } - const QString getModelUUID() const; + const QString getModelUUID() const + { + return _modelUUID; + } + QVariant getValue(); QVariant getValue() const; QList getList() @@ -347,10 +351,18 @@ public: { return _physical; } + const std::map>& getPhysicalProperties() const + { + return _physical; + } std::map>& getAppearanceProperties() { return _appearance; } + const std::map>& getAppearanceProperties() const + { + return _appearance; + } std::map& getLegacyProperties() { return _legacy; diff --git a/src/Mod/Material/App/Model.h b/src/Mod/Material/App/Model.h index 5fe5888de0..b04f412b86 100644 --- a/src/Mod/Material/App/Model.h +++ b/src/Mod/Material/App/Model.h @@ -201,10 +201,6 @@ public: { return QDir(_directory).absolutePath(); } - // const QString getRelativePath() const - // { - // return QDir(_directory).relativeFilePath(QDir(_directory).absolutePath()); - // } const QString getUUID() const { return _uuid; diff --git a/src/Mod/Material/Gui/CMakeLists.txt b/src/Mod/Material/Gui/CMakeLists.txt index 1c5f5b50d1..cbb949b8a9 100644 --- a/src/Mod/Material/Gui/CMakeLists.txt +++ b/src/Mod/Material/Gui/CMakeLists.txt @@ -48,6 +48,8 @@ set(MatGui_UIC_SRCS Array2D.ui Array3D.ui DlgDisplayProperties.ui + DlgInspectAppearance.ui + DlgInspectMaterial.ui DlgMaterial.ui DlgSettingsDefaultMaterial.ui DlgSettingsMaterial.ui @@ -82,9 +84,12 @@ SET(MatGui_SRCS DlgDisplayPropertiesImp.cpp DlgDisplayPropertiesImp.h DlgDisplayProperties.ui - DlgMaterialImp.cpp - DlgMaterialImp.h - DlgDisplayProperties.ui + DlgInspectAppearance.cpp + DlgInspectAppearance.h + DlgInspectAppearance.ui + DlgInspectMaterial.cpp + DlgInspectMaterial.h + DlgInspectMaterial.ui DlgMaterialImp.cpp DlgMaterialImp.h DlgMaterial.ui diff --git a/src/Mod/Material/Gui/Command.cpp b/src/Mod/Material/Gui/Command.cpp index b6d7fbbc66..d6cee068ef 100644 --- a/src/Mod/Material/Gui/Command.cpp +++ b/src/Mod/Material/Gui/Command.cpp @@ -30,6 +30,8 @@ #include #include "DlgDisplayPropertiesImp.h" +#include "DlgInspectAppearance.h" +#include "DlgInspectMaterial.h" #include "DlgMaterialImp.h" #include "MaterialSave.h" #include "MaterialsEditor.h" @@ -39,7 +41,7 @@ //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //=========================================================================== -// Material_Edit +// Materials_Edit //=========================================================================== DEF_STD_CMD_A(CmdMaterialsEdit) @@ -133,6 +135,60 @@ bool StdCmdSetMaterial::isActive() return (Gui::Control().activeDialog() == nullptr) && (Gui::Selection().size() != 0); } +//=========================================================================== +// Materials_InspectAppearance +//=========================================================================== +DEF_STD_CMD_A(CmdInspectAppearance) + +CmdInspectAppearance::CmdInspectAppearance() + : Command("Materials_InspectAppearance") +{ + sGroup = "Standard-View"; + sMenuText = QT_TR_NOOP("Inspect Appearance..."); + sToolTipText = QT_TR_NOOP("Inspect the appearance properties of the selected object"); + sWhatsThis = "Materials_InspectAppearance"; + sStatusTip = QT_TR_NOOP("Inspect the appearance properties of the selected object"); + // sPixmap = "Materials_Edit"; +} + +void CmdInspectAppearance::activated(int iMsg) +{ + Q_UNUSED(iMsg); + Gui::Control().showDialog(new MatGui::TaskInspectAppearance()); +} + +bool CmdInspectAppearance::isActive() +{ + return (Gui::Control().activeDialog() == nullptr); +} + +//=========================================================================== +// Materials_InspectMaterial +//=========================================================================== +DEF_STD_CMD_A(CmdInspectMaterial) + +CmdInspectMaterial::CmdInspectMaterial() + : Command("Materials_InspectMaterial") +{ + sGroup = "Standard-View"; + sMenuText = QT_TR_NOOP("Inspect Material..."); + sToolTipText = QT_TR_NOOP("Inspect the material properties of the selected object"); + sWhatsThis = "Materials_InspectMaterial"; + sStatusTip = QT_TR_NOOP("Inspect the material properties of the selected object"); + // sPixmap = "Materials_Edit"; +} + +void CmdInspectMaterial::activated(int iMsg) +{ + Q_UNUSED(iMsg); + Gui::Control().showDialog(new MatGui::TaskInspectMaterial()); +} + +bool CmdInspectMaterial::isActive() +{ + return (Gui::Control().activeDialog() == nullptr); +} + //--------------------------------------------------------------- void CreateMaterialCommands() @@ -142,4 +198,6 @@ void CreateMaterialCommands() rcCmdMgr.addCommand(new CmdMaterialsEdit()); rcCmdMgr.addCommand(new StdCmdSetAppearance()); rcCmdMgr.addCommand(new StdCmdSetMaterial()); + rcCmdMgr.addCommand(new CmdInspectAppearance()); + rcCmdMgr.addCommand(new CmdInspectMaterial()); } diff --git a/src/Mod/Material/Gui/DlgInspectAppearance.cpp b/src/Mod/Material/Gui/DlgInspectAppearance.cpp new file mode 100644 index 0000000000..86b586d5e0 --- /dev/null +++ b/src/Mod/Material/Gui/DlgInspectAppearance.cpp @@ -0,0 +1,273 @@ +/*************************************************************************** + * Copyright (c) 2024 David Carter * + * * + * This file is part of FreeCAD. * + * * + * FreeCAD is free software: you can redistribute it and/or modify it * + * under the terms of the GNU Lesser General Public License as * + * published by the Free Software Foundation, either version 2.1 of the * + * License, or (at your option) any later version. * + * * + * FreeCAD 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 * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with FreeCAD. If not, see * + * . * + * * + **************************************************************************/ + +#include "PreCompiled.h" +#ifndef _PreComp_ +#include +#include +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include "DlgInspectAppearance.h" +#include "ui_DlgInspectAppearance.h" + + +using namespace MatGui; + +ColorWidget::ColorWidget(const App::Color& color, QWidget* parent) + : QWidget(parent) +{ + _color = color.asValue(); +} + +void ColorWidget::paintEvent(QPaintEvent* event) +{ + QPainter painter(this); + + // Draw a white background + auto color = QColor(255, 255, 255); + auto left = event->rect().left(); + auto width = event->rect().width(); + painter.fillRect(left, event->rect().top(), width, event->rect().height(), QBrush(color)); + + // Draw a black border + color = QColor(0, 0, 0); + left = event->rect().left() + 2; + width = event->rect().width() - 4; + if (event->rect().width() > 75) { + left += (event->rect().width() - 75) / 2; + width = 71; + } + painter.fillRect(left, event->rect().top() + 2, width, event->rect().height() - 4, QBrush(color)); + + // Draw the color + left = event->rect().left() + 5; + width = event->rect().width() - 10; + if (event->rect().width() > 75) { + left += (event->rect().width() - 75) / 2; + width = 65; + } + painter.fillRect(left, event->rect().top() + 5, width, event->rect().height() - 10, QBrush(_color)); +} + +/* TRANSLATOR MatGui::DlgInspectAppearance */ + +DlgInspectAppearance::DlgInspectAppearance(QWidget* parent) + : QWidget(parent) + , ui(new Ui_DlgInspectAppearance) +{ + ui->setupUi(this); + + std::vector views = getSelection(); + update(views); + + Gui::Selection().Attach(this); +} + +DlgInspectAppearance::~DlgInspectAppearance() +{ + Gui::Selection().Detach(this); +} + +bool DlgInspectAppearance::accept() +{ + return true; +} + +std::vector DlgInspectAppearance::getSelection() const +{ + std::vector views; + + // get a single selection + std::vector sel = + Gui::Selection().getSelection(nullptr, Gui::ResolveMode::OldStyleElement, true); + for (const auto& it : sel) { + Gui::ViewProvider* view = + Gui::Application::Instance->getDocument(it.pDoc)->getViewProvider(it.pObject); + views.push_back(view); + } + + return views; +} + +/// @cond DOXERR +void DlgInspectAppearance::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 views = getSelection(); + update(views); + } +} +/// @endcond + +void DlgInspectAppearance::update(std::vector& views) +{ + App::Document* doc = App::GetApplication().getActiveDocument(); + if (doc) { + ui->editDocument->setText(QString::fromUtf8(doc->Label.getValue())); + + if (views.size() == 1) { + auto view = dynamic_cast(views[0]); + if (!view) { + return; + } + auto* obj = view->getObject(); + if (!obj) { + return; + } + auto* labelProp = dynamic_cast(obj->getPropertyByName("Label")); + if (labelProp) { + ui->editObjectLabel->setText(QString::fromUtf8(labelProp->getValue())); + } + else { + ui->editObjectLabel->setText(QLatin1String("")); + } + ui->editObjectName->setText(QLatin1String(obj->getNameInDocument())); + + auto subElement = Gui::Selection().getSelectionEx(); + if (subElement.size() > 0) { + auto& subObject = subElement[0]; + if (subObject.getSubNames().size() > 0) { + ui->editSubShape->setText(QString::fromStdString(subObject.getSubNames()[0])); + } + else { + ui->editSubShape->setText(QLatin1String("")); + } + } + else { + ui->editSubShape->setText(QLatin1String("")); + } + + auto subShapeType = QString::fromUtf8(obj->getTypeId().getName()); + subShapeType.remove(subShapeType.indexOf(QLatin1String("::")), subShapeType.size()); + ui->editSubShapeType->setText(subShapeType); + ui->editShapeType->setText(QString::fromUtf8(obj->getTypeId().getName())); + + ui->tabAppearance->clear(); + if (labelProp && QString::fromUtf8(labelProp->getValue()).size() > 0) { + auto* prop = + dynamic_cast(view->getPropertyByName("ShapeAppearance")); + if (prop) { + for (int index = 0; index < prop->getSize(); index++) { + auto& material = (prop->getValues())[index]; + auto* tab = makeAppearanceTab(material); + ui->tabAppearance->addTab(tab, QString::number(index)); + + index++; + } + } + } + } + } +} + +QWidget* DlgInspectAppearance::makeAppearanceTab(const App::Material& material) +{ + QWidget* tab = new QWidget(this); + + auto* grid = new QGridLayout(); + tab->setLayout(grid); + + int row = 0; + auto* labelDiffuse = new QLabel(); + labelDiffuse->setText(tr("Diffuse Color")); + auto* colorDiffuse = new ColorWidget(material.diffuseColor); + colorDiffuse->setMaximumHeight(23); + + grid->addWidget(labelDiffuse, row, 0); + grid->addWidget(colorDiffuse, row, 1); + row += 1; + + auto* labelAmbient = new QLabel(); + labelAmbient->setText(tr("Ambient Color")); + auto* colorAmbient = new ColorWidget(material.ambientColor); + colorAmbient->setMaximumHeight(23); + + grid->addWidget(labelAmbient, row, 0); + grid->addWidget(colorAmbient, row, 1); + row += 1; + + auto* labelEmissive = new QLabel(); + labelEmissive->setText(tr("Emissive Color")); + auto* colorEmissive = new ColorWidget(material.emissiveColor); + colorEmissive->setMaximumHeight(23); + + grid->addWidget(labelEmissive, row, 0); + grid->addWidget(colorEmissive, row, 1); + row += 1; + + auto* labelSpecular = new QLabel(); + labelSpecular->setText(tr("Specular Color")); + auto* colorSpecular = new ColorWidget(material.specularColor); + colorSpecular->setMaximumHeight(23); + + grid->addWidget(labelSpecular, row, 0); + grid->addWidget(colorSpecular, row, 1); + row += 1; + + auto* labelShininess = new QLabel(); + labelShininess->setText(tr("Shininess")); + auto* editShininess = new QLineEdit(); + editShininess->setText(QString::number(material.shininess)); + editShininess->setEnabled(false); + + grid->addWidget(labelShininess, row, 0); + grid->addWidget(editShininess, row, 1); + + return tab; +} + + +/* TRANSLATOR MatGui::TaskInspectAppearance */ + +TaskInspectAppearance::TaskInspectAppearance() +{ + widget = new DlgInspectAppearance(); + addTaskBox(Gui::BitmapFactory().pixmap("Part_Loft"), widget); +} + +TaskInspectAppearance::~TaskInspectAppearance() = default; + +void TaskInspectAppearance::open() +{} + +void TaskInspectAppearance::clicked(int) +{} + +bool TaskInspectAppearance::accept() +{ + return widget->accept(); +} + +#include "moc_DlgInspectAppearance.cpp" diff --git a/src/Mod/Material/Gui/DlgInspectAppearance.h b/src/Mod/Material/Gui/DlgInspectAppearance.h new file mode 100644 index 0000000000..fbcdb4855c --- /dev/null +++ b/src/Mod/Material/Gui/DlgInspectAppearance.h @@ -0,0 +1,112 @@ +/*************************************************************************** + * Copyright (c) 2024 David Carter * + * * + * This file is part of FreeCAD. * + * * + * FreeCAD is free software: you can redistribute it and/or modify it * + * under the terms of the GNU Lesser General Public License as * + * published by the Free Software Foundation, either version 2.1 of the * + * License, or (at your option) any later version. * + * * + * FreeCAD 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 * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with FreeCAD. If not, see * + * . * + * * + **************************************************************************/ + +#ifndef MATGUI_DLGINSPECTAPPEARANCE_H +#define MATGUI_DLGINSPECTAPPEARANCE_H + +#include + +#include +#include + +namespace App +{ +class Color; +} + +namespace Gui +{ +class ViewProvider; +} + +namespace MatGui +{ +class Ui_DlgInspectAppearance; + +class ColorWidget : public QWidget +{ + Q_OBJECT + +public: + explicit ColorWidget(const App::Color& color, QWidget* parent = nullptr); + ~ColorWidget() override = default; + + QSize sizeHint() const override { return {75,23}; } + +protected: + void paintEvent(QPaintEvent* event) override; + +private: + QColor _color; +}; + +class DlgInspectAppearance: public QWidget, public Gui::SelectionSingleton::ObserverType +{ + Q_OBJECT + +public: + explicit DlgInspectAppearance(QWidget* parent = nullptr); + ~DlgInspectAppearance() override; + + bool accept(); + // bool reject(); + + /// Observer message from the Selection + void OnChange(Gui::SelectionSingleton::SubjectType& rCaller, + Gui::SelectionSingleton::MessageType Reason) override; + +protected: + +private: + std::unique_ptr ui; + + std::vector getSelection() const; + void update(std::vector& views); + QWidget* makeAppearanceTab(const App::Material& material); +}; + + +class TaskInspectAppearance: public Gui::TaskView::TaskDialog +{ + Q_OBJECT + +public: + TaskInspectAppearance(); + ~TaskInspectAppearance() override; + +public: + void open() override; + bool accept() override; + // bool reject() override; + void clicked(int) override; + + QDialogButtonBox::StandardButtons getStandardButtons() const override + { + return QDialogButtonBox::Ok; + } + +private: + DlgInspectAppearance* widget; +}; + +} // namespace MatGui + +#endif // MATGUI_DLGINSPECTAPPEARANCE_H diff --git a/src/Mod/Material/Gui/DlgInspectAppearance.ui b/src/Mod/Material/Gui/DlgInspectAppearance.ui new file mode 100644 index 0000000000..321dc1a0b4 --- /dev/null +++ b/src/Mod/Material/Gui/DlgInspectAppearance.ui @@ -0,0 +1,122 @@ + + + MatGui::DlgInspectAppearance + + + + 0 + 0 + 400 + 300 + + + + Form + + + + + + true + + + + + 0 + 0 + 380 + 280 + + + + + + + Document + + + + + + + + + + + + + + + Document Name + + + + + + + Name of the active document + + + + + + + Label / Internal Name + + + + + + + + + + Sub.Shape / Type + + + + + + + Shape.TypeID / TypeID + + + + + + + + + + + + + Appearance + + + + + + + Tab 1 + + + + + Tab 2 + + + + + + + + + + + + + + + + diff --git a/src/Mod/Material/Gui/DlgInspectMaterial.cpp b/src/Mod/Material/Gui/DlgInspectMaterial.cpp new file mode 100644 index 0000000000..c25586d2b0 --- /dev/null +++ b/src/Mod/Material/Gui/DlgInspectMaterial.cpp @@ -0,0 +1,425 @@ +/*************************************************************************** + * Copyright (c) 2024 David Carter * + * * + * This file is part of FreeCAD. * + * * + * FreeCAD is free software: you can redistribute it and/or modify it * + * under the terms of the GNU Lesser General Public License as * + * published by the Free Software Foundation, either version 2.1 of the * + * License, or (at your option) any later version. * + * * + * FreeCAD 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 * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with FreeCAD. If not, see * + * . * + * * + **************************************************************************/ + +#include "PreCompiled.h" +#ifndef _PreComp_ +#include +#include +#include +#include +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "DlgInspectMaterial.h" +#include "ui_DlgInspectMaterial.h" + + +using namespace MatGui; + +/* TRANSLATOR MatGui::DlgInspectMaterial */ + +DlgInspectMaterial::DlgInspectMaterial(QWidget* parent) + : QWidget(parent) + , ui(new Ui_DlgInspectMaterial) +{ + ui->setupUi(this); + + auto tree = ui->treeMaterials; + auto model = new QStandardItemModel(); + tree->setModel(model); + + tree->setHeaderHidden(true); + + + std::vector views = getSelection(); + update(views); + + connect(ui->buttonClipboard, &QPushButton::clicked, this, &DlgInspectMaterial::onClipboard); + + Gui::Selection().Attach(this); +} + +DlgInspectMaterial::~DlgInspectMaterial() +{ + Gui::Selection().Detach(this); +} + +bool DlgInspectMaterial::accept() +{ + return true; +} + +void DlgInspectMaterial::onClipboard(bool checked) +{ + Q_UNUSED(checked) + + QApplication::clipboard()->setText(clipboardText); +} + +std::vector DlgInspectMaterial::getSelection() const +{ + std::vector views; + + // get a single selection + std::vector sel = + Gui::Selection().getSelection(nullptr, Gui::ResolveMode::OldStyleElement, true); + for (const auto& it : sel) { + Gui::ViewProvider* view = + Gui::Application::Instance->getDocument(it.pDoc)->getViewProvider(it.pObject); + views.push_back(view); + } + + return views; +} + +/// @cond DOXERR +void DlgInspectMaterial::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 views = getSelection(); + update(views); + } +} +/// @endcond + +void DlgInspectMaterial::appendClip(QString text) +{ + // Need to add indent + QString indent(clipboardIndent * 4, QLatin1Char(' ')); + clipboardText += indent + text + QLatin1String("\n"); +} + +QStandardItem* DlgInspectMaterial::clipItem(QString text) +{ + appendClip(text); + auto item = new QStandardItem(text); + return item; +} + +void DlgInspectMaterial::indent() +{ + clipboardIndent += 1; +} + +void DlgInspectMaterial::unindent() +{ + if (clipboardIndent > 0) { + clipboardIndent -= 1; + } +} + +void DlgInspectMaterial::update(std::vector& views) +{ + clipboardText = QLatin1String(""); + clipboardIndent = 0; + App::Document* doc = App::GetApplication().getActiveDocument(); + if (doc) { + appendClip(tr("Document: ") + QString::fromUtf8(doc->Label.getValue())); + ui->editDocument->setText(QString::fromUtf8(doc->Label.getValue())); + + if (views.size() == 1) { + auto view = dynamic_cast(views[0]); + if (!view) { + return; + } + auto* obj = view->getObject(); + if (!obj) { + return; + } + auto* labelProp = dynamic_cast(obj->getPropertyByName("Label")); + if (labelProp) { + ui->editObjectLabel->setText(QString::fromUtf8(labelProp->getValue())); + appendClip(tr("Label: ") + QString::fromUtf8(labelProp->getValue())); + } + else { + ui->editObjectLabel->setText(QLatin1String("")); + } + ui->editObjectName->setText(QLatin1String(obj->getNameInDocument())); + appendClip(tr("Internal Name: ") + QString::fromUtf8(obj->getNameInDocument())); + + auto subElement = Gui::Selection().getSelectionEx(); + if (subElement.size() > 0) { + auto& subObject = subElement[0]; + if (subObject.getSubNames().size() > 0) { + ui->editSubShape->setText(QString::fromStdString(subObject.getSubNames()[0])); + } + else { + ui->editSubShape->setText(QLatin1String("")); + } + } + else { + ui->editSubShape->setText(QLatin1String("")); + } + + auto subShapeType = QString::fromUtf8(obj->getTypeId().getName()); + subShapeType.remove(subShapeType.indexOf(QLatin1String("::")), subShapeType.size()); + appendClip(tr("Type: ") + subShapeType); + ui->editSubShapeType->setText(subShapeType); + appendClip(tr("TypeID: ") + QString::fromUtf8(obj->getTypeId().getName())); + ui->editShapeType->setText(QString::fromUtf8(obj->getTypeId().getName())); + + if (labelProp && QString::fromUtf8(labelProp->getValue()).size() > 0) { + auto* prop = dynamic_cast( + obj->getPropertyByName("ShapeMaterial")); + if (prop) { + updateMaterialTree(prop->getValue()); + } + } + } + } +} + +void DlgInspectMaterial::updateMaterialTree(const Materials::Material& material) +{ + Base::Console().Log("Material '%s'\n", material.getName().toStdString().c_str()); + + auto tree = ui->treeMaterials; + auto model = dynamic_cast(tree->model()); + model->clear(); + + addMaterial(tree, model, material); +} + +void DlgInspectMaterial::addMaterial(QTreeView* tree, + QStandardItemModel* parent, + const Materials::Material& material) +{ + auto card = clipItem(tr("Name: ") + material.getName()); + addExpanded(tree, parent, card); + + indent(); + addMaterialDetails(tree, card, material); + unindent(); +} + +void DlgInspectMaterial::addMaterial(QTreeView* tree, + QStandardItem* parent, + const Materials::Material& material) +{ + auto card = clipItem(tr("Name: ") + material.getName()); + addExpanded(tree, parent, card); + + indent(); + addMaterialDetails(tree, card, material); + unindent(); +} + +void DlgInspectMaterial::addModels(QTreeView* tree, + QStandardItem* parent, + const QSet* models) +{ + if (models->isEmpty()) { + auto none = clipItem(tr("None")); + addExpanded(tree, parent, none); + } + else { + for (const QString& uuid : *models) { + auto model = modelManager.getModel(uuid); + auto name = clipItem(tr("Name: ") + model->getName()); + addExpanded(tree, parent, name); + + indent(); + addModelDetails(tree, name, model); + unindent(); + } + } +} + +void DlgInspectMaterial::addModelDetails(QTreeView* tree, + QStandardItem* parent, + std::shared_ptr& model) +{ + auto uuid = clipItem(tr("UUID: ") + model->getUUID()); + addExpanded(tree, parent, uuid); + + auto library = clipItem(tr("Library: ") + model->getLibrary()->getName()); + addExpanded(tree, parent, library); + + auto libraryPath = + clipItem(tr("Library Directory: ") + model->getLibrary()->getDirectoryPath()); + addExpanded(tree, parent, libraryPath); + + auto directory = clipItem(tr("Sub Directory: ") + model->getDirectory()); + addExpanded(tree, parent, directory); + + auto inherits = clipItem(tr("Inherits:")); + addExpanded(tree, parent, inherits); + + auto& inheritedUuids = model->getInheritance(); + indent(); + if (inheritedUuids.isEmpty()) { + auto none = clipItem(tr("None")); + addExpanded(tree, inherits, none); + } + else { + for (const QString& inherited : inheritedUuids) { + auto inheritedModel = modelManager.getModel(inherited); + + auto name = clipItem(tr("Name: ") + inheritedModel->getName()); + addExpanded(tree, inherits, name); + + indent(); + addModelDetails(tree, name, inheritedModel); + unindent(); + } + } + unindent(); +} + +void DlgInspectMaterial::addProperties( + QTreeView* tree, + QStandardItem* parent, + const std::map>& properties) +{ + if (properties.empty()) { + auto none = clipItem(tr("None")); + addExpanded(tree, parent, none); + } + else { + for (auto& property : properties) { + auto name = clipItem(tr("Name: ") + property.second->getName()); + addExpanded(tree, parent, name); + + indent(); + addPropertyDetails(tree, name, property.second); + unindent(); + } + } +} + +void DlgInspectMaterial::addPropertyDetails( + QTreeView* tree, + QStandardItem* parent, + const std::shared_ptr& property) +{ + auto uuid = clipItem(tr("Model UUID: ") + property->getModelUUID()); + addExpanded(tree, parent, uuid); + auto type = clipItem(tr("Type: ") + property->getPropertyType()); + addExpanded(tree, parent, type); + auto hasValue = clipItem(tr("Has value: ") + (property->isNull() ? tr("No") : tr("Yes"))); + addExpanded(tree, parent, hasValue); +} + +void DlgInspectMaterial::addMaterialDetails(QTreeView* tree, + QStandardItem* parent, + const Materials::Material& material) +{ + auto uuid = clipItem(tr("UUID: ") + material.getUUID()); + addExpanded(tree, parent, uuid); + auto library = clipItem(tr("Library: ") + material.getLibrary()->getName()); + addExpanded(tree, parent, library); + auto libraryPath = + clipItem(tr("Library Directory: ") + material.getLibrary()->getDirectoryPath()); + addExpanded(tree, parent, libraryPath); + auto directory = clipItem(tr("Sub Directory: ") + material.getDirectory()); + addExpanded(tree, parent, directory); + auto inherits = clipItem(tr("Inherits:")); + addExpanded(tree, parent, inherits); + + indent(); + auto parentUUID = material.getParentUUID(); + if (!parentUUID.isEmpty()) { + auto parentMaterial = materialManager.getMaterial(material.getParentUUID()); + addMaterial(tree, inherits, *parentMaterial); + } + else { + auto none = clipItem(tr("None")); + addExpanded(tree, inherits, none); + } + unindent(); + + auto appearance = clipItem(tr("Appearance Models:")); + addExpanded(tree, parent, appearance); + indent(); + addModels(tree, appearance, material.getAppearanceModels()); + unindent(); + + auto physical = clipItem(tr("Physical Models:")); + addExpanded(tree, parent, physical); + indent(); + addModels(tree, physical, material.getPhysicalModels()); + unindent(); + + auto appearanceProperties = clipItem(tr("Appearance Properties:")); + addExpanded(tree, parent, appearanceProperties); + indent(); + addProperties(tree, appearanceProperties, material.getAppearanceProperties()); + unindent(); + + auto physicalProperties = clipItem(tr("Physical Properties:")); + addExpanded(tree, parent, physicalProperties); + indent(); + addProperties(tree, physicalProperties, material.getPhysicalProperties()); + unindent(); +} + +void DlgInspectMaterial::addExpanded(QTreeView* tree, + QStandardItemModel* parent, + QStandardItem* child) +{ + parent->appendRow(child); + tree->setExpanded(child->index(), true); +} + +void DlgInspectMaterial::addExpanded(QTreeView* tree, QStandardItem* parent, QStandardItem* child) +{ + parent->appendRow(child); + tree->setExpanded(child->index(), true); +} + +/* TRANSLATOR MatGui::TaskInspectMaterial */ + +TaskInspectMaterial::TaskInspectMaterial() +{ + widget = new DlgInspectMaterial(); + addTaskBox(Gui::BitmapFactory().pixmap("Part_Loft"), widget); +} + +TaskInspectMaterial::~TaskInspectMaterial() = default; + +void TaskInspectMaterial::open() +{} + +void TaskInspectMaterial::clicked(int) +{} + +bool TaskInspectMaterial::accept() +{ + return widget->accept(); +} + +#include "moc_DlgInspectMaterial.cpp" diff --git a/src/Mod/Material/Gui/DlgInspectMaterial.h b/src/Mod/Material/Gui/DlgInspectMaterial.h new file mode 100644 index 0000000000..710212a2a4 --- /dev/null +++ b/src/Mod/Material/Gui/DlgInspectMaterial.h @@ -0,0 +1,123 @@ +/*************************************************************************** + * Copyright (c) 2024 David Carter * + * * + * This file is part of FreeCAD. * + * * + * FreeCAD is free software: you can redistribute it and/or modify it * + * under the terms of the GNU Lesser General Public License as * + * published by the Free Software Foundation, either version 2.1 of the * + * License, or (at your option) any later version. * + * * + * FreeCAD 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 * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with FreeCAD. If not, see * + * . * + * * + **************************************************************************/ + +#ifndef MATGUI_DLGINSPECTMATERIAL_H +#define MATGUI_DLGINSPECTMATERIAL_H + +#include + +#include +#include +#include + +#include +#include + +#include +#include + +namespace Gui +{ +class ViewProvider; +} + +namespace MatGui +{ +class Ui_DlgInspectMaterial; + +class DlgInspectMaterial: public QWidget, public Gui::SelectionSingleton::ObserverType +{ + Q_OBJECT + +public: + explicit DlgInspectMaterial(QWidget* parent = nullptr); + ~DlgInspectMaterial() override; + + bool accept(); + void onClipboard(bool checked); + + /// Observer message from the Selection + void OnChange(Gui::SelectionSingleton::SubjectType& rCaller, + Gui::SelectionSingleton::MessageType Reason) override; + +private: + std::unique_ptr ui; + Materials::MaterialManager materialManager; + Materials::ModelManager modelManager; + QString clipboardText; + int clipboardIndent; + + void appendClip(QString text); + QStandardItem* clipItem(QString text); + void indent(); + void unindent(); + + std::vector getSelection() const; + void update(std::vector& views); + void updateMaterialTree(const Materials::Material& material); + void + addMaterial(QTreeView* tree, QStandardItemModel* parent, const Materials::Material& material); + void addMaterial(QTreeView* tree, QStandardItem* parent, const Materials::Material& material); + void + addMaterialDetails(QTreeView* tree, QStandardItem* parent, const Materials::Material& material); + void addModels(QTreeView* tree, QStandardItem* parent, const QSet* models); + void addModelDetails(QTreeView* tree, + QStandardItem* parent, + std::shared_ptr& model); + void addProperties( + QTreeView* tree, + QStandardItem* parent, + const std::map>& properties); + void addPropertyDetails(QTreeView* tree, + QStandardItem* parent, + const std::shared_ptr& property); + + void addExpanded(QTreeView* tree, QStandardItemModel* parent, QStandardItem* child); + void addExpanded(QTreeView* tree, QStandardItem* parent, QStandardItem* child); +}; + + +class TaskInspectMaterial: public Gui::TaskView::TaskDialog +{ + Q_OBJECT + +public: + TaskInspectMaterial(); + ~TaskInspectMaterial() override; + +public: + void open() override; + bool accept() override; + // bool reject() override; + void clicked(int) override; + + QDialogButtonBox::StandardButtons getStandardButtons() const override + { + return QDialogButtonBox::Ok; + } + +private: + DlgInspectMaterial* widget; +}; + +} // namespace MatGui + +#endif // MATGUI_DLGINSPECTMATERIAL_H diff --git a/src/Mod/Material/Gui/DlgInspectMaterial.ui b/src/Mod/Material/Gui/DlgInspectMaterial.ui new file mode 100644 index 0000000000..dec62fce7c --- /dev/null +++ b/src/Mod/Material/Gui/DlgInspectMaterial.ui @@ -0,0 +1,145 @@ + + + MatGui::DlgInspectMaterial + + + + 0 + 0 + 400 + 432 + + + + Form + + + + + + true + + + + + 0 + 0 + 376 + 408 + + + + + + + Document + + + + + + + + + + + + + + + Document Name + + + + + + + Name of the active document + + + + + + + Label / Internal Name + + + + + + + + + + Sub.Shape / Type + + + + + + + Shape.TypeID / TypeID + + + + + + + + + + + + + Material + + + + + + Qt::ScrollBarAsNeeded + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + Copy to clipboard + + + + + + + + + + + + + + + + + diff --git a/src/Mod/Material/Gui/Workbench.cpp b/src/Mod/Material/Gui/Workbench.cpp index 65ee6aa6b8..b988ef4791 100644 --- a/src/Mod/Material/Gui/Workbench.cpp +++ b/src/Mod/Material/Gui/Workbench.cpp @@ -47,10 +47,10 @@ Gui::MenuItem* Workbench::setupMenuBar() const Gui::MenuItem* root = StdWorkbench::setupMenuBar(); Gui::MenuItem* item = root->findItem("&Windows"); - Gui::MenuItem* part = new Gui::MenuItem; - root->insertItem(item, part); - part->setCommand("&Materials"); - *part << "Materials_Edit"; + Gui::MenuItem* material = new Gui::MenuItem; + root->insertItem(item, material); + material->setCommand("&Materials"); + *material << "Materials_Edit"; return root; } @@ -59,9 +59,9 @@ Gui::ToolBarItem* Workbench::setupToolBars() const { Gui::ToolBarItem* root = StdWorkbench::setupToolBars(); - Gui::ToolBarItem* solids = new Gui::ToolBarItem(root); - solids->setCommand("Materials"); - *solids << "Materials_Edit"; + Gui::ToolBarItem* material = new Gui::ToolBarItem(root); + material->setCommand("Materials"); + *material << "Materials_Edit"; return root; } diff --git a/src/Mod/Part/Gui/Workbench.cpp b/src/Mod/Part/Gui/Workbench.cpp index e2a1b4453f..98e36e5ede 100644 --- a/src/Mod/Part/Gui/Workbench.cpp +++ b/src/Mod/Part/Gui/Workbench.cpp @@ -117,6 +117,8 @@ Gui::MenuItem* Workbench::setupMenuBar() const << copy << "Part_CheckGeometry" << "Part_Defeaturing" + << "Materials_InspectAppearance" + << "Materials_InspectMaterial" << "Separator" << bop << join << split << compound << "Separator" diff --git a/src/Mod/PartDesign/Gui/Workbench.cpp b/src/Mod/PartDesign/Gui/Workbench.cpp index 8d7ab5d3c1..e49c6275ed 100644 --- a/src/Mod/PartDesign/Gui/Workbench.cpp +++ b/src/Mod/PartDesign/Gui/Workbench.cpp @@ -564,6 +564,9 @@ Gui::MenuItem* Workbench::setupMenuBar() const << "Separator" << dressups << "Separator" + << "Materials_InspectAppearance" + << "Materials_InspectMaterial" + << "Separator" << "PartDesign_Boolean" << "Separator" << "Part_CheckGeometry" diff --git a/tests/src/Mod/Material/App/TestMaterialProperties.cpp b/tests/src/Mod/Material/App/TestMaterialProperties.cpp index 455424c399..447adb1c8d 100644 --- a/tests/src/Mod/Material/App/TestMaterialProperties.cpp +++ b/tests/src/Mod/Material/App/TestMaterialProperties.cpp @@ -130,8 +130,9 @@ TEST_F(TestMaterialProperties, TestEmpty) TEST_F(TestMaterialProperties, TestSingle) { - Materials::MaterialProperty prop(modelProp1); + Materials::MaterialProperty prop(modelProp1, QLatin1String("sampleUUID")); EXPECT_EQ(prop.getType(), Materials::MaterialValue::Quantity); + EXPECT_EQ(prop.getModelUUID(), QLatin1String("sampleUUID")); EXPECT_TRUE(prop.isNull()); auto variant = prop.getValue(); EXPECT_TRUE(variant.canConvert()); @@ -145,6 +146,7 @@ TEST_F(TestMaterialProperties, TestSingle) void check2DArray(Materials::MaterialProperty& prop) { EXPECT_EQ(prop.getType(), Materials::MaterialValue::Array2D); + EXPECT_EQ(prop.getModelUUID(), QLatin1String("sampleUUID")); EXPECT_TRUE(prop.isNull()); auto array = std::static_pointer_cast(prop.getMaterialValue()); EXPECT_EQ(array->rows(), 0); @@ -160,20 +162,20 @@ void check2DArray(Materials::MaterialProperty& prop) TEST_F(TestMaterialProperties, Test2DArray) { - Materials::MaterialProperty prop(modelProp); + Materials::MaterialProperty prop(modelProp, QLatin1String("sampleUUID")); check2DArray(prop); } TEST_F(TestMaterialProperties, Test2DArrayCopy) { - Materials::MaterialProperty propBase(modelProp); + Materials::MaterialProperty propBase(modelProp, QLatin1String("sampleUUID")); Materials::MaterialProperty prop(propBase); check2DArray(prop); } TEST_F(TestMaterialProperties, Test2DArrayAssignment) { - Materials::MaterialProperty propBase(modelProp); + Materials::MaterialProperty propBase(modelProp, QLatin1String("sampleUUID")); Materials::MaterialProperty prop; prop = propBase; @@ -183,6 +185,7 @@ TEST_F(TestMaterialProperties, Test2DArrayAssignment) void check3DArray(Materials::MaterialProperty& prop) { EXPECT_EQ(prop.getType(), Materials::MaterialValue::Array3D); + EXPECT_EQ(prop.getModelUUID(), QLatin1String("sampleUUID")); EXPECT_TRUE(prop.isNull()); auto array = std::static_pointer_cast(prop.getMaterialValue()); EXPECT_EQ(array->depth(), 0); @@ -198,20 +201,20 @@ void check3DArray(Materials::MaterialProperty& prop) TEST_F(TestMaterialProperties, Test3DArray) { - Materials::MaterialProperty prop(model3DProp); + Materials::MaterialProperty prop(model3DProp, QLatin1String("sampleUUID")); check3DArray(prop); } TEST_F(TestMaterialProperties, Test3DArrayCopy) { - Materials::MaterialProperty propBase(model3DProp); + Materials::MaterialProperty propBase(model3DProp, QLatin1String("sampleUUID")); Materials::MaterialProperty prop(propBase); check3DArray(prop); } TEST_F(TestMaterialProperties, Test3DArrayAssignment) { - Materials::MaterialProperty propBase(model3DProp); + Materials::MaterialProperty propBase(model3DProp, QLatin1String("sampleUUID")); Materials::MaterialProperty prop; prop = propBase;