Branch 'kolab/integration/4.13.0' - 23 commits - incidenceeditor-ng/attendeecomboboxdelegate.cpp incidenceeditor-ng/attendeecomboboxdelegate.h incidenceeditor-ng/attendeeline.cpp incidenceeditor-ng/attendeetablemodel.cpp incidenceeditor-ng/attendeetablemodel.h incidenceeditor-ng/CMakeLists.txt incidenceeditor-ng/dialogdesktop.ui incidenceeditor-ng/incidenceattendee.cpp incidenceeditor-ng/incidenceattendee.h incidenceeditor-ng/incidencedialog.cpp incidenceeditor-ng/incidencedialog.h incidenceeditor-ng/incidenceresource.cpp incidenceeditor-ng/incidenceresource.h incidenceeditor-ng/ldaputils.cpp incidenceeditor-ng/ldaputils.h incidenceeditor-ng/resourceitem.cpp incidenceeditor-ng/resourceitem.h incidenceeditor-ng/resourcemanagement.cpp incidenceeditor-ng/resourcemanagement.h incidenceeditor-ng/resourcemanagement.ui incidenceeditor-ng/resourcemodel.cpp incidenceeditor-ng/resourcemodel.h incidenceeditor-ng/tests

Sandro Knauß knauss at kolabsys.com
Mon Aug 11 14:54:31 CEST 2014


 incidenceeditor-ng/CMakeLists.txt                  |   10 
 incidenceeditor-ng/attendeecomboboxdelegate.cpp    |  250 ++++++++++++
 incidenceeditor-ng/attendeecomboboxdelegate.h      |  111 +++++
 incidenceeditor-ng/attendeeline.cpp                |    4 
 incidenceeditor-ng/attendeetablemodel.cpp          |  276 +++++++++++++
 incidenceeditor-ng/attendeetablemodel.h            |  108 +++++
 incidenceeditor-ng/dialogdesktop.ui                |  150 ++++++-
 incidenceeditor-ng/incidenceattendee.cpp           |  429 ++++++++++++++++-----
 incidenceeditor-ng/incidenceattendee.h             |   32 +
 incidenceeditor-ng/incidencedialog.cpp             |   27 +
 incidenceeditor-ng/incidencedialog.h               |    1 
 incidenceeditor-ng/incidenceresource.cpp           |  189 +++++++++
 incidenceeditor-ng/incidenceresource.h             |   84 ++++
 incidenceeditor-ng/ldaputils.cpp                   |   62 +++
 incidenceeditor-ng/ldaputils.h                     |   29 +
 incidenceeditor-ng/resourceitem.cpp                |  167 ++++++++
 incidenceeditor-ng/resourceitem.h                  |  136 ++++++
 incidenceeditor-ng/resourcemanagement.cpp          |  349 +++++++++++++++++
 incidenceeditor-ng/resourcemanagement.h            |   87 ++++
 incidenceeditor-ng/resourcemanagement.ui           |  105 +++++
 incidenceeditor-ng/resourcemodel.cpp               |  246 ++++++++++++
 incidenceeditor-ng/resourcemodel.h                 |  137 ++++++
 incidenceeditor-ng/tests/CMakeLists.txt            |   14 
 incidenceeditor-ng/tests/resourcemanagment_gui.cpp |   43 ++
 24 files changed, 2925 insertions(+), 121 deletions(-)

New commits:
commit d3a296ef1fb14d22d5263ca70a368f192f3569eb
Author: Sandro Knauß <knauss at kolabsys.com>
Date:   Mon Aug 11 13:55:51 2014 +0200

    supress email address in resoucemangement
    
    email addresses for resources are only answerd automatically and are
    used by iTip, but they should not be uesed from a user to send mails to
    it.

diff --git a/incidenceeditor-ng/resourcemanagement.cpp b/incidenceeditor-ng/resourcemanagement.cpp
index 781ae26..e9c31b0 100644
--- a/incidenceeditor-ng/resourcemanagement.cpp
+++ b/incidenceeditor-ng/resourcemanagement.cpp
@@ -242,7 +242,8 @@ void ResourceManagement::showDetails(const KLDAP::LdapObject &obj, const KLDAP::
 
     // Fill formDetails with data
     foreach(const QString & key, obj.attributes().keys()) {
-        if (key ==  QLatin1String("objectClass")) {
+        if (key ==  QLatin1String("objectClass")
+            || key == QLatin1String("email")) {
             continue;
         } else if (key ==  QLatin1String("owner")) {
             QStringList attrs;


commit 35ee7277a26efcda994bbda9f62a68736bb8b354
Author: Sandro Knauß <knauss at kolabsys.com>
Date:   Wed Aug 6 15:20:09 2014 +0200

    Fix column width for attendee/resource tab

diff --git a/incidenceeditor-ng/incidenceattendee.cpp b/incidenceeditor-ng/incidenceattendee.cpp
index 1dd0e12..56084af 100644
--- a/incidenceeditor-ng/incidenceattendee.cpp
+++ b/incidenceeditor-ng/incidenceattendee.cpp
@@ -150,8 +150,7 @@ IncidenceAttendee::IncidenceAttendee( QWidget *parent, IncidenceDateTime *dateTi
   mAttendeeDelegate = new AttendeeLineEditDelegate(this);
   mAttendeeDelegate->setCompletionMode( KGlobalSettings::self()->completionMode() );
 
-  QHeaderView* headerView = mUi->mAttendeeTable->horizontalHeader();
-  headerView->setResizeMode(QHeaderView::ResizeToContents);
+
 
   mUi->mAttendeeTable->setItemDelegateForColumn(AttendeeTableModel::Role, roleDelegate());
   mUi->mAttendeeTable->setItemDelegateForColumn(AttendeeTableModel::FullName, attendeeDelegate());
@@ -709,10 +708,15 @@ AttendeeLineEditDelegate *IncidenceAttendee::attendeeDelegate()
 void IncidenceAttendee::filterLayoutChanged()
 {
 #ifndef KDEPIM_MOBILE_UI
-  mUi->mAttendeeTable->setColumnHidden(AttendeeTableModel::CuType, true);
-  mUi->mAttendeeTable->setColumnHidden(AttendeeTableModel::Name, true);
-  mUi->mAttendeeTable->setColumnHidden(AttendeeTableModel::Email, true);
-  mUi->mAttendeeTable->setColumnHidden(AttendeeTableModel::Available, true);
+    QHeaderView* headerView = mUi->mAttendeeTable->horizontalHeader();
+    headerView->setResizeMode(AttendeeTableModel::Role,  QHeaderView::ResizeToContents);
+    headerView->setResizeMode(AttendeeTableModel::FullName, QHeaderView::Stretch);
+    headerView->setResizeMode(AttendeeTableModel::Status,  QHeaderView::ResizeToContents);
+    headerView->setResizeMode(AttendeeTableModel::Response,  QHeaderView::ResizeToContents);
+    headerView->setSectionHidden(AttendeeTableModel::CuType, true);
+    headerView->setSectionHidden(AttendeeTableModel::Name, true);
+    headerView->setSectionHidden(AttendeeTableModel::Email, true);
+    headerView->setSectionHidden(AttendeeTableModel::Available, true);
 #endif
 }
 
diff --git a/incidenceeditor-ng/incidenceresource.cpp b/incidenceeditor-ng/incidenceresource.cpp
index 5fc1a78..23e229b 100644
--- a/incidenceeditor-ng/incidenceresource.cpp
+++ b/incidenceeditor-ng/incidenceresource.cpp
@@ -92,8 +92,6 @@ IncidenceResource::IncidenceResource(IncidenceAttendee* ieAttendee, Ui::EventOrT
     filterProxyModel->setDynamicSortFilter(true);
     filterProxyModel->setSourceModel(dataModel);
 
-    QHeaderView* headerView = mUi->mResourcesTable->horizontalHeader();
-    headerView->setResizeMode(QHeaderView::ResizeToContents);
 
     mUi->mResourcesTable->setModel(filterProxyModel);
     mUi->mResourcesTable->setItemDelegateForColumn(AttendeeTableModel::Role, ieAttendee->roleDelegate());
@@ -149,9 +147,15 @@ void IncidenceResource::findResources()
 void IncidenceResource::layoutChanged()
 {
 #ifndef KDEPIM_MOBILE_UI
-    mUi->mResourcesTable->setColumnHidden(AttendeeTableModel::CuType, true);
-    mUi->mResourcesTable->setColumnHidden(AttendeeTableModel::Name, true);
-    mUi->mResourcesTable->setColumnHidden(AttendeeTableModel::Email, true);
+    QHeaderView* headerView = mUi->mResourcesTable->horizontalHeader();
+    headerView->setSectionHidden(AttendeeTableModel::CuType, true);
+    headerView->setSectionHidden(AttendeeTableModel::Name, true);
+    headerView->setSectionHidden(AttendeeTableModel::Email, true);
+    headerView->setResizeMode(AttendeeTableModel::Role,  QHeaderView::ResizeToContents);
+    headerView->setResizeMode(AttendeeTableModel::FullName, QHeaderView::Stretch);
+    headerView->setResizeMode(AttendeeTableModel::Available,  QHeaderView::ResizeToContents);
+    headerView->setResizeMode(AttendeeTableModel::Status,  QHeaderView::ResizeToContents);
+    headerView->setResizeMode(AttendeeTableModel::Response,  QHeaderView::ResizeToContents);
 #endif
 }
 


commit e1e1c407f0f8fa88c6199a274478c533ff65e902
Author: Sandro Knauß <knauss at kolabsys.com>
Date:   Wed Aug 6 15:18:43 2014 +0200

    dalogdesktop made book resource via Enter

diff --git a/incidenceeditor-ng/dialogdesktop.ui b/incidenceeditor-ng/dialogdesktop.ui
index 13ee780..a2a7063 100644
--- a/incidenceeditor-ng/dialogdesktop.ui
+++ b/incidenceeditor-ng/dialogdesktop.ui
@@ -858,6 +858,9 @@
           <layout class="QHBoxLayout" name="horizontalLayout_11">
            <item>
             <widget class="KLineEdit" name="mNewResource">
+             <property name="trapEnterKeyEvent" stdset="0">
+              <bool>true</bool>
+             </property>
              <property name="showClearButton" stdset="0">
               <bool>true</bool>
              </property>
@@ -868,6 +871,12 @@
              <property name="text">
               <string>Book resource</string>
              </property>
+             <property name="autoDefault">
+              <bool>false</bool>
+             </property>
+             <property name="default">
+              <bool>false</bool>
+             </property>
             </widget>
            </item>
            <item>
@@ -875,10 +884,13 @@
              <property name="orientation">
               <enum>Qt::Horizontal</enum>
              </property>
+             <property name="sizeType">
+              <enum>QSizePolicy::Preferred</enum>
+             </property>
              <property name="sizeHint" stdset="0">
               <size>
                <width>40</width>
-               <height>20</height>
+               <height>0</height>
               </size>
              </property>
             </spacer>


commit 6ee7e3d32d8accb844ead8df90c1f35dc799faa8
Author: Sandro Knauß <knauss at kolabsys.com>
Date:   Wed Aug 6 15:17:25 2014 +0200

    available status for attendeetablemodel

diff --git a/incidenceeditor-ng/attendeetablemodel.cpp b/incidenceeditor-ng/attendeetablemodel.cpp
index 4ad6b05..0fb3074 100644
--- a/incidenceeditor-ng/attendeetablemodel.cpp
+++ b/incidenceeditor-ng/attendeetablemodel.cpp
@@ -54,7 +54,11 @@ QVariant AttendeeTableModel::data(const QModelIndex &index, int role) const
         case FullName:
             return attendeeList[index.row()]->fullName();
         case Available:
-            return 0;//attendeeList.at(index.row()).available;
+            if (role == Qt::DisplayRole) {
+                return i18n("Unknown");
+            } else {
+                return 0;  //attendeeList.at(index.row()).available;
+            }
         case Status:
             return attendeeList[index.row()]->status();
         case CuType:


commit 3477ab400f59224e7c2051ee91e0604fc7f98b40
Author: Sandro Knauß <knauss at kolabsys.com>
Date:   Wed Aug 6 13:26:20 2014 +0200

    Localize resousemanagement

diff --git a/incidenceeditor-ng/CMakeLists.txt b/incidenceeditor-ng/CMakeLists.txt
index b184732..4b33d45 100644
--- a/incidenceeditor-ng/CMakeLists.txt
+++ b/incidenceeditor-ng/CMakeLists.txt
@@ -70,6 +70,7 @@ set(incidenceeditors_ng_shared_LIB_SRCS
   resourcemanagement.cpp
   resourceitem.cpp
   resourcemodel.cpp
+  ldaputils.cpp
   attendeetablemodel.cpp
   attendeecomboboxdelegate.cpp
 )
@@ -105,6 +106,7 @@ target_link_libraries(incidenceeditorsng
   akonadi-kmime
   ${QT_QTCORE_LIBRARY}
   ${QT_QTGUI_LIBRARY}
+  ${QJSON_LIBRARIES}
   ${KDE4_KDEUI_LIBS}
   ${KDEPIMLIBS_KCALCORE_LIBS}
   ${KDEPIMLIBS_KCALUTILS_LIBS}
@@ -158,6 +160,7 @@ install(TARGETS incidenceeditorsng ${INSTALL_TARGETS_DEFAULT_ARGS})
     ${KDEPIMLIBS_KCALUTILS_LIBS}
     ${KDEPIMLIBS_KCALCORE_LIBS}
     ${KDEPIMLIBS_MAILTRANSPORT_LIBS}
+    ${QJSON_LIBRARIES}
   )
 
   set_target_properties(incidenceeditorsngmobile PROPERTIES
diff --git a/incidenceeditor-ng/attendeetablemodel.cpp b/incidenceeditor-ng/attendeetablemodel.cpp
index a3242e8..4ad6b05 100644
--- a/incidenceeditor-ng/attendeetablemodel.cpp
+++ b/incidenceeditor-ng/attendeetablemodel.cpp
@@ -1,5 +1,7 @@
 #include "attendeetablemodel.h"
 
+#include <klocalizedstring.h>
+
 #include <KCalCore/Attendee>
 #include <KPIMUtils/Email>
 
@@ -125,21 +127,21 @@ QVariant AttendeeTableModel::headerData(int section, Qt::Orientation orientation
     if (orientation == Qt::Horizontal) {
         switch (section) {
         case Role:
-            return QString("role");
+            return i18nc("vcard attendee role", "Role");
         case FullName:
-            return QString("fullname");
+            return i18nc("attendees  (name+emailaddress)",  "Fullname");
         case Available:
-            return QString("available");
+            return i18nc("is attendee available for incidence", "Available");
         case Status:
-            return QString("status");
+          return i18nc("Status of attendee in an incidence (accepted, declined, delegated, ...)", "Status");
         case CuType:
-            return QString("cuType");
+            return i18nc("Type of resource (vCard attribute)", "cuType");
         case Response:
-            return QString("response");
+            return i18nc("has attendee to respond to the invitation", "Response");
         case Name:
-            return QString("name");
+            return i18nc("attendee name", "name");
         case Email:
-            return QString("email");
+            return i18nc("attendee email",  "email");
         }
     }
 
diff --git a/incidenceeditor-ng/dialogdesktop.ui b/incidenceeditor-ng/dialogdesktop.ui
index 2a10c51..13ee780 100644
--- a/incidenceeditor-ng/dialogdesktop.ui
+++ b/incidenceeditor-ng/dialogdesktop.ui
@@ -13,16 +13,7 @@
   <layout class="QVBoxLayout" name="mainVerticalLayout">
    <item>
     <layout class="QGridLayout" name="gridLayout">
-     <property name="leftMargin">
-      <number>0</number>
-     </property>
-     <property name="topMargin">
-      <number>0</number>
-     </property>
-     <property name="rightMargin">
-      <number>0</number>
-     </property>
-     <property name="bottomMargin">
+     <property name="margin">
       <number>0</number>
      </property>
      <item row="0" column="0">
@@ -50,16 +41,7 @@
      <item row="1" column="1">
       <widget class="QWidget" name="mInvitationBar" native="true">
        <layout class="QHBoxLayout" name="horizontalLayout_10">
-        <property name="leftMargin">
-         <number>0</number>
-        </property>
-        <property name="topMargin">
-         <number>0</number>
-        </property>
-        <property name="rightMargin">
-         <number>0</number>
-        </property>
-        <property name="bottomMargin">
+        <property name="margin">
          <number>0</number>
         </property>
         <item>
@@ -213,16 +195,7 @@
      <item row="5" column="1">
       <widget class="QWidget" name="mCompletionPriorityWidget" native="true">
        <layout class="QHBoxLayout" name="horizontalLayout_8">
-        <property name="leftMargin">
-         <number>0</number>
-        </property>
-        <property name="topMargin">
-         <number>0</number>
-        </property>
-        <property name="rightMargin">
-         <number>0</number>
-        </property>
-        <property name="bottomMargin">
+        <property name="margin">
          <number>0</number>
         </property>
         <item>
@@ -809,16 +782,7 @@
            </property>
            <widget class="QWidget" name="page">
             <layout class="QGridLayout" name="gridLayout_2">
-             <property name="leftMargin">
-              <number>0</number>
-             </property>
-             <property name="topMargin">
-              <number>0</number>
-             </property>
-             <property name="rightMargin">
-              <number>0</number>
-             </property>
-             <property name="bottomMargin">
+             <property name="margin">
               <number>0</number>
              </property>
              <item row="0" column="0">
@@ -841,16 +805,7 @@
            </widget>
            <widget class="QWidget" name="page_2">
             <layout class="QGridLayout" name="gridLayout_3">
-             <property name="leftMargin">
-              <number>0</number>
-             </property>
-             <property name="topMargin">
-              <number>0</number>
-             </property>
-             <property name="rightMargin">
-              <number>0</number>
-             </property>
-             <property name="bottomMargin">
+             <property name="margin">
               <number>0</number>
              </property>
              <item row="0" column="0">
@@ -902,7 +857,11 @@
          <item row="1" column="0">
           <layout class="QHBoxLayout" name="horizontalLayout_11">
            <item>
-            <widget class="KLineEdit" name="mNewResource"/>
+            <widget class="KLineEdit" name="mNewResource">
+             <property name="showClearButton" stdset="0">
+              <bool>true</bool>
+             </property>
+            </widget>
            </item>
            <item>
             <widget class="QPushButton" name="mBookResourceButton">
@@ -1178,32 +1137,14 @@
            <widget class="QWidget" name="never_page"/>
            <widget class="QWidget" name="daily_page">
             <layout class="QGridLayout" name="gridLayout_11">
-             <property name="leftMargin">
-              <number>0</number>
-             </property>
-             <property name="topMargin">
-              <number>0</number>
-             </property>
-             <property name="rightMargin">
-              <number>0</number>
-             </property>
-             <property name="bottomMargin">
+             <property name="margin">
               <number>0</number>
              </property>
             </layout>
            </widget>
            <widget class="QWidget" name="weekly_page">
             <layout class="QGridLayout" name="gridLayout_4">
-             <property name="leftMargin">
-              <number>0</number>
-             </property>
-             <property name="topMargin">
-              <number>0</number>
-             </property>
-             <property name="rightMargin">
-              <number>0</number>
-             </property>
-             <property name="bottomMargin">
+             <property name="margin">
               <number>0</number>
              </property>
              <item row="0" column="0">
@@ -1223,16 +1164,7 @@
            </widget>
            <widget class="QWidget" name="Monthly">
             <layout class="QGridLayout" name="gridLayout_6">
-             <property name="leftMargin">
-              <number>0</number>
-             </property>
-             <property name="topMargin">
-              <number>0</number>
-             </property>
-             <property name="rightMargin">
-              <number>0</number>
-             </property>
-             <property name="bottomMargin">
+             <property name="margin">
               <number>0</number>
              </property>
              <item row="0" column="0">
@@ -1265,16 +1197,7 @@
            </widget>
            <widget class="QWidget" name="yearly_page">
             <layout class="QGridLayout" name="gridLayout_7">
-             <property name="leftMargin">
-              <number>0</number>
-             </property>
-             <property name="topMargin">
-              <number>0</number>
-             </property>
-             <property name="rightMargin">
-              <number>0</number>
-             </property>
-             <property name="bottomMargin">
+             <property name="margin">
               <number>0</number>
              </property>
              <item row="0" column="0">
@@ -1366,32 +1289,14 @@
              </property>
              <widget class="QWidget" name="no_end">
               <layout class="QGridLayout" name="gridLayout_16">
-               <property name="leftMargin">
-                <number>0</number>
-               </property>
-               <property name="topMargin">
-                <number>0</number>
-               </property>
-               <property name="rightMargin">
-                <number>0</number>
-               </property>
-               <property name="bottomMargin">
+               <property name="margin">
                 <number>0</number>
                </property>
               </layout>
              </widget>
              <widget class="QWidget" name="end_on">
               <layout class="QGridLayout" name="gridLayout_14">
-               <property name="leftMargin">
-                <number>0</number>
-               </property>
-               <property name="topMargin">
-                <number>0</number>
-               </property>
-               <property name="rightMargin">
-                <number>0</number>
-               </property>
-               <property name="bottomMargin">
+               <property name="margin">
                 <number>0</number>
                </property>
                <item row="0" column="0">
@@ -1424,19 +1329,10 @@
              </widget>
              <widget class="QWidget" name="end_after">
               <layout class="QGridLayout" name="gridLayout_10">
-               <property name="leftMargin">
-                <number>0</number>
-               </property>
-               <property name="topMargin">
-                <number>0</number>
-               </property>
-               <property name="rightMargin">
-                <number>0</number>
-               </property>
-               <property name="bottomMargin">
+               <property name="horizontalSpacing">
                 <number>0</number>
                </property>
-               <property name="horizontalSpacing">
+               <property name="margin">
                 <number>0</number>
                </property>
                <item row="0" column="0">
@@ -1662,6 +1558,21 @@
  </widget>
  <customwidgets>
   <customwidget>
+   <class>KRichTextEdit</class>
+   <extends>KTextEdit</extends>
+   <header>krichtextedit.h</header>
+  </customwidget>
+  <customwidget>
+   <class>KTimeComboBox</class>
+   <extends>KComboBox</extends>
+   <header>ktimecombobox.h</header>
+  </customwidget>
+  <customwidget>
+   <class>KDateComboBox</class>
+   <extends>KComboBox</extends>
+   <header>kdatecombobox.h</header>
+  </customwidget>
+  <customwidget>
    <class>KComboBox</class>
    <extends>QComboBox</extends>
    <header>kcombobox.h</header>
@@ -1683,6 +1594,11 @@
    <header>ktextedit.h</header>
   </customwidget>
   <customwidget>
+   <class>KRichTextWidget</class>
+   <extends>KRichTextEdit</extends>
+   <header>krichtextwidget.h</header>
+  </customwidget>
+  <customwidget>
    <class>KTabWidget</class>
    <extends>QTabWidget</extends>
    <header>ktabwidget.h</header>
@@ -1714,26 +1630,6 @@
    <header>libkdepim/widgets/tagwidgets.h</header>
    <container>1</container>
   </customwidget>
-  <customwidget>
-   <class>KRichTextEdit</class>
-   <extends>KTextEdit</extends>
-   <header>krichtextedit.h</header>
-  </customwidget>
-  <customwidget>
-   <class>KTimeComboBox</class>
-   <extends>KComboBox</extends>
-   <header>ktimecombobox.h</header>
-  </customwidget>
-  <customwidget>
-   <class>KDateComboBox</class>
-   <extends>KComboBox</extends>
-   <header>kdatecombobox.h</header>
-  </customwidget>
-  <customwidget>
-   <class>KRichTextWidget</class>
-   <extends>KRichTextEdit</extends>
-   <header>krichtextwidget.h</header>
-  </customwidget>
  </customwidgets>
  <resources/>
  <connections>
@@ -1744,12 +1640,12 @@
    <slot>setCurrentIndex(int)</slot>
    <hints>
     <hint type="sourcelabel">
-     <x>150</x>
-     <y>298</y>
+     <x>144</x>
+     <y>314</y>
     </hint>
     <hint type="destinationlabel">
-     <x>428</x>
-     <y>298</y>
+     <x>144</x>
+     <y>314</y>
     </hint>
    </hints>
   </connection>
@@ -1760,12 +1656,28 @@
    <slot>setCurrentIndex(int)</slot>
    <hints>
     <hint type="sourcelabel">
-     <x>133</x>
-     <y>223</y>
+     <x>142</x>
+     <y>304</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>104</x>
+     <y>280</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>mNewResource</sender>
+   <signal>returnPressed()</signal>
+   <receiver>mBookResourceButton</receiver>
+   <slot>click()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>271</x>
+     <y>805</y>
     </hint>
     <hint type="destinationlabel">
-     <x>143</x>
-     <y>255</y>
+     <x>402</x>
+     <y>808</y>
     </hint>
    </hints>
   </connection>
diff --git a/incidenceeditor-ng/incidenceresource.cpp b/incidenceeditor-ng/incidenceresource.cpp
index 1178a9e..5fc1a78 100644
--- a/incidenceeditor-ng/incidenceresource.cpp
+++ b/incidenceeditor-ng/incidenceresource.cpp
@@ -70,7 +70,7 @@ IncidenceResource::IncidenceResource(IncidenceAttendee* ieAttendee, Ui::EventOrT
 
 #ifndef KDEPIM_MOBILE_UI
     QStringList attrs;
-    attrs << QLatin1String("cn");
+    attrs << QLatin1String("cn") <<  QLatin1String("mail");
 
     completer = new QCompleter(this);
     ResourceModel *model = new ResourceModel(attrs, this);
diff --git a/incidenceeditor-ng/ldaputils.cpp b/incidenceeditor-ng/ldaputils.cpp
new file mode 100644
index 0000000..89235ea
--- /dev/null
+++ b/incidenceeditor-ng/ldaputils.cpp
@@ -0,0 +1,62 @@
+/*
+ * Copyright 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) version 3 or any later version
+ * accepted by the membership of KDE e.V. (or its successor approved
+ * by the membership of KDE e.V.), which shall act as a proxy
+ * defined in Section 14 of version 3 of the license.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "ldaputils.h"
+#include <klocalizedstring.h>
+
+
+QString translateLDAPAttributeForDisplay(const QString &attribute)
+{
+    QString ret = attribute;
+    if (attribute ==  QLatin1String("cn")) {
+        ret = i18nc("ldap attribute cn", "Common name");
+    } else if (attribute ==  QLatin1String("mail")) {
+        ret = i18nc("ldap attribute mail", "Email");
+    } else if (attribute ==  QLatin1String("givenname")) {
+        ret = i18nc("ldap attribute givenname", "Given name");
+    } else if (attribute ==  QLatin1String("sn")) {
+        ret = i18nc("ldap attribute sn", "Surname");
+    } else if (attribute ==  QLatin1String("ou")) {
+        ret = i18nc("ldap attribute ou", "Organization");
+    } else if (attribute ==  QLatin1String("objectClass")) {
+        ret = i18nc("ldap attribute objectClass", "Object class");
+    } else if (attribute ==  QLatin1String("description")) {
+        ret = i18nc("ldap attribute description", "Description");
+    } else if (attribute ==  QLatin1String("telephoneNumber")) {
+        ret = i18nc("ldap attribute telephoneNumber",  "Telephone");
+    } else if (attribute ==  QLatin1String("mobile")) {
+        ret = i18nc("ldap attribute mobile",  "Mobile");
+    }
+    return ret;
+}
+
+QString translateKolabLDAPAttributeForDisplay(const QString &attribute)
+{
+    QString ret = attribute;
+    if (attribute ==  QLatin1String("numseats")) {
+        ret = i18nc("kolabldap", "Number of seats");
+    } else if (attribute ==  QLatin1String("beamer_present")) {
+        ret = i18nc("kolabldap", "Beamer");
+    } else if (attribute ==  QLatin1String("conf_phone_present")) {
+        ret = i18nc("kolabldap", "Conference phone");
+    }
+    return ret;
+}
diff --git a/incidenceeditor-ng/ldaputils.h b/incidenceeditor-ng/ldaputils.h
new file mode 100644
index 0000000..e89b9ca
--- /dev/null
+++ b/incidenceeditor-ng/ldaputils.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright 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) version 3 or any later version
+ * accepted by the membership of KDE e.V. (or its successor approved
+ * by the membership of KDE e.V.), which shall act as a proxy
+ * defined in Section 14 of version 3 of the license.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef LDAPUTILS_H
+#define LDAPUTILS_H
+
+#include <QString>
+
+QString translateLDAPAttributeForDisplay(const QString &attribute);
+QString translateKolabLDAPAttributeForDisplay(const QString &attribute);
+#endif //LDAPUTLS_H
\ No newline at end of file
diff --git a/incidenceeditor-ng/resourceitem.cpp b/incidenceeditor-ng/resourceitem.cpp
index 7089ea3..08961ad 100644
--- a/incidenceeditor-ng/resourceitem.cpp
+++ b/incidenceeditor-ng/resourceitem.cpp
@@ -163,4 +163,5 @@ void ResourceItem::slotLDAPResult(const KLDAP::LdapClient &/*client*/,
             itemData << "";
         }
     }
+    emit searchFinished();
 }
\ No newline at end of file
diff --git a/incidenceeditor-ng/resourceitem.h b/incidenceeditor-ng/resourceitem.h
index 3c04373..e5997ca 100644
--- a/incidenceeditor-ng/resourceitem.h
+++ b/incidenceeditor-ng/resourceitem.h
@@ -67,6 +67,9 @@ private:
     QVector<QVariant> itemData;
     ResourceItem::Ptr parentItem;
 
+signals:
+    void searchFinished();
+
 public:
     /* Returns the attributes of the requested ldapObject.
      *
diff --git a/incidenceeditor-ng/resourcemanagement.cpp b/incidenceeditor-ng/resourcemanagement.cpp
index e33349a..781ae26 100644
--- a/incidenceeditor-ng/resourcemanagement.cpp
+++ b/incidenceeditor-ng/resourcemanagement.cpp
@@ -25,6 +25,7 @@
 #include "ui_resourcemanagement.h"
 #include "resourcemodel.h"
 #include "freebusyitem.h"
+#include "ldaputils.h"
 
 #include "freebusyganttproxymodel.h"
 
@@ -36,6 +37,8 @@
 #include <akonadi/calendar/freebusymanager.h>
 #include <kldap/ldapobject.h>
 
+#include <qjson/parser.h>
+
 #include <QPointer>
 #include <QSplitter>
 #include <QStringList>
@@ -141,12 +144,12 @@ public:
     {
     }
 
-        QSize sizeHint() const
-            {
-                QSize s = QHeaderView::sizeHint();
-                s.rheight() *= 2;
-                return s;
-            }
+    QSize sizeHint() const
+    {
+        QSize s = QHeaderView::sizeHint();
+        s.rheight() *= 2;
+        return s;
+    }
 };
 
 
@@ -160,10 +163,6 @@ ResourceManagement::ResourceManagement()
     setMainWidget( w );
 
     QVariantList list;
-    //QGridLayout *layout = new QGridLayout( resourceCalender );
-    //layout->setSpacing( 0 );
-    //KOrganizerPart *view = new KOrganizerPart(resourceCalender,  this,  list);
-    //resourceCalender = view->topLevelWidget();
     mModel = new FreeBusyItemModel;
 #ifndef KDEPIM_MOBILE_UI
 
@@ -196,8 +195,9 @@ ResourceManagement::ResourceManagement()
 #endif
 
     QStringList attrs;
-    attrs << QLatin1String("cn") << QLatin1String("mail") << QLatin1String("givenname") << QLatin1String("sn");
-
+    attrs << QLatin1String("cn") << QLatin1String("mail")
+          << QLatin1String("owner") << QLatin1String("givenname") << QLatin1String("sn")
+          << QLatin1String("kolabDescAttribute") << QLatin1String("description");
     ResourceModel *resourcemodel = new ResourceModel(attrs);
     mUi->treeResults->setModel(resourcemodel);
 
@@ -226,11 +226,11 @@ void ResourceManagement::slotStartSearch(const QString &text)
 void ResourceManagement::slotShowDetails(const QModelIndex & current)
 {
     ResourceItem::Ptr item = current.model()->data(current, ResourceModel::Resource).value<ResourceItem::Ptr>();
-    showDetails(item->ldapObject());
+    showDetails(item->ldapObject(), item->ldapClient());
 }
 
 
-void ResourceManagement::showDetails(const KLDAP::LdapObject &obj)
+void ResourceManagement::showDetails(const KLDAP::LdapObject &obj, const KLDAP::LdapClient &client)
 {
     // Clean up formDetails
     QLayoutItem *child;
@@ -238,20 +238,49 @@ void ResourceManagement::showDetails(const KLDAP::LdapObject &obj)
         delete child->widget();
         delete child;
     }
+    mUi->groupOwner->setHidden(true);
 
     // Fill formDetails with data
     foreach(const QString & key, obj.attributes().keys()) {
+        if (key ==  QLatin1String("objectClass")) {
+            continue;
+        } else if (key ==  QLatin1String("owner")) {
+            QStringList attrs;
+            attrs << QLatin1String("cn") << QLatin1String("mail")
+                  << QLatin1String("mobile") <<  QLatin1String("telephoneNumber")
+                  << QLatin1String("kolabDescAttribute") << QLatin1String("description");
+            mOwnerItem = ResourceItem::Ptr(new ResourceItem(KLDAP::LdapDN(QString::fromUtf8(obj.attributes().value(key).at(0))),
+                                                    attrs,  client));
+            connect(mOwnerItem.data(),  SIGNAL(searchFinished()), SLOT(slotOwnerSearchFinished()));
+            mOwnerItem->startSearch();
+            continue;
+        }
         QStringList list;
         foreach(const QByteArray & value, obj.attributes().value(key)) {
             list << QString::fromUtf8(value);
         }
-        kDebug() << key <<  list;
-        mUi->formDetails->addRow(key, new QLabel(list.join("\n")));
+        if (key ==  QLatin1String("kolabDescAttribute")) {
+            QJson::Parser parser;
+            foreach(const QString &attr,  list) {
+                bool ok;
+                QMap <QString, QVariant > map = parser.parse(attr.toUtf8(), &ok).toMap();
+                foreach(const QString &pKey, map.keys()) {
+                    QString value;
+                    if (map.value(pKey).type() ==  QVariant::Bool) {
+                        value = map.value(pKey).toBool()  ?  i18n("yes") : i18n("no");
+                    } else {
+                        value = map.value(pKey).toString();
+                    }
+                    mUi->formDetails->addRow(translateKolabLDAPAttributeForDisplay(pKey), new QLabel(value));
+                 }
+            }
+        } else {
+            mUi->formDetails->addRow(translateLDAPAttributeForDisplay(key), new QLabel(list.join("\n")));
+        }
     }
 
     QString name = QString::fromUtf8(obj.attributes().value("cn")[0]);
     QString email = QString::fromUtf8(obj.attributes().value("mail")[0]);
-    kDebug() <<  name <<  email;
     KCalCore::Attendee::Ptr attendee(new KCalCore::Attendee(name,  email));
     FreeBusyItem::Ptr freebusy( new FreeBusyItem( attendee, this ));
     mModel->clear();
@@ -271,4 +300,49 @@ void ResourceManagement::slotLayoutChanged()
     }
 }
 
+void ResourceManagement::slotOwnerSearchFinished()
+{
+    // Clean up formDetails
+    QLayoutItem *child;
+    while ((child = mUi->formOwner->takeAt(0)) != 0) {
+        delete child->widget();
+        delete child;
+    }
+    mUi->groupOwner->setHidden(false);
+
+    const KLDAP::LdapObject &obj = mOwnerItem->ldapObject();
+    foreach(const QString & key, obj.attributes().keys()) {
+        if (key ==  QLatin1String("objectClass")
+            || key ==  QLatin1String("owner")
+            || key ==  QLatin1String("givenname")
+            || key ==  QLatin1String("sn")) {
+            continue;
+        }
+        QStringList list;
+        foreach(const QByteArray & value, obj.attributes().value(key)) {
+            list << QString::fromUtf8(value);
+          }
+        if (key ==  QLatin1String("kolabDescAttribute")) {
+            QJson::Parser parser;
+            foreach(const QString &attr,  list) {
+                bool ok;
+                QMap <QString, QVariant > map = parser.parse(attr.toUtf8(), &ok).toMap();
+                foreach(const QString &pKey, map.keys()) {
+                    QString value;
+                    if (map.value(pKey).type() ==  QVariant::Bool) {
+                        value = map.value(pKey).toBool()  ?  i18n("yes") : i18n("no");
+                      } else {
+                          value = map.value(pKey).toString();
+                        }
+                    mUi->formOwner->addRow(translateKolabLDAPAttributeForDisplay(pKey), new QLabel(value));
+                  }
+              }
+          } else {
+              mUi->formOwner->addRow(translateLDAPAttributeForDisplay(key), new QLabel(list.join("\n")));
+            }
+      }
+
+}
+
+
 #include "resourcemanagement.moc"
diff --git a/incidenceeditor-ng/resourcemanagement.h b/incidenceeditor-ng/resourcemanagement.h
index c6dea43..8dedb4f 100644
--- a/incidenceeditor-ng/resourcemanagement.h
+++ b/incidenceeditor-ng/resourcemanagement.h
@@ -28,6 +28,7 @@
 #include <ldap/ldapclientsearch.h>
 
 #include "freebusyitemmodel.h"
+#include "resourceitem.h"
 
 # include <KCalCore/FreeBusy>
 #include <KDialog>
@@ -52,7 +53,7 @@ private:
     /* Shows the details of a resource
      *
      */
-    void showDetails(const KLDAP::LdapObject&);
+    void showDetails(const KLDAP::LdapObject&, const KLDAP::LdapClient &client);
 
     QItemSelectionModel *selectionModel;
 
@@ -66,6 +67,11 @@ private slots:
      *
      */
     void slotShowDetails(const QModelIndex & current);
+    
+    /**
+     * The Owner search is done
+     */
+    void slotOwnerSearchFinished();
 
     void slotInsertFreeBusy( const KCalCore::FreeBusy::Ptr &fb, const QString &email );
 
@@ -73,6 +79,7 @@ private slots:
 
 private:
     FreeBusyItemModel *mModel;
+    ResourceItem::Ptr mOwnerItem;
     Ui_resourceManagement *mUi;
 };
 
diff --git a/incidenceeditor-ng/resourcemanagement.ui b/incidenceeditor-ng/resourcemanagement.ui
index 09d6f37..dd3746f 100644
--- a/incidenceeditor-ng/resourcemanagement.ui
+++ b/incidenceeditor-ng/resourcemanagement.ui
@@ -6,89 +6,90 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>916</width>
-    <height>782</height>
+    <width>552</width>
+    <height>566</height>
    </rect>
   </property>
   <property name="windowTitle">
    <string>Form</string>
   </property>
-  <layout class="QHBoxLayout" name="horizontalLayout_2">
-   <property name="spacing">
-    <number>6</number>
-   </property>
+  <layout class="QVBoxLayout" name="verticalLayout_5">
    <item>
-    <layout class="QVBoxLayout" name="verticalLayout" stretch="0,0">
-     <property name="spacing">
-      <number>2</number>
+    <widget class="QSplitter" name="splitter_2">
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
      </property>
-     <item>
-      <widget class="KLineEdit" name="resourceSearch">
-       <property name="maximumSize">
-        <size>
-         <width>400</width>
-         <height>16777215</height>
-        </size>
-       </property>
-      </widget>
-     </item>
-     <item>
-      <widget class="QTreeView" name="treeResults">
-       <property name="minimumSize">
-        <size>
-         <width>200</width>
-         <height>0</height>
-        </size>
-       </property>
-       <property name="maximumSize">
-        <size>
-         <width>400</width>
-         <height>16777215</height>
-        </size>
-       </property>
-       <property name="alternatingRowColors">
-        <bool>true</bool>
-       </property>
-       <property name="selectionBehavior">
-        <enum>QAbstractItemView::SelectRows</enum>
-       </property>
-      </widget>
-     </item>
-    </layout>
-   </item>
-   <item>
-    <layout class="QVBoxLayout" name="verticalLayout_2">
-     <property name="spacing">
-      <number>2</number>
-     </property>
-     <item>
-      <widget class="QGroupBox" name="groupDetails">
-       <property name="enabled">
-        <bool>true</bool>
-       </property>
-       <property name="sizePolicy">
-        <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
-         <horstretch>0</horstretch>
-         <verstretch>0</verstretch>
-        </sizepolicy>
-       </property>
-       <property name="title">
-        <string>Details</string>
-       </property>
-       <layout class="QVBoxLayout" name="verticalLayout_4">
-        <property name="rightMargin">
-         <number>4</number>
-        </property>
+     <widget class="QWidget" name="">
+      <layout class="QVBoxLayout" name="verticalLayout">
+       <item>
+        <widget class="KLineEdit" name="resourceSearch">
+         <property name="showClearButton" stdset="0">
+          <bool>true</bool>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="QTreeView" name="treeResults">
+         <property name="alternatingRowColors">
+          <bool>true</bool>
+         </property>
+         <property name="selectionBehavior">
+          <enum>QAbstractItemView::SelectRows</enum>
+         </property>
+        </widget>
+       </item>
+      </layout>
+     </widget>
+     <widget class="QSplitter" name="splitter">
+      <property name="orientation">
+       <enum>Qt::Vertical</enum>
+      </property>
+      <widget class="QWidget" name="">
+       <layout class="QVBoxLayout" name="verticalLayout_3">
         <item>
-         <layout class="QFormLayout" name="formDetails"/>
+         <widget class="QGroupBox" name="groupDetails">
+          <property name="enabled">
+           <bool>true</bool>
+          </property>
+          <property name="title">
+           <string>Details</string>
+          </property>
+          <layout class="QVBoxLayout" name="verticalLayout_4">
+           <property name="rightMargin">
+            <number>4</number>
+           </property>
+           <item>
+            <layout class="QFormLayout" name="formDetails"/>
+           </item>
+          </layout>
+         </widget>
         </item>
+        <item>
+         <widget class="QGroupBox" name="groupOwner">
+          <property name="enabled">
+           <bool>true</bool>
+          </property>
+          <property name="title">
+           <string>Owner</string>
+          </property>
+          <layout class="QVBoxLayout" name="verticalLayout_2">
+           <item>
+            <layout class="QFormLayout" name="formOwner"/>
+           </item>
+          </layout>
+         </widget>
+        </item>
+       </layout>
+      </widget>
+      <widget class="QWidget" name="">
+       <layout class="QHBoxLayout" name="resourceCalender">
+        <property name="sizeConstraint">
+         <enum>QLayout::SetDefaultConstraint</enum>
+        </property>
        </layout>
       </widget>
-     </item>
-     <item>
-      <layout class="QHBoxLayout" name="resourceCalender"/>
-     </item>
-    </layout>
+     </widget>
+    </widget>
    </item>
   </layout>
  </widget>
diff --git a/incidenceeditor-ng/resourcemodel.cpp b/incidenceeditor-ng/resourcemodel.cpp
index 274dee0..d4f8346 100644
--- a/incidenceeditor-ng/resourcemodel.cpp
+++ b/incidenceeditor-ng/resourcemodel.cpp
@@ -19,6 +19,7 @@
  *
  */
 #include "resourcemodel.h"
+#include "ldaputils.h"
 
 #include <KPIMUtils/Email>
 #include <KDebug>
@@ -43,6 +44,7 @@ ResourceModel::ResourceModel(const QStringList &headers,
     QStringList attrs = ldapSearchCollections.attributes();
     attrs << QLatin1String("uniqueMember");
     ldapSearchCollections.setAttributes(attrs);
+    ldapSearch.setAttributes(headers);
 
     connect(&ldapSearchCollections, SIGNAL(searchData(const QList<KLDAP::LdapResultObject> &)),
             SLOT(slotLDAPCollectionData(const QList<KLDAP::LdapResultObject> &)));
@@ -105,7 +107,7 @@ QVariant ResourceModel::headerData(int section, Qt::Orientation orientation,
                                    int role) const
 {
     if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
-        return rootItem->data(section);
+        return translateLDAPAttributeForDisplay(rootItem->data(section).toString());
     }
 
     return QVariant();


commit 50a757920cef55b555b78e3fc5a5b61fb554bf51
Author: Sandro Knauß <knauss at kolabsys.com>
Date:   Sat Jul 5 12:54:38 2014 +0200

    foo

diff --git a/incidenceeditor-ng/resourcemanagement.cpp b/incidenceeditor-ng/resourcemanagement.cpp
index 4da6343..e33349a 100644
--- a/incidenceeditor-ng/resourcemanagement.cpp
+++ b/incidenceeditor-ng/resourcemanagement.cpp
@@ -19,6 +19,8 @@
  *
  */
 
+//http://stackoverflow.com/questions/18831242/qt-start-editing-of-cell-after-one-click
+
 #include "resourcemanagement.h"
 #include "ui_resourcemanagement.h"
 #include "resourcemodel.h"


commit f2afb5543f5f3e1878f7741cb84a69ad0ea9719e
Author: Sandro Knauß <knauss at kolabsys.com>
Date:   Tue Jun 24 14:48:53 2014 +0200

    completionbox for resources also activate

diff --git a/incidenceeditor-ng/incidenceattendee.cpp b/incidenceeditor-ng/incidenceattendee.cpp
index e10c2cf..1dd0e12 100644
--- a/incidenceeditor-ng/incidenceattendee.cpp
+++ b/incidenceeditor-ng/incidenceattendee.cpp
@@ -147,14 +147,14 @@ IncidenceAttendee::IncidenceAttendee( QWidget *parent, IncidenceDateTime *dateTi
 #else
   mUi->mAttendeeTable->setModel(filterProxyModel);
 
-  AttendeeLineEditDelegate *attendeeDelegate = new AttendeeLineEditDelegate(this);
-  attendeeDelegate->setCompletionMode( KGlobalSettings::self()->completionMode() );
+  mAttendeeDelegate = new AttendeeLineEditDelegate(this);
+  mAttendeeDelegate->setCompletionMode( KGlobalSettings::self()->completionMode() );
 
   QHeaderView* headerView = mUi->mAttendeeTable->horizontalHeader();
   headerView->setResizeMode(QHeaderView::ResizeToContents);
 
   mUi->mAttendeeTable->setItemDelegateForColumn(AttendeeTableModel::Role, roleDelegate());
-  mUi->mAttendeeTable->setItemDelegateForColumn(AttendeeTableModel::FullName, attendeeDelegate);
+  mUi->mAttendeeTable->setItemDelegateForColumn(AttendeeTableModel::FullName, attendeeDelegate());
   mUi->mAttendeeTable->setItemDelegateForColumn(AttendeeTableModel::Status, stateDelegate());
   mUi->mAttendeeTable->setItemDelegateForColumn(AttendeeTableModel::Response, responseDelegate());
 #endif
@@ -700,6 +700,12 @@ AttendeeComboBoxDelegate* IncidenceAttendee::stateDelegate()
   return mStateDelegate;
 }
 
+AttendeeLineEditDelegate *IncidenceAttendee::attendeeDelegate()
+{
+  return mAttendeeDelegate;
+}
+
+
 void IncidenceAttendee::filterLayoutChanged()
 {
 #ifndef KDEPIM_MOBILE_UI
diff --git a/incidenceeditor-ng/incidenceattendee.h b/incidenceeditor-ng/incidenceattendee.h
index 46d47bc..cf07170 100644
--- a/incidenceeditor-ng/incidenceattendee.h
+++ b/incidenceeditor-ng/incidenceattendee.h
@@ -44,6 +44,7 @@ namespace IncidenceEditorNG {
 
 class AttendeeEditor;
 class AttendeeComboBoxDelegate;
+class AttendeeLineEditDelegate;
 class ConflictResolver;
 class IncidenceDateTime;
 
@@ -67,6 +68,7 @@ class INCIDENCEEDITORS_NG_EXPORT IncidenceAttendee : public IncidenceEditor
     AttendeeComboBoxDelegate *stateDelegate();
     AttendeeComboBoxDelegate *roleDelegate();
     AttendeeComboBoxDelegate *responseDelegate();
+    AttendeeLineEditDelegate *attendeeDelegate();
 
     int attendeeCount() const;
 
@@ -130,6 +132,7 @@ class INCIDENCEEDITORS_NG_EXPORT IncidenceAttendee : public IncidenceEditor
 
     /** used dataModel to rely on*/
     AttendeeTableModel *mDataModel;
+    AttendeeLineEditDelegate *mAttendeeDelegate;
     AttendeeComboBoxDelegate *mStateDelegate;
     AttendeeComboBoxDelegate *mRoleDelegate;
     AttendeeComboBoxDelegate *mResponseDelegate;
diff --git a/incidenceeditor-ng/incidenceresource.cpp b/incidenceeditor-ng/incidenceresource.cpp
index a8830e0..1178a9e 100644
--- a/incidenceeditor-ng/incidenceresource.cpp
+++ b/incidenceeditor-ng/incidenceresource.cpp
@@ -86,6 +86,7 @@ IncidenceResource::IncidenceResource(IncidenceAttendee* ieAttendee, Ui::EventOrT
     mUi->mNewResource->setCompleter(completer);
 
     AttendeeLineEditDelegate *attendeeDelegate = new AttendeeLineEditDelegate(this);
+    attendeeDelegate->setCompletionMode( KGlobalSettings::self()->completionMode() );
 
     ResourceFilterProxyModel *filterProxyModel = new ResourceFilterProxyModel(this);
     filterProxyModel->setDynamicSortFilter(true);


commit 0fc0ad295a9eac93fbe4470aebef1ec333c707c5
Author: Sandro Knauß <knauss at kolabsys.com>
Date:   Tue Jun 24 09:59:17 2014 +0200

    using KLineEdit for resourcemanagment

diff --git a/incidenceeditor-ng/resourcemanagement.ui b/incidenceeditor-ng/resourcemanagement.ui
index cf6b003..09d6f37 100644
--- a/incidenceeditor-ng/resourcemanagement.ui
+++ b/incidenceeditor-ng/resourcemanagement.ui
@@ -23,7 +23,14 @@
       <number>2</number>
      </property>
      <item>
-      <widget class="QLineEdit" name="resourceSearch"/>
+      <widget class="KLineEdit" name="resourceSearch">
+       <property name="maximumSize">
+        <size>
+         <width>400</width>
+         <height>16777215</height>
+        </size>
+       </property>
+      </widget>
      </item>
      <item>
       <widget class="QTreeView" name="treeResults">
@@ -33,6 +40,12 @@
          <height>0</height>
         </size>
        </property>
+       <property name="maximumSize">
+        <size>
+         <width>400</width>
+         <height>16777215</height>
+        </size>
+       </property>
        <property name="alternatingRowColors">
         <bool>true</bool>
        </property>
@@ -79,6 +92,13 @@
    </item>
   </layout>
  </widget>
+ <customwidgets>
+  <customwidget>
+   <class>KLineEdit</class>
+   <extends>QLineEdit</extends>
+   <header>klineedit.h</header>
+  </customwidget>
+ </customwidgets>
  <resources/>
  <connections/>
 </ui>


commit fc094d53c38c6a92e40ed1ad43a5cddf6dac9365
Author: Sandro Knauß <knauss at kolabsys.com>
Date:   Thu Jun 19 12:27:36 2014 +0200

    only show first column in treeView

diff --git a/incidenceeditor-ng/resourcemanagement.cpp b/incidenceeditor-ng/resourcemanagement.cpp
index 0097208..4da6343 100644
--- a/incidenceeditor-ng/resourcemanagement.cpp
+++ b/incidenceeditor-ng/resourcemanagement.cpp
@@ -212,6 +212,8 @@ ResourceManagement::ResourceManagement()
     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()));
 }
 
 void ResourceManagement::slotStartSearch(const QString &text)
@@ -260,5 +262,11 @@ void ResourceManagement::slotInsertFreeBusy(const KCalCore::FreeBusy::Ptr &fb, c
 
 }
 
+void ResourceManagement::slotLayoutChanged()
+{
+    for(int i = 1; i < mUi->treeResults->model()->columnCount(QModelIndex());i++) {
+        mUi->treeResults->setColumnHidden(i, true);
+    }
+}
 
 #include "resourcemanagement.moc"
diff --git a/incidenceeditor-ng/resourcemanagement.h b/incidenceeditor-ng/resourcemanagement.h
index 893deac..c6dea43 100644
--- a/incidenceeditor-ng/resourcemanagement.h
+++ b/incidenceeditor-ng/resourcemanagement.h
@@ -69,6 +69,8 @@ private slots:
 
     void slotInsertFreeBusy( const KCalCore::FreeBusy::Ptr &fb, const QString &email );
 
+    void slotLayoutChanged();
+
 private:
     FreeBusyItemModel *mModel;
     Ui_resourceManagement *mUi;


commit ff9b4bf71630462d362eb52fadac5f671bc3aec8
Author: Sandro Knauß <knauss at kolabsys.com>
Date:   Thu Jun 19 12:26:57 2014 +0200

    removed QSharedPointer me

diff --git a/incidenceeditor-ng/resourceitem.cpp b/incidenceeditor-ng/resourceitem.cpp
index d93da1c..7089ea3 100644
--- a/incidenceeditor-ng/resourceitem.cpp
+++ b/incidenceeditor-ng/resourceitem.cpp
@@ -68,7 +68,13 @@ int ResourceItem::childCount() const
 int ResourceItem::childNumber() const
 {
     if (parentItem) {
-        return parentItem->childItems.indexOf(me);
+        int i = 0;
+        foreach (ResourceItem::Ptr child, parentItem->childItems){
+            if (child == this) {
+                return i;
+            }
+            i++;
+        }
     }
 
     return 0;
@@ -98,7 +104,6 @@ bool ResourceItem::insertChild(int position, ResourceItem::Ptr item)
         return false;
     }
 
-    item->me = item;
     childItems.insert(position, item);
 
     return true;
diff --git a/incidenceeditor-ng/resourceitem.h b/incidenceeditor-ng/resourceitem.h
index 70ab212..3c04373 100644
--- a/incidenceeditor-ng/resourceitem.h
+++ b/incidenceeditor-ng/resourceitem.h
@@ -95,8 +95,6 @@ public:
      */
     void startSearch();
 
-    Ptr me;
-
 private:
     /* data source
      *
diff --git a/incidenceeditor-ng/resourcemodel.cpp b/incidenceeditor-ng/resourcemodel.cpp
index 6cfa9c2..274dee0 100644
--- a/incidenceeditor-ng/resourcemodel.cpp
+++ b/incidenceeditor-ng/resourcemodel.cpp
@@ -34,7 +34,6 @@ ResourceModel::ResourceModel(const QStringList &headers,
 
     this->headers = headers;
     rootItem = ResourceItem::Ptr(new ResourceItem(KLDAP::LdapDN(), headers, KLDAP::LdapClient(0)));
-    rootItem->me = rootItem;
 
     ldapSearchCollections.setFilter(QString::fromLatin1("&(objectClass=kolabGroupOfUniqueNames)(mail=*)"
                                     "(|(cn=%1)(givenName=%1)(sn=%1))"));


commit cf61af1fb293c1338d99bb203eca1ada6da7892b
Author: Sandro Knauß <knauss at kolabsys.com>
Date:   Thu Jun 19 11:56:29 2014 +0200

    no dataChanged is needed when new row is added

diff --git a/incidenceeditor-ng/attendeetablemodel.cpp b/incidenceeditor-ng/attendeetablemodel.cpp
index 66ca10b..a3242e8 100644
--- a/incidenceeditor-ng/attendeetablemodel.cpp
+++ b/incidenceeditor-ng/attendeetablemodel.cpp
@@ -92,7 +92,7 @@ bool AttendeeTableModel::setData(const QModelIndex& index, const QVariant& value
             attendeeList[index.row()]->setName(name);
             attendeeList[index.row()]->setEmail(email);
 
-            addEmptyAttendee(true);
+            addEmptyAttendee();
             break;
         case Available:
             //attendeeList[index.row()].available = value.toBool();
@@ -179,11 +179,7 @@ bool AttendeeTableModel::insertAttendee(int position, const KCalCore::Attendee::
 
     endInsertRows();
 
-    QModelIndex topLeft = index(position, 0);
-    QModelIndex bottomRight = index(position, columnCount()-1);
-    emit dataChanged(topLeft, bottomRight);
-
-    addEmptyAttendee(true);
+    addEmptyAttendee();
 
     return true;
 }
@@ -194,7 +190,7 @@ void AttendeeTableModel::setAttendees(const KCalCore::Attendee::List attendees)
 
     attendeeList = attendees;
 
-    addEmptyAttendee(false);
+    addEmptyAttendee();
 
     emit layoutChanged();
 }
@@ -205,7 +201,7 @@ KCalCore::Attendee::List AttendeeTableModel::attendees() const
     return attendeeList;
 }
 
-void AttendeeTableModel::addEmptyAttendee(bool emitDataChanged)
+void AttendeeTableModel::addEmptyAttendee()
 {
     if (mKeepEmpty) {
         bool create=true;
@@ -218,11 +214,6 @@ void AttendeeTableModel::addEmptyAttendee(bool emitDataChanged)
 
         if (create) {
             insertRows(rowCount(),1);
-            if (emitDataChanged) {
-                QModelIndex topLeft = index(rowCount()-1, 0);
-                QModelIndex bottomRight = index(rowCount()-1, columnCount()-1);
-                emit dataChanged(topLeft, bottomRight);
-            }
         }
     }
 }
@@ -237,7 +228,7 @@ void AttendeeTableModel::setKeepEmpty(bool keepEmpty)
 {
     if (keepEmpty != mKeepEmpty) {
         mKeepEmpty = keepEmpty;
-        addEmptyAttendee(true);
+        addEmptyAttendee();
     }
 }
 
diff --git a/incidenceeditor-ng/attendeetablemodel.h b/incidenceeditor-ng/attendeetablemodel.h
index 356230a..01599a4 100644
--- a/incidenceeditor-ng/attendeetablemodel.h
+++ b/incidenceeditor-ng/attendeetablemodel.h
@@ -77,7 +77,7 @@ public:
     void setRemoveEmptyLines(bool removeEmptyLines);
     bool removeEmptyLines();
 private:
-    void addEmptyAttendee(bool emitDataChanged);
+    void addEmptyAttendee();
 
     KCalCore::Attendee::List attendeeList;
     bool mKeepEmpty;


commit d58bf16de26ae96a6a455cb075f6f35160574026
Author: Sandro Knauß <knauss at kolabsys.com>
Date:   Thu Jun 19 11:53:01 2014 +0200

    only shoing freebusy File not all other widgets
    
    (copied from VisualFreeBusyWidget)

diff --git a/incidenceeditor-ng/resourcemanagement.cpp b/incidenceeditor-ng/resourcemanagement.cpp
index e81f6e0..0097208 100644
--- a/incidenceeditor-ng/resourcemanagement.cpp
+++ b/incidenceeditor-ng/resourcemanagement.cpp
@@ -24,20 +24,130 @@
 #include "resourcemodel.h"
 #include "freebusyitem.h"
 
-//#include "korganizer/korganizer_part.h"
-#include "visualfreebusywidget.h"
+#include "freebusyganttproxymodel.h"
+
+#include <kdgantt2/kdganttgraphicsview.h>
+#include <kdgantt2/kdganttview.h>
+#include <kdgantt2/kdganttdatetimegrid.h>
+#include <kdgantt2/kdganttabstractrowcontroller.h>
 
 #include <akonadi/calendar/freebusymanager.h>
 #include <kldap/ldapobject.h>
 
+#include <QPointer>
+#include <QSplitter>
 #include <QStringList>
 #include <QLabel>
 
+
 #include <KDebug>
 
 
 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 );
+    }
+
+    /*reimp*/
+    int maximumItemHeight() const
+    {
+      return mRowHeight*6/8;
+    }
+
+    /*reimp*/
+    int totalHeight() const
+    {
+      return m_model->rowCount() * mRowHeight;
+    }
+
+    /*reimp*/
+    QModelIndex indexAt( int height ) const
+    {
+      return m_model->index( height / mRowHeight, 0 );
+    }
+
+    /*reimp*/
+    QModelIndex indexBelow( const QModelIndex &idx ) const
+    {
+      if ( !idx.isValid() ) {
+        return QModelIndex();
+      }
+      return idx.model()->index( idx.row() + 1, idx.column(), idx.parent() );
+    }
+
+    /*reimp*/
+    QModelIndex indexAbove( const QModelIndex &idx ) const
+    {
+      if ( !idx.isValid() ) {
+        return QModelIndex();
+      }
+      return idx.model()->index( idx.row() - 1, idx.column(), idx.parent() );
+    }
+
+    void setRowHeight( int height )
+    {
+      mRowHeight = height;
+    }
+
+  private:
+    int mRowHeight;
+
+};
+
+class GanttHeaderView : public QHeaderView
+{
+public:
+    explicit GanttHeaderView( QWidget *parent = 0 ) : QHeaderView( Qt::Horizontal, parent )
+    {
+    }
+
+        QSize sizeHint() const
+            {
+                QSize s = QHeaderView::sizeHint();
+                s.rheight() *= 2;
+                return s;
+            }
+};
+
+
 ResourceManagement::ResourceManagement()
 {
 
@@ -54,15 +164,40 @@ ResourceManagement::ResourceManagement()
     //resourceCalender = view->topLevelWidget();
     mModel = new FreeBusyItemModel;
 #ifndef KDEPIM_MOBILE_UI
-    VisualFreeBusyWidget *mVisualWidget = new VisualFreeBusyWidget( mModel, 8, this );
-    mUi->resourceCalender->addWidget( mVisualWidget );
+
+    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
 
     QStringList attrs;
     attrs << QLatin1String("cn") << QLatin1String("mail") << QLatin1String("givenname") << QLatin1String("sn");
 
-    ResourceModel *model = new ResourceModel(attrs);
-    mUi->treeResults->setModel(model);
+    ResourceModel *resourcemodel = new ResourceModel(attrs);
+    mUi->treeResults->setModel(resourcemodel);
 
     // This doesn't work till now :( -> that's why i use the clieck signal
     mUi->treeResults->setSelectionMode(QAbstractItemView::SingleSelection);


commit 3ba3df6da9bda3a9f71e518cf4e103aed0cc7971
Author: Sandro Knauß <knauss at kolabsys.com>
Date:   Thu Jun 19 11:52:29 2014 +0200

    showing fb object

diff --git a/incidenceeditor-ng/resourcemanagement.cpp b/incidenceeditor-ng/resourcemanagement.cpp
index 8b884ed..e81f6e0 100644
--- a/incidenceeditor-ng/resourcemanagement.cpp
+++ b/incidenceeditor-ng/resourcemanagement.cpp
@@ -22,45 +22,71 @@
 #include "resourcemanagement.h"
 #include "ui_resourcemanagement.h"
 #include "resourcemodel.h"
+#include "freebusyitem.h"
 
+//#include "korganizer/korganizer_part.h"
+#include "visualfreebusywidget.h"
+
+#include <akonadi/calendar/freebusymanager.h>
 #include <kldap/ldapobject.h>
 
 #include <QStringList>
 #include <QLabel>
 
+#include <KDebug>
+
+
 using namespace IncidenceEditorNG;
 
 ResourceManagement::ResourceManagement()
 {
-    ui = new Ui::ResourceManagement;
-    ui->setupUi(this);
+
+    mUi = new Ui_resourceManagement;
+
+    QWidget *w = new QWidget( this );
+    mUi->setupUi( w );
+    setMainWidget( w );
+
+    QVariantList list;
+    //QGridLayout *layout = new QGridLayout( resourceCalender );
+    //layout->setSpacing( 0 );
+    //KOrganizerPart *view = new KOrganizerPart(resourceCalender,  this,  list);
+    //resourceCalender = view->topLevelWidget();
+    mModel = new FreeBusyItemModel;
+#ifndef KDEPIM_MOBILE_UI
+    VisualFreeBusyWidget *mVisualWidget = new VisualFreeBusyWidget( mModel, 8, this );
+    mUi->resourceCalender->addWidget( mVisualWidget );
+#endif
 
     QStringList attrs;
     attrs << QLatin1String("cn") << QLatin1String("mail") << QLatin1String("givenname") << QLatin1String("sn");
 
     ResourceModel *model = new ResourceModel(attrs);
-    ui->treeResults->setModel(model);
+    mUi->treeResults->setModel(model);
 
     // This doesn't work till now :( -> that's why i use the clieck signal
-    ui->treeResults->setSelectionMode(QAbstractItemView::SingleSelection);
-    selectionModel = ui->treeResults->selectionModel();
+    mUi->treeResults->setSelectionMode(QAbstractItemView::SingleSelection);
+    selectionModel = mUi->treeResults->selectionModel();
 
-    connect(ui->resourceSearch, SIGNAL(textChanged(const QString&)),
+    connect(mUi->resourceSearch, SIGNAL(textChanged(const QString&)),
             SLOT(slotStartSearch(const QString&)));
 
-    connect(ui->treeResults, SIGNAL(clicked(const QModelIndex &)),
+    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)) );
 }
 
 void ResourceManagement::slotStartSearch(const QString &text)
 {
-    ((ResourceModel*)ui->treeResults->model())->startSearch(text);
+    ((ResourceModel*)mUi->treeResults->model())->startSearch(text);
 }
 
 void ResourceManagement::slotShowDetails(const QModelIndex & current)
 {
-    ResourceItem *item = ((ResourceModel*)current.model())->getItem(current);
+    ResourceItem::Ptr item = current.model()->data(current, ResourceModel::Resource).value<ResourceItem::Ptr>();
     showDetails(item->ldapObject());
 }
 
@@ -69,7 +95,7 @@ void ResourceManagement::showDetails(const KLDAP::LdapObject &obj)
 {
     // Clean up formDetails
     QLayoutItem *child;
-    while ((child = ui->formDetails->takeAt(0)) != 0) {
+    while ((child = mUi->formDetails->takeAt(0)) != 0) {
         delete child->widget();
         delete child;
     }
@@ -80,21 +106,24 @@ void ResourceManagement::showDetails(const KLDAP::LdapObject &obj)
         foreach(const QByteArray & value, obj.attributes().value(key)) {
             list << QString::fromUtf8(value);
         }
-        ui->formDetails->addRow(key, new QLabel(list.join("\n")));
+        kDebug() << key <<  list;
+        mUi->formDetails->addRow(key, new QLabel(list.join("\n")));
     }
 
-    /*
-     * TODO: Has to be needed and tested : )
-    KUrl httpUrl;
-    httpUrl.setUser(  userName );
-    httpUrl.setPassword(  password );
-    httpUrl.setHost(  host );
-    httpUrl.setProtocol(  QLatin1String(  "https" ) );
-    httpUrl.setPath(  QLatin1String( "/freebusy/" ) + user + QLatin1String( ".ifb" ) );
+    QString name = QString::fromUtf8(obj.attributes().value("cn")[0]);
+    QString email = QString::fromUtf8(obj.attributes().value("mail")[0]);
+    kDebug() <<  name <<  email;
+    KCalCore::Attendee::Ptr attendee(new KCalCore::Attendee(name,  email));
+    FreeBusyItem::Ptr freebusy( new FreeBusyItem( attendee, this ));
+    mModel->clear();
+    mModel->addItem(freebusy);
+}
 
-    KIO::Job *job = KIO::get(  url, KIO::NoReload, KIO::HideProgressInfo );
-    */
+void ResourceManagement::slotInsertFreeBusy(const KCalCore::FreeBusy::Ptr &fb, const QString &email)
+{
+    kDebug() <<  fb <<  email;
 
 }
 
+
 #include "resourcemanagement.moc"
diff --git a/incidenceeditor-ng/resourcemanagement.h b/incidenceeditor-ng/resourcemanagement.h
index 3749db6..893deac 100644
--- a/incidenceeditor-ng/resourcemanagement.h
+++ b/incidenceeditor-ng/resourcemanagement.h
@@ -27,15 +27,15 @@
 #include <ldap/ldapclient.h>
 #include <ldap/ldapclientsearch.h>
 
+#include "freebusyitemmodel.h"
+
+# include <KCalCore/FreeBusy>
 #include <KDialog>
 
 #include <QStringList>
 #include <QStringListModel>
 
-namespace Ui
-{
-class ResourceManagement;
-}
+class  Ui_resourceManagement;
 
 namespace IncidenceEditorNG
 {
@@ -54,8 +54,6 @@ private:
      */
     void showDetails(const KLDAP::LdapObject&);
 
-    Ui::ResourceManagement* ui;
-
     QItemSelectionModel *selectionModel;
 
 private slots:
@@ -68,6 +66,12 @@ private slots:
      *
      */
     void slotShowDetails(const QModelIndex & current);
+
+    void slotInsertFreeBusy( const KCalCore::FreeBusy::Ptr &fb, const QString &email );
+
+private:
+    FreeBusyItemModel *mModel;
+    Ui_resourceManagement *mUi;
 };
 
 }
diff --git a/incidenceeditor-ng/resourcemanagement.ui b/incidenceeditor-ng/resourcemanagement.ui
index 38002e1..cf6b003 100644
--- a/incidenceeditor-ng/resourcemanagement.ui
+++ b/incidenceeditor-ng/resourcemanagement.ui
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <ui version="4.0">
- <class>ResourceManagement</class>
+ <class>resourceManagement</class>
  <widget class="QWidget" name="resourceManagement">
   <property name="geometry">
    <rect>
@@ -15,7 +15,7 @@
   </property>
   <layout class="QHBoxLayout" name="horizontalLayout_2">
    <property name="spacing">
-    <number>-1</number>
+    <number>6</number>
    </property>
    <item>
     <layout class="QVBoxLayout" name="verticalLayout" stretch="0,0">
@@ -27,6 +27,12 @@
      </item>
      <item>
       <widget class="QTreeView" name="treeResults">
+       <property name="minimumSize">
+        <size>
+         <width>200</width>
+         <height>0</height>
+        </size>
+       </property>
        <property name="alternatingRowColors">
         <bool>true</bool>
        </property>
@@ -67,14 +73,7 @@
       </widget>
      </item>
      <item>
-      <widget class="QWidget" name="resourceCalender" native="true">
-       <property name="sizePolicy">
-        <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
-         <horstretch>0</horstretch>
-         <verstretch>0</verstretch>
-        </sizepolicy>
-       </property>
-      </widget>
+      <layout class="QHBoxLayout" name="resourceCalender"/>
      </item>
     </layout>
    </item>


commit c7ff61eedf0b77929c24def37fe9dbecd7e13f0a
Author: Sandro Knauß <knauss at kolabsys.com>
Date:   Thu Jun 19 10:27:34 2014 +0200

    showing "name <mail>" for resource completion box

diff --git a/incidenceeditor-ng/incidenceresource.cpp b/incidenceeditor-ng/incidenceresource.cpp
index 9839929..a8830e0 100644
--- a/incidenceeditor-ng/incidenceresource.cpp
+++ b/incidenceeditor-ng/incidenceresource.cpp
@@ -37,6 +37,25 @@
 #include <QCompleter>
 using namespace IncidenceEditorNG;
 
+class SwitchRoleProxy:public QSortFilterProxyModel {
+
+public:
+    SwitchRoleProxy(QObject *parent = 0)
+        : QSortFilterProxyModel(parent) {
+
+    }
+
+    virtual QVariant data(const QModelIndex& index, int role) const {
+        QVariant d;
+        if (role == Qt::DisplayRole || role == Qt::EditRole) {
+            d = QSortFilterProxyModel::data(index, ResourceModel::FullName);
+            return d;
+        }
+        d = QSortFilterProxyModel::data(index, role);
+        return d;
+    }
+};
+
 #ifdef KDEPIM_MOBILE_UI
 IncidenceResource::IncidenceResource(IncidenceAttendee* ieAttendee, Ui::EventOrTodoMore *ui)
 #else
@@ -58,8 +77,11 @@ IncidenceResource::IncidenceResource(IncidenceAttendee* ieAttendee, Ui::EventOrT
 
     KDescendantsProxyModel *proxyModel = new KDescendantsProxyModel( this );
     proxyModel->setSourceModel( model );
+    SwitchRoleProxy *proxyModel2 = new SwitchRoleProxy(this);
+    proxyModel2->setSourceModel(proxyModel);
 
-    completer->setModel(proxyModel);
+    completer->setModel(proxyModel2);
+    completer->setCompletionRole(ResourceModel::FullName);
     completer->setWrapAround(false);
     mUi->mNewResource->setCompleter(completer);
 
diff --git a/incidenceeditor-ng/resourceitem.cpp b/incidenceeditor-ng/resourceitem.cpp
index 09de7b6..d93da1c 100644
--- a/incidenceeditor-ng/resourceitem.cpp
+++ b/incidenceeditor-ng/resourceitem.cpp
@@ -28,10 +28,8 @@ ResourceItem::ResourceItem(const KLDAP::LdapDN &dn, QStringList attrs, const KLD
     : dn(dn)
     , attrs(attrs)
     , mLdapClient(0, this)
+    , parentItem(parent)
 {
-    parentItem = parent;
-
-
     if (!dn.isEmpty()) {
         KLDAP::LdapServer server = ldapClient.server();
 
@@ -86,6 +84,14 @@ QVariant ResourceItem::data(int column) const
     return itemData.value(column);
 }
 
+QVariant ResourceItem::data(const QString &column) const
+{
+    if (mLdapObject.attributes()[column].count() > 0) {
+        return QString::fromUtf8(mLdapObject.attributes()[column][0]);
+    }
+    return QVariant();
+}
+
 bool ResourceItem::insertChild(int position, ResourceItem::Ptr item)
 {
     if (position < 0 || position > childItems.size()) {
diff --git a/incidenceeditor-ng/resourceitem.h b/incidenceeditor-ng/resourceitem.h
index 621fb4a..70ab212 100644
--- a/incidenceeditor-ng/resourceitem.h
+++ b/incidenceeditor-ng/resourceitem.h
@@ -56,6 +56,7 @@ public:
     int childCount() const;
     int columnCount() const;
     QVariant data(int column) const;
+    QVariant data(const QString &column) const;
     bool insertChild(int position, ResourceItem::Ptr item);
     ResourceItem::Ptr parent();
     bool removeChildren(int position, int count);
diff --git a/incidenceeditor-ng/resourcemodel.cpp b/incidenceeditor-ng/resourcemodel.cpp
index 534515c..6cfa9c2 100644
--- a/incidenceeditor-ng/resourcemodel.cpp
+++ b/incidenceeditor-ng/resourcemodel.cpp
@@ -59,7 +59,7 @@ ResourceModel::~ResourceModel()
 
 int ResourceModel::columnCount(const QModelIndex & /* parent */) const
 {
-    return 1;
+    return rootItem->columnCount();
 }
 
 QVariant ResourceModel::data(const QModelIndex &index, int role) const
@@ -68,13 +68,18 @@ QVariant ResourceModel::data(const QModelIndex &index, int role) const
         return QVariant();
     }
 
-    if (role != Qt::DisplayRole && role != Qt::EditRole) {
-        return QVariant();
-    }
+    if ( role == Qt::EditRole ||  role ==  Qt::DisplayRole ) {
+        return getItem(index)->data(index.column());
+    } else if (role == Resource) {
+        ResourceItem *p = getItem(parent(index));
+        return QVariant::fromValue(p->child(index.row()));
+    } else if (role == FullName ) {
+        ResourceItem *item = getItem(index);
+        return KPIMUtils::normalizedAddress(item->data("cn").toString(), item->data("mail").toString());
 
-    ResourceItem *item = getItem(index);
+    }
 
-    return item->data(index.column());
+    return QVariant();
 }
 
 Qt::ItemFlags ResourceModel::flags(const QModelIndex &index) const
@@ -166,16 +171,19 @@ void ResourceModel::startSearch(const QString &query)
 
 void ResourceModel::startSearch()
 {
-    emit layoutAboutToBeChanged();
     // Delete all resources -> only collection elements are shown
     for (int i = 0; i < rootItem->childCount(); i++) {
         if (ldapCollections.contains(rootItem->child(i))) {
+            QModelIndex parentIndex = index(i, 0, QModelIndex());
+            beginRemoveRows(parentIndex, 0, rootItem->child(i)->childCount()-1);
             rootItem->child(i)->removeChildren(0, rootItem->child(i)->childCount());
+            endRemoveRows();
         } else {
+            beginRemoveRows(QModelIndex(), i, i);
             rootItem->removeChildren(i, 1);
+            endRemoveRows();
         }
     }
-    emit layoutChanged();
 
     if (searchString.count() > 0) {
         ldapSearch.startSearch("*" + searchString + "*");
@@ -186,15 +194,18 @@ void ResourceModel::startSearch()
 
 void ResourceModel::slotLDAPCollectionData(const QList<KLDAP::LdapResultObject> &results)
 {
+    emit layoutAboutToBeChanged();
+
     foundCollection = true;
     ldapCollectionsMap.clear();
     ldapCollections.clear();
 
-    emit layoutAboutToBeChanged();
+    kDebug() <<  "Found ldapCollections";
 
     foreach(const KLDAP::LdapResultObject & result, results) {
         ResourceItem::Ptr item(new ResourceItem(result.object.dn(), headers, *result.client, rootItem));
         item->setLdapObject(result.object);
+
         rootItem->insertChild(rootItem->childCount(), item);
         ldapCollections.insert(item);
 
@@ -211,8 +222,6 @@ void ResourceModel::slotLDAPCollectionData(const QList<KLDAP::LdapResultObject>
 
 void ResourceModel::slotLDAPSearchData(const QList<KLDAP::LdapResultObject> &results)
 {
-    emit layoutAboutToBeChanged();
-
     foreach(const KLDAP::LdapResultObject & result, results) {
         //Add the found items to all collections, where it is member
         QList<ResourceItem::Ptr> parents = ldapCollectionsMap.values(result.object.dn().toString());
@@ -223,9 +232,14 @@ void ResourceModel::slotLDAPSearchData(const QList<KLDAP::LdapResultObject> &res
         foreach(ResourceItem::Ptr parent, parents) {
             ResourceItem::Ptr item(new ResourceItem(result.object.dn(), headers, *result.client, parent));
             item->setLdapObject(result.object);
+
+            QModelIndex parentIndex;
+            if (parent !=  rootItem) {
+                parentIndex = index(parent->childNumber(), 0, parentIndex);
+            }
+            beginInsertRows(parentIndex, parent->childCount(), parent->childCount());
             parent->insertChild(parent->childCount(), item);
+            endInsertRows();
         }
     }
-
-    emit layoutChanged();
 }
diff --git a/incidenceeditor-ng/resourcemodel.h b/incidenceeditor-ng/resourcemodel.h
index 90f964d..1814aad 100644
--- a/incidenceeditor-ng/resourcemodel.h
+++ b/incidenceeditor-ng/resourcemodel.h
@@ -41,6 +41,11 @@ public:
     /* Copied from http://qt-project.org/doc/qt-4.8/itemviews-editabletreemodel.html:
      * QT 4.8: Editable Tree Model Example
      */
+    enum Roles {
+        Resource = Qt::UserRole,
+        FullName
+    };
+
     ResourceModel(const QStringList &headers,
                   QObject *parent = 0);
     ~ResourceModel();
@@ -60,10 +65,9 @@ public:
 
     bool removeRows(int position, int rows,
                     const QModelIndex &parent = QModelIndex());
-
-    ResourceItem *getItem(const QModelIndex &index) const;
-
 private:
+    ResourceItem* getItem(const QModelIndex &index) const;
+
     ResourceItem::Ptr rootItem;
 
 


commit 44d16b1139aff39243d6679a570cb1af4b73e1aa
Author: Sandro Knauß <knauss at kolabsys.com>
Date:   Thu Jun 19 10:25:18 2014 +0200

    ResourceItem* -> ResourceItem::Ptr

diff --git a/incidenceeditor-ng/resourceitem.cpp b/incidenceeditor-ng/resourceitem.cpp
index a57c826..09de7b6 100644
--- a/incidenceeditor-ng/resourceitem.cpp
+++ b/incidenceeditor-ng/resourceitem.cpp
@@ -24,7 +24,7 @@
 
 using namespace IncidenceEditorNG;
 
-ResourceItem::ResourceItem(const KLDAP::LdapDN &dn, QStringList attrs, const KLDAP::LdapClient &ldapClient, ResourceItem *parent)
+ResourceItem::ResourceItem(const KLDAP::LdapDN &dn, QStringList attrs, const KLDAP::LdapClient &ldapClient, ResourceItem::Ptr parent)
     : dn(dn)
     , attrs(attrs)
     , mLdapClient(0, this)
@@ -53,11 +53,10 @@ ResourceItem::ResourceItem(const KLDAP::LdapDN &dn, QStringList attrs, const KLD
 
 ResourceItem::~ResourceItem()
 {
-    qDeleteAll(childItems);
 }
 
 
-ResourceItem *ResourceItem::child(int number)
+ResourceItem::Ptr ResourceItem::child(int number)
 {
     return childItems.value(number);
 }
@@ -71,7 +70,7 @@ int ResourceItem::childCount() const
 int ResourceItem::childNumber() const
 {
     if (parentItem) {
-        return parentItem->childItems.indexOf(const_cast<ResourceItem*>(this));
+        return parentItem->childItems.indexOf(me);
     }
 
     return 0;
@@ -87,18 +86,19 @@ QVariant ResourceItem::data(int column) const
     return itemData.value(column);
 }
 
-bool ResourceItem::insertChild(int position, ResourceItem *item)
+bool ResourceItem::insertChild(int position, ResourceItem::Ptr item)
 {
     if (position < 0 || position > childItems.size()) {
         return false;
     }
 
+    item->me = item;
     childItems.insert(position, item);
 
     return true;
 }
 
-ResourceItem *ResourceItem::parent()
+ResourceItem::Ptr ResourceItem::parent()
 {
     return parentItem;
 }
@@ -110,7 +110,7 @@ bool ResourceItem::removeChildren(int position, int count)
     }
 
     for (int row = 0; row < count; ++row) {
-        delete childItems.takeAt(position);
+        childItems.removeAt(position);
     }
 
     return true;
diff --git a/incidenceeditor-ng/resourceitem.h b/incidenceeditor-ng/resourceitem.h
index d0aea66..621fb4a 100644
--- a/incidenceeditor-ng/resourceitem.h
+++ b/incidenceeditor-ng/resourceitem.h
@@ -22,8 +22,10 @@
 #ifndef RESOURCEITEM_H
 #define RESOURCEITEM_H
 
-#include <QObject>
 #include <QList>
+#include <QMetaType>
+#include <QSharedPointer>
+#include <QObject>
 #include <QStringList>
 #include <QVariant>
 #include <QVector>
@@ -41,22 +43,28 @@ public:
     /* Copied from http://qt-project.org/doc/qt-4.8/itemviews-editabletreemodel.html:
      * QT 4.8: Editable Tree Model Example
      */
-    ResourceItem(const KLDAP::LdapDN &dn, QStringList attrs, const KLDAP::LdapClient &ldapClient, ResourceItem *parent = 0);
+
+    /**
+      A shared pointer to an ResourceItem object.
+    */
+    typedef QSharedPointer<ResourceItem> Ptr;
+
+    ResourceItem(const KLDAP::LdapDN &dn, QStringList attrs, const KLDAP::LdapClient &ldapClient, ResourceItem::Ptr parent = ResourceItem::Ptr());
     ~ResourceItem();
 
-    ResourceItem *child(int number);
+    ResourceItem::Ptr child(int number);
     int childCount() const;
     int columnCount() const;
     QVariant data(int column) const;
-    bool insertChild(int position, ResourceItem *item);
-    ResourceItem *parent();
+    bool insertChild(int position, ResourceItem::Ptr item);
+    ResourceItem::Ptr parent();
     bool removeChildren(int position, int count);
     int childNumber() const;
 
 private:
-    QList<ResourceItem*> childItems;
+    QList<ResourceItem::Ptr> childItems;
     QVector<QVariant> itemData;
-    ResourceItem *parentItem;
+    ResourceItem::Ptr parentItem;
 
 public:
     /* Returns the attributes of the requested ldapObject.
@@ -86,6 +94,8 @@ public:
      */
     void startSearch();
 
+    Ptr me;
+
 private:
     /* data source
      *
@@ -116,4 +126,9 @@ private slots:
 
 };
 }
+
+//@cond PRIVATE
+  Q_DECLARE_TYPEINFO(IncidenceEditorNG::ResourceItem::Ptr, Q_MOVABLE_TYPE);
+  Q_DECLARE_METATYPE(IncidenceEditorNG::ResourceItem::Ptr)
+//@endcond
 #endif // RESOURCEITEM_H
diff --git a/incidenceeditor-ng/resourcemodel.cpp b/incidenceeditor-ng/resourcemodel.cpp
index 829e0e0..534515c 100644
--- a/incidenceeditor-ng/resourcemodel.cpp
+++ b/incidenceeditor-ng/resourcemodel.cpp
@@ -20,6 +20,9 @@
  */
 #include "resourcemodel.h"
 
+#include <KPIMUtils/Email>
+#include <KDebug>
+
 
 using namespace IncidenceEditorNG;
 
@@ -30,7 +33,8 @@ ResourceModel::ResourceModel(const QStringList &headers,
 {
 
     this->headers = headers;
-    rootItem = new ResourceItem(KLDAP::LdapDN(), headers, KLDAP::LdapClient(0), 0);
+    rootItem = ResourceItem::Ptr(new ResourceItem(KLDAP::LdapDN(), headers, KLDAP::LdapClient(0)));
+    rootItem->me = rootItem;
 
     ldapSearchCollections.setFilter(QString::fromLatin1("&(objectClass=kolabGroupOfUniqueNames)(mail=*)"
                                     "(|(cn=%1)(givenName=%1)(sn=%1))"));
@@ -51,7 +55,6 @@ ResourceModel::ResourceModel(const QStringList &headers,
 
 ResourceModel::~ResourceModel()
 {
-    delete rootItem;
 }
 
 int ResourceModel::columnCount(const QModelIndex & /* parent */) const
@@ -91,7 +94,7 @@ ResourceItem *ResourceModel::getItem(const QModelIndex &index) const
             return item;
         }
     }
-    return rootItem;
+    return rootItem.data();
 }
 
 QVariant ResourceModel::headerData(int section, Qt::Orientation orientation,
@@ -106,14 +109,11 @@ QVariant ResourceModel::headerData(int section, Qt::Orientation orientation,
 
 QModelIndex ResourceModel::index(int row, int column, const QModelIndex &parent) const
 {
-    if (parent.isValid() && parent.column() != 0) {
-        return QModelIndex();
-    }
     ResourceItem *parentItem = getItem(parent);
 
-    ResourceItem *childItem = parentItem->child(row);
-    if (childItem) {
-        return createIndex(row, column, childItem);
+    ResourceItem::Ptr childItem = parentItem->child(row);
+    if (row < parentItem->childCount() && childItem) {
+        return createIndex(row, column, childItem.data());
     } else {
         return QModelIndex();
     }
@@ -125,14 +125,14 @@ QModelIndex ResourceModel::parent(const QModelIndex &index) const
     if (!index.isValid()) {
         return QModelIndex();
     }
-    ResourceItem *childItem = getItem(index);
-    ResourceItem *parentItem = childItem->parent();
+    ResourceItem* childItem = getItem(index);
+    ResourceItem::Ptr parentItem = childItem->parent();
 
     if (parentItem == rootItem) {
         return QModelIndex();
     }
 
-    return createIndex(parentItem->childNumber(), 0, parentItem);
+    return createIndex(parentItem->childNumber(), index.column(), parentItem.data());
 }
 
 
@@ -193,7 +193,7 @@ void ResourceModel::slotLDAPCollectionData(const QList<KLDAP::LdapResultObject>
     emit layoutAboutToBeChanged();
 
     foreach(const KLDAP::LdapResultObject & result, results) {
-        ResourceItem *item = new ResourceItem(result.object.dn(), headers, *result.client, rootItem);
+        ResourceItem::Ptr item(new ResourceItem(result.object.dn(), headers, *result.client, rootItem));
         item->setLdapObject(result.object);
         rootItem->insertChild(rootItem->childCount(), item);
         ldapCollections.insert(item);
@@ -215,13 +215,13 @@ void ResourceModel::slotLDAPSearchData(const QList<KLDAP::LdapResultObject> &res
 
     foreach(const KLDAP::LdapResultObject & result, results) {
         //Add the found items to all collections, where it is member
-        QList<ResourceItem*> parents = ldapCollectionsMap.values(result.object.dn().toString());
+        QList<ResourceItem::Ptr> parents = ldapCollectionsMap.values(result.object.dn().toString());
         if (parents.count() == 0) {
             parents << rootItem;
         }
 
-        foreach(ResourceItem * parent, parents) {
-            ResourceItem *item = new ResourceItem(result.object.dn(), headers, *result.client, parent);
+        foreach(ResourceItem::Ptr parent, parents) {
+            ResourceItem::Ptr item(new ResourceItem(result.object.dn(), headers, *result.client, parent));
             item->setLdapObject(result.object);
             parent->insertChild(parent->childCount(), item);
         }
diff --git a/incidenceeditor-ng/resourcemodel.h b/incidenceeditor-ng/resourcemodel.h
index 4eb8a33..90f964d 100644
--- a/incidenceeditor-ng/resourcemodel.h
+++ b/incidenceeditor-ng/resourcemodel.h
@@ -64,7 +64,7 @@ public:
     ResourceItem *getItem(const QModelIndex &index) const;
 
 private:
-    ResourceItem *rootItem;
+    ResourceItem::Ptr rootItem;
 
 
 public:
@@ -94,12 +94,12 @@ private:
      * A Resource can be part of different collection, so a QMuliMap is needed
      *
      */
-    QMultiMap<QString, ResourceItem*> ldapCollectionsMap;
+    QMultiMap<QString, ResourceItem::Ptr> ldapCollectionsMap;
 
     /* A Set of all collection ResourceItems
      *
      */
-    QSet <ResourceItem*> ldapCollections;
+    QSet <ResourceItem::Ptr> ldapCollections;
 
     /* Cached searchString (setted by startSearch(QString))
      *


commit bfb208aa8aa048308558f4e25dfee9eea7d6ae88
Author: Sandro Knauß <knauss at kolabsys.com>
Date:   Wed Jun 18 19:12:12 2014 +0200

    make incedentAttendee workable

diff --git a/incidenceeditor-ng/attendeetablemodel.cpp b/incidenceeditor-ng/attendeetablemodel.cpp
index 78c21bd..66ca10b 100644
--- a/incidenceeditor-ng/attendeetablemodel.cpp
+++ b/incidenceeditor-ng/attendeetablemodel.cpp
@@ -3,8 +3,6 @@
 #include <KCalCore/Attendee>
 #include <KPIMUtils/Email>
 
-#include <KDebug>
-
 using namespace IncidenceEditorNG;
 
 AttendeeTableModel::AttendeeTableModel(const KCalCore::Attendee::List &attendees, QObject *parent)
@@ -68,6 +66,9 @@ QVariant AttendeeTableModel::data(const QModelIndex &index, int role) const
         }
 
     }
+    if (role ==  AttendeeRole) {
+        return QVariant::fromValue(attendeeList[index.row()]);
+    }
     return QVariant();
 }
 
@@ -80,6 +81,13 @@ bool AttendeeTableModel::setData(const QModelIndex& index, const QVariant& value
             attendeeList[index.row()]->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())) {
+                    removeRows(index.row(), 1);
+                    return true;
+                }
+            }
             KPIMUtils::extractEmailAddressAndName(value.toString(), email, name);
             attendeeList[index.row()]->setName(name);
             attendeeList[index.row()]->setEmail(email);
@@ -140,7 +148,7 @@ QVariant AttendeeTableModel::headerData(int section, Qt::Orientation orientation
 
 bool AttendeeTableModel::insertRows(int position, int rows, const QModelIndex &parent)
 {
-    beginInsertRows(QModelIndex(), position, position + rows);
+    beginInsertRows(parent, position, position + rows-1);
 
     for (int row = 0; row < rows; ++row) {
         KCalCore::Attendee::Ptr attendee(new KCalCore::Attendee("", ""));
@@ -153,7 +161,7 @@ bool AttendeeTableModel::insertRows(int position, int rows, const QModelIndex &p
 
 bool AttendeeTableModel::removeRows(int position, int rows, const QModelIndex &parent)
 {
-    beginRemoveRows(QModelIndex(), position, position + rows);
+    beginRemoveRows(parent, position, position + rows-1);
 
     for (int row = 0; row < rows; ++row) {
         attendeeList.remove(position);
@@ -171,6 +179,12 @@ bool AttendeeTableModel::insertAttendee(int position, const KCalCore::Attendee::
 
     endInsertRows();
 
+    QModelIndex topLeft = index(position, 0);
+    QModelIndex bottomRight = index(position, columnCount()-1);
+    emit dataChanged(topLeft, bottomRight);
+
+    addEmptyAttendee(true);
+
     return true;
 }
 
@@ -191,7 +205,7 @@ KCalCore::Attendee::List AttendeeTableModel::attendees() const
     return attendeeList;
 }
 
-void AttendeeTableModel::addEmptyAttendee(bool layoutChange)
+void AttendeeTableModel::addEmptyAttendee(bool emitDataChanged)
 {
     if (mKeepEmpty) {
         bool create=true;
@@ -203,14 +217,11 @@ void AttendeeTableModel::addEmptyAttendee(bool layoutChange)
         }
 
         if (create) {
-            if (layoutChange) {
-                emit layoutAboutToBeChanged();
-            }
-
             insertRows(rowCount(),1);
-
-            if (layoutChange) {
-                emit layoutChanged();
+            if (emitDataChanged) {
+                QModelIndex topLeft = index(rowCount()-1, 0);
+                QModelIndex bottomRight = index(rowCount()-1, columnCount()-1);
+                emit dataChanged(topLeft, bottomRight);
             }
         }
     }
@@ -230,6 +241,16 @@ void AttendeeTableModel::setKeepEmpty(bool keepEmpty)
     }
 }
 
+bool AttendeeTableModel::removeEmptyLines()
+{
+    return mRemoveEmptyLines;
+}
+
+void AttendeeTableModel::setRemoveEmptyLines(bool removeEmptyLines)
+{
+    mRemoveEmptyLines = removeEmptyLines;
+}
+
 
 ResourceFilterProxyModel::ResourceFilterProxyModel(QObject *parent)
     : QSortFilterProxyModel(parent)
diff --git a/incidenceeditor-ng/attendeetablemodel.h b/incidenceeditor-ng/attendeetablemodel.h
index dce56f0..356230a 100644
--- a/incidenceeditor-ng/attendeetablemodel.h
+++ b/incidenceeditor-ng/attendeetablemodel.h
@@ -36,6 +36,9 @@ class AttendeeTableModel : public QAbstractTableModel
     Q_OBJECT
 
 public:
+    enum Roles {
+        AttendeeRole = Qt::UserRole
+    };
 
     enum Columns {
       CuType,
@@ -52,7 +55,7 @@ public:
 
     int rowCount(const QModelIndex &parent = QModelIndex()) const;
     int columnCount(const QModelIndex &parent = QModelIndex()) const;
-    QVariant data(const QModelIndex &index, int role) const;
+    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
     QVariant headerData(int section, Qt::Orientation orientation,
                         int role = Qt::DisplayRole) const;
 
@@ -70,11 +73,15 @@ public:
 
     void setKeepEmpty(bool keepEmpty);
     bool keepEmpty();
+
+    void setRemoveEmptyLines(bool removeEmptyLines);
+    bool removeEmptyLines();
 private:
-    void addEmptyAttendee(bool layoutChange);
+    void addEmptyAttendee(bool emitDataChanged);
 
     KCalCore::Attendee::List attendeeList;
     bool mKeepEmpty;
+    bool mRemoveEmptyLines;
 };
 
 class ResourceFilterProxyModel : public QSortFilterProxyModel
diff --git a/incidenceeditor-ng/incidenceattendee.cpp b/incidenceeditor-ng/incidenceattendee.cpp
index 02a1ea7..e10c2cf 100644
--- a/incidenceeditor-ng/incidenceattendee.cpp
+++ b/incidenceeditor-ng/incidenceattendee.cpp
@@ -90,6 +90,7 @@ IncidenceAttendee::IncidenceAttendee( QWidget *parent, IncidenceDateTime *dateTi
   attendees.append(attendee);
   mDataModel = new AttendeeTableModel(attendees, this);
   mDataModel->setKeepEmpty(true);
+  mDataModel->setRemoveEmptyLines(true);
 
   #ifdef KDEPIM_MOBILE_UI
   mRoleDelegate->addItem(DesktopIcon("meeting-participant", 48),
@@ -197,17 +198,22 @@ IncidenceAttendee::IncidenceAttendee( QWidget *parent, IncidenceDateTime *dateTi
 
   connect( mAttendeeEditor, SIGNAL(editingFinished(KPIM::MultiplyingLine*)),
            SLOT(checkIfExpansionIsNeeded(KPIM::MultiplyingLine*)) );
-  connect( mAttendeeEditor, SIGNAL(changed(KCalCore::Attendee::Ptr,KCalCore::Attendee::Ptr)),
-           SLOT(slotAttendeeChanged(KCalCore::Attendee::Ptr,KCalCore::Attendee::Ptr)) );
 
-  connect(mDataModel, SIGNAL(layoutChanged()), SLOT(layoutChanged()));
-  connect(mDataModel, SIGNAL(rowsInserted(const QModelIndex&, int , int)), SLOT(updateCount()));
-  connect(mDataModel, SIGNAL(rowsRemoved(const QModelIndex&, int , int)), SLOT(updateCount()));
+  connect(mDataModel, SIGNAL(layoutChanged()), SLOT(slotAttendeeLayoutChanged()));
+  connect(mDataModel, SIGNAL(rowsAboutToBeRemoved(const QModelIndex&, int , int)), SLOT(slotAttendeeRemoved(const QModelIndex&,int,int)));
+  connect(mDataModel, SIGNAL(rowsInserted(const QModelIndex&, int , int)), SLOT(slotAttendeeAdded(const QModelIndex&,int,int)));
+  connect(mDataModel, SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&)), SLOT(slotAttendeeChanged(const QModelIndex&, const QModelIndex&)));
+
+  connect(filterProxyModel, SIGNAL(rowsInserted(const QModelIndex&, int , int)), SLOT(updateCount()));
+  connect(filterProxyModel, SIGNAL(rowsRemoved(const QModelIndex&, int , int)), SLOT(updateCount()));
+  // only update when FullName is changed
+  connect(filterProxyModel, SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&)), SLOT(updateCount()));
+  connect(filterProxyModel, SIGNAL(layoutChanged()), SLOT(updateCount()));
+  connect(filterProxyModel, SIGNAL(layoutChanged()), SLOT(filterLayoutChanged()));
 }
 
 IncidenceAttendee::~IncidenceAttendee()
 {
-  delete mDataModel;
 }
 
 void IncidenceAttendee::load( const KCalCore::Incidence::Ptr &incidence )
@@ -242,6 +248,7 @@ void IncidenceAttendee::load( const KCalCore::Incidence::Ptr &incidence )
   }
 
   mDataModel->setAttendees(incidence->attendees());
+  slotUpdateConflictLabel(0);
 
   setActions( incidence->type() );
 
@@ -343,7 +350,6 @@ void IncidenceAttendee::changeStatusForMe( KCalCore::Attendee::PartStat stat )
   const IncidenceEditorNG::EditorConfig *config = IncidenceEditorNG::EditorConfig::instance();
   Q_ASSERT( config );
 
-  KCalCore::Attendee::List attendees = mDataModel->attendees();
   for (int i=0;i<mDataModel->rowCount();i++) {
     QModelIndex index = mDataModel->index(i, AttendeeTableModel::Email);
     if ( config->thatIsMe( mDataModel->data(index, Qt::DisplayRole).toString() ) ) {
@@ -492,21 +498,65 @@ void IncidenceEditorNG::IncidenceAttendee::slotSolveConflictPressed()
   }
 }
 
-void IncidenceAttendee::slotAttendeeChanged( const KCalCore::Attendee::Ptr &oldAttendee,
-                                             const KCalCore::Attendee::Ptr &newAttendee )
+void IncidenceAttendee::slotAttendeeChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
 {
-  // if newAttendee's email is empty, we are probably removing an attendee
-  if ( mConflictResolver->containsAttendee( oldAttendee ) ) {
-    mConflictResolver->removeAttendee( oldAttendee );
-  }
-  if ( !mConflictResolver->containsAttendee( newAttendee ) && !newAttendee->email().isEmpty() ) {
-    mConflictResolver->insertAttendee( newAttendee );
+#ifndef KDEPIM_MOBILE_UI
+  if (AttendeeTableModel::FullName <= bottomRight.column() && AttendeeTableModel::FullName >= topLeft.column()) {
+       for (int i = topLeft.row(); i <= bottomRight.row(); i++) {
+           kDebug() <<  i;
+           QModelIndex index = dataModel()->index(i, AttendeeTableModel::Email);
+           KCalCore::Attendee::Ptr attendee = dataModel()->data(index,  AttendeeTableModel::AttendeeRole).value<KCalCore::Attendee::Ptr>();
+           if (mConflictResolver->containsAttendee(attendee)) {
+               mConflictResolver->removeAttendee(attendee);
+           }
+           if (!dataModel()->data(index).toString().isEmpty()) {
+               mConflictResolver->insertAttendee( attendee );
+           }
+       }
   }
   checkDirtyStatus();
+#endif
 }
 
+void IncidenceAttendee::slotAttendeeAdded(const QModelIndex &index, int first, int last)
+{
+    for (int i = first; i <= last; i++) {
+        QModelIndex email = dataModel()->index(i, AttendeeTableModel::Email, index);
+        if (!dataModel()->data(email).toString().isEmpty()) {
+            mConflictResolver->insertAttendee( dataModel()->data(email, AttendeeTableModel::AttendeeRole).value<KCalCore::Attendee::Ptr>() );
+        }
+    }
+    checkDirtyStatus();
+}
+
+void IncidenceAttendee::slotAttendeeRemoved(const QModelIndex &index, int first, int last)
+{
+    for (int i = first; i <= last; i++) {
+        kDebug() <<  i;
+        QModelIndex email = dataModel()->index(i, AttendeeTableModel::Email, index);
+        if (!dataModel()->data(email).toString().isEmpty()) {
+            mConflictResolver->removeAttendee( dataModel()->data(email, AttendeeTableModel::AttendeeRole).value<KCalCore::Attendee::Ptr>() );
+        }
+    }
+    checkDirtyStatus();
+}
+
+void IncidenceAttendee::slotAttendeeLayoutChanged()
+{
+    KCalCore::Attendee::List attendees = mDataModel->attendees();
+    mConflictResolver->clearAttendees();
+    foreach(KCalCore::Attendee::Ptr attendee, attendees) {
+        if (! attendee->email().isEmpty()) {
+            mConflictResolver->insertAttendee(attendee);
+        }
+    }
+    checkDirtyStatus();
+}
+
+
 void IncidenceAttendee::slotUpdateConflictLabel( int count )
 {
+  kDebug() <<  "slotUpdateConflictLabel";
   if ( attendeeCount() > 0 ) {
     mUi->mSolveButton->setEnabled( true );
     if ( count > 0 ) {
@@ -650,7 +700,7 @@ AttendeeComboBoxDelegate* IncidenceAttendee::stateDelegate()
   return mStateDelegate;
 }
 
-void IncidenceAttendee::layoutChanged()
+void IncidenceAttendee::filterLayoutChanged()
 {
 #ifndef KDEPIM_MOBILE_UI
   mUi->mAttendeeTable->setColumnHidden(AttendeeTableModel::CuType, true);
@@ -658,8 +708,6 @@ void IncidenceAttendee::layoutChanged()
   mUi->mAttendeeTable->setColumnHidden(AttendeeTableModel::Email, true);
   mUi->mAttendeeTable->setColumnHidden(AttendeeTableModel::Available, true);
 #endif
-
-  updateCount();
 }
 
 
diff --git a/incidenceeditor-ng/incidenceattendee.h b/incidenceeditor-ng/incidenceattendee.h
index 60c05ae..46d47bc 100644
--- a/incidenceeditor-ng/incidenceattendee.h
+++ b/incidenceeditor-ng/incidenceattendee.h
@@ -86,16 +86,19 @@ class INCIDENCEEDITORS_NG_EXPORT IncidenceAttendee : public IncidenceEditor
     void slotSelectAddresses();
     void slotSolveConflictPressed();
     void slotUpdateConflictLabel( int );
-    void slotAttendeeChanged( const KCalCore::Attendee::Ptr &oldAttendee,
-                              const KCalCore::Attendee::Ptr &newAttendee );
     void slotOrganizerChanged( const QString &organizer );
 
     // wrapper for the conflict resolver
     void slotEventDurationChanged();
 
-    void layoutChanged();
+    void filterLayoutChanged();
     void updateCount();
 
+    void slotAttendeeAdded(const QModelIndex &index, int first, int last);
+    void slotAttendeeRemoved(const QModelIndex &index, int first, int last);
+    void slotAttendeeChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight);
+    void slotAttendeeLayoutChanged();
+
 
   private:
     void changeStatusForMe( KCalCore::Attendee::PartStat );
diff --git a/incidenceeditor-ng/incidenceresource.cpp b/incidenceeditor-ng/incidenceresource.cpp
index 1b0781a..9839929 100644
--- a/incidenceeditor-ng/incidenceresource.cpp
+++ b/incidenceeditor-ng/incidenceresource.cpp
@@ -80,9 +80,12 @@ IncidenceResource::IncidenceResource(IncidenceAttendee* ieAttendee, Ui::EventOrT
 
     connect(mUi->mFindResourcesButton, SIGNAL(clicked()), SLOT(findResources()));
     connect(mUi->mBookResourceButton, SIGNAL(clicked()), SLOT(bookResource()));
-    connect(dataModel, SIGNAL(layoutChanged()), SLOT(layoutChanged()));
-    connect(dataModel, SIGNAL(rowsInserted(const QModelIndex&, int , int)), SLOT(updateCount()));
-    connect(dataModel, SIGNAL(rowsRemoved(const QModelIndex&, int , int)), SLOT(updateCount()));
+    connect(filterProxyModel, SIGNAL(layoutChanged()), SLOT(layoutChanged()));
+    connect(filterProxyModel, SIGNAL(layoutChanged()), SLOT(updateCount()));
+    connect(filterProxyModel, SIGNAL(rowsInserted(const QModelIndex&, int , int)), SLOT(updateCount()));
+    connect(filterProxyModel, SIGNAL(rowsRemoved(const QModelIndex&, int , int)), SLOT(updateCount()));
+    // only update when FullName is changed
+    connect(filterProxyModel, SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&)), SLOT(updateCount()));
 #endif
 }
 
@@ -122,14 +125,11 @@ void IncidenceResource::findResources()
 
 void IncidenceResource::layoutChanged()
 {
-
 #ifndef KDEPIM_MOBILE_UI
     mUi->mResourcesTable->setColumnHidden(AttendeeTableModel::CuType, true);
     mUi->mResourcesTable->setColumnHidden(AttendeeTableModel::Name, true);
     mUi->mResourcesTable->setColumnHidden(AttendeeTableModel::Email, true);
 #endif
-
-    updateCount();
 }
 
 
@@ -141,7 +141,20 @@ void IncidenceResource::updateCount()
 int IncidenceResource::resourceCount() const
 {
 #ifndef KDEPIM_MOBILE_UI
-    return mUi->mResourcesTable->model()->rowCount(QModelIndex());
+    int c=0;
+    QModelIndex index;
+    QAbstractItemModel *model = mUi->mResourcesTable->model();
+    if (!model ) {
+        return 0;
+      }
+    for(int i=0;i< model->rowCount(QModelIndex());i++) {
+        index = model->index(i,AttendeeTableModel::FullName);
+        if (!model->data(index).toString().isEmpty()) {
+            c++;
+          }
+      }
+    return c;
+
 #endif
     return 0;
 }


commit 03f0b80cb957ea0b4f320033f044397ec816a3ca
Author: Sandro Knauß <knauss at kolabsys.com>
Date:   Tue Jun 17 10:12:00 2014 +0200

    Moved logic from IncidenceResource -> IncidenceAttendee

diff --git a/incidenceeditor-ng/incidencedialog.cpp b/incidenceeditor-ng/incidencedialog.cpp
index 9b96a3c..b8dec82 100644
--- a/incidenceeditor-ng/incidencedialog.cpp
+++ b/incidenceeditor-ng/incidencedialog.cpp
@@ -166,9 +166,6 @@ IncidenceDialogPrivate::IncidenceDialogPrivate( Akonadi::IncidenceChanger *chang
   mIeRecurrence = new IncidenceRecurrence( mIeDateTime, mUi );
   mEditor->combine( mIeRecurrence );
 
-  mIeResource = new IncidenceResource( mUi );
-  mEditor->combine( mIeResource );
-
   IncidenceSecrecy *ieSecrecy = new IncidenceSecrecy( mUi );
   mEditor->combine( ieSecrecy );
 
@@ -176,6 +173,9 @@ IncidenceDialogPrivate::IncidenceDialogPrivate( Akonadi::IncidenceChanger *chang
   mIeAttendee->setParent(qq);
   mEditor->combine( mIeAttendee );
 
+  mIeResource = new IncidenceResource( mIeAttendee, mUi );
+  mEditor->combine( mIeResource );
+
   q->connect( mEditor, SIGNAL(showMessage(QString,KMessageWidget::MessageType)),
               SLOT(showMessage(QString,KMessageWidget::MessageType)) );
   q->connect( mEditor, SIGNAL(dirtyStatusChanged(bool)),
@@ -584,7 +584,8 @@ void IncidenceDialogPrivate::load( const Akonadi::Item &item )
 
   // Initialize tab's titles
   updateAttachmentCount( incidence->attachments().size() );
-  updateResourceCount( mIeResource->resourcesCount() );
+  updateResourceCount( mIeResource->resourceCount() );
+  updateAttendeeCount( mIeAttendee->attendeeCount() );
   handleRecurrenceChange( mIeRecurrence->currentRecurrenceType() );
   handleAlarmCountChange( incidence->alarms().count() );
 
diff --git a/incidenceeditor-ng/incidenceresource.cpp b/incidenceeditor-ng/incidenceresource.cpp
index f718e6b..1b0781a 100644
--- a/incidenceeditor-ng/incidenceresource.cpp
+++ b/incidenceeditor-ng/incidenceresource.cpp
@@ -32,82 +32,22 @@
 #include <KDescendantsProxyModel>
 #include <KMessageBox>
 
-#include <KCalUtils/Stringify>
 #include <KPIMUtils/Email>
 
-
 #include <QCompleter>
 using namespace IncidenceEditorNG;
 
 #ifdef KDEPIM_MOBILE_UI
-IncidenceResource::IncidenceResource(Ui::EventOrTodoMore *ui)
+IncidenceResource::IncidenceResource(IncidenceAttendee* ieAttendee, Ui::EventOrTodoMore *ui)
 #else
-IncidenceResource::IncidenceResource(Ui::EventOrTodoDesktop *ui)
+IncidenceResource::IncidenceResource(IncidenceAttendee* ieAttendee, Ui::EventOrTodoDesktop *ui)
 #endif
     : IncidenceEditor(0)
     , mUi(ui)
+    , dataModel(ieAttendee->dataModel())
 {
     setObjectName("IncidenceResource");
 
-    AttendeeComboBoxDelegate* roleDelegate(new AttendeeComboBoxDelegate(this));
-    AttendeeComboBoxDelegate* responseDelegate(new AttendeeComboBoxDelegate(this));
-#ifdef KDEPIM_MOBILE_UI
-    roleDelegate->addItem(DesktopIcon("meeting-participant", 48),
-                          KCalUtils::Stringify::attendeeRole(KCalCore::Attendee::ReqParticipant));
-    roleDelegate->addItem(DesktopIcon("meeting-participant-optional", 48),
-                          KCalUtils::Stringify::attendeeRole(KCalCore::Attendee::OptParticipant));
-    roleDelegate->addItem(DesktopIcon("meeting-observer", 48),
-                          KCalUtils::Stringify::attendeeRole(KCalCore::Attendee::NonParticipant));
-    roleDelegate->addItem(DesktopIcon("meeting-chair", 48),
-                          KCalUtils::Stringify::attendeeRole(KCalCore::Attendee::Chair));
-
-    responseDelegate->addItem( DesktopIcon( "meeting-participant-request-response", 48 ),
-                             i18nc( "@item:inlistbox", "Request Response" ) );
-    responseDelegate->addItem( DesktopIcon( "meeting-participant-no-response", 48 ),
-                             i18nc( "@item:inlistbox", "Request No Response" ) );
-
-#else
-    roleDelegate->addItem(SmallIcon("meeting-participant"),
-                          KCalUtils::Stringify::attendeeRole(KCalCore::Attendee::ReqParticipant));
-    roleDelegate->addItem(SmallIcon("meeting-participant-optional"),
-                          KCalUtils::Stringify::attendeeRole(KCalCore::Attendee::OptParticipant));
-    roleDelegate->addItem(SmallIcon("meeting-observer"),
-                          KCalUtils::Stringify::attendeeRole(KCalCore::Attendee::NonParticipant));
-    roleDelegate->addItem(SmallIcon("meeting-chair"),
-                          KCalUtils::Stringify::attendeeRole(KCalCore::Attendee::Chair));
-
-    responseDelegate->addItem( SmallIcon( "meeting-participant-request-response" ),
-                             i18nc( "@item:inlistbox", "Request Response" ) );
-    responseDelegate->addItem( SmallIcon( "meeting-participant-no-response" ),
-                             i18nc( "@item:inlistbox", "Request No Response" ) );
-
-#endif
-
-    AttendeeComboBoxDelegate *stateDelegate(new AttendeeComboBoxDelegate(this));
-
-#ifdef KDEPIM_MOBILE_UI
-    stateDelegate->addItem(DesktopIcon("task-attention", 48),
-                           KCalUtils::Stringify::attendeeStatus(KCalCore::Attendee::NeedsAction));
-    stateDelegate->addItem(DesktopIcon("task-accepted", 48),
-                           KCalUtils::Stringify::attendeeStatus(KCalCore::Attendee::Accepted));
-    stateDelegate->addItem(DesktopIcon("task-reject", 48),
-                           KCalUtils::Stringify::attendeeStatus(KCalCore::Attendee::Declined));
-    stateDelegate->addItem(DesktopIcon("task-attempt", 48),
-                           KCalUtils::Stringify::attendeeStatus(KCalCore::Attendee::Tentative));
-    stateDelegate->addItem(DesktopIcon("task-delegate", 48),
-                           KCalUtils::Stringify::attendeeStatus(KCalCore::Attendee::Delegated));
-#else
-    stateDelegate->addItem(SmallIcon("task-attention"),
-                           KCalUtils::Stringify::attendeeStatus(KCalCore::Attendee::NeedsAction));
-    stateDelegate->addItem(SmallIcon("task-accepted"),
-                           KCalUtils::Stringify::attendeeStatus(KCalCore::Attendee::Accepted));
-    stateDelegate->addItem(SmallIcon("task-reject"),
-                           KCalUtils::Stringify::attendeeStatus(KCalCore::Attendee::Declined));
-    stateDelegate->addItem(SmallIcon("task-attempt"),
-                           KCalUtils::Stringify::attendeeStatus(KCalCore::Attendee::Tentative));
-    stateDelegate->addItem(SmallIcon("task-delegate"),
-                           KCalUtils::Stringify::attendeeStatus(KCalCore::Attendee::Delegated));
-#endif
 
 #ifndef KDEPIM_MOBILE_UI
     QStringList attrs;
@@ -123,10 +63,8 @@ IncidenceResource::IncidenceResource(Ui::EventOrTodoDesktop *ui)
     completer->setWrapAround(false);
     mUi->mNewResource->setCompleter(completer);
 
-    KCalCore::Attendee::List resources;
     AttendeeLineEditDelegate *attendeeDelegate = new AttendeeLineEditDelegate(this);
 
-    dataModel = new AttendeeTableModel(resources, this);
     ResourceFilterProxyModel *filterProxyModel = new ResourceFilterProxyModel(this);
     filterProxyModel->setDynamicSortFilter(true);
     filterProxyModel->setSourceModel(dataModel);
@@ -135,97 +73,33 @@ IncidenceResource::IncidenceResource(Ui::EventOrTodoDesktop *ui)
     headerView->setResizeMode(QHeaderView::ResizeToContents);
 
     mUi->mResourcesTable->setModel(filterProxyModel);
-    mUi->mResourcesTable->setColumnHidden(AttendeeTableModel::CuType, true);
-    mUi->mResourcesTable->setItemDelegateForColumn(AttendeeTableModel::Role, roleDelegate);
-    mUi->mResourcesTable->setItemDelegateForColumn(AttendeeTableModel::Name, attendeeDelegate);
-    mUi->mResourcesTable->setItemDelegateForColumn(AttendeeTableModel::Status, stateDelegate);
-    mUi->mResourcesTable->setItemDelegateForColumn(AttendeeTableModel::Response, responseDelegate);
-
-
-    AttendeeFilterProxyModel *attendeeProxyModel = new AttendeeFilterProxyModel(this);
-    attendeeProxyModel->setDynamicSortFilter(true);
-    attendeeProxyModel->setSourceModel(dataModel);
-    mUi->mAttendeeTable->setModel(attendeeProxyModel);
-    mUi->mAttendeeTable->setItemDelegateForColumn(AttendeeTableModel::Role, roleDelegate);
-    mUi->mAttendeeTable->setItemDelegateForColumn(AttendeeTableModel::Name, attendeeDelegate);
-    mUi->mAttendeeTable->setItemDelegateForColumn(AttendeeTableModel::Status, stateDelegate);
-    mUi->mAttendeeTable->setItemDelegateForColumn(AttendeeTableModel::Response, responseDelegate);
+    mUi->mResourcesTable->setItemDelegateForColumn(AttendeeTableModel::Role, ieAttendee->roleDelegate());
+    mUi->mResourcesTable->setItemDelegateForColumn(AttendeeTableModel::FullName, attendeeDelegate);
+    mUi->mResourcesTable->setItemDelegateForColumn(AttendeeTableModel::Status, ieAttendee->stateDelegate());
+    mUi->mResourcesTable->setItemDelegateForColumn(AttendeeTableModel::Response, ieAttendee->responseDelegate());
 
     connect(mUi->mFindResourcesButton, SIGNAL(clicked()), SLOT(findResources()));
     connect(mUi->mBookResourceButton, SIGNAL(clicked()), SLOT(bookResource()));
     connect(dataModel, SIGNAL(layoutChanged()), SLOT(layoutChanged()));
-    connect(dataModel, SIGNAL(rowsInserted(const QModelIndex&, int , int)), SLOT(layoutChanged()));
-    connect(dataModel, SIGNAL(rowsRemoved(const QModelIndex&, int , int)), SLOT(layoutChanged()));
+    connect(dataModel, SIGNAL(rowsInserted(const QModelIndex&, int , int)), SLOT(updateCount()));
+    connect(dataModel, SIGNAL(rowsRemoved(const QModelIndex&, int , int)), SLOT(updateCount()));
 #endif
 }
 
 void IncidenceResource::load(const KCalCore::Incidence::Ptr &incidence)
 {
-    mLoadedIncidence = incidence;
-    dataModel->setAttendees(incidence->attendees());
+  //all logic inside IncidenceAtendee (using same model)
 }
 
 void IncidenceResource::save(const KCalCore::Incidence::Ptr &incidence)
 {
-    incidence->clearAttendees();
-    KCalCore::Attendee::List attendees = dataModel->attendees();
-
-    foreach(KCalCore::Attendee::Ptr attendee, attendees) {
-        Q_ASSERT(attendee);
-
-        bool skip = false;
-        if (KPIMUtils::isValidAddress(attendee->email())) {
-            if (KMessageBox::warningYesNo(
-                        0,
-                        i18nc("@info",
-                              "%1 does not look like a valid email address. "
-                              "Are you sure you want to invite this participant?",
-                              attendee->email()),
-                        i18nc("@title:window", "Invalid Email Address")) != KMessageBox::Yes) {
-                skip = true;
-            }
-        }
-        if (!skip) {
-            incidence->addAttendee(attendee);
-        }
-    }
-
-    // Must not have an organizer for items without attendees
-    if (!incidence->attendeeCount()) {
-        return;
-    }
+  //all logic inside IncidenceAtendee (using same model)
 }
 
 bool IncidenceResource::isDirty() const
 {
-    const KCalCore::Attendee::List originalList = mLoadedIncidence->attendees();
-    KCalCore::Attendee::List newList = dataModel->attendees();
-
-    // The lists sizes *must* be the same. When the organizer is attending the
-    // event as well, he should be in the attendees list as well.
-    if (originalList.size() != newList.size()) {
-        return true;
-    }
-
-    // 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) {
-        bool found = false;
-        for (int i = 0; i < newList.count(); ++i) {
-            if (newList[i] == attendee) {
-                newList.remove(i);
-                found = true;
-                break;
-            }
-        }
-
-        if (!found) {
-            // One of the attendees in the original list was not found in the new list.
-            return true;
-        }
-    }
-
-    return false;
+  //all logic inside IncidenceAtendee (using same model)
+  return false;
 }
 
 void IncidenceResource::bookResource()
@@ -248,10 +122,23 @@ void IncidenceResource::findResources()
 
 void IncidenceResource::layoutChanged()
 {
-    emit resourceCountChanged(resourcesCount());
+
+#ifndef KDEPIM_MOBILE_UI
+    mUi->mResourcesTable->setColumnHidden(AttendeeTableModel::CuType, true);
+    mUi->mResourcesTable->setColumnHidden(AttendeeTableModel::Name, true);
+    mUi->mResourcesTable->setColumnHidden(AttendeeTableModel::Email, true);
+#endif
+
+    updateCount();
+}
+
+
+void IncidenceResource::updateCount()
+{
+    emit resourceCountChanged(resourceCount());
 }
 
-int IncidenceResource::resourcesCount() const
+int IncidenceResource::resourceCount() const
 {
 #ifndef KDEPIM_MOBILE_UI
     return mUi->mResourcesTable->model()->rowCount(QModelIndex());
diff --git a/incidenceeditor-ng/incidenceresource.h b/incidenceeditor-ng/incidenceresource.h
index 7208015..11ac84e 100644
--- a/incidenceeditor-ng/incidenceresource.h
+++ b/incidenceeditor-ng/incidenceresource.h
@@ -21,6 +21,7 @@
 #define INCIDENCEEDITOR_INCIDENCERESOURCE_H
 
 #include "incidenceeditor-ng.h"
+#include "incidenceattendee.h"
 #include "attendeetablemodel.h"
 
 #include <QModelIndex>
@@ -40,9 +41,9 @@ class INCIDENCEEDITORS_NG_EXPORT IncidenceResource : public IncidenceEditor
     Q_OBJECT
 public:
 #ifdef KDEPIM_MOBILE_UI
-    explicit IncidenceResource(Ui::EventOrTodoMore *ui);
+    explicit IncidenceResource(IncidenceAttendee* mIeAttendee, Ui::EventOrTodoMore *ui);
 #else
-    explicit IncidenceResource(Ui::EventOrTodoDesktop *ui);
+    explicit IncidenceResource(IncidenceAttendee* mIeAttendee,  Ui::EventOrTodoDesktop *ui);
 #endif
 
     void load(const KCalCore::Incidence::Ptr &incidence);
@@ -50,7 +51,7 @@ public:
     bool isDirty() const;
 
     /** resturn the count of resources */
-    int resourcesCount() const;
+    int resourceCount() const;
 
 signals:
     /** is emitted it the count of the resources is changed.
@@ -62,6 +63,7 @@ private slots:
     void findResources();
     void bookResource();
     void layoutChanged();
+    void updateCount();
 
 private:
 #ifdef KDEPIM_MOBILE_UI


commit 6e0b6f5fb5059e77ba69f7c0faae8cb18e03dfb3
Author: Sandro Knauß <knauss at kolabsys.com>
Date:   Tue Jun 17 10:08:24 2014 +0200

    replacing mAttendeeEditor with TableView

diff --git a/incidenceeditor-ng/dialogdesktop.ui b/incidenceeditor-ng/dialogdesktop.ui
index 3f8f53b..2a10c51 100644
--- a/incidenceeditor-ng/dialogdesktop.ui
+++ b/incidenceeditor-ng/dialogdesktop.ui
@@ -716,6 +716,16 @@
          <string comment="@title:tab attendees of this event or to-do">Attendees</string>
         </attribute>
         <layout class="QGridLayout" name="gridLayout_15">
+         <item row="3" column="0" colspan="3">
+          <widget class="QTableView" name="mAttendeeTable">
+           <property name="editTriggers">
+            <set>QAbstractItemView::AllEditTriggers</set>
+           </property>
+           <attribute name="verticalHeaderVisible">
+            <bool>false</bool>
+           </attribute>
+          </widget>
+         </item>
          <item row="1" column="0" colspan="2">
           <widget class="QLabel" name="label_3">
            <property name="text">
@@ -786,16 +796,6 @@
            </item>
           </layout>
          </item>
-         <item row="3" column="0" colspan="3">
-          <widget class="QWidget" name="mAttendeWidgetPlaceHolder" native="true">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-          </widget>
-         </item>
          <item row="1" column="2">
           <widget class="QStackedWidget" name="mOrganizerStack">
            <property name="sizePolicy">
@@ -883,7 +883,7 @@
             <set>QAbstractItemView::AllEditTriggers</set>
            </property>
            <property name="showGrid">
-            <bool>false</bool>
+            <bool>true</bool>
            </property>
            <property name="gridStyle">
             <enum>Qt::SolidLine</enum>
@@ -894,6 +894,9 @@
            <attribute name="horizontalHeaderHighlightSections">
             <bool>false</bool>
            </attribute>
+           <attribute name="verticalHeaderVisible">
+            <bool>false</bool>
+           </attribute>
           </widget>
          </item>
          <item row="1" column="0">
@@ -930,25 +933,6 @@
            </item>
           </layout>
          </item>
-         <item row="2" column="0">
-          <widget class="QTableView" name="mAttendeeTable">
-           <property name="frameShadow">
-            <enum>QFrame::Plain</enum>
-           </property>
-           <property name="editTriggers">
-            <set>QAbstractItemView::AllEditTriggers</set>
-           </property>
-           <property name="showGrid">
-            <bool>false</bool>
-           </property>
-           <attribute name="horizontalHeaderVisible">
-            <bool>false</bool>
-           </attribute>
-           <attribute name="horizontalHeaderCascadingSectionResizes">
-            <bool>false</bool>
-           </attribute>
-          </widget>
-         </item>
         </layout>
        </widget>
        <widget class="QWidget" name="mReminderTab">
diff --git a/incidenceeditor-ng/incidenceattendee.cpp b/incidenceeditor-ng/incidenceattendee.cpp
index 32d7f04..02a1ea7 100644
--- a/incidenceeditor-ng/incidenceattendee.cpp
+++ b/incidenceeditor-ng/incidenceattendee.cpp
@@ -29,6 +29,7 @@
 #include "editorconfig.h"
 #include "incidencedatetime.h"
 #include "schedulingdialog.h"
+#include "attendeecomboboxdelegate.h"
 #ifdef KDEPIM_MOBILE_UI
 #include "ui_dialogmoremobile.h"
 #else
@@ -39,6 +40,7 @@
 #include <Akonadi/Contact/ContactGroupSearchJob>
 #include <Akonadi/Contact/EmailAddressSelectionDialog>
 
+#include <KCalUtils/Stringify>
 #include <KPIMUtils/Email>
 
 #include <KDebug>
@@ -78,25 +80,83 @@ IncidenceAttendee::IncidenceAttendee( QWidget *parent, IncidenceDateTime *dateTi
   : mUi( ui ),
     mParentWidget( parent ),
     mAttendeeEditor( new AttendeeEditor ),
+    mStateDelegate(new AttendeeComboBoxDelegate(this)),
+    mRoleDelegate(new AttendeeComboBoxDelegate(this)),
+    mResponseDelegate(new AttendeeComboBoxDelegate(this)),
     mConflictResolver( 0 ), mDateTime( dateTime )
 {
-  setObjectName( "IncidenceAttendee" );
+  KCalCore::Attendee::List attendees;
+  KCalCore::Attendee::Ptr attendee(new KCalCore::Attendee("", ""));
+  attendees.append(attendee);
+  mDataModel = new AttendeeTableModel(attendees, this);
+  mDataModel->setKeepEmpty(true);
+
+  #ifdef KDEPIM_MOBILE_UI
+  mRoleDelegate->addItem(DesktopIcon("meeting-participant", 48),
+                        KCalUtils::Stringify::attendeeRole(KCalCore::Attendee::ReqParticipant));
+  mRoleDelegate->addItem(DesktopIcon("meeting-participant-optional", 48),
+                        KCalUtils::Stringify::attendeeRole(KCalCore::Attendee::OptParticipant));
+  mRoleDelegate->addItem(DesktopIcon("meeting-observer", 48),
+                        KCalUtils::Stringify::attendeeRole(KCalCore::Attendee::NonParticipant));
+  mRoleDelegate->addItem(DesktopIcon("meeting-chair", 48),
+                        KCalUtils::Stringify::attendeeRole(KCalCore::Attendee::Chair));
+
+  mResponseDelegate->addItem( DesktopIcon( "meeting-participant-request-response", 48 ),
+                             i18nc( "@item:inlistbox", "Request Response" ) );
+  mResponseDelegate->addItem( DesktopIcon( "meeting-participant-no-response", 48 ),
+                             i18nc( "@item:inlistbox", "Request No Response" ) );
+
+  #else
+  mRoleDelegate->addItem(SmallIcon("meeting-participant"),
+                        KCalUtils::Stringify::attendeeRole(KCalCore::Attendee::ReqParticipant));
+  mRoleDelegate->addItem(SmallIcon("meeting-participant-optional"),
+                        KCalUtils::Stringify::attendeeRole(KCalCore::Attendee::OptParticipant));
+  mRoleDelegate->addItem(SmallIcon("meeting-observer"),
+                        KCalUtils::Stringify::attendeeRole(KCalCore::Attendee::NonParticipant));
+  mRoleDelegate->addItem(SmallIcon("meeting-chair"),
+                        KCalUtils::Stringify::attendeeRole(KCalCore::Attendee::Chair));
+
+  mResponseDelegate->addItem( SmallIcon( "meeting-participant-request-response" ),
+                             i18nc( "@item:inlistbox", "Request Response" ) );
+  mResponseDelegate->addItem( SmallIcon( "meeting-participant-no-response" ),
+                             i18nc( "@item:inlistbox", "Request No Response" ) );
+
+  #endif
+
+  mStateDelegate->setWhatsThis( i18nc( "@info:whatsthis",
+                                    "Edits the current attendance status of the attendee." ) );
+
+  mRoleDelegate->setWhatsThis( i18nc( "@info:whatsthis",
+                                   "Edits the role of the attendee." ) );
+
+  mResponseDelegate->setToolTip( i18nc( "@info:tooltip", "Request a response from the attendee" ) );
+  mResponseDelegate->setWhatsThis( i18nc( "@info:whatsthis",
+                                       "Edits whether to send an email to the "
+                                       "attendee to request a response concerning "
+                                       "attendance." ) );
+
 
-  QGridLayout *layout = new QGridLayout( mUi->mAttendeWidgetPlaceHolder );
-  layout->setSpacing( 0 );
-  layout->addWidget( mAttendeeEditor );
+  setObjectName( "IncidenceAttendee" );
 
-  mAttendeeEditor->setCompletionMode( KGlobalSettings::self()->completionMode() );
-  mAttendeeEditor->setFrameStyle( QFrame::Sunken | QFrame::StyledPanel );
+  AttendeeFilterProxyModel *filterProxyModel = new AttendeeFilterProxyModel(this);
+  filterProxyModel->setDynamicSortFilter(true);
+  filterProxyModel->setSourceModel(mDataModel);
 
 #ifdef KDEPIM_MOBILE_UI
-  mAttendeeEditor->setDynamicSizeHint( false );
-#endif
+#else
+  mUi->mAttendeeTable->setModel(filterProxyModel);
 
-  connect( mAttendeeEditor, SIGNAL(countChanged(int)),
-           SIGNAL(attendeeCountChanged(int)) );
-  connect( mAttendeeEditor, SIGNAL(editingFinished(KPIM::MultiplyingLine*)),
-           SLOT(checkIfExpansionIsNeeded(KPIM::MultiplyingLine*)) );
+  AttendeeLineEditDelegate *attendeeDelegate = new AttendeeLineEditDelegate(this);
+  attendeeDelegate->setCompletionMode( KGlobalSettings::self()->completionMode() );
+
+  QHeaderView* headerView = mUi->mAttendeeTable->horizontalHeader();
+  headerView->setResizeMode(QHeaderView::ResizeToContents);
+
+  mUi->mAttendeeTable->setItemDelegateForColumn(AttendeeTableModel::Role, roleDelegate());
+  mUi->mAttendeeTable->setItemDelegateForColumn(AttendeeTableModel::FullName, attendeeDelegate);
+  mUi->mAttendeeTable->setItemDelegateForColumn(AttendeeTableModel::Status, stateDelegate());
+  mUi->mAttendeeTable->setItemDelegateForColumn(AttendeeTableModel::Response, responseDelegate());
+#endif
 
   mUi->mOrganizerStack->setCurrentIndex( 0 );
 
@@ -139,9 +199,16 @@ IncidenceAttendee::IncidenceAttendee( QWidget *parent, IncidenceDateTime *dateTi
            SLOT(checkIfExpansionIsNeeded(KPIM::MultiplyingLine*)) );
   connect( mAttendeeEditor, SIGNAL(changed(KCalCore::Attendee::Ptr,KCalCore::Attendee::Ptr)),
            SLOT(slotAttendeeChanged(KCalCore::Attendee::Ptr,KCalCore::Attendee::Ptr)) );
+
+  connect(mDataModel, SIGNAL(layoutChanged()), SLOT(layoutChanged()));
+  connect(mDataModel, SIGNAL(rowsInserted(const QModelIndex&, int , int)), SLOT(updateCount()));
+  connect(mDataModel, SIGNAL(rowsRemoved(const QModelIndex&, int , int)), SLOT(updateCount()));
 }
 
-IncidenceAttendee::~IncidenceAttendee() {}
+IncidenceAttendee::~IncidenceAttendee()
+{
+  delete mDataModel;
+}
 
 void IncidenceAttendee::load( const KCalCore::Incidence::Ptr &incidence )
 {
@@ -174,54 +241,45 @@ void IncidenceAttendee::load( const KCalCore::Incidence::Ptr &incidence )
     mUi->mOrganizerLabel->setVisible( true );
   }
 
-  mAttendeeEditor->clear();
-  // NOTE: Do this *before* adding the attendees, otherwise the status of the
-  //       attendee in the line will be 0 after when returning from load()
-  if ( incidence->type() == KCalCore::Incidence::TypeEvent ) {
-    mAttendeeEditor->setActions( AttendeeLine::EventActions );
-  } else {
-    mAttendeeEditor->setActions( AttendeeLine::TodoActions );
-  }
+  mDataModel->setAttendees(incidence->attendees());
 
-  const KCalCore::Attendee::List attendees = incidence->attendees();
-  foreach ( const KCalCore::Attendee::Ptr &a, attendees ) {
-    if (!(a->cuType() == KCalCore::Attendee::Resource || a->cuType() == KCalCore::Attendee::Room)) {
-      mAttendeeEditor->addAttendee( a );
-    }
-  }
+  setActions( incidence->type() );
 
   mWasDirty = false;
 }
 
 void IncidenceAttendee::save( const KCalCore::Incidence::Ptr &incidence )
 {
-  /*incidence->clearAttendees();
-  AttendeeData::List attendees = mAttendeeEditor->attendees();
+  incidence->clearAttendees();
+  KCalCore::Attendee::List attendees = mDataModel->attendees();
 
-  foreach ( AttendeeData::Ptr attendee, attendees ) {
-    Q_ASSERT( attendee );
+  foreach(KCalCore::Attendee::Ptr attendee, attendees) {
+    Q_ASSERT(attendee);
 
     bool skip = false;
-    if ( KPIMUtils::isValidAddress( attendee->email() ) ) {
-      if ( KMessageBox::warningYesNo(
-             0,
-             i18nc( "@info",
-                    "%1 does not look like a valid email address. "
-                    "Are you sure you want to invite this participant?",
-                    attendee->email() ),
-             i18nc( "@title:window", "Invalid Email Address" ) ) != KMessageBox::Yes ) {
+    if (attendee->fullName().isEmpty()) {
+      continue;
+    }
+    if (KPIMUtils::isValidAddress(attendee->email())) {
+      if (KMessageBox::warningYesNo(
+        0,
+        i18nc("@info",
+              "%1 does not look like a valid email address. "
+              "Are you sure you want to invite this participant?",
+              attendee->email()),
+              i18nc("@title:window", "Invalid Email Address")) != KMessageBox::Yes) {
         skip = true;
       }
     }
-    if ( !skip ) {
-      incidence->addAttendee( attendee );
+    if (!skip) {
+      incidence->addAttendee(attendee);
     }
   }
 
   // Must not have an organizer for items without attendees
-  if ( !incidence->attendeeCount() ) {
+  if (!incidence->attendeeCount()) {
     return;
-  }*/
+  }
 
   if ( mUi->mOrganizerStack->currentIndex() == 0 ) {
     incidence->setOrganizer( mUi->mOrganizerCombo->currentText() );
@@ -245,32 +303,34 @@ bool IncidenceAttendee::isDirty() const
   }
 
   const KCalCore::Attendee::List originalList = mLoadedIncidence->attendees();
-  AttendeeData::List newList = mAttendeeEditor->attendees();
+  KCalCore::Attendee::List newList;
+
+  foreach(KCalCore::Attendee::Ptr attendee, mDataModel->attendees()) {
+    if (!attendee->fullName().isEmpty()) {
+      newList.append(attendee);
+    }
+  }
 
   // The lists sizes *must* be the same. When the organizer is attending the
   // event as well, he should be in the attendees list as well.
-  /*if ( originalList.size() != newList.size() ) {
+  if (originalList.size() != newList.size()) {
     return true;
-  }*/
+  }
 
   // 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 ) {
-    if (attendee->cuType() == KCalCore::Attendee::Resource || attendee->cuType() == KCalCore::Attendee::Room) {
-      continue;
-    }
+  foreach(const KCalCore::Attendee::Ptr & attendee, originalList) {
     bool found = false;
-    for ( int i = 0; i < newList.size(); ++i ) {
-      if ( compareAttendees( newList.at( i )->attendee(), attendee) ) {
-        newList.removeAt( i );
+    for (int i = 0; i < newList.count(); ++i) {
+      if (newList[i] == attendee) {
+        newList.remove(i);
         found = true;
         break;
       }
     }
 
-    if ( !found ) {
+    if (!found) {
       // One of the attendees in the original list was not found in the new list.
-      kDebug() << "One of the attendees in the original list was not found in the new list";
       return true;
     }
   }
@@ -283,14 +343,14 @@ void IncidenceAttendee::changeStatusForMe( KCalCore::Attendee::PartStat stat )
   const IncidenceEditorNG::EditorConfig *config = IncidenceEditorNG::EditorConfig::instance();
   Q_ASSERT( config );
 
-  AttendeeData::List attendees = mAttendeeEditor->attendees();
-  mAttendeeEditor->clear();
-
-  foreach ( const AttendeeData::Ptr &attendee, attendees ) {
-    if ( config->thatIsMe( attendee->email() ) ) {
-      attendee->setStatus( stat );
+  KCalCore::Attendee::List attendees = mDataModel->attendees();
+  for (int i=0;i<mDataModel->rowCount();i++) {
+    QModelIndex index = mDataModel->index(i, AttendeeTableModel::Email);
+    if ( config->thatIsMe( mDataModel->data(index, Qt::DisplayRole).toString() ) ) {
+      index = mDataModel->index(i, AttendeeTableModel::Status);
+      mDataModel->setData(index, stat);
+      break;
     }
-    mAttendeeEditor->addAttendee( attendee );
   }
 
   checkDirtyStatus();
@@ -378,13 +438,8 @@ void IncidenceAttendee::groupSearchResult( KJob *job )
 
 void IncidenceAttendee::slotSelectAddresses()
 {
-#ifndef KDEPIM_MOBILE_UI
-  QWidget *dialogParent = mAttendeeEditor;
-#else
-  QWidget *dialogParent = 0;
-#endif
   QWeakPointer<Akonadi::EmailAddressSelectionDialog> dialog(
-    new Akonadi::EmailAddressSelectionDialog( dialogParent ) );
+    new Akonadi::EmailAddressSelectionDialog( ) );
   dialog.data()->view()->view()->setSelectionMode( QAbstractItemView::ExtendedSelection );
 
   if ( dialog.data()->exec() == QDialog::Accepted ) {
@@ -452,7 +507,7 @@ void IncidenceAttendee::slotAttendeeChanged( const KCalCore::Attendee::Ptr &oldA
 
 void IncidenceAttendee::slotUpdateConflictLabel( int count )
 {
-  if ( mAttendeeEditor->attendees().count() > 0 ) {
+  if ( attendeeCount() > 0 ) {
     mUi->mSolveButton->setEnabled( true );
     if ( count > 0 ) {
       QString label = i18ncp( "@label Shows the number of scheduling conflicts",
@@ -498,7 +553,7 @@ void IncidenceAttendee::insertAttendeeFromAddressee( const KABC::Addressee &a )
                                                          KCalCore::Attendee::ReqParticipant,
                                                          a.uid() ) );
 
-  mAttendeeEditor->addAttendee( newAt );
+  mDataModel->insertAttendee(mDataModel->rowCount(), newAt);
 }
 
 void IncidenceAttendee::slotEventDurationChanged()
@@ -529,21 +584,23 @@ void IncidenceAttendee::slotOrganizerChanged( const QString &newOrganizer )
     return;
   }
 
-  AttendeeData::Ptr currentOrganizerAttendee;
-  AttendeeData::Ptr newOrganizerAttendee;
+  int currentOrganizerAttendee = -1;
+  int newOrganizerAttendee = -1;
 
-  Q_FOREACH ( AttendeeData::Ptr attendee, mAttendeeEditor->attendees() ) {
-    if ( attendee->fullName() == mOrganizer ) {
-      currentOrganizerAttendee = attendee;
+  for(int i=0; i<mDataModel->rowCount(); i++) {
+    QModelIndex index = mDataModel->index(i,AttendeeTableModel::FullName);
+    QString fullName = mDataModel->data(index,Qt::DisplayRole).toString();
+    if ( fullName == mOrganizer ) {
+      currentOrganizerAttendee = i;
     }
 
-    if ( attendee->fullName() == newOrganizer ) {
-      newOrganizerAttendee = attendee;
+    if ( fullName == newOrganizer ) {
+      newOrganizerAttendee = i;
     }
   }
 
   int answer = KMessageBox::No;
-  if ( currentOrganizerAttendee ) {
+  if ( currentOrganizerAttendee > -1) {
     answer = KMessageBox::questionYesNo(
       mParentWidget,
       i18nc( "@option",
@@ -555,11 +612,11 @@ void IncidenceAttendee::slotOrganizerChanged( const QString &newOrganizer )
   }
 
   if ( answer == KMessageBox::Yes ) {
-    if ( currentOrganizerAttendee ) {
-      mAttendeeEditor->removeAttendee( currentOrganizerAttendee );
+    if ( currentOrganizerAttendee > -1 ) {
+      mDataModel->removeRows(currentOrganizerAttendee,1);
     }
 
-    if ( !newOrganizerAttendee ) {
+    if ( newOrganizerAttendee == -1 ) {
       bool rsvp = !iAmOrganizer(); // if it is the user, don't make him rsvp.
       KCalCore::Attendee::PartStat status = iAmOrganizer() ? KCalCore::Attendee::Accepted
                                             : KCalCore::Attendee::NeedsAction;
@@ -567,12 +624,135 @@ void IncidenceAttendee::slotOrganizerChanged( const QString &newOrganizer )
       KCalCore::Attendee::Ptr newAt(
         new KCalCore::Attendee( name, email, rsvp, status, KCalCore::Attendee::ReqParticipant ) );
 
-      mAttendeeEditor->addAttendee( newAt );
+      mDataModel->insertAttendee(mDataModel->rowCount(), newAt);
     }
   }
   mOrganizer = newOrganizer;
 }
 
+AttendeeTableModel* IncidenceAttendee::dataModel()
+{
+  return mDataModel;
+}
+
+AttendeeComboBoxDelegate* IncidenceAttendee::responseDelegate()
+{
+  return mResponseDelegate;
+}
+
+AttendeeComboBoxDelegate* IncidenceAttendee::roleDelegate()
+{
+  return mRoleDelegate;
+}
+
+AttendeeComboBoxDelegate* IncidenceAttendee::stateDelegate()
+{
+  return mStateDelegate;
+}
+
+void IncidenceAttendee::layoutChanged()
+{
+#ifndef KDEPIM_MOBILE_UI
+  mUi->mAttendeeTable->setColumnHidden(AttendeeTableModel::CuType, true);
+  mUi->mAttendeeTable->setColumnHidden(AttendeeTableModel::Name, true);
+  mUi->mAttendeeTable->setColumnHidden(AttendeeTableModel::Email, true);
+  mUi->mAttendeeTable->setColumnHidden(AttendeeTableModel::Available, true);
+#endif
+
+  updateCount();
+}
+
+
+void IncidenceAttendee::updateCount()
+{
+  emit attendeeCountChanged(attendeeCount());
+
+  checkDirtyStatus();
+}
+
+int IncidenceAttendee::attendeeCount() const
+{
+#ifndef KDEPIM_MOBILE_UI
+    int c=0;
+    QModelIndex index;
+    QAbstractItemModel *model = mUi->mAttendeeTable->model();
+    if (!model ) {
+      return 0;
+    }
+    for(int i=0;i< model->rowCount(QModelIndex());i++) {
+      index = model->index(i,AttendeeTableModel::FullName);
+      if (!model->data(index).toString().isEmpty()) {
+        c++;
+      }
+    }
+    return c;
+#endif
+    return 0;
+}
+
+void IncidenceAttendee::setActions( KCalCore::Incidence::IncidenceType actions )
+{
+  mStateDelegate->clear();
+  if ( actions ==  KCalCore::Incidence::TypeEvent ) {
+#ifdef KDEPIM_MOBILE_UI
+    mStateDelegate->addItem( DesktopIcon( "task-attention", 48 ),
+                          KCalUtils::Stringify::attendeeStatus( AttendeeData::NeedsAction ) );
+    mStateDelegate->addItem( DesktopIcon( "task-accepted", 48 ),
+                          KCalUtils::Stringify::attendeeStatus( AttendeeData::Accepted ) );
+    mStateDelegate->addItem( DesktopIcon( "task-reject", 48 ),
+                          KCalUtils::Stringify::attendeeStatus( AttendeeData::Declined ) );
+    mStateDelegate->addItem( DesktopIcon( "task-attempt", 48 ),
+                          KCalUtils::Stringify::attendeeStatus( AttendeeData::Tentative ) );
+    mStateDelegate->addItem( DesktopIcon( "task-delegate", 48 ),
+                          KCalUtils::Stringify::attendeeStatus( AttendeeData::Delegated ) );
+#else
+    mStateDelegate->addItem( SmallIcon( "task-attention" ),
+                          KCalUtils::Stringify::attendeeStatus( AttendeeData::NeedsAction ) );
+    mStateDelegate->addItem( SmallIcon( "task-accepted" ),
+                          KCalUtils::Stringify::attendeeStatus( AttendeeData::Accepted ) );
+    mStateDelegate->addItem( SmallIcon( "task-reject" ),
+                          KCalUtils::Stringify::attendeeStatus( AttendeeData::Declined ) );
+    mStateDelegate->addItem( SmallIcon( "task-attempt" ),
+                          KCalUtils::Stringify::attendeeStatus( AttendeeData::Tentative ) );
+    mStateDelegate->addItem( SmallIcon( "task-delegate" ),
+                          KCalUtils::Stringify::attendeeStatus( AttendeeData::Delegated ) );
+#endif
+  } else {
+#ifdef KDEPIM_MOBILE_UI
+    mStateDelegate->addItem( DesktopIcon( "task-attention", 48 ),
+                          KCalUtils::Stringify::attendeeStatus( AttendeeData::NeedsAction ) );
+    mStateDelegate->addItem( DesktopIcon( "task-accepted", 48 ),
+                          KCalUtils::Stringify::attendeeStatus( AttendeeData::Accepted ) );
+    mStateDelegate->addItem( DesktopIcon( "task-reject", 48 ),
+                          KCalUtils::Stringify::attendeeStatus( AttendeeData::Declined ) );
+    mStateDelegate->addItem( DesktopIcon( "task-attempt", 48 ),
+                          KCalUtils::Stringify::attendeeStatus( AttendeeData::Tentative ) );
+    mStateDelegate->addItem( DesktopIcon( "task-delegate", 48 ),
+                          KCalUtils::Stringify::attendeeStatus( AttendeeData::Delegated ) );
+    mStateDelegate->addItem( DesktopIcon( "task-complete", 48 ),
+                          KCalUtils::Stringify::attendeeStatus( AttendeeData::Completed ) );
+    mStateDelegate->addItem( DesktopIcon( "task-ongoing", 48 ),
+                          KCalUtils::Stringify::attendeeStatus( AttendeeData::InProcess ) );
+#else
+    mStateDelegate->addItem( SmallIcon( "task-attention" ),
+                          KCalUtils::Stringify::attendeeStatus( AttendeeData::NeedsAction ) );
+    mStateDelegate->addItem( SmallIcon( "task-accepted" ),
+                          KCalUtils::Stringify::attendeeStatus( AttendeeData::Accepted ) );
+    mStateDelegate->addItem( SmallIcon( "task-reject" ),
+                          KCalUtils::Stringify::attendeeStatus( AttendeeData::Declined ) );
+    mStateDelegate->addItem( SmallIcon( "task-attempt" ),
+                          KCalUtils::Stringify::attendeeStatus( AttendeeData::Tentative ) );
+    mStateDelegate->addItem( SmallIcon( "task-delegate" ),
+                          KCalUtils::Stringify::attendeeStatus( AttendeeData::Delegated ) );
+    mStateDelegate->addItem( SmallIcon( "task-complete" ),
+                          KCalUtils::Stringify::attendeeStatus( AttendeeData::Completed ) );
+    mStateDelegate->addItem( SmallIcon( "task-ongoing" ),
+                          KCalUtils::Stringify::attendeeStatus( AttendeeData::InProcess ) );
+#endif
+  }
+}
+
+
 void IncidenceAttendee::printDebugInfo() const
 {
   kDebug() << "I'm organizer   : " << iAmOrganizer();
@@ -585,11 +765,12 @@ void IncidenceAttendee::printDebugInfo() const
   }
 
   const KCalCore::Attendee::List originalList = mLoadedIncidence->attendees();
-  AttendeeData::List newList = mAttendeeEditor->attendees();
-  kDebug() << "List sizes: " << originalList.count() << newList.count();
+  KCalCore::Attendee::List newList;
 
-  if ( originalList.count() != newList.count() ) {
-    return;
+  foreach(KCalCore::Attendee::Ptr attendee, mDataModel->attendees()) {
+    if (!attendee->fullName().isEmpty()) {
+      newList.append(attendee);
+    }
   }
 
   // Okay, again not the most efficient algorithm, but I'm assuming that in the
@@ -597,8 +778,8 @@ void IncidenceAttendee::printDebugInfo() const
   foreach ( const KCalCore::Attendee::Ptr &attendee, originalList ) {
     bool found = false;
     for ( int i = 0; i < newList.count(); ++i ) {
-      if ( *newList.at( i )->attendee() == *attendee ) {
-        newList.removeAt( i );
+      if ( newList[i] == attendee ) {
+        newList.remove(i);
         found = true;
         break;
       }
@@ -616,7 +797,7 @@ void IncidenceAttendee::printDebugInfo() const
                << attendee->delegator()
                << "; we have:";
       for ( int i = 0; i < newList.count(); ++i ) {
-        KCalCore::Attendee::Ptr attendee = newList.at( i )->attendee();
+        KCalCore::Attendee::Ptr attendee = newList[i];
         kDebug() << "Attendee: " << attendee->email()
                  << attendee->name()
                  << attendee->status()
@@ -631,4 +812,4 @@ void IncidenceAttendee::printDebugInfo() const
       return;
     }
   }
-}
+}
\ No newline at end of file
diff --git a/incidenceeditor-ng/incidenceattendee.h b/incidenceeditor-ng/incidenceattendee.h
index c7ba4e5..60c05ae 100644
--- a/incidenceeditor-ng/incidenceattendee.h
+++ b/incidenceeditor-ng/incidenceattendee.h
@@ -22,6 +22,8 @@
 #define INCIDENCEEDITOR_INCIDENCEATTENDEE_H
 
 #include "incidenceeditor-ng.h"
+#include "attendeetablemodel.h"
+
 
 namespace Ui {
   class EventOrTodoDesktop;
@@ -41,6 +43,7 @@ class KJob;
 namespace IncidenceEditorNG {
 
 class AttendeeEditor;
+class AttendeeComboBoxDelegate;
 class ConflictResolver;
 class IncidenceDateTime;
 
@@ -60,6 +63,13 @@ class INCIDENCEEDITORS_NG_EXPORT IncidenceAttendee : public IncidenceEditor
     virtual bool isDirty() const;
     virtual void printDebugInfo() const;
 
+    AttendeeTableModel * dataModel();
+    AttendeeComboBoxDelegate *stateDelegate();
+    AttendeeComboBoxDelegate *roleDelegate();
+    AttendeeComboBoxDelegate *responseDelegate();
+
+    int attendeeCount() const;
+
   signals:
     void attendeeCountChanged( int );
 
@@ -83,6 +93,10 @@ class INCIDENCEEDITORS_NG_EXPORT IncidenceAttendee : public IncidenceEditor
     // wrapper for the conflict resolver
     void slotEventDurationChanged();
 
+    void layoutChanged();
+    void updateCount();
+
+
   private:
     void changeStatusForMe( KCalCore::Attendee::PartStat );
 
@@ -97,6 +111,7 @@ class INCIDENCEEDITORS_NG_EXPORT IncidenceAttendee : public IncidenceEditor
      */
     void insertAttendeeFromAddressee( const KABC::Addressee &a );
     void fillOrganizerCombo();
+    void setActions( KCalCore::Incidence::IncidenceType actions );
 
 #ifdef KDEPIM_MOBILE_UI
     Ui::EventOrTodoMore *mUi;
@@ -109,6 +124,13 @@ class INCIDENCEEDITORS_NG_EXPORT IncidenceAttendee : public IncidenceEditor
     QMap<KJob *,QWeakPointer<KPIM::MultiplyingLine> > mMightBeGroupLines;
     IncidenceDateTime *mDateTime;
     QString mOrganizer;
+
+    /** used dataModel to rely on*/
+    AttendeeTableModel *mDataModel;
+    AttendeeComboBoxDelegate *mStateDelegate;
+    AttendeeComboBoxDelegate *mRoleDelegate;
+    AttendeeComboBoxDelegate *mResponseDelegate;
+
 };
 
 }


commit 18698ce7a5cf6c996080b5804e276d01082de6ee
Author: Sandro Knauß <knauss at kolabsys.com>
Date:   Tue Jun 17 10:01:59 2014 +0200

    Added keepEmptyLines to model

diff --git a/incidenceeditor-ng/attendeetablemodel.cpp b/incidenceeditor-ng/attendeetablemodel.cpp
index 242976a..78c21bd 100644
--- a/incidenceeditor-ng/attendeetablemodel.cpp
+++ b/incidenceeditor-ng/attendeetablemodel.cpp
@@ -10,8 +10,9 @@ using namespace IncidenceEditorNG;
 AttendeeTableModel::AttendeeTableModel(const KCalCore::Attendee::List &attendees, QObject *parent)
     : QAbstractTableModel(parent)
     , attendeeList(attendees)
+    , mKeepEmpty(false)
 {
-    insertRows(0,1);
+
 }
 
 int AttendeeTableModel::rowCount(const QModelIndex &/*parent*/) const
@@ -21,7 +22,7 @@ int AttendeeTableModel::rowCount(const QModelIndex &/*parent*/) const
 
 int AttendeeTableModel::columnCount(const QModelIndex &/*parent*/) const
 {
-    return 6;
+    return 8;
 }
 
 Qt::ItemFlags AttendeeTableModel::flags(const QModelIndex &index) const
@@ -29,10 +30,10 @@ Qt::ItemFlags AttendeeTableModel::flags(const QModelIndex &index) const
     if (!index.isValid()) {
         return Qt::ItemIsEnabled;
     }
-    if (index.column() == Available) {          //Available is read only
-      return QAbstractTableModel::flags(index);
+    if (index.column() == Available || index.column() == Name || index.column() == Email) {          //Available is read only
+        return QAbstractTableModel::flags(index);
     } else {
-      return QAbstractTableModel::flags(index) | Qt::ItemIsEditable;
+        return QAbstractTableModel::flags(index) | Qt::ItemIsEditable;
     }
 }
 
@@ -50,7 +51,7 @@ QVariant AttendeeTableModel::data(const QModelIndex &index, int role) const
         switch (index.column()) {
         case Role:
             return attendeeList[index.row()]->role();
-        case Name:
+        case FullName:
             return attendeeList[index.row()]->fullName();
         case Available:
             return 0;//attendeeList.at(index.row()).available;
@@ -60,6 +61,10 @@ QVariant AttendeeTableModel::data(const QModelIndex &index, int role) const
             return attendeeList[index.row()]->cuType();
         case Response:
             return attendeeList[index.row()]->RSVP();
+        case Name:
+            return attendeeList[index.row()]->name();
+        case Email:
+            return attendeeList[index.row()]->email();
         }
 
     }
@@ -74,10 +79,12 @@ bool AttendeeTableModel::setData(const QModelIndex& index, const QVariant& value
         case Role:
             attendeeList[index.row()]->setRole(static_cast<KCalCore::Attendee::Role>(value.toInt()));
             break;
-        case Name:
+        case FullName:
             KPIMUtils::extractEmailAddressAndName(value.toString(), email, name);
             attendeeList[index.row()]->setName(name);
             attendeeList[index.row()]->setEmail(email);
+
+            addEmptyAttendee(true);
             break;
         case Available:
             //attendeeList[index.row()].available = value.toBool();
@@ -111,8 +118,8 @@ QVariant AttendeeTableModel::headerData(int section, Qt::Orientation orientation
         switch (section) {
         case Role:
             return QString("role");
-        case Name:
-            return QString("name");
+        case FullName:
+            return QString("fullname");
         case Available:
             return QString("available");
         case Status:
@@ -121,6 +128,10 @@ QVariant AttendeeTableModel::headerData(int section, Qt::Orientation orientation
             return QString("cuType");
         case Response:
             return QString("response");
+        case Name:
+            return QString("name");
+        case Email:
+            return QString("email");
         }
     }
 
@@ -169,6 +180,8 @@ void AttendeeTableModel::setAttendees(const KCalCore::Attendee::List attendees)
 
     attendeeList = attendees;
 
+    addEmptyAttendee(false);
+
     emit layoutChanged();
 }
 
@@ -178,6 +191,46 @@ KCalCore::Attendee::List AttendeeTableModel::attendees() const
     return attendeeList;
 }
 
+void AttendeeTableModel::addEmptyAttendee(bool layoutChange)
+{
+    if (mKeepEmpty) {
+        bool create=true;
+        foreach(KCalCore::Attendee::Ptr attendee, attendeeList) {
+            if (attendee->fullName().isEmpty()) {
+                create=false;
+                break;
+            }
+        }
+
+        if (create) {
+            if (layoutChange) {
+                emit layoutAboutToBeChanged();
+            }
+
+            insertRows(rowCount(),1);
+
+            if (layoutChange) {
+                emit layoutChanged();
+            }
+        }
+    }
+}
+
+
+bool AttendeeTableModel::keepEmpty()
+{
+    return mKeepEmpty;
+}
+
+void AttendeeTableModel::setKeepEmpty(bool keepEmpty)
+{
+    if (keepEmpty != mKeepEmpty) {
+        mKeepEmpty = keepEmpty;
+        addEmptyAttendee(true);
+    }
+}
+
+
 ResourceFilterProxyModel::ResourceFilterProxyModel(QObject *parent)
     : QSortFilterProxyModel(parent)
 {
diff --git a/incidenceeditor-ng/attendeetablemodel.h b/incidenceeditor-ng/attendeetablemodel.h
index ea525e1..dce56f0 100644
--- a/incidenceeditor-ng/attendeetablemodel.h
+++ b/incidenceeditor-ng/attendeetablemodel.h
@@ -40,7 +40,9 @@ public:
     enum Columns {
       CuType,
       Role,
+      FullName,
       Name,
+      Email,
       Available,
       Status,
       Response
@@ -66,8 +68,13 @@ public:
     void setAttendees(const KCalCore::Attendee::List resources);
     KCalCore::Attendee::List attendees() const;
 
+    void setKeepEmpty(bool keepEmpty);
+    bool keepEmpty();
 private:
+    void addEmptyAttendee(bool layoutChange);
+
     KCalCore::Attendee::List attendeeList;
+    bool mKeepEmpty;
 };
 
 class ResourceFilterProxyModel : public QSortFilterProxyModel


commit 967420d0905500477ae67cca0b76fb84a0165328
Author: Sandro Knauß <knauss at kolabsys.com>
Date:   Tue Jun 17 09:55:10 2014 +0200

    add tooltip&whatsthis to Attendee*Delegators

diff --git a/incidenceeditor-ng/attendeecomboboxdelegate.cpp b/incidenceeditor-ng/attendeecomboboxdelegate.cpp
index d90d3fc..d2fc767 100644
--- a/incidenceeditor-ng/attendeecomboboxdelegate.cpp
+++ b/incidenceeditor-ng/attendeecomboboxdelegate.cpp
@@ -2,8 +2,15 @@
 
 #include "attendeeline.h"
 
+#include <QAbstractItemView>
 #include <QApplication>
 #include <QMenu>
+#include <QHelpEvent>
+#include <QToolTip>
+#include <QWhatsThis>
+
+#include <KDebug>
+#include <KLocalizedString>
 
 using namespace IncidenceEditorNG;
 
@@ -22,6 +29,22 @@ void AttendeeComboBoxDelegate::addItem(const QIcon &icon, const QString &text)
     entries << pair;
 }
 
+void AttendeeComboBoxDelegate::clear()
+{
+    entries.clear();
+}
+
+
+void AttendeeComboBoxDelegate::setToolTip(const QString& tT)
+{
+    toolTip = tT;
+}
+
+void AttendeeComboBoxDelegate::setWhatsThis(const QString& wT)
+{
+    whatsThis = wT;
+}
+
 void AttendeeComboBoxDelegate::setStandardIndex(int index)
 {
     standardIndex = index;
@@ -40,6 +63,8 @@ QWidget *AttendeeComboBoxDelegate::createEditor(QWidget *parent, const QStyleOpt
     connect(editor,SIGNAL(rightPressed()),SLOT(rightPressed()));
 
     editor->setPopupMode( QToolButton::MenuButtonPopup);
+    editor->setToolTip(toolTip);
+    editor->setWhatsThis(whatsThis);
     return editor;
 }
 
@@ -67,7 +92,7 @@ void AttendeeComboBoxDelegate::updateEditorGeometry(QWidget *editor, const QStyl
 
 void AttendeeComboBoxDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
 {
-    QStyleOptionToolButton myOption;
+    QStyleOptionButton myOption;;
 
     int value = index.model()->data(index).toUInt();
     if (value >= entries.count()) {
@@ -77,15 +102,12 @@ void AttendeeComboBoxDelegate::paint(QPainter *painter, const QStyleOptionViewIt
     myOption.rect = option.rect;
     myOption.state = option.state;
     myOption.icon = entries[value].first;
-    myOption.iconSize = QSize(48,48);
-    //myOption.features |= QStyleOptionToolButton::MenuButtonPopup;
 
-    QApplication::style()->drawComplexControl(QStyle::CC_ToolButton, &myOption, painter);
+    QApplication::style()->drawControl(QStyle::CE_PushButton, &myOption, painter);
 }
 
 bool AttendeeComboBoxDelegate::eventFilter ( QObject * editor, QEvent * event )
 {
-
   if (event->type() == QEvent::Enter) {
     AttendeeComboBox *comboBox = static_cast<AttendeeComboBox*>(editor);
     comboBox->showMenu();
@@ -111,10 +133,45 @@ void AttendeeComboBoxDelegate::rightPressed()
     emit closeEditor(static_cast<QWidget*>(QObject::sender()),QAbstractItemDelegate::EditNextItem);
 }
 
+
+bool AttendeeComboBoxDelegate::helpEvent( QHelpEvent* event, QAbstractItemView* view,
+    const QStyleOptionViewItem& option, const QModelIndex& index )
+{
+    if (!event || !view) {
+        return false;
+    }
+    switch (event->type()) {
+#ifndef QT_NO_TOOLTIP
+    case QEvent::ToolTip: {
+        QHelpEvent *he = static_cast<QHelpEvent*>(event);
+          QToolTip::showText(he->globalPos(), toolTip, view);
+        return true;
+        break;}
+#endif
+#ifndef QT_NO_WHATSTHIS
+    case QEvent::QueryWhatsThis:
+        return true;
+        break;
+    case QEvent::WhatsThis: {
+        QHelpEvent *he = static_cast<QHelpEvent*>(event);
+          QWhatsThis::showText(he->globalPos(), whatsThis, view);
+        return true;
+        break ; }
+#endif
+    default:
+        break;
+    }
+    return QStyledItemDelegate::helpEvent( event, view, option, index );
+}
+
 AttendeeLineEditDelegate::AttendeeLineEditDelegate(QObject* parent)
     : QStyledItemDelegate(parent)
 {
-
+    toolTip = i18nc( "@info:tooltip",
+                     "Enter the name or email address of the attendee." );
+    whatsThis = i18nc( "@info:whatsthis",
+                       "The email address or name of the attendee. An invitation "
+                       "can be sent to the user if an email address is provided." );
 }
 
 QWidget *AttendeeLineEditDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &/* option */, const QModelIndex &/* index */) const
@@ -122,6 +179,11 @@ QWidget *AttendeeLineEditDelegate::createEditor(QWidget *parent, const QStyleOpt
     AttendeeLineEdit* editor = new AttendeeLineEdit(parent);
     connect(editor,SIGNAL(leftPressed()),SLOT(leftPressed()));
     connect(editor,SIGNAL(rightPressed()),SLOT(rightPressed()));
+    editor->setToolTip(toolTip);
+    editor->setWhatsThis(whatsThis);
+    editor->setCompletionMode(completionMode);
+    editor->setClearButtonShown( true );
+
     return editor;
 }
 
@@ -151,3 +213,38 @@ void AttendeeLineEditDelegate::rightPressed()
 {
     emit closeEditor(static_cast<QWidget*>(QObject::sender()),QAbstractItemDelegate::EditNextItem);
 }
+
+void AttendeeLineEditDelegate::setCompletionMode(KGlobalSettings::Completion mode)
+{
+    completionMode = mode;
+}
+
+bool AttendeeLineEditDelegate::helpEvent( QHelpEvent* event, QAbstractItemView* view,
+    const QStyleOptionViewItem& option, const QModelIndex& index )
+{
+    if (!event || !view) {
+        return false;
+    }
+    switch (event->type()) {
+#ifndef QT_NO_TOOLTIP
+    case QEvent::ToolTip: {
+        QHelpEvent *he = static_cast<QHelpEvent*>(event);
+          QToolTip::showText(he->globalPos(), toolTip, view);
+        return true;
+        break;}
+#endif
+#ifndef QT_NO_WHATSTHIS
+    case QEvent::QueryWhatsThis:
+        return true;
+        break;
+    case QEvent::WhatsThis: {
+        QHelpEvent *he = static_cast<QHelpEvent*>(event);
+          QWhatsThis::showText(he->globalPos(), whatsThis, view);
+        return true;
+        break ; }
+#endif
+    default:
+        break;
+    }
+    return QStyledItemDelegate::helpEvent( event, view, option, index );
+}
diff --git a/incidenceeditor-ng/attendeecomboboxdelegate.h b/incidenceeditor-ng/attendeecomboboxdelegate.h
index caedc50..f61233d 100644
--- a/incidenceeditor-ng/attendeecomboboxdelegate.h
+++ b/incidenceeditor-ng/attendeecomboboxdelegate.h
@@ -22,6 +22,8 @@
 #ifndef INCIDENCEEDITOR_ATTENDEECOMBOBOXDELEGATE_H
 #define INCIDENCEEDITOR_ATTENDEECOMBOBOXDELEGATE_H
 
+#include <kglobalsettings.h>
+
 #include <QStyledItemDelegate>
 #include <QModelIndex>
 #include <QIcon>
@@ -51,11 +53,18 @@ public:
     bool eventFilter ( QObject * editor, QEvent * event );
 
     void addItem(const QIcon&, const QString&);
+    void clear();
+
+    void setToolTip(const QString&);
+    void setWhatsThis(const QString&);
 
     /** choose this index, if the item in the model is unknown
      */
     void setStandardIndex(int);
 
+public slots:
+    bool helpEvent( QHelpEvent* event, QAbstractItemView* view, const QStyleOptionViewItem& option, const QModelIndex& index );
+
 private slots:
   void doCloseEditor(QWidget *editor);
   void rightPressed();
@@ -66,6 +75,8 @@ private:
     QList<QPair<QIcon, QString> > entries;
     /**fallback index */
     int standardIndex;
+    QString toolTip;
+    QString whatsThis;
 };
 
 /** show a AttendeeLineEdit as editor */
@@ -80,9 +91,19 @@ public:
     void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const;
     void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const;
 
+    void setCompletionMode( KGlobalSettings::Completion mode);
+
+public slots:
+    bool helpEvent( QHelpEvent* event, QAbstractItemView* view, const QStyleOptionViewItem& option, const QModelIndex& index );
+
 private slots:
-  void rightPressed();
-  void leftPressed();
+    void rightPressed();
+    void leftPressed();
+
+private:
+    QString toolTip;
+    QString whatsThis;
+    KGlobalSettings::Completion completionMode;
 };
 
 }


commit 3ff3388b814c860c17ea96aacf070672f22c0b50
Author: Sandro Knauß <knauss at kolabsys.com>
Date:   Sat Jun 14 19:17:30 2014 +0200

    have a nice tableView

diff --git a/incidenceeditor-ng/attendeecomboboxdelegate.cpp b/incidenceeditor-ng/attendeecomboboxdelegate.cpp
index 21ec3f8..d90d3fc 100644
--- a/incidenceeditor-ng/attendeecomboboxdelegate.cpp
+++ b/incidenceeditor-ng/attendeecomboboxdelegate.cpp
@@ -3,6 +3,7 @@
 #include "attendeeline.h"
 
 #include <QApplication>
+#include <QMenu>
 
 using namespace IncidenceEditorNG;
 
@@ -10,7 +11,7 @@ AttendeeComboBoxDelegate::AttendeeComboBoxDelegate(QObject *parent)
     : QStyledItemDelegate(parent)
     , standardIndex(0)
 {
-
+    connect(this, SIGNAL(closeEditor(QWidget*)), SLOT(doCloseEditor(QWidget*)));
 }
 
 void AttendeeComboBoxDelegate::addItem(const QIcon &icon, const QString &text)
@@ -26,7 +27,6 @@ void AttendeeComboBoxDelegate::setStandardIndex(int index)
     standardIndex = index;
 }
 
-
 QWidget *AttendeeComboBoxDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &/* option */, const QModelIndex &/* index */) const
 {
     AttendeeComboBox* editor = new AttendeeComboBox(parent);
@@ -36,6 +36,10 @@ QWidget *AttendeeComboBoxDelegate::createEditor(QWidget *parent, const QStyleOpt
         editor->addItem(pair.first, pair.second);
     }
 
+    connect(editor,SIGNAL(leftPressed()),SLOT(leftPressed()));
+    connect(editor,SIGNAL(rightPressed()),SLOT(rightPressed()));
+
+    editor->setPopupMode( QToolButton::MenuButtonPopup);
     return editor;
 }
 
@@ -53,6 +57,7 @@ void AttendeeComboBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel
 {
     AttendeeComboBox *comboBox = static_cast<AttendeeComboBox*>(editor);
     model->setData(index, comboBox->currentIndex(), Qt::EditRole);
+    comboBox->menu()->close();
 }
 
 void AttendeeComboBoxDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &/* index */) const
@@ -62,16 +67,48 @@ void AttendeeComboBoxDelegate::updateEditorGeometry(QWidget *editor, const QStyl
 
 void AttendeeComboBoxDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
 {
-    QStyleOptionButton pushButton;
+    QStyleOptionToolButton myOption;
+
     int value = index.model()->data(index).toUInt();
-    pushButton.rect = option.rect;
-    pushButton.features |= QStyleOptionButton::HasMenu;
     if (value >= entries.count()) {
         value = standardIndex;
     }
-    pushButton.icon = entries[value].first;
 
-    QApplication::style()->drawControl(QStyle::CE_PushButton, &pushButton, painter);
+    myOption.rect = option.rect;
+    myOption.state = option.state;
+    myOption.icon = entries[value].first;
+    myOption.iconSize = QSize(48,48);
+    //myOption.features |= QStyleOptionToolButton::MenuButtonPopup;
+
+    QApplication::style()->drawComplexControl(QStyle::CC_ToolButton, &myOption, painter);
+}
+
+bool AttendeeComboBoxDelegate::eventFilter ( QObject * editor, QEvent * event )
+{
+
+  if (event->type() == QEvent::Enter) {
+    AttendeeComboBox *comboBox = static_cast<AttendeeComboBox*>(editor);
+    comboBox->showMenu();
+    return editor->eventFilter(editor, event);
+  }
+
+  return QStyledItemDelegate::eventFilter(editor, event);
+}
+
+void AttendeeComboBoxDelegate::doCloseEditor(QWidget* editor)
+{
+    AttendeeComboBox *comboBox = static_cast<AttendeeComboBox*>(editor);
+    comboBox->menu()->close();
+}
+
+void AttendeeComboBoxDelegate::leftPressed()
+{
+    emit closeEditor(static_cast<QWidget*>(QObject::sender()),QAbstractItemDelegate::EditPreviousItem);
+}
+
+void AttendeeComboBoxDelegate::rightPressed()
+{
+    emit closeEditor(static_cast<QWidget*>(QObject::sender()),QAbstractItemDelegate::EditNextItem);
 }
 
 AttendeeLineEditDelegate::AttendeeLineEditDelegate(QObject* parent)
@@ -80,22 +117,23 @@ AttendeeLineEditDelegate::AttendeeLineEditDelegate(QObject* parent)
 
 }
 
-
 QWidget *AttendeeLineEditDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &/* option */, const QModelIndex &/* index */) const
 {
-    KPIM::AddresseeLineEdit* editor = new KPIM::AddresseeLineEdit(parent);
+    AttendeeLineEdit* editor = new AttendeeLineEdit(parent);
+    connect(editor,SIGNAL(leftPressed()),SLOT(leftPressed()));
+    connect(editor,SIGNAL(rightPressed()),SLOT(rightPressed()));
     return editor;
 }
 
 void AttendeeLineEditDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
 {
-    KPIM::AddresseeLineEdit *lineedit = static_cast<KPIM::AddresseeLineEdit*>(editor);
+    AttendeeLineEdit *lineedit = static_cast<AttendeeLineEdit*>(editor);
     lineedit->setText(index.model()->data(index, Qt::EditRole).toString());
 }
 
 void AttendeeLineEditDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
 {
-    KPIM::AddresseeLineEdit *lineedit = static_cast<KPIM::AddresseeLineEdit*>(editor);
+    AttendeeLineEdit *lineedit = static_cast<AttendeeLineEdit*>(editor);
     model->setData(index, lineedit->text(), Qt::EditRole);
 }
 
@@ -103,3 +141,13 @@ void AttendeeLineEditDelegate::updateEditorGeometry(QWidget *editor, const QStyl
 {
     editor->setGeometry(option.rect);
 }
+
+void AttendeeLineEditDelegate::leftPressed()
+{
+    emit closeEditor(static_cast<QWidget*>(QObject::sender()),QAbstractItemDelegate::EditPreviousItem);
+}
+
+void AttendeeLineEditDelegate::rightPressed()
+{
+    emit closeEditor(static_cast<QWidget*>(QObject::sender()),QAbstractItemDelegate::EditNextItem);
+}
diff --git a/incidenceeditor-ng/attendeecomboboxdelegate.h b/incidenceeditor-ng/attendeecomboboxdelegate.h
index 6d4b4a5..caedc50 100644
--- a/incidenceeditor-ng/attendeecomboboxdelegate.h
+++ b/incidenceeditor-ng/attendeecomboboxdelegate.h
@@ -33,7 +33,7 @@ namespace IncidenceEditorNG
 
   /**
    * class to show a Icon and Text for an Attendee
-   * you have to set the Items via adItem to have a list to choose from.
+   * you have to set the Items via addItem to have a list to choose from.
    * saves the option as int in the model
    */
 class AttendeeComboBoxDelegate : public QStyledItemDelegate
@@ -48,21 +48,27 @@ public:
     void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const;
     void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
 
+    bool eventFilter ( QObject * editor, QEvent * event );
+
     void addItem(const QIcon&, const QString&);
 
     /** choose this index, if the item in the model is unknown
      */
     void setStandardIndex(int);
 
+private slots:
+  void doCloseEditor(QWidget *editor);
+  void rightPressed();
+  void leftPressed();
+
 private:
     /** all entries to choose from */
     QList<QPair<QIcon, QString> > entries;
     /**fallback index */
     int standardIndex;
-
 };
 
-/** show a KPIM::AddressLineEdit as editor */
+/** show a AttendeeLineEdit as editor */
 class AttendeeLineEditDelegate : public QStyledItemDelegate
 {
     Q_OBJECT
@@ -73,6 +79,10 @@ public:
     void setEditorData(QWidget *editor, const QModelIndex &index) const;
     void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const;
     void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const;
+
+private slots:
+  void rightPressed();
+  void leftPressed();
 };
 
 }
diff --git a/incidenceeditor-ng/attendeeline.cpp b/incidenceeditor-ng/attendeeline.cpp
index 8d624b5..6fe34dd 100644
--- a/incidenceeditor-ng/attendeeline.cpp
+++ b/incidenceeditor-ng/attendeeline.cpp
@@ -103,6 +103,10 @@ void AttendeeComboBox::keyPressEvent( QKeyEvent *ev )
     emit leftPressed();
   } else if ( ev->key() == Qt::Key_Right ) {
     emit rightPressed();
+  } else if ( !mMenu->isVisible() && (
+                  ev->key() == Qt::Key_Down ||
+                  ev->key() == Qt::Key_Space ) )  {
+    showMenu();
   } else {
     QToolButton::keyPressEvent( ev );
   }
diff --git a/incidenceeditor-ng/attendeetablemodel.cpp b/incidenceeditor-ng/attendeetablemodel.cpp
index b947aac..242976a 100644
--- a/incidenceeditor-ng/attendeetablemodel.cpp
+++ b/incidenceeditor-ng/attendeetablemodel.cpp
@@ -11,7 +11,7 @@ AttendeeTableModel::AttendeeTableModel(const KCalCore::Attendee::List &attendees
     : QAbstractTableModel(parent)
     , attendeeList(attendees)
 {
-
+    insertRows(0,1);
 }
 
 int AttendeeTableModel::rowCount(const QModelIndex &/*parent*/) const
@@ -21,7 +21,7 @@ int AttendeeTableModel::rowCount(const QModelIndex &/*parent*/) const
 
 int AttendeeTableModel::columnCount(const QModelIndex &/*parent*/) const
 {
-    return 5;
+    return 6;
 }
 
 Qt::ItemFlags AttendeeTableModel::flags(const QModelIndex &index) const
@@ -29,8 +29,11 @@ Qt::ItemFlags AttendeeTableModel::flags(const QModelIndex &index) const
     if (!index.isValid()) {
         return Qt::ItemIsEnabled;
     }
-
-    return QAbstractTableModel::flags(index) | Qt::ItemIsEditable;
+    if (index.column() == Available) {          //Available is read only
+      return QAbstractTableModel::flags(index);
+    } else {
+      return QAbstractTableModel::flags(index) | Qt::ItemIsEditable;
+    }
 }
 
 QVariant AttendeeTableModel::data(const QModelIndex &index, int role) const
@@ -45,16 +48,18 @@ QVariant AttendeeTableModel::data(const QModelIndex &index, int role) const
 
     if (role == Qt::DisplayRole || role == Qt::EditRole) {
         switch (index.column()) {
-        case 0:
+        case Role:
             return attendeeList[index.row()]->role();
-        case 1:
+        case Name:
             return attendeeList[index.row()]->fullName();
-        case 2:
+        case Available:
             return 0;//attendeeList.at(index.row()).available;
-        case 3:
+        case Status:
             return attendeeList[index.row()]->status();
-        case 4:
+        case CuType:
             return attendeeList[index.row()]->cuType();
+        case Response:
+            return attendeeList[index.row()]->RSVP();
         }
 
     }
@@ -66,23 +71,26 @@ bool AttendeeTableModel::setData(const QModelIndex& index, const QVariant& value
     QString email, name;
     if (index.isValid() && role == Qt::EditRole) {
         switch (index.column()) {
-        case 0:
+        case Role:
             attendeeList[index.row()]->setRole(static_cast<KCalCore::Attendee::Role>(value.toInt()));
             break;
-        case 1:
+        case Name:
             KPIMUtils::extractEmailAddressAndName(value.toString(), email, name);
             attendeeList[index.row()]->setName(name);
             attendeeList[index.row()]->setEmail(email);
             break;
-        case 2:
+        case Available:
             //attendeeList[index.row()].available = value.toBool();
             break;
-        case 3:
+        case Status:
             attendeeList[index.row()]->setStatus(static_cast<KCalCore::Attendee::PartStat>(value.toInt()));
             break;
-        case 4:
+        case CuType:
             attendeeList[index.row()]->setCuType(static_cast<KCalCore::Attendee::CuType>(value.toInt()));
             break;
+        case Response:
+            attendeeList[index.row()]->setRSVP(value.toBool());
+            break;
         default:
             return false;
         }
@@ -101,16 +109,18 @@ QVariant AttendeeTableModel::headerData(int section, Qt::Orientation orientation
 
     if (orientation == Qt::Horizontal) {
         switch (section) {
-        case 0:
+        case Role:
             return QString("role");
-        case 1:
+        case Name:
             return QString("name");
-        case 2:
+        case Available:
             return QString("available");
-        case 3:
+        case Status:
             return QString("status");
-        case 4:
+        case CuType:
             return QString("cuType");
+        case Response:
+            return QString("response");
         }
     }
 
@@ -175,7 +185,7 @@ ResourceFilterProxyModel::ResourceFilterProxyModel(QObject *parent)
 
 bool ResourceFilterProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
 {
-    QModelIndex cuTypeIndex = sourceModel()->index(sourceRow, 4, sourceParent);
+    QModelIndex cuTypeIndex = sourceModel()->index(sourceRow, AttendeeTableModel::CuType, sourceParent);
     KCalCore::Attendee::CuType cuType = static_cast<KCalCore::Attendee::CuType>(sourceModel()->data(cuTypeIndex).toUInt());
 
     return (cuType == KCalCore::Attendee::Resource || cuType == KCalCore::Attendee::Room);
@@ -188,7 +198,7 @@ AttendeeFilterProxyModel::AttendeeFilterProxyModel(QObject *parent)
 
 bool AttendeeFilterProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
 {
-    QModelIndex cuTypeIndex = sourceModel()->index(sourceRow, 4, sourceParent);
+    QModelIndex cuTypeIndex = sourceModel()->index(sourceRow, AttendeeTableModel::CuType, sourceParent);
     KCalCore::Attendee::CuType cuType = static_cast<KCalCore::Attendee::CuType>(sourceModel()->data(cuTypeIndex).toUInt());
 
     return !(cuType == KCalCore::Attendee::Resource || cuType == KCalCore::Attendee::Room);
diff --git a/incidenceeditor-ng/attendeetablemodel.h b/incidenceeditor-ng/attendeetablemodel.h
index d234b36..ea525e1 100644
--- a/incidenceeditor-ng/attendeetablemodel.h
+++ b/incidenceeditor-ng/attendeetablemodel.h
@@ -31,19 +31,21 @@
 namespace IncidenceEditorNG
 {
 
-/* TableView for the Resource Tab
- * 0 = role
- * 1 = name
- * 2 = available
- * 3 = status
- * 4 = cutype
- */
-
 class AttendeeTableModel : public QAbstractTableModel
 {
     Q_OBJECT
 
 public:
+
+    enum Columns {
+      CuType,
+      Role,
+      Name,
+      Available,
+      Status,
+      Response
+    };
+
     AttendeeTableModel(const KCalCore::Attendee::List &resources, QObject *parent = 0);
 
     int rowCount(const QModelIndex &parent = QModelIndex()) const;
diff --git a/incidenceeditor-ng/dialogdesktop.ui b/incidenceeditor-ng/dialogdesktop.ui
index f17885e..3f8f53b 100644
--- a/incidenceeditor-ng/dialogdesktop.ui
+++ b/incidenceeditor-ng/dialogdesktop.ui
@@ -13,7 +13,16 @@
   <layout class="QVBoxLayout" name="mainVerticalLayout">
    <item>
     <layout class="QGridLayout" name="gridLayout">
-     <property name="margin">
+     <property name="leftMargin">
+      <number>0</number>
+     </property>
+     <property name="topMargin">
+      <number>0</number>
+     </property>
+     <property name="rightMargin">
+      <number>0</number>
+     </property>
+     <property name="bottomMargin">
       <number>0</number>
      </property>
      <item row="0" column="0">
@@ -41,7 +50,16 @@
      <item row="1" column="1">
       <widget class="QWidget" name="mInvitationBar" native="true">
        <layout class="QHBoxLayout" name="horizontalLayout_10">
-        <property name="margin">
+        <property name="leftMargin">
+         <number>0</number>
+        </property>
+        <property name="topMargin">
+         <number>0</number>
+        </property>
+        <property name="rightMargin">
+         <number>0</number>
+        </property>
+        <property name="bottomMargin">
          <number>0</number>
         </property>
         <item>
@@ -195,7 +213,16 @@
      <item row="5" column="1">
       <widget class="QWidget" name="mCompletionPriorityWidget" native="true">
        <layout class="QHBoxLayout" name="horizontalLayout_8">
-        <property name="margin">
+        <property name="leftMargin">
+         <number>0</number>
+        </property>
+        <property name="topMargin">
+         <number>0</number>
+        </property>
+        <property name="rightMargin">
+         <number>0</number>
+        </property>
+        <property name="bottomMargin">
          <number>0</number>
         </property>
         <item>
@@ -778,11 +805,20 @@
             </sizepolicy>
            </property>
            <property name="currentIndex">
-            <number>0</number>
+            <number>1</number>
            </property>
            <widget class="QWidget" name="page">
             <layout class="QGridLayout" name="gridLayout_2">
-             <property name="margin">
+             <property name="leftMargin">
+              <number>0</number>
+             </property>
+             <property name="topMargin">
+              <number>0</number>
+             </property>
+             <property name="rightMargin">
+              <number>0</number>
+             </property>
+             <property name="bottomMargin">
               <number>0</number>
              </property>
              <item row="0" column="0">
@@ -805,7 +841,16 @@
            </widget>
            <widget class="QWidget" name="page_2">
             <layout class="QGridLayout" name="gridLayout_3">
-             <property name="margin">
+             <property name="leftMargin">
+              <number>0</number>
+             </property>
+             <property name="topMargin">
+              <number>0</number>
+             </property>
+             <property name="rightMargin">
+              <number>0</number>
+             </property>
+             <property name="bottomMargin">
               <number>0</number>
              </property>
              <item row="0" column="0">
@@ -831,68 +876,80 @@
         <attribute name="title">
          <string>Resources</string>
         </attribute>
-        <widget class="QWidget" name="horizontalLayoutWidget">
-         <property name="geometry">
-          <rect>
-           <x>0</x>
-           <y>230</y>
-           <width>641</width>
-           <height>31</height>
-          </rect>
-         </property>
-         <layout class="QHBoxLayout" name="horizontalLayout_11">
-          <item>
-           <widget class="KLineEdit" name="mNewResource"/>
-          </item>
-          <item>
-           <widget class="QPushButton" name="mBookResourceButton">
-            <property name="text">
-             <string>Book resource</string>
-            </property>
-           </widget>
-          </item>
-          <item>
-           <spacer name="horizontalSpacer_14">
-            <property name="orientation">
-             <enum>Qt::Horizontal</enum>
-            </property>
-            <property name="sizeHint" stdset="0">
-             <size>
-              <width>40</width>
-              <height>20</height>
-             </size>
-            </property>
-           </spacer>
-          </item>
-          <item>
-           <widget class="QPushButton" name="mFindResourcesButton">
-            <property name="text">
-             <string>Find Resources...</string>
-            </property>
-           </widget>
-          </item>
-         </layout>
-        </widget>
-        <widget class="QTableView" name="mResourcesTable">
-         <property name="geometry">
-          <rect>
-           <x>0</x>
-           <y>10</y>
-           <width>631</width>
-           <height>211</height>
-          </rect>
-         </property>
-        </widget>
-        <widget class="QTableView" name="mAttendeeTable">
-         <property name="geometry">
-          <rect>
-           <x>0</x>
-           <y>260</y>
-           <width>631</width>
-           <height>211</height>
-          </rect>
-         </property>
-        </widget>
+        <layout class="QGridLayout" name="gridLayout_5">
+         <item row="0" column="0">
+          <widget class="QTableView" name="mResourcesTable">
+           <property name="editTriggers">
+            <set>QAbstractItemView::AllEditTriggers</set>
+           </property>
+           <property name="showGrid">
+            <bool>false</bool>
+           </property>
+           <property name="gridStyle">
+            <enum>Qt::SolidLine</enum>
+           </property>
+           <property name="wordWrap">
+            <bool>false</bool>
+           </property>
+           <attribute name="horizontalHeaderHighlightSections">
+            <bool>false</bool>
+           </attribute>
+          </widget>
+         </item>
+         <item row="1" column="0">
+          <layout class="QHBoxLayout" name="horizontalLayout_11">
+           <item>
+            <widget class="KLineEdit" name="mNewResource"/>
+           </item>
+           <item>
+            <widget class="QPushButton" name="mBookResourceButton">
+             <property name="text">
+              <string>Book resource</string>
+             </property>
+            </widget>
+           </item>
+           <item>
+            <spacer name="horizontalSpacer_14">
+             <property name="orientation">
+              <enum>Qt::Horizontal</enum>
+             </property>
+             <property name="sizeHint" stdset="0">
+              <size>
+               <width>40</width>
+               <height>20</height>
+              </size>
+             </property>
+            </spacer>
+           </item>
+           <item>
+            <widget class="QPushButton" name="mFindResourcesButton">
+             <property name="text">
+              <string>Find Resources...</string>
+             </property>
+            </widget>
+           </item>
+          </layout>
+         </item>
+         <item row="2" column="0">
+          <widget class="QTableView" name="mAttendeeTable">
+           <property name="frameShadow">
+            <enum>QFrame::Plain</enum>
+           </property>
+           <property name="editTriggers">
+            <set>QAbstractItemView::AllEditTriggers</set>
+           </property>
+           <property name="showGrid">
+            <bool>false</bool>
+           </property>
+           <attribute name="horizontalHeaderVisible">
+            <bool>false</bool>
+           </attribute>
+           <attribute name="horizontalHeaderCascadingSectionResizes">
+            <bool>false</bool>
+           </attribute>
+          </widget>
+         </item>
+        </layout>
        </widget>
        <widget class="QWidget" name="mReminderTab">
         <attribute name="title">
@@ -1137,14 +1194,32 @@
            <widget class="QWidget" name="never_page"/>
            <widget class="QWidget" name="daily_page">
             <layout class="QGridLayout" name="gridLayout_11">
-             <property name="margin">
+             <property name="leftMargin">
+              <number>0</number>
+             </property>
+             <property name="topMargin">
+              <number>0</number>
+             </property>
+             <property name="rightMargin">
+              <number>0</number>
+             </property>
+             <property name="bottomMargin">
               <number>0</number>
              </property>
             </layout>
            </widget>
            <widget class="QWidget" name="weekly_page">
             <layout class="QGridLayout" name="gridLayout_4">
-             <property name="margin">
+             <property name="leftMargin">
+              <number>0</number>
+             </property>
+             <property name="topMargin">
+              <number>0</number>
+             </property>
+             <property name="rightMargin">
+              <number>0</number>
+             </property>
+             <property name="bottomMargin">
               <number>0</number>
              </property>
              <item row="0" column="0">
@@ -1164,7 +1239,16 @@
            </widget>
            <widget class="QWidget" name="Monthly">
             <layout class="QGridLayout" name="gridLayout_6">
-             <property name="margin">
+             <property name="leftMargin">
+              <number>0</number>
+             </property>
+             <property name="topMargin">
+              <number>0</number>
+             </property>
+             <property name="rightMargin">
+              <number>0</number>
+             </property>
+             <property name="bottomMargin">
               <number>0</number>
              </property>
              <item row="0" column="0">
@@ -1197,7 +1281,16 @@
            </widget>
            <widget class="QWidget" name="yearly_page">
             <layout class="QGridLayout" name="gridLayout_7">
-             <property name="margin">
+             <property name="leftMargin">
+              <number>0</number>
+             </property>
+             <property name="topMargin">
+              <number>0</number>
+             </property>
+             <property name="rightMargin">
+              <number>0</number>
+             </property>
+             <property name="bottomMargin">
               <number>0</number>
              </property>
              <item row="0" column="0">
@@ -1289,14 +1382,32 @@
              </property>
              <widget class="QWidget" name="no_end">
               <layout class="QGridLayout" name="gridLayout_16">
-               <property name="margin">
+               <property name="leftMargin">
+                <number>0</number>
+               </property>
+               <property name="topMargin">
+                <number>0</number>
+               </property>
+               <property name="rightMargin">
+                <number>0</number>
+               </property>
+               <property name="bottomMargin">
                 <number>0</number>
                </property>
               </layout>
              </widget>
              <widget class="QWidget" name="end_on">
               <layout class="QGridLayout" name="gridLayout_14">
-               <property name="margin">
+               <property name="leftMargin">
+                <number>0</number>
+               </property>
+               <property name="topMargin">
+                <number>0</number>
+               </property>
+               <property name="rightMargin">
+                <number>0</number>
+               </property>
+               <property name="bottomMargin">
                 <number>0</number>
                </property>
                <item row="0" column="0">
@@ -1329,10 +1440,19 @@
              </widget>
              <widget class="QWidget" name="end_after">
               <layout class="QGridLayout" name="gridLayout_10">
-               <property name="horizontalSpacing">
+               <property name="leftMargin">
+                <number>0</number>
+               </property>
+               <property name="topMargin">
+                <number>0</number>
+               </property>
+               <property name="rightMargin">
+                <number>0</number>
+               </property>
+               <property name="bottomMargin">
                 <number>0</number>
                </property>
-               <property name="margin">
+               <property name="horizontalSpacing">
                 <number>0</number>
                </property>
                <item row="0" column="0">
@@ -1558,21 +1678,6 @@
  </widget>
  <customwidgets>
   <customwidget>
-   <class>KRichTextEdit</class>
-   <extends>KTextEdit</extends>
-   <header>krichtextedit.h</header>
-  </customwidget>
-  <customwidget>
-   <class>KTimeComboBox</class>
-   <extends>KComboBox</extends>
-   <header>ktimecombobox.h</header>
-  </customwidget>
-  <customwidget>
-   <class>KDateComboBox</class>
-   <extends>KComboBox</extends>
-   <header>kdatecombobox.h</header>
-  </customwidget>
-  <customwidget>
    <class>KComboBox</class>
    <extends>QComboBox</extends>
    <header>kcombobox.h</header>
@@ -1586,6 +1691,7 @@
    <class>KSeparator</class>
    <extends>QFrame</extends>
    <header>kseparator.h</header>
+   <container>1</container>
   </customwidget>
   <customwidget>
    <class>KTextEdit</class>
@@ -1593,11 +1699,6 @@
    <header>ktextedit.h</header>
   </customwidget>
   <customwidget>
-   <class>KRichTextWidget</class>
-   <extends>KRichTextEdit</extends>
-   <header>krichtextwidget.h</header>
-  </customwidget>
-  <customwidget>
    <class>KTabWidget</class>
    <extends>QTabWidget</extends>
    <header>ktabwidget.h</header>
@@ -1629,6 +1730,26 @@
    <header>libkdepim/widgets/tagwidgets.h</header>
    <container>1</container>
   </customwidget>
+  <customwidget>
+   <class>KRichTextEdit</class>
+   <extends>KTextEdit</extends>
+   <header>krichtextedit.h</header>
+  </customwidget>
+  <customwidget>
+   <class>KTimeComboBox</class>
+   <extends>KComboBox</extends>
+   <header>ktimecombobox.h</header>
+  </customwidget>
+  <customwidget>
+   <class>KDateComboBox</class>
+   <extends>KComboBox</extends>
+   <header>kdatecombobox.h</header>
+  </customwidget>
+  <customwidget>
+   <class>KRichTextWidget</class>
+   <extends>KRichTextEdit</extends>
+   <header>krichtextwidget.h</header>
+  </customwidget>
  </customwidgets>
  <resources/>
  <connections>
diff --git a/incidenceeditor-ng/incidenceresource.cpp b/incidenceeditor-ng/incidenceresource.cpp
index 5969c86..f718e6b 100644
--- a/incidenceeditor-ng/incidenceresource.cpp
+++ b/incidenceeditor-ng/incidenceresource.cpp
@@ -50,6 +50,7 @@ IncidenceResource::IncidenceResource(Ui::EventOrTodoDesktop *ui)
     setObjectName("IncidenceResource");
 
     AttendeeComboBoxDelegate* roleDelegate(new AttendeeComboBoxDelegate(this));
+    AttendeeComboBoxDelegate* responseDelegate(new AttendeeComboBoxDelegate(this));
 #ifdef KDEPIM_MOBILE_UI
     roleDelegate->addItem(DesktopIcon("meeting-participant", 48),
                           KCalUtils::Stringify::attendeeRole(KCalCore::Attendee::ReqParticipant));
@@ -60,6 +61,11 @@ IncidenceResource::IncidenceResource(Ui::EventOrTodoDesktop *ui)
     roleDelegate->addItem(DesktopIcon("meeting-chair", 48),
                           KCalUtils::Stringify::attendeeRole(KCalCore::Attendee::Chair));
 
+    responseDelegate->addItem( DesktopIcon( "meeting-participant-request-response", 48 ),
+                             i18nc( "@item:inlistbox", "Request Response" ) );
+    responseDelegate->addItem( DesktopIcon( "meeting-participant-no-response", 48 ),
+                             i18nc( "@item:inlistbox", "Request No Response" ) );
+
 #else
     roleDelegate->addItem(SmallIcon("meeting-participant"),
                           KCalUtils::Stringify::attendeeRole(KCalCore::Attendee::ReqParticipant));
@@ -69,6 +75,12 @@ IncidenceResource::IncidenceResource(Ui::EventOrTodoDesktop *ui)
                           KCalUtils::Stringify::attendeeRole(KCalCore::Attendee::NonParticipant));
     roleDelegate->addItem(SmallIcon("meeting-chair"),
                           KCalUtils::Stringify::attendeeRole(KCalCore::Attendee::Chair));
+
+    responseDelegate->addItem( SmallIcon( "meeting-participant-request-response" ),
+                             i18nc( "@item:inlistbox", "Request Response" ) );
+    responseDelegate->addItem( SmallIcon( "meeting-participant-no-response" ),
+                             i18nc( "@item:inlistbox", "Request No Response" ) );
+
 #endif
 
     AttendeeComboBoxDelegate *stateDelegate(new AttendeeComboBoxDelegate(this));
@@ -119,20 +131,25 @@ IncidenceResource::IncidenceResource(Ui::EventOrTodoDesktop *ui)
     filterProxyModel->setDynamicSortFilter(true);
     filterProxyModel->setSourceModel(dataModel);
 
+    QHeaderView* headerView = mUi->mResourcesTable->horizontalHeader();
+    headerView->setResizeMode(QHeaderView::ResizeToContents);
+
     mUi->mResourcesTable->setModel(filterProxyModel);
-    mUi->mResourcesTable->setColumnHidden(4, true);
-    mUi->mResourcesTable->setItemDelegateForColumn(0, roleDelegate);
-    mUi->mResourcesTable->setItemDelegateForColumn(1, attendeeDelegate);
-    mUi->mResourcesTable->setItemDelegateForColumn(3, stateDelegate);
+    mUi->mResourcesTable->setColumnHidden(AttendeeTableModel::CuType, true);
+    mUi->mResourcesTable->setItemDelegateForColumn(AttendeeTableModel::Role, roleDelegate);
+    mUi->mResourcesTable->setItemDelegateForColumn(AttendeeTableModel::Name, attendeeDelegate);
+    mUi->mResourcesTable->setItemDelegateForColumn(AttendeeTableModel::Status, stateDelegate);
+    mUi->mResourcesTable->setItemDelegateForColumn(AttendeeTableModel::Response, responseDelegate);
 
 
     AttendeeFilterProxyModel *attendeeProxyModel = new AttendeeFilterProxyModel(this);
     attendeeProxyModel->setDynamicSortFilter(true);
     attendeeProxyModel->setSourceModel(dataModel);
     mUi->mAttendeeTable->setModel(attendeeProxyModel);
-    mUi->mAttendeeTable->setItemDelegateForColumn(0, roleDelegate);
-    mUi->mAttendeeTable->setItemDelegateForColumn(1, attendeeDelegate);
-    mUi->mAttendeeTable->setItemDelegateForColumn(3, stateDelegate);
+    mUi->mAttendeeTable->setItemDelegateForColumn(AttendeeTableModel::Role, roleDelegate);
+    mUi->mAttendeeTable->setItemDelegateForColumn(AttendeeTableModel::Name, attendeeDelegate);
+    mUi->mAttendeeTable->setItemDelegateForColumn(AttendeeTableModel::Status, stateDelegate);
+    mUi->mAttendeeTable->setItemDelegateForColumn(AttendeeTableModel::Response, responseDelegate);
 
     connect(mUi->mFindResourcesButton, SIGNAL(clicked()), SLOT(findResources()));
     connect(mUi->mBookResourceButton, SIGNAL(clicked()), SLOT(bookResource()));


commit 3db976be01f161ecc45e666baa2897e1d8c01191
Author: Sandro Knauß <knauss at kolabsys.com>
Date:   Tue Jun 3 17:34:50 2014 +0200

    adding TODO: for showing ifb

diff --git a/incidenceeditor-ng/resourcemanagement.cpp b/incidenceeditor-ng/resourcemanagement.cpp
index 48a55d7..8b884ed 100644
--- a/incidenceeditor-ng/resourcemanagement.cpp
+++ b/incidenceeditor-ng/resourcemanagement.cpp
@@ -82,6 +82,19 @@ void ResourceManagement::showDetails(const KLDAP::LdapObject &obj)
         }
         ui->formDetails->addRow(key, new QLabel(list.join("\n")));
     }
+
+    /*
+     * TODO: Has to be needed and tested : )
+    KUrl httpUrl;
+    httpUrl.setUser(  userName );
+    httpUrl.setPassword(  password );
+    httpUrl.setHost(  host );
+    httpUrl.setProtocol(  QLatin1String(  "https" ) );
+    httpUrl.setPath(  QLatin1String( "/freebusy/" ) + user + QLatin1String( ".ifb" ) );
+
+    KIO::Job *job = KIO::get(  url, KIO::NoReload, KIO::HideProgressInfo );
+    */
+
 }
 
 #include "resourcemanagement.moc"


commit 9922c32a2b4d82c1772bda881947f58a04a89dcd
Author: Sandro Knauß <mail at sandroknauss.de>
Date:   Mon Apr 21 00:17:01 2014 +0200

    Added resourcemanagement files and tab in EventEditor
    
    The ResourceManager can now ask a LDAP Server for collection and
    resources that match a queryString.
    * show details on a single resource
    * show the resources in a treeview
    * a resourcemodel and a resourceitem to use it in a model/view env.
    * ResourceTab in EventEditor

diff --git a/incidenceeditor-ng/CMakeLists.txt b/incidenceeditor-ng/CMakeLists.txt
index 219b242..b184732 100644
--- a/incidenceeditor-ng/CMakeLists.txt
+++ b/incidenceeditor-ng/CMakeLists.txt
@@ -43,6 +43,7 @@ set(incidenceeditors_ng_shared_LIB_SRCS
   incidencewhatwhere.cpp
   incidencedatetime.cpp
   incidencerecurrence.cpp
+  incidenceresource.cpp
   incidencesecrecy.cpp
 
   freebusyitem.cpp
@@ -66,6 +67,11 @@ set(incidenceeditors_ng_shared_LIB_SRCS
   individualmailcomponentfactory.cpp
   individualmaildialog.cpp
   opencomposerjob.cpp
+  resourcemanagement.cpp
+  resourceitem.cpp
+  resourcemodel.cpp
+  attendeetablemodel.cpp
+  attendeecomboboxdelegate.cpp
 )
 
 kde4_add_kcfg_files(incidenceeditors_ng_shared_LIB_SRCS globalsettings_base.kcfgc)
@@ -89,6 +95,7 @@ kde4_add_ui_files(incidenceeditors_ng_desktop_LIB_SRCS
   alarmdialog.ui
   attachmenteditdialog.ui
   schedulingdialog.ui
+  resourcemanagement.ui
 )
 
 kde4_add_library(incidenceeditorsng ${LIBRARY_TYPE} ${incidenceeditors_ng_desktop_LIB_SRCS})
diff --git a/incidenceeditor-ng/attendeecomboboxdelegate.cpp b/incidenceeditor-ng/attendeecomboboxdelegate.cpp
new file mode 100644
index 0000000..21ec3f8
--- /dev/null
+++ b/incidenceeditor-ng/attendeecomboboxdelegate.cpp
@@ -0,0 +1,105 @@
+#include "attendeecomboboxdelegate.h"
+
+#include "attendeeline.h"
+
+#include <QApplication>
+
+using namespace IncidenceEditorNG;
+
+AttendeeComboBoxDelegate::AttendeeComboBoxDelegate(QObject *parent)
+    : QStyledItemDelegate(parent)
+    , standardIndex(0)
+{
+
+}
+
+void AttendeeComboBoxDelegate::addItem(const QIcon &icon, const QString &text)
+{
+    QPair<QIcon, QString> pair;
+    pair.first = icon;
+    pair.second = text;
+    entries << pair;
+}
+
+void AttendeeComboBoxDelegate::setStandardIndex(int index)
+{
+    standardIndex = index;
+}
+
+
+QWidget *AttendeeComboBoxDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &/* option */, const QModelIndex &/* index */) const
+{
+    AttendeeComboBox* editor = new AttendeeComboBox(parent);
+    QPair<QIcon, QString> pair;
+
+    foreach(pair, entries) {
+        editor->addItem(pair.first, pair.second);
+    }
+
+    return editor;
+}
+
+void AttendeeComboBoxDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
+{
+    AttendeeComboBox *comboBox = static_cast<AttendeeComboBox*>(editor);
+    int value = index.model()->data(index, Qt::EditRole).toUInt();
+    if (value >= entries.count()) {
+        value = standardIndex;
+    }
+    comboBox->setCurrentIndex(value);
+}
+
+void AttendeeComboBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
+{
+    AttendeeComboBox *comboBox = static_cast<AttendeeComboBox*>(editor);
+    model->setData(index, comboBox->currentIndex(), Qt::EditRole);
+}
+
+void AttendeeComboBoxDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &/* index */) const
+{
+    editor->setGeometry(option.rect);
+}
+
+void AttendeeComboBoxDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
+{
+    QStyleOptionButton pushButton;
+    int value = index.model()->data(index).toUInt();
+    pushButton.rect = option.rect;
+    pushButton.features |= QStyleOptionButton::HasMenu;
+    if (value >= entries.count()) {
+        value = standardIndex;
+    }
+    pushButton.icon = entries[value].first;
+
+    QApplication::style()->drawControl(QStyle::CE_PushButton, &pushButton, painter);
+}
+
+AttendeeLineEditDelegate::AttendeeLineEditDelegate(QObject* parent)
+    : QStyledItemDelegate(parent)
+{
+
+}
+
+
+QWidget *AttendeeLineEditDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &/* option */, const QModelIndex &/* index */) const
+{
+    KPIM::AddresseeLineEdit* editor = new KPIM::AddresseeLineEdit(parent);
+    return editor;
+}
+
+void AttendeeLineEditDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
+{
+    KPIM::AddresseeLineEdit *lineedit = static_cast<KPIM::AddresseeLineEdit*>(editor);
+    lineedit->setText(index.model()->data(index, Qt::EditRole).toString());
+}
+
+void AttendeeLineEditDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
+{
+    KPIM::AddresseeLineEdit *lineedit = static_cast<KPIM::AddresseeLineEdit*>(editor);
+    model->setData(index, lineedit->text(), Qt::EditRole);
+}
+
+void AttendeeLineEditDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &/* index */) const
+{
+    editor->setGeometry(option.rect);
+}
diff --git a/incidenceeditor-ng/attendeecomboboxdelegate.h b/incidenceeditor-ng/attendeecomboboxdelegate.h
new file mode 100644
index 0000000..6d4b4a5
--- /dev/null
+++ b/incidenceeditor-ng/attendeecomboboxdelegate.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright 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) version 3 or any later version
+ * accepted by the membership of KDE e.V. (or its successor approved
+ * by the membership of KDE e.V.), which shall act as a proxy
+ * defined in Section 14 of version 3 of the license.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef INCIDENCEEDITOR_ATTENDEECOMBOBOXDELEGATE_H
+#define INCIDENCEEDITOR_ATTENDEECOMBOBOXDELEGATE_H
+
+#include <QStyledItemDelegate>
+#include <QModelIndex>
+#include <QIcon>
+#include <QString>
+
+
+namespace IncidenceEditorNG
+{
+
+  /**
+   * class to show a Icon and Text for an Attendee
+   * you have to set the Items via adItem to have a list to choose from.
+   * saves the option as int in the model
+   */
+class AttendeeComboBoxDelegate : public QStyledItemDelegate
+{
+    Q_OBJECT
+public:
+    AttendeeComboBoxDelegate(QObject *parent = 0);
+
+    QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const;
+    void setEditorData(QWidget *editor, const QModelIndex &index) const;
+    void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const;
+    void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const;
+    void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
+
+    void addItem(const QIcon&, const QString&);
+
+    /** choose this index, if the item in the model is unknown
+     */
+    void setStandardIndex(int);
+
+private:
+    /** all entries to choose from */
+    QList<QPair<QIcon, QString> > entries;
+    /**fallback index */
+    int standardIndex;
+
+};
+
+/** show a KPIM::AddressLineEdit as editor */
+class AttendeeLineEditDelegate : public QStyledItemDelegate
+{
+    Q_OBJECT
+public:
+    AttendeeLineEditDelegate(QObject *parent = 0);
+
+    QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const;
+    void setEditorData(QWidget *editor, const QModelIndex &index) const;
+    void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const;
+    void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const;
+};
+
+}
+
+#endif
\ No newline at end of file
diff --git a/incidenceeditor-ng/attendeetablemodel.cpp b/incidenceeditor-ng/attendeetablemodel.cpp
new file mode 100644
index 0000000..b947aac
--- /dev/null
+++ b/incidenceeditor-ng/attendeetablemodel.cpp
@@ -0,0 +1,195 @@
+#include "attendeetablemodel.h"
+
+#include <KCalCore/Attendee>
+#include <KPIMUtils/Email>
+
+#include <KDebug>
+
+using namespace IncidenceEditorNG;
+
+AttendeeTableModel::AttendeeTableModel(const KCalCore::Attendee::List &attendees, QObject *parent)
+    : QAbstractTableModel(parent)
+    , attendeeList(attendees)
+{
+
+}
+
+int AttendeeTableModel::rowCount(const QModelIndex &/*parent*/) const
+{
+    return attendeeList.count();
+}
+
+int AttendeeTableModel::columnCount(const QModelIndex &/*parent*/) const
+{
+    return 5;
+}
+
+Qt::ItemFlags AttendeeTableModel::flags(const QModelIndex &index) const
+{
+    if (!index.isValid()) {
+        return Qt::ItemIsEnabled;
+    }
+
+    return QAbstractTableModel::flags(index) | Qt::ItemIsEditable;
+}
+
+QVariant AttendeeTableModel::data(const QModelIndex &index, int role) const
+{
+    if (!index.isValid()) {
+        return QVariant();
+    }
+
+    if (index.row() >= attendeeList.size()) {
+        return QVariant();
+    }
+
+    if (role == Qt::DisplayRole || role == Qt::EditRole) {
+        switch (index.column()) {
+        case 0:
+            return attendeeList[index.row()]->role();
+        case 1:
+            return attendeeList[index.row()]->fullName();
+        case 2:
+            return 0;//attendeeList.at(index.row()).available;
+        case 3:
+            return attendeeList[index.row()]->status();
+        case 4:
+            return attendeeList[index.row()]->cuType();
+        }
+
+    }
+    return QVariant();
+}
+
+bool AttendeeTableModel::setData(const QModelIndex& index, const QVariant& value, int role)
+{
+    QString email, name;
+    if (index.isValid() && role == Qt::EditRole) {
+        switch (index.column()) {
+        case 0:
+            attendeeList[index.row()]->setRole(static_cast<KCalCore::Attendee::Role>(value.toInt()));
+            break;
+        case 1:
+            KPIMUtils::extractEmailAddressAndName(value.toString(), email, name);
+            attendeeList[index.row()]->setName(name);
+            attendeeList[index.row()]->setEmail(email);
+            break;
+        case 2:
+            //attendeeList[index.row()].available = value.toBool();
+            break;
+        case 3:
+            attendeeList[index.row()]->setStatus(static_cast<KCalCore::Attendee::PartStat>(value.toInt()));
+            break;
+        case 4:
+            attendeeList[index.row()]->setCuType(static_cast<KCalCore::Attendee::CuType>(value.toInt()));
+            break;
+        default:
+            return false;
+        }
+        emit dataChanged(index, index);
+        return true;
+    }
+    return false;
+}
+
+QVariant AttendeeTableModel::headerData(int section, Qt::Orientation orientation,
+                                        int role) const
+{
+    if (role != Qt::DisplayRole) {
+        return QVariant();
+    }
+
+    if (orientation == Qt::Horizontal) {
+        switch (section) {
+        case 0:
+            return QString("role");
+        case 1:
+            return QString("name");
+        case 2:
+            return QString("available");
+        case 3:
+            return QString("status");
+        case 4:
+            return QString("cuType");
+        }
+    }
+
+    return QVariant();
+}
+
+bool AttendeeTableModel::insertRows(int position, int rows, const QModelIndex &parent)
+{
+    beginInsertRows(QModelIndex(), position, position + rows);
+
+    for (int row = 0; row < rows; ++row) {
+        KCalCore::Attendee::Ptr attendee(new KCalCore::Attendee("", ""));
+        attendeeList.insert(position, attendee);
+    }
+
+    endInsertRows();
+    return true;
+}
+
+bool AttendeeTableModel::removeRows(int position, int rows, const QModelIndex &parent)
+{
+    beginRemoveRows(QModelIndex(), position, position + rows);
+
+    for (int row = 0; row < rows; ++row) {
+        attendeeList.remove(position);
+    }
+
+    endRemoveRows();
+    return true;
+}
+
+bool AttendeeTableModel::insertAttendee(int position, const KCalCore::Attendee::Ptr& attendee)
+{
+    beginInsertRows(QModelIndex(), position, position);
+
+    attendeeList.insert(position, attendee);
+
+    endInsertRows();
+
+    return true;
+}
+
+void AttendeeTableModel::setAttendees(const KCalCore::Attendee::List attendees)
+{
+    emit layoutAboutToBeChanged();
+
+    attendeeList = attendees;
+
+    emit layoutChanged();
+}
+
+
+KCalCore::Attendee::List AttendeeTableModel::attendees() const
+{
+    return attendeeList;
+}
+
+ResourceFilterProxyModel::ResourceFilterProxyModel(QObject *parent)
+    : QSortFilterProxyModel(parent)
+{
+}
+
+bool ResourceFilterProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
+{
+    QModelIndex cuTypeIndex = sourceModel()->index(sourceRow, 4, sourceParent);
+    KCalCore::Attendee::CuType cuType = static_cast<KCalCore::Attendee::CuType>(sourceModel()->data(cuTypeIndex).toUInt());
+
+    return (cuType == KCalCore::Attendee::Resource || cuType == KCalCore::Attendee::Room);
+}
+
+AttendeeFilterProxyModel::AttendeeFilterProxyModel(QObject *parent)
+    : QSortFilterProxyModel(parent)
+{
+}
+
+bool AttendeeFilterProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
+{
+    QModelIndex cuTypeIndex = sourceModel()->index(sourceRow, 4, sourceParent);
+    KCalCore::Attendee::CuType cuType = static_cast<KCalCore::Attendee::CuType>(sourceModel()->data(cuTypeIndex).toUInt());
+
+    return !(cuType == KCalCore::Attendee::Resource || cuType == KCalCore::Attendee::Room);
+}
diff --git a/incidenceeditor-ng/attendeetablemodel.h b/incidenceeditor-ng/attendeetablemodel.h
new file mode 100644
index 0000000..d234b36
--- /dev/null
+++ b/incidenceeditor-ng/attendeetablemodel.h
@@ -0,0 +1,92 @@
+
+/*
+  Copyright (C) 2014 Sandro Knauß <knauss at kolabsys.com>
+
+  This library is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Library General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or (at your
+  option) any later version.
+
+  This library is distributed in the hope that it will be useful, but WITHOUT
+  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
+  License for more details.
+
+  You should have received a copy of the GNU Library General Public License
+  along with this library; see the file COPYING.LIB.  If not, write to the
+  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+  02110-1301, USA.
+*/
+
+#ifndef INCIDENCEEDITOR_INCIDENCERESOURCETABLEMODEL_H
+#define INCIDENCEEDITOR_INCIDENCERESOURCETABLEMODEL_H
+
+#include <KCalCore/Attendee>
+
+#include <QAbstractTableModel>
+#include <QSortFilterProxyModel>
+#include <QModelIndex>
+#include <QVector>
+
+namespace IncidenceEditorNG
+{
+
+/* TableView for the Resource Tab
+ * 0 = role
+ * 1 = name
+ * 2 = available
+ * 3 = status
+ * 4 = cutype
+ */
+
+class AttendeeTableModel : public QAbstractTableModel
+{
+    Q_OBJECT
+
+public:
+    AttendeeTableModel(const KCalCore::Attendee::List &resources, QObject *parent = 0);
+
+    int rowCount(const QModelIndex &parent = QModelIndex()) const;
+    int columnCount(const QModelIndex &parent = QModelIndex()) const;
+    QVariant data(const QModelIndex &index, int role) const;
+    QVariant headerData(int section, Qt::Orientation orientation,
+                        int role = Qt::DisplayRole) const;
+
+    Qt::ItemFlags flags(const QModelIndex &index) const;
+    bool setData(const QModelIndex &index, const QVariant &value,
+                 int role = Qt::EditRole);
+
+    bool insertRows(int position, int rows, const QModelIndex &index = QModelIndex());
+    bool removeRows(int position, int rows, const QModelIndex &index = QModelIndex());
+
+    bool insertAttendee(int position, const KCalCore::Attendee::Ptr &attendee);
+
+    void setAttendees(const KCalCore::Attendee::List resources);
+    KCalCore::Attendee::List attendees() const;
+
+private:
+    KCalCore::Attendee::List attendeeList;
+};
+
+class ResourceFilterProxyModel : public QSortFilterProxyModel
+{
+    Q_OBJECT
+public:
+    ResourceFilterProxyModel(QObject *parent = 0);
+    bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const;
+};
+
+class AttendeeFilterProxyModel : public QSortFilterProxyModel
+{
+    Q_OBJECT
+public:
+    AttendeeFilterProxyModel(QObject *parent = 0);
+    bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const;
+};
+
+
+}
+
+#endif
+
+
diff --git a/incidenceeditor-ng/dialogdesktop.ui b/incidenceeditor-ng/dialogdesktop.ui
index 45ebb20..f17885e 100644
--- a/incidenceeditor-ng/dialogdesktop.ui
+++ b/incidenceeditor-ng/dialogdesktop.ui
@@ -6,8 +6,8 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>661</width>
-    <height>551</height>
+    <width>909</width>
+    <height>833</height>
    </rect>
   </property>
   <layout class="QVBoxLayout" name="mainVerticalLayout">
@@ -578,7 +578,7 @@
      <item row="12" column="0" colspan="2">
       <widget class="KTabWidget" name="mTabWidget">
        <property name="currentIndex">
-        <number>0</number>
+        <number>2</number>
        </property>
        <widget class="QWidget" name="mGeneralTab">
         <attribute name="title">
@@ -827,6 +827,73 @@
          </item>
         </layout>
        </widget>
+       <widget class="QWidget" name="mResourceTab">
+        <attribute name="title">
+         <string>Resources</string>
+        </attribute>
+        <widget class="QWidget" name="horizontalLayoutWidget">
+         <property name="geometry">
+          <rect>
+           <x>0</x>
+           <y>230</y>
+           <width>641</width>
+           <height>31</height>
+          </rect>
+         </property>
+         <layout class="QHBoxLayout" name="horizontalLayout_11">
+          <item>
+           <widget class="KLineEdit" name="mNewResource"/>
+          </item>
+          <item>
+           <widget class="QPushButton" name="mBookResourceButton">
+            <property name="text">
+             <string>Book resource</string>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <spacer name="horizontalSpacer_14">
+            <property name="orientation">
+             <enum>Qt::Horizontal</enum>
+            </property>
+            <property name="sizeHint" stdset="0">
+             <size>
+              <width>40</width>
+              <height>20</height>
+             </size>
+            </property>
+           </spacer>
+          </item>
+          <item>
+           <widget class="QPushButton" name="mFindResourcesButton">
+            <property name="text">
+             <string>Find Resources...</string>
+            </property>
+           </widget>
+          </item>
+         </layout>
+        </widget>
+        <widget class="QTableView" name="mResourcesTable">
+         <property name="geometry">
+          <rect>
+           <x>0</x>
+           <y>10</y>
+           <width>631</width>
+           <height>211</height>
+          </rect>
+         </property>
+        </widget>
+        <widget class="QTableView" name="mAttendeeTable">
+         <property name="geometry">
+          <rect>
+           <x>0</x>
+           <y>260</y>
+           <width>631</width>
+           <height>211</height>
+          </rect>
+         </property>
+        </widget>
+       </widget>
        <widget class="QWidget" name="mReminderTab">
         <attribute name="title">
          <string comment="@title:tab Tab to configure reminders for events or to-do">Reminder</string>
@@ -1491,11 +1558,6 @@
  </widget>
  <customwidgets>
   <customwidget>
-   <class>KPIM::KCheckComboBox</class>
-   <extends>KComboBox</extends>
-   <header>libkdepim/widgets/kcheckcombobox.h</header>
-  </customwidget>
-  <customwidget>
    <class>KRichTextEdit</class>
    <extends>KTextEdit</extends>
    <header>krichtextedit.h</header>
@@ -1542,6 +1604,11 @@
    <container>1</container>
   </customwidget>
   <customwidget>
+   <class>KPIM::KCheckComboBox</class>
+   <extends>KComboBox</extends>
+   <header>libkdepim/widgets/kcheckcombobox.h</header>
+  </customwidget>
+  <customwidget>
    <class>KPIM::KWeekdayCheckCombo</class>
    <extends>KPIM::KCheckComboBox</extends>
    <header>libkdepim/widgets/kweekdaycheckcombo.h</header>
diff --git a/incidenceeditor-ng/incidenceattendee.cpp b/incidenceeditor-ng/incidenceattendee.cpp
index fa1811f..32d7f04 100644
--- a/incidenceeditor-ng/incidenceattendee.cpp
+++ b/incidenceeditor-ng/incidenceattendee.cpp
@@ -185,7 +185,9 @@ void IncidenceAttendee::load( const KCalCore::Incidence::Ptr &incidence )
 
   const KCalCore::Attendee::List attendees = incidence->attendees();
   foreach ( const KCalCore::Attendee::Ptr &a, attendees ) {
-    mAttendeeEditor->addAttendee( a );
+    if (!(a->cuType() == KCalCore::Attendee::Resource || a->cuType() == KCalCore::Attendee::Room)) {
+      mAttendeeEditor->addAttendee( a );
+    }
   }
 
   mWasDirty = false;
@@ -193,7 +195,7 @@ void IncidenceAttendee::load( const KCalCore::Incidence::Ptr &incidence )
 
 void IncidenceAttendee::save( const KCalCore::Incidence::Ptr &incidence )
 {
-  incidence->clearAttendees();
+  /*incidence->clearAttendees();
   AttendeeData::List attendees = mAttendeeEditor->attendees();
 
   foreach ( AttendeeData::Ptr attendee, attendees ) {
@@ -219,7 +221,7 @@ void IncidenceAttendee::save( const KCalCore::Incidence::Ptr &incidence )
   // Must not have an organizer for items without attendees
   if ( !incidence->attendeeCount() ) {
     return;
-  }
+  }*/
 
   if ( mUi->mOrganizerStack->currentIndex() == 0 ) {
     incidence->setOrganizer( mUi->mOrganizerCombo->currentText() );
@@ -247,13 +249,16 @@ bool IncidenceAttendee::isDirty() const
 
   // The lists sizes *must* be the same. When the organizer is attending the
   // event as well, he should be in the attendees list as well.
-  if ( originalList.size() != newList.size() ) {
+  /*if ( originalList.size() != newList.size() ) {
     return true;
-  }
+  }*/
 
   // 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 ) {
+    if (attendee->cuType() == KCalCore::Attendee::Resource || attendee->cuType() == KCalCore::Attendee::Room) {
+      continue;
+    }
     bool found = false;
     for ( int i = 0; i < newList.size(); ++i ) {
       if ( compareAttendees( newList.at( i )->attendee(), attendee) ) {
@@ -265,6 +270,7 @@ bool IncidenceAttendee::isDirty() const
 
     if ( !found ) {
       // One of the attendees in the original list was not found in the new list.
+      kDebug() << "One of the attendees in the original list was not found in the new list";
       return true;
     }
   }
@@ -605,6 +611,7 @@ void IncidenceAttendee::printDebugInfo() const
                << attendee->RSVP()
                << attendee->role()
                << attendee->uid()
+               << attendee->cuType()
                << attendee->delegate()
                << attendee->delegator()
                << "; we have:";
@@ -616,6 +623,7 @@ void IncidenceAttendee::printDebugInfo() const
                  << attendee->RSVP()
                  << attendee->role()
                  << attendee->uid()
+                 << attendee->cuType()
                  << attendee->delegate()
                  << attendee->delegator();
       }
diff --git a/incidenceeditor-ng/incidencedialog.cpp b/incidenceeditor-ng/incidencedialog.cpp
index dad6e77..9b96a3c 100644
--- a/incidenceeditor-ng/incidencedialog.cpp
+++ b/incidenceeditor-ng/incidencedialog.cpp
@@ -30,6 +30,7 @@
 #include "incidencedatetime.h"
 #include "incidencedescription.h"
 #include "incidencerecurrence.h"
+#include "incidenceresource.h"
 #include "incidencesecrecy.h"
 #include "incidencewhatwhere.h"
 #include "templatemanagementdialog.h"
@@ -59,6 +60,7 @@ namespace IncidenceEditorNG {
 enum Tabs {
   GeneralTab = 0,
   AttendeesTab,
+  ResourcesTab,
   AlarmsTab,
   RecurrenceTab,
   AttachmentsTab
@@ -79,6 +81,7 @@ class IncidenceDialogPrivate : public ItemEditorUi
     IncidenceDateTime *mIeDateTime;
     IncidenceAttendee *mIeAttendee;
     IncidenceRecurrence *mIeRecurrence;
+    IncidenceResource *mIeResource;
     bool mInitiallyDirty;
     Akonadi::Item mItem;
     QString typeToString( const int type ) const;
@@ -96,6 +99,7 @@ class IncidenceDialogPrivate : public ItemEditorUi
     void storeTemplatesInConfig( const QStringList &newTemplates );
     void updateAttachmentCount( int newCount );
     void updateAttendeeCount( int newCount );
+    void updateResourceCount( int newCount );
     void updateButtonStatus( bool isDirty );
     void showMessage( const QString &text, KMessageWidget::MessageType type );
 
@@ -162,6 +166,9 @@ IncidenceDialogPrivate::IncidenceDialogPrivate( Akonadi::IncidenceChanger *chang
   mIeRecurrence = new IncidenceRecurrence( mIeDateTime, mUi );
   mEditor->combine( mIeRecurrence );
 
+  mIeResource = new IncidenceResource( mUi );
+  mEditor->combine( mIeResource );
+
   IncidenceSecrecy *ieSecrecy = new IncidenceSecrecy( mUi );
   mEditor->combine( ieSecrecy );
 
@@ -187,6 +194,8 @@ IncidenceDialogPrivate::IncidenceDialogPrivate( Akonadi::IncidenceChanger *chang
               SLOT(updateAttachmentCount(int)) );
   q->connect( mIeAttendee, SIGNAL(attendeeCountChanged(int)),
               SLOT(updateAttendeeCount(int)) );
+  q->connect( mIeResource, SIGNAL(resourceCountChanged(int)),
+              SLOT(updateResourceCount(int)) );
 }
 
 IncidenceDialogPrivate::~IncidenceDialogPrivate()
@@ -415,6 +424,21 @@ void IncidenceDialogPrivate::updateAttendeeCount( int newCount )
   }
 }
 
+void IncidenceDialogPrivate::updateResourceCount( int newCount )
+{
+  if ( newCount > 0 ) {
+    mUi->mTabWidget->setTabText(
+      ResourcesTab,
+      i18nc( "@title:tab Tab to modify attendees of an event or todo",
+             "&Resources (%1)", newCount ) );
+  } else {
+    mUi->mTabWidget->setTabText(
+      ResourcesTab,
+      i18nc( "@title:tab Tab to modify attendees of an event or todo",
+             "&Resources" ) );
+  }
+}
+
 void IncidenceDialogPrivate::updateButtonStatus( bool isDirty )
 {
   Q_Q( IncidenceDialog );
@@ -518,6 +542,7 @@ void IncidenceDialogPrivate::load( const Akonadi::Item &item )
     mUi->mTabWidget->removeTab( RecurrenceTab );
     mUi->mTabWidget->removeTab( AlarmsTab );
     mUi->mTabWidget->removeTab( AttendeesTab );
+    mUi->mTabWidget->removeTab( ResourcesTab );
   }
 
   mEditor->load( CalendarSupport::incidence( item ) );
@@ -559,6 +584,7 @@ void IncidenceDialogPrivate::load( const Akonadi::Item &item )
 
   // Initialize tab's titles
   updateAttachmentCount( incidence->attachments().size() );
+  updateResourceCount( mIeResource->resourcesCount() );
   handleRecurrenceChange( mIeRecurrence->currentRecurrenceType() );
   handleAlarmCountChange( incidence->alarms().count() );
 
diff --git a/incidenceeditor-ng/incidencedialog.h b/incidenceeditor-ng/incidencedialog.h
index 7d7c36c..4d22699 100644
--- a/incidenceeditor-ng/incidencedialog.h
+++ b/incidenceeditor-ng/incidencedialog.h
@@ -108,6 +108,7 @@ class INCIDENCEEDITORS_NG_EXPORT IncidenceDialog : public KDialog
     Q_PRIVATE_SLOT( d_ptr, void storeTemplatesInConfig(QStringList) )
     Q_PRIVATE_SLOT( d_ptr, void updateAttachmentCount(int) )
     Q_PRIVATE_SLOT( d_ptr, void updateAttendeeCount(int) )
+    Q_PRIVATE_SLOT( d_ptr, void updateResourceCount(int) )
     Q_PRIVATE_SLOT( d_ptr, void updateButtonStatus(bool) )
     Q_PRIVATE_SLOT( d_ptr, void showMessage(QString,KMessageWidget::MessageType) )
 };
diff --git a/incidenceeditor-ng/incidenceresource.cpp b/incidenceeditor-ng/incidenceresource.cpp
new file mode 100644
index 0000000..5969c86
--- /dev/null
+++ b/incidenceeditor-ng/incidenceresource.cpp
@@ -0,0 +1,245 @@
+/*
+  Copyright (C) 2014 Sandro Knauß <knauss at kolabsys.com>
+
+  This library is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Library General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or (at your
+  option) any later version.
+
+  This library is distributed in the hope that it will be useful, but WITHOUT
+  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
+  License for more details.
+
+  You should have received a copy of the GNU Library General Public License
+  along with this library; see the file COPYING.LIB.  If not, write to the
+  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+  02110-1301, USA.
+*/
+
+#include "incidenceresource.h"
+#include "resourcemanagement.h"
+#include "resourcemodel.h"
+#include "attendeecomboboxdelegate.h"
+
+#ifdef KDEPIM_MOBILE_UI
+#include "ui_dialogmoremobile.h"
+#else
+#include "ui_dialogdesktop.h"
+#endif
+
+#include <KDebug>
+#include <KDescendantsProxyModel>
+#include <KMessageBox>
+
+#include <KCalUtils/Stringify>
+#include <KPIMUtils/Email>
+
+
+#include <QCompleter>
+using namespace IncidenceEditorNG;
+
+#ifdef KDEPIM_MOBILE_UI
+IncidenceResource::IncidenceResource(Ui::EventOrTodoMore *ui)
+#else
+IncidenceResource::IncidenceResource(Ui::EventOrTodoDesktop *ui)
+#endif
+    : IncidenceEditor(0)
+    , mUi(ui)
+{
+    setObjectName("IncidenceResource");
+
+    AttendeeComboBoxDelegate* roleDelegate(new AttendeeComboBoxDelegate(this));
+#ifdef KDEPIM_MOBILE_UI
+    roleDelegate->addItem(DesktopIcon("meeting-participant", 48),
+                          KCalUtils::Stringify::attendeeRole(KCalCore::Attendee::ReqParticipant));
+    roleDelegate->addItem(DesktopIcon("meeting-participant-optional", 48),
+                          KCalUtils::Stringify::attendeeRole(KCalCore::Attendee::OptParticipant));
+    roleDelegate->addItem(DesktopIcon("meeting-observer", 48),
+                          KCalUtils::Stringify::attendeeRole(KCalCore::Attendee::NonParticipant));
+    roleDelegate->addItem(DesktopIcon("meeting-chair", 48),
+                          KCalUtils::Stringify::attendeeRole(KCalCore::Attendee::Chair));
+
+#else
+    roleDelegate->addItem(SmallIcon("meeting-participant"),
+                          KCalUtils::Stringify::attendeeRole(KCalCore::Attendee::ReqParticipant));
+    roleDelegate->addItem(SmallIcon("meeting-participant-optional"),
+                          KCalUtils::Stringify::attendeeRole(KCalCore::Attendee::OptParticipant));
+    roleDelegate->addItem(SmallIcon("meeting-observer"),
+                          KCalUtils::Stringify::attendeeRole(KCalCore::Attendee::NonParticipant));
+    roleDelegate->addItem(SmallIcon("meeting-chair"),
+                          KCalUtils::Stringify::attendeeRole(KCalCore::Attendee::Chair));
+#endif
+
+    AttendeeComboBoxDelegate *stateDelegate(new AttendeeComboBoxDelegate(this));
+
+#ifdef KDEPIM_MOBILE_UI
+    stateDelegate->addItem(DesktopIcon("task-attention", 48),
+                           KCalUtils::Stringify::attendeeStatus(KCalCore::Attendee::NeedsAction));
+    stateDelegate->addItem(DesktopIcon("task-accepted", 48),
+                           KCalUtils::Stringify::attendeeStatus(KCalCore::Attendee::Accepted));
+    stateDelegate->addItem(DesktopIcon("task-reject", 48),
+                           KCalUtils::Stringify::attendeeStatus(KCalCore::Attendee::Declined));
+    stateDelegate->addItem(DesktopIcon("task-attempt", 48),
+                           KCalUtils::Stringify::attendeeStatus(KCalCore::Attendee::Tentative));
+    stateDelegate->addItem(DesktopIcon("task-delegate", 48),
+                           KCalUtils::Stringify::attendeeStatus(KCalCore::Attendee::Delegated));
+#else
+    stateDelegate->addItem(SmallIcon("task-attention"),
+                           KCalUtils::Stringify::attendeeStatus(KCalCore::Attendee::NeedsAction));
+    stateDelegate->addItem(SmallIcon("task-accepted"),
+                           KCalUtils::Stringify::attendeeStatus(KCalCore::Attendee::Accepted));
+    stateDelegate->addItem(SmallIcon("task-reject"),
+                           KCalUtils::Stringify::attendeeStatus(KCalCore::Attendee::Declined));
+    stateDelegate->addItem(SmallIcon("task-attempt"),
+                           KCalUtils::Stringify::attendeeStatus(KCalCore::Attendee::Tentative));
+    stateDelegate->addItem(SmallIcon("task-delegate"),
+                           KCalUtils::Stringify::attendeeStatus(KCalCore::Attendee::Delegated));
+#endif
+
+#ifndef KDEPIM_MOBILE_UI
+    QStringList attrs;
+    attrs << QLatin1String("cn");
+
+    completer = new QCompleter(this);
+    ResourceModel *model = new ResourceModel(attrs, this);
+
+    KDescendantsProxyModel *proxyModel = new KDescendantsProxyModel( this );
+    proxyModel->setSourceModel( model );
+
+    completer->setModel(proxyModel);
+    completer->setWrapAround(false);
+    mUi->mNewResource->setCompleter(completer);
+
+    KCalCore::Attendee::List resources;
+    AttendeeLineEditDelegate *attendeeDelegate = new AttendeeLineEditDelegate(this);
+
+    dataModel = new AttendeeTableModel(resources, this);
+    ResourceFilterProxyModel *filterProxyModel = new ResourceFilterProxyModel(this);
+    filterProxyModel->setDynamicSortFilter(true);
+    filterProxyModel->setSourceModel(dataModel);
+
+    mUi->mResourcesTable->setModel(filterProxyModel);
+    mUi->mResourcesTable->setColumnHidden(4, true);
+    mUi->mResourcesTable->setItemDelegateForColumn(0, roleDelegate);
+    mUi->mResourcesTable->setItemDelegateForColumn(1, attendeeDelegate);
+    mUi->mResourcesTable->setItemDelegateForColumn(3, stateDelegate);
+
+
+    AttendeeFilterProxyModel *attendeeProxyModel = new AttendeeFilterProxyModel(this);
+    attendeeProxyModel->setDynamicSortFilter(true);
+    attendeeProxyModel->setSourceModel(dataModel);
+    mUi->mAttendeeTable->setModel(attendeeProxyModel);
+    mUi->mAttendeeTable->setItemDelegateForColumn(0, roleDelegate);
+    mUi->mAttendeeTable->setItemDelegateForColumn(1, attendeeDelegate);
+    mUi->mAttendeeTable->setItemDelegateForColumn(3, stateDelegate);
+
+    connect(mUi->mFindResourcesButton, SIGNAL(clicked()), SLOT(findResources()));
+    connect(mUi->mBookResourceButton, SIGNAL(clicked()), SLOT(bookResource()));
+    connect(dataModel, SIGNAL(layoutChanged()), SLOT(layoutChanged()));
+    connect(dataModel, SIGNAL(rowsInserted(const QModelIndex&, int , int)), SLOT(layoutChanged()));
+    connect(dataModel, SIGNAL(rowsRemoved(const QModelIndex&, int , int)), SLOT(layoutChanged()));
+#endif
+}
+
+void IncidenceResource::load(const KCalCore::Incidence::Ptr &incidence)
+{
+    mLoadedIncidence = incidence;
+    dataModel->setAttendees(incidence->attendees());
+}
+
+void IncidenceResource::save(const KCalCore::Incidence::Ptr &incidence)
+{
+    incidence->clearAttendees();
+    KCalCore::Attendee::List attendees = dataModel->attendees();
+
+    foreach(KCalCore::Attendee::Ptr attendee, attendees) {
+        Q_ASSERT(attendee);
+
+        bool skip = false;
+        if (KPIMUtils::isValidAddress(attendee->email())) {
+            if (KMessageBox::warningYesNo(
+                        0,
+                        i18nc("@info",
+                              "%1 does not look like a valid email address. "
+                              "Are you sure you want to invite this participant?",
+                              attendee->email()),
+                        i18nc("@title:window", "Invalid Email Address")) != KMessageBox::Yes) {
+                skip = true;
+            }
+        }
+        if (!skip) {
+            incidence->addAttendee(attendee);
+        }
+    }
+
+    // Must not have an organizer for items without attendees
+    if (!incidence->attendeeCount()) {
+        return;
+    }
+}
+
+bool IncidenceResource::isDirty() const
+{
+    const KCalCore::Attendee::List originalList = mLoadedIncidence->attendees();
+    KCalCore::Attendee::List newList = dataModel->attendees();
+
+    // The lists sizes *must* be the same. When the organizer is attending the
+    // event as well, he should be in the attendees list as well.
+    if (originalList.size() != newList.size()) {
+        return true;
+    }
+
+    // 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) {
+        bool found = false;
+        for (int i = 0; i < newList.count(); ++i) {
+            if (newList[i] == attendee) {
+                newList.remove(i);
+                found = true;
+                break;
+            }
+        }
+
+        if (!found) {
+            // One of the attendees in the original list was not found in the new list.
+            return true;
+        }
+    }
+
+    return false;
+}
+
+void IncidenceResource::bookResource()
+{
+#ifndef KDEPIM_MOBILE_UI
+    QString name, email;
+
+    KPIMUtils::extractEmailAddressAndName(mUi->mNewResource->text(), email, name);
+    KCalCore::Attendee::Ptr attendee(new KCalCore::Attendee(name, email));
+    attendee->setCuType(KCalCore::Attendee::Resource);
+    dataModel->insertAttendee(dataModel->rowCount(), attendee);
+#endif
+}
+
+void IncidenceResource::findResources()
+{
+    ResourceManagement* dialog = new ResourceManagement();
+    dialog->show();
+}
+
+void IncidenceResource::layoutChanged()
+{
+    emit resourceCountChanged(resourcesCount());
+}
+
+int IncidenceResource::resourcesCount() const
+{
+#ifndef KDEPIM_MOBILE_UI
+    return mUi->mResourcesTable->model()->rowCount(QModelIndex());
+#endif
+    return 0;
+}
+
+#include "incidenceresource.moc"
diff --git a/incidenceeditor-ng/incidenceresource.h b/incidenceeditor-ng/incidenceresource.h
new file mode 100644
index 0000000..7208015
--- /dev/null
+++ b/incidenceeditor-ng/incidenceresource.h
@@ -0,0 +1,82 @@
+/*
+  Copyright (C) 2014 Sandro Knauß <knauss at kolabsys.com>
+
+  This library is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Library General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or (at your
+  option) any later version.
+
+  This library is distributed in the hope that it will be useful, but WITHOUT
+  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
+  License for more details.
+
+  You should have received a copy of the GNU Library General Public License
+  along with this library; see the file COPYING.LIB.  If not, write to the
+  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+  02110-1301, USA.
+*/
+
+#ifndef INCIDENCEEDITOR_INCIDENCERESOURCE_H
+#define INCIDENCEEDITOR_INCIDENCERESOURCE_H
+
+#include "incidenceeditor-ng.h"
+#include "attendeetablemodel.h"
+
+#include <QModelIndex>
+#include <QCompleter>
+
+namespace Ui
+{
+class EventOrTodoDesktop;
+class EventOrTodoMore;
+}
+
+namespace IncidenceEditorNG
+{
+
+class INCIDENCEEDITORS_NG_EXPORT IncidenceResource : public IncidenceEditor
+{
+    Q_OBJECT
+public:
+#ifdef KDEPIM_MOBILE_UI
+    explicit IncidenceResource(Ui::EventOrTodoMore *ui);
+#else
+    explicit IncidenceResource(Ui::EventOrTodoDesktop *ui);
+#endif
+
+    void load(const KCalCore::Incidence::Ptr &incidence);
+    void save(const KCalCore::Incidence::Ptr &incidence);
+    bool isDirty() const;
+
+    /** resturn the count of resources */
+    int resourcesCount() const;
+
+signals:
+    /** is emitted it the count of the resources is changed.
+     * @arg: new count of resources.
+     */
+    void resourceCountChanged(int);
+
+private slots:
+    void findResources();
+    void bookResource();
+    void layoutChanged();
+
+private:
+#ifdef KDEPIM_MOBILE_UI
+    Ui::EventOrTodoMore *mUi;
+#else
+    Ui::EventOrTodoDesktop *mUi;
+#endif
+
+    /** completer for findResources */
+    QCompleter *completer;
+
+    /** used dataModel to rely on*/
+    AttendeeTableModel *dataModel;
+};
+
+}
+
+#endif
\ No newline at end of file
diff --git a/incidenceeditor-ng/resourceitem.cpp b/incidenceeditor-ng/resourceitem.cpp
new file mode 100644
index 0000000..a57c826
--- /dev/null
+++ b/incidenceeditor-ng/resourceitem.cpp
@@ -0,0 +1,155 @@
+/*
+ * Copyright 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) version 3 or any later version
+ * accepted by the membership of KDE e.V. (or its successor approved
+ * by the membership of KDE e.V.), which shall act as a proxy
+ * defined in Section 14 of version 3 of the license.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+#include "resourceitem.h"
+
+#include <kldap/ldapserver.h>
+
+using namespace IncidenceEditorNG;
+
+ResourceItem::ResourceItem(const KLDAP::LdapDN &dn, QStringList attrs, const KLDAP::LdapClient &ldapClient, ResourceItem *parent)
+    : dn(dn)
+    , attrs(attrs)
+    , mLdapClient(0, this)
+{
+    parentItem = parent;
+
+
+    if (!dn.isEmpty()) {
+        KLDAP::LdapServer server = ldapClient.server();
+
+        server.setScope(KLDAP::LdapUrl::Base);
+        server.setBaseDn(dn);
+        mLdapClient.setServer(server);
+
+        connect(&mLdapClient, SIGNAL(result(KLDAP::LdapClient, KLDAP::LdapObject)),
+                SLOT(slotLDAPResult(KLDAP::LdapClient, KLDAP::LdapObject)));
+
+        attrs << QLatin1String("uniqueMember");
+        mLdapClient.setAttributes(attrs);
+    } else {
+        foreach(QString header, attrs) {
+            itemData << header;
+        }
+    }
+}
+
+ResourceItem::~ResourceItem()
+{
+    qDeleteAll(childItems);
+}
+
+
+ResourceItem *ResourceItem::child(int number)
+{
+    return childItems.value(number);
+}
+
+
+int ResourceItem::childCount() const
+{
+    return childItems.count();
+}
+
+int ResourceItem::childNumber() const
+{
+    if (parentItem) {
+        return parentItem->childItems.indexOf(const_cast<ResourceItem*>(this));
+    }
+
+    return 0;
+}
+
+int ResourceItem::columnCount() const
+{
+    return itemData.count();
+}
+
+QVariant ResourceItem::data(int column) const
+{
+    return itemData.value(column);
+}
+
+bool ResourceItem::insertChild(int position, ResourceItem *item)
+{
+    if (position < 0 || position > childItems.size()) {
+        return false;
+    }
+
+    childItems.insert(position, item);
+
+    return true;
+}
+
+ResourceItem *ResourceItem::parent()
+{
+    return parentItem;
+}
+
+bool ResourceItem::removeChildren(int position, int count)
+{
+    if (position < 0 || position + count > childItems.size()) {
+        return false;
+    }
+
+    for (int row = 0; row < count; ++row) {
+        delete childItems.takeAt(position);
+    }
+
+    return true;
+}
+
+const QStringList& ResourceItem::attributes() const
+{
+    return attrs;
+}
+
+const KLDAP::LdapObject& ResourceItem::ldapObject() const
+{
+    return mLdapObject;
+}
+
+void ResourceItem::startSearch()
+{
+    mLdapClient.startQuery("objectclass=*");
+}
+
+void ResourceItem::setLdapObject(const KLDAP::LdapObject& obj)
+{
+    slotLDAPResult(mLdapClient, obj);
+}
+
+const KLDAP::LdapClient& ResourceItem::ldapClient() const
+{
+    return mLdapClient;
+}
+
+void ResourceItem::slotLDAPResult(const KLDAP::LdapClient &/*client*/,
+                                  const KLDAP::LdapObject &obj)
+{
+    mLdapObject = obj;
+    foreach(QString header, attrs) {
+        if (obj.attributes()[header].count() > 0) {
+            itemData << QString::fromUtf8(obj.attributes()[header][0]);
+        } else {
+            itemData << "";
+        }
+    }
+}
\ No newline at end of file
diff --git a/incidenceeditor-ng/resourceitem.h b/incidenceeditor-ng/resourceitem.h
new file mode 100644
index 0000000..d0aea66
--- /dev/null
+++ b/incidenceeditor-ng/resourceitem.h
@@ -0,0 +1,119 @@
+/*
+ * Copyright 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) version 3 or any later version
+ * accepted by the membership of KDE e.V. (or its successor approved
+ * by the membership of KDE e.V.), which shall act as a proxy
+ * defined in Section 14 of version 3 of the license.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef RESOURCEITEM_H
+#define RESOURCEITEM_H
+
+#include <QObject>
+#include <QList>
+#include <QStringList>
+#include <QVariant>
+#include <QVector>
+
+#include <ldap/ldapclient.h>
+#include <kldap/ldapobject.h>
+
+namespace IncidenceEditorNG
+{
+
+class ResourceItem : public QObject
+{
+    Q_OBJECT
+public:
+    /* Copied from http://qt-project.org/doc/qt-4.8/itemviews-editabletreemodel.html:
+     * QT 4.8: Editable Tree Model Example
+     */
+    ResourceItem(const KLDAP::LdapDN &dn, QStringList attrs, const KLDAP::LdapClient &ldapClient, ResourceItem *parent = 0);
+    ~ResourceItem();
+
+    ResourceItem *child(int number);
+    int childCount() const;
+    int columnCount() const;
+    QVariant data(int column) const;
+    bool insertChild(int position, ResourceItem *item);
+    ResourceItem *parent();
+    bool removeChildren(int position, int count);
+    int childNumber() const;
+
+private:
+    QList<ResourceItem*> childItems;
+    QVector<QVariant> itemData;
+    ResourceItem *parentItem;
+
+public:
+    /* Returns the attributes of the requested ldapObject.
+     *
+     */
+    const QStringList &attributes() const;
+
+    /* Returns the ldapObject, that is used as data source.
+     *
+     */
+    const KLDAP::LdapObject& ldapObject() const;
+
+    /* Set the ldapObject, either directy via this function
+     * or use startSearch to request the ldapServer for the ldapObject
+     * with the dn specified via the constructor.
+     *
+     */
+    void setLdapObject(const KLDAP::LdapObject&);
+
+    /* The used ldapClient.
+     *
+     */
+    const KLDAP::LdapClient& ldapClient() const;
+
+    /* Start querying the ldapServer for a object that name is dn
+     *
+     */
+    void startSearch();
+
+private:
+    /* data source
+     *
+     */
+    KLDAP::LdapObject mLdapObject;
+
+    /* dn of the ldapObject
+     *
+     */
+    const KLDAP::LdapDN dn;
+
+    /* Attributes of the ldapObject to request and the header of the Item
+     *
+     */
+    QStringList attrs;
+
+    /* ldapClient to request
+     *
+     */
+    KLDAP::LdapClient mLdapClient;
+
+
+private slots:
+    /* Answer of the LdapServer for the given dn
+     *
+     */
+    void slotLDAPResult(const KLDAP::LdapClient&, const KLDAP::LdapObject&);
+
+};
+}
+#endif // RESOURCEITEM_H
diff --git a/incidenceeditor-ng/resourcemanagement.cpp b/incidenceeditor-ng/resourcemanagement.cpp
new file mode 100644
index 0000000..48a55d7
--- /dev/null
+++ b/incidenceeditor-ng/resourcemanagement.cpp
@@ -0,0 +1,87 @@
+/*
+ * Copyright 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) version 3 or any later version
+ * accepted by the membership of KDE e.V. (or its successor approved
+ * by the membership of KDE e.V.), which shall act as a proxy
+ * defined in Section 14 of version 3 of the license.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "resourcemanagement.h"
+#include "ui_resourcemanagement.h"
+#include "resourcemodel.h"
+
+#include <kldap/ldapobject.h>
+
+#include <QStringList>
+#include <QLabel>
+
+using namespace IncidenceEditorNG;
+
+ResourceManagement::ResourceManagement()
+{
+    ui = new Ui::ResourceManagement;
+    ui->setupUi(this);
+
+    QStringList attrs;
+    attrs << QLatin1String("cn") << QLatin1String("mail") << QLatin1String("givenname") << QLatin1String("sn");
+
+    ResourceModel *model = new ResourceModel(attrs);
+    ui->treeResults->setModel(model);
+
+    // This doesn't work till now :( -> that's why i use the clieck signal
+    ui->treeResults->setSelectionMode(QAbstractItemView::SingleSelection);
+    selectionModel = ui->treeResults->selectionModel();
+
+    connect(ui->resourceSearch, SIGNAL(textChanged(const QString&)),
+            SLOT(slotStartSearch(const QString&)));
+
+    connect(ui->treeResults, SIGNAL(clicked(const QModelIndex &)),
+            SLOT(slotShowDetails(const QModelIndex &)));
+
+}
+
+void ResourceManagement::slotStartSearch(const QString &text)
+{
+    ((ResourceModel*)ui->treeResults->model())->startSearch(text);
+}
+
+void ResourceManagement::slotShowDetails(const QModelIndex & current)
+{
+    ResourceItem *item = ((ResourceModel*)current.model())->getItem(current);
+    showDetails(item->ldapObject());
+}
+
+
+void ResourceManagement::showDetails(const KLDAP::LdapObject &obj)
+{
+    // Clean up formDetails
+    QLayoutItem *child;
+    while ((child = ui->formDetails->takeAt(0)) != 0) {
+        delete child->widget();
+        delete child;
+    }
+
+    // Fill formDetails with data
+    foreach(const QString & key, obj.attributes().keys()) {
+        QStringList list;
+        foreach(const QByteArray & value, obj.attributes().value(key)) {
+            list << QString::fromUtf8(value);
+        }
+        ui->formDetails->addRow(key, new QLabel(list.join("\n")));
+    }
+}
+
+#include "resourcemanagement.moc"
diff --git a/incidenceeditor-ng/resourcemanagement.h b/incidenceeditor-ng/resourcemanagement.h
new file mode 100644
index 0000000..3749db6
--- /dev/null
+++ b/incidenceeditor-ng/resourcemanagement.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright 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) version 3 or any later version
+ * accepted by the membership of KDE e.V. (or its successor approved
+ * by the membership of KDE e.V.), which shall act as a proxy
+ * defined in Section 14 of version 3 of the license.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef RESOURCEMANAGEMENT_H
+#define RESOURCEMANAGEMENT_H
+
+#include "incidenceeditors-ng_export.h"
+
+#include <ldap/ldapclient.h>
+#include <ldap/ldapclientsearch.h>
+
+#include <KDialog>
+
+#include <QStringList>
+#include <QStringListModel>
+
+namespace Ui
+{
+class ResourceManagement;
+}
+
+namespace IncidenceEditorNG
+{
+
+class QTreeModel;
+
+class INCIDENCEEDITORS_NG_EXPORT ResourceManagement : public KDialog
+{
+    Q_OBJECT
+public:
+    ResourceManagement();
+
+private:
+    /* Shows the details of a resource
+     *
+     */
+    void showDetails(const KLDAP::LdapObject&);
+
+    Ui::ResourceManagement* ui;
+
+    QItemSelectionModel *selectionModel;
+
+private slots:
+    /* A new searchString is entered
+     *
+     */
+    void slotStartSearch(const QString&);
+
+    /* A detail view is requested
+     *
+     */
+    void slotShowDetails(const QModelIndex & current);
+};
+
+}
+#endif // RESOURCEMANAGEMENT_H
diff --git a/incidenceeditor-ng/resourcemanagement.ui b/incidenceeditor-ng/resourcemanagement.ui
new file mode 100644
index 0000000..38002e1
--- /dev/null
+++ b/incidenceeditor-ng/resourcemanagement.ui
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>ResourceManagement</class>
+ <widget class="QWidget" name="resourceManagement">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>916</width>
+    <height>782</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Form</string>
+  </property>
+  <layout class="QHBoxLayout" name="horizontalLayout_2">
+   <property name="spacing">
+    <number>-1</number>
+   </property>
+   <item>
+    <layout class="QVBoxLayout" name="verticalLayout" stretch="0,0">
+     <property name="spacing">
+      <number>2</number>
+     </property>
+     <item>
+      <widget class="QLineEdit" name="resourceSearch"/>
+     </item>
+     <item>
+      <widget class="QTreeView" name="treeResults">
+       <property name="alternatingRowColors">
+        <bool>true</bool>
+       </property>
+       <property name="selectionBehavior">
+        <enum>QAbstractItemView::SelectRows</enum>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
+   <item>
+    <layout class="QVBoxLayout" name="verticalLayout_2">
+     <property name="spacing">
+      <number>2</number>
+     </property>
+     <item>
+      <widget class="QGroupBox" name="groupDetails">
+       <property name="enabled">
+        <bool>true</bool>
+       </property>
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="title">
+        <string>Details</string>
+       </property>
+       <layout class="QVBoxLayout" name="verticalLayout_4">
+        <property name="rightMargin">
+         <number>4</number>
+        </property>
+        <item>
+         <layout class="QFormLayout" name="formDetails"/>
+        </item>
+       </layout>
+      </widget>
+     </item>
+     <item>
+      <widget class="QWidget" name="resourceCalender" native="true">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/incidenceeditor-ng/resourcemodel.cpp b/incidenceeditor-ng/resourcemodel.cpp
new file mode 100644
index 0000000..829e0e0
--- /dev/null
+++ b/incidenceeditor-ng/resourcemodel.cpp
@@ -0,0 +1,231 @@
+/*
+ * Copyright 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) version 3 or any later version
+ * accepted by the membership of KDE e.V. (or its successor approved
+ * by the membership of KDE e.V.), which shall act as a proxy
+ * defined in Section 14 of version 3 of the license.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+#include "resourcemodel.h"
+
+
+using namespace IncidenceEditorNG;
+
+ResourceModel::ResourceModel(const QStringList &headers,
+                             QObject *parent)
+    : QAbstractItemModel(parent)
+    , foundCollection(false)
+{
+
+    this->headers = headers;
+    rootItem = new ResourceItem(KLDAP::LdapDN(), headers, KLDAP::LdapClient(0), 0);
+
+    ldapSearchCollections.setFilter(QString::fromLatin1("&(objectClass=kolabGroupOfUniqueNames)(mail=*)"
+                                    "(|(cn=%1)(givenName=%1)(sn=%1))"));
+    ldapSearch.setFilter(QString::fromLatin1("&(objectClass=kolabSharedFolder)(kolabFolderType=event)(mail=*)"
+                         "(|(cn=%1)(givenName=%1)(sn=%1))"));
+
+    QStringList attrs = ldapSearchCollections.attributes();
+    attrs << QLatin1String("uniqueMember");
+    ldapSearchCollections.setAttributes(attrs);
+
+    connect(&ldapSearchCollections, SIGNAL(searchData(const QList<KLDAP::LdapResultObject> &)),
+            SLOT(slotLDAPCollectionData(const QList<KLDAP::LdapResultObject> &)));
+    connect(&ldapSearch, SIGNAL(searchData(const QList<KLDAP::LdapResultObject> &)),
+            SLOT(slotLDAPSearchData(const QList<KLDAP::LdapResultObject> &)));
+
+    ldapSearchCollections.startSearch("*");
+}
+
+ResourceModel::~ResourceModel()
+{
+    delete rootItem;
+}
+
+int ResourceModel::columnCount(const QModelIndex & /* parent */) const
+{
+    return 1;
+}
+
+QVariant ResourceModel::data(const QModelIndex &index, int role) const
+{
+    if (!index.isValid()) {
+        return QVariant();
+    }
+
+    if (role != Qt::DisplayRole && role != Qt::EditRole) {
+        return QVariant();
+    }
+
+    ResourceItem *item = getItem(index);
+
+    return item->data(index.column());
+}
+
+Qt::ItemFlags ResourceModel::flags(const QModelIndex &index) const
+{
+    if (!index.isValid()) {
+        return 0;
+    }
+
+    return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
+}
+
+ResourceItem *ResourceModel::getItem(const QModelIndex &index) const
+{
+    if (index.isValid()) {
+        ResourceItem *item = static_cast<ResourceItem*>(index.internalPointer());
+        if (item) {
+            return item;
+        }
+    }
+    return rootItem;
+}
+
+QVariant ResourceModel::headerData(int section, Qt::Orientation orientation,
+                                   int role) const
+{
+    if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
+        return rootItem->data(section);
+    }
+
+    return QVariant();
+}
+
+QModelIndex ResourceModel::index(int row, int column, const QModelIndex &parent) const
+{
+    if (parent.isValid() && parent.column() != 0) {
+        return QModelIndex();
+    }
+    ResourceItem *parentItem = getItem(parent);
+
+    ResourceItem *childItem = parentItem->child(row);
+    if (childItem) {
+        return createIndex(row, column, childItem);
+    } else {
+        return QModelIndex();
+    }
+}
+
+
+QModelIndex ResourceModel::parent(const QModelIndex &index) const
+{
+    if (!index.isValid()) {
+        return QModelIndex();
+    }
+    ResourceItem *childItem = getItem(index);
+    ResourceItem *parentItem = childItem->parent();
+
+    if (parentItem == rootItem) {
+        return QModelIndex();
+    }
+
+    return createIndex(parentItem->childNumber(), 0, parentItem);
+}
+
+
+bool ResourceModel::removeRows(int position, int rows, const QModelIndex &parent)
+{
+    ResourceItem *parentItem = getItem(parent);
+    bool success = true;
+
+    beginRemoveRows(parent, position, position + rows - 1);
+    success = parentItem->removeChildren(position, rows);
+    endRemoveRows();
+
+    return success;
+}
+
+int ResourceModel::rowCount(const QModelIndex &parent) const
+{
+    ResourceItem *parentItem = getItem(parent);
+
+    return parentItem->childCount();
+}
+
+void ResourceModel::startSearch(const QString &query)
+{
+    searchString = query;
+
+    if (foundCollection) {
+        startSearch();
+    }
+}
+
+void ResourceModel::startSearch()
+{
+    emit layoutAboutToBeChanged();
+    // Delete all resources -> only collection elements are shown
+    for (int i = 0; i < rootItem->childCount(); i++) {
+        if (ldapCollections.contains(rootItem->child(i))) {
+            rootItem->child(i)->removeChildren(0, rootItem->child(i)->childCount());
+        } else {
+            rootItem->removeChildren(i, 1);
+        }
+    }
+    emit layoutChanged();
+
+    if (searchString.count() > 0) {
+        ldapSearch.startSearch("*" + searchString + "*");
+    } else {
+        ldapSearch.startSearch("*");
+    }
+}
+
+void ResourceModel::slotLDAPCollectionData(const QList<KLDAP::LdapResultObject> &results)
+{
+    foundCollection = true;
+    ldapCollectionsMap.clear();
+    ldapCollections.clear();
+
+    emit layoutAboutToBeChanged();
+
+    foreach(const KLDAP::LdapResultObject & result, results) {
+        ResourceItem *item = new ResourceItem(result.object.dn(), headers, *result.client, rootItem);
+        item->setLdapObject(result.object);
+        rootItem->insertChild(rootItem->childCount(), item);
+        ldapCollections.insert(item);
+
+        // Resources in a collection add this link into ldapCollectionsMap
+        foreach(const QByteArray & member, result.object.attributes()["uniqueMember"]) {
+            ldapCollectionsMap.insert(QString::fromLatin1(member), item);
+        }
+    }
+
+    emit layoutChanged();
+
+    startSearch();
+}
+
+void ResourceModel::slotLDAPSearchData(const QList<KLDAP::LdapResultObject> &results)
+{
+    emit layoutAboutToBeChanged();
+
+    foreach(const KLDAP::LdapResultObject & result, results) {
+        //Add the found items to all collections, where it is member
+        QList<ResourceItem*> parents = ldapCollectionsMap.values(result.object.dn().toString());
+        if (parents.count() == 0) {
+            parents << rootItem;
+        }
+
+        foreach(ResourceItem * parent, parents) {
+            ResourceItem *item = new ResourceItem(result.object.dn(), headers, *result.client, parent);
+            item->setLdapObject(result.object);
+            parent->insertChild(parent->childCount(), item);
+        }
+    }
+
+    emit layoutChanged();
+}
diff --git a/incidenceeditor-ng/resourcemodel.h b/incidenceeditor-ng/resourcemodel.h
new file mode 100644
index 0000000..4eb8a33
--- /dev/null
+++ b/incidenceeditor-ng/resourcemodel.h
@@ -0,0 +1,133 @@
+/*
+ * Copyright 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) version 3 or any later version
+ * accepted by the membership of KDE e.V. (or its successor approved
+ * by the membership of KDE e.V.), which shall act as a proxy
+ * defined in Section 14 of version 3 of the license.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef RESOURCEMODEL_H
+#define RESOURCEMODEL_H
+
+#include "resourceitem.h"
+
+#include <libkdepim/ldap/ldapclientsearch.h>
+
+#include <QAbstractItemModel>
+#include <QModelIndex>
+#include <QSet>
+
+namespace IncidenceEditorNG
+{
+
+class ResourceModel : public QAbstractItemModel
+{
+    Q_OBJECT
+
+public:
+    /* Copied from http://qt-project.org/doc/qt-4.8/itemviews-editabletreemodel.html:
+     * QT 4.8: Editable Tree Model Example
+     */
+    ResourceModel(const QStringList &headers,
+                  QObject *parent = 0);
+    ~ResourceModel();
+
+    QVariant data(const QModelIndex &index, int role) const;
+    QVariant headerData(int section, Qt::Orientation orientation,
+                        int role = Qt::DisplayRole) const;
+
+    QModelIndex index(int row, int column,
+                      const QModelIndex &parent = QModelIndex()) const;
+    QModelIndex parent(const QModelIndex &index) const;
+
+    int rowCount(const QModelIndex &parent = QModelIndex()) const;
+    int columnCount(const QModelIndex &parent = QModelIndex()) const;
+
+    Qt::ItemFlags flags(const QModelIndex &index) const;
+
+    bool removeRows(int position, int rows,
+                    const QModelIndex &parent = QModelIndex());
+
+    ResourceItem *getItem(const QModelIndex &index) const;
+
+private:
+    ResourceItem *rootItem;
+
+
+public:
+
+    /* Start search on LDAP Server with the given string.
+     * If the model is not ready to search, the string is cached and is executed afterwards.
+     */
+    void startSearch(const QString&);
+private:
+
+    /* Start search with cached string (stored in searchString)
+     *
+     */
+    void startSearch();
+
+    /* Search for collections of resources
+     *
+     */
+    KLDAP::LdapClientSearch ldapSearchCollections;
+
+    /* Search for matching resources
+     *
+     */
+    KLDAP::LdapClientSearch ldapSearch;
+
+    /* Map from dn of resource -> collectionItem
+     * A Resource can be part of different collection, so a QMuliMap is needed
+     *
+     */
+    QMultiMap<QString, ResourceItem*> ldapCollectionsMap;
+
+    /* A Set of all collection ResourceItems
+     *
+     */
+    QSet <ResourceItem*> ldapCollections;
+
+    /* Cached searchString (setted by startSearch(QString))
+     *
+     */
+    QString searchString;
+
+    /* Is the search of collections ended
+     *
+     */
+    bool foundCollection;
+
+    /* List of all attributes in LDAP an the headers of the model
+     *
+     */
+    QStringList headers;
+
+
+private slots:
+    /* Slot for founded collections
+     *
+     */
+    void slotLDAPCollectionData(const QList<KLDAP::LdapResultObject> &);
+
+    /* Slot for matching resources
+     *
+     */
+    void slotLDAPSearchData(const QList<KLDAP::LdapResultObject> &);
+};
+
+}
+#endif // RESOURCEMODEL_H
diff --git a/incidenceeditor-ng/tests/CMakeLists.txt b/incidenceeditor-ng/tests/CMakeLists.txt
index 5b0c4cd..e248660 100644
--- a/incidenceeditor-ng/tests/CMakeLists.txt
+++ b/incidenceeditor-ng/tests/CMakeLists.txt
@@ -48,4 +48,16 @@ target_link_libraries(testindividualmaildialog
   ${QT_QTGUI_LIBRARY}
   ${KDE4_KDECORE_LIBS}
   ${KDE4_KDEUI_LIBS}
- )
\ No newline at end of file
+ )
+
+set(resourcemanagement_gui_SRCS resourcemanagment_gui.cpp)
+kde4_add_executable(resourcemanagement_gui TEST ${resourcemanagement_gui_SRCS})
+target_link_libraries(resourcemanagement_gui
+  ${QT_QTCORE_LIBRARY}
+  ${QT_QTGUI_LIBRARY}
+  ${QT_QTWEBKIT_LIBRARY}
+  ${KDE4_KDECORE_LIBS}
+  ${KDE4_KDEUI_LIBS}
+  ${KDEPIMLIBS_KMIME_LIBS}
+  incidenceeditorsng
+)
diff --git a/incidenceeditor-ng/tests/resourcemanagment_gui.cpp b/incidenceeditor-ng/tests/resourcemanagment_gui.cpp
new file mode 100644
index 0000000..a991ed8
--- /dev/null
+++ b/incidenceeditor-ng/tests/resourcemanagment_gui.cpp
@@ -0,0 +1,43 @@
+/* Copyright 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) version 3 or any later version
+   accepted by the membership of KDE e.V. (or its successor approved
+   by the membership of KDE e.V.), which shall act as a proxy
+   defined in Section 14 of version 3 of the license.
+
+   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, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <QFile>
+#include "resourcemanagement.h"
+
+#include <kdebug.h>
+#include <kcmdlineargs.h>
+#include <kapplication.h>
+
+using namespace IncidenceEditorNG;
+
+int main (int argc, char **argv)
+{
+  KCmdLineArgs::init(argc, argv, "resourcemanagement_gui", 0, ki18n("resourcemanagement_Gui"),
+                     "1.0", ki18n("Test for resourceManagement"));
+
+  KCmdLineArgs::addStdCmdLineOptions();
+
+  KApplication app;
+
+  ResourceManagement* dialog = new ResourceManagement();
+
+  dialog->show();
+
+  return app.exec();
+}





More information about the commits mailing list