That is need on MacOS build as travis log is bigger than 50k lines which breaks travis rules And by the way deprecations are real All file contains the same modification replace 0 to Qt::WindowFlags() when needed as the class needs to be instantiated Signed-off-by: vejmarie <jmverdun3@gmail.com>
585 lines
20 KiB
C++
585 lines
20 KiB
C++
/***************************************************************************
|
|
* Copyright (c) 2008 Werner Mayer <wmayer[at]users.sourceforge.net> *
|
|
* *
|
|
* 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_INPUTVECTOR_H
|
|
#define GUI_INPUTVECTOR_H
|
|
|
|
#include <cfloat>
|
|
#include <memory>
|
|
#include <boost/any.hpp>
|
|
#include <QDialog>
|
|
#include <QMessageBox>
|
|
#include <QApplication>
|
|
|
|
#include <Gui/propertyeditor/PropertyItem.h>
|
|
|
|
class QGridLayout;
|
|
class QLabel;
|
|
class QDoubleSpinBox;
|
|
class QComboBox;
|
|
|
|
namespace Gui {
|
|
class QuantitySpinBox;
|
|
|
|
class GuiExport LocationWidget : public QWidget
|
|
{
|
|
Q_OBJECT
|
|
|
|
public:
|
|
LocationWidget (QWidget * parent = 0);
|
|
virtual ~LocationWidget();
|
|
QSize sizeHint() const;
|
|
|
|
Base::Vector3d getPosition() const;
|
|
void setPosition(const Base::Vector3d&);
|
|
void setDirection(const Base::Vector3d& dir);
|
|
Base::Vector3d getDirection() const;
|
|
Base::Vector3d getUserDirection(bool* ok=0) const;
|
|
|
|
private Q_SLOTS:
|
|
void on_direction_activated(int);
|
|
|
|
private:
|
|
void changeEvent(QEvent*);
|
|
void retranslateUi();
|
|
|
|
private:
|
|
QGridLayout *box;
|
|
QLabel *xLabel;
|
|
QLabel *yLabel;
|
|
QLabel *zLabel;
|
|
QLabel *dLabel;
|
|
QuantitySpinBox *xValue;
|
|
QuantitySpinBox *yValue;
|
|
QuantitySpinBox *zValue;
|
|
QComboBox *dValue;
|
|
};
|
|
|
|
/** This is the abstract base dialog class that defines the interface for
|
|
* specifying a direction vector by the user.
|
|
* @author Werner Mayer
|
|
*/
|
|
class GuiExport LocationDialog : public QDialog
|
|
{
|
|
Q_OBJECT
|
|
|
|
protected:
|
|
LocationDialog(QWidget* parent = 0, Qt::WindowFlags fl = Qt::WindowFlags());
|
|
virtual ~LocationDialog();
|
|
|
|
protected:
|
|
virtual void changeEvent(QEvent *e) = 0;
|
|
|
|
private Q_SLOTS:
|
|
void on_direction_activated(int);
|
|
|
|
public:
|
|
virtual Base::Vector3d getDirection() const = 0;
|
|
Base::Vector3d getUserDirection(bool* ok=0) const;
|
|
|
|
private:
|
|
virtual void directionActivated(int) = 0;
|
|
};
|
|
|
|
/* TRANSLATOR Gui::LocationDialog */
|
|
|
|
/** This is the template class that implements the interface of LocationDialog.
|
|
* The template argument can be the Ui interface class built by uic out of a
|
|
* .ui file.
|
|
* This class might be very useful for dialogs where a combo box is used to
|
|
* define a direction vector by the user. For such classes the programmer doesn't
|
|
* have to write a subclass to implement the appropriate signals/slots. Instead it's
|
|
* possible to omit this further class and use LocationDialogUi parametrized
|
|
* with the generated Ui class.
|
|
* @author Werner Mayer
|
|
*/
|
|
template <class Ui>
|
|
class LocationDialogUi : public LocationDialog, public Ui
|
|
{
|
|
public:
|
|
LocationDialogUi(QWidget* parent = 0, Qt::WindowFlags fl = Qt::WindowFlags()) : LocationDialog(parent, fl)
|
|
{
|
|
this->setupUi(this);
|
|
this->retranslate();
|
|
}
|
|
virtual ~LocationDialogUi(){}
|
|
|
|
void retranslate()
|
|
{
|
|
Ui::retranslateUi(this);
|
|
|
|
if (this->direction->count() == 0) {
|
|
this->direction->insertItems(0, QStringList()
|
|
<< QApplication::translate("Gui::LocationDialog", "X")
|
|
<< QApplication::translate("Gui::LocationDialog", "Y")
|
|
<< QApplication::translate("Gui::LocationDialog", "Z")
|
|
<< QApplication::translate("Gui::LocationDialog", "User defined...")
|
|
);
|
|
|
|
this->direction->setCurrentIndex(2);
|
|
|
|
// Vector3d declared to use with QVariant see Gui/propertyeditor/PropertyItem.h
|
|
this->direction->setItemData(0, QVariant::fromValue<Base::Vector3d>(Base::Vector3d(1,0,0)));
|
|
this->direction->setItemData(1, QVariant::fromValue<Base::Vector3d>(Base::Vector3d(0,1,0)));
|
|
this->direction->setItemData(2, QVariant::fromValue<Base::Vector3d>(Base::Vector3d(0,0,1)));
|
|
}
|
|
else {
|
|
this->direction->setItemText(0, QApplication::translate("Gui::LocationDialog", "X"));
|
|
this->direction->setItemText(1, QApplication::translate("Gui::LocationDialog", "Y"));
|
|
this->direction->setItemText(2, QApplication::translate("Gui::LocationDialog", "Z"));
|
|
this->direction->setItemText(this->direction->count()-1,
|
|
QApplication::translate("Gui::LocationDialog", "User defined..."));
|
|
}
|
|
}
|
|
|
|
void setPosition(const Base::Vector3d& v)
|
|
{
|
|
this->xPos->setValue(v.x);
|
|
this->yPos->setValue(v.y);
|
|
this->zPos->setValue(v.z);
|
|
}
|
|
|
|
Base::Vector3d getPosition() const
|
|
{
|
|
return Base::Vector3d(this->xPos->value().getValue(),
|
|
this->yPos->value().getValue(),
|
|
this->zPos->value().getValue());
|
|
}
|
|
|
|
Base::Vector3d getDirection() const
|
|
{
|
|
QVariant data = this->direction->itemData (this->direction->currentIndex());
|
|
if (data.canConvert<Base::Vector3d>()) {
|
|
return data.value<Base::Vector3d>();
|
|
}
|
|
else {
|
|
return Base::Vector3d(0,0,1);
|
|
}
|
|
}
|
|
|
|
protected:
|
|
void changeEvent(QEvent *e)
|
|
{
|
|
if (e->type() == QEvent::LanguageChange) {
|
|
this->retranslate();
|
|
}
|
|
else {
|
|
QDialog::changeEvent(e);
|
|
}
|
|
}
|
|
|
|
private:
|
|
void setDirection(const Base::Vector3d& dir)
|
|
{
|
|
if (dir.Length() < Base::Vector3d::epsilon()) {
|
|
return;
|
|
}
|
|
|
|
// check if the user-defined direction is already there
|
|
for (int i=0; i<this->direction->count()-1; i++) {
|
|
QVariant data = this->direction->itemData (i);
|
|
if (data.canConvert<Base::Vector3d>()) {
|
|
const Base::Vector3d val = data.value<Base::Vector3d>();
|
|
if (val == dir) {
|
|
this->direction->setCurrentIndex(i);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
// add a new item before the very last item
|
|
QString display = QString::fromLatin1("(%1,%2,%3)")
|
|
.arg(dir.x)
|
|
.arg(dir.y)
|
|
.arg(dir.z);
|
|
this->direction->insertItem(this->direction->count()-1, display,
|
|
QVariant::fromValue<Base::Vector3d>(dir));
|
|
this->direction->setCurrentIndex(this->direction->count()-2);
|
|
}
|
|
void directionActivated(int index)
|
|
{
|
|
// last item is selected to define direction by user
|
|
if (index+1 == this->direction->count()) {
|
|
bool ok;
|
|
Base::Vector3d dir = this->getUserDirection(&ok);
|
|
if (ok) {
|
|
if (dir.Length() < Base::Vector3d::epsilon()) {
|
|
QMessageBox::critical(this, LocationDialog::tr("Wrong direction"),
|
|
LocationDialog::tr("Direction must not be the null vector"));
|
|
return;
|
|
}
|
|
|
|
setDirection(dir);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
/** This template class does basically the same as LocationDialogUi unless
|
|
* that it doesn inherit from a widget but only from the UI_-generated class.
|
|
* Thus, this class can be used as composition in dialog-based classes without
|
|
* including the ui_-generated header file. The Ui_-class can simply be forward
|
|
* declared, then.
|
|
* @author Werner Mayer
|
|
*/
|
|
template <class Ui>
|
|
class LocationUi : public Ui
|
|
{
|
|
public:
|
|
LocationUi(QDialog *dlg)
|
|
{
|
|
this->setupUi(dlg);
|
|
this->retranslate(dlg);
|
|
}
|
|
~LocationUi()
|
|
{
|
|
}
|
|
|
|
void retranslate(QDialog *dlg)
|
|
{
|
|
Ui::retranslateUi(dlg);
|
|
|
|
if (this->direction->count() == 0) {
|
|
this->direction->insertItems(0, QStringList()
|
|
<< QApplication::translate("Gui::LocationDialog", "X")
|
|
<< QApplication::translate("Gui::LocationDialog", "Y")
|
|
<< QApplication::translate("Gui::LocationDialog", "Z")
|
|
<< QApplication::translate("Gui::LocationDialog", "User defined...")
|
|
);
|
|
|
|
this->direction->setCurrentIndex(2);
|
|
|
|
// Vector3d declared to use with QVariant see Gui/propertyeditor/PropertyItem.h
|
|
this->direction->setItemData(0, QVariant::fromValue<Base::Vector3d>(Base::Vector3d(1,0,0)));
|
|
this->direction->setItemData(1, QVariant::fromValue<Base::Vector3d>(Base::Vector3d(0,1,0)));
|
|
this->direction->setItemData(2, QVariant::fromValue<Base::Vector3d>(Base::Vector3d(0,0,1)));
|
|
}
|
|
else {
|
|
this->direction->setItemText(0, QApplication::translate("Gui::LocationDialog", "X"));
|
|
this->direction->setItemText(1, QApplication::translate("Gui::LocationDialog", "Y"));
|
|
this->direction->setItemText(2, QApplication::translate("Gui::LocationDialog", "Z"));
|
|
this->direction->setItemText(this->direction->count()-1,
|
|
QApplication::translate("Gui::LocationDialog", "User defined..."));
|
|
}
|
|
}
|
|
|
|
void setPosition(const Base::Vector3d& v)
|
|
{
|
|
this->xPos->setValue(v.x);
|
|
this->yPos->setValue(v.y);
|
|
this->zPos->setValue(v.z);
|
|
}
|
|
|
|
Base::Vector3d getPosition() const
|
|
{
|
|
return Base::Vector3d(this->xPos->value().getValue(),
|
|
this->yPos->value().getValue(),
|
|
this->zPos->value().getValue());
|
|
}
|
|
|
|
Base::Vector3d getDirection() const
|
|
{
|
|
QVariant data = this->direction->itemData (this->direction->currentIndex());
|
|
if (data.canConvert<Base::Vector3d>()) {
|
|
return data.value<Base::Vector3d>();
|
|
}
|
|
else {
|
|
return Base::Vector3d(0,0,1);
|
|
}
|
|
}
|
|
|
|
public:
|
|
void setDirection(const Base::Vector3d& dir)
|
|
{
|
|
if (dir.Length() < Base::Vector3d::epsilon()) {
|
|
return;
|
|
}
|
|
|
|
// check if the user-defined direction is already there
|
|
for (int i=0; i<this->direction->count()-1; i++) {
|
|
QVariant data = this->direction->itemData (i);
|
|
if (data.canConvert<Base::Vector3d>()) {
|
|
const Base::Vector3d val = data.value<Base::Vector3d>();
|
|
if (val == dir) {
|
|
this->direction->setCurrentIndex(i);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
// add a new item before the very last item
|
|
QString display = QString::fromLatin1("(%1,%2,%3)")
|
|
.arg(dir.x)
|
|
.arg(dir.y)
|
|
.arg(dir.z);
|
|
this->direction->insertItem(this->direction->count()-1, display,
|
|
QVariant::fromValue<Base::Vector3d>(dir));
|
|
this->direction->setCurrentIndex(this->direction->count()-2);
|
|
}
|
|
bool directionActivated(LocationDialog* dlg, int index)
|
|
{
|
|
// last item is selected to define direction by user
|
|
if (index+1 == this->direction->count()) {
|
|
bool ok;
|
|
Base::Vector3d dir = dlg->getUserDirection(&ok);
|
|
if (ok) {
|
|
if (dir.Length() < Base::Vector3d::epsilon()) {
|
|
QMessageBox::critical(dlg, LocationDialog::tr("Wrong direction"),
|
|
LocationDialog::tr("Direction must not be the null vector"));
|
|
return false;
|
|
}
|
|
setDirection(dir);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
};
|
|
|
|
/** This template class is a subclass of LocationDialog using LocationUi
|
|
* and implements the pure virtual methods of its base class.
|
|
* Other dialog-based classes can directly inherit from this class if the
|
|
* location-interface is required. But note, in this case the ui_-header file
|
|
* needs to be included. If this should be avoided the class LocationUi
|
|
* must be used instead of whereas the Ui_-class can be forward declared.
|
|
* @author Werner Mayer
|
|
*/
|
|
template <class Ui>
|
|
class LocationDialogImp : public LocationDialog
|
|
{
|
|
public:
|
|
LocationDialogImp(QWidget* parent = 0, Qt::WindowFlags fl = Qt::WindowFlags())
|
|
: LocationDialog(parent, fl), ui(this)
|
|
{
|
|
}
|
|
virtual ~LocationDialogImp()
|
|
{
|
|
// no need to delete child widgets, Qt does it all for us
|
|
}
|
|
|
|
Base::Vector3d getDirection() const
|
|
{
|
|
return ui.getDirection();
|
|
}
|
|
|
|
protected:
|
|
void changeEvent(QEvent *e)
|
|
{
|
|
if (e->type() == QEvent::LanguageChange) {
|
|
ui.retranslate(this);
|
|
}
|
|
else {
|
|
QDialog::changeEvent(e);
|
|
}
|
|
}
|
|
|
|
private:
|
|
void directionActivated(int index)
|
|
{
|
|
ui.directionActivated(this,index);
|
|
}
|
|
|
|
protected:
|
|
LocationUi<Ui> ui;
|
|
};
|
|
|
|
/**
|
|
* @brief The AbstractUi class
|
|
* Abstract base class the defines the class interface.
|
|
* @author Werner Mayer
|
|
*/
|
|
class AbstractUi
|
|
{
|
|
public:
|
|
virtual ~AbstractUi() = default;
|
|
virtual void retranslate(QDialog *dlg) = 0;
|
|
virtual void setPosition(const Base::Vector3d& v) = 0;
|
|
virtual Base::Vector3d getPosition() const = 0;
|
|
virtual Base::Vector3d getDirection() const = 0;
|
|
virtual void setDirection(const Base::Vector3d& dir) = 0;
|
|
virtual bool directionActivated(LocationDialog* dlg, int index) = 0;
|
|
virtual boost::any get() = 0;
|
|
};
|
|
|
|
/** This is the template class that implements the interface of AbstractUi.
|
|
* The template argument is the Ui interface class built by uic out of a
|
|
* .ui file.
|
|
* @author Werner Mayer
|
|
*/
|
|
template <class Ui>
|
|
class LocationImpUi : public AbstractUi
|
|
{
|
|
public:
|
|
LocationImpUi(Ui* ui) : ui(ui)
|
|
{
|
|
}
|
|
~LocationImpUi()
|
|
{
|
|
}
|
|
|
|
boost::any get()
|
|
{
|
|
return ui;
|
|
}
|
|
|
|
void retranslate(QDialog *dlg)
|
|
{
|
|
ui->retranslateUi(dlg);
|
|
|
|
if (ui->direction->count() == 0) {
|
|
ui->direction->insertItems(0, QStringList()
|
|
<< QApplication::translate("Gui::LocationDialog", "X")
|
|
<< QApplication::translate("Gui::LocationDialog", "Y")
|
|
<< QApplication::translate("Gui::LocationDialog", "Z")
|
|
<< QApplication::translate("Gui::LocationDialog", "User defined...")
|
|
);
|
|
|
|
ui->direction->setCurrentIndex(2);
|
|
|
|
// Vector3d declared to use with QVariant see Gui/propertyeditor/PropertyItem.h
|
|
ui->direction->setItemData(0, QVariant::fromValue<Base::Vector3d>(Base::Vector3d(1,0,0)));
|
|
ui->direction->setItemData(1, QVariant::fromValue<Base::Vector3d>(Base::Vector3d(0,1,0)));
|
|
ui->direction->setItemData(2, QVariant::fromValue<Base::Vector3d>(Base::Vector3d(0,0,1)));
|
|
}
|
|
else {
|
|
ui->direction->setItemText(0, QApplication::translate("Gui::LocationDialog", "X"));
|
|
ui->direction->setItemText(1, QApplication::translate("Gui::LocationDialog", "Y"));
|
|
ui->direction->setItemText(2, QApplication::translate("Gui::LocationDialog", "Z"));
|
|
ui->direction->setItemText(ui->direction->count()-1,
|
|
QApplication::translate("Gui::LocationDialog", "User defined..."));
|
|
}
|
|
}
|
|
|
|
void setPosition(const Base::Vector3d& v)
|
|
{
|
|
ui->xPos->setValue(v.x);
|
|
ui->yPos->setValue(v.y);
|
|
ui->zPos->setValue(v.z);
|
|
}
|
|
|
|
Base::Vector3d getPosition() const
|
|
{
|
|
return Base::Vector3d(ui->xPos->value().getValue(),
|
|
ui->yPos->value().getValue(),
|
|
ui->zPos->value().getValue());
|
|
}
|
|
|
|
Base::Vector3d getDirection() const
|
|
{
|
|
QVariant data = ui->direction->itemData (ui->direction->currentIndex());
|
|
if (data.canConvert<Base::Vector3d>()) {
|
|
return data.value<Base::Vector3d>();
|
|
}
|
|
else {
|
|
return Base::Vector3d(0,0,1);
|
|
}
|
|
}
|
|
|
|
public:
|
|
void setDirection(const Base::Vector3d& dir)
|
|
{
|
|
if (dir.Length() < Base::Vector3d::epsilon()) {
|
|
return;
|
|
}
|
|
|
|
// check if the user-defined direction is already there
|
|
for (int i=0; i<ui->direction->count()-1; i++) {
|
|
QVariant data = ui->direction->itemData (i);
|
|
if (data.canConvert<Base::Vector3d>()) {
|
|
const Base::Vector3d val = data.value<Base::Vector3d>();
|
|
if (val == dir) {
|
|
ui->direction->setCurrentIndex(i);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
// add a new item before the very last item
|
|
QString display = QString::fromLatin1("(%1,%2,%3)")
|
|
.arg(dir.x)
|
|
.arg(dir.y)
|
|
.arg(dir.z);
|
|
ui->direction->insertItem(ui->direction->count()-1, display,
|
|
QVariant::fromValue<Base::Vector3d>(dir));
|
|
ui->direction->setCurrentIndex(ui->direction->count()-2);
|
|
}
|
|
bool directionActivated(LocationDialog* dlg, int index)
|
|
{
|
|
// last item is selected to define direction by user
|
|
if (index+1 == ui->direction->count()) {
|
|
bool ok;
|
|
Base::Vector3d dir = dlg->getUserDirection(&ok);
|
|
if (ok) {
|
|
if (dir.Length() < Base::Vector3d::epsilon()) {
|
|
QMessageBox::critical(dlg, LocationDialog::tr("Wrong direction"),
|
|
LocationDialog::tr("Direction must not be the null vector"));
|
|
return false;
|
|
}
|
|
setDirection(dir);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
private:
|
|
std::shared_ptr<Ui> ui;
|
|
};
|
|
|
|
/** This is a subclass of LocationDialog using AbstractUi that implements
|
|
* the pure virtual methods of its base class.
|
|
* Other dialog-based classes can directly inherit from this class if the
|
|
* location-interface is required.
|
|
* The advantage of this class compared to LocationDialogImp is that the
|
|
* ui_-header file doesn't need to be included in the header file of its
|
|
* sub-classes because it uses "type erasure with templates".
|
|
* @author Werner Mayer
|
|
*/
|
|
class GuiExport LocationDialogUiImp : public LocationDialog
|
|
{
|
|
public:
|
|
template<class T>
|
|
LocationDialogUiImp(T* t, QWidget* parent = 0, Qt::WindowFlags fl = Qt::WindowFlags())
|
|
: LocationDialog(parent, fl), ui(new LocationImpUi<T>(t))
|
|
{
|
|
std::shared_ptr<T> uit = boost::any_cast< std::shared_ptr<T> >(ui->get());
|
|
uit->setupUi(this);
|
|
ui->retranslate(this);
|
|
}
|
|
virtual ~LocationDialogUiImp();
|
|
|
|
Base::Vector3d getDirection() const;
|
|
|
|
Base::Vector3d getPosition() const;
|
|
|
|
protected:
|
|
void changeEvent(QEvent *e);
|
|
|
|
private:
|
|
void directionActivated(int index);
|
|
|
|
protected:
|
|
std::unique_ptr<AbstractUi> ui;
|
|
};
|
|
|
|
} // namespace Gui
|
|
|
|
#endif // GUI_INPUTVECTOR_H
|