/**************************************************************************** ** ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** This file is part of the examples of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:BSD$ ** You may use this file under the terms of the BSD license as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are ** met: ** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in ** the documentation and/or other materials provided with the ** distribution. ** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor ** the names of its contributors may be used to endorse or promote ** products derived from this software without specific prior written ** permission. ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "graphwidget.h" #include "edge.h" #include "node.h" #include "point.h" #include #include #include #include /** Constructor for GraphWidget @param parent the parent of this widget @param comModel reference to the CommModel */ GraphWidget::GraphWidget(QWidget *parent, CommModel *comModel) : QGraphicsView(parent), timerId(0) { QGraphicsScene *scene = new QGraphicsScene(this); scenex = scene; scene->setItemIndexMethod(QGraphicsScene::NoIndex); scene->setSceneRect(-250, -220, 625, 500); setScene(scene); setCacheMode(CacheBackground); setViewportUpdateMode(BoundingRectViewportUpdate); setRenderHint(QPainter::Antialiasing); setTransformationAnchor(AnchorUnderMouse); scale(qreal(0.8), qreal(0.8)); this->comm = comModel; sourceSet = false; destSet = false; } /** Gets the main window @return main window */ MainWindow * GraphWidget::getMainWindow() { return mainWindow; } /** Sets the main window @param _mainWindow value for mainWindow */ void GraphWidget::setMainWindow(MainWindow * _mainWindow) { mainWindow = _mainWindow; } /** starts the timer when it item moves */ void GraphWidget::itemMoved() { if (!timerId) timerId = startTimer(1000 / 25); } /** Compares the mac addresses of the two nodes @param n1 node 1 @param n2 node 2 @return true if n1 and n2 have the same mac address */ bool GraphWidget::sameMacAddr(node* n1, node* n2) { for(int i = 0; i < 6; i++) { if(n1->mac_addr.addr[i] != n2->mac_addr.addr[i]) return false; } return true; } /** Searches the nodes for a matching ip address @param ip_addr the ip address to look for @return true if a node with a matching ip address was found */ bool GraphWidget::checkIp(uint32_t ip_addr) { foreach (Node * n, allNodes) { if (n->getIpAddr() == ip_addr) { n->setActive(); return true; } } return false; } /** Checks the mac address of a node @param nx the node to check @return true if the mac address matches */ bool GraphWidget::checkMac(node* nx) { foreach (Node * n, allNodes) { //if (n->getIpAddr() == ip_addr) if(sameMacAddr(nx, n->getNodePointer())) { n->setActive(); return true; } } return false; } /** Gets the graphical node representation for a model node @param n the model node @return graphical node representing this node, NULL if it doesn't exist */ Node * GraphWidget::getNode(node * n) { foreach (Node * nx, allNodes) { /*When we get Mac Addresses working, use the next line instead of the IP one.*/ if(sameMacAddr(nx->getNodePointer(), n)) //if (nx->getIpAddr() == n->ip_addr) { perror("getNode: found the node based on mac address.\n"); return nx; } } perror("getNode: couldn't find the node based on mac address.\n"); return NULL; } /** Checks if two model nodes are connected @param n node a @param nb node b @return true if the two nodes are neighbors */ bool GraphWidget::hasEdge(Node * n, node * nb) { Node * neighbor = getNode(nb); foreach (Edge * e, n->edges()) { if (n == e->sourceNode() && neighbor == e->destNode()) { return true; } } return false; } /** Updates the graph @param nodes a vector of all the nodes */ void GraphWidget::updateGraph(std::vector nodes) { if (sourceSet && destSet) { std::vector prefPath = comm->get_preferred_path(); if (!prefPath.empty()) { this->highlightPath(prefPath); } } foreach (node * n, nodes) { if(!(checkMac(n))) //if (!(checkIp(n->ip_addr))) { Node * temp = new Node(this, false, n->ip_addr, n); //delete n; allNodes << temp; scenex->addItem(temp); temp->setY(rand()%200); temp->setX(rand()%200); } } foreach (node * n, nodes) { Node * curnode = getNode(n); struct in_addr theaddr; theaddr.s_addr = curnode->getIpAddr(); //curNode can't be NULL! fprintf(stderr, "ip_addr is: %s\n\n", inet_ntoa(theaddr)); std::vector neighbors = comm->get_neighbors(n); fprintf(stderr, "Its past\n\n", inet_ntoa(theaddr)); foreach (node * nb, neighbors) { //WE SHOULDN'T USE IP FOR ANYTHING. We need to use Mac Address if (/*nb->ip_addr!=0 &&*/ !(hasEdge(curnode, nb))) { Node * neighbor = getNode(nb); //if(neighbor != NULL) scenex->addItem(new Edge(curnode, neighbor, comm, mainWindow, false)); // <- This crashes shit. neighbor is null. } } } foreach (Node * n, allNodes) { bool found = false; foreach (node * nx, nodes) { //if (nx->ip_addr == n->getIpAddr()) if(sameMacAddr(nx, n->getNodePointer())) { found = true; } } if (!found) { n->setInactive(); } } foreach (Node * n, allNodes) { if (!(n->isActive())) { foreach (Edge * e, n->edges()) { scenex->removeItem(e); } } else { foreach (Edge * e, n->edges()) { node * nx = n->getNodePointer(); std::vector neighbors = comm->get_neighbors(nx); if (e->sourceNode() == n) { Node * other = e->destNode(); bool found = false; foreach (node * nb, neighbors) { //if (nb->ip_addr == other->getIpAddr()) if(sameMacAddr(nb, other->getNodePointer())) { found = true; } } if (!found) { scenex->removeItem(e); } } } } } if (! _doPhysics) { plotNodes(); } } /** Handles timer events @param event the event that is being handled */ void GraphWidget::timerEvent(QTimerEvent *event) { Q_UNUSED(event); QList nodes; foreach (QGraphicsItem *item, scene()->items()) { if (Node *node = qgraphicsitem_cast(item)) nodes << node; } foreach (Node *node, nodes) node->calculateForces(_doPhysics); bool itemsMoved = false; foreach (Node *node, nodes) { if (node->advance()) itemsMoved = true; } /*if (!itemsMoved) { killTimer(timerId); timerId = 0; }*/ bool move = false; for (int i = 0; i < allNodes.size() && !move; i++) { Node * n = allNodes[i]; for (int j = 0; j < n->edges().size() && !move; j++) { Edge * e = n->edges()[j]; if (e->tooShort()) { move = true; } } } if (!move) { killTimer(timerId); timerId = 0; } } /** Draws the background of the widget @param painter the painter used for drawing the background @param rect the bounding box of the background */ void GraphWidget::drawBackground(QPainter *painter, const QRectF &rect) { Q_UNUSED(rect); // Shadow QRectF sceneRect = this->sceneRect(); /*QRectF rightShadow(sceneRect.right(), sceneRect.top() + 5, 5, sceneRect.height()); QRectF bottomShadow(sceneRect.left() + 5, sceneRect.bottom(), sceneRect.width(), 5); if (rightShadow.intersects(rect) || rightShadow.contains(rect)) painter->fillRect(rightShadow, Qt::darkGray); if (bottomShadow.intersects(rect) || bottomShadow.contains(rect)) painter->fillRect(bottomShadow, Qt::darkGray);*/ // Fill /* QLinearGradient gradient(sceneRect.topLeft(), sceneRect.bottomRight()); gradient.setColorAt(0, Qt::white); gradient.setColorAt(1, Qt::lightGray); painter->fillRect(rect.intersect(sceneRect), gradient); painter->setBrush(Qt::NoBrush); painter->drawRect(sceneRect); */ // Text QRectF textRect(sceneRect.left() + 4, sceneRect.top() + 4, sceneRect.width() - 4, sceneRect.height() - 4); QString message(tr("")); QFont font = painter->font(); font.setBold(true); font.setPointSize(14); painter->setFont(font); painter->setPen(Qt::lightGray); painter->drawText(textRect.translated(2, 2), message); painter->setPen(Qt::black); painter->drawText(textRect, message); /* foreach(Node* n, allNodes) { struct in_addr theAddr; theAddr.s_addr = n->getIpAddr(); char *stringrepofIpAddress = inet_ntoa(theAddr); painter->drawText(n->getPosition(), QString("%0").arg(stringrepofIpAddress)); }*/ } /* void GraphWidget::scaleView(qreal scaleFactor) { qreal factor = transform().scale(scaleFactor, scaleFactor).mapRect(QRectF(0, 0, 1, 1)).width(); if (factor < 0.07 || factor > 100) return; scale(scaleFactor, scaleFactor); } */ /** Sets a selected node @newIP ip of the selected node */ void GraphWidget::setSelectedIP(uint32_t newIP) { selectedIP = newIP; } uint32_t GraphWidget::getSelectedIP() { return selectedIP; } /** Sets the source mac address @param newMac mac address of the new source node */ void GraphWidget::setSourceMac(mac_t newMac) { foreach (node *n, comm->get_all_nodes()) { if (Node::macEqual(n->mac_addr, newMac)) { this->comm->set_ocu_machine(n); } } sourceMac = newMac; sourceSet = true; } /** Sets the destination mac address @param newMac mac address of the new destination node */ void GraphWidget::setDestinationMac(mac_t newMac) { foreach (node *n, comm->get_all_nodes()) { if (Node::macEqual(n->mac_addr, newMac)) { this->comm->set_target(n); } } destMac = newMac; destSet = true; } /** Gets the destination mac address @return destination mac address */ mac_t GraphWidget::getDestinationMac() { return destMac; } /** Gets the source mac address @return source mac address */ mac_t GraphWidget::getSourceMac() { return sourceMac; } /** Updates the location and appearance of nodes and egdges */ void GraphWidget::updateNodesAndEdges() { /*if (sourceSet && destSet) { std::vector prefPath = comm->get_preferred_path(); if (!prefPath.empty()) { this->highlightPath(prefPath); } }*/ QList::const_iterator stlIter; for( stlIter = allNodes.begin(); stlIter != allNodes.end(); ++stlIter ) //for(std::vector::iterator it = graph->allNodes.begin(); it != allNodes.end(); ++it) { Node *cur = (*stlIter); cur->update(); foreach (Edge* e, cur->edges()) { e->update(); } } mainWindow->updateList(); if (!_doPhysics) { plotNodes(); } } /** Plots the nodes in a circle */ void GraphWidget::plotNodes () { Point *center = mkpt(0, 0); // std::vector nodes = commy->get_all_nodes(); // get graphical nodes QList nodes; foreach (QGraphicsItem *item, scene()->items()) { if (Node *node = qgraphicsitem_cast(item)) nodes << node; } // get points vector std::vector *points = getNPointsOnCircle(center, CIRCLE_RADIUS, nodes.size()); // <-- define a radius size int index = 0; foreach (Node *node, nodes) { Point * posPoint = points->at(index); fprintf(stderr, "new pos for node at index: %d -> (%d, %d)\n", index, posPoint->xval, posPoint->yval); node->setPos(posPoint->xval, posPoint->yval); // node->newPos(posPoint->xval, posPoint->yval); QPointF * qp = new QPointF(posPoint->xval, posPoint->yval); node->settPosition(qp); index++; } this->scenex->update(this->sceneRect()); } /** Gets the points for placing nodes on a circle @param center center of the circle @param radius radius of the circle @param numNodes the number of points that will be generated @return vector with points that form a circle */ std::vector *getNPointsOnCircle(Point *center, int radius, int numNodes) { double alpha = PI * 2 / numNodes; std::vector *points = new std::vector(); int i = -1; while (++i < numNodes) { double theta = alpha * i; Point *currPoint = mkpt (int(cos(theta)*radius),int(sin(theta)*radius)); currPoint = add (center, currPoint); points->push_back (currPoint); } return points; } /** Sets the private physics variable value @param val new physics variable */ void GraphWidget::setDoPhysics(bool val) { _doPhysics = val; } /** Gets the private physics variable value @return true if phyics are enabled */ bool GraphWidget::getDoPhysics() { return _doPhysics; } /** Highlights a set of edges that form a path @param path a vector nodes that are connected */ void GraphWidget::highlightPath(std::vector path) { // insert comm model call to get list //std::vector path = new std::vector(); // REPLACE WITH REAL SHIT. for (int i = 0; i < path.size() - 1; i++) { Node * n1 = getNode(path[i]); Node * n2 = getNode(path[i+1]); scenex->addItem(new Edge(n1, n2, comm, mainWindow, true)); } }