Welcome!

Welcome to the official BlackBerry Support Community Forums.

This is your resource to discuss support topics with your peers, and learn from each other.

inside custom component

Native Development

Reply
New Contributor
Posts: 9
Registered: ‎06-15-2013
My Device: Emulator
My Carrier: MTN
Accepted Solution

How to read data out of a QVariant

I have a multi select list, and I need to get the selected list of people out. 

QML

----------------------------------------------------

ListView {
    id: lv_ingredients
   horizontalAlignment: HorizontalAlignment.Fill

   dataModel: _app.ingredientDataModel

   multiSelectAction: MultiSelectActionItem {
   }

  multiSelectHandler {
      actions: [
               // Add the actions that should appear on the context menu
               // when multiple selection mode is enabled
               ActionItem {
                  title: "Search people"
                  onTriggered: {
                        _app.search(lv_people.selectionList());
                  }
       },

....

----------------------------------------------------

----------------------------------------------------

Search method in _app:

 

void classname::search(const QVariantList &list)

{

    QVariant nlist= personDataModel->data(list.at(0).toList()); //
    qDebug() << "List: " << nlist;
}

----------------------------------------------------
Results in

List: QVariant(QObject*, Person(0x857c310) )

 

Which means I can see this list of Person objects, but I have no way of reading them! How do I get this array out of the QVariant?

Developer
Posts: 16,997
Registered: ‎07-29-2008
My Device: Z10 LE, Z30, Passport
My Carrier: O2 Germany

Re: How to read data out of a QVariant

https://developer.blackberry.com/cascades/reference/qvariant.html#type
----------------------------------------------------------
feel free to press the like button on the right side to thank the user that helped you.
please mark posts as solved if you found a solution.
@SimonHain on twitter
New Contributor
Posts: 9
Registered: ‎06-15-2013
My Device: Emulator
My Carrier: MTN

Re: How to read data out of a QVariant

Value is a template - so I have to say something like

 

QVariant tlist = personDataModel->data(list.at(0).toList());

 

Person* selectedPeople = tlist.value<Person*>();

 

And I get the error: "'qt_metatype_id' is not a member of 'QMetaTypeId<Person*>'"

 

Now before you just Google that error and give me the results - I have no idea where to put those lines of code in the class def (maybe not even in the class def) - maybe not even those lines of code. 

Developer
Posts: 1,746
Registered: ‎04-08-2010
My Device: Passport Silver, PRIV
My Carrier: Telekom.de, O2, Vodafone

Re: How to read data out of a QVariant

to get a Person* from QVariant you have to do a cast

something like

 

if (qobject_cast<Person*>(yourList.at(i))) {

     Person *person = (Person*) yourList.at(i);

-------------------------------------------------------------------------------
ekke (independent software architect, rosenheim, germany)

BlackBerry Elite Developer
BlackBerry Platinum Enterprise Partner
International Development native Mobile Business Apps
BlackBerry 10 | Qt Mobile (Android, iOS)
Workshops / Trainings / Bootcamps

blog: http://ekkes-corner.org
mobile-development: http://appbus.org Twitter: @ekkescorner
Developer
Posts: 1,524
Registered: ‎12-18-2012
My Device: Z30, Z10 LE, DevAlpha C, PlayBook

Re: How to read data out of a QVariant

[ Edited ]

Hi,

 

The code seems to be correct, but variables are named confusingly.

 

QVariant tlist = personDataModel->data(list.at(0).toList());

This line actually returns a first person in selection list. In case none were selected, .at() function will throw an exception and the app will crash.

 

IndexPath is a list consisting of section number, row number etc. Data() method returns a single object for a given indexPath.

 

QVariant is a type which can wrap any primitive type, a map, a list, or a QObject. It can also wrap pointers to custom QObject-derived classes if they are declared using Q_DECLARE_METATYPE. More details on this here (it's Qt 5 docs, but should apply to Qt 4.8 as well):

http://qt-project.org/doc/qt-5.0/qtcore/qmetatype.html#Q_DECLARE_METATYPE

 

Line you're using for conversion to Person* seems correct. To retrieve all persons (untested code, but should work, I've split it into multiple lines for simplicity):

 

foreach (QVariant indexPathV, list)
{
  QVariantList indexPath = indexPathV.toList();
  QVariant personV = personDataModel->data(indexPath);
  Person *person = personV.value<Person *>();
}

In .h file where the person is declared make sure to declare the Person's pointer metatype, otherwise it can't be used in QVariant unless casted manually to / from QObject, which is inconvenient:

 

class Person: public QObject
{
  .............
}

Q_DECLARE_METATYPE(Person *);

Also I suspect that there might be something wrong with dataModel. If the above won't work, please paste the header file where it's declared.

 

If there are compile errors, please paste them entirely including context around them, this might also give us some hints.

 

UPD. qobject_cast can be used to cast QObject* to another type (returns NULL if impossible), but it won't work for extracting a value from QVariant. Use QVariant's .value<>() function instead.

 

QObject *x;
...
MyType *y = qobject_cast<MyType *>(x);
if (y)
{
   y->...
}

 ...

QVariant v;
...
MyType *t = v.value<MyType *>();

 


Andrey Fidrya, @zmeyc on twitter
New Contributor
Posts: 9
Registered: ‎06-15-2013
My Device: Emulator
My Carrier: MTN

Re: How to read data out of a QVariant

[ Edited ]

Please look a little closer... something is missing here

 

void classname::search(const QVariantList &list)
{

    QVariant nlist= personDataModel->data(list.at(0).toList());//I am told that the list sent through is the indexpaths, not the actual object references

    qDebug() << "List : " << nlist; //OUTPUT List : QVariant(QObject*, Person(0x8978310) )
    if (qobject_cast<Person*>(nlist)) //does not compile error: no matching function for call to 'qobject_cast(QVariant&)'
    {
        Person* items = (Person*)nlist; //does not compile error: invalid cast from type 'QVariant' to type 'Person*'
    }
}

 

This is the QML:

ListView {
    id: lv_people
    horizontalAlignment: HorizontalAlignment.Fill

    dataModel: _app.personDataModel

    multiSelectAction: MultiSelectActionItem {
    }

    multiSelectHandler {
        actions: [
        // Add the actions that should appear on the context menu
        // when multiple selection mode is enabled
      ActionItem {
         title: "Search people"
         onTriggered: {
         _app.search(lv_people.selectionList());
      }
},...

and this is Person.h

 

#ifndef PERSON_HPP
#define PERSON_HPP

#include <QObject>

class Person: public QObject
{
Q_OBJECT

    // These are the properties that will be accessible by the datamodel in the view.
   Q_PROPERTY(QString customerID READ customerID WRITE setCustomerID NOTIFY customerIDChanged FINAL)
   Q_PROPERTY(QString firstName READ firstName WRITE setFirstName NOTIFY firstNameChanged FINAL)
   Q_PROPERTY(QString lastName READ lastName WRITE setLastName NOTIFY lastNameChanged FINAL)

   public:
      Person(QObject *parent = 0);
      Person(const QString &id, const QString &firstname, const QString &lastname, QObject *parent = 0);

      QString customerID() const;
      QString firstName() const;
      QString lastName() const;

      void setCustomerID(const QString &newId);
      void setFirstName(const QString &newName);
      void setLastName(const QString &newName);

   Q_SIGNALS:
      void customerIDChanged(const QString &newId);
      Void firstNameChanged(const QString &firstName);
      void lastNameChanged(const QString &lastName);

   private:
      QString m_id;
      QString m_firstName;
      QString m_lastName;
};

#endif

Highlighted
New Contributor
Posts: 9
Registered: ‎06-15-2013
My Device: Emulator
My Carrier: MTN

Re: How to read data out of a QVariant

Thanks Andrey, but I am having a problem with the Q_DECLARE_METATYPE(Person *)

--------------
#ifndef PERSON_HPP
#define PERSON_HPP

#include <QObject>

class Person: public QObject
{
Q_OBJECT

// These are the properties that will be accessible by the datamodel in the view.
Q_PROPERTY(QString customerID READ customerID WRITE setCustomerID NOTIFY customerIDChanged FINAL)
Q_PROPERTY(QString firstName READ firstName WRITE setFirstName NOTIFY firstNameChanged FINAL)
Q_PROPERTY(QString lastName READ lastName WRITE setLastName NOTIFY lastNameChanged FINAL)


public:
Person(QObject *parent = 0);
Person(const QString &id, const QString &firstname, const QString &lastname, QObject *parent = 0);

QString customerID() const;
QString firstName() const;
QString lastName() const;

void setCustomerID(const QString &newId);
void setFirstName(const QString &newName);
void setLastName(const QString &newName);

Q_SIGNALS:
void customerIDChanged(const QString &newId);
void firstNameChanged(const QString &firstName);
void lastNameChanged(const QString &lastName);

private:
QString m_id;
QString m_firstName;
QString m_lastName;
}

Q_DECLARE_METATYPE(Person *);
#endif
--------------
Produces the error: error: new types may not be defined in a return type

Which is common to not ending a class with a ';' - however I have tried many combinations and I just don't know where it will go and compile
Developer
Posts: 1,524
Registered: ‎12-18-2012
My Device: Z30, Z10 LE, DevAlpha C, PlayBook

Re: How to read data out of a QVariant

Class declaration should end with ';'

 

Try removing ';' at the end of Q_DECLARE_METATYPE:

  

class Person: public QObject
{
...
};

Q_DECLARE_METATYPE(Person *)

 Please paste the error which the compiler is giving in this case, if any. Smiley Happy

 


Andrey Fidrya, @zmeyc on twitter
New Contributor
Posts: 9
Registered: ‎06-15-2013
My Device: Emulator
My Carrier: MTN

Re: How to read data out of a QVariant

[ Edited ]

Thanks - you are right - it does seem like the generic GroupDataModel I am using for people is posing a problem. I can see the IndexPaths are now correct but the value returned by the value<Person*>() method is null.

// Tabbed pane project template
#ifndef ApplicationUI_HPP_
#define ApplicationUI_HPP_

#include <QObject>
#include <bb/cascades/GroupDataModel>
#include <bb/cascades/layouts/listlayout.h>

using namespace bb::cascades;

namespace bb { namespace cascades { class Application; }}

/*!
* @brief Application pane object
*
*Use this object to create and init app UI, to create context objects, to register the new meta types etc.
*/
class ApplicationUI : public QObject
{
Q_OBJECT
// A property that is used by the list view in QML
Q_PROPERTY(bb::cascades::DataModel* personDataModel READ personDataModel CONSTANT)

public:
ApplicationUI(bb::cascades::Application *app);
virtual ~ApplicationUI() {}
// "Q_INVOKABLE" allows these functions to be called from main.qml
Q_INVOKABLE void search(const QVariantList &list);

private:
// Functions to call upon initialization to setup the model and database
void initDataModel();

// To alert the user if something has gone wrong
void alert(const QString &message);

// The getter method for the property
bb::cascades::GroupDataModel* personDataModel() const;

// The data shown by the list view.
bb::cascades::GroupDataModel* m_personDataModel;

bool sortAlpha;
};

#endif /* ApplicationUI_HPP_ */

 

Developer
Posts: 1,746
Registered: ‎04-08-2010
My Device: Passport Silver, PRIV
My Carrier: Telekom.de, O2, Vodafone

Re: How to read data out of a QVariant


Zmey wrote:
.....

 

UPD. qobject_cast can be used to cast QObject* to another type (returns NULL if impossible), but it won't work for extracting a value from QVariant. Use QVariant's .value<>() function instead.

 

QObject *x;
...
MyType *y = qobject_cast<MyType *>(x);
if (y)
{
   y->...
}

 ...

QVariant v;
...
MyType *t = v.value<MyType *>();

 


@Zmey

what's wrong with my code ?

if (qobject_cast<Person*>(yourList.at(i))) {
     Person *person = (Person*) yourList.at(i);

I'm doing this in some apps and different use-cases. per ex. I'm having a GroupDataModel using a List of QObject* and there can be different QObject* in there, per ex. Employee*, CarDriver*, Dispatcher*

using the cast it's easy to detect what type a specific entry in my model is

 

 

-------------------------------------------------------------------------------
ekke (independent software architect, rosenheim, germany)

BlackBerry Elite Developer
BlackBerry Platinum Enterprise Partner
International Development native Mobile Business Apps
BlackBerry 10 | Qt Mobile (Android, iOS)
Workshops / Trainings / Bootcamps

blog: http://ekkes-corner.org
mobile-development: http://appbus.org Twitter: @ekkescorner