[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    [libkpeople/dave] src: Major cleanup + new way of creating PIMO:Persons
From:       David Edmundson <kde () davidedmundson ! co ! uk>
Date:       2013-06-30 22:37:54
Message-ID: E1UtQFm-000446-3h () scm ! kde ! org
[Download RAW message or body]

Git commit 0970fc892c29fbbe76eb441378931727a19e46e9 by David Edmundson, on behalf of \
Martin Klapetek. Committed on 28/06/2013 at 22:05.
Pushed by davidedmundson into branch 'dave'.

Major cleanup + new way of creating PIMO:Persons

This patch moves all data manipulation logic into the model itself. The
model now adds/updates/removes contacts, adds/removes persons,
adds/removes contacts to/from persons.

When there is any change, the chain is currently Nepomuk -> Resource
Watcher Service -> Model method. No more direct manipulation of data
from Resource Watcher Service or PersonItem.

Both ContactItem & PersonItem should serve as pure data containers and
have no model data manipulation logic.

Next change is creating persons from list of uris. It turns out that
passing indexes is unreliable as the role int values can overlap. So
then if we call data(UriRole) we can get totally different data and not
the uri.

This new method just takes list of uris and does the right thing (tm).
It checks the uris for their type, sorts them out and performs proper
job. Getting list of uris on the client side is easy as one can iterate
over view()->selectionModel()->selectedIndexes() and gather
PersonsModel::UriRole. The method also handles fake persons, so the
client does not have to worry about that.

M  +3    -93   src/personitem.cpp
M  +1    -5    src/personitem.h
M  +220  -105  src/personsmodel.cpp
M  +24   -15   src/personsmodel.h
M  +35   -57   src/resourcewatcherservice.cpp
M  +2    -2    src/resourcewatcherservice.h
M  +1    -1    src/widgets/plugins/mergecontactswidget.cpp

http://commits.kde.org/libkpeople/0970fc892c29fbbe76eb441378931727a19e46e9

diff --git a/src/personitem.cpp b/src/personitem.cpp
index 6086e41..4133a38 100644
--- a/src/personitem.cpp
+++ b/src/personitem.cpp
@@ -36,13 +36,12 @@ PersonItem::PersonItem(const QUrl &personUri)
     setData(personUri, PersonsModel::UriRole);
 }
 
-PersonItem::PersonItem(const Nepomuk2::Resource &person)
+QUrl PersonItem::uri() const
 {
-    setData(person.uri(), PersonsModel::UriRole);
-    setContacts(person.property(Nepomuk2::Vocabulary::PIMO::groundingOccurrence()).toUrlList());
                
-    kDebug() << "new person" << text() << rowCount();
+    return data(PersonsModel::UriRole).toUrl();
 }
 
+
 QVariant PersonItem::queryChildrenForRole(int role) const
 {
     QVariant ret;
@@ -157,95 +156,6 @@ QVariant PersonItem::data(int role) const
     return ret;
 }
 
-void PersonItem::removeContacts(const QList<QUrl> &contacts)
-{
-    kDebug() << "remove contacts" << contacts;
-    for (int i = 0; i < rowCount(); ) {
-        QStandardItem *item = child(i);
-        if (item && contacts.contains(item->data(PersonsModel::UriRole).toUrl())) {
-            model()->invisibleRootItem()->appendRow(takeRow(i));
-        } else {
-            ++i;
-        }
-    }
-    emitDataChanged();
-}
-
-void PersonItem::addContacts(const QList<QUrl> &_contacts)
-{
-    QList<QUrl> contacts(_contacts);
-    //get existing child-contacts and remove them from the new ones
-    QVariantList uris = queryChildrenForRoleList(PersonsModel::UriRole);
-    foreach (const QVariant &uri, uris) {
-        contacts.removeOne(uri.toUrl());
-    }
-
-    //query the model for the contacts, if they are present, then need to be just \
                moved
-    QList<QStandardItem*> personContacts;
-    foreach (const QUrl &uri, contacts) {
-        QModelIndex index = qobject_cast<PersonsModel*>(model())->indexForUri(uri);
-
-        if (index.parent().isValid()) {
-            //find the parent item of that contact
-            bool isFakePerson = \
                index.parent().data(PersonsModel::UriRole).toString().startsWith("fakeperson");
                
-
-            QStandardItem *item = model()->item(index.parent().row(), 0);
-            Q_ASSERT(item->hasChildren());
-
-            if (isFakePerson) {
-                //take the child contact away from that person item, fake persons \
                have 1 child
-                personContacts.append(item->takeRow(0).first());
-                //if it's a fake person, delete it (it's not part of the model at \
                this point)
-                qobject_cast<PersonsModel*>(model())->removePersonFromModel(index.parent());
                
-            } else {
-                //if it's not a fake person, we just append it without removing
-                personContacts.append(item->child(index.row(), 0));
-            }
-        }
-    }
-
-    //append the moved contacts to this person and remove them from 'contacts'
-    //so they are not added twice
-    foreach (QStandardItem *contactItem, personContacts) {
-        ContactItem *contact = dynamic_cast<ContactItem*>(contactItem);
-        appendRow(contact);
-        contacts.removeOne(contact->uri());
-    }
-
-    foreach (const QUrl &uri, contacts) {
-        ContactItem *item = new ContactItem(uri);
-        appendRow(item);
-        item->loadData();
-    }
-    emitDataChanged();
-}
-
-void PersonItem::setContacts(const QList<QUrl> &contacts)
-{
-    kDebug() << "set contacts" << contacts;
-    if (contacts.isEmpty()) {
-        //nothing to do here
-        return;
-    }
-
-    if (hasChildren()) {
-        QList<QUrl> toRemove;
-        QVariantList uris = queryChildrenForRoleList(PersonsModel::UriRole);
-        foreach (const QVariant &contact, uris) {
-            if (!contacts.contains(contact.toUrl()))
-                toRemove += contact.toUrl();
-        }
-        removeContacts(toRemove);
-    }
-
-    QList<QUrl> toAdd;
-    foreach (const QUrl &contact, contacts) {
-        toAdd += contact;
-    }
-    addContacts(toAdd);
-    Q_ASSERT(hasChildren());
-}
-
 int PersonItem::presenceSortPriority(const QString &presenceName) const
 {
     if (presenceName == QLatin1String("available")) {
diff --git a/src/personitem.h b/src/personitem.h
index 91fcd3c..b93c2e5 100644
--- a/src/personitem.h
+++ b/src/personitem.h
@@ -41,13 +41,9 @@ class KPEOPLE_EXPORT PersonItem : public QStandardItem
 {
 public:
     PersonItem(const QUrl &personUri);
-    PersonItem(const Nepomuk2::Resource &person);
 
     virtual QVariant data(int role) const;
-
-    void removeContacts(const QList<QUrl> &contacts);
-    void addContacts(const QList<QUrl> &contacts);
-    void setContacts(const QList<QUrl> &contacts);
+    QUrl uri() const;
 
     void contactDataChanged();
 
diff --git a/src/personsmodel.cpp b/src/personsmodel.cpp
index 813d0af..3531d8f 100644
--- a/src/personsmodel.cpp
+++ b/src/personsmodel.cpp
@@ -294,51 +294,74 @@ QList<QModelIndex> PersonsModel::indexesForUris(const \
QVariantList& uris) const  return ret;
 }
 
-void PersonsModel::addPerson(const Nepomuk2::Resource &res)
+void PersonsModel::updateContactFinished(Soprano::Util::AsyncQuery *query)
 {
-    Q_D(PersonsModel);
-    Q_ASSERT(!indexForUri(res.uri()).isValid());
-    //pass only the uri as that will not add the contacts from groundingOccurrence
-    //rationale: if we're adding contacts to the person, we need to check the model
-    //           if those contacts are not already in the model and if they are,
-    //           we need to remove them from the toplevel and put them only under
-    //           the person item. In the time of creation, the model() call from
-    //           PersonsModelItem is null, so we cannot check the model.
-    //           Furthermore this slot is used only when new pimo:Person is created
-    //           in Nepomuk and in that case Nepomuk *always* signals propertyAdded
-    //           with "groundingOccurrence", so we get the contacts either way.
-    PersonItem *newPerson = new PersonItem(res.uri());
-    d->persons.insert(res.uri(), newPerson);
-    appendRow(newPerson);
+    ContactItem *contact = query->property("contactItem").value<ContactItem*>();
 
+    if (!contact) {
+        return;
+    }
+
+    contact->finishLoadingData();
 }
 
-void PersonsModel::addContact(const Nepomuk2::Resource &res)
+ContactItem* PersonsModel::contactItemForUri(const QUrl &uri) const
+{
+    Q_D(const PersonsModel);
+    return d->contacts.value(uri);
+}
+
+PersonItem* PersonsModel::personItemForUri(const QUrl &uri) const
+{
+    Q_D(const PersonsModel);
+    return d->persons.value(uri);
+}
+
+void PersonsModel::contactChanged(const QUrl& uri)
+{
+    const QModelIndex index = indexForUri(uri);
+    dataChanged(index, index); //FIXME it's normally bad to do this on a \
QStandardItemModel +}
+
+void PersonsModel::addContact(const QUrl &uri)
 {
     Q_D(PersonsModel);
-    ContactItem *item = new ContactItem(res.uri());
+    ContactItem *item = new ContactItem(uri);
     d->dataSourceWatcher->watchContact(item->data(PersonsModel::IMsRole).toString(),
                                        \
item->data(PersonsModel::UriRole).toString());  
+    //create new fake person for this contact
     PersonItem *person = new PersonItem(QUrl("fakeperson:/" + \
QString::number(d->fakePersonsCounter++))); +
+    d->contacts.insert(uri, item);
+    d->persons.insert(person->uri(), person);
+
+    //append the ContactItem to the fake person PersonItem
     person->appendRow(item);
     appendRow(person);
 
-    d->contacts.insert(res.uri(), item);
+    //load the contact data
     item->loadData();
 }
 
 void PersonsModel::updateContact(ContactItem *contact)
 {
+    if (contact) {
+        updateContact(contact->uri());
+    }
+}
+
+void PersonsModel::updateContact(const QUrl &uri)
+{
     Q_D(PersonsModel);
 
-    kDebug() << "Updating contact" << contact->uri();
+    kDebug() << "Updating contact" << uri;
 
-    QString queryString = d->prepareQuery(contact->uri());
+    QString queryString = d->prepareQuery(uri);
 
     Soprano::Model *m = Nepomuk2::ResourceManager::instance()->mainModel();
     Soprano::Util::AsyncQuery *query = Soprano::Util::AsyncQuery::executeQuery(m, \
                queryString, Soprano::Query::QueryLanguageSparql);
-    query->setProperty("contactItem", QVariant::fromValue<ContactItem*>(contact));
+    query->setProperty("contactItem", \
QVariant::fromValue<ContactItem*>(d->contacts[uri]));  
     connect(query, SIGNAL(nextReady(Soprano::Util::AsyncQuery*)),
             this, SLOT(nextReady(Soprano::Util::AsyncQuery*)));
@@ -347,91 +370,216 @@ void PersonsModel::updateContact(ContactItem *contact)
             this, SLOT(updateContactFinished(Soprano::Util::AsyncQuery*)));
 }
 
-void PersonsModel::updateContactFinished(Soprano::Util::AsyncQuery *query)
+void PersonsModel::removeContact(const QUrl &uri)
 {
-    ContactItem *contact = query->property("contactItem").value<ContactItem*>();
+    Q_D(PersonsModel);
+
+    ContactItem *contact = d->contacts[uri];
 
     if (!contact) {
+        kWarning() << "Contact not found! Uri is" << uri;
         return;
     }
 
-    contact->finishLoadingData();
+    PersonItem *person = dynamic_cast<PersonItem*>(contact->parent());
+
+    if (!person) {
+        kWarning() << "Found contact without valid person!";
+        return;
+    }
+
+    person->removeRow(indexFromItem(contact).row());
+    d->contacts.remove(uri);
+
+    //if the person is now empty, remove it from the model too
+    if (person->rowCount() == 0) {
+        removePerson(person->uri());
+    }
+
 }
 
-ContactItem* PersonsModel::contactItemForUri(const QUrl &uri) const
+void PersonsModel::addPerson(const QUrl &uri)
 {
-    Q_D(const PersonsModel);
-    return d->contacts.value(uri);
+    Q_D(PersonsModel);
+
+    PersonItem *newPerson = new PersonItem(uri);
+    d->persons.insert(uri, newPerson);
+    appendRow(newPerson);
 }
 
-PersonItem* PersonsModel::personItemForUri(const QUrl &uri) const
+void PersonsModel::removePerson(const QUrl &uri)
 {
-    Q_D(const PersonsModel);
-    return d->persons.value(uri);
+    Q_D(PersonsModel);
+
+    PersonItem *person = d->persons[uri];
+
+    if (!person) {
+        kWarning() << "Person not found! Uri is" << uri;
+        return;
+    }
+
+    //move the child contacts into new fake persons
+    while (person->rowCount()) {
+        QUrl pimoPersonUri = QUrl("fakeperson:/" + \
QString::number(d->fakePersonsCounter++)); +        addPerson(pimoPersonUri);
+        d->persons[pimoPersonUri]->appendRow(person->takeRow(person->rowCount() - \
1)); +    }
+
+    removeRow(indexFromItem(person).row());
+    d->persons.remove(uri);
 }
 
-void PersonsModel::createPersonFromContacts(const QList<QUrl> &contacts)
+
+void PersonsModel::addContactsToPerson(const QUrl &personUri, const QList<QUrl> \
&_contacts)  {
-    Q_ASSERT(!contacts.isEmpty());
-    Nepomuk2::SimpleResource newPimoPerson;
-    newPimoPerson.addType(Nepomuk2::Vocabulary::PIMO::Person());
+    Q_D(PersonsModel);
+
+    PersonItem *person = d->persons[personUri];
 
-    foreach(const QUrl &contact, contacts) {
-        newPimoPerson.addProperty(Nepomuk2::Vocabulary::PIMO::groundingOccurrence(), \
contact); +    if (!person) {
+        kWarning() << "Person not found! Uri is" << personUri;
+        return;
     }
 
-    Nepomuk2::SimpleResourceGraph graph;
-    graph << newPimoPerson;
+    QList<QUrl> contacts(_contacts);
 
-    KJob *job = Nepomuk2::storeResources( graph, Nepomuk2::IdentifyNew, \
                Nepomuk2::OverwriteProperties );
-    connect(job, SIGNAL(finished(KJob*)), this, SLOT(jobFinished(KJob*)));
-    //the new person will be added to the model by the resourceCreated and \
propertyAdded Nepomuk signals +    //get existing child-contacts and remove them from \
the new ones +    QVariantList uris = \
person->data(PersonsModel::ChildContactsUriRole).toList(); +    foreach (const \
QVariant &uri, uris) { +        contacts.removeOne(uri.toUrl());
+    }
+
+    //query the model for the contacts, if they are present, then need to be just \
moved +    QList<QStandardItem*> personContacts;
+    foreach (const QUrl &uri, contacts) {
+        ContactItem *contact = d->contacts[uri];
+
+        if (!contact) {
+            kDebug() << "Contact not found" << uri;
+            continue;
+        }
+
+        PersonItem *parentPerson = dynamic_cast<PersonItem*>(contact->parent());
+
+        if (!parentPerson) {
+            kWarning() << "Found contact without valid person!";
+            Q_ASSERT(parentPerson); //this should never ever happen
+        }
+
+        if (parentPerson->uri().toString().startsWith("fakeperson")) {
+            //the contact does not have any real person
+            personContacts.append(parentPerson->takeRow(0));
+            //remove the fake person
+            removePerson(parentPerson->uri());
+        } else {
+            //the contact does already have a person so we just append
+            //it without removing from the original person
+            personContacts.append(contact);
+        }
+    }
+
+    //append the moved contacts to this person and remove them from 'contacts'
+    //so they are not added twice
+    foreach (QStandardItem *contactItem, personContacts) {
+        ContactItem *contact = dynamic_cast<ContactItem*>(contactItem);
+        person->appendRow(contact);
+        contacts.removeOne(contact->uri());
+    }
+
+    //if we have any contacts left, we need to create them
+    foreach (const QUrl &uri, contacts) {
+        ContactItem *item = new ContactItem(uri);
+        d->dataSourceWatcher->watchContact(item->data(PersonsModel::IMsRole).toString(),
 +                                           \
item->data(PersonsModel::UriRole).toString()); +
+        d->contacts.insert(uri, item);
+        //append the ContactItem to the current person
+        person->appendRow(item);
+        //load the contact data
+        item->loadData();
+    }
+}
+
+
+void PersonsModel::removeContactsFromPerson(const QUrl &personUri, const QList<QUrl> \
&contacts) +{
+//     Q_D(PersonsModel);
+    Q_UNUSED(personUri);
+
+    //simply remove the contacts from the model and re-add them
+    //this will take care of removing empty persons in case the contact
+    //is the last one left and also creating new fake persons
+    //without duplicating any code, plus the contact data gets
+    //updated in the process
+    Q_FOREACH (const QUrl &contactUri, contacts) {
+        removeContact(contactUri);
+        addContact(contactUri);
+    }
 }
 
-void PersonsModel::createPersonFromIndexes(const QList<QModelIndex> &indexes)
+void PersonsModel::createPersonFromUris(const QList<QUrl> &uris)
 {
-    Q_ASSERT(!indexes.isEmpty());
+    Q_D(PersonsModel);
     QList<QUrl> personUris;
     QList<QUrl> contactUris;
 
-    Q_FOREACH(const QModelIndex &index, indexes) {
+    //uris identification
+    Soprano::Model *model = Nepomuk2::ResourceManager::instance()->mainModel();
 
-        if (index.data(PersonsModel::UriRole).toString().startsWith("fakeperson")) {
-            contactUris.append(index.data(PersonsModel::ChildContactsUriRole).toList().first().toUrl());
 +    Q_FOREACH (QUrl uri, uris) {
+        if (uri.toString().startsWith("fakeperson")) {
+            uri = d->persons[uri]->data(PersonsModel::ChildContactsUriRole).toList().first().toUrl();
 +        }
+        //for each uri we query it as if it was pimo:Person
+        QString query = QString::fromLatin1("SELECT DISTINCT ?r WHERE { %1 rdf:type \
pimo:Person }") +                        .arg(Soprano::Node::resourceToN3(uri));
+
+        Soprano::QueryResultIterator it = model->executeQuery(query, \
Soprano::Query::QueryLanguageSparql); +        //if the resource with the given uri \
is in fact pimo:Person, +        //we get back one result, if it's not pimo:Person, \
it's nco:PersonContact +        if (it.allElements().size() == 1) {
+            personUris << uri;
         } else {
-            personUris.append(index.data(PersonsModel::UriRole).toUrl());
+            contactUris << uri;
         }
     }
 
-    if (personUris.isEmpty()) {
-        kDebug() << "Got only contacts, creating pimo:person";
-        createPersonFromContacts(contactUris);
-    } else if (personUris.size() == 1) {
-        kDebug() << "Got one pimo:person, adding contacts to it";
-        addContactsToPerson(personUris.first(), contactUris);
-    } else {
-        kDebug() << "Got two pimo:persons, unsupported for now";
-    }
-}
+    KJob *job = 0;
 
-void PersonsModel::addContactsToPerson(const QUrl &personUri, const QList<QUrl> \
                &contacts)
-{
-    //put the contacts from QList<QUrl> into QVariantList
-    QVariantList contactsList;
-    Q_FOREACH(const QUrl &contact, contacts) {
-        contactsList << contact;
+    if (personUris.isEmpty() && !contactUris.isEmpty()) {
+        Nepomuk2::SimpleResource newPimoPerson;
+        newPimoPerson.addType(Nepomuk2::Vocabulary::PIMO::Person());
+
+        foreach(const QUrl &contact, contactUris) {
+            newPimoPerson.addProperty(Nepomuk2::Vocabulary::PIMO::groundingOccurrence(), \
contact); +        }
+
+        Nepomuk2::SimpleResourceGraph graph;
+        graph << newPimoPerson;
+
+        job = Nepomuk2::storeResources( graph, Nepomuk2::IdentifyNew, \
Nepomuk2::OverwriteProperties ); +        //the new person will be added to the model \
by the resourceCreated and propertyAdded Nepomuk signals +    } else if \
(personUris.size() == 1 && !contactUris.isEmpty()) { +        //put the contacts from \
QList<QUrl> into QVariantList +        QVariantList contactsList;
+        Q_FOREACH(const QUrl &contact, contactUris) {
+            contactsList << contact;
+        }
+
+        job = Nepomuk2::addProperty(QList<QUrl>() << personUris.first(),
+                                          \
Nepomuk2::Vocabulary::PIMO::groundingOccurrence(), +                                  \
QVariantList() << contactsList); +    } else if (personUris.size() > 1) {
+        //TODO: merge those two persons then append contacts
     }
 
-    KJob *job = Nepomuk2::addProperty(QList<QUrl>() << personUri,
-                                      \
                Nepomuk2::Vocabulary::PIMO::groundingOccurrence(),
-                                      QVariantList() << contactsList);
     connect(job, SIGNAL(finished(KJob*)), this, SLOT(jobFinished(KJob*)));
 }
 
-void PersonsModel::removeContactsFromPerson(const QUrl &personUri, const QList<QUrl> \
&contacts) +void PersonsModel::unlinkContactFromPerson(const QUrl &personUri, const \
QList<QUrl> &contactUris)  {
     QVariantList contactsList;
-    Q_FOREACH(const QUrl &contact, contacts) {
+    Q_FOREACH(const QUrl &contact, contactUris) {
         contactsList << contact;
     }
 
@@ -447,45 +595,12 @@ void PersonsModel::removeContactsFromPerson(const QUrl \
                &personUri, const QList<Q
     Soprano::Model *model = Nepomuk2::ResourceManager::instance()->mainModel();
 
     QString query = QString::fromLatin1("select distinct ?go where { %1 \
                pimo:groundingOccurrence ?go . }")
-        .arg(Soprano::Node::resourceToN3(personUri));
+    .arg(Soprano::Node::resourceToN3(personUri));
 
     Soprano::QueryResultIterator it = model->executeQuery(query, \
Soprano::Query::QueryLanguageSparql);  if (it.allBindings().count() == 1) {
-        removePerson(personUri);
-    }
-}
-
-void PersonsModel::removePerson(const QUrl &uri)
-{
-    Nepomuk2::Resource oldPerson(uri);
-    oldPerson.remove();
-}
-
-void PersonsModel::removePersonFromModel(const QModelIndex &index)
-{
-    Q_D(PersonsModel);
-    kDebug() << "Removing person from model";
-    PersonItem *person = dynamic_cast<PersonItem*>(itemFromIndex(index));
-    if (!person) {
-        kDebug() << "Invalid person, returning";
-        return;
-    }
-
-    //for each contact we remove we need to create fake person and add it to the \
                model
-    while (person->rowCount()) {
-        QUrl personUri("fakeperson:/" + QString::number(d->fakePersonsCounter++));
-        PersonItem *fakePerson = new PersonItem(personUri);
-        d->persons.insert(personUri, fakePerson);
-        fakePerson->appendRow(person->takeRow(person->rowCount() - 1));
-        invisibleRootItem()->appendRow(fakePerson);
+        //remove the person from Nepomuk
+        Nepomuk2::Resource oldPerson(personUri);
+        oldPerson.remove();
     }
-
-    d->persons.remove(person->data(PersonsModel::UriRole).toUrl());
-    removeRow(index.row());
-}
-
-void PersonsModel::contactChanged(const QUrl& uri)
-{
-    const QModelIndex index = indexForUri(uri);
-    dataChanged(index, index); //FIXME it's normally bad to do this on a \
QStandardItemModel  }
diff --git a/src/personsmodel.h b/src/personsmodel.h
index 4b6a829..9aa175e 100644
--- a/src/personsmodel.h
+++ b/src/personsmodel.h
@@ -74,14 +74,18 @@ public:
     /**Start querying the database using the supplied features*/
     void startQuery(const QList<PersonsModelFeature> &features);
 
-    /** Creates a pimo:person with contacts as groundingOccurances */
-    void createPersonFromContacts(const QList<QUrl> &contacts);
+    /** Creates PIMO:Person with NCO:PersonContacts as grounding occurances
+     *  The list that it's passed can contain uris of both Person and \
PersonContacts, +     *  the method checks their type and does the right thing(tm)
+     *  @param uris list of Person and PersonContact uris
+     */
+    Q_SCRIPTABLE void createPersonFromUris(const QList<QUrl> &uris);
 
-    /**
-     * Creates a pimo:person from indexes, checking if one of them isn't person \
                already and
-     * adding the contacts to it if it is
+    /** Removes the link between contacts and the given person
+     *  @param personUri PIMO:Person uri to unlink the contacts from
+     *  @param contactUris list of NCO:PersonContacts to unlink
      */
-    Q_SCRIPTABLE void createPersonFromIndexes(const QList<QModelIndex> &indexes);
+    Q_SCRIPTABLE void unlinkContactFromPerson(const QUrl &personUri, const \
QList<QUrl> &contactUris);  
     /** Adds contacts to existing PIMO:Person */
     void addContactsToPerson(const QUrl &personUri, const QList<QUrl> &contacts);
@@ -89,11 +93,6 @@ public:
     /** Removes given contacts from existing PIMO:Person */
     void removeContactsFromPerson(const QUrl &personUri, const QList<QUrl> \
&contacts);  
-    /** Removes the link between all contacts, removes the pimo:person but leaves \
                the contacts intact */
-    void removePerson(const QUrl &uri);
-    //FIXME: maybe merge with ^ ?
-    void removePersonFromModel(const QModelIndex &index);
-
     Q_SCRIPTABLE QModelIndex indexForUri(const QUrl &uri) const;
 
     Q_SCRIPTABLE QList<QModelIndex> indexesForUris(const QVariantList& uris) const;
@@ -108,20 +107,30 @@ private Q_SLOTS:
     void queryFinished(Soprano::Util::AsyncQuery *query);
     void contactChanged(const QUrl &uri);
     void updateContactFinished(Soprano::Util::AsyncQuery *query);
-    void updateContact(ContactItem *contact);
 
 private:
     /**
      * @return actual features used to populate the model
      */
     QList<PersonsModelFeature> modelFeatures() const;
-
-    void addPerson(const Nepomuk2::Resource &res);
-    void addContact(const Nepomuk2::Resource &res);
     ContactItem* contactItemForUri(const QUrl &uri) const;
     PersonItem* personItemForUri(const QUrl &uri) const;
     QModelIndex findRecursively(int role, const QVariant &value, const QModelIndex \
&idx = QModelIndex()) const;  
+    /** Adds new contact to the model with @param uri as its URI */
+    void addContact(const QUrl &uri);
+    /** Refreshes data of the contact given by @param uri */
+    void updateContact(const QUrl &uri);
+    /** Convenience function */
+    void updateContact(ContactItem *contact);
+    /** Removes contact with @param uri from the model (not Nepomuk) */
+    void removeContact(const QUrl &uri);
+
+    /** Adds new person to the model with @param uri as its URI */
+    void addPerson(const QUrl &uri);
+    /** Removes person with @param uri from the model (not Nepomuk) */
+    void removePerson(const QUrl &uri);
+
     friend class ResourceWatcherService;
     friend class PersonItem;
     friend class ContactItem;
diff --git a/src/resourcewatcherservice.cpp b/src/resourcewatcherservice.cpp
index 1342c99..2b325d3 100644
--- a/src/resourcewatcherservice.cpp
+++ b/src/resourcewatcherservice.cpp
@@ -55,8 +55,6 @@ ResourceWatcherService::ResourceWatcherService(PersonsModel \
*parent)  d->personWatcher = new Nepomuk2::ResourceWatcher(this);
     d->personWatcher->addType(Nepomuk2::Vocabulary::PIMO::Person());
 
-    connect(d->personWatcher, \
                SIGNAL(resourceCreated(Nepomuk2::Resource,QList<QUrl>)),
-            this, SLOT(personCreated(Nepomuk2::Resource,QList<QUrl>)));
     connect(d->personWatcher, SIGNAL(resourceRemoved(QUrl,QList<QUrl>)),
             this, SLOT(personRemoved(QUrl)));
     connect(d->personWatcher, \
SIGNAL(propertyAdded(Nepomuk2::Resource,Nepomuk2::Types::Property,QVariant)), @@ \
-71,8 +69,10 @@ ResourceWatcherService::ResourceWatcherService(PersonsModel *parent)  \
                d->contactWatcher = new Nepomuk2::ResourceWatcher(this);
     d->contactWatcher->addType(Nepomuk2::Vocabulary::NCO::PersonContact());
 
+    connect(d->contactWatcher, \
SIGNAL(resourceCreated(Nepomuk2::Resource,QList<QUrl>)), +            this, \
SLOT(contactCreated(Nepomuk2::Resource)));  connect(d->contactWatcher, \
                SIGNAL(resourceRemoved(QUrl,QList<QUrl>)),
-            this, SLOT(contactRemoved(QUrl,QList<QUrl>)));
+            this, SLOT(contactRemoved(QUrl)));
     connect(d->contactWatcher, \
SIGNAL(propertyChanged(Nepomuk2::Resource,Nepomuk2::Types::Property,QVariantList,QVariantList)),
                
             this, SLOT(onContactPropertyModified(Nepomuk2::Resource,Nepomuk2::Types::Property,QVariantList,QVariantList)));
  
@@ -91,28 +91,28 @@ void ResourceWatcherService::onPersonPropertyAdded(const \
                Nepomuk2::Resource &res
     if (property.uri() == Nepomuk2::Vocabulary::PIMO::groundingOccurrence()) {
         Q_D(ResourceWatcherService);
         PersonItem *item = d->personsModel->personItemForUri(res.uri());
-        if (item) {
-            item->addContacts(QList<QUrl>() << value.toUrl());
-        } else {
-            kWarning() << "Non-existing person specified!";
+        if (!item) {
+            //if the person does not exist yet, create it first
+            d->personsModel->addPerson(res.uri());
         }
+
+        d->personsModel->addContactsToPerson(res.uri(), QList<QUrl>() << \
value.toUrl());  }
 }
 
-void ResourceWatcherService::onPersonPropertyRemoved(const Nepomuk2::Resource &res, \
const Nepomuk2::Types::Property &property, const QVariant &_value) +void \
ResourceWatcherService::onPersonPropertyRemoved(const Nepomuk2::Resource &res, const \
Nepomuk2::Types::Property &property, const QVariant &value)  {
-    kDebug() << "person property removed:" /*<< res.uri() */<< property.name() << \
_value; +    kDebug() << "person property removed:" /*<< res.uri() */<< \
property.name() << value;  
-    if (property.name() == "groundingOccurrence") {
+    if (property.uri() == Nepomuk2::Vocabulary::PIMO::groundingOccurrence()) {
         Q_D(ResourceWatcherService);
-        PersonItem *item = \
static_cast<PersonItem*>(d->personsModel->itemFromIndex(d->personsModel->indexForUri(res.uri())));
                
-        if (item) {
-            if (_value.canConvert<QUrl>()) {    //one contact was removed from \
                groundingOccurrence
-                item->removeContacts(QList<QUrl>() << _value.toUrl());
-            } else if (_value.canConvert<QList<QUrl> >()) {
-                item->removeContacts(_value.value<QList<QUrl> >());
-            }
+        PersonItem *item = d->personsModel->personItemForUri(res.uri());
+        if (!item) {
+            kWarning() << "Person does not exist in the model!";
+            return;
         }
+
+        d->personsModel->removeContactsFromPerson(res.uri(), QList<QUrl>() << \
value.toUrl());  }
 }
 
@@ -134,14 +134,14 @@ void ResourceWatcherService::onPersonPropertyModified(const \
                Nepomuk2::Resource &
         //in which case it is handled by the propertyAdded and/or propertyRemoved \
slots  return;
     }
-    Q_D(ResourceWatcherService);
-    if (property == Nepomuk2::Vocabulary::PIMO::groundingOccurrence()) {
-        PersonItem *item = \
static_cast<PersonItem*>(d->personsModel->itemFromIndex(d->personsModel->indexForUri(res.uri())));
                
-        if (item) {
-            item->removeContacts(qvariantlist_cast<QUrl>(removed));
-            item->addContacts(qvariantlist_cast<QUrl>(added));
-        }
-    }
+//     Q_D(ResourceWatcherService);
+//     if (property == Nepomuk2::Vocabulary::PIMO::groundingOccurrence()) {
+//         PersonItem *item = \
static_cast<PersonItem*>(d->personsModel->itemFromIndex(d->personsModel->indexForUri(res.uri())));
 +//         if (item) {
+//             item->removeContacts(qvariantlist_cast<QUrl>(removed));
+//             item->addContacts(qvariantlist_cast<QUrl>(added));
+//         }
+//     }
 }
 
 
@@ -155,50 +155,28 @@ void ResourceWatcherService::onContactPropertyModified(const \
Nepomuk2::Resource  if (item) {
         kDebug() << "Existing contact found, running update";
         item->loadData();
-    } else if (!item && removed.isEmpty()) {
-
-        //go through all model features and check mandatory features,
-        //only create contacts that have the mandatory property
-        Q_FOREACH (const PersonsModelFeature &feature, \
                d->personsModel->modelFeatures()) {
-            if (!feature.isOptional()) {
-                if (feature.watcherProperty() == property) {
-                    kDebug() << "Creating new contact";
-                    d->personsModel->addContact(res);
-                    return;
-                }
-            }
-        }
     }
 }
 
-void ResourceWatcherService::personCreated(const Nepomuk2::Resource &res, const \
QList< QUrl > &types) +void ResourceWatcherService::contactCreated(const \
Nepomuk2::Resource &res)  {
-    kDebug() << "new person" /*<< res.uri() */<< types;
+    kDebug() << "new contact created:" << res.uri();
+
     Q_D(ResourceWatcherService);
-    Q_ASSERT(res.hasProperty(Nepomuk2::Vocabulary::PIMO::groundingOccurrence()));
-    QModelIndex idx = d->personsModel->indexForUri(res.uri());
-    if (!idx.isValid()) {
-        d->personsModel->addPerson(res);
-    }
+    //addContact() will also load all wanted properties
+    d->personsModel->addContact(res.uri());
 }
 
-void ResourceWatcherService::contactRemoved(const QUrl &uri, const QList<QUrl> \
&types) +void ResourceWatcherService::contactRemoved(const QUrl &uri)
 {
-    Q_UNUSED(types);
     Q_D(ResourceWatcherService);
-    QModelIndex idx = d->personsModel->indexForUri(uri);
-    if (uri.isValid()) {
-        d->personsModel->removeRow(idx.row());
-    }
-    kDebug() << "contact removed" << uri;
+    kDebug() << "Removing contact with" << uri;
+    d->personsModel->removeContact(uri);
 }
 
 void ResourceWatcherService::personRemoved(const QUrl &uri)
 {
     Q_D(ResourceWatcherService);
-    QModelIndex idx = d->personsModel->indexForUri(uri);
-    if (idx.isValid()) {
-        d->personsModel->removePersonFromModel(idx);
-    }
-    kDebug() << "person removed" << uri;
+    kDebug() << "Removing person with" << uri;
+    d->personsModel->removePerson(uri);
 }
diff --git a/src/resourcewatcherservice.h b/src/resourcewatcherservice.h
index 94210ef..edb1434 100644
--- a/src/resourcewatcherservice.h
+++ b/src/resourcewatcherservice.h
@@ -46,9 +46,9 @@ private Q_SLOTS:
     void onContactPropertyModified(const Nepomuk2::Resource &res, const \
                Nepomuk2::Types::Property &property,
                                    const QVariantList &added, const QVariantList \
&removed);  
-    void personCreated(const Nepomuk2::Resource &res, const QList<QUrl> &types);
     void personRemoved(const QUrl &uri);
-    void contactRemoved(const QUrl &uri, const QList<QUrl> &types);
+    void contactCreated(const Nepomuk2::Resource &res);
+    void contactRemoved(const QUrl &uri);
 
 private:
     ResourceWatcherServicePrivate * const d_ptr;
diff --git a/src/widgets/plugins/mergecontactswidget.cpp \
b/src/widgets/plugins/mergecontactswidget.cpp index 51e11dc..15bd167 100644
--- a/src/widgets/plugins/mergecontactswidget.cpp
+++ b/src/widgets/plugins/mergecontactswidget.cpp
@@ -172,7 +172,7 @@ void MergeContactsWidget::onMergeButtonPressed()
         indexToMergeConverted << pIndex;
     }
     //commented because it removes the test cases
-    m_model->createPersonFromIndexes(indexToMergeConverted);
+//     m_model->createPersonFromIndexes(indexToMergeConverted);
 
     searchForDuplicates();
 }


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic