Skip to content

Commit

Permalink
Add the widget embeddable option and implement it in the `resizable_i…
Browse files Browse the repository at this point in the history
…mages` example.
  • Loading branch information
zmoth committed Feb 20, 2023
1 parent 5465ddc commit fe0d6fa
Show file tree
Hide file tree
Showing 9 changed files with 73 additions and 22 deletions.
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
4 changes: 3 additions & 1 deletion examples/resizable_images/ImageShowModel.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class ImageShowModel : public NodeDelegateModel
public:
ImageShowModel();

~ImageShowModel() = default;
virtual ~ImageShowModel();

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
19 changes: 19 additions & 0 deletions examples/resizable_images/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,25 @@ 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::Type)
.value<QString>();

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

if (!isEmbeded && w) {
w->setWindowTitle(name + "_" + QString::number(nodeId));
w->show();
}
});

view.setWindowTitle("Data Flow: Resizable Images");
view.resize(800, 600);
// Center window.
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
8 changes: 6 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,6 +232,10 @@ 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);
Expand All @@ -245,7 +249,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
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>();
auto w = _graphModel.nodeData<QWidget *>(nodeId, NodeRole::Widget);

if (isEmbeded && w) {
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) {
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>();
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
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>();
auto w = _graphModel.nodeData<QWidget *>(nodeId, NodeRole::Widget);

if (isEmbeded && w) {
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

0 comments on commit fe0d6fa

Please sign in to comment.