Branch 'kolab/integration/4.13.0' - 32 commits - calendarviews/todo incidenceeditor-ng/CMakeLists.txt incidenceeditor-ng/editoritemmanager.cpp incidenceeditor-ng/incidencedialog.cpp incidenceeditor-ng/individualmailcomponentfactory.cpp incidenceeditor-ng/individualmailcomponentfactory.h incidenceeditor-ng/individualmaildialog.cpp incidenceeditor-ng/individualmaildialog.h incidenceeditor-ng/Messages.sh incidenceeditor-ng/opencomposerjob.cpp incidenceeditor-ng/opencomposerjob.h incidenceeditor-ng/tests kmail/kmail_part.rc kmail/kmkernel.cpp kmail/kmkernel.h kmail/kmmainwidget.cpp kmail/kmmainwin.rc kmail/kmreadermainwin.cpp kmail/kmreadermainwin.rc kmail/kmreaderwin.cpp kmail/kmreaderwin.h korganizer/calendarview.cpp korganizer/CMakeLists.txt korganizer/koeventpopupmenu.cpp korganizer/koeventpopupmenu.h korganizer/noteeditdialog.cpp korganizer/noteeditdialog.h korganizer/tests korganizer/views libkdepim/addressline libkdepim/ldap messageviewer/CMakeLists.txt messageviewer/job messageviewer/settings messageviewer/tests messageviewer/viewer messageviewer/widgets

Sandro Knauß knauss at kolabsys.com
Mon Aug 11 13:51:48 CEST 2014


 calendarviews/todo/todoview.cpp                       |   39 +
 calendarviews/todo/todoview.h                         |    6 
 incidenceeditor-ng/CMakeLists.txt                     |    9 
 incidenceeditor-ng/Messages.sh                        |    2 
 incidenceeditor-ng/editoritemmanager.cpp              |    3 
 incidenceeditor-ng/incidencedialog.cpp                |    3 
 incidenceeditor-ng/individualmailcomponentfactory.cpp |  254 ++++++++++
 incidenceeditor-ng/individualmailcomponentfactory.h   |  117 ++++
 incidenceeditor-ng/individualmaildialog.cpp           |   93 +++
 incidenceeditor-ng/individualmaildialog.h             |   57 ++
 incidenceeditor-ng/opencomposerjob.cpp                |  150 ++++++
 incidenceeditor-ng/opencomposerjob.h                  |   57 ++
 incidenceeditor-ng/tests/CMakeLists.txt               |    9 
 incidenceeditor-ng/tests/testindividualmaildialog.cpp |   51 ++
 kmail/kmail_part.rc                                   |    6 
 kmail/kmkernel.cpp                                    |   34 +
 kmail/kmkernel.h                                      |   45 +
 kmail/kmmainwidget.cpp                                |    2 
 kmail/kmmainwin.rc                                    |    6 
 kmail/kmreadermainwin.cpp                             |    2 
 kmail/kmreadermainwin.rc                              |    2 
 kmail/kmreaderwin.cpp                                 |    9 
 kmail/kmreaderwin.h                                   |    2 
 korganizer/CMakeLists.txt                             |    2 
 korganizer/calendarview.cpp                           |    3 
 korganizer/koeventpopupmenu.cpp                       |  147 ++++++
 korganizer/koeventpopupmenu.h                         |    9 
 korganizer/noteeditdialog.cpp                         |  172 +++++++
 korganizer/noteeditdialog.h                           |   69 ++
 korganizer/tests/CMakeLists.txt                       |   32 +
 korganizer/tests/koeventpopupmenutest.cpp             |  274 +++++++++++
 korganizer/tests/koeventpopupmenutest.h               |   46 +
 korganizer/tests/noteeditdialogtest.cpp               |  351 ++++++++++++++
 korganizer/tests/noteeditdialogtest.h                 |   52 ++
 korganizer/views/todoview/kotodoview.cpp              |    7 
 libkdepim/addressline/addresseelineedit.cpp           |   16 
 libkdepim/ldap/ldapclientsearch.cpp                   |   74 +--
 libkdepim/ldap/ldapclientsearch.h                     |   49 ++
 messageviewer/CMakeLists.txt                          |    7 
 messageviewer/job/createeventjob.cpp                  |  103 ++++
 messageviewer/job/createeventjob.h                    |   48 ++
 messageviewer/job/createnotejob.cpp                   |  109 ++++
 messageviewer/job/createnotejob.h                     |   52 ++
 messageviewer/settings/messageviewer.kcfg.cmake       |   12 
 messageviewer/tests/CMakeLists.txt                    |    3 
 messageviewer/tests/eventedittest.cpp                 |  352 ++++++++++++++
 messageviewer/tests/eventedittest.h                   |   50 ++
 messageviewer/tests/noteedittest.cpp                  |  430 ++++++++++++++++++
 messageviewer/tests/noteedittest.h                    |   63 ++
 messageviewer/tests/todoedittest.cpp                  |  122 ++++-
 messageviewer/tests/todoedittest.h                    |    6 
 messageviewer/tests/viewertest.cpp                    |   21 
 messageviewer/tests/viewertest.h                      |    1 
 messageviewer/viewer/viewer.cpp                       |   12 
 messageviewer/viewer/viewer.h                         |    2 
 messageviewer/viewer/viewer_p.cpp                     |   62 ++
 messageviewer/viewer/viewer_p.h                       |   14 
 messageviewer/widgets/eventedit.cpp                   |  332 +++++++++++++
 messageviewer/widgets/eventedit.h                     |   83 +++
 messageviewer/widgets/noteedit.cpp                    |  246 ++++++++++
 messageviewer/widgets/noteedit.h                      |   77 +++
 messageviewer/widgets/todoedit.cpp                    |  124 ++++-
 messageviewer/widgets/todoedit.h                      |    9 
 63 files changed, 4532 insertions(+), 69 deletions(-)

New commits:
commit b4338c3d6decff31c6f0bed3d66d39ea1fffad71
Author: Sandro Knauß <knauss at kolabsys.com>
Date:   Sat Aug 2 17:30:10 2014 +0200

    Add "create Todo/Note" to TodoView

diff --git a/calendarviews/todo/todoview.cpp b/calendarviews/todo/todoview.cpp
index 3f49d06..7f4b9bf 100644
--- a/calendarviews/todo/todoview.cpp
+++ b/calendarviews/todo/todoview.cpp
@@ -396,6 +396,22 @@ TodoView::TodoView( const EventViews::PrefsPtr &prefs,
 
   mItemPopupMenu->addSeparator();
 
+  a = mItemPopupMenu->addAction( KIconLoader::global()->loadIcon( QLatin1String("appointment-new"), KIconLoader::NoGroup, KIconLoader::SizeSmall ),
+                      i18n( "Create Event" ),
+                      this, SLOT(createEvent()) );
+  a->setObjectName(QLatin1String("createevent"));
+  mItemPopupMenuReadWriteEntries << a;
+  mItemPopupMenuItemOnlyEntries << a;
+
+  a = mItemPopupMenu->addAction( KIconLoader::global()->loadIcon( QLatin1String("view-pim-notes"), KIconLoader::NoGroup, KIconLoader::SizeSmall ),
+                      i18n( "Create Note" ),
+                      this, SLOT(createNote()) );
+  a->setObjectName(QLatin1String("createnote"));
+  mItemPopupMenuReadWriteEntries << a;
+  mItemPopupMenuItemOnlyEntries << a;
+
+  mItemPopupMenu->addSeparator();
+
   mCopyPopupMenu =
     new KPIM::KDatePickerPopup( KPIM::KDatePickerPopup::NoDate |
                                 KPIM::KDatePickerPopup::DatePicker |
@@ -1247,3 +1263,26 @@ void TodoView::resizeEvent( QResizeEvent *event )
   scheduleResizeColumns();
 }
 
+void TodoView::createEvent()
+{
+    QModelIndexList selection = mView->selectionModel()->selectedRows();
+    if ( selection.size() != 1 ) {
+        return;
+    }
+
+    const Akonadi::Item todoItem = selection[0].data ( TodoModel::TodoRole ).value<Akonadi::Item>();
+
+    emit createEvent( todoItem );
+}
+
+void TodoView::createNote()
+{
+    QModelIndexList selection = mView->selectionModel()->selectedRows();
+    if ( selection.size() != 1 ) {
+        return;
+    }
+
+    const Akonadi::Item todoItem = selection[0].data ( TodoModel::TodoRole ).value<Akonadi::Item>();
+
+    emit createNote( todoItem );
+}
diff --git a/calendarviews/todo/todoview.h b/calendarviews/todo/todoview.h
index dec962b..7fc5dbd 100644
--- a/calendarviews/todo/todoview.h
+++ b/calendarviews/todo/todoview.h
@@ -100,6 +100,9 @@ class EVENTVIEWS_EXPORT TodoView : public EventViews::EventView
     void restoreViewState();
     void saveViewState();
 
+    void createNote();
+    void createEvent();
+
   protected Q_SLOTS:
     void resizeEvent( QResizeEvent * ) /*Q_DECL_OVERRIDE*/;
     void addQuickTodo( Qt::KeyboardModifiers modifier );
@@ -141,6 +144,9 @@ class EVENTVIEWS_EXPORT TodoView : public EventViews::EventView
     void printPreviewTodo();
     void printTodo();
 
+    void createNote(const Akonadi::Item &item);
+    void createEvent(const Akonadi::Item &item);
+
   private:
     QMenu *createCategoryPopupMenu();
     QString stateSaverGroup() const;
diff --git a/korganizer/koeventpopupmenu.cpp b/korganizer/koeventpopupmenu.cpp
index 1e62f57..6e3a632 100644
--- a/korganizer/koeventpopupmenu.cpp
+++ b/korganizer/koeventpopupmenu.cpp
@@ -269,6 +269,13 @@ void KOEventPopupMenu::forward()
   }
 }
 
+void KOEventPopupMenu::createEvent(const Akonadi::Item &item)
+{
+    mCurrentIncidence = item;
+    createEvent();
+}
+
+
 void KOEventPopupMenu::createEvent()
 {
     // Must be a Incidence
@@ -298,6 +305,12 @@ void KOEventPopupMenu::createEvent()
     }
 }
 
+void KOEventPopupMenu::createNote(const Akonadi::Item &item)
+{
+    mCurrentIncidence = item;
+    createNote();
+}
+
 void KOEventPopupMenu::createNote()
 {
     // Must be a Incidence
diff --git a/korganizer/koeventpopupmenu.h b/korganizer/koeventpopupmenu.h
index 5d16ccc..83a0045 100644
--- a/korganizer/koeventpopupmenu.h
+++ b/korganizer/koeventpopupmenu.h
@@ -44,6 +44,8 @@ class KOEventPopupMenu : public QMenu
 
   public slots:
     void showIncidencePopup( const Akonadi::Item &, const QDate & );
+    void createEvent( const Akonadi::Item &item );
+    void createNote( const Akonadi::Item &item );
 
   protected slots:
     void popupShow();
diff --git a/korganizer/views/todoview/kotodoview.cpp b/korganizer/views/todoview/kotodoview.cpp
index c94af2a..f202d46 100644
--- a/korganizer/views/todoview/kotodoview.cpp
+++ b/korganizer/views/todoview/kotodoview.cpp
@@ -27,6 +27,7 @@
 
 #include "kotodoview.h"
 #include "koprefs.h"
+#include "koeventpopupmenu.h"
 
 #include <calendarsupport/printing/calprinter.h>
 
@@ -39,6 +40,7 @@
 KOTodoView::KOTodoView( bool sidebarView, QWidget *parent )
   : BaseView( parent )
 {
+  KOEventPopupMenu *eventPopup = new KOEventPopupMenu( calendar().data(), this );
   mView = new EventViews::TodoView( KOPrefs::instance()->eventViewsPreferences(),
                                     sidebarView, parent );
   QVBoxLayout *layout = new QVBoxLayout( this );
@@ -103,6 +105,11 @@ KOTodoView::KOTodoView( bool sidebarView, QWidget *parent )
 
   connect( mView, SIGNAL(fullViewChanged(bool)),
            SIGNAL(fullViewChanged(bool)) );
+
+  connect( mView, SIGNAL(createEvent(Akonadi::Item)),
+          eventPopup, SLOT(createEvent(Akonadi::Item)));
+  connect( mView, SIGNAL(createNote(Akonadi::Item)),
+          eventPopup, SLOT(createNote(Akonadi::Item)));
 }
 
 KOTodoView::~KOTodoView()


commit 69f8b45d939c16655eefd141a4ac8b1300e2bd0e
Author: Sandro Knauß <knauss at kolabsys.com>
Date:   Sat Aug 2 14:43:58 2014 +0200

    rename note->event in eventwidget

diff --git a/messageviewer/job/createeventjob.cpp b/messageviewer/job/createeventjob.cpp
index 571b5c0..465af51 100644
--- a/messageviewer/job/createeventjob.cpp
+++ b/messageviewer/job/createeventjob.cpp
@@ -53,7 +53,7 @@ void CreateEventJob::start()
                 mItem = job->items().first();
             }
         } else {
-            qDebug()<<" createTodo Error during fetch: "<<job->errorString();
+            qDebug()<<" createEvent: Error during fetch: "<<job->errorString();
         }
     } else {
         createEvent();
@@ -97,7 +97,7 @@ void CreateEventJob::createEvent()
 void CreateEventJob::slotCreateNewEvent(KJob *job)
 {
     if ( job->error() ) {
-        qDebug() << "Error during create new Todo "<<job->errorString();
+        qDebug() << "Error during create new Event "<<job->errorString();
     }
     Q_EMIT emitResult();
 }
diff --git a/messageviewer/tests/eventedittest.cpp b/messageviewer/tests/eventedittest.cpp
index 32c9b7b..f743d6c 100644
--- a/messageviewer/tests/eventedittest.cpp
+++ b/messageviewer/tests/eventedittest.cpp
@@ -72,9 +72,9 @@ void EventEditTest::shouldHaveDefaultValuesOnCreation()
     MessageViewer::EventEdit edit;
     QVERIFY(edit.collection().isValid());
     QVERIFY(!edit.message());
-    QLineEdit *noteedit = qFindChild<QLineEdit *>(&edit, QLatin1String("noteedit"));
-    QVERIFY(noteedit);
-    QCOMPARE(noteedit->text(), QString());
+    QLineEdit *eventedit = qFindChild<QLineEdit *>(&edit, QLatin1String("eventedit"));
+    QVERIFY(eventedit);
+    QCOMPARE(eventedit->text(), QString());
 
     KPushButton *openEditor = qFindChild<KPushButton *>(&edit, QLatin1String("open-editor-button"));
     KPushButton *save = qFindChild<KPushButton *>(&edit, QLatin1String("save-button"));
@@ -142,9 +142,9 @@ void EventEditTest::shouldEmitEventWhenPressEnter()
     QString subject = QLatin1String("Test Note");
     msg->subject(true)->fromUnicodeString(subject, "us-ascii");
     edit.setMessage(msg);
-    QLineEdit *noteedit = qFindChild<QLineEdit *>(&edit, QLatin1String("noteedit"));
+    QLineEdit *eventedit = qFindChild<QLineEdit *>(&edit, QLatin1String("eventedit"));
     QSignalSpy spy(&edit, SIGNAL(createEvent(KCalCore::Event::Ptr,Akonadi::Collection)));
-    QTest::keyClick(noteedit, Qt::Key_Enter);
+    QTest::keyClick(eventedit, Qt::Key_Enter);
     QCOMPARE(spy.count(), 1);
 }
 
@@ -159,8 +159,8 @@ void EventEditTest::shouldHideWidgetWhenPressEnter()
     QString subject = QLatin1String("Test Note");
     msg->subject(true)->fromUnicodeString(subject, "us-ascii");
     edit.setMessage(msg);
-    QLineEdit *noteedit = qFindChild<QLineEdit *>(&edit, QLatin1String("noteedit"));
-    QTest::keyClick(noteedit, Qt::Key_Enter);
+    QLineEdit *eventedit = qFindChild<QLineEdit *>(&edit, QLatin1String("eventedit"));
+    QTest::keyClick(eventedit, Qt::Key_Enter);
     QCOMPARE(edit.isVisible(), false);
 }
 
@@ -169,9 +169,9 @@ void EventEditTest::shouldHideWidgetWhenPressEscape()
     MessageViewer::EventEdit edit;
     edit.show();
     QTest::qWaitForWindowShown(&edit);
-    QLineEdit *noteedit = qFindChild<QLineEdit *>(&edit, QLatin1String("noteedit"));
-    noteedit->setFocus();
-    QVERIFY(noteedit->hasFocus());
+    QLineEdit *eventedit = qFindChild<QLineEdit *>(&edit, QLatin1String("eventedit"));
+    eventedit->setFocus();
+    QVERIFY(eventedit->hasFocus());
     QTest::keyPress(&edit, Qt::Key_Escape);
     QCOMPARE(edit.isVisible(), false);
 }
@@ -237,9 +237,9 @@ void EventEditTest::shouldNotEmitCreateEventWhenDateIsInvalid()
     QString subject = QLatin1String("Test Note");
     msg->subject(true)->fromUnicodeString(subject, "us-ascii");
     edit.setMessage(msg);
-    QLineEdit *noteedit = qFindChild<QLineEdit *>(&edit, QLatin1String("noteedit"));
+    QLineEdit *eventedit = qFindChild<QLineEdit *>(&edit, QLatin1String("eventedit"));
     QSignalSpy spy(&edit, SIGNAL(createEvent(KCalCore::Event::Ptr,Akonadi::Collection)));
-    QTest::keyClick(noteedit, Qt::Key_Enter);
+    QTest::keyClick(eventedit, Qt::Key_Enter);
     QCOMPARE(spy.count(), 0);
 }
 
@@ -250,9 +250,9 @@ void EventEditTest::shouldEventHasCorrectSubject()
     QString subject = QLatin1String("Test Note");
     msg->subject(true)->fromUnicodeString(subject, "us-ascii");
     edit.setMessage(msg);
-    QLineEdit *noteedit = qFindChild<QLineEdit *>(&edit, QLatin1String("noteedit"));
+    QLineEdit *eventedit = qFindChild<QLineEdit *>(&edit, QLatin1String("eventedit"));
     QSignalSpy spy(&edit, SIGNAL(createEvent(KCalCore::Event::Ptr,Akonadi::Collection)));
-    QTest::keyClick(noteedit, Qt::Key_Enter);
+    QTest::keyClick(eventedit, Qt::Key_Enter);
     QCOMPARE(spy.count(), 1);
     KCalCore::Event::Ptr eventPtr = spy.at(0).at(0).value<KCalCore::Event::Ptr>();
     QVERIFY(eventPtr);
@@ -266,9 +266,9 @@ void EventEditTest::shouldSelectLineWhenPutMessage()
     QString subject = QLatin1String("Test Note");
     msg->subject(true)->fromUnicodeString(subject, "us-ascii");
     edit.setMessage(msg);
-    QLineEdit *noteedit = qFindChild<QLineEdit *>(&edit, QLatin1String("noteedit"));
-    QVERIFY(noteedit->hasSelectedText());
-    const QString selectedText = noteedit->selectedText();
+    QLineEdit *eventedit = qFindChild<QLineEdit *>(&edit, QLatin1String("eventedit"));
+    QVERIFY(eventedit->hasSelectedText());
+    const QString selectedText = eventedit->selectedText();
     QCOMPARE(selectedText, QString::fromLatin1("Reply to \"%1\"").arg(subject));
 }
 
@@ -288,9 +288,9 @@ void EventEditTest::shouldHaveCorrectStartEndDateTime()
     KDateTimeEdit *endDateTime = qFindChild<KDateTimeEdit *>(&edit, QLatin1String("enddatetimeedit"));
     endDateTime->setDateTime(endDt);
 
-    QLineEdit *noteedit = qFindChild<QLineEdit *>(&edit, QLatin1String("noteedit"));
+    QLineEdit *eventedit = qFindChild<QLineEdit *>(&edit, QLatin1String("eventedit"));
     QSignalSpy spy(&edit, SIGNAL(createEvent(KCalCore::Event::Ptr,Akonadi::Collection)));
-    QTest::keyClick(noteedit, Qt::Key_Enter);
+    QTest::keyClick(eventedit, Qt::Key_Enter);
     QCOMPARE(spy.count(), 1);
     KCalCore::Event::Ptr eventPtr = spy.at(0).at(0).value<KCalCore::Event::Ptr>();
     QVERIFY(eventPtr);
@@ -303,12 +303,12 @@ void EventEditTest::shouldSetFocusWhenWeCallTodoEdit()
     MessageViewer::EventEdit edit;
     edit.show();
     QTest::qWaitForWindowShown(&edit);
-    QLineEdit *noteedit = qFindChild<QLineEdit *>(&edit, QLatin1String("noteedit"));
-    noteedit->setFocus();
-    QVERIFY(noteedit->hasFocus());
+    QLineEdit *eventedit = qFindChild<QLineEdit *>(&edit, QLatin1String("eventedit"));
+    eventedit->setFocus();
+    QVERIFY(eventedit->hasFocus());
     edit.setFocus();
     edit.showEventEdit();
-    QVERIFY(noteedit->hasFocus());
+    QVERIFY(eventedit->hasFocus());
 }
 
 void EventEditTest::shouldEnsureEndDateIsNotBeforeStartDate()
@@ -337,12 +337,12 @@ void EventEditTest::shouldShouldEnabledSaveOpenEditorButton()
     msg->subject(true)->fromUnicodeString(QLatin1String("Test note"), "us-ascii");
     edit.setMessage(msg);
 
-    QLineEdit *noteedit = qFindChild<QLineEdit *>(&edit, QLatin1String("noteedit"));
+    QLineEdit *eventedit = qFindChild<QLineEdit *>(&edit, QLatin1String("eventedit"));
     KPushButton *openEditor = qFindChild<KPushButton *>(&edit, QLatin1String("open-editor-button"));
     KPushButton *save = qFindChild<KPushButton *>(&edit, QLatin1String("save-button"));
     QCOMPARE(openEditor->isEnabled(), true);
     QCOMPARE(save->isEnabled(), true);
-    noteedit->clear();
+    eventedit->clear();
 
     QCOMPARE(openEditor->isEnabled(), false);
     QCOMPARE(save->isEnabled(), false);
diff --git a/messageviewer/widgets/eventedit.cpp b/messageviewer/widgets/eventedit.cpp
index 84c7065..0dd5ba1 100644
--- a/messageviewer/widgets/eventedit.cpp
+++ b/messageviewer/widgets/eventedit.cpp
@@ -60,7 +60,7 @@ EventEdit::EventEdit(QWidget *parent)
 
     mEventEdit = new KLineEdit;
     mEventEdit->setClearButtonShown(true);
-    mEventEdit->setObjectName(QLatin1String("noteedit"));
+    mEventEdit->setObjectName(QLatin1String("eventedit"));
     mEventEdit->setFocus();
     connect(mEventEdit, SIGNAL(returnPressed()), SLOT(slotReturnPressed()));
     connect(mEventEdit, SIGNAL(textChanged(QString)), SLOT(slotUpdateButtons(QString)));


commit 1600100e21f5a1ebc541bcfb21fcb9a7e9995518
Author: Sandro Knauß <knauss at kolabsys.com>
Date:   Sat Aug 2 14:39:12 2014 +0200

    Create Event/Note/Todo of of Event/Todo

diff --git a/incidenceeditor-ng/incidencedialog.cpp b/incidenceeditor-ng/incidencedialog.cpp
index c55db38..dad6e77 100644
--- a/incidenceeditor-ng/incidencedialog.cpp
+++ b/incidenceeditor-ng/incidencedialog.cpp
@@ -123,7 +123,7 @@ IncidenceDialogPrivate::IncidenceDialogPrivate( Akonadi::IncidenceChanger *chang
     mCalSelector( new Akonadi::CollectionComboBox ),
     mCloseOnSave( false ),
     mItemManager( new EditorItemManager( this, changer ) ),
-    mEditor( new CombinedIncidenceEditor ),
+    mEditor( new CombinedIncidenceEditor(qq) ),
     mInitiallyDirty( false )
 {
   Q_Q( IncidenceDialog );
@@ -166,6 +166,7 @@ IncidenceDialogPrivate::IncidenceDialogPrivate( Akonadi::IncidenceChanger *chang
   mEditor->combine( ieSecrecy );
 
   mIeAttendee = new IncidenceAttendee( qq, mIeDateTime, mUi );
+  mIeAttendee->setParent(qq);
   mEditor->combine( mIeAttendee );
 
   q->connect( mEditor, SIGNAL(showMessage(QString,KMessageWidget::MessageType)),
diff --git a/korganizer/CMakeLists.txt b/korganizer/CMakeLists.txt
index dc67958..277c8e7 100644
--- a/korganizer/CMakeLists.txt
+++ b/korganizer/CMakeLists.txt
@@ -187,6 +187,7 @@ set(korganizerprivate_LIB_SRCS
     kodaymatrix.cpp
     kodialogmanager.cpp
     koeventpopupmenu.cpp
+    noteeditdialog.cpp
     koeventview.cpp
     koeventviewerdialog.cpp
     koglobals.cpp
@@ -253,6 +254,7 @@ set(korganizerprivate_LIB_SRCS
     pimcommon
     akonadi_next
     akonadi-calendar
+    akonadi-notes
     calendarsupport
     eventviews
     incidenceeditorsng
diff --git a/korganizer/koeventpopupmenu.cpp b/korganizer/koeventpopupmenu.cpp
index c3a9481..1e62f57 100644
--- a/korganizer/koeventpopupmenu.cpp
+++ b/korganizer/koeventpopupmenu.cpp
@@ -27,22 +27,36 @@
 #include "actionmanager.h"
 #include "kocorehelper.h"
 #include "koglobals.h"
+#include "noteeditdialog.h"
 
 #include <calendarsupport/kcalprefs.h>
 #include <calendarsupport/utils.h>
 #include <calendarsupport/printing/calprinter.h>
 #include <calendarsupport/printing/calprintdefaultplugins.h>
 
+#include <KCalCore/CalFormat>
 #include <KCalCore/Incidence>
+#include <Akonadi/Notes/NoteUtils>
+#include <Akonadi/CollectionFetchJob>
+#include <Akonadi/CollectionFetchScope>
+#include <Akonadi/ItemCreateJob>
+
+#include <KDebug>
 
 #include <KActionCollection>
+#include <KMime/Message>
 #include <KMimeTypeTrader>
 
+#include <incidenceeditor-ng/incidencedialogfactory.h>
+#include <incidenceeditor-ng/incidencedialog.h>
+
 KOEventPopupMenu::KOEventPopupMenu( Akonadi::ETMCalendar * calendar, QWidget *parent )
   : QMenu( parent ), mCalendar( calendar )
 {
   mHasAdditionalItems = false;
 
+  QAction *action;
+
   addAction( KOGlobals::self()->smallIcon( QLatin1String("document-preview") ), i18n( "&Show" ),
              this, SLOT(popupShow()) );
   mEditOnlyItems.append(
@@ -72,7 +86,25 @@ KOEventPopupMenu::KOEventPopupMenu( Akonadi::ETMCalendar * calendar, QWidget *pa
                                     i18nc( "delete this incidence", "&Delete" ),
                                     this, SLOT(popupDelete()) ) );
   //------------------------------------------------------------------------
-  mEditOnlyItems.append( addSeparator() );
+  addSeparator();
+  action = addAction( KOGlobals::self()->smallIcon( QLatin1String("task-new") ),
+             i18n( "Create To-do" ),
+             this, SLOT(createTodo()) );
+  action->setObjectName(QLatin1String("createtodo"));
+  mEventOnlyItems.append(action);
+
+  action = addAction( KOGlobals::self()->smallIcon( QLatin1String("appointment-new") ),
+             i18n( "Create Event" ),
+             this, SLOT(createEvent()) );
+  action->setObjectName(QLatin1String("createevent"));
+  mTodoOnlyItems.append(action);
+
+  action = addAction( KOGlobals::self()->smallIcon( QLatin1String("view-pim-notes") ),
+             i18n( "Create Note" ),
+             this, SLOT(createNote()) );
+  action->setObjectName(QLatin1String("createnote"));
+  //------------------------------------------------------------------------
+  addSeparator();
   mTodoOnlyItems.append( addAction( KOGlobals::self()->smallIcon( QLatin1String("task-complete") ),
                                     i18n( "Togg&le To-do Completed" ),
                                     this, SLOT(toggleTodoCompleted()) ) );
@@ -89,6 +121,7 @@ KOEventPopupMenu::KOEventPopupMenu( Akonadi::ETMCalendar * calendar, QWidget *pa
   addAction( KOGlobals::self()->smallIcon( QLatin1String("mail-forward") ),
              i18n( "Send as iCalendar..." ),
              this, SLOT(forward()) );
+
 }
 
 void KOEventPopupMenu::showIncidencePopup( const Akonadi::Item &item, const QDate &qd )
@@ -134,6 +167,10 @@ void KOEventPopupMenu::showIncidencePopup( const Akonadi::Item &item, const QDat
     (*it)->setVisible( incidence->type() == KCalCore::Incidence::TypeTodo );
     (*it)->setEnabled( hasChangeRights );
   }
+  for ( it = mEventOnlyItems.begin(); it != mEventOnlyItems.end(); ++it ) {
+    (*it)->setVisible( incidence->type() == KCalCore::Incidence::TypeEvent );
+    (*it)->setEnabled( hasChangeRights );
+  }
   popup( QCursor::pos() );
 }
 
@@ -232,6 +269,101 @@ void KOEventPopupMenu::forward()
   }
 }
 
+void KOEventPopupMenu::createEvent()
+{
+    // Must be a Incidence
+    if ( !CalendarSupport::hasIncidence( mCurrentIncidence ) ) {
+        return;
+    }
+    // Event ->event doesn't make sense
+    if ( CalendarSupport::hasEvent( mCurrentIncidence ) ) {
+        return;
+    }
+
+    if ( CalendarSupport::hasTodo(mCurrentIncidence) ) {
+        KCalCore::Todo::Ptr todo( CalendarSupport::todo( mCurrentIncidence ) );
+        KCalCore::Event::Ptr event( new KCalCore::Event(*todo) );
+        event->setUid(KCalCore::CalFormat::createUniqueId());
+        event->setDtStart(todo->dtStart());
+        event->setAllDay(todo->allDay());
+        event->setDtEnd(todo->dtDue());
+        Akonadi::Item newEventItem;
+        newEventItem.setMimeType( KCalCore::Event::eventMimeType() );
+        newEventItem.setPayload<KCalCore::Event::Ptr>( event );
+
+        IncidenceEditorNG::IncidenceDialog *dlg = IncidenceEditorNG::IncidenceDialogFactory::create(true, KCalCore::IncidenceBase::TypeEvent, 0, this);
+        dlg->setObjectName(QLatin1String("incidencedialog"));
+        dlg->load(newEventItem);
+        dlg->open();
+    }
+}
+
+void KOEventPopupMenu::createNote()
+{
+    // Must be a Incidence
+    if ( CalendarSupport::hasIncidence( mCurrentIncidence ) ) {
+        KCalCore::Incidence::Ptr incidence( CalendarSupport::incidence( mCurrentIncidence ) );
+        Akonadi::NoteUtils::NoteMessageWrapper note;
+        note.setTitle( incidence->summary() );
+        note.setText( incidence->description(), incidence->descriptionIsRich()? Qt::RichText: Qt::PlainText);
+        note.setFrom(QCoreApplication::applicationName()+QCoreApplication::applicationVersion());
+        note.setLastModifiedDate(KDateTime::currentUtcDateTime());
+        Akonadi::NoteUtils::Attachment attachment( mCurrentIncidence.url().url(), mCurrentIncidence.mimeType() );
+        note.attachments().append( attachment );
+        Akonadi::Item newNoteItem;
+        newNoteItem.setMimeType( Akonadi::NoteUtils::noteMimeType() );
+        newNoteItem.setPayload( note.message() );
+
+        NoteEditDialog *noteedit = new NoteEditDialog(this);
+        connect(noteedit, SIGNAL(createNote(Akonadi::Item,Akonadi::Collection)), this, SLOT(slotCreateNote(Akonadi::Item,Akonadi::Collection)));
+        noteedit->load(newNoteItem);
+        noteedit->show();
+    }
+}
+
+void KOEventPopupMenu::slotCreateNote(const Akonadi::Item &noteItem, const Akonadi::Collection &collection)
+{
+    Akonadi::ItemCreateJob *createJob = new Akonadi::ItemCreateJob(noteItem, collection, this);
+    connect(createJob, SIGNAL(result(KJob*)), this, SLOT(slotCreateNewNoteJobFinished(KJob*)));
+    createJob->start();
+}
+
+void KOEventPopupMenu::slotCreateNewNoteJobFinished(KJob *job)
+{
+    if ( job->error() ) {
+        qDebug() << "Error during create new Note "<<job->errorString();
+    }
+}
+
+void KOEventPopupMenu::createTodo()
+{
+    // Must be a Incidence
+    if ( !CalendarSupport::hasIncidence( mCurrentIncidence ) ) {
+        return;
+    }
+    // Todo->Todo doesn't make sense
+    if ( CalendarSupport::hasTodo( mCurrentIncidence ) ) {
+        return;
+    }
+
+    if ( CalendarSupport::hasEvent(mCurrentIncidence) ) {
+        KCalCore::Event::Ptr event( CalendarSupport::event( mCurrentIncidence ) );
+        KCalCore::Todo::Ptr todo( new KCalCore::Todo(*event) );
+        todo->setUid(KCalCore::CalFormat::createUniqueId());
+        todo->setDtStart(event->dtStart());
+        todo->setAllDay(event->allDay());
+        todo->setDtDue(event->dtEnd());
+        Akonadi::Item newTodoItem;
+        newTodoItem.setMimeType( KCalCore::Todo::todoMimeType() );
+        newTodoItem.setPayload<KCalCore::Todo::Ptr>( todo );
+
+        IncidenceEditorNG::IncidenceDialog *dlg = IncidenceEditorNG::IncidenceDialogFactory::create(true, KCalCore::IncidenceBase::TypeTodo, 0, this);
+        dlg->setObjectName(QLatin1String("incidencedialog"));
+        dlg->load(newTodoItem);
+        dlg->open();
+    }
+}
+
 void KOEventPopupMenu::toggleTodoCompleted()
 {
   if ( CalendarSupport::hasTodo( mCurrentIncidence ) ) {
diff --git a/korganizer/koeventpopupmenu.h b/korganizer/koeventpopupmenu.h
index e04f1de..5d16ccc 100644
--- a/korganizer/koeventpopupmenu.h
+++ b/korganizer/koeventpopupmenu.h
@@ -58,6 +58,12 @@ class KOEventPopupMenu : public QMenu
     void toggleTodoCompleted();
     void dissociateOccurrences();
     void forward();
+    void createTodo();
+    void createEvent();
+    void createNote();
+
+    void slotCreateNote(const Akonadi::Item &noteItem, const Akonadi::Collection &collection);
+    void slotCreateNewNoteJobFinished(KJob*);
 
   signals:
     void configChanged();
@@ -83,6 +89,7 @@ class KOEventPopupMenu : public QMenu
     bool mHasAdditionalItems;
     QList<QAction *> mEditOnlyItems;
     QList<QAction *> mTodoOnlyItems;
+    QList<QAction *> mEventOnlyItems;
     QList<QAction *> mRecurrenceItems;
     QAction *mDissociateOccurrences;
     QAction *mToggleReminder;
diff --git a/korganizer/noteeditdialog.cpp b/korganizer/noteeditdialog.cpp
new file mode 100644
index 0000000..84e20b6
--- /dev/null
+++ b/korganizer/noteeditdialog.cpp
@@ -0,0 +1,172 @@
+/*
+  Copyright (c) 2014 Sandro Knauß <knauss at kolabsys.com>*
+
+  This program is free software; you can redistribute it and/or modify it
+  under the terms of the GNU General Public License, version 2, as
+  published by the Free Software Foundation.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License along
+  with this program; if not, write to the Free Software Foundation, Inc.,
+  51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "noteeditdialog.h"
+
+#include <KLocalizedString>
+#include <KLineEdit>
+#include <KRichTextEdit>
+#include <KIcon>
+#include <KDateTimeEdit>
+#include <QHBoxLayout>
+#include <QGridLayout>
+#include <QEvent>
+#include <QKeyEvent>
+#include <QLabel>
+
+#include <Akonadi/CollectionComboBox>
+#include <KPushButton>
+
+#include <incidenceeditor-ng/incidencedialogfactory.h>
+#include <incidenceeditor-ng/incidencedialog.h>
+
+QAbstractItemModel *NoteEditDialog::_k_noteEditStubModel = 0;
+
+NoteEditDialog::NoteEditDialog(QWidget *parent)
+    : KDialog(parent)
+{
+    setCaption(i18nc("@title:window", "Create Note"));
+    setButtons(KDialog::Ok | KDialog::Cancel );
+    setButtonText(KDialog::Ok, i18nc("@action:save note", "Create note"));
+    setButtonText(KDialog::Cancel, i18nc("@action:discard creating note", "Discard"));
+    setButtonIcon(KDialog::Ok, KIcon(QLatin1String("view-pim-notes")));
+
+    enableButtonOk(false);
+
+    QGridLayout *layout = new QGridLayout(mainWidget());
+
+    QHBoxLayout *hbox = new QHBoxLayout;
+    hbox->setMargin(0);
+    hbox->setSpacing(2);
+
+    mNoteTitle = new KLineEdit;
+    mNoteTitle->setClearButtonShown(true);
+    mNoteTitle->setObjectName(QLatin1String("notetitle"));
+    mNoteTitle->setFocus();
+    connect(mNoteTitle, SIGNAL(textChanged(QString)), SLOT(slotUpdateButtons()));
+
+    mCollectionCombobox = new Akonadi::CollectionComboBox(_k_noteEditStubModel);
+    mCollectionCombobox->setAccessRightsFilter(Akonadi::Collection::CanCreateItem);
+    mCollectionCombobox->setMinimumWidth(250);
+    mCollectionCombobox->setMimeTypeFilter( QStringList() << Akonadi::NoteUtils::noteMimeType() );
+    mCollectionCombobox->setObjectName(QLatin1String("akonadicombobox"));
+#ifndef QT_NO_ACCESSIBILITY
+    mCollectionCombobox->setAccessibleDescription(i18n("Calendar where the new note will be stored."));
+#endif
+    mCollectionCombobox->setToolTip(i18n("Calendar where the new note will be stored."));
+
+    connect(mCollectionCombobox, SIGNAL(currentIndexChanged(int)), SLOT(slotCollectionChanged(int)));
+    connect(mCollectionCombobox, SIGNAL(activated(int)), SLOT(slotCollectionChanged(int)));
+
+    mNoteText = new KRichTextEdit(parent);
+    mNoteText->setObjectName(QLatin1String("notetext"));
+    connect(mNoteText, SIGNAL(textChanged()), SLOT(slotUpdateButtons()));
+
+    //First line
+    hbox->addWidget(mNoteTitle);
+    hbox->addSpacing(5);
+    hbox->addWidget(mCollectionCombobox);
+
+    QLabel *lab = new QLabel(i18n("Title:"));
+    layout->addWidget(lab, 0, 0);
+    layout->addLayout(hbox, 0, 1);
+
+    //Second Line
+    lab = new QLabel(i18n("Text:"));
+    layout->addWidget(lab, 1, 0);
+    layout->addWidget(mNoteText, 1, 1);
+
+    setSizePolicy( QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Fixed ) );
+}
+
+NoteEditDialog::~NoteEditDialog()
+{
+}
+
+void NoteEditDialog::slotUpdateButtons()
+{
+    if (mNoteTitle->text().isEmpty() && mNoteText->toPlainText().isEmpty()) {
+        enableButtonOk(false);
+    } else {
+        enableButtonOk(true);
+    }
+}
+
+Akonadi::Collection NoteEditDialog::collection() const
+{
+    return mCollection;
+}
+
+void NoteEditDialog::slotCollectionChanged(int index)
+{
+    Q_UNUSED(index);
+    setCollection(mCollectionCombobox->currentCollection());
+}
+
+void NoteEditDialog::setCollection(const Akonadi::Collection &value)
+{
+    if (mCollection != value) {
+        mCollection = value;
+        Q_EMIT collectionChanged(mCollection);
+    }
+}
+
+void NoteEditDialog::accept()
+{
+    QDialog::accept();
+    const Akonadi::Collection collection = mCollectionCombobox->currentCollection();
+    if (!collection.isValid()) {
+        kDebug()<<" Collection is not valid";
+        return;
+    }
+
+    if (mNoteTitle->text().isEmpty() && mNoteText->toPlainText().isEmpty()) {
+        kDebug() << " empty note do not save it";
+        return;
+    }
+
+    Akonadi::NoteUtils::NoteMessageWrapper note(mItem.payload<KMime::Message::Ptr>());
+    note.setTitle(mNoteTitle->text());
+    Qt::TextFormat format= Qt::PlainText;
+    if (mNoteText->textMode() == KRichTextEdit::Rich) {
+        format = Qt::RichText;
+    }
+    note.setText(mNoteText->textOrHtml(), format);
+    mItem.setPayload<KMime::Message::Ptr>(note.message());
+    emit createNote(mItem, collection);
+}
+
+
+void NoteEditDialog::load(const Akonadi::Item &item)
+{
+    mItem = item;
+    Akonadi::NoteUtils::NoteMessageWrapper note(item.payload<KMime::Message::Ptr>());
+    mNoteText->setTextOrHtml(note.text());
+    if (note.textFormat() == Qt::RichText) {
+        mNoteText->enableRichTextMode();
+    }
+    mNoteTitle->setText(note.title());
+}
+
+KMime::Message::Ptr NoteEditDialog::note() const
+{
+    if (mItem.hasPayload<KMime::Message::Ptr>()) {
+        return mItem.payload<KMime::Message::Ptr>();
+    } else {
+        return KMime::Message::Ptr();
+    }
+}
diff --git a/korganizer/noteeditdialog.h b/korganizer/noteeditdialog.h
new file mode 100644
index 0000000..01888e8
--- /dev/null
+++ b/korganizer/noteeditdialog.h
@@ -0,0 +1,69 @@
+/*
+  Copyright (c) 2014 Sandro Knauß <knauss at kolabsys.com>
+
+  This program is free software; you can redistribute it and/or modify it
+  under the terms of the GNU General Public License, version 2, as
+  published by the Free Software Foundation.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License along
+  with this program; if not, write to the Free Software Foundation, Inc.,
+  51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+#ifndef NOTEEDITDIALOG_H
+#define NOTEEDITDIALOG_H
+
+#include <KDialog>
+
+#include <Akonadi/Collection>
+#include <Akonadi/Item>
+#include <Akonadi/Notes/NoteUtils>
+#include <KMime/KMimeMessage>
+
+class KLineEdit;
+class KRichTextEdit;
+class QAbstractItemModel;
+namespace Akonadi {
+class CollectionComboBox;
+}
+
+
+class NoteEditDialog : public KDialog
+{
+    Q_OBJECT
+public:
+    explicit NoteEditDialog(QWidget *parent = 0);
+    ~NoteEditDialog();
+
+    Akonadi::Collection collection() const;
+    void setCollection(const Akonadi::Collection &value);
+
+    void load(const Akonadi::Item &item);
+    KMime::Message::Ptr note() const;
+
+    //Used for tests
+    static QAbstractItemModel *_k_noteEditStubModel;
+private Q_SLOTS:
+    void slotCollectionChanged(int);
+    void slotUpdateButtons();
+    virtual void accept();
+
+Q_SIGNALS:
+    void createNote(const Akonadi::Item &note, const Akonadi::Collection &collection);
+    void collectionChanged(const Akonadi::Collection &col);
+
+private:
+    Akonadi::Collection mCollection;
+    Akonadi::Item mItem;
+    KLineEdit *mNoteTitle;
+    KRichTextEdit *mNoteText;
+    Akonadi::CollectionComboBox *mCollectionCombobox;
+};
+
+#endif // NOTEEDITDIALOG_H
diff --git a/korganizer/tests/CMakeLists.txt b/korganizer/tests/CMakeLists.txt
index d38e489..356c7ef 100644
--- a/korganizer/tests/CMakeLists.txt
+++ b/korganizer/tests/CMakeLists.txt
@@ -43,3 +43,35 @@ target_link_libraries(testkcmdesignerfields
   ${KDE4_KIO_LIBS}
   ${QT_QTUITOOLS_LIBRARY}
 )
+
+kde4_add_unit_test(koeventpopmenutest TESTNAME koeventpopmenutest koeventpopupmenutest.cpp ../koeventpopupmenu.cpp ../kocorehelper.cpp ../noteeditdialog.cpp)
+target_link_libraries(koeventpopmenutest
+  ${QT_QTTEST_LIBRARY}
+  ${QT_QTGUI_LIBRARY}
+  ${QT_QTCORE_LIBRARY}
+  ${KDEPIMLIBS_KMIME_LIBS}
+  ${KDEPIMLIBS_AKONADI_LIBS}
+  ${KDEPIMLIBS_AKONADI_CALENDAR_LIBS}
+  ${KDEPIMLIBS_AKONADI_NOTES_LIBS}
+  ${KDEPIMLIBS_KCALCORE_LIBS}
+  incidenceeditorsng
+  calendarsupport
+  korganizer_core
+  korganizerprivate
+)
+
+kde4_add_unit_test(noteeditdialogtest TESTNAME noteeditdialogtest  noteeditdialogtest.cpp ../noteeditdialog.cpp)
+target_link_libraries(noteeditdialogtest
+  ${QT_QTTEST_LIBRARY}
+  ${QT_QTGUI_LIBRARY}
+  ${QT_QTCORE_LIBRARY}
+  ${KDEPIMLIBS_KMIME_LIBS}
+  ${KDEPIMLIBS_AKONADI_LIBS}
+  ${KDEPIMLIBS_AKONADI_CALENDAR_LIBS}
+  ${KDEPIMLIBS_AKONADI_NOTES_LIBS}
+  ${KDEPIMLIBS_KCALCORE_LIBS}
+  incidenceeditorsng
+  calendarsupport
+  korganizer_core
+  korganizerprivate
+  )
\ No newline at end of file
diff --git a/korganizer/tests/koeventpopupmenutest.cpp b/korganizer/tests/koeventpopupmenutest.cpp
new file mode 100644
index 0000000..84164c6
--- /dev/null
+++ b/korganizer/tests/koeventpopupmenutest.cpp
@@ -0,0 +1,274 @@
+/*
+  Copyright (c) 2014 Sandro Knauß <knauss at kolabsys.com>
+
+  This program is free software; you can redistribute it and/or modify it
+  under the terms of the GNU General Public License, version 2, as
+  published by the Free Software Foundation.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License along
+  with this program; if not, write to the Free Software Foundation, Inc.,
+  51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "koeventpopupmenutest.h"
+#include "noteeditdialog.h"
+#include "koeventpopupmenu.h"
+#include <incidenceeditor-ng/incidencedialog.h>
+#include <incidenceeditor-ng/incidenceattendee.h>
+#include <calendarsupport/utils.h>
+#include <Akonadi/EntityTreeModel>
+#include <Akonadi/Notes/NoteUtils>
+#include <KCalCore/Event>
+#include <KCalCore/Todo>
+
+#include <KMime/KMimeMessage>
+#include <QStandardItemModel>
+#include <KPushButton>
+#include <KMessageWidget>
+#include <qtest_kde.h>
+#include <qtestkeyboard.h>
+#include <qtestmouse.h>
+
+#include <QLineEdit>
+#include <QHBoxLayout>
+#include <QShortcut>
+#include <QAction>
+#include <boost/graph/graph_concepts.hpp>
+
+KoEventPopupMenuTest::KoEventPopupMenuTest()
+{
+}
+
+void KoEventPopupMenuTest::createEventFromEvent()
+{
+    Akonadi::ETMCalendar::Ptr calendar(new Akonadi::ETMCalendar());
+    KOEventPopupMenu menu(0);
+
+    KCalCore::Event::Ptr event( new KCalCore::Event() );
+    Akonadi::Item item;
+    item.setMimeType( KCalCore::Event::eventMimeType() );
+    item.setPayload<KCalCore::Event::Ptr>( event );
+
+    menu.setCalendar(calendar);
+    menu.showIncidencePopup(item, QDate());
+    QAction *createevent = qFindChild<QAction *>(&menu, QLatin1String("createevent"));
+    createevent->trigger();
+
+    IncidenceEditorNG::IncidenceDialog *dlg = qFindChild<IncidenceEditorNG::IncidenceDialog *>(&menu, QLatin1String("incidencedialog"));
+    QVERIFY(!dlg);
+
+}
+
+void KoEventPopupMenuTest::createTodoFromTodo()
+{
+    Akonadi::ETMCalendar::Ptr calendar(new Akonadi::ETMCalendar());
+    KOEventPopupMenu menu(0);
+
+    KCalCore::Todo::Ptr todo( new KCalCore::Todo() );
+    Akonadi::Item item;
+    item.setMimeType( KCalCore::Todo::todoMimeType() );
+    item.setPayload<KCalCore::Todo::Ptr>( todo );
+
+    menu.setCalendar(calendar);
+    menu.showIncidencePopup(item, QDate());
+    QAction *createtodo = qFindChild<QAction *>(&menu, QLatin1String("createtodo"));
+    createtodo->trigger();
+
+    IncidenceEditorNG::IncidenceDialog *dlg = qFindChild<IncidenceEditorNG::IncidenceDialog *>(&menu, QLatin1String("incidencedialog"));
+    QVERIFY(!dlg);
+}
+
+void KoEventPopupMenuTest::createEventFromTodo()
+{
+    Akonadi::ETMCalendar::Ptr calendar(new Akonadi::ETMCalendar());
+    KOEventPopupMenu menu(0);
+
+    KCalCore::Todo::Ptr todo( new KCalCore::Todo() );
+    Akonadi::Item item;
+    item.setMimeType( KCalCore::Todo::todoMimeType() );
+    item.setPayload<KCalCore::Todo::Ptr>( todo );
+
+    KDateTime start, end;
+    QString summary(QLatin1String("a test"));
+    start.setTime_t(1402593346);
+    end.setTime_t(1403593346);
+    todo->setDtStart(start);
+    todo->setDtDue(end);
+    todo->setSummary(summary);
+
+    menu.setCalendar(calendar);
+    menu.showIncidencePopup(item, QDate());
+    QAction *createevent = qFindChild<QAction *>(&menu, QLatin1String("createevent"));
+    createevent->trigger();
+    IncidenceEditorNG::IncidenceDialog *dlg = qFindChild<IncidenceEditorNG::IncidenceDialog *>(&menu);
+    QVERIFY(dlg);
+    IncidenceEditorNG::IncidenceEditor *editor = qFindChild<IncidenceEditorNG::IncidenceEditor *>(&menu);
+    QVERIFY(editor);
+    KCalCore::Event::Ptr event(editor->incidence<KCalCore::Event>());
+    QVERIFY(event->uid() != todo->uid());
+    QCOMPARE(event->dtStart(), start);
+    QCOMPARE(event->dtEnd(), end);
+    QCOMPARE(event->allDay(), false);
+    QCOMPARE(event->summary(), summary);
+}
+
+void KoEventPopupMenuTest::createTodoFromEvent()
+{
+    Akonadi::ETMCalendar::Ptr calendar(new Akonadi::ETMCalendar());
+    KOEventPopupMenu menu(0);
+
+    KCalCore::Event::Ptr event( new KCalCore::Event() );
+    Akonadi::Item item;
+    item.setMimeType( KCalCore::Event::eventMimeType() );
+    item.setPayload<KCalCore::Event::Ptr>( event );
+
+    KDateTime start, end;
+    QString summary(QLatin1String("a test"));
+    start.setTime_t(1402593346);
+    end.setTime_t(1403593346);
+    event->setDtStart(start);
+    event->setDtEnd(end);
+    event->setSummary(summary);
+
+    menu.setCalendar(calendar);
+    menu.showIncidencePopup(item, QDate());
+    QAction *createtodo = qFindChild<QAction *>(&menu, QLatin1String("createtodo"));
+    createtodo->trigger();
+    IncidenceEditorNG::IncidenceDialog *dlg = qFindChild<IncidenceEditorNG::IncidenceDialog *>(&menu);
+    QVERIFY(dlg);
+    IncidenceEditorNG::IncidenceEditor *editor = qFindChild<IncidenceEditorNG::IncidenceEditor *>(&menu);
+    QVERIFY(editor);
+    KCalCore::Todo::Ptr todo(editor->incidence<KCalCore::Todo>());
+    QVERIFY(todo->uid() != event->uid());
+    QCOMPARE(todo->dtStart(), start);
+    QCOMPARE(todo->dtDue(), end);
+    QCOMPARE(todo->allDay(), false);
+    QCOMPARE(todo->summary(), summary);
+}
+
+
+void KoEventPopupMenuTest::createNoteFromEvent()
+{
+    Akonadi::ETMCalendar::Ptr calendar(new Akonadi::ETMCalendar());
+    KOEventPopupMenu menu(0);
+
+    KCalCore::Event::Ptr event( new KCalCore::Event() );
+    Akonadi::Item item;
+    item.setMimeType( KCalCore::Event::eventMimeType() );
+    item.setPayload<KCalCore::Event::Ptr>( event );
+
+    KDateTime start, end;
+    QString summary(QLatin1String("A test"));
+    QString description(QLatin1String("A long description"));
+    start.setTime_t(1402593346);
+    end.setTime_t(1403593346);
+    event->setDtStart(start);
+    event->setDtEnd(end);
+    event->setSummary(summary);
+    event->setDescription(description, true);
+
+    menu.setCalendar(calendar);
+    menu.showIncidencePopup(item, QDate());
+    QAction *createnote = qFindChild<QAction *>(&menu, QLatin1String("createnote"));
+    NoteEditDialog *noteedit = qFindChild<NoteEditDialog *>(&menu);
+    QVERIFY(!noteedit);
+    createnote->trigger();
+    noteedit= qFindChild<NoteEditDialog *>(&menu);
+    QVERIFY(noteedit);
+    Akonadi::NoteUtils::NoteMessageWrapper note(noteedit->note());
+    QCOMPARE(note.title(), summary);
+    QCOMPARE(note.text(), description);
+    QCOMPARE(note.textFormat(), Qt::RichText);
+    QCOMPARE(note.attachments().count(), 1);
+    QCOMPARE(note.attachments().at(0).mimetype(), KCalCore::Event::eventMimeType());
+    QCOMPARE(note.attachments().at(0).url(), (QUrl)item.url());
+    QCOMPARE(note.attachments().at(0).data(), QByteArray());
+}
+
+
+void KoEventPopupMenuTest::createNoteFromTodo()
+{
+    Akonadi::ETMCalendar::Ptr calendar(new Akonadi::ETMCalendar());
+    KOEventPopupMenu menu(0);
+
+    KCalCore::Todo::Ptr todo( new KCalCore::Todo() );
+    Akonadi::Item item;
+    item.setMimeType( KCalCore::Todo::todoMimeType() );
+    item.setPayload<KCalCore::Todo::Ptr>( todo );
+
+    KDateTime start, end;
+    QString summary(QLatin1String("a test"));
+    QString description(QLatin1String("A long description"));
+    start.setTime_t(1402593346);
+    end.setTime_t(1403593346);
+    todo->setDtStart(start);
+    todo->setDtDue(end);
+    todo->setSummary(summary);
+    todo->setDescription(description);
+
+    menu.setCalendar(calendar);
+    menu.showIncidencePopup(item, QDate());
+    QAction *createnote = qFindChild<QAction *>(&menu, QLatin1String("createnote"));
+
+    NoteEditDialog *noteedit = qFindChild<NoteEditDialog *>(&menu);
+    QVERIFY(!noteedit);
+    createnote->trigger();
+    noteedit= qFindChild<NoteEditDialog *>(&menu);
+    QVERIFY(noteedit);
+    Akonadi::NoteUtils::NoteMessageWrapper note(noteedit->note());
+    QCOMPARE(note.title(), summary);
+    QCOMPARE(note.text(), description);
+    QCOMPARE(note.attachments().count(), 1);
+    QCOMPARE(note.attachments().at(0).mimetype(), KCalCore::Todo::todoMimeType());
+    QCOMPARE(note.attachments().at(0).url(), (QUrl)item.url());
+    QCOMPARE(note.attachments().at(0).data(), QByteArray());
+}
+
+
+void KoEventPopupMenuTest::defaultMenuEventVisible()
+{
+    Akonadi::ETMCalendar::Ptr calendar(new Akonadi::ETMCalendar());
+    KOEventPopupMenu menu(0);
+
+    KCalCore::Event::Ptr event( new KCalCore::Event() );
+    Akonadi::Item item;
+    item.setMimeType( KCalCore::Event::eventMimeType() );
+    item.setPayload<KCalCore::Event::Ptr>( event );
+
+    menu.setCalendar(calendar);
+    menu.showIncidencePopup(item, QDate());
+    QAction *createevent = qFindChild<QAction *>(&menu, QLatin1String("createevent"));
+    QAction *createnote = qFindChild<QAction *>(&menu, QLatin1String("createnote"));
+    QAction *createtodo = qFindChild<QAction *>(&menu, QLatin1String("createtodo"));
+    QVERIFY(!createevent->isVisible());
+    QVERIFY(createnote->isVisible());
+    QVERIFY(createtodo->isVisible());
+}
+
+void KoEventPopupMenuTest::defaultMenuTodoVisible()
+{
+    Akonadi::ETMCalendar::Ptr calendar(new Akonadi::ETMCalendar());
+    KOEventPopupMenu menu(0);
+
+    KCalCore::Todo::Ptr todo( new KCalCore::Todo() );
+
+    Akonadi::Item item;
+    item.setMimeType( KCalCore::Todo::todoMimeType() );
+    item.setPayload<KCalCore::Todo::Ptr>( todo );
+
+    menu.setCalendar(calendar);
+    menu.showIncidencePopup(item, QDate());
+    QAction *createevent = qFindChild<QAction *>(&menu, QLatin1String("createevent"));
+    QAction *createnote = qFindChild<QAction *>(&menu, QLatin1String("createnote"));
+    QAction *createtodo = qFindChild<QAction *>(&menu, QLatin1String("createtodo"));
+    QVERIFY(createevent->isVisible());
+    QVERIFY(createnote->isVisible());
+    QVERIFY(!createtodo->isVisible());
+}
+
+QTEST_KDEMAIN( KoEventPopupMenuTest, GUI )
diff --git a/korganizer/tests/koeventpopupmenutest.h b/korganizer/tests/koeventpopupmenutest.h
new file mode 100644
index 0000000..8bfe6f0
--- /dev/null
+++ b/korganizer/tests/koeventpopupmenutest.h
@@ -0,0 +1,46 @@
+/*
+  Copyright (c) 2014 Sandro Knauß <knauss at kolabsys.com>
+
+  This program is free software; you can redistribute it and/or modify it
+  under the terms of the GNU General Public License, version 2, as
+  published by the Free Software Foundation.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License along
+  with this program; if not, write to the Free Software Foundation, Inc.,
+  51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef KOEVENTPOPUPMENUTESTTEST_H
+#define KOEVENTPOPUPMENUTESTTEST_H
+
+#include <Akonadi/Collection>
+#include <QObject>
+
+namespace Akonadi {
+    class Collection;
+}
+
+class KoEventPopupMenuTest : public QObject
+{
+    Q_OBJECT
+public:
+    KoEventPopupMenuTest();
+
+private slots:
+    void createEventFromTodo();
+    void createTodoFromEvent();
+    void createEventFromEvent();
+    void createTodoFromTodo();
+    void createNoteFromEvent();
+    void createNoteFromTodo();
+    void defaultMenuEventVisible();
+    void defaultMenuTodoVisible();
+};
+
+#endif // KOEVENTPOPUPMENUTESTTEST_H
+
diff --git a/korganizer/tests/noteeditdialogtest.cpp b/korganizer/tests/noteeditdialogtest.cpp
new file mode 100644
index 0000000..9a94677
--- /dev/null
+++ b/korganizer/tests/noteeditdialogtest.cpp
@@ -0,0 +1,351 @@
+/*
+  Copyright (c) 2014 Sandro Knauß <knauss at kolabsys.com>
+
+  This program is free software; you can redistribute it and/or modify it
+  under the terms of the GNU General Public License, version 2, as
+  published by the Free Software Foundation.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License along
+  with this program; if not, write to the Free Software Foundation, Inc.,
+  51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "noteeditdialogtest.h"
+#include "noteeditdialog.h"
+#include <Akonadi/Collection>
+#include <Akonadi/CollectionComboBox>
+#include <Akonadi/EntityTreeModel>
+
+#include <KMime/KMimeMessage>
+#include <QStandardItemModel>
+#include <KPushButton>
+#include <KMessageWidget>
+#include <KRichTextEdit>
+#include <qtest_kde.h>
+#include <qtestkeyboard.h>
+#include <qtestmouse.h>
+
+#include <QLineEdit>
+#include <QTextEdit>
+#include <QHBoxLayout>
+#include <QShortcut>
+#include <QAction>
+
+Q_DECLARE_METATYPE(KMime::Message::Ptr)
+NoteEditDialogTest::NoteEditDialogTest()
+{
+    qRegisterMetaType<Akonadi::Collection>();
+    qRegisterMetaType<Akonadi::Item>();
+    qRegisterMetaType<KMime::Message::Ptr>();
+
+    QStandardItemModel *model = new QStandardItemModel;
+    for (int id = 42; id < 51; ++id) {
+        Akonadi::Collection collection(id);
+        collection.setRights(Akonadi::Collection::AllRights);
+        collection.setName(QString::number(id));
+        collection.setContentMimeTypes(QStringList() << Akonadi::NoteUtils::noteMimeType());
+
+        QStandardItem *item = new QStandardItem(collection.name());
+        item->setData(QVariant::fromValue(collection),
+                      Akonadi::EntityTreeModel::CollectionRole);
+        item->setData(QVariant::fromValue(collection.id()),
+                      Akonadi::EntityTreeModel::CollectionIdRole);
+
+        model->appendRow(item);
+    }
+    NoteEditDialog::_k_noteEditStubModel = model;
+}
+
+void NoteEditDialogTest::shouldHaveDefaultValuesOnCreation()
+{
+    NoteEditDialog edit;
+    QVERIFY(!edit.note());
+    QLineEdit *notetitle = qFindChild<QLineEdit *>(&edit, QLatin1String("notetitle"));
+    QTextEdit *notetext = qFindChild<QTextEdit *>(&edit, QLatin1String("notetext"));
+    KPushButton *ok = edit.button(KDialog::Ok);
+    QVERIFY(notetitle);
+    QCOMPARE(notetitle->text(), QString());
+    QVERIFY(notetext);
+    QCOMPARE(notetext->toPlainText(), QString());
+    QVERIFY(ok);
+    QCOMPARE(ok->isEnabled(), false);
+}
+
+
+void NoteEditDialogTest::shouldEmitCollectionChanged()
+{
+    NoteEditDialog edit;
+    QSignalSpy spy(&edit, SIGNAL(collectionChanged(Akonadi::Collection)));
+    edit.setCollection(Akonadi::Collection(42));
+    QCOMPARE(spy.count(), 1);
+    QCOMPARE(spy.at(0).at(0).value<Akonadi::Collection>(), Akonadi::Collection(42));
+}
+
+
+void NoteEditDialogTest::shouldNotEmitWhenCollectionIsNotChanged()
+{
+    NoteEditDialog edit;
+    edit.setCollection(Akonadi::Collection(42));
+    QSignalSpy spy(&edit, SIGNAL(collectionChanged(Akonadi::Collection)));
+    edit.setCollection(Akonadi::Collection(42));
+    QCOMPARE(spy.count(), 0);
+}
+
+void NoteEditDialogTest::shouldHaveSameValueAfterSet()
+{
+    NoteEditDialog edit;
+
+    Akonadi::NoteUtils::NoteMessageWrapper note;
+    Akonadi::Item item;
+    item.setMimeType( Akonadi::NoteUtils::noteMimeType() );
+    KMime::Message::Ptr message(note.message());
+    item.setPayload(message);
+
+    edit.setCollection(Akonadi::Collection(42));
+    edit.load(item);
+    QCOMPARE(edit.collection(), Akonadi::Collection(42));
+    QCOMPARE(edit.note()->encodedContent(), message->encodedContent());
+}
+
+void NoteEditDialogTest::shouldHaveFilledText()
+{
+    NoteEditDialog edit;
+
+    Akonadi::NoteUtils::NoteMessageWrapper note;
+    QString title=QLatin1String("title");
+    QString text=QLatin1String("text");
+    note.setTitle(title);
+    note.setText(text);
+    Akonadi::Item item;
+    item.setMimeType( Akonadi::NoteUtils::noteMimeType() );
+    item.setPayload( note.message() );
+
+    edit.load(item);
+    QLineEdit *notetitle = qFindChild<QLineEdit *>(&edit, QLatin1String("notetitle"));
+    QTextEdit *notetext = qFindChild<QTextEdit *>(&edit, QLatin1String("notetext"));
+    QCOMPARE(notetitle->text(), title);
+    QCOMPARE(notetext->toPlainText(), text);
+}
+
+void NoteEditDialogTest::shouldHaveRichText()
+{
+    NoteEditDialog edit;
+
+    Akonadi::NoteUtils::NoteMessageWrapper note;
+    QString title=QLatin1String("title");
+    QString text=QLatin1String("text");
+    note.setTitle(title);
+    note.setText(text, Qt::RichText);
+    Akonadi::Item item;
+    item.setMimeType( Akonadi::NoteUtils::noteMimeType() );
+    item.setPayload( note.message() );
+
+    edit.load(item);
+    KRichTextEdit *notetext = qFindChild<KRichTextEdit *>(&edit, QLatin1String("notetext"));
+    QCOMPARE(notetext->toPlainText(), text);
+    QCOMPARE(notetext->textMode(), KRichTextEdit::Rich);
+}
+
+
+void NoteEditDialogTest::shouldDefaultCollectionIsValid()
+{
+    NoteEditDialog edit;
+    Akonadi::CollectionComboBox *akonadicombobox = qFindChild<Akonadi::CollectionComboBox *>(&edit, QLatin1String("akonadicombobox"));
+    QVERIFY(akonadicombobox);
+    QVERIFY(akonadicombobox->currentCollection().isValid());
+}
+
+void NoteEditDialogTest::shouldEmitCollectionChangedWhenCurrentCollectionWasChanged()
+{
+    NoteEditDialog edit;
+    Akonadi::CollectionComboBox *akonadicombobox = qFindChild<Akonadi::CollectionComboBox *>(&edit, QLatin1String("akonadicombobox"));
+    akonadicombobox->setCurrentIndex(0);
+    QCOMPARE(akonadicombobox->currentIndex(), 0);
+    QSignalSpy spy(&edit, SIGNAL(collectionChanged(Akonadi::Collection)));
+    akonadicombobox->setCurrentIndex(3);
+    QCOMPARE(akonadicombobox->currentIndex(), 3);
+    QCOMPARE(spy.count(), 1);
+}
+
+void NoteEditDialogTest::shouldEmitCorrectCollection()
+{
+    NoteEditDialog edit;
+    Akonadi::CollectionComboBox *akonadicombobox = qFindChild<Akonadi::CollectionComboBox *>(&edit, QLatin1String("akonadicombobox"));
+
+    Akonadi::NoteUtils::NoteMessageWrapper note;
+    QString title=QLatin1String("title");
+    QString text=QLatin1String("text");
+    note.setTitle(title);
+    note.setText(text);
+    Akonadi::Item item;
+    item.setMimeType( Akonadi::NoteUtils::noteMimeType() );
+    item.setPayload( note.message() );
+
+    edit.load(item);
+    akonadicombobox->setCurrentIndex(3);
+    Akonadi::Collection col = akonadicombobox->currentCollection();
+    QSignalSpy spy(&edit, SIGNAL(createNote(Akonadi::Item,Akonadi::Collection)));
+    KPushButton *ok = edit.button(KDialog::Ok);
+    QTest::mouseClick(ok, Qt::LeftButton);
+    QCOMPARE(spy.count(), 1);
+    QCOMPARE(spy.at(0).at(1).value<Akonadi::Collection>(), col);
+}
+
+void NoteEditDialogTest::shouldNotEmitNoteWhenTitleIsEmpty()
+{
+    NoteEditDialog edit;
+    Akonadi::NoteUtils::NoteMessageWrapper note;
+    Akonadi::Item item;
+    item.setMimeType( Akonadi::NoteUtils::noteMimeType() );
+    item.setPayload( note.message() );
+
+    edit.load(item);
+    QSignalSpy spy(&edit, SIGNAL(createNote(Akonadi::Item,Akonadi::Collection)));
+    KPushButton *ok = edit.button(KDialog::Ok);
+
+    QLineEdit *notetitle = qFindChild<QLineEdit *>(&edit, QLatin1String("notetitle"));
+    notetitle->setText(QString());
+    QTest::mouseClick(ok, Qt::LeftButton);
+    QCOMPARE(spy.count(), 0);
+    notetitle->setText(QLatin1String("F"));
+    QTest::mouseClick(ok, Qt::LeftButton);
+    QCOMPARE(spy.count(), 1);
+}
+
+void NoteEditDialogTest::shouldNotEmitNoteWhenTextIsEmpty()
+{
+    NoteEditDialog edit;
+    Akonadi::NoteUtils::NoteMessageWrapper note;
+    Akonadi::Item item;
+    item.setMimeType( Akonadi::NoteUtils::noteMimeType() );
+    item.setPayload( note.message() );
+
+    edit.load(item);
+    QSignalSpy spy(&edit, SIGNAL(createNote(Akonadi::Item,Akonadi::Collection)));
+    KPushButton *ok = edit.button(KDialog::Ok);
+
+    //Need to set title to empty, 'cause NoteUtils uses default title: "New Note"
+    QLineEdit *notetitle = qFindChild<QLineEdit *>(&edit, QLatin1String("notetitle"));
+    notetitle->setText(QString());
+
+    QTest::mouseClick(ok, Qt::LeftButton);
+    QCOMPARE(spy.count(), 0);
+    KRichTextEdit *notetext = qFindChild<KRichTextEdit *>(&edit, QLatin1String("notetext"));
+    notetext->setText(QLatin1String("F"));
+    QTest::mouseClick(ok, Qt::LeftButton);
+    QCOMPARE(spy.count(), 1);
+}
+
+void NoteEditDialogTest::shouldNoteHasCorrectText()
+{
+    NoteEditDialog edit;
+    Akonadi::NoteUtils::NoteMessageWrapper note;
+    QString text(QLatin1String("text"));
+    note.setText(text);
+    Akonadi::Item item;
+    item.setMimeType( Akonadi::NoteUtils::noteMimeType() );
+    item.setPayload( note.message() );
+
+    edit.load(item);
+    QSignalSpy spy(&edit, SIGNAL(createNote(Akonadi::Item,Akonadi::Collection)));
+    KPushButton *ok = edit.button(KDialog::Ok);
+
+    QTest::mouseClick(ok, Qt::LeftButton);
+    QCOMPARE(spy.count(), 1);
+    Akonadi::NoteUtils::NoteMessageWrapper rNote(spy.at(0).at(0).value<Akonadi::Item>().payload<KMime::Message::Ptr>());
+    QCOMPARE(rNote.text(), text);
+    KRichTextEdit *notetext = qFindChild<KRichTextEdit *>(&edit, QLatin1String("notetext"));
+    QString text2 = QLatin1String("F");
+    notetext->setText(text2);
+    QTest::mouseClick(ok, Qt::LeftButton);
+    QCOMPARE(spy.count(), 2);
+    Akonadi::NoteUtils::NoteMessageWrapper r2Note(spy.at(1).at(0).value<Akonadi::Item>().payload<KMime::Message::Ptr>());
+    QCOMPARE(r2Note.text(), text2);
+
+}
+
+void NoteEditDialogTest::shouldNoteHasCorrectTitle()
+{
+    NoteEditDialog edit;
+    Akonadi::NoteUtils::NoteMessageWrapper note;
+    QString text(QLatin1String("text"));
+    note.setTitle(text);
+    Akonadi::Item item;
+    item.setMimeType( Akonadi::NoteUtils::noteMimeType() );
+    item.setPayload( note.message() );
+
+    edit.load(item);
+    QSignalSpy spy(&edit, SIGNAL(createNote(Akonadi::Item,Akonadi::Collection)));
+    KPushButton *ok = edit.button(KDialog::Ok);
+
+    QTest::mouseClick(ok, Qt::LeftButton);
+    QCOMPARE(spy.count(), 1);
+    Akonadi::NoteUtils::NoteMessageWrapper rNote(spy.at(0).at(0).value<Akonadi::Item>().payload<KMime::Message::Ptr>());
+    QCOMPARE(rNote.title(), text);
+    QLineEdit *notetitle = qFindChild<QLineEdit *>(&edit, QLatin1String("notetitle"));
+    QString text2 = QLatin1String("F");
+    notetitle->setText(text2);
+    QTest::mouseClick(ok, Qt::LeftButton);
+    QCOMPARE(spy.count(), 2);
+    Akonadi::NoteUtils::NoteMessageWrapper r2Note(spy.at(1).at(0).value<Akonadi::Item>().payload<KMime::Message::Ptr>());
+    QCOMPARE(r2Note.title(), text2);
+
+}
+
+
+void NoteEditDialogTest::shouldNoteHasCorrectTextFormat()
+{
+    NoteEditDialog edit;
+    Akonadi::NoteUtils::NoteMessageWrapper note;
+    QString text(QLatin1String("text"));
+    note.setText(text);
+    Akonadi::Item item;
+    item.setMimeType( Akonadi::NoteUtils::noteMimeType() );
+    item.setPayload( note.message() );
+
+    edit.load(item);
+    QSignalSpy spy(&edit, SIGNAL(createNote(Akonadi::Item,Akonadi::Collection)));
+    KPushButton *ok = edit.button(KDialog::Ok);
+
+    QTest::mouseClick(ok, Qt::LeftButton);
+    QCOMPARE(spy.count(), 1);
+    Akonadi::NoteUtils::NoteMessageWrapper rNote(spy.at(0).at(0).value<Akonadi::Item>().payload<KMime::Message::Ptr>());
+    QCOMPARE(rNote.textFormat(), Qt::PlainText);
+    KRichTextEdit *notetext = qFindChild<KRichTextEdit *>(&edit, QLatin1String("notetext"));
+    notetext->enableRichTextMode();
+    QTest::mouseClick(ok, Qt::LeftButton);
+    QCOMPARE(spy.count(), 2);
+    Akonadi::NoteUtils::NoteMessageWrapper r2Note(spy.at(1).at(0).value<Akonadi::Item>().payload<KMime::Message::Ptr>());
+    QCOMPARE(r2Note.textFormat(), Qt::RichText);
+
+}
+
+void NoteEditDialogTest::shouldShouldEnabledSaveEditorButton()
+{
+    NoteEditDialog edit;
+    Akonadi::NoteUtils::NoteMessageWrapper note;
+    QString text(QLatin1String("text"));
+    note.setTitle(text);
+    Akonadi::Item item;
+    item.setMimeType( Akonadi::NoteUtils::noteMimeType() );
+    item.setPayload( note.message() );
+
+    edit.load(item);
+
+    KPushButton *ok = edit.button(KDialog::Ok);
+    QLineEdit *notetitle = qFindChild<QLineEdit *>(&edit, QLatin1String("notetitle"));
+
+    QCOMPARE(ok->isEnabled(), true);
+    notetitle->clear();
+
+    QCOMPARE(ok->isEnabled(), false);
+}
+
+
+
+QTEST_KDEMAIN( NoteEditDialogTest, GUI )
diff --git a/korganizer/tests/noteeditdialogtest.h b/korganizer/tests/noteeditdialogtest.h
new file mode 100644
index 0000000..4b4bfe8
--- /dev/null
+++ b/korganizer/tests/noteeditdialogtest.h
@@ -0,0 +1,52 @@
+/*
+  Copyright (c) 2014 Sandro Knauß <knauss at kolabsys.com>
+
+  This program is free software; you can redistribute it and/or modify it
+  under the terms of the GNU General Public License, version 2, as
+  published by the Free Software Foundation.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License along
+  with this program; if not, write to the Free Software Foundation, Inc.,
+  51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef NOTEEDITDIALOGTEST_H
+#define NOTEEDITDIALOGTEST_H
+
+#include <QObject>
+
+
+class NoteEditDialogTest : public QObject
+{
+    Q_OBJECT
+public:
+    NoteEditDialogTest();
+
+private slots:
+    void shouldHaveDefaultValuesOnCreation();
+    void shouldEmitCollectionChanged();
+    void shouldNotEmitWhenCollectionIsNotChanged();
+    void shouldHaveSameValueAfterSet();
+    void shouldHaveFilledText();
+    void shouldHaveRichText();
+    void shouldDefaultCollectionIsValid();
+    void shouldEmitCollectionChangedWhenCurrentCollectionWasChanged();
+    void shouldEmitCorrectCollection();
+
+    void shouldNotEmitNoteWhenTitleIsEmpty();
+    void shouldNotEmitNoteWhenTextIsEmpty();
+
+    void shouldNoteHasCorrectText();
+    void shouldNoteHasCorrectTitle();
+    void shouldNoteHasCorrectTextFormat();
+
+    void shouldShouldEnabledSaveEditorButton();
+};
+
+#endif // NOTEEDITDIALOGTEST_H
+


commit c9b034e3ff4cb80b51f5ddc5c6dfce7652f5624d
Author: Sandro Knauß <knauss at kolabsys.com>
Date:   Thu Jul 31 12:27:21 2014 +0200

    Showing "Create Note" entry

diff --git a/kmail/kmail_part.rc b/kmail/kmail_part.rc
index 2e72884..e0b9541 100644
--- a/kmail/kmail_part.rc
+++ b/kmail/kmail_part.rc
@@ -169,6 +169,8 @@
    </Menu>
    <Separator/>
    <Action name="create_todo"/>
+   <Action name="create_event"/>
+   <Action name="create_note"/>
    <Separator/>
    <Action name="annotate"/>
   </Menu>
@@ -282,6 +284,7 @@
   <Separator/>
   <Action name="create_todo"/>
   <Action name="create_event"/>
+  <Action name="create_note"/>
   <Separator/>
   <Action name="annotate"/>
  </Menu>
diff --git a/kmail/kmmainwidget.cpp b/kmail/kmmainwidget.cpp
index 34d740b..b6655c5 100644
--- a/kmail/kmmainwidget.cpp
+++ b/kmail/kmmainwidget.cpp
@@ -2921,6 +2921,7 @@ void KMMainWidget::showMessagePopup(const Akonadi::Item&msg ,const KUrl&url,cons
         menu->addSeparator();
         menu->addAction( mMsgView->createTodoAction() );
         menu->addAction( mMsgView->createEventAction() );
+        menu->addAction( mMsgView->createNoteAction() );
         menu->addSeparator();
         if (mMsgView) {
             menu->addAction( mMsgView->saveMessageDisplayFormatAction() );
diff --git a/kmail/kmmainwin.rc b/kmail/kmmainwin.rc
index 2e72884..e0b9541 100644
--- a/kmail/kmmainwin.rc
+++ b/kmail/kmmainwin.rc
@@ -169,6 +169,8 @@
    </Menu>
    <Separator/>
    <Action name="create_todo"/>
+   <Action name="create_event"/>
+   <Action name="create_note"/>
    <Separator/>
    <Action name="annotate"/>
   </Menu>
@@ -282,6 +284,7 @@
   <Separator/>
   <Action name="create_todo"/>
   <Action name="create_event"/>
+  <Action name="create_note"/>
   <Separator/>
   <Action name="annotate"/>
  </Menu>
diff --git a/kmail/kmreadermainwin.cpp b/kmail/kmreadermainwin.cpp
index 600152d..684f35a 100644
--- a/kmail/kmreadermainwin.cpp
+++ b/kmail/kmreadermainwin.cpp
@@ -578,6 +578,7 @@ void KMReaderMainWin::showMessagePopup(const Akonadi::Item&msg ,const KUrl&url,c
                 menu->addSeparator();
                 menu->addAction( mReaderWin->createTodoAction() );
                 menu->addAction( mReaderWin->createEventAction() );
+                menu->addAction( mReaderWin->createNoteAction() );
                 menu->addSeparator();
                 menu->addAction( mReaderWin->saveMessageDisplayFormatAction() );
                 menu->addAction( mReaderWin->resetMessageDisplayFormatAction() );
diff --git a/kmail/kmreadermainwin.rc b/kmail/kmreadermainwin.rc
index ef53fae..7a3552d 100644
--- a/kmail/kmreadermainwin.rc
+++ b/kmail/kmreadermainwin.rc
@@ -65,6 +65,8 @@
    <Action name="set_status" />
    <Separator/>
    <Action name="create_todo"/>
+   <Action name="create_event"/>
+   <Action name="create_note"/>
   </Menu>
   <Menu noMerge="1" name="settings">
    <text>&Settings</text>
diff --git a/kmail/kmreaderwin.cpp b/kmail/kmreaderwin.cpp
index 6fa5a12..063ae5b 100644
--- a/kmail/kmreaderwin.cpp
+++ b/kmail/kmreaderwin.cpp
@@ -925,5 +925,7 @@ KAction *KMReaderWin::createEventAction() const
     return mViewer->createEventAction();
 }
 
-
-
+KAction *KMReaderWin::createNoteAction() const
+{
+    return mViewer->createNoteAction();
+}
diff --git a/kmail/kmreaderwin.h b/kmail/kmreaderwin.h
index ee084ad..c95b22d 100644
--- a/kmail/kmreaderwin.h
+++ b/kmail/kmreaderwin.h
@@ -156,6 +156,7 @@ public:
     KAction *expandShortUrlAction() const;
     KAction *createTodoAction() const;
     KAction *createEventAction() const;
+    KAction *createNoteAction() const;
 
     KAction *editContactAction() const { return mEditContactAction; }
 


commit 8bec060a969cf958aea8b767ca138b6684f658ed
Author: Sandro Knauß <knauss at kolabsys.com>
Date:   Thu Jul 31 12:12:18 2014 +0200

    Create notes out of mails

diff --git a/messageviewer/CMakeLists.txt b/messageviewer/CMakeLists.txt
index 6b6b48a..b18af06 100644
--- a/messageviewer/CMakeLists.txt
+++ b/messageviewer/CMakeLists.txt
@@ -99,6 +99,7 @@ set(libmessageviewer_widgets_SRCS
   widgets/invitationsettings.cpp
   widgets/todoedit.cpp
   widgets/eventedit.cpp
+  widgets/noteedit.cpp
 )
 
 set(libmessageviewer_header_SRCS
@@ -154,6 +155,7 @@ set(libmessageviewer_antispam_SRCS
 set(libmessageviewer_job_SRCS
   job/createtodojob.cpp
   job/createeventjob.cpp
+  job/createnotejob.cpp
 )
 
 set(libmessageviewer_SRCS
@@ -189,6 +191,7 @@ target_link_libraries(messageviewer messagecore kdepim kpgp kleo
   ${KDEPIMLIBS_KMIME_LIBS}
   ${KDEPIMLIBS_KMBOX_LIBS}
   ${KDEPIMLIBS_AKONADI_LIBS}
+  ${KDEPIMLIBS_AKONADI_NOTES_LIBS}
   ${KDEPIMLIBS_AKONADI_KMIME_LIBS}
   ${KDEPIMLIBS_KPIMUTILS_LIBS}
   ${KDEPIMLIBS_KABC_LIBS}
diff --git a/messageviewer/job/createnotejob.cpp b/messageviewer/job/createnotejob.cpp
new file mode 100644
index 0000000..3364337
--- /dev/null
+++ b/messageviewer/job/createnotejob.cpp
@@ -0,0 +1,109 @@
+/*
+  Copyright (c) 2014 Sandro Knauß <knauss at kolabsys.com>
+
+  This program is free software; you can redistribute it and/or modify it
+  under the terms of the GNU General Public License, version 2, as
+  published by the Free Software Foundation.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License along
+  with this program; if not, write to the Free Software Foundation, Inc.,
+  51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "createnotejob.h"
+
+#include <Akonadi/KMime/MessageParts>
+#include <Akonadi/ItemFetchJob>
+#include <Akonadi/ItemFetchScope>
+#include <Akonadi/ItemCreateJob>
+
+#include <KMime/Message>
+#include <QApplication>
+#include <QDebug>
+
+using namespace MessageViewer;
+
+CreateNoteJob::CreateNoteJob(const KMime::Message::Ptr &notePtr, const Akonadi::Collection &collection, const Akonadi::Item &item, QObject *parent)
+    : KJob(parent),
+      mItem(item),
+      mCollection(collection),
+      mNote(notePtr)
+{
+}
+
+CreateNoteJob::~CreateNoteJob()
+{
+    qDebug()<<" CreateNoteJob::~CreateNoteJob()";
+}
+
+void CreateNoteJob::start()
+{
+    // We need the full payload to attach the mail
+    if ( !mItem.loadedPayloadParts().contains( Akonadi::MessagePart::Body ) ) {
+        Akonadi::ItemFetchJob *job = new Akonadi::ItemFetchJob( mItem );
+        job->fetchScope().fetchFullPayload();
+        connect( job, SIGNAL(result(KJob*)), this, SLOT(slotFetchDone(KJob*)) );
+
+        if ( job->exec() ) {
+            if ( job->items().count() == 1 ) {
+                mItem = job->items().first();
+            }
+        } else {
+            qDebug()<<" createNote: Error during fetch: "<<job->errorString();
+        }
+    } else {
+        createNote();
+    }
+}
+
+void CreateNoteJob::slotFetchDone(KJob *job)
+{
+    qDebug()<<" void CreateNoteJob::slotFetchDone(KJob *job)";
+    Akonadi::ItemFetchJob *fetchJob = qobject_cast<Akonadi::ItemFetchJob *>(job);
+    if ( fetchJob->items().count() == 1 ) {
+        mItem = fetchJob->items().first();
+    } else {
+        Q_EMIT emitResult();
+        return;
+    }
+    createNote();
+}
+
+void CreateNoteJob::createNote()
+{
+    if ( !mItem.hasPayload<KMime::Message::Ptr>() ) {
+        qDebug()<<" item has not payload";
+        Q_EMIT emitResult();
+        return;
+    }
+    KMime::Message::Ptr msg =  mItem.payload<KMime::Message::Ptr>();
+
+    Akonadi::NoteUtils::Attachment attachment(msg->encodedContent(), msg->mimeType());
+    const KMime::Headers::Subject * const subject = msg->subject(false);
+    if (subject)
+        attachment.setLabel(subject->asUnicodeString());
+    mNote.attachments().append(attachment);
+
+    mNote.setFrom(QCoreApplication::applicationName()+QCoreApplication::applicationVersion());
+    mNote.setLastModifiedDate(KDateTime::currentUtcDateTime());
+
+    Akonadi::Item newNoteItem;
+    newNoteItem.setMimeType( Akonadi::NoteUtils::noteMimeType() );
+    newNoteItem.setPayload( mNote.message() );
+
+    Akonadi::ItemCreateJob *createJob = new Akonadi::ItemCreateJob(newNoteItem, mCollection);
+    connect(createJob, SIGNAL(result(KJob*)), this, SLOT(slotCreateNewNote(KJob*)));
+}
+
+void CreateNoteJob::slotCreateNewNote(KJob *job)
+{
+    if ( job->error() ) {
+        qDebug() << "Error during create new Note "<<job->errorString();
+    }
+    Q_EMIT emitResult();
+}
diff --git a/messageviewer/job/createnotejob.h b/messageviewer/job/createnotejob.h
new file mode 100644
index 0000000..4749745
--- /dev/null
+++ b/messageviewer/job/createnotejob.h
@@ -0,0 +1,52 @@
+/*
+  Copyright (c) 2014 Sandro Knauß <knauss at kolabsys.com>
+
+  This program is free software; you can redistribute it and/or modify it
+  under the terms of the GNU General Public License, version 2, as
+  published by the Free Software Foundation.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License along
+  with this program; if not, write to the Free Software Foundation, Inc.,
+  51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef CREATENOTEJOB_H
+#define CREATENOTEJOB_H
+
+#include <KJob>
+#include <Akonadi/Item>
+#include <Akonadi/Collection>
+#include <Akonadi/Notes/NoteUtils>
+
+#include <kmime/kmime_message.h>
+
+#include <QObject>
+
+namespace MessageViewer {
+class CreateNoteJob : public KJob
+{
+    Q_OBJECT
+public:
+    explicit CreateNoteJob(const KMime::Message::Ptr &notePtr, const Akonadi::Collection &collection, const Akonadi::Item &item, QObject *parent = 0);
+    ~CreateNoteJob();
+
+    void start();
+
+private slots:
+    void slotFetchDone(KJob *job);
+    void slotCreateNewNote(KJob *job);
+
+private:
+    void createNote();
+    Akonadi::Item mItem;
+    Akonadi::Collection mCollection;
+    Akonadi::NoteUtils::NoteMessageWrapper mNote;
+};
+}
+
+#endif // CREATETODOJOB_H
diff --git a/messageviewer/settings/messageviewer.kcfg.cmake b/messageviewer/settings/messageviewer.kcfg.cmake
index 15cbf91..387cd39 100644
--- a/messageviewer/settings/messageviewer.kcfg.cmake
+++ b/messageviewer/settings/messageviewer.kcfg.cmake
@@ -318,6 +318,12 @@ xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0 http://www.kde.org/sta
         <default>-1</default>
       </entry>
     </group>
+    <group name="Note">
+      <entry name="LastNoteSelectedFolder" type="LongLong">
+        <whatsthis>The most recent selected folder using for Notes.</whatsthis>
+        <default>-1</default>
+      </entry>
+    </group>
 
 </kcfg>
 
diff --git a/messageviewer/tests/CMakeLists.txt b/messageviewer/tests/CMakeLists.txt
index 05fb29f..198913e 100644
--- a/messageviewer/tests/CMakeLists.txt
+++ b/messageviewer/tests/CMakeLists.txt
@@ -27,6 +27,7 @@ macro(add_messageviewer_unittest _source)
     ${KDE4_KIO_LIBS}
     ${KDEPIMLIBS_KMIME_LIBS}
     ${KDEPIMLIBS_AKONADI_LIBS}
+    ${KDEPIMLIBS_AKONADI_NOTES_LIBS}
     ${KDEPIMLIBS_KCALCORE_LIBS}
   )
 endmacro ()
@@ -40,6 +41,7 @@ add_messageviewer_unittest( unencryptedmessagetest.cpp )
 kde4_handle_crypto_rpath_for_executable( unencryptedmessagetest )
 add_messageviewer_unittest( todoedittest.cpp )
 add_messageviewer_unittest( eventedittest.cpp )
+add_messageviewer_unittest( noteedittest.cpp )
 ########### viewertest_gui ###############
 
 
diff --git a/messageviewer/tests/noteedittest.cpp b/messageviewer/tests/noteedittest.cpp
new file mode 100644
index 0000000..2562582
--- /dev/null
+++ b/messageviewer/tests/noteedittest.cpp
@@ -0,0 +1,430 @@
+/*
+  Copyright (c) 2014 Sandro Knauß <knauss at kolabsys.com>
+
+  This program is free software; you can redistribute it and/or modify it
+  under the terms of the GNU General Public License, version 2, as
+  published by the Free Software Foundation.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License along
+  with this program; if not, write to the Free Software Foundation, Inc.,
+  51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "noteedittest.h"
+#include "messageviewer/globalsettings_base.h"
+#include "widgets/noteedit.h"
+#include <Akonadi/Collection>
+#include <Akonadi/CollectionComboBox>
+#include <Akonadi/EntityTreeModel>
+
+#include <KMime/KMimeMessage>
+#include <QStandardItemModel>
+#include <KPushButton>
+#include <KMessageWidget>
+#include <qtest_kde.h>
+#include <qtestkeyboard.h>
+#include <qtestmouse.h>
+
+#include <QLineEdit>
+#include <QHBoxLayout>
+#include <QShortcut>
+#include <QAction>
+
+namespace MessageViewer {
+extern MESSAGEVIEWER_EXPORT QAbstractItemModel *_k_noteEditStubModel;
+}
+
+
+Q_DECLARE_METATYPE(KMime::Message::Ptr)
+NoteEditTest::NoteEditTest()
+{
+    qRegisterMetaType<Akonadi::Collection>();
+    qRegisterMetaType<KMime::Message::Ptr>();
+
+    QStandardItemModel *model = new QStandardItemModel;
+    for (int id = 42; id < 51; ++id) {
+        Akonadi::Collection collection(id);
+        collection.setRights(Akonadi::Collection::AllRights);
+        collection.setName(QString::number(id));
+        collection.setContentMimeTypes(QStringList() << Akonadi::NoteUtils::noteMimeType());
+
+        QStandardItem *item = new QStandardItem(collection.name());
+        item->setData(QVariant::fromValue(collection),
+                      Akonadi::EntityTreeModel::CollectionRole);
+        item->setData(QVariant::fromValue(collection.id()),
+                      Akonadi::EntityTreeModel::CollectionIdRole);
+
+        model->appendRow(item);
+    }
+    MessageViewer::_k_noteEditStubModel = model;
+}
+
+void NoteEditTest::shouldHaveDefaultValuesOnCreation()
+{
+    MessageViewer::NoteEdit edit;
+    //We can't test if because it loads from settings and in Jenkins it doesn't exist but here it exists
+    //QVERIFY(edit.collection().isValid());
+    QVERIFY(!edit.message());
+    QLineEdit *noteedit = qFindChild<QLineEdit *>(&edit, QLatin1String("noteedit"));
+    KPushButton *save = qFindChild<KPushButton *>(&edit, QLatin1String("save-button"));
+    QVERIFY(save);
+    QCOMPARE(save->isEnabled(), false);
+    QVERIFY(noteedit);
+    QCOMPARE(noteedit->text(), QString());
+}
+
+void NoteEditTest::shouldEmitCollectionChanged()
+{
+    MessageViewer::NoteEdit edit;
+    QSignalSpy spy(&edit, SIGNAL(collectionChanged(Akonadi::Collection)));
+    edit.setCollection(Akonadi::Collection(42));
+    QCOMPARE(spy.count(), 1);
+    QCOMPARE(spy.at(0).at(0).value<Akonadi::Collection>(), Akonadi::Collection(42));
+}
+
+void NoteEditTest::shouldEmitMessageChanged()
+{
+    MessageViewer::NoteEdit edit;
+    QSignalSpy spy(&edit, SIGNAL(messageChanged(KMime::Message::Ptr)));
+    KMime::Message::Ptr msg(new KMime::Message);
+    edit.setMessage(msg);
+    QCOMPARE(spy.count(), 1);
+    QCOMPARE(spy.at(0).at(0).value<KMime::Message::Ptr>(), msg);
+}
+
+void NoteEditTest::shouldNotEmitWhenCollectionIsNotChanged()
+{
+    MessageViewer::NoteEdit edit;
+    edit.setCollection(Akonadi::Collection(42));
+    QSignalSpy spy(&edit, SIGNAL(collectionChanged(Akonadi::Collection)));
+    edit.setCollection(Akonadi::Collection(42));
+    QCOMPARE(spy.count(), 0);
+}
+
+
+void NoteEditTest::shouldNotEmitWhenMessageIsNotChanged()
+{
+    MessageViewer::NoteEdit edit;
+    KMime::Message::Ptr msg(new KMime::Message);
+    edit.setMessage(msg);
+    QSignalSpy spy(&edit, SIGNAL(messageChanged(KMime::Message::Ptr)));
+    edit.setMessage(msg);
+    QCOMPARE(spy.count(), 0);
+}
+
+void NoteEditTest::shouldHaveSameValueAfterSet()
+{
+    MessageViewer::NoteEdit edit;
+    KMime::Message::Ptr msg(new KMime::Message);
+    edit.setCollection(Akonadi::Collection(42));
+    edit.setMessage(msg);
+    QCOMPARE(edit.collection(), Akonadi::Collection(42));
+    QCOMPARE(edit.message(), msg);
+}
+
+void NoteEditTest::shouldHaveASubject()
+{
+    MessageViewer::NoteEdit edit;
+    KMime::Message::Ptr msg(new KMime::Message);
+
+    QLineEdit *noteedit = qFindChild<QLineEdit *>(&edit, QLatin1String("noteedit"));
+    QVERIFY(noteedit);
+    QCOMPARE(noteedit->text(), QString());
+
+    QString subject = QLatin1String("Test Note");
+    msg->subject(true)->fromUnicodeString(subject, "us-ascii");
+    edit.setMessage(msg);
+
+    QCOMPARE(noteedit->text(), subject);
+}
+
+void NoteEditTest::shouldEmptySubjectWhenMessageIsNull()
+{
+    MessageViewer::NoteEdit edit;
+    KMime::Message::Ptr msg(new KMime::Message);
+    QString subject = QLatin1String("Test Note");
+    msg->subject(true)->fromUnicodeString(subject, "us-ascii");
+    edit.setMessage(msg);
+    QLineEdit *noteedit = qFindChild<QLineEdit *>(&edit, QLatin1String("noteedit"));
+    edit.setMessage(KMime::Message::Ptr());
+    QCOMPARE(noteedit->text(), QString());
+}
+
+void NoteEditTest::shouldEmptySubjectWhenMessageHasNotSubject()
+{
+    MessageViewer::NoteEdit edit;
+    KMime::Message::Ptr msg(new KMime::Message);
+    QString subject = QLatin1String("Test Note");
+    msg->subject(true)->fromUnicodeString(subject, "us-ascii");
+    edit.setMessage(msg);
+    QLineEdit *noteedit = qFindChild<QLineEdit *>(&edit, QLatin1String("noteedit"));
+    KMime::Message::Ptr msgSubjectEmpty(new KMime::Message);
+    edit.setMessage(msgSubjectEmpty);
+    QCOMPARE(noteedit->text(), QString());
+}
+
+void NoteEditTest::shouldSelectLineWhenPutMessage()
+{
+    MessageViewer::NoteEdit edit;
+    KMime::Message::Ptr msg(new KMime::Message);
+    QString subject = QLatin1String("Test Note");
+    msg->subject(true)->fromUnicodeString(subject, "us-ascii");
+    edit.setMessage(msg);
+    QLineEdit *noteedit = qFindChild<QLineEdit *>(&edit, QLatin1String("noteedit"));
+    QVERIFY(noteedit->hasSelectedText());
+    const QString selectedText = noteedit->selectedText();
+    QCOMPARE(selectedText, subject);
+}
+
+void NoteEditTest::shouldEmitCollectionChangedWhenChangeComboboxItem()
+{
+    MessageViewer::NoteEdit edit;
+    Akonadi::CollectionComboBox *akonadicombobox = qFindChild<Akonadi::CollectionComboBox *>(&edit, QLatin1String("akonadicombobox"));
+    QVERIFY(akonadicombobox);
+    QVERIFY(akonadicombobox->currentCollection().isValid());
+}
+
+void NoteEditTest::shouldEmitNotEmitNoteWhenTextIsEmpty()
+{
+    MessageViewer::NoteEdit edit;
+    KMime::Message::Ptr msg(new KMime::Message);
+    edit.setMessage(msg);
+    QLineEdit *noteedit = qFindChild<QLineEdit *>(&edit, QLatin1String("noteedit"));
+    QSignalSpy spy(&edit, SIGNAL(createNote(KMime::Message::Ptr,Akonadi::Collection)));
+    QTest::keyClick(noteedit, Qt::Key_Enter);
+    QCOMPARE(spy.count(), 0);
+}
+
+void NoteEditTest::shouldEmitNotEmitNoteWhenTextTrimmedIsEmpty()
+{
+    MessageViewer::NoteEdit edit;
+    KMime::Message::Ptr msg(new KMime::Message);
+    edit.setMessage(msg);
+    QLineEdit *noteedit = qFindChild<QLineEdit *>(&edit, QLatin1String("noteedit"));
+    QSignalSpy spy(&edit, SIGNAL(createNote(KMime::Message::Ptr,Akonadi::Collection)));
+    noteedit->setText(QLatin1String("      "));
+    QTest::keyClick(noteedit, Qt::Key_Enter);
+    QCOMPARE(spy.count(), 0);
+
+    noteedit->setText(QLatin1String("      F"));
+    QTest::keyClick(noteedit, Qt::Key_Enter);
+    QCOMPARE(spy.count(), 1);
+}
+
+void NoteEditTest::shouldEmitNoteWhenPressEnter()
+{
+    MessageViewer::NoteEdit edit;
+    KMime::Message::Ptr msg(new KMime::Message);
+    QString subject = QLatin1String("Test Note");
+    msg->subject(true)->fromUnicodeString(subject, "us-ascii");
+    edit.setMessage(msg);
+    QLineEdit *noteedit = qFindChild<QLineEdit *>(&edit, QLatin1String("noteedit"));
+    QSignalSpy spy(&edit, SIGNAL(createNote(KMime::Message::Ptr,Akonadi::Collection)));
+    QTest::keyClick(noteedit, Qt::Key_Enter);
+    QCOMPARE(spy.count(), 1);
+}
+
+void NoteEditTest::shouldNoteHasCorrectSubject()
+{
+    MessageViewer::NoteEdit edit;
+    KMime::Message::Ptr msg(new KMime::Message);
+    QString subject = QLatin1String("Test Note");
+    msg->subject(true)->fromUnicodeString(subject, "us-ascii");
+    edit.setMessage(msg);
+    QLineEdit *noteedit = qFindChild<QLineEdit *>(&edit, QLatin1String("noteedit"));
+    QSignalSpy spy(&edit, SIGNAL(createNote(KMime::Message::Ptr,Akonadi::Collection)));
+    QTest::keyClick(noteedit, Qt::Key_Enter);
+    QCOMPARE(spy.count(), 1);
+    KMime::Message::Ptr notePtr = spy.at(0).at(0).value<KMime::Message::Ptr>();
+    QVERIFY(notePtr);
+    Akonadi::NoteUtils::NoteMessageWrapper note(notePtr);
+    QCOMPARE(note.title(), subject);
+}
+
+void NoteEditTest::shouldClearAllWhenCloseWidget()
+{
+    MessageViewer::NoteEdit edit;
+    KMime::Message::Ptr msg(new KMime::Message);
+    QString subject = QLatin1String("Test Note");
+    msg->subject(true)->fromUnicodeString(subject, "us-ascii");
+    edit.setMessage(msg);
+    QLineEdit *noteedit = qFindChild<QLineEdit *>(&edit, QLatin1String("noteedit"));
+    edit.slotCloseWidget();
+    QCOMPARE(noteedit->text(), QString());
+    QVERIFY(!edit.message());
+}
+
+void NoteEditTest::shouldEmitCollectionChangedWhenCurrentCollectionWasChanged()
+{
+    MessageViewer::NoteEdit edit;
+    Akonadi::CollectionComboBox *akonadicombobox = qFindChild<Akonadi::CollectionComboBox *>(&edit, QLatin1String("akonadicombobox"));
+    akonadicombobox->setCurrentIndex(0);
+    QCOMPARE(akonadicombobox->currentIndex(), 0);
+    QSignalSpy spy(&edit, SIGNAL(collectionChanged(Akonadi::Collection)));
+    akonadicombobox->setCurrentIndex(3);
+    QCOMPARE(akonadicombobox->currentIndex(), 3);
+    QCOMPARE(spy.count(), 1);
+}
+
+void NoteEditTest::shouldEmitCorrectCollection()
+{
+    MessageViewer::NoteEdit edit;
+    Akonadi::CollectionComboBox *akonadicombobox = qFindChild<Akonadi::CollectionComboBox *>(&edit, QLatin1String("akonadicombobox"));
+    KMime::Message::Ptr msg(new KMime::Message);
+    QString subject = QLatin1String("Test Note");
+    msg->subject(true)->fromUnicodeString(subject, "us-ascii");
+    edit.setMessage(msg);
+    akonadicombobox->setCurrentIndex(3);
+    Akonadi::Collection col = akonadicombobox->currentCollection();
+    QLineEdit *noteedit = qFindChild<QLineEdit *>(&edit, QLatin1String("noteedit"));
+    QSignalSpy spy(&edit, SIGNAL(createNote(KMime::Message::Ptr,Akonadi::Collection)));
+    QTest::keyClick(noteedit, Qt::Key_Enter);
+    QCOMPARE(spy.count(), 1);
+    QCOMPARE(spy.at(0).at(1).value<Akonadi::Collection>(), col);
+}
+
+void NoteEditTest::shouldHideWidgetWhenClickOnCloseButton()
+{
+    MessageViewer::NoteEdit edit;
+    edit.show();
+    QTest::qWaitForWindowShown(&edit);
+    QVERIFY(edit.isVisible());
+    KPushButton *close = qFindChild<KPushButton *>(&edit, QLatin1String("close-button"));
+    QTest::mouseClick(close, Qt::LeftButton);
+    QCOMPARE(edit.isVisible(), false);
+}
+
+void NoteEditTest::shouldHideWidgetWhenPressEscape()
+{
+    MessageViewer::NoteEdit edit;
+    edit.show();
+    QTest::qWaitForWindowShown(&edit);
+    QLineEdit *noteedit = qFindChild<QLineEdit *>(&edit, QLatin1String("noteedit"));
+    noteedit->setFocus();
+    QVERIFY(noteedit->hasFocus());
+    QTest::keyPress(&edit, Qt::Key_Escape);
+    QCOMPARE(edit.isVisible(), false);
+}
+
+void NoteEditTest::shouldHideWidgetWhenSaveClicked()
+{
+    MessageViewer::NoteEdit edit;
+    edit.show();
+    QTest::qWaitForWindowShown(&edit);
+
+    KMime::Message::Ptr msg(new KMime::Message);
+    msg->subject(true)->fromUnicodeString(QLatin1String("Test Note"), "us-ascii");
+    edit.setMessage(msg);
+    KPushButton *save = qFindChild<KPushButton *>(&edit, QLatin1String("save-button"));
+    QTest::mouseClick(save, Qt::LeftButton);
+    QCOMPARE(edit.isVisible(), false);
+}
+
+void NoteEditTest::shouldSaveCollectionSettings()
+{
+    MessageViewer::NoteEdit edit;
+    Akonadi::CollectionComboBox *akonadicombobox = qFindChild<Akonadi::CollectionComboBox *>(&edit, QLatin1String("akonadicombobox"));
+    akonadicombobox->setCurrentIndex(3);
+    const Akonadi::Collection::Id id = akonadicombobox->currentCollection().id();
+    KPushButton *close = qFindChild<KPushButton *>(&edit, QLatin1String("close-button"));
+    QTest::mouseClick(close, Qt::LeftButton);
+    QCOMPARE(MessageViewer::GlobalSettingsBase::self()->lastNoteSelectedFolder(), id);
+}
+
+void NoteEditTest::shouldSaveCollectionSettingsWhenCloseWidget()
+{
+    MessageViewer::NoteEdit edit;
+    Akonadi::CollectionComboBox *akonadicombobox = qFindChild<Akonadi::CollectionComboBox *>(&edit, QLatin1String("akonadicombobox"));
+    akonadicombobox->setCurrentIndex(4);
+    const Akonadi::Collection::Id id = akonadicombobox->currentCollection().id();
+    edit.writeConfig();
+    QCOMPARE(MessageViewer::GlobalSettingsBase::self()->lastNoteSelectedFolder(), id);
+}
+
+void NoteEditTest::shouldSaveCollectionSettingsWhenDeleteWidget()
+{
+    MessageViewer::NoteEdit *edit = new MessageViewer::NoteEdit;
+    Akonadi::CollectionComboBox *akonadicombobox = qFindChild<Akonadi::CollectionComboBox *>(edit, QLatin1String("akonadicombobox"));
+    akonadicombobox->setCurrentIndex(4);
+    const Akonadi::Collection::Id id = akonadicombobox->currentCollection().id();
+    delete edit;
+    QCOMPARE(MessageViewer::GlobalSettingsBase::self()->lastNoteSelectedFolder(), id);
+}
+
+void NoteEditTest::shouldSetFocusWhenWeCallNoteEdit()
+{
+    MessageViewer::NoteEdit edit;
+    edit.show();
+    QTest::qWaitForWindowShown(&edit);
+    KMime::Message::Ptr msg(new KMime::Message);
+    QString subject = QLatin1String("Test Note");
+    msg->subject(true)->fromUnicodeString(subject, "us-ascii");
+    edit.setMessage(msg);
+    QLineEdit *noteedit = qFindChild<QLineEdit *>(&edit, QLatin1String("noteedit"));
+    QCOMPARE(noteedit->hasFocus(), true);
+    edit.setFocus();
+    QCOMPARE(noteedit->hasFocus(), false);
+    edit.showNoteEdit();
+    QCOMPARE(noteedit->hasFocus(), true);
+}
+
+
+void NoteEditTest::shouldNotEmitNoteWhenMessageIsNull()
+{
+    MessageViewer::NoteEdit edit;
+    QString subject = QLatin1String("Test Note");
+    QLineEdit *noteedit = qFindChild<QLineEdit *>(&edit, QLatin1String("noteedit"));
+    noteedit->setText(subject);
+    QSignalSpy spy(&edit, SIGNAL(createNote(KMime::Message::Ptr,Akonadi::Collection)));
+    QTest::keyClick(noteedit, Qt::Key_Enter);
+    QCOMPARE(spy.count(), 0);
+}
+
+void NoteEditTest::shouldClearLineAfterEmitNewNote()
+{
+    MessageViewer::NoteEdit edit;
+    KMime::Message::Ptr msg(new KMime::Message);
+    QString subject = QLatin1String("Test Note");
+    msg->subject(true)->fromUnicodeString(subject, "us-ascii");
+    edit.setMessage(msg);
+    QLineEdit *noteedit = qFindChild<QLineEdit *>(&edit, QLatin1String("noteedit"));
+    QTest::keyClick(noteedit, Qt::Key_Enter);
+    QCOMPARE(noteedit->text(), QString());
+}
+
+void NoteEditTest::shouldHaveLineEditFocus()
+{
+    MessageViewer::NoteEdit edit;
+    edit.show();
+    QTest::qWaitForWindowShown(&edit);
+    KMime::Message::Ptr msg(new KMime::Message);
+    QString subject = QLatin1String("Test Note");
+    msg->subject(true)->fromUnicodeString(subject, "us-ascii");
+    edit.setMessage(msg);
+    QLineEdit *noteedit = qFindChild<QLineEdit *>(&edit, QLatin1String("noteedit"));
+    QCOMPARE(noteedit->hasFocus(), true);
+}
+
+void NoteEditTest::shouldShouldEnabledSaveEditorButton()
+{
+    MessageViewer::NoteEdit edit;
+    KMime::Message::Ptr msg(new KMime::Message);
+    msg->subject(true)->fromUnicodeString(QLatin1String("Test note"), "us-ascii");
+    edit.setMessage(msg);
+
+    QLineEdit *noteedit = qFindChild<QLineEdit *>(&edit, QLatin1String("noteedit"));
+    KPushButton *save = qFindChild<KPushButton *>(&edit, QLatin1String("save-button"));
+    QCOMPARE(save->isEnabled(), true);
+    noteedit->clear();
+
+    QCOMPARE(save->isEnabled(), false);
+}
+
+
+
+QTEST_KDEMAIN( NoteEditTest, GUI )
diff --git a/messageviewer/tests/noteedittest.h b/messageviewer/tests/noteedittest.h
new file mode 100644
index 0000000..9a00ade
--- /dev/null
+++ b/messageviewer/tests/noteedittest.h
@@ -0,0 +1,63 @@
+/*
+  Copyright (c) 2014 Sandro Knauß <knauss at kolabsys.com>
+
+  This program is free software; you can redistribute it and/or modify it
+  under the terms of the GNU General Public License, version 2, as
+  published by the Free Software Foundation.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License along
+  with this program; if not, write to the Free Software Foundation, Inc.,
+  51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef NOTEEDITTEST_H
+#define NOTEEDITTEST_H
+
+#include <QObject>
+
+
+class NoteEditTest : public QObject
+{
+    Q_OBJECT
+public:
+    NoteEditTest();
+
+private slots:
+    void shouldNotEmitWhenMessageIsNotChanged();
+    void shouldHaveDefaultValuesOnCreation();
+    void shouldEmitCollectionChanged();
+    void shouldEmitMessageChanged();
+    void shouldNotEmitWhenCollectionIsNotChanged();
+    void shouldHaveSameValueAfterSet();
+    void shouldHaveASubject();
+    void shouldEmptySubjectWhenMessageIsNull();
+    void shouldEmptySubjectWhenMessageHasNotSubject();
+    void shouldSelectLineWhenPutMessage();
+    void shouldEmitCollectionChangedWhenChangeComboboxItem();
+    void shouldEmitNoteWhenPressEnter();
+    void shouldEmitNotEmitNoteWhenTextIsEmpty();
+    void shouldNoteHasCorrectSubject();
+    void shouldClearAllWhenCloseWidget();
+    void shouldEmitCollectionChangedWhenCurrentCollectionWasChanged();
+    void shouldClearLineAfterEmitNewNote();
+    void shouldEmitCorrectCollection();
+    void shouldHideWidgetWhenClickOnCloseButton();
+    void shouldHideWidgetWhenPressEscape();
+    void shouldHideWidgetWhenSaveClicked();
+    void shouldSaveCollectionSettings();
+    void shouldSaveCollectionSettingsWhenCloseWidget();
+    void shouldNotEmitNoteWhenMessageIsNull();
+    void shouldHaveLineEditFocus();
+    void shouldEmitNotEmitNoteWhenTextTrimmedIsEmpty();
+    void shouldSaveCollectionSettingsWhenDeleteWidget();
+    void shouldSetFocusWhenWeCallNoteEdit();
+    void shouldShouldEnabledSaveEditorButton();
+};
+
+#endif // NOTEEDITTEST_H
+
diff --git a/messageviewer/tests/viewertest.cpp b/messageviewer/tests/viewertest.cpp
index 2908162..f9b378b 100644
--- a/messageviewer/tests/viewertest.cpp
+++ b/messageviewer/tests/viewertest.cpp
@@ -82,4 +82,24 @@ void ViewerTest::shouldShowCreateTodoWidgetWhenActivateItAndWeHaveAMessage()
     QCOMPARE(createtodowidget->isVisible(), true);
 }
 
+void ViewerTest::shouldShowCreateNoteWidgetWhenActivateItAndWeHaveAMessage()
+{
+  MessageViewer::Viewer viewer(0, 0, new KActionCollection(this));
+  viewer.show();
+  QTest::qWaitForWindowShown(&viewer);
+  QWidget *createnotewidget = qFindChild<QWidget *>(&viewer, QLatin1String("createnotewidget"));
+  QVERIFY(viewer.createNoteAction());
+
+  viewer.createNoteAction()->trigger();
+  //No message => we can show it.
+  QCOMPARE(createnotewidget->isVisible(), false);
+
+  KMime::Message::Ptr msg(new KMime::Message);
+  viewer.setMessage(msg);
+
+  viewer.createNoteAction()->trigger();
+  QCOMPARE(createnotewidget->isVisible(), true);
+}
+
+
 QTEST_KDEMAIN( ViewerTest, GUI )
diff --git a/messageviewer/tests/viewertest.h b/messageviewer/tests/viewertest.h
index ac362ff..cb9ee22 100644
--- a/messageviewer/tests/viewertest.h
+++ b/messageviewer/tests/viewertest.h
@@ -27,6 +27,7 @@ public:
 private slots:
     void shouldHaveDefaultValuesOnCreation();
     void shouldShowCreateTodoWidgetWhenActivateItAndWeHaveAMessage();
+    void shouldShowCreateNoteWidgetWhenActivateItAndWeHaveAMessage();
 };
 
 #endif // VIEWERTEST_H
diff --git a/messageviewer/viewer/viewer.cpp b/messageviewer/viewer/viewer.cpp
index f6a9604..0e2d8a4 100644
--- a/messageviewer/viewer/viewer.cpp
+++ b/messageviewer/viewer/viewer.cpp
@@ -701,6 +701,12 @@ KAction *Viewer::createEventAction()
     return d->mCreateEventAction;
 }
 
+KAction *Viewer::createNoteAction()
+{
+    Q_D( Viewer );
+    return d->mCreateNoteAction;
+}
+
 }
 
 
diff --git a/messageviewer/viewer/viewer.h b/messageviewer/viewer/viewer.h
index 9fa24d8..64d8b41 100644
--- a/messageviewer/viewer/viewer.h
+++ b/messageviewer/viewer/viewer.h
@@ -285,6 +285,7 @@ public:
     KAction *expandShortUrlAction();
     KAction *createTodoAction();
     KAction *createEventAction();
+    KAction *createNoteAction();
 
     HeaderStrategy * headerStrategy() const;
 
diff --git a/messageviewer/viewer/viewer_p.cpp b/messageviewer/viewer/viewer_p.cpp
index fa0070b..705f46a 100644
--- a/messageviewer/viewer/viewer_p.cpp
+++ b/messageviewer/viewer/viewer_p.cpp
@@ -34,6 +34,7 @@
 #include "adblock/adblockmanager.h"
 #include "widgets/todoedit.h"
 #include "widgets/eventedit.h"
+#include "widgets/noteedit.h"
 
 #ifdef MESSAGEVIEWER_READER_HTML_DEBUG
 #include "htmlwriter/filehtmlwriter.h"
@@ -138,6 +139,7 @@
 #include "pimcommon/translator/translatorwidget.h"
 #include "job/createtodojob.h"
 #include "job/createeventjob.h"
+#include "job/createnotejob.h"
 
 #include "interfaces/bodypart.h"
 #include "interfaces/htmlwriter.h"
@@ -1547,6 +1549,11 @@ void ViewerPrivate::createWidgets() {
     mCreateEvent->setObjectName(QLatin1String("createeventwidget"));
     mCreateEvent->hide();
 
+    mCreateNote = new MessageViewer::NoteEdit(readerBox);
+    connect(mCreateNote, SIGNAL(createNote(KMime::Message::Ptr,Akonadi::Collection)), this, SLOT(slotCreateNote(KMime::Message::Ptr,Akonadi::Collection)));
+    mCreateNote->setObjectName(QLatin1String("createnotewidget"));
+    mCreateNote->hide();
+
     mFindBar = new FindBarMailWebView( mViewer, readerBox );
     mTranslatorWidget = new PimCommon::TranslatorWidget(readerBox);
 #ifndef QT_NO_TREEVIEW
@@ -1877,6 +1884,13 @@ void ViewerPrivate::createActions()
     //TODO
     //mCreateEventAction->setShortcut(Qt::CTRL + Qt::Key_T);
     connect( mCreateEventAction, SIGNAL(triggered(bool)), SLOT(slotShowCreateEventWidget()) );
+
+    mCreateNoteAction = new KAction(KIcon( QLatin1String("view-pim-notes") ),i18nc("create a new note out of this message", "Create Note"), this);
+    mCreateNoteAction->setIconText( i18nc("create a new note out of this message", "Create Note") );
+    mCreateNoteAction->setHelpText( i18n("Allows you to create a note from this message") );
+    mCreateNoteAction->setWhatsThis( i18n( "This option starts a editor to create a note. Then you can edit the note to your liking before saving it." ) );
+    ac->addAction(QLatin1String("create_note"), mCreateNoteAction);
+    connect( mCreateNoteAction, SIGNAL(triggered(bool)), SLOT(slotShowCreateNoteWidget()) );
 }
 
 
@@ -3418,3 +3432,19 @@ void ViewerPrivate::slotCreateEvent(const KCalCore::Event::Ptr &eventPtr, const
     CreateEventJob *createJob = new CreateEventJob(eventPtr, collection, mMessageItem, this);
     createJob->start();
 }
+
+void ViewerPrivate::slotShowCreateNoteWidget()
+{
+    if (mMessage) {
+        mCreateNote->setMessage(mMessage);
+        mCreateNote->showNoteEdit();
+    } else {
+        qDebug()<<" There is not valid message";
+    }
+}
+
+void ViewerPrivate::slotCreateNote(const KMime::Message::Ptr &notePtr, const Akonadi::Collection &collection)
+{
+    CreateNoteJob *createJob = new CreateNoteJob(notePtr, collection, mMessageItem, this);
+    createJob->start();
+}
diff --git a/messageviewer/viewer/viewer_p.h b/messageviewer/viewer/viewer_p.h
index 8890f03..819df31 100644
--- a/messageviewer/viewer/viewer_p.h
+++ b/messageviewer/viewer/viewer_p.h
@@ -26,6 +26,7 @@
 
 #include <akonadi/item.h>
 #include <akonadi/monitor.h>
+#include <Akonadi/Notes/NoteUtils>
 #include <kio/job.h>
 #include <kmime/kmime_message.h>
 #include <kservice.h>
@@ -60,6 +61,7 @@ class QTreeView;
 namespace MessageViewer {
 class TodoEdit;
 class EventEdit;
+class NoteEdit;
 class EditorWatcher;
 class HtmlWriter;
 class CSSHelper;
@@ -502,6 +504,8 @@ private slots:
 
     void slotCreateEvent(const KCalCore::Event::Ptr &eventPtr, const Akonadi::Collection &collection);
 
+    void slotCreateNote(const  KMime::Message::Ptr &notePtr, const Akonadi::Collection &collection);
+
 public slots:
     /** An URL has been activate with a click. */
     void slotUrlOpen( const QUrl &url = QUrl());
@@ -615,6 +619,7 @@ public slots:
     void slotExpandShortUrl();
     void slotShowCreateTodoWidget();
     void slotShowCreateEventWidget();
+    void slotShowCreateNoteWidget();
 
 signals:
     void showStatusBarMessage( const QString &message );
@@ -692,6 +697,7 @@ public:
     KAction *mExpandUrlAction;
     KAction *mCreateTodoAction;
     KAction *mCreateEventAction;
+    KAction *mCreateNoteAction;
     KUrl mHoveredUrl;
     KUrl mClickedUrl;
     KUrl mImageUrl;
@@ -729,6 +735,7 @@ public:
     ScamDetectionWarningWidget *mScamDetectionWarning;
     MessageViewer::TodoEdit *mCreateTodo;
     MessageViewer::EventEdit *mCreateEvent;
+    MessageViewer::NoteEdit *mCreateNote;
     // zoom Factor
     static const qreal zoomBy;
     qreal mZoomFactor;
diff --git a/messageviewer/widgets/noteedit.cpp b/messageviewer/widgets/noteedit.cpp
new file mode 100644
index 0000000..9d9df41
--- /dev/null
+++ b/messageviewer/widgets/noteedit.cpp
@@ -0,0 +1,246 @@
+/*
+  Copyright (c) 2014 Sandro Knauß <knauss at kolabsys.com>*
+
+  This program is free software; you can redistribute it and/or modify it
+  under the terms of the GNU General Public License, version 2, as
+  published by the Free Software Foundation.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License along
+  with this program; if not, write to the Free Software Foundation, Inc.,
+  51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "noteedit.h"
+
+#include "messageviewer/globalsettings_base.h"
+
+#include <KLocalizedString>
+#include <KLineEdit>
+#include <KIcon>
+#include <KDateTimeEdit>
+
+#include <QHBoxLayout>
+#include <QEvent>
+#include <QKeyEvent>
+#include <QLabel>
+
+#include <Akonadi/CollectionComboBox>
+#include <KPushButton>
+
+#include <incidenceeditor-ng/incidencedialogfactory.h>
+#include <incidenceeditor-ng/incidencedialog.h>
+
+namespace MessageViewer {
+MESSAGEVIEWER_EXPORT QAbstractItemModel *_k_noteEditStubModel = 0;
+}
+
+using namespace MessageViewer;
+
+NoteEdit::NoteEdit(QWidget *parent)
+    : QWidget(parent)
+{
+    QVBoxLayout *vbox = new QVBoxLayout;
+    vbox->setMargin(5);
+    vbox->setSpacing(2);
+    setLayout(vbox);
+
+    QHBoxLayout *hbox = new QHBoxLayout;
+    hbox->setMargin(0);
+    hbox->setSpacing(2);
+    vbox->addLayout(hbox);
+
+    QLabel *lab = new QLabel(i18n("Note:"));
+    hbox->addWidget(lab);
+
+    mNoteEdit = new KLineEdit;
+    mNoteEdit->setClearButtonShown(true);
+    mNoteEdit->setObjectName(QLatin1String("noteedit"));
+    mNoteEdit->setFocus();
+    connect(mNoteEdit, SIGNAL(returnPressed()), SLOT(slotReturnPressed()));
+    connect(mNoteEdit, SIGNAL(textChanged(QString)), SLOT(slotUpdateButtons(QString)));
+    hbox->addWidget(mNoteEdit);
+
+    hbox->addSpacing(5);
+
+    mCollectionCombobox = new Akonadi::CollectionComboBox(_k_noteEditStubModel);
+    mCollectionCombobox->setAccessRightsFilter(Akonadi::Collection::CanCreateItem);
+    mCollectionCombobox->setMinimumWidth(250);
+    mCollectionCombobox->setMimeTypeFilter( QStringList() << Akonadi::NoteUtils::noteMimeType() );
+    mCollectionCombobox->setObjectName(QLatin1String("akonadicombobox"));
+#ifndef QT_NO_ACCESSIBILITY
+    mCollectionCombobox->setAccessibleDescription(i18n("Calendar where the new event will be stored."));
+#endif
+    mCollectionCombobox->setToolTip(i18n("Calendar where the new event will be stored."));
+
+    connect(mCollectionCombobox, SIGNAL(currentIndexChanged(int)), SLOT(slotCollectionChanged(int)));
+    connect(mCollectionCombobox, SIGNAL(activated(int)), SLOT(slotCollectionChanged(int)));
+    hbox->addWidget(mCollectionCombobox);
+
+    hbox = new QHBoxLayout;
+    hbox->setMargin(0);
+    hbox->setSpacing(2);
+    vbox->addLayout(hbox);
+
+    hbox->addStretch(1);
+
+    hbox = new QHBoxLayout;
+    hbox->setSpacing(2);
+    hbox->setMargin(0);
+    vbox->addLayout(hbox);
+
+    hbox->addStretch(1);
+
+    mSaveButton = new KPushButton(KIcon(QLatin1String("view-pim-notes")), i18n("&Save"));
+    mSaveButton->setObjectName(QLatin1String("save-button"));
+    mSaveButton->setEnabled(false);
+#ifndef QT_NO_ACCESSIBILITY
+    mSaveButton->setAccessibleDescription(i18n("Create new note and close this widget."));
+#endif
+    connect(mSaveButton, SIGNAL(clicked(bool)), this, SLOT(slotReturnPressed()));
+    hbox->addWidget(mSaveButton);
+
+    KPushButton *btn = new KPushButton(KStandardGuiItem::cancel());
+    btn->setObjectName(QLatin1String("close-button"));
+#ifndef QT_NO_ACCESSIBILITY
+    btn->setAccessibleDescription(i18n("Close the widget for creating new notes."));
+#endif
+    connect(btn, SIGNAL(clicked(bool)), this, SLOT(slotCloseWidget()));
+    hbox->addWidget(btn);
+
+    readConfig();
+    setSizePolicy( QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Fixed ) );
+    installEventFilter(this);
+    mCollectionCombobox->installEventFilter(this);
+}
+
+NoteEdit::~NoteEdit()
+{
+    writeConfig();
+}
+
+void NoteEdit::writeConfig()
+{
+    if (mCollectionCombobox->currentCollection().id() != MessageViewer::GlobalSettingsBase::self()->lastNoteSelectedFolder()) {
+        MessageViewer::GlobalSettingsBase::self()->setLastNoteSelectedFolder(mCollectionCombobox->currentCollection().id());
+        MessageViewer::GlobalSettingsBase::self()->writeConfig();
+    }
+}
+
+void NoteEdit::slotUpdateButtons(const QString &subject)
+{
+    const bool subjectIsNotEmpty = !subject.isEmpty();
+    mSaveButton->setEnabled(subjectIsNotEmpty);
+}
+
+void NoteEdit::showNoteEdit()
+{
+    mNoteEdit->setFocus();
+    show();
+}
+
+void NoteEdit::readConfig()
+{
+    const qint64 id = MessageViewer::GlobalSettingsBase::self()->lastNoteSelectedFolder();
+    if (id!=-1) {
+        mCollectionCombobox->setDefaultCollection(Akonadi::Collection(id));
+    }
+}
+
+Akonadi::Collection NoteEdit::collection() const
+{
+    return mCollection;
+}
+
+void NoteEdit::slotCollectionChanged(int /*index*/)
+{
+    setCollection(mCollectionCombobox->currentCollection());
+}
+
+void NoteEdit::setCollection(const Akonadi::Collection &value)
+{
+    if (mCollection != value) {
+        mCollection = value;
+        Q_EMIT collectionChanged(mCollection);
+    }
+}
+
+KMime::Message::Ptr NoteEdit::message() const
+{
+    return mMessage;
+}
+
+void NoteEdit::setMessage(const KMime::Message::Ptr &value)
+{
+    if (mMessage != value) {
+        mMessage = value;
+        const KMime::Headers::Subject * const subject = mMessage ? mMessage->subject(false) : 0;
+        if (subject) {
+            mNoteEdit->setText(subject->asUnicodeString());
+            mNoteEdit->selectAll();
+            mNoteEdit->setFocus();
+        } else {
+            mNoteEdit->clear();
+        }
+        Q_EMIT messageChanged(mMessage);
+    }
+}
+
+void NoteEdit::slotCloseWidget()
+{
+    writeConfig();
+    mNoteEdit->clear();
+    mMessage = KMime::Message::Ptr();
+    hide();
+}
+
+void NoteEdit::slotReturnPressed()
+{
+    if (!mMessage) {
+        kDebug()<<" Message is null";
+        return;
+    }
+    const Akonadi::Collection collection = mCollectionCombobox->currentCollection();
+    if (!collection.isValid()) {
+        kDebug()<<" Collection is not valid";
+        return;
+    }
+
+    if (!mNoteEdit->text().trimmed().isEmpty()) {
+        Akonadi::NoteUtils::NoteMessageWrapper note;
+        note.setTitle(mNoteEdit->text());
+        Q_EMIT createNote(note.message(), collection);
+        mNoteEdit->clear();
+        hide();
+    }
+}
+
+bool NoteEdit::eventFilter(QObject *object, QEvent *e)
+{
+    // Close the bar when pressing Escape.
+    // Not using a QShortcut for this because it could conflict with
+    // window-global actions (e.g. Emil Sedgh binds Esc to "close tab").
+    // With a shortcut override we can catch this before it gets to kactions.
+    const bool shortCutOverride = (e->type() == QEvent::ShortcutOverride);
+    if (shortCutOverride ) {
+        QKeyEvent* kev = static_cast<QKeyEvent* >(e);
+        if (kev->key() == Qt::Key_Escape) {
+            e->accept();
+            slotCloseWidget();
+            return true;
+        } else if ( kev->key() == Qt::Key_Enter ||
+                    kev->key() == Qt::Key_Return ||
+                    kev->key() == Qt::Key_Space) {
+            e->accept();
+            if (object == mCollectionCombobox) {
+                mCollectionCombobox->showPopup();
+            }
+            return true;
+        }
+    }
+    return QWidget::eventFilter(object,e);
+}
\ No newline at end of file
diff --git a/messageviewer/widgets/noteedit.h b/messageviewer/widgets/noteedit.h
new file mode 100644
index 0000000..62c55c1
--- /dev/null
+++ b/messageviewer/widgets/noteedit.h
@@ -0,0 +1,77 @@
+/*
+  Copyright (c) 2014 Sandro Knauß <knauss at kolabsys.com>
+
+  This program is free software; you can redistribute it and/or modify it
+  under the terms of the GNU General Public License, version 2, as
+  published by the Free Software Foundation.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License along
+  with this program; if not, write to the Free Software Foundation, Inc.,
+  51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+#ifndef NOTEEDIT_H
+#define NOTEEDIT_H
+
+#include <QWidget>
+#include "messageviewer_export.h"
+
+#include <Akonadi/Collection>
+#include <Akonadi/Notes/NoteUtils>
+#include <KMime/KMimeMessage>
+
+class KLineEdit;
+class KPushButton;
+namespace Akonadi {
+class CollectionComboBox;
+}
+
+namespace MessageViewer {
+class MESSAGEVIEWER_EXPORT NoteEdit : public QWidget
+{
+    Q_OBJECT
+public:
+    explicit NoteEdit(QWidget *parent = 0);
+    ~NoteEdit();
+
+    Akonadi::Collection collection() const;
+    void setCollection(const Akonadi::Collection &value);
+
+    KMime::Message::Ptr message() const;
+    void setMessage(const KMime::Message::Ptr &value);
+
+    void writeConfig();
+    void showNoteEdit();
+
+public Q_SLOTS:
+    void slotCloseWidget();
+
+private Q_SLOTS:
+    void slotReturnPressed();
+    void slotCollectionChanged(int);
+    void slotUpdateButtons(const QString &subject);
+
+Q_SIGNALS:
+    void createNote(const KMime::Message::Ptr &note, const Akonadi::Collection &collection);
+    void collectionChanged(const Akonadi::Collection &col);
+    void messageChanged(const KMime::Message::Ptr &msg);
+
+protected:
+    bool eventFilter(QObject *object, QEvent *e);
+private:
+    void readConfig();
+    Akonadi::Collection mCollection;
+    KMime::Message::Ptr mMessage;
+    KLineEdit *mNoteEdit;
+    Akonadi::CollectionComboBox *mCollectionCombobox;
+    KPushButton *mSaveButton;
+};
+}
+
+#endif // NOTEEDIT_H


commit b99d995c3a90864edaafc975a632eb785345cc5e
Author: Montel Laurent <montel at kde.org>
Date:   Mon May 12 09:16:39 2014 +0200

    Fix enable disable open editor/save button

diff --git a/messageviewer/tests/eventedittest.cpp b/messageviewer/tests/eventedittest.cpp
index 63d8cab..32c9b7b 100644
--- a/messageviewer/tests/eventedittest.cpp
+++ b/messageviewer/tests/eventedittest.cpp
@@ -76,6 +76,13 @@ void EventEditTest::shouldHaveDefaultValuesOnCreation()
     QVERIFY(noteedit);
     QCOMPARE(noteedit->text(), QString());
 
+    KPushButton *openEditor = qFindChild<KPushButton *>(&edit, QLatin1String("open-editor-button"));
+    KPushButton *save = qFindChild<KPushButton *>(&edit, QLatin1String("save-button"));
+    QVERIFY(openEditor);
+    QVERIFY(save);
+    QCOMPARE(openEditor->isEnabled(), false);
+    QCOMPARE(save->isEnabled(), false);
+
     KDateTime currentDateTime = KDateTime::currentDateTime(KDateTime::LocalZone);
     KDateTimeEdit *startDateTime = qFindChild<KDateTimeEdit *>(&edit, QLatin1String("startdatetimeedit"));
     QVERIFY(startDateTime);
@@ -323,6 +330,23 @@ void EventEditTest::shouldEnsureEndDateIsNotBeforeStartDate()
     QCOMPARE(startDt.time(), endDateTime->time());
 }
 
+void EventEditTest::shouldShouldEnabledSaveOpenEditorButton()
+{
+    MessageViewer::EventEdit edit;
+    KMime::Message::Ptr msg(new KMime::Message);
+    msg->subject(true)->fromUnicodeString(QLatin1String("Test note"), "us-ascii");
+    edit.setMessage(msg);
+
+    QLineEdit *noteedit = qFindChild<QLineEdit *>(&edit, QLatin1String("noteedit"));
+    KPushButton *openEditor = qFindChild<KPushButton *>(&edit, QLatin1String("open-editor-button"));
+    KPushButton *save = qFindChild<KPushButton *>(&edit, QLatin1String("save-button"));
+    QCOMPARE(openEditor->isEnabled(), true);
+    QCOMPARE(save->isEnabled(), true);
+    noteedit->clear();
+
+    QCOMPARE(openEditor->isEnabled(), false);
+    QCOMPARE(save->isEnabled(), false);
+}
 
 
 QTEST_KDEMAIN( EventEditTest, GUI )
diff --git a/messageviewer/tests/eventedittest.h b/messageviewer/tests/eventedittest.h
index 838cc9b..2dcedde 100644
--- a/messageviewer/tests/eventedittest.h
+++ b/messageviewer/tests/eventedittest.h
@@ -44,6 +44,7 @@ private Q_SLOTS:
     void shouldNotEmitCreateEventWhenDateIsInvalid();
     void shouldSetFocusWhenWeCallTodoEdit();
     void shouldEnsureEndDateIsNotBeforeStartDate();
+    void shouldShouldEnabledSaveOpenEditorButton();
 };
 
 #endif // EVENTEDITTEST_H
diff --git a/messageviewer/tests/todoedittest.cpp b/messageviewer/tests/todoedittest.cpp
index aff8842..2ff44ad 100644
--- a/messageviewer/tests/todoedittest.cpp
+++ b/messageviewer/tests/todoedittest.cpp
@@ -71,6 +71,12 @@ void TodoEditTest::shouldHaveDefaultValuesOnCreation()
     //QVERIFY(edit.collection().isValid());
     QVERIFY(!edit.message());
     QLineEdit *noteedit = qFindChild<QLineEdit *>(&edit, QLatin1String("noteedit"));
+    KPushButton *openEditor = qFindChild<KPushButton *>(&edit, QLatin1String("open-editor-button"));
+    KPushButton *save = qFindChild<KPushButton *>(&edit, QLatin1String("save-button"));
+    QVERIFY(openEditor);
+    QVERIFY(save);
+    QCOMPARE(openEditor->isEnabled(), false);
+    QCOMPARE(save->isEnabled(), false);
     QVERIFY(noteedit);
     QCOMPARE(noteedit->text(), QString());
 }
@@ -481,6 +487,24 @@ void TodoEditTest::shouldHideMessageWidgetWhenCloseWidget()
     QCOMPARE(msgwidget->isHidden(), true);
 }
 
+void TodoEditTest::shouldShouldEnabledSaveOpenEditorButton()
+{
+    MessageViewer::TodoEdit edit;
+    KMime::Message::Ptr msg(new KMime::Message);
+    msg->subject(true)->fromUnicodeString(QLatin1String("Test note"), "us-ascii");
+    edit.setMessage(msg);
+
+    QLineEdit *noteedit = qFindChild<QLineEdit *>(&edit, QLatin1String("noteedit"));
+    KPushButton *openEditor = qFindChild<KPushButton *>(&edit, QLatin1String("open-editor-button"));
+    KPushButton *save = qFindChild<KPushButton *>(&edit, QLatin1String("save-button"));
+    QCOMPARE(openEditor->isEnabled(), true);
+    QCOMPARE(save->isEnabled(), true);
+    noteedit->clear();
+
+    QCOMPARE(openEditor->isEnabled(), false);
+    QCOMPARE(save->isEnabled(), false);
+}
+
 
 
 QTEST_KDEMAIN( TodoEditTest, GUI )
diff --git a/messageviewer/tests/todoedittest.h b/messageviewer/tests/todoedittest.h
index 2d88c97..0a03e8e 100644
--- a/messageviewer/tests/todoedittest.h
+++ b/messageviewer/tests/todoedittest.h
@@ -60,6 +60,7 @@ private slots:
     void shouldHideMessageWidget();
     void shouldHideMessageWidgetWhenAddNewMessage();
     void shouldHideMessageWidgetWhenCloseWidget();
+    void shouldShouldEnabledSaveOpenEditorButton();
 };
 
 #endif // TODOEDITTEST_H
diff --git a/messageviewer/widgets/eventedit.cpp b/messageviewer/widgets/eventedit.cpp
index 005b0be..84c7065 100644
--- a/messageviewer/widgets/eventedit.cpp
+++ b/messageviewer/widgets/eventedit.cpp
@@ -63,6 +63,7 @@ EventEdit::EventEdit(QWidget *parent)
     mEventEdit->setObjectName(QLatin1String("noteedit"));
     mEventEdit->setFocus();
     connect(mEventEdit, SIGNAL(returnPressed()), SLOT(slotReturnPressed()));
+    connect(mEventEdit, SIGNAL(textChanged(QString)), SLOT(slotUpdateButtons(QString)));
     hbox->addWidget(mEventEdit);
 
     hbox->addSpacing(5);
@@ -120,22 +121,25 @@ EventEdit::EventEdit(QWidget *parent)
 
     hbox->addStretch(1);
 
-    KPushButton *btn = new KPushButton(KIcon(QLatin1String("appointment-new")), i18n("&Save"));
-    btn->setObjectName(QLatin1String("save-button"));
+    mSaveButton = new KPushButton(KIcon(QLatin1String("appointment-new")), i18n("&Save"));
+    mSaveButton->setObjectName(QLatin1String("save-button"));
+    mSaveButton->setEnabled(false);
 #ifndef QT_NO_ACCESSIBILITY
-    btn->setAccessibleDescription(i18n("Create new event and close this widget."));
+    mSaveButton->setAccessibleDescription(i18n("Create new event and close this widget."));
 #endif
-    connect(btn, SIGNAL(clicked(bool)), this, SLOT(slotReturnPressed()));
-    hbox->addWidget(btn);
+    connect(mSaveButton, SIGNAL(clicked(bool)), this, SLOT(slotReturnPressed()));
+    hbox->addWidget(mSaveButton);
 
-    btn = new KPushButton(i18n("Open &editor..."));
+    mOpenEditorButton = new KPushButton(i18n("Open &editor..."));
 #ifndef QT_NO_ACCESSIBILITY
-    btn->setAccessibleDescription(i18n("Open event editor, where more details can be changed."));
+    mOpenEditorButton->setAccessibleDescription(i18n("Open event editor, where more details can be changed."));
 #endif
-    connect(btn, SIGNAL(clicked(bool)), this, SLOT(slotOpenEditor()));
-    hbox->addWidget(btn);
+    mOpenEditorButton->setObjectName(QLatin1String("open-editor-button"));
+    mOpenEditorButton->setEnabled(false);
+    connect(mOpenEditorButton, SIGNAL(clicked(bool)), this, SLOT(slotOpenEditor()));
+    hbox->addWidget(mOpenEditorButton);
 
-    btn = new KPushButton(KStandardGuiItem::cancel());
+    KPushButton *btn = new KPushButton(KStandardGuiItem::cancel());
     btn->setObjectName(QLatin1String("close-button"));
 #ifndef QT_NO_ACCESSIBILITY
     btn->setAccessibleDescription(i18n("Close the widget for creating new events."));
@@ -162,6 +166,13 @@ void EventEdit::writeConfig()
     }
 }
 
+void EventEdit::slotUpdateButtons(const QString &subject)
+{
+    const bool subjectIsNotEmpty = !subject.isEmpty();
+    mSaveButton->setEnabled(subjectIsNotEmpty);
+    mOpenEditorButton->setEnabled(subjectIsNotEmpty);
+}
+
 void EventEdit::showEventEdit()
 {
     mEventEdit->setFocus();
diff --git a/messageviewer/widgets/eventedit.h b/messageviewer/widgets/eventedit.h
index 2aad9a6..e5c3a74 100644
--- a/messageviewer/widgets/eventedit.h
+++ b/messageviewer/widgets/eventedit.h
@@ -28,6 +28,7 @@
 
 class KLineEdit;
 class KDateTimeEdit;
+class KPushButton;
 namespace Akonadi {
 class CollectionComboBox;
 }
@@ -57,6 +58,7 @@ private Q_SLOTS:
     void slotCollectionChanged(int);
     void slotOpenEditor();
     void slotStartDateTimeChanged(const KDateTime &newDateTime);
+    void slotUpdateButtons(const QString &subject);
 
 Q_SIGNALS:
     void createEvent(const KCalCore::Event::Ptr &event, const Akonadi::Collection &collection);
@@ -73,6 +75,8 @@ private:
     Akonadi::CollectionComboBox *mCollectionCombobox;
     KDateTimeEdit *mStartDateTimeEdit;
     KDateTimeEdit *mEndDateTimeEdit;
+    KPushButton *mSaveButton;
+    KPushButton *mOpenEditorButton;
 };
 }
 
diff --git a/messageviewer/widgets/todoedit.cpp b/messageviewer/widgets/todoedit.cpp
index d3e1d27..3db7f89 100644
--- a/messageviewer/widgets/todoedit.cpp
+++ b/messageviewer/widgets/todoedit.cpp
@@ -68,7 +68,7 @@ TodoEdit::TodoEdit(QWidget *parent)
     mNoteEdit->setClearButtonShown(true);
     mNoteEdit->setObjectName(QLatin1String("noteedit"));
     mNoteEdit->setFocus();
-    connect(mNoteEdit, SIGNAL(textChanged(QString)), SLOT(slotTextEdited()));
+    connect(mNoteEdit, SIGNAL(textChanged(QString)), SLOT(slotTextEdited(QString)));
     connect(mNoteEdit, SIGNAL(returnPressed()), SLOT(slotReturnPressed()));
     hbox->addWidget(mNoteEdit, 1);
 
@@ -93,22 +93,25 @@ TodoEdit::TodoEdit(QWidget *parent)
     vbox->addLayout(hbox);
 
     hbox->addStretch(1);
-    KPushButton *btn = new KPushButton(KIcon(QLatin1String("task-new")), i18n("&Save"));
-    btn->setObjectName(QLatin1String("save-button"));
+    mSaveButton = new KPushButton(KIcon(QLatin1String("task-new")), i18n("&Save"));
+    mSaveButton->setObjectName(QLatin1String("save-button"));
+    mSaveButton->setEnabled(false);
 #ifndef QT_NO_ACCESSIBILITY
-    btn->setAccessibleDescription(i18n("Create new todo and close this widget."));
+    mSaveButton->setAccessibleDescription(i18n("Create new todo and close this widget."));
 #endif
-    connect(btn, SIGNAL(clicked(bool)), this, SLOT(slotReturnPressed()));
-    hbox->addWidget(btn);
+    connect(mSaveButton, SIGNAL(clicked(bool)), this, SLOT(slotReturnPressed()));
+    hbox->addWidget(mSaveButton);
 
-    btn = new KPushButton(i18n("Open &editor..."));
+    mOpenEditorButton = new KPushButton(i18n("Open &editor..."));
+    mOpenEditorButton->setObjectName(QLatin1String("open-editor-button"));
 #ifndef QT_NO_ACCESSIBILITY
-    btn->setAccessibleDescription(i18n("Open todo editor, where more details can be changed."));
+    mOpenEditorButton->setAccessibleDescription(i18n("Open todo editor, where more details can be changed."));
 #endif
-    connect(btn, SIGNAL(clicked(bool)), this, SLOT(slotOpenEditor()));
-    hbox->addWidget(btn);
+    mOpenEditorButton->setEnabled(false);
+    connect(mOpenEditorButton, SIGNAL(clicked(bool)), this, SLOT(slotOpenEditor()));
+    hbox->addWidget(mOpenEditorButton);
 
-    btn = new KPushButton(KStandardGuiItem::cancel());
+    KPushButton *btn = new KPushButton(KStandardGuiItem::cancel());
     btn->setObjectName(QLatin1String("close-button"));
 #ifndef QT_NO_ACCESSIBILITY
     btn->setAccessibleDescription(i18n("Close the widget for creating new todos."));
@@ -128,6 +131,13 @@ TodoEdit::~TodoEdit()
     writeConfig();
 }
 
+void TodoEdit::updateButtons(const QString &subject)
+{
+    const bool subjectIsNotEmpty = !subject.isEmpty();
+    mSaveButton->setEnabled(subjectIsNotEmpty);
+    mOpenEditorButton->setEnabled(subjectIsNotEmpty);
+}
+
 void TodoEdit::showToDoWidget()
 {
     mNoteEdit->setFocus();
@@ -267,8 +277,9 @@ void TodoEdit::slotOpenEditor()
     dlg->open();
 }
 
-void TodoEdit::slotTextEdited()
+void TodoEdit::slotTextEdited(const QString &subject)
 {
+    updateButtons(subject);
     if (mMsgWidget->isVisible()) {
         mMsgWidget->hide();
     }
diff --git a/messageviewer/widgets/todoedit.h b/messageviewer/widgets/todoedit.h
index 888d684..6e4e7b9 100644
--- a/messageviewer/widgets/todoedit.h
+++ b/messageviewer/widgets/todoedit.h
@@ -26,7 +26,7 @@
 
 class KMessageWidget;
 class KLineEdit;
-
+class KPushButton;
 namespace Akonadi {
 class CollectionComboBox;
 }
@@ -55,7 +55,7 @@ private Q_SLOTS:
     void slotReturnPressed();
     void slotCollectionChanged(int);
     void slotOpenEditor();
-    void slotTextEdited();
+    void slotTextEdited(const QString &subject);
 
 Q_SIGNALS:
     void createTodo(const KCalCore::Todo::Ptr &todo, const Akonadi::Collection &collection);
@@ -65,12 +65,15 @@ Q_SIGNALS:
 protected:
     bool eventFilter(QObject *object, QEvent *e);
 private:
+    void updateButtons(const QString &subject);
     void readConfig();
     Akonadi::Collection mCollection;
     KMime::Message::Ptr mMessage;
     KLineEdit *mNoteEdit;
     Akonadi::CollectionComboBox *mCollectionCombobox;
     KMessageWidget *mMsgWidget;
+    KPushButton *mSaveButton;
+    KPushButton *mOpenEditorButton;
 };
 }
 #endif // TODOEDIT_H


commit eba2f631aefc15ff6d81ed3f9dcaa014ac9ad8dd
Author: Montel Laurent <montel at kde.org>
Date:   Tue May 6 13:20:05 2014 +0200

    Fix icon

diff --git a/messageviewer/widgets/todoedit.cpp b/messageviewer/widgets/todoedit.cpp
index be8a747..d3e1d27 100644
--- a/messageviewer/widgets/todoedit.cpp
+++ b/messageviewer/widgets/todoedit.cpp
@@ -93,7 +93,7 @@ TodoEdit::TodoEdit(QWidget *parent)
     vbox->addLayout(hbox);
 
     hbox->addStretch(1);
-    KPushButton *btn = new KPushButton(KIcon(QLatin1String("todo-new")), i18n("&Save"));
+    KPushButton *btn = new KPushButton(KIcon(QLatin1String("task-new")), i18n("&Save"));
     btn->setObjectName(QLatin1String("save-button"));
 #ifndef QT_NO_ACCESSIBILITY
     btn->setAccessibleDescription(i18n("Create new todo and close this widget."));


commit f321dc4ad0b73e58ff7f0602ccb99fca109b4e51
Author: Montel Laurent <montel at kde.org>
Date:   Tue May 6 13:13:32 2014 +0200

    Hide KMessageWidget when we close todowidget

diff --git a/messageviewer/tests/todoedittest.cpp b/messageviewer/tests/todoedittest.cpp
index 341780f..aff8842 100644
--- a/messageviewer/tests/todoedittest.cpp
+++ b/messageviewer/tests/todoedittest.cpp
@@ -418,9 +418,9 @@ void TodoEditTest::shouldShowMessageWidget()
     QLineEdit *noteedit = qFindChild<QLineEdit *>(&edit, QLatin1String("noteedit"));
     noteedit->setText(QLatin1String("Test Note"));
     KMessageWidget *msgwidget = qFindChild<KMessageWidget *>(&edit, QLatin1String("msgwidget"));
-    QVERIFY(!msgwidget->isVisible());
+    QCOMPARE(msgwidget->isVisible(), false);
     QTest::keyClick(noteedit, Qt::Key_Enter);
-    QVERIFY(msgwidget->isVisible());
+    QCOMPARE(msgwidget->isVisible(), true);
 }
 
 void TodoEditTest::shouldHideMessageWidget()
@@ -436,9 +436,49 @@ void TodoEditTest::shouldHideMessageWidget()
     edit.setMessage(msg);
     KMessageWidget *msgwidget = qFindChild<KMessageWidget *>(&edit, QLatin1String("msgwidget"));
     msgwidget->show();
-    QVERIFY(msgwidget->isVisible());
+    QCOMPARE(msgwidget->isVisible(), true);
     noteedit->setText(QLatin1String("Another note"));
-    QVERIFY(!msgwidget->isVisible());
+    QCOMPARE(msgwidget->isVisible(), false);
+}
+
+void TodoEditTest::shouldHideMessageWidgetWhenAddNewMessage()
+{
+    MessageViewer::TodoEdit edit;
+    edit.show();
+    QTest::qWaitForWindowShown(&edit);
+
+    KMime::Message::Ptr msg(new KMime::Message);
+    msg->subject(true)->fromUnicodeString(QLatin1String("Test note"), "us-ascii");
+    edit.setMessage(msg);
+    QLineEdit *noteedit = qFindChild<QLineEdit *>(&edit, QLatin1String("noteedit"));
+    noteedit->setText(QLatin1String("Test Note"));
+    KMessageWidget *msgwidget = qFindChild<KMessageWidget *>(&edit, QLatin1String("msgwidget"));
+    QTest::keyClick(noteedit, Qt::Key_Enter);
+    QCOMPARE(msgwidget->isVisible(), true);
+
+    KMime::Message::Ptr msg2(new KMime::Message);
+    msg2->subject(true)->fromUnicodeString(QLatin1String("Test note 2"), "us-ascii");
+    edit.setMessage(msg2);
+    QCOMPARE(msgwidget->isVisible(), false);
+}
+
+void TodoEditTest::shouldHideMessageWidgetWhenCloseWidget()
+{
+    MessageViewer::TodoEdit edit;
+    edit.show();
+    QTest::qWaitForWindowShown(&edit);
+
+    KMime::Message::Ptr msg(new KMime::Message);
+    msg->subject(true)->fromUnicodeString(QLatin1String("Test note"), "us-ascii");
+    edit.setMessage(msg);
+    QLineEdit *noteedit = qFindChild<QLineEdit *>(&edit, QLatin1String("noteedit"));
+    noteedit->setText(QLatin1String("Test Note"));
+    KMessageWidget *msgwidget = qFindChild<KMessageWidget *>(&edit, QLatin1String("msgwidget"));
+    QTest::keyClick(noteedit, Qt::Key_Enter);
+    QCOMPARE(msgwidget->isVisible(), true);
+    edit.slotCloseWidget();
+
+    QCOMPARE(msgwidget->isHidden(), true);
 }
 
 
diff --git a/messageviewer/tests/todoedittest.h b/messageviewer/tests/todoedittest.h
index 061053b..2d88c97 100644
--- a/messageviewer/tests/todoedittest.h
+++ b/messageviewer/tests/todoedittest.h
@@ -58,6 +58,8 @@ private slots:
     void shouldSetFocusWhenWeCallTodoEdit();
     void shouldShowMessageWidget();
     void shouldHideMessageWidget();
+    void shouldHideMessageWidgetWhenAddNewMessage();
+    void shouldHideMessageWidgetWhenCloseWidget();
 };
 
 #endif // TODOEDITTEST_H
diff --git a/messageviewer/widgets/todoedit.cpp b/messageviewer/widgets/todoedit.cpp
index 6e0266f..be8a747 100644
--- a/messageviewer/widgets/todoedit.cpp
+++ b/messageviewer/widgets/todoedit.cpp
@@ -194,6 +194,7 @@ void TodoEdit::slotCloseWidget()
     writeConfig();
     mNoteEdit->clear();
     mMessage = KMime::Message::Ptr();
+    mMsgWidget->hide();
     hide();
 }
 


commit b7bf383eb519490fc8a989d8f6862216b7657c64
Author: Montel Laurent <montel at kde.org>
Date:   Mon May 12 08:52:26 2014 +0200

    Save when it's necessary

diff --git a/messageviewer/widgets/todoedit.cpp b/messageviewer/widgets/todoedit.cpp
index 4ee7488..6e0266f 100644
--- a/messageviewer/widgets/todoedit.cpp
+++ b/messageviewer/widgets/todoedit.cpp
@@ -136,8 +136,10 @@ void TodoEdit::showToDoWidget()
 
 void TodoEdit::writeConfig()
 {
-    MessageViewer::GlobalSettingsBase::self()->setLastSelectedFolder(mCollectionCombobox->currentCollection().id());
-    MessageViewer::GlobalSettingsBase::self()->writeConfig();
+    if (MessageViewer::GlobalSettingsBase::self()->lastSelectedFolder() != mCollectionCombobox->currentCollection().id()) {
+        MessageViewer::GlobalSettingsBase::self()->setLastSelectedFolder(mCollectionCombobox->currentCollection().id());
+        MessageViewer::GlobalSettingsBase::self()->writeConfig();
+    }
 }
 
 void TodoEdit::readConfig()


commit 939a374430ef30bd179f8a1eb12516192c90db1d
Author: Montel Laurent <montel at kde.org>
Date:   Mon May 12 08:52:55 2014 +0200

    Save config when necessary

diff --git a/messageviewer/widgets/eventedit.cpp b/messageviewer/widgets/eventedit.cpp
index a138d00..005b0be 100644
--- a/messageviewer/widgets/eventedit.cpp
+++ b/messageviewer/widgets/eventedit.cpp
@@ -156,8 +156,10 @@ EventEdit::~EventEdit()
 
 void EventEdit::writeConfig()
 {
-    MessageViewer::GlobalSettingsBase::self()->setLastEventSelectedFolder(mCollectionCombobox->currentCollection().id());
-    MessageViewer::GlobalSettingsBase::self()->writeConfig();
+    if (mCollectionCombobox->currentCollection().id() != MessageViewer::GlobalSettingsBase::self()->lastEventSelectedFolder()) {
+        MessageViewer::GlobalSettingsBase::self()->setLastEventSelectedFolder(mCollectionCombobox->currentCollection().id());
+        MessageViewer::GlobalSettingsBase::self()->writeConfig();
+    }
 }
 
 void EventEdit::showEventEdit()


commit d155b523ebfd7022658aa52b3eb2697023a42ce5
Author: Montel Laurent <montel at kde.org>
Date:   Mon May 12 08:46:05 2014 +0200

    Use KStandardGuiItem::cancel

diff --git a/messageviewer/widgets/eventedit.cpp b/messageviewer/widgets/eventedit.cpp
index ed801bd..a138d00 100644
--- a/messageviewer/widgets/eventedit.cpp
+++ b/messageviewer/widgets/eventedit.cpp
@@ -135,7 +135,7 @@ EventEdit::EventEdit(QWidget *parent)
     connect(btn, SIGNAL(clicked(bool)), this, SLOT(slotOpenEditor()));
     hbox->addWidget(btn);
 
-    btn = new KPushButton(i18n("&Cancel"));
+    btn = new KPushButton(KStandardGuiItem::cancel());
     btn->setObjectName(QLatin1String("close-button"));
 #ifndef QT_NO_ACCESSIBILITY
     btn->setAccessibleDescription(i18n("Close the widget for creating new events."));
diff --git a/messageviewer/widgets/todoedit.cpp b/messageviewer/widgets/todoedit.cpp
index 3751c4e..4ee7488 100644
--- a/messageviewer/widgets/todoedit.cpp
+++ b/messageviewer/widgets/todoedit.cpp
@@ -108,7 +108,7 @@ TodoEdit::TodoEdit(QWidget *parent)
     connect(btn, SIGNAL(clicked(bool)), this, SLOT(slotOpenEditor()));
     hbox->addWidget(btn);
 
-    btn = new KPushButton(i18n("&Cancel"));
+    btn = new KPushButton(KStandardGuiItem::cancel());
     btn->setObjectName(QLatin1String("close-button"));
 #ifndef QT_NO_ACCESSIBILITY
     btn->setAccessibleDescription(i18n("Close the widget for creating new todos."));


commit 51faffd662b3b3287abb8fbf4d18e96066736a3c
Author: Dan Vrátil <dvratil at redhat.com>
Date:   Mon May 5 19:22:31 2014 +0200

    Improve KMail's Create Todo/Event widgets
    
    REVIEW: 117849

diff --git a/messageviewer/CMakeLists.txt b/messageviewer/CMakeLists.txt
index 2dcdf69..6b6b48a 100644
--- a/messageviewer/CMakeLists.txt
+++ b/messageviewer/CMakeLists.txt
@@ -204,6 +204,7 @@ target_link_libraries(messageviewer messagecore kdepim kpgp kleo
   pimcommon
   grantleetheme
   kaddressbookgrantlee
+  incidenceeditorsng
 )
 
 include_directories(
diff --git a/messageviewer/tests/eventedittest.cpp b/messageviewer/tests/eventedittest.cpp
index e0cb6e5..63d8cab 100644
--- a/messageviewer/tests/eventedittest.cpp
+++ b/messageviewer/tests/eventedittest.cpp
@@ -26,13 +26,13 @@
 #include <QStandardItemModel>
 #include <kcalcore/event.h>
 #include <KDateTimeEdit>
+#include <KPushButton>
 
 #include <qtest_kde.h>
 #include <qtestkeyboard.h>
 #include <qtestmouse.h>
 
 #include <QLineEdit>
-#include <QToolButton>
 #include <QHBoxLayout>
 #include <QShortcut>
 #include <QAction>
@@ -169,13 +169,28 @@ void EventEditTest::shouldHideWidgetWhenPressEscape()
     QCOMPARE(edit.isVisible(), false);
 }
 
+void EventEditTest::shouldHideWidgetWhenSaveClicked()
+{
+    MessageViewer::EventEdit edit;
+    edit.show();
+    QTest::qWaitForWindowShown(&edit);
+
+    KMime::Message::Ptr msg(new KMime::Message);
+    msg->subject(true)->fromUnicodeString(QLatin1String("Test Note"), "us-ascii");
+    edit.setMessage(msg);
+    KPushButton *save = qFindChild<KPushButton*>(&edit, QLatin1String("save-button"));
+    QTest::mouseClick(save, Qt::LeftButton);
+    QCOMPARE(edit.isVisible(), false);
+}
+
+
 void EventEditTest::shouldSaveCollectionSettings()
 {
     MessageViewer::EventEdit edit;
     Akonadi::CollectionComboBox *akonadicombobox = qFindChild<Akonadi::CollectionComboBox *>(&edit, QLatin1String("akonadicombobox"));
     akonadicombobox->setCurrentIndex(3);
     const Akonadi::Collection::Id id = akonadicombobox->currentCollection().id();
-    QToolButton *close = qFindChild<QToolButton *>(&edit, QLatin1String("close-button"));
+    KPushButton *close = qFindChild<KPushButton *>(&edit, QLatin1String("close-button"));
     QTest::mouseClick(close, Qt::LeftButton);
     QCOMPARE(MessageViewer::GlobalSettingsBase::self()->lastEventSelectedFolder(), id);
 }
@@ -289,5 +304,25 @@ void EventEditTest::shouldSetFocusWhenWeCallTodoEdit()
     QVERIFY(noteedit->hasFocus());
 }
 
+void EventEditTest::shouldEnsureEndDateIsNotBeforeStartDate()
+{
+    MessageViewer::EventEdit edit;
+    KDateTimeEdit *startDateTime = qFindChild<KDateTimeEdit *>(&edit, QLatin1String("startdatetimeedit"));
+    KDateTimeEdit *endDateTime = qFindChild<KDateTimeEdit *>(&edit, QLatin1String("enddatetimeedit"));
+
+    KDateTime startDt = startDateTime->dateTime();
+    QVERIFY(startDt < endDateTime->dateTime());
+
+    startDt = startDt.addDays(1);
+    startDateTime->setDateTime(startDt);
+    QCOMPARE(startDt.date(), endDateTime->date());
+    QVERIFY(startDt.time() < endDateTime->time());
+
+    startDt = startDt.addSecs(2*3600);
+    startDateTime->setDateTime(startDt);
+    QCOMPARE(startDt.time(), endDateTime->time());
+}
+
+
 
 QTEST_KDEMAIN( EventEditTest, GUI )
diff --git a/messageviewer/tests/eventedittest.h b/messageviewer/tests/eventedittest.h
index c0122a0..838cc9b 100644
--- a/messageviewer/tests/eventedittest.h
+++ b/messageviewer/tests/eventedittest.h
@@ -36,12 +36,14 @@ private Q_SLOTS:
     void shouldSaveCollectionSettingsWhenCloseWidget();
     void shouldSaveCollectionSettings();
     void shouldHideWidgetWhenPressEscape();
+    void shouldHideWidgetWhenSaveClicked();
     void shouldEventHasCorrectSubject();
     void shouldSelectLineWhenPutMessage();
     void shouldHaveCorrectStartEndDateTime();
     void shouldSaveCollectionSettingsWhenDeleteWidget();
     void shouldNotEmitCreateEventWhenDateIsInvalid();
     void shouldSetFocusWhenWeCallTodoEdit();
+    void shouldEnsureEndDateIsNotBeforeStartDate();
 };
 
 #endif // EVENTEDITTEST_H
diff --git a/messageviewer/tests/todoedittest.cpp b/messageviewer/tests/todoedittest.cpp
index e8fe51e..341780f 100644
--- a/messageviewer/tests/todoedittest.cpp
+++ b/messageviewer/tests/todoedittest.cpp
@@ -23,12 +23,13 @@
 #include <Akonadi/EntityTreeModel>
 #include <QStandardItemModel>
 #include <kcalcore/todo.h>
+#include <KPushButton>
+#include <KMessageWidget>
 #include <qtest_kde.h>
 #include <qtestkeyboard.h>
 #include <qtestmouse.h>
 
 #include <QLineEdit>
-#include <QToolButton>
 #include <QHBoxLayout>
 #include <QShortcut>
 #include <QAction>
@@ -289,7 +290,7 @@ void TodoEditTest::shouldHideWidgetWhenClickOnCloseButton()
     edit.show();
     QTest::qWaitForWindowShown(&edit);
     QVERIFY(edit.isVisible());
-    QToolButton *close = qFindChild<QToolButton *>(&edit, QLatin1String("close-button"));
+    KPushButton *close = qFindChild<KPushButton *>(&edit, QLatin1String("close-button"));
     QTest::mouseClick(close, Qt::LeftButton);
     QCOMPARE(edit.isVisible(), false);
 }
@@ -306,13 +307,27 @@ void TodoEditTest::shouldHideWidgetWhenPressEscape()
     QCOMPARE(edit.isVisible(), false);
 }
 
+void TodoEditTest::shouldHideWidgetWhenSaveClicked()
+{
+    MessageViewer::TodoEdit edit;
+    edit.show();
+    QTest::qWaitForWindowShown(&edit);
+
+    KMime::Message::Ptr msg(new KMime::Message);
+    msg->subject(true)->fromUnicodeString(QLatin1String("Test Note"), "us-ascii");
+    edit.setMessage(msg);
+    KPushButton *save = qFindChild<KPushButton *>(&edit, QLatin1String("save-button"));
+    QTest::mouseClick(save, Qt::LeftButton);
+    QCOMPARE(edit.isVisible(), true);
+}
+
 void TodoEditTest::shouldSaveCollectionSettings()
 {
     MessageViewer::TodoEdit edit;
     Akonadi::CollectionComboBox *akonadicombobox = qFindChild<Akonadi::CollectionComboBox *>(&edit, QLatin1String("akonadicombobox"));
     akonadicombobox->setCurrentIndex(3);
     const Akonadi::Collection::Id id = akonadicombobox->currentCollection().id();
-    QToolButton *close = qFindChild<QToolButton *>(&edit, QLatin1String("close-button"));
+    KPushButton *close = qFindChild<KPushButton *>(&edit, QLatin1String("close-button"));
     QTest::mouseClick(close, Qt::LeftButton);
     QCOMPARE(MessageViewer::GlobalSettingsBase::self()->lastSelectedFolder(), id);
 }
@@ -391,4 +406,41 @@ void TodoEditTest::shouldHaveLineEditFocus()
     QCOMPARE(noteedit->hasFocus(), true);
 }
 
+void TodoEditTest::shouldShowMessageWidget()
+{
+    MessageViewer::TodoEdit edit;
+    edit.show();
+    QTest::qWaitForWindowShown(&edit);
+
+    KMime::Message::Ptr msg(new KMime::Message);
+    msg->subject(true)->fromUnicodeString(QLatin1String("Test note"), "us-ascii");
+    edit.setMessage(msg);
+    QLineEdit *noteedit = qFindChild<QLineEdit *>(&edit, QLatin1String("noteedit"));
+    noteedit->setText(QLatin1String("Test Note"));
+    KMessageWidget *msgwidget = qFindChild<KMessageWidget *>(&edit, QLatin1String("msgwidget"));
+    QVERIFY(!msgwidget->isVisible());
+    QTest::keyClick(noteedit, Qt::Key_Enter);
+    QVERIFY(msgwidget->isVisible());
+}
+
+void TodoEditTest::shouldHideMessageWidget()
+{
+    MessageViewer::TodoEdit edit;
+    edit.show();
+    QTest::qWaitForWindowShown(&edit);
+    QLineEdit *noteedit = qFindChild<QLineEdit *>(&edit, QLatin1String("noteedit"));
+    noteedit->setText(QLatin1String("Test note"));
+
+    KMime::Message::Ptr msg(new KMime::Message);
+    msg->subject(true)->fromUnicodeString(QLatin1String("Test note"), "us-ascii");
+    edit.setMessage(msg);
+    KMessageWidget *msgwidget = qFindChild<KMessageWidget *>(&edit, QLatin1String("msgwidget"));
+    msgwidget->show();
+    QVERIFY(msgwidget->isVisible());
+    noteedit->setText(QLatin1String("Another note"));
+    QVERIFY(!msgwidget->isVisible());
+}
+
+
+
 QTEST_KDEMAIN( TodoEditTest, GUI )
diff --git a/messageviewer/tests/todoedittest.h b/messageviewer/tests/todoedittest.h
index 926865f..061053b 100644
--- a/messageviewer/tests/todoedittest.h
+++ b/messageviewer/tests/todoedittest.h
@@ -48,6 +48,7 @@ private slots:
     void shouldEmitCorrectCollection();
     void shouldHideWidgetWhenClickOnCloseButton();
     void shouldHideWidgetWhenPressEscape();
+    void shouldHideWidgetWhenSaveClicked();
     void shouldSaveCollectionSettings();
     void shouldSaveCollectionSettingsWhenCloseWidget();
     void shouldNotEmitTodoWhenMessageIsNull();
@@ -55,6 +56,8 @@ private slots:
     void shouldEmitNotEmitTodoWhenTextTrimmedIsEmpty();
     void shouldSaveCollectionSettingsWhenDeleteWidget();
     void shouldSetFocusWhenWeCallTodoEdit();
+    void shouldShowMessageWidget();
+    void shouldHideMessageWidget();
 };
 
 #endif // TODOEDITTEST_H
diff --git a/messageviewer/widgets/eventedit.cpp b/messageviewer/widgets/eventedit.cpp
index be52916..ed801bd 100644
--- a/messageviewer/widgets/eventedit.cpp
+++ b/messageviewer/widgets/eventedit.cpp
@@ -28,9 +28,12 @@
 #include <QEvent>
 #include <QKeyEvent>
 #include <QLabel>
-#include <QToolButton>
 
 #include <Akonadi/CollectionComboBox>
+#include <KPushButton>
+
+#include <incidenceeditor-ng/incidencedialogfactory.h>
+#include <incidenceeditor-ng/incidencedialog.h>
 
 
 namespace MessageViewer {
@@ -43,29 +46,15 @@ EventEdit::EventEdit(QWidget *parent)
     : QWidget(parent)
 {
     QVBoxLayout *vbox = new QVBoxLayout;
-    vbox->setMargin(2);
-    vbox->setSpacing(0);
+    vbox->setMargin(5);
+    vbox->setSpacing(2);
     setLayout(vbox);
+
     QHBoxLayout *hbox = new QHBoxLayout;
     hbox->setMargin(0);
     hbox->setSpacing(2);
     vbox->addLayout(hbox);
 
-    QToolButton *closeBtn = new QToolButton( this );
-    closeBtn->setIcon( KIcon( QLatin1String("dialog-close") ) );
-    closeBtn->setObjectName(QLatin1String("close-button"));
-    closeBtn->setIconSize( QSize( 16, 16 ) );
-    closeBtn->setToolTip( i18n( "Close" ) );
-
-#ifndef QT_NO_ACCESSIBILITY
-    closeBtn->setAccessibleName( i18n( "Close" ) );
-    closeBtn->setAccessibleDescription( i18n("Close widget to create new Todo") );
-#endif
-
-    closeBtn->setAutoRaise( true );
-    hbox->addWidget( closeBtn );
-    connect( closeBtn, SIGNAL(clicked()), this, SLOT(slotCloseWidget()) );
-
     QLabel *lab = new QLabel(i18n("Event:"));
     hbox->addWidget(lab);
 
@@ -75,23 +64,28 @@ EventEdit::EventEdit(QWidget *parent)
     mEventEdit->setFocus();
     connect(mEventEdit, SIGNAL(returnPressed()), SLOT(slotReturnPressed()));
     hbox->addWidget(mEventEdit);
+
+    hbox->addSpacing(5);
+
     mCollectionCombobox = new Akonadi::CollectionComboBox(_k_eventEditStubModel);
     mCollectionCombobox->setAccessRightsFilter(Akonadi::Collection::CanCreateItem);
     mCollectionCombobox->setMinimumWidth(250);
     mCollectionCombobox->setMimeTypeFilter( QStringList() << KCalCore::Event::eventMimeType() );
     mCollectionCombobox->setObjectName(QLatin1String("akonadicombobox"));
 #ifndef QT_NO_ACCESSIBILITY
-    mCollectionCombobox->setAccessibleDescription( i18n("The most recently selected folder used for Events.") );
+    mCollectionCombobox->setAccessibleDescription( i18n("Calendar where the new event will be stored.") );
 #endif
+    mCollectionCombobox->setToolTip( i18n("Calendar where the new event will be stored.") );
 
     connect(mCollectionCombobox, SIGNAL(currentIndexChanged(int)), SLOT(slotCollectionChanged(int)));
     connect(mCollectionCombobox, SIGNAL(activated(int)), SLOT(slotCollectionChanged(int)));
     hbox->addWidget(mCollectionCombobox);
 
     hbox = new QHBoxLayout;
+    hbox->setMargin(0);
+    hbox->setSpacing(2);
     vbox->addLayout(hbox);
 
-    hbox->addStretch();
     lab = new QLabel(i18n("Start:"));
     hbox->addWidget(lab);
     KDateTime currentDateTime = KDateTime::currentDateTime(KDateTime::LocalZone);
@@ -101,10 +95,12 @@ EventEdit::EventEdit(QWidget *parent)
 #ifndef QT_NO_ACCESSIBILITY
     mStartDateTimeEdit->setAccessibleDescription( i18n("Select start time for event.") );
 #endif
-
-
+    connect(mStartDateTimeEdit, SIGNAL(dateTimeChanged(KDateTime)),
+            this, SLOT(slotStartDateTimeChanged(KDateTime)));
     hbox->addWidget(mStartDateTimeEdit);
 
+    hbox->addSpacing(5);
+
     lab = new QLabel(i18n("End:"));
     hbox->addWidget(lab);
     mEndDateTimeEdit = new KDateTimeEdit;
@@ -115,6 +111,38 @@ EventEdit::EventEdit(QWidget *parent)
 #endif
     hbox->addWidget(mEndDateTimeEdit);
 
+    hbox->addStretch(1);
+
+    hbox = new QHBoxLayout;
+    hbox->setSpacing(2);
+    hbox->setMargin(0);
+    vbox->addLayout(hbox);
+
+    hbox->addStretch(1);
+
+    KPushButton *btn = new KPushButton(KIcon(QLatin1String("appointment-new")), i18n("&Save"));
+    btn->setObjectName(QLatin1String("save-button"));
+#ifndef QT_NO_ACCESSIBILITY
+    btn->setAccessibleDescription(i18n("Create new event and close this widget."));
+#endif
+    connect(btn, SIGNAL(clicked(bool)), this, SLOT(slotReturnPressed()));
+    hbox->addWidget(btn);
+
+    btn = new KPushButton(i18n("Open &editor..."));
+#ifndef QT_NO_ACCESSIBILITY
+    btn->setAccessibleDescription(i18n("Open event editor, where more details can be changed."));
+#endif
+    connect(btn, SIGNAL(clicked(bool)), this, SLOT(slotOpenEditor()));
+    hbox->addWidget(btn);
+
+    btn = new KPushButton(i18n("&Cancel"));
+    btn->setObjectName(QLatin1String("close-button"));
+#ifndef QT_NO_ACCESSIBILITY
+    btn->setAccessibleDescription(i18n("Close the widget for creating new events."));
+#endif
+    connect(btn, SIGNAL(clicked(bool)), this, SLOT(slotCloseWidget()));
+    hbox->addWidget(btn);
+
     readConfig();
     setSizePolicy( QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Fixed ) );
     installEventFilter(this);
@@ -248,3 +276,44 @@ bool EventEdit::eventFilter(QObject *object, QEvent *e)
     }
     return QWidget::eventFilter(object,e);
 }
+
+void EventEdit::slotStartDateTimeChanged(const KDateTime &newDateTime)
+{
+    if (!newDateTime.isValid()) {
+      return;
+    }
+
+    if (mEndDateTimeEdit->date() == newDateTime.date() && mEndDateTimeEdit->time() < newDateTime.time()) {
+        mEndDateTimeEdit->setTime(newDateTime.time());
+    }
+    if (mEndDateTimeEdit->date() < newDateTime.date()) {
+        mEndDateTimeEdit->setDate(newDateTime.date());
+    }
+
+    mEndDateTimeEdit->setMinimumDateTime(newDateTime);
+}
+
+
+void EventEdit::slotOpenEditor()
+{
+    KCalCore::Attachment::Ptr attachment(new KCalCore::Attachment(mMessage->encodedContent().toBase64(), KMime::Message::mimeType()));
+    const KMime::Headers::Subject * const subject = mMessage->subject(false);
+    if (subject) {
+        attachment->setLabel(subject->asUnicodeString());
+    }
+
+    KCalCore::Event::Ptr event(new KCalCore::Event);
+    event->setSummary(mEventEdit->text());
+    event->setDtStart(mStartDateTimeEdit->dateTime());
+    event->setDtEnd(mEndDateTimeEdit->dateTime());
+    event->addAttachment(attachment);
+
+    Akonadi::Item item;
+    item.setPayload<KCalCore::Event::Ptr>(event);
+    item.setMimeType(KCalCore::Event::eventMimeType());
+
+    IncidenceEditorNG::IncidenceDialog *dlg = IncidenceEditorNG::IncidenceDialogFactory::create(true, KCalCore::IncidenceBase::TypeEvent, 0, this);
+    connect(dlg, SIGNAL(finished()), this, SLOT(slotCloseWidget()));
+    dlg->load(item);
+    dlg->open();
+}
diff --git a/messageviewer/widgets/eventedit.h b/messageviewer/widgets/eventedit.h
index c1b6a99..2aad9a6 100644
--- a/messageviewer/widgets/eventedit.h
+++ b/messageviewer/widgets/eventedit.h
@@ -25,6 +25,7 @@
 #include <Akonadi/Collection>
 #include <KMime/Message>
 #include <KCalCore/Event>
+
 class KLineEdit;
 class KDateTimeEdit;
 namespace Akonadi {
@@ -54,6 +55,8 @@ public Q_SLOTS:
 private Q_SLOTS:
     void slotReturnPressed();
     void slotCollectionChanged(int);
+    void slotOpenEditor();
+    void slotStartDateTimeChanged(const KDateTime &newDateTime);
 
 Q_SIGNALS:
     void createEvent(const KCalCore::Event::Ptr &event, const Akonadi::Collection &collection);
diff --git a/messageviewer/widgets/todoedit.cpp b/messageviewer/widgets/todoedit.cpp
index 472ba00..3751c4e 100644
--- a/messageviewer/widgets/todoedit.cpp
+++ b/messageviewer/widgets/todoedit.cpp
@@ -21,15 +21,19 @@
 #include <KLocalizedString>
 #include <KLineEdit>
 #include <KIcon>
+#include <KPushButton>
+#include <KMessageWidget>
 
 #include <QHBoxLayout>
 #include <QEvent>
 #include <QKeyEvent>
 #include <QLabel>
-#include <QToolButton>
 
 #include <Akonadi/CollectionComboBox>
 
+#include <incidenceeditor-ng/incidencedialog.h>
+#include <incidenceeditor-ng/incidencedialogfactory.h>
+
 
 namespace MessageViewer {
 MESSAGEVIEWER_EXPORT QAbstractItemModel *_k_todoEditStubModel = 0;
@@ -40,24 +44,22 @@ using namespace MessageViewer;
 TodoEdit::TodoEdit(QWidget *parent)
     : QWidget(parent)
 {
-    QHBoxLayout *hbox = new QHBoxLayout;
-    hbox->setMargin(2);
-    setLayout(hbox);
+    QVBoxLayout *vbox = new QVBoxLayout;
+    vbox->setMargin(5);
+    vbox->setSpacing(2);
+    setLayout(vbox);
 
-    QToolButton *closeBtn = new QToolButton( this );
-    closeBtn->setIcon( KIcon( QLatin1String("dialog-close") ) );
-    closeBtn->setObjectName(QLatin1String("close-button"));
-    closeBtn->setIconSize( QSize( 16, 16 ) );
-    closeBtn->setToolTip( i18n( "Close" ) );
-
-#ifndef QT_NO_ACCESSIBILITY
-    closeBtn->setAccessibleName( i18n( "Close" ) );
-    closeBtn->setAccessibleDescription( i18n("Close widget to create new Todo") );
-#endif
+    mMsgWidget = new KMessageWidget(this);
+    mMsgWidget->setCloseButtonVisible(true);
+    mMsgWidget->setMessageType(KMessageWidget::Positive);
+    mMsgWidget->setObjectName(QLatin1String("msgwidget"));
+    mMsgWidget->setVisible(false);
+    vbox->addWidget(mMsgWidget);
 
-    closeBtn->setAutoRaise( true );
-    hbox->addWidget( closeBtn );
-    connect( closeBtn, SIGNAL(clicked()), this, SLOT(slotCloseWidget()) );
+    QHBoxLayout *hbox = new QHBoxLayout;
+    hbox->setMargin(0);
+    hbox->setSpacing(2);
+    vbox->addLayout(hbox);
 
     QLabel *lab = new QLabel(i18n("Todo:"));
     hbox->addWidget(lab);
@@ -66,20 +68,55 @@ TodoEdit::TodoEdit(QWidget *parent)
     mNoteEdit->setClearButtonShown(true);
     mNoteEdit->setObjectName(QLatin1String("noteedit"));
     mNoteEdit->setFocus();
+    connect(mNoteEdit, SIGNAL(textChanged(QString)), SLOT(slotTextEdited()));
     connect(mNoteEdit, SIGNAL(returnPressed()), SLOT(slotReturnPressed()));
-    hbox->addWidget(mNoteEdit);
+    hbox->addWidget(mNoteEdit, 1);
+
+    hbox->addSpacing(5);
+
     mCollectionCombobox = new Akonadi::CollectionComboBox(_k_todoEditStubModel);
     mCollectionCombobox->setAccessRightsFilter(Akonadi::Collection::CanCreateItem);
     mCollectionCombobox->setMinimumWidth(250);
     mCollectionCombobox->setMimeTypeFilter( QStringList() << KCalCore::Todo::todoMimeType() );
     mCollectionCombobox->setObjectName(QLatin1String("akonadicombobox"));
 #ifndef QT_NO_ACCESSIBILITY
-    mCollectionCombobox->setAccessibleDescription( i18n("The most recently selected folder used for Todos.") );
+    mCollectionCombobox->setAccessibleDescription( i18n("Todo list where the new task will be stored.") );
 #endif
-
+    mCollectionCombobox->setToolTip( i18n("Todo list where the new task will be stored.") );
     connect(mCollectionCombobox, SIGNAL(currentIndexChanged(int)), SLOT(slotCollectionChanged(int)));
     connect(mCollectionCombobox, SIGNAL(activated(int)), SLOT(slotCollectionChanged(int)));
     hbox->addWidget(mCollectionCombobox);
+
+    hbox = new QHBoxLayout;
+    hbox->setMargin(0);
+    hbox->setSpacing(2);
+    vbox->addLayout(hbox);
+
+    hbox->addStretch(1);
+    KPushButton *btn = new KPushButton(KIcon(QLatin1String("todo-new")), i18n("&Save"));
+    btn->setObjectName(QLatin1String("save-button"));
+#ifndef QT_NO_ACCESSIBILITY
+    btn->setAccessibleDescription(i18n("Create new todo and close this widget."));
+#endif
+    connect(btn, SIGNAL(clicked(bool)), this, SLOT(slotReturnPressed()));
+    hbox->addWidget(btn);
+
+    btn = new KPushButton(i18n("Open &editor..."));
+#ifndef QT_NO_ACCESSIBILITY
+    btn->setAccessibleDescription(i18n("Open todo editor, where more details can be changed."));
+#endif
+    connect(btn, SIGNAL(clicked(bool)), this, SLOT(slotOpenEditor()));
+    hbox->addWidget(btn);
+
+    btn = new KPushButton(i18n("&Cancel"));
+    btn->setObjectName(QLatin1String("close-button"));
+#ifndef QT_NO_ACCESSIBILITY
+    btn->setAccessibleDescription(i18n("Close the widget for creating new todos."));
+#endif
+    connect(btn, SIGNAL(clicked(bool)), this, SLOT(slotCloseWidget()));
+    hbox->addWidget(btn);
+
+
     readConfig();
     setSizePolicy( QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Fixed ) );
     mCollectionCombobox->installEventFilter(this);
@@ -171,10 +208,16 @@ void TodoEdit::slotReturnPressed()
     }
 
     if (!mNoteEdit->text().trimmed().isEmpty()) {
+        mMsgWidget->setText(i18nc("%1 is summary of the todo, %2 is name of the folder in which it is stored",
+                                  "New todo '%1' was added to task list '%2'", mNoteEdit->text(), collection.displayName()));
         KCalCore::Todo::Ptr todo( new KCalCore::Todo );
         todo->setSummary(mNoteEdit->text());
-        Q_EMIT createTodo(todo, collection);
         mNoteEdit->clear();
+
+        // We don't hide the widget here, so that multiple todo's can be added
+        Q_EMIT createTodo(todo, collection);
+
+        mMsgWidget->animatedShow();
     }
 }
 
@@ -206,3 +249,24 @@ bool TodoEdit::eventFilter(QObject *object, QEvent *e)
     }
     return QWidget::eventFilter(object,e);
 }
+
+void TodoEdit::slotOpenEditor()
+{
+    const KMime::Headers::Subject * const subject = mMessage->subject(false);
+    IncidenceEditorNG::IncidenceDialog *dlg = IncidenceEditorNG::IncidenceDialogFactory::createTodoEditor(
+        mNoteEdit->text(), QString(),
+        QStringList() << QString::fromLatin1(mMessage->encodedContent().toBase64()),
+        QStringList(),  // attendees
+        QStringList() << KMime::Message::mimeType(),
+        QStringList() << (subject ? subject->asUnicodeString() : QString()),
+        false, mCollection, false, this);
+    connect(dlg, SIGNAL(finished()), this, SLOT(slotCloseWidget()));
+    dlg->open();
+}
+
+void TodoEdit::slotTextEdited()
+{
+    if (mMsgWidget->isVisible()) {
+        mMsgWidget->hide();
+    }
+}
diff --git a/messageviewer/widgets/todoedit.h b/messageviewer/widgets/todoedit.h
index f0d0774..888d684 100644
--- a/messageviewer/widgets/todoedit.h
+++ b/messageviewer/widgets/todoedit.h
@@ -24,6 +24,7 @@
 #include <KCalCore/Todo>
 #include "messageviewer_export.h"
 
+class KMessageWidget;
 class KLineEdit;
 
 namespace Akonadi {
@@ -53,6 +54,8 @@ public Q_SLOTS:
 private Q_SLOTS:
     void slotReturnPressed();
     void slotCollectionChanged(int);
+    void slotOpenEditor();
+    void slotTextEdited();
 
 Q_SIGNALS:
     void createTodo(const KCalCore::Todo::Ptr &todo, const Akonadi::Collection &collection);
@@ -67,6 +70,7 @@ private:
     KMime::Message::Ptr mMessage;
     KLineEdit *mNoteEdit;
     Akonadi::CollectionComboBox *mCollectionCombobox;
+    KMessageWidget *mMsgWidget;
 };
 }
 #endif // TODOEDIT_H


commit c19f038332402c77fbe7ba8efd7f34dcf3060cec
Author: Montel Laurent <montel at kde.org>
Date:   Tue Apr 8 07:39:59 2014 +0200

    Fix i18n

diff --git a/messageviewer/widgets/eventedit.cpp b/messageviewer/widgets/eventedit.cpp
index b2f6743..be52916 100644
--- a/messageviewer/widgets/eventedit.cpp
+++ b/messageviewer/widgets/eventedit.cpp
@@ -81,7 +81,7 @@ EventEdit::EventEdit(QWidget *parent)
     mCollectionCombobox->setMimeTypeFilter( QStringList() << KCalCore::Event::eventMimeType() );
     mCollectionCombobox->setObjectName(QLatin1String("akonadicombobox"));
 #ifndef QT_NO_ACCESSIBILITY
-    mCollectionCombobox->setAccessibleDescription( i18n("Select collection where Todo will stored.") );
+    mCollectionCombobox->setAccessibleDescription( i18n("The most recently selected folder used for Events.") );
 #endif
 
     connect(mCollectionCombobox, SIGNAL(currentIndexChanged(int)), SLOT(slotCollectionChanged(int)));


commit 8335b81609dcdcfcce0ac6833dfdf42712ef714c
Author: Montel Laurent <montel at kde.org>
Date:   Mon Mar 31 08:26:35 2014 +0200

    Symplify code

diff --git a/messageviewer/widgets/eventedit.cpp b/messageviewer/widgets/eventedit.cpp
index e4e6192..b2f6743 100644
--- a/messageviewer/widgets/eventedit.cpp
+++ b/messageviewer/widgets/eventedit.cpp
@@ -230,7 +230,7 @@ bool EventEdit::eventFilter(QObject *object, QEvent *e)
     // window-global actions (e.g. Emil Sedgh binds Esc to "close tab").
     // With a shortcut override we can catch this before it gets to kactions.
     const bool shortCutOverride = (e->type() == QEvent::ShortcutOverride);
-    if (shortCutOverride || e->type() == QEvent::KeyPress ) {
+    if (shortCutOverride ) {
         QKeyEvent* kev = static_cast<QKeyEvent* >(e);
         if (kev->key() == Qt::Key_Escape) {
             e->accept();
@@ -240,13 +240,10 @@ bool EventEdit::eventFilter(QObject *object, QEvent *e)
                     kev->key() == Qt::Key_Return ||
                     kev->key() == Qt::Key_Space) {
             e->accept();
-            if ( shortCutOverride ) {
-                return true;
-            }
             if (object == mCollectionCombobox) {
                 mCollectionCombobox->showPopup();
-                return true;
             }
+            return true;
         }
     }
     return QWidget::eventFilter(object,e);


commit e60e8cf8d5588344d519d649d75eb55bf8f98b0c
Author: Montel Laurent <montel at kde.org>
Date:   Sun Mar 23 10:58:55 2014 +0100

    Allow to use keyboard to change

diff --git a/messageviewer/widgets/eventedit.cpp b/messageviewer/widgets/eventedit.cpp
index c937dbd..e4e6192 100644
--- a/messageviewer/widgets/eventedit.cpp
+++ b/messageviewer/widgets/eventedit.cpp
@@ -117,6 +117,8 @@ EventEdit::EventEdit(QWidget *parent)
 
     readConfig();
     setSizePolicy( QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Fixed ) );
+    installEventFilter(this);
+    mCollectionCombobox->installEventFilter(this);
 }
 
 EventEdit::~EventEdit()
@@ -221,7 +223,7 @@ void EventEdit::slotReturnPressed()
     }
 }
 
-bool EventEdit::event(QEvent* e)
+bool EventEdit::eventFilter(QObject *object, QEvent *e)
 {
     // Close the bar when pressing Escape.
     // Not using a QShortcut for this because it could conflict with
@@ -235,12 +237,17 @@ bool EventEdit::event(QEvent* e)
             slotCloseWidget();
             return true;
         } else if ( kev->key() == Qt::Key_Enter ||
-                   kev->key() == Qt::Key_Return ) {
+                    kev->key() == Qt::Key_Return ||
+                    kev->key() == Qt::Key_Space) {
             e->accept();
             if ( shortCutOverride ) {
                 return true;
             }
+            if (object == mCollectionCombobox) {
+                mCollectionCombobox->showPopup();
+                return true;
+            }
         }
     }
-    return QWidget::event(e);
+    return QWidget::eventFilter(object,e);
 }
diff --git a/messageviewer/widgets/eventedit.h b/messageviewer/widgets/eventedit.h
index 9f8d975..c1b6a99 100644
--- a/messageviewer/widgets/eventedit.h
+++ b/messageviewer/widgets/eventedit.h
@@ -61,8 +61,7 @@ Q_SIGNALS:
     void messageChanged(const KMime::Message::Ptr &msg);
 
 protected:
-    bool event(QEvent *e);
-
+    bool eventFilter(QObject *object, QEvent *e);
 private:
     void readConfig();
     Akonadi::Collection mCollection;


commit a906b1b7d8c379eb25cc4ba02e923407fac6254a
Author: Montel Laurent <montel at kde.org>
Date:   Sun Mar 23 10:02:57 2014 +0100

    Fix spacing

diff --git a/messageviewer/widgets/eventedit.cpp b/messageviewer/widgets/eventedit.cpp
index c2ff4a4..c937dbd 100644
--- a/messageviewer/widgets/eventedit.cpp
+++ b/messageviewer/widgets/eventedit.cpp
@@ -48,7 +48,7 @@ EventEdit::EventEdit(QWidget *parent)
     setLayout(vbox);
     QHBoxLayout *hbox = new QHBoxLayout;
     hbox->setMargin(0);
-    hbox->setSpacing(0);
+    hbox->setSpacing(2);
     vbox->addLayout(hbox);
 
     QToolButton *closeBtn = new QToolButton( this );


commit 359d03b15e7f3e83e6a5d054a68636a08da8a775
Author: Montel Laurent <montel at kde.org>
Date:   Sun Mar 16 08:39:13 2014 +0100

    Rename variable

diff --git a/messageviewer/widgets/eventedit.cpp b/messageviewer/widgets/eventedit.cpp
index 303ab85..c2ff4a4 100644
--- a/messageviewer/widgets/eventedit.cpp
+++ b/messageviewer/widgets/eventedit.cpp
@@ -69,12 +69,12 @@ EventEdit::EventEdit(QWidget *parent)
     QLabel *lab = new QLabel(i18n("Event:"));
     hbox->addWidget(lab);
 
-    mNoteEdit = new KLineEdit;
-    mNoteEdit->setClearButtonShown(true);
-    mNoteEdit->setObjectName(QLatin1String("noteedit"));
-    mNoteEdit->setFocus();
-    connect(mNoteEdit, SIGNAL(returnPressed()), SLOT(slotReturnPressed()));
-    hbox->addWidget(mNoteEdit);
+    mEventEdit = new KLineEdit;
+    mEventEdit->setClearButtonShown(true);
+    mEventEdit->setObjectName(QLatin1String("noteedit"));
+    mEventEdit->setFocus();
+    connect(mEventEdit, SIGNAL(returnPressed()), SLOT(slotReturnPressed()));
+    hbox->addWidget(mEventEdit);
     mCollectionCombobox = new Akonadi::CollectionComboBox(_k_eventEditStubModel);
     mCollectionCombobox->setAccessRightsFilter(Akonadi::Collection::CanCreateItem);
     mCollectionCombobox->setMinimumWidth(250);
@@ -132,7 +132,7 @@ void EventEdit::writeConfig()
 
 void EventEdit::showEventEdit()
 {
-    mNoteEdit->setFocus();
+    mEventEdit->setFocus();
     show();
 }
 
@@ -173,11 +173,11 @@ void EventEdit::setMessage(const KMime::Message::Ptr &value)
         mMessage = value;
         const KMime::Headers::Subject * const subject = mMessage ? mMessage->subject(false) : 0;
         if (subject) {
-            mNoteEdit->setText(i18n("Reply to \"%1\"", subject->asUnicodeString()));
-            mNoteEdit->selectAll();
-            mNoteEdit->setFocus();
+            mEventEdit->setText(i18n("Reply to \"%1\"", subject->asUnicodeString()));
+            mEventEdit->selectAll();
+            mEventEdit->setFocus();
         } else {
-            mNoteEdit->clear();
+            mEventEdit->clear();
         }
         Q_EMIT messageChanged(mMessage);
     }
@@ -186,7 +186,7 @@ void EventEdit::setMessage(const KMime::Message::Ptr &value)
 void EventEdit::slotCloseWidget()
 {
     writeConfig();
-    mNoteEdit->clear();
+    mEventEdit->clear();
     mMessage = KMime::Message::Ptr();
     hide();
 }
@@ -210,13 +210,13 @@ void EventEdit::slotReturnPressed()
         return;
     }
 
-    if (!mNoteEdit->text().trimmed().isEmpty()) {
+    if (!mEventEdit->text().trimmed().isEmpty()) {
         KCalCore::Event::Ptr event( new KCalCore::Event );
         event->setDtStart(dtstart);
         event->setDtEnd(dtend);
-        event->setSummary(mNoteEdit->text());
+        event->setSummary(mEventEdit->text());
         Q_EMIT createEvent(event, collection);
-        mNoteEdit->clear();
+        mEventEdit->clear();
         hide();
     }
 }
diff --git a/messageviewer/widgets/eventedit.h b/messageviewer/widgets/eventedit.h
index 4ba0566..9f8d975 100644
--- a/messageviewer/widgets/eventedit.h
+++ b/messageviewer/widgets/eventedit.h
@@ -67,7 +67,7 @@ private:
     void readConfig();
     Akonadi::Collection mCollection;
     KMime::Message::Ptr mMessage;
-    KLineEdit *mNoteEdit;
+    KLineEdit *mEventEdit;
     Akonadi::CollectionComboBox *mCollectionCombobox;
     KDateTimeEdit *mStartDateTimeEdit;
     KDateTimeEdit *mEndDateTimeEdit;


commit fbce0752c1123f9bf4e9ee509f0294e58fdd5301
Author: Montel Laurent <montel at kde.org>
Date:   Sun Mar 16 08:37:52 2014 +0100

    Add focus to lineedit

diff --git a/messageviewer/tests/eventedittest.cpp b/messageviewer/tests/eventedittest.cpp
index 349825b..e0cb6e5 100644
--- a/messageviewer/tests/eventedittest.cpp
+++ b/messageviewer/tests/eventedittest.cpp
@@ -276,5 +276,18 @@ void EventEditTest::shouldHaveCorrectStartEndDateTime()
     QCOMPARE(eventPtr->dtEnd(), endDt);
 }
 
+void EventEditTest::shouldSetFocusWhenWeCallTodoEdit()
+{
+    MessageViewer::EventEdit edit;
+    edit.show();
+    QTest::qWaitForWindowShown(&edit);
+    QLineEdit *noteedit = qFindChild<QLineEdit *>(&edit, QLatin1String("noteedit"));
+    noteedit->setFocus();
+    QVERIFY(noteedit->hasFocus());
+    edit.setFocus();
+    edit.showEventEdit();
+    QVERIFY(noteedit->hasFocus());
+}
+
 
 QTEST_KDEMAIN( EventEditTest, GUI )
diff --git a/messageviewer/tests/eventedittest.h b/messageviewer/tests/eventedittest.h
index 1df60f3..c0122a0 100644
--- a/messageviewer/tests/eventedittest.h
+++ b/messageviewer/tests/eventedittest.h
@@ -41,6 +41,7 @@ private Q_SLOTS:
     void shouldHaveCorrectStartEndDateTime();
     void shouldSaveCollectionSettingsWhenDeleteWidget();
     void shouldNotEmitCreateEventWhenDateIsInvalid();
+    void shouldSetFocusWhenWeCallTodoEdit();
 };
 
 #endif // EVENTEDITTEST_H
diff --git a/messageviewer/viewer/viewer_p.cpp b/messageviewer/viewer/viewer_p.cpp
index 8b68c88..fa0070b 100644
--- a/messageviewer/viewer/viewer_p.cpp
+++ b/messageviewer/viewer/viewer_p.cpp
@@ -3407,7 +3407,7 @@ void ViewerPrivate::slotShowCreateEventWidget()
 {
     if (mMessage) {
         mCreateEvent->setMessage(mMessage);
-        mCreateEvent->show();
+        mCreateEvent->showEventEdit();
     } else {
         qDebug()<<" There is not valid message";
     }
diff --git a/messageviewer/widgets/eventedit.cpp b/messageviewer/widgets/eventedit.cpp
index 54d89d5..303ab85 100644
--- a/messageviewer/widgets/eventedit.cpp
+++ b/messageviewer/widgets/eventedit.cpp
@@ -130,6 +130,12 @@ void EventEdit::writeConfig()
     MessageViewer::GlobalSettingsBase::self()->writeConfig();
 }
 
+void EventEdit::showEventEdit()
+{
+    mNoteEdit->setFocus();
+    show();
+}
+
 void EventEdit::readConfig()
 {
     const qint64 id = MessageViewer::GlobalSettingsBase::self()->lastEventSelectedFolder();
diff --git a/messageviewer/widgets/eventedit.h b/messageviewer/widgets/eventedit.h
index 3893aaf..4ba0566 100644
--- a/messageviewer/widgets/eventedit.h
+++ b/messageviewer/widgets/eventedit.h
@@ -46,6 +46,7 @@ public:
     void setMessage(const KMime::Message::Ptr &value);
 
     void writeConfig();
+    void showEventEdit();
 
 public Q_SLOTS:
     void slotCloseWidget();


commit 7edb93ae6a8e9ba1603350b49b2c1c663928e18e
Author: Montel Laurent <montel at kde.org>
Date:   Wed Mar 5 07:39:25 2014 +0100

    Fix margin/spacing

diff --git a/messageviewer/widgets/eventedit.cpp b/messageviewer/widgets/eventedit.cpp
index 7bf69b9..54d89d5 100644
--- a/messageviewer/widgets/eventedit.cpp
+++ b/messageviewer/widgets/eventedit.cpp
@@ -43,11 +43,12 @@ EventEdit::EventEdit(QWidget *parent)
     : QWidget(parent)
 {
     QVBoxLayout *vbox = new QVBoxLayout;
+    vbox->setMargin(2);
     vbox->setSpacing(0);
-    vbox->setMargin(0);
     setLayout(vbox);
     QHBoxLayout *hbox = new QHBoxLayout;
-    hbox->setMargin(2);
+    hbox->setMargin(0);
+    hbox->setSpacing(0);
     vbox->addLayout(hbox);
 
     QToolButton *closeBtn = new QToolButton( this );


commit ac52273df65f7f8bc7c75dc51dc4288622ec45b4
Author: Montel Laurent <montel at kde.org>
Date:   Tue Mar 4 13:10:23 2014 +0100

    Don't emit signal when date is not valid.

diff --git a/messageviewer/tests/eventedittest.cpp b/messageviewer/tests/eventedittest.cpp
index 2417a6e..349825b 100644
--- a/messageviewer/tests/eventedittest.cpp
+++ b/messageviewer/tests/eventedittest.cpp
@@ -70,7 +70,7 @@ EventEditTest::EventEditTest()
 void EventEditTest::shouldHaveDefaultValuesOnCreation()
 {
     MessageViewer::EventEdit edit;
-    QVERIFY(!edit.collection().isValid());
+    QVERIFY(edit.collection().isValid());
     QVERIFY(!edit.message());
     QLineEdit *noteedit = qFindChild<QLineEdit *>(&edit, QLatin1String("noteedit"));
     QVERIFY(noteedit);
@@ -200,6 +200,27 @@ void EventEditTest::shouldSaveCollectionSettingsWhenDeleteWidget()
     QCOMPARE(MessageViewer::GlobalSettingsBase::self()->lastEventSelectedFolder(), id);
 }
 
+void EventEditTest::shouldNotEmitCreateEventWhenDateIsInvalid()
+{
+    MessageViewer::EventEdit edit;
+    KMime::Message::Ptr msg(new KMime::Message);
+
+    KDateTimeEdit *startDateTime = qFindChild<KDateTimeEdit *>(&edit, QLatin1String("startdatetimeedit"));
+    startDateTime->setDateTime(KDateTime());
+
+    KDateTimeEdit *endDateTime = qFindChild<KDateTimeEdit *>(&edit, QLatin1String("enddatetimeedit"));
+    endDateTime->setDateTime(KDateTime());
+
+
+    QString subject = QLatin1String("Test Note");
+    msg->subject(true)->fromUnicodeString(subject, "us-ascii");
+    edit.setMessage(msg);
+    QLineEdit *noteedit = qFindChild<QLineEdit *>(&edit, QLatin1String("noteedit"));
+    QSignalSpy spy(&edit, SIGNAL(createEvent(KCalCore::Event::Ptr,Akonadi::Collection)));
+    QTest::keyClick(noteedit, Qt::Key_Enter);
+    QCOMPARE(spy.count(), 0);
+}
+
 void EventEditTest::shouldEventHasCorrectSubject()
 {
     MessageViewer::EventEdit edit;
diff --git a/messageviewer/tests/eventedittest.h b/messageviewer/tests/eventedittest.h
index 8edd2a6..1df60f3 100644
--- a/messageviewer/tests/eventedittest.h
+++ b/messageviewer/tests/eventedittest.h
@@ -40,6 +40,7 @@ private Q_SLOTS:
     void shouldSelectLineWhenPutMessage();
     void shouldHaveCorrectStartEndDateTime();
     void shouldSaveCollectionSettingsWhenDeleteWidget();
+    void shouldNotEmitCreateEventWhenDateIsInvalid();
 };
 
 #endif // EVENTEDITTEST_H
diff --git a/messageviewer/widgets/eventedit.cpp b/messageviewer/widgets/eventedit.cpp
index acf2db0..7bf69b9 100644
--- a/messageviewer/widgets/eventedit.cpp
+++ b/messageviewer/widgets/eventedit.cpp
@@ -196,10 +196,17 @@ void EventEdit::slotReturnPressed()
         return;
     }
 
+    const KDateTime dtstart = mStartDateTimeEdit->dateTime();
+    const KDateTime dtend = mEndDateTimeEdit->dateTime();
+    if (!dtstart.isValid() || !dtend.isValid()) {
+        kDebug()<<" date is not valid !";
+        return;
+    }
+
     if (!mNoteEdit->text().trimmed().isEmpty()) {
         KCalCore::Event::Ptr event( new KCalCore::Event );
-        event->setDtStart(mStartDateTimeEdit->dateTime());
-        event->setDtEnd(mEndDateTimeEdit->dateTime());
+        event->setDtStart(dtstart);
+        event->setDtEnd(dtend);
         event->setSummary(mNoteEdit->text());
         Q_EMIT createEvent(event, collection);
         mNoteEdit->clear();


commit ce24302b6ee22db8b9f7aa6f3e099a44d539424c
Author: Montel Laurent <montel at kde.org>
Date:   Tue Mar 4 07:50:18 2014 +0100

    Set margin at 0

diff --git a/messageviewer/widgets/eventedit.cpp b/messageviewer/widgets/eventedit.cpp
index f0901cf..acf2db0 100644
--- a/messageviewer/widgets/eventedit.cpp
+++ b/messageviewer/widgets/eventedit.cpp
@@ -44,6 +44,7 @@ EventEdit::EventEdit(QWidget *parent)
 {
     QVBoxLayout *vbox = new QVBoxLayout;
     vbox->setSpacing(0);
+    vbox->setMargin(0);
     setLayout(vbox);
     QHBoxLayout *hbox = new QHBoxLayout;
     hbox->setMargin(2);


commit d09827c802c198714f058f166b4953cc6a0ee713
Author: Montel Laurent <montel at kde.org>
Date:   Tue Mar 4 07:39:15 2014 +0100

    Fix save/load default collection

diff --git a/messageviewer/tests/eventedittest.cpp b/messageviewer/tests/eventedittest.cpp
index b7d6248..2417a6e 100644
--- a/messageviewer/tests/eventedittest.cpp
+++ b/messageviewer/tests/eventedittest.cpp
@@ -184,12 +184,22 @@ void EventEditTest::shouldSaveCollectionSettingsWhenCloseWidget()
 {
     MessageViewer::EventEdit edit;
     Akonadi::CollectionComboBox *akonadicombobox = qFindChild<Akonadi::CollectionComboBox *>(&edit, QLatin1String("akonadicombobox"));
-    akonadicombobox->setCurrentIndex(3);
+    akonadicombobox->setCurrentIndex(4);
     const Akonadi::Collection::Id id = akonadicombobox->currentCollection().id();
     edit.writeConfig();
     QCOMPARE(MessageViewer::GlobalSettingsBase::self()->lastEventSelectedFolder(), id);
 }
 
+void EventEditTest::shouldSaveCollectionSettingsWhenDeleteWidget()
+{
+    MessageViewer::EventEdit *edit = new MessageViewer::EventEdit;
+    Akonadi::CollectionComboBox *akonadicombobox = qFindChild<Akonadi::CollectionComboBox *>(edit, QLatin1String("akonadicombobox"));
+    akonadicombobox->setCurrentIndex(5);
+    const Akonadi::Collection::Id id = akonadicombobox->currentCollection().id();
+    delete edit;
+    QCOMPARE(MessageViewer::GlobalSettingsBase::self()->lastEventSelectedFolder(), id);
+}
+
 void EventEditTest::shouldEventHasCorrectSubject()
 {
     MessageViewer::EventEdit edit;
diff --git a/messageviewer/tests/eventedittest.h b/messageviewer/tests/eventedittest.h
index 5506644..8edd2a6 100644
--- a/messageviewer/tests/eventedittest.h
+++ b/messageviewer/tests/eventedittest.h
@@ -39,6 +39,7 @@ private Q_SLOTS:
     void shouldEventHasCorrectSubject();
     void shouldSelectLineWhenPutMessage();
     void shouldHaveCorrectStartEndDateTime();
+    void shouldSaveCollectionSettingsWhenDeleteWidget();
 };
 
 #endif // EVENTEDITTEST_H
diff --git a/messageviewer/widgets/eventedit.cpp b/messageviewer/widgets/eventedit.cpp
index a4fc38f..f0901cf 100644
--- a/messageviewer/widgets/eventedit.cpp
+++ b/messageviewer/widgets/eventedit.cpp
@@ -119,12 +119,13 @@ EventEdit::EventEdit(QWidget *parent)
 
 EventEdit::~EventEdit()
 {
-
+    writeConfig();
 }
 
 void EventEdit::writeConfig()
 {
     MessageViewer::GlobalSettingsBase::self()->setLastEventSelectedFolder(mCollectionCombobox->currentCollection().id());
+    MessageViewer::GlobalSettingsBase::self()->writeConfig();
 }
 
 void EventEdit::readConfig()


commit d0e3c0a28185a1b104aec502bad9707b98acb45f
Author: Montel Laurent <montel at kde.org>
Date:   Mon Mar 3 21:39:28 2014 +0100

    Fix Bug 331317 - Feature request - Create Calendar event from E-Mail
    
    FIXED-IN: 4.14
    BUG: 331317

diff --git a/messageviewer/widgets/eventedit.cpp b/messageviewer/widgets/eventedit.cpp
index afb6371..a4fc38f 100644
--- a/messageviewer/widgets/eventedit.cpp
+++ b/messageviewer/widgets/eventedit.cpp
@@ -96,6 +96,10 @@ EventEdit::EventEdit(QWidget *parent)
     mStartDateTimeEdit = new KDateTimeEdit;
     mStartDateTimeEdit->setObjectName(QLatin1String("startdatetimeedit"));
     mStartDateTimeEdit->setDateTime(currentDateTime);
+#ifndef QT_NO_ACCESSIBILITY
+    mStartDateTimeEdit->setAccessibleDescription( i18n("Select start time for event.") );
+#endif
+
 
     hbox->addWidget(mStartDateTimeEdit);
 
@@ -104,6 +108,9 @@ EventEdit::EventEdit(QWidget *parent)
     mEndDateTimeEdit = new KDateTimeEdit;
     mEndDateTimeEdit->setObjectName(QLatin1String("enddatetimeedit"));
     mEndDateTimeEdit->setDateTime(currentDateTime.addSecs(3600));
+#ifndef QT_NO_ACCESSIBILITY
+    mEndDateTimeEdit->setAccessibleDescription( i18n("Select end time for event.") );
+#endif
     hbox->addWidget(mEndDateTimeEdit);
 
     readConfig();


commit 79b771829ca89c3fec04bb86dd2d6e7ef3d58c25
Author: Montel Laurent <montel at kde.org>
Date:   Mon Mar 3 21:33:21 2014 +0100

    Add action. Reduce spacing

diff --git a/kmail/kmail_part.rc b/kmail/kmail_part.rc
index 12dbc99..2e72884 100644
--- a/kmail/kmail_part.rc
+++ b/kmail/kmail_part.rc
@@ -2,7 +2,7 @@
      the same menu entries at the same place in KMail and Kontact  -->
 
 <!DOCTYPE kpartgui>
-<kpartgui version="496" name="kmmainwin" >
+<kpartgui version="497" name="kmmainwin" >
  <MenuBar>
   <Menu noMerge="1" name="file" >
    <text>&File</text>
@@ -281,6 +281,7 @@
   <Action name="akonadi_item_copy_to_menu"/>
   <Separator/>
   <Action name="create_todo"/>
+  <Action name="create_event"/>
   <Separator/>
   <Action name="annotate"/>
  </Menu>
diff --git a/kmail/kmmainwin.rc b/kmail/kmmainwin.rc
index 12dbc99..2e72884 100644
--- a/kmail/kmmainwin.rc
+++ b/kmail/kmmainwin.rc
@@ -2,7 +2,7 @@
      the same menu entries at the same place in KMail and Kontact  -->
 
 <!DOCTYPE kpartgui>
-<kpartgui version="496" name="kmmainwin" >
+<kpartgui version="497" name="kmmainwin" >
  <MenuBar>
   <Menu noMerge="1" name="file" >
    <text>&File</text>
@@ -281,6 +281,7 @@
   <Action name="akonadi_item_copy_to_menu"/>
   <Separator/>
   <Action name="create_todo"/>
+  <Action name="create_event"/>
   <Separator/>
   <Action name="annotate"/>
  </Menu>
diff --git a/messageviewer/widgets/eventedit.cpp b/messageviewer/widgets/eventedit.cpp
index 8a8717b..afb6371 100644
--- a/messageviewer/widgets/eventedit.cpp
+++ b/messageviewer/widgets/eventedit.cpp
@@ -43,6 +43,7 @@ EventEdit::EventEdit(QWidget *parent)
     : QWidget(parent)
 {
     QVBoxLayout *vbox = new QVBoxLayout;
+    vbox->setSpacing(0);
     setLayout(vbox);
     QHBoxLayout *hbox = new QHBoxLayout;
     hbox->setMargin(2);


commit 828352bb1bc8467ac64f320ec6b1fb5acf33a505
Author: Montel Laurent <montel at kde.org>
Date:   Mon Mar 3 21:29:58 2014 +0100

    Add end/start time

diff --git a/messageviewer/tests/eventedittest.cpp b/messageviewer/tests/eventedittest.cpp
index 5ec756c..b7d6248 100644
--- a/messageviewer/tests/eventedittest.cpp
+++ b/messageviewer/tests/eventedittest.cpp
@@ -118,7 +118,6 @@ void EventEditTest::shouldNotEmitWhenCollectionIsNotChanged()
     QCOMPARE(spy.count(), 0);
 }
 
-
 void EventEditTest::shouldNotEmitWhenMessageIsNotChanged()
 {
     MessageViewer::EventEdit edit;
@@ -220,5 +219,31 @@ void EventEditTest::shouldSelectLineWhenPutMessage()
     QCOMPARE(selectedText, QString::fromLatin1("Reply to \"%1\"").arg(subject));
 }
 
+void EventEditTest::shouldHaveCorrectStartEndDateTime()
+{
+    MessageViewer::EventEdit edit;
+    KMime::Message::Ptr msg(new KMime::Message);
+    QString subject = QLatin1String("Test Note");
+    msg->subject(true)->fromUnicodeString(subject, "us-ascii");
+    edit.setMessage(msg);
+
+    KDateTime currentDateTime = KDateTime::currentDateTime(KDateTime::LocalZone);
+    KDateTimeEdit *startDateTime = qFindChild<KDateTimeEdit *>(&edit, QLatin1String("startdatetimeedit"));
+    startDateTime->setDateTime(currentDateTime);
+
+    KDateTime endDt = currentDateTime.addDays(1);
+    KDateTimeEdit *endDateTime = qFindChild<KDateTimeEdit *>(&edit, QLatin1String("enddatetimeedit"));
+    endDateTime->setDateTime(endDt);
+
+    QLineEdit *noteedit = qFindChild<QLineEdit *>(&edit, QLatin1String("noteedit"));
+    QSignalSpy spy(&edit, SIGNAL(createEvent(KCalCore::Event::Ptr,Akonadi::Collection)));
+    QTest::keyClick(noteedit, Qt::Key_Enter);
+    QCOMPARE(spy.count(), 1);
+    KCalCore::Event::Ptr eventPtr = spy.at(0).at(0).value<KCalCore::Event::Ptr>();
+    QVERIFY(eventPtr);
+    QCOMPARE(eventPtr->dtStart(), currentDateTime);
+    QCOMPARE(eventPtr->dtEnd(), endDt);
+}
+
 
 QTEST_KDEMAIN( EventEditTest, GUI )
diff --git a/messageviewer/tests/eventedittest.h b/messageviewer/tests/eventedittest.h
index 8055ddb..5506644 100644
--- a/messageviewer/tests/eventedittest.h
+++ b/messageviewer/tests/eventedittest.h
@@ -38,6 +38,7 @@ private Q_SLOTS:
     void shouldHideWidgetWhenPressEscape();
     void shouldEventHasCorrectSubject();
     void shouldSelectLineWhenPutMessage();
+    void shouldHaveCorrectStartEndDateTime();
 };
 
 #endif // EVENTEDITTEST_H
diff --git a/messageviewer/widgets/eventedit.cpp b/messageviewer/widgets/eventedit.cpp
index d4ce112..8a8717b 100644
--- a/messageviewer/widgets/eventedit.cpp
+++ b/messageviewer/widgets/eventedit.cpp
@@ -188,6 +188,8 @@ void EventEdit::slotReturnPressed()
 
     if (!mNoteEdit->text().trimmed().isEmpty()) {
         KCalCore::Event::Ptr event( new KCalCore::Event );
+        event->setDtStart(mStartDateTimeEdit->dateTime());
+        event->setDtEnd(mEndDateTimeEdit->dateTime());
         event->setSummary(mNoteEdit->text());
         Q_EMIT createEvent(event, collection);
         mNoteEdit->clear();


commit c000d4cfea2e28926962fd717419feb820f0b737
Author: Montel Laurent <montel at kde.org>
Date:   Mon Mar 3 21:23:19 2014 +0100

    Add createEventAction

diff --git a/kmail/kmmainwidget.cpp b/kmail/kmmainwidget.cpp
index 7d24201..34d740b 100644
--- a/kmail/kmmainwidget.cpp
+++ b/kmail/kmmainwidget.cpp
@@ -2920,6 +2920,7 @@ void KMMainWidget::showMessagePopup(const Akonadi::Item&msg ,const KUrl&url,cons
         }
         menu->addSeparator();
         menu->addAction( mMsgView->createTodoAction() );
+        menu->addAction( mMsgView->createEventAction() );
         menu->addSeparator();
         if (mMsgView) {
             menu->addAction( mMsgView->saveMessageDisplayFormatAction() );
diff --git a/kmail/kmreadermainwin.cpp b/kmail/kmreadermainwin.cpp
index 2618480..600152d 100644
--- a/kmail/kmreadermainwin.cpp
+++ b/kmail/kmreadermainwin.cpp
@@ -577,6 +577,7 @@ void KMReaderMainWin::showMessagePopup(const Akonadi::Item&msg ,const KUrl&url,c
             if ( msg.isValid() ) {
                 menu->addSeparator();
                 menu->addAction( mReaderWin->createTodoAction() );
+                menu->addAction( mReaderWin->createEventAction() );
                 menu->addSeparator();
                 menu->addAction( mReaderWin->saveMessageDisplayFormatAction() );
                 menu->addAction( mReaderWin->resetMessageDisplayFormatAction() );
diff --git a/kmail/kmreaderwin.cpp b/kmail/kmreaderwin.cpp
index 6d6adf6..6fa5a12 100644
--- a/kmail/kmreaderwin.cpp
+++ b/kmail/kmreaderwin.cpp
@@ -920,5 +920,10 @@ KAction *KMReaderWin::createTodoAction() const
     return mViewer->createTodoAction();
 }
 
+KAction *KMReaderWin::createEventAction() const
+{
+    return mViewer->createEventAction();
+}
+
 
 
diff --git a/kmail/kmreaderwin.h b/kmail/kmreaderwin.h
index d046928..ee084ad 100644
--- a/kmail/kmreaderwin.h
+++ b/kmail/kmreaderwin.h
@@ -155,6 +155,7 @@ public:
     KAction *openBlockableItems() const;
     KAction *expandShortUrlAction() const;
     KAction *createTodoAction() const;
+    KAction *createEventAction() const;
 
     KAction *editContactAction() const { return mEditContactAction; }
 
diff --git a/messageviewer/tests/viewertest.cpp b/messageviewer/tests/viewertest.cpp
index fb36b3f..2908162 100644
--- a/messageviewer/tests/viewertest.cpp
+++ b/messageviewer/tests/viewertest.cpp
@@ -56,6 +56,7 @@ void ViewerTest::shouldHaveDefaultValuesOnCreation()
     QVERIFY(viewer.openBlockableItems());
     QVERIFY(viewer.expandShortUrlAction());
     QVERIFY(viewer.createTodoAction());
+    QVERIFY(viewer.createEventAction());
     QVERIFY(viewer.urlClicked().isEmpty());
     QVERIFY(viewer.imageUrlClicked().isEmpty());
     QCOMPARE(viewer.isFixedFont(), false);
diff --git a/messageviewer/viewer/viewer.cpp b/messageviewer/viewer/viewer.cpp
index 6e84788..f6a9604 100644
--- a/messageviewer/viewer/viewer.cpp
+++ b/messageviewer/viewer/viewer.cpp
@@ -695,6 +695,12 @@ KAction *Viewer::createTodoAction()
     return d->mCreateTodoAction;
 }
 
+KAction *Viewer::createEventAction()
+{
+    Q_D( Viewer );
+    return d->mCreateEventAction;
+}
+
 }
 
 
diff --git a/messageviewer/viewer/viewer.h b/messageviewer/viewer/viewer.h
index ab52727..9fa24d8 100644
--- a/messageviewer/viewer/viewer.h
+++ b/messageviewer/viewer/viewer.h
@@ -284,6 +284,7 @@ public:
     KAction *openBlockableItems();
     KAction *expandShortUrlAction();
     KAction *createTodoAction();
+    KAction *createEventAction();
 
     HeaderStrategy * headerStrategy() const;
 
diff --git a/messageviewer/viewer/viewer_p.cpp b/messageviewer/viewer/viewer_p.cpp
index 07cc7ad..8b68c88 100644
--- a/messageviewer/viewer/viewer_p.cpp
+++ b/messageviewer/viewer/viewer_p.cpp
@@ -1327,6 +1327,7 @@ void ViewerPrivate::resetStateForNewMessage()
     mFindBar->closeBar();
     mTranslatorWidget->slotCloseWidget();
     mCreateTodo->slotCloseWidget();
+    mCreateEvent->slotCloseWidget();
     mScamDetectionWarning->setVisible(false);
 
     if ( mPrinting ) {
@@ -1868,6 +1869,14 @@ void ViewerPrivate::createActions()
     ac->addAction(QLatin1String("create_todo"), mCreateTodoAction);
     mCreateTodoAction->setShortcut(Qt::CTRL + Qt::Key_T);
     connect( mCreateTodoAction, SIGNAL(triggered(bool)), SLOT(slotShowCreateTodoWidget()) );
+
+    mCreateEventAction = new KAction(KIcon( QLatin1String("appointment-new") ),i18n("Create Event"), this);
+    mCreateEventAction->setIconText( i18n( "Create Event" ) );
+    mCreateEventAction->setHelpText( i18n( "Allows you to create a calendar Event" ) );
+    ac->addAction(QLatin1String("create_event"), mCreateEventAction);
+    //TODO
+    //mCreateEventAction->setShortcut(Qt::CTRL + Qt::Key_T);
+    connect( mCreateEventAction, SIGNAL(triggered(bool)), SLOT(slotShowCreateEventWidget()) );
 }
 
 
@@ -3394,6 +3403,16 @@ void ViewerPrivate::slotCreateTodo(const KCalCore::Todo::Ptr &todoPtr, const Ako
     createJob->start();
 }
 
+void ViewerPrivate::slotShowCreateEventWidget()
+{
+    if (mMessage) {
+        mCreateEvent->setMessage(mMessage);
+        mCreateEvent->show();
+    } else {
+        qDebug()<<" There is not valid message";
+    }
+}
+
 void ViewerPrivate::slotCreateEvent(const KCalCore::Event::Ptr &eventPtr, const Akonadi::Collection &collection)
 {
     CreateEventJob *createJob = new CreateEventJob(eventPtr, collection, mMessageItem, this);
diff --git a/messageviewer/viewer/viewer_p.h b/messageviewer/viewer/viewer_p.h
index cf007a7..8890f03 100644
--- a/messageviewer/viewer/viewer_p.h
+++ b/messageviewer/viewer/viewer_p.h
@@ -501,6 +501,7 @@ private slots:
     void slotCreateTodo(const KCalCore::Todo::Ptr &, const Akonadi::Collection &collection);
 
     void slotCreateEvent(const KCalCore::Event::Ptr &eventPtr, const Akonadi::Collection &collection);
+
 public slots:
     /** An URL has been activate with a click. */
     void slotUrlOpen( const QUrl &url = QUrl());
@@ -613,6 +614,7 @@ public slots:
     void slotOpenBlockableItems();
     void slotExpandShortUrl();
     void slotShowCreateTodoWidget();
+    void slotShowCreateEventWidget();
 
 signals:
     void showStatusBarMessage( const QString &message );
@@ -689,6 +691,7 @@ public:
     KAction *mBlockableItems;
     KAction *mExpandUrlAction;
     KAction *mCreateTodoAction;
+    KAction *mCreateEventAction;
     KUrl mHoveredUrl;
     KUrl mClickedUrl;
     KUrl mImageUrl;
diff --git a/messageviewer/widgets/eventedit.cpp b/messageviewer/widgets/eventedit.cpp
index cd74903..d4ce112 100644
--- a/messageviewer/widgets/eventedit.cpp
+++ b/messageviewer/widgets/eventedit.cpp
@@ -63,7 +63,7 @@ EventEdit::EventEdit(QWidget *parent)
     hbox->addWidget( closeBtn );
     connect( closeBtn, SIGNAL(clicked()), this, SLOT(slotCloseWidget()) );
 
-    QLabel *lab = new QLabel(i18n("Todo:"));
+    QLabel *lab = new QLabel(i18n("Event:"));
     hbox->addWidget(lab);
 
     mNoteEdit = new KLineEdit;
@@ -88,6 +88,7 @@ EventEdit::EventEdit(QWidget *parent)
     hbox = new QHBoxLayout;
     vbox->addLayout(hbox);
 
+    hbox->addStretch();
     lab = new QLabel(i18n("Start:"));
     hbox->addWidget(lab);
     KDateTime currentDateTime = KDateTime::currentDateTime(KDateTime::LocalZone);


commit eb8f4bc127d70899b500c34ebc8a5f2140514c37
Author: Montel Laurent <montel at kde.org>
Date:   Mon Mar 3 20:29:41 2014 +0100

    implement create event

diff --git a/messageviewer/CMakeLists.txt b/messageviewer/CMakeLists.txt
index 538f726..2dcdf69 100644
--- a/messageviewer/CMakeLists.txt
+++ b/messageviewer/CMakeLists.txt
@@ -92,13 +92,13 @@ set(libmessageviewer_viewer_SRCS
 
 set(libmessageviewer_widgets_SRCS
   widgets/attachmentdialog.cpp
-  
   widgets/configurewidget.cpp
   widgets/printingsettings.cpp
   widgets/htmlstatusbar.cpp
   widgets/vcardviewer.cpp
   widgets/invitationsettings.cpp
   widgets/todoedit.cpp
+  widgets/eventedit.cpp
 )
 
 set(libmessageviewer_header_SRCS
@@ -153,6 +153,7 @@ set(libmessageviewer_antispam_SRCS
 
 set(libmessageviewer_job_SRCS
   job/createtodojob.cpp
+  job/createeventjob.cpp
 )
 
 set(libmessageviewer_SRCS
diff --git a/messageviewer/job/createeventjob.cpp b/messageviewer/job/createeventjob.cpp
new file mode 100644
index 0000000..571b5c0
--- /dev/null
+++ b/messageviewer/job/createeventjob.cpp
@@ -0,0 +1,103 @@
+/*
+  Copyright (c) 2014 Montel Laurent <montel at kde.org>
+
+  This program is free software; you can redistribute it and/or modify it
+  under the terms of the GNU General Public License, version 2, as
+  published by the Free Software Foundation.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License along
+  with this program; if not, write to the Free Software Foundation, Inc.,
+  51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "createeventjob.h"
+
+#include <Akonadi/KMime/MessageParts>
+#include <Akonadi/ItemFetchJob>
+#include <Akonadi/ItemFetchScope>
+#include <Akonadi/ItemCreateJob>
+
+#include <KMime/Message>
+#include <QDebug>
+
+using namespace MessageViewer;
+
+CreateEventJob::CreateEventJob(const KCalCore::Event::Ptr &eventPtr, const Akonadi::Collection &collection, const Akonadi::Item &item, QObject *parent)
+    : KJob(parent),
+      mItem(item),
+      mCollection(collection),
+      mEventPtr(eventPtr)
+{
+}
+
+CreateEventJob::~CreateEventJob()
+{
+    qDebug()<<" CreateEventJob::~CreateEventJob()";
+}
+
+void CreateEventJob::start()
+{
+    // We need the full payload to attach the mail to the incidence
+    if ( !mItem.loadedPayloadParts().contains( Akonadi::MessagePart::Body ) ) {
+        Akonadi::ItemFetchJob *job = new Akonadi::ItemFetchJob( mItem );
+        job->fetchScope().fetchFullPayload();
+        connect( job, SIGNAL(result(KJob*)), this, SLOT(slotFetchDone(KJob*)) );
+
+        if ( job->exec() ) {
+            if ( job->items().count() == 1 ) {
+                mItem = job->items().first();
+            }
+        } else {
+            qDebug()<<" createTodo Error during fetch: "<<job->errorString();
+        }
+    } else {
+        createEvent();
+    }
+}
+
+void CreateEventJob::slotFetchDone(KJob *job)
+{
+    qDebug()<<" void CreateEventJob::slotFetchDone(KJob *job)";
+    Akonadi::ItemFetchJob *fetchJob = qobject_cast<Akonadi::ItemFetchJob *>(job);
+    if ( fetchJob->items().count() == 1 ) {
+        mItem = fetchJob->items().first();
+    } else {
+        Q_EMIT emitResult();
+        return;
+    }
+    createEvent();
+}
+
+void CreateEventJob::createEvent()
+{
+    if ( !mItem.hasPayload<KMime::Message::Ptr>() ) {
+        qDebug()<<" item has not payload";
+        Q_EMIT emitResult();
+        return;
+    }
+    KMime::Message::Ptr msg =  mItem.payload<KMime::Message::Ptr>();
+
+    KCalCore::Attachment::Ptr attachmentPtr(new KCalCore::Attachment( msg->encodedContent().toBase64(), KMime::Message::mimeType() ));
+    attachmentPtr->setLabel(msg->subject(false)->asUnicodeString());
+    mEventPtr->addAttachment(attachmentPtr);
+
+    Akonadi::Item newTodoItem;
+    newTodoItem.setMimeType( KCalCore::Event::eventMimeType() );
+    newTodoItem.setPayload<KCalCore::Event::Ptr>( mEventPtr );
+
+    Akonadi::ItemCreateJob *createJob = new Akonadi::ItemCreateJob(newTodoItem, mCollection);
+    connect(createJob, SIGNAL(result(KJob*)), this, SLOT(slotCreateNewEvent(KJob*)));
+}
+
+void CreateEventJob::slotCreateNewEvent(KJob *job)
+{
+    if ( job->error() ) {
+        qDebug() << "Error during create new Todo "<<job->errorString();
+    }
+    Q_EMIT emitResult();
+}
diff --git a/messageviewer/job/createeventjob.h b/messageviewer/job/createeventjob.h
new file mode 100644
index 0000000..b87aa2a
--- /dev/null
+++ b/messageviewer/job/createeventjob.h
@@ -0,0 +1,48 @@
+/*
+  Copyright (c) 2014 Montel Laurent <montel at kde.org>
+
+  This program is free software; you can redistribute it and/or modify it
+  under the terms of the GNU General Public License, version 2, as
+  published by the Free Software Foundation.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License along
+  with this program; if not, write to the Free Software Foundation, Inc.,
+  51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef CREATEEVENTJOB_H
+#define CREATEEVENTJOB_H
+#include <KJob>
+#include <Akonadi/Item>
+#include <Akonadi/Collection>
+#include <KCalCore/Event>
+
+#include <QObject>
+namespace MessageViewer {
+class CreateEventJob : public KJob
+{
+    Q_OBJECT
+public:
+    explicit CreateEventJob(const KCalCore::Event::Ptr &eventPtr, const Akonadi::Collection &collection, const Akonadi::Item &item, QObject *parent = 0);
+    ~CreateEventJob();
+
+    void start();
+
+private slots:
+    void slotFetchDone(KJob *job);
+    void slotCreateNewEvent(KJob *job);
+
+private:
+    void createEvent();
+    Akonadi::Item mItem;
+    Akonadi::Collection mCollection;
+    KCalCore::Event::Ptr mEventPtr;
+};
+}
+
+#endif // CREATETODOJOB_H
diff --git a/messageviewer/settings/messageviewer.kcfg.cmake b/messageviewer/settings/messageviewer.kcfg.cmake
index 839219a..15cbf91 100644
--- a/messageviewer/settings/messageviewer.kcfg.cmake
+++ b/messageviewer/settings/messageviewer.kcfg.cmake
@@ -312,6 +312,12 @@ xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0 http://www.kde.org/sta
         <default>-1</default>
       </entry>
     </group>
+    <group name="Event">
+      <entry name="LastEventSelectedFolder" type="LongLong">
+        <whatsthis>The most recent selected folder using for Event.</whatsthis>
+        <default>-1</default>
+      </entry>
+    </group>
 
 </kcfg>
 
diff --git a/messageviewer/tests/CMakeLists.txt b/messageviewer/tests/CMakeLists.txt
index f68a923..05fb29f 100644
--- a/messageviewer/tests/CMakeLists.txt
+++ b/messageviewer/tests/CMakeLists.txt
@@ -39,6 +39,7 @@ kde4_handle_crypto_rpath_for_executable( rendertest )
 add_messageviewer_unittest( unencryptedmessagetest.cpp )
 kde4_handle_crypto_rpath_for_executable( unencryptedmessagetest )
 add_messageviewer_unittest( todoedittest.cpp )
+add_messageviewer_unittest( eventedittest.cpp )
 ########### viewertest_gui ###############
 
 
diff --git a/messageviewer/tests/eventedittest.cpp b/messageviewer/tests/eventedittest.cpp
new file mode 100644
index 0000000..5ec756c
--- /dev/null
+++ b/messageviewer/tests/eventedittest.cpp
@@ -0,0 +1,224 @@
+/*
+  Copyright (c) 2014 Montel Laurent <montel at kde.org>
+
+  This program is free software; you can redistribute it and/or modify it
+  under the terms of the GNU General Public License, version 2, as
+  published by the Free Software Foundation.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License along
+  with this program; if not, write to the Free Software Foundation, Inc.,
+  51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+#include "eventedittest.h"
+#include "widgets/eventedit.h"
+#include "messageviewer/globalsettings_base.h"
+
+#include <Akonadi/Collection>
+#include <Akonadi/CollectionComboBox>
+#include <Akonadi/EntityTreeModel>
+#include <QStandardItemModel>
+#include <kcalcore/event.h>
+#include <KDateTimeEdit>
+
+#include <qtest_kde.h>
+#include <qtestkeyboard.h>
+#include <qtestmouse.h>
+
+#include <QLineEdit>
+#include <QToolButton>
+#include <QHBoxLayout>
+#include <QShortcut>
+#include <QAction>
+
+namespace MessageViewer {
+extern MESSAGEVIEWER_EXPORT QAbstractItemModel *_k_eventEditStubModel;
+}
+
+
+Q_DECLARE_METATYPE(KMime::Message::Ptr)
+EventEditTest::EventEditTest()
+{
+    qRegisterMetaType<Akonadi::Collection>();
+    qRegisterMetaType<KMime::Message::Ptr>();
+    qRegisterMetaType<KCalCore::Event::Ptr>();
+
+    QStandardItemModel *model = new QStandardItemModel;
+    for (int id = 42; id < 51; ++id) {
+        Akonadi::Collection collection(id);
+        collection.setRights(Akonadi::Collection::AllRights);
+        collection.setName(QString::number(id));
+        collection.setContentMimeTypes(QStringList() << KCalCore::Event::eventMimeType());
+
+        QStandardItem *item = new QStandardItem(collection.name());
+        item->setData(QVariant::fromValue(collection),
+                      Akonadi::EntityTreeModel::CollectionRole);
+        item->setData(QVariant::fromValue(collection.id()),
+                      Akonadi::EntityTreeModel::CollectionIdRole);
+
+        model->appendRow(item);
+    }
+    MessageViewer::_k_eventEditStubModel = model;
+}
+
+void EventEditTest::shouldHaveDefaultValuesOnCreation()
+{
+    MessageViewer::EventEdit edit;
+    QVERIFY(!edit.collection().isValid());
+    QVERIFY(!edit.message());
+    QLineEdit *noteedit = qFindChild<QLineEdit *>(&edit, QLatin1String("noteedit"));
+    QVERIFY(noteedit);
+    QCOMPARE(noteedit->text(), QString());
+
+    KDateTime currentDateTime = KDateTime::currentDateTime(KDateTime::LocalZone);
+    KDateTimeEdit *startDateTime = qFindChild<KDateTimeEdit *>(&edit, QLatin1String("startdatetimeedit"));
+    QVERIFY(startDateTime);
+    QCOMPARE(startDateTime->dateTime().date(), currentDateTime.date());
+    QCOMPARE(startDateTime->dateTime().time().hour(), currentDateTime.time().hour());
+    QCOMPARE(startDateTime->dateTime().time().minute(), currentDateTime.time().minute());
+
+    KDateTimeEdit *endDateTime = qFindChild<KDateTimeEdit *>(&edit, QLatin1String("enddatetimeedit"));
+    QVERIFY(endDateTime);
+    QCOMPARE(endDateTime->dateTime().date(), currentDateTime.date());
+    QCOMPARE(endDateTime->dateTime().time().hour(), currentDateTime.time().hour() + 1);
+    QCOMPARE(endDateTime->dateTime().time().minute(), currentDateTime.time().minute());
+}
+
+void EventEditTest::shouldEmitCollectionChanged()
+{
+    MessageViewer::EventEdit edit;
+    QSignalSpy spy(&edit, SIGNAL(collectionChanged(Akonadi::Collection)));
+    edit.setCollection(Akonadi::Collection(42));
+    QCOMPARE(spy.count(), 1);
+    QCOMPARE(spy.at(0).at(0).value<Akonadi::Collection>(), Akonadi::Collection(42));
+}
+
+void EventEditTest::shouldEmitMessageChanged()
+{
+    MessageViewer::EventEdit edit;
+    QSignalSpy spy(&edit, SIGNAL(messageChanged(KMime::Message::Ptr)));
+    KMime::Message::Ptr msg(new KMime::Message);
+    edit.setMessage(msg);
+    QCOMPARE(spy.count(), 1);
+    QCOMPARE(spy.at(0).at(0).value<KMime::Message::Ptr>(), msg);
+}
+
+void EventEditTest::shouldNotEmitWhenCollectionIsNotChanged()
+{
+    MessageViewer::EventEdit edit;
+    edit.setCollection(Akonadi::Collection(42));
+    QSignalSpy spy(&edit, SIGNAL(collectionChanged(Akonadi::Collection)));
+    edit.setCollection(Akonadi::Collection(42));
+    QCOMPARE(spy.count(), 0);
+}
+
+
+void EventEditTest::shouldNotEmitWhenMessageIsNotChanged()
+{
+    MessageViewer::EventEdit edit;
+    KMime::Message::Ptr msg(new KMime::Message);
+    edit.setMessage(msg);
+    QSignalSpy spy(&edit, SIGNAL(messageChanged(KMime::Message::Ptr)));
+    edit.setMessage(msg);
+    QCOMPARE(spy.count(), 0);
+}
+
+void EventEditTest::shouldEmitEventWhenPressEnter()
+{
+    MessageViewer::EventEdit edit;
+    KMime::Message::Ptr msg(new KMime::Message);
+    QString subject = QLatin1String("Test Note");
+    msg->subject(true)->fromUnicodeString(subject, "us-ascii");
+    edit.setMessage(msg);
+    QLineEdit *noteedit = qFindChild<QLineEdit *>(&edit, QLatin1String("noteedit"));
+    QSignalSpy spy(&edit, SIGNAL(createEvent(KCalCore::Event::Ptr,Akonadi::Collection)));
+    QTest::keyClick(noteedit, Qt::Key_Enter);
+    QCOMPARE(spy.count(), 1);
+}
+
+void EventEditTest::shouldHideWidgetWhenPressEnter()
+{
+    MessageViewer::EventEdit edit;
+    edit.show();
+    QTest::qWaitForWindowShown(&edit);
+    QVERIFY(edit.isVisible());
+
+    KMime::Message::Ptr msg(new KMime::Message);
+    QString subject = QLatin1String("Test Note");
+    msg->subject(true)->fromUnicodeString(subject, "us-ascii");
+    edit.setMessage(msg);
+    QLineEdit *noteedit = qFindChild<QLineEdit *>(&edit, QLatin1String("noteedit"));
+    QTest::keyClick(noteedit, Qt::Key_Enter);
+    QCOMPARE(edit.isVisible(), false);
+}
+
+void EventEditTest::shouldHideWidgetWhenPressEscape()
+{
+    MessageViewer::EventEdit edit;
+    edit.show();
+    QTest::qWaitForWindowShown(&edit);
+    QLineEdit *noteedit = qFindChild<QLineEdit *>(&edit, QLatin1String("noteedit"));
+    noteedit->setFocus();
+    QVERIFY(noteedit->hasFocus());
+    QTest::keyPress(&edit, Qt::Key_Escape);
+    QCOMPARE(edit.isVisible(), false);
+}
+
+void EventEditTest::shouldSaveCollectionSettings()
+{
+    MessageViewer::EventEdit edit;
+    Akonadi::CollectionComboBox *akonadicombobox = qFindChild<Akonadi::CollectionComboBox *>(&edit, QLatin1String("akonadicombobox"));
+    akonadicombobox->setCurrentIndex(3);
+    const Akonadi::Collection::Id id = akonadicombobox->currentCollection().id();
+    QToolButton *close = qFindChild<QToolButton *>(&edit, QLatin1String("close-button"));
+    QTest::mouseClick(close, Qt::LeftButton);
+    QCOMPARE(MessageViewer::GlobalSettingsBase::self()->lastEventSelectedFolder(), id);
+}
+
+void EventEditTest::shouldSaveCollectionSettingsWhenCloseWidget()
+{
+    MessageViewer::EventEdit edit;
+    Akonadi::CollectionComboBox *akonadicombobox = qFindChild<Akonadi::CollectionComboBox *>(&edit, QLatin1String("akonadicombobox"));
+    akonadicombobox->setCurrentIndex(3);
+    const Akonadi::Collection::Id id = akonadicombobox->currentCollection().id();
+    edit.writeConfig();
+    QCOMPARE(MessageViewer::GlobalSettingsBase::self()->lastEventSelectedFolder(), id);
+}
+
+void EventEditTest::shouldEventHasCorrectSubject()
+{
+    MessageViewer::EventEdit edit;
+    KMime::Message::Ptr msg(new KMime::Message);
+    QString subject = QLatin1String("Test Note");
+    msg->subject(true)->fromUnicodeString(subject, "us-ascii");
+    edit.setMessage(msg);
+    QLineEdit *noteedit = qFindChild<QLineEdit *>(&edit, QLatin1String("noteedit"));
+    QSignalSpy spy(&edit, SIGNAL(createEvent(KCalCore::Event::Ptr,Akonadi::Collection)));
+    QTest::keyClick(noteedit, Qt::Key_Enter);
+    QCOMPARE(spy.count(), 1);
+    KCalCore::Event::Ptr eventPtr = spy.at(0).at(0).value<KCalCore::Event::Ptr>();
+    QVERIFY(eventPtr);
+    QCOMPARE(eventPtr->summary(), QString::fromLatin1("Reply to \"%1\"").arg(subject));
+}
+
+void EventEditTest::shouldSelectLineWhenPutMessage()
+{
+    MessageViewer::EventEdit edit;
+    KMime::Message::Ptr msg(new KMime::Message);
+    QString subject = QLatin1String("Test Note");
+    msg->subject(true)->fromUnicodeString(subject, "us-ascii");
+    edit.setMessage(msg);
+    QLineEdit *noteedit = qFindChild<QLineEdit *>(&edit, QLatin1String("noteedit"));
+    QVERIFY(noteedit->hasSelectedText());
+    const QString selectedText = noteedit->selectedText();
+    QCOMPARE(selectedText, QString::fromLatin1("Reply to \"%1\"").arg(subject));
+}
+
+
+QTEST_KDEMAIN( EventEditTest, GUI )
diff --git a/messageviewer/tests/eventedittest.h b/messageviewer/tests/eventedittest.h
new file mode 100644
index 0000000..8055ddb
--- /dev/null
+++ b/messageviewer/tests/eventedittest.h
@@ -0,0 +1,43 @@
+/*
+  Copyright (c) 2014 Montel Laurent <montel at kde.org>
+
+  This program is free software; you can redistribute it and/or modify it
+  under the terms of the GNU General Public License, version 2, as
+  published by the Free Software Foundation.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License along
+  with this program; if not, write to the Free Software Foundation, Inc.,
+  51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef EVENTEDITTEST_H
+#define EVENTEDITTEST_H
+#include <QObject>
+
+class EventEditTest : public QObject
+{
+    Q_OBJECT
+public:
+    EventEditTest();
+
+private Q_SLOTS:
+    void shouldHaveDefaultValuesOnCreation();
+    void shouldEmitCollectionChanged();
+    void shouldEmitMessageChanged();
+    void shouldNotEmitWhenCollectionIsNotChanged();
+    void shouldNotEmitWhenMessageIsNotChanged();
+    void shouldHideWidgetWhenPressEnter();
+    void shouldEmitEventWhenPressEnter();
+    void shouldSaveCollectionSettingsWhenCloseWidget();
+    void shouldSaveCollectionSettings();
+    void shouldHideWidgetWhenPressEscape();
+    void shouldEventHasCorrectSubject();
+    void shouldSelectLineWhenPutMessage();
+};
+
+#endif // EVENTEDITTEST_H
diff --git a/messageviewer/viewer/viewer_p.cpp b/messageviewer/viewer/viewer_p.cpp
index f93e130..07cc7ad 100644
--- a/messageviewer/viewer/viewer_p.cpp
+++ b/messageviewer/viewer/viewer_p.cpp
@@ -33,6 +33,7 @@
 #include "scamdetection/scamattribute.h"
 #include "adblock/adblockmanager.h"
 #include "widgets/todoedit.h"
+#include "widgets/eventedit.h"
 
 #ifdef MESSAGEVIEWER_READER_HTML_DEBUG
 #include "htmlwriter/filehtmlwriter.h"
@@ -136,6 +137,7 @@
 #include "findbar/findbarmailwebview.h"
 #include "pimcommon/translator/translatorwidget.h"
 #include "job/createtodojob.h"
+#include "job/createeventjob.h"
 
 #include "interfaces/bodypart.h"
 #include "interfaces/htmlwriter.h"
@@ -1539,6 +1541,11 @@ void ViewerPrivate::createWidgets() {
     mCreateTodo->setObjectName(QLatin1String("createtodowidget"));
     mCreateTodo->hide();
 
+    mCreateEvent = new MessageViewer::EventEdit(readerBox);
+    connect(mCreateEvent, SIGNAL(createEvent(KCalCore::Event::Ptr,Akonadi::Collection)), this, SLOT(slotCreateEvent(KCalCore::Event::Ptr,Akonadi::Collection)));
+    mCreateEvent->setObjectName(QLatin1String("createeventwidget"));
+    mCreateEvent->hide();
+
     mFindBar = new FindBarMailWebView( mViewer, readerBox );
     mTranslatorWidget = new PimCommon::TranslatorWidget(readerBox);
 #ifndef QT_NO_TREEVIEW
@@ -3386,3 +3393,9 @@ void ViewerPrivate::slotCreateTodo(const KCalCore::Todo::Ptr &todoPtr, const Ako
     CreateTodoJob *createJob = new CreateTodoJob(todoPtr, collection, mMessageItem, this);
     createJob->start();
 }
+
+void ViewerPrivate::slotCreateEvent(const KCalCore::Event::Ptr &eventPtr, const Akonadi::Collection &collection)
+{
+    CreateEventJob *createJob = new CreateEventJob(eventPtr, collection, mMessageItem, this);
+    createJob->start();
+}
diff --git a/messageviewer/viewer/viewer_p.h b/messageviewer/viewer/viewer_p.h
index d525b02..cf007a7 100644
--- a/messageviewer/viewer/viewer_p.h
+++ b/messageviewer/viewer/viewer_p.h
@@ -32,6 +32,7 @@
 #include <ksharedconfig.h>
 #include <kurl.h>
 #include <KCalCore/Todo>
+#include <KCalCore/Event>
 
 #include <QObject>
 #include <QTimer>
@@ -58,6 +59,7 @@ class QTreeView;
 
 namespace MessageViewer {
 class TodoEdit;
+class EventEdit;
 class EditorWatcher;
 class HtmlWriter;
 class CSSHelper;
@@ -498,6 +500,7 @@ private slots:
 
     void slotCreateTodo(const KCalCore::Todo::Ptr &, const Akonadi::Collection &collection);
 
+    void slotCreateEvent(const KCalCore::Event::Ptr &eventPtr, const Akonadi::Collection &collection);
 public slots:
     /** An URL has been activate with a click. */
     void slotUrlOpen( const QUrl &url = QUrl());
@@ -722,6 +725,7 @@ public:
     GrantleeTheme::GrantleeThemeManager *mThemeManager;
     ScamDetectionWarningWidget *mScamDetectionWarning;
     MessageViewer::TodoEdit *mCreateTodo;
+    MessageViewer::EventEdit *mCreateEvent;
     // zoom Factor
     static const qreal zoomBy;
     qreal mZoomFactor;
diff --git a/messageviewer/widgets/eventedit.cpp b/messageviewer/widgets/eventedit.cpp
new file mode 100644
index 0000000..cd74903
--- /dev/null
+++ b/messageviewer/widgets/eventedit.cpp
@@ -0,0 +1,219 @@
+/*
+  Copyright (c) 2014 Montel Laurent <montel at kde.org>
+
+  This program is free software; you can redistribute it and/or modify it
+  under the terms of the GNU General Public License, version 2, as
+  published by the Free Software Foundation.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License along
+  with this program; if not, write to the Free Software Foundation, Inc.,
+  51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "eventedit.h"
+
+#include "messageviewer/globalsettings_base.h"
+
+#include <KLocalizedString>
+#include <KLineEdit>
+#include <KIcon>
+#include <KDateTimeEdit>
+
+#include <QHBoxLayout>
+#include <QEvent>
+#include <QKeyEvent>
+#include <QLabel>
+#include <QToolButton>
+
+#include <Akonadi/CollectionComboBox>
+
+
+namespace MessageViewer {
+MESSAGEVIEWER_EXPORT QAbstractItemModel *_k_eventEditStubModel = 0;
+}
+
+using namespace MessageViewer;
+
+EventEdit::EventEdit(QWidget *parent)
+    : QWidget(parent)
+{
+    QVBoxLayout *vbox = new QVBoxLayout;
+    setLayout(vbox);
+    QHBoxLayout *hbox = new QHBoxLayout;
+    hbox->setMargin(2);
+    vbox->addLayout(hbox);
+
+    QToolButton *closeBtn = new QToolButton( this );
+    closeBtn->setIcon( KIcon( QLatin1String("dialog-close") ) );
+    closeBtn->setObjectName(QLatin1String("close-button"));
+    closeBtn->setIconSize( QSize( 16, 16 ) );
+    closeBtn->setToolTip( i18n( "Close" ) );
+
+#ifndef QT_NO_ACCESSIBILITY
+    closeBtn->setAccessibleName( i18n( "Close" ) );
+    closeBtn->setAccessibleDescription( i18n("Close widget to create new Todo") );
+#endif
+
+    closeBtn->setAutoRaise( true );
+    hbox->addWidget( closeBtn );
+    connect( closeBtn, SIGNAL(clicked()), this, SLOT(slotCloseWidget()) );
+
+    QLabel *lab = new QLabel(i18n("Todo:"));
+    hbox->addWidget(lab);
+
+    mNoteEdit = new KLineEdit;
+    mNoteEdit->setClearButtonShown(true);
+    mNoteEdit->setObjectName(QLatin1String("noteedit"));
+    mNoteEdit->setFocus();
+    connect(mNoteEdit, SIGNAL(returnPressed()), SLOT(slotReturnPressed()));
+    hbox->addWidget(mNoteEdit);
+    mCollectionCombobox = new Akonadi::CollectionComboBox(_k_eventEditStubModel);
+    mCollectionCombobox->setAccessRightsFilter(Akonadi::Collection::CanCreateItem);
+    mCollectionCombobox->setMinimumWidth(250);
+    mCollectionCombobox->setMimeTypeFilter( QStringList() << KCalCore::Event::eventMimeType() );
+    mCollectionCombobox->setObjectName(QLatin1String("akonadicombobox"));
+#ifndef QT_NO_ACCESSIBILITY
+    mCollectionCombobox->setAccessibleDescription( i18n("Select collection where Todo will stored.") );
+#endif
+
+    connect(mCollectionCombobox, SIGNAL(currentIndexChanged(int)), SLOT(slotCollectionChanged(int)));
+    connect(mCollectionCombobox, SIGNAL(activated(int)), SLOT(slotCollectionChanged(int)));
+    hbox->addWidget(mCollectionCombobox);
+
+    hbox = new QHBoxLayout;
+    vbox->addLayout(hbox);
+
+    lab = new QLabel(i18n("Start:"));
+    hbox->addWidget(lab);
+    KDateTime currentDateTime = KDateTime::currentDateTime(KDateTime::LocalZone);
+    mStartDateTimeEdit = new KDateTimeEdit;
+    mStartDateTimeEdit->setObjectName(QLatin1String("startdatetimeedit"));
+    mStartDateTimeEdit->setDateTime(currentDateTime);
+
+    hbox->addWidget(mStartDateTimeEdit);
+
+    lab = new QLabel(i18n("End:"));
+    hbox->addWidget(lab);
+    mEndDateTimeEdit = new KDateTimeEdit;
+    mEndDateTimeEdit->setObjectName(QLatin1String("enddatetimeedit"));
+    mEndDateTimeEdit->setDateTime(currentDateTime.addSecs(3600));
+    hbox->addWidget(mEndDateTimeEdit);
+
+    readConfig();
+    setSizePolicy( QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Fixed ) );
+}
+
+EventEdit::~EventEdit()
+{
+
+}
+
+void EventEdit::writeConfig()
+{
+    MessageViewer::GlobalSettingsBase::self()->setLastEventSelectedFolder(mCollectionCombobox->currentCollection().id());
+}
+
+void EventEdit::readConfig()
+{
+    const qint64 id = MessageViewer::GlobalSettingsBase::self()->lastEventSelectedFolder();
+    if (id!=-1) {
+        mCollectionCombobox->setDefaultCollection(Akonadi::Collection(id));
+    }
+}
+
+Akonadi::Collection EventEdit::collection() const
+{
+    return mCollection;
+}
+
+void EventEdit::slotCollectionChanged(int /*index*/)
+{
+    setCollection(mCollectionCombobox->currentCollection());
+}
+
+void EventEdit::setCollection(const Akonadi::Collection &value)
+{
+    if (mCollection != value) {
+        mCollection = value;
+        Q_EMIT collectionChanged(mCollection);
+    }
+}
+
+KMime::Message::Ptr EventEdit::message() const
+{
+    return mMessage;
+}
+
+void EventEdit::setMessage(const KMime::Message::Ptr &value)
+{
+    if (mMessage != value) {
+        mMessage = value;
+        const KMime::Headers::Subject * const subject = mMessage ? mMessage->subject(false) : 0;
+        if (subject) {
+            mNoteEdit->setText(i18n("Reply to \"%1\"", subject->asUnicodeString()));
+            mNoteEdit->selectAll();
+            mNoteEdit->setFocus();
+        } else {
+            mNoteEdit->clear();
+        }
+        Q_EMIT messageChanged(mMessage);
+    }
+}
+
+void EventEdit::slotCloseWidget()
+{
+    writeConfig();
+    mNoteEdit->clear();
+    mMessage = KMime::Message::Ptr();
+    hide();
+}
+
+void EventEdit::slotReturnPressed()
+{
+    if (!mMessage) {
+        kDebug()<<" Message is null";
+        return;
+    }
+    const Akonadi::Collection collection = mCollectionCombobox->currentCollection();
+    if (!collection.isValid()) {
+        kDebug()<<" Collection is not valid";
+        return;
+    }
+
+    if (!mNoteEdit->text().trimmed().isEmpty()) {
+        KCalCore::Event::Ptr event( new KCalCore::Event );
+        event->setSummary(mNoteEdit->text());
+        Q_EMIT createEvent(event, collection);
+        mNoteEdit->clear();
+        hide();
+    }
+}
+
+bool EventEdit::event(QEvent* e)
+{
+    // Close the bar when pressing Escape.
+    // Not using a QShortcut for this because it could conflict with
+    // window-global actions (e.g. Emil Sedgh binds Esc to "close tab").
+    // With a shortcut override we can catch this before it gets to kactions.
+    const bool shortCutOverride = (e->type() == QEvent::ShortcutOverride);
+    if (shortCutOverride || e->type() == QEvent::KeyPress ) {
+        QKeyEvent* kev = static_cast<QKeyEvent* >(e);
+        if (kev->key() == Qt::Key_Escape) {
+            e->accept();
+            slotCloseWidget();
+            return true;
+        } else if ( kev->key() == Qt::Key_Enter ||
+                   kev->key() == Qt::Key_Return ) {
+            e->accept();
+            if ( shortCutOverride ) {
+                return true;
+            }
+        }
+    }
+    return QWidget::event(e);
+}
diff --git a/messageviewer/widgets/eventedit.h b/messageviewer/widgets/eventedit.h
new file mode 100644
index 0000000..3893aaf
--- /dev/null
+++ b/messageviewer/widgets/eventedit.h
@@ -0,0 +1,76 @@
+/*
+  Copyright (c) 2014 Montel Laurent <montel at kde.org>
+
+  This program is free software; you can redistribute it and/or modify it
+  under the terms of the GNU General Public License, version 2, as
+  published by the Free Software Foundation.
+
+  This program is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public License along
+  with this program; if not, write to the Free Software Foundation, Inc.,
+  51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+#ifndef EVENTEDIT_H
+#define EVENTEDIT_H
+
+#include <QWidget>
+#include "messageviewer_export.h"
+
+#include <Akonadi/Collection>
+#include <KMime/Message>
+#include <KCalCore/Event>
+class KLineEdit;
+class KDateTimeEdit;
+namespace Akonadi {
+class CollectionComboBox;
+}
+
+namespace MessageViewer {
+class MESSAGEVIEWER_EXPORT EventEdit : public QWidget
+{
+    Q_OBJECT
+public:
+    explicit EventEdit(QWidget *parent = 0);
+    ~EventEdit();
+
+    Akonadi::Collection collection() const;
+    void setCollection(const Akonadi::Collection &value);
+
+    KMime::Message::Ptr message() const;
+    void setMessage(const KMime::Message::Ptr &value);
+
+    void writeConfig();
+
+public Q_SLOTS:
+    void slotCloseWidget();
+
+private Q_SLOTS:
+    void slotReturnPressed();
+    void slotCollectionChanged(int);
+
+Q_SIGNALS:
+    void createEvent(const KCalCore::Event::Ptr &event, const Akonadi::Collection &collection);
+    void collectionChanged(const Akonadi::Collection &col);
+    void messageChanged(const KMime::Message::Ptr &msg);
+
+protected:
+    bool event(QEvent *e);
+
+private:
+    void readConfig();
+    Akonadi::Collection mCollection;
+    KMime::Message::Ptr mMessage;
+    KLineEdit *mNoteEdit;
+    Akonadi::CollectionComboBox *mCollectionCombobox;
+    KDateTimeEdit *mStartDateTimeEdit;
+    KDateTimeEdit *mEndDateTimeEdit;
+};
+}
+
+#endif // EVENTEDIT_H


commit 9ee94b2c58953ef72e8763fe56697cc9386d919a
Merge: 61d2ca3 f5849c2
Author: Sandro Knauß <knauss at kolabsys.com>
Date:   Mon Aug 11 13:48:59 2014 +0200

    Merge branch 'individual_mail_kolab' into kolab/integration/4.13.0



commit 61d2ca355f95619a1b95c5d2ab0981f67d72e688
Author: Sandro Knauß <knauss at kolabsys.com>
Date:   Mon Apr 21 00:19:47 2014 +0200

    Make LdapClientSearch usable for other circumstances
    
    REVIEW: 17761

diff --git a/libkdepim/addressline/addresseelineedit.cpp b/libkdepim/addressline/addresseelineedit.cpp
index 3cc65cd..e83c0b0 100644
--- a/libkdepim/addressline/addresseelineedit.cpp
+++ b/libkdepim/addressline/addresseelineedit.cpp
@@ -289,6 +289,22 @@ void AddresseeLineEdit::Private::init()
             s_static->ldapTimer = new QTimer;
             s_static->ldapSearch = new KLDAP::LdapClientSearch;
 
+            /* The reasoning behind this filter is:
+             * If it's a person, or a distlist, show it, even if it doesn't have an email address.
+             * If it's not a person, or a distlist, only show it if it has an email attribute.
+             * This allows both resource accounts with an email address which are not a person and
+             * person entries without an email address to show up, while still not showing things
+             * like structural entries in the ldap tree.
+             */
+
+            #if 0
+                s_static->ldapSearch->setFilter(QString::fromLatin1("&(|(objectclass=person)(objectclass=groupOfNames)(mail=*))"
+                                                          "(|(cn=%1*)(mail=%1*)(mail=*@%1*)(givenName=%1*)(sn=%1*))"));
+            #endif
+            //Fix bug 323272 "Exchange doesn't like any queries beginning with *."
+            s_static->ldapSearch->setFilter(QString::fromLatin1( "&(|(objectclass=person)(objectclass=groupOfNames)(mail=*))"
+                                "(|(cn=%1*)(mail=%1*)(givenName=%1*)(sn=%1*))" ));
+
         }
 
         s_static->balooCompletionSource = q->addCompletionSource( i18nc( "@title:group", "Contacts found in your data"), -1 );
diff --git a/libkdepim/ldap/ldapclientsearch.cpp b/libkdepim/ldap/ldapclientsearch.cpp
index ed5c23f..deb71e0 100644
--- a/libkdepim/ldap/ldapclientsearch.cpp
+++ b/libkdepim/ldap/ldapclientsearch.cpp
@@ -30,7 +30,6 @@
 #include "ldapsession.h"
 #include "ldapqueryjob.h"
 
-#include <kldap/ldapobject.h>
 #include <kldap/ldapserver.h>
 #include <kldap/ldapurl.h>
 #include <kldap/ldif.h>
@@ -65,11 +64,6 @@ public:
         delete mClientSearchConfig;
     }
 
-    struct ResultObject {
-        const LdapClient *client;
-        KLDAP::LdapObject object;
-    };
-
     void readWeighForClient( LdapClient *client, const KConfigGroup &config, int clientNumber );
     void readConfig();
     void finish();
@@ -83,11 +77,13 @@ public:
 
     LdapClientSearch *q;
     QList<LdapClient*> mClients;
+    QStringList mAttributes;
     QString mSearchText;
+    QString mFilter;
     QTimer mDataTimer;
     int mActiveClients;
     bool mNoLDAPLookup;
-    QList<ResultObject> mResults;
+    QList<LdapResultObject> mResults;
     QString mConfigFile;
     LdapClientSearchConfig *mClientSearchConfig;
 };
@@ -100,9 +96,20 @@ LdapClientSearch::LdapClientSearch( QObject *parent )
         return;
     }
 
+
+    d->mAttributes << QLatin1String("cn")
+                   << QLatin1String("mail")
+                   << QLatin1String("givenname")
+                   << QLatin1String("sn");
+
+    // Set the filter, to make sure old usage (before 4.14) of this object still works.
+    d->mFilter = QString::fromLatin1("&(|(objectclass=person)(objectclass=groupOfNames)(mail=*))"
+                                "(|(cn=%1*)(mail=%1*)(givenName=%1*)(sn=%1*))");
+
     d->readConfig();
     connect( KDirWatch::self(), SIGNAL(dirty(QString)), this,
              SLOT(slotFileChanged(QString)) );
+
 }
 
 LdapClientSearch::~LdapClientSearch()
@@ -132,6 +139,31 @@ QList<LdapClient*> LdapClientSearch::clients() const
     return d->mClients;
 }
 
+QString LdapClientSearch::filter() const
+{
+    return d->mFilter;
+}
+
+void LdapClientSearch::setFilter(const QString &filter)
+{
+    d->mFilter = filter;
+}
+
+QStringList LdapClientSearch::attributes() const
+{
+    return d->mAttributes;
+}
+
+void LdapClientSearch::setAttributes(const QStringList &attrs)
+{
+
+    if ( attrs != d->mAttributes ) {
+        d->mAttributes = attrs;
+        d->readConfig();
+    }
+}
+
+
 void LdapClientSearch::Private::readConfig()
 {
     q->cancelSearch();
@@ -155,9 +187,7 @@ void LdapClientSearch::Private::readConfig()
 
             readWeighForClient( ldapClient, config, j );
 
-            QStringList attrs;
-            attrs << QLatin1String("cn") << QLatin1String("mail") << QLatin1String("givenname") << QLatin1String("sn");
-            ldapClient->setAttributes( attrs );
+            ldapClient->setAttributes( mAttributes );
 
             q->connect( ldapClient, SIGNAL(result(KLDAP::LdapClient,KLDAP::LdapObject)),
                         q, SLOT(slotLDAPResult(KLDAP::LdapClient,KLDAP::LdapObject)) );
@@ -203,20 +233,7 @@ void LdapClientSearch::startSearch( const QString &txt )
         d->mSearchText = txt;
     }
 
-    /* The reasoning behind this filter is:
-   * If it's a person, or a distlist, show it, even if it doesn't have an email address.
-   * If it's not a person, or a distlist, only show it if it has an email attribute.
-   * This allows both resource accounts with an email address which are not a person and
-   * person entries without an email address to show up, while still not showing things
-   * like structural entries in the ldap tree. */
-
-#if 0
-    const QString filter = QString::fromLatin1( "&(|(objectclass=person)(objectclass=groupOfNames)(mail=*))"
-                                                "(|(cn=%1*)(mail=%1*)(mail=*@%1*)(givenName=%1*)(sn=%1*))" ).arg( d->mSearchText );
-#endif
-    //Fix bug 323272 "Exchange doesn't like any queries beginning with *."
-    const QString filter = QString::fromLatin1( "&(|(objectclass=person)(objectclass=groupOfNames)(mail=*))"
-                                                "(|(cn=%1*)(mail=%1*)(givenName=%1*)(sn=%1*))" ).arg( d->mSearchText );
+    const QString filter = d->mFilter.arg( d->mSearchText );
 
     QList<LdapClient*>::Iterator it;
     QList<LdapClient*>::Iterator end(d->mClients.end());
@@ -242,7 +259,7 @@ void LdapClientSearch::cancelSearch()
 void LdapClientSearch::Private::slotLDAPResult( const LdapClient &client,
                                                 const KLDAP::LdapObject &obj )
 {
-    ResultObject result;
+    LdapResultObject result;
     result.client = &client;
     result.object = obj;
 
@@ -271,6 +288,9 @@ void LdapClientSearch::Private::slotDataTimer()
 {
     QStringList lst;
     LdapResult::List reslist;
+
+    emit q->searchData(mResults);
+
     makeSearchData( lst, reslist );
     if ( !lst.isEmpty() ) {
         emit q->searchData( lst );
@@ -291,8 +311,8 @@ void LdapClientSearch::Private::finish()
 void LdapClientSearch::Private::makeSearchData( QStringList &ret, LdapResult::List &resList )
 {
 
-    QList< ResultObject >::ConstIterator it1;
-    QList< ResultObject >::ConstIterator end1(mResults.constEnd());
+    QList< LdapResultObject >::ConstIterator it1;
+    QList< LdapResultObject >::ConstIterator end1(mResults.constEnd());
     for ( it1 = mResults.constBegin(); it1 != end1; ++it1 ) {
         QString name, mail, givenname, sn;
         QStringList mails;
diff --git a/libkdepim/ldap/ldapclientsearch.h b/libkdepim/ldap/ldapclientsearch.h
index 19c203d..26adf3a 100644
--- a/libkdepim/ldap/ldapclientsearch.h
+++ b/libkdepim/ldap/ldapclientsearch.h
@@ -30,9 +30,19 @@
 
 
 namespace KLDAP {
-class LdapObject;
 class LdapClient;
 
+
+/**
+ * Describes the result returned by an LdapClientSearch query.
+ *
+ * @since 4.14
+ */
+struct LdapResultObject {
+    const LdapClient *client;
+    KLDAP::LdapObject object;
+};
+
 /**
  * Describes the result returned by an LdapClientSearch query.
  *
@@ -101,6 +111,35 @@ public:
      */
     QList<LdapClient*> clients() const;
 
+
+    /**
+     * Returns the filter for the Query
+     *
+     * @since 4.14
+     */
+    QString filter() const;
+
+    /**
+     * Sets the filter for the Query
+     *
+     * @since 4.14
+     */
+    void setFilter(const QString &);
+
+    /**
+     * Returns the attributes, that are queried the LDAP Server.
+     *
+     * @since 4.14
+     */
+    QStringList attributes() const;
+
+     /**
+     * Sets the attributes, that are queried the LDAP Server.
+     *
+     * @since 4.14
+     */
+    void setAttributes(const QStringList&);
+
 Q_SIGNALS:
     /**
      * This signal is emitted whenever new contacts have been found
@@ -119,6 +158,14 @@ Q_SIGNALS:
     void searchData( const KLDAP::LdapResult::List &results );
 
     /**
+     * This signal is emitted whenever new contacts have been found
+     * during the lookup.
+     *
+     * @param results The list of found contacts.
+     */
+    void searchData( const QList<KLDAP::LdapResultObject> &results );
+
+    /**
      * This signal is emitted whenever the lookup is complete or the
      * user has canceled the query.
      */


commit f5849c29a314deeff7b0a4c469bd2cf2d82e5818
Author: Sandro Knauß <knauss at kolabsys.com>
Date:   Sun Jul 27 11:04:15 2014 +0200

    individual mail dialog for incidenceeditor.
    
    REVIEW: 119462

diff --git a/incidenceeditor-ng/CMakeLists.txt b/incidenceeditor-ng/CMakeLists.txt
index 9097780..219b242 100644
--- a/incidenceeditor-ng/CMakeLists.txt
+++ b/incidenceeditor-ng/CMakeLists.txt
@@ -61,6 +61,11 @@ set(incidenceeditors_ng_shared_LIB_SRCS
   categoryeditdialog.cpp
   categoryselectdialog.cpp
   categorydialog.cpp
+
+  # Individual mail
+  individualmailcomponentfactory.cpp
+  individualmaildialog.cpp
+  opencomposerjob.cpp
 )
 
 kde4_add_kcfg_files(incidenceeditors_ng_shared_LIB_SRCS globalsettings_base.kcfgc)
@@ -90,11 +95,13 @@ kde4_add_library(incidenceeditorsng ${LIBRARY_TYPE} ${incidenceeditors_ng_deskto
 
 target_link_libraries(incidenceeditorsng
   akonadi-calendar
+  akonadi-kmime
   ${QT_QTCORE_LIBRARY}
   ${QT_QTGUI_LIBRARY}
   ${KDE4_KDEUI_LIBS}
   ${KDEPIMLIBS_KCALCORE_LIBS}
   ${KDEPIMLIBS_KCALUTILS_LIBS}
+  ${KDEPIMLIBS_MAILTRANSPORT_LIBS}
   kdepim
   kdepimdbusinterfaces # For UriHandler
   calendarsupport      # For KCalPrefs
@@ -133,6 +140,7 @@ install(TARGETS incidenceeditorsng ${INSTALL_TARGETS_DEFAULT_ARGS})
 
   target_link_libraries(incidenceeditorsngmobile
     akonadi-calendar
+    akonadi-kmime
     ${QT_QTCORE_LIBRARY}
     ${QT_QTGUI_LIBRARY}
     ${KDE4_KDEUI_LIBS}
@@ -142,6 +150,7 @@ install(TARGETS incidenceeditorsng ${INSTALL_TARGETS_DEFAULT_ARGS})
     kdgantt2
     ${KDEPIMLIBS_KCALUTILS_LIBS}
     ${KDEPIMLIBS_KCALCORE_LIBS}
+    ${KDEPIMLIBS_MAILTRANSPORT_LIBS}
   )
 
   set_target_properties(incidenceeditorsngmobile PROPERTIES
diff --git a/incidenceeditor-ng/Messages.sh b/incidenceeditor-ng/Messages.sh
index b20d68d..b2fad21 100644
--- a/incidenceeditor-ng/Messages.sh
+++ b/incidenceeditor-ng/Messages.sh
@@ -1,4 +1,4 @@
 #! /bin/sh
 $EXTRACTRC `find . -name \*.ui -o -name \*.kcfg`  >> rc.cpp
-$XGETTEXT `find . -name "*.cpp"` -o $podir/libincidenceeditors.pot
+$XGETTEXT `find . -name "*.cpp" -name "*.h"`  -o $podir/libincidenceeditors.pot
 rm -f rc.cpp
diff --git a/incidenceeditor-ng/editoritemmanager.cpp b/incidenceeditor-ng/editoritemmanager.cpp
index 7cc3614..0d57318 100644
--- a/incidenceeditor-ng/editoritemmanager.cpp
+++ b/incidenceeditor-ng/editoritemmanager.cpp
@@ -19,6 +19,7 @@
 */
 
 #include "editoritemmanager.h"
+#include "individualmailcomponentfactory.h"
 
 #include <calendarsupport/utils.h>
 #include <calendarsupport/kcalprefs.h>
@@ -80,7 +81,7 @@ ItemEditorPrivate::ItemEditorPrivate( Akonadi::IncidenceChanger *changer, Editor
   mFetchScope.fetchFullPayload();
   mFetchScope.setAncestorRetrieval( Akonadi::ItemFetchScope::Parent );
 
-  mChanger = changer ? changer : new Akonadi::IncidenceChanger( qq );
+  mChanger = changer ? changer : new Akonadi::IncidenceChanger( new IndividualMailComponentFactory(qq), qq );
 
   qq->connect( mChanger,
               SIGNAL(modifyFinished(int,Akonadi::Item,Akonadi::IncidenceChanger::ResultCode,QString)),
diff --git a/incidenceeditor-ng/individualmailcomponentfactory.cpp b/incidenceeditor-ng/individualmailcomponentfactory.cpp
new file mode 100644
index 0000000..06c86e6
--- /dev/null
+++ b/incidenceeditor-ng/individualmailcomponentfactory.cpp
@@ -0,0 +1,254 @@
+/*
+  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 "individualmailcomponentfactory.h"
+#include "individualmaildialog.h"
+
+#include <kpimutils/email.h>
+
+#include <KMessageBox>
+
+#include <QDBusConnection>
+#include <QDBusConnectionInterface>
+#include <QDBusInterface>
+#include <QDBusReply>
+
+using namespace IncidenceEditorNG;
+
+// IndividualMessageQueueJob
+
+IndividualMessageQueueJob::IndividualMessageQueueJob(const KPIMIdentities::Identity &identity,
+                                                     const KCalCore::Attendee::List &update, const KCalCore::Attendee::List &edit,
+                                                     QObject *parent)
+    : MailTransport::MessageQueueJob(parent)
+    , mUpdate(update)
+    , mEdit(edit)
+    , mIdentity(identity)
+    , mQueueJob(0)
+    , mComposerJob(0)
+{
+}
+
+void IndividualMessageQueueJob::start()
+{
+    QSet<QString> attendeesTo(QSet<QString>::fromList(addressAttribute().to()));
+    QSet<QString> attendeesCc(QSet<QString>::fromList(addressAttribute().cc()));
+
+    QStringList attendeesAutoTo,  attendeesAutoCc;
+    foreach (const KCalCore::Attendee::Ptr & attendee, mUpdate) {
+        if (attendeesTo.contains(attendee->email())) {
+            attendeesAutoTo.append(attendee->fullName());
+        }
+        if (attendeesCc.contains(attendee->email())) {
+            attendeesAutoCc.append(attendee->fullName());
+        }
+    }
+    if (!attendeesAutoTo.isEmpty() || !attendeesAutoCc.isEmpty() || !addressAttribute().bcc().isEmpty()) {
+        startQueueJob(attendeesAutoTo, attendeesAutoCc);
+    }
+
+    QStringList attendeesComposerTo,  attendeesComposerCc;
+    foreach (const KCalCore::Attendee::Ptr & attendee, mEdit) {
+        if (attendeesTo.contains(attendee->email())) {
+            attendeesComposerTo.append(attendee->fullName());
+        }
+        if (attendeesCc.contains(attendee->email())) {
+            attendeesComposerCc.append(attendee->fullName());
+        }
+    }
+    if (!attendeesComposerTo.isEmpty() || !attendeesComposerCc.isEmpty()) {
+        startComposerJob(attendeesComposerTo, attendeesComposerCc);
+    }
+
+    // No subjob has been started
+    if (!mQueueJob && !mComposerJob) {
+        emitResult();
+    }
+}
+
+void IndividualMessageQueueJob::startQueueJob(const QStringList &to, const QStringList &cc)
+{
+    KMime::Message::Ptr msg(message());
+    msg->to()->fromUnicodeString(to.join(QLatin1String(", ")), "utf-8");
+    msg->cc()->fromUnicodeString(cc.join(QLatin1String(", ")), "utf-8");
+    msg->assemble();
+
+    mQueueJob->setMessage(msg);
+    mQueueJob->transportAttribute().setTransportId(transportAttribute().transportId());
+    mQueueJob->sentBehaviourAttribute().setSentBehaviour(sentBehaviourAttribute().sentBehaviour());
+    mQueueJob->addressAttribute().setFrom(addressAttribute().from());
+    mQueueJob->addressAttribute().setTo(to);
+    mQueueJob->addressAttribute().setCc(cc);
+    mQueueJob->addressAttribute().setBcc(addressAttribute().bcc());
+
+    mQueueJob = new MailTransport::MessageQueueJob(this);
+    connect(mQueueJob, SIGNAL(finished(KJob*)), SLOT(handleJobFinished(KJob*)));
+    mQueueJob->start();
+}
+
+void IndividualMessageQueueJob::startComposerJob(const QStringList &to, const QStringList &cc)
+{
+    mComposerJob = new OpenComposerJob(this, to.join(QLatin1String(", ")), cc.join(QLatin1String(", ")), QString(), message(), mIdentity);
+    connect(mComposerJob, SIGNAL(finished(KJob*)), SLOT(handleJobFinished(KJob*)));
+    mComposerJob->start();
+}
+
+void IndividualMessageQueueJob::handleJobFinished(KJob *job)
+{
+    if (job->error()) {
+        if (job == mQueueJob && mComposerJob) {
+            mComposerJob->kill();
+            mComposerJob = 0;
+        } else if (mComposerJob) {
+            mQueueJob->kill();
+            mQueueJob = 0;
+        }
+        setError(job->error());
+        setErrorText(job->errorString());
+        emitResult();
+        return;
+    }
+    if (job == mQueueJob) {
+        if (!mComposerJob) {
+            emitResult();
+        }
+        mQueueJob = 0;
+    } else {
+        if (!mQueueJob) {
+            emitResult();
+        }
+        mComposerJob = 0;
+    }
+
+}
+
+// IndividualMailAskDelegator
+
+IndividualMailITIPHandlerDialogDelegate::IndividualMailITIPHandlerDialogDelegate(const KCalCore::Incidence::Ptr &incidence,
+                                                                                 KCalCore::iTIPMethod method, QWidget *parent)
+    : Akonadi::ITIPHandlerDialogDelegate(incidence, method, parent)
+{
+}
+
+void IndividualMailITIPHandlerDialogDelegate::openDialog(const QString &question, const KCalCore::Attendee::List &attendees,
+        Action action,
+        const KGuiItem &buttonYes, const KGuiItem &buttonNo)
+{
+    switch (action) {
+    case ActionSendMessage:
+        emit setUpdate(mIncidence, attendees);
+        emit dialogClosed(KMessageBox::Yes, mMethod, mIncidence);
+        break;
+    case ActionDontSendMessage:
+        emit dialogClosed(KMessageBox::No, mMethod, mIncidence);
+        break;
+    default:
+        mDialog = new IndividualMailDialog(question, attendees, buttonYes, buttonNo, mParent);
+        connect(mDialog, SIGNAL(finished(int)), SLOT(onDialogClosed(int)));
+        mDialog->show();
+        break;
+    }
+}
+
+void IndividualMailITIPHandlerDialogDelegate::openDialogIncidenceCreated(Recipient recipient,
+        const QString &question,
+        Action action,
+        const KGuiItem &buttonYes, const KGuiItem &buttonNo)
+{
+    if (recipient == Attendees) {
+        openDialog(question, mIncidence->attendees(), action, buttonYes, buttonNo);
+    } else {
+        KCalCore::Attendee::Ptr organizer(new KCalCore::Attendee(mIncidence->organizer()->name(), mIncidence->organizer()->email()));
+        openDialog(question, KCalCore::Attendee::List() << organizer, action, buttonYes, buttonNo);
+    }
+}
+
+void IndividualMailITIPHandlerDialogDelegate::openDialogIncidenceModified(bool attendeeStatusChanged,
+                                                                          Recipient recipient,
+                                                                          const QString &question,
+                                                                          Action action,
+                                                                          const KGuiItem &buttonYes, const KGuiItem &buttonNo)
+{
+    Q_UNUSED(attendeeStatusChanged);
+    if (recipient == Attendees) {
+        openDialog(question, mIncidence->attendees(), action, buttonYes, buttonNo);
+    } else {
+        KCalCore::Attendee::Ptr organizer(new KCalCore::Attendee(mIncidence->organizer()->name(), mIncidence->organizer()->email()));
+        openDialog(question, KCalCore::Attendee::List() << organizer, action, buttonYes, buttonNo);
+    }
+}
+
+void IndividualMailITIPHandlerDialogDelegate::openDialogIncidenceDeleted(Recipient recipient,
+        const QString &question,
+        Action action,
+        const KGuiItem &buttonYes, const KGuiItem &buttonNo)
+{
+    if (recipient == Attendees) {
+        openDialog(question, mIncidence->attendees(), action, buttonYes, buttonNo);
+    } else {
+        KCalCore::Attendee::Ptr organizer(new KCalCore::Attendee(mIncidence->organizer()->name(), mIncidence->organizer()->email()));
+        openDialog(question, KCalCore::Attendee::List() << organizer, action, buttonYes, buttonNo);
+    }
+}
+
+void IndividualMailITIPHandlerDialogDelegate::onDialogClosed(int result)
+{
+    if (result == KDialog::Yes) {
+        emit setEdit(mIncidence, mDialog->editAttendees());
+        emit setUpdate(mIncidence, mDialog->updateAttendees());
+        emit dialogClosed(KMessageBox::Yes, mMethod, mIncidence);
+    } else {
+        emit dialogClosed(KMessageBox::No, mMethod, mIncidence);
+    }
+}
+
+// IndividualMailJobFactory
+IndividualMailComponentFactory::IndividualMailComponentFactory(QObject *parent)
+    : Akonadi::ITIPHandlerComponentFactory(parent)
+{
+
+}
+
+MailTransport::MessageQueueJob *IndividualMailComponentFactory::createMessageQueueJob(const KCalCore::IncidenceBase::Ptr &incidence,
+        const KPIMIdentities::Identity &identity, QObject *parent)
+{
+    return new IndividualMessageQueueJob(identity, mUpdate.take(incidence->uid()), mEdit.take(incidence->uid()), parent);
+}
+
+Akonadi::ITIPHandlerDialogDelegate *IndividualMailComponentFactory::createITIPHanderDialogDelegate(const KCalCore::Incidence::Ptr &incidence,
+                                                                                             KCalCore::iTIPMethod method, QWidget *parent)
+{
+    IndividualMailITIPHandlerDialogDelegate *askDelegator =  new IndividualMailITIPHandlerDialogDelegate(incidence, method, parent);
+    connect(askDelegator, SIGNAL(setEdit(KCalCore::Incidence::Ptr,KCalCore::Attendee::List)),
+            SLOT(onSetEdit(KCalCore::Incidence::Ptr,KCalCore::Attendee::List)));
+    connect(askDelegator, SIGNAL(setUpdate(KCalCore::Incidence::Ptr,KCalCore::Attendee::List)),
+            SLOT(onSetUpdate(KCalCore::Incidence::Ptr,KCalCore::Attendee::List)));
+
+    return askDelegator;
+}
+
+void IndividualMailComponentFactory::onSetEdit(const KCalCore::Incidence::Ptr &incidence, const KCalCore::Attendee::List &edit)
+{
+    mEdit[incidence->uid()] = edit;
+}
+
+void IndividualMailComponentFactory::onSetUpdate(const KCalCore::Incidence::Ptr &incidence, const KCalCore::Attendee::List &update)
+{
+    mUpdate[incidence->uid()] = update;
+}
diff --git a/incidenceeditor-ng/individualmailcomponentfactory.h b/incidenceeditor-ng/individualmailcomponentfactory.h
new file mode 100644
index 0000000..9dc3657
--- /dev/null
+++ b/incidenceeditor-ng/individualmailcomponentfactory.h
@@ -0,0 +1,117 @@
+/*
+  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_INDUVIDUALMAILJOBFACTORY_H
+#define INCIDENCEEDITOR_INDUVIDUALMAILJOBFACTORY_H
+
+#include "incidenceeditors-ng_export.h"
+
+#include "opencomposerjob.h"
+
+#include <mailtransport/messagequeuejob.h>
+#include <Akonadi/Calendar/IncidenceChanger>
+#include <KPIMIdentities/Identity>
+
+namespace IncidenceEditorNG {
+
+class IndividualMailDialog;
+
+class IndividualMessageQueueJob : public MailTransport::MessageQueueJob
+{
+    Q_OBJECT
+public:
+    explicit IndividualMessageQueueJob(const KPIMIdentities::Identity &identity, const KCalCore::Attendee::List &update, const KCalCore::Attendee::List &edit, QObject *parent);
+
+    virtual void start();
+private slots:
+    void startQueueJob(const QStringList &to, const QStringList &cc);
+    void startComposerJob(const QStringList &to, const QStringList &cc);
+    void handleJobFinished(KJob *job);
+
+private:
+    KCalCore::Attendee::List mUpdate;
+    KCalCore::Attendee::List mEdit;
+    KPIMIdentities::Identity mIdentity;
+    MailTransport::MessageQueueJob *mQueueJob;
+    OpenComposerJob *mComposerJob;
+};
+
+class IndividualMailITIPHandlerDialogDelegate : public Akonadi::ITIPHandlerDialogDelegate
+{
+    Q_OBJECT
+public:
+
+    explicit IndividualMailITIPHandlerDialogDelegate(const KCalCore::Incidence::Ptr &incidence, KCalCore::iTIPMethod method, QWidget *parent);
+
+    virtual void openDialogIncidenceCreated(Recipient recipient,
+                                            const QString &question,
+                                            Action action = ActionAsk,
+                                            const KGuiItem &buttonYes = KGuiItem(i18nc("@action:button dialog positive answer", "Send Email")),
+                                            const KGuiItem &buttonNo = KGuiItem(i18nc("@action:button dialog negative answer", "Do Not Send")));
+
+    virtual void openDialogIncidenceModified(bool attendeeStatusChanged,
+                                             Recipient recipient,
+                                             const QString &question,
+                                             Action action = ActionAsk,
+                                             const KGuiItem &buttonYes = KGuiItem(i18nc("@action:button dialog positive answer", "Send Email")),
+                                             const KGuiItem &buttonNo = KGuiItem(i18nc("@action:button dialog negative answer", "Do Not Send")));
+
+    virtual void openDialogIncidenceDeleted(Recipient recipient,
+                                            const QString &question,
+                                            Action action = ActionAsk,
+                                            const KGuiItem &buttonYes = KGuiItem(i18nc("@action:button dialog positive answer", "Send Email")),
+                                            const KGuiItem &buttonNo = KGuiItem(i18nc("@action:button dialog negative answer", "Do Not Send")));
+
+signals:
+    void setEdit(const KCalCore::Incidence::Ptr &incidence, const KCalCore::Attendee::List &edit);
+    void setUpdate(const KCalCore::Incidence::Ptr &incidence, const KCalCore::Attendee::List &update);
+
+protected:
+    void openDialog(const QString &question, const KCalCore::Attendee::List &attendees,
+                    Action action,
+                    const KGuiItem &buttonYes, const KGuiItem &buttonNo);
+
+private slots:
+    void onDialogClosed(int result);
+private:
+    IndividualMailDialog *mDialog;
+};
+
+class INCIDENCEEDITORS_NG_EXPORT IndividualMailComponentFactory : public Akonadi::ITIPHandlerComponentFactory
+{
+    Q_OBJECT
+public:
+    explicit IndividualMailComponentFactory(QObject *parent = 0);
+    virtual MailTransport::MessageQueueJob *createMessageQueueJob(const KCalCore::IncidenceBase::Ptr &incidence,
+            const KPIMIdentities::Identity &identity, QObject *parent);
+
+    virtual Akonadi::ITIPHandlerDialogDelegate *createITIPHanderDialogDelegate(const KCalCore::Incidence::Ptr &incidence,
+            KCalCore::iTIPMethod method, QWidget *parent);
+
+public slots:
+    void onSetEdit(const KCalCore::Incidence::Ptr &incidence, const KCalCore::Attendee::List &edit);
+    void onSetUpdate(const KCalCore::Incidence::Ptr &incidence, const KCalCore::Attendee::List &update);
+
+private:
+    QHash<QString, KCalCore::Attendee::List> mEdit;
+    QHash<QString, KCalCore::Attendee::List> mUpdate;
+};
+
+}
+#endif
diff --git a/incidenceeditor-ng/individualmaildialog.cpp b/incidenceeditor-ng/individualmaildialog.cpp
new file mode 100644
index 0000000..322d95c
--- /dev/null
+++ b/incidenceeditor-ng/individualmaildialog.cpp
@@ -0,0 +1,93 @@
+/*
+  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 "individualmaildialog.h"
+
+#include <KLocalizedString>
+#include <KDebug>
+
+#include <QGridLayout>
+#include <QComboBox>
+#include <QLabel>
+
+using namespace IncidenceEditorNG;
+
+IndividualMailDialog::IndividualMailDialog(const QString &question, const KCalCore::Attendee::List  &attendees,
+                                           const KGuiItem &buttonYes, const KGuiItem &buttonNo, QWidget *parent)
+    : KDialog(parent)
+{
+    setCaption(i18nc("@title:window", "Group Scheduling Email"));
+    setButtons(KDialog::Yes | KDialog::No | KDialog::Details);
+    setButtonText(KDialog::Details, i18nc("@action:button show list of attendees", "Individual mailsettings"));
+    setButtonGuiItem(KDialog::Yes, buttonYes);
+    setButtonGuiItem(KDialog::No, buttonNo);
+
+    QWidget *widget = new QWidget();
+    QGridLayout *layout = new QGridLayout(widget);
+    int row = 0;
+    foreach (const KCalCore::Attendee::Ptr & attendee, attendees) {
+        QComboBox *options = new QComboBox();
+        options->addItem(i18nc("@item:inlistbox ITIP Messages for one attendee", "Send update"), QVariant(Update));
+        options->addItem(i18nc("@item:inlistbox ITIP Messages for one attendee", "Send no update"), QVariant(NoUpdate));
+        options->addItem(i18nc("@item:inlistbox ITIP Messages for one attendee", "Edit mail"), QVariant(Edit));
+        mAttendeeDecision[attendee] = options;
+
+        layout->addWidget(new QLabel(attendee->fullName()), row, 0);
+        layout->addWidget(options, row, 1);
+        ++row;
+    }
+    widget->sizePolicy().setHorizontalStretch(1);
+    widget->sizePolicy().setVerticalStretch(1);
+
+    QWidget *mW = new QLabel(question);
+
+    setMainWidget(mW);
+    setDetailsWidget(widget);
+}
+
+IndividualMailDialog::~IndividualMailDialog()
+{
+
+}
+
+KCalCore::Attendee::List IndividualMailDialog::editAttendees() const
+{
+    KCalCore::Attendee::List edit;
+    QList<KCalCore::Attendee::Ptr> attendees = mAttendeeDecision.keys();
+    foreach (const KCalCore::Attendee::Ptr & attendee, attendees) {
+        int index = mAttendeeDecision[attendee]->currentIndex();
+        if (mAttendeeDecision[attendee]->itemData(index, Qt::UserRole) == Edit) {
+            edit.append(attendee);
+        }
+    }
+    return edit;
+}
+
+KCalCore::Attendee::List IndividualMailDialog::updateAttendees() const
+{
+    KCalCore::Attendee::List update;
+    QList<KCalCore::Attendee::Ptr> attendees = mAttendeeDecision.keys();
+    foreach (const KCalCore::Attendee::Ptr & attendee, attendees) {
+        int index = mAttendeeDecision[attendee]->currentIndex();
+        if (mAttendeeDecision[attendee]->itemData(index, Qt::UserRole) == Update) {
+            update.append(attendee);
+        }
+    }
+    return update;
+}
diff --git a/incidenceeditor-ng/individualmaildialog.h b/incidenceeditor-ng/individualmaildialog.h
new file mode 100644
index 0000000..3c3331b
--- /dev/null
+++ b/incidenceeditor-ng/individualmaildialog.h
@@ -0,0 +1,57 @@
+/*
+  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_INDIVIDUALMAILDIALOG_H
+#define INCIDENCEEDITOR_INDIVIDUALMAILDIALOG_H
+
+#include <kcalcore/attendee.h>
+#include <KDialog>
+
+#include <QComboBox>
+
+class TestIndividualMailDialog;
+
+namespace IncidenceEditorNG {
+
+// Shows a dialog with a question and the option to select which attendee should get the mail or to open a composer for him.
+// Used to get individual mails for attendees of an event.
+class IndividualMailDialog : public KDialog
+{
+    Q_OBJECT
+    friend TestIndividualMailDialog;
+public:
+    enum Decisions {
+        Update,         /**< send automatic mail to attendee */
+        NoUpdate,       /**< do not send mail to attendee */
+        Edit            /**< open composer for attendee */
+    };
+    explicit IndividualMailDialog(const QString &question, const KCalCore::Attendee::List &attendees,
+                                  const KGuiItem &buttonYes, const KGuiItem &buttonNo, QWidget *parent = 0);
+    virtual ~IndividualMailDialog();
+
+    KCalCore::Attendee::List editAttendees() const;
+    KCalCore::Attendee::List updateAttendees() const;
+
+private:
+    QHash<KCalCore::Attendee::Ptr, QComboBox *> mAttendeeDecision;
+};
+
+}
+
+#endif
diff --git a/incidenceeditor-ng/opencomposerjob.cpp b/incidenceeditor-ng/opencomposerjob.cpp
new file mode 100644
index 0000000..052449a
--- /dev/null
+++ b/incidenceeditor-ng/opencomposerjob.cpp
@@ -0,0 +1,150 @@
+/*
+ * 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 "opencomposerjob.h"
+
+#include <QtCore/QObject>
+#include <QtDBus/QtDBus>
+#include <QtCore/QProcess>
+
+#include <klocalizedstring.h>
+#include <kdbusservicestarter.h>
+
+using namespace IncidenceEditorNG;
+
+OpenComposerJob::OpenComposerJob(QObject *parent,
+                                 const QString &to, const QString &cc, const QString &bcc,
+                                 const KMime::Message::Ptr &message, const KPIMIdentities::Identity &identity)
+    : KJob(parent)
+    , mTo(to)
+    , mCc(cc)
+    , mBcc(bcc)
+    , mMessage(message)
+    , mIdentity(identity)
+    , mSuccess(false)
+{
+    connect(QDBusConnection::sessionBus().interface(), SIGNAL(serviceOwnerChanged(QString,QString,QString)),
+            SLOT(slotServiceOwnerChanged(QString,QString,QString)));
+}
+
+OpenComposerJob::~OpenComposerJob()
+{
+
+}
+
+void OpenComposerJob::start()
+{
+    mSuccess = false;
+    if (QDBusConnection::sessionBus().interface()->isServiceRegistered(QLatin1String("org.kde.kmail"))) {
+        processMail();
+    }
+    //Check if Kontact is already running and if not ...
+    int result = KDBusServiceStarter::self()->findServiceFor(QLatin1String("DBUS/Mailer"), QString(),
+                 &mError, &mDBusService);
+    if (result != 0) {
+        // ... start Kontact
+        result = KDBusServiceStarter::self()->startServiceFor(QLatin1String("DBUS/Mailer"), QString(),
+                 &mError, &mDBusService);
+        if (result != 0) {
+            const bool ok = QProcess::startDetached(QLatin1String("kontact"));
+            if (!ok) {
+                setError(KJob::UserDefinedError);
+                setErrorText(i18nc("errormessage: can't get connection via dbus", "Don't get kmail started"));
+                emitResult();
+                return;
+            }
+        } else {
+            setError(KJob::UserDefinedError);
+            setErrorText(i18nc("errormessage: can't get connection via dbus", "Don't get kmail started"));
+            emitResult();
+            return;
+        }
+    }
+
+    QTimer::singleShot(10000, this, SLOT(timeout()));
+}
+
+void OpenComposerJob::timeout()
+{
+    if (!mSuccess) {
+        setError(KJob::UserDefinedError);
+        setErrorText(i18nc("errormessage: can't get connection via dbus", "Don't get kmail started"));
+        emitResult();
+    }
+}
+
+void OpenComposerJob::slotServiceOwnerChanged(const QString &name, const QString &oldOwner, const QString &newOwner)
+{
+    Q_UNUSED(oldOwner);
+    if (name == QLatin1String("org.kde.kmail") && !newOwner.isEmpty()) {
+        processMail();
+    }
+}
+
+void OpenComposerJob::processMail()
+{
+    Q_ASSERT(mMessage);
+    mSuccess = true;
+
+    bool hidden = false;
+    unsigned int identity = mIdentity.uoid();
+
+    QString subject = mMessage->subject()->asUnicodeString();
+    QString body = QString::fromUtf8(mMessage->contents()[0]->body());
+
+    QList<QVariant> messages;
+
+    if (mMessage->contents().count() == 1) {
+        const QString messageFile;
+        const QStringList attachmentPaths;
+        const QStringList customHeaders;
+        const QString replyTo;
+        const QString inReplyTo;
+
+        messages << mTo << mCc << mBcc << subject << body << hidden
+                 << messageFile << attachmentPaths << customHeaders << replyTo << inReplyTo;
+    } else {
+        KMime::Content *attachment(mMessage->contents().at(1));
+        QString attachName = attachment->contentType()->name();
+        QByteArray attachCte = attachment->contentTransferEncoding()->as7BitString(false);
+        QByteArray attachType = attachment->contentType()->mediaType();
+        QByteArray attachSubType = attachment->contentType()->subType();
+        QByteArray attachContDisp = attachment->contentDisposition()->as7BitString(false);
+        QByteArray attachCharset = attachment->contentType()->charset();
+
+        QByteArray attachParamAttr = "method";
+        QString attachParamValue = attachment->contentType()->parameter(QLatin1String("method"));
+        QByteArray attachData = attachment->encodedBody();
+
+        messages << mTo << mCc << mBcc << subject << body << hidden
+                 << attachName << attachCte << attachData << attachType << attachSubType
+                 << attachParamAttr << attachParamValue << attachContDisp << attachCharset
+                 << identity << false;
+    }
+    QDBusInterface kmailObj(QLatin1String("org.kde.kmail"), QLatin1String("/KMail"), QLatin1String("org.kde.kmail.kmail"));
+
+    QDBusReply<int> composerDbusPath = kmailObj.callWithArgumentList(QDBus::AutoDetect, QLatin1String("openComposer"), messages);
+
+    if (!composerDbusPath.isValid()) {
+        setError(KJob::UserDefinedError);
+        setErrorText(i18nc( "errormessage: dbus is running but still no connection kmail", "Cannot connect to email service"));
+    }
+    emitResult();
+
+}
diff --git a/incidenceeditor-ng/opencomposerjob.h b/incidenceeditor-ng/opencomposerjob.h
new file mode 100644
index 0000000..acb43cc
--- /dev/null
+++ b/incidenceeditor-ng/opencomposerjob.h
@@ -0,0 +1,57 @@
+/*
+ * 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_OPENCOMPOSERJOB_H
+#define INCIDENCEEDITOR_OPENCOMPOSERJOB_H
+
+#include <KPIMIdentities/Identity>
+#include <kmime/kmime_message.h>
+
+#include <KJob>
+namespace IncidenceEditorNG {
+
+// Opens a Composer with a mail with one attachment (costructed my ITIPHandler)
+class OpenComposerJob : public KJob
+{
+    Q_OBJECT
+
+public:
+    explicit OpenComposerJob(QObject *parent,
+                             const QString &to, const QString &cc, const QString &bcc,
+                             const KMime::Message::Ptr &message, const KPIMIdentities::Identity &identity);
+    virtual ~OpenComposerJob();
+
+    virtual void start();
+
+private slots:
+    void slotServiceOwnerChanged(const QString &, const QString &, const QString &);
+    void timeout();
+    void processMail();
+
+private:
+    QString mDBusService;
+    QString mError;
+    QString mTo, mCc, mBcc;
+    KMime::Message::Ptr mMessage;
+    KPIMIdentities::Identity mIdentity;
+    bool mSuccess;
+};
+
+}
+#endif
diff --git a/incidenceeditor-ng/tests/CMakeLists.txt b/incidenceeditor-ng/tests/CMakeLists.txt
index f624663..5b0c4cd 100644
--- a/incidenceeditor-ng/tests/CMakeLists.txt
+++ b/incidenceeditor-ng/tests/CMakeLists.txt
@@ -40,3 +40,12 @@ target_link_libraries(
   incidenceeditorsng
 )
 
+kde4_add_executable(testindividualmaildialog NOGUI TEST testindividualmaildialog.cpp ../individualmaildialog.cpp)
+target_link_libraries(testindividualmaildialog
+  ${KDEPIMLIBS_KCALCORE_LIBS}
+  ${QT_QTTEST_LIBRARY}
+  ${QT_QTCORE_LIBRARY}
+  ${QT_QTGUI_LIBRARY}
+  ${KDE4_KDECORE_LIBS}
+  ${KDE4_KDEUI_LIBS}
+ )
\ No newline at end of file
diff --git a/incidenceeditor-ng/tests/testindividualmaildialog.cpp b/incidenceeditor-ng/tests/testindividualmaildialog.cpp
new file mode 100644
index 0000000..2831cb0
--- /dev/null
+++ b/incidenceeditor-ng/tests/testindividualmaildialog.cpp
@@ -0,0 +1,51 @@
+#include <QObject>
+#include <qtest_kde.h>
+
+#include "individualmaildialog.h"
+
+using namespace IncidenceEditorNG;
+
+class TestIndividualMailDialog : public QObject
+{
+    Q_OBJECT
+private slots:
+    void testDialog() {
+        KCalCore::Attendee::List attendees;
+        KGuiItem buttonYes = KGuiItem(QLatin1String("Send Email"));
+        KGuiItem buttonNo = KGuiItem(QLatin1String("Do not send"));
+
+        KCalCore::Attendee::Ptr attendee1(new KCalCore::Attendee(QLatin1String("test1"), QLatin1String("test1 at example.com")));
+        KCalCore::Attendee::Ptr attendee2(new KCalCore::Attendee(QLatin1String("test2"), QLatin1String("test2 at example.com")));
+        KCalCore::Attendee::Ptr attendee3(new KCalCore::Attendee(QLatin1String("test3"), QLatin1String("test3 at example.com")));
+
+        attendees << attendee1 << attendee2 << attendee3;
+
+        IndividualMailDialog dialog(QLatin1String("title"), attendees, buttonYes, buttonNo, 0);
+
+        QCOMPARE(dialog.editAttendees().count(), 0);
+        QCOMPARE(dialog.updateAttendees().count(), 3);
+
+        // Just make sure, that the QCombobox is sorted like we think
+        QComboBox *first = dialog.mAttendeeDecision[attendees[0]];
+        QCOMPARE((IndividualMailDialog::Decisions)first->itemData(0, Qt::UserRole).toInt(), IndividualMailDialog::Update);
+        QCOMPARE((IndividualMailDialog::Decisions)first->itemData(1, Qt::UserRole).toInt(), IndividualMailDialog::NoUpdate);
+        QCOMPARE((IndividualMailDialog::Decisions)first->itemData(2, Qt::UserRole).toInt(), IndividualMailDialog::Edit);
+
+        // No update for first attendee, other default
+        first->setCurrentIndex(1);
+        QCOMPARE(dialog.editAttendees().count(), 0);
+        QCOMPARE(dialog.updateAttendees().count(), 2);
+        QVERIFY(dialog.updateAttendees().contains(attendee2));
+        QVERIFY(dialog.updateAttendees().contains(attendee3));
+
+        // edit for frist attende, other default
+        first->setCurrentIndex(2);
+        QCOMPARE(dialog.editAttendees().count(), 1);
+        QCOMPARE(dialog.updateAttendees().count(), 2);
+        QCOMPARE(dialog.editAttendees()[0], attendee1);
+   }
+ };
+
+QTEST_KDEMAIN( TestIndividualMailDialog, GUI )
+
+#include "testindividualmaildialog.moc"
diff --git a/korganizer/calendarview.cpp b/korganizer/calendarview.cpp
index ba838f1..5d620f5 100644
--- a/korganizer/calendarview.cpp
+++ b/korganizer/calendarview.cpp
@@ -64,6 +64,7 @@
 #include <incidenceeditor-ng/incidencedefaults.h>
 #include <incidenceeditor-ng/incidencedialog.h>
 #include <incidenceeditor-ng/incidencedialogfactory.h>
+#include <incidenceeditor-ng/individualmailcomponentfactory.h>
 
 #include <libkdepim/widgets/pimmessagebox.h>
 #include <akonadi/calendar/freebusymanager.h>
@@ -106,7 +107,7 @@ CalendarView::CalendarView( QWidget *parent ) : CalendarViewBase( parent ),
                                                 mETMCollectionView( 0 )
 {
   Akonadi::Control::widgetNeedsAkonadi( this );
-  mChanger = new Akonadi::IncidenceChanger( this );
+  mChanger = new Akonadi::IncidenceChanger( new IncidenceEditorNG::IndividualMailComponentFactory( this ), this );
   mChanger->setDefaultCollection( Akonadi::Collection( CalendarSupport::KCalPrefs::instance()->defaultCalendarId() ) );
 
   mChanger->setDestinationPolicy( static_cast<Akonadi::IncidenceChanger::DestinationPolicy>( KOPrefs::instance()->destination() ) );


commit 09cc03e9adfccbac2b42706a9f8ab6bd59eac954
Author: Sandro Knauß <knauss at kolabsys.com>
Date:   Tue Jul 22 17:30:48 2014 +0200

    Add paramenter to ensure the composer to open
    
    REVIEW: 119461

diff --git a/kmail/kmkernel.cpp b/kmail/kmkernel.cpp
index 5e2ffaf..91fa37b 100644
--- a/kmail/kmkernel.cpp
+++ b/kmail/kmkernel.cpp
@@ -643,6 +643,28 @@ int KMKernel::openComposer(const QString &to, const QString &cc,
     return 1;
 }
 
+int KMKernel::openComposer(const QString &to, const QString &cc,
+                           const QString &bcc, const QString &subject,
+                           const QString &body, bool hidden,
+                           const QString &attachName,
+                           const QByteArray &attachCte,
+                           const QByteArray &attachData,
+                           const QByteArray &attachType,
+                           const QByteArray &attachSubType,
+                           const QByteArray &attachParamAttr,
+                           const QString &attachParamValue,
+                           const QByteArray &attachContDisp,
+                           const QByteArray &attachCharset,
+                           unsigned int identity)
+{
+    return openComposer(to, cc, bcc,
+                        subject, body, hidden,
+                        attachName, attachCte, attachData,
+                        attachType, attachSubType, attachParamAttr, attachParamValue,
+                        attachContDisp, attachCharset, identity, true);
+}
+
+
 int KMKernel::openComposer (const QString &to, const QString &cc,
                             const QString &bcc, const QString &subject,
                             const QString &body, bool hidden,
@@ -655,9 +677,9 @@ int KMKernel::openComposer (const QString &to, const QString &cc,
                             const QString &attachParamValue,
                             const QByteArray &attachContDisp,
                             const QByteArray &attachCharset,
-                            unsigned int identity )
+                            unsigned int identity,
+                            bool allowDefaultSend)
 {
-    kDebug();
     KMail::Composer::TemplateContext context = KMail::Composer::New;
     KMime::Message::Ptr msg( new KMime::Message );
     KMime::Content *msgPart = 0;
@@ -740,7 +762,7 @@ int KMKernel::openComposer (const QString &to, const QString &cc,
         cWin->disableForgottenAttachmentsCheck();
     }
 
-    if ( !hidden && !iCalAutoSend ) {
+    if ( !hidden && !(allowDefaultSend && iCalAutoSend)  ) {
         cWin->show();
         // Activate window - doing this instead of KWin::activateWindow(cWin->winId());
         // so that it also works when called from KMailApplication::newInstance()
diff --git a/kmail/kmkernel.h b/kmail/kmkernel.h
index a9b39fd..ecbf0ee 100644
--- a/kmail/kmkernel.h
+++ b/kmail/kmkernel.h
@@ -236,6 +236,51 @@ public Q_SLOTS:
     /**
    * Opens a composer window and prefills it with different
    * message parts.
+   * @since 4.70.0
+   *
+   * @returns The id of composer if more are opened.
+   *
+   * @param to A comma separated list of To addresses.
+   * @param cc A comma separated list of CC addresses.
+   * @param bcc A comma separated list of BCC addresses.
+   * @param subject The message subject.
+   * @param body The message body.
+   * @param hidden Whether the composer window shall initially be hidden.
+   * @param attachName The name of the attachment.
+   * @param attachCte The content transfer encoding of the attachment.
+   * @param attachData The raw data of the attachment.
+   * @param attachType The mime type of the attachment.
+   * @param attachSubType The sub mime type of the attachment.
+   * @param attachParamAttr The parameter attribute of the attachment.
+   * @param attachParamValue The parameter value of the attachment.
+   * @param attachContDisp The content display type of the attachment.
+   * @param attachCharset The charset of the attachment.
+   * @param identity The identity identifier which will be used as sender identity.
+   * @param allowDefaultSend Overwrite automatic sending feature,
+   *                         to make sure a composer is opend
+   */
+    Q_SCRIPTABLE int openComposer( const QString & to,
+                                   const QString & cc,
+                                   const QString & bcc,
+                                   const QString & subject,
+                                   const QString & body,
+                                   bool hidden,
+                                   const QString & attachName,
+                                   const QByteArray & attachCte,
+                                   const QByteArray  &attachData,
+                                   const QByteArray & attachType,
+                                   const QByteArray & attachSubType,
+                                   const QByteArray & attachParamAttr,
+                                   const QString & attachParamValue,
+                                   const QByteArray & attachContDisp,
+                                   const QByteArray & attachCharset,
+                                   unsigned int identity,
+                                   bool allowDefaultSend );
+
+
+    /**
+   * Opens a composer window and prefills it with different
+   * message parts.
    *
    * @returns The DBus object path for the composer.
    *


commit 3719975d51b8806091b84bc7b65185fdc8861597
Author: Sandro Knauß <knauss at kolabsys.com>
Date:   Thu Aug 7 14:49:02 2014 +0200

    Fix creating mail to have correct contentDisposition
    
    REVIEW: 119645

diff --git a/kmail/kmkernel.cpp b/kmail/kmkernel.cpp
index e175278..5e2ffaf 100644
--- a/kmail/kmkernel.cpp
+++ b/kmail/kmkernel.cpp
@@ -706,11 +706,10 @@ int KMKernel::openComposer (const QString &to, const QString &cc,
         } else {
             // Just do what we're told to do
             msgPart = new KMime::Content;
-            msgPart->contentType()->setName( attachName, "utf-8" );
             msgPart->contentTransferEncoding()->fromUnicodeString(QLatin1String(attachCte), "utf-8" );
             msgPart->setBody( attachData ); //TODO: check if was setBodyEncoded
             msgPart->contentType()->setMimeType( attachType + '/' +  attachSubType );
-            msgPart->contentDisposition()->setParameter( QLatin1String(attachParamAttr), attachParamValue ); //TODO: Check if the content disposition parameter needs to be set!
+            msgPart->contentType()->setParameter( QLatin1String(attachParamAttr), attachParamValue ); //TODO: Check if the content disposition parameter needs to be set!
             if( ! MessageViewer::GlobalSettings::self()->exchangeCompatibleInvitations() ) {
                 msgPart->contentDisposition()->fromUnicodeString(QLatin1String(attachContDisp), "utf-8" );
             }
@@ -718,6 +717,9 @@ int KMKernel::openComposer (const QString &to, const QString &cc,
                 // kDebug() << "Set attachCharset to" << attachCharset;
                 msgPart->contentType()->setCharset( attachCharset );
             }
+
+            msgPart->contentType()->setName( attachName, "utf-8" );
+            msgPart->assemble();
             // Don't show the composer window if the automatic sending is checked
             iCalAutoSend = MessageViewer::GlobalSettings::self()->automaticSending();
         }




More information about the commits mailing list