implementation classes don't inherit from UI classes

This commit is contained in:
wmayer
2020-01-12 01:09:25 +01:00
committed by wwmayer
parent f97eb7026d
commit 5673d299f9
6 changed files with 233 additions and 16 deletions

View File

@@ -256,4 +256,36 @@ void LocationDialog::on_direction_activated(int index)
directionActivated(index);
}
// -----------------------------------------------------------
LocationDialogUiImp::~LocationDialogUiImp()
{
// no need to delete child widgets, Qt does it all for us
}
Base::Vector3d LocationDialogUiImp::getDirection() const
{
return ui->getDirection();
}
Base::Vector3d LocationDialogUiImp::getPosition() const
{
return ui->getPosition();
}
void LocationDialogUiImp::changeEvent(QEvent *e)
{
if (e->type() == QEvent::LanguageChange) {
ui->retranslate(this);
}
else {
QDialog::changeEvent(e);
}
}
void LocationDialogUiImp::directionActivated(int index)
{
ui->directionActivated(this,index);
}
#include "moc_InputVector.cpp"

View File

@@ -24,6 +24,8 @@
#define GUI_INPUTVECTOR_H
#include <cfloat>
#include <memory>
#include <boost/any.hpp>
#include <QDialog>
#include <QMessageBox>
#include <QApplication>
@@ -399,6 +401,184 @@ 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 LocationDialogUiImp : public LocationDialog
{
public:
template<class T>
LocationDialogUiImp(T* t, QWidget* parent = 0, Qt::WindowFlags fl = 0)
: 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

View File

@@ -26,6 +26,7 @@
#endif
#include "DlgPartBoxImp.h"
#include "ui_DlgPartBox.h"
using namespace PartGui;
@@ -37,7 +38,7 @@ using namespace PartGui;
* true to construct a modal dialog.
*/
DlgPartBoxImp::DlgPartBoxImp(QWidget* parent, Qt::WindowFlags fl)
: Gui::LocationDialogUi<Ui_DlgPartBox>(parent, fl)
: Gui::LocationDialogUiImp(new Ui_DlgPartBox, parent, fl)
{
}

View File

@@ -23,12 +23,13 @@
#ifndef PARTGUI_DLGPARTBOXIMP_H
#define PARTGUI_DLGPARTBOXIMP_H
#include "ui_DlgPartBox.h"
#include <Gui/InputVector.h>
namespace PartGui {
class Ui_DlgPartBox;
typedef std::shared_ptr<Ui_DlgPartBox> Ui_DlgPartBoxPtr;
class DlgPartBoxImp : public Gui::LocationDialogUi<Ui_DlgPartBox>
class DlgPartBoxImp : public Gui::LocationDialogUiImp
{
Q_OBJECT

View File

@@ -26,22 +26,16 @@
#endif
#include "DlgPartCylinderImp.h"
#include "ui_DlgPartCylinder.h"
using namespace PartGui;
/*
* Constructs a DlgPartCylinder 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.
*/
DlgPartCylinderImp::DlgPartCylinderImp(QWidget* parent, Qt::WindowFlags fl)
: Gui::LocationDialogUi<Ui_DlgPartCylinder>(parent, fl)
: Gui::LocationDialogUiImp(new Ui_DlgPartCylinder, parent, fl)
{
}
/*
/*
* Destroys the object and frees any allocated resources
*/
DlgPartCylinderImp::~DlgPartCylinderImp()
@@ -49,14 +43,19 @@ DlgPartCylinderImp::~DlgPartCylinderImp()
// no need to delete child widgets, Qt does it all for us
}
Ui_DlgPartCylinderPtr DlgPartCylinderImp::getUi() const
{
return boost::any_cast< Ui_DlgPartCylinderPtr >(ui->get());
}
double DlgPartCylinderImp::getRadius() const
{
return this->radius->value().getValue();
return getUi()->radius->value().getValue();
}
double DlgPartCylinderImp::getLength() const
{
return this->length->value().getValue();
return getUi()->length->value().getValue();
}
#include "moc_DlgPartCylinderImp.cpp"

View File

@@ -23,12 +23,13 @@
#ifndef PARTGUI_DLGPARTCYLINDERIMP_H
#define PARTGUI_DLGPARTCYLINDERIMP_H
#include "ui_DlgPartCylinder.h"
#include <Gui/InputVector.h>
namespace PartGui {
class Ui_DlgPartCylinder;
typedef std::shared_ptr<Ui_DlgPartCylinder> Ui_DlgPartCylinderPtr;
class DlgPartCylinderImp : public Gui::LocationDialogUi<Ui_DlgPartCylinder>
class DlgPartCylinderImp : public Gui::LocationDialogUiImp
{
Q_OBJECT
@@ -38,6 +39,9 @@ public:
double getRadius() const;
double getLength() const;
private:
Ui_DlgPartCylinderPtr getUi() const;
};
} // namespace PartGui