refactor: refactored Complex Connection Editor

This commit is contained in:
QwQ 2020-07-25 11:27:04 +08:00
parent 81df0e0f02
commit 51da85cfe1
No known key found for this signature in database
GPG Key ID: E7FAEFAFCD031D4B
10 changed files with 157 additions and 289 deletions

View File

@ -1 +1 @@
5828 5829

View File

@ -4,9 +4,12 @@
#include "core/connection/Generation.hpp" #include "core/connection/Generation.hpp"
#include "core/handler/ConfigHandler.hpp" #include "core/handler/ConfigHandler.hpp"
#include "ui/common/UIBase.hpp" #include "ui/common/UIBase.hpp"
#include "ui/node/NodeBase.hpp"
#include "ui/node/models/InboundNodeModel.hpp" #include "ui/node/models/InboundNodeModel.hpp"
#include "ui/node/models/OutboundNodeModel.hpp" #include "ui/node/models/OutboundNodeModel.hpp"
#include "ui/node/models/RuleNodeModel.hpp" #include "ui/node/models/RuleNodeModel.hpp"
#include "ui/widgets/complex/ChainEditorWidget.hpp"
#include "ui/widgets/complex/RoutingEditorWidget.hpp"
#include "ui/windows/w_ImportConfig.hpp" #include "ui/windows/w_ImportConfig.hpp"
#include "w_InboundEditor.hpp" #include "w_InboundEditor.hpp"
#include "w_JsonEditor.hpp" #include "w_JsonEditor.hpp"
@ -59,19 +62,31 @@ void RouteEditor::SetupNodeWidget()
"SelectedHaloColor": "deepskyblue","HoveredColor": "deepskyblue","LineWidth": 3.0,"ConstructionLineWidth": 2.0, "SelectedHaloColor": "deepskyblue","HoveredColor": "deepskyblue","LineWidth": 3.0,"ConstructionLineWidth": 2.0,
"PointDiameter": 10.0,"UseDataDefinedColors": false}})"); "PointDiameter": 10.0,"UseDataDefinedColors": false}})");
} }
ruleScene = new FlowScene(this); {
ruleView = new FlowView(ruleScene, nodeGraphWidget); ruleWidget = new RoutingEditorWidget(this);
ruleView->scaleDown(); if (!ruleEditorUIWidget->layout())
if (!nodeGraphWidget->layout())
{ {
// The QWidget will take ownership of layout. // The QWidget will take ownership of layout.
nodeGraphWidget->setLayout(new QVBoxLayout()); ruleEditorUIWidget->setLayout(new QVBoxLayout());
} }
auto l = nodeGraphWidget->layout(); auto l = ruleEditorUIWidget->layout();
l->addWidget(ruleView); l->addWidget(ruleWidget);
l->setContentsMargins(0, 0, 0, 0); l->setContentsMargins(0, 0, 0, 0);
l->setSpacing(0); l->setSpacing(0);
} }
{
chainWidget = new ChainEditorWidget(this);
if (!chainEditorUIWidget->layout())
{
// The QWidget will take ownership of layout.
chainEditorUIWidget->setLayout(new QVBoxLayout());
}
auto l = chainEditorUIWidget->layout();
l->addWidget(chainWidget);
l->setContentsMargins(0, 0, 0, 0);
l->setSpacing(0);
}
}
RouteEditor::RouteEditor(QJsonObject connection, QWidget *parent) : QvDialog(parent), root(connection), original(connection) RouteEditor::RouteEditor(QJsonObject connection, QWidget *parent) : QvDialog(parent), root(connection), original(connection)
{ {
@ -83,7 +98,7 @@ RouteEditor::RouteEditor(QJsonObject connection, QWidget *parent) : QvDialog(par
SetupNodeWidget(); SetupNodeWidget();
updateColorScheme(); updateColorScheme();
// //
nodeDispatcher = std::make_shared<NodeDispatcher>(ruleScene); nodeDispatcher = std::make_shared<NodeDispatcher>(ruleWidget->scene());
connect(nodeDispatcher.get(), &NodeDispatcher::OnInboundCreated, this, &RouteEditor::OnDispatcherInboundCreated); connect(nodeDispatcher.get(), &NodeDispatcher::OnInboundCreated, this, &RouteEditor::OnDispatcherInboundCreated);
connect(nodeDispatcher.get(), &NodeDispatcher::OnOutboundCreated, this, &RouteEditor::OnDispatcherOutboundCreated); connect(nodeDispatcher.get(), &NodeDispatcher::OnOutboundCreated, this, &RouteEditor::OnDispatcherOutboundCreated);
connect(nodeDispatcher.get(), &NodeDispatcher::OnRuleCreated, this, &RouteEditor::OnDispatcherRuleCreated); connect(nodeDispatcher.get(), &NodeDispatcher::OnRuleCreated, this, &RouteEditor::OnDispatcherRuleCreated);
@ -136,24 +151,24 @@ void RouteEditor::OnDispatcherInboundOutboundHovered(const QString &tag, const P
void RouteEditor::OnDispatcherInboundCreated(std::shared_ptr<INBOUND>, QtNodes::Node &node) void RouteEditor::OnDispatcherInboundCreated(std::shared_ptr<INBOUND>, QtNodes::Node &node)
{ {
QPoint pos{ 0 + GRAPH_GLOBAL_OFFSET_X, nodeDispatcher->InboundsCount() * 130 + GRAPH_GLOBAL_OFFSET_Y }; QPoint pos{ 0 + GRAPH_GLOBAL_OFFSET_X, nodeDispatcher->InboundsCount() * 130 + GRAPH_GLOBAL_OFFSET_Y };
ruleScene->setNodePosition(node, pos); ruleWidget->scene()->setNodePosition(node, pos);
} }
void RouteEditor::OnDispatcherOutboundCreated(std::shared_ptr<OutboundObjectMeta> out, QtNodes::Node &node) void RouteEditor::OnDispatcherOutboundCreated(std::shared_ptr<OutboundObjectMeta> out, QtNodes::Node &node)
{ {
QPoint pos = nodeGraphWidget->pos(); auto pos = ruleWidget->pos();
pos.setX(pos.x() + 850 + GRAPH_GLOBAL_OFFSET_X); pos.setX(pos.x() + 850 + GRAPH_GLOBAL_OFFSET_X);
pos.setY(pos.y() + nodeDispatcher->OutboundsCount() * 120 + GRAPH_GLOBAL_OFFSET_Y); pos.setY(pos.y() + nodeDispatcher->OutboundsCount() * 120 + GRAPH_GLOBAL_OFFSET_Y);
ruleScene->setNodePosition(node, pos); ruleWidget->scene()->setNodePosition(node, pos);
defaultOutboundCombo->addItem(out->getTag()); defaultOutboundCombo->addItem(out->getTag());
} }
void RouteEditor::OnDispatcherRuleCreated(std::shared_ptr<RuleObject> rule, QtNodes::Node &node) void RouteEditor::OnDispatcherRuleCreated(std::shared_ptr<RuleObject> rule, QtNodes::Node &node)
{ {
auto pos = nodeGraphWidget->pos(); auto pos = ruleWidget->pos();
pos.setX(pos.x() + 350 + GRAPH_GLOBAL_OFFSET_X); pos.setX(pos.x() + 350 + GRAPH_GLOBAL_OFFSET_X);
pos.setY(pos.y() + nodeDispatcher->RulesCount() * 120 + GRAPH_GLOBAL_OFFSET_Y); pos.setY(pos.y() + nodeDispatcher->RulesCount() * 120 + GRAPH_GLOBAL_OFFSET_Y);
ruleScene->setNodePosition(node, pos); ruleWidget->scene()->setNodePosition(node, pos);
ruleListWidget->addItem(rule->QV2RAY_RULE_TAG); ruleListWidget->addItem(rule->QV2RAY_RULE_TAG);
} }
@ -398,19 +413,19 @@ void RouteEditor::on_addOutboundBtn_clicked()
void RouteEditor::on_delBtn_clicked() void RouteEditor::on_delBtn_clicked()
{ {
if (ruleScene->selectedNodes().empty()) if (ruleWidget->scene()->selectedNodes().empty())
{ {
QvMessageBoxWarn(this, tr("Remove Items"), tr("Please select a node from the graph to continue.")); QvMessageBoxWarn(this, tr("Remove Items"), tr("Please select a node from the graph to continue."));
return; return;
} }
const auto selecteNodes = ruleScene->selectedNodes(); const auto selecteNodes = ruleWidget->scene()->selectedNodes();
if (selecteNodes.empty()) if (selecteNodes.empty())
{ {
QvMessageBoxWarn(this, tr("Deleting a node"), tr("You need to select a node first")); QvMessageBoxWarn(this, tr("Deleting a node"), tr("You need to select a node first"));
return; return;
} }
ruleScene->removeNode(*selecteNodes.front()); ruleWidget->scene()->removeNode(*selecteNodes.front());
} }
void RouteEditor::on_addRouteBtn_clicked() void RouteEditor::on_addRouteBtn_clicked()
@ -463,8 +478,7 @@ void RouteEditor::on_debugPainterCB_clicked(bool checked)
{ {
#ifdef QT_DEBUG #ifdef QT_DEBUG
QtNodes::ConnectionPainter::IsDebuggingEnabled = checked; QtNodes::ConnectionPainter::IsDebuggingEnabled = checked;
ruleScene->update(); ruleWidget->repaint();
ruleView->repaint();
#endif #endif
} }

View File

@ -1,13 +1,12 @@
#pragma once #pragma once
#include "base/Qv2rayBase.hpp" #include "base/Qv2rayBase.hpp"
#include "base/models/QvComplexConfigModels.hpp"
#include "common/QvHelpers.hpp" #include "common/QvHelpers.hpp"
#include "ui/common/QvDialog.hpp" #include "ui/common/QvDialog.hpp"
#include "ui/common/UIBase.hpp" #include "ui/common/UIBase.hpp"
#include "ui/messaging/QvMessageBus.hpp" #include "ui/messaging/QvMessageBus.hpp"
#include "ui/node/NodeBase.hpp"
#include "ui_w_RoutesEditor.h" #include "ui_w_RoutesEditor.h"
enum ROUTE_EDIT_MODE enum ROUTE_EDIT_MODE
{ {
RENAME_INBOUND, RENAME_INBOUND,
@ -15,6 +14,15 @@ enum ROUTE_EDIT_MODE
RENAME_RULE, RENAME_RULE,
}; };
class NodeDispatcher;
class ChainEditorWidget;
class RoutingEditorWidget;
namespace QtNodes
{
class Node;
};
namespace QtNodes namespace QtNodes
{ {
class FlowView; class FlowView;
@ -63,26 +71,23 @@ class RouteEditor
void on_linkExistingBtn_clicked(); void on_linkExistingBtn_clicked();
private slots: private slots:
void OnDispatcherOutboundDeleted(const OutboundObjectMeta &); void OnDispatcherOutboundDeleted(const complex::OutboundObjectMeta &);
void OnDispatcherInboundCreated(std::shared_ptr<INBOUND>, QtNodes::Node &); void OnDispatcherInboundCreated(std::shared_ptr<INBOUND>, QtNodes::Node &);
void OnDispatcherOutboundCreated(std::shared_ptr<OutboundObjectMeta>, QtNodes::Node &); void OnDispatcherOutboundCreated(std::shared_ptr<complex::OutboundObjectMeta>, QtNodes::Node &);
void OnDispatcherRuleCreated(std::shared_ptr<RuleObject>, QtNodes::Node &); void OnDispatcherRuleCreated(std::shared_ptr<RuleObject>, QtNodes::Node &);
void OnDispatcherInboundOutboundHovered(const QString &, const ProtocolSettingsInfoObject &); void OnDispatcherInboundOutboundHovered(const QString &, const ProtocolSettingsInfoObject &);
private: private:
// NOTE: Self managed pointer. // NOTE: Self managed pointer.
std::shared_ptr<NodeDispatcher> nodeDispatcher; std::shared_ptr<NodeDispatcher> nodeDispatcher;
ChainEditorWidget *chainWidget;
RoutingEditorWidget *ruleWidget;
// //
bool isLoading = false; bool isLoading = false;
void RenameItemTag(ROUTE_EDIT_MODE mode, const QString originalTag, QString *newTag);
//
QString domainStrategy; QString domainStrategy;
// //
CONFIGROOT root; CONFIGROOT root;
CONFIGROOT original; CONFIGROOT original;
// //
void SetupNodeWidget(); void SetupNodeWidget();
//
QtNodes::FlowScene *ruleScene;
QtNodes::FlowView *ruleView;
}; };

View File

@ -278,7 +278,7 @@
</layout> </layout>
</item> </item>
<item> <item>
<widget class="QWidget" name="nodeGraphWidget" native="true"> <widget class="QWidget" name="ruleEditorUIWidget" native="true">
<property name="minimumSize"> <property name="minimumSize">
<size> <size>
<width>0</width> <width>0</width>
@ -293,6 +293,11 @@
<attribute name="title"> <attribute name="title">
<string>Chain Editor</string> <string>Chain Editor</string>
</attribute> </attribute>
<layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="0">
<widget class="QWidget" name="chainEditorUIWidget" native="true"/>
</item>
</layout>
</widget> </widget>
</widget> </widget>
</item> </item>

View File

@ -5,155 +5,6 @@
#include "ui/node/models/RuleNodeModel.hpp" #include "ui/node/models/RuleNodeModel.hpp"
#include "w_RoutesEditor.hpp" #include "w_RoutesEditor.hpp"
#include <nodes/internal/FlowScene.hpp>
// Do not use reference here, we need deep copy of EVERY QString.
void RouteEditor::RenameItemTag(ROUTE_EDIT_MODE mode, const QString originalTag, QString *newTag)
{
/*
switch (mode)
{
case RENAME_RULE:
if (rules.contains(originalTag) && ruleNodes.contains(originalTag))
{
if (rules.contains(*newTag) && ruleNodes.contains(*newTag))
{
QvMessageBoxWarn(this, tr("Rename tags"), tr("The new tag has been used, we appended a postfix."));
*newTag += "_" + GenerateRandomString(5);
}
const auto &nodeDataModel = (QvRuleNodeModel *) nodeScene->node(ruleNodes.value(originalTag))->nodeDataModel();
if (nodeDataModel == nullptr)
{
LOG(MODULE_GRAPH, "EMPTY NODE WARN")
}
nodeDataModel->setData(*newTag);
//
auto rule = rules.take(originalTag);
rule.QV2RAY_RULE_TAG = *newTag;
rules.insert(*newTag, rule);
ruleNodes.insert(*newTag, ruleNodes.take(originalTag));
//
// No other operation needed, but need to rename the one in the
// ruleOrder list widget.
auto items = ruleListWidget->findItems(originalTag, Qt::MatchExactly);
if (items.isEmpty())
{
LOG(MODULE_UI, "Cannot find a node: " + originalTag)
}
else
{
items.first()->setText(*newTag);
}
abort();
// if (currentRuleTag == originalTag)
// {
// currentRuleTag = *newTag;
// }
}
else
{
LOG(MODULE_UI, "There's nothing match " + originalTag + " in the containers.")
}
break;
case RENAME_OUTBOUND:
if (outbounds.contains(originalTag) && outboundNodes.contains(originalTag))
{
if (outbounds.contains(*newTag) && outboundNodes.contains(*newTag))
{
QvMessageBoxWarn(this, tr("Rename tags"), tr("The new tag has been used, we appended a random string to the tag."));
*newTag += "_" + GenerateRandomString(5);
}
auto out = outbounds.take(originalTag);
out["tag"] = *newTag;
outbounds.insert(*newTag, out);
outboundNodes.insert(*newTag, outboundNodes.take(originalTag));
const auto &node = (QvOutboundNodeModel *) nodeScene->node(outboundNodes.value(*newTag))->nodeDataModel();
if (node == nullptr)
{
LOG(MODULE_GRAPH, "EMPTY NODE WARN")
}
node->setData(*newTag);
// Change outbound tag in rules accordingly.
for (const auto &k : rules.keys())
{
auto v = rules.value(k);
if (v.outboundTag == originalTag)
{
v.outboundTag = *newTag;
// Put this inside the if block since no need an extra
// operation if the condition is false.
rules.insert(k, v);
}
}
// Resolve default outbound.
ResolveDefaultOutboundTag(originalTag, *newTag);
}
else
{
LOG(MODULE_UI, "Failed to rename an outbound --> Item not found.")
}
break;
case RENAME_INBOUND:
if (inbounds.contains(originalTag) && inboundNodes.contains(originalTag))
{
if (inbounds.contains(*newTag) && inboundNodes.contains(*newTag))
{
QvMessageBoxWarn(this, tr("Rename tags"), tr("The new tag has been used, we appended a postfix."));
*newTag += "_" + GenerateRandomString(5);
}
auto in = inbounds.take(originalTag);
in["tag"] = *newTag;
inbounds.insert(*newTag, in);
inboundNodes.insert(*newTag, inboundNodes.take(originalTag));
const auto &node = (QvInboundNodeModel *) nodeScene->node(inboundNodes.value(*newTag))->nodeDataModel();
if (node == nullptr)
{
LOG(MODULE_GRAPH, "EMPTY NODE WARN")
}
node->setData(*newTag);
// Change inbound tag in rules accordingly.
// k -> rule tag
// v -> rule object
for (const auto &k : rules.keys())
{
auto v = rules.value(k);
if (v.inboundTag.contains(originalTag))
{
v.inboundTag.append(*newTag);
v.inboundTag.removeAll(originalTag);
// Put this inside the if block since no need an extra
// operation if the condition is false.
rules.insert(k, v);
}
}
}
else
{
LOG(MODULE_UI, "Failed to rename an outbound --> Item not found.")
}
break;
}*/
}
// Do not use const reference here. // Do not use const reference here.
// void RouteEditor::ResolveDefaultOutboundTag(const QString original, const QString newTag) // void RouteEditor::ResolveDefaultOutboundTag(const QString original, const QString newTag)
//{ //{

View File

@ -49,9 +49,7 @@ void InboundOutboundWidget::changeEvent(QEvent *e)
void InboundOutboundWidget::on_editBtn_clicked() void InboundOutboundWidget::on_editBtn_clicked()
{ {
switch (workingMode) if (workingMode == NODE_INBOUND)
{
case NODE_INBOUND:
{ {
InboundEditor editor{ *inboundObject, parentWidget() }; InboundEditor editor{ *inboundObject, parentWidget() };
*inboundObject = editor.OpenEditor(); *inboundObject = editor.OpenEditor();
@ -59,9 +57,8 @@ void InboundOutboundWidget::on_editBtn_clicked()
const auto newTag = getTag(*inboundObject); const auto newTag = getTag(*inboundObject);
tagTxt->setText(newTag); tagTxt->setText(newTag);
(*inboundObject)["tag"] = newTag; (*inboundObject)["tag"] = newTag;
break;
} }
case NODE_OUTBOUND: else
{ {
if (isExternalOutbound) if (isExternalOutbound)
{ {
@ -92,17 +89,13 @@ void InboundOutboundWidget::on_editBtn_clicked()
const auto newTag = getTag(outboundObject->realOutbound); const auto newTag = getTag(outboundObject->realOutbound);
tagTxt->setText(newTag); tagTxt->setText(newTag);
outboundObject->realOutbound["tag"] = newTag; outboundObject->realOutbound["tag"] = newTag;
break;
}
} }
} }
} }
void InboundOutboundWidget::on_editJsonBtn_clicked() void InboundOutboundWidget::on_editJsonBtn_clicked()
{ {
switch (workingMode) if (workingMode == NODE_INBOUND)
{
case NODE_INBOUND:
{ {
JsonEditor editor{ *inboundObject, parentWidget() }; JsonEditor editor{ *inboundObject, parentWidget() };
*inboundObject = INBOUND{ editor.OpenEditor() }; *inboundObject = INBOUND{ editor.OpenEditor() };
@ -110,16 +103,13 @@ void InboundOutboundWidget::on_editJsonBtn_clicked()
// Set tag // Set tag
tagTxt->setText(newTag); tagTxt->setText(newTag);
(*inboundObject)["tag"] = newTag; (*inboundObject)["tag"] = newTag;
break;
} }
case NODE_OUTBOUND: else
{ {
if (isExternalOutbound) if (isExternalOutbound)
{ {
if (QvMessageBoxAsk(parentWidget(), tr("Edit Outbound"), editExternalMsg) != QMessageBox::Yes) if (QvMessageBoxAsk(parentWidget(), tr("Edit Outbound"), editExternalMsg) != QMessageBox::Yes)
{
return; return;
}
const auto externalId = outboundObject->object.connectionId; const auto externalId = outboundObject->object.connectionId;
const auto root = ConnectionManager->GetConnectionRoot(externalId); const auto root = ConnectionManager->GetConnectionRoot(externalId);
@ -139,37 +129,32 @@ void InboundOutboundWidget::on_editJsonBtn_clicked()
const auto newTag = getTag(outboundObject->realOutbound); const auto newTag = getTag(outboundObject->realOutbound);
tagTxt->setText(newTag); tagTxt->setText(newTag);
outboundObject->realOutbound["tag"] = newTag; outboundObject->realOutbound["tag"] = newTag;
break;
}
} }
} }
} }
void InboundOutboundWidget::on_tagTxt_textEdited(const QString &arg1) void InboundOutboundWidget::on_tagTxt_textEdited(const QString &arg1)
{ {
switch (workingMode) if (workingMode == NODE_INBOUND)
{
case NODE_INBOUND:
{ {
const auto originalTag = (*inboundObject)["tag"].toString(); const auto originalTag = (*inboundObject)["tag"].toString();
if (originalTag == arg1 || dispatcher->RenameTag<NODE_INBOUND>(originalTag, arg1)) if (originalTag == arg1 || dispatcher->RenameTag<NODE_INBOUND>(originalTag, arg1))
{ {
BLACK(tagTxt); BLACK(tagTxt);
(*inboundObject)["tag"] = arg1; (*inboundObject)["tag"] = arg1;
break; return;
} }
RED(tagTxt); RED(tagTxt);
} }
case NODE_OUTBOUND: else
{ {
const auto originalTag = outboundObject->getTag(); const auto originalTag = outboundObject->getTag();
if (originalTag == arg1 || dispatcher->RenameTag<NODE_OUTBOUND>(originalTag, arg1)) if (originalTag == arg1 || dispatcher->RenameTag<NODE_OUTBOUND>(originalTag, arg1))
{ {
BLACK(tagTxt); BLACK(tagTxt);
outboundObject->realOutbound["tag"] = arg1; outboundObject->realOutbound["tag"] = arg1;
break; return;
} }
RED(tagTxt); RED(tagTxt);
} }
} }
}

View File

@ -1,8 +1,9 @@
#include "ChainEditorWidget.hpp" #include "ChainEditorWidget.hpp"
ChainEditorWidget::ChainEditorWidget(QWidget *parent) : QWidget(parent) ChainEditorWidget::ChainEditorWidget(QWidget *parent) : QtNodes::FlowView(parent)
{ {
setupUi(this); setupUi(this);
setScene(new QtNodes::FlowScene(this));
} }
void ChainEditorWidget::changeEvent(QEvent *e) void ChainEditorWidget::changeEvent(QEvent *e)

View File

@ -3,25 +3,21 @@
#include "ui/node/NodeBase.hpp" #include "ui/node/NodeBase.hpp"
#include "ui_ChainEditorWidget.h" #include "ui_ChainEditorWidget.h"
namespace QtNodes #include <nodes/FlowView>
{
class FlowView;
}
class ChainEditorWidget class ChainEditorWidget
: public QWidget : public QtNodes::FlowView
, private Ui::ChainEditorWidget , private Ui::ChainEditorWidget
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit ChainEditorWidget(QWidget *parent = nullptr); explicit ChainEditorWidget(QWidget *parent = nullptr);
auto scene()
{
return QtNodes::FlowView::scene();
}
protected: protected:
void changeEvent(QEvent *e); void changeEvent(QEvent *e);
private:
//
QtNodes::FlowScene *chainScene;
QtNodes::FlowView *chainView;
}; };

View File

@ -1,8 +1,13 @@
#include "RoutingEditorWidget.hpp" #include "RoutingEditorWidget.hpp"
RoutingEditorWidget::RoutingEditorWidget(QWidget *parent) : QWidget(parent) #include <QVBoxLayout>
#include <nodes/FlowScene>
RoutingEditorWidget::RoutingEditorWidget(QWidget *parent) : QtNodes::FlowView(parent)
{ {
setupUi(this); setupUi(this);
setScene(new QtNodes::FlowScene(this));
scaleDown();
} }
void RoutingEditorWidget::changeEvent(QEvent *e) void RoutingEditorWidget::changeEvent(QEvent *e)

View File

@ -2,14 +2,20 @@
#include "ui_RoutingEditorWidget.h" #include "ui_RoutingEditorWidget.h"
#include <nodes/FlowView>
class RoutingEditorWidget class RoutingEditorWidget
: public QWidget : public QtNodes::FlowView
, private Ui::RoutingEditorWidget , private Ui::RoutingEditorWidget
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit RoutingEditorWidget(QWidget *parent = nullptr); explicit RoutingEditorWidget(QWidget *parent = nullptr);
auto scene()
{
return QtNodes::FlowView::scene();
}
protected: protected:
void changeEvent(QEvent *e); void changeEvent(QEvent *e);