Added expression support to QuantitySpinBox and InputField classes.
This commit is contained in:
parent
31a6fece52
commit
897f8b78b8
|
@ -205,6 +205,7 @@ set(Gui_MOC_HDRS
|
|||
DocumentRecovery.h
|
||||
EditorView.h
|
||||
ExpressionCompleter.h
|
||||
DlgExpressionInput.h
|
||||
FileDialog.h
|
||||
Flag.h
|
||||
GraphicsViewZoom.h
|
||||
|
@ -228,6 +229,7 @@ set(Gui_MOC_HDRS
|
|||
PythonEditor.h
|
||||
QuantitySpinBox.h
|
||||
QListWidgetCustom.h
|
||||
QuantitySpinBox_p.h
|
||||
ReportView.h
|
||||
SceneInspector.h
|
||||
SelectionView.h
|
||||
|
@ -308,6 +310,7 @@ SET(Gui_UIC_SRCS
|
|||
DocumentRecovery.ui
|
||||
DownloadManager.ui
|
||||
DownloadItem.ui
|
||||
DlgExpressionInput.ui
|
||||
MouseButtons.ui
|
||||
SceneInspector.ui
|
||||
InputVector.ui
|
||||
|
@ -367,6 +370,7 @@ SET(Dialog_CPP_SRCS
|
|||
DlgProjectUtility.cpp
|
||||
DlgPropertyLink.cpp
|
||||
DlgTipOfTheDayImp.cpp
|
||||
DlgExpressionInput.cpp
|
||||
TaskDlgRelocation.cpp
|
||||
DlgUndoRedo.cpp
|
||||
InputVector.cpp
|
||||
|
@ -398,6 +402,7 @@ SET(Dialog_HPP_SRCS
|
|||
DlgProjectUtility.h
|
||||
DlgPropertyLink.h
|
||||
DlgTipOfTheDayImp.h
|
||||
DlgExpressionInput.h
|
||||
TaskDlgRelocation.h
|
||||
DlgUndoRedo.h
|
||||
InputVector.h
|
||||
|
@ -435,6 +440,7 @@ SET(Dialog_SRCS
|
|||
DlgPropertyLink.ui
|
||||
DlgTipOfTheDay.ui
|
||||
DlgTreeWidget.ui
|
||||
DlgExpressionInput.ui
|
||||
DownloadManager.ui
|
||||
DownloadItem.ui
|
||||
DocumentRecovery.ui
|
||||
|
@ -894,6 +900,7 @@ SET(Widget_HPP_SRCS
|
|||
InputField.h
|
||||
ProgressBar.h
|
||||
QuantitySpinBox.h
|
||||
QuantitySpinBox_p.h
|
||||
SpinBox.h
|
||||
Splashscreen.h
|
||||
WidgetFactory.h
|
||||
|
@ -967,6 +974,7 @@ SET(FreeCADGui_CPP_SRCS
|
|||
Document.cpp
|
||||
DocumentModel.cpp
|
||||
DocumentPyImp.cpp
|
||||
ExpressionBinding.cpp
|
||||
GraphicsViewZoom.cpp
|
||||
ExpressionCompleter.cpp
|
||||
GuiApplicationNativeEventAware.cpp
|
||||
|
@ -988,6 +996,7 @@ SET(FreeCADGui_SRCS
|
|||
BitmapFactory.h
|
||||
Document.h
|
||||
DocumentModel.h
|
||||
ExpressionBinding.cpp
|
||||
ExpressionCompleter.h
|
||||
FreeCADGuiInit.py
|
||||
GraphicsViewZoom.h
|
||||
|
|
173
src/Gui/DlgExpressionInput.cpp
Normal file
173
src/Gui/DlgExpressionInput.cpp
Normal file
|
@ -0,0 +1,173 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) 2015 Eivind Kvedalen <eivind@kvedalen.name> *
|
||||
* *
|
||||
* 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., 51 Franklin Street, *
|
||||
* Fifth Floor, Boston, MA 02110-1301, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "PreCompiled.h"
|
||||
#include <QPainter>
|
||||
#include <QDesktopWidget>
|
||||
|
||||
#include "DlgExpressionInput.h"
|
||||
#include "ui_DlgExpressionInput.h"
|
||||
#include "ExpressionCompleter.h"
|
||||
#include <Base/Tools.h>
|
||||
#include <App/Expression.h>
|
||||
#include <App/DocumentObject.h>
|
||||
|
||||
using namespace App;
|
||||
using namespace Gui::Dialog;
|
||||
|
||||
const int DlgExpressionInput::h = 15;
|
||||
const int DlgExpressionInput::l = 30;
|
||||
const int DlgExpressionInput::r = 30;
|
||||
const int DlgExpressionInput::d = 7;
|
||||
|
||||
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)
|
||||
{
|
||||
assert(path.getDocumentObject() != 0);
|
||||
|
||||
// Setup UI
|
||||
ui->setupUi(this);
|
||||
|
||||
if (expression) {
|
||||
ui->expression->setText(Base::Tools::fromStdString(expression->toString()));
|
||||
textChanged(Base::Tools::fromStdString(expression->toString()));
|
||||
}
|
||||
|
||||
// Connect signal(s)
|
||||
connect(ui->expression, SIGNAL(textChanged(QString)), this, SLOT(textChanged(QString)));
|
||||
connect(ui->discardBtn, SIGNAL(clicked()), this, SLOT(setDiscarded()));
|
||||
|
||||
// Set document object on line edit to create auto completer
|
||||
DocumentObject * docObj = path.getDocumentObject();
|
||||
ui->expression->setDocumentObject(docObj);
|
||||
|
||||
setWindowFlags(Qt::Widget | Qt::FramelessWindowHint);
|
||||
setAttribute(Qt::WA_NoSystemBackground, true);
|
||||
setAttribute(Qt::WA_TranslucentBackground, true);
|
||||
setParent(0);
|
||||
|
||||
ui->expression->setFocus();
|
||||
|
||||
QDesktopWidget widget;
|
||||
setMinimumWidth(widget.availableGeometry(widget.primaryScreen()).width()/2);
|
||||
|
||||
#ifndef FC_DEBUG
|
||||
ui->parsedExpr->setVisible(false);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
DlgExpressionInput::~DlgExpressionInput()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
QPoint DlgExpressionInput::tip() const
|
||||
{
|
||||
return QPoint(l - d, 0);
|
||||
}
|
||||
|
||||
void DlgExpressionInput::paintEvent(QPaintEvent * event) {
|
||||
QPainter painter(this);
|
||||
QPainterPath path;
|
||||
|
||||
path.moveTo(0, h + r / 2);
|
||||
path.arcTo(QRect(0, h, r, r), 180, -90);
|
||||
path.lineTo(l, h);
|
||||
path.lineTo(l - d, 0);
|
||||
path.lineTo(l + d, h);
|
||||
path.lineTo(width() - r - 1, h);
|
||||
path.arcTo(QRect(width() - r - 1, h, r, r), 90, -90);
|
||||
path.lineTo(width() - 1, height() - r);
|
||||
path.arcTo(QRect(width() - r - 1, height() - r - 1, r, r), 0, -90);
|
||||
path.lineTo(r, height() - 1);
|
||||
path.arcTo(QRect(0, height() - r - 1, r, r), -90, -90);
|
||||
path.lineTo(0, h + r/2);
|
||||
|
||||
QPen pen(Qt::black);
|
||||
QBrush brush(QColor(250, 250, 180));
|
||||
pen.setWidthF(2.0);
|
||||
painter.setBrush(brush);
|
||||
painter.setPen(pen);
|
||||
|
||||
painter.fillPath(path, brush);
|
||||
painter.drawPath(path);
|
||||
}
|
||||
|
||||
void DlgExpressionInput::textChanged(const QString &text)
|
||||
{
|
||||
try {
|
||||
boost::shared_ptr<Expression> expr(ExpressionParser::parse(path.getDocumentObject(), text.toUtf8().constData()));
|
||||
|
||||
if (expr) {
|
||||
std::string error = path.getDocumentObject()->ExpressionEngine.validateExpression(path, expr);
|
||||
|
||||
if (error.size() > 0)
|
||||
throw Base::Exception(error.c_str());
|
||||
|
||||
#ifdef FC_DEBUG
|
||||
ui->parsedExpr->setText(Base::Tools::fromStdString(expr->toString()));
|
||||
#endif
|
||||
|
||||
std::auto_ptr<Expression> result(expr->eval());
|
||||
|
||||
expression = expr;
|
||||
ui->okBtn->setEnabled(true);
|
||||
ui->errorMsg->setText(QString::fromUtf8(""));
|
||||
|
||||
NumberExpression * n = Base::freecad_dynamic_cast<NumberExpression>(result.get());
|
||||
if (n) {
|
||||
Base::Quantity value = n->getQuantity();
|
||||
|
||||
if (!value.getUnit().isEmpty() && value.getUnit() != impliedUnit)
|
||||
throw Base::Exception("Unit mismatch between result and required unit");
|
||||
|
||||
value.setUnit(impliedUnit);
|
||||
|
||||
ui->result->setText(value.getUserString());
|
||||
}
|
||||
else
|
||||
ui->result->setText(Base::Tools::fromStdString(result->toString()));
|
||||
}
|
||||
}
|
||||
catch (Base::Exception & e) {
|
||||
ui->errorMsg->setText(QString::fromUtf8(e.what()));
|
||||
QPalette p(ui->errorMsg->palette());
|
||||
p.setColor(QPalette::WindowText, Qt::red);
|
||||
ui->errorMsg->setPalette(p);
|
||||
ui->okBtn->setDisabled(true);
|
||||
ui->result->setText(QString::fromAscii("--"));
|
||||
}
|
||||
}
|
||||
|
||||
void DlgExpressionInput::setDiscarded()
|
||||
{
|
||||
discarded = true;
|
||||
reject();
|
||||
}
|
||||
|
||||
#include "moc_DlgExpressionInput.cpp"
|
85
src/Gui/DlgExpressionInput.h
Normal file
85
src/Gui/DlgExpressionInput.h
Normal file
|
@ -0,0 +1,85 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) 2015 Eivind Kvedalen <eivind@kvedalen.name> *
|
||||
* *
|
||||
* 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., 51 Franklin Street, *
|
||||
* Fifth Floor, Boston, MA 02110-1301, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef GUI_DIALOG_DLGEXPRESSIONINPUT_H
|
||||
#define GUI_DIALOG_DLGEXPRESSIONINPUT_H
|
||||
|
||||
#include <QDialog>
|
||||
#include <Base/Unit.h>
|
||||
#include <App/ObjectIdentifier.h>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
namespace Ui {
|
||||
class DlgExpressionInput;
|
||||
}
|
||||
|
||||
namespace Base {
|
||||
class Quantity;
|
||||
}
|
||||
|
||||
namespace App {
|
||||
class Path;
|
||||
class Expression;
|
||||
class DocumentObject;
|
||||
}
|
||||
|
||||
namespace Gui {
|
||||
|
||||
namespace Dialog {
|
||||
|
||||
class GuiExport DlgExpressionInput : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit DlgExpressionInput(const App::ObjectIdentifier & _path, boost::shared_ptr<const App::Expression> _expression, const Base::Unit &_impliedUnit, QWidget *parent = 0);
|
||||
~DlgExpressionInput();
|
||||
|
||||
boost::shared_ptr<App::Expression> getExpression() const { return expression; }
|
||||
|
||||
bool discardedFormula() const { return discarded; }
|
||||
|
||||
void paintEvent(QPaintEvent *event);
|
||||
|
||||
QPoint tip() const;
|
||||
|
||||
private Q_SLOTS:
|
||||
void textChanged(const QString & text);
|
||||
void setDiscarded();
|
||||
|
||||
private:
|
||||
::Ui::DlgExpressionInput *ui;
|
||||
boost::shared_ptr<App::Expression> expression;
|
||||
App::ObjectIdentifier path;
|
||||
bool discarded;
|
||||
const Base::Unit impliedUnit;
|
||||
|
||||
static const int h;
|
||||
static const int l;
|
||||
static const int r;
|
||||
static const int d;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif // GUI_DIALOG_EXPRESSIONINPUT_H
|
213
src/Gui/DlgExpressionInput.ui
Normal file
213
src/Gui/DlgExpressionInput.ui
Normal file
|
@ -0,0 +1,213 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>DlgExpressionInput</class>
|
||||
<widget class="QDialog" name="DlgExpressionInput">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>600</width>
|
||||
<height>134</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>600</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Formula editor</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<property name="topMargin">
|
||||
<number>25</number>
|
||||
</property>
|
||||
<item row="3" column="0" colspan="4">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="discardBtn">
|
||||
<property name="text">
|
||||
<string>&Discard formula</string>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="default">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="cancelBtn">
|
||||
<property name="text">
|
||||
<string>Cancel</string>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="okBtn">
|
||||
<property name="text">
|
||||
<string>Ok</string>
|
||||
</property>
|
||||
<property name="default">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="2" column="1" colspan="3">
|
||||
<widget class="QLabel" name="errorMsg">
|
||||
<property name="palette">
|
||||
<palette>
|
||||
<active>
|
||||
<colorrole role="Text">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>255</red>
|
||||
<green>0</green>
|
||||
<blue>0</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
</active>
|
||||
<inactive>
|
||||
<colorrole role="Text">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>255</red>
|
||||
<green>0</green>
|
||||
<blue>0</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
</inactive>
|
||||
<disabled>
|
||||
<colorrole role="Text">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>190</red>
|
||||
<green>190</green>
|
||||
<blue>190</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
</disabled>
|
||||
</palette>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>=></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="Gui::ExpressionLineEdit" name="expression"/>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<widget class="QLabel" name="result">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="parsedExpr">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>Gui::ExpressionLineEdit</class>
|
||||
<extends>QLineEdit</extends>
|
||||
<header>ExpressionCompleter.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>cancelBtn</sender>
|
||||
<signal>clicked()</signal>
|
||||
<receiver>DlgExpressionInput</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>399</x>
|
||||
<y>69</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>392</x>
|
||||
<y>85</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>okBtn</sender>
|
||||
<signal>clicked()</signal>
|
||||
<receiver>DlgExpressionInput</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>505</x>
|
||||
<y>68</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>505</x>
|
||||
<y>94</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
154
src/Gui/ExpressionBinding.cpp
Normal file
154
src/Gui/ExpressionBinding.cpp
Normal file
|
@ -0,0 +1,154 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) 2015 Eivind Kvedalen <eivind@kvedalen.name> *
|
||||
* *
|
||||
* 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., 51 Franklin Street, *
|
||||
* Fifth Floor, Boston, MA 02110-1301, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "PreCompiled.h"
|
||||
#ifndef _PreComp_
|
||||
#endif
|
||||
#include "ExpressionBinding.h"
|
||||
#include "Command.h"
|
||||
#include <App/Expression.h>
|
||||
#include <App/DocumentObject.h>
|
||||
#include <Base/Tools.h>
|
||||
#include <App/ObjectIdentifier.h>
|
||||
#include <App/Document.h>
|
||||
|
||||
using namespace Gui;
|
||||
using namespace App;
|
||||
|
||||
ExpressionBinding::ExpressionBinding()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ExpressionBinding::~ExpressionBinding()
|
||||
{
|
||||
}
|
||||
|
||||
bool ExpressionBinding::isBound() const
|
||||
{
|
||||
return path.getDocumentObject() != 0;
|
||||
}
|
||||
|
||||
void Gui::ExpressionBinding::setExpression(boost::shared_ptr<Expression> expr)
|
||||
{
|
||||
DocumentObject * docObj = path.getDocumentObject();
|
||||
|
||||
if (expr) {
|
||||
const std::string error = docObj->ExpressionEngine.validateExpression(path, expr);
|
||||
|
||||
if (error.size())
|
||||
throw Base::Exception(error.c_str());
|
||||
|
||||
}
|
||||
|
||||
docObj->ExpressionEngine.setValue(path, expr);
|
||||
}
|
||||
|
||||
void ExpressionBinding::bind(const App::ObjectIdentifier &_path)
|
||||
{
|
||||
const Property * prop = _path.getProperty();
|
||||
|
||||
Q_ASSERT(prop != 0);
|
||||
|
||||
path = prop->canonicalPath(_path);
|
||||
}
|
||||
|
||||
void ExpressionBinding::bind(const Property &prop)
|
||||
{
|
||||
bind(App::ObjectIdentifier(prop));
|
||||
}
|
||||
|
||||
bool ExpressionBinding::hasExpression() const
|
||||
{
|
||||
return isBound() && getExpression() != 0;
|
||||
}
|
||||
|
||||
boost::shared_ptr<App::Expression> ExpressionBinding::getExpression() const
|
||||
{
|
||||
DocumentObject * docObj = path.getDocumentObject();
|
||||
|
||||
Q_ASSERT(isBound() && docObj != 0);
|
||||
|
||||
return docObj->getExpression(path).expression;
|
||||
}
|
||||
|
||||
std::string ExpressionBinding::getExpressionString() const
|
||||
{
|
||||
if (!getExpression())
|
||||
throw Base::Exception("No expression found.");
|
||||
|
||||
return getExpression()->toString();
|
||||
}
|
||||
|
||||
std::string ExpressionBinding::getEscapedExpressionString() const
|
||||
{
|
||||
return Base::Tools::escapedUnicodeFromUtf8(getExpressionString().c_str());
|
||||
}
|
||||
|
||||
bool ExpressionBinding::apply(const std::string & propName)
|
||||
{
|
||||
if (hasExpression()) {
|
||||
DocumentObject * docObj = path.getDocumentObject();
|
||||
|
||||
if (!docObj)
|
||||
throw Base::Exception("Document object not found.");
|
||||
|
||||
Gui::Command::doCommand(Gui::Command::Doc,"App.getDocument('%s').%s.setExpression('%s', '%s')",
|
||||
docObj->getDocument()->getName(),
|
||||
docObj->getNameInDocument(),
|
||||
path.toEscapedString().c_str(),
|
||||
getEscapedExpressionString().c_str());
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
if (isBound()) {
|
||||
DocumentObject * docObj = path.getDocumentObject();
|
||||
|
||||
if (!docObj)
|
||||
throw Base::Exception("Document object not found.");
|
||||
|
||||
Gui::Command::doCommand(Gui::Command::Doc,"App.getDocument('%s').%s.setExpression('%s', None)",
|
||||
docObj->getDocument()->getName(),
|
||||
docObj->getNameInDocument(),
|
||||
path.toEscapedString().c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool ExpressionBinding::apply()
|
||||
{
|
||||
Property * prop(path.getProperty());
|
||||
|
||||
assert(prop != 0);
|
||||
|
||||
DocumentObject * docObj(path.getDocumentObject());
|
||||
|
||||
if (!docObj)
|
||||
throw Base::Exception("Document object not found.");
|
||||
|
||||
std::string name = docObj->getNameInDocument();
|
||||
|
||||
return apply("App.ActiveDocument." + name + "." + std::string(prop->getName()));
|
||||
}
|
63
src/Gui/ExpressionBinding.h
Normal file
63
src/Gui/ExpressionBinding.h
Normal file
|
@ -0,0 +1,63 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) 2015 Eivind Kvedalen <eivind@kvedalen.name> *
|
||||
* *
|
||||
* 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., 51 Franklin Street, *
|
||||
* Fifth Floor, Boston, MA 02110-1301, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef EXPRESSIONBINDING_H
|
||||
#define EXPRESSIONBINDING_H
|
||||
|
||||
#include <string>
|
||||
#include <App/ObjectIdentifier.h>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
namespace App {
|
||||
class Expression;
|
||||
}
|
||||
|
||||
namespace Gui {
|
||||
|
||||
class GuiExport ExpressionBinding
|
||||
{
|
||||
public:
|
||||
ExpressionBinding();
|
||||
~ExpressionBinding();
|
||||
|
||||
virtual void bind(const App::ObjectIdentifier & _path);
|
||||
virtual void bind(const App::Property & prop);
|
||||
bool isBound() const;
|
||||
virtual bool apply(const std::string &propName);
|
||||
virtual bool apply();
|
||||
bool hasExpression() const;
|
||||
|
||||
protected:
|
||||
const App::ObjectIdentifier & getPath() const { return path; }
|
||||
boost::shared_ptr<App::Expression> getExpression() const;
|
||||
std::string getExpressionString() const;
|
||||
std::string getEscapedExpressionString() const;
|
||||
virtual void setExpression(boost::shared_ptr<App::Expression> expr);
|
||||
|
||||
private:
|
||||
App::ObjectIdentifier path;
|
||||
//boost::shared_ptr<const App::Expression> expression;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // EXPRESSIONBINDING_H
|
78
src/Gui/Icons/bound-expression.svg
Normal file
78
src/Gui/Icons/bound-expression.svg
Normal file
|
@ -0,0 +1,78 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="64px"
|
||||
height="64px"
|
||||
id="svg4069"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.3.1 r9886"
|
||||
sodipodi:docname="New document 7">
|
||||
<defs
|
||||
id="defs4071" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="5.5"
|
||||
inkscape:cx="32"
|
||||
inkscape:cy="32"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
inkscape:document-units="px"
|
||||
inkscape:grid-bbox="true"
|
||||
inkscape:window-width="967"
|
||||
inkscape:window-height="814"
|
||||
inkscape:window-x="589"
|
||||
inkscape:window-y="86"
|
||||
inkscape:window-maximized="0" />
|
||||
<metadata
|
||||
id="metadata4074">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="layer1"
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer">
|
||||
<path
|
||||
sodipodi:type="arc"
|
||||
style="fill:#0000ff;fill-opacity:1;stroke:#0000ff;stroke-width:4.36290264;stroke-linejoin:round;stroke-miterlimit:4.19999981;stroke-opacity:1;stroke-dasharray:none"
|
||||
id="path2985"
|
||||
sodipodi:cx="325"
|
||||
sodipodi:cy="503.43362"
|
||||
sodipodi:rx="68.571426"
|
||||
sodipodi:ry="61.785713"
|
||||
d="m 393.57143,503.43362 a 68.571426,61.785713 0 1 1 -137.14286,0 68.571426,61.785713 0 1 1 137.14286,0 z"
|
||||
transform="matrix(0.44478506,0,0,0.49741082,-112.73696,-218.43771)" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:35.82092285px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:0.89552319;stroke-opacity:1;font-family:Arial;-inkscape-font-specification:Arial"
|
||||
x="32.030895"
|
||||
y="41.949329"
|
||||
id="text3755"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3757"
|
||||
x="32.030895"
|
||||
y="41.949329"
|
||||
style="font-size:35.82092285px;font-style:italic;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;writing-mode:lr-tb;text-anchor:middle;stroke-width:0.89552319;font-family:Arial;-inkscape-font-specification:Arial Italic">f(x)</tspan></text>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.9 KiB |
|
@ -41,6 +41,7 @@
|
|||
<file>ClassBrowser/type_enum.svg</file>
|
||||
<file>ClassBrowser/type_module.svg</file>
|
||||
<file>Std_ViewScreenShot.svg</file>
|
||||
<file>bound-expression.svg</file>
|
||||
<file>breakpoint.svg</file>
|
||||
<file>debug-marker.svg</file>
|
||||
<file>debug-start.svg</file>
|
||||
|
|
|
@ -31,12 +31,17 @@
|
|||
#include <Base/Console.h>
|
||||
#include <Base/Quantity.h>
|
||||
#include <Base/Exception.h>
|
||||
#include <Base/Tools.h>
|
||||
#include <App/Application.h>
|
||||
|
||||
#include <App/PropertyUnits.h>
|
||||
#include <App/DocumentObject.h>
|
||||
#include "ExpressionCompleter.h"
|
||||
#include "Command.h"
|
||||
#include "InputField.h"
|
||||
#include "BitmapFactory.h"
|
||||
|
||||
using namespace Gui;
|
||||
using namespace App;
|
||||
using namespace Base;
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
@ -59,7 +64,8 @@ private:
|
|||
// --------------------------------------------------------------------
|
||||
|
||||
InputField::InputField(QWidget * parent)
|
||||
: QLineEdit(parent),
|
||||
: ExpressionLineEdit(parent),
|
||||
ExpressionBinding(),
|
||||
validInput(true),
|
||||
actUnitValue(0),
|
||||
Maximum(DOUBLE_MAX),
|
||||
|
@ -92,6 +98,43 @@ InputField::~InputField()
|
|||
{
|
||||
}
|
||||
|
||||
void InputField::bind(const App::ObjectIdentifier &_path)
|
||||
{
|
||||
ExpressionBinding::bind(_path);
|
||||
|
||||
PropertyQuantity * prop = freecad_dynamic_cast<PropertyQuantity>(getPath().getProperty());
|
||||
|
||||
if (prop)
|
||||
actQuantity = prop->getValue();
|
||||
|
||||
DocumentObject * docObj = getPath().getDocumentObject();
|
||||
|
||||
if (docObj) {
|
||||
boost::shared_ptr<const Expression> expr(docObj->getExpression(getPath()).expression);
|
||||
|
||||
if (expr)
|
||||
newInput(Tools::fromStdString(expr->toString()));
|
||||
}
|
||||
|
||||
// Create document object, to initialize completer
|
||||
setDocumentObject(docObj);
|
||||
}
|
||||
|
||||
bool InputField::apply(const std::string &propName)
|
||||
{
|
||||
if (!ExpressionBinding::apply(propName)) {
|
||||
Gui::Command::doCommand(Gui::Command::Doc,"%s = %f", propName.c_str(), getQuantity().getValue());
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool InputField::apply()
|
||||
{
|
||||
return ExpressionBinding::apply();
|
||||
}
|
||||
|
||||
QPixmap InputField::getValidationIcon(const char* name, const QSize& size) const
|
||||
{
|
||||
QString key = QString::fromAscii("%1_%2x%3")
|
||||
|
@ -110,6 +153,15 @@ QPixmap InputField::getValidationIcon(const char* name, const QSize& size) const
|
|||
|
||||
void InputField::updateText(const Base::Quantity& quant)
|
||||
{
|
||||
if (isBound()) {
|
||||
boost::shared_ptr<const Expression> e(getPath().getDocumentObject()->getExpression(getPath()).expression);
|
||||
|
||||
if (e) {
|
||||
setText(Tools::fromStdString(e->toString()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
double dFactor;
|
||||
QString txt = quant.getUserString(dFactor,actUnitStr);
|
||||
actUnitValue = quant.getValue()/dFactor;
|
||||
|
@ -182,7 +234,22 @@ void InputField::newInput(const QString & text)
|
|||
try {
|
||||
QString input = text;
|
||||
fixup(input);
|
||||
res = Quantity::parse(input);
|
||||
|
||||
if (isBound()) {
|
||||
boost::shared_ptr<Expression> e(ExpressionParser::parse(getPath().getDocumentObject(), input.toUtf8()));
|
||||
|
||||
setExpression(e);
|
||||
|
||||
std::auto_ptr<Expression> evalRes(getExpression()->eval());
|
||||
|
||||
NumberExpression * value = freecad_dynamic_cast<NumberExpression>(evalRes.get());
|
||||
if (value) {
|
||||
res.setValue(value->getValue());
|
||||
res.setUnit(value->getUnit());
|
||||
}
|
||||
}
|
||||
else
|
||||
res = Quantity::parse(input);
|
||||
}
|
||||
catch(Base::Exception &e){
|
||||
ErrorText = e.what();
|
||||
|
@ -485,14 +552,14 @@ void InputField::showEvent(QShowEvent * event)
|
|||
|
||||
void InputField::focusInEvent(QFocusEvent * event)
|
||||
{
|
||||
if (event->reason() == Qt::TabFocusReason ||
|
||||
event->reason() == Qt::BacktabFocusReason ||
|
||||
event->reason() == Qt::ShortcutFocusReason) {
|
||||
if (!this->hasSelectedText())
|
||||
selectNumber();
|
||||
}
|
||||
|
||||
QLineEdit::focusInEvent(event);
|
||||
if (event->reason() == Qt::TabFocusReason ||
|
||||
event->reason() == Qt::BacktabFocusReason ||
|
||||
event->reason() == Qt::ShortcutFocusReason) {
|
||||
if (!this->hasSelectedText())
|
||||
selectNumber();
|
||||
}
|
||||
|
||||
QLineEdit::focusInEvent(event);
|
||||
}
|
||||
|
||||
void InputField::keyPressEvent(QKeyEvent *event)
|
||||
|
|
|
@ -25,17 +25,27 @@
|
|||
#define GUI_INPUTFIELD_H
|
||||
|
||||
#include <QValidator>
|
||||
#include <App/Property.h>
|
||||
#include <App/Expression.h>
|
||||
#include <Base/Parameter.h>
|
||||
#include <Base/Quantity.h>
|
||||
#include "Widgets.h"
|
||||
#include "Window.h"
|
||||
#include "SpinBox.h"
|
||||
#include "FileDialog.h"
|
||||
#include "ExpressionBinding.h"
|
||||
#include "ExpressionCompleter.h"
|
||||
|
||||
#ifdef Q_MOC_RUN
|
||||
Q_DECLARE_METATYPE(Base::Quantity)
|
||||
#endif
|
||||
|
||||
namespace App {
|
||||
class DocumentObject;
|
||||
class ObjectIdentifier;
|
||||
class Expression;
|
||||
}
|
||||
|
||||
namespace Gui {
|
||||
|
||||
|
||||
|
@ -46,9 +56,9 @@ namespace Gui {
|
|||
* and managing default and history values.
|
||||
* Although it's derived from a QLineEdit widget, it supports most of the properties and signals
|
||||
* of a spin box.
|
||||
* \author Jürgen Riegel
|
||||
* \author Jürgen Riegel
|
||||
*/
|
||||
class GuiExport InputField : public QLineEdit
|
||||
class GuiExport InputField : public ExpressionLineEdit, public ExpressionBinding
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -62,7 +72,7 @@ class GuiExport InputField : public QLineEdit
|
|||
|
||||
|
||||
public:
|
||||
InputField ( QWidget * parent = 0 );
|
||||
InputField (QWidget * parent = 0);
|
||||
virtual ~InputField();
|
||||
|
||||
/// set the field with a quantity
|
||||
|
@ -132,6 +142,10 @@ public:
|
|||
std::vector<QString> getSavedValues(void);
|
||||
//@}
|
||||
|
||||
void bind(const App::ObjectIdentifier &_path);
|
||||
bool apply(const std::string &propName);
|
||||
bool apply();
|
||||
|
||||
Q_SIGNALS:
|
||||
/** gets emitted if the user has entered a VALID input
|
||||
* Valid means the user inputted string obeys all restrictions
|
||||
|
@ -187,6 +201,8 @@ private:
|
|||
double StepSize;
|
||||
int HistorySize;
|
||||
int SaveSize;
|
||||
|
||||
QPalette defaultPalette;
|
||||
};
|
||||
|
||||
} // namespace Gui
|
||||
|
|
|
@ -25,14 +25,31 @@
|
|||
#ifndef _PreComp_
|
||||
# include <QLineEdit>
|
||||
# include <QFocusEvent>
|
||||
# include <QHBoxLayout>
|
||||
# include <QLabel>
|
||||
# include <QStyle>
|
||||
# include <QPixmapCache>
|
||||
# include <QMouseEvent>
|
||||
# include <QToolTip>
|
||||
# include <QApplication>
|
||||
#endif
|
||||
|
||||
#include "QuantitySpinBox.h"
|
||||
#include "QuantitySpinBox_p.h"
|
||||
#include "DlgExpressionInput.h"
|
||||
#include "BitmapFactory.h"
|
||||
#include "Command.h"
|
||||
#include <Base/Tools.h>
|
||||
#include <Base/Exception.h>
|
||||
#include <App/Expression.h>
|
||||
#include <sstream>
|
||||
|
||||
using namespace Gui;
|
||||
using namespace App;
|
||||
using namespace Base;
|
||||
|
||||
namespace Gui {
|
||||
|
||||
class QuantitySpinBoxPrivate
|
||||
{
|
||||
public:
|
||||
|
@ -210,23 +227,183 @@ end:
|
|||
double maximum;
|
||||
double minimum;
|
||||
double singleStep;
|
||||
QPalette defaultPalette;
|
||||
QLabel* iconLabel;
|
||||
};
|
||||
}
|
||||
|
||||
QuantitySpinBox::QuantitySpinBox(QWidget *parent)
|
||||
: QAbstractSpinBox(parent), d_ptr(new QuantitySpinBoxPrivate())
|
||||
: QAbstractSpinBox(parent),
|
||||
ExpressionBinding(),
|
||||
d_ptr(new QuantitySpinBoxPrivate())
|
||||
{
|
||||
d_ptr->locale = locale();
|
||||
this->setContextMenuPolicy(Qt::DefaultContextMenu);
|
||||
QObject::connect(lineEdit(), SIGNAL(textChanged(QString)),
|
||||
this, SLOT(userInput(QString)));
|
||||
d_ptr->defaultPalette = lineEdit()->palette();
|
||||
|
||||
/* Icon for f(x) */
|
||||
d_ptr->iconLabel = new ExpressionLabel(lineEdit());
|
||||
d_ptr->iconLabel->setCursor(Qt::ArrowCursor);
|
||||
QPixmap pixmap = getIcon(":/icons/bound-expression.svg", QSize(lineEdit()->sizeHint().height(), lineEdit()->sizeHint().height()));
|
||||
d_ptr->iconLabel->setPixmap(pixmap);
|
||||
d_ptr->iconLabel->setStyleSheet(QString::fromAscii("QLabel { border: none; padding: 0px; }"));
|
||||
d_ptr->iconLabel->hide();
|
||||
int frameWidth = style()->pixelMetric(QStyle::PM_SpinBoxFrameWidth);
|
||||
lineEdit()->setStyleSheet(QString::fromAscii("QLineEdit { padding-right: %1px } ").arg(d_ptr->iconLabel->sizeHint().width() + frameWidth + 1));
|
||||
|
||||
QObject::connect(d_ptr->iconLabel, SIGNAL(clicked()), this, SLOT(openFormulaDialog()));
|
||||
}
|
||||
|
||||
QuantitySpinBox::~QuantitySpinBox()
|
||||
{
|
||||
}
|
||||
|
||||
void QuantitySpinBox::updateText(const Base::Quantity& quant)
|
||||
QPixmap QuantitySpinBox::getIcon(const char* name, const QSize& size) const
|
||||
{
|
||||
QString key = QString::fromAscii("%1_%2x%3")
|
||||
.arg(QString::fromAscii(name))
|
||||
.arg(size.width())
|
||||
.arg(size.height());
|
||||
QPixmap icon;
|
||||
if (QPixmapCache::find(key, icon))
|
||||
return icon;
|
||||
|
||||
icon = BitmapFactory().pixmapFromSvg(name, size);
|
||||
if (!icon.isNull())
|
||||
QPixmapCache::insert(key, icon);
|
||||
return icon;
|
||||
}
|
||||
|
||||
void QuantitySpinBox::bind(const App::ObjectIdentifier &_path)
|
||||
{
|
||||
Q_D(QuantitySpinBox);
|
||||
|
||||
ExpressionBinding::bind(_path);
|
||||
|
||||
d->iconLabel->show();
|
||||
}
|
||||
|
||||
void Gui::QuantitySpinBox::setExpression(boost::shared_ptr<Expression> expr)
|
||||
{
|
||||
Q_D(QuantitySpinBox);
|
||||
|
||||
Q_ASSERT(isBound());
|
||||
|
||||
try {
|
||||
ExpressionBinding::setExpression(expr);
|
||||
|
||||
if (getExpression()) {
|
||||
std::auto_ptr<Expression> result(getExpression()->eval());
|
||||
NumberExpression * value = freecad_dynamic_cast<NumberExpression>(result.get());
|
||||
|
||||
if (value) {
|
||||
std::stringstream s;
|
||||
s << value->getValue();
|
||||
|
||||
lineEdit()->setText(value->getQuantity().getUserString());
|
||||
setReadOnly(true);
|
||||
|
||||
QPalette p(lineEdit()->palette());
|
||||
p.setColor(QPalette::Text, Qt::lightGray);
|
||||
lineEdit()->setPalette(p);
|
||||
}
|
||||
setToolTip(Base::Tools::fromStdString(getExpression()->toString()));
|
||||
}
|
||||
else {
|
||||
setReadOnly(false);
|
||||
QPalette p(lineEdit()->palette());
|
||||
p.setColor(QPalette::Active, QPalette::Text, d->defaultPalette.color(QPalette::Text));
|
||||
lineEdit()->setPalette(p);
|
||||
|
||||
}
|
||||
d->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);
|
||||
d->iconLabel->setToolTip(QString::fromAscii(e.what()));
|
||||
}
|
||||
}
|
||||
|
||||
bool QuantitySpinBox::apply(const std::string & propName)
|
||||
{
|
||||
if (!ExpressionBinding::apply(propName)) {
|
||||
Gui::Command::doCommand(Gui::Command::Doc, "%s = %f", propName.c_str(), value().getValue());
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool QuantitySpinBox::apply()
|
||||
{
|
||||
return ExpressionBinding::apply();
|
||||
}
|
||||
|
||||
void QuantitySpinBox::resizeEvent(QResizeEvent * event)
|
||||
{
|
||||
Q_D(const QuantitySpinBox);
|
||||
|
||||
QAbstractSpinBox::resizeEvent(event);
|
||||
|
||||
int frameWidth = style()->pixelMetric(QStyle::PM_SpinBoxFrameWidth);
|
||||
|
||||
QPixmap pixmap = getIcon(":/icons/bound-expression.svg", QSize(lineEdit()->rect().height() - frameWidth * 2,
|
||||
lineEdit()->rect().height() - frameWidth * 2));
|
||||
d->iconLabel->setPixmap(pixmap);
|
||||
QSize sz = d->iconLabel->sizeHint();
|
||||
d->iconLabel->move(lineEdit()->rect().right() - frameWidth - sz.width(),
|
||||
lineEdit()->rect().top() - frameWidth);
|
||||
|
||||
try {
|
||||
if (isBound() && getExpression()) {
|
||||
std::auto_ptr<Expression> result(getExpression()->eval());
|
||||
NumberExpression * value = freecad_dynamic_cast<NumberExpression>(result.get());
|
||||
|
||||
if (value) {
|
||||
setReadOnly(true);
|
||||
|
||||
QPalette p(lineEdit()->palette());
|
||||
p.setColor(QPalette::Text, Qt::lightGray);
|
||||
lineEdit()->setPalette(p);
|
||||
}
|
||||
setToolTip(Base::Tools::fromStdString(getExpression()->toString()));
|
||||
}
|
||||
else {
|
||||
setReadOnly(false);
|
||||
QPalette p(lineEdit()->palette());
|
||||
p.setColor(QPalette::Active, QPalette::Text, d->defaultPalette.color(QPalette::Text));
|
||||
lineEdit()->setPalette(p);
|
||||
|
||||
}
|
||||
d->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);
|
||||
d->iconLabel->setToolTip(QString::fromAscii(e.what()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Gui::QuantitySpinBox::keyPressEvent(QKeyEvent *event)
|
||||
{
|
||||
if (event->key() == Qt::Key_Equal && isBound())
|
||||
openFormulaDialog();
|
||||
else {
|
||||
if (!hasExpression())
|
||||
QAbstractSpinBox::keyPressEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void QuantitySpinBox::updateText(const Quantity &quant)
|
||||
{
|
||||
Q_D(QuantitySpinBox);
|
||||
|
||||
|
@ -312,6 +489,21 @@ void QuantitySpinBox::userInput(const QString & text)
|
|||
valueChanged(res.getValue());
|
||||
}
|
||||
|
||||
void QuantitySpinBox::openFormulaDialog()
|
||||
{
|
||||
Q_ASSERT(isBound());
|
||||
|
||||
Q_D(const QuantitySpinBox);
|
||||
Gui::Dialog::DlgExpressionInput box(getPath(), getExpression(), d->unit, this);
|
||||
|
||||
QPoint pos = mapToGlobal(QPoint(width() / 2, height() / 2));
|
||||
box.setGeometry(pos.x() - box.tip().x(), pos.y() - box.tip().y(), width(), height());
|
||||
if (box.exec() == QDialog::Accepted)
|
||||
setExpression(box.getExpression());
|
||||
else if (box.discardedFormula())
|
||||
setExpression(boost::shared_ptr<Expression>());
|
||||
}
|
||||
|
||||
Base::Unit QuantitySpinBox::unit() const
|
||||
{
|
||||
Q_D(const QuantitySpinBox);
|
||||
|
@ -430,6 +622,23 @@ void QuantitySpinBox::showEvent(QShowEvent * event)
|
|||
selectNumber();
|
||||
}
|
||||
|
||||
bool QuantitySpinBox::event(QEvent * event)
|
||||
{
|
||||
if (event->type() == QEvent::ToolTip) {
|
||||
if (isBound() && getExpression() && lineEdit()->isReadOnly()) {
|
||||
QHelpEvent * helpEvent = static_cast<QHelpEvent*>(event);
|
||||
|
||||
QToolTip::showText( helpEvent->globalPos(), Base::Tools::fromStdString(getExpression()->toString()), this);
|
||||
event->accept();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return QAbstractSpinBox::event(event);
|
||||
}
|
||||
else
|
||||
return QAbstractSpinBox::event(event);
|
||||
}
|
||||
|
||||
void QuantitySpinBox::focusInEvent(QFocusEvent * event)
|
||||
{
|
||||
bool hasSel = lineEdit()->hasSelectedText();
|
||||
|
@ -438,8 +647,16 @@ void QuantitySpinBox::focusInEvent(QFocusEvent * event)
|
|||
if (event->reason() == Qt::TabFocusReason ||
|
||||
event->reason() == Qt::BacktabFocusReason ||
|
||||
event->reason() == Qt::ShortcutFocusReason) {
|
||||
if (!hasSel)
|
||||
selectNumber();
|
||||
|
||||
if (isBound() && getExpression() && lineEdit()->isReadOnly()) {
|
||||
QHelpEvent * helpEvent = new QHelpEvent(QEvent::ToolTip, QPoint( 0, rect().height() ), mapToGlobal( QPoint( 0, rect().height() ) ));
|
||||
QApplication::postEvent(this, helpEvent);
|
||||
lineEdit()->setSelection(0, 0);
|
||||
}
|
||||
else {
|
||||
if (!hasSel)
|
||||
selectNumber();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -454,6 +671,7 @@ void QuantitySpinBox::focusOutEvent(QFocusEvent * event)
|
|||
if (state != QValidator::Acceptable) {
|
||||
lineEdit()->setText(d->validStr);
|
||||
}
|
||||
QToolTip::hideText();
|
||||
QAbstractSpinBox::focusOutEvent(event);
|
||||
}
|
||||
|
||||
|
@ -530,3 +748,4 @@ void QuantitySpinBox::fixup(QString &input) const
|
|||
|
||||
|
||||
#include "moc_QuantitySpinBox.cpp"
|
||||
#include "moc_QuantitySpinBox_p.cpp"
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
|
||||
#include <QAbstractSpinBox>
|
||||
#include <Base/Quantity.h>
|
||||
#include "ExpressionBinding.h"
|
||||
|
||||
#ifdef Q_MOC_RUN
|
||||
Q_DECLARE_METATYPE(Base::Quantity)
|
||||
|
@ -34,7 +35,7 @@ Q_DECLARE_METATYPE(Base::Quantity)
|
|||
namespace Gui {
|
||||
|
||||
class QuantitySpinBoxPrivate;
|
||||
class GuiExport QuantitySpinBox : public QAbstractSpinBox
|
||||
class GuiExport QuantitySpinBox : public QAbstractSpinBox, public ExpressionBinding
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -95,6 +96,13 @@ public:
|
|||
virtual QValidator::State validate(QString &input, int &pos) const;
|
||||
virtual void fixup(QString &str) const;
|
||||
|
||||
bool event(QEvent *event);
|
||||
|
||||
void setExpression(boost::shared_ptr<App::Expression> expr);
|
||||
void bind(const App::ObjectIdentifier &_path);
|
||||
bool apply(const std::string &propName);
|
||||
bool apply();
|
||||
|
||||
public Q_SLOTS:
|
||||
/// Sets the field with a quantity
|
||||
void setValue(const Base::Quantity& val);
|
||||
|
@ -103,14 +111,19 @@ public Q_SLOTS:
|
|||
|
||||
protected Q_SLOTS:
|
||||
void userInput(const QString & text);
|
||||
void openFormulaDialog();
|
||||
|
||||
protected:
|
||||
virtual StepEnabled stepEnabled() const;
|
||||
virtual void showEvent(QShowEvent * event);
|
||||
virtual void focusInEvent(QFocusEvent * event);
|
||||
virtual void focusOutEvent(QFocusEvent * event);
|
||||
virtual void keyPressEvent(QKeyEvent *event);
|
||||
virtual void resizeEvent(QResizeEvent *event);
|
||||
|
||||
private:
|
||||
|
||||
QPixmap getIcon(const char *name, const QSize &size) const;
|
||||
void updateText(const Base::Quantity&);
|
||||
|
||||
Q_SIGNALS:
|
||||
|
|
43
src/Gui/QuantitySpinBox_p.h
Normal file
43
src/Gui/QuantitySpinBox_p.h
Normal file
|
@ -0,0 +1,43 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) 2015 Eivind Kvedalen <eivind@kvedalen.name> *
|
||||
* *
|
||||
* 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., 51 Franklin Street, *
|
||||
* Fifth Floor, Boston, MA 02110-1301, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef QUANTITYSPINBOX_P_H
|
||||
#define QUANTITYSPINBOX_P_H
|
||||
|
||||
#include <QLabel>
|
||||
|
||||
class ExpressionLabel : public QLabel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ExpressionLabel(QWidget * parent) : QLabel(parent) { }
|
||||
protected:
|
||||
void mouseReleaseEvent(QMouseEvent * event) {
|
||||
if (rect().contains(event->pos()))
|
||||
Q_EMIT clicked();
|
||||
}
|
||||
|
||||
Q_SIGNALS:
|
||||
void clicked();
|
||||
};
|
||||
|
||||
#endif // QUANTITYSPINBOX_P_H
|
Loading…
Reference in New Issue
Block a user