/**
 * Emits a signal to open an editor at the file and line matching the call
 * information of the current edge.
 * This slot is connected to the "Open Call" popup menu action (for edges).
 */
void GraphWidget::slotOpenCall()
{
	GraphEdge* pEdge;
	QString sFile, sLine;
	
	// Make sure the menu item is an edge
	pEdge = dynamic_cast<GraphEdge*>(m_pMenuItem);
	if (pEdge != NULL && pEdge->getFile() != "")
		emit lineRequested(pEdge->getFile(), pEdge->getLine());
}
/**
 * Adds a call to the graph.
 * A call is made between two functions, the caller and the callee.
 * @param	data	Contains information on the call
 */
void GraphWidget::addCall(const CallData& data)
{
	GraphNode* pCaller, * pCallee;
	GraphEdge* pEdge;
	
	// Find the relevant nodes (create new nodes if necessary)
	pCaller = addNode(data.m_sCaller);
	pCallee = addNode(data.m_sCallee);
	
	// Create a new edge
	pEdge = pCaller->addOutEdge(pCallee);
	pEdge->setCallInfo(data.m_sFile, data.m_sLine, data.m_sText);
}
Beispiel #3
0
void GraphEdge::updateWithEdge(const GraphEdge& edge)
{
  kDebug() << id() << edge.id();
  m_arrowheads = edge.arrowheads();
  m_colors = edge.colors();
  m_dir = edge.dir();
  GraphElement::updateWithElement(edge);
  if (canvasEdge())
  {
    canvasEdge()->computeBoundingRect();
    canvasEdge()->modelChanged();
  }
}
void DrawEdge(const GraphEdge& edge, const Graph& g)
{
  glDisable(GL_LIGHTING);
  glBegin(GL_LINES);
  const GraphNode& from = g.GetNode(edge.GetFrom());
  const GraphNode& to = g.GetNode(edge.GetTo());
  const Vec2f& u = from.GetPos();
  const Vec2f& v = to.GetPos();
  glVertex3f(u.x, 0, u.y);
  glVertex3f(v.x, 0, v.y);
  glEnd();
  glEnable(GL_LIGHTING);
}
Beispiel #5
0
void DualGraph::saveGraph(const char *filename) {
    std::ofstream output(filename);
    for (NodeIter nit(this); !nit.end(); ++nit) {
        GraphNode *node = *nit;
		output << "v " << node->id() << "\n";
	}

    for (EdgeIter eit(this); !eit.end(); ++eit) {
        GraphEdge *edge = *eit;
        output << "e " << edge->from()->id() << " " << edge->to()->id() << "\n";
	}
    output.close();
}
Beispiel #6
0
QList<GraphEdge*> GraphView::getEdges()
{
    QList<GraphEdge*> edges;

    QListIterator<QGraphicsItem*> it(scene()->items());
    while (it.hasNext()) {
        GraphEdge* edge = dynamic_cast<GraphEdge*>(it.next());

        if (edge && edge->isVisible())
            edges.append(edge);
    }

    return edges;
}
Beispiel #7
0
void GraphNode::moveTo(const QPointF& pt)
{
    setCenter(pt);

    QListIterator<GraphEdge*> it(destinationEdges);
    while (it.hasNext())
        it.next()->destinationUpdated();

    it = QListIterator<GraphEdge*>(sourceEdges);
    while (it.hasNext()) {
        GraphEdge* edge = it.next();
        // The undirected edges were already updated because the node is both source and destination
        if (!edge->isUndirected())
            edge->sourceUpdated();
    }
}
Beispiel #8
0
bool Bfs::SearchWithTrail(int from, int to, Trail* trail)
{
  // Need to remember which nodes we have already visited
  std::set<int> visited;
  Breadcrumbs breadcrumbs;

  // Breadth first uses a queue to hold nodes we will visit
  std::queue<GraphEdge> nodesToVisit;

  float cost = 0; // dummy value
  // Put dummy edge in stack to start search. TODO better way, e.g. do/while ?
  nodesToVisit.push(GraphEdge(from, from, cost));

  while (!nodesToVisit.empty()) 
  {
    GraphEdge e = nodesToVisit.front();
    nodesToVisit.pop();

    std::cout << "Trying edge from " << e.GetFrom() << " to " << e.GetTo() << "\n";

    breadcrumbs[e.GetTo()] = e.GetFrom(); // map version
    //breadcrumbs.push_back(e); // vector version
    // In addition to here....
    visited.insert(e.GetTo());

    if (e.GetTo() == to)
    {
      // We have found the finish!
      std::cout << "Successfully got to the finish!\n";
      MakeTrail(from, to, breadcrumbs, trail);
      return true;
    }
    else
    {
      // Push unvisited neighbours onto stack
      const EdgeList& edgelist = m_graph->GetEdgeList(e.GetTo());
      for (EdgeList::const_iterator it = edgelist.begin(); it != edgelist.end(); ++it)
      {
        const GraphEdge& childEdge = *it;
        if (visited.count(childEdge.GetTo()) == 0)
        {
          nodesToVisit.push(childEdge);
          // ...we mark node as visited right away here
          visited.insert(childEdge.GetTo());
        }
      }
    }
  }
  return false;
}
Beispiel #9
0
void Graph :: preprocess(){
	//we want all the edges to have pointer to the nodes its connecting
	//we also want all nodes to know about its adjacency nodes
	//we will do so by traversing all the edges
	for (int e=0; e< edgelist.size(); e++) {
		GraphEdge * thedg = edgelist.at(e);
		int frid = thedg->from;
		int toid = thedg->to;
		
		bool foundfrom = false;
		bool foundto = false;
		GraphNode * fromend;
		GraphNode * toend;
		//find these nodes in the adjlist
		for (int a=0; a<adjlist.size(); a++) {
			GraphNode * nd = adjlist.at(a);
			if (!foundfrom && nd->getnodeid() == frid) {
				fromend = nd;
				thedg->setFrom(fromend);
				fromend->addAdjacentEdge(thedg);
				foundfrom = true;
			}
			if (!foundto && nd->getnodeid() == toid) {
				toend = nd;
				thedg->setTo(toend);
				toend->addAdjacentEdge(thedg);
				foundto = true;
			}
			if(foundto && foundfrom){
				fromend -> addAdjacentNode(toend);
				toend->addAdjacentNode(fromend);
				
				break;
			}
			
		}
	}
}
/**
 * Checks if a tool tip is required for the given position.
 * NOTE: We currently return a tool tip for edges only
 * @param	ptPos	The position to query
 * @param	rc		Holds the tip's rectangle, upon return
 * @return	The tip's text, or QString::null if no tip is required
 */
QString GraphWidget::getTip(const QPoint& ptPos, QRect& rc)
{
	QPoint ptRealPos, ptTopLeft, ptBottomRight;
	QCanvasItemList il;
	QCanvasItemList::Iterator itr;
	GraphEdge* pEdge;
	QString sText, sFile, sLine;
	
	ptRealPos = viewportToContents(ptPos);
	ptRealPos /= m_dZoom;
	pEdge = NULL;
	
	// Check if there is an edge at this position
	il = canvas()->collisions(ptRealPos);
	for (itr = il.begin(); itr != il.end(); ++itr) {
		pEdge = dynamic_cast<GraphEdge*>(*itr);
		if (pEdge != NULL)
			break;
	}
	
	// No tip if no edge was found
	if (pEdge == NULL)
		return QString::null;
	
	// Set the rectangle for the tip (the tip is closed when the mouse leaves
	// this area)
	rc = pEdge->tipRect();
	ptTopLeft = rc.topLeft();
	ptBottomRight = rc.bottomRight();
	ptTopLeft *= m_dZoom;	
	ptBottomRight *= m_dZoom;
	ptTopLeft = contentsToViewport(ptTopLeft);
	ptBottomRight = contentsToViewport(ptBottomRight);
	rc = QRect(ptTopLeft, ptBottomRight);
	
	// Create a tip for this edge
	return pEdge->getTip();
}
Beispiel #11
0
void GraphView::setNodeRadius(int radius)
{
    nodeRadius = radius;

    QListIterator<QGraphicsItem*> it(scene()->items());
    while (it.hasNext()) {
        GraphNode* node = dynamic_cast<GraphNode*>(it.next());

        if (node)
            node->setRadius(radius);
    }

    // After changing the radius of every node, we recalculate the edges
    it.toFront();
    while (it.hasNext()) {
        GraphEdge* edge = dynamic_cast<GraphEdge*>(it.next());

        if (edge)
            edge->updateDrawing();
    }

    scene()->update();
}
/**
 * Writes a description of the graph to the given stream, using the Dot 
 * language.
 * The method allows for both directed graphs and non-directed graphs, the
 * latter are required for drawing purposes (since Dot will not produce the
 * arrow heads and the splines terminate before reaching the nodes).
 * @param	str			The stream to write to
 * @param	sType		Either "graph" or "digraph"
 * @param	sEdge		The edge connector ("--" or "->")
 * @param	bWriteCall	true to write call information, false otherwise
 */
void GraphWidget::write(QTextStream& str, const QString& sType, 
	const QString& sEdge, bool bWriteCall)
{
	QFont font;
	QDictIterator<GraphNode> itr(m_dictNodes);
	GraphEdge* pEdge;
	Encoder enc;
	
	font = Config().getFont(KScopeConfig::Graph);

	// Header
	str << sType << " G {\n";
	
	// Graph attributes
	str << "\tgraph [rankdir=" << Config().getGraphOrientation() << ", "
		<< "kscope_zoom=" << m_dZoom 
		<< "];\n";
	
	// Default node attributes
	str << "\tnode [shape=box, height=\"0.01\", style=filled, "
		<< "fillcolor=\"" << Config().getColor(KScopeConfig::GraphNode).name()
		<< "\", "
		<< "fontcolor=\"" << Config().getColor(KScopeConfig::GraphText).name()
		<< "\", "
		<< "fontname=\"" << font.family() << "\", "
		<< "fontsize=" << QString::number(font.pointSize())
		<< "];\n";
	
	// Iterate over all nodes
	for (; itr.current(); ++itr) {
		// Write a node
		str << "\t" << itr.current()->getFunc() << ";\n";
		
		// Iterate over all edges leaving this node		
		QDictIterator<GraphEdge> itrEdge(itr.current()->getOutEdges());
		for (; itrEdge.current(); ++itrEdge) {
			pEdge = itrEdge.current();
			str << "\t" << pEdge->getHead()->getFunc() << sEdge
				<< pEdge->getTail()->getFunc();
				
			// Write call information
			if (bWriteCall) {
				str << " ["
					<< "kscope_file=\"" << pEdge->getFile() << "\","
					<< "kscope_line=" << pEdge->getLine() << ","
					<< "kscope_text=\"" << enc.encode(pEdge->getText()) << "\"" 
					<< "]";
			}
			
			str << ";\n";
		}
	}
	
	// Close the graph
	str << "}\n";
}
Beispiel #13
0
bool Dfs::SearchWithTrail(int from, int to, Trail* trail)
{
    std::set<int> visited;
    Breadcrumbs breadcrumbs;

    std::stack<GraphEdge> nodesToVisit;
    float cost = 0;
    // Put dummy edge in stack
    nodesToVisit.push(GraphEdge(from, from, cost));
    while (!nodesToVisit.empty())
    {
        GraphEdge e = nodesToVisit.top();
        nodesToVisit.pop();

        std::cout << "Trying edge from " << e.GetFrom() << " to " << e.GetTo() << "\n";

        breadcrumbs[e.GetTo()] = e.GetFrom(); // map version
        // breadcrumbs.push_back(e); // vector version
        visited.insert(e.GetTo());

        if (e.GetTo() == to)
        {
            // We have found the finish! Loop back through the breadcrumbs to create the trail.
            MakeTrail(from, to, breadcrumbs, trail);
            return true;
        }
        else
        {
            // Push unvisited neighbours onto stack
            const EdgeList& edgelist = m_graph->GetEdgeList(e.GetTo());
            for (EdgeList::const_iterator it = edgelist.begin(); it != edgelist.end(); ++it)
            {
                const GraphEdge& childEdge = *it;
                if (visited.count(childEdge.GetTo()) == 0)
                {
                    nodesToVisit.push(childEdge);
                }
            }
        }
    }
    return false;
}
Beispiel #14
0
bool Dfs::SearchNoTrail(int from, int to)
{
    // Need to remember which nodes we have already visited
    std::set<int> visited;

    // Depth first uses a stack to hold nodes we will visit
    std::stack<GraphEdge> nodesToVisit;

    float cost = 0; // dummy value
    // Put dummy edge in stack to start search. TODO better way, e.g. do/while ?
    nodesToVisit.push(GraphEdge(from, from, cost));

    while (!nodesToVisit.empty())
    {
        GraphEdge e = nodesToVisit.top();
        nodesToVisit.pop();

        std::cout << "Trying edge from " << e.GetFrom() << " to " << e.GetTo() << "\n";

        visited.insert(e.GetTo());

        if (e.GetTo() == to)
        {
            // We have found the finish!
            return true;
        }
        else
        {
            // Push unvisited neighbours onto stack
            const EdgeList& edgelist = m_graph->GetEdgeList(e.GetTo());
            for (EdgeList::const_iterator it = edgelist.begin(); it != edgelist.end(); ++it)
            {
                const GraphEdge& childEdge = *it;
                if (visited.count(childEdge.GetTo()) == 0)
                {
                    nodesToVisit.push(childEdge);
                }
            }
        }
    }
    return false;
}
/**
 * Displays an edge on the canvas.
 * Sets the parameters used for drawing the edge on the canvas.
 * @param	sCaller		Identifies the edge's head node
 * @param	sCallee		Identifies the edge's tail node
 * @param	arrCurve	Control points for the edge's spline
 */
void GraphWidget::drawEdge(const QString& sCaller, const QString& sCallee,
	const QPointArray& arrCurve)
{
	GraphNode* pCaller, * pCallee;
	GraphEdge* pEdge;
	
	// Find the edge
	pCaller = addNode(sCaller);
	pCallee = addNode(sCallee);
	pEdge = pCaller->addOutEdge(pCallee);
	
	// Set the visual aspects of the edge
	pEdge->setPoints(arrCurve, s_ai);
	pEdge->setZ(1.0);
	pEdge->setPen(QPen(Qt::black));
	pEdge->setBrush(QBrush(Qt::black));
	
	// Draw the edge
	pEdge->show();
}
Beispiel #16
0
//void GraphEdge::adjust()
void GraphEdge::updateGeometry()
{
    if (!sourceNode_ || !destNode_) return;

    //sourceNode_->adjustSize();
    //destNode_->adjustSize();

    // line from center of sourceNode_ to center of destNode_
    QRectF sSBR (sourceNode_->sceneBoundingRect());
    QRectF dSBR (destNode_->sceneBoundingRect());
    QLineF centerline(sSBR.center(), dSBR.center());

    // set the source and destination points
    if(!sSBR.intersects(dSBR)) {
        QPointF po;
        if(QLineF::BoundedIntersection == centerline.intersect(QLineF(sSBR.topLeft(), sSBR.topRight()), &po)) sourcePoint = po;
        else if(QLineF::BoundedIntersection == centerline.intersect(QLineF(sSBR.bottomRight(), sSBR.topRight()), &po)) sourcePoint = po;
        else if(QLineF::BoundedIntersection == centerline.intersect(QLineF(sSBR.bottomLeft(), sSBR.bottomRight()), &po)) sourcePoint = po;
        else if(QLineF::BoundedIntersection == centerline.intersect(QLineF(sSBR.topLeft(), sSBR.bottomLeft()), &po)) sourcePoint = po;
        if(QLineF::BoundedIntersection == centerline.intersect(QLineF(dSBR.topLeft(), dSBR.topRight()), &po)) destPoint = po;
        else if(QLineF::BoundedIntersection == centerline.intersect(QLineF(dSBR.bottomRight(), dSBR.topRight()), &po)) destPoint = po;
        else if(QLineF::BoundedIntersection == centerline.intersect(QLineF(dSBR.bottomLeft(), dSBR.bottomRight()), &po)) destPoint = po;
        else if(QLineF::BoundedIntersection == centerline.intersect(QLineF(dSBR.topLeft(), dSBR.bottomLeft()), &po)) destPoint = po;
    } else {
        sourcePoint = destPoint = (sSBR.bottomLeft().y() < dSBR.bottomLeft().y()) ? sSBR.bottomLeft() : dSBR.bottomLeft();
    }
    QLineF line(sourcePoint, destPoint);
    // set label centered in the middle of the arrow
    QRectF label (label_->boundingRect());
    label.translate(line.pointAt(0.5));
    if(sourcePoint != destPoint) label.translate(-label.width()/2, -label.height()/2);

    // avoid overlapping
    bool overlapped;
    while(true) {
        overlapped = false;
        Graph *graph = reinterpret_cast<Graph *>(scene());
        if(!graph) break;
        Edges::const_iterator i = graph->edges_.constBegin();
        while (i != graph->edges_.constEnd()) {
            GraphEdge *e = i.value();
            if(e != this && e->label()->geometry().intersects(label)) {
                label.moveTo(label.x(), label.y() + 1 + e->label()->geometry().intersected(label).height());
                overlapped = true;
            }
            ++i;
        }
        // node overlapping
        Nodes::const_iterator j = graph->nodes_.constBegin();
        while (j != graph->nodes_.constEnd()) {
            GraphNode *n = j.value();
            if(n->geometry().intersects(label)) {
                label.moveTo(label.x(), label.y() + 1 + n->geometry().intersected(label).height());
                overlapped = true;
            }
            ++j;
        }

        if(!overlapped) break;
    };

    label_->setGeometry(label);
    labelRect_ = label;

    prepareGeometryChange();


    QGraphicsLayoutItem::updateGeometry();
}
Beispiel #17
0
DualGraph* generateGraph(std::vector<Patch*>& patches) {
	
	DualGraph *dualGraph = new DualGraph;

	std::map<Vertex*, std::vector<Patch*> > ver2patchMap;
	for (auto p : patches) {

		GraphNode *node = dualGraph->addNode();
		p->graphNode = node;

		for (auto v : p->vertices) {
			auto pvec = ver2patchMap[v];
			for (size_t i = 0; i < pvec.size(); ++i) {
				Patch *p0 = pvec[i];
				dualGraph->addEdge(p0->graphNode, node);
				dualGraph->addEdge(node, p0->graphNode);
			}
			ver2patchMap[v].push_back(p);
		}
	}


	//well.. let's print out the dualgraph

	//convert the dual graph to cm
	//first, the position, each center of the cluster
	std::ofstream dgfile("dualgraph.cm");
	
	for (auto p : patches) {
		GraphNode *gnode = p->graphNode;
		dgfile << "Vertex " << gnode->id() + 1 << " " << p->center[0] << " " << p->center[1] << " " << p->center[2] << "\n";
	}

	for (auto p : patches) {
		GraphNode *gnode = p->graphNode;
		for (GraphNode::EdgeIter eit(gnode); !eit.end(); ++eit) {
			GraphEdge *edge = *eit;
			if (edge->to()->id() > gnode->id()) {
				dgfile << "Edge " << edge->from()->id() + 1 << " " << edge->to()->id() + 1 << "\n";
			}
		}
	}

	dualGraph->saveMetis("dualgraph.metis");

	dgfile.close();
	


	std::vector <std::string> edgestr;
	std::set<Vertex*> vertices;
	double total_boundary_length = 0;
	int boundary_count = 0;
	for (auto p : patches) {
		std::set<Vertex*> pvertices;
		for (auto he : p->boundary) {
			
			if (!he->twin()) {
				total_boundary_length += (he->source()->point() - he->target()->point()).norm();
				++boundary_count;
				if ( ver2patchMap[he->source()].size() == 1) {
					//continue;
				}
				vertices.insert(he->source());
				auto itpair = pvertices.insert(he->source());
				if (itpair.second) {
					p->corners.push_back(he->source());
				}

				if ( ver2patchMap[he->target()].size() == 1) {
				//	continue;
				}
				vertices.insert(he->target());
				itpair = pvertices.insert(he->target());
				if (itpair.second) {
					p->corners.push_back(he->target());
				}
				
			}  

			if ( ver2patchMap[he->source()].size() >= 3) {
				vertices.insert(he->source());
				auto itpair = pvertices.insert(he->source());			
				if (itpair.second) {
					p->corners.push_back(he->source());
				}
					
			}


			if ( ver2patchMap[he->target()].size() >= 3) {
				vertices.insert(he->target());
				auto itpair = pvertices.insert(he->target());			
				if (itpair.second) {
					p->corners.push_back(he->target());
				}

			}

		}
	}

	avg_length = total_boundary_length / boundary_count;
	std::map<Vertex*, int> prevOrder, nowOrder;
	std::ofstream output("graph.m");

	int vid = 1;
	for (auto v : vertices) {
		
		output << "Vertex " << vid << " " << v->point()[0] << " " << v->point()[1] << " " << v->point()[2] << "\n";
		prevOrder[v] = v->index();
		nowOrder[v] = vid++;
		
	}

	int fid = 0;
	for (auto p : patches) {
		output << "Face " << ++fid << " ";
	
		for (auto v : p->corners) {
			
			output << nowOrder[v]  << " ";
		}
		output << "\n";
	}

	for (auto v : vertices) {
		
		v->index() = prevOrder[v];
	}

	return dualGraph;
}
Beispiel #18
0
void Graph :: preprocessauthorgraph(){
	//we want all the edges to have pointer to the nodes its connecting
	//we also want all nodes to know about its adjacency nodes
	//we will do so by traversing all the edges
	
	//for this particular data we have to work with string id's
	
	for (int e=0; e< edgelist.size(); e++) {
		GraphEdge * thedg = edgelist.at(e);
		
		string frst = thedg->strfrom;
		string tostr = thedg->strto;
		
		bool foundfrom = false;
		bool foundto = false;
		
		GraphNode * fromend;
		GraphNode * toend;
		
		//find these nodes in the adjlist
		for (int a=0; a<adjlist.size(); a++) {
			GraphNode * nd = adjlist.at(a);
			if (!foundfrom && nd->getstrid() == frst) {
				fromend = nd;
				fromend->addAdjacentEdge(thedg);
				thedg->from = fromend -> getnodeid();
				thedg->setFrom(fromend);
				foundfrom = true;
			}
			if (!foundto && nd->getstrid() == tostr) {
				toend = nd;
				thedg->setTo(toend);
				toend->addAdjacentEdge(thedg);
				thedg->to = toend -> getnodeid();
				foundto = true;
			}
			if(foundto && foundfrom){
				fromend -> addAdjacentNode(toend);
				toend->addAdjacentNode(fromend);
				break;
			}
		}
	}
	
	//change labels to be the first letters
	
	for (int a=0; a<adjlist.size(); a++) {
		string lab = adjlist.at(a)->getLabel(); 
		istringstream iss(lab);
		
		vector<string> names;
		
		do
		{
			string sub;
			iss >> sub;
			names.push_back(sub);
			//cout << "Substring: " << sub << endl;
		} while (iss);
		
		//form the new string
		
		string newlabel;
		newlabel += names[0].substr(0,1);
		newlabel += names[1].substr(0,1);
		/*
		for(int i=0; i<names.size(); i++){
			newlabel += names[i].substr(0, 1);
		}
		*/
		adjlist.at(a)->setShortLabel(newlabel);
		
		//printf("old label: %s, new label: %s \n", lab.c_str(), newlabel.c_str());
		
	}
		
	ramdomizePositions(false); //since author graph has no initial positions
							   // we have to assign positions
	
}
Beispiel #19
0
//엣지를 추가한다.
void SparseGraph::AddEdge(GraphEdge edge)
{
    //엣지의 양끝이 유효한 노드인지 확인한다.
    assert((edge.GetFrom() < m_iNextNodeIndex) && (edge.GetTo() < m_iNextNodeIndex) &&
           "<SparseGraph::AddEdge>: invalid node index");
    
    //유효한 노드이면
    if ((m_Nodes[edge.GetTo()].GetIndex() != -1) &&
        (m_Nodes[edge.GetFrom()].GetIndex() != -1))
    {
        //유니크한 엣지인지 확인한다.
        if (UniqueEdge(edge.GetFrom(), edge.GetTo()))
        {
            m_Edges[edge.GetFrom()].push_back(edge);
        }
        
        
        //거꾸로 방향도 확인한다.
        if (UniqueEdge(edge.GetTo(), edge.GetFrom()))
        {
            GraphEdge NewEdge = edge;
            
            NewEdge.SetTo(edge.GetFrom());
            NewEdge.SetFrom(edge.GetTo());
            
            m_Edges[edge.GetTo()].push_back(NewEdge);
        }
        
    }
}
Beispiel #20
0
void GraphView::addEdgeCommand(bool undirected)
{
    if (edgeSource) {
        GraphNode* edgeDestination = dynamic_cast<GraphNode*>(selectedItem);
        if (edgeDestination && edgeSource != edgeDestination) {
            GraphEdge* existingEdge = NULL;
            bool drawAsArc(false);

            QListIterator<GraphEdge*> it(edgeSource->getDestinationEdges());
            while (it.hasNext() && !existingEdge) {
                GraphEdge* edge = it.next();
                if (edge->getSourceNode() == edgeDestination)
                    existingEdge = edge;
            }

            if (existingEdge) {
                if (!existingEdge->isUndirected()) {
                    if (weightedGraph && !undirectedGraph && currentAction == ADD_DIRECTED_EDGE) {
                        existingEdge->setDrawAsArc(true);
                        drawAsArc = true;
                        existingEdge = NULL;
                    }
                    else
                        undoStack->push(new ChangeEdgeDirectionCommand(existingEdge, false, true));
                }
            }
            else {
                it = QListIterator<GraphEdge*>(edgeSource->getSourceEdges());
                while (it.hasNext() && !existingEdge) {
                    GraphEdge* edge = it.next();
                    if (edge->getDestinationNode() == edgeDestination) {
                       existingEdge = edge;
                       if (currentAction == ADD_UNDIRECTED_EDGE)
                           undoStack->push(new ChangeEdgeDirectionCommand(existingEdge, false, true));
                    }
                }
            }

            if (existingEdge) {
                scene()->removeItem(currentEdge);
                delete currentEdge;
            }
            else {
                currentEdge->setDestinationNode(edgeDestination);
                currentEdge->setDrawAsArc(drawAsArc);
                undoStack->push(new AddEdgeCommand(currentEdge, this));
            }

            currentEdge = NULL;
            edgeSource = NULL;
        }
    }
    else if (selectedItem) {
        edgeSource = dynamic_cast<GraphNode*>(selectedItem);
        currentEdge = new GraphEdge(edgeSource, edgeSource->getCenter(), undirected, !undirectedGraph, weightedGraph, false);
        // Setting the Z value makes sure the selection of nodes are made correct
        currentEdge->setZValue(-1);
        scene()->addItem(currentEdge);
    }

    updateStatus();
}
Beispiel #21
0
void GraphView::executeContextMenu(const QPoint& menuPosition)
{
    QMenu menu;

    GraphNode* node = dynamic_cast<GraphNode*>(selectedItem);
    GraphEdge* edge = dynamic_cast<GraphEdge*>(selectedItem);

    if (node) {
        QAction *changeLabelAction = menu.addAction("Change label");
        QAction *deleteAction = menu.addAction("Delete vertex");
        QAction *selectedAction = menu.exec(menuPosition);

        if (selectedAction == changeLabelAction)
          changeLabel(node);
        else if (selectedAction == deleteAction)
          removeItemCommand(node);
    }
    else if (edge){
        QAction *changeWeightAction(NULL);

        if (weightedGraph)
            changeWeightAction = menu.addAction("Change weight");

        QAction *changeDirectionSDAction(NULL);
        QAction *changeDirectionDSAction(NULL);
        QAction *changeUndirectedAction(NULL);

        if (!undirectedGraph) {
            QMenu *changeDirectionMenu = new QMenu("Change direction");
            menu.addMenu(changeDirectionMenu);
            QString sourceLabel = edge->getSourceNode()->getLabel();
            if (sourceLabel.isEmpty())
                sourceLabel = "no_label";
            QString destinationLabel = edge->getDestinationNode()->getLabel();
            if (destinationLabel.isEmpty())
                destinationLabel = "no_label";

            changeDirectionSDAction = changeDirectionMenu->addAction(sourceLabel + " -> " + destinationLabel);
            changeDirectionDSAction = changeDirectionMenu->addAction(destinationLabel + " -> " + sourceLabel);
            changeUndirectedAction = changeDirectionMenu->addAction("Change to undirected");

            if (edge->isUndirected())
                changeUndirectedAction->setEnabled(false);
            else
                changeDirectionSDAction->setEnabled(false);
        }

        QAction *deleteAction = menu.addAction("Delete edge");
        QAction *selectedAction = menu.exec(menuPosition);

        if (selectedAction) {
            if (selectedAction == deleteAction)
                removeItemCommand(edge);
            else if (selectedAction == changeWeightAction)
                changeWeight(edge);
            else if (selectedAction == changeDirectionSDAction)
                undoStack->push(new ChangeEdgeDirectionCommand(edge, false, false));
            else if (selectedAction == changeDirectionDSAction)
                undoStack->push(new ChangeEdgeDirectionCommand(edge, true, false));
            else if (selectedAction == changeUndirectedAction)
                undoStack->push(new ChangeEdgeDirectionCommand(edge, false, true));
        }
    }
}