Download src/Mod/Material/Gui/BaseDelegate.cpp from AbdulElahGwaith/FreeCAD: direct link, hf CLI and curl.
- Browser
- Download file 16 kB
-
https://huggingface.co/AbdulElahGwaith/FreeCAD/resolve/main/src/Mod/Material/Gui/BaseDelegate.cpp
- Command line
-
hf download hf://AbdulElahGwaith/FreeCAD/src/Mod/Material/Gui/BaseDelegate.cpp
-
curl -L -o BaseDelegate.cpp https://huggingface.co/AbdulElahGwaith/FreeCAD/resolve/main/src/Mod/Material/Gui/BaseDelegate.cpp
16 kB
| // SPDX-License-Identifier: LGPL-2.1-or-later | |
| /*************************************************************************** | |
| * 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/>. * | |
| * * | |
| **************************************************************************/ | |
| using namespace MatGui; | |
| BaseDelegate::BaseDelegate(QObject* parent) | |
| : QStyledItemDelegate(parent) | |
| {} | |
| bool BaseDelegate::newRow(const QAbstractItemModel* model, const QModelIndex& index) const | |
| { | |
| // The model always includes an empty row to allow for additions | |
| return (index.row() == (model->rowCount() - 1)); | |
| } | |
| QString BaseDelegate::getStringValue(const QModelIndex& index) const | |
| { | |
| QVariant item = getValue(index); | |
| auto propertyValue = item.value<QString>(); | |
| return propertyValue; | |
| } | |
| Color BaseDelegate::parseColor(const QString& color) const | |
| { | |
| QString trimmed = color; | |
| trimmed.replace(QRegularExpression(QStringLiteral("\\(([^<]*)\\)")), | |
| QStringLiteral("\\1")); | |
| QStringList parts = trimmed.split(QStringLiteral(",")); | |
| if (parts.length() < 3) { | |
| return Color(); | |
| } | |
| return Color(parts.at(0).toDouble(), parts.at(1).toDouble(), parts.at(2).toDouble(), | |
| parts.length() > 3 ? parts.at(3).toDouble() : 1.0); | |
| } | |
| void BaseDelegate::paintQuantity(QPainter* painter, | |
| const QStyleOptionViewItem& option, | |
| const QModelIndex& index) const | |
| { | |
| auto model = index.model(); | |
| painter->save(); | |
| if (newRow(model, index)) { | |
| painter->drawText(option.rect, 0, QString()); | |
| } | |
| else { | |
| QString text; | |
| QVariant item = getValue(index); | |
| auto quantity = item.value<Base::Quantity>(); | |
| if (quantity.isValid()) { | |
| text = QString::fromStdString(quantity.getUserString()); | |
| } | |
| painter->drawText(option.rect, 0, text); | |
| } | |
| painter->restore(); | |
| } | |
| void BaseDelegate::paintImage(QPainter* painter, | |
| const QStyleOptionViewItem& option, | |
| const QModelIndex& index) const | |
| { | |
| auto propertyValue = getStringValue(index); | |
| painter->save(); | |
| QImage img; | |
| if (!propertyValue.isEmpty()) { | |
| QByteArray by = QByteArray::fromBase64(propertyValue.toUtf8()); | |
| img = QImage::fromData(by).scaled(64, 64, Qt::KeepAspectRatio); | |
| } | |
| QRect target(option.rect); | |
| if (target.width() > target.height()) { | |
| target.setWidth(target.height()); | |
| } | |
| else { | |
| target.setHeight(target.width()); | |
| } | |
| painter->drawImage(target, img, img.rect()); | |
| painter->restore(); | |
| } | |
| void BaseDelegate::paintSVG(QPainter* painter, | |
| const QStyleOptionViewItem& option, | |
| const QModelIndex& index) const | |
| { | |
| auto propertyValue = getStringValue(index); | |
| painter->save(); | |
| if (!propertyValue.isEmpty()) { | |
| QSvgRenderer renderer(propertyValue.toUtf8()); | |
| renderer.render(painter, QRectF(option.rect)); | |
| } | |
| painter->restore(); | |
| } | |
| void BaseDelegate::paintColor(QPainter* painter, | |
| const QStyleOptionViewItem& option, | |
| const QModelIndex& index) const | |
| { | |
| auto propertyValue = getStringValue(index); | |
| painter->save(); | |
| int left = option.rect.left() + 2; | |
| int width = option.rect.width() - 4; | |
| if (option.rect.width() > 75) { | |
| left += (option.rect.width() - 75) / 2; | |
| width = 71; | |
| } | |
| painter->fillRect(left, option.rect.top() + 2, width, option.rect.height() - 4, QBrush(Qt::black)); | |
| left = option.rect.left() + 5; | |
| width = option.rect.width() - 10; | |
| if (option.rect.width() > 75) { | |
| left += (option.rect.width() - 75) / 2; | |
| width = 65; | |
| } | |
| auto color = parseColor(propertyValue).asValue<QColor>(); | |
| painter->fillRect(left, option.rect.top() + 5, width, option.rect.height() - 10, QBrush(color)); | |
| painter->restore(); | |
| } | |
| void BaseDelegate::paintList(QPainter* painter, | |
| const QStyleOptionViewItem& option, | |
| const QModelIndex& index) const | |
| { | |
| Q_UNUSED(index) | |
| painter->save(); | |
| QImage list(QStringLiteral(":/icons/list.svg")); | |
| QRect target(option.rect); | |
| if (target.width() > target.height()) { | |
| target.setWidth(target.height()); | |
| } | |
| else { | |
| target.setHeight(target.width()); | |
| } | |
| painter->drawImage(target, list, list.rect()); | |
| painter->restore(); | |
| } | |
| void BaseDelegate::paintMultiLineString(QPainter* painter, | |
| const QStyleOptionViewItem& option, | |
| const QModelIndex& index) const | |
| { | |
| Q_UNUSED(index) | |
| painter->save(); | |
| QImage table(QStringLiteral(":/icons/multiline.svg")); | |
| QRect target(option.rect); | |
| if (target.width() > target.height()) { | |
| target.setWidth(target.height()); | |
| } | |
| else { | |
| target.setHeight(target.width()); | |
| } | |
| painter->drawImage(target, table, table.rect()); | |
| painter->restore(); | |
| } | |
| void BaseDelegate::paintArray(QPainter* painter, | |
| const QStyleOptionViewItem& option, | |
| const QModelIndex& index) const | |
| { | |
| Q_UNUSED(index) | |
| painter->save(); | |
| QImage table(QStringLiteral(":/icons/table.svg")); | |
| QRect target(option.rect); | |
| if (target.width() > target.height()) { | |
| target.setWidth(target.height()); | |
| } | |
| else { | |
| target.setHeight(target.width()); | |
| } | |
| painter->drawImage(target, table, table.rect()); | |
| painter->restore(); | |
| } | |
| void BaseDelegate::paint(QPainter* painter, | |
| const QStyleOptionViewItem& option, | |
| const QModelIndex& index) const | |
| { | |
| 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); | |
| } | |
| QSize BaseDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const | |
| { | |
| Q_UNUSED(option) | |
| Q_UNUSED(index) | |
| auto type = getType(index); | |
| if (type == Materials::MaterialValue::Color) { | |
| return {75, 23}; // Standard QPushButton size | |
| } | |
| if (type == Materials::MaterialValue::Image || type == Materials::MaterialValue::SVG) { | |
| return {64, 64}; | |
| } | |
| if (type == Materials::MaterialValue::Array2D || type == Materials::MaterialValue::Array3D | |
| || type == Materials::MaterialValue::MultiLineString | |
| || type == Materials::MaterialValue::List || type == Materials::MaterialValue::FileList | |
| || type == Materials::MaterialValue::ImageList) { | |
| return {23, 23}; | |
| } | |
| return QStyledItemDelegate::sizeHint(option, index); | |
| } | |
| void BaseDelegate::setEditorData(QWidget* editor, const QModelIndex& index) const | |
| { | |
| if (!editor) { | |
| return; | |
| } | |
| auto item = getValue(index); | |
| auto type = getType(index); | |
| if (type == Materials::MaterialValue::List) { | |
| auto input = dynamic_cast<Gui::PrefLineEdit*>(editor); | |
| item = input->text(); | |
| return; | |
| } | |
| if (type == Materials::MaterialValue::FileList || type == Materials::MaterialValue::File) { | |
| auto chooser = dynamic_cast<Gui::FileChooser*>(editor); | |
| chooser->setFileName(item.toString()); | |
| return; | |
| } | |
| if (type == Materials::MaterialValue::Quantity) { | |
| auto input = dynamic_cast<Gui::QuantitySpinBox*>(editor); | |
| // input->setQuantityString(item.toString()); | |
| input->setValue(item.value<Base::Quantity>()); | |
| return; | |
| } | |
| if (type == Materials::MaterialValue::List || type == Materials::MaterialValue::ImageList) { | |
| // Handled by dialogs | |
| return; | |
| } | |
| QStyledItemDelegate::setEditorData(editor, index); | |
| } | |
| void BaseDelegate::setModelData(QWidget* editor, | |
| QAbstractItemModel* model, | |
| const QModelIndex& index) const | |
| { | |
| QVariant value; | |
| auto type = getType(index); | |
| if (type == Materials::MaterialValue::FileList || type == Materials::MaterialValue::File) { | |
| auto chooser = dynamic_cast<Gui::FileChooser*>(editor); | |
| value = chooser->fileName(); | |
| } | |
| else if (type == Materials::MaterialValue::Quantity) { | |
| auto input = dynamic_cast<Gui::QuantitySpinBox*>(editor); | |
| // value = input->text(); | |
| // return; | |
| // auto quantity = Base::Quantity::parse(input->text()); | |
| auto quantity = input->value(); | |
| value = QVariant::fromValue(quantity); | |
| } | |
| else if (type == Materials::MaterialValue::Integer) { | |
| auto spinner = dynamic_cast<Gui::IntSpinBox*>(editor); | |
| value = spinner->value(); | |
| } | |
| else if (type == Materials::MaterialValue::Float) { | |
| auto spinner = dynamic_cast<Gui::DoubleSpinBox*>(editor); | |
| value = spinner->value(); | |
| } | |
| else if (type == Materials::MaterialValue::Boolean) { | |
| auto combo = dynamic_cast<Gui::PrefComboBox*>(editor); | |
| value = combo->currentText(); | |
| } | |
| else if (type == Materials::MaterialValue::Image || type == Materials::MaterialValue::SVG) { | |
| // Value was already saved to the property | |
| notifyChanged(index.model(), index); | |
| return; | |
| } | |
| else { | |
| auto lineEdit = dynamic_cast<Gui::PrefLineEdit*>(editor); | |
| value = lineEdit->text(); | |
| } | |
| setValue(model, index, value); | |
| // Q_EMIT model->dataChanged(index, index); | |
| } | |
| QWidget* BaseDelegate::createEditor(QWidget* parent, | |
| const QStyleOptionViewItem& styleOption, | |
| const QModelIndex& index) const | |
| { | |
| Q_UNUSED(styleOption) | |
| auto model = index.model(); | |
| // If this is a new row then it has to be added before the editor is created. Otherwise | |
| // Adding the row while the editor is active can change where the editor is placed. | |
| if (newRow(model, index)) { | |
| const_cast<QAbstractItemModel*>(model)->insertRows(index.row(), 1); | |
| } | |
| auto item = getValue(index); | |
| QWidget* editor = createWidget(parent, item, index); | |
| return editor; | |
| } | |
| QWidget* | |
| BaseDelegate::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::UIntSpinBox(parent); | |
| spinner->setMinimum(0); | |
| spinner->setMaximum(std::numeric_limits<unsigned>::max()); | |
| spinner->setValue(item.toUInt()); | |
| widget = spinner; | |
| } | |
| else if (type == Materials::MaterialValue::Float) { | |
| auto spinner = new Gui::DoubleSpinBox(parent); | |
| // the magnetic permeability is the parameter for which many decimals matter | |
| // the most however, even for this, 6 digits are sufficient | |
| spinner->setDecimals(6); | |
| // for almost all Float parameters of materials a step of 1 would be too large | |
| 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 if (type == Materials::MaterialValue::FileList) { | |
| auto chooser = new Gui::FileChooser(parent); | |
| auto propertyValue = item.toString(); | |
| connect(chooser, | |
| &Gui::FileChooser::fileNameChanged, | |
| [this, chooser, index](const QString&) { | |
| setModelData(chooser, const_cast<QAbstractItemModel*>(index.model()), index); | |
| }); | |
| connect(chooser, | |
| &Gui::FileChooser::fileNameSelected, | |
| [this, chooser, index](const QString&) { | |
| setModelData(chooser, const_cast<QAbstractItemModel*>(index.model()), index); | |
| }); | |
| widget = chooser; | |
| } | |
| else { | |
| // Default editor | |
| auto lineEdit = new Gui::PrefLineEdit(parent); | |
| lineEdit->setText(item.toString()); | |
| widget = lineEdit; | |
| } | |
| return widget; | |
| } | |