Material: Material Preferences

Updates the material preferences including selecting a default material

Preferences adds some options for what gets displayed in the Materials editor.
The option to use the legacy editor is removed in favour of the new
editor.

A new preference page has been added that allows the user to select a
default material. This will then be assigned to any newly created object. In
support of this, a new widget PrefsMaterialTreeWidget has been added as an
extension of the MaterialTreeWidget to automatically save and restore the
selected material.
This commit is contained in:
David Carter
2024-05-12 16:07:30 -04:00
committed by Chris Hennes
parent 6c4f76a8a5
commit 4dcd810ac5
21 changed files with 586 additions and 57 deletions

View File

@@ -31,6 +31,7 @@
#include <Gui/Language/Translator.h>
#include <Gui/WidgetFactory.h>
#include "DlgSettingsDefaultMaterial.h"
#include "DlgSettingsMaterial.h"
#include "Workbench.h"
#include "WorkbenchManipulator.h"
@@ -105,6 +106,8 @@ PyMOD_INIT_FUNC(MatGui)
QObject::tr("Material workbench"));
new Gui::PrefPageProducer<MatGui::DlgSettingsMaterial>(
QT_TRANSLATE_NOOP("QObject", "Material"));
new Gui::PrefPageProducer<MatGui::DlgSettingsDefaultMaterial>(
QT_TRANSLATE_NOOP("QObject", "Material"));
// add resources and reloads the translators
loadMaterialResource();

View File

@@ -49,6 +49,7 @@ set(MatGui_UIC_SRCS
Array3D.ui
DlgDisplayProperties.ui
DlgMaterial.ui
DlgSettingsDefaultMaterial.ui
DlgSettingsMaterial.ui
ImageEdit.ui
ListEdit.ui
@@ -87,6 +88,9 @@ SET(MatGui_SRCS
DlgMaterialImp.cpp
DlgMaterialImp.h
DlgMaterial.ui
DlgSettingsDefaultMaterial.cpp
DlgSettingsDefaultMaterial.h
DlgSettingsDefaultMaterial.ui
DlgSettingsMaterial.cpp
DlgSettingsMaterial.h
DlgSettingsMaterial.ui

View File

@@ -0,0 +1,86 @@
/***************************************************************************
* Copyright (c) 2023 David Carter <dcarter@david.carter.ca> *
* *
* 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 *
* <https://www.gnu.org/licenses/>. *
* *
**************************************************************************/
#include "PreCompiled.h"
#include <Mod/Material/App/ModelUuids.h>
#include "DlgSettingsDefaultMaterial.h"
#include "ui_DlgSettingsDefaultMaterial.h"
using namespace MatGui;
DlgSettingsDefaultMaterial::DlgSettingsDefaultMaterial(QWidget* parent)
: PreferencePage(parent)
, ui(new Ui_DlgSettingsDefaultMaterial)
{
ui->setupUi(this);
ui->widgetMaterial->setParamGrpPath("Mod/Material");
ui->widgetMaterial->setEntryName("DefaultMaterial");
setupFilters();
}
void DlgSettingsDefaultMaterial::setupFilters()
{
// Create a filter to only include current format materials
// that contain at a minimum the Density model
auto filterList = std::make_shared<std::list<std::shared_ptr<Materials::MaterialFilter>>>();
auto filter = std::make_shared<Materials::MaterialFilter>();
filter->setName(tr("Physical"));
filter->addRequiredComplete(Materials::ModelUUIDs::ModelUUID_Mechanical_Density);
filterList->push_back(filter);
ui->widgetMaterial->setIncludeFavorites(false);
ui->widgetMaterial->setIncludeRecent(false);
ui->widgetMaterial->setIncludeEmptyFolders(false);
ui->widgetMaterial->setIncludeLegacy(false);
ui->widgetMaterial->setFilter(filterList);
}
void DlgSettingsDefaultMaterial::saveSettings()
{
ui->widgetMaterial->onSave();
}
void DlgSettingsDefaultMaterial::loadSettings()
{
ui->widgetMaterial->onRestore();
}
/**
* Sets the strings of the subwidgets using the current language.
*/
void DlgSettingsDefaultMaterial::changeEvent(QEvent* e)
{
if (e->type() == QEvent::LanguageChange) {
ui->retranslateUi(this);
}
else {
QWidget::changeEvent(e);
}
}
#include "moc_DlgSettingsDefaultMaterial.cpp"

View File

@@ -0,0 +1,54 @@
/***************************************************************************
* Copyright (c) 2023 David Carter <dcarter@david.carter.ca> *
* *
* 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 *
* <https://www.gnu.org/licenses/>. *
* *
**************************************************************************/
#ifndef MATGUI_DLGSETTINGSDEFAULTMATERIAL_H
#define MATGUI_DLGSETTINGSDEFAULTMATERIAL_H
#include <Gui/PropertyPage.h>
#include <memory>
namespace MatGui
{
class Ui_DlgSettingsDefaultMaterial;
class DlgSettingsDefaultMaterial: public Gui::Dialog::PreferencePage
{
Q_OBJECT
public:
explicit DlgSettingsDefaultMaterial(QWidget* parent = nullptr);
~DlgSettingsDefaultMaterial() override = default;
protected:
void saveSettings() override;
void loadSettings() override;
void changeEvent(QEvent* e) override;
private:
std::unique_ptr<Ui_DlgSettingsDefaultMaterial> ui;
void setupFilters();
};
} // namespace MatGui
#endif // MATGUI_DLGSETTINGSDEFAULTMATERIAL_H

View File

@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MatGui::DlgSettingsDefaultMaterial</class>
<widget class="QWidget" name="MatGui::DlgSettingsDefaultMaterial">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Default Material</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Default Material</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="MatGui::PrefMaterialTreeWidget" name="widgetMaterial" native="true"/>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>MatGui::PrefMaterialTreeWidget</class>
<extends>QWidget</extends>
<header>Mod/Material/Gui/MaterialTreeWidget.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View File

@@ -48,9 +48,14 @@ void DlgSettingsMaterial::saveSettings()
ui->cb_show_empty_libraries->onSave();
ui->cb_show_empty_folders->onSave();
ui->cb_show_legacy->onSave();
ui->cb_show_favorites_editor->onSave();
ui->cb_show_recent_editor->onSave();
ui->cb_show_empty_libraries_editor->onSave();
ui->cb_show_empty_folders_editor->onSave();
ui->cb_show_legacy_editor->onSave();
// Temporary for testing
ui->cb_legacy_editor->onSave();
// ui->cb_legacy_editor->onSave();
}
void DlgSettingsMaterial::loadSettings()
@@ -67,9 +72,14 @@ void DlgSettingsMaterial::loadSettings()
ui->cb_show_empty_libraries->onRestore();
ui->cb_show_empty_folders->onRestore();
ui->cb_show_legacy->onRestore();
ui->cb_show_favorites_editor->onRestore();
ui->cb_show_recent_editor->onRestore();
ui->cb_show_empty_libraries_editor->onRestore();
ui->cb_show_empty_folders_editor->onRestore();
ui->cb_show_legacy_editor->onRestore();
// Temporary for testing
ui->cb_legacy_editor->onRestore();
// ui->cb_legacy_editor->onRestore();
}
/**

View File

@@ -206,31 +206,6 @@ If unchecked, they will be sorted by their name.</string>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="gb_materials_testing">
<property name="title">
<string>Testing</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="Gui::PrefCheckBox" name="cb_legacy_editor">
<property name="text">
<string>Use legacy editor</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="prefEntry" stdset="0">
<cstring>LegacyEditor</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>Mod/Material/Cards</cstring>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="gbMaterialSelector">
<property name="title">
@@ -314,6 +289,92 @@ If unchecked, they will be sorted by their name.</string>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Material Editor</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="Gui::PrefCheckBox" name="cb_show_favorites_editor">
<property name="text">
<string>Show favorites</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="prefEntry" stdset="0">
<cstring>ShowFavorites</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>Mod/Material/Editor</cstring>
</property>
</widget>
</item>
<item>
<widget class="Gui::PrefCheckBox" name="cb_show_recent_editor">
<property name="text">
<string>Show recent</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="prefEntry" stdset="0">
<cstring>ShowRecent</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>Mod/Material/Editor</cstring>
</property>
</widget>
</item>
<item>
<widget class="Gui::PrefCheckBox" name="cb_show_empty_libraries_editor">
<property name="text">
<string>Show empty libraries</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="prefEntry" stdset="0">
<cstring>ShowEmptyLibraries</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>Mod/Material/Editor</cstring>
</property>
</widget>
</item>
<item>
<widget class="Gui::PrefCheckBox" name="cb_show_empty_folders_editor">
<property name="text">
<string>Show empty folders</string>
</property>
<property name="prefEntry" stdset="0">
<cstring>ShowEmptyFolders</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>Mod/Material/Editor</cstring>
</property>
</widget>
</item>
<item>
<widget class="Gui::PrefCheckBox" name="cb_show_legacy_editor">
<property name="text">
<string>Show legacy files</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="prefEntry" stdset="0">
<cstring>ShowLegacy</cstring>
</property>
<property name="prefPath" stdset="0">
<cstring>Mod/Material/Editor</cstring>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">

View File

@@ -709,3 +709,34 @@ void MaterialTreeWidget::saveMaterialTreeChildren(const Base::Reference<Paramete
}
}
}
// --------------------------------------------------------------------
PrefMaterialTreeWidget::PrefMaterialTreeWidget(QWidget* parent)
: MaterialTreeWidget(parent)
, PrefWidget()
{}
PrefMaterialTreeWidget::~PrefMaterialTreeWidget() = default;
void PrefMaterialTreeWidget::restorePreferences()
{
if (getWindowParameter().isNull()) {
failedToRestore(objectName());
return;
}
const char* defaultUuid = "7f9fd73b-50c9-41d8-b7b2-575a030c1eeb";
QString uuid = QString::fromStdString(getWindowParameter()->GetASCII(entryName(), defaultUuid));
setMaterial(uuid);
}
void PrefMaterialTreeWidget::savePreferences()
{
if (getWindowParameter().isNull()) {
failedToSave(objectName());
return;
}
getWindowParameter()->SetASCII(entryName(), getMaterialUUID().toStdString());
}

View File

@@ -37,6 +37,7 @@
#include <FCGlobal.h>
#include <Base/Parameter.h>
#include <Gui/PrefWidgets.h>
#include <Gui/WidgetFactory.h>
@@ -250,6 +251,28 @@ protected:
}
};
/**
* The PrefColorButton class.
*/
class MatGuiExport PrefMaterialTreeWidget: public MaterialTreeWidget, public Gui::PrefWidget
{
Q_OBJECT
Q_PROPERTY(QByteArray prefEntry READ entryName WRITE
setEntryName) // clazy:exclude=qproperty-without-notify
Q_PROPERTY(QByteArray prefPath READ paramGrpPath WRITE
setParamGrpPath) // clazy:exclude=qproperty-without-notify
public:
explicit PrefMaterialTreeWidget(QWidget* parent = nullptr);
~PrefMaterialTreeWidget() override;
protected:
// restore from/save to parameters
void restorePreferences() override;
void savePreferences() override;
};
} // namespace MatGui
#endif // MATGUI_MATERIALTREEWIDGET_H

View File

@@ -831,27 +831,39 @@ void MaterialsEditor::fillMaterialTree()
auto tree = ui->treeMaterials;
auto model = dynamic_cast<QStandardItemModel*>(tree->model());
auto lib = new QStandardItem(tr("Favorites"));
lib->setFlags(Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled);
addExpanded(tree, model, lib, param);
addFavorites(lib);
if (_filterOptions.includeFavorites()) {
auto lib = new QStandardItem(tr("Favorites"));
lib->setFlags(Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled);
addExpanded(tree, model, lib, param);
addFavorites(lib);
}
lib = new QStandardItem(tr("Recent"));
lib->setFlags(Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled);
addExpanded(tree, model, lib, param);
addRecents(lib);
if (_filterOptions.includeRecent()) {
auto lib = new QStandardItem(tr("Recent"));
lib->setFlags(Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled);
addExpanded(tree, model, lib, param);
addRecents(lib);
}
auto libraries = getMaterialManager().getMaterialLibraries();
for (const auto& library : *libraries) {
lib = new QStandardItem(library->getName());
lib->setFlags(Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled);
addExpanded(tree, model, lib, param);
QIcon icon(library->getIconPath());
QIcon folderIcon(QString::fromStdString(":/icons/folder.svg"));
auto modelTree = getMaterialManager().getMaterialTree(library);
addMaterials(*lib, modelTree, folderIcon, icon, param);
bool showLibraries = _filterOptions.includeEmptyLibraries();
if (!_filterOptions.includeEmptyLibraries() && modelTree->size() > 0) {
showLibraries = true;
}
if (showLibraries) {
auto lib = new QStandardItem(library->getName());
lib->setFlags(Qt::ItemIsEnabled | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled);
addExpanded(tree, model, lib, param);
QIcon icon(library->getIconPath());
QIcon folderIcon(QString::fromStdString(":/icons/folder.svg"));
addMaterials(*lib, modelTree, folderIcon, icon, param);
}
}
}

View File

@@ -124,6 +124,7 @@ private:
int _recentMax;
QIcon _warningIcon;
std::shared_ptr<Materials::MaterialFilter> _filter;
Materials::MaterialFilterOptions _filterOptions;
void setup();
@@ -179,6 +180,62 @@ private:
const QIcon& folderIcon,
const QIcon& icon,
const Base::Reference<ParameterGrp>& param);
/* Indicates if we should show favourite materials
*/
bool includeFavorites() const
{
return _filterOptions.includeFavorites();
}
void setIncludeFavorites(bool value)
{
_filterOptions.setIncludeFavorites(value);
}
/* Indicates if we should show recent materials
*/
bool includeRecent() const
{
return _filterOptions.includeRecent();
}
void setIncludeRecent(bool value)
{
_filterOptions.setIncludeRecent(value);
}
/* Indicates if we should include empty folders
*/
bool includeEmptyFolders() const
{
return _filterOptions.includeEmptyFolders();
}
void setIncludeEmptyFolders(bool value)
{
_filterOptions.setIncludeEmptyFolders(value);
}
/* Indicates if we should include empty libraries
*/
bool includeEmptyLibraries() const
{
return _filterOptions.includeEmptyLibraries();
}
void setIncludeEmptyLibraries(bool value)
{
Base::Console().Log("setIncludeEmptyLibraries(%s)\n", (value ? "true" : "false"));
_filterOptions.setIncludeEmptyLibraries(value);
}
/* Indicates if we should include materials in the older format
*/
bool includeLegacy() const
{
return _filterOptions.includeLegacy();
}
void setIncludeLegacy(bool legacy)
{
_filterOptions.setIncludeLegacy(legacy);
}
};
} // namespace MatGui