Skip to content

Commit

Permalink
Expressions: port int spinbox for property editor
Browse files Browse the repository at this point in the history
  • Loading branch information
ickby authored and wwmayer committed Dec 9, 2015
1 parent 4203a6f commit 580a4e1
Show file tree
Hide file tree
Showing 4 changed files with 240 additions and 6 deletions.
176 changes: 176 additions & 0 deletions src/Gui/SpinBox.cpp
Expand Up @@ -406,6 +406,182 @@ void UIntSpinBox::keyPressEvent(QKeyEvent *event)
}
}


IntSpinBox::IntSpinBox(QWidget* parent) : QSpinBox(parent) {

defaultPalette = lineEdit()->palette();

/* Icon for f(x) */
QFontMetrics fm(lineEdit()->font());
int frameWidth = style()->pixelMetric(QStyle::PM_SpinBoxFrameWidth);
iconHeight = fm.height() - frameWidth;
iconLabel = new ExpressionLabel(lineEdit());
iconLabel->setCursor(Qt::ArrowCursor);
QPixmap pixmap = getIcon(":/icons/bound-expression-unset.svg", QSize(iconHeight, iconHeight));
iconLabel->setPixmap(pixmap);
iconLabel->setStyleSheet(QString::fromAscii("QLabel { border: none; padding: 0px; padding-top: %2px; width: %1px; height: %1px }").arg(iconHeight).arg(frameWidth/2));
iconLabel->hide();
lineEdit()->setStyleSheet(QString::fromAscii("QLineEdit { padding-right: %1px } ").arg(iconHeight+frameWidth));

QObject::connect(iconLabel, SIGNAL(clicked()), this, SLOT(openFormulaDialog()));
}

IntSpinBox::~IntSpinBox() {

}


bool IntSpinBox::apply(const std::string& propName) {

if (!ExpressionBinding::apply(propName)) {
Gui::Command::doCommand(Gui::Command::Doc, "%s = %u", propName.c_str(), value());
return true;
}
else
return false;
}

void IntSpinBox::bind(const ObjectIdentifier& _path) {

ExpressionBinding::bind(_path);

int frameWidth = style()->pixelMetric(QStyle::PM_SpinBoxFrameWidth);
lineEdit()->setStyleSheet(QString::fromAscii("QLineEdit { padding-right: %1px } ").arg(iconLabel->sizeHint().width() + frameWidth + 1));

iconLabel->show();
}

void IntSpinBox::setExpression(boost::shared_ptr<Expression> expr)
{
Q_ASSERT(isBound());

try {
ExpressionBinding::setExpression(expr);
}
catch (const Base::Exception & e) {
setReadOnly(true);
QPalette p(lineEdit()->palette());
p.setColor(QPalette::Active, QPalette::Text, Qt::red);
lineEdit()->setPalette(p);
iconLabel->setToolTip(QString::fromAscii(e.what()));
}
}

void IntSpinBox::onChange() {

if (getExpression()) {
std::auto_ptr<Expression> result(getExpression()->eval());
NumberExpression * value = freecad_dynamic_cast<NumberExpression>(result.get());

if (value) {
setValue(boost::math::round(value->getValue()));
setReadOnly(true);
iconLabel->setPixmap(getIcon(":/icons/bound-expression.svg", QSize(iconHeight, iconHeight)));

QPalette p(lineEdit()->palette());
p.setColor(QPalette::Text, Qt::lightGray);
lineEdit()->setPalette(p);
}
setToolTip(Base::Tools::fromStdString(getExpression()->toString()));
}
else {
setReadOnly(false);
iconLabel->setPixmap(getIcon(":/icons/bound-expression-unset.svg", QSize(iconHeight, iconHeight)));
QPalette p(lineEdit()->palette());
p.setColor(QPalette::Active, QPalette::Text, defaultPalette.color(QPalette::Text));
lineEdit()->setPalette(p);

}
iconLabel->setToolTip(QString());
}

void IntSpinBox::resizeEvent(QResizeEvent * event)
{
QAbstractSpinBox::resizeEvent(event);

int frameWidth = style()->pixelMetric(QStyle::PM_SpinBoxFrameWidth);

QSize sz = iconLabel->sizeHint();
iconLabel->move(lineEdit()->rect().right() - frameWidth - sz.width(), 0);

try {
if (isBound() && getExpression()) {
std::auto_ptr<Expression> result(getExpression()->eval());
NumberExpression * value = freecad_dynamic_cast<NumberExpression>(result.get());

if (value) {
setReadOnly(true);
QPixmap pixmap = getIcon(":/icons/bound-expression.svg", QSize(iconHeight, iconHeight));
iconLabel->setPixmap(pixmap);

QPalette p(lineEdit()->palette());
p.setColor(QPalette::Text, Qt::lightGray);
lineEdit()->setPalette(p);
}
setToolTip(Base::Tools::fromStdString(getExpression()->toString()));
}
else {
setReadOnly(false);
QPixmap pixmap = getIcon(":/icons/bound-expression-unset.svg", QSize(iconHeight, iconHeight));
iconLabel->setPixmap(pixmap);

QPalette p(lineEdit()->palette());
p.setColor(QPalette::Active, QPalette::Text, defaultPalette.color(QPalette::Text));
lineEdit()->setPalette(p);

}
iconLabel->setToolTip(QString());
}
catch (const Base::Exception & e) {
setReadOnly(true);
QPalette p(lineEdit()->palette());
p.setColor(QPalette::Active, QPalette::Text, Qt::red);
lineEdit()->setPalette(p);
iconLabel->setToolTip(QString::fromAscii(e.what()));
}

}

void IntSpinBox::openFormulaDialog()
{
Q_ASSERT(isBound());

Gui::Dialog::DlgExpressionInput* box = new Gui::Dialog::DlgExpressionInput(getPath(), getExpression(), Unit(), this);
connect(box, SIGNAL(finished(int)), this, SLOT(finishFormulaDialog()));
box->show();

QPoint pos = mapToGlobal(QPoint(0,0));
box->move(pos-box->expressionPosition());
box->setExpressionInputSize(width(), height());
}

void IntSpinBox::finishFormulaDialog()
{
Gui::Dialog::DlgExpressionInput* box = qobject_cast<Gui::Dialog::DlgExpressionInput*>(sender());
if (!box) {
qWarning() << "Sender is not a Gui::Dialog::DlgExpressionInput";
return;
}

if (box->result() == QDialog::Accepted)
setExpression(box->getExpression());
else if (box->discardedFormula())
setExpression(boost::shared_ptr<Expression>());

box->deleteLater();
}

void IntSpinBox::keyPressEvent(QKeyEvent *event)
{
if (event->text() == QString::fromUtf8("=") && isBound())
openFormulaDialog();
else {
if (!hasExpression())
QAbstractSpinBox::keyPressEvent(event);
}
}


DoubleSpinBox::DoubleSpinBox(QWidget* parent): QDoubleSpinBox(parent) {

defaultPalette = lineEdit()->palette();
Expand Down
27 changes: 26 additions & 1 deletion src/Gui/SpinBox.h
Expand Up @@ -112,7 +112,32 @@ private Q_SLOTS:
UIntSpinBoxPrivate * d;
};

class DoubleSpinBoxPrivate;

/**
* The IntSpinBox class does exactly the same as Qt's QSpinBox but has expression support
* @author Stefan Tröger
*/
class GuiExport IntSpinBox : public QSpinBox, public ExpressionBinding
{
Q_OBJECT

public:
IntSpinBox ( QWidget* parent=0 );
virtual ~IntSpinBox();

void setExpression(boost::shared_ptr<App::Expression> expr);
void bind(const App::ObjectIdentifier &_path);
bool apply(const std::string &propName);

void keyPressEvent(QKeyEvent *event);
void resizeEvent(QResizeEvent *event);

private Q_SLOTS:
void finishFormulaDialog();
void openFormulaDialog();
virtual void onChange();
};

/**
* The DoubleSpinBox class does exactly the same as Qt's QDoubleSpinBox but has expression
* support
Expand Down
41 changes: 36 additions & 5 deletions src/Gui/propertyeditor/PropertyItem.cpp
Expand Up @@ -30,7 +30,6 @@
# include <QLayout>
# include <QLocale>
# include <QPixmap>
# include <QSpinBox>
# include <QTextStream>
# include <QTimer>
#endif
Expand Down Expand Up @@ -555,10 +554,16 @@ void PropertyIntegerItem::setValue(const QVariant& value)

QWidget* PropertyIntegerItem::createEditor(QWidget* parent, const QObject* receiver, const char* method) const
{
QSpinBox *sb = new QSpinBox(parent);
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(true);
}

return sb;
}

Expand All @@ -575,6 +580,16 @@ QVariant PropertyIntegerItem::editorData(QWidget *editor) const
return QVariant(sb->value());
}

QVariant PropertyIntegerItem::toString(const QVariant& v) const {
QString string(PropertyItem::toString(v).toString());

if(hasExpression())
string += QString::fromAscii(" ( %1 )").arg(QString::fromStdString(getExpressionString()));

return QVariant(string);
}


// --------------------------------------------------------------------

TYPESYSTEM_SOURCE(Gui::PropertyEditor::PropertyIntegerConstraintItem, Gui::PropertyEditor::PropertyItem);
Expand Down Expand Up @@ -602,10 +617,16 @@ void PropertyIntegerConstraintItem::setValue(const QVariant& value)

QWidget* PropertyIntegerConstraintItem::createEditor(QWidget* parent, const QObject* receiver, const char* method) const
{
QSpinBox *sb = new QSpinBox(parent);
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(true);
}

return sb;
}

Expand Down Expand Up @@ -634,6 +655,17 @@ QVariant PropertyIntegerConstraintItem::editorData(QWidget *editor) const
return QVariant(sb->value());
}

QVariant PropertyIntegerConstraintItem::toString(const QVariant& v) const {

QString string(PropertyItem::toString(v).toString());

if(hasExpression())
string += QString::fromAscii(" ( %1 )").arg(QString::fromStdString(getExpressionString()));

return QVariant(string);
}


// --------------------------------------------------------------------

TYPESYSTEM_SOURCE(Gui::PropertyEditor::PropertyFloatItem, Gui::PropertyEditor::PropertyItem);
Expand Down Expand Up @@ -682,8 +714,7 @@ QWidget* PropertyFloatItem::createEditor(QWidget* parent, const QObject* receive
sb->bind(getPath());
sb->setAutoApply(true);
}



return sb;
}

Expand Down
2 changes: 2 additions & 0 deletions src/Gui/propertyeditor/PropertyItem.h
Expand Up @@ -189,6 +189,7 @@ class GuiExport PropertyIntegerItem: public PropertyItem
virtual QVariant editorData(QWidget *editor) const;

protected:
virtual QVariant toString(const QVariant&) const;
virtual QVariant value(const App::Property*) const;
virtual void setValue(const QVariant&);

Expand All @@ -209,6 +210,7 @@ class GuiExport PropertyIntegerConstraintItem: public PropertyItem
virtual QVariant editorData(QWidget *editor) const;

protected:
virtual QVariant toString(const QVariant&) const;
virtual QVariant value(const App::Property*) const;
virtual void setValue(const QVariant&);

Expand Down

0 comments on commit 580a4e1

Please sign in to comment.