/*************************************************************************** * Copyright (c) 2004 Werner Mayer * * * * 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 "PreCompiled.h" #ifndef _PreComp_ # include # include # include # include # include # include # include # include # include # include # include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "PropertyItem.h" #include using namespace Gui::PropertyEditor; Gui::PropertyEditor::PropertyItemFactory* Gui::PropertyEditor::PropertyItemFactory::_singleton = NULL; PropertyItemFactory& PropertyItemFactory::instance() { if (_singleton == NULL) _singleton = new PropertyItemFactory; return *_singleton; } void PropertyItemFactory::destruct () { delete _singleton; _singleton = 0; } PropertyItem* PropertyItemFactory::createPropertyItem (const char* sName) const { PropertyItem* w = static_cast(Produce(sName)); return w; } // ---------------------------------------------------- PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyItem) PropertyItem::PropertyItem() : parentItem(0), readonly(false), cleared(false) { precision = Base::UnitsApi::getDecimals(); setAutoApply(true); } PropertyItem::~PropertyItem() { qDeleteAll(childItems); } void PropertyItem::initialize() { } void PropertyItem::reset() { qDeleteAll(childItems); childItems.clear(); } void PropertyItem::setPropertyData(const std::vector& items) { //if we have a single property we can bind it for expression handling if (items.size() == 1) { const App::Property& p = *items.front(); try { // Check for 'DocumentObject' as parent because otherwise 'ObjectIdentifier' raises an exception App::DocumentObject * docObj = Base::freecad_dynamic_cast(p.getContainer()); if (docObj && !docObj->isReadOnly(&p)) { App::ObjectIdentifier id(p); std::vector paths; p.getPaths(paths); //there may be no paths available in this property (for example an empty constraint list) if (id.getProperty() && !paths.empty()) bind(id); } } //it may happen that setting properties is not possible catch (...) { } } propertyItems = items; updateData(); this->initialize(); } void PropertyItem::updateData() { bool ro = true; for (std::vector::const_iterator it = propertyItems.begin(); it != propertyItems.end(); ++it) { App::PropertyContainer* parent = (*it)->getContainer(); if (parent) ro &= (parent->isReadOnly(*it) || (*it)->testStatus(App::Property::ReadOnly)); } this->setReadOnly(ro); } const std::vector& PropertyItem::getPropertyData() const { return propertyItems; } bool PropertyItem::hasProperty(const App::Property* prop) const { std::vector::const_iterator it = std::find(propertyItems.begin(), propertyItems.end(), prop); if (it != propertyItems.end()) return true; else return false; } void PropertyItem::assignProperty(const App::Property*) { } bool PropertyItem::removeProperty(const App::Property* prop) { std::vector::iterator it = std::find(propertyItems.begin(), propertyItems.end(), prop); if (it != propertyItems.end()) { propertyItems.erase(it); } return propertyItems.empty(); } App::Property* PropertyItem::getFirstProperty() { if (propertyItems.empty()) return 0; return propertyItems.front(); } const App::Property* PropertyItem::getFirstProperty() const { if (propertyItems.empty()) return 0; return propertyItems.front(); } void PropertyItem::setParent(PropertyItem* parent) { parentItem = parent; } PropertyItem *PropertyItem::parent() const { return parentItem; } void PropertyItem::appendChild(PropertyItem *item) { childItems.append(item); } void PropertyItem::insertChild(int index, PropertyItem *child) { childItems.insert(index, child); } /*! * \brief PropertyItem::removeChildren * Deletes the children in the range of [from, to] */ void PropertyItem::removeChildren(int from, int to) { int count = to-from+1; for (int i=0; isetParent(nullptr); return child; } PropertyItem *PropertyItem::child(int row) { return childItems.value(row); } int PropertyItem::childCount() const { return childItems.count(); } int PropertyItem::columnCount() const { return 2; } void PropertyItem::setReadOnly(bool ro) { readonly = ro; for (QList::iterator it = childItems.begin(); it != childItems.end(); ++it) (*it)->setReadOnly(ro); } bool PropertyItem::isReadOnly() const { return readonly; } bool PropertyItem::testStatus(App::Property::Status pos) const { std::vector::const_iterator it; for (it = propertyItems.begin(); it != propertyItems.end(); ++it) { if ((*it)->testStatus(pos)) return true; } return false; } void PropertyItem::setDecimals(int prec) { precision = prec; } int PropertyItem::decimals() const { return precision; } QVariant PropertyItem::displayName() const { return QVariant(displayText); } QVariant PropertyItem::toolTip(const App::Property* prop) const { QString str = QApplication::translate("App::Property", prop->getDocumentation()); return QVariant(str); } QVariant PropertyItem::decoration(const QVariant&) const { return QVariant(); } QVariant PropertyItem::toString(const QVariant& prop) const { return prop; } QVariant PropertyItem::value(const App::Property* /*prop*/) const { return QVariant(); } void PropertyItem::setValue(const QVariant& /*value*/) { } QString PropertyItem::pythonIdentifier(const App::Property* prop) const { App::PropertyContainer* parent = prop->getContainer(); if (parent->getTypeId() == App::Document::getClassTypeId()) { App::Document* doc = static_cast(parent); QString docName = QString::fromLatin1(App::GetApplication().getDocumentName(doc)); QString propName = QString::fromLatin1(parent->getPropertyName(prop)); return QString::fromLatin1("FreeCAD.getDocument(\"%1\").%2").arg(docName).arg(propName); } if (parent->getTypeId().isDerivedFrom(App::DocumentObject::getClassTypeId())) { App::DocumentObject* obj = static_cast(parent); App::Document* doc = obj->getDocument(); QString docName = QString::fromLatin1(App::GetApplication().getDocumentName(doc)); QString objName = QString::fromLatin1(obj->getNameInDocument()); QString propName = QString::fromLatin1(parent->getPropertyName(prop)); return QString::fromLatin1("FreeCAD.getDocument(\"%1\").getObject(\"%2\").%3") .arg(docName).arg(objName).arg(propName); } auto* vp = dynamic_cast(parent); if (vp) { App::DocumentObject* obj = vp->getObject(); App::Document* doc = obj->getDocument(); QString docName = QString::fromLatin1(App::GetApplication().getDocumentName(doc)); QString objName = QString::fromLatin1(obj->getNameInDocument()); QString propName = QString::fromLatin1(parent->getPropertyName(prop)); return QString::fromLatin1("FreeCADGui.getDocument(\"%1\").getObject(\"%2\").%3") .arg(docName).arg(objName).arg(propName); } return QString(); } QWidget* PropertyItem::createEditor(QWidget* /*parent*/, const QObject* /*receiver*/, const char* /*method*/) const { return 0; } void PropertyItem::setEditorData(QWidget * /*editor*/, const QVariant& /*data*/) const { } QVariant PropertyItem::editorData(QWidget * /*editor*/) const { return QVariant(); } QString PropertyItem::propertyName() const { if (propName.isEmpty()) return QLatin1String(QT_TRANSLATE_NOOP("App::Property", "")); return propName; } void PropertyItem::setPropertyName(const QString& name) { setObjectName(name); QString display; bool upper = false; for (int i=0; i::const_iterator it = propertyItems.begin(); it != propertyItems.end(); ++it) { App::PropertyContainer* parent = (*it)->getContainer(); if (parent && !parent->isReadOnly(*it) && !(*it)->testStatus(App::Property::ReadOnly)) { QString cmd = QString::fromLatin1("%1 = %2").arg(pythonIdentifier(*it)).arg(value); try { Gui::Command::runCommand(Gui::Command::App, cmd.toUtf8()); } catch (Base::PyException &e) { e.ReportException(); Base::Console().Error("Stack Trace: %s\n",e.getStackTrace().c_str()); } catch (Base::Exception &e) { e.ReportException(); } catch (...) { Base::Console().Error("Unknown C++ exception in PropertyItem::setPropertyValue thrown\n"); } } } } QVariant PropertyItem::data(int column, int role) const { // property name if (column == 0) { if (role == Qt::DisplayRole) return displayName(); // no properties set if (propertyItems.empty()) return QVariant(); else if (role == Qt::ToolTipRole) return toolTip(propertyItems[0]); else return QVariant(); } else { // no properties set if (propertyItems.empty()) { PropertyItem* parent = this->parent(); if (!parent || !parent->parent()) return QVariant(); if (role == Qt::EditRole) { return parent->property(qPrintable(objectName())); } else if (role == Qt::DecorationRole) { QVariant val = parent->property(qPrintable(objectName())); return decoration(val); } else if (role == Qt::DisplayRole) { QVariant val = parent->property(qPrintable(objectName())); return toString(val); } else return QVariant(); } if (role == Qt::EditRole) return value(propertyItems[0]); else if (role == Qt::DecorationRole) return decoration(value(propertyItems[0])); else if (role == Qt::DisplayRole) return toString(value(propertyItems[0])); else if (role == Qt::ToolTipRole) return toolTip(propertyItems[0]); else return QVariant(); } } bool PropertyItem::setData (const QVariant& value) { cleared = false; // This is the basic mechanism to set the value to // a property and if no property is set for this item // it delegates it to its parent which sets then the // property or delegates again to its parent... if (propertyItems.empty()) { PropertyItem* parent = this->parent(); if (!parent || !parent->parent()) return false; parent->setProperty(qPrintable(objectName()),value); return true; } else { setValue(value); return true; } } Qt::ItemFlags PropertyItem::flags(int column) const { Qt::ItemFlags basicFlags = Qt::ItemIsEnabled | Qt::ItemIsSelectable; if (column == 1 && !isReadOnly()) return basicFlags | Qt::ItemIsEditable; else return basicFlags; } int PropertyItem::row() const { if (parentItem) return parentItem->childItems.indexOf(const_cast(this)); return 0; } void PropertyItem::bind(const App::ObjectIdentifier& _path) { Gui::ExpressionBinding::bind(_path); propertyBound(); } void PropertyItem::bind(const App::Property& prop) { Gui::ExpressionBinding::bind(prop); propertyBound(); } QString PropertyItem::expressionAsString() const { if (hasExpression()) { try { std::unique_ptr result(getExpression()->eval()); return QString::fromStdString(result->toString()); } catch (const Base::Exception& e) { e.ReportException(); } } return QString(); } // -------------------------------------------------------------------- PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyStringItem) PropertyStringItem::PropertyStringItem() { } QVariant PropertyStringItem::value(const App::Property* prop) const { assert(prop && prop->getTypeId().isDerivedFrom(App::PropertyString::getClassTypeId())); std::string value = static_cast(prop)->getValue(); return QVariant(QString::fromUtf8(value.c_str())); } void PropertyStringItem::setValue(const QVariant& value) { if (!value.canConvert(QVariant::String)) return; QString val = value.toString(); val = QString::fromUtf8(Base::Interpreter().strToPython(val.toUtf8()).c_str()); QString data = QString::fromLatin1("\"%1\"").arg(val); setPropertyValue(data); } QWidget* PropertyStringItem::createEditor(QWidget* parent, const QObject* receiver, const char* method) const { QLineEdit *le = new QLineEdit(parent); le->setFrame(false); le->setReadOnly(isReadOnly()); QObject::connect(le, SIGNAL(textChanged(const QString&)), receiver, method); return le; } void PropertyStringItem::setEditorData(QWidget *editor, const QVariant& data) const { QLineEdit *le = qobject_cast(editor); le->setText(data.toString()); } QVariant PropertyStringItem::editorData(QWidget *editor) const { QLineEdit *le = qobject_cast(editor); return QVariant(le->text()); } // -------------------------------------------------------------------- PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyFontItem) PropertyFontItem::PropertyFontItem() { } QVariant PropertyFontItem::value(const App::Property* prop) const { assert(prop && prop->getTypeId().isDerivedFrom(App::PropertyFont::getClassTypeId())); std::string value = static_cast(prop)->getValue(); return QVariant(QString::fromUtf8(value.c_str())); } void PropertyFontItem::setValue(const QVariant& value) { if (!value.canConvert(QVariant::String)) return; QString val = value.toString(); QString data = QString::fromLatin1("\"%1\"").arg(val); setPropertyValue(data); } QWidget* PropertyFontItem::createEditor(QWidget* parent, const QObject* receiver, const char* method) const { QComboBox *cb = new QComboBox(parent); cb->setFrame(false); cb->setDisabled(isReadOnly()); QObject::connect(cb, SIGNAL(activated(const QString&)), receiver, method); return cb; } void PropertyFontItem::setEditorData(QWidget *editor, const QVariant& data) const { QComboBox *cb = qobject_cast(editor); QFontDatabase fdb; QStringList familyNames = fdb.families(QFontDatabase::Any); cb->addItems(familyNames); int index = familyNames.indexOf(data.toString()); cb->setCurrentIndex(index); } QVariant PropertyFontItem::editorData(QWidget *editor) const { QComboBox *cb = qobject_cast(editor); return QVariant(cb->currentText()); } // -------------------------------------------------------------------- PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertySeparatorItem) QWidget* PropertySeparatorItem::createEditor(QWidget* parent, const QObject* receiver, const char* method) const { Q_UNUSED(parent); Q_UNUSED(receiver); Q_UNUSED(method); return 0; } // -------------------------------------------------------------------- PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyIntegerItem) PropertyIntegerItem::PropertyIntegerItem() { } QVariant PropertyIntegerItem::value(const App::Property* prop) const { assert(prop && prop->getTypeId().isDerivedFrom(App::PropertyInteger::getClassTypeId())); int value = (int)static_cast(prop)->getValue(); return QVariant(value); } void PropertyIntegerItem::setValue(const QVariant& value) { //if the item has an expression it issues the python code if (!hasExpression()) { if (!value.canConvert(QVariant::Int)) return; int val = value.toInt(); QString data = QString::fromLatin1("%1").arg(val); setPropertyValue(data); } } QWidget* PropertyIntegerItem::createEditor(QWidget* parent, const QObject* receiver, const char* method) const { Gui::IntSpinBox *sb = new Gui::IntSpinBox(parent); sb->setFrame(false); sb->setReadOnly(isReadOnly()); QObject::connect(sb, SIGNAL(valueChanged(int)), receiver, method); if (isBound()) { sb->bind(getPath()); sb->setAutoApply(autoApply()); } return sb; } void PropertyIntegerItem::setEditorData(QWidget *editor, const QVariant& data) const { QSpinBox *sb = qobject_cast(editor); sb->setRange(INT_MIN, INT_MAX); sb->setValue(data.toInt()); } QVariant PropertyIntegerItem::editorData(QWidget *editor) const { QSpinBox *sb = qobject_cast(editor); return QVariant(sb->value()); } QVariant PropertyIntegerItem::toString(const QVariant& v) const { QString string(PropertyItem::toString(v).toString()); if (hasExpression()) string += QString::fromLatin1(" ( %1 )").arg(QString::fromStdString(getExpressionString())); return QVariant(string); } // -------------------------------------------------------------------- PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyIntegerConstraintItem) PropertyIntegerConstraintItem::PropertyIntegerConstraintItem() { } QVariant PropertyIntegerConstraintItem::value(const App::Property* prop) const { assert(prop && prop->getTypeId().isDerivedFrom(App::PropertyIntegerConstraint::getClassTypeId())); int value = (int)static_cast(prop)->getValue(); return QVariant(value); } void PropertyIntegerConstraintItem::setValue(const QVariant& value) { //if the item has an expression it issues the python code if (!hasExpression()) { if (!value.canConvert(QVariant::Int)) return; int val = value.toInt(); QString data = QString::fromLatin1("%1").arg(val); setPropertyValue(data); } } QWidget* PropertyIntegerConstraintItem::createEditor(QWidget* parent, const QObject* receiver, const char* method) const { Gui::IntSpinBox *sb = new Gui::IntSpinBox(parent); sb->setFrame(false); sb->setReadOnly(isReadOnly()); QObject::connect(sb, SIGNAL(valueChanged(int)), receiver, method); if (isBound()) { sb->bind(getPath()); sb->setAutoApply(autoApply()); } return sb; } void PropertyIntegerConstraintItem::setEditorData(QWidget *editor, const QVariant& data) const { const App::PropertyIntegerConstraint* prop = static_cast (getFirstProperty()); const App::PropertyIntegerConstraint::Constraints* c = 0; if (prop) { c = prop->getConstraints(); } QSpinBox *sb = qobject_cast(editor); if (c) { sb->setMinimum(c->LowerBound); sb->setMaximum(c->UpperBound); sb->setSingleStep(c->StepSize); } else { sb->setMinimum(INT_MIN); sb->setMaximum(INT_MAX); } sb->setValue(data.toInt()); } QVariant PropertyIntegerConstraintItem::editorData(QWidget *editor) const { QSpinBox *sb = qobject_cast(editor); return QVariant(sb->value()); } QVariant PropertyIntegerConstraintItem::toString(const QVariant& v) const { QString string(PropertyItem::toString(v).toString()); if (hasExpression()) string += QString::fromLatin1(" ( %1 )").arg(QString::fromStdString(getExpressionString())); return QVariant(string); } // -------------------------------------------------------------------- PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyFloatItem) PropertyFloatItem::PropertyFloatItem() { } QVariant PropertyFloatItem::toString(const QVariant& prop) const { double value = prop.toDouble(); QString data = QLocale::system().toString(value, 'f', decimals()); if (hasExpression()) data += QString::fromLatin1(" ( %1 )").arg(QString::fromStdString(getExpressionString())); return QVariant(data); } QVariant PropertyFloatItem::value(const App::Property* prop) const { assert(prop && prop->getTypeId().isDerivedFrom(App::PropertyFloat::getClassTypeId())); double value = static_cast(prop)->getValue(); return QVariant(value); } void PropertyFloatItem::setValue(const QVariant& value) { //if the item has an expression it issues the python code if (!hasExpression()) { if (!value.canConvert(QVariant::Double)) return; double val = value.toDouble(); QString data = QString::fromLatin1("%1").arg(val,0,'f',decimals()); setPropertyValue(data); } } QWidget* PropertyFloatItem::createEditor(QWidget* parent, const QObject* receiver, const char* method) const { Gui::DoubleSpinBox *sb = new Gui::DoubleSpinBox(parent); sb->setFrame(false); sb->setDecimals(decimals()); sb->setReadOnly(isReadOnly()); QObject::connect(sb, SIGNAL(valueChanged(double)), receiver, method); if (isBound()) { sb->bind(getPath()); sb->setAutoApply(autoApply()); } return sb; } void PropertyFloatItem::setEditorData(QWidget *editor, const QVariant& data) const { QDoubleSpinBox *sb = qobject_cast(editor); sb->setRange((double)INT_MIN, (double)INT_MAX); sb->setValue(data.toDouble()); } QVariant PropertyFloatItem::editorData(QWidget *editor) const { QDoubleSpinBox *sb = qobject_cast(editor); return QVariant(sb->value()); } // -------------------------------------------------------------------- PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyUnitItem) PropertyUnitItem::PropertyUnitItem() { } QVariant PropertyUnitItem::toString(const QVariant& prop) const { const Base::Quantity& unit = prop.value(); QString string = unit.getUserString(); if (hasExpression()) string += QString::fromLatin1(" ( %1 )").arg(QString::fromStdString(getExpressionString())); return QVariant(string); } QVariant PropertyUnitItem::value(const App::Property* prop) const { assert(prop && prop->getTypeId().isDerivedFrom(App::PropertyQuantity::getClassTypeId())); Base::Quantity value = static_cast(prop)->getQuantityValue(); return QVariant::fromValue(value); } void PropertyUnitItem::setValue(const QVariant& value) { //if the item has an expression it handles the python code if (!hasExpression()) { if (!value.canConvert()) return; const Base::Quantity& val = value.value(); QString unit = QString::fromLatin1("'%1 %2'").arg(val.getValue()).arg(val.getUnit().getString()); setPropertyValue(unit); } } QWidget* PropertyUnitItem::createEditor(QWidget* parent, const QObject* receiver, const char* method) const { Gui::QuantitySpinBox *infield = new Gui::QuantitySpinBox(parent); infield->setFrame(false); infield->setMinimumHeight(0); infield->setReadOnly(isReadOnly()); //if we are bound to an expression we need to bind it to the input field if (isBound()) { infield->bind(getPath()); infield->setAutoApply(autoApply()); } QObject::connect(infield, SIGNAL(valueChanged(double)), receiver, method); return infield; } void PropertyUnitItem::setEditorData(QWidget *editor, const QVariant& data) const { const Base::Quantity& value = data.value(); Gui::QuantitySpinBox *infield = qobject_cast(editor); infield->setValue(value); infield->selectAll(); } QVariant PropertyUnitItem::editorData(QWidget *editor) const { Gui::QuantitySpinBox *infield = qobject_cast(editor); Base::Quantity value = infield->value(); return QVariant::fromValue(value); } // -------------------------------------------------------------------- PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyUnitConstraintItem) PropertyUnitConstraintItem::PropertyUnitConstraintItem() { } void PropertyUnitConstraintItem::setEditorData(QWidget *editor, const QVariant& data) const { const Base::Quantity& value = data.value(); Gui::QuantitySpinBox *infield = qobject_cast(editor); infield->setValue(value); infield->selectAll(); const App::PropertyQuantityConstraint* prop = static_cast (getFirstProperty()); const App::PropertyQuantityConstraint::Constraints* c = 0; if (prop) { c = prop->getConstraints(); } if (c) { infield->setMinimum(c->LowerBound); infield->setMaximum(c->UpperBound); infield->setSingleStep(c->StepSize); } else { infield->setMinimum((double)INT_MIN); infield->setMaximum((double)INT_MAX); } } // -------------------------------------------------------------------- PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyFloatConstraintItem) PropertyFloatConstraintItem::PropertyFloatConstraintItem() { } QVariant PropertyFloatConstraintItem::toString(const QVariant& prop) const { double value = prop.toDouble(); QString data = QLocale::system().toString(value, 'f', decimals()); return QVariant(data); } QVariant PropertyFloatConstraintItem::value(const App::Property* prop) const { assert(prop && prop->getTypeId().isDerivedFrom(App::PropertyFloatConstraint::getClassTypeId())); double value = static_cast(prop)->getValue(); return QVariant(value); } void PropertyFloatConstraintItem::setValue(const QVariant& value) { //if the item has an expression it issues the python code if (!hasExpression()) { if (!value.canConvert(QVariant::Double)) return; double val = value.toDouble(); QString data = QString::fromLatin1("%1").arg(val,0,'f',decimals()); setPropertyValue(data); } } QWidget* PropertyFloatConstraintItem::createEditor(QWidget* parent, const QObject* receiver, const char* method) const { Gui::DoubleSpinBox *sb = new Gui::DoubleSpinBox(parent); sb->setDecimals(decimals()); sb->setFrame(false); sb->setReadOnly(isReadOnly()); QObject::connect(sb, SIGNAL(valueChanged(double)), receiver, method); if (isBound()) { sb->bind(getPath()); sb->setAutoApply(autoApply()); } return sb; } void PropertyFloatConstraintItem::setEditorData(QWidget *editor, const QVariant& data) const { const App::PropertyFloatConstraint* prop = static_cast (getFirstProperty()); const App::PropertyFloatConstraint::Constraints* c = 0; if (prop) { c = prop->getConstraints(); } QDoubleSpinBox *sb = qobject_cast(editor); if (c) { sb->setMinimum(c->LowerBound); sb->setMaximum(c->UpperBound); sb->setSingleStep(c->StepSize); } else { sb->setMinimum((double)INT_MIN); sb->setMaximum((double)INT_MAX); sb->setSingleStep(0.1); } sb->setValue(data.toDouble()); } QVariant PropertyFloatConstraintItem::editorData(QWidget *editor) const { QDoubleSpinBox *sb = qobject_cast(editor); return QVariant(sb->value()); } // -------------------------------------------------------------------- PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyPrecisionItem) PropertyPrecisionItem::PropertyPrecisionItem() { setDecimals(16); } // -------------------------------------------------------------------- PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyAngleItem) PropertyAngleItem::PropertyAngleItem() { } void PropertyAngleItem::setEditorData(QWidget *editor, const QVariant& data) const { PropertyUnitConstraintItem::setEditorData(editor, data); } QVariant PropertyAngleItem::toString(const QVariant& prop) const { return PropertyUnitConstraintItem::toString(prop); } // -------------------------------------------------------------------- PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyBoolItem) PropertyBoolItem::PropertyBoolItem() { } QVariant PropertyBoolItem::value(const App::Property* prop) const { assert(prop && prop->getTypeId().isDerivedFrom(App::PropertyBool::getClassTypeId())); bool value = ((App::PropertyBool*)prop)->getValue(); return QVariant(value); } void PropertyBoolItem::setValue(const QVariant& value) { if (!value.canConvert(QVariant::Bool)) return; bool val = value.toBool(); QString data = (val ? QLatin1String("True") : QLatin1String("False")); setPropertyValue(data); } QWidget* PropertyBoolItem::createEditor(QWidget* parent, const QObject* receiver, const char* method) const { QComboBox *cb = new QComboBox(parent); cb->setFrame(false); cb->addItem(QLatin1String("false")); cb->addItem(QLatin1String("true")); cb->setDisabled(isReadOnly()); QObject::connect(cb, SIGNAL(activated(int)), receiver, method); return cb; } void PropertyBoolItem::setEditorData(QWidget *editor, const QVariant& data) const { QComboBox *cb = qobject_cast(editor); cb->setCurrentIndex(cb->findText(data.toString())); } QVariant PropertyBoolItem::editorData(QWidget *editor) const { QComboBox *cb = qobject_cast(editor); return QVariant(cb->currentText()); } // --------------------------------------------------------------- PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyVectorItem) PropertyVectorItem::PropertyVectorItem() { m_x = static_cast(PropertyFloatItem::create()); m_x->setParent(this); m_x->setPropertyName(QLatin1String("x")); this->appendChild(m_x); m_y = static_cast(PropertyFloatItem::create()); m_y->setParent(this); m_y->setPropertyName(QLatin1String("y")); this->appendChild(m_y); m_z = static_cast(PropertyFloatItem::create()); m_z->setParent(this); m_z->setPropertyName(QLatin1String("z")); this->appendChild(m_z); } QVariant PropertyVectorItem::toString(const QVariant& prop) const { const Base::Vector3d& value = prop.value(); QString data = QString::fromLatin1("[%1 %2 %3]") .arg(QLocale::system().toString(value.x, 'f', 2)) .arg(QLocale::system().toString(value.y, 'f', 2)) .arg(QLocale::system().toString(value.z, 'f', 2)); return QVariant(data); } QVariant PropertyVectorItem::value(const App::Property* prop) const { assert(prop && prop->getTypeId().isDerivedFrom(App::PropertyVector::getClassTypeId())); const Base::Vector3d& value = static_cast(prop)->getValue(); return QVariant::fromValue(value); } void PropertyVectorItem::setValue(const QVariant& value) { if (!value.canConvert()) return; const Base::Vector3d& val = value.value(); QString data = QString::fromLatin1("(%1, %2, %3)") .arg(val.x,0,'f',decimals()) .arg(val.y,0,'f',decimals()) .arg(val.z,0,'f',decimals()); setPropertyValue(data); } QWidget* PropertyVectorItem::createEditor(QWidget* parent, const QObject* /*receiver*/, const char* /*method*/) const { QLineEdit *le = new QLineEdit(parent); le->setFrame(false); le->setReadOnly(true); return le; } void PropertyVectorItem::setEditorData(QWidget *editor, const QVariant& data) const { QLineEdit* le = qobject_cast(editor); const Base::Vector3d& value = data.value(); QString text = QString::fromLatin1("[%1 %2 %3]") .arg(QLocale::system().toString(value.x, 'f', 2)) .arg(QLocale::system().toString(value.y, 'f', 2)) .arg(QLocale::system().toString(value.z, 'f', 2)); le->setText(text); } QVariant PropertyVectorItem::editorData(QWidget *editor) const { QLineEdit *le = qobject_cast(editor); return QVariant(le->text()); } double PropertyVectorItem::x() const { return data(1,Qt::EditRole).value().x; } void PropertyVectorItem::setX(double x) { setData(QVariant::fromValue(Base::Vector3d(x, y(), z()))); } double PropertyVectorItem::y() const { return data(1,Qt::EditRole).value().y; } void PropertyVectorItem::setY(double y) { setData(QVariant::fromValue(Base::Vector3d(x(), y, z()))); } double PropertyVectorItem::z() const { return data(1,Qt::EditRole).value().z; } void PropertyVectorItem::setZ(double z) { setData(QVariant::fromValue(Base::Vector3d(x(), y(), z))); } void PropertyVectorItem::propertyBound() { m_x->bind(App::ObjectIdentifier(getPath())<bind(App::ObjectIdentifier(getPath())<bind(App::ObjectIdentifier(getPath())<(PropertyUnitItem::create()); m_x->setParent(this); m_x->setPropertyName(QLatin1String("x")); this->appendChild(m_x); m_y = static_cast(PropertyUnitItem::create()); m_y->setParent(this); m_y->setPropertyName(QLatin1String("y")); this->appendChild(m_y); m_z = static_cast(PropertyUnitItem::create()); m_z->setParent(this); m_z->setPropertyName(QLatin1String("z")); this->appendChild(m_z); } QVariant PropertyVectorDistanceItem::toString(const QVariant& prop) const { const Base::Vector3d& value = prop.value(); QString data = QString::fromLatin1("[") + Base::Quantity(value.x, Base::Unit::Length).getUserString() + QString::fromLatin1(" ") + Base::Quantity(value.y, Base::Unit::Length).getUserString() + QString::fromLatin1(" ") + Base::Quantity(value.z, Base::Unit::Length).getUserString() + QString::fromLatin1("]"); return QVariant(data); } QVariant PropertyVectorDistanceItem::value(const App::Property* prop) const { assert(prop && prop->getTypeId().isDerivedFrom(App::PropertyVector::getClassTypeId())); const Base::Vector3d& value = static_cast(prop)->getValue(); return QVariant::fromValue(value); } void PropertyVectorDistanceItem::setValue(const QVariant& variant) { if (!variant.canConvert()) return; const Base::Vector3d& value = variant.value(); Base::Quantity x = Base::Quantity(value.x, Base::Unit::Length); Base::Quantity y = Base::Quantity(value.y, Base::Unit::Length); Base::Quantity z = Base::Quantity(value.z, Base::Unit::Length); QString data = QString::fromLatin1("(%1, %2, %3)") .arg(x.getValue()) .arg(y.getValue()) .arg(z.getValue()); setPropertyValue(data); } void PropertyVectorDistanceItem::setEditorData(QWidget *editor, const QVariant& data) const { QLineEdit* le = qobject_cast(editor); le->setText(toString(data).toString()); } QWidget* PropertyVectorDistanceItem::createEditor(QWidget* parent, const QObject* /*receiver*/, const char* /*method*/) const { QLineEdit *le = new QLineEdit(parent); le->setFrame(false); le->setReadOnly(true); return le; } QVariant PropertyVectorDistanceItem::editorData(QWidget *editor) const { QLineEdit *le = qobject_cast(editor); return QVariant(le->text()); } Base::Quantity PropertyVectorDistanceItem::x() const { return Base::Quantity(data(1,Qt::EditRole).value().x, Base::Unit::Length); } void PropertyVectorDistanceItem::setX(Base::Quantity x) { setData(QVariant::fromValue(Base::Vector3d(x.getValue(), y().getValue(), z().getValue()))); } Base::Quantity PropertyVectorDistanceItem::y() const { return Base::Quantity(data(1,Qt::EditRole).value().y, Base::Unit::Length); } void PropertyVectorDistanceItem::setY(Base::Quantity y) { setData(QVariant::fromValue(Base::Vector3d(x().getValue(), y.getValue(), z().getValue()))); } Base::Quantity PropertyVectorDistanceItem::z() const { return Base::Quantity(data(1,Qt::EditRole).value().z, Base::Unit::Length); } void PropertyVectorDistanceItem::setZ(Base::Quantity z) { setData(QVariant::fromValue(Base::Vector3d(x().getValue(), y().getValue(), z.getValue()))); } void PropertyVectorDistanceItem::propertyBound() { if (isBound()) { m_x->bind(App::ObjectIdentifier(getPath())<bind(App::ObjectIdentifier(getPath())<bind(App::ObjectIdentifier(getPath())<(PropertyFloatItem::create()); m_a11->setParent(this); m_a11->setPropertyName(QLatin1String("A11")); m_a11->setDecimals(decimals); this->appendChild(m_a11); m_a12 = static_cast(PropertyFloatItem::create()); m_a12->setParent(this); m_a12->setPropertyName(QLatin1String("A12")); m_a12->setDecimals(decimals); this->appendChild(m_a12); m_a13 = static_cast(PropertyFloatItem::create()); m_a13->setParent(this); m_a13->setPropertyName(QLatin1String("A13")); m_a13->setDecimals(decimals); this->appendChild(m_a13); m_a14 = static_cast(PropertyFloatItem::create()); m_a14->setParent(this); m_a14->setPropertyName(QLatin1String("A14")); m_a14->setDecimals(decimals); this->appendChild(m_a14); m_a21 = static_cast(PropertyFloatItem::create()); m_a21->setParent(this); m_a21->setPropertyName(QLatin1String("A21")); m_a21->setDecimals(decimals); this->appendChild(m_a21); m_a22 = static_cast(PropertyFloatItem::create()); m_a22->setParent(this); m_a22->setPropertyName(QLatin1String("A22")); m_a22->setDecimals(decimals); this->appendChild(m_a22); m_a23 = static_cast(PropertyFloatItem::create()); m_a23->setParent(this); m_a23->setPropertyName(QLatin1String("A23")); m_a23->setDecimals(decimals); this->appendChild(m_a23); m_a24 = static_cast(PropertyFloatItem::create()); m_a24->setParent(this); m_a24->setPropertyName(QLatin1String("A24")); m_a24->setDecimals(decimals); this->appendChild(m_a24); m_a31 = static_cast(PropertyFloatItem::create()); m_a31->setParent(this); m_a31->setPropertyName(QLatin1String("A31")); m_a31->setDecimals(decimals); this->appendChild(m_a31); m_a32 = static_cast(PropertyFloatItem::create()); m_a32->setParent(this); m_a32->setPropertyName(QLatin1String("A32")); m_a32->setDecimals(decimals); this->appendChild(m_a32); m_a33 = static_cast(PropertyFloatItem::create()); m_a33->setParent(this); m_a33->setPropertyName(QLatin1String("A33")); m_a33->setDecimals(decimals); this->appendChild(m_a33); m_a34 = static_cast(PropertyFloatItem::create()); m_a34->setParent(this); m_a34->setPropertyName(QLatin1String("A34")); m_a34->setDecimals(decimals); this->appendChild(m_a34); m_a41 = static_cast(PropertyFloatItem::create()); m_a41->setParent(this); m_a41->setPropertyName(QLatin1String("A41")); m_a41->setDecimals(decimals); this->appendChild(m_a41); m_a42 = static_cast(PropertyFloatItem::create()); m_a42->setParent(this); m_a42->setPropertyName(QLatin1String("A42")); m_a42->setDecimals(decimals); this->appendChild(m_a42); m_a43 = static_cast(PropertyFloatItem::create()); m_a43->setParent(this); m_a43->setPropertyName(QLatin1String("A43")); m_a43->setDecimals(decimals); this->appendChild(m_a43); m_a44 = static_cast(PropertyFloatItem::create()); m_a44->setParent(this); m_a44->setPropertyName(QLatin1String("A44")); m_a44->setDecimals(decimals); this->appendChild(m_a44); } QVariant PropertyMatrixItem::toString(const QVariant& prop) const { const Base::Matrix4D& value = prop.value(); QString text = QString::fromLatin1("[%1 %2 %3 %4 %5 %6 %7 %8 %9 %10 %11 %12 %13 %14 %15 %16]") .arg(QLocale::system().toString(value[0][0], 'f', 2)) //(unsigned short usNdx) .arg(QLocale::system().toString(value[0][1], 'f', 2)) .arg(QLocale::system().toString(value[0][2], 'f', 2)) .arg(QLocale::system().toString(value[0][3], 'f', 2)) .arg(QLocale::system().toString(value[1][0], 'f', 2)) .arg(QLocale::system().toString(value[1][1], 'f', 2)) .arg(QLocale::system().toString(value[1][2], 'f', 2)) .arg(QLocale::system().toString(value[1][3], 'f', 2)) .arg(QLocale::system().toString(value[2][0], 'f', 2)) .arg(QLocale::system().toString(value[2][1], 'f', 2)) .arg(QLocale::system().toString(value[2][2], 'f', 2)) .arg(QLocale::system().toString(value[2][3], 'f', 2)) .arg(QLocale::system().toString(value[3][0], 'f', 2)) .arg(QLocale::system().toString(value[3][1], 'f', 2)) .arg(QLocale::system().toString(value[3][2], 'f', 2)) .arg(QLocale::system().toString(value[3][3], 'f', 2)); return QVariant(text); } QVariant PropertyMatrixItem::value(const App::Property* prop) const { assert(prop && prop->getTypeId().isDerivedFrom(App::PropertyMatrix::getClassTypeId())); const Base::Matrix4D& value = static_cast(prop)->getValue(); return QVariant::fromValue(value); } QVariant PropertyMatrixItem::toolTip(const App::Property* prop) const { assert(prop && prop->getTypeId().isDerivedFrom(App::PropertyMatrix::getClassTypeId())); const Base::Matrix4D& value = static_cast(prop)->getValue(); return QVariant(QString::fromStdString(value.analyse())); } void PropertyMatrixItem::setValue(const QVariant& value) { if (!value.canConvert()) return; const Base::Matrix4D& val = value.value(); const int decimals=16; QString data = QString::fromLatin1("FreeCAD.Matrix(%1, %2, %3, %4, %5, %6, %7, %8, %9, %10, %11, %12, %13, %14, %15, %16)") .arg(val[0][0],0, 'f', decimals) .arg(val[0][1],0, 'f', decimals) .arg(val[0][2],0, 'f', decimals) .arg(val[0][3],0, 'f', decimals) .arg(val[1][0],0, 'f', decimals) .arg(val[1][1],0, 'f', decimals) .arg(val[1][2],0, 'f', decimals) .arg(val[1][3],0, 'f', decimals) .arg(val[2][0],0, 'f', decimals) .arg(val[2][1],0, 'f', decimals) .arg(val[2][2],0, 'f', decimals) .arg(val[2][3],0, 'f', decimals) .arg(val[3][0],0, 'f', decimals) .arg(val[3][1],0, 'f', decimals) .arg(val[3][2],0, 'f', decimals) .arg(val[3][3],0, 'f', decimals); setPropertyValue(data); } QWidget* PropertyMatrixItem::createEditor(QWidget* parent, const QObject* /*receiver*/, const char* /*method*/) const { QLineEdit *le = new QLineEdit(parent); le->setFrame(false); le->setReadOnly(true); return le; } void PropertyMatrixItem::setEditorData(QWidget *editor, const QVariant& data) const { QLineEdit* le = qobject_cast(editor); const Base::Matrix4D& value = data.value(); QString text = QString::fromLatin1("[%1 %2 %3 %4 %5 %6 %7 %8 %9 %10 %11 %12 %13 %14 %15 %16]") .arg(QLocale::system().toString(value[0][0], 'f', 2)) //(unsigned short usNdx) .arg(QLocale::system().toString(value[0][1], 'f', 2)) .arg(QLocale::system().toString(value[0][2], 'f', 2)) .arg(QLocale::system().toString(value[0][3], 'f', 2)) .arg(QLocale::system().toString(value[1][0], 'f', 2)) .arg(QLocale::system().toString(value[1][1], 'f', 2)) .arg(QLocale::system().toString(value[1][2], 'f', 2)) .arg(QLocale::system().toString(value[1][3], 'f', 2)) .arg(QLocale::system().toString(value[2][0], 'f', 2)) .arg(QLocale::system().toString(value[2][1], 'f', 2)) .arg(QLocale::system().toString(value[2][2], 'f', 2)) .arg(QLocale::system().toString(value[2][3], 'f', 2)) .arg(QLocale::system().toString(value[3][0], 'f', 2)) .arg(QLocale::system().toString(value[3][1], 'f', 2)) .arg(QLocale::system().toString(value[3][2], 'f', 2)) .arg(QLocale::system().toString(value[3][3], 'f', 2)); le->setText(text); } QVariant PropertyMatrixItem::editorData(QWidget *editor) const { QLineEdit *le = qobject_cast(editor); return QVariant(le->text()); } double PropertyMatrixItem::getA11() const { return data(1,Qt::EditRole).value()[0][0]; } void PropertyMatrixItem::setA11(double A11) { setData(QVariant::fromValue(Base::Matrix4D(A11,getA12(),getA13(),getA14(),getA21(),getA22(),getA23(),getA24(),getA31(),getA32(),getA33(),getA34(),getA41(),getA42(),getA43(),getA44() ))); } double PropertyMatrixItem::getA12() const { return data(1,Qt::EditRole).value()[0][1]; } void PropertyMatrixItem::setA12(double A12) { setData(QVariant::fromValue(Base::Matrix4D(getA11(),A12,getA13(),getA14(),getA21(),getA22(),getA23(),getA24(),getA31(),getA32(),getA33(),getA34(),getA41(),getA42(),getA43(),getA44() ))); } double PropertyMatrixItem::getA13() const { return data(1,Qt::EditRole).value()[0][2]; } void PropertyMatrixItem::setA13(double A13) { setData(QVariant::fromValue(Base::Matrix4D(getA11(),getA12(),A13,getA14(),getA21(),getA22(),getA23(),getA24(),getA31(),getA32(),getA33(),getA34(),getA41(),getA42(),getA43(),getA44() ))); } double PropertyMatrixItem::getA14() const { return data(1,Qt::EditRole).value()[0][3]; } void PropertyMatrixItem::setA14(double A14) { setData(QVariant::fromValue(Base::Matrix4D(getA11(),getA12(),getA13(),A14,getA21(),getA22(),getA23(),getA24(),getA31(),getA32(),getA33(),getA34(),getA41(),getA42(),getA43(),getA44() ))); } double PropertyMatrixItem::getA21() const { return data(1,Qt::EditRole).value()[1][0]; } void PropertyMatrixItem::setA21(double A21) { setData(QVariant::fromValue(Base::Matrix4D(getA11(),getA12(),getA13(),getA14(),A21,getA22(),getA23(),getA24(),getA31(),getA32(),getA33(),getA34(),getA41(),getA42(),getA43(),getA44() ))); } double PropertyMatrixItem::getA22() const { return data(1,Qt::EditRole).value()[1][1]; } void PropertyMatrixItem::setA22(double A22) { setData(QVariant::fromValue(Base::Matrix4D(getA11(),getA12(),getA13(),getA14(),getA21(),A22,getA23(),getA24(),getA31(),getA32(),getA33(),getA34(),getA41(),getA42(),getA43(),getA44() ))); } double PropertyMatrixItem::getA23() const { return data(1,Qt::EditRole).value()[1][2]; } void PropertyMatrixItem::setA23(double A23) { setData(QVariant::fromValue(Base::Matrix4D(getA11(),getA12(),getA13(),getA14(),getA21(),getA22(),A23,getA24(),getA31(),getA32(),getA33(),getA34(),getA41(),getA42(),getA43(),getA44() ))); } double PropertyMatrixItem::getA24() const { return data(1,Qt::EditRole).value()[1][3]; } void PropertyMatrixItem::setA24(double A24) { setData(QVariant::fromValue(Base::Matrix4D(getA11(),getA12(),getA13(),getA14(),getA21(),getA22(),getA23(),A24,getA31(),getA32(),getA33(),getA34(),getA41(),getA42(),getA43(),getA44() ))); } double PropertyMatrixItem::getA31() const { return data(1,Qt::EditRole).value()[2][0]; } void PropertyMatrixItem::setA31(double A31) { setData(QVariant::fromValue(Base::Matrix4D(getA11(),getA12(),getA13(),getA14(),getA21(),getA22(),getA23(),getA24(),A31,getA32(),getA33(),getA34(),getA41(),getA42(),getA43(),getA44() ))); } double PropertyMatrixItem::getA32() const { return data(1,Qt::EditRole).value()[2][1]; } void PropertyMatrixItem::setA32(double A32) { setData(QVariant::fromValue(Base::Matrix4D(getA11(),getA12(),getA13(),getA14(),getA21(),getA22(),getA23(),getA24(),getA31(),A32,getA33(),getA34(),getA41(),getA42(),getA43(),getA44() ))); } double PropertyMatrixItem::getA33() const { return data(1,Qt::EditRole).value()[2][2]; } void PropertyMatrixItem::setA33(double A33) { setData(QVariant::fromValue(Base::Matrix4D(getA11(),getA12(),getA13(),getA14(),getA21(),getA22(),getA23(),getA24(),getA31(),getA32(),A33,getA34(),getA41(),getA42(),getA43(),getA44() ))); } double PropertyMatrixItem::getA34() const { return data(1,Qt::EditRole).value()[2][3]; } void PropertyMatrixItem::setA34(double A34) { setData(QVariant::fromValue(Base::Matrix4D(getA11(),getA12(),getA13(),getA14(),getA21(),getA22(),getA23(),getA24(),getA31(),getA32(),getA33(),A34,getA41(),getA42(),getA43(),getA44() ))); } double PropertyMatrixItem::getA41() const { return data(1,Qt::EditRole).value()[3][0]; } void PropertyMatrixItem::setA41(double A41) { setData(QVariant::fromValue(Base::Matrix4D(getA11(),getA12(),getA13(),getA14(),getA21(),getA22(),getA23(),getA24(),getA31(),getA32(),getA33(),getA34(),A41,getA42(),getA43(),getA44() ))); } double PropertyMatrixItem::getA42() const { return data(1,Qt::EditRole).value()[3][1]; } void PropertyMatrixItem::setA42(double A42) { setData(QVariant::fromValue(Base::Matrix4D(getA11(),getA12(),getA13(),getA14(),getA21(),getA22(),getA23(),getA24(),getA31(),getA32(),getA33(),getA34(),getA41(),A42,getA43(),getA44() ))); } double PropertyMatrixItem::getA43() const { return data(1,Qt::EditRole).value()[3][2]; } void PropertyMatrixItem::setA43(double A43) { setData(QVariant::fromValue(Base::Matrix4D(getA11(),getA12(),getA13(),getA14(),getA21(),getA22(),getA23(),getA24(),getA31(),getA32(),getA33(),getA34(),getA41(),getA42(),A43,getA44() ))); } double PropertyMatrixItem::getA44() const { return data(1,Qt::EditRole).value()[3][3]; } void PropertyMatrixItem::setA44(double A44) { setData(QVariant::fromValue(Base::Matrix4D(getA11(),getA12(),getA13(),getA14(),getA21(),getA22(),getA23(),getA24(),getA31(),getA32(),getA33(),getA34(),getA41(),getA42(),getA43(),A44 ))); } // -------------------------------------------------------------------- PlacementEditor::PlacementEditor(const QString& name, QWidget * parent) : LabelButton(parent), _task(0) { propertyname = name; propertyname.replace(QLatin1String(" "), QLatin1String("")); } PlacementEditor::~PlacementEditor() { } void PlacementEditor::browse() { Gui::TaskView::TaskDialog* dlg = Gui::Control().activeDialog(); Gui::Dialog::TaskPlacement* task; task = qobject_cast(dlg); if (dlg && !task) { // there is already another task dialog which must be closed first Gui::Control().showDialog(dlg); return; } if (!task) { task = new Gui::Dialog::TaskPlacement(); } if (!_task) { _task = task; connect(task, SIGNAL(placementChanged(const QVariant &, bool, bool)), this, SLOT(updateValue(const QVariant&, bool, bool))); } task->setPlacement(value().value()); task->setPropertyName(propertyname); Gui::Control().showDialog(task); } void PlacementEditor::showValue(const QVariant& d) { const Base::Placement& p = d.value(); double angle; Base::Vector3d dir, pos; p.getRotation().getRawValue(dir, angle); angle = Base::toDegrees(angle); pos = p.getPosition(); QString data = QString::fromUtf8("[(%1 %2 %3);%4 \xc2\xb0;(%5 %6 %7)]") .arg(QLocale::system().toString(dir.x,'f',2)) .arg(QLocale::system().toString(dir.y,'f',2)) .arg(QLocale::system().toString(dir.z,'f',2)) .arg(QLocale::system().toString(angle,'f',2)) .arg(QLocale::system().toString(pos.x,'f',2)) .arg(QLocale::system().toString(pos.y,'f',2)) .arg(QLocale::system().toString(pos.z,'f',2)); getLabel()->setText(data); } void PlacementEditor::updateValue(const QVariant& v, bool incr, bool data) { if (data) { if (incr) { QVariant u = value(); const Base::Placement& plm = u.value(); const Base::Placement& rel = v.value(); Base::Placement data = rel * plm; setValue(QVariant::fromValue(data)); } else { setValue(v); } } } PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyPlacementItem) PropertyPlacementItem::PropertyPlacementItem() : init_axis(false), changed_value(false), rot_angle(0), rot_axis(0,0,1) { m_a = static_cast(PropertyUnitItem::create()); m_a->setParent(this); m_a->setPropertyName(QLatin1String(QT_TRANSLATE_NOOP("App::Property", "Angle"))); this->appendChild(m_a); m_d = static_cast(PropertyVectorItem::create()); m_d->setParent(this); m_d->setPropertyName(QLatin1String(QT_TRANSLATE_NOOP("App::Property", "Axis"))); m_d->setReadOnly(true); this->appendChild(m_d); m_p = static_cast(PropertyVectorDistanceItem::create()); m_p->setParent(this); m_p->setPropertyName(QLatin1String(QT_TRANSLATE_NOOP("App::Property", "Position"))); m_p->setReadOnly(true); this->appendChild(m_p); } PropertyPlacementItem::~PropertyPlacementItem() { } Base::Quantity PropertyPlacementItem::getAngle() const { QVariant value = data(1, Qt::EditRole); if (!value.canConvert()) return Base::Quantity(0.0); const Base::Placement& val = value.value(); double angle; Base::Vector3d dir; val.getRotation().getRawValue(dir, angle); if (dir * this->rot_axis < 0.0) angle = -angle; return Base::Quantity(Base::toDegrees(angle), Base::Unit::Angle); } void PropertyPlacementItem::setAngle(Base::Quantity angle) { QVariant value = data(1, Qt::EditRole); if (!value.canConvert()) return; Base::Placement val = value.value(); Base::Rotation rot; rot.setValue(this->rot_axis, Base::toRadians(angle.getValue())); val.setRotation(rot); changed_value = true; rot_angle = angle.getValue(); setValue(QVariant::fromValue(val)); } Base::Vector3d PropertyPlacementItem::getAxis() const { // We must store the rotation axis in a member because // if we read the value from the property we would always // get a normalized vector which makes it quite unhandy // to work with return this->rot_axis; } void PropertyPlacementItem::setAxis(const Base::Vector3d& axis) { QVariant value = data(1, Qt::EditRole); if (!value.canConvert()) return; this->rot_axis = axis; Base::Placement val = value.value(); Base::Rotation rot = val.getRotation(); Base::Vector3d dummy; double angle; rot.getValue(dummy, angle); if (dummy * axis < 0.0) angle = -angle; rot.setValue(axis, angle); val.setRotation(rot); changed_value = true; setValue(QVariant::fromValue(val)); } Base::Vector3d PropertyPlacementItem::getPosition() const { QVariant value = data(1, Qt::EditRole); if (!value.canConvert()) return Base::Vector3d(0,0,0); const Base::Placement& val = value.value(); return val.getPosition(); } void PropertyPlacementItem::setPosition(const Base::Vector3d& pos) { QVariant value = data(1, Qt::EditRole); if (!value.canConvert()) return; Base::Placement val = value.value(); val.setPosition(pos); changed_value = true; setValue(QVariant::fromValue(val)); } void PropertyPlacementItem::assignProperty(const App::Property* prop) { // Choose an adaptive epsilon to avoid changing the axis when they are considered to // be equal. See https://forum.freecadweb.org/viewtopic.php?f=10&t=24662&start=10 double eps = std::pow(10.0, -2*(decimals()+1)); if (prop->getTypeId().isDerivedFrom(App::PropertyPlacement::getClassTypeId())) { const Base::Placement& value = static_cast(prop)->getValue(); double angle; Base::Vector3d dir; value.getRotation().getRawValue(dir, angle); Base::Vector3d cross = this->rot_axis.Cross(dir); double len2 = cross.Sqr(); if (angle != 0) { // vectors are not parallel if (len2 > eps) this->rot_axis = dir; // vectors point into opposite directions else if (this->rot_axis.Dot(dir) < 0) this->rot_axis = -this->rot_axis; } this->rot_angle = Base::toDegrees(angle); } } QVariant PropertyPlacementItem::value(const App::Property* prop) const { assert(prop && prop->getTypeId().isDerivedFrom(App::PropertyPlacement::getClassTypeId())); const Base::Placement& value = static_cast(prop)->getValue(); double angle; Base::Vector3d dir; value.getRotation().getRawValue(dir, angle); if (!init_axis) { if (m_a->hasExpression()) { QString str = m_a->expressionAsString(); const_cast(this)->rot_angle = str.toDouble(); } else { const_cast(this)->rot_angle = Base::toDegrees(angle); } PropertyItem* x = m_d->child(0); PropertyItem* y = m_d->child(1); PropertyItem* z = m_d->child(2); if (x->hasExpression()) { QString str = x->expressionAsString(); dir.x = str.toDouble(); } if (y->hasExpression()) { QString str = y->expressionAsString(); dir.y = str.toDouble(); } if (z->hasExpression()) { QString str = z->expressionAsString(); dir.z = str.toDouble(); } const_cast(this)->rot_axis = dir; const_cast(this)->init_axis = true; } return QVariant::fromValue(value); } QVariant PropertyPlacementItem::toolTip(const App::Property* prop) const { assert(prop && prop->getTypeId().isDerivedFrom(App::PropertyPlacement::getClassTypeId())); const Base::Placement& p = static_cast(prop)->getValue(); double angle; Base::Vector3d dir, pos; p.getRotation().getRawValue(dir, angle); angle = Base::toDegrees(angle); pos = p.getPosition(); QString data = QString::fromUtf8("Axis: (%1 %2 %3)\n" "Angle: %4\n" "Position: (%5 %6 %7)") .arg(QLocale::system().toString(dir.x,'f',decimals())) .arg(QLocale::system().toString(dir.y,'f',decimals())) .arg(QLocale::system().toString(dir.z,'f',decimals())) .arg(Base::Quantity(angle, Base::Unit::Angle).getUserString()) .arg(Base::Quantity(pos.x, Base::Unit::Length).getUserString()) .arg(Base::Quantity(pos.y, Base::Unit::Length).getUserString()) .arg(Base::Quantity(pos.z, Base::Unit::Length).getUserString()); return QVariant(data); } QVariant PropertyPlacementItem::toString(const QVariant& prop) const { const Base::Placement& p = prop.value(); double angle; Base::Vector3d dir, pos; p.getRotation().getRawValue(dir, angle); angle = Base::toDegrees(angle); pos = p.getPosition(); QString data = QString::fromUtf8("[(%1 %2 %3); %4; (%5 %6 %7)]") .arg(QLocale::system().toString(dir.x,'f',2)) .arg(QLocale::system().toString(dir.y,'f',2)) .arg(QLocale::system().toString(dir.z,'f',2)) .arg(Base::Quantity(angle, Base::Unit::Angle).getUserString()) .arg(Base::Quantity(pos.x, Base::Unit::Length).getUserString()) .arg(Base::Quantity(pos.y, Base::Unit::Length).getUserString()) .arg(Base::Quantity(pos.z, Base::Unit::Length).getUserString()); return QVariant(data); } void PropertyPlacementItem::setValue(const QVariant& value) { if (!value.canConvert()) return; // Accept this only if the user changed the axis, angle or position but // not if >this< item loses focus if (!changed_value) return; changed_value = false; const Base::Placement& val = value.value(); Base::Vector3d pos = val.getPosition(); QString data = QString::fromLatin1("App.Placement(" "App.Vector(%1,%2,%3)," "App.Rotation(App.Vector(%4,%5,%6),%7))") .arg(pos.x) .arg(pos.y) .arg(pos.z) .arg(rot_axis.x) .arg(rot_axis.y) .arg(rot_axis.z) .arg(rot_angle,0); setPropertyValue(data); } QWidget* PropertyPlacementItem::createEditor(QWidget* parent, const QObject* receiver, const char* method) const { PlacementEditor *pe = new PlacementEditor(this->propertyName(), parent); QObject::connect(pe, SIGNAL(valueChanged(const QVariant &)), receiver, method); pe->setDisabled(isReadOnly()); return pe; } void PropertyPlacementItem::setEditorData(QWidget *editor, const QVariant& data) const { PlacementEditor *pe = qobject_cast(editor); pe->setValue(data); } QVariant PropertyPlacementItem::editorData(QWidget *editor) const { PlacementEditor *pe = qobject_cast(editor); return pe->value(); } void PropertyPlacementItem::propertyBound() { if (isBound()) { m_a->bind(App::ObjectIdentifier(getPath())<bind(App::ObjectIdentifier(getPath())<bind(App::ObjectIdentifier(getPath())<getTypeId().isDerivedFrom(App::PropertyEnumeration::getClassTypeId())); const App::PropertyEnumeration* prop_enum = static_cast(prop); const std::vector& value = prop_enum->getEnumVector(); long currentItem = prop_enum->getValue(); if (currentItem < 0 || currentItem >= static_cast(value.size())) return QVariant(QString()); return QVariant(QString::fromUtf8(value[currentItem].c_str())); } void PropertyEnumItem::setValue(const QVariant& value) { if (!value.canConvert(QVariant::StringList)) return; QStringList items = value.toStringList(); if (!items.isEmpty()) { QByteArray val = items.front().toUtf8(); std::string str = Base::Tools::escapedUnicodeFromUtf8(val); QString data = QString::fromLatin1("u\"%1\"").arg(QString::fromStdString(str)); setPropertyValue(data); } } QWidget* PropertyEnumItem::createEditor(QWidget* parent, const QObject* receiver, const char* method) const { QComboBox *cb = new QComboBox(parent); cb->setFrame(false); cb->setDisabled(isReadOnly()); QObject::connect(cb, SIGNAL(activated(int)), receiver, method); return cb; } void PropertyEnumItem::setEditorData(QWidget *editor, const QVariant& data) const { const std::vector& items = getPropertyData(); QStringList commonModes, modes; for (std::vector::const_iterator it = items.begin(); it != items.end(); ++it) { if ((*it)->getTypeId() == App::PropertyEnumeration::getClassTypeId()) { App::PropertyEnumeration* prop = static_cast(*it); if (prop->getEnums() == 0) { commonModes.clear(); break; } const std::vector& value = prop->getEnumVector(); if (it == items.begin()) { for (std::vector::const_iterator jt = value.begin(); jt != value.end(); ++jt) commonModes << QString::fromUtf8(jt->c_str()); } else { for (std::vector::const_iterator jt = value.begin(); jt != value.end(); ++jt) { if (commonModes.contains(QString::fromUtf8(jt->c_str()))) modes << QString::fromUtf8(jt->c_str()); } commonModes = modes; modes.clear(); } } } QComboBox *cb = qobject_cast(editor); if (!commonModes.isEmpty()) { cb->clear(); cb->addItems(commonModes); cb->setCurrentIndex(cb->findText(data.toString())); } } QVariant PropertyEnumItem::editorData(QWidget *editor) const { QComboBox *cb = qobject_cast(editor); return QVariant(cb->currentText()); } // --------------------------------------------------------------- PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyStringListItem) PropertyStringListItem::PropertyStringListItem() { } QWidget* PropertyStringListItem::createEditor(QWidget* parent, const QObject* receiver, const char* method) const { Gui::LabelEditor* le = new Gui::LabelEditor(parent); le->setAutoFillBackground(true); le->setDisabled(isReadOnly()); QObject::connect(le, SIGNAL(textChanged(const QString&)), receiver, method); return le; } void PropertyStringListItem::setEditorData(QWidget *editor, const QVariant& data) const { Gui::LabelEditor *le = qobject_cast(editor); QStringList list = data.toStringList(); le->setText(list.join(QChar::fromLatin1('\n'))); } QVariant PropertyStringListItem::editorData(QWidget *editor) const { Gui::LabelEditor *le = qobject_cast(editor); QString complete = le->text(); QStringList list = complete.split(QChar::fromLatin1('\n')); return QVariant(list); } QVariant PropertyStringListItem::toString(const QVariant& prop) const { QStringList list = prop.toStringList(); if (list.size() > 10) { list = list.mid(0, 10); list.append(QLatin1String("...")); } QString text = QString::fromUtf8("[%1]").arg(list.join(QLatin1String(","))); text.replace(QString::fromUtf8("'"),QString::fromUtf8("\\'")); return QVariant(text); } QVariant PropertyStringListItem::value(const App::Property* prop) const { assert(prop && prop->getTypeId().isDerivedFrom(App::PropertyStringList::getClassTypeId())); QStringList list; const std::vector& value = ((App::PropertyStringList*)prop)->getValues(); for ( std::vector::const_iterator jt = value.begin(); jt != value.end(); ++jt ) { list << QString::fromUtf8(jt->c_str()); } return QVariant(list); } void PropertyStringListItem::setValue(const QVariant& value) { if (!value.canConvert(QVariant::StringList)) return; QStringList values = value.toStringList(); QString data; QTextStream str(&data); str << "["; for (QStringList::Iterator it = values.begin(); it != values.end(); ++it) { QString text(*it); text.replace(QString::fromUtf8("'"),QString::fromUtf8("\\'")); std::string pystr = Base::Tools::escapedUnicodeFromUtf8(text.toUtf8()); str << "u\"" << pystr.c_str() << "\", "; } str << "]"; setPropertyValue(data); } // --------------------------------------------------------------- PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyFloatListItem) PropertyFloatListItem::PropertyFloatListItem() { } QWidget* PropertyFloatListItem::createEditor(QWidget* parent, const QObject* receiver, const char* method) const { Gui::LabelEditor* le = new Gui::LabelEditor(parent); le->setAutoFillBackground(true); le->setInputType(Gui::LabelEditor::Float); le->setDisabled(isReadOnly()); QObject::connect(le, SIGNAL(textChanged(const QString&)), receiver, method); return le; } void PropertyFloatListItem::setEditorData(QWidget *editor, const QVariant& data) const { Gui::LabelEditor *le = qobject_cast(editor); QStringList list = data.toStringList(); le->setText(list.join(QChar::fromLatin1('\n'))); } QVariant PropertyFloatListItem::editorData(QWidget *editor) const { Gui::LabelEditor *le = qobject_cast(editor); QString complete = le->text(); QStringList list = complete.split(QChar::fromLatin1('\n')); return QVariant(list); } QVariant PropertyFloatListItem::toString(const QVariant& prop) const { QStringList list = prop.toStringList(); if (list.size() > 10) { list = list.mid(0, 10); list.append(QLatin1String("...")); } QString text = QString::fromUtf8("[%1]").arg(list.join(QLatin1String(","))); return QVariant(text); } QVariant PropertyFloatListItem::value(const App::Property* prop) const { assert(prop && prop->getTypeId().isDerivedFrom(App::PropertyFloatList::getClassTypeId())); QStringList list; const std::vector& value = static_cast(prop)->getValues(); for (std::vector::const_iterator jt = value.begin(); jt != value.end(); ++jt) { list << QString::number(*jt, 'f', decimals()); } return QVariant(list); } void PropertyFloatListItem::setValue(const QVariant& value) { if (!value.canConvert(QVariant::StringList)) return; QStringList values = value.toStringList(); QString data; QTextStream str(&data); str << "["; for (QStringList::Iterator it = values.begin(); it != values.end(); ++it) { str << *it << ","; } str << "]"; if (data == QString::fromUtf8("[,]")) data = QString::fromUtf8("[]"); setPropertyValue(data); } // --------------------------------------------------------------- PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyIntegerListItem) PropertyIntegerListItem::PropertyIntegerListItem() { } QWidget* PropertyIntegerListItem::createEditor(QWidget* parent, const QObject* receiver, const char* method) const { Gui::LabelEditor* le = new Gui::LabelEditor(parent); le->setAutoFillBackground(true); le->setInputType(Gui::LabelEditor::Integer); le->setDisabled(isReadOnly()); QObject::connect(le, SIGNAL(textChanged(const QString&)), receiver, method); return le; } void PropertyIntegerListItem::setEditorData(QWidget *editor, const QVariant& data) const { Gui::LabelEditor *le = qobject_cast(editor); QStringList list = data.toStringList(); le->setText(list.join(QChar::fromLatin1('\n'))); } QVariant PropertyIntegerListItem::editorData(QWidget *editor) const { Gui::LabelEditor *le = qobject_cast(editor); QString complete = le->text(); QStringList list = complete.split(QChar::fromLatin1('\n')); return QVariant(list); } QVariant PropertyIntegerListItem::toString(const QVariant& prop) const { QStringList list = prop.toStringList(); if (list.size() > 10) { list = list.mid(0, 10); list.append(QLatin1String("...")); } QString text = QString::fromUtf8("[%1]").arg(list.join(QLatin1String(","))); return QVariant(text); } QVariant PropertyIntegerListItem::value(const App::Property* prop) const { assert(prop && prop->getTypeId().isDerivedFrom(App::PropertyIntegerList::getClassTypeId())); QStringList list; const std::vector& value = static_cast(prop)->getValues(); for (std::vector::const_iterator jt = value.begin(); jt != value.end(); ++jt) { list << QString::number(*jt); } return QVariant(list); } void PropertyIntegerListItem::setValue(const QVariant& value) { if (!value.canConvert(QVariant::StringList)) return; QStringList values = value.toStringList(); QString data; QTextStream str(&data); str << "["; for (QStringList::Iterator it = values.begin(); it != values.end(); ++it) { str << *it << ","; } str << "]"; if (data == QString::fromUtf8("[,]")) data = QString::fromUtf8("[]"); setPropertyValue(data); } // -------------------------------------------------------------------- PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyColorItem) PropertyColorItem::PropertyColorItem() { } QVariant PropertyColorItem::decoration(const QVariant& value) const { QColor color = value.value(); int size = QApplication::style()->pixelMetric(QStyle::PM_ListViewIconSize); QPixmap p(size, size); p.fill(color); return QVariant(p); } QVariant PropertyColorItem::toString(const QVariant& prop) const { QColor value = prop.value(); QString color = QString::fromLatin1("[%1, %2, %3]") .arg(value.red()).arg(value.green()).arg(value.blue()); return QVariant(color); } QVariant PropertyColorItem::value(const App::Property* prop) const { assert(prop && prop->getTypeId().isDerivedFrom(App::PropertyColor::getClassTypeId())); App::Color value = ((App::PropertyColor*)prop)->getValue(); return QVariant(value.asValue()); } void PropertyColorItem::setValue(const QVariant& value) { if (!value.canConvert()) return; QColor col = value.value(); App::Color val; val.setValue(col); QString data = QString::fromLatin1("(%1,%2,%3)") .arg(val.r,0,'f',decimals()) .arg(val.g,0,'f',decimals()) .arg(val.b,0,'f',decimals()); setPropertyValue(data); } QWidget* PropertyColorItem::createEditor(QWidget* parent, const QObject* receiver, const char* method) const { Gui::ColorButton* cb = new Gui::ColorButton( parent ); cb->setDisabled(isReadOnly()); QObject::connect(cb, SIGNAL(changed()), receiver, method); return cb; } void PropertyColorItem::setEditorData(QWidget *editor, const QVariant& data) const { Gui::ColorButton *cb = qobject_cast(editor); QColor color = data.value(); cb->setColor(color); } QVariant PropertyColorItem::editorData(QWidget *editor) const { Gui::ColorButton *cb = qobject_cast(editor); QVariant var; var.setValue(cb->color()); return var; } // -------------------------------------------------------------------- namespace Gui { namespace PropertyEditor { class Material { public: QColor diffuseColor; QColor ambientColor; QColor specularColor; QColor emissiveColor; float shininess; float transparency; }; } } Q_DECLARE_METATYPE(Gui::PropertyEditor::Material) PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyMaterialItem) PropertyMaterialItem::PropertyMaterialItem() { diffuse = static_cast(PropertyColorItem::create()); diffuse->setParent(this); diffuse->setPropertyName(QLatin1String("DiffuseColor")); this->appendChild(diffuse); ambient = static_cast(PropertyColorItem::create()); ambient->setParent(this); ambient->setPropertyName(QLatin1String("AmbientColor")); this->appendChild(ambient); specular = static_cast(PropertyColorItem::create()); specular->setParent(this); specular->setPropertyName(QLatin1String("SpecularColor")); this->appendChild(specular); emissive = static_cast(PropertyColorItem::create()); emissive->setParent(this); emissive->setPropertyName(QLatin1String("EmissiveColor")); this->appendChild(emissive); shininess = static_cast(PropertyFloatItem::create()); shininess->setParent(this); shininess->setPropertyName(QLatin1String("Shininess")); this->appendChild(shininess); transparency = static_cast(PropertyFloatItem::create()); transparency->setParent(this); transparency->setPropertyName(QLatin1String("Transparency")); this->appendChild(transparency); } PropertyMaterialItem::~PropertyMaterialItem() { } void PropertyMaterialItem::propertyBound() { } QColor PropertyMaterialItem::getDiffuseColor() const { QVariant value = data(1, Qt::EditRole); if (!value.canConvert()) return QColor(); Material val = value.value(); return val.diffuseColor; } void PropertyMaterialItem::setDiffuseColor(const QColor& color) { QVariant value = data(1, Qt::EditRole); if (!value.canConvert()) return; Material mat = value.value(); mat.diffuseColor = color; setValue(QVariant::fromValue(mat)); } QColor PropertyMaterialItem::getAmbientColor() const { QVariant value = data(1, Qt::EditRole); if (!value.canConvert()) return QColor(); Material val = value.value(); return val.ambientColor; } void PropertyMaterialItem::setAmbientColor(const QColor& color) { QVariant value = data(1, Qt::EditRole); if (!value.canConvert()) return; Material mat = value.value(); mat.ambientColor = color; setValue(QVariant::fromValue(mat)); } QColor PropertyMaterialItem::getSpecularColor() const { QVariant value = data(1, Qt::EditRole); if (!value.canConvert()) return QColor(); Material val = value.value(); return val.specularColor; } void PropertyMaterialItem::setSpecularColor(const QColor& color) { QVariant value = data(1, Qt::EditRole); if (!value.canConvert()) return; Material mat = value.value(); mat.specularColor = color; setValue(QVariant::fromValue(mat)); } QColor PropertyMaterialItem::getEmissiveColor() const { QVariant value = data(1, Qt::EditRole); if (!value.canConvert()) return QColor(); Material val = value.value(); return val.emissiveColor; } void PropertyMaterialItem::setEmissiveColor(const QColor& color) { QVariant value = data(1, Qt::EditRole); if (!value.canConvert()) return; Material mat = value.value(); mat.emissiveColor = color; setValue(QVariant::fromValue(mat)); } float PropertyMaterialItem::getShininess() const { QVariant value = data(1, Qt::EditRole); if (!value.canConvert()) return 0; Material val = value.value(); return val.shininess; } void PropertyMaterialItem::setShininess(float s) { QVariant value = data(1, Qt::EditRole); if (!value.canConvert()) return; Material mat = value.value(); mat.shininess = s; setValue(QVariant::fromValue(mat)); } float PropertyMaterialItem::getTransparency() const { QVariant value = data(1, Qt::EditRole); if (!value.canConvert()) return 0; Material val = value.value(); return val.transparency; } void PropertyMaterialItem::setTransparency(float t) { QVariant value = data(1, Qt::EditRole); if (!value.canConvert()) return; Material mat = value.value(); mat.transparency = t; setValue(QVariant::fromValue(mat)); } QVariant PropertyMaterialItem::decoration(const QVariant& value) const { // use the diffuse color Material val = value.value(); QColor color = val.diffuseColor; int size = QApplication::style()->pixelMetric(QStyle::PM_ListViewIconSize); QPixmap p(size, size); p.fill(color); return QVariant(p); } QVariant PropertyMaterialItem::toString(const QVariant& prop) const { // use the diffuse color Material val = prop.value(); QColor value = val.diffuseColor; QString color = QString::fromLatin1("[%1, %2, %3]") .arg(value.red()).arg(value.green()).arg(value.blue()); return QVariant(color); } QVariant PropertyMaterialItem::toolTip(const App::Property* prop) const { assert(prop && prop->getTypeId().isDerivedFrom(App::PropertyMaterial::getClassTypeId())); const App::Material& value = static_cast(prop)->getValue(); QColor dc = value.diffuseColor.asValue(); QColor ac = value.ambientColor.asValue(); QColor sc = value.specularColor.asValue(); QColor ec = value.emissiveColor.asValue(); QString data = QString::fromUtf8( "Diffuse color: [%1, %2, %3]\n" "Ambient color: [%4, %5, %6]\n" "Specular color: [%7, %8, %9]\n" "Emissive color: [%10, %11, %12]\n" "Shininess: %13\n" "Transparency: %14" ) .arg(dc.red()).arg(dc.green()).arg(dc.blue()) .arg(ac.red()).arg(ac.green()).arg(ac.blue()) .arg(sc.red()).arg(sc.green()).arg(sc.blue()) .arg(ec.red()).arg(ec.green()).arg(ec.blue()) .arg(value.shininess) .arg(value.transparency) ; return QVariant(data); } QVariant PropertyMaterialItem::value(const App::Property* prop) const { assert(prop && prop->getTypeId().isDerivedFrom(App::PropertyMaterial::getClassTypeId())); const App::Material& value = static_cast(prop)->getValue(); Material mat; mat.diffuseColor = value.diffuseColor.asValue(); mat.ambientColor = value.ambientColor.asValue(); mat.specularColor = value.specularColor.asValue(); mat.emissiveColor = value.emissiveColor.asValue(); mat.shininess = value.shininess; mat.transparency = value.transparency; return QVariant::fromValue(mat); } void PropertyMaterialItem::setValue(const QVariant& value) { if (!value.canConvert()) return; Material mat = value.value(); App::Color dc; dc.setValue(mat.diffuseColor); App::Color ac; ac.setValue(mat.ambientColor); App::Color sc; sc.setValue(mat.specularColor); App::Color ec; ec.setValue(mat.emissiveColor); float s = mat.shininess; float t = mat.transparency; QString data = QString::fromLatin1( "App.Material(" "DiffuseColor=(%1,%2,%3)," "AmbientColor=(%4,%5,%6)," "SpecularColor=(%7,%8,%9)," "EmissiveColor=(%10,%11,%12)," "Shininess=(%13)," "Transparency=(%14)," ")" ) .arg(dc.r, 0, 'f', decimals()) .arg(dc.g, 0, 'f', decimals()) .arg(dc.b, 0, 'f', decimals()) .arg(ac.r, 0, 'f', decimals()) .arg(ac.g, 0, 'f', decimals()) .arg(ac.b, 0, 'f', decimals()) .arg(sc.r, 0, 'f', decimals()) .arg(sc.g, 0, 'f', decimals()) .arg(sc.b, 0, 'f', decimals()) .arg(ec.r, 0, 'f', decimals()) .arg(ec.g, 0, 'f', decimals()) .arg(ec.b, 0, 'f', decimals()) .arg(s, 0, 'f', decimals()) .arg(t, 0, 'f', decimals()) ; setPropertyValue(data); } QWidget* PropertyMaterialItem::createEditor(QWidget* parent, const QObject* receiver, const char* method) const { Gui::ColorButton* cb = new Gui::ColorButton(parent); cb->setDisabled(isReadOnly()); QObject::connect(cb, SIGNAL(changed()), receiver, method); return cb; } void PropertyMaterialItem::setEditorData(QWidget *editor, const QVariant& data) const { if (!data.canConvert()) return; Material val = data.value(); Gui::ColorButton *cb = qobject_cast(editor); cb->setColor(val.diffuseColor); } QVariant PropertyMaterialItem::editorData(QWidget *editor) const { Gui::ColorButton *cb = qobject_cast(editor); QVariant value = data(1, Qt::EditRole); if (!value.canConvert()) return QVariant(); Material val = value.value(); val.diffuseColor = cb->color(); return QVariant::fromValue(val); } // -------------------------------------------------------------------- PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyMaterialListItem) PropertyMaterialListItem::PropertyMaterialListItem() { // This editor gets a list of materials but it only edits the first item. diffuse = static_cast(PropertyColorItem::create()); diffuse->setParent(this); diffuse->setPropertyName(QLatin1String("DiffuseColor")); this->appendChild(diffuse); ambient = static_cast(PropertyColorItem::create()); ambient->setParent(this); ambient->setPropertyName(QLatin1String("AmbientColor")); this->appendChild(ambient); specular = static_cast(PropertyColorItem::create()); specular->setParent(this); specular->setPropertyName(QLatin1String("SpecularColor")); this->appendChild(specular); emissive = static_cast(PropertyColorItem::create()); emissive->setParent(this); emissive->setPropertyName(QLatin1String("EmissiveColor")); this->appendChild(emissive); shininess = static_cast(PropertyFloatItem::create()); shininess->setParent(this); shininess->setPropertyName(QLatin1String("Shininess")); this->appendChild(shininess); transparency = static_cast(PropertyFloatItem::create()); transparency->setParent(this); transparency->setPropertyName(QLatin1String("Transparency")); this->appendChild(transparency); } PropertyMaterialListItem::~PropertyMaterialListItem() { } void PropertyMaterialListItem::propertyBound() { } QColor PropertyMaterialListItem::getDiffuseColor() const { QVariant value = data(1, Qt::EditRole); if (!value.canConvert()) return QColor(); QVariantList list = value.toList(); if (list.isEmpty()) return QColor(); if (!list[0].canConvert()) return QColor(); Material mat = list[0].value(); return mat.diffuseColor; } void PropertyMaterialListItem::setDiffuseColor(const QColor& color) { QVariant value = data(1, Qt::EditRole); if (!value.canConvert()) return; QVariantList list = value.toList(); if (list.isEmpty()) return; if (!list[0].canConvert()) return; Material mat = list[0].value(); mat.diffuseColor = color; list[0] = QVariant::fromValue(mat); setValue(list); } QColor PropertyMaterialListItem::getAmbientColor() const { QVariant value = data(1, Qt::EditRole); if (!value.canConvert()) return QColor(); QVariantList list = value.toList(); if (list.isEmpty()) return QColor(); if (!list[0].canConvert()) return QColor(); Material mat = list[0].value(); return mat.ambientColor; } void PropertyMaterialListItem::setAmbientColor(const QColor& color) { QVariant value = data(1, Qt::EditRole); if (!value.canConvert()) return; QVariantList list = value.toList(); if (list.isEmpty()) return; if (!list[0].canConvert()) return; Material mat = list[0].value(); mat.ambientColor = color; list[0] = QVariant::fromValue(mat); setValue(list); } QColor PropertyMaterialListItem::getSpecularColor() const { QVariant value = data(1, Qt::EditRole); if (!value.canConvert()) return QColor(); QVariantList list = value.toList(); if (list.isEmpty()) return QColor(); if (!list[0].canConvert()) return QColor(); Material mat = list[0].value(); return mat.specularColor; } void PropertyMaterialListItem::setSpecularColor(const QColor& color) { QVariant value = data(1, Qt::EditRole); if (!value.canConvert()) return; QVariantList list = value.toList(); if (list.isEmpty()) return; if (!list[0].canConvert()) return; Material mat = list[0].value(); mat.specularColor = color; list[0] = QVariant::fromValue(mat); setValue(list); } QColor PropertyMaterialListItem::getEmissiveColor() const { QVariant value = data(1, Qt::EditRole); if (!value.canConvert()) return QColor(); QVariantList list = value.toList(); if (list.isEmpty()) return QColor(); if (!list[0].canConvert()) return QColor(); Material mat = list[0].value(); return mat.emissiveColor; } void PropertyMaterialListItem::setEmissiveColor(const QColor& color) { QVariant value = data(1, Qt::EditRole); if (!value.canConvert()) return; QVariantList list = value.toList(); if (list.isEmpty()) return; if (!list[0].canConvert()) return; Material mat = list[0].value(); mat.emissiveColor = color; list[0] = QVariant::fromValue(mat); setValue(list); } float PropertyMaterialListItem::getShininess() const { QVariant value = data(1, Qt::EditRole); if (!value.canConvert()) return 0; QVariantList list = value.toList(); if (list.isEmpty()) return 0; if (!list[0].canConvert()) return 0; Material mat = list[0].value(); return mat.shininess; } void PropertyMaterialListItem::setShininess(float s) { QVariant value = data(1, Qt::EditRole); if (!value.canConvert()) return; QVariantList list = value.toList(); if (list.isEmpty()) return; if (!list[0].canConvert()) return; Material mat = list[0].value(); mat.shininess = s; list[0] = QVariant::fromValue(mat); setValue(list); } float PropertyMaterialListItem::getTransparency() const { QVariant value = data(1, Qt::EditRole); if (!value.canConvert()) return 0; QVariantList list = value.toList(); if (list.isEmpty()) return 0; if (!list[0].canConvert()) return 0; Material mat = list[0].value(); return mat.transparency; } void PropertyMaterialListItem::setTransparency(float t) { QVariant value = data(1, Qt::EditRole); if (!value.canConvert()) return; QVariantList list = value.toList(); if (list.isEmpty()) return; if (!list[0].canConvert()) return; Material mat = list[0].value(); mat.transparency = t; list[0] = QVariant::fromValue(mat); setValue(list); } QVariant PropertyMaterialListItem::decoration(const QVariant& value) const { if (!value.canConvert()) return QVariant(); QVariantList list = value.toList(); if (list.isEmpty()) return QVariant(); if (!list[0].canConvert()) return QVariant(); // use the diffuse color Material mat = list[0].value(); QColor color = mat.diffuseColor; int size = QApplication::style()->pixelMetric(QStyle::PM_ListViewIconSize); QPixmap p(size, size); p.fill(color); return QVariant(p); } QVariant PropertyMaterialListItem::toString(const QVariant& prop) const { if (!prop.canConvert()) return QVariant(); QVariantList list = prop.toList(); if (list.isEmpty()) return QVariant(); if (!list[0].canConvert()) return QVariant(); // use the diffuse color Material mat = list[0].value(); QColor value = mat.diffuseColor; QString color = QString::fromLatin1("[%1, %2, %3]") .arg(value.red()).arg(value.green()).arg(value.blue()); return QVariant(color); } QVariant PropertyMaterialListItem::toolTip(const App::Property* prop) const { assert(prop && prop->getTypeId().isDerivedFrom(App::PropertyMaterialList::getClassTypeId())); const std::vector& values = static_cast(prop)->getValues(); if (values.empty()) return QVariant(); App::Material value = values.front(); QColor dc = value.diffuseColor.asValue(); QColor ac = value.ambientColor.asValue(); QColor sc = value.specularColor.asValue(); QColor ec = value.emissiveColor.asValue(); QString data = QString::fromUtf8( "Diffuse color: [%1, %2, %3]\n" "Ambient color: [%4, %5, %6]\n" "Specular color: [%7, %8, %9]\n" "Emissive color: [%10, %11, %12]\n" "Shininess: %13\n" "Transparency: %14" ) .arg(dc.red()).arg(dc.green()).arg(dc.blue()) .arg(ac.red()).arg(ac.green()).arg(ac.blue()) .arg(sc.red()).arg(sc.green()).arg(sc.blue()) .arg(ec.red()).arg(ec.green()).arg(ec.blue()) .arg(value.shininess) .arg(value.transparency) ; return QVariant(data); } QVariant PropertyMaterialListItem::value(const App::Property* prop) const { assert(prop && prop->getTypeId().isDerivedFrom(App::PropertyMaterialList::getClassTypeId())); const std::vector& value = static_cast(prop)->getValues(); QVariantList variantList; for (std::vector::const_iterator it = value.begin(); it != value.end(); ++it) { Material mat; mat.diffuseColor = it->diffuseColor.asValue(); mat.ambientColor = it->ambientColor.asValue(); mat.specularColor = it->specularColor.asValue(); mat.emissiveColor = it->emissiveColor.asValue(); mat.shininess = it->shininess; mat.transparency = it->transparency; variantList << QVariant::fromValue(mat); } return variantList; } void PropertyMaterialListItem::setValue(const QVariant& value) { if (!value.canConvert()) return; QVariantList list = value.toList(); if (list.isEmpty()) return; QString data; QTextStream str(&data); str << "("; for (QVariantList::iterator it = list.begin(); it != list.end(); ++it) { Material mat = it->value(); App::Color dc; dc.setValue(mat.diffuseColor); App::Color ac; ac.setValue(mat.ambientColor); App::Color sc; sc.setValue(mat.specularColor); App::Color ec; ec.setValue(mat.emissiveColor); float s = mat.shininess; float t = mat.transparency; QString item = QString::fromLatin1( "App.Material(" "DiffuseColor=(%1,%2,%3)," "AmbientColor=(%4,%5,%6)," "SpecularColor=(%7,%8,%9)," "EmissiveColor=(%10,%11,%12)," "Shininess=(%13)," "Transparency=(%14)," ")" ) .arg(dc.r, 0, 'f', decimals()) .arg(dc.g, 0, 'f', decimals()) .arg(dc.b, 0, 'f', decimals()) .arg(ac.r, 0, 'f', decimals()) .arg(ac.g, 0, 'f', decimals()) .arg(ac.b, 0, 'f', decimals()) .arg(sc.r, 0, 'f', decimals()) .arg(sc.g, 0, 'f', decimals()) .arg(sc.b, 0, 'f', decimals()) .arg(ec.r, 0, 'f', decimals()) .arg(ec.g, 0, 'f', decimals()) .arg(ec.b, 0, 'f', decimals()) .arg(s, 0, 'f', decimals()) .arg(t, 0, 'f', decimals()) ; str << item << ", "; } str << ")"; setPropertyValue(data); } QWidget* PropertyMaterialListItem::createEditor(QWidget* parent, const QObject* receiver, const char* method) const { Gui::ColorButton* cb = new Gui::ColorButton(parent); cb->setDisabled(isReadOnly()); QObject::connect(cb, SIGNAL(changed()), receiver, method); return cb; } void PropertyMaterialListItem::setEditorData(QWidget *editor, const QVariant& data) const { if (!data.canConvert()) return; QVariantList list = data.toList(); if (list.isEmpty()) return; if (!list[0].canConvert()) return; // use the diffuse color Material mat = list[0].value(); QColor color = mat.diffuseColor; Gui::ColorButton *cb = qobject_cast(editor); cb->setColor(color); } QVariant PropertyMaterialListItem::editorData(QWidget *editor) const { Gui::ColorButton *cb = qobject_cast(editor); QVariant value = data(1, Qt::EditRole); if (!value.canConvert()) return QVariant(); QVariantList list = value.toList(); if (list.isEmpty()) return QVariant(); if (!list[0].canConvert()) return QVariant(); // use the diffuse color Material mat = list[0].value(); mat.diffuseColor = cb->color(); list[0] = QVariant::fromValue(mat); return list; } // -------------------------------------------------------------------- PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyFileItem) PropertyFileItem::PropertyFileItem() { } QVariant PropertyFileItem::value(const App::Property* prop) const { assert(prop && prop->getTypeId().isDerivedFrom(App::PropertyFile::getClassTypeId())); std::string value = static_cast(prop)->getValue(); return QVariant(QString::fromUtf8(value.c_str())); } void PropertyFileItem::setValue(const QVariant& value) { if (!value.canConvert(QVariant::String)) return; QString val = value.toString(); QString data = QString::fromLatin1("\"%1\"").arg(val); setPropertyValue(data); } QVariant PropertyFileItem::toolTip(const App::Property* prop) const { return value(prop); } QWidget* PropertyFileItem::createEditor(QWidget* parent, const QObject* receiver, const char* method) const { Gui::FileChooser *fc = new Gui::FileChooser(parent); fc->setAutoFillBackground(true); fc->setDisabled(isReadOnly()); QObject::connect(fc, SIGNAL(fileNameSelected(const QString&)), receiver, method); return fc; } void PropertyFileItem::setEditorData(QWidget *editor, const QVariant& data) const { Gui::FileChooser *fc = qobject_cast(editor); fc->setFileName(data.toString()); } QVariant PropertyFileItem::editorData(QWidget *editor) const { Gui::FileChooser *fc = qobject_cast(editor); return QVariant(fc->fileName()); } // -------------------------------------------------------------------- PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyPathItem) PropertyPathItem::PropertyPathItem() { } QVariant PropertyPathItem::value(const App::Property* prop) const { assert(prop && prop->getTypeId().isDerivedFrom(App::PropertyPath::getClassTypeId())); std::string value = static_cast(prop)->getValue().string(); return QVariant(QString::fromUtf8(value.c_str())); } void PropertyPathItem::setValue(const QVariant& value) { if (!value.canConvert(QVariant::String)) return; QString val = value.toString(); QString data = QString::fromLatin1("\"%1\"").arg(val); setPropertyValue(data); } QVariant PropertyPathItem::toolTip(const App::Property* prop) const { return value(prop); } QWidget* PropertyPathItem::createEditor(QWidget* parent, const QObject* receiver, const char* method) const { Gui::FileChooser *fc = new Gui::FileChooser(parent); fc->setMode(FileChooser::Directory); fc->setAutoFillBackground(true); fc->setDisabled(isReadOnly()); QObject::connect(fc, SIGNAL(fileNameSelected(const QString&)), receiver, method); return fc; } void PropertyPathItem::setEditorData(QWidget *editor, const QVariant& data) const { Gui::FileChooser *fc = qobject_cast(editor); fc->setFileName(data.toString()); } QVariant PropertyPathItem::editorData(QWidget *editor) const { Gui::FileChooser *fc = qobject_cast(editor); return QVariant(fc->fileName()); } // -------------------------------------------------------------------- PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyTransientFileItem) PropertyTransientFileItem::PropertyTransientFileItem() { } QVariant PropertyTransientFileItem::value(const App::Property* prop) const { assert(prop && prop->getTypeId().isDerivedFrom(App::PropertyFileIncluded::getClassTypeId())); std::string value = static_cast(prop)->getValue(); return QVariant(QString::fromUtf8(value.c_str())); } void PropertyTransientFileItem::setValue(const QVariant& value) { if (!value.canConvert(QVariant::String)) return; QString val = value.toString(); QString data = QString::fromLatin1("\"%1\"").arg(val); setPropertyValue(data); } QVariant PropertyTransientFileItem::toolTip(const App::Property* prop) const { return value(prop); } QWidget* PropertyTransientFileItem::createEditor(QWidget* parent, const QObject* receiver, const char* method) const { Gui::FileChooser *fc = new Gui::FileChooser(parent); fc->setAutoFillBackground(true); fc->setDisabled(isReadOnly()); QObject::connect(fc, SIGNAL(fileNameSelected(const QString&)), receiver, method); return fc; } void PropertyTransientFileItem::setEditorData(QWidget *editor, const QVariant& data) const { Gui::FileChooser *fc = qobject_cast(editor); fc->setFileName(data.toString()); } QVariant PropertyTransientFileItem::editorData(QWidget *editor) const { Gui::FileChooser *fc = qobject_cast(editor); return QVariant(fc->fileName()); } // --------------------------------------------------------------- LinkSelection::LinkSelection(const QStringList& list) : link(list) { } LinkSelection::~LinkSelection() { } void LinkSelection::select() { Gui::Selection().clearSelection(); Gui::Selection().addSelection((const char*)link[0].toLatin1(), (const char*)link[1].toLatin1()); this->deleteLater(); } // --------------------------------------------------------------- LinkLabel::LinkLabel (QWidget * parent) : QWidget(parent) { QHBoxLayout *layout = new QHBoxLayout(this); layout->setMargin(0); layout->setSpacing(1); label = new QLabel(this); label->setAutoFillBackground(true); label->setTextFormat(Qt::RichText); layout->addWidget(label); editButton = new QPushButton(QLatin1String("..."), this); #if defined (Q_OS_MAC) editButton->setAttribute(Qt::WA_LayoutUsesWidgetRect); // layout size from QMacStyle was not correct #endif editButton->setToolTip(tr("Change the linked object")); layout->addWidget(editButton); // setLayout(layout); connect(label, SIGNAL(linkActivated(const QString&)), this, SLOT(onLinkActivated(const QString&))); connect(editButton, SIGNAL(clicked()), this, SLOT(onEditClicked())); } LinkLabel::~LinkLabel() { } void LinkLabel::setPropertyLink(const QStringList& o) { link = o; QString linkcolor = QApplication::palette().color(QPalette::Link).name(); QString text = QString::fromLatin1( "" "

" "%4" "

" ) .arg(link[0]) .arg(link[1]) .arg(linkcolor) .arg(link[2]); label->setText(text); } QStringList LinkLabel::propertyLink() const { return link; } void LinkLabel::onLinkActivated (const QString& s) { Q_UNUSED(s); LinkSelection* select = new LinkSelection(link); QTimer::singleShot(50, select, SLOT(select())); } void LinkLabel::onEditClicked () { Gui::Dialog::DlgPropertyLink dlg(link, this); if (dlg.exec() == QDialog::Accepted) { setPropertyLink(dlg.propertyLink()); /*emit*/ linkChanged(link); } } void LinkLabel::resizeEvent(QResizeEvent* e) { editButton->setFixedWidth(e->size().height()); editButton->setFixedHeight(e->size().height()); } PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyLinkItem) PropertyLinkItem::PropertyLinkItem() { } QVariant PropertyLinkItem::toString(const QVariant& prop) const { QStringList list = prop.toStringList(); return QVariant(list[2]); } QVariant PropertyLinkItem::value(const App::Property* prop) const { assert(prop && prop->getTypeId().isDerivedFrom(App::PropertyLink::getClassTypeId())); const App::PropertyLink* prop_link = static_cast(prop); App::PropertyContainer* c = prop_link->getContainer(); // the list has five elements: // [document name, internal name, label, internal name of container, property name] App::DocumentObject* obj = prop_link->getValue(); QStringList list; if (obj) { list << QString::fromLatin1(obj->getDocument()->getName()); list << QString::fromLatin1(obj->getNameInDocument()); list << QString::fromUtf8(obj->Label.getValue()); } else { // no object assigned // the document name if (c->getTypeId().isDerivedFrom(App::DocumentObject::getClassTypeId())) { App::DocumentObject* obj = static_cast(c); list << QString::fromLatin1(obj->getDocument()->getName()); } else { list << QString::fromLatin1(""); } // the internal object name list << QString::fromLatin1("Null"); // the object label list << QString::fromLatin1(""); } // the name of this object if (c->getTypeId().isDerivedFrom(App::DocumentObject::getClassTypeId())) { App::DocumentObject* obj = static_cast(c); list << QString::fromLatin1(obj->getNameInDocument()); } else { list << QString::fromLatin1("Null"); } list << QString::fromLatin1(prop->getName()); return QVariant(list); } void PropertyLinkItem::setValue(const QVariant& value) { if (!value.canConvert(QVariant::StringList)) return; QStringList items = value.toStringList(); if (items.size() > 1) { QString d = items[0]; QString o = items[1]; QString data; if ( o.isEmpty() ) data = QString::fromLatin1("None"); else data = QString::fromLatin1("App.getDocument('%1').getObject('%2')").arg(d).arg(o); setPropertyValue(data); } } QWidget* PropertyLinkItem::createEditor(QWidget* parent, const QObject* receiver, const char* method) const { LinkLabel *ll = new LinkLabel(parent); ll->setAutoFillBackground(true); ll->setDisabled(isReadOnly()); QObject::connect(ll, SIGNAL(linkChanged(const QStringList&)), receiver, method); return ll; } void PropertyLinkItem::setEditorData(QWidget *editor, const QVariant& data) const { QStringList list = data.toStringList(); LinkLabel *ll = static_cast(editor); ll->setPropertyLink(list); } QVariant PropertyLinkItem::editorData(QWidget *editor) const { LinkLabel *ll = static_cast(editor); return QVariant(ll->propertyLink()); } // -------------------------------------------------------------------- LinkListLabel::LinkListLabel (QWidget * parent) : QWidget(parent) { QHBoxLayout *layout = new QHBoxLayout(this); layout->setMargin(0); layout->setSpacing(1); label = new QLabel(this); label->setAutoFillBackground(true); layout->addWidget(label); editButton = new QPushButton(QLatin1String("..."), this); editButton->setToolTip(tr("Change the linked objects")); layout->addWidget(editButton); // setLayout(layout); connect(editButton, SIGNAL(clicked()), this, SLOT(onEditClicked())); } LinkListLabel::~LinkListLabel() { } void LinkListLabel::setPropertyLinkList(const QVariantList& o) { links = o; if (links.isEmpty()) { label->clear(); } else if (links.size() == 1) { QStringList s = links.front().toStringList(); label->setText(s[2]); } else { QStringList obj; for (QVariantList::iterator it = links.begin(); it != links.end(); ++it) obj << it->toStringList()[2]; label->setText(QString::fromLatin1("[%1]").arg(obj.join(QString::fromLatin1(", ")))); } } QVariantList LinkListLabel::propertyLinkList() const { return links; } void LinkListLabel::onEditClicked () { QStringList list = links.front().toStringList(); Gui::Dialog::DlgPropertyLink dlg(list, this); dlg.setSelectionMode(QAbstractItemView::ExtendedSelection); if (dlg.exec() == QDialog::Accepted) { setPropertyLinkList(dlg.propertyLinkList()); Q_EMIT linkChanged(links); } } void LinkListLabel::resizeEvent(QResizeEvent* e) { editButton->setFixedWidth(e->size().height()); } PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyLinkListItem) PropertyLinkListItem::PropertyLinkListItem() { } QVariant PropertyLinkListItem::toString(const QVariant& prop) const { QVariantList list = prop.toList(); if (list.empty()) { return QString(); } else if (list.size() == 1) { QStringList item = list.front().toStringList(); return QString::fromLatin1("%1").arg(item[2]); } else { QStringList obj; for (QVariantList::iterator it = list.begin(); it != list.end(); ++it) obj << it->toStringList()[2]; return QString::fromLatin1("[%1]").arg(obj.join(QString::fromLatin1(", "))); } } QVariant PropertyLinkListItem::value(const App::Property* prop) const { assert(prop && prop->getTypeId().isDerivedFrom(App::PropertyLinkList::getClassTypeId())); const App::PropertyLinkList* prop_link = static_cast(prop); App::PropertyContainer* c = prop_link->getContainer(); // the name of this object QString objName; if (c->getTypeId().isDerivedFrom(App::DocumentObject::getClassTypeId())) { App::DocumentObject* obj = static_cast(c); objName = QString::fromLatin1(obj->getNameInDocument()); } else { objName = QString::fromLatin1("Null"); } // each item is a list of five elements: //[document name, internal name, label, internal name of container, property name] // the variant list contains at least one item std::vector obj = prop_link->getValues(); QVariantList varList; if (!obj.empty()) { for (std::vector::iterator it = obj.begin(); it != obj.end(); ++it) { QStringList list; list << QString::fromLatin1((*it)->getDocument()->getName()); list << QString::fromLatin1((*it)->getNameInDocument()); list << QString::fromUtf8((*it)->Label.getValue()); list << objName; list << QString::fromLatin1(prop->getName()); varList << list; } } else { QStringList list; // no object assigned // the document name if (c->getTypeId().isDerivedFrom(App::DocumentObject::getClassTypeId())) { App::DocumentObject* obj = static_cast(c); list << QString::fromLatin1(obj->getDocument()->getName()); } else { list << QString::fromLatin1(""); } // the internal object name list << QString::fromLatin1("Null"); // the object label list << QString::fromLatin1(""); list << objName; list << QString::fromLatin1(prop->getName()); varList << list; } return QVariant(varList); } void PropertyLinkListItem::setValue(const QVariant& value) { if (!value.canConvert(QVariant::List)) return; QVariantList items = value.toList(); QStringList data; for (QVariantList::iterator it = items.begin(); it != items.end(); ++it) { QStringList list = it->toStringList(); QString d = list[0]; QString o = list[1]; if (!o.isEmpty()) data << QString::fromLatin1("App.getDocument('%1').getObject('%2')").arg(d).arg(o); } setPropertyValue(QString::fromLatin1("[%1]").arg(data.join(QString::fromLatin1(", ")))); } QWidget* PropertyLinkListItem::createEditor(QWidget* parent, const QObject* receiver, const char* method) const { LinkListLabel *ll = new LinkListLabel(parent); ll->setAutoFillBackground(true); ll->setDisabled(isReadOnly()); QObject::connect(ll, SIGNAL(linkChanged(const QVariantList&)), receiver, method); return ll; } void PropertyLinkListItem::setEditorData(QWidget *editor, const QVariant& data) const { QVariantList list = data.toList(); LinkListLabel *ll = static_cast(editor); ll->setPropertyLinkList(list); } QVariant PropertyLinkListItem::editorData(QWidget *editor) const { LinkListLabel *ll = static_cast(editor); return QVariant(ll->propertyLinkList()); } // -------------------------------------------------------------------- PropertyItemEditorFactory::PropertyItemEditorFactory() { } PropertyItemEditorFactory::~PropertyItemEditorFactory() { } #if (QT_VERSION >= 0x050300) QWidget * PropertyItemEditorFactory::createEditor (int /*type*/, QWidget * /*parent*/) const { // do not allow to create any editor widgets because we do that in subclasses of PropertyItem return 0; } QByteArray PropertyItemEditorFactory::valuePropertyName (int /*type*/) const { // do not allow to set properties because we do that in subclasses of PropertyItem return ""; } #else QWidget * PropertyItemEditorFactory::createEditor (QVariant::Type /*type*/, QWidget * /*parent*/) const { // do not allow to create any editor widgets because we do that in subclasses of PropertyItem return 0; } QByteArray PropertyItemEditorFactory::valuePropertyName (QVariant::Type /*type*/) const { // do not allow to set properties because we do that in subclasses of PropertyItem return ""; } #endif #include "moc_PropertyItem.cpp"