| | |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | #include <QColorDialog> |
| | #include <QDesktopServices> |
| | #include <QIODevice> |
| | #include <QItemSelectionModel> |
| | #include <QMessageBox> |
| | #include <QPainter> |
| | #include <QString> |
| | #include <QStringList> |
| | #include <QSvgRenderer> |
| | #include <QTextStream> |
| | #include <QVariant> |
| | #include <limits> |
| |
|
| |
|
| | #include <App/Application.h> |
| | #include <Base/Interpreter.h> |
| | #include <Base/Quantity.h> |
| | #include <Gui/Application.h> |
| | #include <Gui/Command.h> |
| | #include <Gui/InputField.h> |
| | #include <Gui/PrefWidgets.h> |
| | #include <Gui/SpinBox.h> |
| | #include <Gui/WaitCursor.h> |
| |
|
| | #include <Mod/Material/App/Exceptions.h> |
| | #include <Mod/Material/App/ModelManager.h> |
| |
|
| | #include "Array2D.h" |
| | #include "Array3D.h" |
| | #include "ImageEdit.h" |
| | #include "ListEdit.h" |
| | #include "MaterialDelegate.h" |
| | #include "MaterialSave.h" |
| | #include "TextEdit.h" |
| |
|
| |
|
| | using namespace MatGui; |
| |
|
| | MaterialDelegate::MaterialDelegate(QObject* parent) |
| | : BaseDelegate(parent) |
| | {} |
| |
|
| | bool MaterialDelegate::newRow(const QAbstractItemModel* model, const QModelIndex& index) const |
| | { |
| | Q_UNUSED(model) |
| | Q_UNUSED(index) |
| |
|
| | |
| | return false; |
| | } |
| |
|
| | Materials::MaterialValue::ValueType MaterialDelegate::getType(const QModelIndex& index) const |
| | { |
| | auto treeModel = dynamic_cast<const QStandardItemModel*>(index.model()); |
| | auto item = treeModel->itemFromIndex(index); |
| | auto group = item->parent(); |
| | if (!group) { |
| | return {}; |
| | } |
| |
|
| | int row = index.row(); |
| | QString propertyType; |
| | if (group->child(row, 1)) { |
| | propertyType = group->child(row, 2)->text(); |
| | } |
| |
|
| | return Materials::MaterialValue::mapType(propertyType); |
| | } |
| |
|
| | QString MaterialDelegate::getUnits(const QModelIndex& index) const |
| | { |
| | auto treeModel = dynamic_cast<const QStandardItemModel*>(index.model()); |
| | auto item = treeModel->itemFromIndex(index); |
| | auto group = item->parent(); |
| | if (!group) { |
| | return {}; |
| | } |
| |
|
| | int row = index.row(); |
| | QString propertyUnits; |
| | if (group->child(row, 1)) { |
| | propertyUnits = group->child(row, 3)->text(); |
| | } |
| | return propertyUnits; |
| | } |
| |
|
| | QVariant MaterialDelegate::getValue(const QModelIndex& index) const |
| | { |
| | auto treeModel = dynamic_cast<const QStandardItemModel*>(index.model()); |
| | auto item = treeModel->itemFromIndex(index); |
| | auto group = item->parent(); |
| | if (!group) { |
| | return {}; |
| | } |
| |
|
| | int row = index.row(); |
| | QVariant propertyValue; |
| | if (group->child(row, 1)) { |
| | auto material = group->child(row, 1)->data().value<std::shared_ptr<Materials::Material>>(); |
| | |
| | auto propertyName = group->child(row, 0)->data().toString(); |
| | propertyValue = material->getProperty(propertyName)->getValue(); |
| | } |
| | return propertyValue; |
| | } |
| |
|
| | void MaterialDelegate::setValue(QAbstractItemModel* model, |
| | const QModelIndex& index, |
| | const QVariant& value) const |
| | { |
| | auto matModel = dynamic_cast<const QStandardItemModel*>(model); |
| | auto item = matModel->itemFromIndex(index); |
| | auto group = item->parent(); |
| | if (!group) { |
| | return; |
| | } |
| |
|
| | int row = index.row(); |
| | if (group->child(row, 1)) { |
| | auto material = group->child(row, 1)->data().value<std::shared_ptr<Materials::Material>>(); |
| | auto propertyName = group->child(row, 0)->data().toString(); |
| | std::string _name = propertyName.toStdString(); |
| | auto property = material->getProperty(propertyName); |
| |
|
| | try { |
| | property->setValue(value); |
| | } |
| | catch (const Base::ValueError&) { |
| | |
| | auto quantity = value.value<Base::Quantity>(); |
| | Base::Console().log("Units mismatch '%s' = '%s', " |
| | "setting to default property units '%s'\n", |
| | propertyName.toStdString().c_str(), |
| | quantity.getUserString().c_str(), |
| | property->getUnits().toStdString().c_str()); |
| |
|
| | QMessageBox msgBox; |
| | msgBox.setWindowTitle(QStringLiteral("Property Units Mismatch")); |
| | msgBox.setText(QStringLiteral("Units mismatch '%1' = '%2', " |
| | "setting to default property units '%3'\n") |
| | .arg(propertyName) |
| | .arg(QString::fromStdString(quantity.getUserString())) |
| | .arg(property->getUnits())); |
| | msgBox.exec(); |
| |
|
| | property->setQuantity( |
| | Base::Quantity(quantity.getValue(), property->getUnits().toStdString())); |
| | } |
| |
|
| | group->child(row, 1)->setText(property->getString()); |
| | } |
| |
|
| | notifyChanged(model, index); |
| | } |
| |
|
| | void MaterialDelegate::notifyChanged(const QAbstractItemModel* model, |
| | const QModelIndex& index) const |
| | { |
| | auto treeModel = dynamic_cast<const QStandardItemModel*>(model); |
| | auto item = treeModel->itemFromIndex(index); |
| | auto group = item->parent(); |
| | if (!group) { |
| | return; |
| | } |
| |
|
| | int row = index.row(); |
| | if (group->child(row, 1)) { |
| | auto material = group->child(row, 1)->data().value<std::shared_ptr<Materials::Material>>(); |
| | |
| | auto propertyName = group->child(row, 0)->data().toString(); |
| | auto propertyValue = material->getProperty(propertyName)->getValue(); |
| | material->setEditStateAlter(); |
| |
|
| | Q_EMIT const_cast<MaterialDelegate*>(this)->propertyChange(propertyName, propertyValue); |
| | } |
| | } |
| |
|
| | bool MaterialDelegate::editorEvent(QEvent* event, |
| | QAbstractItemModel* model, |
| | const QStyleOptionViewItem& option, |
| | const QModelIndex& index) |
| | { |
| | if (index.column() == 1) { |
| | if (event->type() == QEvent::MouseButtonDblClick) { |
| | auto treeModel = dynamic_cast<const QStandardItemModel*>(index.model()); |
| |
|
| | |
| | |
| | auto item = treeModel->itemFromIndex(index); |
| | auto group = item->parent(); |
| | if (!group) { |
| | return QStyledItemDelegate::editorEvent(event, model, option, index); |
| | } |
| |
|
| | int row = index.row(); |
| |
|
| | |
| | QString propertyName = group->child(row, 0)->data().toString(); |
| |
|
| | auto type = getType(index); |
| | if (type == Materials::MaterialValue::Color) { |
| | showColorModal(propertyName, item); |
| | |
| | return true; |
| | } |
| | if (type == Materials::MaterialValue::MultiLineString) { |
| | showMultiLineStringModal(propertyName, item); |
| | |
| | return true; |
| | } |
| | if (type == Materials::MaterialValue::List || type == Materials::MaterialValue::FileList |
| | || type == Materials::MaterialValue::ImageList) { |
| | showListModal(propertyName, item); |
| | |
| | return true; |
| | } |
| | if (type == Materials::MaterialValue::Array2D) { |
| | showArray2DModal(propertyName, item); |
| | |
| | return true; |
| | } |
| | if (type == Materials::MaterialValue::Array3D) { |
| | showArray3DModal(propertyName, item); |
| | |
| | return true; |
| | } |
| | if (type == Materials::MaterialValue::Image || type == Materials::MaterialValue::SVG) { |
| | showImageModal(propertyName, item); |
| | |
| | return true; |
| | } |
| | } |
| | } |
| | return QStyledItemDelegate::editorEvent(event, model, option, index); |
| | } |
| |
|
| | void MaterialDelegate::showColorModal(const QString& propertyName, QStandardItem* item) |
| | { |
| | auto currentColor = parseColor(item->text()).asValue<QColor>(); |
| | auto dlg = new QColorDialog(currentColor); |
| |
|
| | dlg->setAttribute(Qt::WA_DeleteOnClose); |
| | if (Gui::DialogOptions::dontUseNativeColorDialog()) { |
| | dlg->setOptions(QColorDialog::DontUseNativeDialog); |
| | } |
| | dlg->setOption(QColorDialog::ColorDialogOption::ShowAlphaChannel, false); |
| |
|
| | dlg->setCurrentColor(currentColor); |
| | dlg->adjustSize(); |
| |
|
| | connect(dlg, &QColorDialog::finished, this, [&](int result) { |
| | if (result == QDialog::Accepted) { |
| | QColor color = dlg->selectedColor(); |
| | if (color.isValid()) { |
| | QString colorText = QString(QStringLiteral("(%1,%2,%3,%4)")) |
| | .arg(color.red() / 255.0) |
| | .arg(color.green() / 255.0) |
| | .arg(color.blue() / 255.0) |
| | .arg(color.alpha() / 255.0); |
| | item->setText(colorText); |
| | Q_EMIT const_cast<MaterialDelegate*>(this)->propertyChange(propertyName, |
| | item->text()); |
| | } |
| | } |
| | }); |
| |
|
| | dlg->exec(); |
| | } |
| |
|
| | void MaterialDelegate::showImageModal(const QString& propertyName, QStandardItem* item) |
| | { |
| | auto material = item->data().value<std::shared_ptr<Materials::Material>>(); |
| | auto dlg = new ImageEdit(propertyName, material); |
| |
|
| | dlg->setAttribute(Qt::WA_DeleteOnClose); |
| |
|
| | dlg->adjustSize(); |
| |
|
| | |
| |
|
| | dlg->exec(); |
| | } |
| |
|
| | void MaterialDelegate::showListModal(const QString& propertyName, QStandardItem* item) |
| | { |
| | auto material = item->data().value<std::shared_ptr<Materials::Material>>(); |
| | auto dlg = new ListEdit(propertyName, material); |
| |
|
| | dlg->setAttribute(Qt::WA_DeleteOnClose); |
| |
|
| | dlg->adjustSize(); |
| |
|
| | |
| |
|
| | dlg->exec(); |
| | } |
| |
|
| | void MaterialDelegate::showMultiLineStringModal(const QString& propertyName, QStandardItem* item) |
| | { |
| | auto material = item->data().value<std::shared_ptr<Materials::Material>>(); |
| | auto dlg = new TextEdit(propertyName, material); |
| |
|
| | dlg->setAttribute(Qt::WA_DeleteOnClose); |
| |
|
| | dlg->adjustSize(); |
| |
|
| | |
| |
|
| | dlg->exec(); |
| | } |
| |
|
| |
|
| | void MaterialDelegate::showArray2DModal(const QString& propertyName, QStandardItem* item) |
| | { |
| | auto material = item->data().value<std::shared_ptr<Materials::Material>>(); |
| | auto dlg = new Array2D(propertyName, material); |
| |
|
| | dlg->setAttribute(Qt::WA_DeleteOnClose); |
| |
|
| | dlg->adjustSize(); |
| |
|
| | |
| |
|
| | dlg->exec(); |
| | } |
| |
|
| | void MaterialDelegate::showArray3DModal(const QString& propertyName, QStandardItem* item) |
| | { |
| | auto material = item->data().value<std::shared_ptr<Materials::Material>>(); |
| | auto dlg = new Array3D(propertyName, material); |
| |
|
| | dlg->setAttribute(Qt::WA_DeleteOnClose); |
| |
|
| | dlg->adjustSize(); |
| |
|
| | |
| |
|
| | dlg->exec(); |
| | } |
| |
|
| | void MaterialDelegate::paint(QPainter* painter, |
| | const QStyleOptionViewItem& option, |
| | const QModelIndex& index) const |
| | { |
| | if (index.column() != 1) { |
| | QStyledItemDelegate::paint(painter, option, index); |
| | return; |
| | } |
| |
|
| | auto treeModel = dynamic_cast<const QStandardItemModel*>(index.model()); |
| |
|
| | |
| | auto item = treeModel->itemFromIndex(index); |
| | auto group = item->parent(); |
| | if (!group) { |
| | QStyledItemDelegate::paint(painter, option, index); |
| | return; |
| | } |
| |
|
| | auto type = getType(index); |
| | if (type == Materials::MaterialValue::Quantity) { |
| | paintQuantity(painter, option, index); |
| | return; |
| | } |
| | if (type == Materials::MaterialValue::Image) { |
| | paintImage(painter, option, index); |
| | return; |
| | } |
| | if (type == Materials::MaterialValue::SVG) { |
| | paintSVG(painter, option, index); |
| | return; |
| | } |
| | if (type == Materials::MaterialValue::Color) { |
| | paintColor(painter, option, index); |
| | return; |
| | } |
| | if (type == Materials::MaterialValue::List || type == Materials::MaterialValue::FileList |
| | || type == Materials::MaterialValue::ImageList) { |
| | paintList(painter, option, index); |
| | return; |
| | } |
| | if (type == Materials::MaterialValue::MultiLineString) { |
| | paintMultiLineString(painter, option, index); |
| | return; |
| | } |
| | if (type == Materials::MaterialValue::Array2D || type == Materials::MaterialValue::Array3D) { |
| | paintArray(painter, option, index); |
| | return; |
| | } |
| |
|
| | QStyledItemDelegate::paint(painter, option, index); |
| | } |
| |
|
| | QWidget* MaterialDelegate::createEditor(QWidget* parent, |
| | const QStyleOptionViewItem& styleOption, |
| | const QModelIndex& index) const |
| | { |
| | Q_UNUSED(styleOption) |
| |
|
| | if (index.column() != 1) { |
| | return nullptr; |
| | } |
| |
|
| | auto treeModel = dynamic_cast<const QStandardItemModel*>(index.model()); |
| |
|
| | |
| | auto item = treeModel->itemFromIndex(index); |
| | auto group = item->parent(); |
| | if (!group) { |
| | return nullptr; |
| | } |
| |
|
| | QVariant value = treeModel->data(index); |
| | QWidget* editor = createWidget(parent, value, index); |
| |
|
| | return editor; |
| | } |
| |
|
| | QWidget* MaterialDelegate::createWidget(QWidget* parent, |
| | const QVariant& item, |
| | const QModelIndex& index) const |
| | { |
| | QWidget* widget = nullptr; |
| |
|
| | auto type = getType(index); |
| | if (type == Materials::MaterialValue::Integer) { |
| | auto spinner = new Gui::IntSpinBox(parent); |
| | spinner->setMinimum(0); |
| | spinner->setMaximum(std::numeric_limits<int>::max()); |
| | spinner->setValue(item.toInt()); |
| | widget = spinner; |
| | } |
| | else if (type == Materials::MaterialValue::Float) { |
| | auto spinner = new Gui::DoubleSpinBox(parent); |
| |
|
| | |
| | |
| | spinner->setDecimals(6); |
| |
|
| | |
| | spinner->setSingleStep(0.1); |
| |
|
| | spinner->setMinimum(std::numeric_limits<double>::min()); |
| | spinner->setMaximum(std::numeric_limits<double>::max()); |
| | spinner->setValue(item.toDouble()); |
| | widget = spinner; |
| | } |
| | else if (type == Materials::MaterialValue::Boolean) { |
| | auto combo = new Gui::PrefComboBox(parent); |
| | combo->insertItem(0, QStringLiteral("")); |
| | combo->insertItem(1, tr("False")); |
| | combo->insertItem(2, tr("True")); |
| | combo->setCurrentText(item.toString()); |
| | widget = combo; |
| | } |
| | else if (type == Materials::MaterialValue::Quantity) { |
| | |
| | auto input = new Gui::QuantitySpinBox(parent); |
| | input->setMinimum(std::numeric_limits<double>::min()); |
| | input->setMaximum(std::numeric_limits<double>::max()); |
| | input->setUnitText(getUnits(index)); |
| | |
| | input->setValue(item.value<Base::Quantity>()); |
| |
|
| | widget = input; |
| | } |
| | else if (type == Materials::MaterialValue::File) { |
| | auto chooser = new Gui::FileChooser(parent); |
| | if (!item.toString().isEmpty()) { |
| | chooser->setFileName(item.toString()); |
| | } |
| |
|
| | widget = chooser; |
| | } |
| | else { |
| | |
| | auto lineEdit = new Gui::PrefLineEdit(parent); |
| | lineEdit->setText(item.toString()); |
| | widget = lineEdit; |
| | } |
| |
|
| | return widget; |
| | } |
| |
|
| | #include "moc_MaterialDelegate.cpp" |
| |
|