diff --git a/src/Gui/DlgExpressionInput.cpp b/src/Gui/DlgExpressionInput.cpp index d8cc47199..b4d9c6f20 100644 --- a/src/Gui/DlgExpressionInput.cpp +++ b/src/Gui/DlgExpressionInput.cpp @@ -23,6 +23,7 @@ #include "PreCompiled.h" #include #include +#include #include "DlgExpressionInput.h" #include "ui_DlgExpressionInput.h" @@ -35,14 +36,16 @@ using namespace App; using namespace Gui::Dialog; -DlgExpressionInput::DlgExpressionInput(const App::ObjectIdentifier & _path, boost::shared_ptr _expression, const Base::Unit & _impliedUnit, QWidget *parent) : - QDialog(parent), - ui(new Ui::DlgExpressionInput), - expression(_expression ? _expression->copy() : 0), - path(_path), - discarded(false), - impliedUnit(_impliedUnit), - minimumWidth(10) +DlgExpressionInput::DlgExpressionInput(const App::ObjectIdentifier & _path, + boost::shared_ptr _expression, + const Base::Unit & _impliedUnit, QWidget *parent) + : QDialog(parent) + , ui(new Ui::DlgExpressionInput) + , expression(_expression ? _expression->copy() : 0) + , path(_path) + , discarded(false) + , impliedUnit(_impliedUnit) + , minimumWidth(10) { assert(path.getDocumentObject() != 0); @@ -62,39 +65,39 @@ DlgExpressionInput::DlgExpressionInput(const App::ObjectIdentifier & _path, boos DocumentObject * docObj = path.getDocumentObject(); ui->expression->setDocumentObject(docObj); - setWindowFlags(Qt::Widget | Qt::FramelessWindowHint); + setWindowFlags(Qt::SubWindow | Qt::Widget | Qt::Popup | Qt::FramelessWindowHint); setAttribute(Qt::WA_NoSystemBackground, true); setAttribute(Qt::WA_TranslucentBackground, true); - setWindowFlags(Qt::Popup); ui->expression->setFocus(); + qApp->installEventFilter(this); } DlgExpressionInput::~DlgExpressionInput() { + qApp->removeEventFilter(this); delete ui; } QPoint DlgExpressionInput::expressionPosition() const { - return QPoint(0, ui->ctrlArea->height()+3); + return ui->expression->pos(); } void DlgExpressionInput::textChanged(const QString &text) { try { - //resize the input field according to text size QFontMetrics fm(ui->expression->font()); int width = fm.width(text) + 15; - if(width < minimumWidth) + if (width < minimumWidth) ui->expression->setMinimumWidth(minimumWidth); else - ui->expression->setMinimumWidth(width); + ui->expression->setMinimumWidth(width); if(this->width() < ui->expression->minimumWidth()) setMinimumWidth(ui->expression->minimumWidth()); - + //now handle expression boost::shared_ptr expr(ExpressionParser::parse(path.getDocumentObject(), text.toUtf8().constData())); @@ -108,7 +111,7 @@ void DlgExpressionInput::textChanged(const QString &text) expression = expr; ui->okBtn->setEnabled(true); - ui->msg->setText(QString::fromUtf8("")); + ui->msg->clear(); NumberExpression * n = Base::freecad_dynamic_cast(result.get()); if (n) { @@ -123,7 +126,7 @@ void DlgExpressionInput::textChanged(const QString &text) } else ui->msg->setText(Base::Tools::fromStdString(result->toString())); - + //set default palette as we may have read text right now ui->msg->setPalette(ui->okBtn->palette()); } @@ -143,24 +146,43 @@ void DlgExpressionInput::setDiscarded() reject(); } -void DlgExpressionInput::setExpressionInputSize(int width, int height) { - - if(ui->expression->minimumHeight() < height) +void DlgExpressionInput::setExpressionInputSize(int width, int height) +{ + if (ui->expression->minimumHeight() < height) ui->expression->setMinimumHeight(height); - - if(ui->expression->minimumWidth() < width) + + if (ui->expression->minimumWidth() < width) ui->expression->setMinimumWidth(width); - + minimumWidth = width; } -void DlgExpressionInput::mousePressEvent(QMouseEvent*) { - - - //we need to reject the dialog when clicked on the background. As the background is transparent - //this is the expected behaviour for the user +void DlgExpressionInput::mousePressEvent(QMouseEvent*) +{ + //we need to reject the dialog when clicked on the background. As the background is transparent + //this is the expected behaviour for the user this->reject(); } +bool DlgExpressionInput::eventFilter(QObject *obj, QEvent *ev) +{ + // if the user clicks on a widget different to this + if (ev->type() == QEvent::MouseButtonPress && obj != this) { + QMouseEvent* me = static_cast(ev); + // Here we must get the global position of the mouse press event + // and compute it relative to this widget. + // If the position is inside the rectange of this widget we ignore + // it because the user could have clicked inside a sub-widget. + // If the user clicked outside this widget will be rejected. + // See also mousePressEvent(). + QPoint pos = this->mapFromGlobal(me->globalPos()); + if (!this->rect().contains(pos)) { + this->reject(); + } + } + + return false; +} + #include "moc_DlgExpressionInput.cpp" diff --git a/src/Gui/DlgExpressionInput.h b/src/Gui/DlgExpressionInput.h index d5b950e23..543887b7f 100644 --- a/src/Gui/DlgExpressionInput.h +++ b/src/Gui/DlgExpressionInput.h @@ -61,7 +61,7 @@ public: QPoint expressionPosition() const; void setExpressionInputSize(int width, int height); - void setGeometry(int x, int y, int w, int h); + bool eventFilter(QObject *obj, QEvent *event); private Q_SLOTS: void textChanged(const QString & text); diff --git a/src/Gui/DlgExpressionInput.ui b/src/Gui/DlgExpressionInput.ui index ced996cd3..d0350ad6c 100644 --- a/src/Gui/DlgExpressionInput.ui +++ b/src/Gui/DlgExpressionInput.ui @@ -226,17 +226,8 @@ label expression - result - horizontalSpacer_2 widget - ctrlArea - - verticalSpacer - horizontalSpacer - horizontalSpacer_2 - - horizontalSpacer_3 diff --git a/src/Gui/QuantitySpinBox.cpp b/src/Gui/QuantitySpinBox.cpp index 642e35dab..efb6a818c 100644 --- a/src/Gui/QuantitySpinBox.cpp +++ b/src/Gui/QuantitySpinBox.cpp @@ -23,6 +23,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ +# include # include # include # include @@ -502,16 +503,29 @@ void QuantitySpinBox::openFormulaDialog() Q_ASSERT(isBound()); Q_D(const QuantitySpinBox); - Gui::Dialog::DlgExpressionInput box(getPath(), getExpression(), d->unit, this); + Gui::Dialog::DlgExpressionInput* box = new Gui::Dialog::DlgExpressionInput(getPath(), getExpression(), d->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()); + box->move(pos-box->expressionPosition()); + box->setExpressionInputSize(width(), height()); +} - if (box.exec() == QDialog::Accepted) - setExpression(box.getExpression()); - else if (box.discardedFormula()) +void QuantitySpinBox::finishFormulaDialog() +{ + Gui::Dialog::DlgExpressionInput* box = qobject_cast(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()); + + box->deleteLater(); } Base::Unit QuantitySpinBox::unit() const diff --git a/src/Gui/QuantitySpinBox.h b/src/Gui/QuantitySpinBox.h index 5206b72ef..8b88cee69 100644 --- a/src/Gui/QuantitySpinBox.h +++ b/src/Gui/QuantitySpinBox.h @@ -112,6 +112,7 @@ public Q_SLOTS: protected Q_SLOTS: void userInput(const QString & text); void openFormulaDialog(); + void finishFormulaDialog(); protected: virtual StepEnabled stepEnabled() const;