graphwidget.cpp

来自「linux下的sourceinsight」· C++ 代码 · 共 1,163 行 · 第 1/3 页

CPP
1,163
字号
		// Set the new zoom factor	if (bIn)		m_dZoom *= 2.0;	else		m_dZoom /= 2.0;			// Apply the transformation matrix	mtx.scale(m_dZoom, m_dZoom);	setWorldMatrix(mtx);}/** * Determines the initial zoom factor. * This method is called from the file parser and therefore does not redraw * the widget. * @param	dZoom	The zoom factor to use */void GraphWidget::setZoom(double dZoom){	m_dZoom = dZoom;}/** * Changes the graph's direction 90 degrees counter-clockwise. */void GraphWidget::rotate(){	QString sDir;	int i;		// Get the current direction	sDir = Config().getGraphOrientation();		// Find the next direction	for (i = 0; i < 4 && sDir != GRAPH_DIRS[i]; i++);	if (i == 4)		i = 0;	else		i = (i + 1) % 4;	// Set the new direction	sDir = GRAPH_DIRS[i];	Config().setGraphOrientation(sDir);}/** * 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();}/** * Resizes the canvas. * @param	nWidth	The new width * @param	nHiehgt	The new height */void GraphWidget::resize(int nWidth, int nHeight){	canvas()->resize(nWidth + 2, nHeight + 2);}/** * Displays a node on the canvas. * Sets the parameters used for drawing the node on the canvas. * @param	sFunc	The function corresponding to the node to draw * @param	rect	The coordinates of the node's rectangle */void GraphWidget::drawNode(const QString& sFunc, const QRect& rect){	GraphNode* pNode;		// Find the node	pNode = addNode(sFunc);		// Set the visual aspects of the node	pNode->setRect(rect);	pNode->setZ(2.0);	pNode->setPen(QPen(Qt::black));	pNode->setFont(Config().getFont(KScopeConfig::Graph));		if (pNode->isMultiCall())		pNode->setBrush(Config().getColor(KScopeConfig::GraphMultiCall));	else		pNode->setBrush(Config().getColor(KScopeConfig::GraphNode));		// Draw the node	pNode->show();}/** * 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();}#define PI 3.14159265/** * Sets and computes values used for drawing arrows. * Initialises the static ArroInfo structure, which is passed in drawEdge(). * @param	nLength		The arrow head length * @param	nDegrees	The angle, in degrees, between the base line and each *						of the arrow head's sides */void GraphWidget::setArrowInfo(int nLength, int nDegrees){	double dRad;		// Turn degrees into radians	dRad = ((double)nDegrees) * PI / 180.0;		s_ai.m_dLength = (double)nLength;	s_ai.m_dTan = tan(dRad);	s_ai.m_dSqrt = sqrt(1 + s_ai.m_dTan * s_ai.m_dTan);}/** * Draws the contents of the canvas on this view. * NOTE: This method is overriden to fix a strange bug in Qt that leaves * a border around the canvas part of the view. It should be deleted once * this bug is fixed. * TODO: Is there a better way of erasing the border? * @param	pPainter	Used to paint on the view * @param	nX			The horizontal origin of the area to draw * @param	nY			The vertical origin of the area to draw * @param	nWidth		The width of the area to draw * @param	nHeight		The height of the area to draw */void GraphWidget::drawContents(QPainter* pPainter, int nX, int nY, 	int nWidth, int nHeight){	// Draw the contents of the canvas	QCanvasView::drawContents(pPainter, nX, nY, nWidth, nHeight);		// Erase the canvas's area border	if (canvas() != NULL) {		QRect rect = canvas()->rect();		pPainter->setBrush(QBrush()); // Null brush		pPainter->setPen(Config().getColor(KScopeConfig::GraphBack));		pPainter->drawRect(-1, -1, rect.width() + 2, rect.height() + 2);	}}/** * Handles mouse clicks over the graph view. * @param	pEvent	Includes information on the mouse press event */void GraphWidget::contentsMousePressEvent(QMouseEvent* pEvent){	QPoint ptRealPos;	QCanvasItemList il;	QCanvasItemList::Iterator itr;	QString sFunc;	GraphNode* pNode;	GraphEdge* pEdge;		pNode = NULL;	pEdge = NULL;		// Handle right-clicks only	if (pEvent->button() != Qt::RightButton) {		QCanvasView::contentsMousePressEvent(pEvent);		return;	}		// Take the zoom factor into consideration	ptRealPos = pEvent->pos();	ptRealPos /= m_dZoom;		// Check if an item was clicked	il = canvas()->collisions(ptRealPos);	for (itr = il.begin(); itr != il.end(); ++itr) {		if (dynamic_cast<GraphNode*>(*itr) != NULL)			pNode = dynamic_cast<GraphNode*>(*itr);		else if (dynamic_cast<GraphEdge*>(*itr) != NULL)			pEdge = dynamic_cast<GraphEdge*>(*itr);	}		// Handle clicks over different types of items	if (pNode != NULL) {		// Show a context menu for nodes		showNodeMenu(pNode, pEvent->globalPos());	}	else if (pEdge != NULL) {		// Show a context menu for edges		showEdgeMenu(pEdge, pEvent->globalPos());	}	else {		// Take the default action		QCanvasView::contentsMousePressEvent(pEvent);	}}/** * 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";}/** * Removes all edges attached to a function node at the given direction. * Any strongly connected components that are no longer connected to that * function are deleted. * @param	pNode	The node for which to remove the edges * @param	bOut	true for outgoing edges, false for incoming */void GraphWidget::removeEdges(GraphNode* pNode, bool bOut){	// Remove the edges	if (bOut)		pNode->removeOutEdges();	else		pNode->removeInEdges();			// Remove all graph components no longer connected to this one	removeDisconnected(pNode);}/** * Removes all edges and nodes that are not weakly connected to the given node. * This function is called to clean up the graph after edges were removed from * the given node. * @param	pNode	The node to which all other nodes have to be connected */void GraphWidget::removeDisconnected(GraphNode* pNode){	QDictIterator<GraphNode> itr(m_dictNodes);		// Find all weakly connected components attached to this node	pNode->dfs();		// Delete all unmarked nodes, reset marked ones	while (itr.current()) {		if (!(*itr)->dfsVisited()) {			m_dictNodes.remove((*itr)->getFunc());		}		else {			(*itr)->dfsReset();			++itr;		}	}}/** * Shows a popup menu for a node. * This menu is shown after a node has been right-clicked. * @param	pNode	The node for which to show the menu * @param	ptPos	The position of the menu  */void GraphWidget::showNodeMenu(GraphNode* pNode, const QPoint& ptPos){	// Remember the node	m_pMenuItem = pNode;		// Show the popup menu.	if (pNode->isMultiCall())		m_pMultiCallPopup->popup(ptPos);	else		m_pNodePopup->popup(ptPos);}/** * Shows a popup menu for an edge.

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?