From 809244977033abf2bd934244c9b88b39d8ba1f8a Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Tue, 27 Oct 2009 11:41:49 +1000 Subject: Error when a QVariant property is used as a grouped property This crashed as the metatype of QVariant is -1. --- src/declarative/qml/qmlcompiler.cpp | 2 +- .../qmllanguage/data/invalidGroupedProperty.1.errors.txt | 1 + .../auto/declarative/qmllanguage/data/invalidGroupedProperty.1.qml | 6 ++++++ .../qmllanguage/data/invalidGroupedProperty.2.errors.txt | 1 + .../auto/declarative/qmllanguage/data/invalidGroupedProperty.2.qml | 7 +++++++ tests/auto/declarative/qmllanguage/tst_qmllanguage.cpp | 7 +++++-- 6 files changed, 21 insertions(+), 3 deletions(-) create mode 100644 tests/auto/declarative/qmllanguage/data/invalidGroupedProperty.1.errors.txt create mode 100644 tests/auto/declarative/qmllanguage/data/invalidGroupedProperty.1.qml create mode 100644 tests/auto/declarative/qmllanguage/data/invalidGroupedProperty.2.errors.txt create mode 100644 tests/auto/declarative/qmllanguage/data/invalidGroupedProperty.2.qml diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp index 69ebf9c..60282dc 100644 --- a/src/declarative/qml/qmlcompiler.cpp +++ b/src/declarative/qml/qmlcompiler.cpp @@ -1687,7 +1687,7 @@ bool QmlCompiler::buildGroupedProperty(QmlParser::Property *prop, if (prop->type < (int)QVariant::UserType) { QmlEnginePrivate *ep = static_cast(QObjectPrivate::get(engine)); - if (ep->valueTypes[prop->type]) { + if (prop->type >= 0 /* QVariant == -1 */ && ep->valueTypes[prop->type]) { COMPILE_CHECK(buildValueTypeProperty(ep->valueTypes[prop->type], prop->value, obj, ctxt.incr())); obj->addValueTypeProperty(prop); diff --git a/tests/auto/declarative/qmllanguage/data/invalidGroupedProperty.1.errors.txt b/tests/auto/declarative/qmllanguage/data/invalidGroupedProperty.1.errors.txt new file mode 100644 index 0000000..7c00ce4 --- /dev/null +++ b/tests/auto/declarative/qmllanguage/data/invalidGroupedProperty.1.errors.txt @@ -0,0 +1 @@ +5:5:Invalid property access diff --git a/tests/auto/declarative/qmllanguage/data/invalidGroupedProperty.1.qml b/tests/auto/declarative/qmllanguage/data/invalidGroupedProperty.1.qml new file mode 100644 index 0000000..5e95c48 --- /dev/null +++ b/tests/auto/declarative/qmllanguage/data/invalidGroupedProperty.1.qml @@ -0,0 +1,6 @@ +import Qt 4.6 + +Object { + property var o; + o.blah: 10 +} diff --git a/tests/auto/declarative/qmllanguage/data/invalidGroupedProperty.2.errors.txt b/tests/auto/declarative/qmllanguage/data/invalidGroupedProperty.2.errors.txt new file mode 100644 index 0000000..7c00ce4 --- /dev/null +++ b/tests/auto/declarative/qmllanguage/data/invalidGroupedProperty.2.errors.txt @@ -0,0 +1 @@ +5:5:Invalid property access diff --git a/tests/auto/declarative/qmllanguage/data/invalidGroupedProperty.2.qml b/tests/auto/declarative/qmllanguage/data/invalidGroupedProperty.2.qml new file mode 100644 index 0000000..b11d34c --- /dev/null +++ b/tests/auto/declarative/qmllanguage/data/invalidGroupedProperty.2.qml @@ -0,0 +1,7 @@ +import Qt 4.6 + +Object { + property int o; + o.blah: 10 +} + diff --git a/tests/auto/declarative/qmllanguage/tst_qmllanguage.cpp b/tests/auto/declarative/qmllanguage/tst_qmllanguage.cpp index d51bbcc..4bc02c0 100644 --- a/tests/auto/declarative/qmllanguage/tst_qmllanguage.cpp +++ b/tests/auto/declarative/qmllanguage/tst_qmllanguage.cpp @@ -180,7 +180,6 @@ void tst_qmllanguage::errors_data() QTest::newRow("invalidID.5") << "invalidID.5.qml" << "invalidID.5.errors.txt" << false; QTest::newRow("invalidID.6") << "invalidID.6.qml" << "invalidID.6.errors.txt" << false; - QTest::newRow("unsupportedProperty") << "unsupportedProperty.qml" << "unsupportedProperty.errors.txt" << false; QTest::newRow("nullDotProperty") << "nullDotProperty.qml" << "nullDotProperty.errors.txt" << true; QTest::newRow("fakeDotProperty") << "fakeDotProperty.qml" << "fakeDotProperty.errors.txt" << false; @@ -191,12 +190,16 @@ void tst_qmllanguage::errors_data() QTest::newRow("failingComponent") << "failingComponentTest.qml" << "failingComponent.errors.txt" << false; QTest::newRow("missingSignal") << "missingSignal.qml" << "missingSignal.errors.txt" << false; QTest::newRow("finalOverride") << "finalOverride.qml" << "finalOverride.errors.txt" << false; + QTest::newRow("customParserIdNotAllowed") << "customParserIdNotAllowed.qml" << "customParserIdNotAllowed.errors.txt" << false; + QTest::newRow("invalidGroupedProperty.1") << "invalidGroupedProperty.1.qml" << "invalidGroupedProperty.1.errors.txt" << false; + QTest::newRow("invalidGroupedProperty.2") << "invalidGroupedProperty.2.qml" << "invalidGroupedProperty.2.errors.txt" << false; QTest::newRow("importNamespaceConflict") << "importNamespaceConflict.qml" << "importNamespaceConflict.errors.txt" << false; QTest::newRow("importVersionMissing (builtin)") << "importVersionMissingBuiltIn.qml" << "importVersionMissingBuiltIn.errors.txt" << false; QTest::newRow("importVersionMissing (installed)") << "importVersionMissingInstalled.qml" << "importVersionMissingInstalled.errors.txt" << false; - QTest::newRow("customParserIdNotAllowed") << "customParserIdNotAllowed.qml" << "customParserIdNotAllowed.errors.txt" << false; + + } void tst_qmllanguage::errors() -- cgit v0.12 From baedccfc09c3a95a7a900318cf384fd8a03e3eeb Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Tue, 27 Oct 2009 11:47:16 +1000 Subject: Improve highlight range API and fix incorrect list end calc. --- examples/declarative/focusscope/test3.qml | 4 +- examples/declarative/listview/itemlist.qml | 4 +- examples/declarative/listview/listview.qml | 7 ++-- examples/declarative/parallax/ParallaxView.qml | 19 +-------- examples/declarative/parallax/parallax.qml | 49 +++++++++++----------- src/declarative/fx/qfxlistview.cpp | 57 +++++++++++++++----------- src/declarative/fx/qfxlistview.h | 8 ++-- 7 files changed, 70 insertions(+), 78 deletions(-) diff --git a/examples/declarative/focusscope/test3.qml b/examples/declarative/focusscope/test3.qml index e5aa7b6..1b3181b 100644 --- a/examples/declarative/focusscope/test3.qml +++ b/examples/declarative/focusscope/test3.qml @@ -40,8 +40,8 @@ Rectangle { model: model delegate: verticalDelegate preferredHighlightBegin: 100 - preferredHighlightEnd: 101 - strictlyEnforceHighlightRange: true + preferredHighlightEnd: 100 + highlightRangeMode: "StrictlyEnforceRange" } diff --git a/examples/declarative/listview/itemlist.qml b/examples/declarative/listview/itemlist.qml index 6dfc90b..77f5c2d 100644 --- a/examples/declarative/listview/itemlist.qml +++ b/examples/declarative/listview/itemlist.qml @@ -30,8 +30,8 @@ Rectangle { anchors.bottomMargin: 30 model: itemModel preferredHighlightBegin: 0 - preferredHighlightEnd: 1 - strictlyEnforceHighlightRange: true + preferredHighlightEnd: 0 + highlightRangeMode: "StrictlyEnforceRange" orientation: "Horizontal" } diff --git a/examples/declarative/listview/listview.qml b/examples/declarative/listview/listview.qml index 98974fd..b614904 100644 --- a/examples/declarative/listview/listview.qml +++ b/examples/declarative/listview/listview.qml @@ -41,7 +41,7 @@ Rectangle { // current item within the the bounds of the range, however // items will not scroll beyond the beginning or end of the view, // forcing the highlight to move outside the range at the ends. - // The third list sets strictlyEnforceHighlightRange to true + // The third list sets the highlightRangeMode to StrictlyEnforceRange // and sets a range smaller than the height of an item. This // forces the current item to change when the view is flicked, // since the highlight is unable to move. @@ -61,6 +61,7 @@ Rectangle { model: MyPetsModel; delegate: petDelegate; highlight: petHighlight preferredHighlightBegin: 80 preferredHighlightEnd: 220 + highlightRangeMode: "ApplyRange" currentIndex: list1.currentIndex } ListView { @@ -69,7 +70,7 @@ Rectangle { model: MyPetsModel; delegate: petDelegate; highlight: petHighlight currentIndex: list1.currentIndex preferredHighlightBegin: 125 - preferredHighlightEnd: 126 - strictlyEnforceHighlightRange: true + preferredHighlightEnd: 125 + highlightRangeMode: "StrictlyEnforceRange" } } diff --git a/examples/declarative/parallax/ParallaxView.qml b/examples/declarative/parallax/ParallaxView.qml index 4ddab00..38bb8c0 100644 --- a/examples/declarative/parallax/ParallaxView.qml +++ b/examples/declarative/parallax/ParallaxView.qml @@ -10,7 +10,6 @@ Item { width: Math.max(list.viewportWidth, parent.width) } - /* default property alias content: visualModel.children ListView { id: list @@ -21,21 +20,7 @@ Item { highlight: Item { height: 1; width: 1} preferredHighlightBegin: 0 - preferredHighlightEnd: 1 - strictlyEnforceHighlightRange: true - } - */ - - default property alias content: flickArea.data - Flickable { - id: list - anchors.fill: parent - overShoot: false - viewportWidth: flickArea.width - - Item { - id: flickArea - width: childrenRect.width - } + preferredHighlightEnd: 0 + highlightRangeMode: "StrictlyEnforceRange" } } diff --git a/examples/declarative/parallax/parallax.qml b/examples/declarative/parallax/parallax.qml index 9adcfd7..b2139ec 100644 --- a/examples/declarative/parallax/parallax.qml +++ b/examples/declarative/parallax/parallax.qml @@ -9,37 +9,34 @@ Rectangle { anchors.fill: parent background: "pics/background.jpg" - Row { - Item { - width: 320 - height: 480 - - Clock { - anchors.centerIn: parent - } + Item { + width: 320 + height: 480 + + Clock { + anchors.centerIn: parent } + } - Item { - width: 320 - height: 480 + Item { + width: 320 + height: 480 - Smiley {} - } + Smiley {} + } - Item { - width: 320 - height: 480 - - Loader { - anchors.centerIn: parent - width: 300; height: 460 - clip: true - resizeMode: Loader.SizeItemToLoader - - source: "../../../demos/declarative/samegame/samegame.qml" - } + Item { + width: 320 + height: 480 + + Loader { + anchors.centerIn: parent + width: 300; height: 460 + clip: true + resizeMode: Loader.SizeItemToLoader + + source: "../../../demos/declarative/samegame/samegame.qml" } - } } diff --git a/src/declarative/fx/qfxlistview.cpp b/src/declarative/fx/qfxlistview.cpp index 1a4a60c..28d2bb2 100644 --- a/src/declarative/fx/qfxlistview.cpp +++ b/src/declarative/fx/qfxlistview.cpp @@ -176,9 +176,9 @@ public: , highlightRangeStart(0), highlightRangeEnd(0) , highlightComponent(0), highlight(0), trackedItem(0) , moveReason(Other), buffer(0), highlightPosAnimator(0), highlightSizeAnimator(0), spacing(0.0) - , highlightMoveSpeed(400), highlightResizeSpeed(400) + , highlightMoveSpeed(400), highlightResizeSpeed(400), highlightRange(QFxListView::NoHighlightRange) , ownModel(false), wrap(false), autoHighlight(true) - , haveHighlightRange(false), strictHighlightRange(false) + , haveHighlightRange(false) {} void init(); @@ -392,12 +392,12 @@ public: qreal spacing; qreal highlightMoveSpeed; qreal highlightResizeSpeed; + QFxListView::HighlightRangeMode highlightRange; bool ownModel : 1; bool wrap : 1; bool autoHighlight : 1; bool haveHighlightRange : 1; - bool strictHighlightRange : 1; }; void QFxListViewPrivate::init() @@ -798,7 +798,7 @@ void QFxListViewPrivate::fixupY() if (orient == Qt::Horizontal) return; - if (haveHighlightRange && strictHighlightRange) { + if (haveHighlightRange && highlightRange == QFxListView::StrictlyEnforceRange) { if (currentItem && highlight && currentItem->position() != highlight->position()) { moveReason = Mouse; timeline.clear(); @@ -813,7 +813,7 @@ void QFxListViewPrivate::fixupX() if (orient == Qt::Vertical) return; - if (haveHighlightRange && strictHighlightRange) { + if (haveHighlightRange && highlightRange == QFxListView::StrictlyEnforceRange) { if (currentItem && highlight && currentItem->position() != highlight->position()) { moveReason = Mouse; timeline.clear(); @@ -1141,19 +1141,25 @@ void QFxListView::setHighlightFollowsCurrentItem(bool autoHighlight) /*! \qmlproperty real ListView::preferredHighlightBegin \qmlproperty real ListView::preferredHighlightEnd - \qmlproperty bool ListView::strictlyEnforceHighlightRange + \qmlproperty bool ListView::highlightRangeMode These properties set the preferred range of the highlight (current item) within the view. - If the strictlyEnforceHighlightRange property is false (default) + If highlightRangeMode is set to \e ApplyRange the view will + attempt to maintain the highlight within the range, however the highlight can move outside of the range at the ends of the list or due to a mouse interaction. - If strictlyEnforceHighlightRange is true then the highlight will never - move outside the range. This means that the current item will change + If highlightRangeMode is set to \e StrictlyEnforceRange the highlight will never + move outside of the range. This means that the current item will change if a keyboard or mouse action would cause the highlight to move outside of the range. + + The default value is \e NoHighlightRange. + + Note that a valid range requires preferredHighlightEnd to be greater + than or equal to preferredHighlightBegin. */ qreal QFxListView::preferredHighlightBegin() const { @@ -1165,7 +1171,7 @@ void QFxListView::setPreferredHighlightBegin(qreal start) { Q_D(QFxListView); d->highlightRangeStart = start; - d->haveHighlightRange = d->highlightRangeStart < d->highlightRangeEnd; + d->haveHighlightRange = d->highlightRange != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd; } qreal QFxListView::preferredHighlightEnd() const @@ -1178,19 +1184,20 @@ void QFxListView::setPreferredHighlightEnd(qreal end) { Q_D(QFxListView); d->highlightRangeEnd = end; - d->haveHighlightRange = d->highlightRangeStart < d->highlightRangeEnd; + d->haveHighlightRange = d->highlightRange != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd; } -bool QFxListView::strictlyEnforceHighlightRange() const +QFxListView::HighlightRangeMode QFxListView::highlightRangeMode() const { Q_D(const QFxListView); - return d->strictHighlightRange; + return d->highlightRange; } -void QFxListView::setStrictlyEnforceHighlightRange(bool strict) +void QFxListView::setHighlightRangeMode(HighlightRangeMode mode) { Q_D(QFxListView); - d->strictHighlightRange = strict; + d->highlightRange = mode; + d->haveHighlightRange = d->highlightRange != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd; } /*! @@ -1375,14 +1382,14 @@ void QFxListView::viewportMoved() if (isFlicking() || d->pressed) d->moveReason = QFxListViewPrivate::Mouse; if (d->moveReason == QFxListViewPrivate::Mouse) { - if (d->haveHighlightRange && d->strictHighlightRange && d->highlight) { + if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange && d->highlight) { int idx = d->snapIndex(); if (idx >= 0 && idx != d->currentIndex) d->updateCurrent(idx); qreal pos = d->currentItem->position(); - if (pos > d->position() + d->highlightRangeEnd - d->highlight->size()) - pos = d->position() + d->highlightRangeEnd - d->highlight->size(); + if (pos > d->position() + d->highlightRangeEnd - 1 - d->highlight->size()) + pos = d->position() + d->highlightRangeEnd - 1 - d->highlight->size(); if (pos < d->position() + d->highlightRangeStart) pos = d->position() + d->highlightRangeStart; d->highlight->setPosition(pos); @@ -1396,7 +1403,7 @@ qreal QFxListView::minYExtent() const if (d->orient == Qt::Horizontal) return QFxFlickable::minYExtent(); qreal extent = -d->startPosition(); - if (d->haveHighlightRange && d->strictHighlightRange) + if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) extent += d->highlightRangeStart; return extent; @@ -1408,8 +1415,8 @@ qreal QFxListView::maxYExtent() const if (d->orient == Qt::Horizontal) return QFxFlickable::maxYExtent(); qreal extent; - if (d->haveHighlightRange && d->strictHighlightRange) - extent = -(d->endPosition() - d->highlightRangeEnd); + if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) + extent = -(d->positionAt(count()-1) - d->highlightRangeEnd); else extent = -(d->endPosition() - height()); qreal minY = minYExtent(); @@ -1424,7 +1431,7 @@ qreal QFxListView::minXExtent() const if (d->orient == Qt::Vertical) return QFxFlickable::minXExtent(); qreal extent = -d->startPosition(); - if (d->haveHighlightRange && d->strictHighlightRange) + if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) extent += d->highlightRangeStart; return extent; @@ -1436,8 +1443,8 @@ qreal QFxListView::maxXExtent() const if (d->orient == Qt::Vertical) return QFxFlickable::maxXExtent(); qreal extent; - if (d->haveHighlightRange && d->strictHighlightRange) - extent = -(d->endPosition() - d->highlightRangeEnd); + if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) + extent = -(d->positionAt(count()-1) - d->highlightRangeEnd); else extent = -(d->endPosition() - width()); qreal minX = minXExtent(); @@ -1536,7 +1543,7 @@ void QFxListView::trackedPositionChanged() if (!isFlicking() && !d->pressed && d->moveReason != QFxListViewPrivate::Mouse) { const qreal trackedPos = d->trackedItem->position(); if (d->haveHighlightRange) { - if (d->strictHighlightRange) { + if (d->highlightRange == StrictlyEnforceRange) { qreal pos = d->position(); if (trackedPos > pos + d->highlightRangeEnd - d->trackedItem->size()) pos = trackedPos - d->highlightRangeEnd + d->trackedItem->size(); diff --git a/src/declarative/fx/qfxlistview.h b/src/declarative/fx/qfxlistview.h index 1ff0e27..0fa0fa0 100644 --- a/src/declarative/fx/qfxlistview.h +++ b/src/declarative/fx/qfxlistview.h @@ -69,7 +69,7 @@ class Q_DECLARATIVE_EXPORT QFxListView : public QFxFlickable Q_PROPERTY(qreal preferredHighlightBegin READ preferredHighlightBegin WRITE setPreferredHighlightBegin) Q_PROPERTY(qreal preferredHighlightEnd READ preferredHighlightEnd WRITE setPreferredHighlightEnd) - Q_PROPERTY(bool strictlyEnforceHighlightRange READ strictlyEnforceHighlightRange WRITE setStrictlyEnforceHighlightRange) + Q_PROPERTY(HighlightRangeMode highlightRangeMode READ highlightRangeMode WRITE setHighlightRangeMode) Q_PROPERTY(qreal spacing READ spacing WRITE setSpacing NOTIFY spacingChanged) Q_PROPERTY(Qt::Orientation orientation READ orientation WRITE setOrientation NOTIFY orientationChanged) @@ -80,6 +80,7 @@ class Q_DECLARATIVE_EXPORT QFxListView : public QFxFlickable Q_PROPERTY(qreal highlightMoveSpeed READ highlightMoveSpeed WRITE setHighlightMoveSpeed NOTIFY highlightMoveSpeedChanged) Q_PROPERTY(qreal highlightResizeSpeed READ highlightResizeSpeed WRITE setHighlightResizeSpeed NOTIFY highlightResizeSpeedChanged) + Q_ENUMS(HighlightRangeMode) Q_CLASSINFO("DefaultProperty", "data") public: @@ -104,8 +105,9 @@ public: bool highlightFollowsCurrentItem() const; void setHighlightFollowsCurrentItem(bool); - bool strictlyEnforceHighlightRange() const; - void setStrictlyEnforceHighlightRange(bool strict); + enum HighlightRangeMode { NoHighlightRange, ApplyRange, StrictlyEnforceRange }; + HighlightRangeMode highlightRangeMode() const; + void setHighlightRangeMode(HighlightRangeMode mode); qreal preferredHighlightBegin() const; void setPreferredHighlightBegin(qreal); -- cgit v0.12 From b214f0da048a71cd7da410c32c111d3b92cbca47 Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Tue, 27 Oct 2009 13:07:33 +1000 Subject: Fix dragging at the end of a flickable with overShoot: false --- src/declarative/fx/qfxflickable.cpp | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/src/declarative/fx/qfxflickable.cpp b/src/declarative/fx/qfxflickable.cpp index a83ee66..cbfe9f6 100644 --- a/src/declarative/fx/qfxflickable.cpp +++ b/src/declarative/fx/qfxflickable.cpp @@ -618,11 +618,18 @@ void QFxFlickablePrivate::handleMouseMoveEvent(QGraphicsSceneMouseEvent *event) newY = minY + (newY - minY) / 2; if (newY < maxY && maxY - minY < 0) newY = maxY + (newY - maxY) / 2; - if (q->overShoot() || (newY <= minY && newY >= maxY)) { + if (!q->overShoot() && (newY > minY || newY < maxY)) { + if (newY > minY) + newY = minY; + else if (newY < maxY) + newY = maxY; + else + rejectY = true; + } + if (!rejectY) { _moveY.setValue(newY); moved = true; - } else if (!q->overShoot()) - rejectY = true; + } if (qAbs(dy) > DragThreshold) stealMouse = true; } @@ -638,11 +645,19 @@ void QFxFlickablePrivate::handleMouseMoveEvent(QGraphicsSceneMouseEvent *event) newX = minX + (newX - minX) / 2; if (newX < maxX && maxX - minX < 0) newX = maxX + (newX - maxX) / 2; - if (q->overShoot() || (newX <= minX && newX >= maxX)) { + if (!q->overShoot() && (newX > minX || newX < maxX)) { + if (newX > minX) + newX = minX; + else if (newX < maxX) + newX = maxX; + else + rejectX = true; + } + if (!rejectX) { _moveX.setValue(newX); moved = true; - } else if (!q->overShoot()) - rejectX = true; + } + if (qAbs(dx) > DragThreshold) stealMouse = true; } -- cgit v0.12 From 76ece6b01e88199349e4c98897b5a846e8253c9d Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Tue, 27 Oct 2009 13:37:59 +1000 Subject: Don't crash when requesting an attached object for non-QML object --- src/declarative/qml/qmlengine.cpp | 2 ++ .../data/qmlAttachedPropertiesObjectMethod.1.qml | 5 ++++ .../data/qmlAttachedPropertiesObjectMethod.2.qml | 6 +++++ .../declarative/qmllanguage/tst_qmllanguage.cpp | 30 ++++++++++++++++++++++ 4 files changed, 43 insertions(+) create mode 100644 tests/auto/declarative/qmllanguage/data/qmlAttachedPropertiesObjectMethod.1.qml create mode 100644 tests/auto/declarative/qmllanguage/data/qmlAttachedPropertiesObjectMethod.2.qml diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp index ab3c23a..0e239ce 100644 --- a/src/declarative/qml/qmlengine.cpp +++ b/src/declarative/qml/qmlengine.cpp @@ -476,6 +476,8 @@ QmlEngine *qmlEngine(const QObject *obj) QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool create) { QmlDeclarativeData *data = QmlDeclarativeData::get(object); + if (!data) + return 0; // Attached properties are only on objects created by QML QObject *rv = data->attachedProperties?data->attachedProperties->value(id):0; if (rv || !create) diff --git a/tests/auto/declarative/qmllanguage/data/qmlAttachedPropertiesObjectMethod.1.qml b/tests/auto/declarative/qmllanguage/data/qmlAttachedPropertiesObjectMethod.1.qml new file mode 100644 index 0000000..99a9746 --- /dev/null +++ b/tests/auto/declarative/qmllanguage/data/qmlAttachedPropertiesObjectMethod.1.qml @@ -0,0 +1,5 @@ +import Test 1.0 +import Qt 4.6 +Object { +} + diff --git a/tests/auto/declarative/qmllanguage/data/qmlAttachedPropertiesObjectMethod.2.qml b/tests/auto/declarative/qmllanguage/data/qmlAttachedPropertiesObjectMethod.2.qml new file mode 100644 index 0000000..8179dbd --- /dev/null +++ b/tests/auto/declarative/qmllanguage/data/qmlAttachedPropertiesObjectMethod.2.qml @@ -0,0 +1,6 @@ +import Test 1.0 +import Qt 4.6 +Object { + MyQmlObject.value: 10 +} + diff --git a/tests/auto/declarative/qmllanguage/tst_qmllanguage.cpp b/tests/auto/declarative/qmllanguage/tst_qmllanguage.cpp index 4bc02c0..5ef1a7d 100644 --- a/tests/auto/declarative/qmllanguage/tst_qmllanguage.cpp +++ b/tests/auto/declarative/qmllanguage/tst_qmllanguage.cpp @@ -74,6 +74,8 @@ private slots: void importsOrder_data(); void importsOrder(); + void qmlAttachedPropertiesObjectMethod(); + // regression tests for crashes void crash1(); @@ -1012,6 +1014,34 @@ void tst_qmllanguage::importsOrder() testType(qml,type); } +void tst_qmllanguage::qmlAttachedPropertiesObjectMethod() +{ + QObject object; + + QCOMPARE(qmlAttachedPropertiesObject(&object, false), (QObject *)0); + QCOMPARE(qmlAttachedPropertiesObject(&object, true), (QObject *)0); + + { + QmlComponent component(&engine, TEST_FILE("qmlAttachedPropertiesObjectMethod.1.qml")); + VERIFY_ERRORS(0); + QObject *object = component.create(); + QVERIFY(object != 0); + + QCOMPARE(qmlAttachedPropertiesObject(object, false), (QObject *)0); + QVERIFY(qmlAttachedPropertiesObject(object, true) != 0); + } + + { + QmlComponent component(&engine, TEST_FILE("qmlAttachedPropertiesObjectMethod.2.qml")); + VERIFY_ERRORS(0); + QObject *object = component.create(); + QVERIFY(object != 0); + + QVERIFY(qmlAttachedPropertiesObject(object, false) != 0); + QVERIFY(qmlAttachedPropertiesObject(object, true) != 0); + } +} + void tst_qmllanguage::crash1() { QmlComponent component(&engine, "Component {}"); -- cgit v0.12 From a9745ccc4d1d5e8e033a805fe1870221250f7dec Mon Sep 17 00:00:00 2001 From: Yann Bodson Date: Tue, 27 Oct 2009 13:55:34 +1000 Subject: make listview/dynamic.qml work again --- .../declarative/listview/content/ClickAutoRepeating.qml | 16 +++++++++------- examples/declarative/listview/dynamic.qml | 8 ++++---- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/examples/declarative/listview/content/ClickAutoRepeating.qml b/examples/declarative/listview/content/ClickAutoRepeating.qml index f0e7df1..796f9e3 100644 --- a/examples/declarative/listview/content/ClickAutoRepeating.qml +++ b/examples/declarative/listview/content/ClickAutoRepeating.qml @@ -4,25 +4,27 @@ Item { id: page property int repeatdelay: 300 property int repeatperiod: 75 - property bool pressed: false + property bool isPressed: false + signal pressed signal released signal clicked - pressed: SequentialAnimation { + + isPressed: SequentialAnimation { id: autoRepeat - PropertyAction { target: page; property: "pressed"; value: true } - ScriptAction { script: page.onPressed } - ScriptAction { script: page.onClicked } + PropertyAction { target: page; property: "isPressed"; value: true } + ScriptAction { script: page.pressed() } + ScriptAction { script: page.clicked() } PauseAnimation { duration: repeatdelay } SequentialAnimation { repeat: true - ScriptAction { script: page.onClicked } + ScriptAction { script: page.clicked() } PauseAnimation { duration: repeatperiod } } } MouseRegion { anchors.fill: parent onPressed: autoRepeat.start() - onReleased: { autoRepeat.stop(); parent.pressed = false; page.released } + onReleased: { autoRepeat.stop(); parent.isPressed = false; page.released() } } } diff --git a/examples/declarative/listview/dynamic.qml b/examples/declarative/listview/dynamic.qml index 4f8e483..f48cc4e 100644 --- a/examples/declarative/listview/dynamic.qml +++ b/examples/declarative/listview/dynamic.qml @@ -59,8 +59,8 @@ Item { id: fruitDelegate Item { width: parent.width; height: 55 - Text { id: label; font.pixelSize: 24; text: name; elide: "ElideRight"; anchors.right: cost.left; anchors.left:parent.left } - Text { id: cost; font.pixelSize: 24; text: '$'+Number(cost).toFixed(2); anchors.right: itemButtons.left } + Text { id: label; font.pixelSize: 24; text: name; elide: "ElideRight"; anchors.right: costText.left; anchors.left:parent.left } + Text { id: costText; font.pixelSize: 24; text: '$'+Number(cost).toFixed(2); anchors.right: itemButtons.left } Row { anchors.top: label.bottom spacing: 5 @@ -77,11 +77,11 @@ Item { width: childrenRect.width Image { source: "content/pics/add.png" ClickAutoRepeating { id: clickUp; anchors.fill: parent; onClicked: fruitModel.set(index,"cost",Number(cost)+0.25) } - scale: clickUp.pressed ? 0.9 : 1 + scale: clickUp.isPressed ? 0.9 : 1 } Image { source: "content/pics/del.png" ClickAutoRepeating { id: clickDown; anchors.fill: parent; onClicked: fruitModel.set(index,"cost",Math.max(0,Number(cost)-0.25)) } - scale: clickDown.pressed ? 0.9 : 1 + scale: clickDown.isPressed ? 0.9 : 1 } Image { source: "content/pics/trash.png" MouseRegion { anchors.fill: parent; onClicked: fruitModel.remove(index) } -- cgit v0.12 From 578a9db47635e8a5dad55022c10f0222e7b1f29c Mon Sep 17 00:00:00 2001 From: Bea Lam Date: Tue, 27 Oct 2009 14:04:03 +1000 Subject: Allow debugger components to be reset/cleared. --- tools/qmldebugger/canvasframerate.cpp | 63 +++++++++++++++++++++++------ tools/qmldebugger/canvasframerate.h | 22 +++++++--- tools/qmldebugger/expressionquerywidget.cpp | 25 +++++------- tools/qmldebugger/expressionquerywidget.h | 2 +- tools/qmldebugger/objectpropertiesview.cpp | 7 +++- tools/qmldebugger/objectpropertiesview.h | 1 + tools/qmldebugger/objecttree.cpp | 3 ++ tools/qmldebugger/qmldebugger.cpp | 3 +- tools/qmldebugger/watchtable.cpp | 18 +++++++-- tools/qmldebugger/watchtable.h | 3 +- 10 files changed, 109 insertions(+), 38 deletions(-) diff --git a/tools/qmldebugger/canvasframerate.cpp b/tools/qmldebugger/canvasframerate.cpp index 7c5d089..ae0131f 100644 --- a/tools/qmldebugger/canvasframerate.cpp +++ b/tools/qmldebugger/canvasframerate.cpp @@ -178,7 +178,6 @@ 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); @@ -247,11 +246,10 @@ void CanvasFrameRatePlugin::messageReceived(const QByteArray &data) ld = d; } -CanvasFrameRate::CanvasFrameRate(QmlDebugConnection *client, QWidget *parent) -: QWidget(parent) +CanvasFrameRate::CanvasFrameRate(QWidget *parent) +: QWidget(parent), + m_plugin(0) { - m_plugin = new CanvasFrameRatePlugin(client); - QVBoxLayout *layout = new QVBoxLayout; layout->setContentsMargins(0,0,0,0); layout->setSpacing(0); @@ -261,7 +259,8 @@ CanvasFrameRate::CanvasFrameRate(QmlDebugConnection *client, QWidget *parent) layout->addWidget(m_tabs); QHBoxLayout *bottom = new QHBoxLayout; - bottom->setSpacing(5); + bottom->setContentsMargins(5, 0, 5, 0); + bottom->setSpacing(10); layout->addLayout(bottom); QLabel *label = new QLabel("Resolution", this); @@ -275,15 +274,51 @@ CanvasFrameRate::CanvasFrameRate(QmlDebugConnection *client, QWidget *parent) bottom->addStretch(2); - QCheckBox *check = new QCheckBox("Enable", this); - bottom->addWidget(check); - QObject::connect(check, SIGNAL(stateChanged(int)), - this, SLOT(stateChanged(int))); + m_enabledCheckBox = new QCheckBox("Enable", this); + bottom->addWidget(m_enabledCheckBox); + QObject::connect(m_enabledCheckBox, SIGNAL(stateChanged(int)), + this, SLOT(enabledStateChanged(int))); QPushButton *pb = new QPushButton(tr("New Tab"), this); QObject::connect(pb, SIGNAL(clicked()), this, SLOT(newTab())); bottom->addWidget(pb); +} + +void CanvasFrameRate::reset(QmlDebugConnection *conn) +{ + delete m_plugin; + m_plugin = 0; + + QWidget *w; + for (int i=0; icount(); 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(sender())); + } +} + +void CanvasFrameRate::handleConnected(QmlDebugConnection *conn) +{ + delete m_plugin; + m_plugin = new CanvasFrameRatePlugin(conn); + enabledStateChanged(m_enabledCheckBox->checkState()); newTab(); } @@ -299,6 +334,9 @@ QSize CanvasFrameRate::sizeHint() const 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)), @@ -317,11 +355,12 @@ void CanvasFrameRate::newTab() m_tabs->setCurrentIndex(id); } -void CanvasFrameRate::stateChanged(int s) +void CanvasFrameRate::enabledStateChanged(int s) { bool checked = s != 0; - static_cast(m_plugin)->setEnabled(checked); + if (m_plugin) + static_cast(m_plugin)->setEnabled(checked); } QT_END_NAMESPACE diff --git a/tools/qmldebugger/canvasframerate.h b/tools/qmldebugger/canvasframerate.h index aa275aa..6c1ff9f 100644 --- a/tools/qmldebugger/canvasframerate.h +++ b/tools/qmldebugger/canvasframerate.h @@ -1,31 +1,43 @@ #ifndef CANVASFRAMERATE_H #define CANVASFRAMERATE_H -#include +#include +#include + +#include QT_BEGIN_NAMESPACE -class QmlDebugConnection; class QTabWidget; class QSpinBox; +class QCheckBox; + +class CanvasFrameRatePlugin; + class CanvasFrameRate : public QWidget { Q_OBJECT public: - CanvasFrameRate(QmlDebugConnection *, QWidget *parent = 0); + CanvasFrameRate(QWidget *parent = 0); + + void reset(QmlDebugConnection *conn); void setSizeHint(const QSize &); virtual QSize sizeHint() const; private slots: void newTab(); - void stateChanged(int); + void enabledStateChanged(int); + void connectionStateChanged(QAbstractSocket::SocketState state); private: + void handleConnected(QmlDebugConnection *conn); + QTabWidget *m_tabs; QSpinBox *m_spin; - QObject *m_plugin; + CanvasFrameRatePlugin *m_plugin; QSize m_sizeHint; + QCheckBox *m_enabledCheckBox; }; QT_END_NAMESPACE diff --git a/tools/qmldebugger/expressionquerywidget.cpp b/tools/qmldebugger/expressionquerywidget.cpp index 53ede3a..f8f5aef 100644 --- a/tools/qmldebugger/expressionquerywidget.cpp +++ b/tools/qmldebugger/expressionquerywidget.cpp @@ -17,28 +17,25 @@ ExpressionQueryWidget::ExpressionQueryWidget(QmlEngineDebug *client, QWidget *pa m_client(client), m_query(0), m_textEdit(new QTextEdit), - m_lineEdit(0), - m_button(0) + m_lineEdit(0) { m_prompt = QLatin1String(">> "); QVBoxLayout *layout = new QVBoxLayout(this); layout->setMargin(0); + layout->setSpacing(0); layout->addWidget(m_textEdit); updateTitle(); if (m_style == Compact) { - QHBoxLayout *hbox = new QHBoxLayout; - m_button = new QPushButton(tr("Query")); - m_button->setEnabled(false); - connect(m_button, SIGNAL(clicked()), SLOT(executeExpression())); m_lineEdit = new QLineEdit; connect(m_lineEdit, SIGNAL(returnPressed()), SLOT(executeExpression())); - connect(m_lineEdit, SIGNAL(textChanged(QString)), SLOT(lineEditTextChanged(QString))); + QHBoxLayout *hbox = new QHBoxLayout; + hbox->setMargin(5); + hbox->setSpacing(5); hbox->addWidget(new QLabel(tr("Expression:"))); hbox->addWidget(m_lineEdit); - hbox->addWidget(m_button); layout->addLayout(hbox); m_textEdit->setReadOnly(true); @@ -53,6 +50,12 @@ void ExpressionQueryWidget::setEngineDebug(QmlEngineDebug *client) m_client = client; } +void ExpressionQueryWidget::clear() +{ + m_textEdit->clear(); + m_lineEdit->clear(); +} + void ExpressionQueryWidget::updateTitle() { if (m_currObject.debugId() < 0) { @@ -153,12 +156,6 @@ void ExpressionQueryWidget::showResult() } } -void ExpressionQueryWidget::lineEditTextChanged(const QString &s) -{ - if (m_button) - m_button->setEnabled(!s.isEmpty()); -} - bool ExpressionQueryWidget::eventFilter(QObject *obj, QEvent *event) { if (obj == m_textEdit) { diff --git a/tools/qmldebugger/expressionquerywidget.h b/tools/qmldebugger/expressionquerywidget.h index 3d9b580..6fab059 100644 --- a/tools/qmldebugger/expressionquerywidget.h +++ b/tools/qmldebugger/expressionquerywidget.h @@ -24,6 +24,7 @@ public: ExpressionQueryWidget(QmlEngineDebug *client = 0, QWidget *parent = 0); void setEngineDebug(QmlEngineDebug *client); + void clear(); protected: bool eventFilter(QObject *obj, QEvent *event); @@ -34,7 +35,6 @@ public slots: private slots: void executeExpression(); void showResult(); - void lineEditTextChanged(const QString &s); private: void appendPrompt(); diff --git a/tools/qmldebugger/objectpropertiesview.cpp b/tools/qmldebugger/objectpropertiesview.cpp index 274552a..ae9e8be 100644 --- a/tools/qmldebugger/objectpropertiesview.cpp +++ b/tools/qmldebugger/objectpropertiesview.cpp @@ -43,6 +43,7 @@ ObjectPropertiesView::ObjectPropertiesView(QmlEngineDebug *client, QWidget *pare setLayout(layout); m_tree = new QTreeWidget(this); + m_tree->setAlternatingRowColors(true); m_tree->setExpandsOnDoubleClick(false); m_tree->setHeaderLabels(QStringList() << tr("Property") << tr("Value")); QObject::connect(m_tree, SIGNAL(itemActivated(QTreeWidgetItem *, int)), @@ -58,6 +59,11 @@ void ObjectPropertiesView::setEngineDebug(QmlEngineDebug *client) m_client = client; } +void ObjectPropertiesView::clear() +{ + setObject(QmlDebugObjectReference()); +} + void ObjectPropertiesView::reload(const QmlDebugObjectReference &obj) { if (!m_client) @@ -105,7 +111,6 @@ void ObjectPropertiesView::setObject(const QmlDebugObjectReference &object) m_object = object; m_tree->clear(); - QList properties = object.properties(); for (int i=0; idata(0, Qt::UserRole).value(); if (obj.debugId() < 0) { qWarning("QML Object Tree: bad object id"); diff --git a/tools/qmldebugger/qmldebugger.cpp b/tools/qmldebugger/qmldebugger.cpp index 2828026..5455878 100644 --- a/tools/qmldebugger/qmldebugger.cpp +++ b/tools/qmldebugger/qmldebugger.cpp @@ -45,7 +45,8 @@ QmlDebugger::QmlDebugger(QWidget *parent) m_tabs = new QTabWidget(this); layout->addWidget(m_tabs); - CanvasFrameRate *cfr = new CanvasFrameRate(&client, this); + CanvasFrameRate *cfr = new CanvasFrameRate(this); + cfr->reset(&client); cfr->setSizeHint(QSize(800, 600)); m_tabs->addTab(cfr, tr("Frame Rate")); diff --git a/tools/qmldebugger/watchtable.cpp b/tools/qmldebugger/watchtable.cpp index 774727b..ee74cfb 100644 --- a/tools/qmldebugger/watchtable.cpp +++ b/tools/qmldebugger/watchtable.cpp @@ -18,7 +18,7 @@ WatchTableModel::WatchTableModel(QmlEngineDebug *client, QObject *parent) } WatchTableModel::~WatchTableModel() -{ +{ for (int i=0; iremoveWatch(m_columns[i].watch); + delete m_columns[i].watch; + } + m_columns.clear(); + m_values.clear(); + reset(); +} //---------------------------------------------- @@ -281,7 +292,7 @@ void WatchTableHeaderView::mousePressEvent(QMouseEvent *me) QList actions; actions << &action; if (QMenu::exec(actions, me->globalPos())) - m_model->stopWatching(col); + m_model->removeWatchAt(col); } } } @@ -293,6 +304,7 @@ WatchTableView::WatchTableView(WatchTableModel *model, QWidget *parent) : QTableView(parent), m_model(model) { + setAlternatingRowColors(true); connect(model, SIGNAL(watchCreated(QmlDebugWatch*)), SLOT(watchCreated(QmlDebugWatch*))); connect(this, SIGNAL(activated(QModelIndex)), SLOT(indexActivated(QModelIndex))); } diff --git a/tools/qmldebugger/watchtable.h b/tools/qmldebugger/watchtable.h index 772142c..67c2565 100644 --- a/tools/qmldebugger/watchtable.h +++ b/tools/qmldebugger/watchtable.h @@ -29,7 +29,8 @@ public: QmlDebugWatch *findWatch(int column) const; int columnForWatch(QmlDebugWatch *watch) const; - void stopWatching(int column); + void removeWatchAt(int column); + void removeAllWatches(); int rowCount(const QModelIndex &parent = QModelIndex()) const; int columnCount(const QModelIndex &parent = QModelIndex()) const; -- cgit v0.12 From 2af9bc37a5955e8e1da2c3ba03fa0be763e2ae5e Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Tue, 27 Oct 2009 14:05:26 +1000 Subject: Simplify the defaultObjects handling As the scope object is no longer added to the defaultObjects list it makes sense that the root object remain constant at position 0 --- src/declarative/qml/qmlbasicscript.cpp | 2 +- src/declarative/qml/qmlcontext.cpp | 21 +-------------------- src/declarative/qml/qmlcontext_p.h | 6 ------ src/declarative/qml/qmlcontextscriptclass.cpp | 2 +- src/declarative/qml/qmlexpression.cpp | 10 ++++++---- 5 files changed, 9 insertions(+), 32 deletions(-) diff --git a/src/declarative/qml/qmlbasicscript.cpp b/src/declarative/qml/qmlbasicscript.cpp index b7aac54..eba4307 100644 --- a/src/declarative/qml/qmlbasicscript.cpp +++ b/src/declarative/qml/qmlbasicscript.cpp @@ -658,7 +658,7 @@ QVariant QmlBasicScript::run(QmlContext *context, QObject *me) case ScriptInstruction::FetchRootConstant: { - QObject *obj = contextPrivate->defaultObjects.last(); + QObject *obj = contextPrivate->defaultObjects.at(0); stack.push(fetch_value(obj, instr.constant.idx, instr.constant.type)); if (obj && instr.constant.notify != 0) diff --git a/src/declarative/qml/qmlcontext.cpp b/src/declarative/qml/qmlcontext.cpp index 7ba3544..2ebdf10 100644 --- a/src/declarative/qml/qmlcontext.cpp +++ b/src/declarative/qml/qmlcontext.cpp @@ -50,9 +50,6 @@ #include #include -// 6-bits -#define MAXIMUM_DEFAULT_OBJECTS 63 - QT_BEGIN_NAMESPACE QmlContextPrivate::QmlContextPrivate() @@ -130,22 +127,6 @@ void QmlContextPrivate::init() parent->d_func()->childContexts.insert(q); } -void QmlContextPrivate::addDefaultObject(QObject *object, Priority priority) -{ - if (defaultObjects.count() >= (MAXIMUM_DEFAULT_OBJECTS - 1)) { - qWarning("QmlContext: Cannot have more than %d default objects on " - "one bind context.", MAXIMUM_DEFAULT_OBJECTS - 1); - return; - } - - if (priority == HighPriority) { - defaultObjects.insert(highPriorityCount++, object); - } else { - defaultObjects.append(object); - } -} - - /*! \class QmlContext \brief The QmlContext class defines a context within a QML engine. @@ -366,7 +347,7 @@ QmlContext *QmlContext::parentContext() const void QmlContext::addDefaultObject(QObject *defaultObject) { Q_D(QmlContext); - d->addDefaultObject(defaultObject, QmlContextPrivate::NormalPriority); + d->defaultObjects.prepend(defaultObject); } /*! diff --git a/src/declarative/qml/qmlcontext_p.h b/src/declarative/qml/qmlcontext_p.h index be7bf1d..6af5f64 100644 --- a/src/declarative/qml/qmlcontext_p.h +++ b/src/declarative/qml/qmlcontext_p.h @@ -104,12 +104,6 @@ public: void dump(); void dump(int depth); - enum Priority { - HighPriority, - NormalPriority - }; - void addDefaultObject(QObject *, Priority); - void invalidateEngines(); QSet childContexts; diff --git a/src/declarative/qml/qmlcontextscriptclass.cpp b/src/declarative/qml/qmlcontextscriptclass.cpp index 4df23f0..a978df2 100644 --- a/src/declarative/qml/qmlcontextscriptclass.cpp +++ b/src/declarative/qml/qmlcontextscriptclass.cpp @@ -155,7 +155,7 @@ QmlContextScriptClass::queryProperty(QmlContext *bindContext, QObject *scopeObje } } - for (int ii = 0; ii < cp->defaultObjects.count(); ++ii) { + for (int ii = cp->defaultObjects.count() - 1; ii >= 0; --ii) { QScriptClass::QueryFlags rv = ep->objectClass->queryProperty(cp->defaultObjects.at(ii), name, flags, bindContext); diff --git a/src/declarative/qml/qmlexpression.cpp b/src/declarative/qml/qmlexpression.cpp index 3b89a23..c62756b 100644 --- a/src/declarative/qml/qmlexpression.cpp +++ b/src/declarative/qml/qmlexpression.cpp @@ -293,8 +293,7 @@ QVariant QmlExpressionPrivate::evalQtScript(QObject *secondaryScope, bool *isUnd QmlEnginePrivate *ep = QmlEnginePrivate::get(engine); if (secondaryScope) - ctxtPriv->defaultObjects.insert(ctxtPriv->highPriorityCount, - secondaryScope); + ctxtPriv->defaultObjects.append(secondaryScope); QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); @@ -328,8 +327,11 @@ QVariant QmlExpressionPrivate::evalQtScript(QObject *secondaryScope, bool *isUnd return QVariant(); } - if (secondaryScope) - ctxtPriv->defaultObjects.removeAt(ctxtPriv->highPriorityCount); + if (secondaryScope) { + QObject *last = ctxtPriv->defaultObjects.takeLast(); + Q_ASSERT(last == secondaryScope); + Q_UNUSED(last); + } QVariant rv; -- cgit v0.12 From b590c65a82ec6fe085d6d609bf342e2c18b8e6c9 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Tue, 27 Oct 2009 14:39:27 +1000 Subject: Alias cleanup testcase --- .../auto/declarative/qmllanguage/data/alias.7.qml | 14 +++++++++++ .../declarative/qmllanguage/tst_qmllanguage.cpp | 27 ++++++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 tests/auto/declarative/qmllanguage/data/alias.7.qml diff --git a/tests/auto/declarative/qmllanguage/data/alias.7.qml b/tests/auto/declarative/qmllanguage/data/alias.7.qml new file mode 100644 index 0000000..d3cf5fe --- /dev/null +++ b/tests/auto/declarative/qmllanguage/data/alias.7.qml @@ -0,0 +1,14 @@ +import Qt 4.6 + +Object { + property Object object + property alias aliasedObject: target.object + + object: Object { + id: target + + property Object object + object: Object {} + } +} + diff --git a/tests/auto/declarative/qmllanguage/tst_qmllanguage.cpp b/tests/auto/declarative/qmllanguage/tst_qmllanguage.cpp index 5ef1a7d..2746e98 100644 --- a/tests/auto/declarative/qmllanguage/tst_qmllanguage.cpp +++ b/tests/auto/declarative/qmllanguage/tst_qmllanguage.cpp @@ -695,6 +695,33 @@ void tst_qmllanguage::aliasProperties() QCOMPARE(object->property("a").toInt(), 1923); } + + // Ptr Alias Cleanup - check that aliases to ptr types return 0 + // if the object aliased to is removed + { + QmlComponent component(&engine, TEST_FILE("alias.7.qml")); + VERIFY_ERRORS(0); + + QObject *object = component.create(); + QVERIFY(object != 0); + + QObject *object1 = qvariant_cast(object->property("object")); + QVERIFY(object1 != 0); + QObject *object2 = qvariant_cast(object1->property("object")); + QVERIFY(object2 != 0); + + QObject *alias = qvariant_cast(object->property("aliasedObject")); + QVERIFY(alias == object2); + + delete object1; + + QObject *alias2 = object; // "Random" start value + int status = -1; + void *a[] = { &alias2, 0, &status }; + QMetaObject::metacall(object, QMetaObject::ReadProperty, + object->metaObject()->indexOfProperty("aliasedObject"), a); + QVERIFY(alias2 == 0); + } } // Test that the root element in a composite type can be a Component -- cgit v0.12 From 377c3cc4ff74097d173b8518430f36689fbd3331 Mon Sep 17 00:00:00 2001 From: Bea Lam Date: Tue, 27 Oct 2009 14:57:41 +1000 Subject: Increase minimum height --- tools/qmldebugger/canvasframerate.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/qmldebugger/canvasframerate.cpp b/tools/qmldebugger/canvasframerate.cpp index ae0131f..10c3dbf 100644 --- a/tools/qmldebugger/canvasframerate.cpp +++ b/tools/qmldebugger/canvasframerate.cpp @@ -56,7 +56,7 @@ private: QLineGraph::QLineGraph(QWidget *parent) : QWidget(parent), sb(Qt::Horizontal, this), position(-1), samplesPerWidth(99), resolutionForHeight(50), ignoreScroll(false) { - setMinimumHeight(180); + setMinimumHeight(200); sb.setMaximum(0); sb.setMinimum(0); -- cgit v0.12 From b5b6861dd1a82ea9be9b2d2f89ba5cc9dea150ac Mon Sep 17 00:00:00 2001 From: Bea Lam Date: Tue, 27 Oct 2009 14:57:57 +1000 Subject: Add -stayontop option. --- tools/qmlviewer/main.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/tools/qmlviewer/main.cpp b/tools/qmlviewer/main.cpp index f82867f..3f531e4 100644 --- a/tools/qmlviewer/main.cpp +++ b/tools/qmlviewer/main.cpp @@ -28,6 +28,7 @@ void usage() qWarning(" -frameless ............................... run with no window frame"); qWarning(" -maximized................................ run maximized"); qWarning(" -fullscreen............................... run fullscreen"); + qWarning(" -stayontop................................ keep viewer window on top"); qWarning(" -skin ...................... run with a skin window frame"); qWarning(" \"list\" for a list of built-ins"); qWarning(" -resizeview .............................. resize the view, not the skin"); @@ -105,6 +106,7 @@ int main(int argc, char ** argv) QString translationFile; bool useGL = false; bool fullScreen = false; + bool stayOnTop = false; bool maximized = false; for (int i = 1; i < argc; ++i) { @@ -116,6 +118,8 @@ int main(int argc, char ** argv) maximized = true; } else if (arg == "-fullscreen") { fullScreen = true; + } else if (arg == "-stayontop") { + stayOnTop = true; } else if (arg == "-skin") { if (lastArg) usage(); skin = QString(argv[++i]); @@ -183,9 +187,12 @@ int main(int argc, char ** argv) app.installTranslator(&qmlTranslator); } - QmlViewer viewer(0, frameless ? Qt::FramelessWindowHint : Qt::Widget); + Qt::WFlags wflags = (frameless ? Qt::FramelessWindowHint : Qt::Widget); + if (stayOnTop) + wflags |= Qt::WindowStaysOnTopHint; + + QmlViewer viewer(0, wflags); if (!scriptopts.isEmpty()) { - QStringList options = scriptopts.split(QLatin1Char(','), QString::SkipEmptyParts); -- cgit v0.12 From 7333e6bf09c64fc8c895068bf17a8fc891477976 Mon Sep 17 00:00:00 2001 From: Yann Bodson Date: Tue, 27 Oct 2009 15:02:39 +1000 Subject: listview/dynamic improvements --- examples/declarative/listview/dynamic.qml | 108 ++++++++++++++---------------- 1 file changed, 52 insertions(+), 56 deletions(-) diff --git a/examples/declarative/listview/dynamic.qml b/examples/declarative/listview/dynamic.qml index f48cc4e..78346f3 100644 --- a/examples/declarative/listview/dynamic.qml +++ b/examples/declarative/listview/dynamic.qml @@ -1,54 +1,48 @@ import Qt 4.6 import "content" -Item { - width: 320 - height: 500 +Rectangle { + width: 640; height: 480 + color: "#343434" ListModel { id: fruitModel ListElement { - name: "Apple" - cost: 2.45 + name: "Apple"; cost: 2.45 attributes: [ ListElement { description: "Core" }, ListElement { description: "Deciduous" } ] } ListElement { - name: "Banana" - cost: 1.95 + name: "Banana"; cost: 1.95 attributes: [ ListElement { description: "Tropical" }, ListElement { description: "Seedless" } ] } ListElement { - name: "Cumquat" - cost: 3.25 + name: "Cumquat"; cost: 3.25 types: [ "Small", "Smaller" ] attributes: [ ListElement { description: "Citrus" } ] } ListElement { - name: "Durian" - cost: 9.95 + name: "Durian"; cost: 9.95 attributes: [ ListElement { description: "Tropical" }, ListElement { description: "Smelly" } ] } ListElement { - name: "Elderberry" - cost: 0.05 + name: "Elderberry"; cost: 0.05 attributes: [ ListElement { description: "Berry" } ] } ListElement { - name: "Fig" - cost: 0.25 + name: "Fig"; cost: 0.25 attributes: [ ListElement { description: "Flower" } ] @@ -59,83 +53,85 @@ Item { id: fruitDelegate Item { width: parent.width; height: 55 - Text { id: label; font.pixelSize: 24; text: name; elide: "ElideRight"; anchors.right: costText.left; anchors.left:parent.left } - Text { id: costText; font.pixelSize: 24; text: '$'+Number(cost).toFixed(2); anchors.right: itemButtons.left } - Row { - anchors.top: label.bottom - spacing: 5 - Repeater { - model: attributes - Component { - Text { text: description } - } + + Column { + id: moveButtons; x: 5; width: childrenRect.width; anchors.verticalCenter: parent.verticalCenter + Image { source: "content/pics/go-up.png" + MouseRegion { anchors.fill: parent; onClicked: fruitModel.move(index,index-1,1) } + } + Image { source: "content/pics/go-down.png" + MouseRegion { anchors.fill: parent; onClicked: fruitModel.move(index,index+1,1) } + } + } + + Column { + anchors { right: itemButtons.left; verticalCenter: parent.verticalCenter; left: moveButtons.right; leftMargin: 10 } + Text { + id: label; font.bold: true; text: name; elide: Text.ElideRight; font.pixelSize: 15 + width: parent.width; color: "White" + } + Row { + spacing: 5 + Repeater { model: attributes; Component { Text { text: description; color: "White" } } } } } + Row { id: itemButtons - anchors.right: parent.right - width: childrenRect.width - Image { source: "content/pics/add.png" + anchors.right: removeButton.left; anchors.rightMargin: 35; spacing: 10 + width: childrenRect.width; anchors.verticalCenter: parent.verticalCenter + Image { source: "content/pics/list-add.png" ClickAutoRepeating { id: clickUp; anchors.fill: parent; onClicked: fruitModel.set(index,"cost",Number(cost)+0.25) } - scale: clickUp.isPressed ? 0.9 : 1 + scale: clickUp.isPressed ? 0.9 : 1; transformOrigin: Item.Center } - Image { source: "content/pics/del.png" + Text { id: costText; text: '$'+Number(cost).toFixed(2); font.pixelSize: 15; color: "White"; font.bold: true; } + Image { source: "content/pics/list-remove.png" ClickAutoRepeating { id: clickDown; anchors.fill: parent; onClicked: fruitModel.set(index,"cost",Math.max(0,Number(cost)-0.25)) } - scale: clickDown.isPressed ? 0.9 : 1 - } - Image { source: "content/pics/trash.png" - MouseRegion { anchors.fill: parent; onClicked: fruitModel.remove(index) } - } - Column { - width: childrenRect.width - Image { source: "content/pics/moreUp.png" - MouseRegion { anchors.fill: parent; onClicked: fruitModel.move(index,index-1,1) } - } - Image { source: "content/pics/moreDown.png" - MouseRegion { anchors.fill: parent; onClicked: fruitModel.move(index,index+1,1) } - } + scale: clickDown.isPressed ? 0.9 : 1; transformOrigin: Item.Center } } + Image { + id: removeButton; source: "content/pics/archive-remove.png" + anchors { verticalCenter: parent.verticalCenter; right: parent.right; rightMargin: 10 } + MouseRegion { anchors.fill:parent; onClicked: fruitModel.remove(index) } + } } } ListView { - model: fruitModel - delegate: fruitDelegate - anchors.top: parent.top - anchors.left: parent.left - anchors.right: parent.right - anchors.bottom: buttons.top + model: fruitModel; delegate: fruitDelegate + anchors { top: parent.top; left: parent.left; right: parent.right; bottom: buttons.top } } Row { - width: childrenRect.width + x: 8; width: childrenRect.width height: childrenRect.height - anchors.bottom: parent.bottom + anchors { bottom: parent.bottom; bottomMargin: 8 } + spacing: 8 id: buttons - Image { source: "content/pics/add.png" + Image { source: "content/pics/archive-insert.png" MouseRegion { anchors.fill: parent; onClicked: { fruitModel.append({ "name":"Pizza Margarita", "cost":5.95, "attributes":[{"description": "Cheese"},{"description": "Tomato"}] - }) + }) } } } - Image { source: "content/pics/add.png" + Image { source: "content/pics/archive-insert.png" MouseRegion { anchors.fill: parent; onClicked: { fruitModel.insert(0,{ "name":"Pizza Supreme", "cost":9.95, "attributes":[{"description": "Cheese"},{"description": "Tomato"},{"description": "The Works"}] - }) + }) } } } - Image { source: "content/pics/trash.png" + Image { source: "content/pics/archive-remove.png" MouseRegion { anchors.fill: parent; onClicked: fruitModel.clear() } } } -- cgit v0.12 From 7a0f9e754f76b052bf1474ec7c1d5f59b774de54 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Tue, 27 Oct 2009 15:05:36 +1000 Subject: Update parallax example --- examples/declarative/parallax/ParallaxView.qml | 64 ++- examples/declarative/parallax/parallax.qml | 18 +- examples/declarative/parallax/pics/home-page.svg | 445 +++++++++++++++++++++ .../declarative/parallax/pics/yast-joystick.png | Bin 0 -> 2723 bytes examples/declarative/parallax/pics/yast-wol.png | Bin 0 -> 3769 bytes 5 files changed, 523 insertions(+), 4 deletions(-) create mode 100644 examples/declarative/parallax/pics/home-page.svg create mode 100644 examples/declarative/parallax/pics/yast-joystick.png create mode 100644 examples/declarative/parallax/pics/yast-wol.png diff --git a/examples/declarative/parallax/ParallaxView.qml b/examples/declarative/parallax/ParallaxView.qml index 38bb8c0..1708ad1 100644 --- a/examples/declarative/parallax/ParallaxView.qml +++ b/examples/declarative/parallax/ParallaxView.qml @@ -1,7 +1,11 @@ import Qt 4.6 Item { + id: root + property alias background: background.source + default property alias content: visualModel.children + property int currentIndex: 0 Image { id: background @@ -10,9 +14,12 @@ Item { width: Math.max(list.viewportWidth, parent.width) } - default property alias content: visualModel.children ListView { id: list + + currentIndex: root.currentIndex + onCurrentIndexChanged: root.currentIndex = currentIndex + orientation: "Horizontal" overShoot: false anchors.fill: parent @@ -23,4 +30,59 @@ Item { preferredHighlightEnd: 0 highlightRangeMode: "StrictlyEnforceRange" } + + ListView { + id: selector + + currentIndex: root.currentIndex + onCurrentIndexChanged: root.currentIndex = currentIndex + + height: 50 + anchors.bottom: parent.bottom + anchors.horizontalCenter: parent.horizontalCenter + width: Math.min(count * 50, parent.width - 20) + interactive: width == parent.width - 20 + orientation: "Horizontal" + + delegate: Item { + width: 50; height: 50 + id: delegateRoot + + Image { + id: image + source: modelData.icon + smooth: true + scale: 0.8 + transformOrigin: "Center" + } + + MouseRegion { + anchors.fill: parent + onClicked: { root.currentIndex = index } + } + + states: State { + name: "Selected" + when: delegateRoot.ListView.isCurrentItem == true + PropertyChanges { + target: image + scale: 1 + y: -5 + } + } + transitions: Transition { + NumberAnimation { + properties: "scale,y" + } + } + } + model: visualModel.children + + Rectangle { + color: "#40FFFFFF" + x: -10; + y: -10; + width: parent.width + 20; height: parent.height + 10 + } + } } diff --git a/examples/declarative/parallax/parallax.qml b/examples/declarative/parallax/parallax.qml index b2139ec..52bd210 100644 --- a/examples/declarative/parallax/parallax.qml +++ b/examples/declarative/parallax/parallax.qml @@ -2,14 +2,18 @@ import Qt 4.6 import "../clock" Rectangle { + id: root + width: 320 height: 480 ParallaxView { + id: parallax anchors.fill: parent background: "pics/background.jpg" Item { + property url icon: "pics/yast-wol.png" width: 320 height: 480 @@ -19,6 +23,8 @@ Rectangle { } Item { + property url icon: "pics/home-page.svg" + width: 320 height: 480 @@ -26,18 +32,24 @@ Rectangle { } Item { + property url icon: "pics/yast-joystick.png" + width: 320 height: 480 Loader { - anchors.centerIn: parent - width: 300; height: 460 + anchors.top: parent.top + anchors.topMargin: 10 + anchors.horizontalCenter: parent.horizontalCenter + + width: 300; height: 400 clip: true resizeMode: Loader.SizeItemToLoader source: "../../../demos/declarative/samegame/samegame.qml" } } - } + currentIndex: root.currentIndex + } } diff --git a/examples/declarative/parallax/pics/home-page.svg b/examples/declarative/parallax/pics/home-page.svg new file mode 100644 index 0000000..4f16958 --- /dev/null +++ b/examples/declarative/parallax/pics/home-page.svg @@ -0,0 +1,445 @@ + +image/svg+xmlGo HomeJakub Steinerhttp://jimmac.musichall.czhomereturngodefaultuserdirectoryTuomas Kuosmanen + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/examples/declarative/parallax/pics/yast-joystick.png b/examples/declarative/parallax/pics/yast-joystick.png new file mode 100644 index 0000000..858cea0 Binary files /dev/null and b/examples/declarative/parallax/pics/yast-joystick.png differ diff --git a/examples/declarative/parallax/pics/yast-wol.png b/examples/declarative/parallax/pics/yast-wol.png new file mode 100644 index 0000000..7712180 Binary files /dev/null and b/examples/declarative/parallax/pics/yast-wol.png differ -- cgit v0.12 From e6d3632493112fce4244fceb1a864814b8cc3b43 Mon Sep 17 00:00:00 2001 From: Yann Bodson Date: Tue, 27 Oct 2009 15:08:56 +1000 Subject: forgot icons --- .../declarative/listview/content/pics/archive-insert.png | Bin 0 -> 896 bytes .../declarative/listview/content/pics/archive-remove.png | Bin 0 -> 1074 bytes examples/declarative/listview/content/pics/go-down.png | Bin 0 -> 892 bytes examples/declarative/listview/content/pics/go-up.png | Bin 0 -> 929 bytes examples/declarative/listview/content/pics/list-add.png | Bin 0 -> 907 bytes .../declarative/listview/content/pics/list-remove.png | Bin 0 -> 498 bytes 6 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 examples/declarative/listview/content/pics/archive-insert.png create mode 100644 examples/declarative/listview/content/pics/archive-remove.png create mode 100644 examples/declarative/listview/content/pics/go-down.png create mode 100644 examples/declarative/listview/content/pics/go-up.png create mode 100644 examples/declarative/listview/content/pics/list-add.png create mode 100644 examples/declarative/listview/content/pics/list-remove.png diff --git a/examples/declarative/listview/content/pics/archive-insert.png b/examples/declarative/listview/content/pics/archive-insert.png new file mode 100644 index 0000000..b706248 Binary files /dev/null and b/examples/declarative/listview/content/pics/archive-insert.png differ diff --git a/examples/declarative/listview/content/pics/archive-remove.png b/examples/declarative/listview/content/pics/archive-remove.png new file mode 100644 index 0000000..9640f6b Binary files /dev/null and b/examples/declarative/listview/content/pics/archive-remove.png differ diff --git a/examples/declarative/listview/content/pics/go-down.png b/examples/declarative/listview/content/pics/go-down.png new file mode 100644 index 0000000..63331a5 Binary files /dev/null and b/examples/declarative/listview/content/pics/go-down.png differ diff --git a/examples/declarative/listview/content/pics/go-up.png b/examples/declarative/listview/content/pics/go-up.png new file mode 100644 index 0000000..4459024 Binary files /dev/null and b/examples/declarative/listview/content/pics/go-up.png differ diff --git a/examples/declarative/listview/content/pics/list-add.png b/examples/declarative/listview/content/pics/list-add.png new file mode 100644 index 0000000..e029787 Binary files /dev/null and b/examples/declarative/listview/content/pics/list-add.png differ diff --git a/examples/declarative/listview/content/pics/list-remove.png b/examples/declarative/listview/content/pics/list-remove.png new file mode 100644 index 0000000..2bb1a59 Binary files /dev/null and b/examples/declarative/listview/content/pics/list-remove.png differ -- cgit v0.12 From bc363b7c4819e1e4837079d6e6489654dee7de97 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Tue, 27 Oct 2009 15:10:41 +1000 Subject: Add QFxVisualItemModel::children notify signal --- src/declarative/fx/qfxvisualitemmodel.cpp | 6 ++++++ src/declarative/fx/qfxvisualitemmodel.h | 5 ++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/declarative/fx/qfxvisualitemmodel.cpp b/src/declarative/fx/qfxvisualitemmodel.cpp index e1ac246..7ee6eea 100644 --- a/src/declarative/fx/qfxvisualitemmodel.cpp +++ b/src/declarative/fx/qfxvisualitemmodel.cpp @@ -123,6 +123,10 @@ public: emit q->countChanged(); } + void emitChildrenChanged() { + Q_Q(QFxVisualItemModel); + emit q->childrenChanged(); + } ItemList children; }; @@ -224,6 +228,8 @@ void QFxVisualItemModelPrivate::ItemList::append(QFxItem *item) QmlConcreteList::append(item); item->QObject::setParent(model->q_ptr); model->itemAppended(); + + model->emitChildrenChanged(); } QFxVisualItemModelAttached *QFxVisualItemModel::qmlAttachedProperties(QObject *obj) diff --git a/src/declarative/fx/qfxvisualitemmodel.h b/src/declarative/fx/qfxvisualitemmodel.h index 5b613d8..8e33279 100644 --- a/src/declarative/fx/qfxvisualitemmodel.h +++ b/src/declarative/fx/qfxvisualitemmodel.h @@ -108,7 +108,7 @@ class Q_DECLARATIVE_EXPORT QFxVisualItemModel : public QFxVisualModel Q_OBJECT Q_DECLARE_PRIVATE(QFxVisualItemModel) - Q_PROPERTY(QmlList* children READ children DESIGNABLE false) + Q_PROPERTY(QmlList* children READ children NOTIFY childrenChanged DESIGNABLE false) Q_CLASSINFO("DefaultProperty", "children") public: @@ -128,6 +128,9 @@ public: static QFxVisualItemModelAttached *qmlAttachedProperties(QObject *obj); +signals: + void childrenChanged(); + private: Q_DISABLE_COPY(QFxVisualItemModel) }; -- cgit v0.12 From cc4bca61687f6441984ccc58ad177d24b6d3e92f Mon Sep 17 00:00:00 2001 From: Bea Lam Date: Tue, 27 Oct 2009 15:43:23 +1000 Subject: Move qmldebugger/ into qmldebugger/standalone dir. --- tools/qmldebugger/canvasframerate.cpp | 368 --------------------- tools/qmldebugger/canvasframerate.h | 46 --- tools/qmldebugger/engine.cpp | 179 ---------- tools/qmldebugger/engine.h | 61 ---- tools/qmldebugger/engine.png | Bin 6394 -> 0 bytes tools/qmldebugger/engines.qml | 46 --- tools/qmldebugger/expressionquerywidget.cpp | 218 ------------ tools/qmldebugger/expressionquerywidget.h | 65 ---- tools/qmldebugger/main.cpp | 34 -- tools/qmldebugger/objectpropertiesview.cpp | 197 ----------- tools/qmldebugger/objectpropertiesview.h | 51 --- tools/qmldebugger/objecttree.cpp | 180 ---------- tools/qmldebugger/objecttree.h | 54 --- tools/qmldebugger/qmldebugger.cpp | 131 -------- tools/qmldebugger/qmldebugger.h | 47 --- tools/qmldebugger/qmldebugger.pri | 24 -- tools/qmldebugger/qmldebugger.pro | 8 - tools/qmldebugger/qmldebugger.qrc | 7 - tools/qmldebugger/refresh.png | Bin 6169 -> 0 bytes tools/qmldebugger/standalone/canvasframerate.cpp | 368 +++++++++++++++++++++ tools/qmldebugger/standalone/canvasframerate.h | 46 +++ tools/qmldebugger/standalone/engine.cpp | 179 ++++++++++ tools/qmldebugger/standalone/engine.h | 61 ++++ tools/qmldebugger/standalone/engine.png | Bin 0 -> 6394 bytes tools/qmldebugger/standalone/engines.qml | 46 +++ .../standalone/expressionquerywidget.cpp | 218 ++++++++++++ .../qmldebugger/standalone/expressionquerywidget.h | 65 ++++ tools/qmldebugger/standalone/main.cpp | 34 ++ .../standalone/objectpropertiesview.cpp | 197 +++++++++++ .../qmldebugger/standalone/objectpropertiesview.h | 51 +++ tools/qmldebugger/standalone/objecttree.cpp | 180 ++++++++++ tools/qmldebugger/standalone/objecttree.h | 54 +++ tools/qmldebugger/standalone/qmldebugger.cpp | 131 ++++++++ tools/qmldebugger/standalone/qmldebugger.h | 47 +++ tools/qmldebugger/standalone/qmldebugger.pri | 16 + tools/qmldebugger/standalone/qmldebugger.qrc | 7 + tools/qmldebugger/standalone/refresh.png | Bin 0 -> 6169 bytes tools/qmldebugger/standalone/standalone.pro | 18 + tools/qmldebugger/standalone/watchtable.cpp | 325 ++++++++++++++++++ tools/qmldebugger/standalone/watchtable.h | 114 +++++++ tools/qmldebugger/watchtable.cpp | 325 ------------------ tools/qmldebugger/watchtable.h | 114 ------- 42 files changed, 2157 insertions(+), 2155 deletions(-) delete mode 100644 tools/qmldebugger/canvasframerate.cpp delete mode 100644 tools/qmldebugger/canvasframerate.h delete mode 100644 tools/qmldebugger/engine.cpp delete mode 100644 tools/qmldebugger/engine.h delete mode 100644 tools/qmldebugger/engine.png delete mode 100644 tools/qmldebugger/engines.qml delete mode 100644 tools/qmldebugger/expressionquerywidget.cpp delete mode 100644 tools/qmldebugger/expressionquerywidget.h delete mode 100644 tools/qmldebugger/main.cpp delete mode 100644 tools/qmldebugger/objectpropertiesview.cpp delete mode 100644 tools/qmldebugger/objectpropertiesview.h delete mode 100644 tools/qmldebugger/objecttree.cpp delete mode 100644 tools/qmldebugger/objecttree.h delete mode 100644 tools/qmldebugger/qmldebugger.cpp delete mode 100644 tools/qmldebugger/qmldebugger.h delete mode 100644 tools/qmldebugger/qmldebugger.pri delete mode 100644 tools/qmldebugger/qmldebugger.pro delete mode 100644 tools/qmldebugger/qmldebugger.qrc delete mode 100644 tools/qmldebugger/refresh.png create mode 100644 tools/qmldebugger/standalone/canvasframerate.cpp create mode 100644 tools/qmldebugger/standalone/canvasframerate.h create mode 100644 tools/qmldebugger/standalone/engine.cpp create mode 100644 tools/qmldebugger/standalone/engine.h create mode 100644 tools/qmldebugger/standalone/engine.png create mode 100644 tools/qmldebugger/standalone/engines.qml create mode 100644 tools/qmldebugger/standalone/expressionquerywidget.cpp create mode 100644 tools/qmldebugger/standalone/expressionquerywidget.h create mode 100644 tools/qmldebugger/standalone/main.cpp create mode 100644 tools/qmldebugger/standalone/objectpropertiesview.cpp create mode 100644 tools/qmldebugger/standalone/objectpropertiesview.h create mode 100644 tools/qmldebugger/standalone/objecttree.cpp create mode 100644 tools/qmldebugger/standalone/objecttree.h create mode 100644 tools/qmldebugger/standalone/qmldebugger.cpp create mode 100644 tools/qmldebugger/standalone/qmldebugger.h create mode 100644 tools/qmldebugger/standalone/qmldebugger.pri create mode 100644 tools/qmldebugger/standalone/qmldebugger.qrc create mode 100644 tools/qmldebugger/standalone/refresh.png create mode 100644 tools/qmldebugger/standalone/standalone.pro create mode 100644 tools/qmldebugger/standalone/watchtable.cpp create mode 100644 tools/qmldebugger/standalone/watchtable.h delete mode 100644 tools/qmldebugger/watchtable.cpp delete mode 100644 tools/qmldebugger/watchtable.h diff --git a/tools/qmldebugger/canvasframerate.cpp b/tools/qmldebugger/canvasframerate.cpp deleted file mode 100644 index 10c3dbf..0000000 --- a/tools/qmldebugger/canvasframerate.cpp +++ /dev/null @@ -1,368 +0,0 @@ -#include "canvasframerate.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -QT_BEGIN_NAMESPACE - -class QLineGraph : public QWidget -{ -Q_OBJECT -public: - QLineGraph(QWidget * = 0); - - void setPosition(int); - -public slots: - void addSample(int, int, int, bool); - void setResolutionForHeight(int); - -protected: - virtual void paintEvent(QPaintEvent *); - -private slots: - void scrollbarChanged(int); - -private: - void updateScrollbar(); - void drawSample(QPainter *, int, const QRect &); - void drawTime(QPainter *, const QRect &); - struct Sample { - int sample[3]; - 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) -{ - setMinimumHeight(200); - - sb.setMaximum(0); - sb.setMinimum(0); - sb.setSingleStep(1); - - QVBoxLayout *layout = new QVBoxLayout; - setLayout(layout); - layout->addStretch(2); - layout->addWidget(&sb); - QObject::connect(&sb, SIGNAL(valueChanged(int)), this, SLOT(scrollbarChanged(int))); -} - -void QLineGraph::scrollbarChanged(int v) -{ - if(ignoreScroll) - return; - - if (v == sb.maximum()) - position = -1; - else - position = v; - 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 d, bool isBreak) -{ - Sample s; - s.isBreak = isBreak; - s.sample[0] = a; - s.sample[1] = b; - s.sample[2] = d; - _samples << s; - updateScrollbar(); - update(); -} - -void QLineGraph::setPosition(int p) -{ - scrollbarChanged(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) -{ - 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)) - 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(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); -} - -void QLineGraph::setResolutionForHeight(int resolution) -{ - resolutionForHeight = resolution; - update(); -} - -class CanvasFrameRatePlugin : public QmlDebugClient -{ -Q_OBJECT -public: - CanvasFrameRatePlugin(QmlDebugConnection *client); - -signals: - void sample(int, int, int, bool); - -protected: - virtual void messageReceived(const QByteArray &); - -private: - int lb; - int ld; -}; - -CanvasFrameRatePlugin::CanvasFrameRatePlugin(QmlDebugConnection *client) -: QmlDebugClient(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) -{ - QVBoxLayout *layout = new QVBoxLayout; - layout->setContentsMargins(0,0,0,0); - layout->setSpacing(0); - setLayout(layout); - - m_tabs = new QTabWidget(this); - layout->addWidget(m_tabs); - - QHBoxLayout *bottom = new QHBoxLayout; - bottom->setContentsMargins(5, 0, 5, 0); - bottom->setSpacing(10); - layout->addLayout(bottom); - - QLabel *label = new QLabel("Resolution", this); - bottom->addWidget(label); - - m_spin = new QSpinBox(this); - m_spin->setRange(50,200); - m_spin->setValue(50); - m_spin->setSuffix("ms"); - bottom->addWidget(m_spin); - - bottom->addStretch(2); - - m_enabledCheckBox = new QCheckBox("Enable", this); - bottom->addWidget(m_enabledCheckBox); - QObject::connect(m_enabledCheckBox, SIGNAL(stateChanged(int)), - this, SLOT(enabledStateChanged(int))); - - QPushButton *pb = new QPushButton(tr("New Tab"), this); - QObject::connect(pb, SIGNAL(clicked()), this, SLOT(newTab())); - bottom->addWidget(pb); -} - -void CanvasFrameRate::reset(QmlDebugConnection *conn) -{ - delete m_plugin; - m_plugin = 0; - - QWidget *w; - for (int i=0; icount(); 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(sender())); - } -} - -void CanvasFrameRate::handleConnected(QmlDebugConnection *conn) -{ - delete m_plugin; - m_plugin = new CanvasFrameRatePlugin(conn); - enabledStateChanged(m_enabledCheckBox->checkState()); - newTab(); -} - -void CanvasFrameRate::setSizeHint(const QSize &size) -{ - m_sizeHint = size; -} - -QSize CanvasFrameRate::sizeHint() const -{ - return m_sizeHint; -} - -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 id = m_tabs->count(); - - QLineGraph *graph = new QLineGraph(this); - QObject::connect(m_plugin, SIGNAL(sample(int,int,int,bool)), - graph, SLOT(addSample(int,int,int,bool))); - QObject::connect(m_spin, SIGNAL(valueChanged(int)), graph, SLOT(setResolutionForHeight(int))); - - QString name = QLatin1String("Graph ") + QString::number(id); - m_tabs->addTab(graph, name); - m_tabs->setCurrentIndex(id); -} - -void CanvasFrameRate::enabledStateChanged(int s) -{ - bool checked = s != 0; - - if (m_plugin) - static_cast(m_plugin)->setEnabled(checked); -} - -QT_END_NAMESPACE - -#include "canvasframerate.moc" diff --git a/tools/qmldebugger/canvasframerate.h b/tools/qmldebugger/canvasframerate.h deleted file mode 100644 index 6c1ff9f..0000000 --- a/tools/qmldebugger/canvasframerate.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef CANVASFRAMERATE_H -#define CANVASFRAMERATE_H - -#include -#include - -#include - -QT_BEGIN_NAMESPACE - -class QTabWidget; -class QSpinBox; -class QCheckBox; - -class CanvasFrameRatePlugin; - -class CanvasFrameRate : public QWidget -{ - Q_OBJECT -public: - CanvasFrameRate(QWidget *parent = 0); - - void reset(QmlDebugConnection *conn); - - void setSizeHint(const QSize &); - virtual QSize sizeHint() const; - -private slots: - void newTab(); - void enabledStateChanged(int); - void connectionStateChanged(QAbstractSocket::SocketState state); - -private: - void handleConnected(QmlDebugConnection *conn); - - QTabWidget *m_tabs; - QSpinBox *m_spin; - CanvasFrameRatePlugin *m_plugin; - QSize m_sizeHint; - QCheckBox *m_enabledCheckBox; -}; - -QT_END_NAMESPACE - -#endif // CANVASFRAMERATE_H - diff --git a/tools/qmldebugger/engine.cpp b/tools/qmldebugger/engine.cpp deleted file mode 100644 index a1fd009..0000000 --- a/tools/qmldebugger/engine.cpp +++ /dev/null @@ -1,179 +0,0 @@ -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "engine.h" -#include "objectpropertiesview.h" -#include "expressionquerywidget.h" -#include "objecttree.h" -#include "watchtable.h" - -QT_BEGIN_NAMESPACE - - -class DebuggerEngineItem : public QObject -{ - Q_OBJECT - Q_PROPERTY(QString name READ name CONSTANT); - Q_PROPERTY(int engineId READ engineId CONSTANT); - -public: - DebuggerEngineItem(const QString &name, int id) - : m_name(name), m_engineId(id) {} - - QString name() const { return m_name; } - int engineId() const { return m_engineId; } - -private: - QString m_name; - int m_engineId; -}; - -EnginePane::EnginePane(QmlDebugConnection *conn, QWidget *parent) -: QWidget(parent), m_client(new QmlEngineDebug(conn, this)), m_engines(0), m_context(0), m_watchTableModel(0), m_exprQueryWidget(0) -{ - QVBoxLayout *layout = new QVBoxLayout(this); - layout->setContentsMargins(0, 0, 0, 0); - - QFile enginesFile(":/engines.qml"); - enginesFile.open(QFile::ReadOnly); - Q_ASSERT(enginesFile.isOpen()); - - m_engineView = new QmlView(this); - m_engineView->rootContext()->setContextProperty("engines", qVariantFromValue(&m_engineItems)); - m_engineView->setContentResizable(true); - m_engineView->setQml(enginesFile.readAll()); - m_engineView->execute(); - m_engineView->setFixedHeight(100); - QObject::connect(m_engineView->root(), SIGNAL(engineClicked(int)), - this, SLOT(engineSelected(int))); - QObject::connect(m_engineView->root(), SIGNAL(refreshEngines()), - this, SLOT(refreshEngines())); - - m_engineView->setVisible(false); - layout->addWidget(m_engineView); - - QSplitter *splitter = new QSplitter; - - m_objTree = new ObjectTree(m_client, this); - m_propertiesView = new ObjectPropertiesView(m_client); - m_watchTableModel = new WatchTableModel(m_client, this); - - m_watchTableView = new WatchTableView(m_watchTableModel); - m_watchTableView->setModel(m_watchTableModel); - WatchTableHeaderView *header = new WatchTableHeaderView(m_watchTableModel); - m_watchTableView->setHorizontalHeader(header); - - connect(m_objTree, SIGNAL(currentObjectChanged(QmlDebugObjectReference)), - m_propertiesView, SLOT(reload(QmlDebugObjectReference))); - connect(m_objTree, SIGNAL(expressionWatchRequested(QmlDebugObjectReference,QString)), - m_watchTableModel, SLOT(expressionWatchRequested(QmlDebugObjectReference,QString))); - - connect(m_propertiesView, SIGNAL(activated(QmlDebugObjectReference,QmlDebugPropertyReference)), - m_watchTableModel, SLOT(togglePropertyWatch(QmlDebugObjectReference,QmlDebugPropertyReference))); - - connect(m_watchTableModel, SIGNAL(watchCreated(QmlDebugWatch*)), - m_propertiesView, SLOT(watchCreated(QmlDebugWatch*))); - - connect(m_watchTableView, SIGNAL(objectActivated(int)), - m_objTree, SLOT(setCurrentObject(int))); - - m_exprQueryWidget = new ExpressionQueryWidget(m_client); - connect(m_objTree, SIGNAL(currentObjectChanged(QmlDebugObjectReference)), - m_exprQueryWidget, SLOT(setCurrentObject(QmlDebugObjectReference))); - - QSplitter *propertiesTab = new QSplitter(Qt::Vertical); - propertiesTab->addWidget(m_propertiesView); - propertiesTab->addWidget(m_exprQueryWidget); - propertiesTab->setStretchFactor(0, 2); - propertiesTab->setStretchFactor(1, 1); - - m_tabs = new QTabWidget(this); - m_tabs->addTab(propertiesTab, tr("Properties")); - m_tabs->addTab(m_watchTableView, tr("Watched")); - - splitter->addWidget(m_objTree); - splitter->addWidget(m_tabs); - splitter->setStretchFactor(1, 2); - layout->addWidget(splitter); -} - -void EnginePane::engineSelected(int id) -{ - qWarning() << "Engine selected" << id; - queryContext(id); -} - -void EnginePane::queryContext(int id) -{ - if (m_context) { - delete m_context; - m_context = 0; - } - - m_context = m_client->queryRootContexts(QmlDebugEngineReference(id), this); - if (!m_context->isWaiting()) - contextChanged(); - else - QObject::connect(m_context, SIGNAL(stateChanged(State)), - this, SLOT(contextChanged())); -} - -void EnginePane::contextChanged() -{ - //dump(m_context->rootContext(), 0); - - foreach (const QmlDebugObjectReference &object, m_context->rootContext().objects()) - m_objTree->reload(object.debugId()); - - delete m_context; m_context = 0; -} - -void EnginePane::refreshEngines() -{ - if (m_engines) - return; - - m_engines = m_client->queryAvailableEngines(this); - if (!m_engines->isWaiting()) - enginesChanged(); - else - QObject::connect(m_engines, SIGNAL(stateChanged(State)), - this, SLOT(enginesChanged())); -} - -void EnginePane::enginesChanged() -{ - qDeleteAll(m_engineItems); - m_engineItems.clear(); - - QList engines = m_engines->engines(); - delete m_engines; m_engines = 0; - - if (engines.isEmpty()) - qWarning("qmldebugger: no engines found!"); - - for (int ii = 0; ii < engines.count(); ++ii) - m_engineItems << new DebuggerEngineItem(engines.at(ii).name(), - engines.at(ii).debugId()); - - m_engineView->rootContext()->setContextProperty("engines", qVariantFromValue(&m_engineItems)); - - m_engineView->setVisible(m_engineItems.count() > 1); - if (m_engineItems.count() == 1) - engineSelected(qobject_cast(m_engineItems.at(0))->engineId()); -} - - -#include "engine.moc" - -QT_END_NAMESPACE - diff --git a/tools/qmldebugger/engine.h b/tools/qmldebugger/engine.h deleted file mode 100644 index a3ebe46..0000000 --- a/tools/qmldebugger/engine.h +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef ENGINE_H -#define ENGINE_H - -#include -#include -#include -#include -#include -#include - -QT_BEGIN_NAMESPACE - -class ObjectPropertiesView; -class QmlDebugConnection; -class QmlDebugPropertyReference; -class QmlDebugWatch; -class ObjectTree; -class WatchTableModel; -class WatchTableView; -class ExpressionQueryWidget; - -class QTabWidget; - -class EnginePane : public QWidget -{ -Q_OBJECT -public: - EnginePane(QmlDebugConnection *, QWidget *parent = 0); - -public slots: - void refreshEngines(); - -private slots: - void enginesChanged(); - - void queryContext(int); - void contextChanged(); - - void engineSelected(int); - -private: - QmlEngineDebug *m_client; - QmlDebugEnginesQuery *m_engines; - QmlDebugRootContextQuery *m_context; - - ObjectTree *m_objTree; - QTabWidget *m_tabs; - WatchTableView *m_watchTableView; - WatchTableModel *m_watchTableModel; - ExpressionQueryWidget *m_exprQueryWidget; - - QmlView *m_engineView; - QList m_engineItems; - - ObjectPropertiesView *m_propertiesView; -}; - -QT_END_NAMESPACE - -#endif // ENGINE_H - diff --git a/tools/qmldebugger/engine.png b/tools/qmldebugger/engine.png deleted file mode 100644 index a0a8a04..0000000 Binary files a/tools/qmldebugger/engine.png and /dev/null differ diff --git a/tools/qmldebugger/engines.qml b/tools/qmldebugger/engines.qml deleted file mode 100644 index 1e9335b..0000000 --- a/tools/qmldebugger/engines.qml +++ /dev/null @@ -1,46 +0,0 @@ -import Qt 4.6 - -Item { - height: 100 - id: Root - signal engineClicked(int id) - signal refreshEngines() - - Row { - anchors.fill: parent - Repeater { - model: engines - Item { - width: 100; height: 100; - Image { - id: EngineIcon; - source: "qrc:/engine.png" - anchors.horizontalCenter: parent.horizontalCenter - } - Text { - anchors.top: EngineIcon.bottom; - text: modelData.name + "(" + modelData.engineId + ")" - anchors.horizontalCenter: parent.horizontalCenter - } - MouseRegion { - anchors.fill: parent - onClicked: Root.engineClicked(modelData.engineId); - } - } - } - } - - - Image { - y: 15 - source: "qrc:/refresh.png"; - width: 75; - height: 63; - smooth: true - anchors.right: parent.right - MouseRegion { - anchors.fill: parent - onClicked: Root.refreshEngines() - } - } -} diff --git a/tools/qmldebugger/expressionquerywidget.cpp b/tools/qmldebugger/expressionquerywidget.cpp deleted file mode 100644 index f8f5aef..0000000 --- a/tools/qmldebugger/expressionquerywidget.cpp +++ /dev/null @@ -1,218 +0,0 @@ -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "expressionquerywidget.h" - -ExpressionQueryWidget::ExpressionQueryWidget(QmlEngineDebug *client, QWidget *parent) - : QWidget(parent), - m_style(Compact), - m_client(client), - m_query(0), - m_textEdit(new QTextEdit), - m_lineEdit(0) -{ - m_prompt = QLatin1String(">> "); - - QVBoxLayout *layout = new QVBoxLayout(this); - layout->setMargin(0); - layout->setSpacing(0); - layout->addWidget(m_textEdit); - - updateTitle(); - - if (m_style == Compact) { - m_lineEdit = new QLineEdit; - connect(m_lineEdit, SIGNAL(returnPressed()), SLOT(executeExpression())); - QHBoxLayout *hbox = new QHBoxLayout; - hbox->setMargin(5); - hbox->setSpacing(5); - hbox->addWidget(new QLabel(tr("Expression:"))); - hbox->addWidget(m_lineEdit); - layout->addLayout(hbox); - - m_textEdit->setReadOnly(true); - m_lineEdit->installEventFilter(this); - } else { - m_textEdit->installEventFilter(this); - } -} - -void ExpressionQueryWidget::setEngineDebug(QmlEngineDebug *client) -{ - m_client = client; -} - -void ExpressionQueryWidget::clear() -{ - m_textEdit->clear(); - m_lineEdit->clear(); -} - -void ExpressionQueryWidget::updateTitle() -{ - if (m_currObject.debugId() < 0) { - m_title = tr("Expression queries"); - } else { - QString desc = QLatin1String("<") - + m_currObject.className() + QLatin1String(": ") - + (m_currObject.name().isEmpty() ? QLatin1String("") : m_currObject.name()) - + QLatin1String(">"); - m_title = tr("Expression queries (using context for %1)" , "Selected object").arg(desc); - } -} - -void ExpressionQueryWidget::appendPrompt() -{ - m_textEdit->moveCursor(QTextCursor::End); - - if (m_style == Compact) { - m_textEdit->insertPlainText("\n"); - } else { - m_textEdit->setTextColor(Qt::gray); - m_textEdit->append(m_prompt); - } -} - -void ExpressionQueryWidget::setCurrentObject(const QmlDebugObjectReference &obj) -{ - m_currObject = obj; - updateTitle(); -} - -void ExpressionQueryWidget::checkCurrentContext() -{ - m_textEdit->moveCursor(QTextCursor::End); - - if (m_currObject.debugId() != -1 && m_currObject.debugId() != m_objectAtLastFocus.debugId()) - showCurrentContext(); - m_objectAtLastFocus = m_currObject; -} - -void ExpressionQueryWidget::showCurrentContext() -{ - m_textEdit->moveCursor(QTextCursor::End); - m_textEdit->setTextColor(Qt::darkGreen); - m_textEdit->append(m_currObject.className() - + QLatin1String(": ") - + (m_currObject.name().isEmpty() ? QLatin1String("") : m_currObject.name())); - appendPrompt(); -} - -void ExpressionQueryWidget::executeExpression() -{ - if (!m_client) - return; - - if (m_style == Compact) - m_expr = m_lineEdit->text().trimmed(); - else - m_expr = m_expr.trimmed(); - - if (!m_expr.isEmpty() && m_currObject.debugId() != -1) { - if (m_query) - delete m_query; - m_query = m_client->queryExpressionResult(m_currObject.debugId(), m_expr, this); - if (!m_query->isWaiting()) - showResult(); - else - QObject::connect(m_query, SIGNAL(stateChanged(State)), - this, SLOT(showResult())); - - m_lastExpr = m_expr; - if (m_lineEdit) - m_lineEdit->clear(); - } -} - -void ExpressionQueryWidget::showResult() -{ - if (m_query) { - m_textEdit->moveCursor(QTextCursor::End); - QString result; - if (m_query->result().isNull()) - result = QLatin1String(""); - else - result = m_query->result().toString(); - - if (m_style == Compact) { - m_textEdit->setTextColor(Qt::black); - m_textEdit->setFontWeight(QFont::Bold); - m_textEdit->insertPlainText(m_expr + " : "); - m_textEdit->setFontWeight(QFont::Normal); - m_textEdit->insertPlainText(result); - } else { - m_textEdit->append(result); - } - appendPrompt(); - m_expr.clear(); - } -} - -bool ExpressionQueryWidget::eventFilter(QObject *obj, QEvent *event) -{ - if (obj == m_textEdit) { - switch (event->type()) { - case QEvent::KeyPress: - { - QKeyEvent *keyEvent = static_cast(event); - int key = keyEvent->key(); - if (key == Qt::Key_Return || key == Qt::Key_Enter) { - executeExpression(); - return true; - } else if (key == Qt::Key_Backspace) { - // ensure m_expr doesn't contain backspace characters - QTextCursor cursor = m_textEdit->textCursor(); - bool atLastLine = !(cursor.block().next().isValid()); - if (!atLastLine) - return true; - if (cursor.columnNumber() <= m_prompt.count()) - return true; - cursor.deletePreviousChar(); - m_expr = cursor.block().text().mid(m_prompt.count()); - return true; - } else { - m_textEdit->moveCursor(QTextCursor::End); - m_textEdit->setTextColor(Qt::black); - m_expr += keyEvent->text(); - } - break; - } - case QEvent::FocusIn: - checkCurrentContext(); - m_textEdit->moveCursor(QTextCursor::End); - break; - default: - break; - } - } else if (obj == m_lineEdit) { - switch (event->type()) { - case QEvent::KeyPress: - { - QKeyEvent *keyEvent = static_cast(event); - int key = keyEvent->key(); - if (key == Qt::Key_Up && m_lineEdit->text() != m_lastExpr) { - m_expr = m_lineEdit->text(); - if (!m_lastExpr.isEmpty()) - m_lineEdit->setText(m_lastExpr); - } else if (key == Qt::Key_Down) { - m_lineEdit->setText(m_expr); - } - break; - } - case QEvent::FocusIn: - checkCurrentContext(); - break; - default: - break; - } - } - return QWidget::eventFilter(obj, event); -} diff --git a/tools/qmldebugger/expressionquerywidget.h b/tools/qmldebugger/expressionquerywidget.h deleted file mode 100644 index 6fab059..0000000 --- a/tools/qmldebugger/expressionquerywidget.h +++ /dev/null @@ -1,65 +0,0 @@ -#ifndef EXPRESSIONQUERYWIDGET_H -#define EXPRESSIONQUERYWIDGET_H - -#include - -#include - -QT_BEGIN_NAMESPACE - -class QGroupBox; -class QTextEdit; -class QLineEdit; -class QPushButton; - -class ExpressionQueryWidget : public QWidget -{ - Q_OBJECT -public: - enum Style { - Compact, - Shell - }; - - ExpressionQueryWidget(QmlEngineDebug *client = 0, QWidget *parent = 0); - - void setEngineDebug(QmlEngineDebug *client); - void clear(); - -protected: - bool eventFilter(QObject *obj, QEvent *event); - -public slots: - void setCurrentObject(const QmlDebugObjectReference &obj); - -private slots: - void executeExpression(); - void showResult(); - -private: - void appendPrompt(); - void checkCurrentContext(); - void showCurrentContext(); - void updateTitle(); - - Style m_style; - - QmlEngineDebug *m_client; - QmlDebugExpressionQuery *m_query; - QTextEdit *m_textEdit; - QLineEdit *m_lineEdit; - QPushButton *m_button; - QString m_prompt; - QString m_expr; - QString m_lastExpr; - - QString m_title; - - QmlDebugObjectReference m_currObject; - QmlDebugObjectReference m_objectAtLastFocus; -}; - -QT_END_NAMESPACE - -#endif - diff --git a/tools/qmldebugger/main.cpp b/tools/qmldebugger/main.cpp deleted file mode 100644 index c9983cd..0000000 --- a/tools/qmldebugger/main.cpp +++ /dev/null @@ -1,34 +0,0 @@ -#include - -#include "qmldebugger.h" - -int main(int argc, char ** argv) -{ - QApplication app(argc, argv); - - QStringList args = app.arguments(); - - QmlDebugger win; - if (args.contains("--engine")) - win.showEngineTab(); - - for (int i=0; i - -#include -#include - -#include -#include -#include - -#include "objectpropertiesview.h" - -QT_BEGIN_NAMESPACE - -class PropertiesViewItem : public QObject, public QTreeWidgetItem -{ - Q_OBJECT -public: - PropertiesViewItem(QTreeWidget *widget); - PropertiesViewItem(QTreeWidgetItem *parent); - - QmlDebugPropertyReference property; -}; - -PropertiesViewItem::PropertiesViewItem(QTreeWidget *widget) - : QTreeWidgetItem(widget) -{ -} - -PropertiesViewItem::PropertiesViewItem(QTreeWidgetItem *parent) - : QTreeWidgetItem(parent) -{ -} - -ObjectPropertiesView::ObjectPropertiesView(QmlEngineDebug *client, QWidget *parent) - : QWidget(parent), - m_client(client), - m_query(0), - m_watch(0) -{ - QVBoxLayout *layout = new QVBoxLayout; - layout->setContentsMargins(0, 0, 0, 0); - layout->setSpacing(0); - setLayout(layout); - - m_tree = new QTreeWidget(this); - m_tree->setAlternatingRowColors(true); - m_tree->setExpandsOnDoubleClick(false); - m_tree->setHeaderLabels(QStringList() << tr("Property") << tr("Value")); - QObject::connect(m_tree, SIGNAL(itemActivated(QTreeWidgetItem *, int)), - this, SLOT(itemActivated(QTreeWidgetItem *))); - - m_tree->setColumnCount(2); - - layout->addWidget(m_tree); -} - -void ObjectPropertiesView::setEngineDebug(QmlEngineDebug *client) -{ - m_client = client; -} - -void ObjectPropertiesView::clear() -{ - setObject(QmlDebugObjectReference()); -} - -void ObjectPropertiesView::reload(const QmlDebugObjectReference &obj) -{ - if (!m_client) - return; - if (m_query) - delete m_query; - - m_query = m_client->queryObjectRecursive(obj, this); - if (!m_query->isWaiting()) - queryFinished(); - else - QObject::connect(m_query, SIGNAL(stateChanged(State)), - this, SLOT(queryFinished())); -} - -void ObjectPropertiesView::queryFinished() -{ - if (!m_client || !m_query) - return; - - QmlDebugObjectReference obj = m_query->object(); - - QmlDebugWatch *watch = m_client->addWatch(obj, this); - if (watch->state() == QmlDebugWatch::Dead) { - delete watch; - watch = 0; - } else { - if (m_watch) { - m_client->removeWatch(m_watch); - delete m_watch; - } - m_watch = watch; - QObject::connect(watch, SIGNAL(valueChanged(QByteArray,QVariant)), - this, SLOT(valueChanged(QByteArray,QVariant))); - } - - delete m_query; - m_query = 0; - - setObject(obj); -} - -void ObjectPropertiesView::setObject(const QmlDebugObjectReference &object) -{ - m_object = object; - m_tree->clear(); - - QList properties = object.properties(); - for (int i=0; iproperty = p; - - item->setText(0, p.name()); - item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); - if (!p.hasNotifySignal()) { - item->setForeground(0, Qt::gray); - item->setForeground(1, Qt::gray); - } - - if (!p.binding().isEmpty()) { - PropertiesViewItem *binding = new PropertiesViewItem(item); - binding->setText(1, p.binding()); - binding->setForeground(1, Qt::darkGreen); - } - - item->setExpanded(true); - } - - m_tree->resizeColumnToContents(0); -} - -void ObjectPropertiesView::watchCreated(QmlDebugWatch *watch) -{ - if (watch->objectDebugId() == m_object.debugId() - && qobject_cast(watch)) { - connect(watch, SIGNAL(stateChanged(State)), SLOT(watchStateChanged())); - setWatched(qobject_cast(watch)->name(), true); - } -} - -void ObjectPropertiesView::watchStateChanged() -{ - QmlDebugWatch *watch = qobject_cast(sender()); - - if (watch->objectDebugId() == m_object.debugId() - && qobject_cast(watch) - && watch->state() == QmlDebugWatch::Inactive) { - setWatched(qobject_cast(watch)->name(), false); - } -} - -void ObjectPropertiesView::setWatched(const QString &property, bool watched) -{ - for (int i=0; itopLevelItemCount(); i++) { - PropertiesViewItem *item = static_cast(m_tree->topLevelItem(i)); - if (item->property.name() == property && item->property.hasNotifySignal()) { - QFont font = m_tree->font(); - font.setBold(watched); - item->setFont(0, font); - } - } -} - -void ObjectPropertiesView::valueChanged(const QByteArray &name, const QVariant &value) -{ - for (int i=0; itopLevelItemCount(); i++) { - PropertiesViewItem *item = static_cast(m_tree->topLevelItem(i)); - if (item->property.name() == name) { - if (value.isNull()) { - item->setText(1, QLatin1String("") - + QLatin1String(" : ") - + item->property.valueTypeName()); - } else { - item->setText(1, value.toString()); - } - } - } -} - -void ObjectPropertiesView::itemActivated(QTreeWidgetItem *i) -{ - PropertiesViewItem *item = static_cast(i); - if (!item->property.name().isEmpty()) - emit activated(m_object, item->property); -} - -QT_END_NAMESPACE - -#include "objectpropertiesview.moc" diff --git a/tools/qmldebugger/objectpropertiesview.h b/tools/qmldebugger/objectpropertiesview.h deleted file mode 100644 index 6a1fc03..0000000 --- a/tools/qmldebugger/objectpropertiesview.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef PROPERTIESTABLEMODEL_H -#define PROPERTIESTABLEMODEL_H - -#include - -#include - -QT_BEGIN_NAMESPACE - -class QTreeWidget; -class QTreeWidgetItem; -class QmlDebugConnection; - -class ObjectPropertiesView : public QWidget -{ - Q_OBJECT -public: - ObjectPropertiesView(QmlEngineDebug *client = 0, QWidget *parent = 0); - - void setEngineDebug(QmlEngineDebug *client); - void clear(); - -signals: - void activated(const QmlDebugObjectReference &, const QmlDebugPropertyReference &); - -public slots: - void reload(const QmlDebugObjectReference &); - void watchCreated(QmlDebugWatch *); - -private slots: - void queryFinished(); - void watchStateChanged(); - void valueChanged(const QByteArray &name, const QVariant &value); - void itemActivated(QTreeWidgetItem *i); - -private: - void setObject(const QmlDebugObjectReference &object); - void setWatched(const QString &property, bool watched); - - QmlEngineDebug *m_client; - QmlDebugObjectQuery *m_query; - QmlDebugWatch *m_watch; - - QTreeWidget *m_tree; - QmlDebugObjectReference m_object; -}; - - -QT_END_NAMESPACE - -#endif diff --git a/tools/qmldebugger/objecttree.cpp b/tools/qmldebugger/objecttree.cpp deleted file mode 100644 index 4059e77..0000000 --- a/tools/qmldebugger/objecttree.cpp +++ /dev/null @@ -1,180 +0,0 @@ -#include -#include -#include - -#include - -#include -#include -#include - -#include "objecttree.h" - -Q_DECLARE_METATYPE(QmlDebugObjectReference) - -ObjectTree::ObjectTree(QmlEngineDebug *client, QWidget *parent) - : QTreeWidget(parent), - m_client(client), - m_query(0) -{ - setHeaderHidden(true); - setMinimumWidth(250); - - connect(this, SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)), - this, SLOT(currentItemChanged(QTreeWidgetItem *))); -} - -void ObjectTree::setEngineDebug(QmlEngineDebug *client) -{ - m_client = client; -} - -void ObjectTree::reload(int objectDebugId) -{ - if (!m_client) - return; - - if (m_query) { - delete m_query; - m_query = 0; - } - - m_query = m_client->queryObjectRecursive(QmlDebugObjectReference(objectDebugId), this); - if (!m_query->isWaiting()) - objectFetched(); - else - QObject::connect(m_query, SIGNAL(stateChanged(State)), - this, SLOT(objectFetched())); -} - -void ObjectTree::setCurrentObject(int debugId) -{ - QTreeWidgetItem *item = findItemByObjectId(debugId); - if (item) { - setCurrentItem(item); - scrollToItem(item); - item->setExpanded(true); - } -} - -void ObjectTree::objectFetched() -{ - dump(m_query->object(), 0); - buildTree(m_query->object(), 0); - - delete m_query; - m_query = 0; -} - -void ObjectTree::currentItemChanged(QTreeWidgetItem *item) -{ - if (!item) - return; - - QmlDebugObjectReference obj = item->data(0, Qt::UserRole).value(); - if (obj.debugId() < 0) { - qWarning("QML Object Tree: bad object id"); - return; - } - emit currentObjectChanged(obj); -} - -void ObjectTree::buildTree(const QmlDebugObjectReference &obj, QTreeWidgetItem *parent) -{ - if (!parent) - clear(); - - QTreeWidgetItem *item = parent ? new QTreeWidgetItem(parent) : new QTreeWidgetItem(this); - item->setText(0, obj.className()); - item->setData(0, Qt::UserRole, qVariantFromValue(obj)); - - if (parent && obj.contextDebugId() >= 0 - && obj.contextDebugId() != parent->data(0, Qt::UserRole - ).value().contextDebugId()) { - QmlDebugFileReference source = obj.source(); - if (!source.url().isEmpty()) { - QString toolTipString = QLatin1String("URL: ") + source.url().toString(); - item->setToolTip(0, toolTipString); - } - item->setForeground(0, QColor("orange")); - } else { - item->setExpanded(true); - } - - if (obj.contextDebugId() < 0) - item->setForeground(0, Qt::lightGray); - - for (int ii = 0; ii < obj.children().count(); ++ii) - buildTree(obj.children().at(ii), item); -} - -void ObjectTree::dump(const QmlDebugContextReference &ctxt, int ind) -{ - QByteArray indent(ind * 4, ' '); - qWarning().nospace() << indent.constData() << ctxt.debugId() << " " - << qPrintable(ctxt.name()); - - for (int ii = 0; ii < ctxt.contexts().count(); ++ii) - dump(ctxt.contexts().at(ii), ind + 1); - - for (int ii = 0; ii < ctxt.objects().count(); ++ii) - dump(ctxt.objects().at(ii), ind); -} - -void ObjectTree::dump(const QmlDebugObjectReference &obj, int ind) -{ - QByteArray indent(ind * 4, ' '); - qWarning().nospace() << indent.constData() << qPrintable(obj.className()) - << " " << qPrintable(obj.name()) << " " - << obj.debugId(); - - for (int ii = 0; ii < obj.children().count(); ++ii) - dump(obj.children().at(ii), ind + 1); -} - -QTreeWidgetItem *ObjectTree::findItemByObjectId(int debugId) const -{ - for (int i=0; idata(0, Qt::UserRole).value().debugId() == debugId) - return item; - - QTreeWidgetItem *child; - for (int i=0; ichildCount(); i++) { - child = findItem(item->child(i), debugId); - if (child) - return child; - } - - return 0; -} - -void ObjectTree::mousePressEvent(QMouseEvent *me) -{ - QTreeWidget::mousePressEvent(me); - if (!currentItem()) - return; - if(me->button() == Qt::RightButton && me->type() == QEvent::MouseButtonPress) { - QAction action(tr("Add watch..."), 0); - QList actions; - actions << &action; - QmlDebugObjectReference obj = - currentItem()->data(0, Qt::UserRole).value(); - if (QMenu::exec(actions, me->globalPos())) { - bool ok = false; - QString watch = QInputDialog::getText(this, tr("Watch expression"), - tr("Expression:"), QLineEdit::Normal, QString(), &ok); - if (ok && !watch.isEmpty()) - emit expressionWatchRequested(obj, watch); - } - } -} diff --git a/tools/qmldebugger/objecttree.h b/tools/qmldebugger/objecttree.h deleted file mode 100644 index 95820f3..0000000 --- a/tools/qmldebugger/objecttree.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef OBJECTTREE_H -#define OBJECTTREE_H - -#include - -QT_BEGIN_NAMESPACE - -class QTreeWidgetItem; - -class QmlEngineDebug; -class QmlDebugObjectReference; -class QmlDebugObjectQuery; -class QmlDebugContextReference; -class QmlDebugConnection; - - -class ObjectTree : public QTreeWidget -{ - Q_OBJECT -public: - ObjectTree(QmlEngineDebug *client = 0, QWidget *parent = 0); - - void setEngineDebug(QmlEngineDebug *client); - -signals: - void currentObjectChanged(const QmlDebugObjectReference &); - void expressionWatchRequested(const QmlDebugObjectReference &, const QString &); - -public slots: - void reload(int objectDebugId); - void setCurrentObject(int debugId); - -protected: - virtual void mousePressEvent(QMouseEvent *); - -private slots: - void objectFetched(); - void currentItemChanged(QTreeWidgetItem *); - -private: - QTreeWidgetItem *findItemByObjectId(int debugId) const; - QTreeWidgetItem *findItem(QTreeWidgetItem *item, int debugId) const; - void dump(const QmlDebugContextReference &, int); - void dump(const QmlDebugObjectReference &, int); - void buildTree(const QmlDebugObjectReference &, QTreeWidgetItem *parent); - - QmlEngineDebug *m_client; - QmlDebugObjectQuery *m_query; -}; - -QT_END_NAMESPACE - - -#endif diff --git a/tools/qmldebugger/qmldebugger.cpp b/tools/qmldebugger/qmldebugger.cpp deleted file mode 100644 index 5455878..0000000 --- a/tools/qmldebugger/qmldebugger.cpp +++ /dev/null @@ -1,131 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -#include "canvasframerate.h" -#include "engine.h" -#include "qmldebugger.h" - -QmlDebugger::QmlDebugger(QWidget *parent) -: QWidget(parent) -{ - QVBoxLayout *layout = new QVBoxLayout; - setLayout(layout); - - - QHBoxLayout *connectLayout = new QHBoxLayout; - layout->addLayout(connectLayout); - connectLayout->addStretch(2); - - m_connectionState = new QLabel(this); - connectLayout->addWidget(m_connectionState); - m_host = new QLineEdit(this); - m_host->setText("127.0.0.1"); - connectLayout->addWidget(m_host); - m_port = new QSpinBox(this); - m_port->setMinimum(1024); - m_port->setMaximum(20000); - m_port->setValue(3768); - connectLayout->addWidget(m_port); - m_connectButton = new QPushButton(tr("Connect"), this); - QObject::connect(m_connectButton, SIGNAL(clicked()), - this, SLOT(connectToHost())); - connectLayout->addWidget(m_connectButton); - m_disconnectButton = new QPushButton(tr("Disconnect"), this); - QObject::connect(m_disconnectButton, SIGNAL(clicked()), - this, SLOT(disconnectFromHost())); - m_disconnectButton->setEnabled(false); - connectLayout->addWidget(m_disconnectButton); - - m_tabs = new QTabWidget(this); - layout->addWidget(m_tabs); - - CanvasFrameRate *cfr = new CanvasFrameRate(this); - cfr->reset(&client); - cfr->setSizeHint(QSize(800, 600)); - m_tabs->addTab(cfr, tr("Frame Rate")); - - m_enginePane = new EnginePane(&client, this); - m_tabs->addTab(m_enginePane, tr("QML Engine")); - - QObject::connect(&client, SIGNAL(stateChanged(QAbstractSocket::SocketState)), - this, SLOT(connectionStateChanged())); - connectionStateChanged(); - - QObject::connect(&client, SIGNAL(error(QAbstractSocket::SocketError)), - this, SLOT(connectionError(QAbstractSocket::SocketError))); - - - m_tabs->setCurrentIndex(1); - connectToHost(); -} - -void QmlDebugger::setHost(const QString &host) -{ - m_host->setText(host); -} - -void QmlDebugger::setPort(quint16 port) -{ - m_port->setValue(port); -} - -void QmlDebugger::showEngineTab() -{ - m_tabs->setCurrentWidget(m_enginePane); -} - -void QmlDebugger::connectionStateChanged() -{ - switch (client.state()) { - default: - case QAbstractSocket::UnconnectedState: - m_connectionState->setText(tr("Disconnected")); - m_connectButton->setEnabled(true); - m_disconnectButton->setEnabled(false); - break; - case QAbstractSocket::HostLookupState: - m_connectionState->setText(tr("Resolving")); - m_connectButton->setEnabled(false); - m_disconnectButton->setEnabled(true); - break; - case QAbstractSocket::ConnectingState: - m_connectionState->setText(tr("Connecting")); - m_connectButton->setEnabled(false); - m_disconnectButton->setEnabled(true); - break; - case QAbstractSocket::ConnectedState: - m_connectionState->setText(tr("Connected")); - m_connectButton->setEnabled(false); - m_disconnectButton->setEnabled(true); - - QTimer::singleShot(0, m_enginePane, SLOT(refreshEngines())); - break; - case QAbstractSocket::ClosingState: - m_connectionState->setText(tr("Closing")); - m_connectButton->setEnabled(false); - m_disconnectButton->setEnabled(false); - break; - } -} - -void QmlDebugger::connectionError(QAbstractSocket::SocketError socketError) -{ - qWarning() << "qmldebugger cannot connect:" << socketError - << client.errorString(); -} - -void QmlDebugger::connectToHost() -{ - client.connectToHost(m_host->text(), m_port->value()); -} - -void QmlDebugger::disconnectFromHost() -{ - client.disconnectFromHost(); -} diff --git a/tools/qmldebugger/qmldebugger.h b/tools/qmldebugger/qmldebugger.h deleted file mode 100644 index 9203e33..0000000 --- a/tools/qmldebugger/qmldebugger.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef QMLDEBUGGER_H -#define QMLDEBUGGER_H - -#include -#include -#include - -class QLabel; -class QLineEdit; -class QSpinBox; -class QPushButton; -class QTabWidget; - -class EnginePane; - -class QmlDebugger : public QWidget -{ - Q_OBJECT -public: - QmlDebugger(QWidget * = 0); - - void setHost(const QString &host); - void setPort(quint16 port); - void showEngineTab(); - -public slots: - void connectToHost(); - void disconnectFromHost(); - -private slots: - void connectionStateChanged(); - void connectionError(QAbstractSocket::SocketError socketError); - -private: - QmlDebugConnection client; - - QLabel *m_connectionState; - QLineEdit *m_host; - QSpinBox *m_port; - QPushButton *m_connectButton; - QPushButton *m_disconnectButton; - - EnginePane *m_enginePane; - QTabWidget *m_tabs; -}; - -#endif diff --git a/tools/qmldebugger/qmldebugger.pri b/tools/qmldebugger/qmldebugger.pri deleted file mode 100644 index c49d334..0000000 --- a/tools/qmldebugger/qmldebugger.pri +++ /dev/null @@ -1,24 +0,0 @@ -QT += network declarative -contains(QT_CONFIG, opengles2)|contains(QT_CONFIG, opengles1): QT += opengl - -# Input -HEADERS += $$PWD/qmldebugger.h \ - $$PWD/canvasframerate.h \ - $$PWD/watchtable.h \ - $$PWD/engine.h \ - $$PWD/objecttree.h \ - $$PWD/objectpropertiesview.h \ - $$PWD/expressionquerywidget.h - -SOURCES += $$PWD/qmldebugger.cpp \ - $$PWD/main.cpp \ - $$PWD/canvasframerate.cpp \ - $$PWD/watchtable.cpp \ - $$PWD/engine.cpp \ - $$PWD/objecttree.cpp \ - $$PWD/objectpropertiesview.cpp \ - $$PWD/expressionquerywidget.cpp - -RESOURCES += $$PWD/qmldebugger.qrc - -OTHER_FILES += $$PWD/engines.qml diff --git a/tools/qmldebugger/qmldebugger.pro b/tools/qmldebugger/qmldebugger.pro deleted file mode 100644 index 4cdfd18..0000000 --- a/tools/qmldebugger/qmldebugger.pro +++ /dev/null @@ -1,8 +0,0 @@ -DESTDIR = ../../bin - -include(qmldebugger.pri) - -target.path=$$[QT_INSTALL_BINS] -INSTALLS += target - -CONFIG += console diff --git a/tools/qmldebugger/qmldebugger.qrc b/tools/qmldebugger/qmldebugger.qrc deleted file mode 100644 index cb53ad5..0000000 --- a/tools/qmldebugger/qmldebugger.qrc +++ /dev/null @@ -1,7 +0,0 @@ - - - engines.qml - engine.png - refresh.png - - diff --git a/tools/qmldebugger/refresh.png b/tools/qmldebugger/refresh.png deleted file mode 100644 index 8befc80..0000000 Binary files a/tools/qmldebugger/refresh.png and /dev/null differ diff --git a/tools/qmldebugger/standalone/canvasframerate.cpp b/tools/qmldebugger/standalone/canvasframerate.cpp new file mode 100644 index 0000000..10c3dbf --- /dev/null +++ b/tools/qmldebugger/standalone/canvasframerate.cpp @@ -0,0 +1,368 @@ +#include "canvasframerate.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QLineGraph : public QWidget +{ +Q_OBJECT +public: + QLineGraph(QWidget * = 0); + + void setPosition(int); + +public slots: + void addSample(int, int, int, bool); + void setResolutionForHeight(int); + +protected: + virtual void paintEvent(QPaintEvent *); + +private slots: + void scrollbarChanged(int); + +private: + void updateScrollbar(); + void drawSample(QPainter *, int, const QRect &); + void drawTime(QPainter *, const QRect &); + struct Sample { + int sample[3]; + 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) +{ + setMinimumHeight(200); + + sb.setMaximum(0); + sb.setMinimum(0); + sb.setSingleStep(1); + + QVBoxLayout *layout = new QVBoxLayout; + setLayout(layout); + layout->addStretch(2); + layout->addWidget(&sb); + QObject::connect(&sb, SIGNAL(valueChanged(int)), this, SLOT(scrollbarChanged(int))); +} + +void QLineGraph::scrollbarChanged(int v) +{ + if(ignoreScroll) + return; + + if (v == sb.maximum()) + position = -1; + else + position = v; + 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 d, bool isBreak) +{ + Sample s; + s.isBreak = isBreak; + s.sample[0] = a; + s.sample[1] = b; + s.sample[2] = d; + _samples << s; + updateScrollbar(); + update(); +} + +void QLineGraph::setPosition(int p) +{ + scrollbarChanged(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) +{ + 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)) + 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(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); +} + +void QLineGraph::setResolutionForHeight(int resolution) +{ + resolutionForHeight = resolution; + update(); +} + +class CanvasFrameRatePlugin : public QmlDebugClient +{ +Q_OBJECT +public: + CanvasFrameRatePlugin(QmlDebugConnection *client); + +signals: + void sample(int, int, int, bool); + +protected: + virtual void messageReceived(const QByteArray &); + +private: + int lb; + int ld; +}; + +CanvasFrameRatePlugin::CanvasFrameRatePlugin(QmlDebugConnection *client) +: QmlDebugClient(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) +{ + QVBoxLayout *layout = new QVBoxLayout; + layout->setContentsMargins(0,0,0,0); + layout->setSpacing(0); + setLayout(layout); + + m_tabs = new QTabWidget(this); + layout->addWidget(m_tabs); + + QHBoxLayout *bottom = new QHBoxLayout; + bottom->setContentsMargins(5, 0, 5, 0); + bottom->setSpacing(10); + layout->addLayout(bottom); + + QLabel *label = new QLabel("Resolution", this); + bottom->addWidget(label); + + m_spin = new QSpinBox(this); + m_spin->setRange(50,200); + m_spin->setValue(50); + m_spin->setSuffix("ms"); + bottom->addWidget(m_spin); + + bottom->addStretch(2); + + m_enabledCheckBox = new QCheckBox("Enable", this); + bottom->addWidget(m_enabledCheckBox); + QObject::connect(m_enabledCheckBox, SIGNAL(stateChanged(int)), + this, SLOT(enabledStateChanged(int))); + + QPushButton *pb = new QPushButton(tr("New Tab"), this); + QObject::connect(pb, SIGNAL(clicked()), this, SLOT(newTab())); + bottom->addWidget(pb); +} + +void CanvasFrameRate::reset(QmlDebugConnection *conn) +{ + delete m_plugin; + m_plugin = 0; + + QWidget *w; + for (int i=0; icount(); 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(sender())); + } +} + +void CanvasFrameRate::handleConnected(QmlDebugConnection *conn) +{ + delete m_plugin; + m_plugin = new CanvasFrameRatePlugin(conn); + enabledStateChanged(m_enabledCheckBox->checkState()); + newTab(); +} + +void CanvasFrameRate::setSizeHint(const QSize &size) +{ + m_sizeHint = size; +} + +QSize CanvasFrameRate::sizeHint() const +{ + return m_sizeHint; +} + +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 id = m_tabs->count(); + + QLineGraph *graph = new QLineGraph(this); + QObject::connect(m_plugin, SIGNAL(sample(int,int,int,bool)), + graph, SLOT(addSample(int,int,int,bool))); + QObject::connect(m_spin, SIGNAL(valueChanged(int)), graph, SLOT(setResolutionForHeight(int))); + + QString name = QLatin1String("Graph ") + QString::number(id); + m_tabs->addTab(graph, name); + m_tabs->setCurrentIndex(id); +} + +void CanvasFrameRate::enabledStateChanged(int s) +{ + bool checked = s != 0; + + if (m_plugin) + static_cast(m_plugin)->setEnabled(checked); +} + +QT_END_NAMESPACE + +#include "canvasframerate.moc" diff --git a/tools/qmldebugger/standalone/canvasframerate.h b/tools/qmldebugger/standalone/canvasframerate.h new file mode 100644 index 0000000..6c1ff9f --- /dev/null +++ b/tools/qmldebugger/standalone/canvasframerate.h @@ -0,0 +1,46 @@ +#ifndef CANVASFRAMERATE_H +#define CANVASFRAMERATE_H + +#include +#include + +#include + +QT_BEGIN_NAMESPACE + +class QTabWidget; +class QSpinBox; +class QCheckBox; + +class CanvasFrameRatePlugin; + +class CanvasFrameRate : public QWidget +{ + Q_OBJECT +public: + CanvasFrameRate(QWidget *parent = 0); + + void reset(QmlDebugConnection *conn); + + void setSizeHint(const QSize &); + virtual QSize sizeHint() const; + +private slots: + void newTab(); + void enabledStateChanged(int); + void connectionStateChanged(QAbstractSocket::SocketState state); + +private: + void handleConnected(QmlDebugConnection *conn); + + QTabWidget *m_tabs; + QSpinBox *m_spin; + CanvasFrameRatePlugin *m_plugin; + QSize m_sizeHint; + QCheckBox *m_enabledCheckBox; +}; + +QT_END_NAMESPACE + +#endif // CANVASFRAMERATE_H + diff --git a/tools/qmldebugger/standalone/engine.cpp b/tools/qmldebugger/standalone/engine.cpp new file mode 100644 index 0000000..a1fd009 --- /dev/null +++ b/tools/qmldebugger/standalone/engine.cpp @@ -0,0 +1,179 @@ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "engine.h" +#include "objectpropertiesview.h" +#include "expressionquerywidget.h" +#include "objecttree.h" +#include "watchtable.h" + +QT_BEGIN_NAMESPACE + + +class DebuggerEngineItem : public QObject +{ + Q_OBJECT + Q_PROPERTY(QString name READ name CONSTANT); + Q_PROPERTY(int engineId READ engineId CONSTANT); + +public: + DebuggerEngineItem(const QString &name, int id) + : m_name(name), m_engineId(id) {} + + QString name() const { return m_name; } + int engineId() const { return m_engineId; } + +private: + QString m_name; + int m_engineId; +}; + +EnginePane::EnginePane(QmlDebugConnection *conn, QWidget *parent) +: QWidget(parent), m_client(new QmlEngineDebug(conn, this)), m_engines(0), m_context(0), m_watchTableModel(0), m_exprQueryWidget(0) +{ + QVBoxLayout *layout = new QVBoxLayout(this); + layout->setContentsMargins(0, 0, 0, 0); + + QFile enginesFile(":/engines.qml"); + enginesFile.open(QFile::ReadOnly); + Q_ASSERT(enginesFile.isOpen()); + + m_engineView = new QmlView(this); + m_engineView->rootContext()->setContextProperty("engines", qVariantFromValue(&m_engineItems)); + m_engineView->setContentResizable(true); + m_engineView->setQml(enginesFile.readAll()); + m_engineView->execute(); + m_engineView->setFixedHeight(100); + QObject::connect(m_engineView->root(), SIGNAL(engineClicked(int)), + this, SLOT(engineSelected(int))); + QObject::connect(m_engineView->root(), SIGNAL(refreshEngines()), + this, SLOT(refreshEngines())); + + m_engineView->setVisible(false); + layout->addWidget(m_engineView); + + QSplitter *splitter = new QSplitter; + + m_objTree = new ObjectTree(m_client, this); + m_propertiesView = new ObjectPropertiesView(m_client); + m_watchTableModel = new WatchTableModel(m_client, this); + + m_watchTableView = new WatchTableView(m_watchTableModel); + m_watchTableView->setModel(m_watchTableModel); + WatchTableHeaderView *header = new WatchTableHeaderView(m_watchTableModel); + m_watchTableView->setHorizontalHeader(header); + + connect(m_objTree, SIGNAL(currentObjectChanged(QmlDebugObjectReference)), + m_propertiesView, SLOT(reload(QmlDebugObjectReference))); + connect(m_objTree, SIGNAL(expressionWatchRequested(QmlDebugObjectReference,QString)), + m_watchTableModel, SLOT(expressionWatchRequested(QmlDebugObjectReference,QString))); + + connect(m_propertiesView, SIGNAL(activated(QmlDebugObjectReference,QmlDebugPropertyReference)), + m_watchTableModel, SLOT(togglePropertyWatch(QmlDebugObjectReference,QmlDebugPropertyReference))); + + connect(m_watchTableModel, SIGNAL(watchCreated(QmlDebugWatch*)), + m_propertiesView, SLOT(watchCreated(QmlDebugWatch*))); + + connect(m_watchTableView, SIGNAL(objectActivated(int)), + m_objTree, SLOT(setCurrentObject(int))); + + m_exprQueryWidget = new ExpressionQueryWidget(m_client); + connect(m_objTree, SIGNAL(currentObjectChanged(QmlDebugObjectReference)), + m_exprQueryWidget, SLOT(setCurrentObject(QmlDebugObjectReference))); + + QSplitter *propertiesTab = new QSplitter(Qt::Vertical); + propertiesTab->addWidget(m_propertiesView); + propertiesTab->addWidget(m_exprQueryWidget); + propertiesTab->setStretchFactor(0, 2); + propertiesTab->setStretchFactor(1, 1); + + m_tabs = new QTabWidget(this); + m_tabs->addTab(propertiesTab, tr("Properties")); + m_tabs->addTab(m_watchTableView, tr("Watched")); + + splitter->addWidget(m_objTree); + splitter->addWidget(m_tabs); + splitter->setStretchFactor(1, 2); + layout->addWidget(splitter); +} + +void EnginePane::engineSelected(int id) +{ + qWarning() << "Engine selected" << id; + queryContext(id); +} + +void EnginePane::queryContext(int id) +{ + if (m_context) { + delete m_context; + m_context = 0; + } + + m_context = m_client->queryRootContexts(QmlDebugEngineReference(id), this); + if (!m_context->isWaiting()) + contextChanged(); + else + QObject::connect(m_context, SIGNAL(stateChanged(State)), + this, SLOT(contextChanged())); +} + +void EnginePane::contextChanged() +{ + //dump(m_context->rootContext(), 0); + + foreach (const QmlDebugObjectReference &object, m_context->rootContext().objects()) + m_objTree->reload(object.debugId()); + + delete m_context; m_context = 0; +} + +void EnginePane::refreshEngines() +{ + if (m_engines) + return; + + m_engines = m_client->queryAvailableEngines(this); + if (!m_engines->isWaiting()) + enginesChanged(); + else + QObject::connect(m_engines, SIGNAL(stateChanged(State)), + this, SLOT(enginesChanged())); +} + +void EnginePane::enginesChanged() +{ + qDeleteAll(m_engineItems); + m_engineItems.clear(); + + QList engines = m_engines->engines(); + delete m_engines; m_engines = 0; + + if (engines.isEmpty()) + qWarning("qmldebugger: no engines found!"); + + for (int ii = 0; ii < engines.count(); ++ii) + m_engineItems << new DebuggerEngineItem(engines.at(ii).name(), + engines.at(ii).debugId()); + + m_engineView->rootContext()->setContextProperty("engines", qVariantFromValue(&m_engineItems)); + + m_engineView->setVisible(m_engineItems.count() > 1); + if (m_engineItems.count() == 1) + engineSelected(qobject_cast(m_engineItems.at(0))->engineId()); +} + + +#include "engine.moc" + +QT_END_NAMESPACE + diff --git a/tools/qmldebugger/standalone/engine.h b/tools/qmldebugger/standalone/engine.h new file mode 100644 index 0000000..a3ebe46 --- /dev/null +++ b/tools/qmldebugger/standalone/engine.h @@ -0,0 +1,61 @@ +#ifndef ENGINE_H +#define ENGINE_H + +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class ObjectPropertiesView; +class QmlDebugConnection; +class QmlDebugPropertyReference; +class QmlDebugWatch; +class ObjectTree; +class WatchTableModel; +class WatchTableView; +class ExpressionQueryWidget; + +class QTabWidget; + +class EnginePane : public QWidget +{ +Q_OBJECT +public: + EnginePane(QmlDebugConnection *, QWidget *parent = 0); + +public slots: + void refreshEngines(); + +private slots: + void enginesChanged(); + + void queryContext(int); + void contextChanged(); + + void engineSelected(int); + +private: + QmlEngineDebug *m_client; + QmlDebugEnginesQuery *m_engines; + QmlDebugRootContextQuery *m_context; + + ObjectTree *m_objTree; + QTabWidget *m_tabs; + WatchTableView *m_watchTableView; + WatchTableModel *m_watchTableModel; + ExpressionQueryWidget *m_exprQueryWidget; + + QmlView *m_engineView; + QList m_engineItems; + + ObjectPropertiesView *m_propertiesView; +}; + +QT_END_NAMESPACE + +#endif // ENGINE_H + diff --git a/tools/qmldebugger/standalone/engine.png b/tools/qmldebugger/standalone/engine.png new file mode 100644 index 0000000..a0a8a04 Binary files /dev/null and b/tools/qmldebugger/standalone/engine.png differ diff --git a/tools/qmldebugger/standalone/engines.qml b/tools/qmldebugger/standalone/engines.qml new file mode 100644 index 0000000..1e9335b --- /dev/null +++ b/tools/qmldebugger/standalone/engines.qml @@ -0,0 +1,46 @@ +import Qt 4.6 + +Item { + height: 100 + id: Root + signal engineClicked(int id) + signal refreshEngines() + + Row { + anchors.fill: parent + Repeater { + model: engines + Item { + width: 100; height: 100; + Image { + id: EngineIcon; + source: "qrc:/engine.png" + anchors.horizontalCenter: parent.horizontalCenter + } + Text { + anchors.top: EngineIcon.bottom; + text: modelData.name + "(" + modelData.engineId + ")" + anchors.horizontalCenter: parent.horizontalCenter + } + MouseRegion { + anchors.fill: parent + onClicked: Root.engineClicked(modelData.engineId); + } + } + } + } + + + Image { + y: 15 + source: "qrc:/refresh.png"; + width: 75; + height: 63; + smooth: true + anchors.right: parent.right + MouseRegion { + anchors.fill: parent + onClicked: Root.refreshEngines() + } + } +} diff --git a/tools/qmldebugger/standalone/expressionquerywidget.cpp b/tools/qmldebugger/standalone/expressionquerywidget.cpp new file mode 100644 index 0000000..f8f5aef --- /dev/null +++ b/tools/qmldebugger/standalone/expressionquerywidget.cpp @@ -0,0 +1,218 @@ +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "expressionquerywidget.h" + +ExpressionQueryWidget::ExpressionQueryWidget(QmlEngineDebug *client, QWidget *parent) + : QWidget(parent), + m_style(Compact), + m_client(client), + m_query(0), + m_textEdit(new QTextEdit), + m_lineEdit(0) +{ + m_prompt = QLatin1String(">> "); + + QVBoxLayout *layout = new QVBoxLayout(this); + layout->setMargin(0); + layout->setSpacing(0); + layout->addWidget(m_textEdit); + + updateTitle(); + + if (m_style == Compact) { + m_lineEdit = new QLineEdit; + connect(m_lineEdit, SIGNAL(returnPressed()), SLOT(executeExpression())); + QHBoxLayout *hbox = new QHBoxLayout; + hbox->setMargin(5); + hbox->setSpacing(5); + hbox->addWidget(new QLabel(tr("Expression:"))); + hbox->addWidget(m_lineEdit); + layout->addLayout(hbox); + + m_textEdit->setReadOnly(true); + m_lineEdit->installEventFilter(this); + } else { + m_textEdit->installEventFilter(this); + } +} + +void ExpressionQueryWidget::setEngineDebug(QmlEngineDebug *client) +{ + m_client = client; +} + +void ExpressionQueryWidget::clear() +{ + m_textEdit->clear(); + m_lineEdit->clear(); +} + +void ExpressionQueryWidget::updateTitle() +{ + if (m_currObject.debugId() < 0) { + m_title = tr("Expression queries"); + } else { + QString desc = QLatin1String("<") + + m_currObject.className() + QLatin1String(": ") + + (m_currObject.name().isEmpty() ? QLatin1String("") : m_currObject.name()) + + QLatin1String(">"); + m_title = tr("Expression queries (using context for %1)" , "Selected object").arg(desc); + } +} + +void ExpressionQueryWidget::appendPrompt() +{ + m_textEdit->moveCursor(QTextCursor::End); + + if (m_style == Compact) { + m_textEdit->insertPlainText("\n"); + } else { + m_textEdit->setTextColor(Qt::gray); + m_textEdit->append(m_prompt); + } +} + +void ExpressionQueryWidget::setCurrentObject(const QmlDebugObjectReference &obj) +{ + m_currObject = obj; + updateTitle(); +} + +void ExpressionQueryWidget::checkCurrentContext() +{ + m_textEdit->moveCursor(QTextCursor::End); + + if (m_currObject.debugId() != -1 && m_currObject.debugId() != m_objectAtLastFocus.debugId()) + showCurrentContext(); + m_objectAtLastFocus = m_currObject; +} + +void ExpressionQueryWidget::showCurrentContext() +{ + m_textEdit->moveCursor(QTextCursor::End); + m_textEdit->setTextColor(Qt::darkGreen); + m_textEdit->append(m_currObject.className() + + QLatin1String(": ") + + (m_currObject.name().isEmpty() ? QLatin1String("") : m_currObject.name())); + appendPrompt(); +} + +void ExpressionQueryWidget::executeExpression() +{ + if (!m_client) + return; + + if (m_style == Compact) + m_expr = m_lineEdit->text().trimmed(); + else + m_expr = m_expr.trimmed(); + + if (!m_expr.isEmpty() && m_currObject.debugId() != -1) { + if (m_query) + delete m_query; + m_query = m_client->queryExpressionResult(m_currObject.debugId(), m_expr, this); + if (!m_query->isWaiting()) + showResult(); + else + QObject::connect(m_query, SIGNAL(stateChanged(State)), + this, SLOT(showResult())); + + m_lastExpr = m_expr; + if (m_lineEdit) + m_lineEdit->clear(); + } +} + +void ExpressionQueryWidget::showResult() +{ + if (m_query) { + m_textEdit->moveCursor(QTextCursor::End); + QString result; + if (m_query->result().isNull()) + result = QLatin1String(""); + else + result = m_query->result().toString(); + + if (m_style == Compact) { + m_textEdit->setTextColor(Qt::black); + m_textEdit->setFontWeight(QFont::Bold); + m_textEdit->insertPlainText(m_expr + " : "); + m_textEdit->setFontWeight(QFont::Normal); + m_textEdit->insertPlainText(result); + } else { + m_textEdit->append(result); + } + appendPrompt(); + m_expr.clear(); + } +} + +bool ExpressionQueryWidget::eventFilter(QObject *obj, QEvent *event) +{ + if (obj == m_textEdit) { + switch (event->type()) { + case QEvent::KeyPress: + { + QKeyEvent *keyEvent = static_cast(event); + int key = keyEvent->key(); + if (key == Qt::Key_Return || key == Qt::Key_Enter) { + executeExpression(); + return true; + } else if (key == Qt::Key_Backspace) { + // ensure m_expr doesn't contain backspace characters + QTextCursor cursor = m_textEdit->textCursor(); + bool atLastLine = !(cursor.block().next().isValid()); + if (!atLastLine) + return true; + if (cursor.columnNumber() <= m_prompt.count()) + return true; + cursor.deletePreviousChar(); + m_expr = cursor.block().text().mid(m_prompt.count()); + return true; + } else { + m_textEdit->moveCursor(QTextCursor::End); + m_textEdit->setTextColor(Qt::black); + m_expr += keyEvent->text(); + } + break; + } + case QEvent::FocusIn: + checkCurrentContext(); + m_textEdit->moveCursor(QTextCursor::End); + break; + default: + break; + } + } else if (obj == m_lineEdit) { + switch (event->type()) { + case QEvent::KeyPress: + { + QKeyEvent *keyEvent = static_cast(event); + int key = keyEvent->key(); + if (key == Qt::Key_Up && m_lineEdit->text() != m_lastExpr) { + m_expr = m_lineEdit->text(); + if (!m_lastExpr.isEmpty()) + m_lineEdit->setText(m_lastExpr); + } else if (key == Qt::Key_Down) { + m_lineEdit->setText(m_expr); + } + break; + } + case QEvent::FocusIn: + checkCurrentContext(); + break; + default: + break; + } + } + return QWidget::eventFilter(obj, event); +} diff --git a/tools/qmldebugger/standalone/expressionquerywidget.h b/tools/qmldebugger/standalone/expressionquerywidget.h new file mode 100644 index 0000000..6fab059 --- /dev/null +++ b/tools/qmldebugger/standalone/expressionquerywidget.h @@ -0,0 +1,65 @@ +#ifndef EXPRESSIONQUERYWIDGET_H +#define EXPRESSIONQUERYWIDGET_H + +#include + +#include + +QT_BEGIN_NAMESPACE + +class QGroupBox; +class QTextEdit; +class QLineEdit; +class QPushButton; + +class ExpressionQueryWidget : public QWidget +{ + Q_OBJECT +public: + enum Style { + Compact, + Shell + }; + + ExpressionQueryWidget(QmlEngineDebug *client = 0, QWidget *parent = 0); + + void setEngineDebug(QmlEngineDebug *client); + void clear(); + +protected: + bool eventFilter(QObject *obj, QEvent *event); + +public slots: + void setCurrentObject(const QmlDebugObjectReference &obj); + +private slots: + void executeExpression(); + void showResult(); + +private: + void appendPrompt(); + void checkCurrentContext(); + void showCurrentContext(); + void updateTitle(); + + Style m_style; + + QmlEngineDebug *m_client; + QmlDebugExpressionQuery *m_query; + QTextEdit *m_textEdit; + QLineEdit *m_lineEdit; + QPushButton *m_button; + QString m_prompt; + QString m_expr; + QString m_lastExpr; + + QString m_title; + + QmlDebugObjectReference m_currObject; + QmlDebugObjectReference m_objectAtLastFocus; +}; + +QT_END_NAMESPACE + +#endif + diff --git a/tools/qmldebugger/standalone/main.cpp b/tools/qmldebugger/standalone/main.cpp new file mode 100644 index 0000000..c9983cd --- /dev/null +++ b/tools/qmldebugger/standalone/main.cpp @@ -0,0 +1,34 @@ +#include + +#include "qmldebugger.h" + +int main(int argc, char ** argv) +{ + QApplication app(argc, argv); + + QStringList args = app.arguments(); + + QmlDebugger win; + if (args.contains("--engine")) + win.showEngineTab(); + + for (int i=0; i + +#include +#include + +#include +#include +#include + +#include "objectpropertiesview.h" + +QT_BEGIN_NAMESPACE + +class PropertiesViewItem : public QObject, public QTreeWidgetItem +{ + Q_OBJECT +public: + PropertiesViewItem(QTreeWidget *widget); + PropertiesViewItem(QTreeWidgetItem *parent); + + QmlDebugPropertyReference property; +}; + +PropertiesViewItem::PropertiesViewItem(QTreeWidget *widget) + : QTreeWidgetItem(widget) +{ +} + +PropertiesViewItem::PropertiesViewItem(QTreeWidgetItem *parent) + : QTreeWidgetItem(parent) +{ +} + +ObjectPropertiesView::ObjectPropertiesView(QmlEngineDebug *client, QWidget *parent) + : QWidget(parent), + m_client(client), + m_query(0), + m_watch(0) +{ + QVBoxLayout *layout = new QVBoxLayout; + layout->setContentsMargins(0, 0, 0, 0); + layout->setSpacing(0); + setLayout(layout); + + m_tree = new QTreeWidget(this); + m_tree->setAlternatingRowColors(true); + m_tree->setExpandsOnDoubleClick(false); + m_tree->setHeaderLabels(QStringList() << tr("Property") << tr("Value")); + QObject::connect(m_tree, SIGNAL(itemActivated(QTreeWidgetItem *, int)), + this, SLOT(itemActivated(QTreeWidgetItem *))); + + m_tree->setColumnCount(2); + + layout->addWidget(m_tree); +} + +void ObjectPropertiesView::setEngineDebug(QmlEngineDebug *client) +{ + m_client = client; +} + +void ObjectPropertiesView::clear() +{ + setObject(QmlDebugObjectReference()); +} + +void ObjectPropertiesView::reload(const QmlDebugObjectReference &obj) +{ + if (!m_client) + return; + if (m_query) + delete m_query; + + m_query = m_client->queryObjectRecursive(obj, this); + if (!m_query->isWaiting()) + queryFinished(); + else + QObject::connect(m_query, SIGNAL(stateChanged(State)), + this, SLOT(queryFinished())); +} + +void ObjectPropertiesView::queryFinished() +{ + if (!m_client || !m_query) + return; + + QmlDebugObjectReference obj = m_query->object(); + + QmlDebugWatch *watch = m_client->addWatch(obj, this); + if (watch->state() == QmlDebugWatch::Dead) { + delete watch; + watch = 0; + } else { + if (m_watch) { + m_client->removeWatch(m_watch); + delete m_watch; + } + m_watch = watch; + QObject::connect(watch, SIGNAL(valueChanged(QByteArray,QVariant)), + this, SLOT(valueChanged(QByteArray,QVariant))); + } + + delete m_query; + m_query = 0; + + setObject(obj); +} + +void ObjectPropertiesView::setObject(const QmlDebugObjectReference &object) +{ + m_object = object; + m_tree->clear(); + + QList properties = object.properties(); + for (int i=0; iproperty = p; + + item->setText(0, p.name()); + item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); + if (!p.hasNotifySignal()) { + item->setForeground(0, Qt::gray); + item->setForeground(1, Qt::gray); + } + + if (!p.binding().isEmpty()) { + PropertiesViewItem *binding = new PropertiesViewItem(item); + binding->setText(1, p.binding()); + binding->setForeground(1, Qt::darkGreen); + } + + item->setExpanded(true); + } + + m_tree->resizeColumnToContents(0); +} + +void ObjectPropertiesView::watchCreated(QmlDebugWatch *watch) +{ + if (watch->objectDebugId() == m_object.debugId() + && qobject_cast(watch)) { + connect(watch, SIGNAL(stateChanged(State)), SLOT(watchStateChanged())); + setWatched(qobject_cast(watch)->name(), true); + } +} + +void ObjectPropertiesView::watchStateChanged() +{ + QmlDebugWatch *watch = qobject_cast(sender()); + + if (watch->objectDebugId() == m_object.debugId() + && qobject_cast(watch) + && watch->state() == QmlDebugWatch::Inactive) { + setWatched(qobject_cast(watch)->name(), false); + } +} + +void ObjectPropertiesView::setWatched(const QString &property, bool watched) +{ + for (int i=0; itopLevelItemCount(); i++) { + PropertiesViewItem *item = static_cast(m_tree->topLevelItem(i)); + if (item->property.name() == property && item->property.hasNotifySignal()) { + QFont font = m_tree->font(); + font.setBold(watched); + item->setFont(0, font); + } + } +} + +void ObjectPropertiesView::valueChanged(const QByteArray &name, const QVariant &value) +{ + for (int i=0; itopLevelItemCount(); i++) { + PropertiesViewItem *item = static_cast(m_tree->topLevelItem(i)); + if (item->property.name() == name) { + if (value.isNull()) { + item->setText(1, QLatin1String("") + + QLatin1String(" : ") + + item->property.valueTypeName()); + } else { + item->setText(1, value.toString()); + } + } + } +} + +void ObjectPropertiesView::itemActivated(QTreeWidgetItem *i) +{ + PropertiesViewItem *item = static_cast(i); + if (!item->property.name().isEmpty()) + emit activated(m_object, item->property); +} + +QT_END_NAMESPACE + +#include "objectpropertiesview.moc" diff --git a/tools/qmldebugger/standalone/objectpropertiesview.h b/tools/qmldebugger/standalone/objectpropertiesview.h new file mode 100644 index 0000000..6a1fc03 --- /dev/null +++ b/tools/qmldebugger/standalone/objectpropertiesview.h @@ -0,0 +1,51 @@ +#ifndef PROPERTIESTABLEMODEL_H +#define PROPERTIESTABLEMODEL_H + +#include + +#include + +QT_BEGIN_NAMESPACE + +class QTreeWidget; +class QTreeWidgetItem; +class QmlDebugConnection; + +class ObjectPropertiesView : public QWidget +{ + Q_OBJECT +public: + ObjectPropertiesView(QmlEngineDebug *client = 0, QWidget *parent = 0); + + void setEngineDebug(QmlEngineDebug *client); + void clear(); + +signals: + void activated(const QmlDebugObjectReference &, const QmlDebugPropertyReference &); + +public slots: + void reload(const QmlDebugObjectReference &); + void watchCreated(QmlDebugWatch *); + +private slots: + void queryFinished(); + void watchStateChanged(); + void valueChanged(const QByteArray &name, const QVariant &value); + void itemActivated(QTreeWidgetItem *i); + +private: + void setObject(const QmlDebugObjectReference &object); + void setWatched(const QString &property, bool watched); + + QmlEngineDebug *m_client; + QmlDebugObjectQuery *m_query; + QmlDebugWatch *m_watch; + + QTreeWidget *m_tree; + QmlDebugObjectReference m_object; +}; + + +QT_END_NAMESPACE + +#endif diff --git a/tools/qmldebugger/standalone/objecttree.cpp b/tools/qmldebugger/standalone/objecttree.cpp new file mode 100644 index 0000000..4059e77 --- /dev/null +++ b/tools/qmldebugger/standalone/objecttree.cpp @@ -0,0 +1,180 @@ +#include +#include +#include + +#include + +#include +#include +#include + +#include "objecttree.h" + +Q_DECLARE_METATYPE(QmlDebugObjectReference) + +ObjectTree::ObjectTree(QmlEngineDebug *client, QWidget *parent) + : QTreeWidget(parent), + m_client(client), + m_query(0) +{ + setHeaderHidden(true); + setMinimumWidth(250); + + connect(this, SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)), + this, SLOT(currentItemChanged(QTreeWidgetItem *))); +} + +void ObjectTree::setEngineDebug(QmlEngineDebug *client) +{ + m_client = client; +} + +void ObjectTree::reload(int objectDebugId) +{ + if (!m_client) + return; + + if (m_query) { + delete m_query; + m_query = 0; + } + + m_query = m_client->queryObjectRecursive(QmlDebugObjectReference(objectDebugId), this); + if (!m_query->isWaiting()) + objectFetched(); + else + QObject::connect(m_query, SIGNAL(stateChanged(State)), + this, SLOT(objectFetched())); +} + +void ObjectTree::setCurrentObject(int debugId) +{ + QTreeWidgetItem *item = findItemByObjectId(debugId); + if (item) { + setCurrentItem(item); + scrollToItem(item); + item->setExpanded(true); + } +} + +void ObjectTree::objectFetched() +{ + dump(m_query->object(), 0); + buildTree(m_query->object(), 0); + + delete m_query; + m_query = 0; +} + +void ObjectTree::currentItemChanged(QTreeWidgetItem *item) +{ + if (!item) + return; + + QmlDebugObjectReference obj = item->data(0, Qt::UserRole).value(); + if (obj.debugId() < 0) { + qWarning("QML Object Tree: bad object id"); + return; + } + emit currentObjectChanged(obj); +} + +void ObjectTree::buildTree(const QmlDebugObjectReference &obj, QTreeWidgetItem *parent) +{ + if (!parent) + clear(); + + QTreeWidgetItem *item = parent ? new QTreeWidgetItem(parent) : new QTreeWidgetItem(this); + item->setText(0, obj.className()); + item->setData(0, Qt::UserRole, qVariantFromValue(obj)); + + if (parent && obj.contextDebugId() >= 0 + && obj.contextDebugId() != parent->data(0, Qt::UserRole + ).value().contextDebugId()) { + QmlDebugFileReference source = obj.source(); + if (!source.url().isEmpty()) { + QString toolTipString = QLatin1String("URL: ") + source.url().toString(); + item->setToolTip(0, toolTipString); + } + item->setForeground(0, QColor("orange")); + } else { + item->setExpanded(true); + } + + if (obj.contextDebugId() < 0) + item->setForeground(0, Qt::lightGray); + + for (int ii = 0; ii < obj.children().count(); ++ii) + buildTree(obj.children().at(ii), item); +} + +void ObjectTree::dump(const QmlDebugContextReference &ctxt, int ind) +{ + QByteArray indent(ind * 4, ' '); + qWarning().nospace() << indent.constData() << ctxt.debugId() << " " + << qPrintable(ctxt.name()); + + for (int ii = 0; ii < ctxt.contexts().count(); ++ii) + dump(ctxt.contexts().at(ii), ind + 1); + + for (int ii = 0; ii < ctxt.objects().count(); ++ii) + dump(ctxt.objects().at(ii), ind); +} + +void ObjectTree::dump(const QmlDebugObjectReference &obj, int ind) +{ + QByteArray indent(ind * 4, ' '); + qWarning().nospace() << indent.constData() << qPrintable(obj.className()) + << " " << qPrintable(obj.name()) << " " + << obj.debugId(); + + for (int ii = 0; ii < obj.children().count(); ++ii) + dump(obj.children().at(ii), ind + 1); +} + +QTreeWidgetItem *ObjectTree::findItemByObjectId(int debugId) const +{ + for (int i=0; idata(0, Qt::UserRole).value().debugId() == debugId) + return item; + + QTreeWidgetItem *child; + for (int i=0; ichildCount(); i++) { + child = findItem(item->child(i), debugId); + if (child) + return child; + } + + return 0; +} + +void ObjectTree::mousePressEvent(QMouseEvent *me) +{ + QTreeWidget::mousePressEvent(me); + if (!currentItem()) + return; + if(me->button() == Qt::RightButton && me->type() == QEvent::MouseButtonPress) { + QAction action(tr("Add watch..."), 0); + QList actions; + actions << &action; + QmlDebugObjectReference obj = + currentItem()->data(0, Qt::UserRole).value(); + if (QMenu::exec(actions, me->globalPos())) { + bool ok = false; + QString watch = QInputDialog::getText(this, tr("Watch expression"), + tr("Expression:"), QLineEdit::Normal, QString(), &ok); + if (ok && !watch.isEmpty()) + emit expressionWatchRequested(obj, watch); + } + } +} diff --git a/tools/qmldebugger/standalone/objecttree.h b/tools/qmldebugger/standalone/objecttree.h new file mode 100644 index 0000000..95820f3 --- /dev/null +++ b/tools/qmldebugger/standalone/objecttree.h @@ -0,0 +1,54 @@ +#ifndef OBJECTTREE_H +#define OBJECTTREE_H + +#include + +QT_BEGIN_NAMESPACE + +class QTreeWidgetItem; + +class QmlEngineDebug; +class QmlDebugObjectReference; +class QmlDebugObjectQuery; +class QmlDebugContextReference; +class QmlDebugConnection; + + +class ObjectTree : public QTreeWidget +{ + Q_OBJECT +public: + ObjectTree(QmlEngineDebug *client = 0, QWidget *parent = 0); + + void setEngineDebug(QmlEngineDebug *client); + +signals: + void currentObjectChanged(const QmlDebugObjectReference &); + void expressionWatchRequested(const QmlDebugObjectReference &, const QString &); + +public slots: + void reload(int objectDebugId); + void setCurrentObject(int debugId); + +protected: + virtual void mousePressEvent(QMouseEvent *); + +private slots: + void objectFetched(); + void currentItemChanged(QTreeWidgetItem *); + +private: + QTreeWidgetItem *findItemByObjectId(int debugId) const; + QTreeWidgetItem *findItem(QTreeWidgetItem *item, int debugId) const; + void dump(const QmlDebugContextReference &, int); + void dump(const QmlDebugObjectReference &, int); + void buildTree(const QmlDebugObjectReference &, QTreeWidgetItem *parent); + + QmlEngineDebug *m_client; + QmlDebugObjectQuery *m_query; +}; + +QT_END_NAMESPACE + + +#endif diff --git a/tools/qmldebugger/standalone/qmldebugger.cpp b/tools/qmldebugger/standalone/qmldebugger.cpp new file mode 100644 index 0000000..5455878 --- /dev/null +++ b/tools/qmldebugger/standalone/qmldebugger.cpp @@ -0,0 +1,131 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "canvasframerate.h" +#include "engine.h" +#include "qmldebugger.h" + +QmlDebugger::QmlDebugger(QWidget *parent) +: QWidget(parent) +{ + QVBoxLayout *layout = new QVBoxLayout; + setLayout(layout); + + + QHBoxLayout *connectLayout = new QHBoxLayout; + layout->addLayout(connectLayout); + connectLayout->addStretch(2); + + m_connectionState = new QLabel(this); + connectLayout->addWidget(m_connectionState); + m_host = new QLineEdit(this); + m_host->setText("127.0.0.1"); + connectLayout->addWidget(m_host); + m_port = new QSpinBox(this); + m_port->setMinimum(1024); + m_port->setMaximum(20000); + m_port->setValue(3768); + connectLayout->addWidget(m_port); + m_connectButton = new QPushButton(tr("Connect"), this); + QObject::connect(m_connectButton, SIGNAL(clicked()), + this, SLOT(connectToHost())); + connectLayout->addWidget(m_connectButton); + m_disconnectButton = new QPushButton(tr("Disconnect"), this); + QObject::connect(m_disconnectButton, SIGNAL(clicked()), + this, SLOT(disconnectFromHost())); + m_disconnectButton->setEnabled(false); + connectLayout->addWidget(m_disconnectButton); + + m_tabs = new QTabWidget(this); + layout->addWidget(m_tabs); + + CanvasFrameRate *cfr = new CanvasFrameRate(this); + cfr->reset(&client); + cfr->setSizeHint(QSize(800, 600)); + m_tabs->addTab(cfr, tr("Frame Rate")); + + m_enginePane = new EnginePane(&client, this); + m_tabs->addTab(m_enginePane, tr("QML Engine")); + + QObject::connect(&client, SIGNAL(stateChanged(QAbstractSocket::SocketState)), + this, SLOT(connectionStateChanged())); + connectionStateChanged(); + + QObject::connect(&client, SIGNAL(error(QAbstractSocket::SocketError)), + this, SLOT(connectionError(QAbstractSocket::SocketError))); + + + m_tabs->setCurrentIndex(1); + connectToHost(); +} + +void QmlDebugger::setHost(const QString &host) +{ + m_host->setText(host); +} + +void QmlDebugger::setPort(quint16 port) +{ + m_port->setValue(port); +} + +void QmlDebugger::showEngineTab() +{ + m_tabs->setCurrentWidget(m_enginePane); +} + +void QmlDebugger::connectionStateChanged() +{ + switch (client.state()) { + default: + case QAbstractSocket::UnconnectedState: + m_connectionState->setText(tr("Disconnected")); + m_connectButton->setEnabled(true); + m_disconnectButton->setEnabled(false); + break; + case QAbstractSocket::HostLookupState: + m_connectionState->setText(tr("Resolving")); + m_connectButton->setEnabled(false); + m_disconnectButton->setEnabled(true); + break; + case QAbstractSocket::ConnectingState: + m_connectionState->setText(tr("Connecting")); + m_connectButton->setEnabled(false); + m_disconnectButton->setEnabled(true); + break; + case QAbstractSocket::ConnectedState: + m_connectionState->setText(tr("Connected")); + m_connectButton->setEnabled(false); + m_disconnectButton->setEnabled(true); + + QTimer::singleShot(0, m_enginePane, SLOT(refreshEngines())); + break; + case QAbstractSocket::ClosingState: + m_connectionState->setText(tr("Closing")); + m_connectButton->setEnabled(false); + m_disconnectButton->setEnabled(false); + break; + } +} + +void QmlDebugger::connectionError(QAbstractSocket::SocketError socketError) +{ + qWarning() << "qmldebugger cannot connect:" << socketError + << client.errorString(); +} + +void QmlDebugger::connectToHost() +{ + client.connectToHost(m_host->text(), m_port->value()); +} + +void QmlDebugger::disconnectFromHost() +{ + client.disconnectFromHost(); +} diff --git a/tools/qmldebugger/standalone/qmldebugger.h b/tools/qmldebugger/standalone/qmldebugger.h new file mode 100644 index 0000000..9203e33 --- /dev/null +++ b/tools/qmldebugger/standalone/qmldebugger.h @@ -0,0 +1,47 @@ +#ifndef QMLDEBUGGER_H +#define QMLDEBUGGER_H + +#include +#include +#include + +class QLabel; +class QLineEdit; +class QSpinBox; +class QPushButton; +class QTabWidget; + +class EnginePane; + +class QmlDebugger : public QWidget +{ + Q_OBJECT +public: + QmlDebugger(QWidget * = 0); + + void setHost(const QString &host); + void setPort(quint16 port); + void showEngineTab(); + +public slots: + void connectToHost(); + void disconnectFromHost(); + +private slots: + void connectionStateChanged(); + void connectionError(QAbstractSocket::SocketError socketError); + +private: + QmlDebugConnection client; + + QLabel *m_connectionState; + QLineEdit *m_host; + QSpinBox *m_port; + QPushButton *m_connectButton; + QPushButton *m_disconnectButton; + + EnginePane *m_enginePane; + QTabWidget *m_tabs; +}; + +#endif diff --git a/tools/qmldebugger/standalone/qmldebugger.pri b/tools/qmldebugger/standalone/qmldebugger.pri new file mode 100644 index 0000000..aad5eb1 --- /dev/null +++ b/tools/qmldebugger/standalone/qmldebugger.pri @@ -0,0 +1,16 @@ +QT += network declarative +contains(QT_CONFIG, opengles2)|contains(QT_CONFIG, opengles1): QT += opengl + +# Input +HEADERS += $$PWD/canvasframerate.h \ + $$PWD/watchtable.h \ + $$PWD/objecttree.h \ + $$PWD/objectpropertiesview.h \ + $$PWD/expressionquerywidget.h + +SOURCES += $$PWD/canvasframerate.cpp \ + $$PWD/watchtable.cpp \ + $$PWD/objecttree.cpp \ + $$PWD/objectpropertiesview.cpp \ + $$PWD/expressionquerywidget.cpp + diff --git a/tools/qmldebugger/standalone/qmldebugger.qrc b/tools/qmldebugger/standalone/qmldebugger.qrc new file mode 100644 index 0000000..cb53ad5 --- /dev/null +++ b/tools/qmldebugger/standalone/qmldebugger.qrc @@ -0,0 +1,7 @@ + + + engines.qml + engine.png + refresh.png + + diff --git a/tools/qmldebugger/standalone/refresh.png b/tools/qmldebugger/standalone/refresh.png new file mode 100644 index 0000000..8befc80 Binary files /dev/null and b/tools/qmldebugger/standalone/refresh.png differ diff --git a/tools/qmldebugger/standalone/standalone.pro b/tools/qmldebugger/standalone/standalone.pro new file mode 100644 index 0000000..72e3ef5 --- /dev/null +++ b/tools/qmldebugger/standalone/standalone.pro @@ -0,0 +1,18 @@ +DESTDIR = ../../bin + +include(qmldebugger.pri) + +HEADERS += $$PWD/qmldebugger.h \ + $$PWD/engine.h + +SOURCES += $$PWD/qmldebugger.cpp \ + $$PWD/engine.cpp \ + $$PWD/main.cpp + +RESOURCES += $$PWD/qmldebugger.qrc +OTHER_FILES += $$PWD/engines.qml + +target.path=$$[QT_INSTALL_BINS] +INSTALLS += target + +CONFIG += console diff --git a/tools/qmldebugger/standalone/watchtable.cpp b/tools/qmldebugger/standalone/watchtable.cpp new file mode 100644 index 0000000..ee74cfb --- /dev/null +++ b/tools/qmldebugger/standalone/watchtable.cpp @@ -0,0 +1,325 @@ +#include "watchtable.h" + +#include +#include +#include +#include + +#include +#include + +QT_BEGIN_NAMESPACE + + +WatchTableModel::WatchTableModel(QmlEngineDebug *client, QObject *parent) + : QAbstractTableModel(parent), + m_client(client) +{ +} + +WatchTableModel::~WatchTableModel() +{ + for (int i=0; i(watch)) + property = qobject_cast(watch)->name(); + + connect(watch, SIGNAL(valueChanged(QByteArray,QVariant)), + SLOT(watchedValueChanged(QByteArray,QVariant))); + + connect(watch, SIGNAL(stateChanged(State)), SLOT(watchStateChanged())); + + int col = columnCount(QModelIndex()); + beginInsertColumns(QModelIndex(), col, col); + + WatchedEntity e; + e.title = title; + e.hasFirstValue = false; + e.property = property; + e.watch = watch; + m_columns.append(e); + + endInsertColumns(); +} + +void WatchTableModel::removeWatch(QmlDebugWatch *watch) +{ + int column = columnForWatch(watch); + if (column == -1) + return; + + WatchedEntity entity = m_columns.takeAt(column); + + for (QList::Iterator iter = m_values.begin(); iter != m_values.end();) { + if (iter->column == column) { + iter = m_values.erase(iter); + } else { + if(iter->column > column) + --iter->column; + ++iter; + } + } + + reset(); +} + +void WatchTableModel::updateWatch(QmlDebugWatch *watch, const QVariant &value) +{ + int column = columnForWatch(watch); + if (column == -1) + return; + + addValue(column, value); + + if (!m_columns[column].hasFirstValue) { + m_columns[column].hasFirstValue = true; + m_values[m_values.count() - 1].first = true; + } +} + +QmlDebugWatch *WatchTableModel::findWatch(int column) const +{ + if (column < m_columns.count()) + return m_columns.at(column).watch; + return 0; +} + +QmlDebugWatch *WatchTableModel::findWatch(int objectDebugId, const QString &property) const +{ + for (int i=0; iobjectDebugId() == objectDebugId + && m_columns[i].property == property) { + return m_columns[i].watch; + } + } + return 0; +} + +int WatchTableModel::rowCount(const QModelIndex &) const +{ + return m_values.count(); +} + +int WatchTableModel::columnCount(const QModelIndex &) const +{ + return m_columns.count(); +} + +QVariant WatchTableModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if (orientation == Qt::Horizontal) { + if (section < m_columns.count() && role == Qt::DisplayRole) + return m_columns.at(section).title; + } else { + if (role == Qt::DisplayRole) + return section + 1; + } + return QVariant(); +} + +QVariant WatchTableModel::data(const QModelIndex &idx, int role) const +{ + if (m_values.at(idx.row()).column == idx.column()) { + if (role == Qt::DisplayRole) { + const QVariant &value = m_values.at(idx.row()).variant; + QString str = value.toString(); + + if (str.isEmpty() && QmlMetaType::isObject(value.userType())) { + QObject *o = QmlMetaType::toQObject(value); + if(o) { + QString objectName = o->objectName(); + if(objectName.isEmpty()) + objectName = QLatin1String(""); + str = QLatin1String(o->metaObject()->className()) + + QLatin1String(": ") + objectName; + } + } + + if(str.isEmpty()) { + QDebug d(&str); + d << value; + } + return QVariant(str); + } else if(role == Qt::BackgroundRole) { + if(m_values.at(idx.row()).first) + return QColor(Qt::green); + else + return QVariant(); + } else { + return QVariant(); + } + } else { + return QVariant(); + } +} + +void WatchTableModel::watchStateChanged() +{ + QmlDebugWatch *watch = qobject_cast(sender()); + + if (watch && watch->state() == QmlDebugWatch::Inactive) { + removeWatch(watch); + watch->deleteLater(); + } +} + +int WatchTableModel::columnForWatch(QmlDebugWatch *watch) const +{ + for (int i=0; iremoveWatch(watch); + return; + } + + watch = m_client->addWatch(property, this); + if (watch->state() == QmlDebugWatch::Dead) { + delete watch; + watch = 0; + } else { + QString desc = property.name() + + QLatin1String(" on\n") + + object.className() + + QLatin1String(": ") + + (object.name().isEmpty() ? QLatin1String("") : object.name()); + addWatch(watch, desc); + emit watchCreated(watch); + } +} + +void WatchTableModel::watchedValueChanged(const QByteArray &propertyName, const QVariant &value) +{ + Q_UNUSED(propertyName); + QmlDebugWatch *watch = qobject_cast(sender()); + if (watch) + updateWatch(watch, value); +} + +void WatchTableModel::expressionWatchRequested(const QmlDebugObjectReference &obj, const QString &expr) +{ + if (!m_client) + return; + + QmlDebugWatch *watch = m_client->addWatch(obj, expr, this); + + if (watch->state() == QmlDebugWatch::Dead) { + delete watch; + watch = 0; + } else { + addWatch(watch, expr); + emit watchCreated(watch); + } +} + +void WatchTableModel::removeWatchAt(int column) +{ + if (!m_client) + return; + + QmlDebugWatch *watch = findWatch(column); + if (watch) { + m_client->removeWatch(watch); + delete watch; + watch = 0; + } +} + +void WatchTableModel::removeAllWatches() +{ + for (int i=0; iremoveWatch(m_columns[i].watch); + delete m_columns[i].watch; + } + m_columns.clear(); + m_values.clear(); + reset(); +} + +//---------------------------------------------- + +WatchTableHeaderView::WatchTableHeaderView(WatchTableModel *model, QWidget *parent) + : QHeaderView(Qt::Horizontal, parent), + m_model(model) +{ + setClickable(true); +} + +void WatchTableHeaderView::mousePressEvent(QMouseEvent *me) +{ + QHeaderView::mousePressEvent(me); + + if (me->button() == Qt::RightButton && me->type() == QEvent::MouseButtonPress) { + int col = logicalIndexAt(me->pos()); + if (col >= 0) { + QAction action(tr("Stop watching"), 0); + QList actions; + actions << &action; + if (QMenu::exec(actions, me->globalPos())) + m_model->removeWatchAt(col); + } + } +} + + +//---------------------------------------------- + +WatchTableView::WatchTableView(WatchTableModel *model, QWidget *parent) + : QTableView(parent), + m_model(model) +{ + setAlternatingRowColors(true); + connect(model, SIGNAL(watchCreated(QmlDebugWatch*)), SLOT(watchCreated(QmlDebugWatch*))); + connect(this, SIGNAL(activated(QModelIndex)), SLOT(indexActivated(QModelIndex))); +} + +void WatchTableView::indexActivated(const QModelIndex &index) +{ + QmlDebugWatch *watch = m_model->findWatch(index.column()); + if (watch) + emit objectActivated(watch->objectDebugId()); +} + +void WatchTableView::watchCreated(QmlDebugWatch *watch) +{ + int column = m_model->columnForWatch(watch); + resizeColumnToContents(column); +} + +QT_END_NAMESPACE diff --git a/tools/qmldebugger/standalone/watchtable.h b/tools/qmldebugger/standalone/watchtable.h new file mode 100644 index 0000000..67c2565 --- /dev/null +++ b/tools/qmldebugger/standalone/watchtable.h @@ -0,0 +1,114 @@ +#ifndef WATCHTABLEMODEL_H +#define WATCHTABLEMODEL_H + +#include +#include + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QmlDebugWatch; +class QmlEngineDebug; +class QmlDebugConnection; +class QmlDebugPropertyReference; +class QmlDebugObjectReference; + +class WatchTableModel : public QAbstractTableModel +{ + Q_OBJECT +public: + WatchTableModel(QmlEngineDebug *client = 0, QObject *parent = 0); + ~WatchTableModel(); + + void setEngineDebug(QmlEngineDebug *client); + + QmlDebugWatch *findWatch(int column) const; + int columnForWatch(QmlDebugWatch *watch) const; + + void removeWatchAt(int column); + void removeAllWatches(); + + int rowCount(const QModelIndex &parent = QModelIndex()) const; + int columnCount(const QModelIndex &parent = QModelIndex()) const; + QVariant headerData(int section, Qt::Orientation orientation, int role) const; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + +signals: + void watchCreated(QmlDebugWatch *watch); + +public slots: + void togglePropertyWatch(const QmlDebugObjectReference &obj, const QmlDebugPropertyReference &prop); + void expressionWatchRequested(const QmlDebugObjectReference &, const QString &); + +private slots: + void watchStateChanged(); + void watchedValueChanged(const QByteArray &propertyName, const QVariant &value); + +private: + void addWatch(QmlDebugWatch *watch, const QString &title); + void removeWatch(QmlDebugWatch *watch); + void updateWatch(QmlDebugWatch *watch, const QVariant &value); + + QmlDebugWatch *findWatch(int objectDebugId, const QString &property) const; + + void addValue(int column, const QVariant &value); + + struct WatchedEntity + { + QString title; + bool hasFirstValue; + QString property; + QPointer watch; + }; + + struct Value { + int column; + QVariant variant; + bool first; + }; + + QmlEngineDebug *m_client; + QList m_columns; + QList m_values; +}; + + +class WatchTableHeaderView : public QHeaderView +{ + Q_OBJECT +public: + WatchTableHeaderView(WatchTableModel *model, QWidget *parent = 0); + +protected: + void mousePressEvent(QMouseEvent *me); + +private: + WatchTableModel *m_model; +}; + + +class WatchTableView : public QTableView +{ + Q_OBJECT +public: + WatchTableView(WatchTableModel *model, QWidget *parent = 0); + +signals: + void objectActivated(int objectDebugId); + +private slots: + void indexActivated(const QModelIndex &index); + void watchCreated(QmlDebugWatch *watch); + +private: + WatchTableModel *m_model; +}; + + +QT_END_NAMESPACE + +#endif // WATCHTABLEMODEL_H diff --git a/tools/qmldebugger/watchtable.cpp b/tools/qmldebugger/watchtable.cpp deleted file mode 100644 index ee74cfb..0000000 --- a/tools/qmldebugger/watchtable.cpp +++ /dev/null @@ -1,325 +0,0 @@ -#include "watchtable.h" - -#include -#include -#include -#include - -#include -#include - -QT_BEGIN_NAMESPACE - - -WatchTableModel::WatchTableModel(QmlEngineDebug *client, QObject *parent) - : QAbstractTableModel(parent), - m_client(client) -{ -} - -WatchTableModel::~WatchTableModel() -{ - for (int i=0; i(watch)) - property = qobject_cast(watch)->name(); - - connect(watch, SIGNAL(valueChanged(QByteArray,QVariant)), - SLOT(watchedValueChanged(QByteArray,QVariant))); - - connect(watch, SIGNAL(stateChanged(State)), SLOT(watchStateChanged())); - - int col = columnCount(QModelIndex()); - beginInsertColumns(QModelIndex(), col, col); - - WatchedEntity e; - e.title = title; - e.hasFirstValue = false; - e.property = property; - e.watch = watch; - m_columns.append(e); - - endInsertColumns(); -} - -void WatchTableModel::removeWatch(QmlDebugWatch *watch) -{ - int column = columnForWatch(watch); - if (column == -1) - return; - - WatchedEntity entity = m_columns.takeAt(column); - - for (QList::Iterator iter = m_values.begin(); iter != m_values.end();) { - if (iter->column == column) { - iter = m_values.erase(iter); - } else { - if(iter->column > column) - --iter->column; - ++iter; - } - } - - reset(); -} - -void WatchTableModel::updateWatch(QmlDebugWatch *watch, const QVariant &value) -{ - int column = columnForWatch(watch); - if (column == -1) - return; - - addValue(column, value); - - if (!m_columns[column].hasFirstValue) { - m_columns[column].hasFirstValue = true; - m_values[m_values.count() - 1].first = true; - } -} - -QmlDebugWatch *WatchTableModel::findWatch(int column) const -{ - if (column < m_columns.count()) - return m_columns.at(column).watch; - return 0; -} - -QmlDebugWatch *WatchTableModel::findWatch(int objectDebugId, const QString &property) const -{ - for (int i=0; iobjectDebugId() == objectDebugId - && m_columns[i].property == property) { - return m_columns[i].watch; - } - } - return 0; -} - -int WatchTableModel::rowCount(const QModelIndex &) const -{ - return m_values.count(); -} - -int WatchTableModel::columnCount(const QModelIndex &) const -{ - return m_columns.count(); -} - -QVariant WatchTableModel::headerData(int section, Qt::Orientation orientation, int role) const -{ - if (orientation == Qt::Horizontal) { - if (section < m_columns.count() && role == Qt::DisplayRole) - return m_columns.at(section).title; - } else { - if (role == Qt::DisplayRole) - return section + 1; - } - return QVariant(); -} - -QVariant WatchTableModel::data(const QModelIndex &idx, int role) const -{ - if (m_values.at(idx.row()).column == idx.column()) { - if (role == Qt::DisplayRole) { - const QVariant &value = m_values.at(idx.row()).variant; - QString str = value.toString(); - - if (str.isEmpty() && QmlMetaType::isObject(value.userType())) { - QObject *o = QmlMetaType::toQObject(value); - if(o) { - QString objectName = o->objectName(); - if(objectName.isEmpty()) - objectName = QLatin1String(""); - str = QLatin1String(o->metaObject()->className()) + - QLatin1String(": ") + objectName; - } - } - - if(str.isEmpty()) { - QDebug d(&str); - d << value; - } - return QVariant(str); - } else if(role == Qt::BackgroundRole) { - if(m_values.at(idx.row()).first) - return QColor(Qt::green); - else - return QVariant(); - } else { - return QVariant(); - } - } else { - return QVariant(); - } -} - -void WatchTableModel::watchStateChanged() -{ - QmlDebugWatch *watch = qobject_cast(sender()); - - if (watch && watch->state() == QmlDebugWatch::Inactive) { - removeWatch(watch); - watch->deleteLater(); - } -} - -int WatchTableModel::columnForWatch(QmlDebugWatch *watch) const -{ - for (int i=0; iremoveWatch(watch); - return; - } - - watch = m_client->addWatch(property, this); - if (watch->state() == QmlDebugWatch::Dead) { - delete watch; - watch = 0; - } else { - QString desc = property.name() - + QLatin1String(" on\n") - + object.className() - + QLatin1String(": ") - + (object.name().isEmpty() ? QLatin1String("") : object.name()); - addWatch(watch, desc); - emit watchCreated(watch); - } -} - -void WatchTableModel::watchedValueChanged(const QByteArray &propertyName, const QVariant &value) -{ - Q_UNUSED(propertyName); - QmlDebugWatch *watch = qobject_cast(sender()); - if (watch) - updateWatch(watch, value); -} - -void WatchTableModel::expressionWatchRequested(const QmlDebugObjectReference &obj, const QString &expr) -{ - if (!m_client) - return; - - QmlDebugWatch *watch = m_client->addWatch(obj, expr, this); - - if (watch->state() == QmlDebugWatch::Dead) { - delete watch; - watch = 0; - } else { - addWatch(watch, expr); - emit watchCreated(watch); - } -} - -void WatchTableModel::removeWatchAt(int column) -{ - if (!m_client) - return; - - QmlDebugWatch *watch = findWatch(column); - if (watch) { - m_client->removeWatch(watch); - delete watch; - watch = 0; - } -} - -void WatchTableModel::removeAllWatches() -{ - for (int i=0; iremoveWatch(m_columns[i].watch); - delete m_columns[i].watch; - } - m_columns.clear(); - m_values.clear(); - reset(); -} - -//---------------------------------------------- - -WatchTableHeaderView::WatchTableHeaderView(WatchTableModel *model, QWidget *parent) - : QHeaderView(Qt::Horizontal, parent), - m_model(model) -{ - setClickable(true); -} - -void WatchTableHeaderView::mousePressEvent(QMouseEvent *me) -{ - QHeaderView::mousePressEvent(me); - - if (me->button() == Qt::RightButton && me->type() == QEvent::MouseButtonPress) { - int col = logicalIndexAt(me->pos()); - if (col >= 0) { - QAction action(tr("Stop watching"), 0); - QList actions; - actions << &action; - if (QMenu::exec(actions, me->globalPos())) - m_model->removeWatchAt(col); - } - } -} - - -//---------------------------------------------- - -WatchTableView::WatchTableView(WatchTableModel *model, QWidget *parent) - : QTableView(parent), - m_model(model) -{ - setAlternatingRowColors(true); - connect(model, SIGNAL(watchCreated(QmlDebugWatch*)), SLOT(watchCreated(QmlDebugWatch*))); - connect(this, SIGNAL(activated(QModelIndex)), SLOT(indexActivated(QModelIndex))); -} - -void WatchTableView::indexActivated(const QModelIndex &index) -{ - QmlDebugWatch *watch = m_model->findWatch(index.column()); - if (watch) - emit objectActivated(watch->objectDebugId()); -} - -void WatchTableView::watchCreated(QmlDebugWatch *watch) -{ - int column = m_model->columnForWatch(watch); - resizeColumnToContents(column); -} - -QT_END_NAMESPACE diff --git a/tools/qmldebugger/watchtable.h b/tools/qmldebugger/watchtable.h deleted file mode 100644 index 67c2565..0000000 --- a/tools/qmldebugger/watchtable.h +++ /dev/null @@ -1,114 +0,0 @@ -#ifndef WATCHTABLEMODEL_H -#define WATCHTABLEMODEL_H - -#include -#include - -#include -#include -#include -#include - -QT_BEGIN_NAMESPACE - -class QmlDebugWatch; -class QmlEngineDebug; -class QmlDebugConnection; -class QmlDebugPropertyReference; -class QmlDebugObjectReference; - -class WatchTableModel : public QAbstractTableModel -{ - Q_OBJECT -public: - WatchTableModel(QmlEngineDebug *client = 0, QObject *parent = 0); - ~WatchTableModel(); - - void setEngineDebug(QmlEngineDebug *client); - - QmlDebugWatch *findWatch(int column) const; - int columnForWatch(QmlDebugWatch *watch) const; - - void removeWatchAt(int column); - void removeAllWatches(); - - int rowCount(const QModelIndex &parent = QModelIndex()) const; - int columnCount(const QModelIndex &parent = QModelIndex()) const; - QVariant headerData(int section, Qt::Orientation orientation, int role) const; - QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; - -signals: - void watchCreated(QmlDebugWatch *watch); - -public slots: - void togglePropertyWatch(const QmlDebugObjectReference &obj, const QmlDebugPropertyReference &prop); - void expressionWatchRequested(const QmlDebugObjectReference &, const QString &); - -private slots: - void watchStateChanged(); - void watchedValueChanged(const QByteArray &propertyName, const QVariant &value); - -private: - void addWatch(QmlDebugWatch *watch, const QString &title); - void removeWatch(QmlDebugWatch *watch); - void updateWatch(QmlDebugWatch *watch, const QVariant &value); - - QmlDebugWatch *findWatch(int objectDebugId, const QString &property) const; - - void addValue(int column, const QVariant &value); - - struct WatchedEntity - { - QString title; - bool hasFirstValue; - QString property; - QPointer watch; - }; - - struct Value { - int column; - QVariant variant; - bool first; - }; - - QmlEngineDebug *m_client; - QList m_columns; - QList m_values; -}; - - -class WatchTableHeaderView : public QHeaderView -{ - Q_OBJECT -public: - WatchTableHeaderView(WatchTableModel *model, QWidget *parent = 0); - -protected: - void mousePressEvent(QMouseEvent *me); - -private: - WatchTableModel *m_model; -}; - - -class WatchTableView : public QTableView -{ - Q_OBJECT -public: - WatchTableView(WatchTableModel *model, QWidget *parent = 0); - -signals: - void objectActivated(int objectDebugId); - -private slots: - void indexActivated(const QModelIndex &index); - void watchCreated(QmlDebugWatch *watch); - -private: - WatchTableModel *m_model; -}; - - -QT_END_NAMESPACE - -#endif // WATCHTABLEMODEL_H -- cgit v0.12 From 07bdaf208962b1c8605736f30920f4e6dfb0418e Mon Sep 17 00:00:00 2001 From: Bea Lam Date: Tue, 27 Oct 2009 15:45:53 +1000 Subject: Add qmldebugger/creatorplugin --- .../creatorplugin/QmlInspector.pluginspec | 28 ++ tools/qmldebugger/creatorplugin/README | 5 + tools/qmldebugger/creatorplugin/creatorplugin.pro | 29 ++ tools/qmldebugger/creatorplugin/images/logo.png | Bin 0 -> 2662 bytes .../creatorplugin/inspectoroutputpane.cpp | 108 +++++ .../creatorplugin/inspectoroutputpane.h | 55 +++ tools/qmldebugger/creatorplugin/qmlinspector.h | 25 ++ tools/qmldebugger/creatorplugin/qmlinspector.qrc | 6 + .../qmldebugger/creatorplugin/qmlinspectormode.cpp | 495 +++++++++++++++++++++ tools/qmldebugger/creatorplugin/qmlinspectormode.h | 91 ++++ .../creatorplugin/qmlinspectorplugin.cpp | 138 ++++++ .../qmldebugger/creatorplugin/qmlinspectorplugin.h | 50 +++ tools/qmldebugger/creatorplugin/runcontrol.cpp | 135 ++++++ tools/qmldebugger/creatorplugin/runcontrol.h | 65 +++ tools/qmldebugger/qmldebugger.pro | 10 + 15 files changed, 1240 insertions(+) create mode 100644 tools/qmldebugger/creatorplugin/QmlInspector.pluginspec create mode 100644 tools/qmldebugger/creatorplugin/README create mode 100644 tools/qmldebugger/creatorplugin/creatorplugin.pro create mode 100644 tools/qmldebugger/creatorplugin/images/logo.png create mode 100644 tools/qmldebugger/creatorplugin/inspectoroutputpane.cpp create mode 100644 tools/qmldebugger/creatorplugin/inspectoroutputpane.h create mode 100644 tools/qmldebugger/creatorplugin/qmlinspector.h create mode 100644 tools/qmldebugger/creatorplugin/qmlinspector.qrc create mode 100644 tools/qmldebugger/creatorplugin/qmlinspectormode.cpp create mode 100644 tools/qmldebugger/creatorplugin/qmlinspectormode.h create mode 100644 tools/qmldebugger/creatorplugin/qmlinspectorplugin.cpp create mode 100644 tools/qmldebugger/creatorplugin/qmlinspectorplugin.h create mode 100644 tools/qmldebugger/creatorplugin/runcontrol.cpp create mode 100644 tools/qmldebugger/creatorplugin/runcontrol.h create mode 100644 tools/qmldebugger/qmldebugger.pro diff --git a/tools/qmldebugger/creatorplugin/QmlInspector.pluginspec b/tools/qmldebugger/creatorplugin/QmlInspector.pluginspec new file mode 100644 index 0000000..cdba135 --- /dev/null +++ b/tools/qmldebugger/creatorplugin/QmlInspector.pluginspec @@ -0,0 +1,28 @@ + + Nokia Corporation + (C) 2008-2009 Nokia Corporation + +Commercial Usage + +Licensees holding valid Qt Commercial licenses may use this plugin 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 plugin may be used under the terms of the GNU Lesser +General Public License version 2.1 as published by the Free Software +Foundation. 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. + Qml support + http://qt.nokia.com + + + + + + + + \ No newline at end of file diff --git a/tools/qmldebugger/creatorplugin/README b/tools/qmldebugger/creatorplugin/README new file mode 100644 index 0000000..e7e205e --- /dev/null +++ b/tools/qmldebugger/creatorplugin/README @@ -0,0 +1,5 @@ +To enable this project, qmldebugger.pro requires that these two environment +variables be defined: + +CREATOR_SRC_DIR -> source directory for Qt Creator +CREATOR_BUILD_DIR -> build directory for Qt Creator diff --git a/tools/qmldebugger/creatorplugin/creatorplugin.pro b/tools/qmldebugger/creatorplugin/creatorplugin.pro new file mode 100644 index 0000000..d191a37 --- /dev/null +++ b/tools/qmldebugger/creatorplugin/creatorplugin.pro @@ -0,0 +1,29 @@ +TEMPLATE = lib +TARGET = QmlInspector + +INCLUDEPATH += . +DEPENDPATH += . + +include(../standalone/qmldebugger.pri) + +HEADERS += qmlinspectorplugin.h \ + qmlinspector.h \ + qmlinspectormode.h \ + inspectoroutputpane.h \ + runcontrol.h + +SOURCES += qmlinspectorplugin.cpp \ + qmlinspectormode.cpp \ + inspectoroutputpane.cpp \ + runcontrol.cpp + +OTHER_FILES += QmlInspector.pluginspec +RESOURCES += qmlinspector.qrc + +IDE_BUILD_TREE=$$(CREATOR_BUILD_DIR) + +include($$(CREATOR_SRC_DIR)/src/qtcreatorplugin.pri) +include($$(CREATOR_SRC_DIR)/src/plugins/projectexplorer/projectexplorer.pri) +include($$(CREATOR_SRC_DIR)/src/plugins/coreplugin/coreplugin.pri) +LIBS += -L$$(CREATOR_BUILD_DIR)/lib/qtcreator + diff --git a/tools/qmldebugger/creatorplugin/images/logo.png b/tools/qmldebugger/creatorplugin/images/logo.png new file mode 100644 index 0000000..5ac14a5 Binary files /dev/null and b/tools/qmldebugger/creatorplugin/images/logo.png differ diff --git a/tools/qmldebugger/creatorplugin/inspectoroutputpane.cpp b/tools/qmldebugger/creatorplugin/inspectoroutputpane.cpp new file mode 100644 index 0000000..d3f9913 --- /dev/null +++ b/tools/qmldebugger/creatorplugin/inspectoroutputpane.cpp @@ -0,0 +1,108 @@ +#include + +#include "inspectoroutputpane.h" + +InspectorOutputPane::InspectorOutputPane(QObject *parent) + : Core::IOutputPane(parent), + m_textEdit(new QTextEdit) +{ +} + +InspectorOutputPane::~InspectorOutputPane() +{ + delete m_textEdit; +} + +QWidget *InspectorOutputPane::outputWidget(QWidget *parent) +{ + Q_UNUSED(parent); + return m_textEdit; +} + +QList InspectorOutputPane::toolBarWidgets() const +{ + return QList(); +} + +QString InspectorOutputPane::name() const +{ + return tr("Inspector Output"); +} + +int InspectorOutputPane::priorityInStatusBar() const +{ + return 1; +} + +void InspectorOutputPane::clearContents() +{ + m_textEdit->clear(); +} + +void InspectorOutputPane::visibilityChanged(bool visible) +{ + Q_UNUSED(visible); +} + +void InspectorOutputPane::setFocus() +{ + m_textEdit->setFocus(); +} + +bool InspectorOutputPane::hasFocus() +{ + return m_textEdit->hasFocus(); +} + +bool InspectorOutputPane::canFocus() +{ + return true; +} + +bool InspectorOutputPane::canNavigate() +{ + return false; +} + +bool InspectorOutputPane::canNext() +{ + return false; +} + +bool InspectorOutputPane::canPrevious() +{ + return false; +} + +void InspectorOutputPane::goToNext() +{ +} + +void InspectorOutputPane::goToPrev() +{ +} + +void InspectorOutputPane::addOutput(RunControl *, const QString &text) +{ + m_textEdit->insertPlainText(text); + m_textEdit->moveCursor(QTextCursor::End); +} + +void InspectorOutputPane::addOutputInline(RunControl *, const QString &text) +{ + m_textEdit->insertPlainText(text); + m_textEdit->moveCursor(QTextCursor::End); +} + +void InspectorOutputPane::addErrorOutput(RunControl *, const QString &text) +{ + m_textEdit->append(text); + m_textEdit->moveCursor(QTextCursor::End); +} + +void InspectorOutputPane::addInspectorStatus(const QString &text) +{ + m_textEdit->append(text); + m_textEdit->moveCursor(QTextCursor::End); +} + diff --git a/tools/qmldebugger/creatorplugin/inspectoroutputpane.h b/tools/qmldebugger/creatorplugin/inspectoroutputpane.h new file mode 100644 index 0000000..60c648a --- /dev/null +++ b/tools/qmldebugger/creatorplugin/inspectoroutputpane.h @@ -0,0 +1,55 @@ +#ifndef INSPECTOROUTPUTPANE_H +#define INSPECTOROUTPUTPANE_H + +#include + +#include + + +QT_BEGIN_NAMESPACE + +class QTextEdit; + +class RunControl; + +class InspectorOutputPane : public Core::IOutputPane +{ + Q_OBJECT +public: + InspectorOutputPane(QObject *parent = 0); + virtual ~InspectorOutputPane(); + + virtual QWidget *outputWidget(QWidget *parent); + virtual QList toolBarWidgets() const; + virtual QString name() const; + + virtual int priorityInStatusBar() const; + + virtual void clearContents(); + virtual void visibilityChanged(bool visible); + + virtual void setFocus(); + virtual bool hasFocus(); + virtual bool canFocus(); + + virtual bool canNavigate(); + virtual bool canNext(); + virtual bool canPrevious(); + virtual void goToNext(); + virtual void goToPrev(); + +public slots: + void addOutput(RunControl *, const QString &text); + void addOutputInline(RunControl *, const QString &text); + + void addErrorOutput(RunControl *, const QString &text); + void addInspectorStatus(const QString &text); + +private: + QTextEdit *m_textEdit; +}; + +QT_END_NAMESPACE + +#endif + diff --git a/tools/qmldebugger/creatorplugin/qmlinspector.h b/tools/qmldebugger/creatorplugin/qmlinspector.h new file mode 100644 index 0000000..98b9cbe --- /dev/null +++ b/tools/qmldebugger/creatorplugin/qmlinspector.h @@ -0,0 +1,25 @@ +#ifndef QMLINSPECTOR_H +#define QMLINSPECTOR_H + +#include + +namespace QmlInspector { + namespace Constants { + const char * const RUN = "QmlInspector.Run"; + const char * const STOP = "QmlInspector.Stop"; + + const char * const C_INSPECTOR = "QmlInspector"; + }; + + class StartParameters + { + public: + StartParameters() : port(0) {} + ~StartParameters() {} + + QString address; + quint16 port; + }; +}; + +#endif diff --git a/tools/qmldebugger/creatorplugin/qmlinspector.qrc b/tools/qmldebugger/creatorplugin/qmlinspector.qrc new file mode 100644 index 0000000..45e8dda --- /dev/null +++ b/tools/qmldebugger/creatorplugin/qmlinspector.qrc @@ -0,0 +1,6 @@ + + + images/logo.png + + + diff --git a/tools/qmldebugger/creatorplugin/qmlinspectormode.cpp b/tools/qmldebugger/creatorplugin/qmlinspectormode.cpp new file mode 100644 index 0000000..9367b19 --- /dev/null +++ b/tools/qmldebugger/creatorplugin/qmlinspectormode.cpp @@ -0,0 +1,495 @@ +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include "../standalone/objectpropertiesview.h" +#include "../standalone/objecttree.h" +#include "../standalone/watchtable.h" +#include "../standalone/canvasframerate.h" +#include "../standalone/expressionquerywidget.h" + +#include "qmlinspector.h" +#include "qmlinspectormode.h" + +QT_BEGIN_NAMESPACE + + +class EngineSpinBox : public QSpinBox +{ + Q_OBJECT +public: + struct EngineInfo + { + QString name; + int id; + }; + + EngineSpinBox(QWidget *parent = 0); + + void addEngine(int engine, const QString &name); + void clearEngines(); + +protected: + virtual QString textFromValue(int value) const; + virtual int valueFromText(const QString &text) const; + +private: + QList m_engines; +}; + +EngineSpinBox::EngineSpinBox(QWidget *parent) + : QSpinBox(parent) +{ + setEnabled(false); + setReadOnly(true); + setRange(0, 0); +} + +void EngineSpinBox::addEngine(int engine, const QString &name) +{ + EngineInfo info; + info.id = engine; + if (name.isEmpty()) + info.name = tr("Engine %1", "engine number").arg(engine); + else + info.name = name; + m_engines << info; + + setRange(0, m_engines.count()-1); +} + +void EngineSpinBox::clearEngines() +{ + m_engines.clear(); +} + +QString EngineSpinBox::textFromValue(int value) const +{ + for (int i=0; i"); +} + +int EngineSpinBox::valueFromText(const QString &text) const +{ + for (int i=0; ivalue(); +} + +void QmlInspectorMode::connectToViewer() +{ + if (m_conn && m_conn->state() != QAbstractSocket::UnconnectedState) + return; + + delete m_client; m_client = 0; + + if (m_conn) { + m_conn->disconnectFromHost(); + delete m_conn; + } + + m_conn = new QmlDebugConnection(this); + connect(m_conn, SIGNAL(stateChanged(QAbstractSocket::SocketState)), + SLOT(connectionStateChanged())); + connect(m_conn, SIGNAL(error(QAbstractSocket::SocketError)), + SLOT(connectionError())); + m_conn->connectToHost(m_addressEdit->text(), m_portSpinBox->value()); +} + +void QmlInspectorMode::disconnectFromViewer() +{ + m_conn->disconnectFromHost(); +} + +void QmlInspectorMode::connectionStateChanged() +{ + switch (m_conn->state()) { + default: + case QAbstractSocket::UnconnectedState: + emit statusMessage(tr("[Inspector] disconnected\n\n")); + m_addressEdit->setEnabled(true); + m_portSpinBox->setEnabled(true); + break; + case QAbstractSocket::HostLookupState: + emit statusMessage(tr("[Inspector] resolving host...")); + break; + case QAbstractSocket::ConnectingState: + emit statusMessage(tr("[Inspector] connecting to debug server...")); + break; + case QAbstractSocket::ConnectedState: + { + emit statusMessage(tr("[Inspector] connected\n")); + m_addressEdit->setEnabled(false); + m_portSpinBox->setEnabled(false); + + if (!m_client) { + m_client = new QmlEngineDebug(m_conn, this); + m_objectTreeWidget->setEngineDebug(m_client); + m_propertiesWidget->setEngineDebug(m_client); + m_watchTableModel->setEngineDebug(m_client); + m_expressionWidget->setEngineDebug(m_client); + } + + m_objectTreeWidget->clear(); + m_propertiesWidget->clear(); + m_expressionWidget->clear(); + m_watchTableModel->removeAllWatches(); + m_frameRateWidget->reset(m_conn); + + reloadEngines(); + break; + } + case QAbstractSocket::ClosingState: + emit statusMessage(tr("[Inspector] closing...")); + break; + } +} + +void QmlInspectorMode::connectionError() +{ + emit statusMessage(tr("[Inspector] error: (%1) %2", "%1=error code, %2=error message") + .arg(m_conn->error()).arg(m_conn->errorString())); +} + +void QmlInspectorMode::initActions() +{ + m_actions.startAction = new QAction(tr("Start Inspector"), this); + m_actions.startAction->setIcon(QIcon(ProjectExplorer::Constants::ICON_RUN)); + + m_actions.stopAction = new QAction(tr("Stop Inspector"), this); + m_actions.stopAction->setIcon(QIcon(ProjectExplorer::Constants::ICON_STOP)); + + Core::ICore *core = Core::ICore::instance(); + Core::ActionManager *am = core->actionManager(); + Core::UniqueIDManager *uidm = core->uniqueIDManager(); + + QList context; + context << uidm->uniqueIdentifier(QmlInspector::Constants::C_INSPECTOR); + + am->registerAction(m_actions.startAction, QmlInspector::Constants::RUN, context); + connect(m_actions.startAction, SIGNAL(triggered()), SIGNAL(startViewer())); + + am->registerAction(m_actions.stopAction, QmlInspector::Constants::STOP, context); + connect(m_actions.stopAction, SIGNAL(triggered()), SIGNAL(stopViewer())); +} + + +QToolButton *QmlInspectorMode::createToolButton(QAction *action) +{ + QToolButton *button = new QToolButton; + button->setDefaultAction(action); + return button; +} + +QWidget *QmlInspectorMode::createMainView() +{ + initWidgets(); + + Utils::FancyMainWindow *mainWindow = new Utils::FancyMainWindow; + mainWindow->setTabPosition(Qt::AllDockWidgetAreas, QTabWidget::North); + mainWindow->setDocumentMode(true); + + QBoxLayout *editorHolderLayout = new QVBoxLayout; + editorHolderLayout->setMargin(0); + editorHolderLayout->setSpacing(0); + + QWidget *editorAndFindWidget = new QWidget; + editorAndFindWidget->setLayout(editorHolderLayout); + editorHolderLayout->addWidget(new Core::EditorManagerPlaceHolder(this)); + editorHolderLayout->addWidget(new Core::FindToolBarPlaceHolder(editorAndFindWidget)); + + Utils::StyledBar *treeOptionBar = new Utils::StyledBar; + QHBoxLayout *treeOptionBarLayout = new QHBoxLayout(treeOptionBar); + treeOptionBarLayout->setContentsMargins(5, 0, 5, 0); + treeOptionBarLayout->setSpacing(5); + treeOptionBarLayout->addWidget(new QLabel(tr("QML engine:"))); + treeOptionBarLayout->addWidget(m_engineSpinBox); + + QWidget *treeWindow = new QWidget; + QVBoxLayout *treeWindowLayout = new QVBoxLayout(treeWindow); + treeWindowLayout->setMargin(0); + treeWindowLayout->setSpacing(0); + treeWindowLayout->addWidget(treeOptionBar); + treeWindowLayout->addWidget(m_objectTreeWidget); + + Core::MiniSplitter *documentAndTree = new Core::MiniSplitter; + documentAndTree->addWidget(editorAndFindWidget); + documentAndTree->addWidget(new Core::RightPanePlaceHolder(this)); + documentAndTree->addWidget(treeWindow); + documentAndTree->setStretchFactor(0, 2); + documentAndTree->setStretchFactor(1, 0); + documentAndTree->setStretchFactor(2, 0); + + Utils::StyledBar *configBar = new Utils::StyledBar; + configBar->setProperty("topBorder", true); + + QHBoxLayout *configBarLayout = new QHBoxLayout(configBar); + configBarLayout->setMargin(0); + configBarLayout->setSpacing(5); + + Core::ICore *core = Core::ICore::instance(); + Core::ActionManager *am = core->actionManager(); + configBarLayout->addWidget(createToolButton(am->command(QmlInspector::Constants::RUN)->action())); + configBarLayout->addWidget(createToolButton(am->command(QmlInspector::Constants::STOP)->action())); + configBarLayout->addWidget(m_addressEdit); + configBarLayout->addWidget(m_portSpinBox); + configBarLayout->addStretch(); + + QWidget *widgetAboveTabs = new QWidget; + QVBoxLayout *widgetAboveTabsLayout = new QVBoxLayout(widgetAboveTabs); + widgetAboveTabsLayout->setMargin(0); + widgetAboveTabsLayout->setSpacing(0); + widgetAboveTabsLayout->addWidget(documentAndTree); + widgetAboveTabsLayout->addWidget(configBar); + + Core::MiniSplitter *mainSplitter = new Core::MiniSplitter(Qt::Vertical); + mainSplitter->addWidget(widgetAboveTabs); + mainSplitter->addWidget(createBottomWindow()); + mainSplitter->setStretchFactor(0, 3); + mainSplitter->setStretchFactor(1, 1); + + QWidget *centralWidget = new QWidget; + QVBoxLayout *centralLayout = new QVBoxLayout(centralWidget); + centralLayout->setMargin(0); + centralLayout->setSpacing(0); + centralLayout->addWidget(mainSplitter); + + mainWindow->setCentralWidget(centralWidget); + + return mainWindow; +} + +QWidget *QmlInspectorMode::createBottomWindow() +{ + Utils::FancyMainWindow *win = new Utils::FancyMainWindow; + win->setTabPosition(Qt::AllDockWidgetAreas, QTabWidget::North); + win->setDocumentMode(true); + win->setTrackingEnabled(true); + + Core::MiniSplitter *leftSplitter = new Core::MiniSplitter(Qt::Vertical); + leftSplitter->addWidget(m_propertiesWidget); + leftSplitter->addWidget(m_expressionWidget); + leftSplitter->setStretchFactor(0, 2); + leftSplitter->setStretchFactor(1, 1); + + Core::MiniSplitter *propSplitter = new Core::MiniSplitter(Qt::Horizontal); + propSplitter->addWidget(leftSplitter); + propSplitter->addWidget(m_watchTableView); + propSplitter->setStretchFactor(0, 2); + propSplitter->setStretchFactor(1, 1); + propSplitter->setWindowTitle(tr("Properties and Watchers")); + + QDockWidget *propertiesDock = win->addDockForWidget(propSplitter); + win->addDockWidget(Qt::TopDockWidgetArea, propertiesDock); + + QDockWidget *frameRateDock = win->addDockForWidget(m_frameRateWidget); + win->addDockWidget(Qt::TopDockWidgetArea, frameRateDock); + + // stack the dock widgets as tabs + win->tabifyDockWidget(frameRateDock, propertiesDock); + + return win; +} + +QWidget *QmlInspectorMode::createModeWindow() +{ + // right-side window with editor, output etc. + Core::MiniSplitter *mainWindowSplitter = new Core::MiniSplitter; + mainWindowSplitter->addWidget(createMainView()); + mainWindowSplitter->addWidget(new Core::OutputPanePlaceHolder(this)); + mainWindowSplitter->setStretchFactor(0, 10); + mainWindowSplitter->setStretchFactor(1, 0); + mainWindowSplitter->setOrientation(Qt::Vertical); + + // navigation + right-side window + Core::MiniSplitter *splitter = new Core::MiniSplitter; + splitter->addWidget(new Core::NavigationWidgetPlaceHolder(this)); + splitter->addWidget(mainWindowSplitter); + splitter->setStretchFactor(0, 0); + splitter->setStretchFactor(1, 1); + return splitter; +} + +void QmlInspectorMode::initWidgets() +{ + m_objectTreeWidget = new ObjectTree; + m_propertiesWidget = new ObjectPropertiesView; + m_watchTableView = new WatchTableView(m_watchTableModel); + m_frameRateWidget = new CanvasFrameRate; + m_expressionWidget = new ExpressionQueryWidget; + + // FancyMainWindow uses widgets' window titles for tab labels + m_objectTreeWidget->setWindowTitle(tr("Object Tree")); + m_frameRateWidget->setWindowTitle(tr("Frame rate")); + + m_watchTableView->setModel(m_watchTableModel); + WatchTableHeaderView *header = new WatchTableHeaderView(m_watchTableModel); + m_watchTableView->setHorizontalHeader(header); + + connect(m_objectTreeWidget, SIGNAL(currentObjectChanged(QmlDebugObjectReference)), + m_propertiesWidget, SLOT(reload(QmlDebugObjectReference))); + connect(m_objectTreeWidget, SIGNAL(expressionWatchRequested(QmlDebugObjectReference,QString)), + m_watchTableModel, SLOT(expressionWatchRequested(QmlDebugObjectReference,QString))); + + connect(m_propertiesWidget, SIGNAL(activated(QmlDebugObjectReference,QmlDebugPropertyReference)), + m_watchTableModel, SLOT(togglePropertyWatch(QmlDebugObjectReference,QmlDebugPropertyReference))); + + connect(m_watchTableModel, SIGNAL(watchCreated(QmlDebugWatch*)), + m_propertiesWidget, SLOT(watchCreated(QmlDebugWatch*))); + + connect(m_watchTableModel, SIGNAL(rowsInserted(QModelIndex,int,int)), + m_watchTableView, SLOT(scrollToBottom())); + + connect(m_watchTableView, SIGNAL(objectActivated(int)), + m_objectTreeWidget, SLOT(setCurrentObject(int))); + + connect(m_objectTreeWidget, SIGNAL(currentObjectChanged(QmlDebugObjectReference)), + m_expressionWidget, SLOT(setCurrentObject(QmlDebugObjectReference))); + + m_addressEdit = new QLineEdit; + m_addressEdit->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred); + m_addressEdit->setText("127.0.0.1"); + + m_portSpinBox = new QSpinBox; + m_portSpinBox->setMinimum(1024); + m_portSpinBox->setMaximum(20000); + m_portSpinBox->setValue(3768); + + m_engineSpinBox = new EngineSpinBox; + m_engineSpinBox->setEnabled(false); + connect(m_engineSpinBox, SIGNAL(valueChanged(int)), + SLOT(queryEngineContext(int))); +} + +void QmlInspectorMode::reloadEngines() +{ + if (m_engineQuery) { + emit statusMessage("[Inspector] Waiting for response to previous engine query"); + return; + } + + m_engineSpinBox->setEnabled(false); + + m_engineQuery = m_client->queryAvailableEngines(this); + if (!m_engineQuery->isWaiting()) + enginesChanged(); + else + QObject::connect(m_engineQuery, SIGNAL(stateChanged(State)), + this, SLOT(enginesChanged())); +} + +void QmlInspectorMode::enginesChanged() +{ + m_engineSpinBox->clearEngines(); + + QList engines = m_engineQuery->engines(); + delete m_engineQuery; m_engineQuery = 0; + + if (engines.isEmpty()) + qWarning("qmldebugger: no engines found!"); + + m_engineSpinBox->setEnabled(true); + + for (int i=0; iaddEngine(engines.at(i).debugId(), engines.at(i).name()); + + if (engines.count() > 0) { + m_engineSpinBox->setValue(engines.at(0).debugId()); + queryEngineContext(engines.at(0).debugId()); + } +} + +void QmlInspectorMode::queryEngineContext(int id) +{ + if (id < 0) + return; + + if (m_contextQuery) { + delete m_contextQuery; + m_contextQuery = 0; + } + + m_contextQuery = m_client->queryRootContexts(QmlDebugEngineReference(id), this); + if (!m_contextQuery->isWaiting()) + contextChanged(); + else + QObject::connect(m_contextQuery, SIGNAL(stateChanged(State)), + this, SLOT(contextChanged())); +} + +void QmlInspectorMode::contextChanged() +{ + //dump(m_contextQuery->rootContext(), 0); + + foreach (const QmlDebugObjectReference &object, m_contextQuery->rootContext().objects()) + m_objectTreeWidget->reload(object.debugId()); + + delete m_contextQuery; m_contextQuery = 0; +} + +QT_END_NAMESPACE + +#include "qmlinspectormode.moc" + diff --git a/tools/qmldebugger/creatorplugin/qmlinspectormode.h b/tools/qmldebugger/creatorplugin/qmlinspectormode.h new file mode 100644 index 0000000..c70d630 --- /dev/null +++ b/tools/qmldebugger/creatorplugin/qmlinspectormode.h @@ -0,0 +1,91 @@ +#ifndef QMLINSPECTORMODE_H +#define QMLINSPECTORMODE_H + +#include + +#include +#include + +QT_BEGIN_NAMESPACE + +class QToolButton; +class QLineEdit; +class QSpinBox; +class QLabel; + +class QmlEngineDebug; +class QmlDebugConnection; +class QmlDebugEnginesQuery; +class QmlDebugRootContextQuery; +class ObjectTree; +class WatchTableModel; +class WatchTableView; +class ObjectPropertiesView; +class CanvasFrameRate; +class ExpressionQueryWidget; +class EngineSpinBox; + + +class QmlInspectorMode : public Core::BaseMode +{ + Q_OBJECT + +public: + QmlInspectorMode(QObject *parent = 0); + + + quint16 viewerPort() const; + +signals: + void startViewer(); + void stopViewer(); + void statusMessage(const QString &text); + +public slots: + void connectToViewer(); // using host, port from widgets + void disconnectFromViewer(); + +private slots: + void connectionStateChanged(); + void connectionError(); + void reloadEngines(); + void enginesChanged(); + void queryEngineContext(int); + void contextChanged(); + +private: + struct Actions { + QAction *startAction; + QAction *stopAction; + }; + + void initActions(); + QWidget *createModeWindow(); + QWidget *createMainView(); + void initWidgets(); + QWidget *createBottomWindow(); + QToolButton *createToolButton(QAction *action); + + Actions m_actions; + + QmlDebugConnection *m_conn; + QmlEngineDebug *m_client; + + QmlDebugEnginesQuery *m_engineQuery; + QmlDebugRootContextQuery *m_contextQuery; + + ObjectTree *m_objectTreeWidget; + ObjectPropertiesView *m_propertiesWidget; + WatchTableModel *m_watchTableModel; + WatchTableView *m_watchTableView; + CanvasFrameRate *m_frameRateWidget; + ExpressionQueryWidget *m_expressionWidget; + + QLineEdit *m_addressEdit; + QSpinBox *m_portSpinBox; + EngineSpinBox *m_engineSpinBox; +}; + +QT_END_NAMESPACE + +#endif diff --git a/tools/qmldebugger/creatorplugin/qmlinspectorplugin.cpp b/tools/qmldebugger/creatorplugin/qmlinspectorplugin.cpp new file mode 100644 index 0000000..c743974 --- /dev/null +++ b/tools/qmldebugger/creatorplugin/qmlinspectorplugin.cpp @@ -0,0 +1,138 @@ +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include + +#include "runcontrol.h" +#include "qmlinspector.h" +#include "qmlinspectormode.h" +#include "inspectoroutputpane.h" +#include "qmlinspectorplugin.h" + +QT_BEGIN_NAMESPACE + + +QmlInspectorPlugin::QmlInspectorPlugin() + : m_inspectMode(0), + m_runControl(0) +{ +} + +QmlInspectorPlugin::~QmlInspectorPlugin() +{ +} + +void QmlInspectorPlugin::shutdown() +{ + removeObject(m_inspectMode); + delete m_inspectMode; + m_inspectMode = 0; + + removeObject(m_outputPane); + delete m_outputPane; + m_outputPane = 0; +} + +bool QmlInspectorPlugin::initialize(const QStringList &arguments, QString *errorString) +{ + Q_UNUSED(arguments); + Q_UNUSED(errorString); + + Core::ICore *core = Core::ICore::instance(); + Core::UniqueIDManager *uidm = core->uniqueIDManager(); + + QList modeContext; + modeContext.append(uidm->uniqueIdentifier(QmlInspector::Constants::C_INSPECTOR)); + + QList inspectorContext; + inspectorContext.append(uidm->uniqueIdentifier(Core::Constants::C_EDITORMANAGER)); + inspectorContext.append(uidm->uniqueIdentifier(QmlInspector::Constants::C_INSPECTOR)); + inspectorContext.append(uidm->uniqueIdentifier(Core::Constants::C_NAVIGATION_PANE)); + + m_inspectMode = new QmlInspectorMode(this); + connect(m_inspectMode, SIGNAL(startViewer()), SLOT(startViewer())); + connect(m_inspectMode, SIGNAL(stopViewer()), SLOT(stopViewer())); + m_inspectMode->setContext(modeContext); + addObject(m_inspectMode); + + m_outputPane = new InspectorOutputPane; + addObject(m_outputPane); + + connect(m_inspectMode, SIGNAL(statusMessage(QString)), + m_outputPane, SLOT(addInspectorStatus(QString))); + + m_runControlFactory = new QmlInspectorRunControlFactory(this); + addAutoReleasedObject(m_runControlFactory); + + return true; +} + +void QmlInspectorPlugin::extensionsInitialized() +{ +} + +void QmlInspectorPlugin::startViewer() +{ + stopViewer(); + + ProjectExplorer::Project *project = 0; + ProjectExplorer::ProjectExplorerPlugin *plugin = ProjectExplorer::ProjectExplorerPlugin::instance(); + if (plugin) + project = plugin->currentProject(); + if (!project) { + qDebug() << "No project loaded"; // TODO should this just run the debugger without a viewer? + return; + } + + QSharedPointer rc = project->activeRunConfiguration(); + + QmlInspector::StartParameters sp; + sp.port = m_inspectMode->viewerPort(); + + m_runControl = m_runControlFactory->create(rc, ProjectExplorer::Constants::RUNMODE, sp); + + if (m_runControl) { + connect(m_runControl, SIGNAL(started()), m_inspectMode, SLOT(connectToViewer())); + connect(m_runControl, SIGNAL(finished()), m_inspectMode, SLOT(disconnectFromViewer())); + + connect(m_runControl, SIGNAL(addToOutputWindow(RunControl*,QString)), + m_outputPane, SLOT(addOutput(RunControl*,QString))); + connect(m_runControl, SIGNAL(addToOutputWindowInline(RunControl*,QString)), + m_outputPane, SLOT(addOutputInline(RunControl*,QString))); + connect(m_runControl, SIGNAL(error(RunControl*,QString)), + m_outputPane, SLOT(addErrorOutput(RunControl*,QString))); + + m_runControl->start(); + m_outputPane->popup(false); + } + +} + +void QmlInspectorPlugin::stopViewer() +{ + if (m_runControl) { + m_runControl->stop(); + m_runControl->deleteLater(); + m_runControl = 0; + } +} + + +Q_EXPORT_PLUGIN(QmlInspectorPlugin) + +QT_END_NAMESPACE + diff --git a/tools/qmldebugger/creatorplugin/qmlinspectorplugin.h b/tools/qmldebugger/creatorplugin/qmlinspectorplugin.h new file mode 100644 index 0000000..b0237e2 --- /dev/null +++ b/tools/qmldebugger/creatorplugin/qmlinspectorplugin.h @@ -0,0 +1,50 @@ +#ifndef QMLINSPECTORPLUGIN_H +#define QMLINSPECTORPLUGIN_H + +#include + +#include +#include + +QT_BEGIN_NAMESPACE + +class QStringList; + + +class QmlInspectorRunControlFactory; +class QmlInspectorMode; +class InspectorOutputPane; + +namespace ProjectExplorer +{ + class RunControl; +} + +class QmlInspectorPlugin : public ExtensionSystem::IPlugin +{ + Q_OBJECT + +public: + QmlInspectorPlugin(); + ~QmlInspectorPlugin(); + + virtual bool initialize(const QStringList &arguments, QString *errorString); + virtual void extensionsInitialized(); + virtual void shutdown(); + +private slots: + void startViewer(); + void stopViewer(); + +private: + QmlInspectorMode *m_inspectMode; + InspectorOutputPane *m_outputPane; + + QmlInspectorRunControlFactory *m_runControlFactory; + QPointer m_runControl; +}; + + +QT_END_NAMESPACE + +#endif // QMLINSPECTORPLUGIN_H diff --git a/tools/qmldebugger/creatorplugin/runcontrol.cpp b/tools/qmldebugger/creatorplugin/runcontrol.cpp new file mode 100644 index 0000000..11c7165 --- /dev/null +++ b/tools/qmldebugger/creatorplugin/runcontrol.cpp @@ -0,0 +1,135 @@ +#include +#include + +#include +#include +#include + +#include "runcontrol.h" + +using namespace ProjectExplorer; + + +QmlInspectorRunControlFactory::QmlInspectorRunControlFactory(QObject *parent) + : ProjectExplorer::IRunControlFactory(parent) +{ +} + +bool QmlInspectorRunControlFactory::canRun(const QSharedPointer &runConfiguration, const QString &mode) const +{ + Q_UNUSED(runConfiguration); + if (mode != ProjectExplorer::Constants::RUNMODE) + return false; + return true; +} + +ProjectExplorer::RunControl *QmlInspectorRunControlFactory::create(const QSharedPointer &runConfiguration, const QString &mode) +{ + Q_UNUSED(mode); + return new QmlInspectorRunControl(runConfiguration); +} + +ProjectExplorer::RunControl *QmlInspectorRunControlFactory::create(const QSharedPointer &runConfiguration, +const QString &mode, const QmlInspector::StartParameters &sp) +{ + Q_UNUSED(mode); + return new QmlInspectorRunControl(runConfiguration, sp); +} + +QString QmlInspectorRunControlFactory::displayName() const +{ + return tr("Qml Inspector"); +} + +QWidget *QmlInspectorRunControlFactory::configurationWidget(const QSharedPointer &runConfiguration) +{ + Q_UNUSED(runConfiguration); + return 0; +} + + + +QmlInspectorRunControl::QmlInspectorRunControl(const QSharedPointer &runConfiguration, +const QmlInspector::StartParameters &sp) + : ProjectExplorer::RunControl(runConfiguration), + m_running(false), + m_viewerLauncher(0), + m_startParams(sp) +{ +} + +QmlInspectorRunControl::~QmlInspectorRunControl() +{ +} + +void QmlInspectorRunControl::start() +{ + if (m_running || m_viewerLauncher) + return; + + m_viewerLauncher = new ProjectExplorer::ApplicationLauncher(this); + connect(m_viewerLauncher, SIGNAL(applicationError(QString)), SLOT(applicationError(QString))); + connect(m_viewerLauncher, SIGNAL(processExited(int)), SLOT(viewerExited())); + connect(m_viewerLauncher, SIGNAL(appendOutput(QString)), SLOT(appendOutput(QString))); + connect(m_viewerLauncher, SIGNAL(bringToForegroundRequested(qint64)), + this, SLOT(appStarted())); + + QSharedPointer rc = + runConfiguration().objectCast(); + if (rc.isNull()) { // TODO + return; + } + + ProjectExplorer::Environment env = rc->environment(); + env.set("QML_DEBUG_SERVER_PORT", QString::number(m_startParams.port)); + + QStringList arguments = rc->commandLineArguments(); + arguments << QLatin1String("-stayontop"); + + m_viewerLauncher->setEnvironment(env.toStringList()); + m_viewerLauncher->setWorkingDirectory(rc->workingDirectory()); + + m_running = true; + + m_viewerLauncher->start(static_cast(rc->runMode()), + rc->executable(), arguments); +} + +void QmlInspectorRunControl::stop() +{ + if (m_viewerLauncher->isRunning()) + m_viewerLauncher->stop(); +} + +bool QmlInspectorRunControl::isRunning() const +{ + return m_running; +} + +void QmlInspectorRunControl::appStarted() +{ + QTimer::singleShot(500, this, SLOT(delayedStart())); +} + +void QmlInspectorRunControl::appendOutput(const QString &s) +{ + emit addToOutputWindow(this, s); +} + +void QmlInspectorRunControl::delayedStart() +{ + emit started(); +} + +void QmlInspectorRunControl::viewerExited() +{ + m_running = false; + emit finished(); + + deleteLater(); +} + +void QmlInspectorRunControl::applicationError(const QString &s) +{ + emit error(this, s); +} diff --git a/tools/qmldebugger/creatorplugin/runcontrol.h b/tools/qmldebugger/creatorplugin/runcontrol.h new file mode 100644 index 0000000..b2976f6 --- /dev/null +++ b/tools/qmldebugger/creatorplugin/runcontrol.h @@ -0,0 +1,65 @@ +#ifndef QMLINSPECTORRUNCONTROL_H +#define QMLINSPECTORRUNCONTROL_H + +#include + +#include + +#include "qmlinspector.h" + +namespace ProjectExplorer { + class ApplicationLauncher; +} + +class QmlInspectorRunControlFactory : public ProjectExplorer::IRunControlFactory +{ + Q_OBJECT + +public: + explicit QmlInspectorRunControlFactory(QObject *parent); + + virtual bool canRun( + const QSharedPointer &runConfiguration, + const QString &mode) const; + + virtual ProjectExplorer::RunControl *create( + const QSharedPointer &runConfiguration, + const QString &mode); + + ProjectExplorer::RunControl *create( + const QSharedPointer &runConfiguration, + const QString &mode, + const QmlInspector::StartParameters &sp); + + virtual QString displayName() const; + + virtual QWidget *configurationWidget(const QSharedPointer &runConfiguration); +}; + +class QmlInspectorRunControl : public ProjectExplorer::RunControl +{ + Q_OBJECT + +public: + explicit QmlInspectorRunControl(const QSharedPointer &runConfiguration, + const QmlInspector::StartParameters &sp = QmlInspector::StartParameters()); + ~QmlInspectorRunControl(); + + virtual void start(); + virtual void stop(); + virtual bool isRunning() const; + +private slots: + void appendOutput(const QString &s); + void appStarted(); + void delayedStart(); + void viewerExited(); + void applicationError(const QString &error); + +private: + bool m_running; + ProjectExplorer::ApplicationLauncher *m_viewerLauncher; + QmlInspector::StartParameters m_startParams; +}; + +#endif diff --git a/tools/qmldebugger/qmldebugger.pro b/tools/qmldebugger/qmldebugger.pro new file mode 100644 index 0000000..2dd353a --- /dev/null +++ b/tools/qmldebugger/qmldebugger.pro @@ -0,0 +1,10 @@ +TEMPLATE = subdirs +CONFIG += ordered + +SUBDIRS = standalone + +CREATOR_SRC = $$(CREATOR_SRC_DIR) +CREATOR_BUILD = $$(CREATOR_BUILD_DIR) +!isEmpty(CREATOR_SRC):!isEmpty(CREATOR_BUILD) { + SUBDIRS += creatorplugin +} -- cgit v0.12