diff options
Diffstat (limited to 'src/app/graph/graph.cpp')
-rw-r--r-- | src/app/graph/graph.cpp | 465 |
1 files changed, 465 insertions, 0 deletions
diff --git a/src/app/graph/graph.cpp b/src/app/graph/graph.cpp new file mode 100644 index 000000000..f93ebc057 --- /dev/null +++ b/src/app/graph/graph.cpp @@ -0,0 +1,465 @@ +/************************************************************************** +** +** This file is part of the Qt Build Suite +** +** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (info@qt.nokia.com) +** +** +** GNU Lesser General Public License Usage +** +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this file. +** Please review the following information to ensure the GNU Lesser General +** Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. +** Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +**************************************************************************/ + +#include <tools/logger.h> +#include <tools/options.h> +#include <buildgraph/artifact.h> +#include <buildgraph/buildgraph.h> +#include <tools/fileinfo.h> +#include <Qbs/oldsourceproject.h> + +#include <cassert> + +#include <QCoreApplication> +#include <QProcess> +#include <QDir> +#include <QFileInfo> +#include <QDebug> +#include <cstdlib> +#include <cstdio> +#include <cassert> +#include <cmath> + +#include <QGraphicsView> +#include <QWheelEvent> +#include <QGraphicsScene> +#include <QGraphicsItem> +#include <QApplication> +#include <QFile> +#include <QTextStream> +#include <QDebug> +#include <QProcess> +#include <QFont> +#include <QStyle> +#include <QLineEdit> +#include <QGridLayout> +#include <QAbstractListModel> +#include <QTimer> + +#include <qtconcurrent/runextensions.h> +#include <QtCore/QFuture> + +class QGV : public QGraphicsView +{ +public: + QGV(QGraphicsScene *scene) : QGraphicsView(scene) + { + setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform); + setDragMode(ScrollHandDrag); + scaleView(0.5); + } + +protected: + void wheelEvent ( QWheelEvent * event ) + { + scaleView(pow((double)2, event->delta() / 240.0)); + } + + void scaleView(qreal scaleFactor) + { + qreal factor = transform().scale(scaleFactor, scaleFactor).mapRect(QRectF(0, 0, 1, 1)).width(); + if (factor < 0.07 || factor > 100) + return; + + scale(scaleFactor, scaleFactor); + } +}; + +struct ArtifactC +{ + qbs::Artifact *artifact; + QString text; + QString label; + int grade; + QRectF rectangle; + int row; + int col; + QGraphicsRectItem *graphicsRectItem; +}; + +QHash<qbs::Artifact *, ArtifactC *> cartifacts; +const qreal SCALE = 100.0f; +const qreal VSPACE = 200.0f; + +class MainWaffl : public QWidget +{ +Q_OBJECT +public: + MainWaffl(QGraphicsScene *scene) + : grid(this) + , qgv(scene) + { + grid.addWidget(&qgv, 0,0,1,1); + grid.addWidget(&searchBox, 1,0,1,1); + + connect(&searchBox, SIGNAL(textChanged ( const QString &)), + this, SLOT(startSearchTimer())); + connect(&searchTimer, SIGNAL(timeout()), + this, SLOT(search())); + l = cartifacts.values(); + qgv.centerOn(0,0); + } +private slots: + void startSearchTimer() + { + searchTimer.start(100); + } + void search() + { + searchTimer.stop(); + foreach (ArtifactC *nc, currentHis) { + nc->graphicsRectItem->setBrush(QColor(Qt::white)); + } + currentHis.clear(); + + QString t = searchBox.text(); + if (t.isEmpty()) + return; + foreach (ArtifactC *nc, l) { + if (nc->label.contains(t)) { + currentHis.append(nc); + nc->graphicsRectItem->setBrush(QColor(Qt::red)); + qgv.ensureVisible(nc->graphicsRectItem); + } + } + } +private: + QList<ArtifactC *> currentHis; + QTimer searchTimer; + QGridLayout grid; + QLineEdit searchBox; + QGV qgv; + QList<ArtifactC *> l; +}; + +qbs::CommandLineOptions options; + +void targetToScene(QGraphicsScene *scene, qbs::BuildProduct *t); +int main(int argc, char *argv[]) +{ +//#ifndef Q_OS_WIN +// QApplication::setGraphicsSystem("opengl"); +//#endif + QApplication app(argc, argv); + app.setApplicationName("qbs"); + app.setOrganizationName("Nokia"); + app.setOrganizationDomain("qt.nokia.com"); + + // read commandline + QStringList arguments = app.arguments(); + arguments.removeFirst(); + + if (!options.readCommandLineArguments(arguments)) { + qbs::CommandLineOptions::printHelp(); + return 1; + } + if (options.isHelpSet()) { + qbs::CommandLineOptions::printHelp(); + return 0; + } + + qbs::SourceProject sourceProject(options.settings()); + sourceProject.setSearchPaths(options.searchPaths()); + sourceProject.loadPlugins(options.pluginPaths()); + QFuture<bool> loadProjectFuture = QtConcurrent::run(&qbs::SourceProject::loadProject, + &sourceProject, + options.projectFileName(), + options.buildConfigurations()); + loadProjectFuture.waitForFinished(); + foreach (const qbs::Error &error, sourceProject.errors()) { + qbsError() << error.toString(); + return 4; + } + + QGraphicsScene scene; + foreach (qbs::BuildProject::Ptr t, sourceProject.buildProjects()) { + foreach (qbs::BuildProduct::Ptr p, t->buildProducts()) { + targetToScene(&scene, p.data()); + } + } + QRectF sr = scene.sceneRect(); + sr.adjust(-50, -50, 50, 50); + scene.setSceneRect(sr); + MainWaffl waffl(&scene); + waffl.showMaximized(); + + return app.exec(); +} + + +QMap<int, QMap<int, ArtifactC *> > table; + +int startcol = 0; +int endcol = 0; +void step1(qbs::Artifact *artifact, int l) +{ + if (!cartifacts.contains(artifact)) { + ArtifactC *nc = new ArtifactC; + cartifacts.insert(artifact, nc); + nc->text = artifact->fileName; + nc->label = qbs::FileInfo::fileName(artifact->fileName); + nc->artifact = artifact; + QMap<int, ArtifactC *> & line = table[l]; + int col = startcol; + while (line.contains(col)) { + col++; + } + table[l][col] = nc; + endcol = qMax(endcol, col); + foreach (qbs::Artifact *n2, artifact->children) { + step1(n2, l + 1); + } + startcol = endcol + 1; + } +} + + +QList<ArtifactC *> ncl; +QMap<int, int> layerx; +QMap<int, int> layerC; +QMultiMap<ArtifactC *, ArtifactC *> edges; + +void targetToScene(QGraphicsScene *scene, qbs::BuildProduct *t) +{ + QFont sceneFont = scene->font(); + sceneFont.setPointSize(14); + scene->setFont(sceneFont); + + QPen pen = QColor(Qt::black); + QBrush brush = QColor(Qt::white); + + foreach (qbs::Artifact *targetArtifact, t->targetArtifacts) + step1(targetArtifact, 1); + startcol = endcol + 1; + QFontMetricsF metrics(sceneFont); + + // draw artifacts + pen.setWidth(1); + pen.setCapStyle(Qt::FlatCap); + pen.setJoinStyle(Qt::MiterJoin); + for (QMap<int, QMap<int, ArtifactC *> >::const_iterator i = table.constBegin(); i != table.constEnd(); i++) { + int row = i.key(); + QMap<int, ArtifactC *> line = i.value(); + for (QMap<int, ArtifactC *>::const_iterator j = line.constBegin(); j != line.constEnd(); j++) { + int col = j.key(); + ArtifactC *nc = j.value(); + QRectF textRect = metrics.boundingRect(nc->label); + nc->row = row; + nc->col = col; + int x = row * (400 + VSPACE); + int y = col * 200; + nc->rectangle = textRect; + nc->rectangle.setWidth(400); + nc->rectangle.moveCenter(QPointF(x , y)); + + QGraphicsRectItem *item = scene->addRect(nc->rectangle, pen, brush); + item->setToolTip(nc->text); + nc->graphicsRectItem = item; + + QGraphicsSimpleTextItem *slabel = scene->addSimpleText(nc->label); + slabel->setBrush(Qt::black); + slabel->setFont(sceneFont); + + QRect textrect = QStyle::alignedRect (Qt::LeftToRight, + Qt::AlignCenter, + textRect.size().toSize(), + nc->rectangle.toRect()); + slabel->setPos(textrect.topLeft()); + + // insert edges + foreach (qbs::Artifact *c, nc->artifact->children) { + edges.insert(nc, cartifacts[c]); + } + } + } + + // draw edges + pen.setWidth(3); + + for (QMap<ArtifactC *, ArtifactC *>::const_iterator i = edges.constBegin(); + i != edges.constEnd(); + i++) { + ArtifactC * k = i.key(); + ArtifactC * v = i.value(); + assert(v); + QPainterPath path; + + QPointF fromP; + QPointF toP; + + + if (k->row < v->row) { + fromP = QPointF(k->rectangle.x() + k->rectangle.width(), k->rectangle.y() + k->rectangle.height()/2); + toP = QPointF(v->rectangle.x(), v->rectangle.y() + v->rectangle.height()/2); + } else { + fromP = QPointF(k->rectangle.x() + k->rectangle.width(), k->rectangle.y() + k->rectangle.height()/2); + toP = QPointF(v->rectangle.x(), v->rectangle.y() + v->rectangle.height()/2); + } + /* + } else if (k->row > v->row) { + fromP = QPointF(k->rc.x() + k->rc.width()/2, k->rc.y()); + toP = QPointF(v->rc.x() + v->rc.width()/2, v->rc.y() + v->rc.height()); + } else if (k->row < v->row) { + fromP = QPointF(k->rc.x() + k->rc.width()/2, k->rc.y() + v->rc.height()); + toP = QPointF(v->rc.x() + v->rc.width()/2, v->rc.y() ); + } + */ + + path.moveTo(fromP); + + QPointF c1 = fromP; + c1.setX(c1.x() + VSPACE/2); + QPointF c2 = toP; + c2.setX(c2.x() - VSPACE/2); + + path.cubicTo(c1, c2, toP); + + scene->addPath(path)->setPen(pen); + + QPolygonF poly; + poly.append(QPointF(toP.x() - 4, toP.y())); + poly.append(QPointF(toP.x() + 4, toP.y())); + poly.append(QPointF(toP.x(), toP.y() - 12)); + + QGraphicsItem *arrow = scene->addPolygon(poly, pen, QBrush(Qt::black)); + arrow->setTransformOriginPoint(toP.x(), toP.y()); + arrow->setRotation(-path.angleAtPercent(1) + 90); + } + + + + +} + + +#if 0 + if (directive == QLatin1String("graph")) { + qreal scale, width, height; + in >> scale >> width >> height; + scene->setSceneRect(0, 0, width * SCALE, height * SCALE); + + } else if (directive == QLatin1String("artifact")) { + QString name, label, style, shape, color, fillcolor; + qreal x, y, width, height; + in >> name >> x >> y >> width >> height; + + unsigned char labelReadState = 0; + while (!in.atEnd() && labelReadState != 2) { + QString s = in.read(1); + switch (labelReadState) { + case 0: + if (s.at(0) == QLatin1Char('"')) + labelReadState = 1; + break; + case 1: + if (s == QLatin1String("\"")) { + labelReadState = 2; + } else { + label.append(s); + } + break; + } + } + in >> style >> shape >> color >> fillcolor; + + label.replace(QLatin1String("\\n"), QLatin1String("\n")); + QPen pen = QColor(color); + QBrush brush = QColor(fillcolor); + + QRectF rc; + rc.setSize(QSizeF(width * SCALE, height * SCALE)); + rc.moveCenter(QPointF(x * SCALE, toY(y * SCALE))); + + QGraphicsItem *item = 0; + if (shape == QLatin1String("ellipse")) + item = scene->addEllipse(rc, pen, brush); + else + item = scene->addRect(rc, pen, brush); + item->setToolTip(label); + + QGraphicsSimpleTextItem *slabel = scene->addSimpleText(label); + slabel->setBrush(Qt::black); + slabel->setFont(sceneFont); + + QRect textrect = QStyle::alignedRect (Qt::LeftToRight, + Qt::AlignCenter, + slabel->boundingRect().size().toSize(), + rc.toRect()); + slabel->setPos(textrect.topLeft()); + + } else if (directive == QLatin1String("edge")) { + QString tail, head; + int n; + QString color; + + in >> tail >> head >> n; + color = line.split(' ').last(); + + QVector<QPointF> points; + for (int i = 0; i < n; ++i) { + qreal x, y; + in >> x >> y; + points.append(QPointF(x * SCALE, toY(y * SCALE))); + } + + QPainterPath path = fromControlPoints(points); + + QPen pen; + pen.setWidth(2); + if (color != "black") { + pen = QPen(QColor(0x33,0x33,0xff)); + pen.setWidth(1); + } + + scene->addPath(path)->setPen(pen); + + QPointF endPt = points.last(); + + QPolygonF poly; + poly.append(QPointF(endPt.x() - 4, endPt.y())); + poly.append(QPointF(endPt.x() + 4, endPt.y())); + poly.append(QPointF(endPt.x(), endPt.y() - 12)); + + QGraphicsItem *arrow = scene->addPolygon(poly, pen, QBrush(color + == "black"? Qt::black : QColor(0x33,0x33,0xff))); + arrow->setTransformOriginPoint(endPt.x(), endPt.y()); + arrow->setRotation(-path.angleAtPercent(1) + 90); + +#endif + + +#include "graph.moc" |