Files

422 lines
9.3 KiB
C++
Raw Permalink Normal View History

2017-06-13 15:31:41 +02:00
#include "IntervalConditionModel.hpp"
#include <QtCore/QJsonValue>
#include <QtCore/QDebug>
#include <QtGui/QDoubleValidator>
#include <QtWidgets/QWidget>
#include <QtWidgets/QFormLayout>
#include <QtWidgets/QLabel>
#include <QtWidgets/QLineEdit>
#include "ExpressionRangeData.hpp"
#include "ExpressionBoolData.hpp"
IntervalConditionModel::
IntervalConditionModel()
{
_widget = new QWidget();
auto l = new QFormLayout();
//-------------
_interval1Label = new QLineEdit();
_interval1Label->setPlaceholderText("Interval1");
connect(_interval1Label, &QLineEdit::textChanged,
this, &IntervalConditionModel::onIntervalEdited);
_interval2Label = new QLineEdit();
_interval2Label->setPlaceholderText("Interval1");
connect(_interval2Label, &QLineEdit::textChanged,
this, &IntervalConditionModel::onIntervalEdited);
_interval3Label = new QLineEdit();
_interval3Label->setPlaceholderText("Interval1");
connect(_interval3Label, &QLineEdit::textChanged,
this, &IntervalConditionModel::onIntervalEdited);
_interval4Label = new QLineEdit();
_interval4Label->setPlaceholderText("Interval1");
connect(_interval4Label, &QLineEdit::textChanged,
this, &IntervalConditionModel::onIntervalEdited);
#if 0
_thenLabel = new QLabel();
_thenLabel->setMargin(3);
_thenLabel->setFrameStyle(QFrame::Panel | QFrame::Sunken);
//-------------
_elseLabel = new QLabel();
_elseLabel->setMargin(3);
_elseLabel->setFrameStyle(QFrame::Panel | QFrame::Sunken);
//-------------
#endif
_variableLabel = new QLabel();
_variableLabel->setMargin(3);
_variableLabel->setFrameStyle(QFrame::Panel | QFrame::Sunken);
_variableLabel->setTextInteractionFlags(Qt::TextSelectableByMouse);
//-------------
_rangeLabel = new QLabel();
_rangeLabel->setMargin(3);
_rangeLabel->setFrameStyle(QFrame::Panel | QFrame::Sunken);
l->addRow("Interval1:", _interval1Label);
l->addRow("Interval2:", _interval2Label);
l->addRow("Interval3:", _interval3Label);
l->addRow("Interval4:", _interval4Label);
l->addRow("Expression:", _variableLabel);
l->addRow("Range:", _rangeLabel);
_widget->setLayout(l);
}
QJsonObject
IntervalConditionModel::
save() const
{
QJsonObject modelJson = NodeDataModel::save();
#if 0
if (_expression)
modelJson["expression"] = _expression->expression();
#endif
return modelJson;
}
void
IntervalConditionModel::
restore(QJsonObject const &p)
{
QJsonValue v = p["expression"];
#if 0
if (!v.isUndefined())
{
QString str = v.toString();
_expression = std::make_shared<ExpressionRangeData>(str);
_lineEdit->setText(str);
}
#endif
}
unsigned int
IntervalConditionModel::
nPorts(PortType portType) const
{
unsigned int result = 1;
switch (portType)
{
case PortType::In:
result = 5;
break;
case PortType::Out:
result = 1;
default:
break;
}
return result;
}
void
IntervalConditionModel::
onFunctionIndexChanged(int index)
{
Q_UNUSED(index);
processData();
}
void
IntervalConditionModel::
setInData(std::shared_ptr<NodeData> data, PortIndex portIndex)
{
switch (portIndex)
{
case 0:
{
_controlInput = std::dynamic_pointer_cast<ExpressionRangeData>(data);
break;
}
case 1:
{
_input1 = std::dynamic_pointer_cast<ExpressionRangeData>(data);
break;
}
case 2:
{
_input2 = std::dynamic_pointer_cast<ExpressionRangeData>(data);
break;
}
case 3:
{
_input3 = std::dynamic_pointer_cast<ExpressionRangeData>(data);
break;
}
case 4:
{
_input4 = std::dynamic_pointer_cast<ExpressionRangeData>(data);
break;
}
}
processData();
}
QWidget *
IntervalConditionModel::
embeddedWidget()
{
return _widget;
}
QString
IntervalConditionModel::
convertBoolRangeToText(std::vector<bool> const &range) const
{
QString result("(");
for (std::size_t i = 0; i < range.size() - 1; ++i)
{
result = result + (range[i] ? "t" : "f") + ", ";
}
result = result + (range.back() ? "t" : "f") + ")";
return result;
}
QString
IntervalConditionModel::
convertRangeToText(std::vector<double> const &range) const
{
QString result("(");
for (std::size_t i = 0; i < range.size() - 1; ++i)
{
result = result + QString::number(range[i]) + ", ";
}
result = result + QString::number(range.back()) + ")";
return result;
}
std::vector<double>
IntervalConditionModel::
applyFunction(std::vector<double> const &range0,
std::vector<double> const &range1,
std::vector<double> const &range2,
std::vector<double> const &range3,
std::vector<double> const &range4) const
{
std::vector<double> result;
for (std::size_t i = 0; i < range0.size(); ++i)
{
result.push_back( range0[i] ? range1[i] : range2[i]);
if (range0[i] >= _intervalRange1 && range0[i] < _intervalRange2)
{
result.push_back(range1[i]);
}
else if (range0[i] >= _intervalRange2 && range0[i] < _intervalRange3)
{
result.push_back(range2[i]);
}
else if (range0[i] >= _intervalRange3 && range0[i] < _intervalRange4)
{
result.push_back(range3[i]);
}
else
{
result.push_back(range4[i]);
}
}
return result;
}
void
IntervalConditionModel::
processData()
{
if (!processIntervals())
{
_expression = std::make_shared<ExpressionRangeData>();
emit dataInvalidated(0);
return;
}
// std::cout << " borders " << _intervalRange1<< " " << _intervalRange2<< " " << _intervalRange3 << " " << _intervalRange4 << std::endl;
auto n0 = _controlInput.lock(); // control
auto n1 = _input1.lock();
auto n2 = _input2.lock();
auto n3 = _input3.lock();
auto n4 = _input4.lock();
if (n0 && n1 && n2 && n3 && n4)
{
QString input0 = n0->expression();
QString input1 = n1->expression();
QString input2 = n2->expression();
QString input3 = n3->expression();
QString input4 = n4->expression();
std::vector<double> const & inputRange0 = n0->range();
std::vector<double> const & inputRange1 = n1->range();
std::vector<double> const & inputRange2 = n2->range();
std::vector<double> const & inputRange3 = n3->range();
std::vector<double> const & inputRange4 = n4->range();
#if 0
_ifLabel->setText(convertBoolRangeToText(inputRange0));
_input1Label->setText(convertRangeToText(inputRange1));
_inout2Label->setText(convertRangeToText(inputRange2));
_inout3Label->setText(convertRangeToText(inputRange3));
#endif
if ((inputRange1.size() != inputRange2.size()) ||
(inputRange0.size() != inputRange2.size()) ||
(inputRange3.size() != inputRange2.size()) ||
(inputRange4.size() != inputRange2.size()))
{
_expression = std::make_shared<ExpressionRangeData>();
emit dataInvalidated(0);
return;
}
std::vector<double> modifiedRange = applyFunction(inputRange0, inputRange1, inputRange2, inputRange3, inputRange4);
// QString tt(" ( (%1) ? %2 : %3 ) ");
QString tt(" ( (%1 >= %2 && %1 < %3) ? %4 : ((%1 >= %3 && %1 < %5) ? %6 : ((%1 >= %5 && %1 <= %7) ? %8 : %9 ) ) ) ");
_expression = std::make_shared<ExpressionRangeData>(tt.arg(input0, QString::number(_intervalRange1),
QString::number(_intervalRange2),
input1, QString::number(_intervalRange3),
input2, QString::number(_intervalRange4), input3, input4),
modifiedRange);
_variableLabel->setText(_expression->expression());
_variableLabel->adjustSize();
_rangeLabel->setText(convertRangeToText(modifiedRange));
_rangeLabel->adjustSize();
emit dataUpdated(0);
}
}
NodeDataType
IntervalConditionModel::
dataType(PortType portType, PortIndex index) const
{
switch (portType)
{
case PortType::In:
return ExpressionRangeData().type();
break;
case PortType::Out:
return ExpressionRangeData().type();
break;
}
}
std::shared_ptr<NodeData>
IntervalConditionModel::
outData(PortIndex)
{
return _expression;
}
void
IntervalConditionModel::
onIntervalEdited(QString const &string)
{
Q_UNUSED(string);
processData();
}
bool
IntervalConditionModel::
processIntervals()
{
bool isOk = true;
bool ook;
QString i1 = _interval1Label->text();
if (!i1.isEmpty())
{
_intervalRange1 = i1.toDouble(&ook);
isOk = isOk && ook;
}
QString i2 = _interval2Label->text();
if (!i2.isEmpty())
{
_intervalRange2 = i2.toDouble(&ook);
isOk = isOk && ook;
}
QString i3 = _interval3Label->text();
if (!i3.isEmpty())
{
_intervalRange3 = i3.toDouble(&ook);
isOk = isOk && ook;
}
QString i4 = _interval4Label->text();
if (!i4.isEmpty())
{
_intervalRange4 = i4.toDouble(&ook);
isOk = isOk && ook;
}
return isOk;
}