Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Runtime validation and error reporting #46

Merged
merged 7 commits into from Jan 25, 2017
Merged
31 changes: 26 additions & 5 deletions examples/calculator/DivisionModel.hpp
Expand Up @@ -13,6 +13,9 @@
/// In this example it has no logic.
class DivisionModel : public MathOperationDataModel
{
private:
bool isModelValid = true;
QString modelValidationError = QString("");
public:

virtual
Expand Down Expand Up @@ -45,7 +48,7 @@ class DivisionModel : public MathOperationDataModel
default:
break;
}
return QString("");
return QString("");
}

QString
Expand All @@ -56,6 +59,14 @@ class DivisionModel : public MathOperationDataModel
clone() const override
{ return std::make_unique<DivisionModel>(); }

bool
isValid() const override
{ return isModelValid; }

QString
errorMessage() const override
{ return modelValidationError; }

public:

void
Expand All @@ -74,14 +85,24 @@ class DivisionModel : public MathOperationDataModel
auto n1 = _number1.lock();
auto n2 = _number2.lock();

if (n1 && n2 && (n2->number() != 0.0))
if (n2 && (n2->number() == 0.0))
{
_result = std::make_shared<NumberData>(n1->number() /
n2->number());
isModelValid = false;
modelValidationError = QString("Division by zero error");
}
else
{
_result.reset();
isModelValid = true;
modelValidationError = QString("");
if (n1 && n2)
{
_result = std::make_shared<NumberData>(n1->number() /
n2->number());
}
else
{
_result.reset();
}
}

emit dataUpdated(outPortIndex);
Expand Down
11 changes: 11 additions & 0 deletions src/FlowScene.cpp
Expand Up @@ -215,6 +215,17 @@ setRegistry(std::shared_ptr<DataModelRegistry> registry)
}


void
FlowScene::
iterateOverNodes(std::function<void(Node*)> visitor)
{
for (const auto& _node : _nodes)
{
visitor(_node.second.get());
}
}


//------------------------------------------------------------------------------

void
Expand Down
4 changes: 4 additions & 0 deletions src/FlowScene.hpp
Expand Up @@ -6,6 +6,7 @@
#include <unordered_map>
#include <tuple>
#include <memory>
#include <functional>

#include "Connection.hpp"
#include "Export.hpp"
Expand Down Expand Up @@ -64,6 +65,9 @@ class NODE_EDITOR_PUBLIC FlowScene
void
setRegistry(std::shared_ptr<DataModelRegistry> registry);

void
iterateOverNodes(std::function<void(Node*)> visitor);

public:

void
Expand Down
7 changes: 6 additions & 1 deletion src/Node.cpp
Expand Up @@ -176,7 +176,12 @@ propagateData(std::shared_ptr<NodeData> nodeData,
PortIndex inPortIndex) const
{
_nodeDataModel->setInData(nodeData, inPortIndex);


//Recalculate the nodes visuals. A data change can result in the node taking more space than before, so this forces a recalculate+repaint on the affected node
_nodeGraphicsObject->setGeometryChanged();
_nodeGeometry.recalculateSize();
_nodeGraphicsObject->update();
_nodeGraphicsObject->moveConnections();
}


Expand Down
8 changes: 8 additions & 0 deletions src/NodeDataModel.hpp
Expand Up @@ -74,6 +74,14 @@ class NODE_EDITOR_PUBLIC NodeDataModel
virtual
bool
resizable() const { return false; }

virtual
bool
isValid() const { return true; }

virtual
QString
errorMessage() const { return QString(""); }

signals:

Expand Down
30 changes: 30 additions & 0 deletions src/NodeGeometry.cpp
Expand Up @@ -89,6 +89,12 @@ recalculateSize() const
}

_width = std::max(_width, captionWidth());

if (!_dataModel->isValid())
{
_width = std::max(_width, errorWidth());
_height += errorHeight() + _spacing;
}
}


Expand Down Expand Up @@ -248,6 +254,26 @@ captionWidth() const
}


unsigned int
NodeGeometry::
errorHeight() const
{
QString msg = _dataModel->errorMessage();

return _boldFontMetrics.boundingRect(msg).height();
}


unsigned int
NodeGeometry::
errorWidth() const
{
QString msg = _dataModel->errorMessage();

return _boldFontMetrics.boundingRect(msg).width();
}


unsigned int
NodeGeometry::
portWidth(PortType portType) const
Expand All @@ -259,9 +285,13 @@ portWidth(PortType portType) const
QString name;

if (_dataModel->portCaptionVisible(portType, i))
{
name = _dataModel->portCaption(portType, i);
}
else
{
name = _dataModel->dataType(portType, i).name;
}

width = std::max(unsigned(_fontMetrics.width(name)),
width);
Expand Down
6 changes: 6 additions & 0 deletions src/NodeGeometry.hpp
Expand Up @@ -102,6 +102,12 @@ class NodeGeometry
QPointF
widgetPosition() const;

unsigned int
errorHeight() const;

unsigned int
errorWidth() const;

private:

unsigned int
Expand Down
46 changes: 46 additions & 0 deletions src/NodePainter.cpp
Expand Up @@ -40,6 +40,8 @@ paint(QPainter* painter,
drawEntryLabels(painter, geom, state, model);

drawResizeRect(painter, geom, model);

drawErrorRect(painter, geom, model);
}


Expand Down Expand Up @@ -274,9 +276,13 @@ drawEntryLabels(QPainter * painter,
QString s;

if (model->portCaptionVisible(portType, i))
{
s = model->portCaption(portType, i);
}
else
{
s = model->dataType(portType, i).name;
}

auto rect = metrics.boundingRect(s);

Expand Down Expand Up @@ -319,3 +325,43 @@ drawResizeRect(QPainter * painter,
painter->drawEllipse(geom.resizeRect());
}
}

void
NodePainter::
drawErrorRect(QPainter * painter,
NodeGeometry const & geom,
NodeDataModel* const model)
{
if (!model->isValid())
{
//Drawing the red background
painter->setBrush(Qt::red);

double const radius = 3.0;

NodeStyle const& nodeStyle = StyleCollection::nodeStyle();

float diam = nodeStyle.ConnectionPointDiameter;

QRectF boundary(0.0, geom.height() - geom.errorHeight(), geom.width(), geom.errorHeight());
QMarginsF m(diam, diam, diam, diam);

painter->drawRoundedRect(boundary.marginsAdded(m), radius, radius);

//Drawing the error message itself
QString const &errorMsg = model->errorMessage();

QFont f = painter->font();

QFontMetrics metrics(f);

auto rect = metrics.boundingRect(errorMsg);

QPointF position((geom.width() - rect.width()) / 2.0,
geom.height() - (geom.errorHeight() - diam) / 2.0);

painter->setFont(f);
painter->setPen(nodeStyle.FontColor);
painter->drawText(position, errorMsg);
}
}
6 changes: 6 additions & 0 deletions src/NodePainter.hpp
Expand Up @@ -62,4 +62,10 @@ class NodePainter
drawResizeRect(QPainter* painter,
NodeGeometry const& geom,
NodeDataModel* const model);

static
void
drawErrorRect(QPainter * painter,
NodeGeometry const & geom,
NodeDataModel* const model);
};