diff --git a/src/App/FeatureTest.cpp b/src/App/FeatureTest.cpp index c98664685..15392cb5e 100644 --- a/src/App/FeatureTest.cpp +++ b/src/App/FeatureTest.cpp @@ -98,10 +98,10 @@ FeatureTest::FeatureTest() ADD_PROPERTY(QuantityLength,(1.0)); QuantityLength.setUnit(Base::Unit::Length); - ADD_PROPERTY(QuantityMass,(1.0)); - QuantityMass.setUnit(Base::Unit::Mass); - ADD_PROPERTY(QuantityAngle,(1.0)); - QuantityAngle.setUnit(Base::Unit::Angle); + //ADD_PROPERTY(QuantityMass,(1.0)); + //QuantityMass.setUnit(Base::Unit::Mass); + //ADD_PROPERTY(QuantityAngle,(1.0)); + //QuantityAngle.setUnit(Base::Unit::Angle); } diff --git a/src/App/FeatureTest.h b/src/App/FeatureTest.h index 8d4676140..886047c39 100644 --- a/src/App/FeatureTest.h +++ b/src/App/FeatureTest.h @@ -94,8 +94,8 @@ public: App::PropertyInteger TypeTransient; App::PropertyQuantity QuantityLength; - App::PropertyQuantity QuantityMass; - App::PropertyQuantity QuantityAngle; + //App::PropertyQuantity QuantityMass; + //App::PropertyQuantity QuantityAngle; /** @name methods overide Feature */ //@{ diff --git a/src/Base/Quantity.cpp b/src/Base/Quantity.cpp index 4ddf5516d..315e2c515 100644 --- a/src/Base/Quantity.cpp +++ b/src/Base/Quantity.cpp @@ -38,6 +38,13 @@ # pragma warning(disable : 4335) // disable MAC file format warning on VC #endif +#ifndef DOUBLE_MAX +# define DOUBLE_MAX 1.7976931348623157E+308 /* max decimal value of a "double"*/ +#endif +#ifndef DOUBLE_MIN +# define DOUBLE_MIN 2.2250738585072014E-308 /* min decimal value of a "double"*/ +#endif + using namespace Base; Quantity::Quantity() @@ -113,18 +120,41 @@ double Quantity::getUserPrefered(QString &unitString)const return Base::UnitsApi::schemaPrefUnit(_Unit,unitString).getValue() * _Value; } +std::string Quantity::getUserString(void)const +{ + std::stringstream sstream; + sstream << _Value << _Unit.getString(); + //TODO: implementing + return sstream.str(); +} + +/// true if it has a number without a unit +bool Quantity::isDimensionless(void)const +{ + return _Value != DOUBLE_MIN && _Unit.isEmpty(); +} +// true if it has a number and a valid unit +bool Quantity::isQuantity(void)const +{ + return _Value != DOUBLE_MIN && !_Unit.isEmpty(); +} +// true if it has a number with or without a unit +bool Quantity::isValid(void)const +{ + return _Value != DOUBLE_MIN ; +} + +void Quantity::setInvalid(void) +{ + _Value = DOUBLE_MIN ; +} + // === Parser & Scanner stuff =============================================== // include the Scanner and the Parser for the Quantitys Quantity QuantResult; -#ifndef DOUBLE_MAX -# define DOUBLE_MAX 1.7976931348623157E+308 /* max decimal value of a "double"*/ -#endif -#ifndef DOUBLE_MIN -# define DOUBLE_MIN 2.2250738585072014E-308 /* min decimal value of a "double"*/ -#endif // error func diff --git a/src/Base/Quantity.h b/src/Base/Quantity.h index 724357a4d..c64d2f74b 100644 --- a/src/Base/Quantity.h +++ b/src/Base/Quantity.h @@ -66,6 +66,16 @@ public: double getValue(void) const{return _Value;} void setValue(double val){_Value = val;} + /// true if it has a number without a unit + bool isDimensionless(void)const; + /// true if it has a number and a valid unit + bool isQuantity(void)const; + /// true if it has a number with or without a unit + bool isValid(void)const; + /// sets the quantity invalid + void setInvalid(void); + + protected: double _Value; Unit _Unit; diff --git a/src/Gui/CMakeLists.txt b/src/Gui/CMakeLists.txt index 124c4f8e2..db271fc9c 100644 --- a/src/Gui/CMakeLists.txt +++ b/src/Gui/CMakeLists.txt @@ -129,6 +129,7 @@ set(Gui_MOC_HDRS DownloadManager.h DlgActionsImp.h DlgActivateWindowImp.h + DlgUnitsCalculatorImp.h DlgCommandsImp.h DlgCustomizeImp.h DlgCustomizeSpaceball.h @@ -219,6 +220,7 @@ SET(Gui_UIC_SRCS DemoMode.ui DlgActions.ui DlgActivateWindow.ui + DlgUnitsCalculator.ui DlgAuthorization.ui DlgChooseIcon.ui DlgCommands.ui @@ -295,6 +297,7 @@ SET(Dialog_CPP_SRCS Clipping.cpp DemoMode.cpp DlgActivateWindowImp.cpp + DlgUnitsCalculatorImp.cpp DlgDisplayPropertiesImp.cpp DlgInputDialogImp.cpp DlgMacroExecuteImp.cpp @@ -323,6 +326,7 @@ SET(Dialog_HPP_SRCS Clipping.h DemoMode.h DlgActivateWindowImp.h + DlgUnitsCalculatorImp.h DlgDisplayPropertiesImp.h DlgInputDialogImp.h DlgMacroExecuteImp.h @@ -354,6 +358,7 @@ SET(Dialog_SRCS Clipping.ui DemoMode.ui DlgActivateWindow.ui + DlgUnitsCalculator.ui DlgAuthorization.ui DlgDisplayProperties.ui DlgInputDialog.ui diff --git a/src/Gui/CommandStd.cpp b/src/Gui/CommandStd.cpp index b9bac32da..a482b3664 100644 --- a/src/Gui/CommandStd.cpp +++ b/src/Gui/CommandStd.cpp @@ -61,6 +61,7 @@ #include "WorkbenchManager.h" #include "Workbench.h" #include "Selection.h" +#include "DlgUnitsCalculatorImp.h" using Base::Console; using Base::Sequencer; @@ -647,6 +648,28 @@ void StdCmdMeasurementSimple::activated(int iMsg) updateActive(); commitCommand(); } +//=========================================================================== +// Std_UnitsCalculater +//=========================================================================== +DEF_STD_CMD(StdCmdUnitsCalculator); + +StdCmdUnitsCalculator::StdCmdUnitsCalculator() + : Command("Std_UnitsCalculater") +{ + sGroup = QT_TR_NOOP("Tools"); + sMenuText = QT_TR_NOOP("&Units calculator..."); + sToolTipText = QT_TR_NOOP("Start the units calculator"); + sWhatsThis = QT_TR_NOOP("Start the units calculator"); + sStatusTip = QT_TR_NOOP("Start the units calculator"); + //sPixmap = ""; + eType = 0; +} + +void StdCmdUnitsCalculator::activated(int iMsg) +{ + Gui::Dialog::DlgUnitsCalculator *dlg = new Gui::Dialog::DlgUnitsCalculator( getMainWindow() ); + dlg->show(); +} namespace Gui { @@ -673,6 +696,7 @@ void CreateStdCommands(void) rcCmdMgr.addCommand(new StdCmdFreeCADForum()); rcCmdMgr.addCommand(new StdCmdFreeCADFAQ()); rcCmdMgr.addCommand(new StdCmdPythonWebsite()); + rcCmdMgr.addCommand(new StdCmdUnitsCalculator()); //rcCmdMgr.addCommand(new StdCmdMeasurementSimple()); //rcCmdMgr.addCommand(new StdCmdDownloadOnlineHelp()); //rcCmdMgr.addCommand(new StdCmdDescription()); diff --git a/src/Gui/DlgUnitsCalculator.ui b/src/Gui/DlgUnitsCalculator.ui new file mode 100644 index 000000000..480c4b102 --- /dev/null +++ b/src/Gui/DlgUnitsCalculator.ui @@ -0,0 +1,124 @@ + + + DlgUnitCalculator + + + + 0 + 0 + 375 + 139 + + + + Units calculater + + + + + + + + + 100 + 0 + + + + + + + + as: + + + + + + + + 100 + 0 + + + + + + + + => + + + + + + + + 150 + 0 + + + + true + + + + + + + + + true + + + + + + + + + Help + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Copy + + + + + + + Close + + + + + + + + + + Gui::InputField + QLineEdit +
Gui/InputField.h
+
+
+ + +
diff --git a/src/Gui/DlgUnitsCalculatorImp.cpp b/src/Gui/DlgUnitsCalculatorImp.cpp new file mode 100644 index 000000000..6d6900b5b --- /dev/null +++ b/src/Gui/DlgUnitsCalculatorImp.cpp @@ -0,0 +1,137 @@ +/*************************************************************************** + * Copyright (c) 2013 Jürgen Riegel * + * * + * 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., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#include "PreCompiled.h" +#ifndef _PreComp_ +#endif + +#include "DlgUnitsCalculatorImp.h" + +using namespace Gui::Dialog; + +/* TRANSLATOR Gui::Dialog::DlgUnitsCalculator */ + +/** + * Constructs a DlgUnitsCalculator which is a child of 'parent', with the + * name 'name' and widget flags set to 'f' + * + * The dialog will by default be modeless, unless you set 'modal' to + * TRUE to construct a modal dialog. + */ +DlgUnitsCalculator::DlgUnitsCalculator( QWidget* parent, Qt::WFlags fl ) + : QDialog( parent, fl ) +{ + // create widgets + setupUi(this); + + connect(this->ValueInput, SIGNAL(valueChanged(Base::Quantity)), this, SLOT(valueChanged(Base::Quantity))); + connect(this->UnitInput, SIGNAL(valueChanged(Base::Quantity)), this, SLOT(unitValueChanged(Base::Quantity))); + + connect(this->pushButton_Help, SIGNAL(pressed()), this, SLOT(help())); + connect(this->pushButton_Close, SIGNAL(pressed()), this, SLOT(accept())); + connect(this->pushButton_Copy, SIGNAL(pressed()), this, SLOT(copy())); + + connect(this->ValueInput, SIGNAL(parseError(QString)), this, SLOT(parseError(QString))); + connect(this->UnitInput, SIGNAL(parseError(QString)), this, SLOT(parseError(QString))); + + actUnit.setInvalid(); +} + +/** Destroys the object and frees any allocated resources */ +DlgUnitsCalculator::~DlgUnitsCalculator() +{ +} + + +void DlgUnitsCalculator::accept() +{ + + QDialog::accept(); + delete this; +} + +void DlgUnitsCalculator::reject() +{ + + QDialog::reject(); + delete this; +} + +void DlgUnitsCalculator::unitValueChanged(const Base::Quantity& unit) +{ + actUnit = unit; + valueChanged(actValue); +} + +void DlgUnitsCalculator::valueChanged(const Base::Quantity& quant) +{ + + if(actUnit.isValid()){ + + double value = quant.getValue()/actUnit.getValue(); + QString out(QString::fromAscii("%1 %2")); + out = out.arg(value).arg(this->UnitInput->text()); + this->ValueOutput->setText(out); + QPalette *palette = new QPalette(); + palette->setColor(QPalette::Base,QColor(200,255,200)); + this->ValueOutput->setPalette(*palette); + + }else{ + //this->ValueOutput->setValue(quant); + this->ValueOutput->setText(QString::fromAscii(quant.getUserString().c_str())); + QPalette *palette = new QPalette(); + palette->setColor(QPalette::Base,QColor(200,255,200)); + this->ValueOutput->setPalette(*palette); + } + actValue = quant; + +} + +void DlgUnitsCalculator::parseError(const QString& errorText) +{ + + + QPalette *palette = new QPalette(); + palette->setColor(QPalette::Base,QColor(255,200,200)); + this->ValueOutput->setPalette(*palette); + + this->ValueOutput->setText(QString()); + +} +void DlgUnitsCalculator::copy(void) +{ + //TODO: copy the value to the clipboard + QDialog::accept(); + delete this; + +} + +void DlgUnitsCalculator::help(void) +{ + //TODO: call help page Std_UnitsCalculator +} + + + + +#include "moc_DlgUnitsCalculatorImp.cpp" diff --git a/src/Gui/DlgUnitsCalculatorImp.h b/src/Gui/DlgUnitsCalculatorImp.h new file mode 100644 index 000000000..fbe3cfe93 --- /dev/null +++ b/src/Gui/DlgUnitsCalculatorImp.h @@ -0,0 +1,66 @@ +/*************************************************************************** + * Copyright (c) 2013 Jürgen Riegel * + * * + * 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., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#ifndef GUI_DIALOG_DlgActivateWindowImp_H +#define GUI_DIALOG_DlgActivateWindowImp_H + +#include "ui_DlgUnitsCalculator.h" + +namespace Gui { +namespace Dialog { + +/** + * The DlgUnitsCalculator provides a unit conversion dialog + * \author Juergen Riegel + */ +class DlgUnitsCalculator : public QDialog, public Ui_DlgUnitCalculator +{ + Q_OBJECT + +public: + DlgUnitsCalculator( QWidget* parent = 0, Qt::WFlags fl = 0 ); + ~DlgUnitsCalculator(); + +protected: + void accept(); + void reject(); + +protected Q_SLOTS: + void unitValueChanged(const Base::Quantity&); + void valueChanged(const Base::Quantity&); + + void copy(void); + void help(void); + + void parseError(const QString& errorText); + +private: + Base::Quantity actValue; + Base::Quantity actUnit; + +}; + +} // namespace Dialog +} // namespace Gui + +#endif // GUI_DIALOG_DlgActivateWindowImp_H diff --git a/src/Gui/InputField.cpp b/src/Gui/InputField.cpp index 91e305fa8..157c2ed60 100644 --- a/src/Gui/InputField.cpp +++ b/src/Gui/InputField.cpp @@ -24,49 +24,157 @@ #include "PreCompiled.h" #include +#include +#include +#include #include "InputField.h" using namespace Gui; +using namespace Base; // -------------------------------------------------------------------- InputField::InputField ( QWidget * parent ) : QLineEdit(parent) { + this->setContextMenuPolicy(Qt::DefaultContextMenu); + + QObject::connect(this, SIGNAL(textChanged (QString)), + this, SLOT(newInput(QString))); } InputField::~InputField() { } +void InputField::contextMenuEvent(QContextMenuEvent *event) +{ + QMenu *menu = createStandardContextMenu(); + QAction *saveAction = menu->addAction(tr("My Menu Item")); + //... + QAction *saveAction2 = menu->exec(event->globalPos()); + delete menu; +} +void InputField::newInput(const QString & text) +{ + Quantity res; + try{ + res = Quantity::parse(text.toAscii()); + }catch(Base::Exception &e){ + ErrorText = e.what(); + this->setToolTip(QString::fromAscii(ErrorText.c_str())); + QPalette *palette = new QPalette(); + palette->setColor(QPalette::Base,QColor(255,200,200)); + setPalette(*palette); + parseError(QString::fromAscii(ErrorText.c_str())); + return; + } + QPalette *palette = new QPalette(); + palette->setColor(QPalette::Base,QColor(200,255,200)); + setPalette(*palette); + ErrorText = ""; + this->setToolTip(QString::fromAscii(ErrorText.c_str())); + // signaling + valueChanged(res); + +} + +void InputField::pushToHistory(std::string value) +{ + if(_handle.isValid()){ + _handle->SetASCII("Hist1",_handle->GetASCII("Hist0","").c_str()); + _handle->SetASCII("Hist0",value.c_str()); + } +} + +std::vector InputField::getHistory(void) +{ + std::vector res; + + if(_handle.isValid()){ + std::string tmp; + tmp = _handle->GetASCII("Hist0",""); + if( tmp != ""){ + res.push_back(tmp); + tmp = _handle->GetASCII("Hist1",""); + if( tmp != ""){ + res.push_back(tmp); + //tmp = _handle->GetASCII("Hist2",""); + } + } + } + return res; +} /** Sets the preference path to \a path. */ void InputField::setParamGrpPath( const QByteArray& path ) { -//#ifdef FC_DEBUG -// if (getWindowParameter().isValid()) -// { -// if ( paramGrpPath() != path ) -// Base::Console().Warning("Widget already attached\n"); -// } -//#endif -// -// if ( paramGrpPath() != path ) -// { -// if ( setGroupName( path ) ) -// { -// m_sPrefGrp = path; -// assert(getWindowParameter().isValid()); -// getWindowParameter()->Attach(this); -// } -// } + + _handle = App::GetApplication().GetParameterGroupByPath( path); + if(_handle.isValid()) + sGroupString = path; + } /** Returns the widget's preferences path. */ QByteArray InputField::paramGrpPath() const { - return m_sPrefGrp; + if(_handle.isValid()) + return sGroupString.c_str(); +} + +/// sets the field with a quantity +void InputField::setValue(const Base::Quantity& quant) +{ + actQuantity = quant; + if(!quant.getUnit().isEmpty()) + actUnit = quant.getUnit(); + + setText(QString::fromAscii(quant.getUserString().c_str())); +} + +void InputField::setUnit(const Base::Unit& unit) +{ + actUnit = unit; +} + + + +/// get the value of the singleStep property +double InputField::singleStep(void)const +{ + return 0.0; +} + +/// set the value of the singleStep property +void InputField::setSingleStep(double) +{ + +} + +/// get the value of the maximum property +double InputField::maximum(void)const +{ + return 0.0; +} + +/// set the value of the maximum property +void InputField::setMaximum(double) +{ + +} + +/// get the value of the minimum property +double InputField::minimum(void)const +{ + return 0.0; +} + +/// set the value of the minimum property +void InputField::setMinimum(double) +{ + } diff --git a/src/Gui/InputField.h b/src/Gui/InputField.h index 0e7ee8a4d..f0274028f 100644 --- a/src/Gui/InputField.h +++ b/src/Gui/InputField.h @@ -25,6 +25,7 @@ #define GUI_INPUTFIELD_H #include +#include #include "Widgets.h" #include "Window.h" #include "SpinBox.h" @@ -34,28 +35,99 @@ namespace Gui { /** - * The InputField class. + * The InputField class + * The input field widget handles all around user input of Quantities. Thats + * include parsing and checking input. Providing a context menu for common operations + * and managing default and history values. + * Although its derived from a QLineEdit widget, its supports most of the properties and signals + * of a * \author Jürgen Riegel */ class GuiExport InputField : public QLineEdit { Q_OBJECT - Q_PROPERTY( QByteArray prefPath READ paramGrpPath WRITE setParamGrpPath ) + Q_PROPERTY( QByteArray prefPath READ paramGrpPath WRITE setParamGrpPath ) + Q_PROPERTY(double singleStep READ singleStep WRITE setSingleStep ) + Q_PROPERTY(double maximum READ maximum WRITE setMaximum ) + Q_PROPERTY(double minimum READ minimum WRITE setMinimum ) + public: InputField ( QWidget * parent = 0 ); virtual ~InputField(); - // PROPERTIES - // getters + /// sets the field with a quantity + void setValue(const Base::Quantity&); + /** sets the Unit this field working with. + * After seting the Unit the field will only acceppt + * user input with this unit type. Or if the user input + * a value without unit, this one will be added to the resulting + * Quantity. + */ + void setUnit(const Base::Unit&); + + /// get the value of the singleStep property + double singleStep(void)const; + /// set the value of the singleStep property + void setSingleStep(double); + /// get the value of the maximum property + double maximum(void)const; + /// set the value of the maximum property + void setMaximum(double); + /// get the value of the minimum property + double minimum(void)const; + /// set the value of the minimum property + void setMinimum(double); + + /** @name history and default management */ + //@{ + /// the param group path where the widget write and read the dafault values QByteArray paramGrpPath () const; - // setters + /// set the param group path where the widget write and read the dafault values void setParamGrpPath ( const QByteArray& name ); + /// push a new value to the history + void pushToHistory(std::string value); + /// get the history of the field, newest first + std::vector getHistory(void); + //@} + + +Q_SIGNALS: + /** gets emited if the user has entered a VALID input + * Valid means the user inputed string obays all restrictions + * like: minimum, maximum and/or the right Unit (if specified). + * If you want the unfiltered/unvalidated input use valueChanged(const QString&) + * instead: + */ + void valueChanged(const Base::Quantity&); + /** gets emited if the user has entered a VALID input + * Valid means the user inputed string obays all restrictions + * like: minimum, maximum and/or the right Unit (if specified). + * If you want the unfiltered/unvalidated input use valueChanged(const QString&) + * instead: + */ + void valueChanged(double); + + /// signal for an invalid user input (signals a lot while typing!) + void parseError(const QString& errorText); + +protected Q_SLOTS: + void newInput(const QString & text); + +protected: + virtual void contextMenuEvent ( QContextMenuEvent * event ); private: QByteArray m_sPrefGrp; + std::string ErrorText; + /// handle to the parameter group for defaults and history + ParameterGrp::handle _handle; + std::string sGroupString; + + Base::Quantity actQuantity; + Base::Unit actUnit; }; diff --git a/src/Gui/Workbench.cpp b/src/Gui/Workbench.cpp index 13ee7d523..8a40656cb 100644 --- a/src/Gui/Workbench.cpp +++ b/src/Gui/Workbench.cpp @@ -492,7 +492,7 @@ MenuItem* StdWorkbench::setupMenuBar() const *tool << "Std_DlgParameter" << "Separator" << "Std_ViewScreenShot" << "Std_SceneInspector" << "Std_ExportGraphviz" << "Std_ProjectUtil" - << "Std_DemoMode" << "Separator" << "Std_DlgCustomize"; + << "Std_DemoMode" << "Std_UnitsCalculater" << "Separator" << "Std_DlgCustomize"; // Macro MenuItem* macro = new MenuItem( menuBar ); diff --git a/src/Mod/Sketcher/Gui/EditDatumDialog.cpp b/src/Mod/Sketcher/Gui/EditDatumDialog.cpp index 31a60bced..cae9d5c48 100644 --- a/src/Mod/Sketcher/Gui/EditDatumDialog.cpp +++ b/src/Mod/Sketcher/Gui/EditDatumDialog.cpp @@ -93,6 +93,8 @@ void EditDatumDialog::exec(bool atCursor) Ui::InsertDatum ui_ins_datum; ui_ins_datum.setupUi(&dlg); + //ui_ins_datum.lineEdit->setParamGrpPath("User parameter:History/Sketcher/SetDatum"); + double init_val; if (Constr->Type == Sketcher::Angle || ((Constr->Type == Sketcher::DistanceX || Constr->Type == Sketcher::DistanceY) && diff --git a/src/Mod/Sketcher/Gui/InsertDatum.ui b/src/Mod/Sketcher/Gui/InsertDatum.ui index 7ffa41be5..d27befec3 100644 --- a/src/Mod/Sketcher/Gui/InsertDatum.ui +++ b/src/Mod/Sketcher/Gui/InsertDatum.ui @@ -44,7 +44,15 @@ - + + + Gui::InputField + QLineEdit +
Gui/InputField.h
+
+
+ + buttonBox accepted()