From 6ddbc147cadc4d450bb8e20cedf1b99e0fcbf894 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Fri, 22 May 2009 13:47:04 +1000 Subject: Store the type of the attached properties object --- src/declarative/qml/qmlmetatype.cpp | 14 +++- src/declarative/qml/qmlmetatype.h | 24 +++++-- src/declarative/qml/qmlprivate.h | 96 +++++++++++++++++----------- tests/auto/declarative/qmlparser/testtypes.h | 2 +- 4 files changed, 90 insertions(+), 46 deletions(-) diff --git a/src/declarative/qml/qmlmetatype.cpp b/src/declarative/qml/qmlmetatype.cpp index 2e490a4..6d44f7a 100644 --- a/src/declarative/qml/qmlmetatype.cpp +++ b/src/declarative/qml/qmlmetatype.cpp @@ -112,6 +112,7 @@ public: QmlPrivate::Func m_opFunc; const QMetaObject *m_baseMetaObject; QmlAttachedPropertiesFunc m_attachedPropertiesFunc; + const QMetaObject *m_attachedPropertiesType; int m_parserStatusCast; QmlPrivate::CreateFunc m_extFunc; const QMetaObject *m_extMetaObject; @@ -124,7 +125,7 @@ public: QmlTypePrivate::QmlTypePrivate() : m_isInterface(false), m_iid(0), m_typeId(0), m_listId(0), m_qmlListId(0), - m_opFunc(0), m_baseMetaObject(0), m_attachedPropertiesFunc(0), + m_opFunc(0), m_baseMetaObject(0), m_attachedPropertiesFunc(0), m_attachedPropertiesType(0), m_parserStatusCast(-1), m_extFunc(0), m_extMetaObject(0), m_index(-1), m_customParser(0), m_isSetup(false) { @@ -149,6 +150,7 @@ QmlType::QmlType(int type, int listType, int qmlListType, QmlPrivate::Func opFunc, const char *qmlName, const QMetaObject *metaObject, QmlAttachedPropertiesFunc attachedPropertiesFunc, + const QMetaObject *attachedType, int parserStatusCast, QmlPrivate::CreateFunc extFunc, const QMetaObject *extMetaObject, int index, QmlCustomParser *customParser) @@ -161,6 +163,7 @@ QmlType::QmlType(int type, int listType, int qmlListType, d->m_opFunc = opFunc; d->m_baseMetaObject = metaObject; d->m_attachedPropertiesFunc = attachedPropertiesFunc; + d->m_attachedPropertiesType = attachedType; d->m_parserStatusCast = parserStatusCast; d->m_extFunc = extFunc; d->m_index = index; @@ -348,6 +351,11 @@ QmlAttachedPropertiesFunc QmlType::attachedPropertiesFunction() const return d->m_attachedPropertiesFunc; } +const QMetaObject *QmlType::attachedPropertiesType() const +{ + return d->m_attachedPropertiesType; +} + int QmlType::parserStatusCast() const { return d->m_parserStatusCast; @@ -404,7 +412,7 @@ int QmlMetaType::registerInterface(const QmlPrivate::MetaTypeIds &id, return index; } -int QmlMetaType::registerType(const QmlPrivate::MetaTypeIds &id, QmlPrivate::Func func, const char *cname, const QMetaObject *mo, QmlAttachedPropertiesFunc attach, int pStatus, int object, QmlPrivate::CreateFunc extFunc, const QMetaObject *extmo, QmlCustomParser *parser) +int QmlMetaType::registerType(const QmlPrivate::MetaTypeIds &id, QmlPrivate::Func func, const char *cname, const QMetaObject *mo, QmlAttachedPropertiesFunc attach, const QMetaObject *attachMo, int pStatus, int object, QmlPrivate::CreateFunc extFunc, const QMetaObject *extmo, QmlCustomParser *parser) { Q_UNUSED(object); QWriteLocker lock(metaTypeDataLock()); @@ -421,7 +429,7 @@ int QmlMetaType::registerType(const QmlPrivate::MetaTypeIds &id, QmlPrivate::Fun int index = data->types.count(); QmlType *type = new QmlType(id.typeId, id.listId, id.qmlListId, - func, cname, mo, attach, pStatus, extFunc, + func, cname, mo, attach, attachMo, pStatus, extFunc, extmo, index, parser); data->types.append(type); diff --git a/src/declarative/qml/qmlmetatype.h b/src/declarative/qml/qmlmetatype.h index cc3887c..d10a0f0 100644 --- a/src/declarative/qml/qmlmetatype.h +++ b/src/declarative/qml/qmlmetatype.h @@ -59,7 +59,7 @@ class QmlCustomParser; class Q_DECLARATIVE_EXPORT QmlMetaType { public: - static int registerType(const QmlPrivate::MetaTypeIds &, QmlPrivate::Func, const char *, const QMetaObject *, QmlAttachedPropertiesFunc, int pStatus, int object, QmlPrivate::CreateFunc extFunc, const QMetaObject *extmo, QmlCustomParser *); + static int registerType(const QmlPrivate::MetaTypeIds &, QmlPrivate::Func, const char *, const QMetaObject *, QmlAttachedPropertiesFunc, const QMetaObject *, int pStatus, int object, QmlPrivate::CreateFunc extFunc, const QMetaObject *extmo, QmlCustomParser *); static int registerInterface(const QmlPrivate::MetaTypeIds &, QmlPrivate::Func, const char *); static bool copy(int type, void *data, const void *copy = 0); @@ -136,6 +136,7 @@ public: const QMetaObject *baseMetaObject() const; QmlAttachedPropertiesFunc attachedPropertiesFunction() const; + const QMetaObject *attachedPropertiesType() const; int parserStatusCast() const; QVariant fromObject(QObject *) const; @@ -146,7 +147,7 @@ private: friend class QmlMetaType; friend class QmlTypePrivate; QmlType(int, int, int, QmlPrivate::Func, const char *, int); - QmlType(int, int, int, QmlPrivate::Func, const char *, const QMetaObject *, QmlAttachedPropertiesFunc, int, QmlPrivate::CreateFunc, const QMetaObject *, int, QmlCustomParser *); + QmlType(int, int, int, QmlPrivate::Func, const char *, const QMetaObject *, QmlAttachedPropertiesFunc, const QMetaObject *, int, QmlPrivate::CreateFunc, const QMetaObject *, int, QmlCustomParser *); ~QmlType(); QmlTypePrivate *d; @@ -165,6 +166,7 @@ int qmlRegisterType(const char *typeName) return QmlMetaType::registerType(ids, QmlPrivate::list_nocreate_op, 0, &T::staticMetaObject, QmlPrivate::attachedPropertiesFunc(), + QmlPrivate::attachedPropertiesMetaObject(), QmlPrivate::StaticCastSelector::cast(), QmlPrivate::StaticCastSelector::cast(), 0, 0, 0); @@ -183,6 +185,7 @@ int qmlRegisterType(const char *qmlName, const char *typeName) return QmlMetaType::registerType(ids, QmlPrivate::list_op, qmlName, &T::staticMetaObject, QmlPrivate::attachedPropertiesFunc(), + QmlPrivate::attachedPropertiesMetaObject(), QmlPrivate::StaticCastSelector::cast(), QmlPrivate::StaticCastSelector::cast(), 0, 0, 0); @@ -200,11 +203,15 @@ int qmlRegisterExtendedType(const char *typeName) QmlAttachedPropertiesFunc attached = QmlPrivate::attachedPropertiesFunc(); - if (!attached) + const QMetaObject * attachedMo = + QmlPrivate::attachedPropertiesMetaObject(); + if (!attached) { attached = QmlPrivate::attachedPropertiesFunc(); + attachedMo = QmlPrivate::attachedPropertiesMetaObject(); + } return QmlMetaType::registerType(ids, QmlPrivate::list_nocreate_op, 0, - &T::staticMetaObject, attached, + &T::staticMetaObject, attached, attachedMo, QmlPrivate::StaticCastSelector::cast(), QmlPrivate::StaticCastSelector::cast(), &QmlPrivate::CreateParent::create, &E::staticMetaObject, 0); @@ -222,13 +229,17 @@ int qmlRegisterExtendedType(const char *qmlName, const char *typeName) QmlAttachedPropertiesFunc attached = QmlPrivate::attachedPropertiesFunc(); - if (!attached) + const QMetaObject * attachedMo = + QmlPrivate::attachedPropertiesMetaObject(); + if (!attached) { attached = QmlPrivate::attachedPropertiesFunc(); + attachedMo = QmlPrivate::attachedPropertiesMetaObject(); + } return QmlMetaType::registerType(ids, QmlPrivate::list_op, qmlName, &T::staticMetaObject, - attached, + attached, attachedMo, QmlPrivate::StaticCastSelector::cast(), QmlPrivate::StaticCastSelector::cast(), &QmlPrivate::CreateParent::create, @@ -263,6 +274,7 @@ int qmlRegisterCustomType(const char *qmlName, const char *typeName, QmlCustomPa return QmlMetaType::registerType(ids, QmlPrivate::list_op, qmlName, &T::staticMetaObject, QmlPrivate::attachedPropertiesFunc(), + QmlPrivate::attachedPropertiesMetaObject(), QmlPrivate::StaticCastSelector::cast(), QmlPrivate::StaticCastSelector::cast(), 0, 0, parser); diff --git a/src/declarative/qml/qmlprivate.h b/src/declarative/qml/qmlprivate.h index 590e0c0..2a9c503 100644 --- a/src/declarative/qml/qmlprivate.h +++ b/src/declarative/qml/qmlprivate.h @@ -123,57 +123,81 @@ namespace QmlPrivate } }; - template - struct AttachedPropertySelector - { - static inline QmlAttachedPropertiesFunc func() - { - return 0; - } - }; - template - struct AttachedPropertySelector - { - static inline QmlAttachedPropertiesFunc func() - { - return &T::qmlAttachedProperties; - } - }; - - template < typename T > - class has_attachedProperties { + template + class has_attachedPropertiesMember + { typedef int yes_type; typedef char no_type; + template + struct Selector {}; - template - struct dummy {}; - - template - struct dummy_const {}; - - template - struct dummy_static {}; + template + static yes_type test(Selector*); - template - static no_type check(dummy *); + template + static no_type test(...); - template - static no_type check(dummy_const *); + public: + static bool const value = sizeof(test(0)) == sizeof(yes_type); + }; - template - static yes_type check(dummy_static *); + template + class has_attachedPropertiesMethod + { + typedef int yes_type; + typedef char no_type; - template + template + static yes_type check(ReturnType *(*)(QObject *)); static no_type check(...); public: - static bool const value = sizeof(check(0)) == sizeof(yes_type); + static bool const value = sizeof(check(&T::qmlAttachedProperties)) == sizeof(yes_type); }; + template + class has_attachedPropertiesMethod + { + public: + static bool const value = false; + }; + + template + class AttachedPropertySelector + { + public: + static inline QmlAttachedPropertiesFunc func() { return 0; } + static inline const QMetaObject *metaObject() { return 0; } + }; + template + class AttachedPropertySelector + { + static inline QObject *attachedProperties(QObject *obj) { + return T::qmlAttachedProperties(obj); + } + template + static inline const QMetaObject *attachedPropertiesMetaObject(ReturnType *(*)(QObject *)) { + return &ReturnType::staticMetaObject; + } + public: + static inline QmlAttachedPropertiesFunc func() { + return &attachedProperties; + } + static inline const QMetaObject *metaObject() { + return attachedPropertiesMetaObject(&T::qmlAttachedProperties); + } + }; + template inline QmlAttachedPropertiesFunc attachedPropertiesFunc() { - return AttachedPropertySelector::value>::func(); + return AttachedPropertySelector::value>::value>::func(); + } + + template + inline const QMetaObject *attachedPropertiesMetaObject() + { + return AttachedPropertySelector::value>::value>::metaObject(); } struct MetaTypeIds { diff --git a/tests/auto/declarative/qmlparser/testtypes.h b/tests/auto/declarative/qmlparser/testtypes.h index c1f85b9..e124631 100644 --- a/tests/auto/declarative/qmlparser/testtypes.h +++ b/tests/auto/declarative/qmlparser/testtypes.h @@ -66,7 +66,7 @@ public: MyInterface *interface() const { return m_interface; } void setInterface(MyInterface *iface) { m_interface = iface; } - static QObject *qmlAttachedProperties(QObject *other) { + static MyQmlObject *qmlAttachedProperties(QObject *other) { MyQmlObject *rv = new MyQmlObject; rv->setParent(other); return rv; -- cgit v0.12 From ce49990c3764304e76b4d2c1705fcad677ec9f73 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Fri, 22 May 2009 15:38:57 +1000 Subject: Add canvas framerate monitor application --- src/declarative/canvas/monitor/main.cpp | 287 +++++++++++++++++++++++++ src/declarative/canvas/monitor/monitor.pro | 8 + src/declarative/canvas/qsimplecanvasserver.cpp | 31 ++- src/declarative/canvas/qsimplecanvasserver_p.h | 4 + 4 files changed, 328 insertions(+), 2 deletions(-) create mode 100644 src/declarative/canvas/monitor/main.cpp create mode 100644 src/declarative/canvas/monitor/monitor.pro diff --git a/src/declarative/canvas/monitor/main.cpp b/src/declarative/canvas/monitor/main.cpp new file mode 100644 index 0000000..f5f40bd --- /dev/null +++ b/src/declarative/canvas/monitor/main.cpp @@ -0,0 +1,287 @@ +#include +#include +#include +#include +#include + +class QLineGraph : public QWidget +{ +Q_OBJECT +public: + QLineGraph(QWidget * = 0); + + void setPosition(int); + +public slots: + void addSample(int, int, int, int, bool); + +protected: + virtual void paintEvent(QPaintEvent *); + virtual void mousePressEvent(QMouseEvent *); + virtual void resizeEvent(QResizeEvent *); + virtual void showEvent(QShowEvent *); + +private slots: + void scrollbarChanged(int); + +private: + void positionScrollbar(); + void updateScrollbar(); + void drawSample(QPainter *, int, const QRect &); + void drawTime(QPainter *, const QRect &); + struct Sample { + int sample[4]; + bool isBreak; + }; + QList _samples; + + QScrollBar sb; + int position; + int samplesPerWidth; + int resolutionForHeight; + bool ignoreScroll; +}; + +QLineGraph::QLineGraph(QWidget *parent) +: QWidget(parent), sb(Qt::Horizontal, this), position(-1), samplesPerWidth(99), resolutionForHeight(50), ignoreScroll(false) +{ + sb.setMaximum(0); + sb.setMinimum(0); + sb.setSingleStep(1); + + QObject::connect(&sb, SIGNAL(valueChanged(int)), this, SLOT(scrollbarChanged(int))); +} + +void QLineGraph::scrollbarChanged(int v) +{ + if(ignoreScroll) + return; + + position = v; + update(); +} + +void QLineGraph::positionScrollbar() +{ + sb.setFixedWidth(width()); + sb.move(0, height() - sb.height()); +} + +void QLineGraph::resizeEvent(QResizeEvent *e) +{ + QWidget::resizeEvent(e); + positionScrollbar(); +} + +void QLineGraph::showEvent(QShowEvent *e) +{ + QWidget::showEvent(e); + positionScrollbar(); +} + +void QLineGraph::mousePressEvent(QMouseEvent *) +{ + if(position == -1) { + position = qMax(0, _samples.count() - samplesPerWidth - 1); + } else { + position = -1; + } + update(); +} + +void QLineGraph::updateScrollbar() +{ + ignoreScroll = true; + sb.setMaximum(qMax(0, _samples.count() - samplesPerWidth - 1)); + + if(position == -1) { + sb.setValue(sb.maximum()); + } else { + sb.setValue(position); + } + ignoreScroll = false; +} + +void QLineGraph::addSample(int a, int b, int c, int d, bool isBreak) +{ + Sample s; + s.isBreak = isBreak; + s.sample[0] = a; + s.sample[1] = b; + s.sample[2] = c; + s.sample[3] = d; + _samples << s; + updateScrollbar(); + update(); +} + +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[3] / 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[3])); + + t = sampleTime; + } + } + +} + +void QLineGraph::drawSample(QPainter *p, int s, 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 scaleY = 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)) + p->drawRect(QRect(lastXEnd, yEnd, scaleX, _samples.at(ii).sample[s] * scaleY)); + + lastXEnd = xEnd; + } + p->restore(); +} + +void QLineGraph::paintEvent(QPaintEvent *) +{ + QPainter p(this); + p.setRenderHint(QPainter::Antialiasing); + + + QRect r(50, 10, width() - 60, height() - 60); + p.setBrush(QColor("lightsteelblue")); + drawSample(&p, 0, r); + + p.setBrush(QColor("pink")); + drawSample(&p, 1, r); + + p.setBrush(QColor("green")); + drawSample(&p, 2, r); + + p.setBrush(Qt::NoBrush); + p.drawRect(r); + + 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); +} + +class MyReader : public QObject +{ +Q_OBJECT +public: + MyReader(const QString &host, int port); + +signals: + void sample(int, int, int, int, bool); + +private slots: + void readyRead(); + +private: + QTcpSocket *socket; + + int la; + int lb; + int ld; +}; + +MyReader::MyReader(const QString &host, int port) +: socket(0), la(-1) +{ + socket = new QTcpSocket(this); + QObject::connect(socket, SIGNAL(readyRead()), this, SLOT(readyRead())); + socket->connectToHost(host, port); + socket->waitForConnected(); +} + +void MyReader::readyRead() +{ + static int la = -1; + static int lb; + static int ld; + + if(socket->canReadLine()) { + QString line = socket->readLine(); + + int a; + int b; + int c; + int d; + int isBreak; + sscanf(line.toLatin1().constData(), "%d %d %d %d %d", &a, &b, &c, &d, &isBreak); + + if (la != -1) + emit sample(c, lb, la, ld, isBreak); + + la = a; + lb = b; + ld = d; + } +} + +int main(int argc, char ** argv) +{ + if(argc != 3) { + qWarning() << "Usage:" << argv[0] << "host port"; + return -1; + } + + QApplication app(argc, argv); + + MyReader reader(argv[1], atoi(argv[2])); + + QLineGraph graph; + QObject::connect(&reader, SIGNAL(sample(int,int,int,int,bool)), &graph, SLOT(addSample(int,int,int,int,bool))); + graph.setFixedSize(800, 600); + graph.show(); + + return app.exec(); +} + +#include "main.moc" diff --git a/src/declarative/canvas/monitor/monitor.pro b/src/declarative/canvas/monitor/monitor.pro new file mode 100644 index 0000000..e3b0a29 --- /dev/null +++ b/src/declarative/canvas/monitor/monitor.pro @@ -0,0 +1,8 @@ +TEMPLATE = app +TARGET = +DEPENDPATH += . +INCLUDEPATH += . +QT += network + +# Input +SOURCES += main.cpp diff --git a/src/declarative/canvas/qsimplecanvasserver.cpp b/src/declarative/canvas/qsimplecanvasserver.cpp index 4d4adda..ed781b8 100644 --- a/src/declarative/canvas/qsimplecanvasserver.cpp +++ b/src/declarative/canvas/qsimplecanvasserver.cpp @@ -44,17 +44,37 @@ #ifndef Q_OS_WIN32 #include #endif +#include QT_BEGIN_NAMESPACE +class FrameBreakAnimation : public QAbstractAnimation +{ +public: + FrameBreakAnimation(QSimpleCanvasServer *s) + : QAbstractAnimation(s), server(s) + { + start(); + } + + virtual int duration() const { return -1; } + virtual void updateCurrentTime(int msecs) { + server->frameBreak(); + } + +private: + QSimpleCanvasServer *server; +}; + QSimpleCanvasServer::QSimpleCanvasServer(int port, QObject *parent) -: QObject(parent), _tcpServer(new QTcpServer(this)) +: QObject(parent), _breaks(0), _tcpServer(new QTcpServer(this)) { QObject::connect(_tcpServer, SIGNAL(newConnection()), this, SLOT(newConnection())); _time.start(); + new FrameBreakAnimation(this); if (!_tcpServer->listen(QHostAddress::Any, port)) { qWarning() << "QSimpleCanvasServer: Cannot listen on port" << port; return; @@ -80,8 +100,10 @@ void QSimpleCanvasServer::addTiming(quint32 paint, data[2] = ::htonl(timeBetweenFrames); */ + bool isFrameBreak = _breaks > 1; + _breaks = 0; int e = _time.elapsed(); - QString d = QString::number(paint) + QLatin1String(" ") + QString::number(repaint) + QLatin1String(" ") + QString::number(timeBetweenFrames) + QLatin1String(" ") + QString::number(e) + QLatin1String("\n"); + QString d = QString::number(paint) + QLatin1String(" ") + QString::number(repaint) + QLatin1String(" ") + QString::number(timeBetweenFrames) + QLatin1String(" ") + QString::number(e) + QLatin1String(" ") + QString::number(isFrameBreak) + QLatin1String("\n"); QByteArray ba = d.toLatin1(); // XXX @@ -90,6 +112,11 @@ void QSimpleCanvasServer::addTiming(quint32 paint, _tcpClients.at(ii)->write(ba.constData(), ba.length()); } +void QSimpleCanvasServer::frameBreak() +{ + _breaks++; +} + void QSimpleCanvasServer::disconnected() { QTcpSocket *socket = static_cast(sender()); diff --git a/src/declarative/canvas/qsimplecanvasserver_p.h b/src/declarative/canvas/qsimplecanvasserver_p.h index 7d53357..ce04e8d 100644 --- a/src/declarative/canvas/qsimplecanvasserver_p.h +++ b/src/declarative/canvas/qsimplecanvasserver_p.h @@ -62,6 +62,10 @@ private Q_SLOTS: void disconnected(); private: + friend class FrameBreakAnimation; + void frameBreak(); + int _breaks; + QTcpServer *_tcpServer; QList _tcpClients; QTime _time; -- cgit v0.12