forked from qt-creator/qt-creator
debugger: make qml debugger start talking to qmlviewer
This commit is contained in:
569
src/plugins/debugger/qml/canvasframerate.cpp
Normal file
569
src/plugins/debugger/qml/canvasframerate.cpp
Normal file
@@ -0,0 +1,569 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** Commercial Usage
|
||||
**
|
||||
** Licensees holding valid Qt Commercial licenses may use this file in
|
||||
** accordance with the Qt Commercial License Agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Nokia.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** Alternatively, 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.
|
||||
**
|
||||
** If you are unsure which license is appropriate for your use, please
|
||||
** contact the sales department at http://qt.nokia.com/contact.
|
||||
**
|
||||
**************************************************************************/
|
||||
#include "canvasframerate.h"
|
||||
|
||||
#include <QtCore/qdebug.h>
|
||||
#include <QtCore/qstringlist.h>
|
||||
#include <QtCore/qdatastream.h>
|
||||
#include <QtCore/qmargins.h>
|
||||
|
||||
#include <QtGui/qapplication.h>
|
||||
#include <QtGui/qpainter.h>
|
||||
#include <QtGui/qtooltip.h>
|
||||
#include <QtGui/qslider.h>
|
||||
#include <QtGui/qscrollbar.h>
|
||||
#include <QtGui/qspinbox.h>
|
||||
#include <QtGui/qgroupbox.h>
|
||||
#include <QtGui/qboxlayout.h>
|
||||
#include <QtGui/qlabel.h>
|
||||
#include <QtGui/qlineedit.h>
|
||||
#include <QtGui/qpushbutton.h>
|
||||
#include <QtGui/qtabwidget.h>
|
||||
#include <QtGui/qevent.h>
|
||||
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
class QLineGraph : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
QLineGraph(QAbstractSlider *slider, QWidget * = 0);
|
||||
|
||||
void setPosition(int);
|
||||
|
||||
public slots:
|
||||
void addSample(int, int, int, bool);
|
||||
void setResolutionForHeight(int);
|
||||
void clear();
|
||||
|
||||
protected:
|
||||
virtual void paintEvent(QPaintEvent *);
|
||||
virtual void mouseMoveEvent(QMouseEvent *);
|
||||
virtual void leaveEvent(QEvent *);
|
||||
virtual void wheelEvent(QWheelEvent *event);
|
||||
|
||||
private slots:
|
||||
void sliderChanged(int);
|
||||
|
||||
private:
|
||||
void updateSlider();
|
||||
void drawSample(QPainter *, int, const QRect &, QList<QRect> *);
|
||||
void drawTime(QPainter *, const QRect &);
|
||||
QRect findContainingRect(const QList<QRect> &rects, const QPoint &pos) const;
|
||||
struct Sample {
|
||||
int sample[3];
|
||||
bool isBreak;
|
||||
};
|
||||
QList<Sample> _samples;
|
||||
|
||||
QAbstractSlider *slider;
|
||||
int position;
|
||||
int samplesPerWidth;
|
||||
int resolutionForHeight;
|
||||
bool ignoreScroll;
|
||||
QMargins graphMargins;
|
||||
|
||||
QList<QRect> rectsPaintTime; // time to do a paintEvent()
|
||||
QList<QRect> rectsTimeBetween; // time between frames
|
||||
QRect highlightedBar;
|
||||
};
|
||||
|
||||
QLineGraph::QLineGraph(QAbstractSlider *slider, QWidget *parent)
|
||||
: QWidget(parent), slider(slider), position(-1), samplesPerWidth(99), resolutionForHeight(50),
|
||||
ignoreScroll(false), graphMargins(65, 10, 71, 35)
|
||||
{
|
||||
setMouseTracking(true);
|
||||
|
||||
slider->setMaximum(0);
|
||||
slider->setMinimum(0);
|
||||
slider->setSingleStep(1);
|
||||
|
||||
connect(slider, SIGNAL(valueChanged(int)), this, SLOT(sliderChanged(int)));
|
||||
}
|
||||
|
||||
void QLineGraph::sliderChanged(int v)
|
||||
{
|
||||
if (ignoreScroll)
|
||||
return;
|
||||
|
||||
if (v == slider->maximum())
|
||||
position = -1;
|
||||
else
|
||||
position = v;
|
||||
|
||||
update();
|
||||
|
||||
// update highlightedRect
|
||||
QPoint pos = mapFromGlobal(QCursor::pos());
|
||||
if (geometry().contains(pos)) {
|
||||
QMouseEvent *me = new QMouseEvent(QEvent::MouseMove, pos,
|
||||
Qt::NoButton, Qt::NoButton, Qt::NoModifier);
|
||||
QApplication::postEvent(this, me);
|
||||
}
|
||||
}
|
||||
|
||||
void QLineGraph::clear()
|
||||
{
|
||||
_samples.clear();
|
||||
rectsPaintTime.clear();
|
||||
rectsTimeBetween.clear();
|
||||
highlightedBar = QRect();
|
||||
position = -1;
|
||||
|
||||
updateSlider();
|
||||
update();
|
||||
}
|
||||
|
||||
void QLineGraph::updateSlider()
|
||||
{
|
||||
ignoreScroll = true;
|
||||
slider->setMaximum(qMax(0, _samples.count() - samplesPerWidth - 1));
|
||||
|
||||
if (position == -1) {
|
||||
slider->setValue(slider->maximum());
|
||||
} else {
|
||||
slider->setValue(position);
|
||||
}
|
||||
ignoreScroll = false;
|
||||
}
|
||||
|
||||
void QLineGraph::addSample(int a, int b, int d, bool isBreak)
|
||||
{
|
||||
Sample s;
|
||||
s.isBreak = isBreak;
|
||||
s.sample[0] = a;
|
||||
s.sample[1] = b;
|
||||
s.sample[2] = d;
|
||||
_samples << s;
|
||||
updateSlider();
|
||||
update();
|
||||
}
|
||||
|
||||
void QLineGraph::setPosition(int p)
|
||||
{
|
||||
sliderChanged(p);
|
||||
}
|
||||
|
||||
void QLineGraph::drawTime(QPainter *p, const QRect &rect)
|
||||
{
|
||||
if (_samples.isEmpty())
|
||||
return;
|
||||
|
||||
int first = position;
|
||||
if (first == -1)
|
||||
first = qMax(0, _samples.count() - samplesPerWidth - 1);
|
||||
int last = qMin(_samples.count() - 1, first + samplesPerWidth);
|
||||
|
||||
qreal scaleX = qreal(rect.width()) / qreal(samplesPerWidth);
|
||||
|
||||
int t = 0;
|
||||
|
||||
for (int ii = first; ii <= last; ++ii) {
|
||||
int sampleTime = _samples.at(ii).sample[2] / 1000;
|
||||
if (sampleTime != t) {
|
||||
|
||||
int xEnd = rect.left() + scaleX * (ii - first);
|
||||
p->drawLine(xEnd, rect.bottom(), xEnd, rect.bottom() + 7);
|
||||
|
||||
QRect text(xEnd - 30, rect.bottom() + 10, 60, 30);
|
||||
|
||||
p->drawText(text, Qt::AlignHCenter | Qt::AlignTop, QString::number(_samples.at(ii).sample[2]));
|
||||
|
||||
t = sampleTime;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void QLineGraph::drawSample(QPainter *p, int s, const QRect &rect, QList<QRect> *record)
|
||||
{
|
||||
if (_samples.isEmpty())
|
||||
return;
|
||||
|
||||
int first = position;
|
||||
if (first == -1)
|
||||
first = qMax(0, _samples.count() - samplesPerWidth - 1);
|
||||
int last = qMin(_samples.count() - 1, first + samplesPerWidth);
|
||||
|
||||
qreal scaleY = qreal(rect.height()) / resolutionForHeight;
|
||||
qreal scaleX = qreal(rect.width()) / qreal(samplesPerWidth);
|
||||
|
||||
int xEnd;
|
||||
int lastXEnd = rect.left();
|
||||
|
||||
p->save();
|
||||
p->setPen(Qt::NoPen);
|
||||
for (int ii = first + 1; ii <= last; ++ii) {
|
||||
|
||||
xEnd = rect.left() + scaleX * (ii - first);
|
||||
int yEnd = rect.bottom() - _samples.at(ii).sample[s] * scaleY;
|
||||
|
||||
if (!(s == 0 && _samples.at(ii).isBreak)) {
|
||||
QRect bar(lastXEnd, yEnd, scaleX, _samples.at(ii).sample[s] * scaleY);
|
||||
record->append(bar);
|
||||
p->drawRect(bar);
|
||||
}
|
||||
|
||||
lastXEnd = xEnd;
|
||||
}
|
||||
p->restore();
|
||||
}
|
||||
|
||||
void QLineGraph::paintEvent(QPaintEvent *)
|
||||
{
|
||||
QPainter p(this);
|
||||
p.setRenderHint(QPainter::Antialiasing);
|
||||
|
||||
QRect r(graphMargins.left(), graphMargins.top(),
|
||||
width() - graphMargins.right(), height() - graphMargins.bottom());
|
||||
|
||||
p.save();
|
||||
p.rotate(-90);
|
||||
p.translate(-r.height()/2 - r.width()/2 - graphMargins.right(), -r.height()/2);
|
||||
p.drawText(r, Qt::AlignCenter, tr("Frame rate"));
|
||||
p.restore();
|
||||
|
||||
p.setBrush(QColor("lightsteelblue"));
|
||||
rectsTimeBetween.clear();
|
||||
drawSample(&p, 0, r, &rectsTimeBetween);
|
||||
|
||||
p.setBrush(QColor("pink"));
|
||||
rectsPaintTime.clear();
|
||||
drawSample(&p, 1, r, &rectsPaintTime);
|
||||
|
||||
if (!highlightedBar.isNull()) {
|
||||
p.setBrush(Qt::darkGreen);
|
||||
p.drawRect(highlightedBar);
|
||||
}
|
||||
|
||||
p.setBrush(Qt::NoBrush);
|
||||
p.drawRect(r);
|
||||
|
||||
slider->setGeometry(x() + r.x(), slider->y(), r.width(), slider->height());
|
||||
|
||||
for (int ii = 0; ii <= resolutionForHeight; ++ii) {
|
||||
int y = 1 + r.bottom() - ii * r.height() / resolutionForHeight;
|
||||
|
||||
if ((ii % 10) == 0) {
|
||||
p.drawLine(r.left() - 20, y, r.left(), y);
|
||||
QRect text(r.left() - 20 - 53, y - 10, 50, 20);
|
||||
p.drawText(text, Qt::AlignRight | Qt::AlignVCenter, QString::number(ii));
|
||||
} else {
|
||||
p.drawLine(r.left() - 7, y, r.left(), y);
|
||||
}
|
||||
}
|
||||
|
||||
drawTime(&p, r);
|
||||
}
|
||||
|
||||
void QLineGraph::mouseMoveEvent(QMouseEvent *event)
|
||||
{
|
||||
QPoint pos = event->pos();
|
||||
|
||||
QRect rect = findContainingRect(rectsPaintTime, pos);
|
||||
if (rect.isNull())
|
||||
rect = findContainingRect(rectsTimeBetween, pos);
|
||||
|
||||
if (!highlightedBar.isNull())
|
||||
update(highlightedBar.adjusted(-1, -1, 1, 1));
|
||||
highlightedBar = rect;
|
||||
|
||||
if (!rect.isNull()) {
|
||||
QRect graph(graphMargins.left(), graphMargins.top(),
|
||||
width() - graphMargins.right(), height() - graphMargins.bottom());
|
||||
qreal scaleY = qreal(graph.height()) / resolutionForHeight;
|
||||
QToolTip::showText(event->globalPos(), QString::number(qRound(rect.height() / scaleY)), this, rect);
|
||||
update(rect.adjusted(-1, -1, 1, 1));
|
||||
}
|
||||
}
|
||||
|
||||
void QLineGraph::leaveEvent(QEvent *)
|
||||
{
|
||||
if (!highlightedBar.isNull()) {
|
||||
QRect bar = highlightedBar.adjusted(-1, -1, 1, 1);
|
||||
highlightedBar = QRect();
|
||||
update(bar);
|
||||
}
|
||||
}
|
||||
|
||||
void QLineGraph::wheelEvent(QWheelEvent *event)
|
||||
{
|
||||
QWheelEvent we(QPoint(0,0), event->delta(), event->buttons(), event->modifiers(), event->orientation());
|
||||
QApplication::sendEvent(slider, &we);
|
||||
}
|
||||
|
||||
void QLineGraph::setResolutionForHeight(int resolution)
|
||||
{
|
||||
resolutionForHeight = resolution;
|
||||
update();
|
||||
}
|
||||
|
||||
QRect QLineGraph::findContainingRect(const QList<QRect> &rects, const QPoint &pos) const
|
||||
{
|
||||
for (int i=0; i<rects.count(); ++i) {
|
||||
if (rects[i].contains(pos))
|
||||
return rects[i];
|
||||
}
|
||||
return QRect();
|
||||
}
|
||||
|
||||
|
||||
class GraphWindow : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
GraphWindow(QWidget *parent = 0);
|
||||
|
||||
virtual QSize sizeHint() const;
|
||||
|
||||
public slots:
|
||||
void addSample(int, int, int, bool);
|
||||
void setResolutionForHeight(int);
|
||||
void clear();
|
||||
|
||||
private:
|
||||
QLineGraph *m_graph;
|
||||
};
|
||||
|
||||
GraphWindow::GraphWindow(QWidget *parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
QSlider *scroll = new QSlider(Qt::Horizontal);
|
||||
scroll->setFocusPolicy(Qt::WheelFocus);
|
||||
m_graph = new QLineGraph(scroll);
|
||||
|
||||
setFocusPolicy(Qt::WheelFocus);
|
||||
setFocusProxy(scroll);
|
||||
|
||||
QVBoxLayout *layout = new QVBoxLayout(this);
|
||||
layout->setContentsMargins(0, 0, 5, 0);
|
||||
layout->setSpacing(0);
|
||||
layout->addWidget(m_graph, 2);
|
||||
layout->addWidget(new QLabel(tr("Total time elapsed (ms)")), 0, Qt::AlignHCenter);
|
||||
layout->addWidget(scroll);
|
||||
}
|
||||
|
||||
void GraphWindow::addSample(int a, int b, int d, bool isBreak)
|
||||
{
|
||||
m_graph->addSample(a, b, d, isBreak);
|
||||
}
|
||||
|
||||
void GraphWindow::setResolutionForHeight(int res)
|
||||
{
|
||||
m_graph->setResolutionForHeight(res);
|
||||
}
|
||||
|
||||
void GraphWindow::clear()
|
||||
{
|
||||
m_graph->clear();
|
||||
}
|
||||
|
||||
QSize GraphWindow::sizeHint() const
|
||||
{
|
||||
return QSize(400, 220);
|
||||
}
|
||||
|
||||
|
||||
class CanvasFrameRatePlugin : public QDeclarativeDebugClient
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
CanvasFrameRatePlugin(QDeclarativeDebugConnection *client);
|
||||
|
||||
signals:
|
||||
void sample(int, int, int, bool);
|
||||
|
||||
protected:
|
||||
virtual void messageReceived(const QByteArray &);
|
||||
|
||||
private:
|
||||
int lb;
|
||||
int ld;
|
||||
};
|
||||
|
||||
CanvasFrameRatePlugin::CanvasFrameRatePlugin(QDeclarativeDebugConnection *client)
|
||||
: QDeclarativeDebugClient(QLatin1String("CanvasFrameRate"), client), lb(-1)
|
||||
{
|
||||
}
|
||||
|
||||
void CanvasFrameRatePlugin::messageReceived(const QByteArray &data)
|
||||
{
|
||||
QByteArray rwData = data;
|
||||
QDataStream stream(&rwData, QIODevice::ReadOnly);
|
||||
|
||||
int b; int c; int d; bool isBreak;
|
||||
stream >> b >> c >> d >> isBreak;
|
||||
|
||||
if (lb != -1)
|
||||
emit sample(c, lb, ld, isBreak);
|
||||
|
||||
lb = b;
|
||||
ld = d;
|
||||
}
|
||||
|
||||
CanvasFrameRate::CanvasFrameRate(QWidget *parent)
|
||||
: QWidget(parent),
|
||||
m_plugin(0)
|
||||
{
|
||||
m_tabs = new QTabWidget(this);
|
||||
|
||||
QHBoxLayout *bottom = new QHBoxLayout;
|
||||
bottom->setMargin(0);
|
||||
bottom->setSpacing(10);
|
||||
|
||||
m_res = new QSpinBox;
|
||||
m_res->setRange(30, 200);
|
||||
m_res->setValue(m_res->minimum());
|
||||
m_res->setSingleStep(10);
|
||||
m_res->setSuffix(QLatin1String("ms"));
|
||||
bottom->addWidget(new QLabel(tr("Resolution:")));
|
||||
bottom->addWidget(m_res);
|
||||
|
||||
bottom->addStretch();
|
||||
|
||||
m_clearButton = new QPushButton(tr("Clear"));
|
||||
connect(m_clearButton, SIGNAL(clicked()), SLOT(clearGraph()));
|
||||
bottom->addWidget(m_clearButton);
|
||||
|
||||
QPushButton *pb = new QPushButton(tr("New Graph"), this);
|
||||
connect(pb, SIGNAL(clicked()), this, SLOT(newTab()));
|
||||
bottom->addWidget(pb);
|
||||
|
||||
m_group = new QGroupBox(tr("Enabled"));
|
||||
m_group->setCheckable(true);
|
||||
m_group->setChecked(false);
|
||||
connect(m_group, SIGNAL(toggled(bool)), SLOT(enabledToggled(bool)));
|
||||
|
||||
QVBoxLayout *groupLayout = new QVBoxLayout(m_group);
|
||||
groupLayout->setContentsMargins(5, 0, 5, 0);
|
||||
groupLayout->setSpacing(2);
|
||||
groupLayout->addWidget(m_tabs);
|
||||
groupLayout->addLayout(bottom);
|
||||
|
||||
QVBoxLayout *layout = new QVBoxLayout;
|
||||
layout->setContentsMargins(0, 10, 0, 0);
|
||||
layout->setSpacing(0);
|
||||
layout->addWidget(m_group);
|
||||
setLayout(layout);
|
||||
}
|
||||
|
||||
void CanvasFrameRate::reset(QDeclarativeDebugConnection *conn)
|
||||
{
|
||||
delete m_plugin;
|
||||
m_plugin = 0;
|
||||
|
||||
QWidget *w;
|
||||
for (int i = 0; i < m_tabs->count(); ++i) {
|
||||
w = m_tabs->widget(i);
|
||||
m_tabs->removeTab(i);
|
||||
delete w;
|
||||
}
|
||||
|
||||
if (conn) {
|
||||
connect(conn, SIGNAL(stateChanged(QAbstractSocket::SocketState)),
|
||||
SLOT(connectionStateChanged(QAbstractSocket::SocketState)));
|
||||
if (conn->state() == QAbstractSocket::ConnectedState)
|
||||
handleConnected(conn);
|
||||
}
|
||||
}
|
||||
|
||||
void CanvasFrameRate::connectionStateChanged(QAbstractSocket::SocketState state)
|
||||
{
|
||||
if (state == QAbstractSocket::UnconnectedState) {
|
||||
delete m_plugin;
|
||||
m_plugin = 0;
|
||||
} else if (state == QAbstractSocket::ConnectedState) {
|
||||
handleConnected(qobject_cast<QDeclarativeDebugConnection*>(sender()));
|
||||
}
|
||||
}
|
||||
|
||||
void CanvasFrameRate::handleConnected(QDeclarativeDebugConnection *conn)
|
||||
{
|
||||
delete m_plugin;
|
||||
m_plugin = new CanvasFrameRatePlugin(conn);
|
||||
enabledToggled(m_group->isChecked());
|
||||
newTab();
|
||||
}
|
||||
|
||||
void CanvasFrameRate::setSizeHint(const QSize &size)
|
||||
{
|
||||
m_sizeHint = size;
|
||||
}
|
||||
|
||||
QSize CanvasFrameRate::sizeHint() const
|
||||
{
|
||||
return m_sizeHint;
|
||||
}
|
||||
|
||||
void CanvasFrameRate::clearGraph()
|
||||
{
|
||||
if (m_tabs->count()) {
|
||||
GraphWindow *w = qobject_cast<GraphWindow*>(m_tabs->currentWidget());
|
||||
if (w)
|
||||
w->clear();
|
||||
}
|
||||
}
|
||||
|
||||
void CanvasFrameRate::newTab()
|
||||
{
|
||||
if (!m_plugin)
|
||||
return;
|
||||
|
||||
if (m_tabs->count()) {
|
||||
QWidget *w = m_tabs->widget(m_tabs->count() - 1);
|
||||
QObject::disconnect(m_plugin, SIGNAL(sample(int,int,int,bool)),
|
||||
w, SLOT(addSample(int,int,int,bool)));
|
||||
}
|
||||
|
||||
int count = m_tabs->count();
|
||||
|
||||
GraphWindow *graph = new GraphWindow;
|
||||
graph->setResolutionForHeight(m_res->value());
|
||||
connect(m_plugin, SIGNAL(sample(int,int,int,bool)),
|
||||
graph, SLOT(addSample(int,int,int,bool)));
|
||||
connect(m_res, SIGNAL(valueChanged(int)),
|
||||
graph, SLOT(setResolutionForHeight(int)));
|
||||
|
||||
QString name = QLatin1String("Graph ") + QString::number(count + 1);
|
||||
m_tabs->addTab(graph, name);
|
||||
m_tabs->setCurrentIndex(count);
|
||||
}
|
||||
|
||||
void CanvasFrameRate::enabledToggled(bool checked)
|
||||
{
|
||||
if (m_plugin)
|
||||
static_cast<QDeclarativeDebugClient *>(m_plugin)->setEnabled(checked);
|
||||
}
|
||||
|
||||
} // Internal
|
||||
} // Debugger
|
||||
|
||||
#include "canvasframerate.moc"
|
||||
88
src/plugins/debugger/qml/canvasframerate.h
Normal file
88
src/plugins/debugger/qml/canvasframerate.h
Normal file
@@ -0,0 +1,88 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** Commercial Usage
|
||||
**
|
||||
** Licensees holding valid Qt Commercial licenses may use this file in
|
||||
** accordance with the Qt Commercial License Agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Nokia.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** Alternatively, 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.
|
||||
**
|
||||
** If you are unsure which license is appropriate for your use, please
|
||||
** contact the sales department at http://qt.nokia.com/contact.
|
||||
**
|
||||
**************************************************************************/
|
||||
#ifndef CANVASFRAMERATE_H
|
||||
#define CANVASFRAMERATE_H
|
||||
|
||||
#include <private/qdeclarativedebugclient_p.h>
|
||||
|
||||
#include <QtCore/qpointer.h>
|
||||
#include <QtGui/qwidget.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QTabWidget;
|
||||
class QSlider;
|
||||
class QGroupBox;
|
||||
class QLabel;
|
||||
class QSpinBox;
|
||||
class QPushButton;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
|
||||
class CanvasFrameRatePlugin;
|
||||
|
||||
class CanvasFrameRate : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
CanvasFrameRate(QWidget *parent = 0);
|
||||
|
||||
void reset(QDeclarativeDebugConnection *conn);
|
||||
|
||||
void setSizeHint(const QSize &);
|
||||
virtual QSize sizeHint() const;
|
||||
|
||||
signals:
|
||||
void contextHelpIdChanged(const QString &helpId);
|
||||
|
||||
private slots:
|
||||
void clearGraph();
|
||||
void newTab();
|
||||
void enabledToggled(bool);
|
||||
void connectionStateChanged(QAbstractSocket::SocketState state);
|
||||
|
||||
private:
|
||||
void handleConnected(QDeclarativeDebugConnection *conn);
|
||||
|
||||
QGroupBox *m_group;
|
||||
QTabWidget *m_tabs;
|
||||
QSpinBox *m_res;
|
||||
QPushButton *m_clearButton;
|
||||
CanvasFrameRatePlugin *m_plugin;
|
||||
QSize m_sizeHint;
|
||||
};
|
||||
|
||||
} // Internal
|
||||
} // Debugger
|
||||
|
||||
#endif // CANVASFRAMERATE_H
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
HEADERS += \
|
||||
$$PWD/qmlengine.h \
|
||||
$$PWD/canvasframerate.h \
|
||||
|
||||
SOURCES += \
|
||||
$$PWD/qmlengine.cpp \
|
||||
$$PWD/canvasframerate.cpp \
|
||||
|
||||
QT += declarative
|
||||
|
||||
FORMS +=
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include "qmlengine.h"
|
||||
|
||||
#include "debuggerconstants.h"
|
||||
#include "debuggerplugin.h"
|
||||
#include "debuggerdialogs.h"
|
||||
#include "debuggerstringutils.h"
|
||||
|
||||
@@ -40,6 +41,10 @@
|
||||
#include "watchhandler.h"
|
||||
#include "watchutils.h"
|
||||
|
||||
#include "canvasframerate.h"
|
||||
|
||||
#include <projectexplorer/environment.h>
|
||||
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <QtCore/QDateTime>
|
||||
@@ -55,6 +60,10 @@
|
||||
#include <QtGui/QToolTip>
|
||||
|
||||
#include <QtNetwork/QTcpSocket>
|
||||
#include <QtNetwork/QHostAddress>
|
||||
|
||||
#include <private/qdeclarativedebug_p.h>
|
||||
#include <private/qdeclarativedebugclient_p.h>
|
||||
|
||||
#define DEBUG_QML 1
|
||||
#if DEBUG_QML
|
||||
@@ -97,6 +106,36 @@ QString QmlEngine::QmlCommand::toString() const
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// QmlDebuggerClient
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
class QmlDebuggerClient : public QDeclarativeDebugClient
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
QmlDebuggerClient(QDeclarativeDebugConnection *connection, QmlEngine *engine)
|
||||
: QDeclarativeDebugClient(QLatin1String("Debugger"), connection)
|
||||
, m_connection(connection), m_engine(engine)
|
||||
{
|
||||
setEnabled(true);
|
||||
}
|
||||
|
||||
void messageReceived(const QByteArray &data)
|
||||
{
|
||||
m_engine->messageReceived(data);
|
||||
}
|
||||
|
||||
|
||||
QDeclarativeDebugConnection *m_connection;
|
||||
QmlEngine *m_engine;
|
||||
};
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// QmlEngine
|
||||
@@ -109,6 +148,13 @@ QmlEngine::QmlEngine(const DebuggerStartParameters &startParameters)
|
||||
m_congestion = 0;
|
||||
m_inAir = 0;
|
||||
|
||||
m_conn = 0;
|
||||
m_client = 0;
|
||||
m_engineQuery = 0;
|
||||
m_contextQuery = 0;
|
||||
|
||||
m_frameRate = 0;
|
||||
|
||||
m_sendTimer.setSingleShot(true);
|
||||
m_sendTimer.setInterval(100); // ms
|
||||
connect(&m_sendTimer, SIGNAL(timeout()), this, SLOT(handleSendTimer()));
|
||||
@@ -128,6 +174,7 @@ QmlEngine::QmlEngine(const DebuggerStartParameters &startParameters)
|
||||
//connect(m_socket, SIGNAL(proxyAuthenticationRequired(QNetworkProxy, QAuthenticator *)))
|
||||
//connect(m_socket, SIGNAL(stateChanged(QAbstractSocket::SocketState)),
|
||||
// thism SLOT(socketStateChanged(QAbstractSocket::SocketState)));
|
||||
|
||||
}
|
||||
|
||||
QmlEngine::~QmlEngine()
|
||||
@@ -153,8 +200,9 @@ void QmlEngine::socketReadyRead()
|
||||
|
||||
void QmlEngine::socketConnected()
|
||||
{
|
||||
qDebug() << "SOCKET CONNECTED.";
|
||||
showStatusMessage("Socket connected.");
|
||||
m_socket->waitForConnected(2000);
|
||||
//m_socket->waitForConnected(2000);
|
||||
//sendCommand("Locator", "redirect", "ID");
|
||||
}
|
||||
|
||||
@@ -168,6 +216,7 @@ void QmlEngine::socketError(QAbstractSocket::SocketError)
|
||||
QString msg = tr("%1.").arg(m_socket->errorString());
|
||||
//QMessageBox::critical(q->mainWindow(), tr("Error"), msg);
|
||||
showStatusMessage(msg);
|
||||
qDebug() << "SOCKET ERROR: " << msg;
|
||||
exitDebugger();
|
||||
}
|
||||
|
||||
@@ -199,19 +248,95 @@ void QmlEngine::exitDebugger()
|
||||
SDEBUG("QmlEngine::exitDebugger()");
|
||||
}
|
||||
|
||||
const int serverPort = 3768;
|
||||
|
||||
void QmlEngine::startDebugger()
|
||||
{
|
||||
qDebug() << "STARTING QML ENGINE";
|
||||
setState(InferiorRunningRequested);
|
||||
showStatusMessage(tr("Running requested..."), 5000);
|
||||
/* const DebuggerStartParameters &sp = startParameters();
|
||||
QTC_ASSERT(state() == DebuggerNotReady, setState(DebuggerNotReady));
|
||||
setState(EngineStarting);
|
||||
const DebuggerStartParameters &sp = startParameters();
|
||||
const int pos = sp.remoteChannel.indexOf(QLatin1Char(':'));
|
||||
const QString host = sp.remoteChannel.left(pos);
|
||||
const quint16 port = sp.remoteChannel.mid(pos + 1).toInt();
|
||||
qDebug() << "STARTING QML ENGINE" << host << port << sp.remoteChannel
|
||||
<< sp.executable << sp.processArgs << sp.workingDirectory;
|
||||
|
||||
ProjectExplorer::Environment env = ProjectExplorer::Environment::systemEnvironment(); // empty env by default
|
||||
env.set("QML_DEBUG_SERVER_PORT", QString::number(serverPort));
|
||||
|
||||
connect(&m_proc, SIGNAL(error(QProcess::ProcessError)),
|
||||
SLOT(handleProcError(QProcess::ProcessError)));
|
||||
connect(&m_proc, SIGNAL(finished(int, QProcess::ExitStatus)),
|
||||
SLOT(handleProcFinished(int, QProcess::ExitStatus)));
|
||||
connect(&m_proc, SIGNAL(readyReadStandardOutput()),
|
||||
SLOT(readProcStandardOutput()));
|
||||
connect(&m_proc, SIGNAL(readyReadStandardError()),
|
||||
SLOT(readProcStandardError()));
|
||||
|
||||
setState(AdapterStarting);
|
||||
m_proc.setEnvironment(env.toStringList());
|
||||
m_proc.setWorkingDirectory(sp.workingDirectory);
|
||||
m_proc.start(sp.executable, sp.processArgs);
|
||||
|
||||
//QTimer::singleShot(0, this, SLOT(runInferior()));
|
||||
m_socket->connectToHost(host, port); */
|
||||
|
||||
if (!m_proc.waitForStarted()) {
|
||||
setState(AdapterStartFailed);
|
||||
startFailed();
|
||||
return;
|
||||
}
|
||||
qDebug() << "PROC STARTED.";
|
||||
//m_socket->connectToHost(host, port);
|
||||
//startSuccessful();
|
||||
//showStatusMessage(tr("Running requested..."), 5000);
|
||||
//setState(InferiorRunning); // FIXME
|
||||
|
||||
setState(AdapterStarted);
|
||||
setState(InferiorStarting);
|
||||
|
||||
//m_frameRate = new CanvasFrameRate(0);
|
||||
//m_frameRate->show();
|
||||
}
|
||||
|
||||
void QmlEngine::setupConnection()
|
||||
{
|
||||
QTC_ASSERT(m_conn == 0, /**/);
|
||||
m_conn = new QDeclarativeDebugConnection(this);
|
||||
|
||||
connect(m_conn, SIGNAL(stateChanged(QAbstractSocket::SocketState)),
|
||||
SLOT(connectionStateChanged()));
|
||||
connect(m_conn, SIGNAL(error(QAbstractSocket::SocketError)),
|
||||
SLOT(connectionError()));
|
||||
connect(m_conn, SIGNAL(connected()),
|
||||
SLOT(connectionConnected()));
|
||||
|
||||
QTC_ASSERT(m_client == 0, /**/);
|
||||
m_client = new QmlDebuggerClient(m_conn, this);
|
||||
|
||||
//m_objectTreeWidget->setEngineDebug(m_client);
|
||||
//m_propertiesWidget->setEngineDebug(m_client);
|
||||
//m_watchTableModel->setEngineDebug(m_client);
|
||||
//m_expressionWidget->setEngineDebug(m_client);
|
||||
|
||||
// resetViews();
|
||||
// m_frameRateWidget->reset(m_conn);
|
||||
// reloadEngines();
|
||||
|
||||
QHostAddress ha(QHostAddress::LocalHost);
|
||||
|
||||
qDebug() << "CONNECTING TO " << ha.toString() << serverPort;
|
||||
m_conn->connectToHost(ha, serverPort);
|
||||
|
||||
if (!m_conn->waitForConnected()) {
|
||||
qDebug() << "CONNECTION FAILED";
|
||||
setState(InferiorStartFailed);
|
||||
startFailed();
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug() << "CONNECTION SUCCESSFUL";
|
||||
setState(InferiorRunning);
|
||||
startSuccessful();
|
||||
setState(InferiorRunning); // FIXME
|
||||
}
|
||||
|
||||
void QmlEngine::continueInferior()
|
||||
@@ -231,6 +356,7 @@ void QmlEngine::runInferior()
|
||||
|
||||
void QmlEngine::interruptInferior()
|
||||
{
|
||||
qDebug() << "INTERRUPT";
|
||||
QByteArray reply;
|
||||
QDataStream rs(&reply, QIODevice::WriteOnly);
|
||||
rs << QByteArray("INTERRUPT");
|
||||
@@ -503,6 +629,12 @@ void QmlEngine::handleSendTimer()
|
||||
*/
|
||||
}
|
||||
|
||||
void QmlEngine::sendMessage(const QByteArray &msg)
|
||||
{
|
||||
QTC_ASSERT(m_client, return);
|
||||
m_client->sendMessage(msg);
|
||||
}
|
||||
|
||||
void QmlEngine::sendCommandNow(const QmlCommand &cmd)
|
||||
{
|
||||
++m_inAir;
|
||||
@@ -743,5 +875,131 @@ void QmlEngine::messageReceived(const QByteArray &message)
|
||||
|
||||
}
|
||||
|
||||
QString QmlEngine::errorMessage(QProcess::ProcessError error)
|
||||
{
|
||||
switch (error) {
|
||||
case QProcess::FailedToStart:
|
||||
return tr("The Gdb process failed to start. Either the "
|
||||
"invoked program is missing, or you may have insufficient "
|
||||
"permissions to invoke the program.");
|
||||
case QProcess::Crashed:
|
||||
return tr("The Gdb process crashed some time after starting "
|
||||
"successfully.");
|
||||
case QProcess::Timedout:
|
||||
return tr("The last waitFor...() function timed out. "
|
||||
"The state of QProcess is unchanged, and you can try calling "
|
||||
"waitFor...() again.");
|
||||
case QProcess::WriteError:
|
||||
return tr("An error occurred when attempting to write "
|
||||
"to the Gdb process. For example, the process may not be running, "
|
||||
"or it may have closed its input channel.");
|
||||
case QProcess::ReadError:
|
||||
return tr("An error occurred when attempting to read from "
|
||||
"the Gdb process. For example, the process may not be running.");
|
||||
default:
|
||||
return tr("An unknown error in the Gdb process occurred. ");
|
||||
}
|
||||
}
|
||||
|
||||
void QmlEngine::handleProcError(QProcess::ProcessError error)
|
||||
{
|
||||
showMessage(_("HANDLE QML ERROR"));
|
||||
switch (error) {
|
||||
case QProcess::Crashed:
|
||||
break; // will get a processExited() as well
|
||||
// impossible case QProcess::FailedToStart:
|
||||
case QProcess::ReadError:
|
||||
case QProcess::WriteError:
|
||||
case QProcess::Timedout:
|
||||
default:
|
||||
m_proc.kill();
|
||||
setState(EngineShuttingDown, true);
|
||||
plugin()->showMessageBox(QMessageBox::Critical, tr("Gdb I/O Error"),
|
||||
errorMessage(error));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void QmlEngine::handleProcFinished(int code, QProcess::ExitStatus type)
|
||||
{
|
||||
showMessage(_("QML VIEWER PROCESS FINISHED, status %1, code %2").arg(type).arg(code));
|
||||
setState(DebuggerNotReady, true);
|
||||
}
|
||||
|
||||
void QmlEngine::readProcStandardError()
|
||||
{
|
||||
qDebug() << "STD ERR" << m_proc.readAllStandardError();
|
||||
if (!m_conn)
|
||||
setupConnection();
|
||||
}
|
||||
|
||||
void QmlEngine::readProcStandardOutput()
|
||||
{
|
||||
qDebug() << "STD ERR" << m_proc.readAllStandardOutput();
|
||||
}
|
||||
|
||||
void QmlEngine::connectionStateChanged()
|
||||
{
|
||||
QTC_ASSERT(m_conn, return);
|
||||
QAbstractSocket::SocketState state = m_conn->state();
|
||||
qDebug() << "CONNECTION STATE: " << state;
|
||||
switch (state) {
|
||||
case QAbstractSocket::UnconnectedState:
|
||||
{
|
||||
showStatusMessage(tr("[QmlEngine] disconnected.\n\n"));
|
||||
|
||||
delete m_engineQuery;
|
||||
m_engineQuery = 0;
|
||||
delete m_contextQuery;
|
||||
m_contextQuery = 0;
|
||||
|
||||
// resetViews();
|
||||
|
||||
// updateMenuActions();
|
||||
|
||||
break;
|
||||
}
|
||||
case QAbstractSocket::HostLookupState:
|
||||
showStatusMessage(tr("[QmlEngine] resolving host..."));
|
||||
break;
|
||||
case QAbstractSocket::ConnectingState:
|
||||
showStatusMessage(tr("[QmlEngine] connecting to debug server..."));
|
||||
break;
|
||||
case QAbstractSocket::ConnectedState:
|
||||
showStatusMessage(tr("[QmlEngine] connected.\n"));
|
||||
//setupConnection()
|
||||
break;
|
||||
case QAbstractSocket::ClosingState:
|
||||
showStatusMessage(tr("[QmlEngine] closing..."));
|
||||
break;
|
||||
case QAbstractSocket::BoundState:
|
||||
showStatusMessage(tr("[QmlEngine] bound state"));
|
||||
break;
|
||||
case QAbstractSocket::ListeningState:
|
||||
showStatusMessage(tr("[QmlEngine] listening state"));
|
||||
break;
|
||||
default:
|
||||
showStatusMessage(tr("[QmlEngine] unknown state: %1").arg(state));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void QmlEngine::connectionError()
|
||||
{
|
||||
QTC_ASSERT(m_conn, return);
|
||||
showStatusMessage(tr("[QmlEngine] error: (%1) %2", "%1=error code, %2=error message")
|
||||
.arg(m_conn->error()).arg(m_conn->errorString()));
|
||||
}
|
||||
|
||||
void QmlEngine::connectionConnected()
|
||||
{
|
||||
QTC_ASSERT(m_conn, return);
|
||||
showStatusMessage(tr("[QmlEngine] error: (%1) %2", "%1=error code, %2=error message")
|
||||
.arg(m_conn->error()).arg(m_conn->errorString()));
|
||||
}
|
||||
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Debugger
|
||||
|
||||
#include "qmlengine.moc"
|
||||
|
||||
@@ -36,14 +36,20 @@
|
||||
#include <QtCore/QHash>
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QPoint>
|
||||
#include <QtCore/QProcess>
|
||||
#include <QtCore/QQueue>
|
||||
#include <QtCore/QTimer>
|
||||
#include <QtCore/QVariant>
|
||||
|
||||
#include <QtNetwork/QAbstractSocket>
|
||||
#include <QtNetwork/QTcpSocket>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QTcpSocket;
|
||||
class QDeclarativeDebugConnection;
|
||||
class QDeclarativeEngineDebug;
|
||||
class QDeclarativeDebugEnginesQuery;
|
||||
class QDeclarativeDebugRootContextQuery;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace Debugger {
|
||||
@@ -52,6 +58,8 @@ namespace Internal {
|
||||
class ScriptAgent;
|
||||
class WatchData;
|
||||
class QmlResponse;
|
||||
class CanvasFrameRate;
|
||||
class QmlDebuggerClient;
|
||||
|
||||
class DEBUGGER_EXPORT QmlEngine : public DebuggerEngine
|
||||
{
|
||||
@@ -120,7 +128,22 @@ private:
|
||||
unsigned int debuggerCapabilities() const;
|
||||
|
||||
Q_SLOT void startDebugging();
|
||||
void setupConnection();
|
||||
|
||||
void sendMessage(const QByteArray &msg);
|
||||
|
||||
private slots:
|
||||
void handleProcFinished(int, QProcess::ExitStatus status);
|
||||
void handleProcError(QProcess::ProcessError error);
|
||||
void readProcStandardOutput();
|
||||
void readProcStandardError();
|
||||
|
||||
void connectionError();
|
||||
void connectionConnected();
|
||||
void connectionStateChanged();
|
||||
|
||||
private:
|
||||
QString errorMessage(QProcess::ProcessError error);
|
||||
typedef void (QmlEngine::*QmlCommandCallback)
|
||||
(const QmlResponse &record, const QVariant &cookie);
|
||||
|
||||
@@ -159,9 +182,13 @@ private:
|
||||
QTcpSocket *m_socket;
|
||||
QByteArray m_inbuffer;
|
||||
QList<QByteArray> m_services;
|
||||
QProcess m_proc;
|
||||
|
||||
signals:
|
||||
void sendMessage(const QByteArray &);
|
||||
QDeclarativeDebugConnection *m_conn;
|
||||
QmlDebuggerClient *m_client;
|
||||
QDeclarativeDebugEnginesQuery *m_engineQuery;
|
||||
QDeclarativeDebugRootContextQuery *m_contextQuery;
|
||||
CanvasFrameRate *m_frameRate;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
Reference in New Issue
Block a user