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 + -
显示快捷键?