Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Cast a QVariant to a QList<customObject>



  • Hello everyone,

    I did a search in the forum but didn't find anything. (If I'm wrong, just link me the threads please).

    I have some customs classes, and I need to map them with some QVariant.
    What I'm doing is a constructor from a QVariant to instantiate them from the QVariant, and an operator QVariant() const in order to use static_cast to cast the object to a QVariant.

    But now I'm facing one problem with QList. I have for example a QVariant containing a QList of QMap<QString, QVariant>. A QMap<QString, QVariant> represent my object A. I'm able to cast a QMap to a A and vice versa.

    My question is from a QVariant like this (QList<QMap<QString, QVariant> >), how can I cast it to a QList of my custom type (QList<A>).

    Code:
    @#include <QDebug>

    using namespace std;

    class A
    {
    public:
    int value;

    public:
        A () {cout << "Default constructor" << endl;}
        A (int arg)
        {   
            this->value = arg;
        }   
        A (QVariant variant) throw (int)
        {   
            cout << "Constructor from variant" << endl;
            if (!variant.canConvert(QVariant::Map))
                throw 1;
            QMap<QString,QVariant> mapVariant = variant.toMap();
            this->value = mapVariant["value"].toInt();
        }   
        A operator=(A& copy)
        {   
            cout << "Constructor by copy" << endl;
            this->value = copy.value;
            return (*this);
        }   
        virtual ~A ()
        {}  
    
        operator QVariant() const
        {   
            QMap<QString,QVariant> mapAns = QMap<QString,QVariant>();
            mapAns.insert("value", this->value);
    
            return mapAns;
        }   
    

    };
    Q_DECLARE_METATYPE(A);

    Q_DECLARE_METATYPE(QList<A>);
    int main(int argc, const char *argv[])
    {
    cout << "[Log] Beginning of the prog(" << argv[0] << ")" << endl;

    QList<QMap<QString, QVariant> > listVariant = QList<QMap<QString, QVariant> >();
    
    QMap<QString, QVariant> mapA1 = QMap<QString,QVariant>();
    QMap<QString, QVariant> mapA2 = QMap<QString,QVariant>();
    QMap<QString, QVariant> mapA3 = QMap<QString,QVariant>();
    QMap<QString, QVariant> mapA4 = QMap<QString,QVariant>();
    mapA1.insert("value", 4); 
    mapA2.insert("value", 9); 
    mapA3.insert("value", 3); 
    mapA4.insert("value", 2); 
    
    listVariant.append(mapA1);
    listVariant.append(mapA2);
    listVariant.append(mapA3);
    listVariant.append(mapA4);
    
    QList<A> listA = static_cast<QList< A > >(listVariant);
    qDebug() << "[Debug] listA (" << listA << ")";
    
    cout << "[Log] End of the prog" << endl;
    return 0;
    

    }
    @



  • Little up to clarify my claim. I made an even simpler example without any custom type, and I don't get the cast.

    I create a QStringList, I pass it to a QVariant, and then I want to cast it to a QList<QString>.

    The SL object is composed by my "test 1" and "test 2" QString. But my listResult is completely empty.
    @
    Q_DECLARE_METATYPE(QList<QString>);
    @

    @
    QStringList SL = QStringList();
    SL.append("test 1");
    SL.append("test 2");
    qDebug() << "[Debug] SL (" << SL << ")";

    QList<QString> listResult = QVariant(SL).value<QList<QString> >();
    qDebug() << "[Debug] listResult (" << listResult << ")";
    @


  • Lifetime Qt Champion

    Hi,

    QStringList and QList<QString> are two different thing (Not a typedef in this case).

    Try with @QStringList listResult = QVariant(SL).value<QStringList>();@



  • Ok, so that was a bad example to show my goal hahahaaaaa :(

    I have a QList<QVariant>, and the QVariant inside are mapped to a custom type. (see the code above on the first post).

    So from a QList<QVariant> I want to cast it to a QList<CustomType>.

    The problem is that it cast without error from the compiler in the below example, but the listA is completely empty.

    My current example from the first post:
    @
    QList<QVariant> listVariant = QList<QVariant>();

    QMap<QString, QVariant> mapA1 = QMap<QString,QVariant>();
    QMap<QString, QVariant> mapA2 = QMap<QString,QVariant>();
    QMap<QString, QVariant> mapA3 = QMap<QString,QVariant>();
    QMap<QString, QVariant> mapA4 = QMap<QString,QVariant>();
    mapA1.insert("value", 4); 
    mapA2.insert("value", 9); 
    mapA3.insert("value", 3); 
    mapA4.insert("value", 2); 
    
    listVariant.append(QVariant(mapA1));
    listVariant.append(QVariant(mapA2));
    listVariant.append(QVariant(mapA3));
    listVariant.append(QVariant(mapA4));
    
    qDebug() << "[Debug] QVariant(listVariant) (" << QVariant(listVariant) << ")";
    

    //output: [Debug] QVariant(listVariant) ( QVariant(QVariantList, (QVariant(QVariantMap, QMap(("value", QVariant(int, 4) ) ) ) , //QVariant(QVariantMap, QMap(("value", QVariant(int, 9) ) ) ) , QVariant(QVariantMap, QMap(("value", QVariant(int, 3) ) ) ) , //QVariant(QVariantMap, QMap(("value", QVariant(int, 2) ) ) ) ) ) )

    QList<A> listA = QVariant(listVariant).value<QList<A> >();
    
    
    qDebug() << "[Debug] listA (" << listA << ")";
    

    //Output: [Debug] listA ( () )

    @


  • Lifetime Qt Champion

    static_cast is normally used to cast a pointer to an object to one of it's derivative, or a numeric datatype to another (i.e int to char etc...) without any check.

    What you are trying to achieve is to transform a QVariantList containing QVariantHash into a class that does not inherit at all from QVariant.

    The QVariant operator is basically used to put your class in a QVariant (it is used where you would otherwise have to use QVariant::fromValue)

    The value<T> function will work on a QVariant if the object in contains already is of the type T or can be converted to type T. AFAIK QVariantHash cannot be converted to A.

    Hope this helps


Log in to reply