[Kde-pim] SEGV reading Akonadi::Attribute from retrieveItem

Jesús Pérez kdelists at chuso.net
Fri Jun 6 16:41:22 BST 2014


> > > If you need to have access to item's parent collection attributes, you
> > > need to retrieve the collection manually.
> >
> > So I need to use a CollectionFetchJob?
>
> Yes. The good things is that you don't need to return the item directly
> in retrieveItem() method, but you can do it asynchronously, so you can
> have something like

Hi, Daniel.

Thank you for spending your time providing me with such a detailed response.

I finally achieved my goal, thanks to your advice.

But I had to adjust your solution a little, just for the record:

> CollectionFetchJob *fetchJob = new CollectionFetchJob(Collection(item.parentCollectionId()));

I found no such Akonadi::Item::parentCollectionId() method. I guess
you mean item.parentCollection().id(), don't you?

Anyway, when called from retrieveItems, item.parentCollection().id()
returns the actual collection id. But when called from retrieveItem,
item.parentCollection().id() returns a wrong negative integer.
I finally found that this can be fixed by calling
changeRecorder()->itemFetchScope().setAncestorRetrieval(ItemFetchScope::Parent)
in resource constructor.

Then I found that, although I get the right collection id and fetch
job runs with no errors, I got no collections. Using the
CollectionFetchJob constructor that receives a list of Collection::Id
as parameter instead worked better. I.e., I replaced

new CollectionFetchJob(Collection(item.parentCollectionId()))

with

new CollectionFetchJob(QList<Collection::Id>() << item.parentCollection().id())

I don't know why, I think that both should work.

Finally, here's a working implementation:
http://anongit.chuso.net/testresource/tree/testresource.cpp?id=667a874#n60
Yes, I know I should check return values and all, this is just a quick
proof of concept, not the actual project ;-)

Now, I can store an array of collection_ids -> attribute_value in a
private attribute in resource class so I don't have to refetch
collection for every item since these values never change.

Now, one consideration: may I be doing the wrong choice? Wouldn't it
be better to store this value in remoteId?
I mean: this value never changes and needs to be read every time
retrieveItem is called since it stores whose backend module this item
belongs to. Wouldn't it be easier and give better performance to do
something like this thus avoiding both changing fetch scopes and
invoking fetch jobs?

void testResource::retrieveCollections()
{
  Collection c1;
  c1.setRemoteId(module_name);
  // Do stuff
  collectionsRetrieved( Collection::List() << c1 << ... << cn );
}

void testResource::retrieveItems( const Akonadi::Collection &collection )
{
  QString module = collection.remoteId();
  foreach( const QString &id, get_ids_from_backend( module ) ) {
    Item item( QLatin1String( "text/directory" ) );
    item.setRemoteId( id + "@" + module );

    items << item;
  }

  itemsRetrieved( items );
}

bool testResource::retrieveItem( const Akonadi::Item &item, const
QSet<QByteArray> &parts )
{
  QString module = item.remoteId().replace(QRegExp(".*@"), "");
  QString remoteId = item.remoteId().replace(QRegExp("@.*"), "");

  SomeClass payload = get_payload_from_backend(module, remoteId);
  // Do stuff...

  itemRetrieved( newItem );
}
_______________________________________________
KDE PIM mailing list kde-pim at kde.org
https://mail.kde.org/mailman/listinfo/kde-pim
KDE PIM home page at http://pim.kde.org/



More information about the kde-pim mailing list