Monitor
graphwidget.cpp
00001 /****************************************************************************
00002 **
00003 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
00004 ** All rights reserved.
00005 ** Contact: Nokia Corporation (qt-info@nokia.com)
00006 **
00007 ** This file is part of the examples of the Qt Toolkit.
00008 **
00009 ** $QT_BEGIN_LICENSE:BSD$
00010 ** You may use this file under the terms of the BSD license as follows:
00011 **
00012 ** "Redistribution and use in source and binary forms, with or without
00013 ** modification, are permitted provided that the following conditions are
00014 ** met:
00015 **   * Redistributions of source code must retain the above copyright
00016 **     notice, this list of conditions and the following disclaimer.
00017 **   * Redistributions in binary form must reproduce the above copyright
00018 **     notice, this list of conditions and the following disclaimer in
00019 **     the documentation and/or other materials provided with the
00020 **     distribution.
00021 **   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
00022 **     the names of its contributors may be used to endorse or promote
00023 **     products derived from this software without specific prior written
00024 **     permission.
00025 **
00026 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00027 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00028 ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00029 ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
00030 ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00031 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00032 ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00033 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00034 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00035 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00036 ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
00037 ** $QT_END_LICENSE$
00038 **
00039 ****************************************************************************/
00040 
00041 #include "graphwidget.h"
00042 #include "edge.h"
00043 #include "node.h"
00044 #include "point.h"
00045 
00046 #include <QtGui>
00047 #include <arpa/inet.h>
00048 #include <netinet/in.h>
00049 
00050 #include <math.h>
00051 
00057 GraphWidget::GraphWidget(QWidget *parent,  CommModel *comModel)
00058     : QGraphicsView(parent), timerId(0)
00059 {
00060     QGraphicsScene *scene = new QGraphicsScene(this);
00061     scenex = scene;
00062     scene->setItemIndexMethod(QGraphicsScene::NoIndex);
00063     scene->setSceneRect(-250, -220, 625, 500);
00064     setScene(scene);
00065     setCacheMode(CacheBackground);
00066     setViewportUpdateMode(BoundingRectViewportUpdate);
00067     setRenderHint(QPainter::Antialiasing);
00068     setTransformationAnchor(AnchorUnderMouse);
00069     scale(qreal(0.8), qreal(0.8));
00070     this->comm = comModel;
00071     sourceSet = false;
00072     destSet = false;
00073 }
00074 
00079 MainWindow * GraphWidget::getMainWindow()
00080 {
00081     return mainWindow;
00082 }
00083 
00088 void GraphWidget::setMainWindow(MainWindow * _mainWindow)
00089 {
00090     mainWindow = _mainWindow;
00091 }
00092 
00096 void GraphWidget::itemMoved()
00097 {
00098     if (!timerId)
00099         timerId = startTimer(1000 / 25);
00100 }
00101 
00108 bool GraphWidget::sameMacAddr(node* n1, node* n2)
00109 {
00110     for(int i = 0; i < 6; i++)
00111     {
00112         if(n1->mac_addr.addr[i] != n2->mac_addr.addr[i])
00113             return false;
00114     }
00115     return true;
00116 }
00117 
00123 bool GraphWidget::checkIp(uint32_t ip_addr)
00124 {
00125     foreach (Node * n, allNodes)
00126     {
00127         if (n->getIpAddr() == ip_addr)
00128         {
00129             n->setActive();
00130             return true;
00131         }
00132     }
00133     return false;
00134 }
00135 
00141 bool GraphWidget::checkMac(node* nx)
00142 {
00143     foreach (Node * n, allNodes)
00144     {
00145         //if (n->getIpAddr() == ip_addr)
00146         if(sameMacAddr(nx, n->getNodePointer()))
00147         {
00148             n->setActive();
00149             return true;
00150         }
00151     }
00152     return false;
00153 }
00154 
00160 Node * GraphWidget::getNode(node * n)
00161 {
00162     foreach (Node * nx, allNodes)
00163     {
00164         /*When we get Mac Addresses working, use the next line instead of the IP one.*/
00165         if(sameMacAddr(nx->getNodePointer(), n))
00166         //if (nx->getIpAddr() == n->ip_addr)
00167         {
00168             perror("getNode: found the node based on mac address.\n");
00169             return nx;
00170         }
00171     }
00172     perror("getNode: couldn't find the node based on mac address.\n");
00173     return NULL;
00174 }
00175 
00182 bool GraphWidget::hasEdge(Node * n, node * nb)
00183 {
00184     Node * neighbor = getNode(nb);
00185     foreach (Edge * e, n->edges())
00186     {
00187         if (n == e->sourceNode() && neighbor == e->destNode())
00188         {
00189             return true;
00190         }
00191     }
00192     return false;
00193 }
00194 
00199 void GraphWidget::updateGraph(std::vector<node *> nodes)
00200 {
00201     if (sourceSet && destSet)
00202     {
00203         std::vector<node *> prefPath = comm->get_preferred_path();
00204         if (!prefPath.empty())
00205         {
00206             this->highlightPath(prefPath);
00207         }
00208     }
00209 
00210     foreach (node * n, nodes)
00211     {
00212         if(!(checkMac(n)))
00213         //if (!(checkIp(n->ip_addr)))
00214         {
00215             Node * temp = new Node(this, false, n->ip_addr, n);
00216             //delete n;
00217             allNodes << temp;
00218             scenex->addItem(temp);
00219             temp->setY(rand()%200);
00220             temp->setX(rand()%200);
00221 
00222         }
00223     }
00224 
00225     foreach (node * n, nodes)
00226     {
00227         Node * curnode = getNode(n);
00228         struct in_addr theaddr;
00229         theaddr.s_addr = curnode->getIpAddr(); //curNode can't be NULL!
00230 
00231         fprintf(stderr, "ip_addr is: %s\n\n", inet_ntoa(theaddr));
00232         std::vector<node *> neighbors = comm->get_neighbors(n);
00233         fprintf(stderr, "Its past\n\n", inet_ntoa(theaddr));
00234         foreach (node * nb, neighbors)
00235         {
00236             //WE SHOULDN'T USE IP FOR ANYTHING.  We need to use Mac Address
00237             if (/*nb->ip_addr!=0 &&*/ !(hasEdge(curnode, nb)))
00238             {
00239                 Node * neighbor = getNode(nb);
00240                 //if(neighbor != NULL)
00241                     scenex->addItem(new Edge(curnode, neighbor, comm, mainWindow, false)); // <- This crashes shit.  neighbor is null.
00242             }
00243         }
00244     }
00245 
00246 
00247     foreach (Node * n, allNodes)
00248     {
00249         bool found = false;
00250         foreach (node * nx, nodes)
00251         {
00252             //if (nx->ip_addr == n->getIpAddr())
00253             if(sameMacAddr(nx, n->getNodePointer()))
00254             {
00255                 found = true;
00256             }
00257         }
00258         if (!found)
00259         {
00260             n->setInactive();
00261         }
00262     }
00263 
00264     foreach (Node * n, allNodes)
00265     {
00266         if (!(n->isActive()))
00267         {
00268             foreach (Edge * e, n->edges())
00269             {
00270                 scenex->removeItem(e);
00271             }
00272         }
00273         else
00274         {
00275             foreach (Edge * e, n->edges())
00276             {
00277                 node * nx = n->getNodePointer();
00278                 std::vector<node *> neighbors = comm->get_neighbors(nx);
00279 
00280                 if (e->sourceNode() == n)
00281                 {
00282                     Node * other = e->destNode();
00283 
00284                     bool found = false;
00285                     foreach (node * nb, neighbors)
00286                     {
00287                         //if (nb->ip_addr == other->getIpAddr())
00288                         if(sameMacAddr(nb, other->getNodePointer()))
00289                         {
00290                             found = true;
00291                         }
00292                     }
00293 
00294                     if (!found)
00295                     {
00296                         scenex->removeItem(e);
00297                     }
00298                 }
00299             }
00300         }
00301     }
00302 
00303     if (!   _doPhysics) {
00304         plotNodes();
00305     }
00306 
00307 }
00308 
00313 void GraphWidget::timerEvent(QTimerEvent *event)
00314 {
00315     Q_UNUSED(event);
00316 
00317     QList<Node *> nodes;
00318     foreach (QGraphicsItem *item, scene()->items()) {
00319         if (Node *node = qgraphicsitem_cast<Node *>(item))
00320             nodes << node;
00321     }
00322 
00323     foreach (Node *node, nodes)
00324         node->calculateForces(_doPhysics);
00325 
00326     bool itemsMoved = false;
00327     foreach (Node *node, nodes) {
00328         if (node->advance())
00329             itemsMoved = true;
00330     }
00331 
00332     /*if (!itemsMoved) {
00333         killTimer(timerId);
00334         timerId = 0;
00335     }*/
00336     bool move = false;
00337     for (int i = 0; i < allNodes.size() && !move; i++)
00338     {
00339         Node * n = allNodes[i];
00340         for (int j = 0; j < n->edges().size() && !move; j++)
00341         {
00342             Edge * e = n->edges()[j];
00343             if (e->tooShort())
00344             {
00345                 move = true;
00346             }
00347         }
00348     }
00349     if (!move)
00350     {
00351         killTimer(timerId);
00352         timerId = 0;
00353     }
00354 }
00355 
00356 
00363 void GraphWidget::drawBackground(QPainter *painter, const QRectF &rect)
00364 {
00365     Q_UNUSED(rect);
00366 
00367     // Shadow
00368     QRectF sceneRect = this->sceneRect();
00369     /*QRectF rightShadow(sceneRect.right(), sceneRect.top() + 5, 5, sceneRect.height());
00370     QRectF bottomShadow(sceneRect.left() + 5, sceneRect.bottom(), sceneRect.width(), 5);
00371     if (rightShadow.intersects(rect) || rightShadow.contains(rect))
00372         painter->fillRect(rightShadow, Qt::darkGray);
00373     if (bottomShadow.intersects(rect) || bottomShadow.contains(rect))
00374         painter->fillRect(bottomShadow, Qt::darkGray);*/
00375 
00376     // Fill
00377     /*
00378     QLinearGradient gradient(sceneRect.topLeft(), sceneRect.bottomRight());
00379     gradient.setColorAt(0, Qt::white);
00380     gradient.setColorAt(1, Qt::lightGray);
00381     painter->fillRect(rect.intersect(sceneRect), gradient);
00382     painter->setBrush(Qt::NoBrush);
00383     painter->drawRect(sceneRect);
00384     */
00385 
00386     // Text
00387     QRectF textRect(sceneRect.left() + 4, sceneRect.top() + 4,
00388                     sceneRect.width() - 4, sceneRect.height() - 4);
00389     QString message(tr(""));
00390 
00391     QFont font = painter->font();
00392     font.setBold(true);
00393     font.setPointSize(14);
00394     painter->setFont(font);
00395     painter->setPen(Qt::lightGray);
00396     painter->drawText(textRect.translated(2, 2), message);
00397     painter->setPen(Qt::black);
00398     painter->drawText(textRect, message);
00399 /*
00400     foreach(Node* n, allNodes)
00401     {
00402         struct in_addr theAddr;
00403         theAddr.s_addr = n->getIpAddr();
00404         char *stringrepofIpAddress = inet_ntoa(theAddr);
00405 
00406         painter->drawText(n->getPosition(), QString("%0").arg(stringrepofIpAddress));
00407     }*/
00408 
00409 }
00410 /*
00411 void GraphWidget::scaleView(qreal scaleFactor)
00412 {
00413     qreal factor = transform().scale(scaleFactor, scaleFactor).mapRect(QRectF(0, 0, 1, 1)).width();
00414     if (factor < 0.07 || factor > 100)
00415         return;
00416 
00417     scale(scaleFactor, scaleFactor);
00418 }
00419 */
00420 
00425 void GraphWidget::setSelectedIP(uint32_t newIP)
00426 {
00427     selectedIP = newIP;
00428 }
00429 
00430 uint32_t GraphWidget::getSelectedIP()
00431 {
00432     return selectedIP;
00433 }
00434 
00439 void GraphWidget::setSourceMac(mac_t newMac)
00440 {
00441     foreach (node *n, comm->get_all_nodes())
00442     {
00443         if (Node::macEqual(n->mac_addr, newMac))
00444         {
00445             this->comm->set_ocu_machine(n);
00446         }
00447     }
00448     sourceMac = newMac;
00449     sourceSet = true;
00450 }
00451 
00456 void GraphWidget::setDestinationMac(mac_t newMac)
00457 {
00458     foreach (node *n, comm->get_all_nodes())
00459     {
00460         if (Node::macEqual(n->mac_addr, newMac))
00461         {
00462             this->comm->set_target(n);
00463         }
00464     }
00465     destMac = newMac;
00466     destSet = true;
00467 }
00468 
00473 mac_t GraphWidget::getDestinationMac()
00474 {
00475     return destMac;
00476 }
00477 
00482 mac_t GraphWidget::getSourceMac()
00483 {
00484     return sourceMac;
00485 }
00486 
00487 
00491 void GraphWidget::updateNodesAndEdges()
00492 {
00493     /*if (sourceSet && destSet)
00494     {
00495         std::vector<node *> prefPath = comm->get_preferred_path();
00496         if (!prefPath.empty())
00497         {
00498             this->highlightPath(prefPath);
00499         }
00500     }*/
00501 
00502     QList<Node *>::const_iterator stlIter;
00503     for( stlIter = allNodes.begin(); stlIter != allNodes.end(); ++stlIter )
00504     //for(std::vector<Node *>::iterator it = graph->allNodes.begin(); it != allNodes.end(); ++it)
00505     {
00506         Node *cur = (*stlIter);
00507         cur->update();
00508 
00509         foreach (Edge* e, cur->edges())
00510         {
00511             e->update();
00512         }
00513     }
00514 
00515     mainWindow->updateList();
00516 
00517     if (!_doPhysics) {
00518         plotNodes();
00519     }
00520 }
00521 
00522 
00526 void GraphWidget::plotNodes () {
00527     Point *center = mkpt(0, 0);
00528 
00529 //    std::vector<node*> nodes = commy->get_all_nodes();
00530 
00531     // get graphical nodes
00532     QList<Node *> nodes;
00533     foreach (QGraphicsItem *item, scene()->items()) {
00534         if (Node *node = qgraphicsitem_cast<Node *>(item))
00535             nodes << node;
00536     }
00537 
00538     // get points vector
00539     std::vector<Point*> *points = getNPointsOnCircle(center, CIRCLE_RADIUS, nodes.size()); // <-- define a radius size
00540 
00541     int index = 0;
00542     foreach (Node *node, nodes) {
00543         Point * posPoint = points->at(index);
00544         fprintf(stderr, "new pos for node at index: %d -> (%d, %d)\n", index, posPoint->xval, posPoint->yval);
00545         node->setPos(posPoint->xval, posPoint->yval);
00546 //        node->newPos(posPoint->xval, posPoint->yval);
00547         QPointF * qp = new QPointF(posPoint->xval, posPoint->yval);
00548         node->settPosition(qp);
00549         index++;
00550     }
00551 
00552     this->scenex->update(this->sceneRect());
00553 }
00554 
00562 std::vector<Point*> *getNPointsOnCircle(Point *center, int radius, int numNodes) {
00563 
00564     double alpha = PI * 2 / numNodes;
00565     std::vector<Point*> *points = new std::vector<Point*>();
00566 
00567     int i = -1;
00568     while (++i < numNodes) {
00569         double theta = alpha * i;
00570         Point *currPoint = mkpt (int(cos(theta)*radius),int(sin(theta)*radius));
00571         currPoint = add (center, currPoint);
00572         points->push_back (currPoint);
00573 
00574     }
00575 
00576     return points;
00577 }
00578 
00583 void GraphWidget::setDoPhysics(bool val) {
00584     _doPhysics = val;
00585 }
00586 
00591 bool GraphWidget::getDoPhysics() {
00592     return _doPhysics;
00593 }
00594 
00599 void GraphWidget::highlightPath(std::vector<node *> path) {
00600     // insert comm model call to get list
00601     //std::vector<node *> path = new std::vector<node *>(); // REPLACE WITH REAL SHIT.
00602 
00603     for (int i = 0; i < path.size() - 1; i++) {
00604         Node * n1 = getNode(path[i]);
00605         Node * n2 = getNode(path[i+1]);
00606 
00607         scenex->addItem(new Edge(n1, n2, comm, mainWindow, true));
00608     }
00609 }
 All Classes Functions