void recurseObjectIdList(const QDeclarativeDebugObjectReference &ref, QList<int> &debugIds, QList<QString> &objectIds)
{
    debugIds << ref.debugId();
    objectIds << ref.idString();
    foreach (const QDeclarativeDebugObjectReference &child, ref.children())
        recurseObjectIdList(child, debugIds, objectIds);
}
void QmlJSLiveTextPreview::changeSelectedElements(QList<int> offsets, const QString &wordAtCursor)
{
    if (m_editors.isEmpty() || !m_previousDoc || !m_clientProxy)
        return;

    QDeclarativeDebugObjectReference objectRefUnderCursor;
    objectRefUnderCursor = m_clientProxy.data()->objectReferenceForId(wordAtCursor);

    QList<int> selectedReferences;
    bool containsReferenceUnderCursor = false;

    foreach(int offset, offsets) {
        if (offset >= 0) {
            QList<int> list = objectReferencesForOffset(offset);

            if (!containsReferenceUnderCursor && objectRefUnderCursor.debugId() != -1) {
                foreach(int id, list) {
                    if (id == objectRefUnderCursor.debugId()) {
                        containsReferenceUnderCursor = true;
                        break;
                    }
                }
            }

            selectedReferences << list;
        }
Beispiel #3
0
void tst_QDeclarativeDebug::watch_property()
{
    QDeclarativeDebugObjectReference obj = findRootObject();
    QDeclarativeDebugPropertyReference prop = findProperty(obj.properties(), "width");

    QDeclarativeDebugPropertyWatch *watch;

    QDeclarativeEngineDebug *unconnected = new QDeclarativeEngineDebug(0);
    watch = unconnected->addWatch(prop, this);
    QCOMPARE(watch->state(), QDeclarativeDebugWatch::Dead);
    delete watch;
    delete unconnected;

    watch = m_dbg->addWatch(QDeclarativeDebugPropertyReference(), this);
    QVERIFY(QDeclarativeDebugTest::waitForSignal(watch, SIGNAL(stateChanged(QDeclarativeDebugWatch::State))));
    QCOMPARE(watch->state(), QDeclarativeDebugWatch::Inactive);
    delete watch;

    watch = m_dbg->addWatch(prop, this);
    QCOMPARE(watch->state(), QDeclarativeDebugWatch::Waiting);
    QCOMPARE(watch->objectDebugId(), obj.debugId());
    QCOMPARE(watch->name(), prop.name());

    QSignalSpy spy(watch, SIGNAL(valueChanged(QByteArray,QVariant)));

    int origWidth = m_rootItem->property("width").toInt();
    m_rootItem->setProperty("width", origWidth*2);

    // stateChanged() is received before valueChanged()
    QVERIFY(QDeclarativeDebugTest::waitForSignal(watch, SIGNAL(stateChanged(QDeclarativeDebugWatch::State))));
    QCOMPARE(watch->state(), QDeclarativeDebugWatch::Active);
    QCOMPARE(spy.count(), 1);

    m_dbg->removeWatch(watch);
    delete watch;

    // restore original value and verify spy doesn't get additional signal since watch has been removed
    m_rootItem->setProperty("width", origWidth);
    QTest::qWait(100);
    QCOMPARE(spy.count(), 1);

    QCOMPARE(spy.at(0).at(0).value<QByteArray>(), prop.name().toUtf8());
    QCOMPARE(spy.at(0).at(1).value<QVariant>(), qVariantFromValue(origWidth*2));
}
Beispiel #4
0
void tst_QDeclarativeDebug::setMethodBody()
{
    QDeclarativeDebugObjectReference obj = findRootObject(2);

    QObject *root = m_components.at(2);
    // Without args
    {
    QVariant rv;
    QVERIFY(QMetaObject::invokeMethod(root, "myMethodNoArgs", Qt::DirectConnection,
                                      Q_RETURN_ARG(QVariant, rv)));
    QVERIFY(rv == QVariant(qreal(3)));


    QVERIFY(m_dbg->setMethodBody(obj.debugId(), "myMethodNoArgs", "return 7"));
    QTest::qWait(100);

    QVERIFY(QMetaObject::invokeMethod(root, "myMethodNoArgs", Qt::DirectConnection,
                                      Q_RETURN_ARG(QVariant, rv)));
    QVERIFY(rv == QVariant(qreal(7)));
    }

    // With args
    {
    QVariant rv;
    QVERIFY(QMetaObject::invokeMethod(root, "myMethod", Qt::DirectConnection,
                                      Q_RETURN_ARG(QVariant, rv), Q_ARG(QVariant, QVariant(19))));
    QVERIFY(rv == QVariant(qreal(28)));

    QVERIFY(m_dbg->setMethodBody(obj.debugId(), "myMethod", "return a + 7"));
    QTest::qWait(100);

    QVERIFY(QMetaObject::invokeMethod(root, "myMethod", Qt::DirectConnection,
                                      Q_RETURN_ARG(QVariant, rv), Q_ARG(QVariant, QVariant(19))));
    QVERIFY(rv == QVariant(qreal(26)));
    }
}
QString ObjectPropertiesView::propertyBaseClass(const QDeclarativeDebugObjectReference &object, const QDeclarativeDebugPropertyReference &property, int &depth)
{
    ExtensionSystem::PluginManager *pluginManager = ExtensionSystem::PluginManager::instance();
    QmlJSEditor::ModelManagerInterface *modelManager = pluginManager->getObject<QmlJSEditor::ModelManagerInterface>();
    QmlJS::Snapshot snapshot = modelManager->snapshot();

    QmlJS::Document::Ptr document = snapshot.document(object.source().url().path());
    if (document.isNull()) {

        QFile inFile(object.source().url().path());
        QString contents;
        if (inFile.open(QIODevice::ReadOnly)) {
            QTextStream ins(&inFile);
            contents = ins.readAll();
            inFile.close();
        }

        document = QmlJS::Document::create(object.source().url().path());
        document->setSource(contents);
        if (!document->parse())
            return QString();

        snapshot.insert(document);
    }

    PropertyTypeFinder find(document, snapshot, modelManager->importPaths());
    QString baseClassName = find(object.source().lineNumber(), object.source().columnNumber(), property.name());

    if (baseClassName.isEmpty()) {
        if (!object.idString().isEmpty())
            baseClassName = object.idString();
        else
            baseClassName = QString("<%1>").arg(object.className());
    }

    depth = find.depth();

    return baseClassName;

}
void ObjectPropertiesView::setObject(const QDeclarativeDebugObjectReference &object)
{
    m_object = object;
    m_tree->clear();

    QHash<QString, PropertiesViewItem*> baseClassItems;
    PropertiesViewItem* currentParentItem = 0;

    QList<QString> insertedPropertyNames;

    QList<QDeclarativeDebugPropertyReference> properties = object.properties();
    for (int i=0; i<properties.count(); ++i) {
        const QDeclarativeDebugPropertyReference &p = properties[i];

        // ignore overridden/redefined/shadowed properties; and do special ignore for QGraphicsObject* parent,
        // which is useless while debugging.
        if (insertedPropertyNames.contains(p.name())
            || (p.name() == "parent" && p.valueTypeName() == "QGraphicsObject*"))
        {
            continue;
        }
        insertedPropertyNames.append(p.name());

        if (m_showUnwatchableProperties || p.hasNotifySignal()) {

            PropertiesViewItem *item = 0;

            if (m_groupByItemType) {
                int depth = 0;
                QString baseClassName = propertyBaseClass(object, p, depth);
                if (!baseClassItems.contains(baseClassName)) {
                    PropertiesViewItem *baseClassItem = new PropertiesViewItem(m_tree, PropertiesViewItem::ClassType);
                    baseClassItem->setData(0, PropertiesViewItem::CanEditRole, false);
                    baseClassItem->setData(0, PropertiesViewItem::ClassDepthRole, depth);
                    baseClassItem->setText(0, baseClassName);

                    QFont font = m_tree->font();
                    font.setBold(true);
                    baseClassItem->setFont(0, font);

                    baseClassItems.insert(baseClassName, baseClassItem);

                }
                currentParentItem = baseClassItems.value(baseClassName);
                item = new PropertiesViewItem(currentParentItem);
            } else
                item = new PropertiesViewItem(m_tree);

            item->property = p;
            item->setData(0, PropertiesViewItem::ObjectIdStringRole, object.idString());
            item->setText(0, p.name());
            Qt::ItemFlags itemFlags = Qt::ItemIsSelectable | Qt::ItemIsEnabled;

            bool canEdit = object.idString().length() && QmlInspector::instance()->canEditProperty(item->property.valueTypeName());
            item->setData(0, PropertiesViewItem::CanEditRole, canEdit);

            if (canEdit)
                itemFlags |= Qt::ItemIsEditable;

            item->setFlags(itemFlags);
            if (m_watchTableModel.data() && m_watchTableModel.data()->isWatchingProperty(p)) {
                QFont font = m_tree->font();
                font.setBold(true);
                item->setFont(0, font);
            }

            setPropertyValue(item, p.value(), !p.hasNotifySignal());

            item->setText(2, p.valueTypeName());

            // binding is set after property value to ensure it is added to the end of the
            // list, if the value is a list
            if (!p.binding().isEmpty()) {
                PropertiesViewItem *binding = new PropertiesViewItem(item, PropertiesViewItem::BindingType);
                binding->setText(1, p.binding());
                binding->setForeground(1, Qt::darkGreen);
            }

        }
    }
    if (m_groupByItemType)
        sortBaseClassItems();
    m_tree->expandAll();

}
Beispiel #7
0
void tst_QDeclarativeDebug::watch_expression()
{
    QFETCH(QString, expr);
    QFETCH(int, increment);
    QFETCH(int, incrementCount);

    int origWidth = m_rootItem->property("width").toInt();

    QDeclarativeDebugObjectReference obj = findRootObject();

    QDeclarativeDebugObjectExpressionWatch *watch;

    QDeclarativeEngineDebug *unconnected = new QDeclarativeEngineDebug(0);
    watch = unconnected->addWatch(obj, expr, this);
    QCOMPARE(watch->state(), QDeclarativeDebugWatch::Dead);
    delete watch;
    delete unconnected;

    watch = m_dbg->addWatch(QDeclarativeDebugObjectReference(), expr, this);
    QVERIFY(QDeclarativeDebugTest::waitForSignal(watch, SIGNAL(stateChanged(QDeclarativeDebugWatch::State))));
    QCOMPARE(watch->state(), QDeclarativeDebugWatch::Inactive);
    delete watch;

    watch = m_dbg->addWatch(obj, expr, this);
    QCOMPARE(watch->state(), QDeclarativeDebugWatch::Waiting);
    QCOMPARE(watch->objectDebugId(), obj.debugId());
    QCOMPARE(watch->expression(), expr);

    QSignalSpy spyState(watch, SIGNAL(stateChanged(QDeclarativeDebugWatch::State)));

    QSignalSpy spy(watch, SIGNAL(valueChanged(QByteArray,QVariant)));
    int expectedSpyCount = incrementCount + 1;  // should also get signal with expression's initial value

    int width = origWidth;
    for (int i=0; i<incrementCount+1; i++) {
        if (i > 0) {
            width += increment;
            m_rootItem->setProperty("width", width);
        }
        if (!QDeclarativeDebugTest::waitForSignal(watch, SIGNAL(valueChanged(QByteArray,QVariant))))
            QFAIL("Did not receive valueChanged() for expression");
    }

    if (spyState.count() == 0)
        QVERIFY(QDeclarativeDebugTest::waitForSignal(watch, SIGNAL(stateChanged(QDeclarativeDebugWatch::State))));
    QCOMPARE(spyState.count(), 1);
    QCOMPARE(watch->state(), QDeclarativeDebugWatch::Active);

    m_dbg->removeWatch(watch);
    delete watch;

    // restore original value and verify spy doesn't get a signal since watch has been removed
    m_rootItem->setProperty("width", origWidth);
    QTest::qWait(100);
    QCOMPARE(spy.count(), expectedSpyCount);

    width = origWidth + increment;
    for (int i=0; i<spy.count(); i++) {
        QCOMPARE(spy.at(i).at(1).value<QVariant>().toInt(), width);
        width += increment;
    }
}
Beispiel #8
0
void tst_QDeclarativeDebug::watch_object()
{
    QDeclarativeDebugEnginesQuery *q_engines = m_dbg->queryAvailableEngines(this);
    waitForQuery(q_engines);

    QVERIFY(q_engines->engines().count() > 0);
    QDeclarativeDebugRootContextQuery *q_context = m_dbg->queryRootContexts(q_engines->engines()[0].debugId(), this);
    waitForQuery(q_context);

    QVERIFY(q_context->rootContext().objects().count() > 0);
    QDeclarativeDebugObjectQuery *q_obj = m_dbg->queryObject(q_context->rootContext().objects()[0], this);
    waitForQuery(q_obj);

    QDeclarativeDebugObjectReference obj = q_obj->object();

    delete q_engines;
    delete q_context;
    delete q_obj;

    QDeclarativeDebugWatch *watch;

    QDeclarativeEngineDebug *unconnected = new QDeclarativeEngineDebug(0);
    watch = unconnected->addWatch(obj, this);
    QCOMPARE(watch->state(), QDeclarativeDebugWatch::Dead);
    delete watch;
    delete unconnected;

    watch = m_dbg->addWatch(QDeclarativeDebugObjectReference(), this);
    QVERIFY(QDeclarativeDebugTest::waitForSignal(watch, SIGNAL(stateChanged(QDeclarativeDebugWatch::State))));
    QCOMPARE(watch->state(), QDeclarativeDebugWatch::Inactive);
    delete watch;

    watch = m_dbg->addWatch(obj, this);
    QCOMPARE(watch->state(), QDeclarativeDebugWatch::Waiting);
    QCOMPARE(watch->objectDebugId(), obj.debugId());

    QSignalSpy spy(watch, SIGNAL(valueChanged(QByteArray,QVariant)));

    int origWidth = m_rootItem->property("width").toInt();
    int origHeight = m_rootItem->property("height").toInt();
    m_rootItem->setProperty("width", origWidth*2);
    m_rootItem->setProperty("height", origHeight*2);

    // stateChanged() is received before any valueChanged() signals
    QVERIFY(QDeclarativeDebugTest::waitForSignal(watch, SIGNAL(stateChanged(QDeclarativeDebugWatch::State))));
    QCOMPARE(watch->state(), QDeclarativeDebugWatch::Active);
    QVERIFY(spy.count() > 0);

    int newWidth = -1;
    int newHeight = -1;
    for (int i=0; i<spy.count(); i++) {
        const QVariantList &values = spy[i];
        if (values[0].value<QByteArray>() == "width")
            newWidth = values[1].value<QVariant>().toInt();
        else if (values[0].value<QByteArray>() == "height")
            newHeight = values[1].value<QVariant>().toInt();

    }

    m_dbg->removeWatch(watch);
    delete watch;

    // since watch has been removed, restoring the original values should not trigger a valueChanged()
    spy.clear();
    m_rootItem->setProperty("width", origWidth);
    m_rootItem->setProperty("height", origHeight);
    QTest::qWait(100);
    QCOMPARE(spy.count(), 0);

    QCOMPARE(newWidth, origWidth * 2);
    QCOMPARE(newHeight, origHeight * 2);
}
Beispiel #9
0
void tst_QDeclarativeDebug::recursiveCompareObjects(const QDeclarativeDebugObjectReference &a, const QDeclarativeDebugObjectReference &b) const
{
    QCOMPARE(a.debugId(), b.debugId());
    QCOMPARE(a.className(), b.className());
    QCOMPARE(a.name(), b.name());
    QCOMPARE(a.contextDebugId(), b.contextDebugId());

    QCOMPARE(a.source().url(), b.source().url());
    QCOMPARE(a.source().lineNumber(), b.source().lineNumber());
    QCOMPARE(a.source().columnNumber(), b.source().columnNumber());

    QCOMPARE(a.properties().count(), b.properties().count());
    QCOMPARE(a.children().count(), b.children().count());

    QList<QDeclarativeDebugPropertyReference> aprops = a.properties();
    QList<QDeclarativeDebugPropertyReference> bprops = b.properties();

    for (int i=0; i<aprops.count(); i++)
        compareProperties(aprops[i], bprops[i]);

    for (int i=0; i<a.children().count(); i++)
        recursiveCompareObjects(a.children()[i], b.children()[i]);
}
Beispiel #10
0
void tst_QDeclarativeDebug::recursiveObjectTest(QObject *o, const QDeclarativeDebugObjectReference &oref, bool recursive) const
{
    const QMetaObject *meta = o->metaObject();

    QDeclarativeType *type = QDeclarativeMetaType::qmlType(meta);
    QString className = type ? QString(type->qmlTypeName()) : QString(meta->className());
    className = className.mid(className.lastIndexOf(QLatin1Char('/'))+1);

    QCOMPARE(oref.debugId(), QDeclarativeDebugService::idForObject(o));
    QCOMPARE(oref.name(), o->objectName());
    QCOMPARE(oref.className(), className);
    QCOMPARE(oref.contextDebugId(), QDeclarativeDebugService::idForObject(qmlContext(o)));

    const QObjectList &children = o->children();
    for (int i=0; i<children.count(); i++) {
        QObject *child = children[i];
        if (!qmlContext(child))
            continue;
        int debugId = QDeclarativeDebugService::idForObject(child);
        QVERIFY(debugId >= 0);

        QDeclarativeDebugObjectReference cref;
        foreach (const QDeclarativeDebugObjectReference &ref, oref.children()) {
            if (ref.debugId() == debugId) {
                cref = ref;
                break;
            }
        }
        QVERIFY(cref.debugId() >= 0);

        if (recursive)
            recursiveObjectTest(child, cref, true);
    }

    foreach (const QDeclarativeDebugPropertyReference &p, oref.properties()) {
        QCOMPARE(p.objectDebugId(), QDeclarativeDebugService::idForObject(o));

        // signal properties are fake - they are generated from QDeclarativeBoundSignal children
        if (p.name().startsWith("on") && p.name().length() > 2 && p.name()[2].isUpper()) {
            QVERIFY(p.value().toString().startsWith('{') && p.value().toString().endsWith('}'));
            QVERIFY(p.valueTypeName().isEmpty());
            QVERIFY(p.binding().isEmpty());
            QVERIFY(!p.hasNotifySignal());
            continue;
        }

        QMetaProperty pmeta = meta->property(meta->indexOfProperty(p.name().toUtf8().constData()));

        QCOMPARE(p.name(), QString::fromUtf8(pmeta.name()));

        if (pmeta.type() > 0 && pmeta.type() < QVariant::UserType) // TODO test complex types
            QCOMPARE(p.value(), pmeta.read(o));

        if (p.name() == "parent")
            QVERIFY(p.valueTypeName() == "QGraphicsObject*" || p.valueTypeName() == "QDeclarativeItem*");
        else
            QCOMPARE(p.valueTypeName(), QString::fromUtf8(pmeta.typeName()));

        QDeclarativeAbstractBinding *binding = 
            QDeclarativePropertyPrivate::binding(QDeclarativeProperty(o, p.name()));
        if (binding)
            QCOMPARE(binding->expression(), p.binding());

        QCOMPARE(p.hasNotifySignal(), pmeta.hasNotifySignal());

        QVERIFY(pmeta.isValid());
    }
}