⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 revgraphview.cpp

📁 LINUX 下以 QT/KDE 写的 SVN 客户端
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*************************************************************************** *   Copyright (C) 2006-2007 by Rajko Albrecht                             * *   ral@alwins-world.de                                                   * *                                                                         * *   This program is free software; you can redistribute it and/or modify  * *   it under the terms of the GNU General Public License as published by  * *   the Free Software Foundation; either version 2 of the License, or     * *   (at your option) any later version.                                   * *                                                                         * *   This program is distributed in the hope that it will be useful,       * *   but WITHOUT ANY WARRANTY; without even the implied warranty of        * *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         * *   GNU General Public License for more details.                          * *                                                                         * *   You should have received a copy of the GNU General Public License     * *   along with this program; if not, write to the                         * *   Free Software Foundation, Inc.,                                       * *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.         * ***************************************************************************/#include "revgraphview.h"#include "graphtreelabel.h"#include "pannerview.h"#include "graphtree_defines.h"#include "src/settings/kdesvnsettings.h"#include "../stopdlg.h"#include "src/svnqt/client.hpp"#include <kapp.h>#include <kdebug.h>#include <ktempfile.h>#include <ktempdir.h>#include <kprocess.h>#include <klocale.h>#include <kfiledialog.h>#include <kmessagebox.h>#include <qtooltip.h>#include <qwmatrix.h>#include <qpopupmenu.h>#include <qpainter.h>#include <qregexp.h>#include <math.h>#define LABEL_WIDTH 160#define LABEL_HEIGHT 90class GraphViewTip:public QToolTip{public:  GraphViewTip( QWidget* p ):QToolTip(p) {}  virtual ~GraphViewTip(){}protected:    void maybeTip( const QPoint & );};void GraphViewTip::maybeTip( const QPoint & pos){    if (!parentWidget()->inherits( "RevGraphView" )) return;    RevGraphView* cgv = (RevGraphView*)parentWidget();    QPoint cPos = cgv->viewportToContents(pos);    QCanvasItemList l = cgv->canvas()->collisions(cPos);    if (l.count() == 0) return;    QCanvasItem* i = l.first();    if (i->rtti() == GRAPHTREE_LABEL) {        GraphTreeLabel*tl = (GraphTreeLabel*)i;        QString nm = tl->nodename();        QString tipStr = cgv->toolTip(nm);        if (tipStr.length()>0) {            QPoint vPosTL = cgv->contentsToViewport(i->boundingRect().topLeft());            QPoint vPosBR = cgv->contentsToViewport(i->boundingRect().bottomRight());            tip(QRect(vPosTL, vPosBR), tipStr);        }    }}RevGraphView::RevGraphView(QObject*aListener,svn::Client*_client,QWidget * parent, const char * name, WFlags f) : QCanvasView(parent,name,f){    m_Canvas = 0L;    m_Client = _client;    m_Listener = aListener;    dotTmpFile = 0;    m_Selected = 0;    renderProcess = 0;    m_Marker = 0;    m_Tip = new GraphViewTip(this);    m_CompleteView = new PannerView(this);    m_CompleteView->setVScrollBarMode(QScrollView::AlwaysOff);    m_CompleteView->setHScrollBarMode(QScrollView::AlwaysOff);    m_CompleteView->raise();    m_CompleteView->hide();    connect(this, SIGNAL(contentsMoving(int,int)),            this, SLOT(contentsMovingSlot(int,int)));    connect(m_CompleteView, SIGNAL(zoomRectMoved(int,int)),            this, SLOT(zoomRectMoved(int,int)));    connect(m_CompleteView, SIGNAL(zoomRectMoveFinished()),            this, SLOT(zoomRectMoveFinished()));    m_LastAutoPosition = TopLeft;    _isMoving = false;    _noUpdateZoomerPos = false;    m_LabelMap[""]="";}RevGraphView::~RevGraphView(){    setCanvas(0);    delete m_Canvas;    delete dotTmpFile;    delete m_CompleteView;    delete m_Tip;    delete renderProcess;}void RevGraphView::showText(const QString&s){    clear();    m_Canvas = new QCanvas(QApplication::desktop()->width(),                        QApplication::desktop()->height());    QCanvasText* t = new QCanvasText(s, m_Canvas);    t->move(5, 5);    t->show();    center(0,0);    setCanvas(m_Canvas);    m_Canvas->update();    m_CompleteView->hide();}void RevGraphView::clear(){    if (m_Selected) {        m_Selected->setSelected(false);        m_Selected=0;    }    if (m_Marker) {        m_Marker->hide();        delete m_Marker;        m_Marker=0;    }    if (!m_Canvas) return;    delete m_Canvas;    m_Canvas = 0;    setCanvas(0);    m_CompleteView->setCanvas(0);}void RevGraphView::beginInsert(){    viewport()->setUpdatesEnabled(false);}void RevGraphView::endInsert(){    if (m_Canvas) {        _cvZoom = 0;        updateSizes();        m_Canvas->update();    }    viewport()->setUpdatesEnabled(true);}void RevGraphView::readDotOutput(KProcess*,char *   buffer,int   buflen){    dotOutput+=QString::fromLocal8Bit(buffer, buflen);}void RevGraphView::dotExit(KProcess*p){    if (p!=renderProcess)return;    // remove line breaks when lines to long    QRegExp endslash("\\\\\\n");    dotOutput.replace(endslash,"");    double scale = 1.0, scaleX = 1.0, scaleY = 1.0;    double dotWidth, dotHeight;    QTextStream* dotStream;    dotStream = new QTextStream(dotOutput, IO_ReadOnly);    QString line,cmd;    int lineno=0;    clear();    beginInsert();    /* mostly taken from kcachegrind */    while (1) {        line = dotStream->readLine();        if (line.isNull()) break;        lineno++;        if (line.isEmpty()) continue;        QTextStream lineStream(line, IO_ReadOnly);        lineStream >> cmd;        if (cmd == "stop") {break; }        if (cmd == "graph") {            lineStream >> scale >> dotWidth >> dotHeight;            scaleX = scale * 60; scaleY = scale * 100;            int w = (int)(scaleX * dotWidth);            int h = (int)(scaleY * dotHeight);            _xMargin = 50;            if (w < QApplication::desktop()->width())                _xMargin += (QApplication::desktop()->width()-w)/2;            _yMargin = 50;            if (h < QApplication::desktop()->height())                _yMargin += (QApplication::desktop()->height()-h)/2;            m_Canvas = new QCanvas(int(w+2*_xMargin), int(h+2*_yMargin));            continue;        }        if ((cmd != "node") && (cmd != "edge")) {            kdWarning() << "Ignoring unknown command '" << cmd << "' from dot ("                << dotTmpFile->name() << ":" << lineno << ")" << endl;            continue;        }        if (cmd=="node") {            QString nodeName, label;            QString _x,_y,_w,_h;            double x, y, width, height;            lineStream >> nodeName >> _x >> _y >> _w >> _h;            x=_x.toDouble();            y=_y.toDouble();            width=_w.toDouble();            height=_h.toDouble();            // better here 'cause dot may scramble utf8 labels so we regenerate it better            // and do not read it in.            label = getLabelstring(nodeName);            int xx = (int)(scaleX * x + _xMargin);            int yy = (int)(scaleY * (dotHeight - y) + _yMargin);            int w = (int)(scaleX * width);            int h = (int)(scaleY * height);            QRect r(xx-w/2, yy-h/2, w, h);            GraphTreeLabel*t=new GraphTreeLabel(label,nodeName,r,m_Canvas);            if (isStart(nodeName)) {                ensureVisible(r.x(),r.y());            }            t->setBgColor(getBgColor(nodeName));            t->setZ(1.0);            t->show();            m_NodeList[nodeName]=t;        } else {            QString node1Name, node2Name, label;            QString _x,_y;            double x, y;            QPointArray pa;            int points, i;            lineStream >> node1Name >> node2Name;            lineStream >> points;            pa.resize(points);            for (i=0;i<points;++i) {                if (lineStream.atEnd()) break;                lineStream >> _x >> _y;                x=_x.toDouble();                y=_y.toDouble();                int xx = (int)(scaleX * x + _xMargin);                int yy = (int)(scaleY * (dotHeight - y) + _yMargin);                if (0) qDebug("   P %d: ( %f / %f ) => ( %d / %d)",                    i, x, y, xx, yy);                pa.setPoint(i, xx, yy);            }            if (i < points) {                qDebug("CallGraphView: Can't read %d spline points (%d)",                    points,  lineno);                continue;            }            GraphEdge * n = new GraphEdge(m_Canvas);            QColor arrowColor = Qt::black;            n->setPen(QPen(arrowColor,1));            n->setControlPoints(pa,false);            n->setZ(0.5);            n->show();            /* arrow */            QPoint arrowDir;            int indexHead = -1;            QMap<QString,GraphTreeLabel*>::Iterator it;            it = m_NodeList.find(node2Name);            if (it!=m_NodeList.end()) {                it.data()->setSource(node1Name);            }            it = m_NodeList.find(node1Name);            if (it!=m_NodeList.end()) {                GraphTreeLabel*tlab = it.data();                if (tlab) {                    QPoint toCenter = tlab->rect().center();                    int dx0 = pa.point(0).x() - toCenter.x();                    int dy0 = pa.point(0).y() - toCenter.y();                    int dx1 = pa.point(points-1).x() - toCenter.x();                    int dy1 = pa.point(points-1).y() - toCenter.y();                    if (dx0*dx0+dy0*dy0 > dx1*dx1+dy1*dy1) {                    // start of spline is nearer to call target node                        indexHead=-1;                        while(arrowDir.isNull() && (indexHead<points-2)) {                            indexHead++;                            arrowDir = pa.point(indexHead) - pa.point(indexHead+1);                        }                    }                }            }            if (arrowDir.isNull()) {                indexHead = points;                // sometimes the last spline points from dot are the same...                while(arrowDir.isNull() && (indexHead>1)) {                    indexHead--;                    arrowDir = pa.point(indexHead) - pa.point(indexHead-1);                }            }            if (!arrowDir.isNull()) {                arrowDir *= 10.0/sqrt(double(arrowDir.x()*arrowDir.x() +                    arrowDir.y()*arrowDir.y()));                QPointArray a(3);                a.setPoint(0, pa.point(indexHead) + arrowDir);                a.setPoint(1, pa.point(indexHead) + QPoint(arrowDir.y()/2,                    -arrowDir.x()/2));                a.setPoint(2, pa.point(indexHead) + QPoint(-arrowDir.y()/2,                    arrowDir.x()/2));                GraphEdgeArrow* aItem = new GraphEdgeArrow(n,m_Canvas);                aItem->setPoints(a);                aItem->setBrush(arrowColor);                aItem->setZ(1.5);                aItem->show();//                sItem->setArrow(aItem);            }        }    }    if (!m_Canvas) {        QString s = i18n("Error running the graph layouting tool.\n");        s += i18n("Please check that 'dot' is installed (package GraphViz).");        showText(s);    } else {        setCanvas(m_Canvas);        m_CompleteView->setCanvas(m_Canvas);    }    endInsert();    delete p;    renderProcess=0;}bool RevGraphView::isStart(const QString&nodeName)const{    bool res = false;    trevTree::ConstIterator it;    it = m_Tree.find(nodeName);    if (it==m_Tree.end()) {        return res;    }    switch (it.data().Action) {        case 'A':            res = true;            break;    }    return res;}char RevGraphView::getAction(const QString&nodeName)const{    trevTree::ConstIterator it;    it = m_Tree.find(nodeName);    if (it==m_Tree.end()) {        return (char)0;    }    return it.data().Action;}QColor RevGraphView::getBgColor(const QString&nodeName)const{    trevTree::ConstIterator it;    it = m_Tree.find(nodeName);    QColor res = Qt::white;    if (it==m_Tree.end()) {        return res;    }    switch (it.data().Action) {        case 'D':            res = Kdesvnsettings::tree_delete_color();            break;        case 'R':        case 'M':            res = Kdesvnsettings::tree_modify_color();            break;        case 'A':            res = Kdesvnsettings::tree_add_color();            break;        case 'C':        case 1:            res = Kdesvnsettings::tree_copy_color();            break;        case 2:            res = Kdesvnsettings::tree_rename_color();            break;        default:            res = Kdesvnsettings::tree_modify_color();            break;    }    return res;}const QString&RevGraphView::getLabelstring(const QString&nodeName){    QMap<QString,QString>::ConstIterator nIt;    nIt = m_LabelMap.find(nodeName);    if (nIt!=m_LabelMap.end()) {        return nIt.data();    }    trevTree::ConstIterator it1;    it1 = m_Tree.find(nodeName);    if (it1==m_Tree.end()) {        return m_LabelMap[""];    }    QString res;    switch (it1.data().Action) {    case 'D':        res = i18n("Deleted at revision %1").arg(it1.data().rev);    break;    case 'A':        res = i18n("Added at revision %1 as %2")            .arg(it1.data().rev)            .arg(it1.data().name);    break;    case 'C':    case 1:        res = i18n("Copied to %1 at revision %2").arg(it1.data().name).arg(it1.data().rev);    break;    case 2:        res = i18n("Renamed to %1 at revision %2").arg(it1.data().name).arg(it1.data().rev);    break;    case 'M':        res = i18n("Modified at revision %1").arg(it1.data().rev);    break;    case 'R':        res = i18n("Replaced at revision %1").arg(it1.data().rev);        break;    default:        res=i18n("Revision %1").arg(it1.data().rev);    break;    }    m_LabelMap[nodeName]=res;    return m_LabelMap[nodeName];}void RevGraphView::dumpRevtree(){    delete dotTmpFile;    clear();    dotOutput = "";    dotTmpFile = new KTempFile(QString::null,".dot");    dotTmpFile->setAutoDelete(true);    QTextStream* stream = dotTmpFile->textStream();    if (!stream) {        showText(i18n("Could not open tempfile %1 for writing.").arg(dotTmpFile->name()));        return;    }    *stream << "digraph \"callgraph\" {\n";    *stream << "  bgcolor=\"transparent\";\n";    int dir = Kdesvnsettings::tree_direction();    *stream << QString("  rankdir=\"");    switch (dir) {        case 3:            *stream << "TB";        break;        case 2:            *stream << "RL";        break;        case 1:            *stream << "BT";        break;        case 0:        default:            *stream << "LR";        break;    }    *stream << "\";\n";

⌨️ 快捷键说明

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