[SCM] ktp-contact-list packaging branch, master, updated. debian/15.12.1-2-1070-g6c56f91

Maximiliano Curia maxy at moszumanska.debian.org
Sat May 28 00:04:46 UTC 2016


Gitweb-URL: http://git.debian.org/?p=pkg-kde/applications/ktp-contact-list.git;a=commitdiff;h=170146b

The following commit has been merged in the master branch:
commit 170146b4b3351baedfb1adc28ba166a97de5c49a
Author: Dario Freddi <drf at kde.org>
Date:   Mon May 10 20:20:03 2010 +0000

    Base support for Metacontacts.
    
    The UI now supports adding/removing contacts from a Metacontact, and also lets you create metacontacts.
    
    Signed-off-by: Dario Freddi <dario.freddi at collabora.co.uk>
    
    svn path=/trunk/playground/network/telepathy-contactlist/; revision=1125157
---
 CMakeLists.txt                              |   9 ++
 add-meta-contact-job.cpp                    |  95 ++++++++++++++++++
 add-contact-job.h => add-meta-contact-job.h |  25 ++---
 contacts-list-model.cpp                     |  75 ++++++++++----
 contacts-list-model.h                       |   4 +
 main-widget.cpp                             | 149 ++++++++++++++++++++++++++++
 main-widget.h                               |   2 +
 meta-contact-item.cpp                       | 111 +++++++++++++++++++--
 meta-contact-item.h                         |  11 ++
 remove-contacts-job.cpp                     |  52 ++++++++++
 telepathy-bridge.cpp                        |   6 ++
 telepathy-bridge.h                          |  25 ++++-
 12 files changed, 518 insertions(+), 46 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 23e0ce3..85d52a2 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -78,6 +78,7 @@ set (contactlist_SRCS
      remove-contacts-from-group-job.cpp
      add-contact-job.cpp
      remove-contacts-job.cpp
+     add-meta-contact-job.cpp
 )
 
 kde4_add_ui_files (contactlist_SRCS
@@ -99,6 +100,13 @@ soprano_add_ontology (nco_SRCS
                       "trig"
 )
 
+soprano_add_ontology (nao_SRCS
+                      ${SHAREDDESKTOPONTOLOGIES_ROOT_DIR}/nepomuk/nao.trig
+                      "NAO"
+                      "Nepomuk::Vocabulary"
+                      "trig"
+)
+
 soprano_add_ontology (telepathy_SRCS
                       ${TELEPATHY_TRIG_SOURCE}
                       "Telepathy"
@@ -110,6 +118,7 @@ kde4_add_executable (telepathy_contactlist_prototype
                      ${contactlist_SRCS}
                      ${contactlist_NEPOMUK_SRCS}
                      ${nco_SRCS}
+                     ${nao_SRCS}
                      ${pimo_SRCS}
                      ${telepathy_SRCS}
 )
diff --git a/add-meta-contact-job.cpp b/add-meta-contact-job.cpp
new file mode 100644
index 0000000..e4796e0
--- /dev/null
+++ b/add-meta-contact-job.cpp
@@ -0,0 +1,95 @@
+/*
+ * This file is part of telepathy-contactslist-prototype
+ *
+ * Copyright (C) 2009-2010 Collabora Ltd. <info at collabora.co.uk>
+ *   @Author Dario Freddi <dario.freddi at collabora.co.uk>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include "add-meta-contact-job.h"
+
+#include "telepathy-base-job_p.h"
+#include <QTimer>
+#include <Soprano/Node>
+#include <pimo.h>
+#include <person.h>
+#include <nco.h>
+#include <informationelement.h>
+#include <personcontact.h>
+#include <nao.h>
+#include <Nepomuk/Variant>
+
+class AddMetaContactJobPrivate : public TelepathyBaseJobPrivate
+{
+    Q_DECLARE_PUBLIC(AddMetaContactJob)
+    AddMetaContactJob * const q_ptr;
+
+public:
+    AddMetaContactJobPrivate(AddMetaContactJob *parent)
+        : TelepathyBaseJobPrivate(parent), q_ptr(parent)
+    {}
+    virtual ~AddMetaContactJobPrivate() {}
+
+    QString name;
+    QList< Nepomuk::PersonContact > contacts;
+
+    // Operation Q_PRIVATE_SLOTS
+    void __k__addMetaContact();
+};
+
+AddMetaContactJob::AddMetaContactJob(const QString& name, const QList< Nepomuk::PersonContact > contacts,
+                                     QObject *parent)
+    : TelepathyBaseJob(*new AddMetaContactJobPrivate(this), parent)
+{
+    Q_D(AddMetaContactJob);
+
+    d->name = name;
+    d->contacts = contacts;
+}
+
+AddMetaContactJob::~AddMetaContactJob()
+{
+
+}
+
+void AddMetaContactJob::start()
+{
+    // Go for it
+    QTimer::singleShot(0, this, SLOT(__k__addMetaContact()));
+}
+
+void AddMetaContactJobPrivate::__k__addMetaContact()
+{
+    Q_Q(AddMetaContactJob);
+
+    // FIXME: Get the Nepomuk Resource for myself in the standardised way, once it is standardised.
+    Nepomuk::Resource me(QUrl::fromEncoded("nepomuk:/myself"));
+
+    // Create the metacontact
+    Nepomuk::Person person;
+    Nepomuk::Thing thing;
+    person.setProperty(Nepomuk::Vocabulary::NAO::prefLabel(),
+                       name);
+
+    // Ok, now add the contacts to the metacontact
+    foreach (const Nepomuk::PersonContact &contact, contacts) {
+        person.addGroundingOccurrence(contact);
+    }
+
+    q->emitResult();
+}
+
+#include "add-meta-contact-job.moc"
diff --git a/add-contact-job.h b/add-meta-contact-job.h
similarity index 63%
copy from add-contact-job.h
copy to add-meta-contact-job.h
index 770438c..72eefae 100644
--- a/add-contact-job.h
+++ b/add-meta-contact-job.h
@@ -19,33 +19,30 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
-#ifndef ADD_CONTACT_JOB_H
-#define ADD_CONTACT_JOB_H
+#ifndef ADD_META_CONTACT_JOB_H
+#define ADD_META_CONTACT_JOB_H
 
 #include <telepathy-base-job.h>
 
 namespace Nepomuk {
-    class IMAccount;
-    class Person;
+class PersonContact;
 }
 
-class AddContactJobPrivate;
-class AddContactJob : public TelepathyBaseJob
+class AddMetaContactJobPrivate;
+class AddMetaContactJob : public TelepathyBaseJob
 {
     Q_OBJECT
-    Q_DISABLE_COPY(AddContactJob)
-    Q_DECLARE_PRIVATE(AddContactJob)
+    Q_DISABLE_COPY(AddMetaContactJob)
+    Q_DECLARE_PRIVATE(AddMetaContactJob)
 
     // Our Q_PRIVATE_SLOTS who perform the real job
-    Q_PRIVATE_SLOT(d_func(), void __k__addContact())
-    Q_PRIVATE_SLOT(d_func(), void void __k__onContactsRetrieved(Tp::PendingOperation* op))
+    Q_PRIVATE_SLOT(d_func(), void __k__addMetaContact())
 
 public:
-    AddContactJob(const Nepomuk::IMAccount &account, const QString &contactId,
-                  const QString &petName, const Nepomuk::Person &metacontact, QObject *parent = 0);
-    virtual ~AddContactJob();
+    AddMetaContactJob(const QString &name, const QList< Nepomuk::PersonContact > contacts , QObject *parent = 0);
+    virtual ~AddMetaContactJob();
 
     virtual void start();
 };
 
-#endif // ADD_CONTACT_JOB_H
+#endif // ADD_META_CONTACT_JOB_H
diff --git a/contacts-list-model.cpp b/contacts-list-model.cpp
index 90e971c..12e4071 100644
--- a/contacts-list-model.cpp
+++ b/contacts-list-model.cpp
@@ -61,37 +61,35 @@ ContactsListModel::ContactsListModel(QObject *parent)
     // FIXME: Get the Nepomuk Resource for myself in the standardised way, once it is standardised.
     Nepomuk::Resource me(QUrl::fromEncoded("nepomuk:/myself"));
 
-    // Get the Nepomuk model to query.
-    Soprano::Model *model = Nepomuk::ResourceManager::instance()->mainModel();
-
     // Get ALL THE METACONTACT!!!!11!!111!!11one111!!!!eleven!!!1!
-    // FIXME: Actually make this code do something, then port it to QueryServiceClient
-    QString metaContactquery = QString("select distinct ?a where { ?a a %7 . }")
+    QString metaContactQuery = QString("select distinct ?a where { ?a a %1 }")
             .arg(Soprano::Node::resourceToN3(Nepomuk::Vocabulary::PIMO::Person()));
 
-    Soprano::QueryResultIterator metaIt = model->executeQuery(metaContactquery, Soprano::Query::QueryLanguageSparql);
-
-    while(metaIt.next()) {
-        Nepomuk::Person foundPimoPerson(metaIt.binding("a").uri());
+    m_metaContactsQuery = new Nepomuk::Query::QueryServiceClient(this);
+    connect(m_metaContactsQuery, SIGNAL(newEntries(QList<Nepomuk::Query::Result>)),
+            this, SLOT(onMetaContactsQueryNewEntries(QList<Nepomuk::Query::Result>)));
+    connect(m_metaContactsQuery, SIGNAL(entriesRemoved(QList<QUrl>)),
+            this, SLOT(onMetaContactsEntriesRemoved(QList<QUrl>)));
 
-        kDebug() << "Found a PIMO Person.";
-   //     MetaContactItem *item = new MetaContactItem(foundPimoPerson, 0);
-   //     item->setParentItem(m_rootItem);
-   //     m_rootItem->appendChildItem(item);
-   //     connect(item, SIGNAL(dirty()), SLOT(onItemDirty()));
+    bool queryResult = m_metaContactsQuery->sparqlQuery(metaContactQuery);
+    kDebug() << "Metacontact query result " << queryResult;
+    if (!queryResult) {
+        KMessageBox::error(0, i18n("It was not possible to query Nepomuk database. Please check your "
+                                   "installation and make sure Nepomuk is running."));
     }
 
-    // Get all the Telepathy PersonContacts that are not in a metacontact
-    // FIXME: At the moment, this just gets all Telepathy PersonContacts.
-    QString query = QString("select distinct ?r ?account where { ?r a %1 . ?r %2 ?account . ?acccount a %3 . "
-                            "?account %4 ?t . ?account %5 ?t . ?t a %3 . ?s %2 ?t . ?s a %1 . %6 %7 ?s }")
+    // Get all the Telepathy PersonContacts which do not belong to any metacontact
+    QString query = QString("select distinct ?r ?account where { ?r a %1 . ?r %2 ?account . "
+                            "?acccount a %3 . ?account %4 ?t . ?account %5 ?t . ?t a %3 . ?s %2 ?t . "
+                            "?s a %1 . %6 %7 ?s . optional { ?u a %8 . ?u %7 ?r } . filter(!bound(?u))  }")
             .arg(Soprano::Node::resourceToN3(Nepomuk::Vocabulary::NCO::PersonContact()))
             .arg(Soprano::Node::resourceToN3(Nepomuk::Vocabulary::NCO::hasIMAccount()))
             .arg(Soprano::Node::resourceToN3(Nepomuk::Vocabulary::NCO::IMAccount()))
             .arg(Soprano::Node::resourceToN3(Nepomuk::Vocabulary::Telepathy::isBuddyOf()))
             .arg(Soprano::Node::resourceToN3(Nepomuk::Vocabulary::Telepathy::publishesPresenceTo()))
             .arg(Soprano::Node::resourceToN3(me.resourceUri()))
-            .arg(Soprano::Node::resourceToN3(Nepomuk::Vocabulary::PIMO::groundingOccurrence()));
+            .arg(Soprano::Node::resourceToN3(Nepomuk::Vocabulary::PIMO::groundingOccurrence()))
+            .arg(Soprano::Node::resourceToN3(Nepomuk::Vocabulary::PIMO::Person()));
 
     m_contactsQuery = new Nepomuk::Query::QueryServiceClient(this);
     connect(m_contactsQuery, SIGNAL(newEntries(QList<Nepomuk::Query::Result>)),
@@ -101,8 +99,8 @@ ContactsListModel::ContactsListModel(QObject *parent)
 
     Nepomuk::Query::RequestPropertyMap rpm;
     rpm.insert("account", Nepomuk::Vocabulary::NCO::IMAccount());
-    bool queryResult = m_contactsQuery->sparqlQuery(query, rpm);
-    kDebug() << "Query result " << queryResult;
+    queryResult = m_contactsQuery->sparqlQuery(query, rpm);
+    kDebug() << "Contact query result " << queryResult;
     if (!queryResult) {
         KMessageBox::error(0, i18n("It was not possible to query Nepomuk database. Please check your "
                                    "installation and make sure Nepomuk is running."));
@@ -147,7 +145,13 @@ void ContactsListModel::onContactsQueryEntriesRemoved(const QList< QUrl > &entri
 
             if (contactItem) {
                 // Yeah, we're here. Now let's have a look through metacontacts available
-                AbstractTreeItem *metacontact = contactItem->parentItem();
+                MetaContactItem *metacontact = dynamic_cast<MetaContactItem*>(contactItem->parentItem());
+                if (metacontact->type() != MetaContactItem::FakeMetaContact) {
+                    // Not our business
+                    kDebug() << "Skipping deletion as the metacontact is real";
+                    continue;
+                }
+
                 metacontact->removeChildItem(contactItem);
                 delete contactItem;
                 if (metacontact->childItems().isEmpty()) {
@@ -162,6 +166,31 @@ void ContactsListModel::onContactsQueryEntriesRemoved(const QList< QUrl > &entri
     reset();
 }
 
+void ContactsListModel::onMetaContactsEntriesRemoved(const QList< QUrl > &entries)
+{
+    Q_UNUSED(entries)
+    // Not a big deal here actually, deletion is handled in MetaContactItem.
+    // We just keep this slot for the day when it will be useful
+}
+
+void ContactsListModel::onMetaContactsQueryNewEntries(const QList< Nepomuk::Query::Result > &entries)
+{
+    kDebug();
+    // Iterate over all the IMAccounts/PersonContacts found.
+    foreach (const Nepomuk::Query::Result &result, entries) {
+        kDebug()<<result.resource();
+        Nepomuk::Person foundPimoPerson(result.resource().resourceUri());
+        kDebug() << "Found a PIMO Person "<< foundPimoPerson;
+        MetaContactItem *item = new MetaContactItem(MetaContactItem::RealMetaContact, 0);
+        item->setParentItem(m_rootItem);
+        m_rootItem->appendChildItem(item);
+        item->setPimoPerson(foundPimoPerson);
+        connect(item, SIGNAL(dirty()), SLOT(onItemDirty()));
+    }
+
+    reset();
+}
+
 ContactsListModel::~ContactsListModel()
 {
     kDebug();
@@ -378,6 +407,8 @@ void ContactsListModel::onItemDirty()
         kWarning() << "Invalid sender.";
     }
 
+    reset();
+
     // FIXME: Port this stuff to new tree structure.
    // QModelIndex itemIndex = index(m_contactItems.indexOf(item), 0, QModelIndex());
    // Q_EMIT dataChanged(itemIndex, itemIndex);
diff --git a/contacts-list-model.h b/contacts-list-model.h
index 1397525..35a8f81 100644
--- a/contacts-list-model.h
+++ b/contacts-list-model.h
@@ -68,6 +68,9 @@ private Q_SLOTS:
     void onContactsQueryNewEntries(const QList<Nepomuk::Query::Result>&);
     void onContactsQueryEntriesRemoved(const QList<QUrl>&);
 
+    void onMetaContactsQueryNewEntries(const QList< Nepomuk::Query::Result >&);
+    void onMetaContactsEntriesRemoved(const QList<QUrl>&);
+
 private:
     Q_DISABLE_COPY(ContactsListModel);
 
@@ -78,6 +81,7 @@ private:
     AbstractTreeItem *m_rootItem;
 
     Nepomuk::Query::QueryServiceClient *m_contactsQuery;
+    Nepomuk::Query::QueryServiceClient *m_metaContactsQuery;
 };
 
 
diff --git a/main-widget.cpp b/main-widget.cpp
index 9d9014e..4275e95 100644
--- a/main-widget.cpp
+++ b/main-widget.cpp
@@ -44,9 +44,16 @@
 #include <KMessageBox>
 
 #include <Nepomuk/ResourceManager>
+#include <Nepomuk/Variant>
 #include <Nepomuk/Query/QueryServiceClient>
+#include <Nepomuk/Query/ComparisonTerm>
+#include <Nepomuk/Query/ResourceTypeTerm>
+#include <Nepomuk/Query/LiteralTerm>
+#include <Nepomuk/Query/AndTerm>
 
 #include <Soprano/QueryResultIterator>
+#include <pimo.h>
+#include <nao.h>
 
 const int SPACING = 4;
 const int AVATAR_SIZE = 32;
@@ -243,6 +250,45 @@ void MainWidget::onCustomContextMenuRequested(const QPoint& point)
                         SLOT(onRequestAddToGroup(bool)));
             }
         }
+
+        // Add/remove to metacontacts
+        // First of all: can it be added to a metacontact?
+        bool canAddToMetaContact = false;
+        MetaContactItem *metaContactItem = dynamic_cast<MetaContactItem*>(contactItem->parentItem());
+        if (metaContactItem) {
+            canAddToMetaContact = metaContactItem->type() == MetaContactItem::FakeMetaContact ? true : false;
+        } else {
+            canAddToMetaContact = true;
+        }
+
+        if (canAddToMetaContact) {
+            // Let's list available metacontacts here
+            QString metaContactQuery = QString("select distinct ?a where { ?a a %7 . }")
+                .arg(Soprano::Node::resourceToN3(Nepomuk::Vocabulary::PIMO::Person()));
+            Soprano::Model *model = Nepomuk::ResourceManager::instance()->mainModel();
+            Soprano::QueryResultIterator it = model->executeQuery(metaContactQuery,
+                                                                  Soprano::Query::QueryLanguageSparql);
+
+            QMenu *parentAction = new QMenu(i18n("Add to metacontact"));
+            menu->addMenu(parentAction);
+            // Iterate over all the IMAccounts found.
+            while(it.next()) {
+                Nepomuk::Person foundPerson(it.binding("a").uri());
+                kDebug() << foundPerson;
+                QAction *action = parentAction->addAction(foundPerson.genericLabel());
+                connect(action, SIGNAL(triggered(bool)),
+                        this, SLOT(onAddToMetaContact(bool)));
+            }
+
+            QAction *action = parentAction->addAction(i18nc("Adds a new metacontact", "Add new..."));
+            connect(action, SIGNAL(triggered(bool)),
+                    this, SLOT(onAddToMetaContact(bool)));
+        } else {
+            // We can remove it from a metacontact instead
+            QAction *action = menu->addAction(i18n("Remove from metacontact"));
+            connect(action, SIGNAL(triggered(bool)),
+                    this, SLOT(onRemoveFromMetacontact(bool)));
+        }
     }
 
     MetaContactItem *metaContactItem = dynamic_cast<MetaContactItem*>(abstractItem);
@@ -383,6 +429,33 @@ void MainWidget::onContactBlockRequest(bool )
 
 }
 
+void MainWidget::onRemoveFromMetacontact(bool )
+{
+    // Pick the current model index
+    QModelIndex idx = m_groupedContactsProxyModel->mapToSource(m_contactsListView->currentIndex());
+    if (!idx.isValid()) {
+        // Flee
+        kDebug() << "Invalid index";
+        return;
+    }
+
+    // Ok, what is it?
+    AbstractTreeItem *abstractItem = static_cast<AbstractTreeItem*>(idx.internalPointer());
+    ContactItem *contactItem = dynamic_cast<ContactItem*>(abstractItem);
+
+    Q_ASSERT(contactItem);
+
+    KJob *job = TelepathyBridge::instance()->removeContact(contactItem->personContact(),
+                                                           TelepathyBridge::RemoveFromMetacontactMode);
+
+    QEventLoop e;
+    connect(job, SIGNAL(finished(KJob*)), &e, SLOT(quit()));
+    job->start();
+    qDebug() << "Running job...";
+    e.exec();
+    qDebug() << "Job run, "<< job->error();
+}
+
 void MainWidget::onContactRemovalRequest(bool )
 {
     QAction *action = qobject_cast< QAction* >(sender());
@@ -537,5 +610,81 @@ void MainWidget::onAddContactRequest(bool )
     }
 }
 
+void MainWidget::onAddToMetaContact(bool )
+{
+    QAction *action = qobject_cast< QAction* >(sender());
+    if (!action) {
+        kDebug() << "invalid";
+        return;
+    }
+
+    QString metaContactName = action->text();
+    kDebug() << "Request adding to metacontact " << metaContactName;
+
+    // Pick the current model index
+    QModelIndex idx = m_groupedContactsProxyModel->mapToSource(m_contactsListView->currentIndex());
+    if (!idx.isValid()) {
+        // Flee
+        kDebug() << "Invalid index";
+        return;
+    }
+
+    // Ok, what is it?
+    AbstractTreeItem *abstractItem = static_cast<AbstractTreeItem*>(idx.internalPointer());
+    ContactItem *contactItem = dynamic_cast<ContactItem*>(abstractItem);
+
+    Q_ASSERT(contactItem);
+
+    if (metaContactName == i18nc("Adds a new metacontact", "Add new...")) {
+        // Prompt to create a new metacontact
+        // Let's build a dialog
+        KDialog *dial = new KDialog(this);
+        QWidget *w = new QWidget;
+        QLabel *l = new QLabel(i18n("Please enter a name for this new metacontact"));
+        KLineEdit *contactId = new KLineEdit();
+        QVBoxLayout *lay = new QVBoxLayout;
+        lay->addWidget(l);
+        lay->addWidget(contactId);
+
+        w->setLayout(lay);
+        dial->setMainWidget(w);
+
+        if (dial->exec() == KDialog::Accepted) {
+            // Add the contact
+            metaContactName = contactId->text();
+            KJob *job = TelepathyBridge::instance()->addMetaContact(contactId->text(),
+                                                                    QList< Nepomuk::PersonContact >() <<
+                                                                    contactItem->personContact());
+            QEventLoop e;
+            connect(job, SIGNAL(finished(KJob*)), &e, SLOT(quit()));
+            job->start();
+            qDebug() << "Running job...";
+            e.exec();
+            qDebug() << "Job run, "<< job->error();
+        }
+
+        return;
+    }
+
+    // Ok, now let's add the contact
+    Soprano::QueryResultIterator it;
+    {
+        using namespace Nepomuk::Query;
+        using namespace Nepomuk::Vocabulary;
+        ResourceTypeTerm rtterm(PIMO::Person());
+        ComparisonTerm cmpterm(NAO::prefLabel(), LiteralTerm(metaContactName));
+        Query query(AndTerm(cmpterm, rtterm));
+        Soprano::Model *model = Nepomuk::ResourceManager::instance()->mainModel();
+        it = model->executeQuery(query.toSparqlQuery(), Soprano::Query::QueryLanguageSparql);
+        kDebug() << query.toSparqlQuery();
+    }
+
+    // Iterate over all the IMAccounts found.
+    while(it.next()) {
+        Nepomuk::Person foundPerson(it.binding("r").uri());
+        foundPerson.addGroundingOccurrence(contactItem->personContact());
+    }
+}
+
 #include "main-widget.moc"
 
diff --git a/main-widget.h b/main-widget.h
index 3f845a3..d5cfbfc 100644
--- a/main-widget.h
+++ b/main-widget.h
@@ -66,6 +66,8 @@ public slots:
     void onHandlerReady(bool);
     void onRequestAddToGroup(bool);
     void onAddContactRequest(bool);
+    void onAddToMetaContact(bool);
+    void onRemoveFromMetacontact(bool);
 };
 
 
diff --git a/meta-contact-item.cpp b/meta-contact-item.cpp
index e191819..13a6202 100644
--- a/meta-contact-item.cpp
+++ b/meta-contact-item.cpp
@@ -25,6 +25,14 @@
 
 #include <KDebug>
 #include <KIcon>
+#include <nco.h>
+#include <nao.h>
+#include <telepathy.h>
+#include <pimo.h>
+#include <Nepomuk/Variant>
+#include <Nepomuk/Query/Result>
+#include <Nepomuk/Query/QueryServiceClient>
+#include <KMessageBox>
 
 MetaContactItem::MetaContactItem(MetaContactType type, QObject *parent)
   : QObject(parent),
@@ -46,6 +54,8 @@ MetaContactItem::MetaContactItem(MetaContactType type, QObject *parent)
 MetaContactItem::~MetaContactItem()
 {
     kDebug();
+    NepomukSignalWatcher *watcher = NepomukSignalWatcher::instance();
+    watcher->unregisterCallbackOnSubject(m_pimoPerson, this);
 }
 
 void MetaContactItem::onStatementAdded(const Soprano::Statement &statement)
@@ -67,22 +77,103 @@ void MetaContactItem::setPimoPerson(const Nepomuk::Person& pimoPerson)
     // Subscribe to Nepomuk change signals for our Nepomuk Resources.
     NepomukSignalWatcher *watcher = NepomukSignalWatcher::instance();
     watcher->registerCallbackOnSubject(m_pimoPerson, this);
+
+    // FIXME: Get the Nepomuk Resource for myself in the standardised way, once it is standardised.
+    Nepomuk::Resource me(QUrl::fromEncoded("nepomuk:/myself"));
+
+    // Ok, now we need a decent query to find out our children.
+    // Get all the Telepathy PersonContacts which belong to this metacontact, and match our criteria
+    QString query = QString("select distinct ?r ?account where { %8 %7 ?r . ?r a %1 . ?r %2 ?account . "
+                            "?acccount a %3 . ?account %4 ?t . ?account %5 ?t . ?t a %3 . ?s %2 ?t . "
+                            "?s a %1 . %6 %7 ?s }")
+            .arg(Soprano::Node::resourceToN3(Nepomuk::Vocabulary::NCO::PersonContact()))
+            .arg(Soprano::Node::resourceToN3(Nepomuk::Vocabulary::NCO::hasIMAccount()))
+            .arg(Soprano::Node::resourceToN3(Nepomuk::Vocabulary::NCO::IMAccount()))
+            .arg(Soprano::Node::resourceToN3(Nepomuk::Vocabulary::Telepathy::isBuddyOf()))
+            .arg(Soprano::Node::resourceToN3(Nepomuk::Vocabulary::Telepathy::publishesPresenceTo()))
+            .arg(Soprano::Node::resourceToN3(me.resourceUri()))
+            .arg(Soprano::Node::resourceToN3(Nepomuk::Vocabulary::PIMO::groundingOccurrence()))
+            .arg(Soprano::Node::resourceToN3(pimoPerson.resourceUri()));
+
+    m_queryClient = new Nepomuk::Query::QueryServiceClient(this);
+    connect(m_queryClient, SIGNAL(newEntries(QList<Nepomuk::Query::Result>)),
+            this, SLOT(onNewEntries(QList<Nepomuk::Query::Result>)));
+    connect(m_queryClient, SIGNAL(entriesRemoved(QList<QUrl>)),
+            this, SLOT(onEntriesRemoved(QList<QUrl>)));
+
+    Nepomuk::Query::RequestPropertyMap rpm;
+    rpm.insert("account", Nepomuk::Vocabulary::NCO::IMAccount());
+    bool queryResult = m_queryClient->sparqlQuery(query, rpm);
+    kDebug() << "Query result for " << pimoPerson << queryResult;
+    if (!queryResult) {
+        KMessageBox::error(0, i18n("It was not possible to query Nepomuk database. Please check your "
+                                   "installation and make sure Nepomuk is running."));
+    }
 }
 
-QString MetaContactItem::displayName() const
+void MetaContactItem::onEntriesRemoved(const QList< QUrl > &entries)
 {
-    // FIXME: What should we actually return here?
-    if (childItems().isEmpty()) {
-        return QString();
+    kDebug();
+    bool isDirty = false;
+    // Find and remove
+    foreach (const QUrl &url, entries) {
+        kDebug() << "Attempting to remove resource " << url;
+        // Iterate our children
+        foreach (AbstractTreeItem *item, childItems()) {
+            ContactItem *contactItem = dynamic_cast<ContactItem*>(item);
+
+            if (contactItem) {
+                removeChildItem(contactItem);
+                delete contactItem;
+                isDirty = true;
+            }
+        }
     }
 
-    ContactItem *item = dynamic_cast<ContactItem*>(childItems().first());
+    emit dirty();
+}
 
-    if (!item) {
-        return QString();
+void MetaContactItem::onNewEntries(const QList< Nepomuk::Query::Result > &entries)
+{
+    kDebug();
+    // Iterate over all the IMAccounts/PersonContacts found.
+    foreach (const Nepomuk::Query::Result &result, entries) {
+        Nepomuk::PersonContact foundPersonContact(result.resource().resourceUri());
+        Nepomuk::IMAccount foundIMAccount(result.requestProperty(Nepomuk::Vocabulary::NCO::IMAccount()).uri());
+        kDebug() << "New resource added";
+
+        // Create the contact item itself, parenting it to this metacontact.
+        ContactItem *item = new ContactItem(foundPersonContact, foundIMAccount, 0);
+        item->setParentItem(this);
+        appendChildItem(item);
+        connect(item, SIGNAL(dirty()), this, SIGNAL(dirty()));
     }
 
-    return item->displayName();
+    emit dirty();
+}
+
+QString MetaContactItem::displayName() const
+{
+    switch (m_type) {
+        case RealMetaContact:
+            // Let's display what PIMOPerson says
+            return m_pimoPerson.genericLabel();
+            break;
+        case FakeMetaContact:
+            // In this case, let's just display the name of the first contact
+            if (childItems().isEmpty()) {
+                return QString();
+            }
+
+            ContactItem *item = dynamic_cast<ContactItem*>(childItems().first());
+
+            if (!item) {
+                return QString();
+            }
+
+            return item->displayName();
+            break;
+    }
 }
 
 const KIcon &MetaContactItem::presenceIcon() const
@@ -133,6 +224,10 @@ const QPixmap& MetaContactItem::avatar() const
     return item->avatar();
 }
 
+MetaContactItem::MetaContactType MetaContactItem::type() const
+{
+    return m_type;
+}
 
 #include "meta-contact-item.moc"
 
diff --git a/meta-contact-item.h b/meta-contact-item.h
index 8d7b8e2..597aa2b 100644
--- a/meta-contact-item.h
+++ b/meta-contact-item.h
@@ -31,6 +31,13 @@
 #include <QObject>
 #include <QPixmap>
 
+namespace Nepomuk {
+namespace Query {
+class QueryServiceClient;
+class Result;
+}
+}
+
 class KIcon;
 
 class MetaContactItem : public QObject,
@@ -53,6 +60,7 @@ public:
     const KIcon &presenceIcon() const;
     const QPixmap& avatar() const;
     QStringList groups() const;
+    MetaContactType type() const;
 
     void setPimoPerson(const Nepomuk::Person &pimoPerson);
     Nepomuk::Person pimoPerson() const;
@@ -63,6 +71,8 @@ Q_SIGNALS:
     void dirty();
 
 private Q_SLOTS:
+    void onNewEntries(const QList<Nepomuk::Query::Result>&);
+    void onEntriesRemoved(const QList<QUrl>&);
 //    void updatePresenceIcon();
 
 private:
@@ -72,6 +82,7 @@ private:
     Nepomuk::Person m_pimoPerson;
     KIcon *m_invalidPresenceIcon;
     QPixmap m_invalidPixmap;
+    Nepomuk::Query::QueryServiceClient *m_queryClient;
 };
 
 
diff --git a/remove-contacts-job.cpp b/remove-contacts-job.cpp
index 080202b..380ae00 100644
--- a/remove-contacts-job.cpp
+++ b/remove-contacts-job.cpp
@@ -38,6 +38,12 @@
 #include <TelepathyQt4/AccountManager>
 #include <TelepathyQt4/ContactManager>
 #include <TelepathyQt4/PendingOperation>
+#include <Soprano/Node>
+#include <pimo.h>
+#include <Soprano/Model>
+#include <Nepomuk/ResourceManager>
+#include <Soprano/QueryResultIterator>
+#include <informationelement.h>
 
 class RemoveContactsJobPrivate : public TelepathyBaseJobPrivate
 {
@@ -144,6 +150,7 @@ void RemoveContactsJobPrivate::__k__removeContacts()
     Q_Q(RemoveContactsJob);
 
     QHash< TelepathyAccountProxy*, QList< Tp::ContactPtr > > tbd;
+    QHash< TelepathyAccountProxy*, QList< Nepomuk::PersonContact > > proxyToContacts;
 
     foreach (const Nepomuk::PersonContact &contact, contacts) {
         // Retrieve IM identifiers first
@@ -154,6 +161,7 @@ void RemoveContactsJobPrivate::__k__removeContacts()
 
         foreach (TelepathyAccountProxy *proxy, TelepathyBridge::instance()->d_func()->accountProxiesForContact(contact)) {
             tbd[proxy] << proxy->contactsForIdentifiers(imIDs);
+            proxyToContacts[proxy] << contact;
         }
     }
 
@@ -195,6 +203,50 @@ void RemoveContactsJobPrivate::__k__removeContacts()
                 addOperation(i.key()->account()->connection()->contactManager()->blockContacts(i.value()));
             }
         }
+        if (removalModes & TelepathyBridge::RemoveFromMetacontactMode) {
+            // Check if this contact is associated to a metacontact
+            Soprano::Model *model = Nepomuk::ResourceManager::instance()->mainModel();
+
+            // FIXME: Port to new OSCAF standard for accessing "me" as soon as it
+            // becomes available.
+            Nepomuk::Thing me(QUrl::fromEncoded("nepomuk:/myself"));
+
+            foreach (const Nepomuk::PersonContact &contact, proxyToContacts[i.key()]) {
+                QString query = QString("select distinct ?r where { ?r a %1 . ?r %2 %3 }")
+                                .arg(Soprano::Node::resourceToN3(Nepomuk::Vocabulary::PIMO::Person()))
+                                .arg(Soprano::Node::resourceToN3(Nepomuk::Vocabulary::PIMO::groundingOccurrence()))
+                                .arg(Soprano::Node::resourceToN3(contact.resourceUri()));
+
+
+                Soprano::QueryResultIterator it = model->executeQuery(query, Soprano::Query::QueryLanguageSparql);
+
+                while (it.next()) {
+                    Nepomuk::Person foundPerson(it.binding("r").uri());
+
+                    if (foundPerson.resourceUri() == me.resourceUri()) {
+                        kDebug() << "Skipping myself resource for removing from metacontact";
+                        continue;
+                    }
+
+                    // Ok, let's now remove the grounding occurrence
+                    QList< Nepomuk::InformationElement > gOccs = foundPerson.groundingOccurrences();
+                    {
+                        QList< Nepomuk::InformationElement >::iterator it = gOccs.begin();
+                        while (it != gOccs.end()) {
+                            if ((*it).resourceUri() == contact.resourceUri()) {
+                                kDebug() << "Matched groundingOccurrence metacontact->contact, removing";
+                                it = gOccs.erase(it);
+                            } else {
+                                ++it;
+                            }
+                        }
+                    }
+
+                    // Set the new property
+                    foundPerson.setGroundingOccurrences(gOccs);
+                }
+            }
+        }
     }
 }
 
diff --git a/telepathy-bridge.cpp b/telepathy-bridge.cpp
index e2d4e74..1b18323 100644
--- a/telepathy-bridge.cpp
+++ b/telepathy-bridge.cpp
@@ -37,6 +37,7 @@
 #include "add-contacts-to-group-job.h"
 #include "remove-contacts-job.h"
 #include "add-contact-job.h"
+#include "add-meta-contact-job.h"
 
 #include <TelepathyQt4/AccountManager>
 #include <TelepathyQt4/PendingReady>
@@ -416,5 +417,10 @@ KJob* TelepathyBridge::addContact(const Nepomuk::IMAccount& account, const QStri
     return new AddContactJob(account, contactId, petName, metacontact, this);
 }
 
+KJob* TelepathyBridge::addMetaContact(const QString& name, const QList< Nepomuk::PersonContact > contacts)
+{
+    return new AddMetaContactJob(name, contacts, this);
+}
+
 
 #include "telepathy-bridge.moc"
diff --git a/telepathy-bridge.h b/telepathy-bridge.h
index 0a5928a..8044a9b 100644
--- a/telepathy-bridge.h
+++ b/telepathy-bridge.h
@@ -73,10 +73,14 @@ public:
         RemoveSubscriptionMode = 1,
         /** Revokes the contact's subscription to your presence */
         RemovePublicationMode = 2,
+        /** Removes the contact from the corresponding metacontact, if any.
+         *  The metacontact is  not deleted.
+         */
+        RemoveFromMetacontactMode = 4,
         /** Blocks the contact */
-        BlockMode = 4,
+        BlockMode = 8,
         /** Removes the metacontact only - leaves unaltered the underlying real contacts */
-        RemoveMetaContactMode = 8
+        RemoveMetaContactMode = 16
     };
     Q_DECLARE_FLAGS(RemovalModes, RemovalMode)
 
@@ -111,6 +115,8 @@ public:
         ProtocolNotCapableError = 105,
         /** The operation requested the account to be online, but it is not */
         AccountNotOnlineError = 106,
+        /** An operation attempted to create a nepomuk resource which already exists */
+        ResourceAlreadyExistsError = 107,
         /** Telepathy triggered an error */
         TelepathyErrorError = 200
     };
@@ -406,6 +412,21 @@ public:
                      const QString &petName, const Nepomuk::Person &metacontact);
 
     /**
+     * rief Adds a metacontact
+     *
+     * This function attempts to add a metacontact. It will return a valid KJob ready to be started.
+     *
+     * \param name The name of the new metacontact
+     * \param contacts A list of contacts to be associated to this metacontact
+     *
+     * 
eturns A valid KJob ready to be started
+     *
+     * 
ote Please remember that KJob has to be explicitly started using KJob::start(),
+     *       differently from Tp::PendingOperation.
+     */
+    KJob *addMetaContact(const QString &name, const QList< Nepomuk::PersonContact > contacts);
+
+    /**
      * 
eturns whether TelepathyBridge is ready to be used or not. This function will return true after a successful 
-- 
ktp-contact-list packaging



More information about the pkg-kde-commits mailing list