Branch 'dev/invitations' - akonadi/calendar

Sandro Knauß knauss at kolabsys.com
Thu Sep 4 15:26:22 CEST 2014


 akonadi/calendar/CMakeLists.txt                      |    1 
 akonadi/calendar/calfilterpartstatusproxymodel_p.cpp |  111 +++++++++++++++++++
 akonadi/calendar/calfilterpartstatusproxymodel_p.h   |   52 ++++++++
 akonadi/calendar/etmcalendar.cpp                     |   14 ++
 akonadi/calendar/etmcalendar_p.h                     |    3 
 akonadi/calendar/tests/etmcalendartest.cpp           |   70 +++++++++++
 akonadi/calendar/tests/etmcalendartest.h             |    2 
 7 files changed, 252 insertions(+), 1 deletion(-)

New commits:
commit ad3da17925335acf9b5bc68a5188bc21af5a0bb2
Author: Sandro Knauß <knauss at kolabsys.com>
Date:   Thu Sep 4 15:22:02 2014 +0200

    Filter out new invitatins and declined events from etmcalendar.
    
    invitations and declined events are available over a search collection,
    so we don't want to show them in normal calendars.
    
    Kolab: #3549

diff --git a/akonadi/calendar/CMakeLists.txt b/akonadi/calendar/CMakeLists.txt
index 951c700..3e68aa9 100644
--- a/akonadi/calendar/CMakeLists.txt
+++ b/akonadi/calendar/CMakeLists.txt
@@ -22,6 +22,7 @@ set(akonadicalendar_LIB_SRC
   calendarclipboard.cpp
   calendarmodel.cpp
   calfilterproxymodel_p.cpp
+  calfilterpartstatusproxymodel_p.cpp
   etmcalendar.cpp
   history.cpp
   history_p.cpp
diff --git a/akonadi/calendar/calfilterpartstatusproxymodel_p.cpp b/akonadi/calendar/calfilterpartstatusproxymodel_p.cpp
new file mode 100644
index 0000000..a1f90ea
--- /dev/null
+++ b/akonadi/calendar/calfilterpartstatusproxymodel_p.cpp
@@ -0,0 +1,111 @@
+/*
+  Copyright (c) 2014 Sandro Knauß <knauss at kolabsys.com>
+
+  This library is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Library General Public License as published by
+  the Free Software Foundation; either version 2 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 Library General Public
+  License for more details.
+
+  You should have received a copy of the GNU Library General Public License
+  along with this library; see the file COPYING.LIB.  If not, write to the
+  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+  02110-1301, USA.
+*/
+
+#include "calfilterpartstatusproxymodel_p.h"
+#include "utils_p.h"
+
+#include <akonadi/collection.h>
+#include <akonadi/item.h>
+#include <akonadi/entitytreemodel.h>
+
+#include <kcalcore/incidence.h>
+#include <kcalcore/attendee.h>
+
+using namespace Akonadi;
+
+class CalFilterPartStatusProxyModel::Private
+{
+public:
+    explicit Private()
+        : mFilterVirtual(false)
+    {
+    }
+    bool mFilterVirtual;
+    QList<KCalCore::Attendee::PartStat> mBlockedStatusList;
+};
+
+
+CalFilterPartStatusProxyModel::CalFilterPartStatusProxyModel(QObject *parent)
+    : QSortFilterProxyModel(parent)
+    , d(new Private())
+{
+}
+
+CalFilterPartStatusProxyModel::~CalFilterPartStatusProxyModel()
+{
+    delete d;
+}
+
+const QList<KCalCore::Attendee::PartStat> &CalFilterPartStatusProxyModel::blockedStatusList() const
+{
+    return d->mBlockedStatusList;
+}
+
+void CalFilterPartStatusProxyModel::setBlockedStatusList(const QList<KCalCore::Attendee::PartStat> &blockStatusList)
+{
+    d->mBlockedStatusList = blockStatusList;
+}
+
+
+bool CalFilterPartStatusProxyModel::filterVirtual() const
+{
+    return d->mFilterVirtual;
+}
+
+void CalFilterPartStatusProxyModel::setFilterVirtual(bool filterVirtual)
+{
+    d->mFilterVirtual = filterVirtual;
+}
+
+
+bool CalFilterPartStatusProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
+{
+    const QModelIndex idx = sourceModel()->index(source_row, 0, source_parent);
+    if (!idx.isValid())
+        return false;
+
+    const Akonadi::Item item = idx.data(Akonadi::EntityTreeModel::ItemRole).value<Akonadi::Item>();
+    if (!item.isValid() || !item.hasPayload<KCalCore::Incidence::Ptr>()) {
+        return false;
+    }
+
+    const KCalCore::Incidence::Ptr incidence = item.payload<KCalCore::Incidence::Ptr>();
+    if (!incidence) {
+        return false;
+    }
+
+    // Incidences from virtual collections are always ok
+    const Akonadi::Collection col = idx.data(Akonadi::EntityTreeModel::ParentCollectionRole).value<Akonadi::Collection>();
+    if (!d->mFilterVirtual && col.isVirtual()) {
+        return true;
+    }
+
+    foreach (const KCalCore::Attendee::Ptr &attendee, incidence->attendees()) {
+        if ( CalendarUtils::thatIsMe(attendee->email()) ) {
+            if ( d->mBlockedStatusList.contains(attendee->status()) ) {
+                return false;
+            } else {
+                return true;
+            }
+        }
+    }
+
+    // We are not attendee, so we accept the incidence
+    return true;
+}
diff --git a/akonadi/calendar/calfilterpartstatusproxymodel_p.h b/akonadi/calendar/calfilterpartstatusproxymodel_p.h
new file mode 100644
index 0000000..9e34bce
--- /dev/null
+++ b/akonadi/calendar/calfilterpartstatusproxymodel_p.h
@@ -0,0 +1,52 @@
+/*
+  Copyright (c) 2014 Sandro Knauß <knauss at kolabsys.com>
+
+  This library is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Library General Public License as published by
+  the Free Software Foundation; either version 2 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 Library General Public
+  License for more details.
+
+  You should have received a copy of the GNU Library General Public License
+  along with this library; see the file COPYING.LIB.  If not, write to the
+  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+  02110-1301, USA.
+*/
+
+#ifndef AKONADI_CALFILTERPARTSTATUSPROXYMODEL_P_H
+#define AKONADI_CALFILTERPARTSTATUSPROXYMODEL_P_H
+
+#include <QSortFilterProxyModel>
+#include <kcalcore/attendee.h>
+
+namespace Akonadi {
+
+class CalFilterPartStatusProxyModel : public QSortFilterProxyModel
+{
+    Q_OBJECT
+public:
+    explicit CalFilterPartStatusProxyModel(QObject *parent=0);
+    ~CalFilterPartStatusProxyModel();
+
+    void setFilterVirtual(bool filterVirtual);
+    bool filterVirtual() const;
+
+    void setBlockedStatusList(const QList<KCalCore::Attendee::PartStat> &blockStatusList);
+    const QList<KCalCore::Attendee::PartStat> &blockedStatusList() const;
+
+protected:
+    /* reimp */
+    bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const;
+
+private:
+    class Private;
+    Private *const d;
+};
+
+}
+
+#endif
diff --git a/akonadi/calendar/etmcalendar.cpp b/akonadi/calendar/etmcalendar.cpp
index 194091c..ff051c3 100644
--- a/akonadi/calendar/etmcalendar.cpp
+++ b/akonadi/calendar/etmcalendar.cpp
@@ -23,6 +23,7 @@
 #include "calendarmodel_p.h"
 #include "kcolumnfilterproxymodel_p.h"
 #include "calfilterproxymodel_p.h"
+#include "calfilterpartstatusproxymodel_p.h"
 #include "utils_p.h"
 
 #include <akonadi/item.h>
@@ -66,6 +67,7 @@ ETMCalendarPrivate::ETMCalendarPrivate(ETMCalendar *qq) : CalendarBasePrivate(qq
     , mCheckableProxyModel(0)
     , mCollectionProxyModel(0)
     , mCalFilterProxyModel(0)
+    , mCalFilterPartStatusProxyModel(0)
     , mSelectionProxy(0)
     , mCollectionFilteringEnabled(true)
     , q(qq)
@@ -185,8 +187,18 @@ void ETMCalendarPrivate::setupFilteredETM()
     mCalFilterProxyModel->setSourceModel(mSelectionProxy);
     mCalFilterProxyModel->setObjectName("KCalCore::CalFilter filtering");
 
+    mCalFilterPartStatusProxyModel = new CalFilterPartStatusProxyModel(this);
+    mCalFilterPartStatusProxyModel->setFilterVirtual(false);
+    QList<KCalCore::Attendee::PartStat> blockedStatusList;
+    blockedStatusList << KCalCore::Attendee::NeedsAction;
+    blockedStatusList << KCalCore::Attendee::Declined;
+    mCalFilterPartStatusProxyModel->setDynamicSortFilter(true);
+    mCalFilterPartStatusProxyModel->setBlockedStatusList(blockedStatusList);
+    mCalFilterPartStatusProxyModel->setSourceModel(mCalFilterProxyModel);
+    mCalFilterPartStatusProxyModel->setObjectName("PartStatus filtering");
+
     mFilteredETM = new Akonadi::EntityMimeTypeFilterModel(this);
-    mFilteredETM->setSourceModel(mCalFilterProxyModel);
+    mFilteredETM->setSourceModel(mCalFilterPartStatusProxyModel);
     mFilteredETM->setHeaderGroup(Akonadi::EntityTreeModel::ItemListHeaders);
     mFilteredETM->setSortRole(CalendarModel::SortRole);
     mFilteredETM->setObjectName("Show headers");
diff --git a/akonadi/calendar/etmcalendar_p.h b/akonadi/calendar/etmcalendar_p.h
index ec57722..c998c01 100644
--- a/akonadi/calendar/etmcalendar_p.h
+++ b/akonadi/calendar/etmcalendar_p.h
@@ -41,6 +41,7 @@ class EntityTreeModel;
 class EntityMimeTypeFilterModel;
 class CollectionFilterProxyModel;
 class CalFilterProxyModel;
+class CalFilterPartStatusProxyModel;
 
 static bool isStructuralCollection(const Akonadi::Collection &collection)
 {
@@ -133,6 +134,8 @@ public:
     CheckableProxyModel *mCheckableProxyModel;
     Akonadi::CollectionFilterProxyModel *mCollectionProxyModel;
     Akonadi::CalFilterProxyModel *mCalFilterProxyModel; //KCalCore::CalFilter stuff
+    //filter out all invitations and declined events
+    Akonadi::CalFilterPartStatusProxyModel *mCalFilterPartStatusProxyModel;
     KSelectionProxyModel *mSelectionProxy;
     bool mCollectionFilteringEnabled;
     QSet<Akonadi::Collection::Id> mPopulatedCollectionIds;
diff --git a/akonadi/calendar/tests/etmcalendartest.cpp b/akonadi/calendar/tests/etmcalendartest.cpp
index f093363..c45684e 100644
--- a/akonadi/calendar/tests/etmcalendartest.cpp
+++ b/akonadi/calendar/tests/etmcalendartest.cpp
@@ -30,6 +30,7 @@
 #include <akonadi/itemdeletejob.h>
 #include <akonadi/itemmodifyjob.h>
 #include <KCheckableProxyModel>
+#include <KEMailSettings>
 
 #include <QTestEventLoop>
 #include <QSignalSpy>
@@ -532,6 +533,75 @@ void ETMCalendarTest::testShareETM()
     QVERIFY(calendar2->incidences().isEmpty());
 }
 
+void ETMCalendarTest::testFilterInvitations()
+{
+    int anz = mCalendar->model()->rowCount();
+    QString uid = QLatin1String("invite-01");
+    Item item;
+    Incidence::Ptr incidence = Incidence::Ptr(new Event());
+    KEMailSettings emailSettings;
+    KCalCore::Attendee::Ptr me(new KCalCore::Attendee(QLatin1String("me"), emailSettings.getSetting(KEMailSettings::EmailAddress)));
+
+    item.setMimeType(Event::eventMimeType());
+    incidence->setUid(uid);
+    incidence->setDtStart(KDateTime::currentDateTime(KDateTime::UTC));
+    incidence->setSummary(QLatin1String("summary"));
+
+    me->setStatus(KCalCore::Attendee::NeedsAction);
+    incidence->addAttendee(me);
+
+    item.setPayload<KCalCore::Incidence::Ptr>(incidence);
+    ItemCreateJob *job = new ItemCreateJob(item, mCollection, this);
+    AKVERIFYEXEC(job);
+    waitForIt();
+    // incidence do not pop up in model
+    QCOMPARE(mCalendar->model()->rowCount(), anz);
+
+    kDebug() << "first invite ended";
+}
+
+void ETMCalendarTest::testFilterInvitationsChanged()
+{
+    int anz = mCalendar->model()->rowCount();
+
+    KEMailSettings emailSettings;
+    KCalCore::Attendee::Ptr me(new KCalCore::Attendee(QLatin1String("me"), emailSettings.getSetting(KEMailSettings::EmailAddress)));
+
+    QString uid = QLatin1String("invite-02");
+    mIncidencesToAdd = 1;
+    createIncidence(uid);
+    waitForIt();
+    QCOMPARE(mCalendar->model()->rowCount(), anz+1);
+
+    Incidence::Ptr incidence = mCalendar->incidence(uid);
+    Item item = mCalendar->item(uid);
+
+    incidence->addAttendee(me);
+    incidence->setRevision(1);
+    item.setPayload<KCalCore::Incidence::Ptr>(incidence);
+
+    mIncidencesToDelete = 1;
+    ItemModifyJob *modifyJob = new ItemModifyJob(item,  this);
+    AKVERIFYEXEC(modifyJob);
+    waitForIt();
+    QCOMPARE(mCalendar->model()->rowCount(), anz);
+
+    me->setStatus(KCalCore::Attendee::Accepted);
+    incidence->clearAttendees();
+    incidence->addAttendee(me);
+
+    incidence->setRevision(2);
+
+    item.setPayload<KCalCore::Incidence::Ptr>(incidence);
+    item.setRevision(2);
+    mIncidencesToAdd = 1;
+    modifyJob = new ItemModifyJob(item,  this);
+    AKVERIFYEXEC(modifyJob);
+    waitForIt();
+    QCOMPARE(mCalendar->model()->rowCount(), anz+1);
+}
+
+
 void ETMCalendarTest::waitForIt()
 {
     QTestEventLoop::instance().enterLoop(10);
diff --git a/akonadi/calendar/tests/etmcalendartest.h b/akonadi/calendar/tests/etmcalendartest.h
index 1d219e7..22f3e38 100644
--- a/akonadi/calendar/tests/etmcalendartest.h
+++ b/akonadi/calendar/tests/etmcalendartest.h
@@ -50,6 +50,8 @@ private Q_SLOTS:
     void testUidChange();
     void testItem(); // tests item()
     void testShareETM();
+    void testFilterInvitations();
+    void testFilterInvitationsChanged();
 
 public Q_SLOTS:
     void calendarIncidenceAdded(const KCalCore::Incidence::Ptr &incidence);   /**Q_DECL_OVERRIDE*/




More information about the commits mailing list