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
Developer
minmax
Posts: 54
Registered: ‎09-25-2012
My Device: Dev Alpha, Z10
Accepted Solution

GroupDataModel how to find an item and get indexPath

Hi All!

 

I have a problem with GroupDataModel.

I create and populate model like bellow:

    
m_model = new GroupDataModel(QStringList() << "displayName", this);
...
QVariantMap entry;
entry["contactId"] = QString::number(contact->getId());
entry["displayName"] = contact->getDisplayName();
entry["icon"] = contact->getSmallPhoto();

m_model->insert(entry);

 after I cath some signal like contactDeleted(int id) and want to remove related item from model:

void ContactsViewModel::onContactDeleted(int id)
{
  //QVariantList indexPath = m_model->lowerBound(QVariantList() << QString::number(id));
  //QVariantList indexPath = m_model->lowerBound(QVariantList() << id);
  //QVariantList indexPath = m_model->find(QVariantList() << QString::number(id));
  QVariantList indexPath = m_model->find(QVariantList() << id);

  if (!indexPath.isEmpty())
  {
    m_model->removeAt(indexPath);
  }
}

 But model return always indexPath for the first item!!! I used and GroupDataModel::find and GroupDataModel::lowerBound but result is always the same!

Please help me, how I can found correct item?

Please use plain text.
Developer
minmax
Posts: 54
Registered: ‎09-25-2012
My Device: Dev Alpha, Z10

Re: GroupDataModel how to find an item and get indexPath

[ Edited ]

Somebody help me please! :smileysad:
What I should do for getting valid indexPath?
Also I need good perfomance, so I dont think what take items as QList and search it in cycle it's good way.
And also I do not understand why find and lowerBound methods do not work...

Please use plain text.
Developer
Zmey
Posts: 1,512
Registered: ‎12-18-2012
My Device: PlayBook, Z10, DAC

Re: GroupDataModel how to find an item and get indexPath

Hi,

 

From my understanding of the docs, it's possible to search only on the fields which are present in sortingKeys.

I think GroupDataModel is building indexes on these fields.

 

I've performed some tests:

 

If only displayName is present in sorting keys:

 

    GroupDataModel *model = new GroupDataModel(QStringList() << "displayName", this);

    QVariantMap entry;
    entry["contactId"] = "100";
    entry["displayName"] = "Alex";
    entry["icon"] = "icon1.png";
    model->insert(entry);

    entry["contactId"] = "200";
    entry["displayName"] = "Andrew";
    entry["icon"] = "icon2.png";
    model->insert(entry);

then searching by displayName will work properly:

QVariantList indexPath = model->find(QVariantList() << "Andrew");
qDebug() << "indexPath" << indexPath << "\n";
// this will print (QVariant(int, 0) ,  QVariant(int, 1) ) which is
// section 0, item 1

 But searching by contactId will not work, because it's not present in sortingKeys.

 


 

If you add contactId to sortingKeys:

GroupDataModel *model = new GroupDataModel(QStringList() << "displayName" << "contactId", this);

then searching solely by displayName will no longer work. Find() is matching values for all keys, so it will return only entries with empty contactId. But lowerBound() can be used instead:

QVariantList indexPath = model->lowerBound(QVariantList() << "Andrew");
qDebug() << "indexPath" << indexPath << "\n";
// this will return:
// indexPath (QVariant(int, 0) ,  QVariant(int, 1) )  

 

Note though that lowerBound is not a complete replacement for find. It returns a suggested insertion index for the element. So if it's unable to find a match it will return (0, 0) as suggested insertion point, but not an empty indexPath. :smileysad:

 


 

When you have multiple sorting keys the following code kind of works for finding a name:

 


GroupDataModel *model = new GroupDataModel(QStringList() << "displayName" << "contactId", this); QVariantMap matchMap; //matchMap["contactId"] = "200"; matchMap["displayName"] = "Andrew"; QVariantList indexPath = model->lowerBound(matchMap); qDebug() << "indexPath" << indexPath << "\n";

But if the name is not found lowerBound will return (0, 0) - a suggested insertion point. :smileyhappy: So it's not possible to differentiate it from 'not found' return value.

 

But if you try to supply a contactId

 

    matchMap["contactId"] = "200";
    //matchMap["displayName"] = "Andrew";

it will NOT work at all, because it's performing the search in the order in which sortingKeys were declared.

In this case it will try to match 'empty' QVariant to displayName, won't find anything and will return (0, 0) as suggested insertion point without even trying to match contactId-s. :smileysad:

 

The find() function isn't suitable as well because it performs exact match on all fields and requires all sortingKeys to be set.

 

I hope I haven't confused you completely now! :Online2long:

 


 

 

So, the conclusion seems to be:

 

find() can only find an exact match and compares all keys of the item supplied with keys in sortingKeys. If some of the values are omitted it expects them to be NULL in model.

 

lowerBound() returns a suggested insertion point or (0, 0) if nothing was matched. It compares values passed to it with sorting keys from left to right (if the first sortingKey wasn't matched it doesn't compare others).

 

So these methods aren't well suited for finding a value of specific key. A possible workaround is iterating the model entries manually and comparing their values, but this is slow.

 

I suggest creating your own datamodel by inheriting from DataModel class. It's not very hard and you can implement any kind of search in it.

 


Andrey Fidrya, @zmeyc on twitter
Please use plain text.
Developer
minmax
Posts: 54
Registered: ‎09-25-2012
My Device: Dev Alpha, Z10

Re: GroupDataModel how to find an item and get indexPath

Oh, thank you very much for detailed reply!
Now I understand everything! :smileyhappy:
Yes, looks like I'll be do own DataModel because performance for me it importent case.
Also thank you! You really help me! :smileyhappy:
Please use plain text.