+ fix transparent background for Windows systems

+ set application-wide event filter and handle mouse press events
+ fix expressPosition() to return exact position of line edit
+ fix warnings in ui file
+ use DlgExpressionInput as non-modal dialog in QuantitySpinBox
This commit is contained in:
wmayer 2015-09-26 19:36:11 +02:00
parent 98ed315b2d
commit 309373c404
5 changed files with 72 additions and 44 deletions

View File

@ -23,6 +23,7 @@
#include "PreCompiled.h"
#include <QPainter>
#include <QDesktopWidget>
#include <QMouseEvent>
#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<const Expression> _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<const Expression> _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<Expression> 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<NumberExpression>(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<QMouseEvent*>(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"

View File

@ -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);

View File

@ -226,17 +226,8 @@
</layout>
<zorder>label</zorder>
<zorder>expression</zorder>
<zorder>result</zorder>
<zorder>horizontalSpacer_2</zorder>
<zorder>widget</zorder>
<zorder></zorder>
<zorder>ctrlArea</zorder>
<zorder></zorder>
<zorder>verticalSpacer</zorder>
<zorder>horizontalSpacer</zorder>
<zorder>horizontalSpacer_2</zorder>
<zorder></zorder>
<zorder>horizontalSpacer_3</zorder>
</widget>
<customwidgets>
<customwidget>

View File

@ -23,6 +23,7 @@
#include "PreCompiled.h"
#ifndef _PreComp_
# include <QDebug>
# include <QLineEdit>
# include <QFocusEvent>
# include <QHBoxLayout>
@ -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<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();
}
Base::Unit QuantitySpinBox::unit() const

View File

@ -112,6 +112,7 @@ public Q_SLOTS:
protected Q_SLOTS:
void userInput(const QString & text);
void openFormulaDialog();
void finishFormulaDialog();
protected:
virtual StepEnabled stepEnabled() const;