diff --git a/edge.cpp b/edge.cpp index e602999..6ee60c1 100644 --- a/edge.cpp +++ b/edge.cpp @@ -16,12 +16,18 @@ Edge::Edge(Node *sourceNode, Node *destNode) setAcceptedMouseButtons(0); m_sourceNode = sourceNode; m_destNode = destNode; - m_sourceNode->addEdge(this); - m_destNode->addEdge(this); + m_sourceNode->addEdge(this,true); + m_destNode->addEdge(this,false); adjust(); // setZValue(1); } +Edge::~Edge() +{ + m_sourceNode->removeEdge(this); + m_destNode->removeEdge(this); +} + Node *Edge::sourceNode() const { return m_sourceNode; @@ -32,7 +38,10 @@ Node *Edge::destNode() const return m_destNode; } -/// @note This is brute force. Isn't there a simple fv for this? +/** @note This is brute force. Isn't there a simple fv for this? + * The precision is not the best either + */ + QPointF firstNotContainedPoint(const QLineF &line, const QRectF &rect, bool reverse = false) @@ -104,15 +113,26 @@ void Edge::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) return; // Draw the arrows - double angle = ::acos(line.dx() / line.length()); + m_angle = ::acos(line.dx() / line.length()); if (line.dy() >= 0) - angle = TwoPi - angle; + m_angle = TwoPi - m_angle; + + qDebug() << m_angle; - QPointF destArrowP1 = m_destPoint + QPointF(sin(angle - Pi / 3) * m_arrowSize, - cos(angle - Pi / 3) * m_arrowSize); - QPointF destArrowP2 = m_destPoint + QPointF(sin(angle - Pi + Pi / 3) * m_arrowSize, - cos(angle - Pi + Pi / 3) * m_arrowSize); + QPointF destArrowP1 = m_destPoint + QPointF(sin(m_angle - Pi / 3) * m_arrowSize, + cos(m_angle - Pi / 3) * m_arrowSize); + QPointF destArrowP2 = m_destPoint + QPointF(sin(m_angle - Pi + Pi / 3) * m_arrowSize, + cos(m_angle - Pi + Pi / 3) * m_arrowSize); painter->setBrush(Qt::black); painter->drawPolygon(QPolygonF() << line.p2() << destArrowP1 << destArrowP2); } + +double Edge::getAngle() const +{ + qDebug() << __PRETTY_FUNCTION__; + + qDebug() << m_angle; + + return m_angle; +} diff --git a/edge.h b/edge.h index 3d4c4b0..8d5de87 100644 --- a/edge.h +++ b/edge.h @@ -10,9 +10,11 @@ class Edge : public QGraphicsItem public: Edge(Node *sourceNode, Node *destNode); + ~Edge(); Node *sourceNode() const; Node *destNode() const; + double getAngle() const; void adjust(); @@ -29,7 +31,7 @@ private: QPointF m_sourcePoint; QPointF m_destPoint; qreal m_arrowSize; - + double m_angle; }; #endif diff --git a/graphwidget.cpp b/graphwidget.cpp index fb890c4..a74a361 100644 --- a/graphwidget.cpp +++ b/graphwidget.cpp @@ -1,15 +1,22 @@ #include "graphwidget.h" + #include -#include "node.h" +#include -//#include + +#include "node.h" #include "edge.h" #include "math.h" +#include "mainwindow.h" + + GraphWidget::GraphWidget(QWidget *parent) : QGraphicsView(parent), + m_parent(parent), m_activeNode(0), - m_showingNodeNumbers(false) + m_showingNodeNumbers(false), + m_followNode(0) { qDebug() << __PRETTY_FUNCTION__; @@ -60,14 +67,58 @@ GraphWidget::GraphWidget(QWidget *parent) : node6->setPos(-10, 100); m_nodeList.append(node6); + Node *node7 = new Node(this); + node7->setHtml(QString("node

important

shit")); + m_scene->addItem(node7); + node7->setPos(-200, 50); + m_nodeList.append(node7); + + Node *node8 = new Node(this); + node8->setHtml(QString("more than\none lins")); + m_scene->addItem(node8); + node8->setPos(50, -80); + m_nodeList.append(node8); + + Node *node9 = new Node(this); + node9->setHtml(QString("iam a bald and italian guy")); + m_scene->addItem(node9); + node9->setPos(50, 40); + m_nodeList.append(node9); + + Node *node10 = new Node(this); + node10->setHtml(QString("no joke")); + m_scene->addItem(node10); + node10->setPos(-160, -10); + m_nodeList.append(node10); + + Node *node11 = new Node(this); + node11->setHtml(QString("salalal")); + m_scene->addItem(node11); + node11->setPos(-120, -120); + m_nodeList.append(node11); + + Node *node12 = new Node(this); + node12->setHtml(QString("lalalala")); + m_scene->addItem(node12); + node12->setPos(130, -10); + m_nodeList.append(node12);; + m_scene->addItem(new Edge(node1, node2)); m_scene->addItem(new Edge(node1, node3)); m_scene->addItem(new Edge(node3, node4)); m_scene->addItem(new Edge(node1, node5)); m_scene->addItem(new Edge(node5, node6)); + m_scene->addItem(new Edge(node4, node11)); + m_scene->addItem(new Edge(node2, node12)); + m_scene->addItem(new Edge(node3, node10)); + m_scene->addItem(new Edge(node10, node7)); + m_scene->addItem(new Edge(node5, node7)); + m_scene->addItem(new Edge(node2, node8)); + m_scene->addItem(new Edge(node2, node9)); + m_activeNode = m_nodeList.first(); - m_activeNode->setActive(true); + m_activeNode->setActive(); } QGraphicsScene *GraphWidget::getScene() @@ -78,20 +129,24 @@ QGraphicsScene *GraphWidget::getScene() void GraphWidget::keyPressEvent(QKeyEvent *event) { qDebug() << __PRETTY_FUNCTION__; -// qDebug() << event->key(); + qDebug() << event->key(); switch (event->key()) { case Qt::Key_Up: - m_activeNode->moveBy(0, -20); + if (m_activeNode) + m_activeNode->moveBy(0, -20); break; case Qt::Key_Down: - m_activeNode->moveBy(0, 20); + if (m_activeNode) + m_activeNode->moveBy(0, 20); break; case Qt::Key_Left: - m_activeNode->moveBy(-20, 0); + if (m_activeNode) + m_activeNode->moveBy(-20, 0); break; case Qt::Key_Right: - m_activeNode->moveBy(20, 0); + if (m_activeNode) + m_activeNode->moveBy(20, 0); break; case Qt::Key_Plus: scaleView(qreal(1.2)); @@ -100,12 +155,30 @@ void GraphWidget::keyPressEvent(QKeyEvent *event) scaleView(1 / qreal(1.2)); break; case Qt::Key_F: - { // need brackets because of local variable m_showingNodeNumbers = !m_showingNodeNumbers; - int i =0; - for (QList::const_iterator it = m_nodeList.begin(); it != m_nodeList.end(); it++, i++) - dynamic_cast(*it)->showNumber(i,m_showingNodeNumbers); - } + if (m_showingNodeNumbers) + m_followNumber.clear(); + + showingAllNodeNumbers(m_showingNodeNumbers); + if (m_showingNodeNumbers) + { + m_nodeList.first()->showNumber(0,true,true); + m_followNode = m_nodeList.first(); + } + break; + + case Qt::Key_Insert: + if (!m_activeNode) + { + dynamic_cast(m_parent)->getStatusBar()->showMessage( + tr("No active node."), + 5000); // millisec + + } + else + { + insertNode(); + } break; case Qt::Key_0: @@ -118,10 +191,74 @@ void GraphWidget::keyPressEvent(QKeyEvent *event) case Qt::Key_7: case Qt::Key_8: case Qt::Key_9: + if (!m_showingNodeNumbers) + break; + + m_followNumber.append(QString::number(event->key()-48)); + showingAllNodeNumbers(false); + showingNodeNumbersBeginWithNumber(m_followNumber.toInt(), true); + + break; - m_activeNode->setActive(false); - m_activeNode = m_nodeList[3]; - m_activeNode->setActive(true); + case Qt::Key_Backspace: + if (!m_showingNodeNumbers) + break; + + if (!m_followNumber.isEmpty()) + { + m_followNumber.remove(m_followNumber.length()-1,1); + if (m_followNumber.isEmpty()) + { + showingAllNodeNumbers(true); + m_nodeList.first()->showNumber(0,true,true); + m_followNode = m_nodeList.first(); + } + else + { + showingAllNodeNumbers(false); + showingNodeNumbersBeginWithNumber(m_followNumber.toInt(), true); + } + } + break; + + case Qt::Key_Return: + case Qt::Key_Enter: + if (m_followNode && m_showingNodeNumbers) + { + qDebug() << m_activeNode; + qDebug() << m_followNode; + showingAllNodeNumbers(false); + if (m_activeNode) + m_activeNode->setActive(false); + m_activeNode = m_followNode; + m_activeNode->setActive(); + m_showingNodeNumbers = false; + } + break; + + case Qt::Key_Delete: + + if (m_activeNode) + { + if (m_followNode==m_activeNode) + m_followNode=0; + + m_nodeList.removeAll(m_activeNode); + delete m_activeNode; + m_activeNode = 0; + + if (m_showingNodeNumbers) + { + m_showingNodeNumbers = false; + showingAllNodeNumbers(false); + } + } + else + { + dynamic_cast(m_parent)->getStatusBar()->showMessage( + tr("No active node."), + 5000); // millisec + } break; @@ -159,7 +296,6 @@ void GraphWidget::scaleView(qreal scaleFactor) scale(scaleFactor, scaleFactor); } -/// @note this == 0? how is it possible? void GraphWidget::setActiveNode(Node *node) { qDebug() << __PRETTY_FUNCTION__; @@ -168,5 +304,80 @@ void GraphWidget::setActiveNode(Node *node) m_activeNode->setActive(false); m_activeNode = node; - m_activeNode->setActive(true); + m_activeNode->setActive(); +} + +void GraphWidget::insertNode() +{ + qDebug() << __PRETTY_FUNCTION__; + + double angle(m_activeNode->calculateBiggestAngle()); + + qreal length(100); + + qDebug() << "angle: "; + qDebug() << angle; + + QPointF pos(length * cos(angle), length * sin(angle)); + + + qDebug() << pos; + + Node *node = new Node(this); + node->setHtml(QString("new node")); + m_scene->addItem(node); + node->setPos(m_activeNode->pos() + +// m_activeNode->boundingRect().center() + + pos); + m_nodeList.append(node); + + m_scene->addItem(new Edge(m_activeNode, node)); +} + +void GraphWidget::showingAllNodeNumbers(const bool &show) +{ + int i =0; + for (QList::const_iterator it = m_nodeList.begin(); it != m_nodeList.end(); it++, i++) + dynamic_cast(*it)->showNumber(i,show); +} + +void GraphWidget::showingNodeNumbersBeginWithNumber(const int &number, const bool &show) +{ + int i(0); + int hit(0); + for (QList::const_iterator it = m_nodeList.begin(); it != m_nodeList.end(); it++, i++) + { + if (i == number) + { + hit++; + dynamic_cast(*it)->showNumber(i,show,true); + m_followNode = dynamic_cast(*it); + continue; + } + if (numberStartsWithNumber(i, number)) + { + hit++; + dynamic_cast(*it)->showNumber(i,show); + } + } + if (hit==1) + { + showingAllNodeNumbers(false); + if (m_activeNode) + m_activeNode->setActive(false); + + m_activeNode = m_followNode; + m_activeNode->setActive(); + m_showingNodeNumbers = false; + } + else if (hit == 0) + { + m_showingNodeNumbers = false; + showingAllNodeNumbers(false); + } +} + +bool GraphWidget::numberStartsWithNumber(const int &number, const int &prefix) +{ + return (QString::number(number)).startsWith(QString::number(prefix)); } diff --git a/graphwidget.h b/graphwidget.h index f9cb66e..7cc17a5 100644 --- a/graphwidget.h +++ b/graphwidget.h @@ -17,6 +17,7 @@ public: GraphWidget(QWidget *parent = 0); QGraphicsScene *getScene(); void setActiveNode(Node *node); + void insertNode(); protected: @@ -28,11 +29,18 @@ protected: private: + void showingAllNodeNumbers(const bool &show = true); + void showingNodeNumbersBeginWithNumber(const int &number, const bool &show = true); + bool numberStartsWithNumber(const int &number, const int &prefix); + qreal calculateBiggestAngle(Node *node); + QList m_nodeList; + QWidget *m_parent; Node *m_activeNode; QGraphicsScene *m_scene; bool m_showingNodeNumbers; - + QString m_followNumber; + Node *m_followNode; }; diff --git a/mainwindow.cpp b/mainwindow.cpp index 5140074..45a29c3 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -47,7 +47,7 @@ MainWindow::MainWindow(QWidget *parent) : connect(m_ui->actionAbout_QtMindMap, SIGNAL(activated()), this, SLOT(about())); - m_graphicsView = new GraphWidget(m_ui->centralWidget); + m_graphicsView = new GraphWidget(this); setCentralWidget(m_graphicsView); } @@ -120,3 +120,8 @@ void MainWindow::aboutDestroyed() setEnabled(true); } + +QStatusBar * MainWindow::getStatusBar() +{ + return m_ui->statusBar; +} diff --git a/mainwindow.h b/mainwindow.h index 483bf36..cd54171 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -18,6 +18,7 @@ class MainWindow : public QMainWindow public: explicit MainWindow(QWidget *parent = 0); ~MainWindow(); + QStatusBar * getStatusBar(); public slots: void klakk(); diff --git a/mainwindow.ui b/mainwindow.ui index 4485505..029f7d3 100644 --- a/mainwindow.ui +++ b/mainwindow.ui @@ -55,6 +55,9 @@ + + false + &New @@ -63,6 +66,9 @@ + + false + &Open @@ -71,6 +77,9 @@ + + false + &Save @@ -92,6 +101,9 @@ + + false + &Close diff --git a/node.cpp b/node.cpp index c53c0c5..09b38b7 100644 --- a/node.cpp +++ b/node.cpp @@ -5,12 +5,14 @@ #include #include +static const double Pi = 3.14159265358979323846264338327950288419717; + Node::Node(GraphWidget *parent) : m_graph(parent), m_isActive(false), - m_activeEdge(0), m_number(-1), m_hasBorder(true) + m_numberIsSpecial(false) { qDebug() << __PRETTY_FUNCTION__; @@ -26,18 +28,35 @@ Node::Node(GraphWidget *parent) : // setTextInteractionFlags(Qt::TextEditorInteraction); } -void Node::addEdge(Edge *edge) +Node::~Node() +{ + qDebug() << __PRETTY_FUNCTION__; + foreach (EdgeElement element, m_edgeList) delete element.edge; +} + +void Node::addEdge(Edge *edge, bool startsFromThisNode) { qDebug() << __PRETTY_FUNCTION__; - m_edgeList << edge; + m_edgeList.push_back(EdgeElement(edge, startsFromThisNode)); edge->adjust(); } +void Node::removeEdge(Edge *edge) +{ + qDebug() << __PRETTY_FUNCTION__; + + for(QList::iterator it = m_edgeList.begin(); it != m_edgeList.end(); it++) + if (it->edge == edge) + { + m_edgeList.erase(it); + return; + } +} QVariant Node::itemChange(GraphicsItemChange change, const QVariant &value) { - qDebug() << __PRETTY_FUNCTION__; +// qDebug() << __PRETTY_FUNCTION__; switch (change) { @@ -62,7 +81,7 @@ QVariant Node::itemChange(GraphicsItemChange change, const QVariant &value) case ItemPositionHasChanged: - foreach (Edge *edge, m_edgeList) edge->adjust(); + foreach (EdgeElement element, m_edgeList) element.edge->adjust(); break; default: break; @@ -73,7 +92,13 @@ QVariant Node::itemChange(GraphicsItemChange change, const QVariant &value) void Node::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *w) { - qDebug() << __PRETTY_FUNCTION__; +// qDebug() << __PRETTY_FUNCTION__; + + if (m_number != -1) + { + painter->setBackground(m_numberIsSpecial ? Qt::green : Qt::yellow); + painter->setBackgroundMode(Qt::OpaqueMode); + } QGraphicsTextItem::paint(painter, option, w); @@ -84,12 +109,10 @@ void Node::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWid boundingRect().bottomRight().toPoint() - QPoint(1,1))); - qDebug() << m_number; - if (m_number != -1) { - painter->setPen(Qt::yellow); - painter->setBackground(Qt::black); + painter->setPen(Qt::white); + painter->setBackground(Qt::red); painter->setBackgroundMode(Qt::OpaqueMode); painter->drawText(boundingRect().topLeft()+QPointF(0,11), QString("%1").arg(m_number)); } @@ -104,34 +127,45 @@ void Node::setActive(const bool &active) } +/// @note who shall set active: press or release? void Node::mousePressEvent(QGraphicsSceneMouseEvent *event) { qDebug() << __PRETTY_FUNCTION__; + m_graph->setActiveNode(this); + QGraphicsItem::mousePressEvent(event); } -void Node::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) +void Node::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) { qDebug() << __PRETTY_FUNCTION__; - m_graph->setActiveNode(this); + m_graph->insertNode(); + + QGraphicsItem::mouseDoubleClickEvent(event); +} + +void Node::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) +{ + qDebug() << __PRETTY_FUNCTION__; QGraphicsItem::mouseReleaseEvent(event); } void Node::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { - qDebug() << __PRETTY_FUNCTION__; +// qDebug() << __PRETTY_FUNCTION__; QGraphicsItem::mouseMoveEvent(event); } -void Node::showNumber(const int &number, const bool& show) +void Node::showNumber(const int &number, const bool& show, const bool &numberIsSpecial) { - qDebug() << __PRETTY_FUNCTION__; +// qDebug() << __PRETTY_FUNCTION__; m_number = show ? number : -1; + m_numberIsSpecial = numberIsSpecial; update(); } @@ -140,3 +174,60 @@ void Node::setBorder(const bool &hasBorder) m_hasBorder = hasBorder; update(); } + +double Node::calculateBiggestAngle() +{ + qDebug() << __PRETTY_FUNCTION__; + + if (m_edgeList.empty()) + return 1.5 * Pi; + + if (m_edgeList.size()==1) + { + if (m_edgeList.first().startsFromThisNode) + { + return Pi - m_edgeList.first().edge->getAngle(); + } + else + { + return 2 * Pi - m_edgeList.first().edge->getAngle(); + } + } + + QList tmp; + for(QList::iterator it = m_edgeList.begin(); it != m_edgeList.end(); it++) + { + if (it->startsFromThisNode) + { + tmp.push_back(Pi - it->edge->getAngle()); + } + else + { + tmp.push_back(2 * Pi - it->edge->getAngle()); + } + } + + qSort(tmp.begin(), tmp.end()); + + qDebug() << tmp; + + double prev(tmp.last()); + double max_prev(tmp.last()); + double max(0); + + /// @bug algorith is baaad + for(QList::const_iterator it = tmp.begin(); it!=tmp.end(); it++) + { + if (abs(*it - prev) > abs(max) ) + { + max = *it - prev; + max_prev = prev; + } + prev = *it; + } + + qDebug() << max; + qDebug() << max_prev; + + return max_prev + max / 2 ; +} diff --git a/node.h b/node.h index 1c89eeb..7fefc02 100644 --- a/node.h +++ b/node.h @@ -13,30 +13,49 @@ class Node : public QGraphicsTextItem public: Node(GraphWidget *graphWidget = 0); + ~Node(); - void addEdge(Edge *edge); + void addEdge(Edge *edge, bool startsFromThisNode); + void removeEdge(Edge *edge); // QList edges() const; - void setActive(const bool &active); - void showNumber(const int &number, const bool& show); void setBorder(const bool &hasBorder); - + void setActive(const bool &active = true); + void showNumber(const int &number, const bool& show = true, const bool &numberIsSpecial = false); + double calculateBiggestAngle(); protected: void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); QVariant itemChange(GraphicsItemChange change, const QVariant &value); void mousePressEvent(QGraphicsSceneMouseEvent *event); + void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event); void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); void mouseMoveEvent(QGraphicsSceneMouseEvent *event); private: - QList m_edgeList; + struct EdgeElement + { + Edge *edge; + bool startsFromThisNode; + EdgeElement(Edge *e, bool s) : edge(e), startsFromThisNode(s) {} + }; +// class EdgeList : public QList +// { +// public: +// int compareItems(QCollection::Item a, QCollection::Item b) +// { +// return (EdgeElement)a.edge = (EdgeElement)b.edge; +// } +// }; + + QList m_edgeList; GraphWidget *m_graph; bool m_isActive; - Edge *m_activeEdge; +// Edge *m_activeEdge; int m_number; bool m_hasBorder; + bool m_numberIsSpecial; }; #endif // NODE_H diff --git a/qtmindmap.pro.user b/qtmindmap.pro.user index 675c486..a2bd180 100644 --- a/qtmindmap.pro.user +++ b/qtmindmap.pro.user @@ -182,7 +182,7 @@ qtmindmap.pro false - false + true 3768