Branch 'kolab/integration/4.13.0' - 10 commits - calendarsupport/utils.cpp calendarsupport/utils.h calendarviews/agenda calendarviews/CMakeLists.txt calendarviews/helper.cpp calendarviews/month incidenceeditor-ng/attendeetablemodel.cpp incidenceeditor-ng/attendeetablemodel.h incidenceeditor-ng/CMakeLists.txt incidenceeditor-ng/editoritemmanager.cpp incidenceeditor-ng/freebusyitemmodel.cpp incidenceeditor-ng/incidenceattendee.cpp incidenceeditor-ng/incidenceattendee.h incidenceeditor-ng/incidencedialog.cpp incidenceeditor-ng/incidenceresource.cpp incidenceeditor-ng/incidenceresource.h incidenceeditor-ng/resourcemanagement.cpp incidenceeditor-ng/resourcemanagement.h korganizer/calendarview.cpp korganizer/calendarview.h plugins/messageviewer

Sandro Knauß knauss at kolabsys.com
Thu Sep 25 00:04:58 CEST 2014


 calendarsupport/utils.cpp                                 |   49 ++
 calendarsupport/utils.h                                   |   30 +
 calendarviews/CMakeLists.txt                              |    1 
 calendarviews/agenda/agenda.cpp                           |  124 ++----
 calendarviews/agenda/agenda.h                             |   31 -
 calendarviews/agenda/agendaitem.cpp                       |  103 ++---
 calendarviews/agenda/agendaitem.h                         |   13 
 calendarviews/agenda/agendaview.cpp                       |  245 +++++++-----
 calendarviews/agenda/agendaview.h                         |   14 
 calendarviews/agenda/viewcalendar.cpp                     |  169 ++++++++
 calendarviews/agenda/viewcalendar.h                       |  103 +++++
 calendarviews/helper.cpp                                  |    2 
 calendarviews/month/monthitem.cpp                         |   13 
 incidenceeditor-ng/CMakeLists.txt                         |    4 
 incidenceeditor-ng/attendeetablemodel.cpp                 |   55 +-
 incidenceeditor-ng/attendeetablemodel.h                   |    9 
 incidenceeditor-ng/editoritemmanager.cpp                  |    7 
 incidenceeditor-ng/freebusyitemmodel.cpp                  |   38 +
 incidenceeditor-ng/incidenceattendee.cpp                  |   99 ++++
 incidenceeditor-ng/incidenceattendee.h                    |    5 
 incidenceeditor-ng/incidencedialog.cpp                    |    6 
 incidenceeditor-ng/incidenceresource.cpp                  |   38 +
 incidenceeditor-ng/incidenceresource.h                    |   11 
 incidenceeditor-ng/resourcemanagement.cpp                 |  283 +++++++-------
 incidenceeditor-ng/resourcemanagement.h                   |   28 +
 korganizer/calendarview.cpp                               |  114 +++++
 korganizer/calendarview.h                                 |   10 
 plugins/messageviewer/bodypartformatter/text_calendar.cpp |   19 
 28 files changed, 1185 insertions(+), 438 deletions(-)

New commits:
commit 9e9555b36d4ff237fd94fc15cafd4ffaa6ad6382
Author: Sandro Knauß <knauss at kolabsys.com>
Date:   Wed Sep 10 11:07:59 2014 +0200

    Resourcemanagement: cleanup and AgenaView
    
    * add AgendaView for resources
    * show availabe status for attendees
    * Ok button of resourcemanagement book resource
    * Change of attendeestatus triggers update isDirty
    
    Kolab: 3581
    Kolab: 3583
    Kolab: 3582
    Kolab: 3397

diff --git a/incidenceeditor-ng/CMakeLists.txt b/incidenceeditor-ng/CMakeLists.txt
index fcfa555..eb53e5b 100644
--- a/incidenceeditor-ng/CMakeLists.txt
+++ b/incidenceeditor-ng/CMakeLists.txt
@@ -7,6 +7,7 @@ include_directories(
   ${CMAKE_CURRENT_BINARY_DIR}
   ${CMAKE_SOURCE_DIR}/calendarsupport
   ${CMAKE_BINARY_DIR}/calendarsupport
+  ${CMAKE_SOURCE_DIR}/calendarviews
   ${CMAKE_SOURCE_DIR}/libkdepim
   ${CMAKE_BINARY_DIR}/incidenceeditor-ng
   ${Boost_INCLUDE_DIR}
@@ -114,6 +115,7 @@ target_link_libraries(incidenceeditorsng
   kdepim
   kdepimdbusinterfaces # For UriHandler
   calendarsupport      # For KCalPrefs
+  eventviews
   kdgantt2             # For FreeBusy Editor
 )
 
@@ -156,6 +158,7 @@ install(TARGETS incidenceeditorsng ${INSTALL_TARGETS_DEFAULT_ARGS})
     kdepim               # For KPIM::K{Date|Time}Edit
     calendarsupport      # For KCalPrefs
     kdepimdbusinterfaces # For UriHandler
+    eventviews
     kdgantt2
     ${KDEPIMLIBS_KCALUTILS_LIBS}
     ${KDEPIMLIBS_KCALCORE_LIBS}
@@ -186,6 +189,7 @@ target_link_libraries(kincidenceeditor
   ${KDEPIMLIBS_KCALUTILS_LIBS}
   incidenceeditorsng
   calendarsupport
+  eventviews
   kdepimdbusinterfaces
 )
 
diff --git a/incidenceeditor-ng/attendeetablemodel.cpp b/incidenceeditor-ng/attendeetablemodel.cpp
index 0fb3074..022f98a 100644
--- a/incidenceeditor-ng/attendeetablemodel.cpp
+++ b/incidenceeditor-ng/attendeetablemodel.cpp
@@ -47,33 +47,47 @@ QVariant AttendeeTableModel::data(const QModelIndex &index, int role) const
         return QVariant();
     }
 
+    KCalCore::Attendee::Ptr attendee = attendeeList[index.row()];
     if (role == Qt::DisplayRole || role == Qt::EditRole) {
         switch (index.column()) {
         case Role:
-            return attendeeList[index.row()]->role();
+            return attendee->role();
         case FullName:
-            return attendeeList[index.row()]->fullName();
-        case Available:
+            return attendee->fullName();
+        case Available: {
+            AvailableStatus available = attendeeAvailable[attendee];
             if (role == Qt::DisplayRole) {
-                return i18n("Unknown");
+                switch (available) {
+                case Free:
+                    return i18n("Free");
+                case Busy:
+                    return i18n("Busy");
+                case Accepted:
+                    return i18n("Accepted");
+                case Unkown:
+                    return i18n("Unknown");
+                default:
+                    return i18n("Unknown");
+                }
             } else {
-                return 0;  //attendeeList.at(index.row()).available;
+                return available;
             }
+        }
         case Status:
-            return attendeeList[index.row()]->status();
+            return attendee->status();
         case CuType:
-            return attendeeList[index.row()]->cuType();
+            return attendee->cuType();
         case Response:
-            return attendeeList[index.row()]->RSVP();
+            return attendee->RSVP();
         case Name:
-            return attendeeList[index.row()]->name();
+            return attendee->name();
         case Email:
-            return attendeeList[index.row()]->email();
+            return attendee->email();
         }
 
     }
     if (role ==  AttendeeRole) {
-        return QVariant::fromValue(attendeeList[index.row()]);
+        return QVariant::fromValue(attendee);
     }
     return QVariant();
 }
@@ -82,35 +96,36 @@ bool AttendeeTableModel::setData(const QModelIndex& index, const QVariant& value
 {
     QString email, name;
     if (index.isValid() && role == Qt::EditRole) {
+        KCalCore::Attendee::Ptr attendee = attendeeList[index.row()];
         switch (index.column()) {
         case Role:
-            attendeeList[index.row()]->setRole(static_cast<KCalCore::Attendee::Role>(value.toInt()));
+            attendee->setRole(static_cast<KCalCore::Attendee::Role>(value.toInt()));
             break;
         case FullName:
             if (mRemoveEmptyLines && value.toString().trimmed().isEmpty()) {
                 // Do not remove last empty line if mKeepEmpty==true (only works if initaly there is only one empty line)
-                if (!mKeepEmpty || !(attendeeList[index.row()]->name().isEmpty() && attendeeList[index.row()]->email().isEmpty())) {
+                if (!mKeepEmpty || !(attendee->name().isEmpty() && attendee->email().isEmpty())) {
                     removeRows(index.row(), 1);
                     return true;
                 }
             }
             KPIMUtils::extractEmailAddressAndName(value.toString(), email, name);
-            attendeeList[index.row()]->setName(name);
-            attendeeList[index.row()]->setEmail(email);
+            attendee->setName(name);
+            attendee->setEmail(email);
 
             addEmptyAttendee();
             break;
         case Available:
-            //attendeeList[index.row()].available = value.toBool();
+            attendeeAvailable[attendee] = static_cast<AvailableStatus>(value.toInt());
             break;
         case Status:
-            attendeeList[index.row()]->setStatus(static_cast<KCalCore::Attendee::PartStat>(value.toInt()));
+            attendee->setStatus(static_cast<KCalCore::Attendee::PartStat>(value.toInt()));
             break;
         case CuType:
-            attendeeList[index.row()]->setCuType(static_cast<KCalCore::Attendee::CuType>(value.toInt()));
+            attendee->setCuType(static_cast<KCalCore::Attendee::CuType>(value.toInt()));
             break;
         case Response:
-            attendeeList[index.row()]->setRSVP(value.toBool());
+            attendee->setRSVP(value.toBool());
             break;
         default:
             return false;
@@ -170,6 +185,7 @@ bool AttendeeTableModel::removeRows(int position, int rows, const QModelIndex &p
     beginRemoveRows(parent, position, position + rows-1);
 
     for (int row = 0; row < rows; ++row) {
+        attendeeAvailable.remove(attendeeList.at(position));
         attendeeList.remove(position);
     }
 
@@ -195,6 +211,7 @@ void AttendeeTableModel::setAttendees(const KCalCore::Attendee::List attendees)
     emit layoutAboutToBeChanged();
 
     attendeeList = attendees;
+    attendeeAvailable = QMap<KCalCore::Attendee::Ptr, AvailableStatus>();
 
     addEmptyAttendee();
 
diff --git a/incidenceeditor-ng/attendeetablemodel.h b/incidenceeditor-ng/attendeetablemodel.h
index 01599a4..9098331 100644
--- a/incidenceeditor-ng/attendeetablemodel.h
+++ b/incidenceeditor-ng/attendeetablemodel.h
@@ -51,6 +51,14 @@ public:
       Response
     };
 
+    enum AvailableStatus {
+      Unkown,
+      Free,
+      Accepted,
+      Busy,
+      Tentative
+    };
+
     AttendeeTableModel(const KCalCore::Attendee::List &resources, QObject *parent = 0);
 
     int rowCount(const QModelIndex &parent = QModelIndex()) const;
@@ -80,6 +88,7 @@ private:
     void addEmptyAttendee();
 
     KCalCore::Attendee::List attendeeList;
+    QMap<KCalCore::Attendee::Ptr, AvailableStatus> attendeeAvailable;
     bool mKeepEmpty;
     bool mRemoveEmptyLines;
 };
diff --git a/incidenceeditor-ng/freebusyitemmodel.cpp b/incidenceeditor-ng/freebusyitemmodel.cpp
index 0426ad0..62141f9 100644
--- a/incidenceeditor-ng/freebusyitemmodel.cpp
+++ b/incidenceeditor-ng/freebusyitemmodel.cpp
@@ -258,31 +258,42 @@ void FreeBusyItemModel::setFreeBusyPeriods( const QModelIndex &parent,
   ItemPrivateData *parentData = static_cast<ItemPrivateData*>( parent.internalPointer() );
   QModelIndex first = index( 0, 0, parent );
   QModelIndex last = index( parentData->childCount() - 1, 0, parent );
+  int fb_count = list.size();
+  int childCount = parentData->childCount();
 
-  if ( parentData->childCount() > 0 ) {
-    beginRemoveRows( parent, 0, parentData->childCount() - 1 );
-    for ( int i = parentData->childCount() - 1; i >= 0; --i ) {
+  if ( childCount > 0 && fb_count < childCount ) {
+      beginRemoveRows( parent, fb_count-1<0 ? 0 : fb_count-1 , childCount - 1 );
+    for ( int i = childCount - 1; i > fb_count; --i ) {
       delete parentData->removeChild( i );
     }
     endRemoveRows();
+    if (fb_count > 0) {
+        last = index(fb_count-1, 0, parent);
+        emit dataChanged(first, last);
+    }
+  } else if (fb_count > childCount) {
+      beginInsertRows( parent, childCount-1 < 0 ? 0 : childCount-1, fb_count - 1 );
+      for ( int i=childCount-1; i < fb_count; ++i ) {
+        ItemPrivateData *childData= new ItemPrivateData( parentData );
+        parentData->appendChild( childData );
+      }
+      endInsertRows();
+      if (childCount > 0) {
+          last = index(childCount-1, 0, parent);
+          emit dataChanged(first, last);
+      }
+  } else if (fb_count == childCount && fb_count > 0) {
+      emit dataChanged( first, last );
   }
-
-  int fb_count = list.size();
-  beginInsertRows( parent, 0, fb_count - 1 );
-  for ( int i=0; i < fb_count; ++i ) {
-    ItemPrivateData *childData= new ItemPrivateData( parentData );
-    parentData->appendChild( childData );
-  }
-  endInsertRows();
-  emit dataChanged( first, last );
 }
 
 void FreeBusyItemModel::clear()
 {
+  beginResetModel();
   mFreeBusyItems.clear();
   delete mRootData;
   mRootData = new ItemPrivateData( 0 );
-  reset();
+  endResetModel();
 }
 
 void IncidenceEditorNG::FreeBusyItemModel::removeRow( int row )
@@ -376,6 +387,7 @@ void FreeBusyItemModel::slotInsertFreeBusy( const KCalCore::FreeBusy::Ptr &fb,
       item->setFreeBusy( fb );
       const int row = mFreeBusyItems.indexOf( item );
       const QModelIndex parent = index( row, 0 );
+      emit dataChanged(parent, parent);
       setFreeBusyPeriods( parent, fb->fullBusyPeriods() );
     }
   }
diff --git a/incidenceeditor-ng/incidenceattendee.cpp b/incidenceeditor-ng/incidenceattendee.cpp
index cb34435..bab0c00 100644
--- a/incidenceeditor-ng/incidenceattendee.cpp
+++ b/incidenceeditor-ng/incidenceattendee.cpp
@@ -30,6 +30,7 @@
 #include "incidencedatetime.h"
 #include "schedulingdialog.h"
 #include "attendeecomboboxdelegate.h"
+#include "freebusyitemmodel.h"
 #ifdef KDEPIM_MOBILE_UI
 #include "ui_dialogmoremobile.h"
 #else
@@ -173,6 +174,12 @@ IncidenceAttendee::IncidenceAttendee( QWidget *parent, IncidenceDateTime *dateTi
   connect( mConflictResolver, SIGNAL(conflictsDetected(int)),
            this, SLOT(slotUpdateConflictLabel(int)) );
 
+  connect( mConflictResolver->model(),  SIGNAL(rowsInserted(const QModelIndex&, int, int)),
+    SLOT(slotFreeBusyAdded(const QModelIndex&, int, int)) );
+  connect(mConflictResolver->model(), SIGNAL(layoutChanged()), SLOT(updateFBStatus()));
+  connect(mConflictResolver->model(), SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&)),
+      SLOT(slotFreeBusyChanged(const QModelIndex&, const QModelIndex&)));
+
   slotUpdateConflictLabel( 0 ); //initialize label
 
   // confict resolver (should show also resources)
@@ -230,7 +237,12 @@ void IncidenceAttendee::load( const KCalCore::Incidence::Ptr &incidence )
     mUi->mOrganizerLabel->setVisible( true );
   }
 
-  mDataModel->setAttendees(incidence->attendees());
+  KCalCore::Attendee::List attendees;
+  foreach(const KCalCore::Attendee::Ptr &a, incidence->attendees()) {
+      attendees << KCalCore::Attendee::Ptr(new KCalCore::Attendee(*a));
+  }
+
+  mDataModel->setAttendees(attendees);
   slotUpdateConflictLabel(0);
 
   setActions( incidence->type() );
@@ -309,10 +321,10 @@ bool IncidenceAttendee::isDirty() const
 
   // Okay, again not the most efficient algorithm, but I'm assuming that in the
   // bulk of the use cases, the number of attendees is not much higher than 10 or so.
-  foreach(const KCalCore::Attendee::Ptr & attendee, originalList) {
+  foreach(const KCalCore::Attendee::Ptr &attendee, originalList) {
     bool found = false;
     for (int i = 0; i < newList.count(); ++i) {
-      if (newList[i] == attendee) {
+      if (*(newList[i]) == *attendee) {
         newList.remove(i);
         found = true;
         break;
@@ -566,6 +578,86 @@ void IncidenceAttendee::slotConflictResolverLayoutChanged()
     checkDirtyStatus();
 }
 
+void IncidenceAttendee::slotFreeBusyAdded(const QModelIndex &parent, int first, int last)
+{
+    // We are only interested in toplevel changes
+    if (parent.isValid()) {
+        return;
+    }
+    QAbstractItemModel *model = mConflictResolver->model();
+    for (int i = first; i <= last; i++) {
+        QModelIndex index = model->index(i, 0, parent);
+        const KCalCore::Attendee::Ptr &attendee = model->data(index, FreeBusyItemModel::AttendeeRole).value<KCalCore::Attendee::Ptr>();
+        const KCalCore::FreeBusy::Ptr &fb = model->data(index, FreeBusyItemModel::FreeBusyRole).value<KCalCore::FreeBusy::Ptr>();
+        if (attendee) {
+            updateFBStatus(attendee, fb);
+        }
+    }
+}
+
+void IncidenceAttendee::slotFreeBusyChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
+{
+    // We are only interested in toplevel changes
+    if (topLeft.parent().isValid()) {
+        return;
+    }
+    QAbstractItemModel *model = mConflictResolver->model();
+    for (int i = topLeft.row(); i <= bottomRight.row(); i++) {
+        QModelIndex index = model->index(i, 0);
+        const KCalCore::Attendee::Ptr &attendee = model->data(index, FreeBusyItemModel::AttendeeRole).value<KCalCore::Attendee::Ptr>();
+        const KCalCore::FreeBusy::Ptr &fb = model->data(index, FreeBusyItemModel::FreeBusyRole).value<KCalCore::FreeBusy::Ptr>();
+        if (attendee) {
+            updateFBStatus(attendee, fb);
+        }
+    }
+}
+
+void IncidenceAttendee::updateFBStatus()
+{
+    QAbstractItemModel *model = mConflictResolver->model();
+    for (int i = 0; i < model->rowCount(); i++) {
+        QModelIndex index = model->index(i, 0);
+        const KCalCore::Attendee::Ptr &attendee = model->data(index, FreeBusyItemModel::AttendeeRole).value<KCalCore::Attendee::Ptr>();
+        const KCalCore::FreeBusy::Ptr &fb = model->data(index, FreeBusyItemModel::FreeBusyRole).value<KCalCore::FreeBusy::Ptr>();
+        if (attendee) {
+            updateFBStatus(attendee, fb);
+        }
+    }
+}
+
+void IncidenceAttendee::updateFBStatus(const KCalCore::Attendee::Ptr &attendee, const KCalCore::FreeBusy::Ptr &fb)
+{
+    KCalCore::Attendee::List attendees = mDataModel->attendees();
+    KDateTime startTime = mDateTime->currentStartDateTime();
+    KDateTime endTime = mDateTime->currentEndDateTime();
+    QAbstractItemModel *model = mConflictResolver->model();
+    if (attendees.contains(attendee)) {
+        int row = dataModel()->attendees().indexOf(attendee);
+        QModelIndex attendeeIndex = dataModel()->index(row, AttendeeTableModel::Available);
+        if (fb) {
+            KCalCore::Period::List busyPeriods = fb->busyPeriods();
+            for ( KCalCore::Period::List::Iterator it = busyPeriods.begin(); it != busyPeriods.end(); ++it ) {
+                // periods started before and laping into the incidence (s < startTime && e >= startTime)
+                // periods starting in the time of incidende (s >= startTime && s <= endTime)
+                if ( ((*it).start() < startTime && (*it).end() > startTime) ||
+                    ((*it).start() >= startTime && (*it).start() <= endTime) ) {
+                    switch (attendee->status()) {
+                    case KCalCore::Attendee::Accepted:
+                        dataModel()->setData(attendeeIndex, AttendeeTableModel::Accepted);
+                        return;
+                    default:
+                        dataModel()->setData(attendeeIndex, AttendeeTableModel::Busy);
+                        return;
+                    }
+                }
+            }
+            dataModel()->setData(attendeeIndex, AttendeeTableModel::Free);
+        } else {
+            dataModel()->setData(attendeeIndex, AttendeeTableModel::Unkown);
+        }
+    }
+}
+
 void IncidenceAttendee::slotUpdateConflictLabel( int count )
 {
   kDebug() <<  "slotUpdateConflictLabel";
@@ -710,6 +802,7 @@ void IncidenceAttendee::slotEventDurationChanged()
 
   mConflictResolver->setEarliestDateTime( start );
   mConflictResolver->setLatestDateTime( end );
+  updateFBStatus();
 }
 
 void IncidenceAttendee::slotOrganizerChanged( const QString &newOrganizer )
diff --git a/incidenceeditor-ng/incidenceattendee.h b/incidenceeditor-ng/incidenceattendee.h
index 36af4e8..5cb2092 100644
--- a/incidenceeditor-ng/incidenceattendee.h
+++ b/incidenceeditor-ng/incidenceattendee.h
@@ -24,6 +24,7 @@
 #include "incidenceeditor-ng.h"
 #include "attendeetablemodel.h"
 
+#include <KCalCore/FreeBusy>
 
 namespace Ui {
   class EventOrTodoDesktop;
@@ -105,6 +106,10 @@ class INCIDENCEEDITORS_NG_EXPORT IncidenceAttendee : public IncidenceEditor
     void slotConflictResolverAttendeeRemoved(const QModelIndex &index, int first, int last);
     void slotConflictResolverAttendeeChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight);
     void slotConflictResolverLayoutChanged();
+    void slotFreeBusyAdded(const QModelIndex &index, int first, int last);
+    void slotFreeBusyChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight);
+    void updateFBStatus();
+    void updateFBStatus(const KCalCore::Attendee::Ptr &attendee, const KCalCore::FreeBusy::Ptr &fb);
 
     void slotGroupSubstitutionAttendeeAdded(const QModelIndex &index, int first, int last);
     void slotGroupSubstitutionAttendeeRemoved(const QModelIndex &index, int first, int last);
diff --git a/incidenceeditor-ng/incidencedialog.cpp b/incidenceeditor-ng/incidencedialog.cpp
index dc82880..440fb54 100644
--- a/incidenceeditor-ng/incidencedialog.cpp
+++ b/incidenceeditor-ng/incidencedialog.cpp
@@ -173,7 +173,7 @@ IncidenceDialogPrivate::IncidenceDialogPrivate( Akonadi::IncidenceChanger *chang
   mIeAttendee->setParent(qq);
   mEditor->combine( mIeAttendee );
 
-  mIeResource = new IncidenceResource( mIeAttendee, mUi );
+  mIeResource = new IncidenceResource( mIeAttendee, mIeDateTime, mUi );
   mEditor->combine( mIeResource );
 
   q->connect( mEditor, SIGNAL(showMessage(QString,KMessageWidget::MessageType)),
diff --git a/incidenceeditor-ng/incidenceresource.cpp b/incidenceeditor-ng/incidenceresource.cpp
index 23e229b..87eb89b 100644
--- a/incidenceeditor-ng/incidenceresource.cpp
+++ b/incidenceeditor-ng/incidenceresource.cpp
@@ -21,6 +21,7 @@
 #include "resourcemanagement.h"
 #include "resourcemodel.h"
 #include "attendeecomboboxdelegate.h"
+#include "incidencedatetime.h"
 
 #ifdef KDEPIM_MOBILE_UI
 #include "ui_dialogmoremobile.h"
@@ -57,15 +58,24 @@ public:
 };
 
 #ifdef KDEPIM_MOBILE_UI
-IncidenceResource::IncidenceResource(IncidenceAttendee* ieAttendee, Ui::EventOrTodoMore *ui)
+IncidenceResource::IncidenceResource(IncidenceAttendee* ieAttendee, IncidenceDateTime *dateTime, Ui::EventOrTodoMore *ui)
 #else
-IncidenceResource::IncidenceResource(IncidenceAttendee* ieAttendee, Ui::EventOrTodoDesktop *ui)
+IncidenceResource::IncidenceResource(IncidenceAttendee* ieAttendee, IncidenceDateTime *dateTime, Ui::EventOrTodoDesktop *ui)
 #endif
     : IncidenceEditor(0)
     , mUi(ui)
     , dataModel(ieAttendee->dataModel())
+    , mDateTime(dateTime)
+    , resourceDialog(new ResourceManagement())
 {
     setObjectName("IncidenceResource");
+    connect(resourceDialog, SIGNAL(okClicked()),
+            SLOT(dialogOkPressed()));
+
+    connect( mDateTime, SIGNAL(startDateChanged(QDate)),
+             SLOT(slotDateChanged()) );
+    connect( mDateTime, SIGNAL(endDateChanged(QDate)),
+             SLOT(slotDateChanged()) );
 
 
 #ifndef KDEPIM_MOBILE_UI
@@ -112,9 +122,15 @@ IncidenceResource::IncidenceResource(IncidenceAttendee* ieAttendee, Ui::EventOrT
 
 void IncidenceResource::load(const KCalCore::Incidence::Ptr &incidence)
 {
-  //all logic inside IncidenceAtendee (using same model)
+    slotDateChanged();
+}
+
+void IncidenceResource::slotDateChanged()
+{
+    resourceDialog->slotDateChanged(mDateTime->startDate(), mDateTime->endDate());
 }
 
+
 void IncidenceResource::save(const KCalCore::Incidence::Ptr &incidence)
 {
   //all logic inside IncidenceAtendee (using same model)
@@ -140,10 +156,22 @@ void IncidenceResource::bookResource()
 
 void IncidenceResource::findResources()
 {
-    ResourceManagement* dialog = new ResourceManagement();
-    dialog->show();
+    resourceDialog->show();
 }
 
+void IncidenceResource::dialogOkPressed()
+{
+    ResourceItem::Ptr item = resourceDialog->selectedItem();
+    QString name = item->ldapObject().value(QLatin1String("cn"));
+    QString email = item->ldapObject().value(QLatin1String("mail"));
+#ifndef KDEPIM_MOBILE_UI
+    KCalCore::Attendee::Ptr attendee(new KCalCore::Attendee(name, email));
+    attendee->setCuType(KCalCore::Attendee::Resource);
+    dataModel->insertAttendee(dataModel->rowCount(), attendee);
+#endif
+}
+
+
 void IncidenceResource::layoutChanged()
 {
 #ifndef KDEPIM_MOBILE_UI
diff --git a/incidenceeditor-ng/incidenceresource.h b/incidenceeditor-ng/incidenceresource.h
index 11ac84e..67c7208 100644
--- a/incidenceeditor-ng/incidenceresource.h
+++ b/incidenceeditor-ng/incidenceresource.h
@@ -35,15 +35,16 @@ class EventOrTodoMore;
 
 namespace IncidenceEditorNG
 {
+class ResourceManagement;
 
 class INCIDENCEEDITORS_NG_EXPORT IncidenceResource : public IncidenceEditor
 {
     Q_OBJECT
 public:
 #ifdef KDEPIM_MOBILE_UI
-    explicit IncidenceResource(IncidenceAttendee* mIeAttendee, Ui::EventOrTodoMore *ui);
+    explicit IncidenceResource(IncidenceAttendee* mIeAttendee, IncidenceDateTime *dateTime, Ui::EventOrTodoMore *ui);
 #else
-    explicit IncidenceResource(IncidenceAttendee* mIeAttendee,  Ui::EventOrTodoDesktop *ui);
+    explicit IncidenceResource(IncidenceAttendee* mIeAttendee, IncidenceDateTime *dateTime, Ui::EventOrTodoDesktop *ui);
 #endif
 
     void load(const KCalCore::Incidence::Ptr &incidence);
@@ -65,6 +66,9 @@ private slots:
     void layoutChanged();
     void updateCount();
 
+    void slotDateChanged();
+
+    void dialogOkPressed();
 private:
 #ifdef KDEPIM_MOBILE_UI
     Ui::EventOrTodoMore *mUi;
@@ -77,6 +81,9 @@ private:
 
     /** used dataModel to rely on*/
     AttendeeTableModel *dataModel;
+    IncidenceDateTime *mDateTime;
+
+    ResourceManagement* resourceDialog;
 };
 
 }
diff --git a/incidenceeditor-ng/resourcemanagement.cpp b/incidenceeditor-ng/resourcemanagement.cpp
index e9c31b0..b69d2bb 100644
--- a/incidenceeditor-ng/resourcemanagement.cpp
+++ b/incidenceeditor-ng/resourcemanagement.cpp
@@ -29,6 +29,12 @@
 
 #include "freebusyganttproxymodel.h"
 
+#include <calendarviews/agenda/agendaview.h>
+#include <calendarviews/agenda/viewcalendar.h>
+
+#include <KCalCore/Event>
+#include <KCalCore/MemoryCalendar>
+
 #include <kdgantt2/kdganttgraphicsview.h>
 #include <kdgantt2/kdganttview.h>
 #include <kdgantt2/kdganttdatetimegrid.h>
@@ -43,118 +49,72 @@
 #include <QSplitter>
 #include <QStringList>
 #include <QLabel>
-
+#include <QColor>
 
 #include <KDebug>
-
+#include <KSystemTimeZones>
 
 using namespace IncidenceEditorNG;
 
-class RowController : public KDGantt::AbstractRowController
-{
-  private:
-    static const int ROW_HEIGHT ;
-    QPointer<QAbstractItemModel> m_model;
-
-  public:
-    RowController()
-    {
-      mRowHeight = 20;
-    }
-
-    void setModel( QAbstractItemModel *model )
-    {
-      m_model = model;
-    }
-
-    /*reimp*/
-    int headerHeight() const
-    {
-      return mRowHeight + 10;
-    }
-
-    /*reimp*/
-    bool isRowVisible( const QModelIndex & ) const
-    {
-      return true;
-    }
-
-    /*reimp*/
-    bool isRowExpanded( const QModelIndex & ) const
-    {
-      return false;
-    }
-
-    /*reimp*/
-    KDGantt::Span rowGeometry( const QModelIndex &idx ) const
-    {
-      return KDGantt::Span( idx.row() * mRowHeight, mRowHeight );
-    }
+enum FbStatus {
+    Unkown,
+    Free,
+    Busy,
+    Tentative
+};
 
-    /*reimp*/
-    int maximumItemHeight() const
+class FreebusyViewCalendar : public EventViews::ViewCalendar
+{
+public:
+    virtual ~FreebusyViewCalendar() {};
+    virtual bool isValid(const KCalCore::Incidence::Ptr &incidence) const
     {
-      return mRowHeight*6/8;
+        return incidence->uid().startsWith("fb-");
     }
 
-    /*reimp*/
-    int totalHeight() const
+    virtual QString displayName(const KCalCore::Incidence::Ptr &incidence) const
     {
-      return m_model->rowCount() * mRowHeight;
+        Q_UNUSED(incidence);
+        return QLatin1String("Freebusy");
     }
 
-    /*reimp*/
-    QModelIndex indexAt( int height ) const
+    virtual QColor resourceColor(const KCalCore::Incidence::Ptr &incidence) const
     {
-      return m_model->index( height / mRowHeight, 0 );
-    }
+        bool ok = false;
+        int status = incidence->customProperty("FREEBUSY", "STATUS").toInt(&ok);
 
-    /*reimp*/
-    QModelIndex indexBelow( const QModelIndex &idx ) const
-    {
-      if ( !idx.isValid() ) {
-        return QModelIndex();
-      }
-      return idx.model()->index( idx.row() + 1, idx.column(), idx.parent() );
-    }
+        if (!ok) {
+            return QColor("#555");
+        }
 
-    /*reimp*/
-    QModelIndex indexAbove( const QModelIndex &idx ) const
-    {
-      if ( !idx.isValid() ) {
-        return QModelIndex();
-      }
-      return idx.model()->index( idx.row() - 1, idx.column(), idx.parent() );
+        switch (status) {
+        case Busy:
+            return QColor("#f00");
+        case Tentative:
+            return QColor("#f70");
+        case Free:
+            return QColor("#0f0");
+        default:
+            return QColor("#555");
+        }
     }
 
-    void setRowHeight( int height )
+    virtual QString iconForIncidence(const KCalCore::Incidence::Ptr &incidence) const
     {
-      mRowHeight = height;
+        return QString();
     }
 
-  private:
-    int mRowHeight;
-
-};
-
-class GanttHeaderView : public QHeaderView
-{
-public:
-    explicit GanttHeaderView( QWidget *parent = 0 ) : QHeaderView( Qt::Horizontal, parent )
+    virtual KCalCore::Calendar::Ptr getCalendar() const
     {
+        return mCalendar;
     }
 
-    QSize sizeHint() const
-    {
-        QSize s = QHeaderView::sizeHint();
-        s.rheight() *= 2;
-        return s;
-    }
+    KCalCore::Calendar::Ptr mCalendar;
 };
 
-
 ResourceManagement::ResourceManagement()
 {
+    setButtonText(KDialog::Ok, i18nc("@action:button add resource to attendeelist", "Book resource"));
 
     mUi = new Ui_resourceManagement;
 
@@ -163,36 +123,26 @@ ResourceManagement::ResourceManagement()
     setMainWidget( w );
 
     QVariantList list;
-    mModel = new FreeBusyItemModel;
-#ifndef KDEPIM_MOBILE_UI
-
-    KDGantt::GraphicsView *mGanttGraphicsView = new KDGantt::GraphicsView( this );
-    mGanttGraphicsView->setObjectName( "mGanttGraphicsView" );
-    mGanttGraphicsView->setToolTip(
-        i18nc( "@info:tooltip",
-            "Shows the Free/Busy status of a resource.") );
-    mGanttGraphicsView->setWhatsThis(
-        i18nc( "@info:whatsthis",
-            "Shows the Free/Busy status of a resource.") );
-    FreeBusyGanttProxyModel *model = new FreeBusyGanttProxyModel( this );
-    model->setSourceModel( mModel );
-
-    RowController *mRowController = new RowController;
-    mRowController->setRowHeight( fontMetrics().height()*4 );   //TODO: detect
-
-    mRowController->setModel( model );
-    mGanttGraphicsView->setRowController( mRowController );
-
-    KDGantt::DateTimeGrid *mGanttGrid = new KDGantt::DateTimeGrid;
-    mGanttGrid->setScale( KDGantt::DateTimeGrid::ScaleDay );
-    mGanttGrid->setDayWidth( 300 );
-    mGanttGrid->setRowSeparators( true );
-    mGanttGraphicsView->setGrid( mGanttGrid );
-    mGanttGraphicsView->setModel( model );
-    mGanttGraphicsView->viewport()->setFixedWidth( 300 * 30 );
-
-    mUi->resourceCalender->addWidget( mGanttGraphicsView );
-#endif
+    mModel = new FreeBusyItemModel(this);
+
+    connect(mModel, SIGNAL(layoutChanged()), SLOT(slotFbModelLayoutChanged()));
+    connect(mModel, SIGNAL(modelReset()), SLOT(slotFbModelLayoutChanged()));
+    connect(mModel, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
+                    SLOT(slotFbModelRowsRemoved(QModelIndex,int,int)));
+    connect(mModel, SIGNAL(rowsInserted(QModelIndex,int,int)),
+                    SLOT(slotFbModelRowsAdded(QModelIndex,int,int)));
+    connect(mModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
+                    SLOT(slotFbModelRowsChanged(QModelIndex,QModelIndex)));
+
+    mAgendaView = new EventViews::AgendaView(QDate(), QDate(), false,  false);
+
+    KCalCore::Calendar::Ptr cal = KCalCore::Calendar::Ptr(new KCalCore::MemoryCalendar(KSystemTimeZones::local()));
+    FreebusyViewCalendar *fbCalendar = new FreebusyViewCalendar();
+    fbCalendar->mCalendar = cal;
+    mFbCalendar = EventViews::ViewCalendar::Ptr(fbCalendar);
+    mAgendaView->addCalendar(mFbCalendar);
+
+    mUi->resourceCalender->addWidget( mAgendaView );
 
     QStringList attrs;
     attrs << QLatin1String("cn") << QLatin1String("mail")
@@ -201,7 +151,7 @@ ResourceManagement::ResourceManagement()
     ResourceModel *resourcemodel = new ResourceModel(attrs);
     mUi->treeResults->setModel(resourcemodel);
 
-    // This doesn't work till now :( -> that's why i use the clieck signal
+    // This doesn't work till now :( -> that's why i use the click signal
     mUi->treeResults->setSelectionMode(QAbstractItemView::SingleSelection);
     selectionModel = mUi->treeResults->selectionModel();
 
@@ -211,13 +161,20 @@ ResourceManagement::ResourceManagement()
     connect(mUi->treeResults, SIGNAL(clicked(const QModelIndex &)),
             SLOT(slotShowDetails(const QModelIndex &)));
 
-    Akonadi::FreeBusyManager *m = Akonadi::FreeBusyManager::self();
-    connect( m, SIGNAL(freeBusyRetrieved(KCalCore::FreeBusy::Ptr,QString)),
-        SLOT(slotInsertFreeBusy(KCalCore::FreeBusy::Ptr,QString)) );
-
     connect(resourcemodel,SIGNAL(layoutChanged()),SLOT(slotLayoutChanged()));
 }
 
+ResourceManagement::~ResourceManagement()
+{
+    delete mModel;
+}
+
+
+ResourceItem::Ptr ResourceManagement::selectedItem() const
+{
+    return mSelectedItem;
+}
+
 void ResourceManagement::slotStartSearch(const QString &text)
 {
     ((ResourceModel*)mUi->treeResults->model())->startSearch(text);
@@ -226,10 +183,10 @@ void ResourceManagement::slotStartSearch(const QString &text)
 void ResourceManagement::slotShowDetails(const QModelIndex & current)
 {
     ResourceItem::Ptr item = current.model()->data(current, ResourceModel::Resource).value<ResourceItem::Ptr>();
+    mSelectedItem = item;
     showDetails(item->ldapObject(), item->ldapClient());
 }
 
-
 void ResourceManagement::showDetails(const KLDAP::LdapObject &obj, const KLDAP::LdapClient &client)
 {
     // Clean up formDetails
@@ -286,11 +243,7 @@ void ResourceManagement::showDetails(const KLDAP::LdapObject &obj, const KLDAP::
     FreeBusyItem::Ptr freebusy( new FreeBusyItem( attendee, this ));
     mModel->clear();
     mModel->addItem(freebusy);
-}
 
-void ResourceManagement::slotInsertFreeBusy(const KCalCore::FreeBusy::Ptr &fb, const QString &email)
-{
-    kDebug() <<  fb <<  email;
 
 }
 
@@ -340,10 +293,88 @@ void ResourceManagement::slotOwnerSearchFinished()
               }
           } else {
               mUi->formOwner->addRow(translateLDAPAttributeForDisplay(key), new QLabel(list.join("\n")));
-            }
+          }
       }
 
 }
 
+void ResourceManagement::slotDateChanged(QDate start, QDate end)
+{
+    int days = start.daysTo(end);
+    if (days < 7) {
+        end = start.addDays(7);
+    }
+    mAgendaView->showDates(start, end);
+}
+
+void ResourceManagement::slotFbModelLayoutChanged()
+{
+    if (mFbEvent.count() > 0) {
+        mFbCalendar->getCalendar()->deleteAllEvents();
+        mFbEvent.clear();
+        for (int i = mModel->rowCount()-1; i>=0; i--) {
+            QModelIndex parent = mModel->index(i, 0);
+            slotFbModelRowsAdded(parent, 0, mModel->rowCount(parent)-1);
+        }
+    }
+}
+
+void ResourceManagement::slotFbModelRowsAdded(const QModelIndex &parent, int first, int last)
+{
+    if (!parent.isValid()) {
+        return;
+    }
+    for(int i=first; i<=last; i++) {
+        QModelIndex index = mModel->index(i, 0, parent);
+
+        const KCalCore::FreeBusyPeriod &period = mModel->data(index, FreeBusyItemModel::FreeBusyPeriodRole).value<KCalCore::FreeBusyPeriod>();
+        const KCalCore::Attendee::Ptr &attendee = mModel->data(parent, FreeBusyItemModel::AttendeeRole).value<KCalCore::Attendee::Ptr>();
+        const KCalCore::FreeBusy::Ptr &fb = mModel->data(parent, FreeBusyItemModel::FreeBusyRole).value<KCalCore::FreeBusy::Ptr>();
+
+        KCalCore::Event::Ptr inc = KCalCore::Event::Ptr(new KCalCore::Event());
+        inc->setDtStart(period.start());
+        inc->setDtEnd(period.end());
+        inc->setUid(QLatin1String("fb-") + fb->uid());
+        //TODO: set to correct status if it is added to KCalCore
+        inc->setCustomProperty("FREEBUSY", "STATUS", QString::number(Busy));
+        inc->setSummary(period.summary().isEmpty()? i18n("Busy") : period.summary());
+
+        mFbEvent.insert(index, inc);
+        mFbCalendar->getCalendar()->addEvent(inc);
+
+    }
+}
+
+void ResourceManagement::slotFbModelRowsRemoved(const QModelIndex &parent, int first, int last)
+{
+    if (!parent.isValid()) {
+        for (int i = first; i<=last; i--) {
+            QModelIndex index = mModel->index(i, 0);
+            slotFbModelRowsRemoved(index, 0, mModel->rowCount(index)-1);
+        }
+    } else {
+        for(int i=first; i<=last; i++) {
+            QModelIndex index = mModel->index(i, 0, parent);
+            KCalCore::Event::Ptr inc = mFbEvent.take(index);
+            mFbCalendar->getCalendar()->deleteEvent(inc);
+        }
+    }
+}
+
+void ResourceManagement::slotFbModelRowsChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
+{
+    if (!topLeft.parent().isValid()) {
+        return;
+    }
+    for (int i = topLeft.row(); i <= bottomRight.row(); i++) {
+        QModelIndex index = mModel->index(i, 0, topLeft.parent());
+        KCalCore::Event::Ptr inc = mFbEvent.value(index);
+        mFbCalendar->getCalendar()->beginChange(inc);
+        mFbCalendar->getCalendar()->endChange(inc);
+    }
+}
+
+
+
 
 #include "resourcemanagement.moc"
diff --git a/incidenceeditor-ng/resourcemanagement.h b/incidenceeditor-ng/resourcemanagement.h
index 8dedb4f..ee8dc19 100644
--- a/incidenceeditor-ng/resourcemanagement.h
+++ b/incidenceeditor-ng/resourcemanagement.h
@@ -30,7 +30,9 @@
 #include "freebusyitemmodel.h"
 #include "resourceitem.h"
 
-# include <KCalCore/FreeBusy>
+#include <calendarviews/agenda/viewcalendar.h>
+
+#include <KCalCore/FreeBusy>
 #include <KDialog>
 
 #include <QStringList>
@@ -38,6 +40,11 @@
 
 class  Ui_resourceManagement;
 
+namespace EventViews
+{
+    class AgendaView;
+}
+
 namespace IncidenceEditorNG
 {
 
@@ -48,6 +55,12 @@ class INCIDENCEEDITORS_NG_EXPORT ResourceManagement : public KDialog
     Q_OBJECT
 public:
     ResourceManagement();
+    ~ResourceManagement();
+
+    ResourceItem::Ptr selectedItem() const;
+
+public slots:
+    void slotDateChanged(QDate start, QDate end);
 
 private:
     /* Shows the details of a resource
@@ -67,20 +80,27 @@ private slots:
      *
      */
     void slotShowDetails(const QModelIndex & current);
-    
+
     /**
      * The Owner search is done
      */
     void slotOwnerSearchFinished();
 
-    void slotInsertFreeBusy( const KCalCore::FreeBusy::Ptr &fb, const QString &email );
-
     void slotLayoutChanged();
 
+    void slotFbModelLayoutChanged();
+    void slotFbModelRowsRemoved(const QModelIndex &parent, int first, int last);
+    void slotFbModelRowsAdded(const QModelIndex &parent, int first, int last);
+    void slotFbModelRowsChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight);
+
 private:
     FreeBusyItemModel *mModel;
     ResourceItem::Ptr mOwnerItem;
+    ResourceItem::Ptr mSelectedItem;
+    EventViews::ViewCalendar::Ptr mFbCalendar;
     Ui_resourceManagement *mUi;
+    QMap<QModelIndex,KCalCore::Event::Ptr> mFbEvent;
+    EventViews::AgendaView *mAgendaView;
 };
 
 }


commit f192b4ecdcd1673684735d01991f15c8dec4ec4d
Author: Sandro Knauß <knauss at kolabsys.com>
Date:   Mon Sep 15 16:25:04 2014 +0200

    CalendarViews: Get rid of Akonadi::Item in Agendaview [2/2]

diff --git a/calendarviews/CMakeLists.txt b/calendarviews/CMakeLists.txt
index 516233f..9dff9a8 100644
--- a/calendarviews/CMakeLists.txt
+++ b/calendarviews/CMakeLists.txt
@@ -53,6 +53,7 @@ set(eventviews_LIB_SRCS
   agenda/timelabels.cpp
   agenda/timelabelszone.cpp
   agenda/timescaleconfigdialog.cpp
+  agenda/viewcalendar.cpp
 
   journal/journalframe.cpp
   journal/journalview.cpp
diff --git a/calendarviews/agenda/agenda.cpp b/calendarviews/agenda/agenda.cpp
index 01c3d8d..6aace12 100644
--- a/calendarviews/agenda/agenda.cpp
+++ b/calendarviews/agenda/agenda.cpp
@@ -29,7 +29,7 @@
 #include "agenda.h"
 #include "agendaitem.h"
 #include "agendaview.h"
-#include "helper.h"
+#include "viewcalendar.h"
 #include "prefs.h"
 
 #include <Akonadi/Calendar/ETMCalendar>
@@ -207,7 +207,7 @@ class Agenda::Private
              int columns, int rows, int rowSize, bool isInteractive )
       : mAgendaView( agendaView ), mScrollArea( scrollArea ), mAllDayMode( false ),
         mColumns( columns ), mRows( rows ), mGridSpacingX( 0.0 ), mGridSpacingY( rowSize ),
-        mDesiredGridSpacingY( rowSize ), mCalendar( 0 ), mChanger( 0 ),
+        mDesiredGridSpacingY( rowSize ), mChanger( 0 ),
         mResizeBorderWidth( 0 ), mScrollBorderWidth( 0 ), mScrollDelay( 0 ), mScrollOffset( 0 ),
         mWorkingHoursEnable( false ), mHolidayMask( 0 ), mWorkingHoursYTop( 0 ),
         mWorkingHoursYBottom( 0 ), mHasSelection( 0 ), mSelectedId( -1 ), mMarcusBains( 0 ),
@@ -225,15 +225,15 @@ class Agenda::Private
       return mAgendaView->preferences();
     }
 
-    bool isQueuedForDeletion( Akonadi::Item::Id id ) const
+    bool isQueuedForDeletion( const QString &uid ) const
     {
       // if mAgendaItemsById contains it it means that a createAgendaItem() was called
       // before the previous agenda items were deleted.
-      return mItemsQueuedForDeletion.contains( id ) && !mAgendaItemsById.contains( id );
+      return mItemsQueuedForDeletion.contains( uid ) && !mAgendaItemsById.contains( uid );
     }
 
-    QMultiHash<Akonadi::Item::Id, AgendaItem::QPtr> mAgendaItemsById; // It's a QMultiHash because recurring incidences might have many agenda items
-    QSet<Akonadi::Item::Id> mItemsQueuedForDeletion;
+    QMultiHash<QString, AgendaItem::QPtr> mAgendaItemsById; // It's a QMultiHash because recurring incidences might have many agenda items
+    QSet<QString> mItemsQueuedForDeletion;
 
     AgendaView *mAgendaView;
     QScrollArea *mScrollArea;
@@ -251,8 +251,6 @@ class Agenda::Private
     double mGridSpacingY;
     double mDesiredGridSpacingY;
 
-    // We need the calendar for drag'n'drop and for paint the ResourceColor
-    Akonadi::ETMCalendar::Ptr mCalendar;
     Akonadi::IncidenceChanger *mChanger;
 
     // size of border, where mouse action will resize the AgendaItem
@@ -293,10 +291,10 @@ class Agenda::Private
 
     // Currently selected item
     QPointer<AgendaItem> mSelectedItem;
-    // Id of the last selected item. Used for reselecting in situations
+    // Uid of the last selected incidence. Used for reselecting in situations
     // where the selected item points to a no longer valid incidence, for
     // example during resource reload.
-    Akonadi::Item::Id mSelectedId;
+    QString mSelectedId;
 
     // The Marcus Bains Line widget.
     MarcusBains *mMarcusBains;
@@ -314,6 +312,8 @@ class Agenda::Private
 
     bool mReturnPressed;
     bool mIsInteractive;
+
+    MultiViewCalendar::Ptr mCalendar;
 };
 
 /*
@@ -349,9 +349,9 @@ Agenda::~Agenda()
   delete d;
 }
 
-Akonadi::Item Agenda::selectedIncidence() const
+KCalCore::Incidence::Ptr Agenda::selectedIncidence() const
 {
-  return d->mSelectedItem ? d->mSelectedItem->incidence() : Akonadi::Item();
+  return d->mSelectedItem ? d->mSelectedItem->incidence() : KCalCore::Incidence::Ptr();
 }
 
 QDate Agenda::selectedIncidenceDate() const
@@ -359,7 +359,7 @@ QDate Agenda::selectedIncidenceDate() const
   return d->mSelectedItem ? d->mSelectedItem->occurrenceDate() : QDate();
 }
 
-Akonadi::Item::Id Agenda::lastSelectedItemId() const
+QString Agenda::lastSelectedItemId() const
 {
   return d->mSelectedId;
 }
@@ -583,7 +583,7 @@ bool Agenda::eventFilter_drag( QObject *obj, QDropEvent *de )
 
     const QList<KUrl> incidenceUrls = CalendarSupport::incidenceItemUrls( md );
     const KCalCore::Incidence::List incidences =
-      CalendarSupport::incidences( md, d->mCalendar->timeSpec() );
+      CalendarSupport::incidences( md, d->mCalendar->mETMCalendar->timeSpec() );
 
     Q_ASSERT( !incidenceUrls.isEmpty() || !incidences.isEmpty() );
 
@@ -674,8 +674,7 @@ bool Agenda::eventFilter_mouse( QObject *object, QMouseEvent *me )
       } else {
         AgendaItem::QPtr item = dynamic_cast<AgendaItem *>(object);
         if (item) {
-          const Akonadi::Item aitem = item->incidence();
-          KCalCore::Incidence::Ptr incidence = CalendarSupport::incidence( aitem );
+          KCalCore::Incidence::Ptr incidence = item->incidence();
           if ( incidence->isReadOnly() ) {
             d->mActionItem = 0;
           } else {
@@ -736,8 +735,7 @@ bool Agenda::eventFilter_mouse( QObject *object, QMouseEvent *me )
     QPoint indicatorPos = gridToContents( contentsToGrid( viewportPos ) );
     if ( object != this ) {
       AgendaItem::QPtr moveItem = dynamic_cast<AgendaItem *>( object );
-      const Akonadi::Item aitem = moveItem ? moveItem->incidence() : Akonadi::Item();
-      KCalCore::Incidence::Ptr incidence = CalendarSupport::incidence( aitem );
+      KCalCore::Incidence::Ptr incidence =  moveItem ? moveItem->incidence() : KCalCore::Incidence::Ptr();
       if ( incidence && !incidence->isReadOnly() ) {
         if ( !d->mActionItem ) {
           setNoActionCursor( moveItem, viewportPos );
@@ -1165,8 +1163,7 @@ void Agenda::endItemAction()
 
   bool multiModify = false;
   // FIXME: do the cloning here...
-  Akonadi::Item inc = d->mActionItem->incidence();
-  const KCalCore::Incidence::Ptr incidence = CalendarSupport::incidence( inc );
+  const KCalCore::Incidence::Ptr incidence = d->mActionItem->incidence();
   d->mItemMoved = d->mItemMoved && !( d->mStartCell.x() == d->mEndCell.x() &&
                                       d->mStartCell.y() == d->mEndCell.y() );
 
@@ -1174,8 +1171,7 @@ void Agenda::endItemAction()
   if ( d->mItemMoved ) {
     bool modify = false;
     if ( incidence->recurs() ) {
-      const int res = d->mAgendaView->showMoveRecurDialog(
-        CalendarSupport::incidence( d->mActionItem->incidence() ), d->mActionItem->occurrenceDate() );
+      const int res = d->mAgendaView->showMoveRecurDialog( d->mActionItem->incidence(), d->mActionItem->occurrenceDate() );
       switch ( res ) {
       case KCalUtils::RecurrenceActions::AllOccurrences: // All occurrences
         // Moving the whole sequene of events is handled by the itemModified below.
@@ -1194,9 +1190,7 @@ void Agenda::endItemAction()
           // don't recreate items, they already have the correct position
           d->mAgendaView->enableAgendaUpdate( false );
 
-          Akonadi::Item item;
-          item.setPayload( newInc );
-          d->mActionItem->setIncidence( item );
+          d->mActionItem->setIncidence( newInc );
           d->mActionItem->dissociateFromMultiItem();
 
           addIncidence = true;
@@ -1248,8 +1242,10 @@ void Agenda::endItemAction()
       // calling when we move item.
       // Not perfect need to improve it!
       //mChanger->endChange( inc );
-      d->mAgendaView->updateEventDates( modif, addIncidence, inc.parentCollection().id() );
-
+      Akonadi::Item item = d->mCalendar->item(incidence);
+      if (item.isValid()) {
+        d->mAgendaView->updateEventDates( modif, addIncidence, item.parentCollection().id() );
+      }
       if ( addIncidence ) {
         // delete the one we dragged, there's a new one being added async, due to dissociation.
         delete modif;
@@ -1257,7 +1253,10 @@ void Agenda::endItemAction()
     } else {
       // the item was moved, but not further modified, since it's not recurring
       // make sure the view updates anyhow, with the right item
-      d->mAgendaView->updateEventDates( placeItem, addIncidence, inc.parentCollection().id() );
+      Akonadi::Item item = d->mCalendar->item(incidence);
+      if (item.isValid()) {
+        d->mAgendaView->updateEventDates( placeItem, addIncidence, item.parentCollection().id() );
+      }
     }
   }
 
@@ -1296,7 +1295,7 @@ void Agenda::setActionCursor( int actionType, bool acting )
 
 void Agenda::setNoActionCursor( AgendaItem::QPtr moveItem, const QPoint &pos )
 {
-  const Akonadi::Item item = moveItem ? moveItem->incidence() : Akonadi::Item();
+  const KCalCore::Incidence::Ptr item = moveItem ? moveItem->incidence() : KCalCore::Incidence::Ptr();
 
   const bool noResize = CalendarSupport::hasTodo( item );
 
@@ -1697,7 +1696,7 @@ void Agenda::setStartTime( const QTime &startHour )
 /*
   Insert AgendaItem into agenda.
 */
-AgendaItem::QPtr Agenda::insertItem( const Akonadi::Item &incidence, const KDateTime &qd,
+AgendaItem::QPtr Agenda::insertItem( const KCalCore::Incidence::Ptr &incidence, const KDateTime &qd,
                                      int X, int YTop, int YBottom, int itemPos, int itemCount,
                                      bool isSelected )
 {
@@ -1724,8 +1723,7 @@ AgendaItem::QPtr Agenda::insertItem( const Akonadi::Item &incidence, const KDate
                       int( ( YBottom + 1 ) * d->mGridSpacingY ) );
   agendaItem->setCellXY( X, YTop, YBottom );
   agendaItem->setCellXRight( X );
-  agendaItem->setResourceColor( EventViews::resourceColor( incidence,
-                                                           d->preferences() ) );
+  agendaItem->setResourceColor(d->mCalendar->resourceColor(incidence));
   agendaItem->installEventFilter( this );
 
   agendaItem->move( int( X * d->mGridSpacingX ), int( YTop * d->mGridSpacingY ) );
@@ -1744,7 +1742,7 @@ AgendaItem::QPtr Agenda::insertItem( const Akonadi::Item &incidence, const KDate
 /*
   Insert all-day AgendaItem into agenda.
 */
-AgendaItem::QPtr Agenda::insertAllDayItem( const Akonadi::Item &incidence, const KDateTime &occurrenceDateTime,
+AgendaItem::QPtr Agenda::insertAllDayItem( const KCalCore::Incidence::Ptr &incidence, const KDateTime &occurrenceDateTime,
                                            int XBegin, int XEnd, bool isSelected )
 {
   if ( !d->mAllDayMode ) {
@@ -1769,8 +1767,7 @@ AgendaItem::QPtr Agenda::insertAllDayItem( const Akonadi::Item &incidence, const
   agendaItem->resize( int( endIt ) - int( startIt ), int( d->mGridSpacingY ) );
 
   agendaItem->installEventFilter( this );
-  agendaItem->setResourceColor( EventViews::resourceColor( incidence,
-                                                           d->preferences() ) );
+  agendaItem->setResourceColor(d->mCalendar->resourceColor(incidence));
   agendaItem->move( int( XBegin * d->mGridSpacingX ), 0 ) ;
   d->mItems.append( agendaItem );
 
@@ -1781,26 +1778,26 @@ AgendaItem::QPtr Agenda::insertAllDayItem( const Akonadi::Item &incidence, const
   return agendaItem;
 }
 
-AgendaItem::QPtr Agenda::createAgendaItem( const Akonadi::Item &item, int itemPos,
+AgendaItem::QPtr Agenda::createAgendaItem( const KCalCore::Incidence::Ptr &incidence, int itemPos,
                                            int itemCount, const KDateTime &qd, bool isSelected )
 {
-  if ( !item.isValid() ) {
+  if ( !incidence ) {
     kWarning() << "Agenda::createAgendaItem() item is invalid.";
     return AgendaItem::QPtr();
   }
 
-  AgendaItem::QPtr agendaItem = new AgendaItem( d->mAgendaView, d->mCalendar, item,
+  AgendaItem::QPtr agendaItem = new AgendaItem( d->mAgendaView, d->mCalendar, incidence,
                                                 itemPos, itemCount, qd, isSelected, this );
 
   connect( agendaItem, SIGNAL(removeAgendaItem(AgendaItem::QPtr)), SLOT(removeAgendaItem(AgendaItem::QPtr)) );
   connect( agendaItem, SIGNAL(showAgendaItem(AgendaItem::QPtr)), SLOT(showAgendaItem(AgendaItem::QPtr)) );
 
-  d->mAgendaItemsById.insert( item.id(), agendaItem );
+  d->mAgendaItemsById.insert( incidence->uid(), agendaItem );
 
   return agendaItem;
 }
 
-void Agenda::insertMultiItem( const Akonadi::Item &event, const KDateTime &occurrenceDateTime, int XBegin,
+void Agenda::insertMultiItem( const KCalCore::Incidence::Ptr &event, const KDateTime &occurrenceDateTime, int XBegin,
                               int XEnd, int YTop, int YBottom, bool isSelected )
 {
   KCalCore::Event::Ptr ev = CalendarSupport::event( event );
@@ -1873,26 +1870,19 @@ void Agenda::removeIncidence( const KCalCore::Incidence::Ptr &incidence )
     return;
   }
 
-  // we get the id from the property, because the item might have been deleted from the etm/mCalendar
-  bool ok = false;
-  Akonadi::Item::Id id = incidence->customProperty( "VOLATILE", "AKONADI-ID" ).toLongLong( &ok );
-
-  if ( id == -1 || !ok ) {
-    id = d->mCalendar->item( incidence->instanceIdentifier() ).id();
-
-    if ( id == -1 ) {
+  /*
+  if ( !d->mViewCalendar->item(incidence).isValid() ) {
       // Ok, we really don't know the ID, give up.
       kWarning() << "Agenda::removeIncidence() Item to remove is invalid. uid = "
                  << incidence->instanceIdentifier();
       return;
-    }
-  }
+  } */
 
-  if ( d->isQueuedForDeletion( id ) ) {
+  if ( d->isQueuedForDeletion( incidence->uid() ) ) {
     return; // It's already queued for deletion
   }
 
-  AgendaItem::List agendaItems = d->mAgendaItemsById.values( id );
+  AgendaItem::List agendaItems = d->mAgendaItemsById.values( incidence->uid() );
   if ( agendaItems.isEmpty() ) {
     // We're not displaying such item
     // kDebug() << "Ignoring";
@@ -1933,7 +1923,7 @@ bool Agenda::removeAgendaItem( AgendaItem::QPtr agendaItem )
   // removeChild( thisItem );
 
   taken = d->mItems.removeAll( agendaItem ) > 0;
-  d->mAgendaItemsById.remove( agendaItem->incidence().id(), agendaItem );
+  d->mAgendaItemsById.remove( agendaItem->incidence()->uid(), agendaItem );
 
   QList<AgendaItem::QPtr>::iterator it;
   for ( it = conflictItems.begin(); it != conflictItems.end(); ++it ) {
@@ -1949,7 +1939,7 @@ bool Agenda::removeAgendaItem( AgendaItem::QPtr agendaItem )
     }
   }
   d->mItemsToDelete.append( agendaItem );
-  d->mItemsQueuedForDeletion.insert( agendaItem->incidence().id() );
+  d->mItemsQueuedForDeletion.insert( agendaItem->incidence()->uid() );
   agendaItem->setVisible( false );
   QTimer::singleShot( 0, this, SLOT(deleteItemsToDelete()) );
   return taken;
@@ -2132,12 +2122,12 @@ void Agenda::deselectItem()
     return;
   }
 
-  const Akonadi::Item selectedItem = d->mSelectedItem->incidence();
+  const KCalCore::Incidence::Ptr selectedItem = d->mSelectedItem->incidence();
 
   foreach ( AgendaItem::QPtr item, d->mItems ) {
     if ( item ) {
-      const Akonadi::Item itemInc = item->incidence();
-      if( itemInc.isValid() && selectedItem.isValid() && itemInc.id() == selectedItem.id() ) {
+      const KCalCore::Incidence::Ptr itemInc = item->incidence();
+      if( itemInc && selectedItem && itemInc->uid() == selectedItem->uid() ) {
         item->select( false );
       }
     }
@@ -2153,26 +2143,26 @@ void Agenda::selectItem( AgendaItem::QPtr item )
   }
   deselectItem();
   if ( item == 0 ) {
-    emit incidenceSelected( Akonadi::Item(), QDate() );
+    emit incidenceSelected( KCalCore::Incidence::Ptr(), QDate() );
     return;
   }
   d->mSelectedItem = item;
   d->mSelectedItem->select();
-  Q_ASSERT( CalendarSupport::hasIncidence( d->mSelectedItem->incidence() ) );
-  d->mSelectedId = d->mSelectedItem->incidence().id();
+  Q_ASSERT( d->mSelectedItem->incidence() );
+  d->mSelectedId = d->mSelectedItem->incidence()->uid();
 
   foreach ( AgendaItem::QPtr item, d->mItems ) {
-    if( item && item->incidence().id() == d->mSelectedId ) {
+    if( item && item->incidence()->uid() == d->mSelectedId ) {
       item->select();
     }
   }
   emit incidenceSelected( d->mSelectedItem->incidence(), d->mSelectedItem->occurrenceDate() );
 }
 
-void Agenda::selectItemByItemId( const Akonadi::Item::Id &id )
+void Agenda::selectIncidenceByUid( const QString &uid )
 {
   foreach ( AgendaItem::QPtr item, d->mItems ) {
-    if ( item && item->incidence().id() == id ) {
+    if ( item && item->incidence()->uid() == uid ) {
       selectItem( item );
       break;
     }
@@ -2181,7 +2171,7 @@ void Agenda::selectItemByItemId( const Akonadi::Item::Id &id )
 
 void Agenda::selectItem( const Akonadi::Item &item )
 {
-  selectItemByItemId( item.id() );
+  selectIncidenceByUid( CalendarSupport::incidence(item)->uid() );
 }
 
 // This function seems never be called.
@@ -2230,7 +2220,7 @@ KCalCore::DateList Agenda::dateList() const
   return d->mSelectedDates;
 }
 
-void Agenda::setCalendar( const Akonadi::ETMCalendar::Ptr &cal )
+void Agenda::setCalendar( const MultiViewCalendar::Ptr &cal )
 {
   d->mCalendar = cal;
 }
@@ -2269,9 +2259,9 @@ QScrollArea *Agenda::scrollArea() const
   return d->mScrollArea;
 }
 
-AgendaItem::List Agenda::agendaItems( Akonadi::Item::Id id ) const
+AgendaItem::List Agenda::agendaItems( const QString &uid ) const
 {
-  return d->mAgendaItemsById.values( id );
+  return d->mAgendaItemsById.values( uid );
 }
 
 AgendaScrollArea::AgendaScrollArea( bool isAllDay, AgendaView *agendaView,
diff --git a/calendarviews/agenda/agenda.h b/calendarviews/agenda/agenda.h
index e2a2607..e1dd790 100644
--- a/calendarviews/agenda/agenda.h
+++ b/calendarviews/agenda/agenda.h
@@ -27,6 +27,7 @@
 
 #include "eventviews_export.h"
 #include "agendaitem.h"
+#include "viewcalendar.h"
 
 #include <Akonadi/Item>
 
@@ -72,7 +73,7 @@ class EVENTVIEWS_EXPORT Agenda : public QWidget
 
     virtual ~Agenda();
 
-    Akonadi::Item selectedIncidence() const;
+    KCalCore::Incidence::Ptr selectedIncidence() const;
     QDate selectedIncidenceDate() const;
     QSize sizeHint() const;
     QSize minimumSizeHint() const;
@@ -93,14 +94,14 @@ class EVENTVIEWS_EXPORT Agenda : public QWidget
 
     QScrollArea *scrollArea() const;
 
-    AgendaItem::List agendaItems( Akonadi::Entity::Id id ) const;
+    AgendaItem::List agendaItems( const QString &uid ) const;
 
     /**
       Returns the uid of the last incidence that was selected. This
       persists across reloads and clear, so that if the same uid
       reappears, it can be reselected.
     */
-    Akonadi::Item::Id lastSelectedItemId() const;
+    QString lastSelectedItemId() const;
 
     bool eventFilter ( QObject *, QEvent * );
 
@@ -120,13 +121,13 @@ class EVENTVIEWS_EXPORT Agenda : public QWidget
 
     void setStartTime( const QTime &startHour );
 
-    AgendaItem::QPtr insertItem ( const Akonadi::Item &incidence, const KDateTime &occurrenceDateTime, int X, int YTop,
+    AgendaItem::QPtr insertItem ( const KCalCore::Incidence::Ptr &incidence, const KDateTime &occurrenceDateTime, int X, int YTop,
                                   int YBottom, int itemPos, int itemCount, bool isSelected );
 
-    AgendaItem::QPtr insertAllDayItem ( const Akonadi::Item &event, const KDateTime &occurrenceDateTime, int XBegin,
+    AgendaItem::QPtr insertAllDayItem ( const KCalCore::Incidence::Ptr &event, const KDateTime &occurrenceDateTime, int XBegin,
                                         int XEnd, bool isSelected );
 
-    void insertMultiItem ( const Akonadi::Item &event, const KDateTime &occurrenceDateTime, int XBegin, int XEnd,
+    void insertMultiItem ( const KCalCore::Incidence::Ptr &event, const KDateTime &occurrenceDateTime, int XBegin, int XEnd,
                            int YTop, int YBottom, bool isSelected );
 
     /**
@@ -158,7 +159,7 @@ class EVENTVIEWS_EXPORT Agenda : public QWidget
     void setDateList( const KCalCore::DateList &selectedDates );
     KCalCore::DateList dateList() const;
 
-    void setCalendar( const Akonadi::ETMCalendar::Ptr &cal );
+    void setCalendar( const EventViews::MultiViewCalendar::Ptr &cal );
 
     void setIncidenceChanger( Akonadi::IncidenceChanger *changer );
 
@@ -186,7 +187,7 @@ class EVENTVIEWS_EXPORT Agenda : public QWidget
       @param id the item id of the item that should be selected. If no such
       item exists, the selection is not changed.
     */
-    void selectItemByItemId( const Akonadi::Item::Id &id );
+    void selectIncidenceByUid( const QString &id );
     void selectItem( const Akonadi::Item &item );
 
     bool removeAgendaItem( AgendaItem::QPtr item );
@@ -197,19 +198,19 @@ class EVENTVIEWS_EXPORT Agenda : public QWidget
     void newTimeSpanSignal( const QPoint &, const QPoint & );
     void newStartSelectSignal();
 
-    void showIncidenceSignal( const Akonadi::Item & );
-    void editIncidenceSignal( const Akonadi::Item & );
-    void deleteIncidenceSignal( const Akonadi::Item & );
-    void showIncidencePopupSignal( const Akonadi::Item &, const QDate &);
+    void showIncidenceSignal( const KCalCore::Incidence::Ptr & );
+    void editIncidenceSignal( const KCalCore::Incidence::Ptr & );
+    void deleteIncidenceSignal( const KCalCore::Incidence::Ptr & );
+    void showIncidencePopupSignal( const KCalCore::Incidence::Ptr &, const QDate &);
 
     void showNewEventPopupSignal();
 
-    void incidenceSelected( const Akonadi::Item &, const QDate & );
+    void incidenceSelected( const KCalCore::Incidence::Ptr &, const QDate & );
 
     void lowerYChanged( int );
     void upperYChanged( int );
 
-    void startDragSignal( const Akonadi::Item & );
+    void startDragSignal( const KCalCore::Incidence::Ptr & );
     void droppedIncidences( const KCalCore::Incidence::List &, const QPoint &gpos, bool allDay );
     void droppedIncidences( const QList<KUrl> &, const QPoint &gpos, bool allDay );
 
@@ -233,7 +234,7 @@ class EVENTVIEWS_EXPORT Agenda : public QWidget
       RESIZERIGHT
     };
 
-    AgendaItem::QPtr createAgendaItem( const Akonadi::Item &item, int itemPos,
+    AgendaItem::QPtr createAgendaItem( const KCalCore::Incidence::Ptr &item, int itemPos,
                                        int itemCount, const KDateTime &qd, bool isSelected );
 
   protected:
diff --git a/calendarviews/agenda/agendaitem.cpp b/calendarviews/agenda/agendaitem.cpp
index bcb022c..6625dd1 100644
--- a/calendarviews/agenda/agendaitem.cpp
+++ b/calendarviews/agenda/agendaitem.cpp
@@ -22,6 +22,7 @@
 */
 #include "agendaitem.h"
 #include "eventview.h"
+#include "viewcalendar.h"
 #include "helper.h"
 #include "prefs.h"
 #include "prefs_base.h" // for enums
@@ -62,35 +63,32 @@ QPixmap *AgendaItem::eventPxmp = 0;
 
 //-----------------------------------------------------------------------------
 
-AgendaItem::AgendaItem( EventView *eventView, const Akonadi::ETMCalendar::Ptr &calendar,
-                        const Akonadi::Item &item,
+
+AgendaItem::AgendaItem( EventView *eventView, const MultiViewCalendar::Ptr &calendar,
+                        const KCalCore::Incidence::Ptr &item,
                         int itemPos, int itemCount,
                         const KDateTime &qd, bool isSelected, QWidget *parent )
   : QWidget( parent ), mEventView( eventView ), mCalendar( calendar ), mIncidence( item ),
     mOccurrenceDateTime( qd ), mValid( true ), mCloned( false ), mSelected( isSelected ), mSpecialEvent( false )
 {
-  if ( !CalendarSupport::hasIncidence( mIncidence ) ) {
+  if ( !mIncidence ) {
     mValid = false;
     return;
   }
 
-  KCalCore::Incidence::Ptr incidence = CalendarSupport::incidence( item );
-  mIncidence.setPayload( KCalCore::Incidence::Ptr( incidence->clone() ) );
-  Q_ASSERT( incidence );
-  if ( incidence->customProperty( "KABC", "BIRTHDAY" ) == QLatin1String("YES") ||
-       incidence->customProperty( "KABC", "ANNIVERSARY" ) == QLatin1String("YES") ) {
-    const int years = EventViews::yearDiff( incidence->dtStart().date(), qd.toTimeSpec( mEventView->preferences()->timeSpec() ).date() );
+  mIncidence = Incidence::Ptr(mIncidence->clone());
+  if ( mIncidence->customProperty( "KABC", "BIRTHDAY" ) == QLatin1String("YES") ||
+       mIncidence->customProperty( "KABC", "ANNIVERSARY" ) == QLatin1String("YES") ) {
+    const int years = EventViews::yearDiff( mIncidence->dtStart().date(), qd.toTimeSpec( mEventView->preferences()->timeSpec() ).date() );
     if ( years > 0 ) {
-      incidence = KCalCore::Incidence::Ptr( incidence->clone() );
-      incidence->setReadOnly( false );
-      incidence->setSummary( i18np( "%2 (1 year)", "%2 (%1 years)", years, incidence->summary() ) );
-      incidence->setReadOnly( true );
+      mIncidence->setReadOnly( false );
+      mIncidence->setSummary( i18np( "%2 (1 year)", "%2 (%1 years)", years, mIncidence->summary() ) );
+      mIncidence->setReadOnly( true );
       mCloned = true;
-      mIncidence.setPayload<KCalCore::Incidence::Ptr>( incidence );
     }
   }
 
-  mLabelText = incidence->summary();
+  mLabelText = mIncidence->summary();
   mIconAlarm = false;
   mIconRecur = false;
   mIconReadonly = false;
@@ -126,20 +124,18 @@ void AgendaItem::updateIcons()
   if ( !mValid ) {
     return;
   }
-  KCalCore::Incidence::Ptr incidence = CalendarSupport::incidence( mIncidence );
-  Q_ASSERT( incidence );
-  mIconReadonly = incidence->isReadOnly();
-  mIconRecur = incidence->recurs() || incidence->hasRecurrenceId();
-  mIconAlarm = incidence->hasEnabledAlarms();
-  if ( incidence->attendeeCount() > 1 ) {
-    if ( mEventView->kcalPreferences()->thatIsMe( incidence->organizer()->email() ) ) {
+  mIconReadonly = mIncidence->isReadOnly();
+  mIconRecur = mIncidence->recurs() || mIncidence->hasRecurrenceId();
+  mIconAlarm = mIncidence->hasEnabledAlarms();
+  if ( mIncidence->attendeeCount() > 1 ) {
+    if ( mEventView->kcalPreferences()->thatIsMe( mIncidence->organizer()->email() ) ) {
       mIconReply = false;
       mIconGroup = false;
       mIconGroupTent = false;
       mIconOrganizer = true;
     } else {
       KCalCore::Attendee::Ptr me =
-        incidence->attendeeByMails( mEventView->kcalPreferences()->allEmails() );
+        mIncidence->attendeeByMails( mEventView->kcalPreferences()->allEmails() );
 
       if ( me ) {
         if ( me->status() == KCalCore::Attendee::NeedsAction && me->RSVP() ) {
@@ -207,13 +203,13 @@ bool AgendaItem::dissociateFromMultiItem()
   return true;
 }
 
-void AgendaItem::setIncidence( const Akonadi::Item &incidence )
+void AgendaItem::setIncidence( const KCalCore::Incidence::Ptr &incidence )
 {
   mValid = false;
-  if ( CalendarSupport::hasIncidence( incidence ) ) {
+  if ( incidence ) {
     mValid = true;
     mIncidence = incidence;
-    mLabelText = CalendarSupport::incidence( incidence )->summary();
+    mLabelText = mIncidence->summary();
     updateIcons();
   }
 }
@@ -638,11 +634,10 @@ void AgendaItem::addAttendee( const QString &newAttendee )
     return;
   }
 
-  const KCalCore::Incidence::Ptr incidence = CalendarSupport::incidence( mIncidence );
   QString name, email;
   KPIMUtils::extractEmailAddressAndName( newAttendee, email, name );
   if ( !( name.isEmpty() && email.isEmpty() ) ) {
-    incidence->addAttendee( KCalCore::Attendee::Ptr( new KCalCore::Attendee( name, email ) ) );
+    mIncidence->addAttendee( KCalCore::Attendee::Ptr( new KCalCore::Attendee( name, email ) ) );
     KMessageBox::information(
       this,
       i18n( "Attendee \"%1\" added to the calendar item \"%2\"",
@@ -667,8 +662,7 @@ void AgendaItem::dropEvent( QDropEvent *e )
   bool decoded = md->hasText();
   QString text = md->text();
   if ( decoded && text.startsWith( QLatin1String( "file:" ) ) ) {
-    const KCalCore::Incidence::Ptr incidence = CalendarSupport::incidence( mIncidence );
-    incidence->addAttachment( KCalCore::Attachment::Ptr( new KCalCore::Attachment( text ) ) );
+    mIncidence->addAttachment( KCalCore::Attachment::Ptr( new KCalCore::Attachment( text ) ) );
     return;
   }
 
@@ -739,11 +733,10 @@ static void conditionalPaint( QPainter *p, bool condition, int &x, int y,
 void AgendaItem::paintIcon( QPainter *p, int &x, int y, int ft )
 {
   QString iconName;
-  Incidence::Ptr incidence = mIncidence.payload<KCalCore::Incidence::Ptr>();
-  if ( incidence->customProperty( "KABC", "ANNIVERSARY" ) == QLatin1String("YES") ) {
+  if ( mIncidence->customProperty( "KABC", "ANNIVERSARY" ) == QLatin1String("YES") ) {
     mSpecialEvent = true;
     iconName =  QLatin1String("view-calendar-wedding-anniversary");
-  } else if ( incidence->customProperty( "KABC", "BIRTHDAY" ) == QLatin1String("YES") ) {
+  } else if ( mIncidence->customProperty( "KABC", "BIRTHDAY" ) == QLatin1String("YES") ) {
     mSpecialEvent = true;
     // We don't draw icon. The icon is drawn already, because it's the Akonadi::Collection's icon
   }
@@ -762,17 +755,16 @@ void AgendaItem::paintIcons( QPainter *p, int &x, int y, int ft )
   QSet<EventView::ItemIcon> icons = mEventView->preferences()->agendaViewIcons();
 
   if ( icons.contains( EventViews::EventView::CalendarCustomIcon ) ) {
-    const QString iconName = mEventView->iconForItem( mIncidence );
+    const QString iconName = mCalendar->iconForIncidence( mIncidence );
     if ( !iconName.isEmpty() && iconName != QLatin1String("view-calendar") && iconName != QLatin1String("office-calendar") ) {
       conditionalPaint( p, true, x, y, ft, SmallIcon( iconName ) );
     }
   }
 
-  Incidence::Ptr incidence = mIncidence.payload<KCalCore::Incidence::Ptr>();
-  const bool isTodo = incidence && incidence->type() == Incidence::TypeTodo;
+  const bool isTodo = mIncidence && mIncidence->type() == Incidence::TypeTodo;
 
   if ( isTodo && icons.contains( EventViews::EventView::TaskIcon ) ) {
-    const QString iconName = incidence->iconName( mOccurrenceDateTime.toTimeSpec( incidence->dtStart().timeSpec() ) );
+    const QString iconName = mIncidence->iconName( mOccurrenceDateTime.toTimeSpec( mIncidence->dtStart().timeSpec() ) );
     conditionalPaint( p, !mSpecialEvent, x, y, ft, SmallIcon( iconName ) );
   }
 
@@ -860,10 +852,8 @@ void AgendaItem::paintEvent( QPaintEvent *ev )
     }
   }
 
-  const KCalCore::Incidence::Ptr incidence = CalendarSupport::incidence( mIncidence );
-  Q_ASSERT( incidence );
   QColor categoryColor;
-  const QStringList categories = incidence->categories();
+  const QStringList categories = mIncidence->categories();
   QString cat;
   if ( !categories.isEmpty() ) {
     cat = categories.first();
@@ -939,25 +929,25 @@ void AgendaItem::paintEvent( QPaintEvent *ev )
   QString shortH;
   QString longH;
   if ( !isMultiItem() ) {
-    shortH = KGlobal::locale()->formatTime(incidence->dateTime( KCalCore::Incidence::RoleDisplayStart ).
+    shortH = KGlobal::locale()->formatTime(mIncidence->dateTime( KCalCore::Incidence::RoleDisplayStart ).
              toTimeSpec( mEventView->preferences()->timeSpec() ).time() );
 
     if ( CalendarSupport::hasEvent( mIncidence ) ) {
       longH = i18n( "%1 - %2",
                     shortH,
                     KGlobal::locale()->formatTime(
-                      incidence->dateTime( KCalCore::Incidence::RoleEnd ).toTimeSpec(
+                      mIncidence->dateTime( KCalCore::Incidence::RoleEnd ).toTimeSpec(
                         mEventView->preferences()->timeSpec() ).time() ) );
     } else {
       longH = shortH;
     }
   } else if ( !mMultiItemInfo->mFirstMultiItem ) {
     shortH = KGlobal::locale()->formatTime(
-      incidence->dtStart().toTimeSpec( mEventView->preferences()->timeSpec() ).time() );
+      mIncidence->dtStart().toTimeSpec( mEventView->preferences()->timeSpec() ).time() );
     longH = shortH;
   } else {
     shortH = KGlobal::locale()->formatTime(
-      incidence->dateTime( KCalCore::Incidence::RoleEnd ).toTimeSpec(
+      mIncidence->dateTime( KCalCore::Incidence::RoleEnd ).toTimeSpec(
         mEventView->preferences()->timeSpec() ).time() );
     longH = i18n( "- %1", shortH );
   }
@@ -992,7 +982,7 @@ void AgendaItem::paintEvent( QPaintEvent *ev )
   if ( ( 2 * singleLineHeight ) > ( height() - 2 * margin ) ) {
     int x = margin, txtWidth;
 
-    if ( incidence->allDay() ) {
+    if ( mIncidence->allDay() ) {
       x += visRect.left();
       const int y =  qRound( ( height() - 16 ) / 2.0 );
       paintIcons( &p, x, y, ft );
@@ -1015,7 +1005,7 @@ void AgendaItem::paintEvent( QPaintEvent *ev )
        ( isMultiItem() && mMultiItemInfo->mNextMultiItem && mMultiItemInfo->mFirstMultiItem ) ) {
     int x = margin, txtWidth;
 
-    if ( incidence->allDay() ) {
+    if ( mIncidence->allDay() ) {
       x += visRect.left();
       paintIcons( &p, x, margin, ft );
       txtWidth = visRect.right() - margin - x;
@@ -1041,7 +1031,7 @@ void AgendaItem::paintEvent( QPaintEvent *ev )
 
   int x = margin, txtWidth, hTxtWidth, eventX;
 
-  if ( incidence->allDay() ) {
+  if ( mIncidence->allDay() ) {
     shortH.clear();
     longH.clear();
 
@@ -1051,9 +1041,9 @@ void AgendaItem::paintEvent( QPaintEvent *ev )
         shortH =
           i18n( "%1 - %2",
                 KGlobal::locale()->formatDate(
-                  incidence->dtStart().toTimeSpec( mEventView->preferences()->timeSpec() ).date() ),
+                  mIncidence->dtStart().toTimeSpec( mEventView->preferences()->timeSpec() ).date() ),
                 KGlobal::locale()->formatDate(
-                  incidence->dateTime( KCalCore::Incidence::RoleEnd ).toTimeSpec(
+                  mIncidence->dateTime( KCalCore::Incidence::RoleEnd ).toTimeSpec(
                     mEventView->preferences()->timeSpec() ).date() ) );
         longH = shortH;
 
@@ -1219,12 +1209,9 @@ void AgendaItem::drawRoundedRect( QPainter *p, const QRect &rect,
 
   QLinearGradient gradient( QPointF( r.x(), r.y() ), QPointF( r.x(), r.height() ) );
 
-  const KCalCore::Incidence::Ptr incidence = CalendarSupport::incidence( mIncidence );
-  Q_ASSERT( incidence );
-
   if ( r.height() > 50 ) {
-    if ( incidence->allDay() &&
-         incidence->dtStart() == incidence->dateTime( KCalCore::Incidence::RoleEnd ) &&
+    if ( mIncidence->allDay() &&
+         mIncidence->dtStart() == mIncidence->dateTime( KCalCore::Incidence::RoleEnd ) &&
          CalendarSupport::hasEvent( mIncidence ) ) {
       gradient.setColorAt( 0, bgColor.light( 130 ) );
       qreal t = 1.0 - ( r.height() - 18.0 ) / r.height();
@@ -1238,8 +1225,8 @@ void AgendaItem::drawRoundedRect( QPainter *p, const QRect &rect,
     }
     gradient.setColorAt( 1, bgColor.dark( 110 ) );
   } else {
-    if ( incidence->allDay() &&
-         incidence->dtStart() == incidence->dateTime( KCalCore::Incidence::RoleEnd ) &&
+    if ( mIncidence->allDay() &&
+         mIncidence->dtStart() == mIncidence->dateTime( KCalCore::Incidence::RoleEnd ) &&
          !CalendarSupport::hasTodo( mIncidence ) ) {
       gradient.setColorAt( 0, bgColor.light( 130 ) );
       gradient.setColorAt( 0.35, bgColor.light( 115 ) );
@@ -1373,8 +1360,8 @@ bool AgendaItem::event( QEvent *event )
       QToolTip::showText(
         helpEvent->globalPos(),
         KCalUtils::IncidenceFormatter::toolTipStr(
-          CalendarSupport::displayName( mCalendar.data(), mIncidence.parentCollection() ),
-          CalendarSupport::incidence( mIncidence ),
+          mCalendar->displayName(mIncidence),
+          mIncidence,
           mOccurrenceDateTime.toTimeSpec( mEventView->preferences()->timeSpec() ).date(), true, mEventView->preferences()->timeSpec() ),
         this );
     }
diff --git a/calendarviews/agenda/agendaitem.h b/calendarviews/agenda/agendaitem.h
index fcc48a5..74b8a53 100644
--- a/calendarviews/agenda/agendaitem.h
+++ b/calendarviews/agenda/agendaitem.h
@@ -24,6 +24,7 @@
 #define EVENTVIEWS_AGENDAITEM_H
 
 #include "eventviews_export.h"
+#include "viewcalendar.h"
 
 #include <calendarsupport/cellitem.h>
 
@@ -85,8 +86,8 @@ class EVENTVIEWS_EXPORT AgendaItem : public QWidget, public CalendarSupport::Cel
     typedef QList<QPtr> List;
 
     AgendaItem( EventView *eventView,
-                const Akonadi::ETMCalendar::Ptr &calendar,
-                const Akonadi::Item &incidence,
+                const MultiViewCalendar::Ptr &calendar,
+                const KCalCore::Incidence::Ptr &incidence,
                 int itemPos,
                 int itemCount,
                 const KDateTime &qd,
@@ -207,9 +208,9 @@ class EVENTVIEWS_EXPORT AgendaItem : public QWidget, public CalendarSupport::Cel
 
     bool dissociateFromMultiItem();
 
-    void setIncidence( const Akonadi::Item &incidence );
+    void setIncidence( const KCalCore::Incidence::Ptr &incidence );
 
-    const Akonadi::Item & incidence() const
+    const KCalCore::Incidence::Ptr& incidence() const
     {
       return mIncidence;
     }
@@ -295,8 +296,8 @@ class EVENTVIEWS_EXPORT AgendaItem : public QWidget, public CalendarSupport::Cel
     int mCellYTop, mCellYBottom;
 
     EventView *mEventView;
-    Akonadi::ETMCalendar::Ptr mCalendar;
-    Akonadi::Item mIncidence;
+    MultiViewCalendar::Ptr mCalendar;
+    KCalCore::Incidence::Ptr mIncidence;
     KDateTime mOccurrenceDateTime;
     bool mValid;
     bool mCloned;
diff --git a/calendarviews/agenda/agendaview.cpp b/calendarviews/agenda/agendaview.cpp
index 3c8d56d..b77b0b7 100644
--- a/calendarviews/agenda/agendaview.cpp
+++ b/calendarviews/agenda/agendaview.cpp
@@ -26,6 +26,7 @@
 #include "agendaview.h"
 #include "agenda.h"
 #include "agendaitem.h"
+#include "viewcalendar.h"
 #include "alternatelabel.h"
 #include "calendardecoration.h"
 #include "decorationlabel.h"
@@ -61,6 +62,7 @@
 #include <QSplitter>
 #include <QStyle>
 #include <QTimer>
+#include <boost/graph/buffer_concepts.hpp>
 
 using namespace EventViews;
 
@@ -195,8 +197,11 @@ class AgendaView::Private : public Akonadi::ETMCalendar::CalendarObserver
         mUpdateAllDayAgenda( true ),
         mUpdateAgenda( true ),
         mIsInteractive( isInteractive ),
-        mUpdateEventIndicatorsScheduled( false )
+        mUpdateEventIndicatorsScheduled( false ),
+        mViewCalendar(MultiViewCalendar::Ptr( new MultiViewCalendar()))
     {
+      mViewCalendar->mAgendaView = q;
+      mViewCalendar->setETMCalendar(q->calendar());
     }
 
   public:
@@ -250,6 +255,7 @@ class AgendaView::Private : public Akonadi::ETMCalendar::CalendarObserver
     // color
     QMap<QDate, KCalCore::Event::List > mBusyDays;
 
+    EventViews::MultiViewCalendar::Ptr mViewCalendar;
     bool makesWholeDayBusy( const KCalCore::Incidence::Ptr &incidence ) const;
     CalendarDecoration::Decoration *loadCalendarDecoration( const QString &name );
     void clearView();
@@ -265,10 +271,10 @@ class AgendaView::Private : public Akonadi::ETMCalendar::CalendarObserver
 
     void changeColumns( int numColumns );
 
-    AgendaItem::List agendaItems( Akonadi::Entity::Id id ) const;
+    AgendaItem::List agendaItems( const QString &uid ) const;
 
     // insertAtDateTime is in the view's timezone
-    void insertIncidence( const Akonadi::Item &,
+    void insertIncidence( const KCalCore::Incidence::Ptr &,
                           const KDateTime &insertAtDateTime, bool createSelected );
     void reevaluateIncidence( const KCalCore::Incidence::Ptr &incidence );
 
@@ -313,10 +319,10 @@ bool AgendaView::Private::datesEqual( const KCalCore::Incidence::Ptr &one, const
   return true;
 }
 
-AgendaItem::List AgendaView::Private::agendaItems( Akonadi::Item::Id id ) const
+AgendaItem::List AgendaView::Private::agendaItems( const QString &uid ) const
 {
-  AgendaItem::List allDayAgendaItems = mAllDayAgenda->agendaItems( id );
-  return allDayAgendaItems.isEmpty() ? mAgenda->agendaItems( id ) : allDayAgendaItems;
+  AgendaItem::List allDayAgendaItems = mAllDayAgenda->agendaItems( uid );
+  return allDayAgendaItems.isEmpty() ? mAgenda->agendaItems( uid ) : allDayAgendaItems;
 }
 
 bool AgendaView::Private::mightBeVisible( const KCalCore::Incidence::Ptr &incidence ) const
@@ -389,34 +395,32 @@ QList<QDate> AgendaView::Private::generateDateList( const QDate &start, const QD
 
 void AgendaView::Private::reevaluateIncidence( const KCalCore::Incidence::Ptr &incidence )
 {
-  const Akonadi::Item item = q->calendar()->item( incidence );
-  if ( !incidence || !item.isValid() ) {
-    kWarning() << "invalid incidence or item not found." << item.isValid() << incidence;
+  if (!incidence || !mViewCalendar->isValid( incidence )) {
+    kWarning() << "invalid or unknown incidence." << incidence;
     return;
   }
 
   q->removeIncidence( incidence );
-  q->displayIncidence( item, false );
+  q->displayIncidence( incidence, false );
   mAgenda->checkScrollBoundaries();
   q->updateEventIndicators();
 }
 
 void AgendaView::Private::calendarIncidenceAdded( const KCalCore::Incidence::Ptr &incidence )
 {
-  Akonadi::Item item = q->calendar()->item( incidence );
-  if ( !incidence || incidence->uid().isEmpty() || !item.isValid()) {
-    kError() << "AgendaView::Private::calendarIncidenceAdded() Invalid incidence or item:" << incidence << item.isValid();
+  if (!incidence || !mViewCalendar->isValid( incidence )) {
+    kWarning() << "invalid or unknown incidence." << incidence;
     Q_ASSERT( false );
     return;
   }
 
-  if ( incidence->hasRecurrenceId() ) {
+  if ( incidence->hasRecurrenceId() && mViewCalendar->isValid(incidence)) {
     // Reevaluate the main event instead, if it was inserted before this one
-    KCalCore::Incidence::Ptr mainIncidence = q->calendar()->incidence( incidence->uid() );
+    KCalCore::Incidence::Ptr mainIncidence = mViewCalendar->findCalendar(incidence)->getCalendar()->incidence( incidence->uid() );
     if ( mainIncidence ) {
       reevaluateIncidence( mainIncidence );
     }
-  } else if ( q->displayIncidence( item, false ) ) {
+  } else if ( q->displayIncidence( incidence, false ) ) {
     mAgenda->checkScrollBoundaries();
     q->scheduleUpdateEventIndicators();
   }
@@ -430,13 +434,7 @@ void AgendaView::Private::calendarIncidenceChanged( const KCalCore::Incidence::P
     return;
   }
 
-  Akonadi::Item item = q->calendar()->item( incidence->instanceIdentifier() );
-  if ( !item.isValid() ) {
-    kWarning() << "AgendaView::calendarIncidenceChanged() Invalid item for incidence " << incidence->uid();
-    return;
-  }
-
-  AgendaItem::List agendaItems = this->agendaItems( item.id() );
+  AgendaItem::List agendaItems = this->agendaItems( incidence->uid() );
   if ( agendaItems.isEmpty() ) {
     kWarning() << "AgendaView::calendarIncidenceChanged() Invalid agendaItem for incidence " << incidence->uid();
     return;
@@ -445,22 +443,20 @@ void AgendaView::Private::calendarIncidenceChanged( const KCalCore::Incidence::P
   // Optimization: If the dates didn't change, just repaint it.
   // This optimization for now because we need to process collisions between agenda items.
   if ( false && !incidence->recurs() && agendaItems.count() == 1 ) {
-    KCalCore::Incidence::Ptr originalIncidence = agendaItems.first()->incidence().payload<KCalCore::Incidence::Ptr>();
+    KCalCore::Incidence::Ptr originalIncidence = agendaItems.first()->incidence();
 
     if ( datesEqual( originalIncidence, incidence ) ) {
       foreach ( const AgendaItem::QPtr &agendaItem, agendaItems ) {
-        Akonadi::Item itemClone = item;
-        itemClone.setPayload<KCalCore::Incidence::Ptr>( KCalCore::Incidence::Ptr( incidence->clone() ) );
-        agendaItem->setIncidence( itemClone );
+        agendaItem->setIncidence( KCalCore::Incidence::Ptr( incidence->clone() ) );
         agendaItem->update();
       }
       return;
     }
   }
 
-  if ( incidence->hasRecurrenceId() ) {
+    if ( incidence->hasRecurrenceId() && mViewCalendar->isValid(incidence) ) {
     // Reevaluate the main event instead, if it exists
-    KCalCore::Incidence::Ptr mainIncidence = q->calendar()->incidence( incidence->uid() );
+    KCalCore::Incidence::Ptr mainIncidence = mViewCalendar->findCalendar(incidence)->getCalendar()->incidence( incidence->uid() );
     reevaluateIncidence( mainIncidence ? mainIncidence : incidence );
   } else {
     reevaluateIncidence( incidence );
@@ -483,9 +479,11 @@ void AgendaView::Private::calendarIncidenceDeleted( const KCalCore::Incidence::P
   if ( incidence->hasRecurrenceId()) {
     // Reevaluate the main event, if it exists. The exception was removed so the main recurrent series
     // will no be bigger.
-    KCalCore::Incidence::Ptr mainIncidence = q->calendar()->incidence( incidence->uid() );
-    if ( mainIncidence ) {
-      reevaluateIncidence( mainIncidence  );
+    if ( mViewCalendar->isValid(incidence) ) {
+      KCalCore::Incidence::Ptr mainIncidence = mViewCalendar->findCalendar(incidence)->getCalendar()->incidence( incidence->uid() );
+      if ( mainIncidence ) {
+        reevaluateIncidence( mainIncidence  );
+      }
     }
   } else if ( mightBeVisible( incidence ) ) {
     // No need to call setChanges(), that triggers a fillAgenda()
@@ -532,17 +530,16 @@ void AgendaView::Private::clearView()
   mBusyDays.clear();
 }
 
-void AgendaView::Private::insertIncidence( const Akonadi::Item &aitem,
+void AgendaView::Private::insertIncidence( const KCalCore::Incidence::Ptr &incidence,
                                            const KDateTime &insertAtDateTime,
                                            bool createSelected )
 {
-  if ( !q->filterByCollectionSelection( aitem ) ) {
+  if ( !q->filterByCollectionSelection( incidence ) ) {
     return;
   }
 
-  KCalCore::Incidence::Ptr incidence = CalendarSupport::incidence( aitem );
-  KCalCore::Event::Ptr event = CalendarSupport::event( aitem );
-  KCalCore::Todo::Ptr todo = CalendarSupport::todo( aitem );
+  KCalCore::Event::Ptr event = CalendarSupport::event( incidence );
+  KCalCore::Todo::Ptr todo = CalendarSupport::todo( incidence );
 
   const QDate insertAtDate = insertAtDateTime.date();
 
@@ -591,10 +588,10 @@ void AgendaView::Private::insertIncidence( const Akonadi::Item &aitem,
   const KDateTime::Spec timeSpec = q->preferences()->timeSpec();
   const QDate today = KDateTime::currentDateTime( timeSpec ).date();
   if ( todo && todo->isOverdue() && today >= insertAtDate ) {
-    mAllDayAgenda->insertAllDayItem( aitem, insertAtDateTime, curCol, curCol,
+    mAllDayAgenda->insertAllDayItem( incidence, insertAtDateTime, curCol, curCol,
                                      createSelected );
   } else if ( incidence->allDay() ) {
-    mAllDayAgenda->insertAllDayItem( aitem, insertAtDateTime, beginX, endX,
+    mAllDayAgenda->insertAllDayItem( incidence, insertAtDateTime, beginX, endX,
                                      createSelected );
   } else if ( event && event->isMultiDay( timeSpec ) ) {
     // TODO: We need a better isMultiDay(), one that receives the occurrence.
@@ -615,7 +612,7 @@ void AgendaView::Private::insertIncidence( const Akonadi::Item &aitem,
     }
     const int endY = mAgenda->timeToY( endTime ) - 1;
     if ( ( beginX <= 0 && curCol == 0 ) || beginX == curCol ) {
-      mAgenda->insertMultiItem( aitem, insertAtDateTime, beginX, endX, startY, endY,
+      mAgenda->insertMultiItem( incidence, insertAtDateTime, beginX, endX, startY, endY,
                                 createSelected );
     }
     if ( beginX == curCol ) {
@@ -686,7 +683,7 @@ void AgendaView::Private::insertIncidence( const Akonadi::Item &aitem,
     if ( endY < startY ) {
       endY = startY;
     }
-    mAgenda->insertItem( aitem, insertAtDateTime, curCol, startY, endY, 1, 1,
+    mAgenda->insertItem( incidence, insertAtDateTime, curCol, startY, endY, 1, 1,
                          createSelected );
     if ( startY < mMinY[curCol] ) {
       mMinY[curCol] = startY;
@@ -836,8 +833,8 @@ void AgendaView::init( const QDate &start, const QDate &end )
 
 AgendaView::~AgendaView()
 {
-  if ( calendar() ) {
-    calendar()->unregisterObserver( d );
+  foreach(const ViewCalendar::Ptr &cal, d->mViewCalendar->mSubCalendars) {
+    cal->getCalendar()->unregisterObserver(d);
   }
 
   delete d;
@@ -851,19 +848,27 @@ void AgendaView::setCalendar( const Akonadi::ETMCalendar::Ptr &cal )
   Q_ASSERT( cal );
   EventView::setCalendar( cal );
   calendar()->registerObserver( d );
-  d->mAgenda->setCalendar( calendar() );
-  d->mAllDayAgenda->setCalendar( calendar() );
+  d->mViewCalendar->setETMCalendar(cal);
+  d->mAgenda->setCalendar( d->mViewCalendar );
+  d->mAllDayAgenda->setCalendar( d->mViewCalendar );
+}
+
+void AgendaView::addCalendar(const ViewCalendar::Ptr &cal)
+{
+  d->mViewCalendar->addCalendar(cal);
+  cal->getCalendar()->registerObserver(d);
 }
 
+
 void AgendaView::connectAgenda( Agenda *agenda, Agenda *otherAgenda )
 {
   connect( agenda, SIGNAL(showNewEventPopupSignal()),
            SIGNAL(showNewEventPopupSignal()) );
 
-  connect( agenda, SIGNAL(showIncidencePopupSignal(Akonadi::Item,QDate)),
-           SIGNAL(showIncidencePopupSignal(Akonadi::Item,QDate)));
+  connect( agenda, SIGNAL(showIncidencePopupSignal(KCalCore::Incidence::Ptr,QDate)),
+           SLOT(slotShowIncidencePopup(KCalCore::Incidence::Ptr,QDate)));
 
-  agenda->setCalendar( calendar() );
+  agenda->setCalendar( d->mViewCalendar );
 
   connect( agenda, SIGNAL(newEventSignal()), SIGNAL(newEventSignal()) );
 
@@ -872,22 +877,22 @@ void AgendaView::connectAgenda( Agenda *agenda, Agenda *otherAgenda )
   connect( agenda, SIGNAL(newStartSelectSignal()),
            SIGNAL(timeSpanSelectionChanged()) );
 
-  connect( agenda, SIGNAL(editIncidenceSignal(Akonadi::Item)),
-                   SIGNAL(editIncidenceSignal(Akonadi::Item)) );
-  connect( agenda, SIGNAL(showIncidenceSignal(Akonadi::Item)),
-                   SIGNAL(showIncidenceSignal(Akonadi::Item)) );
-  connect( agenda, SIGNAL(deleteIncidenceSignal(Akonadi::Item)),
-                   SIGNAL(deleteIncidenceSignal(Akonadi::Item)) );
+  connect( agenda, SIGNAL(editIncidenceSignal(KCalCore::Incidence::Ptr)),
+                   SLOT(slotEditIncidence(KCalCore::Incidence::Ptr)) );
+  connect( agenda, SIGNAL(showIncidenceSignal(KCalCore::Incidence::Ptr)),
+                  SLOT(slotShowIncidence(KCalCore::Incidence::Ptr)) );
+  connect( agenda, SIGNAL(deleteIncidenceSignal(KCalCore::Incidence::Ptr)),
+                  SLOT(slotDeleteIncidence(KCalCore::Incidence::Ptr)) );
 
   // drag signals
-  connect( agenda, SIGNAL(startDragSignal(Akonadi::Item)),
-           SLOT(startDrag(Akonadi::Item)) );
+  connect( agenda, SIGNAL(startDragSignal(KCalCore::Incidence::Ptr)),
+          SLOT(startDrag(KCalCore::Incidence::Ptr)) );
 
   // synchronize selections
-  connect( agenda, SIGNAL(incidenceSelected(Akonadi::Item,QDate)),
+  connect( agenda, SIGNAL(incidenceSelected(KCalCore::Incidence::Ptr,QDate)),
            otherAgenda, SLOT(deselectItem()) );
-  connect( agenda, SIGNAL(incidenceSelected(Akonadi::Item,QDate)),
-           SIGNAL(incidenceSelected(Akonadi::Item,QDate)) );
+  connect( agenda, SIGNAL(incidenceSelected(KCalCore::Incidence::Ptr,QDate)),
+           SLOT(slotIncidenceSelected(KCalCore::Incidence::Ptr,QDate)) );
 
   // rescheduling of todos by d'n'd
   connect( agenda, SIGNAL(droppedIncidences(KCalCore::Incidence::List,QPoint,bool)),
@@ -897,6 +902,47 @@ void AgendaView::connectAgenda( Agenda *agenda, Agenda *otherAgenda )
 
 }
 
+void AgendaView::slotIncidenceSelected(const KCalCore::Incidence::Ptr &incidence,QDate date)
+{
+  Akonadi::Item item = d->mViewCalendar->item(incidence);
+  if (item.isValid()) {
+    emit incidenceSelected(item, date);
+  }
+}
+
+void AgendaView::slotShowIncidencePopup(const KCalCore::Incidence::Ptr &incidence, QDate date)
+{
+  Akonadi::Item item = d->mViewCalendar->item(incidence);
+  kDebug() << "wanna see the popup for " << incidence->uid() << item.id();
+  if (item.isValid()) {
+    emit showIncidencePopupSignal(item, date);
+   }
+}
+
+void AgendaView::slotShowIncidence(const KCalCore::Incidence::Ptr &incidence)
+{
+  Akonadi::Item item = d->mViewCalendar->item(incidence);
+  if (item.isValid()) {
+    emit showIncidenceSignal(item);
+  }
+}
+
+void AgendaView::slotEditIncidence(const KCalCore::Incidence::Ptr &incidence)
+{
+  Akonadi::Item item = d->mViewCalendar->item(incidence);
+  if (item.isValid()) {
+    emit editIncidenceSignal(item);
+   }
+}
+
+void AgendaView::slotDeleteIncidence(const KCalCore::Incidence::Ptr &incidence)
+{
+  Akonadi::Item item = d->mViewCalendar->item(incidence);
+  if (item.isValid()) {
+    emit deleteIncidenceSignal(item);
+   }
+}
+
 void AgendaView::zoomInVertically( )
 {
   if ( !d->mIsSideBySide ) {
@@ -1237,14 +1283,14 @@ Akonadi::Item::List AgendaView::selectedIncidences() const
 {
   Akonadi::Item::List selected;
 
-  Akonadi::Item agendaitem = d->mAgenda->selectedIncidence();
-  if ( agendaitem.isValid() ) {
-    selected.append( agendaitem );
+  KCalCore::Incidence::Ptr agendaitem = d->mAgenda->selectedIncidence();
+  if ( agendaitem ) {
+    selected.append( d->mViewCalendar->item(agendaitem) );
   }
 
-  Akonadi::Item dayitem = d->mAllDayAgenda->selectedIncidence();
-  if ( dayitem.isValid() ) {
-    selected.append( dayitem );
+  KCalCore::Incidence::Ptr dayitem = d->mAllDayAgenda->selectedIncidence();
+  if ( dayitem ) {
+    selected.append( d->mViewCalendar->item(dayitem) );
   }
 
   return selected;
@@ -1419,9 +1465,9 @@ void AgendaView::updateEventDates( AgendaItem *item, bool addIncidence,
   int daysLength = 0;
   //  startDt.setDate( startDate );
 
-  const Akonadi::Item aitem = item->incidence();
+  Akonadi::Item aitem = d->mViewCalendar->item(item->incidence());
   KCalCore::Incidence::Ptr incidence = CalendarSupport::incidence( aitem );
-  if ( !incidence || !changer() ) {
+  if ( !aitem.isValid() || !incidence || !changer() ) {
     kWarning() << "changer is " << changer() << " and incidence is " << incidence.data();
     return;
   }
@@ -1460,7 +1506,7 @@ void AgendaView::updateEventDates( AgendaItem *item, bool addIncidence,
   }
 
   // FIXME: use a visitor here
-  if ( const KCalCore::Event::Ptr ev = CalendarSupport::event( aitem ) ) {
+  if ( const KCalCore::Event::Ptr ev = CalendarSupport::event( incidence ) ) {
     startDt = incidence->dtStart();
     // convert to calendar timespec because we then manipulate it
     // with time coming from the calendar
@@ -1479,7 +1525,7 @@ void AgendaView::updateEventDates( AgendaItem *item, bool addIncidence,
       QTimer::singleShot( 0, this, SLOT(updateView()) );
       return;
     }
-  } else if ( const KCalCore::Todo::Ptr td = CalendarSupport::todo( aitem ) ) {
+  } else if ( const KCalCore::Todo::Ptr td = CalendarSupport::todo( incidence ) ) {
     startDt = td->hasStartDate() ? td->dtStart() : td->dtDue();
     // convert to calendar timespec because we then manipulate it with time coming from
     // the calendar
@@ -1505,7 +1551,7 @@ void AgendaView::updateEventDates( AgendaItem *item, bool addIncidence,
   // A commented code block which had 150 lines to adjust recurrence was here.
   // I deleted it in rev 1180272 to make this function readable.
 
-  if ( const KCalCore::Event::Ptr ev = CalendarSupport::event( aitem ) ) {
+  if ( const KCalCore::Event::Ptr ev = CalendarSupport::event( incidence ) ) {
     /* setDtEnd() must be called before setDtStart(), otherwise, when moving
      * events, CalendarLocal::incidenceUpdated() will not remove the old hash
      * and that causes the event to be shown in the old date also (bug #179157).
@@ -1515,7 +1561,7 @@ void AgendaView::updateEventDates( AgendaItem *item, bool addIncidence,
     ev->setDtEnd(
       endDt.toTimeSpec( incidence->dateTime( KCalCore::Incidence::RoleEnd ).timeSpec() ) );
     incidence->setDtStart( startDt.toTimeSpec( incidence->dtStart().timeSpec() ) );
-  } else if ( const KCalCore::Todo::Ptr td = CalendarSupport::todo( aitem ) ) {
+  } else if ( const KCalCore::Todo::Ptr td = CalendarSupport::todo( incidence ) ) {
     if ( td->hasStartDate() ) {
       td->setDtStart( startDt.toTimeSpec( incidence->dtStart().timeSpec() ) );
     }
@@ -1652,7 +1698,7 @@ void AgendaView::fillAgenda()
     return;
   }
 
-  if ( !calendar() ) {
+  if ( d->mViewCalendar->calendars() == 0) {
     kWarning() << "No calendar is set";
     return;
   }
@@ -1664,8 +1710,8 @@ void AgendaView::fillAgenda()
 
   /* Remember the item Ids of the selected items. In case one of the
    * items was deleted and re-added, we want to reselect it. */
-  const Akonadi::Item::Id selectedAgendaId = d->mAgenda->lastSelectedItemId();
-  const Akonadi::Item::Id selectedAllDayAgendaId = d->mAllDayAgenda->lastSelectedItemId();
+  const QString selectedAgendaId = d->mAgenda->lastSelectedItemId();
+  const QString selectedAllDayAgendaId = d->mAllDayAgenda->lastSelectedItemId();
 
   enableAgendaUpdate( true );
   d->clearView();
@@ -1684,17 +1730,16 @@ void AgendaView::fillAgenda()
   setChanges( NothingChanged );
 
   bool somethingReselected = false;
-  const KCalCore::Incidence::List incidences = calendar()->incidences();
+  const KCalCore::Incidence::List incidences = d->mViewCalendar->incidences();
 
   foreach ( const KCalCore::Incidence::Ptr &incidence, incidences ) {
     Q_ASSERT( incidence );
-    Akonadi::Item aitem = calendar()->item( incidence );
-    const bool wasSelected = aitem.id() == selectedAgendaId  ||
-                             aitem.id() == selectedAllDayAgendaId;
+      const bool wasSelected = incidence->uid() == selectedAgendaId  ||
+                               incidence->uid() == selectedAllDayAgendaId;
 
     if ( ( incidence->allDay() && d->mUpdateAllDayAgenda ) ||
           ( !incidence->allDay() && d->mUpdateAgenda ) ) {
-      displayIncidence( aitem, wasSelected );
+      displayIncidence( incidence, wasSelected );
     }
 
     if ( wasSelected ) {
@@ -1719,19 +1764,18 @@ void AgendaView::fillAgenda()
   }
 }
 
-bool AgendaView::displayIncidence( const Akonadi::Item &aitem, bool createSelected )
+bool AgendaView::displayIncidence( const  KCalCore::Incidence::Ptr &incidence, bool createSelected )
 {
-  KCalCore::Incidence::Ptr incidence = CalendarSupport::incidence( aitem );
   if ( !incidence || incidence->hasRecurrenceId() ) {
     return false;
   }
 
-  KCalCore::Todo::Ptr todo = CalendarSupport::todo( aitem );
+  KCalCore::Todo::Ptr todo = CalendarSupport::todo( incidence );
   if ( todo && ( !preferences()->showTodosAgendaView() || !todo->hasDueDate() ) ) {
     return false;
   }
 
-  KCalCore::Event::Ptr event = CalendarSupport::event( aitem );
+  KCalCore::Event::Ptr event = CalendarSupport::event( incidence );
   const QDate today = QDate::currentDate();
   KCalCore::DateTimeList::iterator t;
 
@@ -1789,7 +1833,7 @@ bool AgendaView::displayIncidence( const Akonadi::Item &aitem, bool createSelect
       if ( occurrenceDate.date() == today ) {
         alreadyAddedToday = true;
       }
-      d->insertIncidence( item, occurrenceDate, createSelected );
+      d->insertIncidence( incidence, occurrenceDate, createSelected );
     }
 
   } else {
@@ -1844,7 +1888,7 @@ bool AgendaView::displayIncidence( const Akonadi::Item &aitem, bool createSelect
       busyEvents.append( event );
     }
 
-    d->insertIncidence( aitem, t->toTimeSpec( timeSpec ), createSelected );
+    d->insertIncidence( incidence, t->toTimeSpec( timeSpec ), createSelected );
   }
 
   // Can be multiday
@@ -1972,6 +2016,21 @@ void AgendaView::slotIncidencesDropped( const KCalCore::Incidence::List &inciden
     }
   }
 }
+
+void AgendaView::startDrag(const KCalCore::Incidence::Ptr &incidence)
+{
+  if ( !calendar() ) {
+    kError() << "No Calendar set";
+    return;
+  }
+
+  const Akonadi::Item item = d->mViewCalendar->item(incidence);
+  if (item.isValid()) {
+    startDrag(item);
+  }
+}
+
+
 void AgendaView::startDrag( const Akonadi::Item &incidence )
 {
   if ( !calendar() ) {
@@ -2114,8 +2173,8 @@ void AgendaView::removeIncidence( const KCalCore::Incidence::Ptr &incidence )
   d->mAllDayAgenda->removeIncidence( incidence );
   d->mAgenda->removeIncidence( incidence );
 
-  if ( !incidence->hasRecurrenceId() ) {
-    KCalCore::Incidence::List exceptions = calendar()->instances( incidence );
+  if ( !incidence->hasRecurrenceId() && d->mViewCalendar->isValid(incidence)) {
+    KCalCore::Incidence::List exceptions = d->mViewCalendar->findCalendar(incidence)->getCalendar()->instances( incidence );
     foreach ( const KCalCore::Incidence::Ptr &exception, exceptions ) {
       if ( exception->allDay() ) {
         d->mAllDayAgenda->removeIncidence( exception );
@@ -2166,16 +2225,22 @@ QSplitter *AgendaView::splitter() const
   return d->mSplitterAgenda;
 }
 
-bool AgendaView::filterByCollectionSelection( const Akonadi::Item &incidence )
+bool AgendaView::filterByCollectionSelection( const KCalCore::Incidence::Ptr &incidence )
 {
+  const Akonadi::Item item = d->mViewCalendar->item(incidence);
+
+  if (!item.isValid()) {
+    return true;
+  }
+
   if ( customCollectionSelection() ) {
-    return customCollectionSelection()->contains( incidence.parentCollection().id() );
+    return customCollectionSelection()->contains(item.parentCollection().id() );
   }
 
   if ( collectionId() < 0 ) {
     return true;
   } else {
-    return collectionId() == incidence.storageCollectionId();
+    return collectionId() == item.storageCollectionId();
   }
 }
 
diff --git a/calendarviews/agenda/agendaview.h b/calendarviews/agenda/agendaview.h
index 206a1ba..e8e0b99 100644
--- a/calendarviews/agenda/agendaview.h
+++ b/calendarviews/agenda/agendaview.h
@@ -28,6 +28,7 @@
 
 #include "eventviews_export.h"
 #include "eventview.h"
+#include "viewcalendar.h"
 
 #include <KCalCore/Todo>
 
@@ -135,6 +136,7 @@ class EVENTVIEWS_EXPORT AgendaView : public EventView
 
     /* reimp from EventView */
     virtual void setCalendar( const Akonadi::ETMCalendar::Ptr &cal );
+    virtual void addCalendar( const ViewCalendar::Ptr &cal);
 
     QSplitter *splitter() const;
 
@@ -164,6 +166,7 @@ class EVENTVIEWS_EXPORT AgendaView : public EventView
 
     void clearSelection();
 
+    void startDrag( const KCalCore::Incidence::Ptr & );
     void startDrag( const Akonadi::Item & );
 
     void readSettings();
@@ -239,11 +242,18 @@ class EVENTVIEWS_EXPORT AgendaView : public EventView
 
     void alignAgendas();
 
+  private slots:
+    void slotIncidenceSelected(const KCalCore::Incidence::Ptr &incidence, QDate date);
+    void slotShowIncidencePopup(const KCalCore::Incidence::Ptr &incidence, QDate date);
+    void slotEditIncidence(const KCalCore::Incidence::Ptr &incidence);
+    void slotShowIncidence(const KCalCore::Incidence::Ptr &incidence);
+    void slotDeleteIncidence(const KCalCore::Incidence::Ptr &incidence);
+
   private:
     void init( const QDate &start, const QDate &end );
-    bool filterByCollectionSelection( const Akonadi::Item &incidence );
+    bool filterByCollectionSelection( const  KCalCore::Incidence::Ptr &incidence );
     void setupTimeLabel( TimeLabels *timeLabel );
-    bool displayIncidence( const Akonadi::Item &incidence, bool createSelected );
+    bool displayIncidence( const KCalCore::Incidence::Ptr &incidence, bool createSelected );
 
 #ifndef EVENTVIEWS_NODECOS
     typedef QList<EventViews::CalendarDecoration::Decoration *> DecorationList;
diff --git a/calendarviews/agenda/viewcalendar.cpp b/calendarviews/agenda/viewcalendar.cpp
new file mode 100644
index 0000000..595c783
--- /dev/null
+++ b/calendarviews/agenda/viewcalendar.cpp
@@ -0,0 +1,169 @@
+#include "viewcalendar.h"
+#include "agendaview.h"
+#include "helper.h"
+
+#include <calendarsupport/utils.h>
+
+using namespace EventViews;
+
+ViewCalendar::~ViewCalendar()
+{
+}
+
+MultiViewCalendar::~MultiViewCalendar()
+{
+}
+
+KCalCore::Calendar::Ptr MultiViewCalendar::getCalendar() const
+{
+    return KCalCore::Calendar::Ptr();
+}
+
+KCalCore::Incidence::List MultiViewCalendar::incidences() const
+{
+    KCalCore::Incidence::List list;
+    foreach(const ViewCalendar::Ptr &cal, mSubCalendars) {
+        if (cal->getCalendar()) {
+            list += cal->getCalendar()->incidences();
+        }
+    }
+    return list;
+}
+
+int MultiViewCalendar::calendars() const
+{
+    return mSubCalendars.size();
+}
+
+
+ViewCalendar::Ptr MultiViewCalendar::findCalendar(const KCalCore::Incidence::Ptr &incidence) const
+{
+    foreach(const ViewCalendar::Ptr &cal, mSubCalendars) {
+        if (cal->isValid(incidence)) {
+            return cal;
+        }
+    }
+    return ViewCalendar::Ptr();
+}
+
+void MultiViewCalendar::addCalendar(const ViewCalendar::Ptr &calendar)
+{
+    if (!mSubCalendars.contains(calendar)) {
+        mSubCalendars.append(calendar);
+    }
+}
+
+void MultiViewCalendar::setETMCalendar(const Akonadi::ETMCalendar::Ptr &calendar)
+{
+    if (!mETMCalendar) {
+        mETMCalendar = AkonadiViewCalendar::Ptr(new AkonadiViewCalendar);
+        mETMCalendar->mAgendaView = mAgendaView;
+    }
+    mETMCalendar->mCalendar = calendar;
+    addCalendar(mETMCalendar);
+}
+
+QString MultiViewCalendar::displayName(const KCalCore::Incidence::Ptr &incidence) const
+{
+    ViewCalendar::Ptr cal = findCalendar(incidence);
+    if (cal) {
+        return cal->displayName(incidence);
+    }
+    return QString();
+}
+
+QString MultiViewCalendar::iconForIncidence(const KCalCore::Incidence::Ptr &incidence) const
+{
+    ViewCalendar::Ptr cal = findCalendar(incidence);
+    if (cal) {
+        return cal->iconForIncidence(incidence);
+    }
+    return QString();
+}
+
+bool MultiViewCalendar::isValid(const KCalCore::Incidence::Ptr &incidence) const
+{
+    ViewCalendar::Ptr cal = findCalendar(incidence);
+    return cal;
+}
+
+QColor MultiViewCalendar::resourceColor(const KCalCore::Incidence::Ptr &incidence) const
+{
+    ViewCalendar::Ptr cal = findCalendar(incidence);
+    if (cal) {
+        return cal->resourceColor(incidence);
+    }
+    return QColor();
+}
+
+Akonadi::Item MultiViewCalendar::item(const KCalCore::Incidence::Ptr &incidence) const
+{
+    if (mETMCalendar->isValid(incidence)) {
+        return mETMCalendar->item(incidence);
+    }
+
+    return Akonadi::Item();
+}
+
+AkonadiViewCalendar::~AkonadiViewCalendar()
+{
+}
+
+bool AkonadiViewCalendar::isValid(const KCalCore::Incidence::Ptr &incidence) const
+{
+    if (!mCalendar) {
+        return false;
+    }
+
+    if (item(incidence).isValid()) {
+        return true;
+    }
+    return false;
+}
+
+Akonadi::Item AkonadiViewCalendar::item(const KCalCore::Incidence::Ptr &incidence) const
+{
+    if (!mCalendar) {
+        return Akonadi::Item();
+    }
+    bool ok = false;
+    Akonadi::Item::Id id = incidence->customProperty("VOLATILE", "AKONADI-ID").toLongLong(&ok);
+
+    if (id == -1 || !ok) {
+        id = mCalendar->item(incidence).id();
+
+        if (id == -1) {
+            // Ok, we really don't know the ID, give up.
+            kWarning() << "Agenda::removeIncidence() Item to remove is invalid. uid = "
+                       << incidence->instanceIdentifier();
+            return Akonadi::Item();
+        }
+        return mCalendar->item(incidence->instanceIdentifier());
+    }
+    return mCalendar->item(id);
+}
+
+QString AkonadiViewCalendar::displayName(const KCalCore::Incidence::Ptr &incidence) const
+{
+    return CalendarSupport::displayName( mCalendar.data(), item(incidence).parentCollection() );
+}
+
+QColor AkonadiViewCalendar::resourceColor(const KCalCore::Incidence::Ptr &incidence) const
+{
+    return EventViews::resourceColor( item(incidence), mAgendaView->preferences() );
+}
+
+QString AkonadiViewCalendar::iconForIncidence(const KCalCore::Incidence::Ptr &incidence) const
+{
+    return mAgendaView->iconForItem(item(incidence));
+}
+
+KDateTime::Spec AkonadiViewCalendar::timeSpec() const
+{
+    return mCalendar->timeSpec();
+}
+
+KCalCore::Calendar::Ptr AkonadiViewCalendar::getCalendar() const
+{
+    return mCalendar;
+}
diff --git a/calendarviews/agenda/viewcalendar.h b/calendarviews/agenda/viewcalendar.h
new file mode 100644
index 0000000..53551e5
--- /dev/null
+++ b/calendarviews/agenda/viewcalendar.h
@@ -0,0 +1,103 @@
+/*
+Copyright (c) 2014 Sandro Knauß <knauss 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 EVENTVIEWS_VIEWCALENDAR_H
+#define EVENTVIEWS_VIEWCALENDAR_H
+
+#include "eventviews_export.h"
+
+#include <Akonadi/Item>
+#include <Akonadi/Calendar/ETMCalendar>
+#include <KCalCore/Incidence>
+
+#include <QColor>
+#include <QList>
+
+namespace EventViews {
+
+class AgendaView;
+
+class EVENTVIEWS_EXPORT ViewCalendar {
+
+public:
+  typedef QSharedPointer<ViewCalendar> Ptr;
+
+  virtual ~ViewCalendar();
+  virtual bool isValid(const KCalCore::Incidence::Ptr &incidence) const=0;
+  virtual QString displayName(const KCalCore::Incidence::Ptr &incidence) const=0;
+
+  virtual QColor resourceColor(const KCalCore::Incidence::Ptr &incidence) const=0;
+  virtual QString iconForIncidence(const KCalCore::Incidence::Ptr &incidence) const=0;
+
+  virtual KCalCore::Calendar::Ptr getCalendar() const=0;
+};
+
+
+class EVENTVIEWS_EXPORT AkonadiViewCalendar: public ViewCalendar {
+public:
+    typedef QSharedPointer<AkonadiViewCalendar> Ptr;
+
+    virtual ~AkonadiViewCalendar();
+    virtual bool isValid(const KCalCore::Incidence::Ptr &incidence) const;
+    virtual QString displayName(const KCalCore::Incidence::Ptr &incidence) const;
+
+    virtual QColor resourceColor(const KCalCore::Incidence::Ptr &incidence) const;
+    virtual QString iconForIncidence(const KCalCore::Incidence::Ptr &incidence) const;
+
+    virtual Akonadi::Item item(const KCalCore::Incidence::Ptr &incidence) const;
+
+    virtual KCalCore::Calendar::Ptr getCalendar() const;
+
+    KDateTime::Spec timeSpec() const;
+
+    Akonadi::ETMCalendar::Ptr mCalendar;
+    AgendaView *mAgendaView;
+};
+
+class EVENTVIEWS_EXPORT MultiViewCalendar {
+public:
+    typedef QSharedPointer<MultiViewCalendar> Ptr;
+
+    virtual ~MultiViewCalendar();
+    ViewCalendar::Ptr findCalendar(const KCalCore::Incidence::Ptr &incidence) const;
+    virtual bool isValid(const KCalCore::Incidence::Ptr &incidence) const;
+    virtual QString displayName(const KCalCore::Incidence::Ptr &incidence) const;
+
+    virtual QColor resourceColor(const KCalCore::Incidence::Ptr &incidence) const;
+    virtual QString iconForIncidence(const KCalCore::Incidence::Ptr &incidence) const;
+
+    virtual Akonadi::Item item(const KCalCore::Incidence::Ptr &incidence) const;
+
+    void addCalendar(const ViewCalendar::Ptr &calendar);
+    void setETMCalendar(const Akonadi::ETMCalendar::Ptr &calendar);
+    int calendars() const;
+    KCalCore::Calendar::Ptr getCalendar() const;
+    KCalCore::Incidence::List incidences() const;
+
+    AgendaView *mAgendaView;
+    AkonadiViewCalendar::Ptr mETMCalendar;
+    QList<ViewCalendar::Ptr> mSubCalendars;
+};
+
+
+}
+
+#endif
\ No newline at end of file


commit 03f23911254a82be13f15c39906bd71d1c25c274
Author: Sandro Knauß <knauss at kolabsys.com>
Date:   Mon Sep 15 16:19:16 2014 +0200

    CalenderSupport: handles now also KCalCore::Incidence::Ptr [1/2]
    
    need for CalendarViews: Get rid of Akonadi::Item in Agendaview [2/2]

diff --git a/calendarsupport/utils.cpp b/calendarsupport/utils.cpp
index 481de05..cdf0a0e 100644
--- a/calendarsupport/utils.cpp
+++ b/calendarsupport/utils.cpp
@@ -87,7 +87,7 @@ KCalCore::Event::Ptr CalendarSupport::event( const Akonadi::Item &item )
   //relying on exception for performance reasons
   try {
     KCalCore::Incidence::Ptr incidence = item.payload<KCalCore::Incidence::Ptr>();
-    if ( incidence && incidence->type() == KCalCore::Incidence::TypeEvent ) {
+    if ( hasEvent(incidence) ) {
       return item.payload<KCalCore::Event::Ptr>();
     }
   } catch( Akonadi::PayloadException ) {
@@ -96,6 +96,14 @@ KCalCore::Event::Ptr CalendarSupport::event( const Akonadi::Item &item )
   return KCalCore::Event::Ptr();
 }
 
+KCalCore::Event::Ptr CalendarSupport::event(const KCalCore::Incidence::Ptr &incidence)
+{
+    if (hasEvent(incidence)) {
+        return incidence.dynamicCast<KCalCore::Event>();
+    }
+    return KCalCore::Event::Ptr();
+}
+
 KCalCore::Event::List CalendarSupport::eventsFromItems( const Akonadi::Item::List &items )
 {
   KCalCore::Event::List events;
@@ -122,7 +130,7 @@ KCalCore::Todo::Ptr CalendarSupport::todo( const Akonadi::Item &item )
 {
   try {
     KCalCore::Incidence::Ptr incidence = item.payload<KCalCore::Incidence::Ptr>();
-    if ( incidence && incidence->type() == KCalCore::Incidence::TypeTodo ) {
+    if ( hasTodo(incidence) ) {
       return item.payload<KCalCore::Todo::Ptr>();
     }
   } catch( Akonadi::PayloadException ) {
@@ -131,11 +139,19 @@ KCalCore::Todo::Ptr CalendarSupport::todo( const Akonadi::Item &item )
   return KCalCore::Todo::Ptr();
 }
 
+KCalCore::Todo::Ptr CalendarSupport::todo(const KCalCore::Incidence::Ptr &incidence)
+{
+    if (hasTodo(incidence)) {
+        return incidence.dynamicCast<KCalCore::Todo>();
+    }
+    return KCalCore::Todo::Ptr();
+}
+
 KCalCore::Journal::Ptr CalendarSupport::journal( const Akonadi::Item &item )
 {
   try {
     KCalCore::Incidence::Ptr incidence = item.payload<KCalCore::Incidence::Ptr>();
-    if ( incidence && incidence->type() == KCalCore::Incidence::TypeJournal ) {
+    if ( hasJournal(incidence) ) {
       return item.payload<KCalCore::Journal::Ptr>();
     }
   } catch( Akonadi::PayloadException ) {
@@ -144,6 +160,14 @@ KCalCore::Journal::Ptr CalendarSupport::journal( const Akonadi::Item &item )
   return KCalCore::Journal::Ptr();
 }
 
+KCalCore::Journal::Ptr CalendarSupport::journal(const KCalCore::Incidence::Ptr &incidence)
+{
+    if (hasJournal(incidence)) {
+        return incidence.dynamicCast<KCalCore::Journal>();
+    }
+    return KCalCore::Journal::Ptr();
+}
+
 bool CalendarSupport::hasIncidence( const Akonadi::Item &item )
 {
   return item.hasPayload<KCalCore::Incidence::Ptr>();
@@ -154,16 +178,31 @@ bool CalendarSupport::hasEvent( const Akonadi::Item &item )
   return item.hasPayload<KCalCore::Event::Ptr>();
 }
 
+bool CalendarSupport::hasEvent(const KCalCore::Incidence::Ptr &incidence)
+{
+    return incidence && incidence->type() ==  KCalCore::Incidence::TypeEvent;
+}
+
 bool CalendarSupport::hasTodo( const Akonadi::Item &item )
 {
   return item.hasPayload<KCalCore::Todo::Ptr>();
 }
 
+bool CalendarSupport::hasTodo(const KCalCore::Incidence::Ptr &incidence)
+{
+    return incidence && incidence->type() ==  KCalCore::Incidence::TypeTodo;
+}
+
 bool CalendarSupport::hasJournal( const Akonadi::Item &item )
 {
   return item.hasPayload<KCalCore::Journal::Ptr>();
 }
 
+bool CalendarSupport::hasJournal(const KCalCore::Incidence::Ptr &incidence)
+{
+    return incidence && incidence->type() ==  KCalCore::Incidence::TypeJournal;
+}
+
 QMimeData *CalendarSupport::createMimeData( const Akonadi::Item::List &items,
                                             const KDateTime::Spec &timeSpec )
 {
diff --git a/calendarsupport/utils.h b/calendarsupport/utils.h
index e96856a..d3f4567 100644
--- a/calendarsupport/utils.h
+++ b/calendarsupport/utils.h
@@ -72,6 +72,11 @@ namespace CalendarSupport {
   CALENDARSUPPORT_EXPORT KCalCore::Event::Ptr event( const Akonadi::Item &item );
 
   /**
+   * returns the event from an incidence, or a null pointer if the item has no such payload
+   */
+  CALENDARSUPPORT_EXPORT KCalCore::Event::Ptr event( const KCalCore::Incidence::Ptr &incidence );
+
+  /**
    * returns event pointers from an akonadi item, or a null pointer if the item has no such payload
    */
   CALENDARSUPPORT_EXPORT KCalCore::Event::List eventsFromItems( const Akonadi::Item::List &items );
@@ -88,11 +93,21 @@ namespace CalendarSupport {
   CALENDARSUPPORT_EXPORT KCalCore::Todo::Ptr todo( const Akonadi::Item &item );
 
   /**
+   * returns the todo from an incidence, or a null pointer if the item has no such payload
+   */
+  CALENDARSUPPORT_EXPORT KCalCore::Todo::Ptr todo( const  KCalCore::Incidence::Ptr &incidence );
+
+  /**
    * returns the journal from an akonadi item, or a null pointer if the item has no such payload
    */
   CALENDARSUPPORT_EXPORT KCalCore::Journal::Ptr journal( const Akonadi::Item &item );
 
   /**
+   * returns the journal from an incidence, or a null pointer if the item has no such payload
+   */
+  CALENDARSUPPORT_EXPORT KCalCore::Journal::Ptr journal( const KCalCore::Incidence::Ptr &incidence );
+
+  /**
    * returns whether an Akonadi item contains an incidence
    */
   CALENDARSUPPORT_EXPORT bool hasIncidence( const Akonadi::Item &item );
@@ -103,16 +118,31 @@ namespace CalendarSupport {
   CALENDARSUPPORT_EXPORT bool hasEvent( const Akonadi::Item &item );
 
   /**
+   * returns whether an incidence contains an event
+   */
+  CALENDARSUPPORT_EXPORT bool hasEvent( const KCalCore::Incidence::Ptr &incidence );
+
+  /**
    * returns whether an Akonadi item contains a todo
    */
   CALENDARSUPPORT_EXPORT bool hasTodo( const Akonadi::Item &item );
 
   /**
+   * returns whether an incidence contains a todo
+   */
+  CALENDARSUPPORT_EXPORT bool hasTodo( const KCalCore::Incidence::Ptr &incidence );
+
+  /**
    * returns whether an Akonadi item contains a journal
    */
   CALENDARSUPPORT_EXPORT bool hasJournal( const Akonadi::Item &item );
 
   /**
+   * returns whether an incidence contains a journal
+   */
+  CALENDARSUPPORT_EXPORT bool hasJournal( const KCalCore::Incidence::Ptr &incidence );
+
+  /**
    * returns whether this item can be deleted
    */
   CALENDARSUPPORT_EXPORT bool hasDeleteRights( const Akonadi::Item &item );


commit 8417d9af6a38a586749f0399c9145ac2057c8670
Author: Sandro Knauß <knauss at kolabsys.com>
Date:   Tue Sep 2 16:34:41 2014 +0200

    CalendarSupport: show displayName if available for collections

diff --git a/calendarsupport/utils.cpp b/calendarsupport/utils.cpp
index b398959..481de05 100644
--- a/calendarsupport/utils.cpp
+++ b/calendarsupport/utils.cpp
@@ -622,7 +622,9 @@ QString CalendarSupport::displayName( Akonadi::ETMCalendar *calendar, const Akon
   const QString dName = fullCollection.displayName();
 
   if ( !dName.isEmpty() ) {
-    return fullCollection.name().startsWith( QLatin1String( "akonadi_" ) ) ? i18n( "My %1", dName ) : fullCollection.name();
+    return fullCollection.name().startsWith( QLatin1String( "akonadi_" ) ) ? i18n( "My %1", dName ) : dName;
+  } else if ( !fullCollection.name().isEmpty() ) {
+    return fullCollection.name();
   } else {
     return i18nc( "unknown resource", "Unknown" );
   }


commit f73efcb672c86b984e9820f8b0182046bebe7db8
Author: Sandro Knauß <knauss at kolabsys.com>
Date:   Tue Sep 2 15:27:06 2014 +0200

    CalendarViews: show color for parent Collection

diff --git a/calendarviews/helper.cpp b/calendarviews/helper.cpp
index 50d868d..8ca2b62 100644
--- a/calendarviews/helper.cpp
+++ b/calendarviews/helper.cpp
@@ -51,7 +51,7 @@ QColor EventViews::resourceColor( const Akonadi::Item &item, const PrefsPtr &pre
   if ( !item.isValid() ) {
     return QColor();
   }
-  const QString id = QString::number( item.storageCollectionId() );
+  const QString id = QString::number( item.parentCollection().id() );
   return preferences->resourceColor( id );
 }
 
diff --git a/calendarviews/month/monthitem.cpp b/calendarviews/month/monthitem.cpp
index 1872617..364c1cd 100644
--- a/calendarviews/month/monthitem.cpp
+++ b/calendarviews/month/monthitem.cpp
@@ -629,13 +629,7 @@ QColor IncidenceMonthItem::bgColor() const
     if ( prefs->monthViewColors() == PrefsBase::MonthItemResourceOnly ||
          prefs->monthViewColors() == PrefsBase::MonthItemResourceInsideCategoryOutside ) {
 
-      const QString id = QString::number( akonadiItem().storageCollectionId() );
-      if ( id.isEmpty() ) {
-        // item got removed from calendar, give up.
-        return QColor();
-      }
-
-      bgColor = monthScene()->monthView()->preferences()->resourceColor( id );
+      bgColor = EventViews::resourceColor(akonadiItem(), prefs);
     } else {
       bgColor = catColor();
     }
@@ -658,10 +652,7 @@ QColor IncidenceMonthItem::frameColor() const
        ( mIncidence->categories().isEmpty() && prefs->monthViewColors() ==
          PrefsBase::MonthItemResourceInsideCategoryOutside ) ) {
     Q_ASSERT( mIncidence );
-    const QString id = QString::number( akonadiItem().storageCollectionId() );
-    if ( !id.isEmpty() ) {
-      frameColor = prefs->resourceColor( id );
-    }
+    frameColor = EventViews::resourceColor(akonadiItem(), prefs);
   } else {
     frameColor = catColor();
   }


commit 3188364ca92e77e926a8fd043067bbe53de30ac5
Author: Sandro Knauß <knauss at kolabsys.com>
Date:   Wed Sep 10 23:55:21 2014 +0200

    IncidenceEditor-ng: Initalize currectAction with None to not trigger load two times

diff --git a/incidenceeditor-ng/editoritemmanager.cpp b/incidenceeditor-ng/editoritemmanager.cpp
index 97105db..20ddc7e 100644
--- a/incidenceeditor-ng/editoritemmanager.cpp
+++ b/incidenceeditor-ng/editoritemmanager.cpp
@@ -77,6 +77,7 @@ class ItemEditorPrivate
 
 ItemEditorPrivate::ItemEditorPrivate( Akonadi::IncidenceChanger *changer, EditorItemManager *qq )
   : q_ptr( qq ), mItemMonitor( 0 ), mIsCounterProposal( false )
+  , currentAction(EditorItemManager::None)
 {
   mFetchScope.fetchFullPayload();
   mFetchScope.setAncestorRetrieval( Akonadi::ItemFetchScope::Parent );


commit b2e300e70c44938e09f0bb221fa367a975b17ac8
Author: Sandro Knauß <knauss at kolabsys.com>
Date:   Tue Sep 2 15:03:32 2014 +0200

    IncidenceEditor-ng: Use stoargeCollection to store an incidence and not parentCollection.

diff --git a/incidenceeditor-ng/editoritemmanager.cpp b/incidenceeditor-ng/editoritemmanager.cpp
index 0cc4314..97105db 100644
--- a/incidenceeditor-ng/editoritemmanager.cpp
+++ b/incidenceeditor-ng/editoritemmanager.cpp
@@ -333,7 +333,8 @@ void EditorItemManager::save()
     KCalCore::Incidence::Ptr incidence = CalendarSupport::incidence( d->mItem );
 
     KCalCore::Incidence::Ptr oldPayload = CalendarSupport::incidence( d->mPrevItem );
-    if ( d->mItem.parentCollection() == d->mItemUi->selectedCollection() ) {
+    if ( d->mItem.parentCollection() == d->mItemUi->selectedCollection()
+         || d->mItem.storageCollectionId() == d->mItemUi->selectedCollection().id()) {
       d->mChanger->modifyIncidence( d->mItem, oldPayload );
     } else {
       Q_ASSERT( d->mItemUi->selectedCollection().isValid() );
diff --git a/incidenceeditor-ng/incidencedialog.cpp b/incidenceeditor-ng/incidencedialog.cpp
index b8dec82..dc82880 100644
--- a/incidenceeditor-ng/incidencedialog.cpp
+++ b/incidenceeditor-ng/incidencedialog.cpp
@@ -564,8 +564,8 @@ void IncidenceDialogPrivate::load( const Akonadi::Item &item )
   kDebug() << "Loading item " << item.id() << "; parent " << item.parentCollection().id()
            << "; storage " << item.storageCollectionId();
 
-  if ( item.parentCollection().isValid() ) {
-    mCalSelector->setDefaultCollection( item.parentCollection() );
+  if ( item.storageCollectionId() > -1 ) {
+    mCalSelector->setDefaultCollection(Akonadi::Collection(item.storageCollectionId()));
   }
 
   if ( !mCalSelector->mimeTypeFilter().contains( "text/calendar" ) ||


commit cfd8bd8dcc3866bd4ca836148463770221ce49ad
Author: Sandro Knauß <knauss at kolabsys.com>
Date:   Fri Sep 12 13:42:32 2014 +0200

    IncidenceEditor-ng: Do not run a movejob, if access items through search collections

diff --git a/incidenceeditor-ng/editoritemmanager.cpp b/incidenceeditor-ng/editoritemmanager.cpp
index 0d57318..0cc4314 100644
--- a/incidenceeditor-ng/editoritemmanager.cpp
+++ b/incidenceeditor-ng/editoritemmanager.cpp
@@ -167,7 +167,8 @@ void ItemEditorPrivate::onModifyFinished( int, const Akonadi::Item &item,
 {
   Q_Q( EditorItemManager );
   if ( resultCode == Akonadi::IncidenceChanger::ResultCodeSuccess ) {
-    if ( mItem.parentCollection() == mItemUi->selectedCollection() ) {
+    if ( mItem.parentCollection() == mItemUi->selectedCollection() ||
+         mItem.storageCollectionId() == mItemUi->selectedCollection().id()) {
       mItem = item;
       emit q->itemSaveFinished( EditorItemManager::Modify );
       setupMonitor();


commit 413bf5c610e758d5095ed41719b6c93d6dacd700
Author: Sandro Knauß <knauss at kolabsys.com>
Date:   Wed Sep 3 13:06:38 2014 +0200

    plugins/messageviewer: Added postpone button for invitations in kmail

diff --git a/plugins/messageviewer/bodypartformatter/text_calendar.cpp b/plugins/messageviewer/bodypartformatter/text_calendar.cpp
index de735ba..a285c04 100644
--- a/plugins/messageviewer/bodypartformatter/text_calendar.cpp
+++ b/plugins/messageviewer/bodypartformatter/text_calendar.cpp
@@ -308,6 +308,9 @@ static QString directoryForStatus( Attendee::PartStat status )
   case Attendee::Delegated:
     dir = QLatin1String( "delegated" );
     break;
+  case Attendee::NeedsAction:
+    dir = QLatin1String( "request" );
+    break;
   default:
     break;
   }
@@ -979,7 +982,7 @@ class UrlHandler : public Interface::BodyPartURLHandler
 
       // find our delegator, we need to inform him as well
       QString delegator;
-      if ( myself && !myself->delegator().isEmpty() ) {
+      if ( status !=  Attendee::NeedsAction && myself && !myself->delegator().isEmpty() ) {
         Attendee::List attendees = incidence->attendees();
         Attendee::List::ConstIterator end = attendees.constEnd();
         for ( Attendee::List::ConstIterator it = attendees.constBegin();
@@ -993,7 +996,7 @@ class UrlHandler : public Interface::BodyPartURLHandler
         }
       }
 
-      if ( ( myself && myself->RSVP() ) || heuristicalRSVP( incidence ) ) {
+      if ( status !=  Attendee::NeedsAction && ( ( myself && myself->RSVP() ) || heuristicalRSVP( incidence ) ) ) {
         Attendee::Ptr newMyself = setStatusOnMyself( incidence, myself, status, receiver );
         if ( newMyself && status == Attendee::Delegated ) {
           newMyself->setDelegate( delegateString );
@@ -1009,7 +1012,7 @@ class UrlHandler : public Interface::BodyPartURLHandler
             ok = mail( viewerInstance, incidence, dir, iTIPReply, receiver, delegator );
           }
         }
-      } else if ( !myself && ( status != Attendee::Declined ) ) {
+      } else if ( !myself && ( status != Attendee::Declined && status !=  Attendee::NeedsAction ) ) {
         // forwarded invitation
         QString name;
         QString email;
@@ -1271,6 +1274,9 @@ class UrlHandler : public Interface::BodyPartURLHandler
       else if ( path == QLatin1String( "decline" ) ) {
         result = handleInvitation( iCal, Attendee::Declined, part, viewerInstance );
       }
+      else if ( path == QLatin1String( "postpone" ) ) {
+        result = handleInvitation( iCal, Attendee::NeedsAction, part, viewerInstance );
+      }
       else if ( path == QLatin1String( "decline_counter" ) ) {
         result = handleDeclineCounter( iCal, part, viewerInstance );
       }
@@ -1422,6 +1428,9 @@ class UrlHandler : public Interface::BodyPartURLHandler
         else if ( path == QLatin1String("decline" ) ) {
           return i18n( "Decline invitation" );
         }
+        else if ( path == QLatin1String("postpone" ) ) {
+          return i18n( "Postpone" );
+        }
         else if ( path == QLatin1String("decline_counter" ) ) {
           return i18n( "Decline counter proposal" );
         }
@@ -1457,11 +1466,11 @@ class UrlHandler : public Interface::BodyPartURLHandler
 
     bool askForComment( Attendee::PartStat status ) const
     {
-      if ( ( status != Attendee::Accepted &&
+      if ( status !=  Attendee::NeedsAction && ( ( status != Attendee::Accepted &&
              GlobalSettings::self()->askForCommentWhenReactingToInvitation() ==
              GlobalSettings::EnumAskForCommentWhenReactingToInvitation::AskForAllButAcceptance ) ||
            ( GlobalSettings::self()->askForCommentWhenReactingToInvitation() ==
-             GlobalSettings::EnumAskForCommentWhenReactingToInvitation::AlwaysAsk ) ) {
+             GlobalSettings::EnumAskForCommentWhenReactingToInvitation::AlwaysAsk ) ) ) {
         return true;
       }
       return false;


commit fb3505739dc6c5ee7e4699bd94593a210a3dba0e
Author: Sandro Knauß <knauss at kolabsys.com>
Date:   Thu Aug 28 14:01:34 2014 +0200

    korganizer: Add Search for Invitations,decliend events

diff --git a/korganizer/calendarview.cpp b/korganizer/calendarview.cpp
index 5d620f5..f2391e7 100644
--- a/korganizer/calendarview.cpp
+++ b/korganizer/calendarview.cpp
@@ -80,7 +80,15 @@
 #include <Akonadi/Control>
 #include <Akonadi/AttributeFactory>
 #include <Akonadi/Calendar/TodoPurger>
-
+#include <Akonadi/SearchCreateJob>
+#include <Akonadi/CollectionModifyJob>
+#include <Akonadi/SearchQuery>
+#include <akonadi/persistentsearchattribute.h>
+#include <akonadi/entitydisplayattribute.h>
+
+#include <KCalCore/Event>
+#include <KCalCore/Todo>
+#include <KCalCore/Journal>
 #include <KCalCore/CalFilter>
 #include <KCalCore/FileStorage>
 #include <KCalCore/ICalFormat>
@@ -90,7 +98,9 @@
 #include <KCalUtils/Stringify>
 #include <KCalUtils/DndFactory>
 
+#include <KPIMIdentities/IdentityManager>
 
+#include <klocalizedstring.h>
 #include <KFileDialog>
 #include <KNotification>
 #include <KRun>
@@ -104,7 +114,8 @@
 
 CalendarView::CalendarView( QWidget *parent ) : CalendarViewBase( parent ),
                                                 mCheckableProxyModel( 0 ),
-                                                mETMCollectionView( 0 )
+                                                mETMCollectionView( 0 ),
+                                                mIdentityManager(/*ro=*/ true)
 {
   Akonadi::Control::widgetNeedsAkonadi( this );
   mChanger = new Akonadi::IncidenceChanger( new IncidenceEditorNG::IndividualMailComponentFactory( this ), this );
@@ -118,6 +129,8 @@ CalendarView::CalendarView( QWidget *parent ) : CalendarViewBase( parent ),
   mCalendar = Akonadi::ETMCalendar::Ptr( new Akonadi::ETMCalendar( CalendarSupport::calendarSingleton() ) );
 
   mCalendar->setObjectName( QLatin1String("KOrg Calendar") );
+  connect(mCalendar->entityTreeModel(), SIGNAL(collectionTreeFetched(Akonadi::Collection::List)),
+          SLOT(onCheckVirtualCollections(Akonadi::Collection::List)));
   mCalendarClipboard = new Akonadi::CalendarClipboard( mCalendar, mChanger, this );
   mITIPHandler = new Akonadi::ITIPHandler( this );
   mITIPHandler->setCalendar( mCalendar );
@@ -261,6 +274,10 @@ CalendarView::CalendarView( QWidget *parent ) : CalendarViewBase( parent ),
   connect( this, SIGNAL(incidenceSelected(Akonadi::Item,QDate)),
            mEventViewer, SLOT(setIncidence(Akonadi::Item,QDate)) );
 
+   // IdentityManager
+   connect(&mIdentityManager, SIGNAL(changed()),
+            SLOT(onIdentitiesChanged()));
+
   //TODO: do a pretty Summary,
   QString s;
   s = i18n( "<p><em>No Item Selected</em></p>"
@@ -321,6 +338,99 @@ Akonadi::ETMCalendar::Ptr CalendarView::calendar() const
   return mCalendar;
 }
 
+void CalendarView::onCheckVirtualCollections(const Akonadi::Collection::List &collections)
+{
+    foreach(Akonadi::Collection col,  collections) {
+        kDebug() << "found collection:" << col.name();
+        if (col.name() == QLatin1String("OpenInvitations")) {
+            mOpenInvitationCollection = col;
+        } else if (col.name() == QLatin1String("DeclinedInvitations")) {
+            mDeclineCollection = col;
+        }
+    }
+    onIdentitiesChanged();
+}
+
+void CalendarView::onIdentitiesChanged()
+{
+    Akonadi::SearchQuery query;
+    foreach (const QString email, mIdentityManager.allEmails()) {
+        query.addTerm(Akonadi::IncidenceSearchTerm(Akonadi::IncidenceSearchTerm::PartStatus, QString(email+ QString::number(KCalCore::Attendee::NeedsAction))));
+    }
+    if (!mOpenInvitationCollection.isValid()) {
+        const QString name = QLatin1String("OpenInvitations");
+        Akonadi::SearchCreateJob *job = new Akonadi::SearchCreateJob(name, query);
+        job->setSearchMimeTypes(QStringList() << KCalCore::Event::eventMimeType()
+            << KCalCore::Todo::todoMimeType()
+            << KCalCore::Journal::journalMimeType());
+        connect(job, SIGNAL(result(KJob*)), SLOT(createSearchJobFinished(KJob*)));
+
+        kDebug() <<  "We have to create a OpenIncidence virtual Collection";
+    } else {
+        Akonadi::PersistentSearchAttribute *attribute = mOpenInvitationCollection.attribute<Akonadi::PersistentSearchAttribute>( Akonadi::Entity::AddIfMissing );
+        Akonadi::EntityDisplayAttribute *displayname  = mOpenInvitationCollection.attribute<Akonadi::EntityDisplayAttribute >( Akonadi::Entity::AddIfMissing );
+        attribute->setQueryString( QString::fromLatin1(query.toJSON()) );
+        displayname->setDisplayName(i18nc("A collection of all open invidation", "open invitations"));
+        Akonadi::CollectionModifyJob *job = new Akonadi::CollectionModifyJob( mOpenInvitationCollection, this );
+        connect( job, SIGNAL(result(KJob*)), this, SLOT(modifyResult(KJob*)) );
+        kDebug() <<  "updating OpenIncidence (" << mOpenInvitationCollection.id() << ") virtual Collection";
+        kDebug() <<  query.toJSON();
+    }
+
+    query = Akonadi::SearchQuery();
+    foreach (const QString email, mIdentityManager.allEmails()) {
+        query.addTerm(Akonadi::IncidenceSearchTerm(Akonadi::IncidenceSearchTerm::PartStatus, QString(email+ QString::number(KCalCore::Attendee::Declined))));
+    }
+    if (!mDeclineCollection.isValid()) {
+        const QString name = QLatin1String("DeclinedInvitations");
+        Akonadi::SearchCreateJob *job = new Akonadi::SearchCreateJob(name, query);
+        job->setSearchMimeTypes(QStringList() << KCalCore::Event::eventMimeType()
+            << KCalCore::Todo::todoMimeType()
+            << KCalCore::Journal::journalMimeType());
+        connect(job, SIGNAL(result(KJob*)), SLOT(createSearchJobFinished(KJob*)));
+
+        kDebug() <<  "We have to create a DeclinedIncidence virtual Collection";
+    } else {
+        Akonadi::PersistentSearchAttribute *persistentsearch = mDeclineCollection.attribute<Akonadi::PersistentSearchAttribute >( Akonadi::Entity::AddIfMissing );
+        Akonadi::EntityDisplayAttribute *displayname  = mDeclineCollection.attribute<Akonadi::EntityDisplayAttribute >( Akonadi::Entity::AddIfMissing );
+
+        persistentsearch->setQueryString( QString::fromLatin1(query.toJSON()) );
+        displayname->setDisplayName(i18nc("A collection of all declined invidation", "decliend invitations"));
+        Akonadi::CollectionModifyJob *job = new Akonadi::CollectionModifyJob( mDeclineCollection, this );
+        connect( job, SIGNAL(result(KJob*)), this, SLOT(modifyResult(KJob*)) );
+        kDebug() <<  "updating DeclinedIncidence(" << mDeclineCollection.id() << ") virtual Collection";
+        kDebug() <<  query.toJSON();
+    }
+}
+
+
+void CalendarView::modifyResult(KJob* job)
+{
+    if (job->error()) {
+        kDebug() << "Error occurred " <<  job->errorString();
+        return;
+    }
+    kDebug() << "modify was successfull";
+}
+
+
+void CalendarView::createSearchJobFinished( KJob *job )
+{
+    Akonadi::SearchCreateJob *createJob = qobject_cast<Akonadi::SearchCreateJob *>(job);
+    const Akonadi::Collection searchCollection = createJob->createdCollection();
+    if (job->error()) {
+        qDebug() << "Error occurred " <<  searchCollection.name();
+        return;
+    }
+    qDebug() << "Created search folder successfully " <<  searchCollection.name();
+
+    if (searchCollection.name() ==  QLatin1String("OpenInvitations")) {
+        mOpenInvitationCollection = searchCollection;
+    } else if (searchCollection.name() ==  QLatin1String("DeclinedInvitations")) {
+        mDeclineCollection = searchCollection;
+    }
+}
+
 QDate CalendarView::activeDate( bool fallbackToToday )
 {
   KOrg::BaseView *curView = mViewManager->currentView();
diff --git a/korganizer/calendarview.h b/korganizer/calendarview.h
index 0e94f8c..b77beb5 100644
--- a/korganizer/calendarview.h
+++ b/korganizer/calendarview.h
@@ -34,6 +34,8 @@
 #include <KCalCore/Visitor>
 #include <KCalCore/ScheduleMessage>
 
+#include <KPIMIdentities/IdentityManager>
+
 #include <akonadi/calendar/itiphandler.h>
 
 #include <calendarsupport/messagewidget.h>
@@ -656,6 +658,10 @@ class KORGANIZERPRIVATE_EXPORT CalendarView : public KOrg::CalendarViewBase,
     void onCheckableProxyToggled( bool newState );
     void onTodosPurged(bool success, int numDeleted, int numIgnored);
 
+    void onCheckVirtualCollections(const Akonadi::Collection::List &collections);
+    void createSearchJobFinished(KJob *job);
+    void modifyResult(KJob* job);
+    void onIdentitiesChanged();
   private:
     void init();
     Akonadi::Collection selectedCollection() const;
@@ -728,6 +734,10 @@ class KORGANIZERPRIVATE_EXPORT CalendarView : public KOrg::CalendarViewBase,
     Akonadi::CalendarClipboard *mCalendarClipboard;
     KOCheckableProxyModel *mCheckableProxyModel;
     AkonadiCollectionView *mETMCollectionView;
+
+    KPIMIdentities::IdentityManager mIdentityManager;
+    Akonadi::Collection mOpenInvitationCollection;
+    Akonadi::Collection mDeclineCollection;
 };
 
 #endif




More information about the commits mailing list