summaryrefslogtreecommitdiffstats
path: root/src/gui/graphicsview
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/graphicsview')
-rw-r--r--src/gui/graphicsview/graphicsview.pri3
-rw-r--r--src/gui/graphicsview/qgraph_p.h179
2 files changed, 181 insertions, 1 deletions
diff --git a/src/gui/graphicsview/graphicsview.pri b/src/gui/graphicsview/graphicsview.pri
index 0c0747e..ce35721 100644
--- a/src/gui/graphicsview/graphicsview.pri
+++ b/src/gui/graphicsview/graphicsview.pri
@@ -20,7 +20,8 @@ HEADERS += graphicsview/qgraphicsgridlayout.h \
graphicsview/qgraphicsview_p.h \
graphicsview/qgraphicswidget.h \
graphicsview/qgraphicswidget_p.h \
- graphicsview/qgridlayoutengine_p.h
+ graphicsview/qgridlayoutengine_p.h \
+ graphicsview/qgraph_p.h
SOURCES += graphicsview/qgraphicsgridlayout.cpp \
graphicsview/qgraphicsitem.cpp \
diff --git a/src/gui/graphicsview/qgraph_p.h b/src/gui/graphicsview/qgraph_p.h
new file mode 100644
index 0000000..4a6bc8f
--- /dev/null
+++ b/src/gui/graphicsview/qgraph_p.h
@@ -0,0 +1,179 @@
+#include <QtCore/QHash>
+#include <QtCore/QQueue>
+#include <QtCore/QString>
+#include <QtCore/QDebug>
+
+#include <float.h>
+
+template <typename Vertex, typename EdgeData>
+class Graph
+{
+public:
+ Graph() {}
+
+ class iterator {
+ public:
+ iterator(Graph *graph, bool begin) : g(graph){
+ if (begin) {
+ row = g->m_graph.begin();
+ //test if the graph is empty
+ if (row != g->m_graph.end())
+ {
+ column = (*row)->begin();
+ }
+ } else {
+ row = g->m_graph.end();
+ }
+ }
+
+ inline Vertex *operator*() {
+ return column.key();
+ }
+
+ inline bool operator==(const iterator &o) const { return !(*this != o); }
+ inline bool operator!=(const iterator &o) const {
+ if (row == g->m_graph.end()) {
+ return row != o.row;}
+ else {
+ return row != o.row || column != o.column;
+ }
+ }
+ inline iterator& operator=(const iterator &o) const { row = o.row; column = o.column; return *this;}
+
+ // prefix
+ iterator &operator++() {
+ if (row != g->m_graph.end()) {
+ ++column;
+ if (column == (*row)->end()) {
+ ++row;
+ if (row != g->m_graph.end()) {
+ column = (*row)->begin();
+ }
+ }
+ }
+ return *this;
+ }
+
+ private:
+ Graph *g;
+ Q_TYPENAME QHash<Vertex *, QHash<Vertex *, EdgeData *> * >::iterator row;
+ Q_TYPENAME QHash<Vertex *, EdgeData *>::iterator column;
+ };
+
+ iterator begin() {
+ return iterator(this,true);
+ }
+
+ iterator end() {
+ return iterator(this,false);
+ }
+
+ EdgeData *edgeData(Vertex *first, Vertex *second) {
+ return m_graph.value(first)->value(second);
+ }
+
+ void createEdge(Vertex *first, Vertex *second, EdgeData *data)
+ {
+ // Creates a bidirectional edge
+ createDirectedEdge(first, second, data);
+ createDirectedEdge(second, first, data);
+ }
+
+ void removeEdge(Vertex *first, Vertex *second)
+ {
+ // Creates a bidirectional edge
+ EdgeData *data = edgeData(first, second);
+ if (data) delete data;
+ removeDirectedEdge(first, second);
+ removeDirectedEdge(second, first);
+ }
+
+ QList<Vertex *> adjacentVertices(Vertex *vertex) const
+ {
+ QHash<Vertex *, EdgeData *> *row = m_graph.value(vertex);
+ QList<Vertex *> l;
+ if (row)
+ l = row->keys();
+ return l;
+ }
+
+ void setRootVertex(Vertex *vertex)
+ {
+ userVertex = vertex;
+ }
+
+ QString serializeToDot() { // traversal
+ QString vertices;
+ QString edges;
+ QQueue<Vertex *> queue;
+ QSet<Vertex *> visited;
+ bool ok;
+ Vertex *v = firstVertex(&ok);
+ if (ok) {
+ queue.enqueue(v);
+ }
+ while (!queue.isEmpty()) {
+ Vertex *v = queue.dequeue();
+ vertices += QString::fromAscii("%1 [label=\"%2\"]\n").arg(v->toString()).arg(v->toString());
+ visited.insert(v);
+ // visit it here
+ QList<Vertex *> vertices = adjacentVertices(v);
+ for (int i = 0; i < vertices.count(); ++i) {
+ Vertex *v1 = vertices.at(i);
+ EdgeData *data = edgeData(v, v1);
+ edges+=QString::fromAscii("%1->%2 [label=\"[%3,%4]\"]\n").arg(v->toString()).arg(v1->toString()).arg(data->minSize).arg(data->maxSize);
+ if (!queue.contains(v1) && !visited.contains(v1)) {
+ queue.enqueue(v1);
+ } else {
+ // a cycle....
+ }
+ }
+ }
+ return QString::fromAscii("digraph anchorlayout {\nnode [shape=\"rect\"]\n%1%2}").arg(vertices).arg(edges);
+ }
+
+ Vertex *firstVertex(bool *ok)
+ {
+ if (userVertex) {
+ *ok = true;
+ return userVertex;
+ }
+
+ Vertex *v = 0;
+ *ok = false;
+ Q_TYPENAME Graph::iterator it = Graph::begin();
+ if (it != Graph::end()) {
+ v = *it;
+ *ok = true;
+ }
+ return v;
+ }
+
+protected:
+ void createDirectedEdge(Vertex *from, Vertex *to, EdgeData *data)
+ {
+ QHash<Vertex *, EdgeData *> *adjacentToFirst = m_graph.value(from);
+ if (!adjacentToFirst) {
+ adjacentToFirst = new QHash<Vertex *, EdgeData *>();
+ m_graph.insert(from, adjacentToFirst);
+ }
+ adjacentToFirst->insert(to, data);
+ }
+
+ void removeDirectedEdge(Vertex *from, Vertex *to)
+ {
+ QHash<Vertex *, EdgeData *> *adjacentToFirst = m_graph.value(from);
+ adjacentToFirst->remove(to);
+ if (adjacentToFirst->isEmpty()) {
+ //nobody point to 'from' so we can remove it from the graph
+ QHash<Vertex *, EdgeData *> *adjacentToFirst = m_graph.take(from);
+ delete adjacentToFirst;
+ delete from;
+ }
+ }
+
+private:
+ Vertex *userVertex;
+
+ QHash<Vertex *, QHash<Vertex *, EdgeData *> *> m_graph;
+};