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

Add node widget embeddable option #374

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions examples/dynamic_ports/DynamicPortsModel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,10 @@ QVariant DynamicPortsModel::nodeData(NodeId nodeId, NodeRole role) const
result = _nodePortCounts[nodeId].out;
break;

case NodeRole::WidgetEmbeddable:
result = true;
break;

case NodeRole::Widget: {
result = QVariant::fromValue(widget(nodeId));
break;
Expand Down Expand Up @@ -194,6 +198,9 @@ bool DynamicPortsModel::setNodeData(NodeId nodeId, NodeRole role, QVariant value
widget(nodeId)->populateButtons(PortType::Out, value.toUInt());
break;

case NodeRole::WidgetEmbeddable:
break;

case NodeRole::Widget:
break;
}
Expand Down
2 changes: 1 addition & 1 deletion examples/resizable_images/ImageLoaderModel.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ using QtNodes::PortType;

/// The model dictates the number of inputs and outputs for the Node.
/// In this example it has no logic.
class ImageLoaderModel : public NodeDelegateModel
class ImageLoaderModel final : public NodeDelegateModel
{
Q_OBJECT

Expand Down
5 changes: 5 additions & 0 deletions examples/resizable_images/ImageShowModel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ ImageShowModel::ImageShowModel()
_label->installEventFilter(this);
}

ImageShowModel::~ImageShowModel()
{
delete _label;
}

unsigned int ImageShowModel::nPorts(PortType portType) const
{
unsigned int result = 1;
Expand Down
6 changes: 4 additions & 2 deletions examples/resizable_images/ImageShowModel.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@ using QtNodes::PortType;

/// The model dictates the number of inputs and outputs for the Node.
/// In this example it has no logic.
class ImageShowModel : public NodeDelegateModel
class ImageShowModel final : public NodeDelegateModel
{
Q_OBJECT

public:
ImageShowModel();

~ImageShowModel() = default;
~ImageShowModel() override;

public:
QString caption() const override { return QString("Image Display"); }
Expand All @@ -41,6 +41,8 @@ class ImageShowModel : public NodeDelegateModel

void setInData(std::shared_ptr<NodeData> nodeData, PortIndex const port) override;

bool widgetEmbeddable() const override { return false; }

QWidget *embeddedWidget() override { return _label; }

bool resizable() const override { return true; }
Expand Down
20 changes: 20 additions & 0 deletions examples/resizable_images/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,26 @@ int main(int argc, char *argv[])

GraphicsView view(&scene);

QObject::connect(&scene,
&DataFlowGraphicsScene::nodeDoubleClicked,
&dataFlowGraphModel,
[&dataFlowGraphModel](QtNodes::NodeId nodeId) {
QString name = dataFlowGraphModel
.nodeData(nodeId, QtNodes::NodeRole::Caption)
.value<QString>();

bool isEmbeded = dataFlowGraphModel
zmoth marked this conversation as resolved.
Show resolved Hide resolved
.nodeData(nodeId, QtNodes::NodeRole::WidgetEmbeddable)
.value<bool>();
auto w = dataFlowGraphModel.nodeData(nodeId, QtNodes::NodeRole::Widget)
.value<QWidget *>();

if (!isEmbeded && w) {
zmoth marked this conversation as resolved.
Show resolved Hide resolved
w->setWindowTitle(name + "_" + QString::number(nodeId));
w->show();
}
});

view.setWindowTitle("Data Flow: Resizable Images");
view.resize(800, 600);
// Center window.
Expand Down
7 changes: 7 additions & 0 deletions examples/simple_graph_model/SimpleGraphModel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,10 @@ QVariant SimpleGraphModel::nodeData(NodeId nodeId, NodeRole role) const
result = 1u;
break;

case NodeRole::WidgetEmbeddable:
result = true;
break;

case NodeRole::Widget:
result = QVariant();
break;
Expand Down Expand Up @@ -167,6 +171,9 @@ bool SimpleGraphModel::setNodeData(NodeId nodeId, NodeRole role, QVariant value)
case NodeRole::OutPortCount:
break;

case NodeRole::WidgetEmbeddable:
break;

case NodeRole::Widget:
break;
}
Expand Down
7 changes: 7 additions & 0 deletions examples/vertical_layout/SimpleGraphModel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,10 @@ QVariant SimpleGraphModel::nodeData(NodeId nodeId, NodeRole role) const
result = 3u;
break;

case NodeRole::WidgetEmbeddable:
result = true;
break;

case NodeRole::Widget:
result = QVariant();
break;
Expand Down Expand Up @@ -167,6 +171,9 @@ bool SimpleGraphModel::setNodeData(NodeId nodeId, NodeRole role, QVariant value)
case NodeRole::OutPortCount:
break;

case NodeRole::WidgetEmbeddable:
break;

case NodeRole::Widget:
break;
}
Expand Down
23 changes: 12 additions & 11 deletions include/QtNodes/internal/Definitions.hpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#pragma once
#pragma once

#include "Export.hpp"

Expand All @@ -22,16 +22,17 @@ Q_NAMESPACE_EXPORT(NODE_EDITOR_PUBLIC)
* Constants used for fetching QVariant data from GraphModel.
*/
enum class NodeRole {
Type = 0, ///< Type of the current node, usually a string.
Position = 1, ///< `QPointF` positon of the node on the scene.
Size = 2, ///< `QSize` for resizable nodes.
CaptionVisible = 3, ///< `bool` for caption visibility.
Caption = 4, ///< `QString` for node caption.
Style = 5, ///< Custom NodeStyle as QJsonDocument
InternalData = 6, ///< Node-stecific user data as QJsonObject
InPortCount = 7, ///< `unsigned int`
OutPortCount = 9, ///< `unsigned int`
Widget = 10, ///< Optional `QWidget*` or `nullptr`
Type = 0, ///< Type of the current node, usually a string.
Position, ///< `QPointF` positon of the node on the scene.
Size, ///< `QSize` for resizable nodes.
CaptionVisible, ///< `bool` for caption visibility.
Caption, ///< `QString` for node caption.
Style, ///< Custom NodeStyle as QJsonDocument
InternalData, ///< Node-stecific user data as QJsonObject
InPortCount, ///< `unsigned int`
OutPortCount, ///< `unsigned int`
WidgetEmbeddable, ///< `bool` for widget embeddability
Widget, ///< Optional `QWidget*` or `nullptr`
};
Q_ENUM_NS(NodeRole)

Expand Down
6 changes: 5 additions & 1 deletion include/QtNodes/internal/NodeDelegateModel.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ class StyleCollection;
* AbstractGraphModel.
* This class is the same what has been called NodeDataModel before v3.
*/
class NODE_EDITOR_PUBLIC NodeDelegateModel : public QObject, public Serializable
class NODE_EDITOR_PUBLIC NodeDelegateModel
: public QObject
, public Serializable
{
Q_OBJECT

Expand Down Expand Up @@ -78,6 +80,8 @@ class NODE_EDITOR_PUBLIC NodeDelegateModel : public QObject, public Serializable
*/
virtual QWidget *embeddedWidget() = 0;

virtual bool widgetEmbeddable() const { return true; }

virtual bool resizable() const { return false; }

public Q_SLOTS:
Expand Down
19 changes: 17 additions & 2 deletions src/DataFlowGraphModel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ QVariant DataFlowGraphModel::nodeData(NodeId nodeId, NodeRole role) const
break;

case NodeRole::CaptionVisible:
result = model->captionVisible();
result = model->widgetEmbeddable() ? model->captionVisible() : true;
break;

case NodeRole::Caption:
Expand Down Expand Up @@ -232,10 +232,17 @@ QVariant DataFlowGraphModel::nodeData(NodeId nodeId, NodeRole role) const
result = model->nPorts(PortType::Out);
break;

case NodeRole::WidgetEmbeddable:
result = model->widgetEmbeddable();
break;

case NodeRole::Widget: {
auto w = model->embeddedWidget();
result = QVariant::fromValue(w);
} break;

default:
break;
}

return result;
Expand All @@ -245,7 +252,7 @@ NodeFlags DataFlowGraphModel::nodeFlags(NodeId nodeId) const
{
auto it = _models.find(nodeId);

if (it != _models.end() && it->second->resizable())
if (it != _models.end() && it->second->widgetEmbeddable() && it->second->resizable())
return NodeFlag::Resizable;

return NodeFlag::NoFlags;
Expand Down Expand Up @@ -293,8 +300,14 @@ bool DataFlowGraphModel::setNodeData(NodeId nodeId, NodeRole role, QVariant valu
case NodeRole::OutPortCount:
break;

case NodeRole::WidgetEmbeddable:
break;

case NodeRole::Widget:
break;

default:
break;
}

return result;
Expand Down Expand Up @@ -333,7 +346,9 @@ QVariant DataFlowGraphModel::portData(NodeId nodeId,

case PortRole::Caption:
result = model->portCaption(portType, portIndex);
break;

default:
break;
}

Expand Down
12 changes: 9 additions & 3 deletions src/DefaultHorizontalNodeGeometry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,10 @@ void DefaultHorizontalNodeGeometry::recomputeSize(NodeId const nodeId) const
{
unsigned int height = maxVerticalPortsExtent(nodeId);

if (auto w = _graphModel.nodeData<QWidget *>(nodeId, NodeRole::Widget)) {
bool isEmbeded = _graphModel.nodeData(nodeId, NodeRole::WidgetEmbeddable).value<bool>();
zmoth marked this conversation as resolved.
Show resolved Hide resolved
auto w = _graphModel.nodeData<QWidget *>(nodeId, NodeRole::Widget);

if (isEmbeded && w) {
zmoth marked this conversation as resolved.
Show resolved Hide resolved
height = std::max(height, static_cast<unsigned int>(w->height()));
}

Expand All @@ -48,7 +51,7 @@ void DefaultHorizontalNodeGeometry::recomputeSize(NodeId const nodeId) const

unsigned int width = inPortWidth + outPortWidth + 4 * _portSpasing;

if (auto w = _graphModel.nodeData<QWidget *>(nodeId, NodeRole::Widget)) {
if (isEmbeded && w) {
zmoth marked this conversation as resolved.
Show resolved Hide resolved
width += w->width();
}

Expand Down Expand Up @@ -150,7 +153,10 @@ QPointF DefaultHorizontalNodeGeometry::widgetPosition(NodeId const nodeId) const

unsigned int captionHeight = captionRect(nodeId).height();

if (auto w = _graphModel.nodeData<QWidget *>(nodeId, NodeRole::Widget)) {
bool isEmbeded = _graphModel.nodeData(nodeId, NodeRole::WidgetEmbeddable).value<bool>();
zmoth marked this conversation as resolved.
Show resolved Hide resolved
auto w = _graphModel.nodeData<QWidget *>(nodeId, NodeRole::Widget);

if (isEmbeded && w) {
zmoth marked this conversation as resolved.
Show resolved Hide resolved
// If the widget wants to use as much vertical space as possible,
// place it immediately after the caption.
if (w->sizePolicy().verticalPolicy() & QSizePolicy::ExpandFlag) {
Expand Down
12 changes: 9 additions & 3 deletions src/DefaultVerticalNodeGeometry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,10 @@ void DefaultVerticalNodeGeometry::recomputeSize(NodeId const nodeId) const
{
unsigned int height = _portSpasing; // maxHorizontalPortsExtent(nodeId);

if (auto w = _graphModel.nodeData<QWidget *>(nodeId, NodeRole::Widget)) {
bool isEmbeded = _graphModel.nodeData(nodeId, NodeRole::WidgetEmbeddable).value<bool>();
zmoth marked this conversation as resolved.
Show resolved Hide resolved
auto w = _graphModel.nodeData<QWidget *>(nodeId, NodeRole::Widget);

if (isEmbeded && w) {
zmoth marked this conversation as resolved.
Show resolved Hide resolved
height = std::max(height, static_cast<unsigned int>(w->height()));
}

Expand Down Expand Up @@ -64,7 +67,7 @@ void DefaultVerticalNodeGeometry::recomputeSize(NodeId const nodeId) const

unsigned int width = std::max(totalInPortsWidth, totalOutPortsWidth);

if (auto w = _graphModel.nodeData<QWidget *>(nodeId, NodeRole::Widget)) {
if (isEmbeded && w) {
width = std::max(width, static_cast<unsigned int>(w->width()));
}

Expand Down Expand Up @@ -177,7 +180,10 @@ QPointF DefaultVerticalNodeGeometry::widgetPosition(NodeId const nodeId) const

unsigned int captionHeight = captionRect(nodeId).height();

if (auto w = _graphModel.nodeData<QWidget *>(nodeId, NodeRole::Widget)) {
bool isEmbeded = _graphModel.nodeData(nodeId, NodeRole::WidgetEmbeddable).value<bool>();
auto w = _graphModel.nodeData<QWidget *>(nodeId, NodeRole::Widget);

if (isEmbeded && w) {
// If the widget wants to use as much vertical space as possible,
// place it immediately after the caption.
if (w->sizePolicy().verticalPolicy() & QSizePolicy::ExpandFlag) {
Expand Down
6 changes: 5 additions & 1 deletion src/NodeGraphicsObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,9 @@ void NodeGraphicsObject::embedQWidget()
AbstractNodeGeometry &geometry = nodeScene()->nodeGeometry();
geometry.recomputeSize(_nodeId);

if (!_graphModel.nodeData(_nodeId, NodeRole::WidgetEmbeddable).value<bool>())
return;

if (auto w = _graphModel.nodeData(_nodeId, NodeRole::Widget).value<QWidget *>()) {
_proxyWidget = new QGraphicsProxyWidget(this);

Expand Down Expand Up @@ -245,7 +248,8 @@ void NodeGraphicsObject::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
setSelected(true);
}

if (_nodeState.resizing()) {
if (_nodeState.resizing()
&& _graphModel.nodeData(_nodeId, NodeRole::WidgetEmbeddable).value<bool>()) {
auto diff = event->pos() - event->lastPos();

if (auto w = _graphModel.nodeData<QWidget *>(_nodeId, NodeRole::Widget)) {
Expand Down