Branch 'kolab/integration/4.13.0' - 4 commits - korganizer/akonadicollectionview.cpp korganizer/CMakeLists.txt korganizer/views

Christian Mollekopf mollekopf at kolabsys.com
Mon Dec 8 18:28:50 CET 2014


 korganizer/CMakeLists.txt                            |    1 
 korganizer/akonadicollectionview.cpp                 |   17 -
 korganizer/views/collectionview/controller.cpp       |  224 ----------------
 korganizer/views/collectionview/controller.h         |   53 ---
 korganizer/views/collectionview/person.h             |   46 +++
 korganizer/views/collectionview/personsearchjob.cpp  |  253 +++++++++++++++++++
 korganizer/views/collectionview/personsearchjob.h    |   65 ++++
 korganizer/views/collectionview/reparentingmodel.cpp |   11 
 8 files changed, 386 insertions(+), 284 deletions(-)

New commits:
commit 1ea0b044332472c6240eb969a961f4f01cb126ab
Merge: f2444f0 3c161af
Author: Christian Mollekopf <chrigi_1 at fastmail.fm>
Date:   Mon Dec 8 14:46:58 2014 +0100

    Merge remote-tracking branch 'kolab/dev/fix_quickview' into kolab/integration/4.13.0



commit f2444f0c654c041aecabf8b0b25ed5ecffead8d5
Author: Christian Mollekopf <chrigi_1 at fastmail.fm>
Date:   Thu Dec 4 13:39:47 2014 +0100

    Move PersonSearchJob to separate file.

diff --git a/korganizer/CMakeLists.txt b/korganizer/CMakeLists.txt
index 377a48f..07218db 100644
--- a/korganizer/CMakeLists.txt
+++ b/korganizer/CMakeLists.txt
@@ -176,6 +176,7 @@ set(korganizerprivate_LIB_SRCS
     views/collectionview/reparentingmodel.cpp
     views/collectionview/controller.cpp
     views/collectionview/collectionsearchjob.cpp
+    views/collectionview/personsearchjob.cpp
     views/collectionview/calendardelegate.cpp
     views/collectionview/quickview.cpp
     calendarview.cpp
diff --git a/korganizer/views/collectionview/controller.cpp b/korganizer/views/collectionview/controller.cpp
index 04fd3cb..d6f294d 100644
--- a/korganizer/views/collectionview/controller.cpp
+++ b/korganizer/views/collectionview/controller.cpp
@@ -36,6 +36,7 @@
 #include <akonadi/collectionidentificationattribute.h>
 
 #include "collectionsearchjob.h"
+#include "personsearchjob.h"
 
 CollectionNode::CollectionNode(ReparentingModel& personModel, const Akonadi::Collection& col)
 :   Node(personModel),
@@ -270,229 +271,6 @@ void PersonNodeManager::checkSourceIndexRemoval(const QModelIndex &sourceIndex)
 }
 
 
-PersonSearchJob::PersonSearchJob(const QString& searchString, QObject* parent)
-    : KJob(parent),
-    mSearchString(searchString)
-{
-    connect(&mLdapSearch, SIGNAL(searchData(const QList<KLDAP::LdapResultObject> &)),
-            SLOT(onLDAPSearchData(const QList<KLDAP::LdapResultObject> &)));
-
-    connect(&mLdapSearch, SIGNAL(searchDone()),
-            SLOT(onLDAPSearchDone()));
-}
-
-PersonSearchJob::~PersonSearchJob()
-{
-    mLdapSearch.cancelSearch();
-}
-
-bool PersonSearchJob::kill(KJob::KillVerbosity verbosity)
-{
-    mLdapSearch.cancelSearch();
-    return KJob::kill(verbosity);
-}
-
-void PersonSearchJob::start()
-{
-    Baloo::PIM::CollectionQuery query;
-    query.setNamespace(QStringList() << QLatin1String("usertoplevel"));
-    query.nameMatches(mSearchString);
-    query.setLimit(200);
-    Baloo::PIM::ResultIterator it = query.exec();
-    Akonadi::Collection::List collections;
-    while (it.next()) {
-        collections << Akonadi::Collection(it.id());
-    }
-    kDebug() << "Found persons " << collections.size();
-
-    mCollectionSearchDone = false;
-    mLdapSearchDone = false;
-
-    mLdapSearch.startSearch(QLatin1String("*") + mSearchString);
-
-    if (collections.isEmpty()) {
-        //We didn't find anything
-        mCollectionSearchDone = true;
-        return;
-    }
-
-    Akonadi::CollectionFetchJob *fetchJob = new Akonadi::CollectionFetchJob(collections, Akonadi::CollectionFetchJob::Base, this);
-    fetchJob->fetchScope().setAncestorRetrieval(Akonadi::CollectionFetchScope::All);
-    fetchJob->fetchScope().setListFilter(Akonadi::CollectionFetchScope::NoFilter);
-    connect(fetchJob, SIGNAL(collectionsReceived(Akonadi::Collection::List)), this, SLOT(onCollectionsReceived(Akonadi::Collection::List)));
-    connect(fetchJob, SIGNAL(result(KJob*)), this, SLOT(onCollectionsFetched(KJob*)));
-
-    //The IMAP resource should add a "Person" attribute to the collections in the person namespace,
-    //the ldap query can then be used to update the name (entitydisplayattribute) for the person.
-}
-
-void PersonSearchJob::onLDAPSearchData(const QList< KLDAP::LdapResultObject > &list)
-{
-    QList<Person> persons;
-    Q_FOREACH(const KLDAP::LdapResultObject &item, list) {
-        Person person;
-        person.name = QString::fromUtf8(item.object.value(QLatin1String("cn")));
-        person.mail = QString::fromUtf8(item.object.value(QLatin1String("mail")));
-
-        const int depth = item.object.dn().depth();
-        for ( int i = 0; i < depth; ++i ) {
-            const QString rdnStr = item.object.dn().rdnString(i);
-            if ( rdnStr.startsWith(QLatin1String("ou="), Qt::CaseInsensitive) ) {
-                person.ou = rdnStr.mid(3);
-                break;
-            }
-        }
-        const QStringList &parts = person.mail.split(QLatin1Char('@'));
-        if (parts.count() == 2) {
-            const QString &uid = parts.at(0);
-            person.uid = uid;
-            if (mMatches.contains(uid)) {
-                const Person &p = mMatches.value(uid);
-                if (p.mail != person.mail ) {
-                    if (p.rootCollection > -1) {
-                        person.rootCollection = p.rootCollection;
-                        person.updateDisplayName = p.updateDisplayName;
-                        updatePersonCollection(person);
-                        mMatches.insert(uid, person);
-                    } else {
-                        kWarning() << "That should not happen: we found two times persons with the same uid ("<< uid << "), but differnet name:" << p.name << "vs" << person.name;
-                    }
-                }
-            } else {            //New person found
-                mMatches.insert(uid, person);
-                persons << person;
-            }
-        } else {
-            kWarning() << item.object.dn().toString() << ": invalid email address" << person.mail;
-        }
-    }
-    if (persons.count() > 0) {
-        emit personsFound(persons);
-    }
-}
-
-void PersonSearchJob::onLDAPSearchDone()
-{
-    mLdapSearchDone = true;
-    if (mCollectionSearchDone) {
-        emitResult();
-    }
-}
-
-void PersonSearchJob::onCollectionsReceived(const Akonadi::Collection::List &list)
-{
-    QList<Person> persons;
-    Q_FOREACH(const Akonadi::Collection &col, list) {
-        Person person;
-        const QString &uid = col.name();
-        const CollectionIdentificationAttribute *const attr = col.attribute<CollectionIdentificationAttribute>();
-        const Akonadi::EntityDisplayAttribute *const displayname = col.attribute<Akonadi::EntityDisplayAttribute>();
-        person.rootCollection = col.id();
-        person.uid = uid;
-        if (attr) {
-            person.ou = QString::fromUtf8(attr->ou());
-            person.mail = QString::fromUtf8(attr->mail());
-            person.name = QString::fromUtf8(attr->identifier());
-            if (!displayname || displayname->displayName().isEmpty() || displayname->displayName() == person.name) {
-                person.updateDisplayName = true;
-            }
-        } else {
-            person.name = col.displayName();
-            if (!displayname || displayname->displayName().isEmpty()) {
-                person.updateDisplayName = true;
-            }
-        }
-        if (mMatches.contains(uid)) {
-            Person p = mMatches.value(uid);
-            if (p.rootCollection > -1) {
-                //two collection with the same uid ?! 
-                kWarning() << "Two collections match to same person" << p.rootCollection << person.rootCollection;
-            } else if (p.mail != person.mail) {
-                p.rootCollection = person.rootCollection;
-                p.updateDisplayName = person.updateDisplayName;
-                updatePersonCollection(p);
-            } else {
-                mMatches.insert(uid, person);
-                emit personUpdate(person);
-            }
-        } else {
-            mMatches.insert(uid, person);
-            persons << person;
-        }
-    }
-
-    if (persons.count() > 0) {
-        emit personsFound(persons);
-    }
-}
-
-void PersonSearchJob::updatePersonCollection(const Person &person)
-{
-    Akonadi::Collection c(person.rootCollection);
-    CollectionIdentificationAttribute *identification = c.attribute<CollectionIdentificationAttribute>(Akonadi::Entity::AddIfMissing);
-
-    if (person.updateDisplayName) {
-        Akonadi::EntityDisplayAttribute *displayname  = c.attribute<Akonadi::EntityDisplayAttribute >(Akonadi::Entity::AddIfMissing);
-        displayname->setDisplayName(person.name);
-    }
-
-    //identification->setIdentifier("Other Users/" + person.uid);
-    identification->setIdentifier(person.name.toUtf8());
-    identification->setName(person.name.toUtf8());
-    identification->setCollectionNamespace("usertoplevel");
-    identification->setMail(person.mail.toUtf8());
-    identification->setOu(person.ou.toUtf8());
-
-    Akonadi::CollectionModifyJob *job = new Akonadi::CollectionModifyJob( c, this );
-    connect(job, SIGNAL(result(KJob*)), this, SLOT(modifyResult(KJob*)));
-}
-
-void PersonSearchJob::onCollectionsFetched(KJob *job)
-{
-    if (job->error()) {
-        kWarning() << job->errorString();
-    }
-    mCollectionSearchDone = true;
-    if (mLdapSearchDone) {
-        emitResult();
-    }
-}
-
-QList<Person> PersonSearchJob::matches() const
-{
-    return mMatches.values();
-}
-
-void PersonSearchJob::modifyResult(KJob *job)
-{
-    if (job->error()) {
-        kWarning() << job->errorString();
-        return;
-    }
-
-    const Akonadi::CollectionModifyJob *modifyJob = static_cast<Akonadi::CollectionModifyJob*>(job);
-    const Akonadi::Collection &col = modifyJob->collection();
-
-    const CollectionIdentificationAttribute *const attr = col.attribute<CollectionIdentificationAttribute>();
-    const Akonadi::EntityDisplayAttribute *const displayname = col.attribute<Akonadi::EntityDisplayAttribute>();
-    const QString &uid = col.name();
-    Person &person = mMatches[col.name()];
-    person.rootCollection = col.id();
-    person.uid = uid;
-    if (attr) {
-        person.ou = QString::fromUtf8(attr->ou());
-        person.mail = QString::fromUtf8(attr->mail());
-        person.name = QString::fromUtf8(attr->identifier());
-        if (!displayname || displayname->displayName().isEmpty() || displayname->displayName() == person.name) {
-            person.updateDisplayName = true;
-        }
-    }
-    kDebug() << "modified person to" << person.uid << person.name << person.rootCollection;
-
-    mMatches.insert(person.uid, person);
-    emit personUpdate(person);
-}
-
 
 Controller::Controller(ReparentingModel* personModel, ReparentingModel* searchModel, QObject* parent)
     : QObject(parent),
diff --git a/korganizer/views/collectionview/controller.h b/korganizer/views/collectionview/controller.h
index 4422ba8..e54b4ff 100644
--- a/korganizer/views/collectionview/controller.h
+++ b/korganizer/views/collectionview/controller.h
@@ -28,6 +28,7 @@
 #include <Akonadi/EntityTreeModel>
 #include <Akonadi/Collection>
 #include "reparentingmodel.h"
+#include "person.h"
 
 #include <libkdepim/ldap/ldapclientsearch.h>
 
@@ -45,23 +46,6 @@ enum NodeTypeRoles {
     CollectionNodeRole
 };
 
-struct Person
-{
-    Person(): rootCollection(-1), updateDisplayName(false) {};
-    QString name;
-    QString uid;
-    QString ou;
-    QString mail;
-    Akonadi::Collection::Id rootCollection;
-    bool updateDisplayName;
-    
-    //FIXME not sure we actually require those two
-    QStringList folderPaths;
-    QList<Akonadi::Collection::Id> collections;
-};
-
-Q_DECLARE_METATYPE(Person);
-
 /**
  * We need to emit signals in the subclass but don't want to make the parent a QObject
  */
@@ -139,41 +123,8 @@ private:
     void updateSourceIndex(const QModelIndex &sourceIndex);
 };
 
-class PersonSearchJob : public KJob
-{
-    Q_OBJECT
-public:
-    explicit PersonSearchJob(const QString &searchString, QObject* parent = 0);
-    virtual ~PersonSearchJob();
-
-    virtual void start();
-
-    QList<Person> matches() const;
-
-Q_SIGNALS:
-    void personsFound(const QList<Person> &persons);
-    void personUpdate(const Person &person);
-
-public Q_SLOTS:
-    bool kill(KillVerbosity verbosity=Quietly);
-
-private Q_SLOTS:
-    void onCollectionsReceived(const Akonadi::Collection::List &);
-    void onCollectionsFetched(KJob *);
-    void onLDAPSearchData(const QList<KLDAP::LdapResultObject> &);
-    void onLDAPSearchDone();
-    void updatePersonCollection(const Person &person);
-    void modifyResult(KJob *job);
-
-private:
-    QString mSearchString;
-    QHash<QString, Person> mMatches;
-    KLDAP::LdapClientSearch mLdapSearch;
-    bool mCollectionSearchDone;
-    bool mLdapSearchDone;
-};
-
 class CollectionSearchJob;
+class PersonSearchJob;
 
 /**
  * Add search results to the search model, and use the selection to add results to the person model.
diff --git a/korganizer/views/collectionview/person.h b/korganizer/views/collectionview/person.h
new file mode 100644
index 0000000..8fe979b
--- /dev/null
+++ b/korganizer/views/collectionview/person.h
@@ -0,0 +1,46 @@
+/*
+  Copyright (C) 2014 Christian Mollekopf <mollekopf at kolabsys.com>
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  This program 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 General Public License for more details.
+
+  You should have received a copy of the GNU General Public License along
+  with this program; if not, write to the Free Software Foundation, Inc.,
+  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+  As a special exception, permission is given to link this program
+  with any edition of Qt, and distribute the resulting executable,
+  without including the source code for Qt in the source distribution.
+*/
+
+#ifndef KORG_PERSON_H
+#define KORG_PERSON_H
+
+#include <QStringList>
+#include <Akonadi/Collection>
+
+struct Person
+{
+    Person(): rootCollection(-1), updateDisplayName(false) {};
+    QString name;
+    QString uid;
+    QString ou;
+    QString mail;
+    Akonadi::Collection::Id rootCollection;
+    bool updateDisplayName;
+    
+    //FIXME not sure we actually require those two
+    QStringList folderPaths;
+    QList<Akonadi::Collection::Id> collections;
+};
+
+Q_DECLARE_METATYPE(Person);
+
+#endif
diff --git a/korganizer/views/collectionview/personsearchjob.cpp b/korganizer/views/collectionview/personsearchjob.cpp
new file mode 100644
index 0000000..9fcda4e
--- /dev/null
+++ b/korganizer/views/collectionview/personsearchjob.cpp
@@ -0,0 +1,253 @@
+/*
+  Copyright (C) 2014 Christian Mollekopf <mollekopf at kolabsys.com>
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  This program 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 General Public License for more details.
+
+  You should have received a copy of the GNU General Public License along
+  with this program; if not, write to the Free Software Foundation, Inc.,
+  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+  As a special exception, permission is given to link this program
+  with any edition of Qt, and distribute the resulting executable,
+  without including the source code for Qt in the source distribution.
+*/
+#include "personsearchjob.h"
+
+#include <Akonadi/EntityDisplayAttribute>
+#include <Akonadi/CollectionModifyJob>
+#include <Akonadi/CollectionFetchJob>
+#include <Akonadi/CollectionFetchScope>
+#include <KLocale>
+#include <baloo/pim/collectionquery.h>
+#include <akonadi/collectionidentificationattribute.h>
+
+PersonSearchJob::PersonSearchJob(const QString& searchString, QObject* parent)
+    : KJob(parent),
+    mSearchString(searchString)
+{
+    connect(&mLdapSearch, SIGNAL(searchData(const QList<KLDAP::LdapResultObject> &)),
+            SLOT(onLDAPSearchData(const QList<KLDAP::LdapResultObject> &)));
+
+    connect(&mLdapSearch, SIGNAL(searchDone()),
+            SLOT(onLDAPSearchDone()));
+}
+
+PersonSearchJob::~PersonSearchJob()
+{
+    mLdapSearch.cancelSearch();
+}
+
+bool PersonSearchJob::kill(KJob::KillVerbosity verbosity)
+{
+    mLdapSearch.cancelSearch();
+    return KJob::kill(verbosity);
+}
+
+void PersonSearchJob::start()
+{
+    Baloo::PIM::CollectionQuery query;
+    query.setNamespace(QStringList() << QLatin1String("usertoplevel"));
+    query.nameMatches(mSearchString);
+    query.setLimit(200);
+    Baloo::PIM::ResultIterator it = query.exec();
+    Akonadi::Collection::List collections;
+    while (it.next()) {
+        collections << Akonadi::Collection(it.id());
+    }
+    kDebug() << "Found persons " << collections.size();
+
+    mCollectionSearchDone = false;
+    mLdapSearchDone = false;
+
+    mLdapSearch.startSearch(QLatin1String("*") + mSearchString);
+
+    if (collections.isEmpty()) {
+        //We didn't find anything
+        mCollectionSearchDone = true;
+        return;
+    }
+
+    Akonadi::CollectionFetchJob *fetchJob = new Akonadi::CollectionFetchJob(collections, Akonadi::CollectionFetchJob::Base, this);
+    fetchJob->fetchScope().setAncestorRetrieval(Akonadi::CollectionFetchScope::All);
+    fetchJob->fetchScope().setListFilter(Akonadi::CollectionFetchScope::NoFilter);
+    connect(fetchJob, SIGNAL(collectionsReceived(Akonadi::Collection::List)), this, SLOT(onCollectionsReceived(Akonadi::Collection::List)));
+    connect(fetchJob, SIGNAL(result(KJob*)), this, SLOT(onCollectionsFetched(KJob*)));
+
+    //The IMAP resource should add a "Person" attribute to the collections in the person namespace,
+    //the ldap query can then be used to update the name (entitydisplayattribute) for the person.
+}
+
+void PersonSearchJob::onLDAPSearchData(const QList< KLDAP::LdapResultObject > &list)
+{
+    QList<Person> persons;
+    Q_FOREACH(const KLDAP::LdapResultObject &item, list) {
+        Person person;
+        person.name = QString::fromUtf8(item.object.value(QLatin1String("cn")));
+        person.mail = QString::fromUtf8(item.object.value(QLatin1String("mail")));
+
+        const int depth = item.object.dn().depth();
+        for ( int i = 0; i < depth; ++i ) {
+            const QString rdnStr = item.object.dn().rdnString(i);
+            if ( rdnStr.startsWith(QLatin1String("ou="), Qt::CaseInsensitive) ) {
+                person.ou = rdnStr.mid(3);
+                break;
+            }
+        }
+        const QStringList &parts = person.mail.split(QLatin1Char('@'));
+        if (parts.count() == 2) {
+            const QString &uid = parts.at(0);
+            person.uid = uid;
+            if (mMatches.contains(uid)) {
+                const Person &p = mMatches.value(uid);
+                if (p.mail != person.mail ) {
+                    if (p.rootCollection > -1) {
+                        person.rootCollection = p.rootCollection;
+                        person.updateDisplayName = p.updateDisplayName;
+                        updatePersonCollection(person);
+                        mMatches.insert(uid, person);
+                    } else {
+                        kWarning() << "That should not happen: we found two times persons with the same uid ("<< uid << "), but differnet name:" << p.name << "vs" << person.name;
+                    }
+                }
+            } else {            //New person found
+                mMatches.insert(uid, person);
+                persons << person;
+            }
+        } else {
+            kWarning() << item.object.dn().toString() << ": invalid email address" << person.mail;
+        }
+    }
+    if (persons.count() > 0) {
+        emit personsFound(persons);
+    }
+}
+
+void PersonSearchJob::onLDAPSearchDone()
+{
+    mLdapSearchDone = true;
+    if (mCollectionSearchDone) {
+        emitResult();
+    }
+}
+
+void PersonSearchJob::onCollectionsReceived(const Akonadi::Collection::List &list)
+{
+    QList<Person> persons;
+    Q_FOREACH(const Akonadi::Collection &col, list) {
+        Person person;
+        const QString &uid = col.name();
+        const CollectionIdentificationAttribute *const attr = col.attribute<CollectionIdentificationAttribute>();
+        const Akonadi::EntityDisplayAttribute *const displayname = col.attribute<Akonadi::EntityDisplayAttribute>();
+        person.rootCollection = col.id();
+        person.uid = uid;
+        if (attr) {
+            person.ou = QString::fromUtf8(attr->ou());
+            person.mail = QString::fromUtf8(attr->mail());
+            person.name = QString::fromUtf8(attr->identifier());
+            if (!displayname || displayname->displayName().isEmpty() || displayname->displayName() == person.name) {
+                person.updateDisplayName = true;
+            }
+        } else {
+            person.name = col.displayName();
+            if (!displayname || displayname->displayName().isEmpty()) {
+                person.updateDisplayName = true;
+            }
+        }
+        if (mMatches.contains(uid)) {
+            Person p = mMatches.value(uid);
+            if (p.rootCollection > -1) {
+                //two collection with the same uid ?! 
+                kWarning() << "Two collections match to same person" << p.rootCollection << person.rootCollection;
+            } else if (p.mail != person.mail) {
+                p.rootCollection = person.rootCollection;
+                p.updateDisplayName = person.updateDisplayName;
+                updatePersonCollection(p);
+            } else {
+                mMatches.insert(uid, person);
+                emit personUpdate(person);
+            }
+        } else {
+            mMatches.insert(uid, person);
+            persons << person;
+        }
+    }
+
+    if (persons.count() > 0) {
+        emit personsFound(persons);
+    }
+}
+
+void PersonSearchJob::updatePersonCollection(const Person &person)
+{
+    Akonadi::Collection c(person.rootCollection);
+    CollectionIdentificationAttribute *identification = c.attribute<CollectionIdentificationAttribute>(Akonadi::Entity::AddIfMissing);
+
+    if (person.updateDisplayName) {
+        Akonadi::EntityDisplayAttribute *displayname  = c.attribute<Akonadi::EntityDisplayAttribute >(Akonadi::Entity::AddIfMissing);
+        displayname->setDisplayName(person.name);
+    }
+
+    //identification->setIdentifier("Other Users/" + person.uid);
+    identification->setIdentifier(person.name.toUtf8());
+    identification->setName(person.name.toUtf8());
+    identification->setCollectionNamespace("usertoplevel");
+    identification->setMail(person.mail.toUtf8());
+    identification->setOu(person.ou.toUtf8());
+
+    Akonadi::CollectionModifyJob *job = new Akonadi::CollectionModifyJob( c, this );
+    connect(job, SIGNAL(result(KJob*)), this, SLOT(modifyResult(KJob*)));
+}
+
+void PersonSearchJob::onCollectionsFetched(KJob *job)
+{
+    if (job->error()) {
+        kWarning() << job->errorString();
+    }
+    mCollectionSearchDone = true;
+    if (mLdapSearchDone) {
+        emitResult();
+    }
+}
+
+QList<Person> PersonSearchJob::matches() const
+{
+    return mMatches.values();
+}
+
+void PersonSearchJob::modifyResult(KJob *job)
+{
+    if (job->error()) {
+        kWarning() << job->errorString();
+        return;
+    }
+
+    const Akonadi::CollectionModifyJob *modifyJob = static_cast<Akonadi::CollectionModifyJob*>(job);
+    const Akonadi::Collection &col = modifyJob->collection();
+
+    const CollectionIdentificationAttribute *const attr = col.attribute<CollectionIdentificationAttribute>();
+    const Akonadi::EntityDisplayAttribute *const displayname = col.attribute<Akonadi::EntityDisplayAttribute>();
+    const QString &uid = col.name();
+    Person &person = mMatches[col.name()];
+    person.rootCollection = col.id();
+    person.uid = uid;
+    if (attr) {
+        person.ou = QString::fromUtf8(attr->ou());
+        person.mail = QString::fromUtf8(attr->mail());
+        person.name = QString::fromUtf8(attr->identifier());
+        if (!displayname || displayname->displayName().isEmpty() || displayname->displayName() == person.name) {
+            person.updateDisplayName = true;
+        }
+    }
+    kDebug() << "modified person to" << person.uid << person.name << person.rootCollection;
+
+    mMatches.insert(person.uid, person);
+    emit personUpdate(person);
+}
diff --git a/korganizer/views/collectionview/personsearchjob.h b/korganizer/views/collectionview/personsearchjob.h
new file mode 100644
index 0000000..43d8350
--- /dev/null
+++ b/korganizer/views/collectionview/personsearchjob.h
@@ -0,0 +1,65 @@
+/*
+  Copyright (C) 2014 Christian Mollekopf <mollekopf at kolabsys.com>
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  This program 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 General Public License for more details.
+
+  You should have received a copy of the GNU General Public License along
+  with this program; if not, write to the Free Software Foundation, Inc.,
+  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+  As a special exception, permission is given to link this program
+  with any edition of Qt, and distribute the resulting executable,
+  without including the source code for Qt in the source distribution.
+*/
+
+#ifndef KORG_PERSONSEARCHJOB_H
+#define KORG_PERSONSEARCHJOB_H
+
+#include <KJob>
+#include <Akonadi/Collection>
+#include <libkdepim/ldap/ldapclientsearch.h>
+#include "person.h"
+
+class PersonSearchJob : public KJob
+{
+    Q_OBJECT
+public:
+    explicit PersonSearchJob(const QString &searchString, QObject* parent = 0);
+    virtual ~PersonSearchJob();
+
+    virtual void start();
+
+    QList<Person> matches() const;
+
+Q_SIGNALS:
+    void personsFound(const QList<Person> &persons);
+    void personUpdate(const Person &person);
+
+public Q_SLOTS:
+    bool kill(KillVerbosity verbosity=Quietly);
+
+private Q_SLOTS:
+    void onCollectionsReceived(const Akonadi::Collection::List &);
+    void onCollectionsFetched(KJob *);
+    void onLDAPSearchData(const QList<KLDAP::LdapResultObject> &);
+    void onLDAPSearchDone();
+    void updatePersonCollection(const Person &person);
+    void modifyResult(KJob *job);
+
+private:
+    QString mSearchString;
+    QHash<QString, Person> mMatches;
+    KLDAP::LdapClientSearch mLdapSearch;
+    bool mCollectionSearchDone;
+    bool mLdapSearchDone;
+};
+
+#endif


commit 3c161aff18e0ecb193f8e88a01633ac2231b041e
Author: Sandro Knauß <knauss at kolabsys.com>
Date:   Tue Dec 2 13:05:12 2014 +0100

    Add calendar permamently
    
    If a collection is going from referenced -> enabled an updateNode is
    triggerd, but nodes are not nessesary are available. The the "old" days
    we used checkSourceIndex, also for dataChanged. This patch addes the
    implicit creatation of unknown nodes.
    
    (better debug messages)
    
    KOLAB: #4010

diff --git a/korganizer/views/collectionview/reparentingmodel.cpp b/korganizer/views/collectionview/reparentingmodel.cpp
index 5a3e3fe..8490e1f 100644
--- a/korganizer/views/collectionview/reparentingmodel.cpp
+++ b/korganizer/views/collectionview/reparentingmodel.cpp
@@ -297,7 +297,8 @@ void ReparentingModel::updateNode(const ReparentingModel::Node::Ptr &node)
         }
     }
 
-    kWarning() << "no node to update"; 
+    kWarning() << objectName() << "no node to update, create new node";
+    addNode(node);
 }
 
 void ReparentingModel::removeNode(const ReparentingModel::Node& node)
@@ -451,7 +452,7 @@ void ReparentingModel::removeDuplicates(const QModelIndex &sourceIndex)
             if (proxyNode->isDuplicateOf(descendant)) {
                 //Removenode from proxy
                 if (!proxyNode->parent) {
-                    kWarning() << "Found proxy that is already not part of the model " << proxyNode->data(Qt::DisplayRole).toString();
+                    kWarning() <<  objectName() << "Found proxy that is already not part of the model " << proxyNode->data(Qt::DisplayRole).toString();
                     continue;
                 }
                 const int targetRow = proxyNode->row();
@@ -466,7 +467,7 @@ void ReparentingModel::removeDuplicates(const QModelIndex &sourceIndex)
 
 void ReparentingModel::onSourceRowsInserted(QModelIndex parent, int start, int end)
 {
-    kDebug() << parent << start << end;
+    // kDebug() << objectName() << parent << start << end;
     for (int row = start; row <= end; row++) {
         QModelIndex sourceIndex = sourceModel()->index(row, 0, parent);
         Q_ASSERT(sourceIndex.isValid());
@@ -512,7 +513,7 @@ void ReparentingModel::onSourceRowsInserted(QModelIndex parent, int start, int e
 
 void ReparentingModel::onSourceRowsAboutToBeRemoved(QModelIndex parent, int start, int end)
 {
-    // kDebug() << parent << start << end;
+    // kDebug() << objectName() << parent << start << end;
     //we remove in reverse order as otherwise the indexes in parentNode->children wouldn't be correct
     for (int row = end; row >= start; row--) {
         QModelIndex sourceIndex = sourceModel()->index(row, 0, parent);
@@ -596,6 +597,7 @@ void ReparentingModel::onSourceLayoutChanged()
 
 void ReparentingModel::onSourceDataChanged(QModelIndex begin, QModelIndex end)
 {
+    // kDebug() << objectName() << begin << end;
     for (int row = begin.row(); row <= end.row(); row++) {
         mNodeManager->updateSourceIndex(sourceModel()->index(row, begin.column(), begin.parent()));
     }
@@ -663,6 +665,7 @@ ReparentingModel::Node *ReparentingModel::getSourceNode(const QModelIndex &sourc
             return n;
         }
     }
+    // kDebug() << objectName() <<  "no node found for " << sourceIndex;
     return 0;
 }
 


commit 1d7dd390ec45488bbf18571bee28fb03e7723971
Author: Sandro Knauß <knauss at kolabsys.com>
Date:   Tue Dec 2 13:02:29 2014 +0100

    Other collection get enabled when adding collection from search
    
    NewCalendarChecker triggers dataChanges, before other models have the
    possibility to add the new calendars in there dataset.
    
    KOLAB: #3990

diff --git a/korganizer/akonadicollectionview.cpp b/korganizer/akonadicollectionview.cpp
index 5d27815..18a16d6 100644
--- a/korganizer/akonadicollectionview.cpp
+++ b/korganizer/akonadicollectionview.cpp
@@ -92,6 +92,7 @@ public:
         mCheckableProxy(model)
     {
         connect(model, SIGNAL(rowsInserted(QModelIndex, int, int)), this, SLOT(onSourceRowsInserted(QModelIndex, int, int)));
+        qRegisterMetaType<QPersistentModelIndex>("QPersistentModelIndex");
     }
 
 private slots:
@@ -103,12 +104,16 @@ private slots:
             return;
         }
         for (int i = start; i <= end; i++) {
-            kDebug() << "checking " << mCheckableProxy->index(i, 0, parent).data().toString();
+            kDebug() << "checking " << i << parent << mCheckableProxy->index(i, 0, parent).data().toString();
             const QModelIndex index = mCheckableProxy->index(i, 0, parent);
-            mCheckableProxy->setData(index, Qt::Checked, Qt::CheckStateRole);
-            if (mCheckableProxy->hasChildren(index)) {
-                onSourceRowsInserted(index, 0, mCheckableProxy->rowCount(index) - 1);
-            }
+            QMetaObject::invokeMethod(this, "setCheckState", Qt::QueuedConnection, QGenericReturnArgument(), Q_ARG(QPersistentModelIndex, index));
+        }
+    }
+    void setCheckState(const QPersistentModelIndex &index)
+    {
+        mCheckableProxy->setData(index, Qt::Checked, Qt::CheckStateRole);
+        if (mCheckableProxy->hasChildren(index)) {
+            onSourceRowsInserted(index, 0, mCheckableProxy->rowCount(index) - 1);
         }
     }
 
@@ -535,6 +540,7 @@ AkonadiCollectionView::AkonadiCollectionView( CalendarView *view, bool hasContex
 
   SortProxyModel *sortProxy = new SortProxyModel( this );
   sortProxy->setSourceModel(collectionFilter);
+  sortProxy->setObjectName(QLatin1String("sortproxy"));
 
   mCollectionView = new Akonadi::EntityTreeView( this );
   mCollectionView->header()->hide();
@@ -1043,7 +1049,6 @@ void AkonadiCollectionView::onAction(const QModelIndex &index, int a)
         case StyledCalendarDelegate::RemoveFromList: {
             const QVariant var = index.data(PersonRole);
             if (var.isValid()) {
-                kDebug() << "person";
                 mController->removePerson(var.value<Person>());
             } else {
                 const Akonadi::Collection col = CalendarSupport::collectionFromIndex(index);




More information about the commits mailing list