diff --git a/incidenceeditor-ng/incidencecategories.cpp b/incidenceeditor-ng/incidencecategories.cpp
index 8d13d58f03..29b6b0edb5 100644
--- a/incidenceeditor-ng/incidencecategories.cpp
+++ b/incidenceeditor-ng/incidencecategories.cpp
@@ -1,110 +1,110 @@
 /*
   Copyright (c) 2010 Bertjan Broeksema <broeksema@kde.org>
   Copyright (c) 2010 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.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 "incidencecategories.h"
 
 #include "editorconfig.h"
 
 #include "ui_dialogdesktop.h"
 
 #include <libkdepim/widgets/tagwidgets.h>
 #include <KConfigSkeleton>
 #include <KDebug>
 
 #include <Akonadi/TagCreateJob>
 
 using namespace IncidenceEditorNG;
 
 IncidenceCategories::IncidenceCategories( Ui::EventOrTodoDesktop *ui )
   : mUi( ui )
 {
   setObjectName( "IncidenceCategories" );
 
   connect( mUi->mTagWidget, SIGNAL(selectionChanged(Akonadi::Tag::List)),
           SLOT(onSelectionChanged(Akonadi::Tag::List)) );
 }
 
 void IncidenceCategories::onSelectionChanged(const Akonadi::Tag::List &list)
 {
   mSelectedTags = list;
   mDirty = true;
   checkDirtyStatus();
 }
 
 void IncidenceCategories::load( const KCalCore::Incidence::Ptr &incidence )
 {
   mLoadedIncidence = incidence;
   mDirty = false;
   if ( mLoadedIncidence ) {
     checkForUnknownCategories( mLoadedIncidence->categories() );
   } else {
     mSelectedTags.clear();
   }
 
   mWasDirty = false;
 }
 
 void IncidenceCategories::load( const Akonadi::Item &item )
 {
   mSelectedTags = item.tags();
   mUi->mTagWidget->setSelection(item.tags());
 }
 
 void IncidenceCategories::save( const KCalCore::Incidence::Ptr &incidence )
 {
   Q_ASSERT( incidence );
   incidence->setCategories( categories() );
 }
 
 void IncidenceCategories::save( Akonadi::Item &item )
 {
   if (item.tags() != mSelectedTags) {
     item.setTags(mSelectedTags);
   }
 }
 
 QStringList IncidenceCategories::categories() const
 {
   QStringList list;
   Q_FOREACH (const Akonadi::Tag &tag, mSelectedTags) {
     list << tag.name();
   }
   return list;
 }
 
 bool IncidenceCategories::isDirty() const
 {
   return mDirty;
 }
 
 void IncidenceCategories::printDebugInfo() const
 {
   kDebug() << "mSelectedCategories = " << categories();
   kDebug() << "mLoadedIncidence->categories() = " << mLoadedIncidence->categories();
 }
 
 void IncidenceCategories::checkForUnknownCategories( const QStringList &categoriesToCheck )
 {
   foreach ( const QString &category, categoriesToCheck ) {
-    Akonadi::TagCreateJob *tagCreateJob = new Akonadi::TagCreateJob(Akonadi::Tag(category), this);
+    Akonadi::TagCreateJob *tagCreateJob = new Akonadi::TagCreateJob(Akonadi::Tag::genericTag(category), this);
     tagCreateJob->setMergeIfExisting(true);
     //TODO add the missing tags to the item and add them to the list of selected tags in the widget
   }
 }
diff --git a/libkdepim/widgets/tagwidgets.cpp b/libkdepim/widgets/tagwidgets.cpp
index f2e4a5952a..2c516e7ac0 100644
--- a/libkdepim/widgets/tagwidgets.cpp
+++ b/libkdepim/widgets/tagwidgets.cpp
@@ -1,168 +1,168 @@
 /*
   Copyright (c) 2014 Christian Mollekopf <mollekopf@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 "tagwidgets.h"
 #include <KJob>
 #include <QLayout>
 #include <QItemSelectionModel>
 
 #include <Akonadi/Tag>
 #include <Akonadi/TagFetchJob>
 #include <Akonadi/TagFetchScope>
 #include <Akonadi/TagCreateJob>
 #include <Akonadi/TagWidget>
 #include <Akonadi/TagModel>
 #include <Akonadi/Monitor>
 #include <KCheckableProxyModel>
 #include <KLineEdit>
 
 using namespace KPIM;
 
 TagWidget::TagWidget(QWidget* parent)
 :   QWidget(parent)
 {
     mTagWidget = new Akonadi::TagWidget(this);
     connect(mTagWidget, SIGNAL(selectionChanged(Akonadi::Tag::List)), this, SLOT(onSelectionChanged(Akonadi::Tag::List)));
     QHBoxLayout *l = new QHBoxLayout;
     l->addWidget(mTagWidget);
     setLayout(l);
 }
 
 void TagWidget::onSelectionChanged(const Akonadi::Tag::List &tags)
 {
     Q_UNUSED(tags);
     mCachedTagNames.clear();
     Q_FOREACH (const Akonadi::Tag &tag, mTagWidget->selection()) {
         mCachedTagNames << tag.name();
     }
     emit selectionChanged(mCachedTagNames);
     emit selectionChanged(tags);
 }
 
 void TagWidget::setSelection(const QStringList &tagNames)
 {
     mTagList.clear();
     mCachedTagNames = tagNames;
     foreach (const QString &name, tagNames) {
       //TODO fetch by GID instead, we don't really want to create tags here
-      Akonadi::TagCreateJob *tagCreateJob = new Akonadi::TagCreateJob(Akonadi::Tag(name), this);
+      Akonadi::TagCreateJob *tagCreateJob = new Akonadi::TagCreateJob(Akonadi::Tag::genericTag(name), this);
       tagCreateJob->setMergeIfExisting(true);
       connect(tagCreateJob, SIGNAL(result(KJob*)), this, SLOT(onTagCreated(KJob*)));
     }
 }
 
 void TagWidget::onTagCreated(KJob *job)
 {
     if (job->error()) {
         kWarning() << "Failed to create tag " << job->errorString();
         return;
     }
     Akonadi::TagCreateJob *createJob = static_cast<Akonadi::TagCreateJob*>(job);
     mTagList << createJob->tag();
     mTagWidget->setSelection(mTagList);
 }
 
 QStringList TagWidget::selection() const
 {
     return mCachedTagNames;
 }
 
 
 TagSelectionDialog::TagSelectionDialog(QWidget* parent)
 :   Akonadi::TagSelectionDialog(parent)
 {
 
 }
 
 void TagSelectionDialog::setSelection(const QStringList &tagNames)
 {
     mTagList.clear();
     foreach (const QString &name, tagNames) {
       //TODO fetch by GID instead, we don't really want to create tags here
-      Akonadi::TagCreateJob *tagCreateJob = new Akonadi::TagCreateJob(Akonadi::Tag(name), this);
+      Akonadi::TagCreateJob *tagCreateJob = new Akonadi::TagCreateJob(Akonadi::Tag::genericTag(name), this);
       tagCreateJob->setMergeIfExisting(true);
       connect(tagCreateJob, SIGNAL(result(KJob*)), this, SLOT(onTagCreated(KJob*)));
     }
 }
 
 void TagSelectionDialog::onTagCreated(KJob *job)
 {
     if (job->error()) {
         kWarning() << "Failed to create tag " << job->errorString();
         return;
     }
     Akonadi::TagCreateJob *createJob = static_cast<Akonadi::TagCreateJob*>(job);
     mTagList << createJob->tag();
     Akonadi::TagSelectionDialog::setSelection(mTagList);
 }
 
 QStringList TagSelectionDialog::selection() const
 {
     QStringList list;
     Q_FOREACH (const Akonadi::Tag &tag, Akonadi::TagSelectionDialog::selection()) {
         list << tag.name();
     }
     return list;
 }
 
 Akonadi::Tag::List TagSelectionDialog::tagSelection() const
 {
     return Akonadi::TagSelectionDialog::selection();
 }
 
 class MatchingCheckableProxyModel : public KCheckableProxyModel
 {
 public:
     MatchingCheckableProxyModel(QObject* parent = 0): KCheckableProxyModel(parent) {}
     virtual QModelIndexList match(const QModelIndex& start, int role, const QVariant& value, int hits = 1, Qt::MatchFlags flags = Qt::MatchExactly) const
     {
         if (role == Qt::CheckStateRole) {
             return selectionModel()->selectedRows();
         }
         return KCheckableProxyModel::match(start, role, value, hits, flags);
     }
 };
 
 TagSelectionCombo::TagSelectionCombo(QWidget* parent)
 :   KPIM::KCheckComboBox(parent)
 {
     Akonadi::Monitor *monitor = new Akonadi::Monitor(this);
     monitor->setTypeMonitored(Akonadi::Monitor::Tags);
 
     Akonadi::TagModel *model = new Akonadi::TagModel(monitor, this);
 
     QItemSelectionModel *selectionModel = new QItemSelectionModel(model, this);
     KCheckableProxyModel *checkableProxy = new MatchingCheckableProxyModel( this );
     checkableProxy->setSourceModel( model );
     checkableProxy->setSelectionModel( selectionModel );
 
     setModel(checkableProxy);
 
     //We need to reconnect from the constructor of KCheckComboBox to the new model
     connect(checkableProxy, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
             this, SLOT(updateCheckedItems(QModelIndex,QModelIndex)) );
 }
 
 TagCombo::TagCombo(QWidget* parent)
 :   KComboBox(parent)
 {
     Akonadi::Monitor *monitor = new Akonadi::Monitor(this);
     monitor->setTypeMonitored(Akonadi::Monitor::Tags);
     Akonadi::TagModel *model = new Akonadi::TagModel(monitor, this);
     setModel(model);
 }
 
diff --git a/mailcommon/tag/tag.cpp b/mailcommon/tag/tag.cpp
index 5752ac4767..e3a09f4895 100644
--- a/mailcommon/tag/tag.cpp
+++ b/mailcommon/tag/tag.cpp
@@ -1,147 +1,156 @@
 /* Copyright 2010 Thomas McGuire <mcguire@kde.org>
    Copyright 2012 Laurent Montel <montel@kde.org>
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License as
    published by the Free Software Foundation; either version 2 of
    the License or (at your option) version 3 or any later version
    accepted by the membership of KDE e.V. (or its successor approved
    by the membership of KDE e.V.), which shall act as a proxy
    defined in Section 14 of version 3 of the license.
 
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 #include "tag.h"
 
 #include <Akonadi/Tag>
 #include <Akonadi/TagAttribute>
 
+#include <QUuid>
 #include <QDebug>
 
 using namespace MailCommon;
 
 Tag::Ptr Tag::createDefaultTag(const QString& name)
 {
     Tag::Ptr tag( new Tag() );
     tag->tagName = name;
     tag->iconName = QLatin1String("mail-tagged");
 
     tag->priority = -1;
     tag->inToolbar = false;
     tag->isImmutable = false;
     return tag;
 }
 
 Tag::Ptr Tag::fromAkonadi(const Akonadi::Tag& akonadiTag)
 {
     Tag::Ptr tag( new Tag() );
     tag->tagName = akonadiTag.name();
     tag->mTag = akonadiTag;
     tag->priority = -1;
     tag->iconName = QLatin1String("mail-tagged");
     tag->inToolbar = false;
     tag->isImmutable = akonadiTag.isImmutable();
     Akonadi::TagAttribute *attr = akonadiTag.attribute<Akonadi::TagAttribute>();
     if (attr) {
         if (!attr->iconName().isEmpty()) {
             tag->iconName = attr->iconName();
         }
         tag->inToolbar = attr->inToolbar();
         tag->shortcut = KShortcut(attr->shortcut());
         tag->textColor = attr->textColor();
         tag->backgroundColor = attr->backgroundColor();
         if (!attr->font().isEmpty()) {
             tag->textFont.fromString( attr->font() );
         }
         tag->priority = attr->priority();
     }
     return tag;
 }
 
 Akonadi::Tag Tag::saveToAkonadi(Tag::SaveFlags saveFlags) const
 {
-    Akonadi::Tag tag( tagName );
+    Akonadi::Tag tag = mTag;
+    if (tag.gid().isEmpty()) {
+        tag.setGid(QUuid::createUuid().toByteArray().mid(1, 36));
+    }
+    if (isImmutable) {
+        tag.setType(Akonadi::Tag::PLAIN);
+    } else {
+        tag.setType(Akonadi::Tag::GENERIC);
+    }
     Akonadi::TagAttribute *attr = tag.attribute<Akonadi::TagAttribute>(Akonadi::AttributeEntity::AddIfMissing);
     attr->setDisplayName( tagName );
     attr->setIconName( iconName );
     attr->setInToolbar( inToolbar );
     attr->setShortcut( shortcut.toString() );
     attr->setPriority( priority );
 
     if ( textColor.isValid() && (saveFlags & TextColor) )
         attr->setTextColor( textColor );
     else
         attr->setTextColor( QColor() );
 
     if ( backgroundColor.isValid() && (saveFlags & BackgroundColor) )
         attr->setBackgroundColor( backgroundColor );
     else
         attr->setBackgroundColor( QColor() );
 
     if ( (textFont != QFont()) && (saveFlags & Font) )
         attr->setFont( textFont.toString() );
     else
         attr->setFont( QString() );
 
     tag.addAttribute(attr);
     return tag;
 }
 
 bool Tag::compare( Tag::Ptr &tag1, Tag::Ptr &tag2 )
 {
     if ( tag1->priority < tag2->priority )
         return true;
     else if (tag1->priority == tag2->priority)
         return ( tag1->tagName < tag2->tagName );
     else
         return false;
 }
 
 bool Tag::compareName( Tag::Ptr &tag1, Tag::Ptr &tag2 )
 {
     return ( tag1->tagName < tag2->tagName );
 }
 
 bool Tag::operator==( const Tag &other ) const
 {
 #if 0
     if (mTag.isValid()) {
         return id() == other.id();
     }
 #endif
     return tagName == other.tagName &&
             textColor == other.textColor &&
             backgroundColor == other.backgroundColor &&
             textFont == other.textFont &&
             iconName == other.iconName &&
             inToolbar == other.inToolbar &&
             shortcut.toString() == other.shortcut.toString() &&
             priority == other.priority;
 }
 
 bool Tag::operator!=( const Tag &other ) const
 {
     return !( *this == other );
 }
 
 qint64 Tag::id() const
 {
     return mTag.id();
 }
 
 QString Tag::name() const
 {
     return mTag.name();
 }
 
 Akonadi::Tag Tag::tag() const
 {
     return mTag;
 }