1 /*
2  *  SPDX-FileCopyrightText: 2014-2015 Andreas Cord-Landwehr <cordlandwehr@kde.org>
3  *
4  *  SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
5  */
6 
7 #include "view.h"
8 #include "models/nodemodel.h"
9 #include "models/edgemodel.h"
10 #include "models/nodepropertymodel.h"
11 #include "models/edgepropertymodel.h"
12 #include "models/nodetypemodel.h"
13 #include "models/edgetypemodel.h"
14 #include "qtquickitems/nodeitem.h"
15 #include "qtquickitems/edgeitem.h"
16 #include "dialogs/nodeproperties.h"
17 #include "dialogs/edgeproperties.h"
18 #include "logging_p.h"
19 
20 #include <QQmlApplicationEngine>
21 #include <KLocalizedContext>
22 #include <QQmlComponent>
23 #include <QQmlContext>
24 #include <QQmlEngine>
25 #include <QPointer>
26 #include <QStandardPaths>
27 
28 using namespace GraphTheory;
29 
30 class GraphTheory::ViewPrivate {
31 public:
ViewPrivate()32     ViewPrivate()
33         : m_edgeModel(new EdgeModel())
34         , m_nodeModel(new NodeModel())
35         , m_edgeTypeModel(new EdgeTypeModel())
36         , m_nodeTypeModel(new NodeTypeModel)
37     {
38     }
39 
~ViewPrivate()40     ~ViewPrivate()
41     {
42         delete m_edgeModel;
43         delete m_nodeModel;
44         delete m_edgeTypeModel;
45         delete m_nodeTypeModel;
46     }
47 
48     GraphDocumentPtr m_document;
49     EdgeModel *m_edgeModel;
50     NodeModel *m_nodeModel;
51     EdgeTypeModel *m_edgeTypeModel;
52     NodeTypeModel *m_nodeTypeModel;
53 };
54 
55 
View(QWidget * parent)56 View::View(QWidget *parent)
57     : QQuickWidget(parent)
58     , d(new ViewPrivate)
59 {
60     setResizeMode(QQuickWidget::SizeRootObjectToView);
61 
62     // workaround for QTBUG-40765
63     qApp->setAttribute(Qt::AA_DontCreateNativeWidgetSiblings);
64 
65     // prepare i18n
66     auto context = new KLocalizedContext(this);
67     context->setTranslationDomain("libgraphtheory");
68     engine()->rootContext()->setContextObject(context);
69 
70     qmlRegisterType<GraphTheory::Node>("org.kde.rocs.graphtheory", 1, 0, "Node");
71     qmlRegisterType<GraphTheory::Edge>("org.kde.rocs.graphtheory", 1, 0, "Edge");
72     qmlRegisterType<GraphTheory::NodeType>("org.kde.rocs.graphtheory", 1, 0, "NodeType");
73     qmlRegisterType<GraphTheory::EdgeType>("org.kde.rocs.graphtheory", 1, 0, "EdgeType");
74     qmlRegisterType<GraphTheory::NodeItem>("org.kde.rocs.graphtheory", 1, 0, "NodeItem");
75     qmlRegisterType<GraphTheory::EdgeItem>("org.kde.rocs.graphtheory", 1, 0, "EdgeItem");
76     qmlRegisterType<GraphTheory::NodeModel>("org.kde.rocs.graphtheory", 1, 0, "NodeModel");
77     qmlRegisterType<GraphTheory::EdgeModel>("org.kde.rocs.graphtheory", 1, 0, "EdgeModel");
78     qmlRegisterType<GraphTheory::NodePropertyModel>("org.kde.rocs.graphtheory", 1, 0, "NodePropertyModel");
79     qmlRegisterType<GraphTheory::EdgePropertyModel>("org.kde.rocs.graphtheory", 1, 0, "EdgePropertyModel");
80     qmlRegisterType<GraphTheory::NodeTypeModel>("org.kde.rocs.graphtheory", 1, 0, "NodeTypeModel");
81     qmlRegisterType<GraphTheory::EdgeTypeModel>("org.kde.rocs.graphtheory", 1, 0, "EdgeTypeModel");
82 
83     QUrl path = QUrl("qrc:/libgraphtheory/qml/Scene.qml");
84     QQmlComponent *component = new QQmlComponent(engine());
85     component->loadUrl(path);
86     if (!component->isReady() ) {
87         qCWarning(GRAPHTHEORY_GENERAL) << component->errorString();
88         return;
89     }
90 
91     // register editor elements at context
92     engine()->rootContext()->setContextProperty("nodeModel", d->m_nodeModel);
93     engine()->rootContext()->setContextProperty("edgeModel", d->m_edgeModel);
94     engine()->rootContext()->setContextProperty("nodeTypeModel", d->m_nodeTypeModel);
95     engine()->rootContext()->setContextProperty("edgeTypeModel", d->m_edgeTypeModel);
96 
97     // create rootObject after context is set up
98     QObject *topLevel = component->create();
99 
100     // connections to QML signals
101     connect(topLevel, SIGNAL(createNode(qreal,qreal,int)),
102             this, SLOT(createNode(qreal,qreal,int)));
103     connect(topLevel, SIGNAL(createEdge(GraphTheory::Node*,GraphTheory::Node*,int)),
104             this, SLOT(createEdge(GraphTheory::Node*,GraphTheory::Node*,int)));
105     connect(topLevel, SIGNAL(deleteNode(GraphTheory::Node*)),
106             this, SLOT(deleteNode(GraphTheory::Node*)));
107     connect(topLevel, SIGNAL(deleteEdge(GraphTheory::Edge*)),
108             this, SLOT(deleteEdge(GraphTheory::Edge*)));
109     connect(topLevel, SIGNAL(showNodePropertiesDialog(GraphTheory::Node*)),
110             this, SLOT(showNodePropertiesDialog(GraphTheory::Node*)));
111     connect(topLevel, SIGNAL(showEdgePropertiesDialog(GraphTheory::Edge*)),
112             this, SLOT(showEdgePropertiesDialog(GraphTheory::Edge*)));
113 
114     // create widget
115     setContent(path, component, topLevel);
116 }
117 
~View()118 View::~View()
119 {
120 
121 }
122 
setGraphDocument(GraphDocumentPtr document)123 void View::setGraphDocument(GraphDocumentPtr document)
124 {
125     d->m_document = document;
126     d->m_nodeModel->setDocument(d->m_document);
127     d->m_edgeModel->setDocument(d->m_document);
128     d->m_nodeTypeModel->setDocument(d->m_document);
129     d->m_edgeTypeModel->setDocument(d->m_document);
130 }
131 
graphDocument() const132 GraphDocumentPtr View::graphDocument() const
133 {
134     return d->m_document;
135 }
136 
createNode(qreal x,qreal y,int typeIndex)137 void View::createNode(qreal x, qreal y, int typeIndex)
138 {
139     Q_ASSERT(typeIndex >= 0);
140     Q_ASSERT(typeIndex < d->m_nodeTypeModel->rowCount());
141     NodePtr node = Node::create(d->m_document);
142     node->setType(d->m_nodeTypeModel->type(typeIndex));
143     node->setX(x);
144     node->setY(y);
145 }
146 
createEdge(Node * from,Node * to,int typeIndex)147 void View::createEdge(Node *from, Node *to, int typeIndex)
148 {
149     Q_ASSERT(typeIndex >= 0);
150     Q_ASSERT(typeIndex < d->m_edgeTypeModel->rowCount());
151     if (!from || !to) {
152         return;
153     }
154     if (!from->isValid() || !to->isValid()) {
155         return;
156     }
157     EdgePtr edge = Edge::create(from->self(), to->self());
158     edge->setType(d->m_edgeTypeModel->type(typeIndex));
159 }
160 
deleteNode(GraphTheory::Node * node)161 void View::deleteNode(GraphTheory::Node *node)
162 {
163     if (!node || !node->isValid()) {
164         return;
165     }
166     node->destroy();
167 }
168 
deleteEdge(GraphTheory::Edge * edge)169 void View::deleteEdge(GraphTheory::Edge *edge)
170 {
171     if (!edge || !edge->isValid()) {
172         return;
173     }
174     edge->destroy();
175 }
176 
showNodePropertiesDialog(Node * node)177 void View::showNodePropertiesDialog(Node *node)
178 {
179     QPointer<NodeProperties> dialog = new NodeProperties();
180     dialog->setData(node->self());
181     dialog->show(); // workaround: scene-drag not working with modal dialogs
182 }
183 
showEdgePropertiesDialog(Edge * edge)184 void View::showEdgePropertiesDialog(Edge *edge)
185 {
186     QPointer<EdgeProperties> dialog = new EdgeProperties();
187     dialog->setData(edge->self());
188     dialog->show(); // workaround: scene-drag not working with modal dialogs
189 }
190