Weird Qt error (for editing properties)

A bit related to this question , but you don't really need to read it. Screenshot is helpful though:

uwBko.png

So what happens when you click on an object, change a property, deselect it and then reselect it, the property editor will reset to all 0s, even if they are not the actual values. When you click on the text boxes in the editor, the correct value appears. Does this mean it's just a display issue or what? Why does editor have two different meanings? This only happens when the highlighted lines (with arrows) remain intact - if they are commented out, this will not happen. Code:

void PropertyBrowser::objectUpdated() {
    if(m_selectedObjects.isEmpty()) {
        return;
    }
    m_variantManager->disconnect(this); // <--- THIS LINE
    QMapIterator<QtProperty*, QByteArray> i(m_propertyMap);
    bool diff;
    while(i.hasNext()) {
        i.next();
        diff = false;
        for(int j = 1; j < m_selectedObjects.size(); ++j) {
            if(m_selectedObjects.at(j)->property(i.value()) != m_selectedObjects.at(j - 1)->property(i.value())) {
                diff = true;
                break;
            }
        }
        if(diff) setBackgroundColor(topLevelItem(i.key()), QColor(232,232,232));
        else setBackgroundColor(topLevelItem(i.key()), Qt::white);
        m_variantManager->setValue(i.key(), m_selectedObjects.first()->property(i.value()));
    }

    connect(m_variantManager, SIGNAL(valueChanged(QtProperty*, QVariant)), 
            this, SLOT(valueChanged(QtProperty*, QVariant)));  // <--- AND THIS LINE
}

      

However, I need these lines because they prevent a setValue

signal from triggering valueChanged

that causes other problems. This indicates that calling this function fixes the problem:

void PropertyBrowser::valueChanged(QtProperty *property, const QVariant &value) {
    if(m_propertyMap.find(property) != m_propertyMap.end()) { 
        foreach(QObject *obj, m_selectedObjects) {
            obj->setProperty(m_propertyMap[property], value);
        }
    }
}

      

But the only thing this THAT function does is update the actual object ... this has nothing to do with the property editor (or shouldn't). Here's the whole class if you need it:

/* 
 * File:   PropertyBrowser.cpp
 * Author: mark
 * 
 * Created on August 23, 2009, 10:29 PM
 */

#include <QtCore/QMetaProperty>
#include "PropertyBrowser.h"

PropertyBrowser::PropertyBrowser(QWidget* parent)
: QtTreePropertyBrowser(parent), m_variantManager(new QtVariantPropertyManager(this)) {
    setHeaderVisible(false);
    setPropertiesWithoutValueMarked(true);
    setIndentation(10);
    setResizeMode(ResizeToContents);
    setFactoryForManager(m_variantManager, new QtVariantEditorFactory);
    setAlternatingRowColors(false);
    connect(m_variantManager, SIGNAL(valueChanged(QtProperty*, QVariant)),
            this, SLOT(valueChanged(QtProperty*, QVariant)));
}

void PropertyBrowser::valueChanged(QtProperty *property, const QVariant &value) {
    if(m_propertyMap.find(property) != m_propertyMap.end()) { 
        foreach(QObject *obj, m_selectedObjects) {
            obj->setProperty(m_propertyMap[property], value);
        }
    }
}

QString PropertyBrowser::humanize(QString str) const {
    return str.at(0).toUpper() + str.mid(1).replace(QRegExp("([a-z])([A-Z])"), "\\1 \\2");
}

void PropertyBrowser::setSelectedObjects(QList<QObject*> objs) {
    foreach(QObject *obj, m_selectedObjects) {
        obj->disconnect(this);
    }
    clear();
    m_variantManager->clear();
    m_selectedObjects = objs;
    m_propertyMap.clear();
    if(objs.isEmpty()) {
        return;
    }
    for(int i = 0; i < objs.first()->metaObject()->propertyCount(); ++i) {
        QMetaProperty metaProperty(objs.first()->metaObject()->property(i));
        QtProperty * const property
                = m_variantManager->addProperty(metaProperty.type(), humanize(metaProperty.name()));
        property->setEnabled(metaProperty.isWritable());
        m_propertyMap[property] = metaProperty.name();
        addProperty(property);
    }
    foreach(QObject *obj, m_selectedObjects) {
        connect(obj, SIGNAL(propertyChanged()), SLOT(objectUpdated()));
    }
    objectUpdated();
}

void PropertyBrowser::objectUpdated() {
    if(m_selectedObjects.isEmpty()) {
        return;
    }
    m_variantManager->disconnect(this); // <---
    QMapIterator<QtProperty*, QByteArray> i(m_propertyMap);
    bool diff;
    while(i.hasNext()) {
        i.next();
        diff = false;
        for(int j = 1; j < m_selectedObjects.size(); ++j) {
            if(m_selectedObjects.at(j)->property(i.value()) != m_selectedObjects.at(j - 1)->property(i.value())) {
                diff = true;
                break;
            }
        }
        if(diff) setBackgroundColor(topLevelItem(i.key()), QColor(232,232,232));
        else setBackgroundColor(topLevelItem(i.key()), Qt::white);
        m_variantManager->setValue(i.key(), m_selectedObjects.first()->property(i.value()));
    }

    connect(m_variantManager, SIGNAL(valueChanged(QtProperty*, QVariant)), // <---
            this, SLOT(valueChanged(QtProperty*, QVariant)));
}

      

Otherwise it's a cool class if you want to use it. Let you edit the properties of any QObject so that they are supplied with Q_PROPERTY.

Corresponding class: http://qt.nokia.com/products/appdev/add-on-products/catalog/4/Widgets/qtpropertybrowser/

0


source to share


1 answer


Are you connecting anything else with m_variantManager? The disconnect line will disconnect everything from "this", but you will only connect one slot.

Not sure if this will fix anything, but you can stop signals on one object using object-> blockSignals (true). This will close the object until you call the function with false.

Try disabling just the signal you are connecting by disabling m_variantManager instead of disabling and adding qDebug () to the appropriate slots - there is an incorrect signal that is issued when you disconnect.



EDIT: Since you are implementing the slot yourself, you can always have a flag and check it in PropertyBrowser :: valueChanged and then just ignore the signal.

I wonder if m_variantManager-> addProperty () (called from setSelected () does not set the values ​​immediately, or sets them, but the update queue. Then your disconnection in the Updated () object causes these events to be discarded.

+2


source







All Articles