Expressions: Integrate into the property editor

- basic infrastructure for handling of expressions
- port the unit properties editor to support expressions
- port placement editor to support expressions
- expressions for double spinbox
- expressions in sketch constraints
This commit is contained in:
Stefan Tröger
2015-10-06 08:45:15 +02:00
committed by wmayer
parent f037bf9f52
commit 96a586d04a
11 changed files with 467 additions and 62 deletions

View File

@@ -36,6 +36,7 @@
#endif
#include <Base/Tools.h>
#include <Base/Console.h>
#include <App/Application.h>
#include <App/Document.h>
#include <App/DocumentObject.h>
@@ -53,12 +54,13 @@
#include <Gui/QuantitySpinBox.h>
#include "PropertyItem.h"
#include <SpinBox.h>
using namespace Gui::PropertyEditor;
TYPESYSTEM_SOURCE(Gui::PropertyEditor::PropertyItem, Base::BaseClass);
PropertyItem::PropertyItem() : parentItem(0), readonly(false)
PropertyItem::PropertyItem() : parentItem(0), readonly(false), cleared(false)
{
precision = Base::UnitsApi::getDecimals();
}
@@ -80,6 +82,26 @@ void PropertyItem::reset()
void PropertyItem::setPropertyData(const std::vector<App::Property*>& items)
{
//if we have a single property we can bind it for expression handling
if(items.size() == 1) {
const App::Property& p = *items.front();
if(!(p.getContainer()->getPropertyType(&p) & App::Prop_ReadOnly)) {
App::ObjectIdentifier id(p);
std::vector<App::ObjectIdentifier> 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);
}
else
setReadOnly(true);
}
propertyItems = items;
updateData();
this->initialize();
@@ -346,15 +368,24 @@ QVariant PropertyItem::data(int column, int role) const
bool PropertyItem::setData (const QVariant& value)
{
//check if we have an expression set. If so we do nothing, as than the editor is responsible
//for issuing the relevant python code
if(hasExpression())
return true;
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 {
@@ -363,6 +394,7 @@ bool PropertyItem::setData (const QVariant& value)
}
}
Qt::ItemFlags PropertyItem::flags(int column) const
{
Qt::ItemFlags basicFlags = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
@@ -380,6 +412,17 @@ int PropertyItem::row() const
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();
}
// --------------------------------------------------------------------
TYPESYSTEM_SOURCE(Gui::PropertyEditor::PropertyStringItem, Gui::PropertyEditor::PropertyItem);
@@ -409,6 +452,7 @@ QWidget* PropertyStringItem::createEditor(QWidget* parent, const QObject* receiv
{
QLineEdit *le = new QLineEdit(parent);
le->setFrame(false);
le->setReadOnly(isReadOnly());
QObject::connect(le, SIGNAL(textChanged(const QString&)), receiver, method);
return le;
}
@@ -454,6 +498,7 @@ QWidget* PropertyFontItem::createEditor(QWidget* parent, const QObject* receiver
{
QComboBox *cb = new QComboBox(parent);
cb->setFrame(false);
cb->setDisabled(isReadOnly());
QObject::connect(cb, SIGNAL(activated(const QString&)), receiver, method);
return cb;
}
@@ -512,6 +557,7 @@ QWidget* PropertyIntegerItem::createEditor(QWidget* parent, const QObject* recei
{
QSpinBox *sb = new QSpinBox(parent);
sb->setFrame(false);
sb->setReadOnly(isReadOnly());
QObject::connect(sb, SIGNAL(valueChanged(int)), receiver, method);
return sb;
}
@@ -558,6 +604,7 @@ QWidget* PropertyIntegerConstraintItem::createEditor(QWidget* parent, const QObj
{
QSpinBox *sb = new QSpinBox(parent);
sb->setFrame(false);
sb->setReadOnly(isReadOnly());
QObject::connect(sb, SIGNAL(valueChanged(int)), receiver, method);
return sb;
}
@@ -599,6 +646,10 @@ QVariant PropertyFloatItem::toString(const QVariant& prop) const
{
double value = prop.toDouble();
QString data = QLocale::system().toString(value, 'f', decimals());
if(hasExpression())
data += QString::fromAscii(" ( %1 )").arg(QString::fromStdString(getExpressionString()));
return QVariant(data);
}
@@ -621,10 +672,18 @@ void PropertyFloatItem::setValue(const QVariant& value)
QWidget* PropertyFloatItem::createEditor(QWidget* parent, const QObject* receiver, const char* method) const
{
QDoubleSpinBox *sb = new QDoubleSpinBox(parent);
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(true);
}
return sb;
}
@@ -653,7 +712,11 @@ PropertyUnitItem::PropertyUnitItem()
QVariant PropertyUnitItem::toString(const QVariant& prop) const
{
const Base::Quantity& unit = prop.value<Base::Quantity>();
return QVariant(unit.getUserString());
QString string = unit.getUserString();
if(hasExpression())
string += QString::fromAscii(" ( %1 )").arg(QString::fromStdString(getExpressionString()));
return QVariant(string);
}
QVariant PropertyUnitItem::value(const App::Property* prop) const
@@ -679,6 +742,14 @@ QWidget* PropertyUnitItem::createEditor(QWidget* parent, const QObject* receiver
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(true);
}
QObject::connect(infield, SIGNAL(valueChanged(double)), receiver, method);
return infield;
}
@@ -767,10 +838,17 @@ void PropertyFloatConstraintItem::setValue(const QVariant& value)
QWidget* PropertyFloatConstraintItem::createEditor(QWidget* parent, const QObject* receiver, const char* method) const
{
QDoubleSpinBox *sb = new QDoubleSpinBox(parent);
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(true);
}
return sb;
}
@@ -873,6 +951,7 @@ QWidget* PropertyBoolItem::createEditor(QWidget* parent, const QObject* receiver
cb->setFrame(false);
cb->addItem(QLatin1String("false"));
cb->addItem(QLatin1String("true"));
cb->setDisabled(isReadOnly());
QObject::connect(cb, SIGNAL(activated(int)), receiver, method);
return cb;
}
@@ -994,6 +1073,13 @@ void PropertyVectorItem::setZ(double z)
setData(QVariant::fromValue(Base::Vector3d(x(), y(), z)));
}
void PropertyVectorItem::propertyBound() {
m_x->bind(App::ObjectIdentifier(getPath())<<App::ObjectIdentifier::String("x"));
m_y->bind(App::ObjectIdentifier(getPath())<<App::ObjectIdentifier::String("y"));
m_z->bind(App::ObjectIdentifier(getPath())<<App::ObjectIdentifier::String("z"));
}
// ---------------------------------------------------------------
@@ -1100,6 +1186,15 @@ 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())<<App::ObjectIdentifier::String("x"));
m_y->bind(App::ObjectIdentifier(getPath())<<App::ObjectIdentifier::String("y"));
m_z->bind(App::ObjectIdentifier(getPath())<<App::ObjectIdentifier::String("z"));
};
}
// ---------------------------------------------------------------
@@ -1708,9 +1803,10 @@ void PropertyPlacementItem::setValue(const QVariant& value)
}
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;
}
@@ -1726,6 +1822,20 @@ QVariant PropertyPlacementItem::editorData(QWidget *editor) const
return pe->value();
}
void PropertyPlacementItem::propertyBound() {
if(isBound()) {
m_a->bind(App::ObjectIdentifier(getPath())<<App::ObjectIdentifier::String("Rotation")
<<App::ObjectIdentifier::String("Angle"));
m_d->bind(App::ObjectIdentifier(getPath())<<App::ObjectIdentifier::String("Rotation")
<<App::ObjectIdentifier::String("Axis"));
m_p->bind(App::ObjectIdentifier(getPath())<<App::ObjectIdentifier::String("Base"));
}
}
// ---------------------------------------------------------------
TYPESYSTEM_SOURCE(Gui::PropertyEditor::PropertyEnumItem, Gui::PropertyEditor::PropertyItem);
@@ -1763,6 +1873,7 @@ QWidget* PropertyEnumItem::createEditor(QWidget* parent, const QObject* receiver
{
QComboBox *cb = new QComboBox(parent);
cb->setFrame(false);
cb->setDisabled(isReadOnly());
QObject::connect(cb, SIGNAL(activated(int)), receiver, method);
return cb;
}
@@ -1822,6 +1933,7 @@ QWidget* PropertyStringListItem::createEditor(QWidget* parent, const QObject* re
{
Gui::LabelEditor* le = new Gui::LabelEditor(parent);
le->setAutoFillBackground(true);
le->setDisabled(isReadOnly());
QObject::connect(le, SIGNAL(textChanged(const QString&)), receiver, method);
return le;
}
@@ -1890,6 +2002,7 @@ QWidget* PropertyFloatListItem::createEditor(QWidget* parent, const QObject* rec
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;
}
@@ -1958,6 +2071,7 @@ QWidget* PropertyIntegerListItem::createEditor(QWidget* parent, const QObject* r
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;
}
@@ -2068,6 +2182,7 @@ void PropertyColorItem::setValue(const QVariant& value)
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;
}
@@ -2121,6 +2236,7 @@ QWidget* PropertyFileItem::createEditor(QWidget* parent, const QObject* receiver
{
Gui::FileChooser *fc = new Gui::FileChooser(parent);
fc->setAutoFillBackground(true);
fc->setDisabled(isReadOnly());
QObject::connect(fc, SIGNAL(fileNameSelected(const QString&)), receiver, method);
return fc;
}
@@ -2172,6 +2288,7 @@ QWidget* PropertyPathItem::createEditor(QWidget* parent, const QObject* receiver
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;
}
@@ -2222,6 +2339,7 @@ QWidget* PropertyTransientFileItem::createEditor(QWidget* parent, const QObject*
{
Gui::FileChooser *fc = new Gui::FileChooser(parent);
fc->setAutoFillBackground(true);
fc->setDisabled(isReadOnly());
QObject::connect(fc, SIGNAL(fileNameSelected(const QString&)), receiver, method);
return fc;
}
@@ -2381,6 +2499,7 @@ QWidget* PropertyLinkItem::createEditor(QWidget* parent, const QObject* receiver
{
LinkLabel *ll = new LinkLabel(parent);
ll->setAutoFillBackground(true);
ll->setDisabled(isReadOnly());
QObject::connect(ll, SIGNAL(linkChanged(const QStringList&)), receiver, method);
return ll;
}