diff --git a/app/build.gradle b/app/build.gradle
index 46e60fe5f917a40475b589fead2d2f5939951a47..93ff59a8d1b2682fd19c9c6b54fa0442f42218f6 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -61,7 +61,7 @@ if (versionPropsFile.exists() && versionPropsFile.canRead()) {
     versionProps.load(new FileInputStream(versionPropsFile))
     def runTasks = gradle.startParameter.taskNames
     versionBuild = Integer.valueOf(versionProps['VERSION_BUILD'].toString())
-    if (!(':app:assembleDebug' in runTasks) && !('assembleDebug' in runTasks) && !('installDebug' in runTasks)) {
+    if (!runTasks.intersect([':app:assembleBeta', 'assembleBeta', ':app:assembleRelease', 'assembleRelease']).empty) {
         println "Increasing version number"
         versionBuild = versionBuild + 1
     }
@@ -143,7 +143,7 @@ dependencies {
 
     // General Java libs
     compile 'com.google.guava:guava:19.0'
-    compile 'de.greenrobot:eventbus:2.4.0'
+    compile 'org.greenrobot:eventbus:3.0.0'
 
     compile 'joda-time:joda-time:2.9.1'
     compile 'org.joda:joda-convert:1.8'
@@ -163,12 +163,12 @@ dependencies {
     compile "com.github.Raizlabs.DBFlow:dbflow:3.1.1"
 
     // Appcompat
-    compile 'com.android.support:appcompat-v7:24.0.0'
-    compile 'com.android.support:design:24.0.0'
-    compile 'com.android.support:support-v4:24.0.0'
-    compile 'com.android.support:recyclerview-v7:24.0.0'
-    compile 'com.android.support:preference-v14:24.0.0'
-    compile 'com.android.support:cardview-v7:24.0.0'
+    compile 'com.android.support:appcompat-v7:24.2.0'
+    compile 'com.android.support:design:24.2.0'
+    compile 'com.android.support:support-v4:24.2.0'
+    compile 'com.android.support:recyclerview-v7:24.2.0'
+    compile 'com.android.support:preference-v14:24.2.0'
+    compile 'com.android.support:cardview-v7:24.2.0'
 
     // Reactive Libs
     compile 'io.reactivex:rxandroid:1.2.1'
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index fccfadc5df4b814cf6a655f61d375bb87f48a987..141ece2a9fca1790379ff96e9db649dea31d0bf0 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -74,6 +74,13 @@
             android:parentActivityName=".ui.LoginActivity"
             android:theme="@style/SetupTheme" />
 
+        <activity
+            android:name=".ui.setup.CoreSetupActivity"
+            android:label="Core Setup"
+            android:launchMode="singleTask"
+            android:parentActivityName=".ui.chat.MainActivity"
+            android:theme="@style/SetupTheme" />
+
         <activity
             android:name=".ui.settings.SettingsActivity"
             android:label="Settings"
diff --git a/app/src/main/java/de/kuschku/libquassel/BusProvider.java b/app/src/main/java/de/kuschku/libquassel/BusProvider.java
index f4306182311a22993ee9871974e4f31cef6b9a11..46119430fccb6aba4bf8238844b84627b67098dd 100644
--- a/app/src/main/java/de/kuschku/libquassel/BusProvider.java
+++ b/app/src/main/java/de/kuschku/libquassel/BusProvider.java
@@ -24,10 +24,13 @@ package de.kuschku.libquassel;
 import android.support.annotation.NonNull;
 import android.util.Log;
 
+import org.greenrobot.eventbus.EventBus;
+import org.greenrobot.eventbus.NoSubscriberEvent;
+import org.greenrobot.eventbus.Subscribe;
+import org.greenrobot.eventbus.ThreadMode;
+
 import java.util.UUID;
 
-import de.greenrobot.event.EventBus;
-import de.greenrobot.event.NoSubscriberEvent;
 import de.kuschku.libquassel.events.BacklogReceivedEvent;
 import de.kuschku.libquassel.events.GeneralErrorEvent;
 import de.kuschku.libquassel.events.LagChangedEvent;
@@ -86,10 +89,7 @@ public class BusProvider {
             this.identifier = identifier;
         }
 
-        public void onEvent(GeneralErrorEvent event) {
-            Log.e(identifier, event.getClass().getSimpleName(), event.exception);
-        }
-
+        @Subscribe(threadMode = ThreadMode.MAIN)
         public void onEvent(NoSubscriberEvent event) {
             if (!(event.originalEvent instanceof LagChangedEvent) && !(event.originalEvent instanceof BacklogReceivedEvent))
                 Log.e(identifier, String.valueOf(event));
diff --git a/app/src/main/java/de/kuschku/libquassel/CoreConnection.java b/app/src/main/java/de/kuschku/libquassel/CoreConnection.java
index dbf6a154d27a77a00aead03ec73ace28813c3c43..081b643b97e4f4db32b37e55d4af61fd4b511187 100644
--- a/app/src/main/java/de/kuschku/libquassel/CoreConnection.java
+++ b/app/src/main/java/de/kuschku/libquassel/CoreConnection.java
@@ -26,6 +26,9 @@ import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 import android.util.Log;
 
+import org.greenrobot.eventbus.Subscribe;
+import org.greenrobot.eventbus.ThreadMode;
+
 import java.io.IOException;
 import java.net.InetSocketAddress;
 import java.net.Socket;
@@ -211,10 +214,12 @@ public class CoreConnection {
         inputThread.start();
     }
 
+    @Subscribe(threadMode = ThreadMode.ASYNC)
     public void onEventAsync(HandshakeFailedEvent event) {
         this.close();
     }
 
+    @Subscribe
     public void onEvent(@NonNull ConnectionChangeEvent event) {
         this.status = event.status;
         if (event.status == ConnectionChangeEvent.Status.INITIALIZING_DATA && heartbeatThread != null)
diff --git a/app/src/main/java/de/kuschku/libquassel/IProtocolHandler.java b/app/src/main/java/de/kuschku/libquassel/IProtocolHandler.java
index fdf74804bddf5c5fbf5108656f1b73b6c99c2987..c2ba4b244eaa2bb1d9fbdb2fa138b5d33a191c76 100644
--- a/app/src/main/java/de/kuschku/libquassel/IProtocolHandler.java
+++ b/app/src/main/java/de/kuschku/libquassel/IProtocolHandler.java
@@ -23,6 +23,9 @@ package de.kuschku.libquassel;
 
 import android.support.annotation.NonNull;
 
+import org.greenrobot.eventbus.Subscribe;
+import org.greenrobot.eventbus.ThreadMode;
+
 import de.kuschku.libquassel.client.Client;
 import de.kuschku.libquassel.functions.types.Heartbeat;
 import de.kuschku.libquassel.functions.types.HeartbeatReply;
@@ -37,26 +40,37 @@ import de.kuschku.libquassel.objects.types.ClientLoginReject;
 import de.kuschku.libquassel.objects.types.SessionInit;
 
 public interface IProtocolHandler {
+    @Subscribe(threadMode = ThreadMode.MAIN)
     void onEventMainThread(InitDataFunction packedFunc);
 
+    @Subscribe(threadMode = ThreadMode.MAIN)
     void onEventMainThread(InitRequestFunction packedFunc);
 
+    @Subscribe(threadMode = ThreadMode.MAIN)
     void onEventMainThread(RpcCallFunction packedFunc);
 
+    @Subscribe(threadMode = ThreadMode.MAIN)
     void onEventMainThread(SyncFunction packedFunc);
 
+    @Subscribe
     void onEvent(ClientInitReject message);
 
+    @Subscribe
     void onEvent(ClientInitAck message);
 
+    @Subscribe
     void onEvent(ClientLoginAck message);
 
+    @Subscribe
     void onEvent(ClientLoginReject message);
 
+    @Subscribe
     void onEvent(SessionInit message);
 
+    @Subscribe
     void onEvent(Heartbeat message);
 
+    @Subscribe(threadMode = ThreadMode.MAIN)
     void onEventMainThread(HeartbeatReply message);
 
     @NonNull
diff --git a/app/src/main/java/de/kuschku/libquassel/ProtocolHandler.java b/app/src/main/java/de/kuschku/libquassel/ProtocolHandler.java
index 685c074ba23d514b77437973a016cd70a3b125b6..bf18fdfd5bb059a5df16296b49dc206dc5124965 100644
--- a/app/src/main/java/de/kuschku/libquassel/ProtocolHandler.java
+++ b/app/src/main/java/de/kuschku/libquassel/ProtocolHandler.java
@@ -24,9 +24,13 @@ package de.kuschku.libquassel;
 import android.support.annotation.NonNull;
 import android.util.Log;
 
+import org.greenrobot.eventbus.Subscribe;
+import org.greenrobot.eventbus.ThreadMode;
 import org.joda.time.DateTime;
 import org.joda.time.Interval;
 
+import java.util.logging.Logger;
+
 import de.kuschku.libquassel.client.Client;
 import de.kuschku.libquassel.events.ConnectionChangeEvent;
 import de.kuschku.libquassel.events.CoreSetupRequiredEvent;
@@ -43,6 +47,7 @@ import de.kuschku.libquassel.objects.types.ClientInitAck;
 import de.kuschku.libquassel.objects.types.ClientInitReject;
 import de.kuschku.libquassel.objects.types.ClientLoginAck;
 import de.kuschku.libquassel.objects.types.ClientLoginReject;
+import de.kuschku.libquassel.objects.types.CoreSetupAck;
 import de.kuschku.libquassel.objects.types.SessionInit;
 import de.kuschku.libquassel.syncables.SyncableRegistry;
 import de.kuschku.libquassel.syncables.types.SyncableObject;
@@ -63,6 +68,7 @@ public class ProtocolHandler implements IProtocolHandler {
         this.client = client;
     }
 
+    @Subscribe(threadMode = ThreadMode.MAIN)
     public void onEventMainThread(@NonNull InitDataFunction packedFunc) {
         try {
             SyncableObject object = SyncableRegistry.from(packedFunc);
@@ -74,9 +80,11 @@ public class ProtocolHandler implements IProtocolHandler {
         }
     }
 
+    @Subscribe(threadMode = ThreadMode.MAIN)
     public void onEventMainThread(@NonNull InitRequestFunction packedFunc) {
     }
 
+    @Subscribe(threadMode = ThreadMode.MAIN)
     public void onEventMainThread(@NonNull RpcCallFunction packedFunc) {
         try {
             if (packedFunc.functionName.substring(0, 1).equals("2")) {
@@ -91,7 +99,10 @@ public class ProtocolHandler implements IProtocolHandler {
         }
     }
 
+    @Subscribe(threadMode = ThreadMode.MAIN)
     public void onEventMainThread(@NonNull SyncFunction packedFunc) {
+//        Log.d("ProtocolHandler", String.format("Sync Call: %s::%s(%s, %s)", packedFunc.className, packedFunc.methodName, packedFunc.objectName, packedFunc.params));
+
         try {
             final Object syncable = client.unsafe_getObjectByIdentifier(packedFunc.className, packedFunc.objectName);
 
@@ -113,39 +124,51 @@ public class ProtocolHandler implements IProtocolHandler {
         }
     }
 
+    @Subscribe
     public void onEvent(@NonNull ClientInitReject message) {
         busProvider.sendEvent(new HandshakeFailedEvent(message.Error));
     }
 
+    @Subscribe
     public void onEvent(ClientInitAck message) {
         client.setCore(message);
 
         if (client.core().Configured) {
             // Send an event to notify that login is necessary
-            busProvider.sendEvent(new LoginRequireEvent(false));
+            busProvider.event.postSticky(new LoginRequireEvent(false));
         } else {
             // Send an event to notify that the core is not yet set up
-            busProvider.sendEvent(new CoreSetupRequiredEvent());
+            busProvider.event.postSticky(new CoreSetupRequiredEvent());
         }
     }
 
+    @Subscribe
+    public void onEvent(CoreSetupAck message) {
+        busProvider.event.postSticky(new LoginRequireEvent(false));
+    }
+
+    @Subscribe
     public void onEvent(ClientLoginAck message) {
     }
 
+    @Subscribe
     public void onEvent(@NonNull ClientLoginReject message) {
         busProvider.sendEvent(new LoginRequireEvent(true));
     }
 
+    @Subscribe
     public void onEvent(@NonNull SessionInit message) {
         client.setConnectionStatus(ConnectionChangeEvent.Status.INITIALIZING_DATA);
 
         client.init(message.SessionState);
     }
 
+    @Subscribe
     public void onEvent(@NonNull Heartbeat heartbeat) {
         busProvider.dispatch(new HeartbeatReply(heartbeat));
     }
 
+    @Subscribe(threadMode = ThreadMode.MAIN)
     public void onEventMainThread(@NonNull HeartbeatReply heartbeat) {
         DateTime dateTime = DateTime.now().toDateTimeISO();
         Interval interval = new Interval(heartbeat.dateTime, dateTime);
@@ -155,6 +178,7 @@ public class ProtocolHandler implements IProtocolHandler {
         client.setLatency(lag);
     }
 
+    @Subscribe
     public void onEvent(@NonNull ConnectionChangeEvent event) {
     }
 
diff --git a/app/src/main/java/de/kuschku/libquassel/client/Client.java b/app/src/main/java/de/kuschku/libquassel/client/Client.java
index 0e236662a9e5a9682c0673abe09231a0d56d274d..a100e0d6c6e7eb0e740245d9af91f6ad0d27f7d6 100644
--- a/app/src/main/java/de/kuschku/libquassel/client/Client.java
+++ b/app/src/main/java/de/kuschku/libquassel/client/Client.java
@@ -117,7 +117,7 @@ public class Client extends AClient {
         this.metaDataManager = metaDataManager;
     }
 
-    public QBufferViewManager bufferViewManager() {
+    public QBufferViewManager<?> bufferViewManager() {
         return bufferViewManager;
     }
 
diff --git a/app/src/main/java/de/kuschku/libquassel/localtypes/BacklogFilter.java b/app/src/main/java/de/kuschku/libquassel/localtypes/BacklogFilter.java
index 482e78f5cbedad5b17ce5d950b743bb80452c25c..9779d45b0cd42953a6652b2814ac42b340690e2a 100644
--- a/app/src/main/java/de/kuschku/libquassel/localtypes/BacklogFilter.java
+++ b/app/src/main/java/de/kuschku/libquassel/localtypes/BacklogFilter.java
@@ -23,24 +23,17 @@ package de.kuschku.libquassel.localtypes;
 
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
-import android.text.format.DateUtils;
-import android.util.Log;
 
-import org.joda.time.DateTime;
-import org.joda.time.DateTimeUtils;
-import org.joda.time.LocalDate;
+import org.greenrobot.eventbus.EventBus;
+import org.greenrobot.eventbus.Subscribe;
+import org.greenrobot.eventbus.ThreadMode;
 
 import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
 import java.util.Set;
 
-import de.greenrobot.event.EventBus;
 import de.kuschku.libquassel.client.Client;
 import de.kuschku.libquassel.message.Message;
-import de.kuschku.libquassel.primitives.types.BufferInfo;
 import de.kuschku.libquassel.syncables.types.interfaces.QNetwork;
-import de.kuschku.util.backports.Objects;
 import de.kuschku.util.observables.callbacks.UICallback;
 import de.kuschku.util.observables.lists.ObservableComparableSortedList;
 
@@ -163,6 +156,7 @@ public class BacklogFilter implements UICallback {
         update();
     }
 
+    @Subscribe(threadMode = ThreadMode.ASYNC)
     public void onEventAsync(UpdateAddEvent event) {
         for (Message message : unfiltered) {
             if (!filterItem(message)) {
@@ -171,6 +165,7 @@ public class BacklogFilter implements UICallback {
         }
     }
 
+    @Subscribe(threadMode = ThreadMode.ASYNC)
     public void onEventAsync(UpdateRemoveEvent event) {
         for (Message message : unfiltered) {
             if (filterItem(message)) {
@@ -179,10 +174,12 @@ public class BacklogFilter implements UICallback {
         }
     }
 
+    @Subscribe(threadMode = ThreadMode.ASYNC)
     public void onEventAsync(@NonNull MessageFilterEvent event) {
         if (!filterItem(event.msg)) bus.post(new MessageInsertEvent(event.msg));
     }
 
+    @Subscribe(threadMode = ThreadMode.MAIN)
     public void onEventMainThread(@NonNull MessageInsertEvent event) {
         filtered.add(event.msg);
         client.bufferSyncer().addActivity(event.msg);
@@ -190,6 +187,7 @@ public class BacklogFilter implements UICallback {
             updateDayChangeMessages();
     }
 
+    @Subscribe(threadMode = ThreadMode.MAIN)
     public void onEventMainThread(@NonNull MessageRemoveEvent event) {
         filtered.remove(event.msg);
         if (event.msg.type != Message.Type.DayChange)
diff --git a/app/src/main/java/de/kuschku/libquassel/objects/MessageTypeRegistry.java b/app/src/main/java/de/kuschku/libquassel/objects/MessageTypeRegistry.java
index b2778942526eca4cc4a13eb85f882ef03e29d037..2171ea6e95dd8c5267bb289ddb314d991fd5f4b1 100644
--- a/app/src/main/java/de/kuschku/libquassel/objects/MessageTypeRegistry.java
+++ b/app/src/main/java/de/kuschku/libquassel/objects/MessageTypeRegistry.java
@@ -77,7 +77,7 @@ public class MessageTypeRegistry {
     public static <T> QVariant<Map<String, QVariant>> toVariantMap(@NonNull final T data) {
         assertTrue(serializerMap.containsKey(data.getClass().getSimpleName()));
 
-        final QVariant<Map<String, QVariant>> map = (QVariant<Map<String, QVariant>>) serializerMap.get(data.getClass().getSimpleName()).toVariantMap(data);
+        final QVariant<Map<String, QVariant>> map = new QVariant<>(serializerMap.get(data.getClass().getSimpleName()).toVariantMap(data));
         map.data.put("MsgType", new QVariant(data.getClass().getSimpleName()));
         return map;
     }
diff --git a/app/src/main/java/de/kuschku/libquassel/objects/serializers/ClientInitAckSerializer.java b/app/src/main/java/de/kuschku/libquassel/objects/serializers/ClientInitAckSerializer.java
index e471f7039c00cf10ef0908575b1daf547dc035da..b381cf547cbd2b046d00027a2112c36ec15210bc 100644
--- a/app/src/main/java/de/kuschku/libquassel/objects/serializers/ClientInitAckSerializer.java
+++ b/app/src/main/java/de/kuschku/libquassel/objects/serializers/ClientInitAckSerializer.java
@@ -51,19 +51,19 @@ public class ClientInitAckSerializer implements ObjectSerializer<ClientInitAck>
 
     @NonNull
     @Override
-    public QVariant<Map<String, QVariant>> toVariantMap(@NonNull final ClientInitAck data) {
-        final List<Map<String, QVariant>> storageBackends = new ArrayList<>();
+    public Map<String, QVariant<Object>> toVariantMap(@NonNull final ClientInitAck data) {
+        final List<Map<String, QVariant<Object>>> storageBackends = new ArrayList<>();
         final StorageBackendSerializer storageBackendSerializer = StorageBackendSerializer.get();
         if (data.StorageBackends != null)
             for (StorageBackend backend : data.StorageBackends) {
-                storageBackends.add((Map<String, QVariant>) storageBackendSerializer.toVariantMap(backend));
+                storageBackends.add(storageBackendSerializer.toVariantMap(backend));
             }
 
-        final QVariant<Map<String, QVariant>> map = new QVariant<>(new HashMap<>());
-        map.data.put("Configured", new QVariant<>(data.Configured));
-        map.data.put("LoginEnabled", new QVariant<>(data.LoginEnabled));
-        map.data.put("StorageBackends", new QVariant<>(storageBackends));
-        map.data.put("CoreFeatures", new QVariant<>(data.CoreFeatures));
+        final Map<String, QVariant<Object>> map = new HashMap<>();
+        map.put("Configured", new QVariant<>(data.Configured));
+        map.put("LoginEnabled", new QVariant<>(data.LoginEnabled));
+        map.put("StorageBackends", new QVariant<>(storageBackends));
+        map.put("CoreFeatures", new QVariant<>(data.CoreFeatures));
         return map;
     }
 
diff --git a/app/src/main/java/de/kuschku/libquassel/objects/serializers/ClientInitRejectSerializer.java b/app/src/main/java/de/kuschku/libquassel/objects/serializers/ClientInitRejectSerializer.java
index a13b8e6c35d2c302cc19147c769d822c5731f6ba..95c66511254cf207bec274dc787795cf6381b4c1 100644
--- a/app/src/main/java/de/kuschku/libquassel/objects/serializers/ClientInitRejectSerializer.java
+++ b/app/src/main/java/de/kuschku/libquassel/objects/serializers/ClientInitRejectSerializer.java
@@ -47,9 +47,9 @@ public class ClientInitRejectSerializer implements ObjectSerializer<ClientInitRe
 
     @NonNull
     @Override
-    public QVariant<Map<String, QVariant>> toVariantMap(@NonNull final ClientInitReject data) {
-        final QVariant<Map<String, QVariant>> map = new QVariant<>(new HashMap<>());
-        map.data.put("Error", new QVariant<>(data.Error));
+    public Map<String, QVariant<Object>> toVariantMap(@NonNull final ClientInitReject data) {
+        final Map<String, QVariant<Object>> map = new HashMap<>();
+        map.put("Error", new QVariant<>(data.Error));
         return map;
     }
 
diff --git a/app/src/main/java/de/kuschku/libquassel/objects/serializers/ClientInitSerializer.java b/app/src/main/java/de/kuschku/libquassel/objects/serializers/ClientInitSerializer.java
index 2ebab3b0d5f5612a53c5f3a33eeb7282c65dc62b..f8f65b1e721dd8e17eca5354d2b9f5041d3b4483 100644
--- a/app/src/main/java/de/kuschku/libquassel/objects/serializers/ClientInitSerializer.java
+++ b/app/src/main/java/de/kuschku/libquassel/objects/serializers/ClientInitSerializer.java
@@ -47,13 +47,13 @@ public class ClientInitSerializer implements ObjectSerializer<ClientInit> {
 
     @NonNull
     @Override
-    public QVariant<Map<String, QVariant>> toVariantMap(@NonNull final ClientInit data) {
-        final QVariant<Map<String, QVariant>> map = new QVariant<>(new HashMap<>());
-        map.data.put("ClientDate", new QVariant<>(data.ClientDate));
-        map.data.put("UseSsl", new QVariant<>(data.UseSsl));
-        map.data.put("ClientVersion", new QVariant<>(data.ClientVersion));
-        map.data.put("UseCompression", new QVariant<>(data.UseCompression));
-        map.data.put("ProtocolVersion", new QVariant<>(data.ProtocolVersion));
+    public Map<String, QVariant<Object>> toVariantMap(@NonNull final ClientInit data) {
+        final Map<String, QVariant<Object>> map = new HashMap<>();
+        map.put("ClientDate", new QVariant<>(data.ClientDate));
+        map.put("UseSsl", new QVariant<>(data.UseSsl));
+        map.put("ClientVersion", new QVariant<>(data.ClientVersion));
+        map.put("UseCompression", new QVariant<>(data.UseCompression));
+        map.put("ProtocolVersion", new QVariant<>(data.ProtocolVersion));
         return map;
     }
 
diff --git a/app/src/main/java/de/kuschku/libquassel/objects/serializers/ClientLoginAckSerializer.java b/app/src/main/java/de/kuschku/libquassel/objects/serializers/ClientLoginAckSerializer.java
index 64197e7b9234986b8199337b40505c77d915f297..b6b444c3c0cca5940a935e5696973b132d46f111 100644
--- a/app/src/main/java/de/kuschku/libquassel/objects/serializers/ClientLoginAckSerializer.java
+++ b/app/src/main/java/de/kuschku/libquassel/objects/serializers/ClientLoginAckSerializer.java
@@ -46,8 +46,8 @@ public class ClientLoginAckSerializer implements ObjectSerializer<ClientLoginAck
 
     @NonNull
     @Override
-    public QVariant<Map<String, QVariant>> toVariantMap(@NonNull final ClientLoginAck data) {
-        return new QVariant<>(new HashMap<>());
+    public Map<String, QVariant<Object>> toVariantMap(@NonNull final ClientLoginAck data) {
+        return new HashMap<>();
     }
 
     @NonNull
diff --git a/app/src/main/java/de/kuschku/libquassel/objects/serializers/ClientLoginRejectSerializer.java b/app/src/main/java/de/kuschku/libquassel/objects/serializers/ClientLoginRejectSerializer.java
index e4791d5bdf7225df8ad07d1cea75f2a034b5ed0e..856bfe7f1ad4f149f4b1fb314eccdfdb2b679bda 100644
--- a/app/src/main/java/de/kuschku/libquassel/objects/serializers/ClientLoginRejectSerializer.java
+++ b/app/src/main/java/de/kuschku/libquassel/objects/serializers/ClientLoginRejectSerializer.java
@@ -49,11 +49,11 @@ public class ClientLoginRejectSerializer implements ObjectSerializer<ClientLogin
 
     @NonNull
     @Override
-    public QVariant<Map<String, QVariant>> toVariantMap(@NonNull final ClientLoginReject data) {
-        final QVariant<Map<String, QVariant>> map = new QVariant<>(new HashMap<>());
-        assertNotNull(map.data);
+    public Map<String, QVariant<Object>> toVariantMap(@NonNull final ClientLoginReject data) {
+        final Map<String, QVariant<Object>> map = new HashMap<>();
+        assertNotNull(map);
 
-        map.data.put("Error", new QVariant<>(data.Error));
+        map.put("Error", new QVariant<>(data.Error));
         return map;
     }
 
diff --git a/app/src/main/java/de/kuschku/libquassel/objects/serializers/ClientLoginSerializer.java b/app/src/main/java/de/kuschku/libquassel/objects/serializers/ClientLoginSerializer.java
index 57b4f6d9a2b0d21d08ea2a88fcf320be79298a89..1e737af40cd55ff132c6f265ec28fde1d4c3e682 100644
--- a/app/src/main/java/de/kuschku/libquassel/objects/serializers/ClientLoginSerializer.java
+++ b/app/src/main/java/de/kuschku/libquassel/objects/serializers/ClientLoginSerializer.java
@@ -49,12 +49,11 @@ public class ClientLoginSerializer implements ObjectSerializer<ClientLogin> {
 
     @NonNull
     @Override
-    public QVariant<Map<String, QVariant>> toVariantMap(@NonNull final ClientLogin data) {
-        final QVariant<Map<String, QVariant>> map = new QVariant<>(new HashMap<>());
-        assertNotNull(map.data);
+    public Map<String, QVariant<Object>> toVariantMap(@NonNull final ClientLogin data) {
+        final Map<String, QVariant<Object>> map = new HashMap<>();
 
-        map.data.put("User", new QVariant<>(data.User));
-        map.data.put("Password", new QVariant<>(data.Password));
+        map.put("User", new QVariant<>(data.User));
+        map.put("Password", new QVariant<>(data.Password));
         return map;
     }
 
diff --git a/app/src/main/java/de/kuschku/libquassel/objects/serializers/CoreSetupAckSerializer.java b/app/src/main/java/de/kuschku/libquassel/objects/serializers/CoreSetupAckSerializer.java
index ddea9e35f0ba2ef6d3ee5cf1790c93b5176b5b23..bc5ba93937c31522e2d8894318c29bafa401d46a 100644
--- a/app/src/main/java/de/kuschku/libquassel/objects/serializers/CoreSetupAckSerializer.java
+++ b/app/src/main/java/de/kuschku/libquassel/objects/serializers/CoreSetupAckSerializer.java
@@ -46,8 +46,8 @@ public class CoreSetupAckSerializer implements ObjectSerializer<CoreSetupAck> {
 
     @NonNull
     @Override
-    public QVariant<Map<String, QVariant>> toVariantMap(@NonNull final CoreSetupAck data) {
-        return new QVariant<>(new HashMap<>());
+    public Map<String, QVariant<Object>> toVariantMap(@NonNull final CoreSetupAck data) {
+        return new HashMap<>();
     }
 
     @NonNull
diff --git a/app/src/main/java/de/kuschku/libquassel/objects/serializers/CoreSetupDataSerializer.java b/app/src/main/java/de/kuschku/libquassel/objects/serializers/CoreSetupDataSerializer.java
index a9ad0afd3de1892c625e4faddbc1a37e022a07a3..703597f1662b2eb75b821783034844a46266ddd3 100644
--- a/app/src/main/java/de/kuschku/libquassel/objects/serializers/CoreSetupDataSerializer.java
+++ b/app/src/main/java/de/kuschku/libquassel/objects/serializers/CoreSetupDataSerializer.java
@@ -49,11 +49,9 @@ public class CoreSetupDataSerializer implements ObjectSerializer<CoreSetupData>
 
     @NonNull
     @Override
-    public QVariant<Map<String, QVariant>> toVariantMap(@NonNull final CoreSetupData data) {
-        final QVariant<Map<String, QVariant>> map = new QVariant<>(new HashMap<>());
-        assertNotNull(map.data);
-
-        map.data.put("SetupData", SetupDataInitializer.get().toVariantMap(data.SetupData));
+    public Map<String, QVariant<Object>> toVariantMap(@NonNull final CoreSetupData data) {
+        final Map<String, QVariant<Object>> map = new HashMap<>();
+        map.put("SetupData", new QVariant<>(SetupDataInitializer.get().toVariantMap(data.SetupData)));
         return map;
     }
 
diff --git a/app/src/main/java/de/kuschku/libquassel/objects/serializers/CoreSetupRejectSerializer.java b/app/src/main/java/de/kuschku/libquassel/objects/serializers/CoreSetupRejectSerializer.java
index 1818796bf7799a181f42f509199e5de35261ac3b..b03a1f82707712b2ce6aa074e104d187ca19e973 100644
--- a/app/src/main/java/de/kuschku/libquassel/objects/serializers/CoreSetupRejectSerializer.java
+++ b/app/src/main/java/de/kuschku/libquassel/objects/serializers/CoreSetupRejectSerializer.java
@@ -49,11 +49,9 @@ public class CoreSetupRejectSerializer implements ObjectSerializer<CoreSetupReje
 
     @NonNull
     @Override
-    public QVariant<Map<String, QVariant>> toVariantMap(@NonNull final CoreSetupReject data) {
-        final QVariant<Map<String, QVariant>> map = new QVariant<>(new HashMap<>());
-        assertNotNull(map.data);
-
-        map.data.put("Error", new QVariant<>(data.Error));
+    public Map<String, QVariant<Object>> toVariantMap(@NonNull final CoreSetupReject data) {
+        final Map<String, QVariant<Object>> map = new HashMap<>();
+        map.put("Error", new QVariant<>(data.Error));
         return map;
     }
 
diff --git a/app/src/main/java/de/kuschku/libquassel/objects/serializers/NetworkServerSerializer.java b/app/src/main/java/de/kuschku/libquassel/objects/serializers/NetworkServerSerializer.java
index cfeac07c9e87e3bea6026118527b06542fbc6b19..66f622dda62f6e132fcd54302c4e8ecc1bd17f1f 100644
--- a/app/src/main/java/de/kuschku/libquassel/objects/serializers/NetworkServerSerializer.java
+++ b/app/src/main/java/de/kuschku/libquassel/objects/serializers/NetworkServerSerializer.java
@@ -49,21 +49,20 @@ public class NetworkServerSerializer implements ObjectSerializer<NetworkServer>
 
     @NonNull
     @Override
-    public QVariant<Map<String, QVariant>> toVariantMap(@NonNull NetworkServer data) {
-        final QVariant<Map<String, QVariant>> map = new QVariant<>(new HashMap<>());
-        assertNotNull(map.data);
+    public Map<String, QVariant<Object>> toVariantMap(@NonNull NetworkServer data) {
+        final Map<String, QVariant<Object>> map = new HashMap<>();
 
-        map.data.put("UseSSL", new QVariant<>(data.UseSSL));
-        map.data.put("sslVersion", new QVariant<>(data.sslVersion));
-        map.data.put("Host", new QVariant<>(data.Host));
-        map.data.put("Port", new QVariant<>(data.Port));
-        map.data.put("Password", new QVariant<>(data.Password));
-        map.data.put("UseProxy", new QVariant<>(data.UseProxy));
-        map.data.put("ProxyType", new QVariant<>(data.ProxyType));
-        map.data.put("ProxyHost", new QVariant<>(data.ProxyHost));
-        map.data.put("ProxyPort", new QVariant<>(data.ProxyPort));
-        map.data.put("ProxyUser", new QVariant<>(data.ProxyUser));
-        map.data.put("ProxyPass", new QVariant<>(data.ProxyPass));
+        map.put("UseSSL", new QVariant<>(data.UseSSL));
+        map.put("sslVersion", new QVariant<>(data.sslVersion));
+        map.put("Host", new QVariant<>(data.Host));
+        map.put("Port", new QVariant<>(data.Port));
+        map.put("Password", new QVariant<>(data.Password));
+        map.put("UseProxy", new QVariant<>(data.UseProxy));
+        map.put("ProxyType", new QVariant<>(data.ProxyType));
+        map.put("ProxyHost", new QVariant<>(data.ProxyHost));
+        map.put("ProxyPort", new QVariant<>(data.ProxyPort));
+        map.put("ProxyUser", new QVariant<>(data.ProxyUser));
+        map.put("ProxyPass", new QVariant<>(data.ProxyPass));
         return map;
     }
 
diff --git a/app/src/main/java/de/kuschku/libquassel/objects/serializers/ObjectSerializer.java b/app/src/main/java/de/kuschku/libquassel/objects/serializers/ObjectSerializer.java
index e47f77170a6efb6415065c7a7062c253fc17ad04..d2486ebb7f386724d9867695a7b48318f0c724cc 100644
--- a/app/src/main/java/de/kuschku/libquassel/objects/serializers/ObjectSerializer.java
+++ b/app/src/main/java/de/kuschku/libquassel/objects/serializers/ObjectSerializer.java
@@ -31,7 +31,7 @@ import de.kuschku.libquassel.primitives.types.QVariant;
 
 public interface ObjectSerializer<T> {
     @Nullable
-    QVariant<Map<String, QVariant>> toVariantMap(@NonNull T data);
+    Map<String, QVariant<Object>> toVariantMap(@NonNull T data);
 
     @NonNull
     T fromDatastream(@NonNull Map<String, QVariant> map);
diff --git a/app/src/main/java/de/kuschku/libquassel/objects/serializers/SessionInitSerializer.java b/app/src/main/java/de/kuschku/libquassel/objects/serializers/SessionInitSerializer.java
index 757fc8e0bfa467e9d11fec3e31575f54df34b857..d6f2a7469f9616f06d81268e68a98092906bc0c4 100644
--- a/app/src/main/java/de/kuschku/libquassel/objects/serializers/SessionInitSerializer.java
+++ b/app/src/main/java/de/kuschku/libquassel/objects/serializers/SessionInitSerializer.java
@@ -47,9 +47,9 @@ public class SessionInitSerializer implements ObjectSerializer<SessionInit> {
 
     @NonNull
     @Override
-    public QVariant<Map<String, QVariant>> toVariantMap(@NonNull final SessionInit data) {
-        final QVariant<Map<String, QVariant>> map = new QVariant<>(new HashMap<>());
-        map.data.put("SessionState", SessionStateSerializer.get().toVariantMap(data.SessionState));
+    public Map<String, QVariant<Object>> toVariantMap(@NonNull final SessionInit data) {
+        final Map<String, QVariant<Object>> map = new HashMap<>();
+        map.put("SessionState", new QVariant<>(SessionStateSerializer.get().toVariantMap(data.SessionState)));
         return map;
     }
 
diff --git a/app/src/main/java/de/kuschku/libquassel/objects/serializers/SessionStateSerializer.java b/app/src/main/java/de/kuschku/libquassel/objects/serializers/SessionStateSerializer.java
index 68de942a963023b1a17cc9015c245bb5e2cb90b6..060cca0b896e0a5a94da7ba3da13580664cc61c3 100644
--- a/app/src/main/java/de/kuschku/libquassel/objects/serializers/SessionStateSerializer.java
+++ b/app/src/main/java/de/kuschku/libquassel/objects/serializers/SessionStateSerializer.java
@@ -51,7 +51,7 @@ public class SessionStateSerializer implements ObjectSerializer<SessionState> {
 
     @Nullable
     @Override
-    public QVariant<Map<String, QVariant>> toVariantMap(@NonNull final SessionState data) {
+    public Map<String, QVariant<Object>> toVariantMap(@NonNull final SessionState data) {
         return null;
     }
 
diff --git a/app/src/main/java/de/kuschku/libquassel/objects/serializers/SetupDataInitializer.java b/app/src/main/java/de/kuschku/libquassel/objects/serializers/SetupDataInitializer.java
index 15c0c3014e87b5d74bd212f6e778094312c76135..6b9ab09fe45cb4391cc65c76c46e80b6ac1668f8 100644
--- a/app/src/main/java/de/kuschku/libquassel/objects/serializers/SetupDataInitializer.java
+++ b/app/src/main/java/de/kuschku/libquassel/objects/serializers/SetupDataInitializer.java
@@ -49,14 +49,13 @@ public class SetupDataInitializer implements ObjectSerializer<SetupData> {
 
     @NonNull
     @Override
-    public QVariant<Map<String, QVariant>> toVariantMap(@NonNull final SetupData data) {
-        final QVariant<Map<String, QVariant>> map = new QVariant<>(new HashMap<>());
-        assertNotNull(map.data);
+    public Map<String, QVariant<Object>> toVariantMap(@NonNull final SetupData data) {
+        final Map<String, QVariant<Object>> map = new HashMap<>();
 
-        map.data.put("AdminPasswd", new QVariant<>(data.AdminPasswd));
-        map.data.put("AdminUser", new QVariant<>(data.AdminUser));
-        map.data.put("Backend", new QVariant<>(data.Backend));
-        map.data.put("ConnectionProperties", new QVariant<>(data.ConnectionProperties));
+        map.put("AdminPasswd", new QVariant<>(data.AdminPasswd));
+        map.put("AdminUser", new QVariant<>(data.AdminUser));
+        map.put("Backend", new QVariant<>(data.Backend));
+        map.put("ConnectionProperties", new QVariant<>(data.ConnectionProperties));
         return map;
     }
 
diff --git a/app/src/main/java/de/kuschku/libquassel/objects/serializers/StorageBackendSerializer.java b/app/src/main/java/de/kuschku/libquassel/objects/serializers/StorageBackendSerializer.java
index 15fdefbab31bf826b87f9cf1047ef366aabca9d9..5146ef205dcb1efba57218fd7e16c73ac7a79fbb 100644
--- a/app/src/main/java/de/kuschku/libquassel/objects/serializers/StorageBackendSerializer.java
+++ b/app/src/main/java/de/kuschku/libquassel/objects/serializers/StorageBackendSerializer.java
@@ -50,14 +50,13 @@ public class StorageBackendSerializer implements ObjectSerializer<StorageBackend
 
     @NonNull
     @Override
-    public QVariant<Map<String, QVariant>> toVariantMap(@NonNull final StorageBackend data) {
-        final QVariant<Map<String, QVariant>> map = new QVariant<>(new HashMap<>());
-        assertNotNull(map.data);
+    public Map<String, QVariant<Object>> toVariantMap(@NonNull final StorageBackend data) {
+        final Map<String, QVariant<Object>> map = new HashMap<>();
 
-        map.data.put("DisplayName", new QVariant<>(data.DisplayName));
-        map.data.put("SetupDefaults", new QVariant<>(data.SetupDefaults));
-        map.data.put("Description", new QVariant<>(data.Description));
-        map.data.put("SetupKeys", new QVariant<>(data.SetupKeys));
+        map.put("DisplayName", new QVariant<>(data.DisplayName));
+        map.put("SetupDefaults", new QVariant<>(data.SetupDefaults));
+        map.put("Description", new QVariant<>(data.Description));
+        map.put("SetupKeys", new QVariant<>(data.SetupKeys));
         return map;
     }
 
diff --git a/app/src/main/java/de/kuschku/libquassel/objects/serializers/StringObjectMapSerializer.java b/app/src/main/java/de/kuschku/libquassel/objects/serializers/StringObjectMapSerializer.java
index d7e5cb8178e6966fbbae8d9a34df6f19b45061cd..135708e5183a203281fea3cb682feb098fae441b 100644
--- a/app/src/main/java/de/kuschku/libquassel/objects/serializers/StringObjectMapSerializer.java
+++ b/app/src/main/java/de/kuschku/libquassel/objects/serializers/StringObjectMapSerializer.java
@@ -48,12 +48,11 @@ public class StringObjectMapSerializer<T> implements ObjectSerializer<Map<String
 
     @NonNull
     @Override
-    public QVariant<Map<String, QVariant>> toVariantMap(@NonNull Map<String, T> data) {
-        final QVariant<Map<String, QVariant>> map = new QVariant<>(new HashMap<>());
-        assertNotNull(map.data);
+    public Map<String, QVariant<Object>> toVariantMap(@NonNull Map<String, T> data) {
+        final Map<String, QVariant<Object>> map = new HashMap<>();
 
         for (Map.Entry<String, T> entry : data.entrySet()) {
-            map.data.put(entry.getKey(), new QVariant<>(entry.getValue()));
+            map.put(entry.getKey(), new QVariant<>(entry.getValue()));
         }
         return map;
     }
diff --git a/app/src/main/java/de/kuschku/libquassel/objects/types/CoreStatus.java b/app/src/main/java/de/kuschku/libquassel/objects/types/CoreStatus.java
index ab354495f951c25214055e2583938919fe37c089..cb963987613845a859bc1ab6a4c1872a9f6f0f76 100644
--- a/app/src/main/java/de/kuschku/libquassel/objects/types/CoreStatus.java
+++ b/app/src/main/java/de/kuschku/libquassel/objects/types/CoreStatus.java
@@ -21,11 +21,16 @@
 
 package de.kuschku.libquassel.objects.types;
 
+import android.os.Bundle;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
+import android.util.Log;
 
+import java.util.ArrayList;
 import java.util.List;
 
+import de.kuschku.libquassel.primitives.types.QVariant;
+
 public class CoreStatus {
     public final boolean Configured;
     public final boolean LoginEnabled;
@@ -51,4 +56,66 @@ public class CoreStatus {
                 ", StorageBackends=" + StorageBackends +
                 '}';
     }
+
+    public ArrayList<Bundle> getStorageBackendsAsBundle() {
+        if (StorageBackends == null)
+            return null;
+
+        ArrayList<Bundle> backends = new ArrayList<>(StorageBackends.size());
+        for (StorageBackend backend : StorageBackends) {
+            Bundle bundle = new Bundle();
+            bundle.putString("displayName", backend.DisplayName);
+            bundle.putString("description", backend.Description);
+            Bundle defaults = new Bundle();
+            Bundle types = new Bundle();
+            for (String key : backend.SetupKeys) {
+                QVariant value = backend.SetupDefaults.get(key);
+                if (value != null) {
+                    switch (value.type.type) {
+                        case Int:
+                        case UInt: {
+                            defaults.putInt(key, (int) value.data);
+                            types.putString(key, "int");
+                        } break;
+                        case Short:
+                        case UShort: {
+                            defaults.putShort(key, (short) value.data);
+                            types.putString(key, "short");
+                        } break;
+                        case Long:
+                        case ULong: {
+                            defaults.putLong(key, (long) value.data);
+                            types.putString(key, "long");
+                        } break;
+                        case Bool: {
+                            defaults.putBoolean(key, (boolean) value.data);
+                            types.putString(key, "boolean");
+                        } break;
+                        case Double: {
+                            bundle.putDouble(key, (double) value.data);
+                            types.putString(key, "double");
+                        } break;
+                        case Float: {
+                            defaults.putDouble(key, (float) value.data);
+                            types.putString(key, "float");
+                        } break;
+                        case QString: {
+                            defaults.putString(key, (String) value.data);
+                            types.putString(key, "string");
+                        } break;
+                        default: {
+                            Log.w("CoreSetup", "Found configuration element with incompatible type: " + key + " : " + value.type.type);
+                        } break;
+                    }
+                } else {
+                    defaults.putString(key, "");
+                    types.putString(key, "string");
+                }
+            }
+            bundle.putBundle("defaults", defaults);
+            bundle.putBundle("types", types);
+            backends.add(bundle);
+        }
+        return backends;
+    }
 }
diff --git a/app/src/main/java/de/kuschku/libquassel/primitives/serializers/UserTypeSerializer.java b/app/src/main/java/de/kuschku/libquassel/primitives/serializers/UserTypeSerializer.java
index f07130ffadc62ea2b59276aa7b2d74498d02351d..bd7e0d6806b3c1d3ddb530f49febd10a6a676dc3 100644
--- a/app/src/main/java/de/kuschku/libquassel/primitives/serializers/UserTypeSerializer.java
+++ b/app/src/main/java/de/kuschku/libquassel/primitives/serializers/UserTypeSerializer.java
@@ -44,10 +44,10 @@ public class UserTypeSerializer<T> implements PrimitiveSerializer<T> {
 
     @Override
     public void serialize(@NonNull ByteChannel channel, @NonNull T data) throws IOException {
-        QVariant<Map<String, QVariant>> variantMap = objectSerializer.toVariantMap(data);
+        QVariant<Map<String, QVariant<Object>>> variantMap = new QVariant<>(objectSerializer.toVariantMap(data));
         assertNotNull(variantMap);
 
-        VariantSerializer.<Map<String, QVariant>>get().serialize(channel, variantMap);
+        VariantSerializer.<Map<String, QVariant<Object>>>get().serialize(channel, variantMap);
     }
 
     @SuppressWarnings("RedundantCast")
diff --git a/app/src/main/java/de/kuschku/libquassel/primitives/types/BufferInfo.java b/app/src/main/java/de/kuschku/libquassel/primitives/types/BufferInfo.java
index 12ae3b4ff0ee3e6f9fb9ec1f74cc0916824b4199..f29a3421a3e76b95187058f368bbc7b9b6dd9985 100644
--- a/app/src/main/java/de/kuschku/libquassel/primitives/types/BufferInfo.java
+++ b/app/src/main/java/de/kuschku/libquassel/primitives/types/BufferInfo.java
@@ -28,6 +28,8 @@ import com.raizlabs.android.dbflow.annotation.PrimaryKey;
 import com.raizlabs.android.dbflow.annotation.Table;
 import com.raizlabs.android.dbflow.structure.BaseModel;
 
+import java.util.List;
+
 import de.kuschku.libquassel.localtypes.orm.ConnectedDatabase;
 
 @Table(database = ConnectedDatabase.class)
@@ -76,6 +78,8 @@ public class BufferInfo extends BaseModel {
         QUERY(0x04),
         GROUP(0x08);
 
+        public static final int ALL = STATUS.id | CHANNEL.id| QUERY.id | GROUP.id;
+
         public final short id;
 
         Type(short id) {
diff --git a/app/src/main/java/de/kuschku/libquassel/primitives/types/QVariant.java b/app/src/main/java/de/kuschku/libquassel/primitives/types/QVariant.java
index f3128fb5a0f60c768eb4230cefe1da795df926b6..40453d6f79dfaf8f7acc9d4f901f42b1225ad7bf 100644
--- a/app/src/main/java/de/kuschku/libquassel/primitives/types/QVariant.java
+++ b/app/src/main/java/de/kuschku/libquassel/primitives/types/QVariant.java
@@ -24,8 +24,13 @@ package de.kuschku.libquassel.primitives.types;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 
+import java.util.ArrayList;
+import java.util.Set;
+
 import de.kuschku.libquassel.primitives.QMetaType;
 import de.kuschku.libquassel.primitives.QMetaTypeRegistry;
+import de.kuschku.libquassel.syncables.SyncableRegistry;
+import de.kuschku.libquassel.syncables.types.interfaces.QSyncableObject;
 
 public class QVariant<T> {
     @Nullable
@@ -34,8 +39,16 @@ public class QVariant<T> {
     public final QMetaType<T> type;
 
     public QVariant(@NonNull T data) {
-        this.type = QMetaTypeRegistry.getTypeByObject(data);
-        this.data = data;
+        if (data instanceof QSyncableObject) {
+            this.data = (T) SyncableRegistry.toVariantMap((QSyncableObject) data);
+            this.type = QMetaTypeRegistry.getTypeByObject(this.data);
+        } else if (data instanceof Set) {
+            this.data = (T) new ArrayList((Set) data);
+            this.type = QMetaTypeRegistry.getTypeByObject(this.data);
+        } else {
+            this.data = data;
+            this.type = QMetaTypeRegistry.getTypeByObject(this.data);
+        }
     }
 
     public QVariant(@NonNull QMetaType<T> type, @Nullable T data) {
diff --git a/app/src/main/java/de/kuschku/libquassel/protocols/DatastreamPeer.java b/app/src/main/java/de/kuschku/libquassel/protocols/DatastreamPeer.java
index 716699c6cf5b2bcc57ac826723cd63ef389cef7c..8b05a4e3331bf159063f8465f712ad2153b4a565 100644
--- a/app/src/main/java/de/kuschku/libquassel/protocols/DatastreamPeer.java
+++ b/app/src/main/java/de/kuschku/libquassel/protocols/DatastreamPeer.java
@@ -23,10 +23,14 @@ package de.kuschku.libquassel.protocols;
 
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
+import android.util.Log;
 
 import com.google.common.base.Function;
 import com.google.common.collect.Lists;
 
+import org.greenrobot.eventbus.Subscribe;
+import org.greenrobot.eventbus.ThreadMode;
+
 import java.io.ByteArrayOutputStream;
 import java.io.DataOutputStream;
 import java.io.IOException;
@@ -34,6 +38,7 @@ import java.nio.BufferOverflowException;
 import java.nio.BufferUnderflowException;
 import java.nio.ByteBuffer;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -137,6 +142,7 @@ public class DatastreamPeer implements RemotePeer {
         });
     }
 
+    @Subscribe(threadMode = ThreadMode.BACKGROUND)
     public void onEventBackgroundThread(@NonNull SyncFunction func) {
         assertNotNull(connection.getOutputExecutor());
         assertFalse(connection.getOutputExecutor().isShutdown());
@@ -146,6 +152,7 @@ public class DatastreamPeer implements RemotePeer {
         ));
     }
 
+    @Subscribe(threadMode = ThreadMode.BACKGROUND)
     public void onEventBackgroundThread(@NonNull RpcCallFunction func) {
         assertNotNull(connection.getOutputExecutor());
         assertFalse(connection.getOutputExecutor().isShutdown());
@@ -155,6 +162,7 @@ public class DatastreamPeer implements RemotePeer {
         ));
     }
 
+    @Subscribe(threadMode = ThreadMode.BACKGROUND)
     public void onEventBackgroundThread(@NonNull InitRequestFunction func) {
         assertNotNull(connection.getOutputExecutor());
         assertFalse(connection.getOutputExecutor().isShutdown());
@@ -164,6 +172,7 @@ public class DatastreamPeer implements RemotePeer {
         ));
     }
 
+    @Subscribe(threadMode = ThreadMode.BACKGROUND)
     public void onEventBackgroundThread(@NonNull InitDataFunction func) {
         assertNotNull(connection.getOutputExecutor());
         assertFalse(connection.getOutputExecutor().isShutdown());
@@ -173,6 +182,7 @@ public class DatastreamPeer implements RemotePeer {
         ));
     }
 
+    @Subscribe(threadMode = ThreadMode.BACKGROUND)
     public void onEventBackgroundThread(@NonNull Heartbeat func) {
         assertNotNull(connection.getOutputExecutor());
         assertFalse(connection.getOutputExecutor().isShutdown());
@@ -182,6 +192,7 @@ public class DatastreamPeer implements RemotePeer {
         ));
     }
 
+    @Subscribe(threadMode = ThreadMode.BACKGROUND)
     public void onEventBackgroundThread(@NonNull HeartbeatReply func) {
         assertNotNull(connection.getOutputExecutor());
         assertFalse(connection.getOutputExecutor().isShutdown());
@@ -191,6 +202,7 @@ public class DatastreamPeer implements RemotePeer {
         ));
     }
 
+    @Subscribe(threadMode = ThreadMode.BACKGROUND)
     public void onEventBackgroundThread(@NonNull HandshakeFunction func) {
         assertNotNull(connection.getOutputExecutor());
         assertFalse(connection.getOutputExecutor().isShutdown());
@@ -292,8 +304,8 @@ public class DatastreamPeer implements RemotePeer {
                 connection.getChannel().flush();
                 // Close the buffer
                 fakeChannel.close();
-            } catch (IOException e) {
-                e.printStackTrace();
+            } catch (Exception e) {
+                busProvider.sendEvent(new GeneralErrorEvent(e));
             }
         }
     }
diff --git a/app/src/main/java/de/kuschku/libquassel/protocols/LegacyPeer.java b/app/src/main/java/de/kuschku/libquassel/protocols/LegacyPeer.java
index 66bf43d9dbd78c65deb6d6588f689ebb027d46de..29264c056c517a665f2f1f596ff3184dbf7165c1 100644
--- a/app/src/main/java/de/kuschku/libquassel/protocols/LegacyPeer.java
+++ b/app/src/main/java/de/kuschku/libquassel/protocols/LegacyPeer.java
@@ -23,6 +23,9 @@ package de.kuschku.libquassel.protocols;
 
 import android.support.annotation.NonNull;
 
+import org.greenrobot.eventbus.Subscribe;
+import org.greenrobot.eventbus.ThreadMode;
+
 import java.io.ByteArrayOutputStream;
 import java.io.DataOutputStream;
 import java.io.IOException;
@@ -87,6 +90,7 @@ public class LegacyPeer implements RemotePeer {
         this.parseExecutor = Executors.newCachedThreadPool();
     }
 
+    @Subscribe(threadMode = ThreadMode.BACKGROUND)
     public final void onEventBackgroundThread(@NonNull SyncFunction func) {
         assertNotNull(connection.getOutputExecutor());
         final List serialize = UnpackedSyncFunctionSerializer.get().serialize(func);
@@ -95,42 +99,49 @@ public class LegacyPeer implements RemotePeer {
                         serialize)));
     }
 
+    @Subscribe(threadMode = ThreadMode.BACKGROUND)
     public void onEventBackgroundThread(@NonNull RpcCallFunction func) {
         assertNotNull(connection.getOutputExecutor());
         connection.getOutputExecutor().submit(new OutputRunnable<>(VariantSerializer.get(),
                 new QVariant<>(UnpackedRpcCallFunctionSerializer.get().serialize(func))));
     }
 
+    @Subscribe(threadMode = ThreadMode.BACKGROUND)
     public void onEventBackgroundThread(@NonNull InitRequestFunction func) {
         assertNotNull(connection.getOutputExecutor());
         connection.getOutputExecutor().submit(new OutputRunnable<>(VariantSerializer.get(),
                 new QVariant<>(InitRequestFunctionSerializer.get().serialize(func))));
     }
 
+    @Subscribe(threadMode = ThreadMode.BACKGROUND)
     public void onEventBackgroundThread(@NonNull InitDataFunction func) {
         assertNotNull(connection.getOutputExecutor());
         connection.getOutputExecutor().submit(new OutputRunnable<>(VariantSerializer.get(),
                 new QVariant<>(InitDataFunctionSerializer.get().serialize(func))));
     }
 
+    @Subscribe(threadMode = ThreadMode.BACKGROUND)
     public void onEventBackgroundThread(@NonNull Heartbeat func) {
         assertNotNull(connection.getOutputExecutor());
         connection.getOutputExecutor().submit(new OutputRunnable<>(VariantSerializer.get(),
                 new QVariant<>(HeartbeatSerializer.get().serialize(func))));
     }
 
+    @Subscribe(threadMode = ThreadMode.BACKGROUND)
     public void onEventBackgroundThread(@NonNull HeartbeatReply func) {
         assertNotNull(connection.getOutputExecutor());
         connection.getOutputExecutor().submit(new OutputRunnable<>(VariantSerializer.get(),
                 new QVariant<>(HeartbeatReplySerializer.get().serialize(func))));
     }
 
+    @Subscribe(threadMode = ThreadMode.BACKGROUND)
     public void onEventBackgroundThread(@NonNull HandshakeFunction func) {
         assertNotNull(connection.getOutputExecutor());
         connection.getOutputExecutor().submit(new OutputRunnable<>(
                 VariantSerializer.get(), MessageTypeRegistry.toVariantMap(func.data)));
     }
 
+    @Subscribe(threadMode = ThreadMode.BACKGROUND)
     public void processMessage() throws IOException {
         buffer = ByteBuffer.allocate(4);
         connection.getChannel().read(buffer);
diff --git a/app/src/main/java/de/kuschku/libquassel/protocols/RemotePeer.java b/app/src/main/java/de/kuschku/libquassel/protocols/RemotePeer.java
index f1411e65b62309d09548128ee2b1c3384a6c6fde..05329d4c216514e14c188b02b6edbd4526e74d42 100644
--- a/app/src/main/java/de/kuschku/libquassel/protocols/RemotePeer.java
+++ b/app/src/main/java/de/kuschku/libquassel/protocols/RemotePeer.java
@@ -23,6 +23,9 @@ package de.kuschku.libquassel.protocols;
 
 import android.support.annotation.NonNull;
 
+import org.greenrobot.eventbus.Subscribe;
+import org.greenrobot.eventbus.ThreadMode;
+
 import java.io.IOException;
 import java.nio.ByteBuffer;
 
@@ -39,18 +42,25 @@ public interface RemotePeer {
     byte LEGACY = 0x01;
     int PROTOCOL_VERSION_LEGACY = 10;
 
+    @Subscribe(threadMode = ThreadMode.BACKGROUND)
     void onEventBackgroundThread(@NonNull SyncFunction func);
 
+    @Subscribe(threadMode = ThreadMode.BACKGROUND)
     void onEventBackgroundThread(@NonNull RpcCallFunction func);
 
+    @Subscribe(threadMode = ThreadMode.BACKGROUND)
     void onEventBackgroundThread(@NonNull InitRequestFunction func);
 
+    @Subscribe(threadMode = ThreadMode.BACKGROUND)
     void onEventBackgroundThread(@NonNull InitDataFunction func);
 
+    @Subscribe(threadMode = ThreadMode.BACKGROUND)
     void onEventBackgroundThread(@NonNull HandshakeFunction func);
 
+    @Subscribe(threadMode = ThreadMode.BACKGROUND)
     void onEventBackgroundThread(@NonNull Heartbeat func);
 
+    @Subscribe(threadMode = ThreadMode.BACKGROUND)
     void onEventBackgroundThread(@NonNull HeartbeatReply func);
 
     void processMessage() throws IOException;
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/SyncableRegistry.java b/app/src/main/java/de/kuschku/libquassel/syncables/SyncableRegistry.java
index 138d654d65e8152705f72c37011cb26cc065fcf9..a5ba1969320278f12f7c4641ca5ceab9f2130a0b 100644
--- a/app/src/main/java/de/kuschku/libquassel/syncables/SyncableRegistry.java
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/SyncableRegistry.java
@@ -30,6 +30,7 @@ import java.util.Map;
 import de.kuschku.libquassel.exceptions.UnknownTypeException;
 import de.kuschku.libquassel.functions.types.InitDataFunction;
 import de.kuschku.libquassel.objects.serializers.ObjectSerializer;
+import de.kuschku.libquassel.primitives.types.QVariant;
 import de.kuschku.libquassel.syncables.serializers.AliasManagerSerializer;
 import de.kuschku.libquassel.syncables.serializers.BufferSyncerSerializer;
 import de.kuschku.libquassel.syncables.serializers.BufferViewConfigSerializer;
@@ -41,6 +42,7 @@ import de.kuschku.libquassel.syncables.serializers.IrcUserSerializer;
 import de.kuschku.libquassel.syncables.serializers.NetworkConfigSerializer;
 import de.kuschku.libquassel.syncables.serializers.NetworkSerializer;
 import de.kuschku.libquassel.syncables.types.SyncableObject;
+import de.kuschku.libquassel.syncables.types.interfaces.QSyncableObject;
 
 public class SyncableRegistry {
     @NonNull
@@ -66,8 +68,18 @@ public class SyncableRegistry {
     @SuppressWarnings("unchecked")
     @Nullable
     public static SyncableObject from(@NonNull InitDataFunction function) throws UnknownTypeException {
-        ObjectSerializer<? extends SyncableObject> serializer = map.get(function.className);
-        if (serializer == null) throw new UnknownTypeException(function.className, function);
+        String className = function.className;
+        ObjectSerializer<? extends SyncableObject> serializer = map.get(className);
+        if (serializer == null) throw new UnknownTypeException(className, function);
         return serializer.from(function);
     }
+
+    @SuppressWarnings("unchecked")
+    @Nullable
+    public static Map<String, QVariant<Object>> toVariantMap(QSyncableObject data) {
+        String className = data.getClass().getSimpleName();
+        ObjectSerializer<QSyncableObject> serializer = map.get(className);
+        if (serializer == null) throw new UnknownTypeException(className);
+        return serializer.toVariantMap(data);
+    }
 }
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/serializers/AliasManagerSerializer.java b/app/src/main/java/de/kuschku/libquassel/syncables/serializers/AliasManagerSerializer.java
index ce5eccb1182071eef6331899111e85671e8ce7b6..79ebc3f45f2cdb7ff44842ab7b0de276f1beb83c 100644
--- a/app/src/main/java/de/kuschku/libquassel/syncables/serializers/AliasManagerSerializer.java
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/serializers/AliasManagerSerializer.java
@@ -24,6 +24,8 @@ package de.kuschku.libquassel.syncables.serializers;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 
+import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
@@ -33,6 +35,7 @@ import de.kuschku.libquassel.functions.types.UnpackedFunction;
 import de.kuschku.libquassel.objects.serializers.ObjectSerializer;
 import de.kuschku.libquassel.primitives.types.QVariant;
 import de.kuschku.libquassel.syncables.types.impl.AliasManager;
+import de.kuschku.libquassel.syncables.types.interfaces.QAliasManager;
 
 import static de.kuschku.util.AndroidAssert.assertNotNull;
 
@@ -52,8 +55,20 @@ public class AliasManagerSerializer implements ObjectSerializer<AliasManager> {
 
     @Nullable
     @Override
-    public QVariant<Map<String, QVariant>> toVariantMap(@NonNull AliasManager data) {
-        throw new IllegalArgumentException();
+    public Map<String, QVariant<Object>> toVariantMap(@NonNull AliasManager data) {
+        HashMap<String, QVariant<Object>> aliases = new HashMap<>();
+        List<String> names = new ArrayList<>(data.aliases().size());
+        List<String> expansions = new ArrayList<>(data.aliases().size());
+        for (QAliasManager.Alias alias : data.aliases()) {
+            names.add(alias.name);
+            expansions.add(alias.expansion);
+        }
+        aliases.put("names", new QVariant(names));
+        aliases.put("expansions", new QVariant(expansions));
+
+        HashMap<String, QVariant<Object>> map = new HashMap<>();
+        map.put("Aliases", new QVariant(aliases));
+        return map;
     }
 
     @NonNull
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/serializers/BufferSyncerSerializer.java b/app/src/main/java/de/kuschku/libquassel/syncables/serializers/BufferSyncerSerializer.java
index 795ec95a519b0874fd0e7f043d4d178036ef7519..bbe5b3127f6f08ffd03117331ee8f46c033d79ae 100644
--- a/app/src/main/java/de/kuschku/libquassel/syncables/serializers/BufferSyncerSerializer.java
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/serializers/BufferSyncerSerializer.java
@@ -50,7 +50,7 @@ public class BufferSyncerSerializer implements ObjectSerializer<BufferSyncer> {
 
     @Nullable
     @Override
-    public QVariant<Map<String, QVariant>> toVariantMap(@NonNull BufferSyncer data) {
+    public Map<String, QVariant<Object>> toVariantMap(@NonNull BufferSyncer data) {
         // FIXME: IMPLEMENT
         throw new IllegalArgumentException();
     }
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/serializers/BufferViewConfigSerializer.java b/app/src/main/java/de/kuschku/libquassel/syncables/serializers/BufferViewConfigSerializer.java
index fb595c757fba33624b9bef618fa2dec03bbff6f8..58c63c43033b0008b3c6cbe626c2fbbcf18dc8c1 100644
--- a/app/src/main/java/de/kuschku/libquassel/syncables/serializers/BufferViewConfigSerializer.java
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/serializers/BufferViewConfigSerializer.java
@@ -49,20 +49,20 @@ public class BufferViewConfigSerializer implements ObjectSerializer<BufferViewCo
 
     @NonNull
     @Override
-    public QVariant<Map<String, QVariant>> toVariantMap(@NonNull BufferViewConfig data) {
-        final QVariant<Map<String, QVariant>> map = new QVariant<>(new HashMap<>());
-        map.data.put("bufferViewName", new QVariant<>(data.bufferViewName()));
-        map.data.put("TemporarilyRemovedBuffers", new QVariant<>(data.temporarilyRemovedBuffers()));
-        map.data.put("hideInactiveNetworks", new QVariant<>(data.hideInactiveBuffers()));
-        map.data.put("BufferList", new QVariant<>(data.bufferList()));
-        map.data.put("allowedBufferTypes", new QVariant<>(data.allowedBufferTypes()));
-        map.data.put("sortAlphabetically", new QVariant<>(data.sortAlphabetically()));
-        map.data.put("disableDecoration", new QVariant<>(data.disableDecoration()));
-        map.data.put("addNewBuffersAutomatically", new QVariant<>(data.addNewBuffersAutomatically()));
-        map.data.put("networkId", new QVariant<>(data.networkId()));
-        map.data.put("minimumActivity", new QVariant<>(data.minimumActivity()));
-        map.data.put("hideInactiveBuffers", new QVariant<>(data.hideInactiveBuffers()));
-        map.data.put("RemovedBuffers", new QVariant<>(data.removedBuffers()));
+    public Map<String, QVariant<Object>> toVariantMap(@NonNull BufferViewConfig data) {
+        final Map<String, QVariant<Object>> map = new HashMap<>();
+        map.put("bufferViewName", new QVariant<>(data.bufferViewName()));
+        map.put("TemporarilyRemovedBuffers", new QVariant<>(data.temporarilyRemovedBuffers()));
+        map.put("hideInactiveNetworks", new QVariant<>(data.hideInactiveBuffers()));
+        map.put("BufferList", new QVariant<>(data.bufferList()));
+        map.put("allowedBufferTypes", new QVariant<>(data.allowedBufferTypes()));
+        map.put("sortAlphabetically", new QVariant<>(data.sortAlphabetically()));
+        map.put("disableDecoration", new QVariant<>(data.disableDecoration()));
+        map.put("addNewBuffersAutomatically", new QVariant<>(data.addNewBuffersAutomatically()));
+        map.put("networkId", new QVariant<>("NetworkId", data.networkId()));
+        map.put("minimumActivity", new QVariant<>(data.minimumActivity()));
+        map.put("hideInactiveBuffers", new QVariant<>(data.hideInactiveBuffers()));
+        map.put("RemovedBuffers", new QVariant<>(data.removedBuffers()));
         return map;
     }
 
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/serializers/BufferViewManagerSerializer.java b/app/src/main/java/de/kuschku/libquassel/syncables/serializers/BufferViewManagerSerializer.java
index 0df74fa33d8d5909380e7ce085b4ef3345acd340..eb0c6a7866752a0910848a1a0dbdcf1b826319f3 100644
--- a/app/src/main/java/de/kuschku/libquassel/syncables/serializers/BufferViewManagerSerializer.java
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/serializers/BufferViewManagerSerializer.java
@@ -24,6 +24,8 @@ package de.kuschku.libquassel.syncables.serializers;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 
+import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
@@ -33,6 +35,7 @@ import de.kuschku.libquassel.functions.types.UnpackedFunction;
 import de.kuschku.libquassel.objects.serializers.ObjectSerializer;
 import de.kuschku.libquassel.primitives.types.QVariant;
 import de.kuschku.libquassel.syncables.types.impl.BufferViewManager;
+import de.kuschku.libquassel.syncables.types.interfaces.QBufferViewConfig;
 import de.kuschku.libquassel.syncables.types.interfaces.QBufferViewManager;
 
 @SuppressWarnings({"unchecked", "ConstantConditions"})
@@ -50,9 +53,18 @@ public class BufferViewManagerSerializer implements ObjectSerializer<QBufferView
 
     @Nullable
     @Override
-    public QVariant<Map<String, QVariant>> toVariantMap(@NonNull QBufferViewManager data) {
-        // FIXME: IMPLEMENT
-        throw new IllegalArgumentException();
+    public Map<String, QVariant<Object>> toVariantMap(@NonNull QBufferViewManager data) {
+        HashMap<String, QVariant<Object>> map = new HashMap<>();
+        map.put("BufferViewIds", new QVariant(getBufferViewIds(data)));
+        return map;
+    }
+
+    @NonNull
+    private List<Integer> getBufferViewIds(@NonNull QBufferViewManager<?> data) {
+        List<Integer> bufferViewIds = new ArrayList<>(data.bufferViewConfigs().size());
+        for (QBufferViewConfig config : data.bufferViewConfigs())
+        bufferViewIds.add(config.bufferViewId());
+        return bufferViewIds;
     }
 
     @NonNull
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/serializers/IdentitySerializer.java b/app/src/main/java/de/kuschku/libquassel/syncables/serializers/IdentitySerializer.java
index b5d9716d2e8640d0adea9d8b4d9eef503a6fba64..1deebc220d40865443a047982bc97e32a1f6072b 100644
--- a/app/src/main/java/de/kuschku/libquassel/syncables/serializers/IdentitySerializer.java
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/serializers/IdentitySerializer.java
@@ -49,27 +49,27 @@ public class IdentitySerializer implements ObjectSerializer<Identity> {
 
     @NonNull
     @Override
-    public QVariant<Map<String, QVariant>> toVariantMap(@NonNull Identity data) {
-        final QVariant<Map<String, QVariant>> map = new QVariant<>(new HashMap<>());
-        map.data.put("identityName", new QVariant(data.identityName()));
-        map.data.put("nicks", new QVariant(data.nicks()));
-        map.data.put("ident", new QVariant(data.ident()));
-        map.data.put("realName", new QVariant(data.realName()));
-        map.data.put("identityId", new QVariant(data.id()));
-        map.data.put("autoAwayEnabled", new QVariant(data.autoAwayEnabled()));
-        map.data.put("autoAwayReasonEnabled", new QVariant(data.autoAwayReasonEnabled()));
-        map.data.put("autoAwayTime", new QVariant(data.autoAwayTime()));
-        map.data.put("awayNickEnabled", new QVariant(data.awayNickEnabled()));
-        map.data.put("awayReasonEnabled", new QVariant(data.awayReasonEnabled()));
-        map.data.put("detachAwayEnabled", new QVariant(data.detachAwayEnabled()));
-        map.data.put("detachAwayReasonEnabled", new QVariant(data.detachAwayReasonEnabled()));
-        map.data.put("awayReason", new QVariant(data.awayReason()));
-        map.data.put("autoAwayReason", new QVariant(data.autoAwayReason()));
-        map.data.put("detachAwayReason", new QVariant(data.detachAwayReason()));
-        map.data.put("partReason", new QVariant(data.partReason()));
-        map.data.put("quitReason", new QVariant(data.quitReason()));
-        map.data.put("awayNick", new QVariant(data.awayNick()));
-        map.data.put("kickReason", new QVariant(data.kickReason()));
+    public Map<String, QVariant<Object>> toVariantMap(@NonNull Identity data) {
+        final Map<String, QVariant<Object>> map = new HashMap<>();
+        map.put("identityName", new QVariant(data.identityName()));
+        map.put("nicks", new QVariant(data.nicks()));
+        map.put("ident", new QVariant(data.ident()));
+        map.put("realName", new QVariant(data.realName()));
+        map.put("identityId", new QVariant(data.id()));
+        map.put("autoAwayEnabled", new QVariant(data.autoAwayEnabled()));
+        map.put("autoAwayReasonEnabled", new QVariant(data.autoAwayReasonEnabled()));
+        map.put("autoAwayTime", new QVariant(data.autoAwayTime()));
+        map.put("awayNickEnabled", new QVariant(data.awayNickEnabled()));
+        map.put("awayReasonEnabled", new QVariant(data.awayReasonEnabled()));
+        map.put("detachAwayEnabled", new QVariant(data.detachAwayEnabled()));
+        map.put("detachAwayReasonEnabled", new QVariant(data.detachAwayReasonEnabled()));
+        map.put("awayReason", new QVariant(data.awayReason()));
+        map.put("autoAwayReason", new QVariant(data.autoAwayReason()));
+        map.put("detachAwayReason", new QVariant(data.detachAwayReason()));
+        map.put("partReason", new QVariant(data.partReason()));
+        map.put("quitReason", new QVariant(data.quitReason()));
+        map.put("awayNick", new QVariant(data.awayNick()));
+        map.put("kickReason", new QVariant(data.kickReason()));
         return map;
     }
 
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/serializers/IgnoreListManagerSerializer.java b/app/src/main/java/de/kuschku/libquassel/syncables/serializers/IgnoreListManagerSerializer.java
index 97b367e33d536efd89f902c3b0a9e6b15f9962d5..c250b9540e7b9deb8495a55d08a5467008384c88 100644
--- a/app/src/main/java/de/kuschku/libquassel/syncables/serializers/IgnoreListManagerSerializer.java
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/serializers/IgnoreListManagerSerializer.java
@@ -24,6 +24,8 @@ package de.kuschku.libquassel.syncables.serializers;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 
+import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
@@ -33,6 +35,7 @@ import de.kuschku.libquassel.functions.types.UnpackedFunction;
 import de.kuschku.libquassel.objects.serializers.ObjectSerializer;
 import de.kuschku.libquassel.primitives.types.QVariant;
 import de.kuschku.libquassel.syncables.types.impl.IgnoreListManager;
+import de.kuschku.libquassel.syncables.types.interfaces.QIgnoreListManager;
 
 import static de.kuschku.util.AndroidAssert.assertNotNull;
 
@@ -52,9 +55,33 @@ public class IgnoreListManagerSerializer implements ObjectSerializer<IgnoreListM
 
     @Nullable
     @Override
-    public QVariant<Map<String, QVariant>> toVariantMap(@NonNull IgnoreListManager data) {
-        // FIXME: IMPLEMENT
-        throw new IllegalArgumentException();
+    public Map<String, QVariant<Object>> toVariantMap(@NonNull IgnoreListManager data) {
+        HashMap<String, QVariant<Object>> map = new HashMap<>();
+        List<Integer> scope = new ArrayList<>(data.ignoreRules().size());
+        List<Integer> ignoreType = new ArrayList<>(data.ignoreRules().size());
+        List<Boolean> isActive = new ArrayList<>(data.ignoreRules().size());
+        List<String> scopeRule = new ArrayList<>(data.ignoreRules().size());
+        List<Boolean> isRegEx = new ArrayList<>(data.ignoreRules().size());
+        List<Integer> strictness = new ArrayList<>(data.ignoreRules().size());
+        List<String> ignoreRule = new ArrayList<>(data.ignoreRules().size());
+        for (IgnoreListManager.IgnoreListItem item : data.ignoreRules()) {
+            scope.add(item.getScope().value);
+            ignoreType.add(item.getType().value);
+            isActive.add(item.isActive());
+            scopeRule.add(item.getScopeRule());
+            isRegEx.add(item.isRegEx());
+            strictness.add(item.getStrictness().value);
+            ignoreRule.add(item.getIgnoreRule().rule());
+        }
+
+        map.put("scope", new QVariant(scope));
+        map.put("ignoreType", new QVariant(ignoreType));
+        map.put("isActive", new QVariant(isActive));
+        map.put("scopeRule", new QVariant(scopeRule));
+        map.put("isRegEx", new QVariant(isRegEx));
+        map.put("strictness", new QVariant(strictness));
+        map.put("ignoreRule", new QVariant(ignoreRule));
+        return map;
     }
 
     @NonNull
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/serializers/IrcChannelSerializer.java b/app/src/main/java/de/kuschku/libquassel/syncables/serializers/IrcChannelSerializer.java
index 93471798fef60ede24405c6074d778da62d07b02..664358fab6cd577ddd9ec0898c98564d2b0bebc7 100644
--- a/app/src/main/java/de/kuschku/libquassel/syncables/serializers/IrcChannelSerializer.java
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/serializers/IrcChannelSerializer.java
@@ -49,14 +49,14 @@ public class IrcChannelSerializer implements ObjectSerializer<IrcChannel> {
 
     @NonNull
     @Override
-    public QVariant<Map<String, QVariant>> toVariantMap(@NonNull IrcChannel data) {
-        final QVariant<Map<String, QVariant>> map = new QVariant<>(new HashMap<>());
-        map.data.put("name", new QVariant<>(data.name()));
-        map.data.put("topic", new QVariant<>(data.topic()));
-        map.data.put("password", new QVariant<>(data.password()));
-        map.data.put("UserModes", StringObjectMapSerializer.<String>get().toVariantMap(data.userModes()));
-        map.data.put("ChanModes", new QVariant<>(data.chanModes()));
-        map.data.put("encrypted", new QVariant<>(data.encrypted()));
+    public Map<String, QVariant<Object>> toVariantMap(@NonNull IrcChannel data) {
+        final Map<String, QVariant<Object>> map = new HashMap<>();
+        map.put("name", new QVariant(data.name()));
+        map.put("topic", new QVariant<>(data.topic()));
+        map.put("password", new QVariant<>(data.password()));
+        map.put("UserModes", new QVariant<>(StringObjectMapSerializer.<String>get().toVariantMap(data.userModes())));
+        map.put("ChanModes", new QVariant<>(data.chanModes()));
+        map.put("encrypted", new QVariant<>(data.encrypted()));
         return map;
     }
 
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/serializers/IrcUserSerializer.java b/app/src/main/java/de/kuschku/libquassel/syncables/serializers/IrcUserSerializer.java
index 2c0f6b396c83dfbae405b3c5e18304e4be6316da..d7c8c2cdbcbe4ec065e9cd4177927d61ebce80c8 100644
--- a/app/src/main/java/de/kuschku/libquassel/syncables/serializers/IrcUserSerializer.java
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/serializers/IrcUserSerializer.java
@@ -53,27 +53,26 @@ public class IrcUserSerializer implements ObjectSerializer<IrcUser> {
 
     @NonNull
     @Override
-    public QVariant<Map<String, QVariant>> toVariantMap(@NonNull IrcUser data) {
-        final QVariant<Map<String, QVariant>> map = new QVariant<>(new HashMap<>());
-        assertNotNull(map.data);
+    public Map<String, QVariant<Object>> toVariantMap(@NonNull IrcUser data) {
+        final Map<String, QVariant<Object>> map = new HashMap<>();
 
-        map.data.put("server", new QVariant<>(data.server()));
-        map.data.put("ircOperator", new QVariant<>(data.ircOperator()));
-        map.data.put("away", new QVariant<>(data.isAway()));
-        map.data.put("lastAwayMessage", new QVariant<>(data.lastAwayMessage()));
-        map.data.put("idleTime", new QVariant<>(data.idleTime()));
-        map.data.put("whoisServiceReply", new QVariant<>(data.whoisServiceReply()));
-        map.data.put("suserHost", new QVariant<>(data.suserHost()));
-        map.data.put("nick", new QVariant<>(data.nick()));
-        map.data.put("realName", new QVariant<>(data.realName()));
-        map.data.put("account", new QVariant<>(data.account()));
-        map.data.put("awayMessage", new QVariant<>(data.awayMessage()));
-        map.data.put("loginTime", new QVariant<>(data.loginTime()));
-        map.data.put("encrypted", new QVariant<>(data.encrypted()));
-        map.data.put("channels", new QVariant<>(data.channels()));
-        map.data.put("host", new QVariant<>(data.host()));
-        map.data.put("userModes", new QVariant<>(data.userModes()));
-        map.data.put("user", new QVariant<>(data.user()));
+        map.put("server", new QVariant<>(data.server()));
+        map.put("ircOperator", new QVariant<>(data.ircOperator()));
+        map.put("away", new QVariant<>(data.isAway()));
+        map.put("lastAwayMessage", new QVariant<>(data.lastAwayMessage()));
+        map.put("idleTime", new QVariant<>(data.idleTime()));
+        map.put("whoisServiceReply", new QVariant<>(data.whoisServiceReply()));
+        map.put("suserHost", new QVariant<>(data.suserHost()));
+        map.put("nick", new QVariant<>(data.nick()));
+        map.put("realName", new QVariant<>(data.realName()));
+        map.put("account", new QVariant<>(data.account()));
+        map.put("awayMessage", new QVariant<>(data.awayMessage()));
+        map.put("loginTime", new QVariant<>(data.loginTime()));
+        map.put("encrypted", new QVariant<>(data.encrypted()));
+        map.put("channels", new QVariant<>(data.channels()));
+        map.put("host", new QVariant<>(data.host()));
+        map.put("userModes", new QVariant<>(data.userModes()));
+        map.put("user", new QVariant<>(data.user()));
         return map;
     }
 
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/serializers/NetworkConfigSerializer.java b/app/src/main/java/de/kuschku/libquassel/syncables/serializers/NetworkConfigSerializer.java
index 7bd6e1ef24e68441a39f187aa35b88b32d61ed74..ce39ca35ae9aee5f739d485bea9c0f911b22e832 100644
--- a/app/src/main/java/de/kuschku/libquassel/syncables/serializers/NetworkConfigSerializer.java
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/serializers/NetworkConfigSerializer.java
@@ -24,6 +24,7 @@ package de.kuschku.libquassel.syncables.serializers;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 
+import java.util.HashMap;
 import java.util.Map;
 
 import de.kuschku.libquassel.functions.types.PackedFunction;
@@ -49,9 +50,17 @@ public class NetworkConfigSerializer implements ObjectSerializer<QNetworkConfig>
 
     @Nullable
     @Override
-    public QVariant<Map<String, QVariant>> toVariantMap(@NonNull QNetworkConfig data) {
-        // FIXME: IMPLEMENT
-        throw new IllegalArgumentException();
+    public Map<String, QVariant<Object>> toVariantMap(@NonNull QNetworkConfig data) {
+        HashMap<String, QVariant<Object>> map = new HashMap<>();
+        map.put("standardCtcp", new QVariant<>(data.standardCtcp()));
+        map.put("autoWhoEnabled", new QVariant<>(data.autoWhoEnabled()));
+        map.put("autoWhoDelay", new QVariant<>(data.autoWhoDelay()));
+        map.put("autoWhoNickLimit", new QVariant<>(data.autoWhoNickLimit()));
+        map.put("autoWhoInterval", new QVariant<>(data.autoWhoInterval()));
+        map.put("pingTimeoutEnabled", new QVariant<>(data.pingTimeoutEnabled()));
+        map.put("pingInterval", new QVariant<>(data.pingInterval()));
+        map.put("maxPingCount", new QVariant<>(data.maxPingCount()));
+        return map;
     }
 
     @NonNull
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/serializers/NetworkInfoSerializer.java b/app/src/main/java/de/kuschku/libquassel/syncables/serializers/NetworkInfoSerializer.java
index 8a69026cfccd291d123cfd007b5b559ac21335dd..8b17901a6016454c07bb0aef36eda54a0e6eab13 100644
--- a/app/src/main/java/de/kuschku/libquassel/syncables/serializers/NetworkInfoSerializer.java
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/serializers/NetworkInfoSerializer.java
@@ -52,33 +52,33 @@ public class NetworkInfoSerializer implements ObjectSerializer<NetworkInfo> {
 
     @Nullable
     @Override
-    public QVariant<Map<String, QVariant>> toVariantMap(@NonNull NetworkInfo data) {
-        QVariant<Map<String, QVariant>> map = new QVariant<>(new HashMap<>());
-        map.data.put("networkName", new QVariant<>(data.networkName()));
-        map.data.put("identity", new QVariant<>(data.identity()));
+    public Map<String, QVariant<Object>> toVariantMap(@NonNull NetworkInfo data) {
+        Map<String, QVariant<Object>> map = new HashMap<>();
+        map.put("networkName", new QVariant<>(data.networkName()));
+        map.put("identity", new QVariant<>(data.identity()));
 
-        map.data.put("codecForServer", new QVariant<>(data.codecForServer()));
-        map.data.put("codecForEncoding", new QVariant<>(data.codecForEncoding()));
-        map.data.put("codecForDecoding", new QVariant<>(data.codecForDecoding()));
+        map.put("codecForServer", new QVariant<>(data.codecForServer()));
+        map.put("codecForEncoding", new QVariant<>(data.codecForEncoding()));
+        map.put("codecForDecoding", new QVariant<>(data.codecForDecoding()));
 
-        map.data.put("ServerList", new QVariant<>(data.serverList()));
-        map.data.put("useRandomServer", new QVariant<>(data.useRandomServer()));
+        map.put("ServerList", new QVariant<>(data.serverList()));
+        map.put("useRandomServer", new QVariant<>(data.useRandomServer()));
 
-        map.data.put("perform", new QVariant<>(data.perform()));
+        map.put("perform", new QVariant<>(data.perform()));
 
-        map.data.put("useAutoIdentify", new QVariant<>(data.useAutoIdentify()));
-        map.data.put("autoIdentifyService", new QVariant<>(data.autoIdentifyService()));
-        map.data.put("autoIdentifyPassword", new QVariant<>(data.autoIdentifyPassword()));
+        map.put("useAutoIdentify", new QVariant<>(data.useAutoIdentify()));
+        map.put("autoIdentifyService", new QVariant<>(data.autoIdentifyService()));
+        map.put("autoIdentifyPassword", new QVariant<>(data.autoIdentifyPassword()));
 
-        map.data.put("useSasl", new QVariant<>(data.useSasl()));
-        map.data.put("saslAccount", new QVariant<>(data.saslAccount()));
-        map.data.put("saslPassword", new QVariant<>(data.saslPassword()));
+        map.put("useSasl", new QVariant<>(data.useSasl()));
+        map.put("saslAccount", new QVariant<>(data.saslAccount()));
+        map.put("saslPassword", new QVariant<>(data.saslPassword()));
 
-        map.data.put("useAutoReconnect", new QVariant<>(data.useAutoReconnect()));
-        map.data.put("autoReconnectInterval", new QVariant<>(data.autoReconnectInterval()));
-        map.data.put("autoReconnectRetries", new QVariant<>(data.autoReconnectRetries()));
-        map.data.put("unlimitedReconnectRetries", new QVariant<>(data.unlimitedReconnectRetries()));
-        map.data.put("rejoinChannels", new QVariant<>(data.rejoinChannels()));
+        map.put("useAutoReconnect", new QVariant<>(data.useAutoReconnect()));
+        map.put("autoReconnectInterval", new QVariant<>(data.autoReconnectInterval()));
+        map.put("autoReconnectRetries", new QVariant<>(data.autoReconnectRetries()));
+        map.put("unlimitedReconnectRetries", new QVariant<>(data.unlimitedReconnectRetries()));
+        map.put("rejoinChannels", new QVariant<>(data.rejoinChannels()));
         return map;
     }
 
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/serializers/NetworkSerializer.java b/app/src/main/java/de/kuschku/libquassel/syncables/serializers/NetworkSerializer.java
index 0acbfd0ee6a167c2dbe8090d43a3520f1307301d..9eda5e7dd4cf55a15692e74184e0232b60034190 100644
--- a/app/src/main/java/de/kuschku/libquassel/syncables/serializers/NetworkSerializer.java
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/serializers/NetworkSerializer.java
@@ -61,7 +61,7 @@ public class NetworkSerializer implements ObjectSerializer<Network> {
 
     @Nullable
     @Override
-    public QVariant<Map<String, QVariant>> toVariantMap(@NonNull Network data) {
+    public Map<String, QVariant<Object>> toVariantMap(@NonNull Network data) {
         // FIXME: IMPLEMENT
         throw new IllegalArgumentException();
     }
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/abstracts/ABufferViewConfig.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/abstracts/ABufferViewConfig.java
index 7c3bfa6d36397e2bc16568e4ce9f47e13a8309bf..b6dfae13e9750de66ad0370a26a96a06135a85d3 100644
--- a/app/src/main/java/de/kuschku/libquassel/syncables/types/abstracts/ABufferViewConfig.java
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/abstracts/ABufferViewConfig.java
@@ -25,7 +25,7 @@ import de.kuschku.libquassel.primitives.QMetaType;
 import de.kuschku.libquassel.syncables.types.SyncableObject;
 import de.kuschku.libquassel.syncables.types.interfaces.QBufferViewConfig;
 
-public abstract class ABufferViewConfig<T extends ABufferViewConfig<T>> extends SyncableObject<T> implements QBufferViewConfig {
+public abstract class ABufferViewConfig<T extends ABufferViewConfig<T>> extends SyncableObject<T> implements QBufferViewConfig<T> {
     static final String intName = QMetaType.Type.Int.getSerializableName();
 
     @Override
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/abstracts/ABufferViewManager.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/abstracts/ABufferViewManager.java
index bbed86b1e706f0b2435f66707b47d91da3948dae..57f282d288302f9737b86adb0e03f3743e06270c 100644
--- a/app/src/main/java/de/kuschku/libquassel/syncables/types/abstracts/ABufferViewManager.java
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/abstracts/ABufferViewManager.java
@@ -27,53 +27,30 @@ import de.kuschku.libquassel.syncables.types.SyncableObject;
 import de.kuschku.libquassel.syncables.types.interfaces.QBufferViewConfig;
 import de.kuschku.libquassel.syncables.types.interfaces.QBufferViewManager;
 
-public abstract class ABufferViewManager<T extends ABufferViewManager<T>> extends SyncableObject<T> implements QBufferViewManager {
+public abstract class ABufferViewManager<T extends ABufferViewManager<T>> extends SyncableObject<T> implements QBufferViewManager<T> {
     @Override
-    public void addBufferViewConfig(QBufferViewConfig config) {
-        _addBufferViewConfig(config);
-        requestCreateBufferView(config);
-
-    }
-
-    @Override
-    public void addBufferViewConfig(int bufferViewConfigId) {
-        _addBufferViewConfig(bufferViewConfigId);
-        syncVar("addBufferViewConfig", bufferViewConfigId);
-
-    }
-
-    @Override
-    public void newBufferViewConfig(int bufferViewConfigId) {
-        _newBufferViewConfig(bufferViewConfigId);
-        syncVar("newBufferViewConfig", bufferViewConfigId);
-
+    public void createBufferView(QBufferViewConfig bufferView) {
+        //_addBufferViewConfig(bufferView);
+        syncVar("requestCreateBufferView", bufferView);
     }
 
     @Override
-    public void deleteBufferViewConfig(int bufferViewConfigId) {
-        _deleteBufferViewConfig(bufferViewConfigId);
-        requestDeleteBufferView(bufferViewConfigId);
-
+    public void createBufferViews(List<QBufferViewConfig> bufferViews) {
+        //for (QBufferViewConfig config : bufferViews)
+//            _addBufferViewConfig(config);
+        syncVar("requestCreateBufferViews", bufferViews);
     }
 
     @Override
-    public void requestCreateBufferView(QBufferViewConfig bufferView) {
-        _requestCreateBufferView(bufferView);
-        syncVar("requestCreateBufferView", bufferView);
-
-    }
-
-    @Override
-    public void requestDeleteBufferView(int bufferViewId) {
-        _requestDeleteBufferView(bufferViewId);
+    public void deleteBufferView(int bufferViewId) {
+//        _deleteBufferViewConfig(bufferViewId);
         syncVar("requestDeleteBufferView", bufferViewId);
-
     }
 
     @Override
-    public void requestDeleteBufferViews(List<Integer> bufferViews) {
-        _requestDeleteBufferViews(bufferViews);
+    public void deleteBufferViews(List<Integer> bufferViews) {
+//        for (int config : bufferViews)
+//            _deleteBufferViewConfig(config);
         syncVar("requestDeleteBufferViews", bufferViews);
-
     }
 }
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/abstracts/AIgnoreListManager.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/abstracts/AIgnoreListManager.java
index 603385e55fb0c3f6d312844d89931206aa442cb5..a8b519caa6f96c21de283d7e0aa7496993affa91 100644
--- a/app/src/main/java/de/kuschku/libquassel/syncables/types/abstracts/AIgnoreListManager.java
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/abstracts/AIgnoreListManager.java
@@ -23,55 +23,37 @@ package de.kuschku.libquassel.syncables.types.abstracts;
 
 import android.support.annotation.NonNull;
 
+import java.util.Map;
+
 import de.kuschku.libquassel.message.Message;
+import de.kuschku.libquassel.primitives.types.QVariant;
+import de.kuschku.libquassel.syncables.serializers.IgnoreListManagerSerializer;
 import de.kuschku.libquassel.syncables.types.SyncableObject;
+import de.kuschku.libquassel.syncables.types.impl.IgnoreListManager;
 import de.kuschku.libquassel.syncables.types.interfaces.QIgnoreListManager;
 import de.kuschku.libquassel.syncables.types.interfaces.QNetwork;
 
 import static de.kuschku.util.AndroidAssert.assertNotNull;
 
 public abstract class AIgnoreListManager<T extends AIgnoreListManager<T>> extends SyncableObject<T> implements QIgnoreListManager {
-    @Override
-    public void requestRemoveIgnoreListItem(String ignoreRule) {
-        _requestRemoveIgnoreListItem(ignoreRule);
-        syncVar("requestRemoveIgnoreListItem", ignoreRule);
-    }
-
     @Override
     public void removeIgnoreListItem(String ignoreRule) {
         _removeIgnoreListItem(ignoreRule);
-        syncVar("removeIgnoreListItem", ignoreRule);
-    }
-
-    @Override
-    public void requestToggleIgnoreRule(String ignoreRule) {
-        _requestToggleIgnoreRule(ignoreRule);
-        syncVar("requestToggleIgnoreRule", ignoreRule);
+        syncVar("requestRemoveIgnoreListItem", ignoreRule);
     }
 
     @Override
     public void toggleIgnoreRule(String ignoreRule) {
         _toggleIgnoreRule(ignoreRule);
-        syncVar("toggleIgnoreRule", ignoreRule);
+        syncVar("requestToggleIgnoreRule", ignoreRule);
     }
 
     @Override
     public void addIgnoreListItem(int type, String ignoreRule, boolean isRegEx, int strictness, int scope, String scopeRule, boolean isActive) {
         _addIgnoreListItem(type, ignoreRule, isRegEx, strictness, scope, scopeRule, isActive);
-        requestAddIgnoreListItem(type, ignoreRule, isRegEx, strictness, scope, scopeRule, isActive);
-    }
-
-    @Override
-    public void requestAddIgnoreListItem(int type, String ignoreRule, boolean isRegEx, int strictness, int scope, String scopeRule, boolean isActive) {
-        _requestAddIgnoreListItem(type, ignoreRule, isRegEx, strictness, scope, scopeRule, isActive);
         syncVar("requestAddIgnoreListItem", type, ignoreRule, isRegEx, strictness, scope, scopeRule, isActive);
     }
 
-    @Override
-    public void requestAddIgnoreListItem(@NonNull IgnoreType type, String ignoreRule, boolean isRegEx, @NonNull StrictnessType strictness, @NonNull ScopeType scope, String scopeRule, boolean isActive) {
-        requestAddIgnoreListItem(type.value, ignoreRule, isRegEx, strictness.value, scope.value, scopeRule, isActive);
-    }
-
     @Override
     public void addIgnoreListItem(@NonNull IgnoreType type, String ignoreRule, boolean isRegEx, @NonNull StrictnessType strictness, @NonNull ScopeType scope, String scopeRule, boolean isActive) {
         addIgnoreListItem(type.value, ignoreRule, isRegEx, strictness.value, scope.value, scopeRule, isActive);
@@ -82,4 +64,9 @@ public abstract class AIgnoreListManager<T extends AIgnoreListManager<T>> extend
         assertNotNull(network);
         return match(message.content, message.sender, message.type, network.networkName(), message.bufferInfo.name) != StrictnessType.UnmatchedStrictness;
     }
+
+    @Override
+    public void requestUpdate(Map<String, QVariant<Object>> variantMap) {
+        syncVar("requestUpdate", variantMap);
+    }
 }
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/BufferViewConfig.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/BufferViewConfig.java
index f41b5035dcb3ee8b38bcf7545d87e4623cfba7ff..dc96d51a6e8b9fd7d60abadcd5125b4ad05c66e4 100644
--- a/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/BufferViewConfig.java
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/BufferViewConfig.java
@@ -138,7 +138,7 @@ public class BufferViewConfig extends ABufferViewConfig<BufferViewConfig> {
 
     @Override
     public void updateNetworks() {
-        if (this.networkId == 0) {
+        if (this.networkId == 0 || this.networkId == -1) {
             networkList.retainAll(client.networkManager().networks());
             networkList.addAll(client.networkManager().networks());
         } else {
@@ -473,4 +473,12 @@ public class BufferViewConfig extends ABufferViewConfig<BufferViewConfig> {
         this.temporarilyRemovedBuffers.addAll(from.temporarilyRemovedBuffers);
         _update();
     }
+
+    @Override
+    public String toString() {
+        return "BufferViewConfig{" +
+                "bufferViewId=" + bufferViewId +
+                ", bufferViewName='" + bufferViewName + '\'' +
+                '}';
+    }
 }
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/BufferViewManager.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/BufferViewManager.java
index 2ef6d81fc80bae5008c08f8f272dd1c887c41165..e3b93c7d3703102d2ece3a936daeabc2ebf61037 100644
--- a/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/BufferViewManager.java
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/BufferViewManager.java
@@ -22,7 +22,6 @@
 package de.kuschku.libquassel.syncables.types.impl;
 
 import android.support.annotation.NonNull;
-import android.util.Log;
 
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -33,7 +32,6 @@ import java.util.Set;
 
 import de.kuschku.libquassel.BusProvider;
 import de.kuschku.libquassel.client.Client;
-import de.kuschku.libquassel.primitives.types.BufferInfo;
 import de.kuschku.libquassel.primitives.types.QVariant;
 import de.kuschku.libquassel.syncables.types.abstracts.ABufferViewManager;
 import de.kuschku.libquassel.syncables.types.interfaces.QBufferViewConfig;
@@ -59,13 +57,12 @@ public class BufferViewManager extends ABufferViewManager<BufferViewManager> {
         return bufferViewConfigs.get(bufferViewId);
     }
 
-    @Override
     public void _addBufferViewConfig(@NonNull QBufferViewConfig config) {
-        if (bufferViewConfigs.containsValue(config))
-            return;
+        if (!bufferViewConfigs.containsValue(config)) {
 
-        bufferViewConfigs.put(config.bufferViewId(), config);
-        _update();
+            bufferViewConfigs.put(config.bufferViewId(), config);
+            _update();
+        }
     }
 
     @Override
@@ -73,42 +70,23 @@ public class BufferViewManager extends ABufferViewManager<BufferViewManager> {
         if (bufferViewConfigs.containsKey(bufferViewConfigId))
             return;
 
-        _addBufferViewConfig(BufferViewConfig.create(bufferViewConfigId));
+        BufferViewConfig config = BufferViewConfig.create(bufferViewConfigId);
+        _addBufferViewConfig(config);
+        client.requestInitObject("BufferViewConfig", String.valueOf(bufferViewConfigId));
         _update();
     }
 
-    @Override
-    public void _newBufferViewConfig(int bufferViewConfigId) {
-        _addBufferViewConfig(bufferViewConfigId);
-    }
-
     @Override
     public void _deleteBufferViewConfig(int bufferViewConfigId) {
-        if (bufferViewConfigs.containsKey(bufferViewConfigId))
+        if (!bufferViewConfigs.containsKey(bufferViewConfigId))
             return;
 
         bufferViewConfigs.remove(bufferViewConfigId);
         _update();
     }
 
-    @Override
-    public void _requestCreateBufferView(QBufferViewConfig bufferView) {
-        // Do nothing, we’re on the client – the server will receive the sync just as expected
-    }
-
-    @Override
-    public void _requestDeleteBufferView(int bufferViewId) {
-        // Do nothing, we’re on the client – the server will receive the sync just as expected
-    }
-
-    @Override
-    public void _requestDeleteBufferViews(List<Integer> bufferViews) {
-        // Do nothing, we’re on the client – the server will receive the sync just as expected
-    }
-
     @Override
     public void checkForNewBuffers(int bufferId) {
-        Log.w("DEBUG", "Checking if buffer needs to be added somewhere: " + bufferId + ": " + client.bufferManager().buffer(bufferId));
         for (QBufferViewConfig config : bufferViewConfigs()) {
             config.checkAddBuffer(bufferId);
         }
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/IgnoreListManager.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/IgnoreListManager.java
index 5a4bb36fb7f2afd871eecb8281b0d43708b5ed96..42c07da2b44e8861788a7394793f079efeaf460a 100644
--- a/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/IgnoreListManager.java
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/IgnoreListManager.java
@@ -63,11 +63,6 @@ public class IgnoreListManager extends AIgnoreListManager<IgnoreListManager> {
         }
     }
 
-    @Override
-    public void _requestRemoveIgnoreListItem(String ignoreRule) {
-        // Do nothing, we’re on the client – the server will receive the sync just as expected
-    }
-
     @Override
     public void _removeIgnoreListItem(String ignoreRule) {
         ignoreList.remove(indexOf(ignoreRule));
@@ -82,11 +77,6 @@ public class IgnoreListManager extends AIgnoreListManager<IgnoreListManager> {
         return -1;
     }
 
-    @Override
-    public void _requestToggleIgnoreRule(String ignoreRule) {
-        // Do nothing, we’re on the client – the server will receive the sync just as expected
-    }
-
     @Override
     public void _toggleIgnoreRule(String ignoreRule) {
         IgnoreListItem item = ignoreList.get(indexOf(ignoreRule));
@@ -94,11 +84,6 @@ public class IgnoreListManager extends AIgnoreListManager<IgnoreListManager> {
         _update();
     }
 
-    @Override
-    public void _requestAddIgnoreListItem(int type, String ignoreRule, boolean isRegEx, int strictness, int scope, String scopeRule, boolean isActive) {
-        // Do nothing, we’re on the client – the server will receive the sync just as expected
-    }
-
     @Override
     public void _addIgnoreListItem(int type, @NonNull String ignoreRule, boolean isRegEx, int strictness, int scope, @NonNull String scopeRule, boolean isActive) {
         if (contains(ignoreRule))
@@ -167,6 +152,10 @@ public class IgnoreListManager extends AIgnoreListManager<IgnoreListManager> {
         return String.valueOf(ignoreList);
     }
 
+    public List<IgnoreListItem> ignoreRules() {
+        return ignoreList;
+    }
+
     public class IgnoreListItem {
         private final IgnoreType type;
         @NonNull
@@ -176,12 +165,43 @@ public class IgnoreListManager extends AIgnoreListManager<IgnoreListManager> {
         private final ScopeType scope;
         @NonNull
         private final SmartRegEx[] scopeRules;
+        private final String scopeRule;
         private boolean isActive;
 
         public IgnoreListItem(int type, @Nullable String ignoreRule, boolean isRegEx, int strictness, int scope, @Nullable String scopeRule, boolean isActive) {
             this(IgnoreType.of(type), ignoreRule, isRegEx, StrictnessType.of(strictness), ScopeType.of(scope), scopeRule, isActive);
         }
 
+        public IgnoreType getType() {
+            return type;
+        }
+
+        @NonNull
+        public SmartRegEx getIgnoreRule() {
+            return ignoreRule;
+        }
+
+        public boolean isRegEx() {
+            return isRegEx;
+        }
+
+        public StrictnessType getStrictness() {
+            return strictness;
+        }
+
+        public ScopeType getScope() {
+            return scope;
+        }
+
+        @NonNull
+        public String getScopeRule() {
+            return scopeRule;
+        }
+
+        public boolean isActive() {
+            return isActive;
+        }
+
         public IgnoreListItem(IgnoreType type, @Nullable String ignoreRule, boolean isRegEx, StrictnessType strictness, ScopeType scope, @Nullable String scopeRule, boolean isActive) {
             if (scopeRule == null)
                 scopeRule = "";
@@ -196,6 +216,7 @@ public class IgnoreListManager extends AIgnoreListManager<IgnoreListManager> {
             this.isActive = isActive;
 
             String[] scopeRules = scopeRule.split(";");
+            this.scopeRule = scopeRule;
             this.scopeRules = new SmartRegEx[scopeRules.length];
             for (int i = 0; i < scopeRules.length; i++) {
                 this.scopeRules[i] = new SmartRegEx(scopeRules[i].trim(), Pattern.CASE_INSENSITIVE, SmartRegEx.Syntax.WILDCARD);
@@ -239,4 +260,9 @@ public class IgnoreListManager extends AIgnoreListManager<IgnoreListManager> {
                     '}';
         }
     }
+
+    @Override
+    public void requestUpdate() {
+        requestUpdate(IgnoreListManagerSerializer.get().toVariantMap(this));
+    }
 }
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/interfaces/QBufferViewConfig.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/interfaces/QBufferViewConfig.java
index 0dce495a7c9ce765a989a653726e3b6878381564..68df23553ec98f6be9dc25f110582d765d269da2 100644
--- a/app/src/main/java/de/kuschku/libquassel/syncables/types/interfaces/QBufferViewConfig.java
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/interfaces/QBufferViewConfig.java
@@ -29,7 +29,7 @@ import de.kuschku.libquassel.syncables.Synced;
 import de.kuschku.util.observables.lists.ObservableList;
 import de.kuschku.util.observables.lists.ObservableSet;
 
-public interface QBufferViewConfig extends QObservable {
+public interface QBufferViewConfig<T extends QBufferViewConfig> extends QSyncableObject<T> {
 
     int bufferViewId();
 
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/interfaces/QBufferViewManager.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/interfaces/QBufferViewManager.java
index d34328459e94a16c4b2df2436f27567d844ae7cb..17a394ffcf8cb876018c8542f28179661661be36 100644
--- a/app/src/main/java/de/kuschku/libquassel/syncables/types/interfaces/QBufferViewManager.java
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/interfaces/QBufferViewManager.java
@@ -28,50 +28,29 @@ import java.util.List;
 import de.kuschku.libquassel.primitives.types.BufferInfo;
 import de.kuschku.libquassel.syncables.Synced;
 
-public interface QBufferViewManager extends QObservable {
+public interface QBufferViewManager<T extends QBufferViewManager<T>> extends QSyncableObject<T> {
     @NonNull
     List<QBufferViewConfig> bufferViewConfigs();
 
     QBufferViewConfig bufferViewConfig(int bufferViewId);
 
-    @Synced
-    void addBufferViewConfig(QBufferViewConfig config);
-
-    void _addBufferViewConfig(QBufferViewConfig config);
-
-    @Synced
-    void addBufferViewConfig(int bufferViewConfigId);
-
     void _addBufferViewConfig(int bufferViewConfigId);
 
-    @Synced
-    void newBufferViewConfig(int bufferViewConfigId);
-
-    void _newBufferViewConfig(int bufferViewConfigId);
+    void _addBufferViewConfig(final QBufferViewConfig bufferViewConfig);
 
     @Synced
-    void deleteBufferViewConfig(int bufferViewConfigId);
+    void createBufferView(final QBufferViewConfig bufferView);
 
-    void _deleteBufferViewConfig(int bufferViewConfigId);
-
-    //QVariant(QVariantMap, QMap(("BufferList", QVariant(QVariantList, () ) ) ( "RemovedBuffers" ,  QVariant(QVariantList, () ) ) ( "TemporarilyRemovedBuffers" ,  QVariant(QVariantList, () ) ) ( "addNewBuffersAutomatically" ,  QVariant(bool, true) ) ( "allowedBufferTypes" ,  QVariant(int, 15) ) ( "bufferViewName" ,  QVariant(QString, "All Chats") ) ( "disableDecoration" ,  QVariant(bool, false) ) ( "hideInactiveBuffers" ,  QVariant(bool, false) ) ( "hideInactiveNetworks" ,  QVariant(bool, false) ) ( "minimumActivity" ,  QVariant(int, 0) ) ( "networkId" ,  QVariant(NetworkId, ) ) ( "sortAlphabetically" ,  QVariant(bool, true) ) )
     @Synced
-    void requestCreateBufferView(final QBufferViewConfig bufferView);
-
-    void _requestCreateBufferView(final QBufferViewConfig bufferView);
-
-    //@Synced void requestCreateBufferView(final Map<String, QVariant> properties);
-    //@Synced void requestCreateBufferViews(final List<QVariant> properties);
+    void createBufferViews(final List<QBufferViewConfig> bufferViewConfigs);
 
     @Synced
-    void requestDeleteBufferView(int bufferViewId);
-
-    void _requestDeleteBufferView(int bufferViewId);
+    void deleteBufferView(int bufferViewId);
 
     @Synced
-    void requestDeleteBufferViews(final List<Integer> bufferViews);
+    void deleteBufferViews(final List<Integer> bufferViews);
 
-    void _requestDeleteBufferViews(final List<Integer> bufferViews);
+    void _deleteBufferViewConfig(int bufferViewConfigId);
 
     void checkForNewBuffers(int bufferId);
 }
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/interfaces/QIgnoreListManager.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/interfaces/QIgnoreListManager.java
index 48d2b28ba54911a42f23470c35af03f1d624ea7e..77392c55e5f3cc79625d31c62f115999bbb8533b 100644
--- a/app/src/main/java/de/kuschku/libquassel/syncables/types/interfaces/QIgnoreListManager.java
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/interfaces/QIgnoreListManager.java
@@ -23,38 +23,23 @@ package de.kuschku.libquassel.syncables.types.interfaces;
 
 import android.support.annotation.NonNull;
 
+import java.util.Map;
+
 import de.kuschku.libquassel.message.Message;
+import de.kuschku.libquassel.primitives.types.QVariant;
 import de.kuschku.libquassel.syncables.Synced;
 
 public interface QIgnoreListManager extends QObservable {
-    @Synced
-    void requestRemoveIgnoreListItem(final String ignoreRule);
-
-    void _requestRemoveIgnoreListItem(final String ignoreRule);
-
     @Synced
     void removeIgnoreListItem(final String ignoreRule);
 
     void _removeIgnoreListItem(final String ignoreRule);
 
-    @Synced
-    void requestToggleIgnoreRule(final String ignoreRule);
-
-    void _requestToggleIgnoreRule(final String ignoreRule);
-
     @Synced
     void toggleIgnoreRule(final String ignoreRule);
 
     void _toggleIgnoreRule(final String ignoreRule);
 
-    @Synced
-    void requestAddIgnoreListItem(IgnoreType type, final String ignoreRule, boolean isRegEx, StrictnessType strictness, ScopeType scope, final String scopeRule, boolean isActive);
-
-    @Synced
-    void requestAddIgnoreListItem(int type, final String ignoreRule, boolean isRegEx, int strictness, int scope, final String scopeRule, boolean isActive);
-
-    void _requestAddIgnoreListItem(int type, final String ignoreRule, boolean isRegEx, int strictness, int scope, final String scopeRule, boolean isActive);
-
     @Synced
     void addIgnoreListItem(IgnoreType type, final String ignoreRule, boolean isRegEx, StrictnessType strictness, ScopeType scope, final String scopeRule, boolean isActive);
 
@@ -67,6 +52,10 @@ public interface QIgnoreListManager extends QObservable {
 
     boolean matches(Message message, QNetwork network);
 
+    void requestUpdate(Map<String, QVariant<Object>> variantMap);
+
+    void requestUpdate();
+
     enum IgnoreType {
         SenderIgnore(0),
         MessageIgnore(1),
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/service/ClientBackgroundThread.java b/app/src/main/java/de/kuschku/quasseldroid_ng/service/ClientBackgroundThread.java
index aa2b0c6a912c1c79eb3769cd7aa3909345c5b1cb..32c8fa3cf0c84ce4980d82b523a26e977e6e5ca0 100644
--- a/app/src/main/java/de/kuschku/quasseldroid_ng/service/ClientBackgroundThread.java
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/service/ClientBackgroundThread.java
@@ -25,6 +25,7 @@ import android.content.Context;
 import android.support.annotation.NonNull;
 
 import org.acra.ACRA;
+import org.greenrobot.eventbus.Subscribe;
 
 import java.io.IOException;
 import java.net.ConnectException;
@@ -70,7 +71,7 @@ public class ClientBackgroundThread implements Runnable {
                 account.id.toString()
         );
         this.client.connect(account.toAddress());
-        this.client.provider.event.registerSticky(this);
+        this.client.provider.event.register(this);
 
         settings = new Settings(context);
         manager = new AccountManager(context);
@@ -95,6 +96,7 @@ public class ClientBackgroundThread implements Runnable {
         client.disconnect();
     }
 
+    @Subscribe(sticky = true)
     public void onEvent(LoginRequireEvent event) {
         if (!event.failedLast) {
             Account account = manager.account(settings.preferenceLastAccount.get());
@@ -102,6 +104,7 @@ public class ClientBackgroundThread implements Runnable {
         }
     }
 
+    @Subscribe(sticky = true)
     public void onEvent(GeneralErrorEvent event) {
         if (!(event.exception instanceof ConnectException))
             ACRA.getErrorReporter().handleSilentException(event.exception);
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/BufferViewConfigSpinnerAdapter.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/BufferViewConfigSpinnerAdapter.java
index 1a2dad4dee4a1a4dedeba06d46ba1b36b16e2a07..767e1e50d484b909810fc742bb2c28df52134285 100644
--- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/BufferViewConfigSpinnerAdapter.java
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/BufferViewConfigSpinnerAdapter.java
@@ -26,6 +26,7 @@ import android.database.DataSetObserver;
 import android.support.annotation.Nullable;
 import android.support.v7.view.ContextThemeWrapper;
 import android.support.v7.widget.ThemedSpinnerAdapter;
+import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -38,8 +39,9 @@ import de.kuschku.libquassel.syncables.types.interfaces.QBufferViewConfig;
 import de.kuschku.libquassel.syncables.types.interfaces.QBufferViewManager;
 import de.kuschku.quasseldroid_ng.R;
 import de.kuschku.quasseldroid_ng.ui.theme.AppContext;
+import de.kuschku.util.observables.callbacks.GeneralCallback;
 
-public class BufferViewConfigSpinnerAdapter implements ThemedSpinnerAdapter {
+public class BufferViewConfigSpinnerAdapter implements ThemedSpinnerAdapter, GeneralCallback {
     private final AppContext context;
     private final QBufferViewManager bufferViewManager;
     @Nullable
@@ -50,6 +52,7 @@ public class BufferViewConfigSpinnerAdapter implements ThemedSpinnerAdapter {
     public BufferViewConfigSpinnerAdapter(AppContext context, QBufferViewManager bufferViewManager) {
         this.context = context;
         this.bufferViewManager = bufferViewManager;
+        this.bufferViewManager.addObserver(this);
     }
 
     @Nullable
@@ -67,7 +70,8 @@ public class BufferViewConfigSpinnerAdapter implements ThemedSpinnerAdapter {
     public View getDropDownView(int position, View convertView, ViewGroup parent) {
         LayoutInflater inflater = LayoutInflater.from(new ContextThemeWrapper(parent.getContext(), theme));
         TextView view = (TextView) inflater.inflate(R.layout.widget_md_spinner_item, parent, false);
-        view.setText(((QBufferViewConfig) getItem(position)).bufferViewName());
+        QBufferViewConfig config = (QBufferViewConfig) getItem(position);
+        view.setText(config == null ? "" : config.bufferViewName());
         return view;
     }
 
@@ -88,12 +92,19 @@ public class BufferViewConfigSpinnerAdapter implements ThemedSpinnerAdapter {
 
     @Override
     public Object getItem(int position) {
-        return bufferViewManager.bufferViewConfigs().get(position);
+        if (position >= 0 && position < bufferViewManager.bufferViewConfigs().size())
+            return bufferViewManager.bufferViewConfigs().get(position);
+        else
+            return null;
     }
 
     @Override
     public long getItemId(int position) {
-        return ((QBufferViewConfig) getItem(position)).bufferViewId();
+        QBufferViewConfig bufferViewConfig = (QBufferViewConfig) getItem(position);
+        if (bufferViewConfig != null)
+            return bufferViewConfig.bufferViewId();
+        else
+            return -1;
     }
 
     @Override
@@ -105,7 +116,11 @@ public class BufferViewConfigSpinnerAdapter implements ThemedSpinnerAdapter {
     public View getView(int position, View convertView, ViewGroup parent) {
         LayoutInflater inflater = LayoutInflater.from(parent.getContext());
         TextView view = (TextView) inflater.inflate(R.layout.widget_md_spinner_item, parent, false);
-        view.setText(((QBufferViewConfig) getItem(position)).bufferViewName());
+        QBufferViewConfig viewConfig = (QBufferViewConfig) getItem(position);
+        view.setText(viewConfig == null ? "" : viewConfig.bufferViewName());
+        if (viewConfig == null) {
+            Log.d("DEBUG", String.valueOf(bufferViewManager.bufferViewConfigs()));
+        }
         return view;
     }
 
@@ -123,4 +138,11 @@ public class BufferViewConfigSpinnerAdapter implements ThemedSpinnerAdapter {
     public boolean isEmpty() {
         return getCount() == 0;
     }
+
+    @Override
+    public void notifyChanged() {
+        for (DataSetObserver observer : observers) {
+            observer.onChanged();
+        }
+    }
 }
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/ChannelDetailActivity.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/ChannelDetailActivity.java
index f8bb27f59edbd93519f3bd6b6b13a139ecc0cdfb..484c665fd326c14f9751b5e4702f7b63ff4c2a12 100644
--- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/ChannelDetailActivity.java
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/ChannelDetailActivity.java
@@ -32,6 +32,9 @@ import android.view.View;
 import android.widget.LinearLayout;
 import android.widget.TextView;
 
+import org.greenrobot.eventbus.Subscribe;
+import org.greenrobot.eventbus.ThreadMode;
+
 import butterknife.Bind;
 import butterknife.ButterKnife;
 import de.kuschku.libquassel.client.Client;
@@ -148,8 +151,4 @@ public class ChannelDetailActivity extends BoundActivity {
 
         getSupportActionBar().setDisplayHomeAsUpEnabled(true);
     }
-
-    public void onEventMainThread(GeneralErrorEvent event) {
-        Log.e("ChannelDetailActivity", String.valueOf(event));
-    }
 }
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/MainActivity.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/MainActivity.java
index 8fd941a5c7dbffa80ef0a7d2c5cc71068a3ea029..238c12c4076d9521947d0d42d2415eb2203317f7 100644
--- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/MainActivity.java
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/MainActivity.java
@@ -39,7 +39,7 @@ import android.support.v7.widget.LinearLayoutManager;
 import android.support.v7.widget.RecyclerView;
 import android.support.v7.widget.SearchView;
 import android.support.v7.widget.Toolbar;
-import android.view.ActionMode;
+import android.util.Log;
 import android.view.Menu;
 import android.view.MenuItem;
 import android.view.View;
@@ -49,12 +49,15 @@ import android.widget.Toast;
 import com.afollestad.materialdialogs.MaterialDialog;
 import com.jakewharton.rxbinding.support.v7.widget.RxSearchView;
 
-import org.acra.ACRA;
+import org.greenrobot.eventbus.Subscribe;
+import org.greenrobot.eventbus.ThreadMode;
 
-import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.concurrent.TimeUnit;
 
 import butterknife.Bind;
@@ -62,15 +65,24 @@ import butterknife.ButterKnife;
 import de.kuschku.libquassel.client.Client;
 import de.kuschku.libquassel.events.BufferChangeEvent;
 import de.kuschku.libquassel.events.ConnectionChangeEvent;
+import de.kuschku.libquassel.events.CoreSetupRequiredEvent;
 import de.kuschku.libquassel.events.GeneralErrorEvent;
 import de.kuschku.libquassel.events.LoginRequireEvent;
 import de.kuschku.libquassel.events.UnknownCertificateEvent;
+import de.kuschku.libquassel.functions.types.HandshakeFunction;
+import de.kuschku.libquassel.functions.types.SyncFunction;
 import de.kuschku.libquassel.localtypes.BacklogFilter;
 import de.kuschku.libquassel.localtypes.buffers.Buffer;
 import de.kuschku.libquassel.localtypes.buffers.ChannelBuffer;
 import de.kuschku.libquassel.localtypes.buffers.QueryBuffer;
 import de.kuschku.libquassel.message.Message;
+import de.kuschku.libquassel.objects.types.CoreSetupData;
+import de.kuschku.libquassel.objects.types.SetupData;
+import de.kuschku.libquassel.primitives.types.BufferInfo;
+import de.kuschku.libquassel.primitives.types.QVariant;
+import de.kuschku.libquassel.syncables.types.impl.BufferViewConfig;
 import de.kuschku.libquassel.syncables.types.interfaces.QBacklogManager;
+import de.kuschku.libquassel.syncables.types.interfaces.QBufferViewManager;
 import de.kuschku.libquassel.syncables.types.interfaces.QIrcChannel;
 import de.kuschku.libquassel.syncables.types.interfaces.QIrcUser;
 import de.kuschku.quasseldroid_ng.R;
@@ -81,6 +93,7 @@ import de.kuschku.quasseldroid_ng.ui.chat.fragment.ChatFragment;
 import de.kuschku.quasseldroid_ng.ui.chat.fragment.LoadingFragment;
 import de.kuschku.quasseldroid_ng.ui.chat.util.Status;
 import de.kuschku.quasseldroid_ng.ui.settings.SettingsActivity;
+import de.kuschku.quasseldroid_ng.ui.setup.CoreSetupActivity;
 import de.kuschku.util.accounts.Account;
 import de.kuschku.util.accounts.AccountManager;
 import de.kuschku.util.certificates.CertificateUtils;
@@ -91,6 +104,7 @@ import rx.android.schedulers.AndroidSchedulers;
 import static de.kuschku.util.AndroidAssert.assertNotNull;
 
 public class MainActivity extends BoundActivity {
+    public static final int REQUEST_CODE_CORESETUP = 1;
     /**
      * Host layout for content fragment, for example showing a loader or the chat
      */
@@ -158,19 +172,16 @@ public class MainActivity extends BoundActivity {
         chatList.setAdapter(chatListAdapter);
 
         chatListToolbar.inflateMenu(R.menu.chatlist);
-        chatListToolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
-            @Override
-            public boolean onMenuItemClick(MenuItem item) {
-                switch (item.getItemId()) {
-                    case R.id.action_show_all: {
-                        item.setChecked(chatListAdapter.toggleShowAll());
-                    }
-                    break;
-                    case R.id.action_manage_chat_lists: {
-                    }
+        chatListToolbar.setOnMenuItemClickListener(item -> {
+            switch (item.getItemId()) {
+                case R.id.action_show_all: {
+                    item.setChecked(chatListAdapter.toggleShowAll());
+                }
+                break;
+                case R.id.action_manage_chat_lists: {
                 }
-                return false;
             }
+            return false;
         });
 
         DrawerLayout drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
@@ -283,6 +294,7 @@ public class MainActivity extends BoundActivity {
 
     */
 
+    @Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
     public void onEventMainThread(ConnectionChangeEvent event) {
         onConnectionChange(event.status);
     }
@@ -296,10 +308,12 @@ public class MainActivity extends BoundActivity {
         }
     }
 
+    @Subscribe(threadMode = ThreadMode.MAIN)
     public void onEventMainThread(GeneralErrorEvent event) {
         Toast.makeText(getApplication(), event.exception.getClass().getSimpleName() + ": " + event.debugInfo, Toast.LENGTH_LONG).show();
     }
 
+    @Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
     public void onEventMainThread(BufferChangeEvent event) {
         Client client = context.client();
         if (client != null) {
@@ -468,6 +482,33 @@ public class MainActivity extends BoundActivity {
         }
     }
 
+    @Override
+    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+        switch (requestCode) {
+            case REQUEST_CODE_CORESETUP: {
+                if (resultCode == RESULT_OK) {
+                    context.provider().event.removeStickyEvent(CoreSetupRequiredEvent.class);
+
+                    Log.d("DEBUG", "Received result: " + data.getExtras());
+
+                    Account account = manager.account(context.settings().preferenceLastAccount.get());
+                    Bundle config = data.getParcelableExtra("config");
+                    Map<String, QVariant> configData = new HashMap<>();
+                    for (String key : config.keySet()) {
+                        configData.put(key, new QVariant<>(config.get(key)));
+                    }
+                    context.provider().dispatch(new HandshakeFunction(new CoreSetupData(new SetupData(
+                            account.user,
+                            account.pass,
+                            data.getStringExtra("selectedBackend"),
+                            configData
+                    ))));
+                }
+            } break;
+        }
+    }
+
+    @Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
     public void onEventMainThread(@NonNull UnknownCertificateEvent event) {
         new MaterialDialog.Builder(this)
                 .content(context.themeUtil().translations.warningCertificate + "\n" + CertificateUtils.certificateToFingerprint(event.certificate, ""))
@@ -485,6 +526,16 @@ public class MainActivity extends BoundActivity {
                 .show();
     }
 
+    @Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
+    public void onEventMainThread(CoreSetupRequiredEvent event) {
+        Log.d("DEBUG", String.valueOf(context.client().core().StorageBackends));
+
+        Intent intent = new Intent(getApplicationContext(), CoreSetupActivity.class);
+        intent.putExtra("storageBackends", context.client().core().getStorageBackendsAsBundle());
+        startActivityForResult(intent, REQUEST_CODE_CORESETUP);
+    }
+
+    @Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
     public void onEventMainThread(LoginRequireEvent event) {
         if (event.failedLast) {
             new MaterialDialog.Builder(this)
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/drawer/BufferViewConfigAdapter.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/drawer/BufferViewConfigAdapter.java
index 88903608ad0a629f9984ca57b0ee4c25238f1fd2..571af03b82e31abc9bbd07c04cb540836edf4a34 100644
--- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/drawer/BufferViewConfigAdapter.java
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/drawer/BufferViewConfigAdapter.java
@@ -49,7 +49,7 @@ public class BufferViewConfigAdapter extends ExpandableRecyclerAdapter<NetworkVi
     private final ObservableSortedList<NetworkItem> items;
     private final Map<QNetwork, NetworkItem> itemMap = new WeakHashMap<>();
     private final Map<Integer, BufferViewHolder> bufferViewHolderMap = new WeakHashMap<>();
-    private QBufferViewConfig config;
+    private QBufferViewConfig<?> config;
     private WeakReference<RecyclerView> recyclerView = new WeakReference<>(null);
     private int open;
     private OnBufferClickListener bufferClickListener;
@@ -213,21 +213,24 @@ public class BufferViewConfigAdapter extends ExpandableRecyclerAdapter<NetworkVi
     }
 
     public void selectConfig(int id) {
-        QBufferViewConfig newconfig = context.client().bufferViewManager().bufferViewConfig(id);
+        QBufferViewConfig<?> newconfig = context.client().bufferViewManager().bufferViewConfig(id);
         Parcelable state = (newconfig == config) ? saveState() : null;
 
         if (config != null)
             config.networkList().removeCallback(callback);
         config = newconfig;
-        config.updateNetworks();
+        if (config != null)
+            config.updateNetworks();
         items.clear();
         itemMap.clear();
-        for (QNetwork network : config.networkList()) {
-            NetworkItem networkItem = new NetworkItem(context, config, network, this);
-            itemMap.put(network, networkItem);
-            items.add(networkItem);
+        if (config != null) {
+            for (QNetwork network : config.networkList()) {
+                NetworkItem networkItem = new NetworkItem(context, config, network, this);
+                itemMap.put(network, networkItem);
+                items.add(networkItem);
+            }
+            config.networkList().addCallback(callback);
         }
-        config.networkList().addCallback(callback);
 
         loadState(state);
     }
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/drawer/NetworkItem.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/drawer/NetworkItem.java
index 68399e4a859439a497684a01d8de1434965bb2b1..51e479d8806f8d9f4b42ab9ed520c70dcdf6f11b 100644
--- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/drawer/NetworkItem.java
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/drawer/NetworkItem.java
@@ -40,7 +40,7 @@ import de.kuschku.util.observables.lists.ObservableSortedList;
 
 public class NetworkItem implements ParentListItem {
     private final AppContext context;
-    private final QBufferViewConfig config;
+    private final QBufferViewConfig<?> config;
     private final QNetwork network;
     private final BufferViewConfigAdapter bufferViewConfigAdapter;
     private final ObservableSortedList<Buffer> buffers = new ObservableSortedList<>(Buffer.class, new ObservableSortedList.ItemComparator<Buffer>() {
@@ -103,7 +103,7 @@ public class NetworkItem implements ParentListItem {
     };
     private ObservableSet<Integer> backingSet;
 
-    public NetworkItem(AppContext context, QBufferViewConfig config, QNetwork network, BufferViewConfigAdapter bufferViewConfigAdapter) {
+    public NetworkItem(AppContext context, QBufferViewConfig<?> config, QNetwork network, BufferViewConfigAdapter bufferViewConfigAdapter) {
         this.context = context;
         this.config = config;
         this.network = network;
@@ -185,7 +185,7 @@ public class NetworkItem implements ParentListItem {
 
     @Override
     public boolean isInitiallyExpanded() {
-        return network.isConnected();
+        return network != null && network.isConnected();
     }
 
     public QNetwork getNetwork() {
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/drawer/NetworkViewHolder.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/drawer/NetworkViewHolder.java
index 3151de82b9875d15068144aa03657d9cdc5586ce..7283e7c58257b26e6420ee2b94e636fa75b5346b 100644
--- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/drawer/NetworkViewHolder.java
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/drawer/NetworkViewHolder.java
@@ -48,6 +48,6 @@ public class NetworkViewHolder extends ParentViewHolder {
     }
 
     public void bind(AppContext context, NetworkItem item) {
-        name.setText(item.getNetwork().networkName());
+        name.setText(item.getNetwork() == null ? "" : item.getNetwork().networkName());
     }
 }
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/fragment/ChatFragment.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/fragment/ChatFragment.java
index d6e7bf9f3aa76b1a676e70f1f0d100c94823c55d..f18ea1fef984cd8709dce11838b1ddb6717f4d6f 100644
--- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/fragment/ChatFragment.java
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/fragment/ChatFragment.java
@@ -33,6 +33,9 @@ import android.view.ViewGroup;
 
 import com.sothree.slidinguppanel.SlidingUpPanelLayout;
 
+import org.greenrobot.eventbus.Subscribe;
+import org.greenrobot.eventbus.ThreadMode;
+
 import butterknife.Bind;
 import butterknife.ButterKnife;
 import de.kuschku.libquassel.client.Client;
@@ -116,6 +119,7 @@ public class ChatFragment extends BoundFragment {
         return view;
     }
 
+    @Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
     public void onEventMainThread(BufferChangeEvent event) {
         setMarkerline();
 
@@ -144,6 +148,7 @@ public class ChatFragment extends BoundFragment {
         onEventMainThread(new BufferChangeEvent());
     }
 
+    @Subscribe(threadMode = ThreadMode.MAIN)
     public void onEventMainThread(BacklogReceivedEvent event) {
         Client client = context.client();
         if (client != null && client.backlogManager().open() == event.bufferId) {
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/fragment/LoadingFragment.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/fragment/LoadingFragment.java
index 8d106bf601ad7140633e76b0b7a7ff6088e12379..41879e6a1d62363c433c3da843425c897652bab8 100644
--- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/fragment/LoadingFragment.java
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/chat/fragment/LoadingFragment.java
@@ -29,6 +29,9 @@ import android.view.ViewGroup;
 import android.widget.ProgressBar;
 import android.widget.TextView;
 
+import org.greenrobot.eventbus.Subscribe;
+import org.greenrobot.eventbus.ThreadMode;
+
 import java.util.Locale;
 
 import butterknife.Bind;
@@ -66,6 +69,7 @@ public class LoadingFragment extends BoundFragment {
         count.setText(String.format(Locale.US, "%d/%d", position, 5));
     }
 
+    @Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
     public void onEventMainThread(ConnectionChangeEvent event) {
         progressBar.setIndeterminate(true);
 
@@ -73,6 +77,7 @@ public class LoadingFragment extends BoundFragment {
         showProgressState(event.status.ordinal() + 1);
     }
 
+    @Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
     public void onEventMainThread(InitEvent event) {
         if (context.client().connectionStatus() == ConnectionChangeEvent.Status.INITIALIZING_DATA) {
             progressBar.setIndeterminate(false);
@@ -83,6 +88,7 @@ public class LoadingFragment extends BoundFragment {
         }
     }
 
+    @Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
     public void onEventMainThread(BacklogInitEvent event) {
         if (context.client().connectionStatus() == ConnectionChangeEvent.Status.LOADING_BACKLOG) {
             progressBar.setIndeterminate(false);
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/CoreSetupActivity.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/CoreSetupActivity.java
new file mode 100644
index 0000000000000000000000000000000000000000..8bd440dd77f08bbe076f85af05295851eabf349e
--- /dev/null
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/CoreSetupActivity.java
@@ -0,0 +1,171 @@
+/*
+ * QuasselDroid - Quassel client for Android
+ * Copyright (C) 2016 Janne Koschinski
+ * Copyright (C) 2016 Ken Børge Viktil
+ * Copyright (C) 2016 Magnus Fjell
+ * Copyright (C) 2016 Martin Sandsmark <martin.sandsmark@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 3 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package de.kuschku.quasseldroid_ng.ui.setup;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.support.design.widget.FloatingActionButton;
+import android.support.v4.app.FragmentManager;
+import android.support.v4.app.FragmentPagerAdapter;
+import android.support.v4.view.ViewPager;
+import android.support.v7.app.AppCompatActivity;
+import android.view.View;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+import butterknife.Bind;
+import butterknife.ButterKnife;
+import de.kuschku.quasseldroid_ng.R;
+import de.kuschku.quasseldroid_ng.ui.setup.slides.AccountSetupCoreSlide;
+import de.kuschku.quasseldroid_ng.ui.setup.slides.AccountSetupNameSlide;
+import de.kuschku.quasseldroid_ng.ui.setup.slides.AccountSetupUserSlide;
+import de.kuschku.quasseldroid_ng.ui.setup.slides.CoreBackendSelectSlide;
+import de.kuschku.quasseldroid_ng.ui.setup.slides.CoreBackendSetupSlide;
+import de.kuschku.quasseldroid_ng.ui.setup.slides.SlideFragment;
+import de.kuschku.util.accounts.Account;
+import de.kuschku.util.accounts.AccountManager;
+
+public class CoreSetupActivity extends AppCompatActivity implements ValidUpdateCallback {
+
+    @Bind(R.id.view_pager)
+    ViewPager viewPager;
+    @Bind(R.id.btn)
+    FloatingActionButton btn;
+    private SlidePagerAdapter slidePagerAdapter;
+    private int lastValidPage = -1;
+
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        Intent intent = getIntent();
+        if (intent == null) {
+            finish();
+            return;
+        }
+
+        setContentView(R.layout.activity_setup);
+        ButterKnife.bind(this);
+
+        slidePagerAdapter = new SlidePagerAdapter(getSupportFragmentManager());
+        viewPager.setAdapter(slidePagerAdapter);
+
+        CoreBackendSelectSlide backendSelectSlide = new CoreBackendSelectSlide();
+        backendSelectSlide.setArguments(intent.getExtras());
+        CoreBackendSetupSlide backendSetupSlide = new CoreBackendSetupSlide();
+        backendSetupSlide.setArguments(intent.getExtras());
+
+        slidePagerAdapter.addFragment(backendSelectSlide);
+        slidePagerAdapter.addFragment(backendSetupSlide);
+
+        SlideFragment item = slidePagerAdapter.getItem(viewPager.getCurrentItem());
+
+        updateValidity(item.isValid());
+
+        btn.setOnClickListener(v -> {
+            if (viewPager.getCurrentItem() == slidePagerAdapter.getCount() - 1) {
+                onDone();
+            } else {
+                viewPager.setCurrentItem(viewPager.getCurrentItem() + 1, true);
+            }
+        });
+
+        slidePagerAdapter.getItem(viewPager.getCurrentItem()).addChangeListener(CoreSetupActivity.this);
+        viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
+            @Override
+            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
+
+            }
+
+            @Override
+            public void onPageSelected(int position) {
+                SlideFragment slideFragment = slidePagerAdapter.getItem(viewPager.getCurrentItem());
+                Bundle bundle = new Bundle();
+                for (int i = 0; i < slidePagerAdapter.getCount(); i++) {
+                    slidePagerAdapter.getItem(i).removeChangeListener(CoreSetupActivity.this);
+                    slidePagerAdapter.getItem(i).getData(bundle);
+                }
+                slideFragment.addChangeListener(CoreSetupActivity.this);
+                slidePagerAdapter.getItem(position).setData(bundle);
+                updateValidity(slideFragment.isValid());
+                if (viewPager.getCurrentItem() == slidePagerAdapter.list.size() - 1) {
+                    btn.setImageResource(R.drawable.ic_check_dark);
+                } else {
+                    btn.setImageResource(R.drawable.ic_arrow_right_dark);
+                }
+            }
+
+            @Override
+            public void onPageScrollStateChanged(int state) {
+
+            }
+        });
+    }
+
+    private void onDone() {
+        Bundle bundle = new Bundle();
+        for (SlideFragment fragment : slidePagerAdapter.list) {
+            fragment.getData(bundle);
+        }
+
+        Intent result = new Intent();
+        result.putExtras(bundle);
+        setResult(RESULT_OK, result);
+        finish();
+    }
+
+    public void updateValidity(boolean validity) {
+        btn.setVisibility(validity ? View.VISIBLE : View.GONE);
+        if (validity) {
+            lastValidPage = viewPager.getCurrentItem();
+        } else {
+            lastValidPage = viewPager.getCurrentItem() - 1;
+        }
+        slidePagerAdapter.notifyDataSetChanged();
+    }
+
+    private class SlidePagerAdapter extends FragmentPagerAdapter {
+        List<SlideFragment> list = new ArrayList<>();
+
+        public SlidePagerAdapter(FragmentManager fm) {
+            super(fm);
+        }
+
+        @Override
+        public SlideFragment getItem(int position) {
+            return list.get(position);
+        }
+
+        @Override
+        public int getCount() {
+            return Math.min(lastValidPage + 2, list.size());
+        }
+
+        public void addFragment(SlideFragment fragment) {
+            list.add(fragment);
+            notifyDataSetChanged();
+        }
+    }
+}
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/StorageBackendItem.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/StorageBackendItem.java
new file mode 100644
index 0000000000000000000000000000000000000000..2ed84321415b71479419c54de9ca780aebed75ca
--- /dev/null
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/StorageBackendItem.java
@@ -0,0 +1,169 @@
+/*
+ * QuasselDroid - Quassel client for Android
+ * Copyright (C) 2016 Janne Koschinski
+ * Copyright (C) 2016 Ken Børge Viktil
+ * Copyright (C) 2016 Magnus Fjell
+ * Copyright (C) 2016 Martin Sandsmark <martin.sandsmark@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 3 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package de.kuschku.quasseldroid_ng.ui.setup;
+
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.os.Bundle;
+import android.support.annotation.ColorInt;
+import android.support.v7.widget.AppCompatImageButton;
+import android.support.v7.widget.AppCompatRadioButton;
+import android.support.v7.widget.RecyclerView;
+import android.util.Pair;
+import android.view.View;
+import android.widget.TextView;
+
+import com.mikepenz.fastadapter.utils.ViewHolderFactory;
+import com.mikepenz.materialdrawer.model.AbstractDrawerItem;
+import com.mikepenz.materialdrawer.util.DrawerUIUtils;
+
+import de.kuschku.quasseldroid_ng.R;
+import de.kuschku.util.accounts.Account;
+
+public class StorageBackendItem extends AbstractDrawerItem<StorageBackendItem, StorageBackendItem.ViewHolder> {
+    private final String displayName;
+    private final String description;
+    protected Pair<Integer, ColorStateList> colorStateList;
+
+    public StorageBackendItem(String displayName, String description) {
+        this.displayName = displayName;
+        this.description = description;
+    }
+
+    @Override
+    public int getType() {
+        return R.id.item_backend;
+    }
+
+    @Override
+    public int getLayoutRes() {
+        return R.layout.widget_core_backend;
+    }
+
+    @Override
+    public boolean isSelectable() {
+        return true;
+    }
+
+    @Override
+    public void bindView(ViewHolder viewHolder) {
+        Context ctx = viewHolder.itemView.getContext();
+
+        //set the identifier from the drawerItem here. It can be used to run tests
+        viewHolder.itemView.setId(hashCode());
+
+        //set the item selected if it is
+        viewHolder.itemView.setSelected(isSelected());
+
+        //get the correct color for the text
+        int color = getColor(ctx);
+        int selectedTextColor = getSelectedTextColor(ctx);
+
+        viewHolder.name.setText(displayName);
+
+        viewHolder.select.setChecked(isSelected());
+        viewHolder.select.setClickable(false);
+
+        viewHolder.description.setText(description);
+
+        viewHolder.name.setTextColor(getTextColorStateList(color, selectedTextColor));
+
+        viewHolder.description.setTextColor(getTextColorStateList(color, selectedTextColor));
+
+        //for android API 17 --> Padding not applied via xml
+        DrawerUIUtils.setDrawerVerticalPadding(viewHolder.view);
+
+        //call the onPostBindView method to trigger post bind view actions (like the listener to modify the item if required)
+        onPostBindView(this, viewHolder.itemView);
+    }
+
+    @Override
+    public ViewHolderFactory getFactory() {
+        return new ItemFactory();
+    }
+
+    /**
+     * helper method to decide for the correct color
+     *
+     * @param ctx
+     * @return
+     */
+    protected int getColor(Context ctx) {
+        int color;
+        if (this.isEnabled()) {
+            color = com.mikepenz.materialdrawer.R.color.material_drawer_primary_text;
+        } else {
+            color = com.mikepenz.materialdrawer.R.color.material_drawer_hint_text;
+        }
+        return color;
+    }
+
+    /**
+     * helper method to decide for the correct color
+     *
+     * @param ctx
+     * @return
+     */
+    protected int getSelectedTextColor(Context ctx) {
+        return com.mikepenz.materialdrawer.R.color.material_drawer_selected_text;
+    }
+
+    /**
+     * helper to get the ColorStateList for the text and remembering it so we do not have to recreate it all the time
+     *
+     * @param color
+     * @param selectedTextColor
+     * @return
+     */
+    protected ColorStateList getTextColorStateList(@ColorInt int color, @ColorInt int selectedTextColor) {
+        if (colorStateList == null || color + selectedTextColor != colorStateList.first) {
+            colorStateList = new Pair<>(color + selectedTextColor, DrawerUIUtils.getTextColorStateList(color, selectedTextColor));
+        }
+
+        return colorStateList.second;
+    }
+
+    public String getDisplayName() {
+        return displayName;
+    }
+
+    public static class ItemFactory implements ViewHolderFactory<ViewHolder> {
+        public ViewHolder create(View v) {
+            return new ViewHolder(v);
+        }
+    }
+
+    protected static class ViewHolder extends RecyclerView.ViewHolder {
+        private View view;
+        private AppCompatRadioButton select;
+        private TextView name;
+        private TextView description;
+
+        private ViewHolder(View view) {
+            super(view);
+            this.view = view;
+            this.select = (AppCompatRadioButton) view.findViewById(R.id.backend_select);
+            this.name = (TextView) view.findViewById(R.id.backend_name);
+            this.description = (TextView) view.findViewById(R.id.backend_description);
+        }
+    }
+}
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/slides/AccountSetupCoreSlide.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/slides/AccountSetupCoreSlide.java
index 9fa726126bbd3736d91f328e2f67c91ca93a5c6f..fcd92767f4422fb55fb1a5b6e013bfd89b87425b 100644
--- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/slides/AccountSetupCoreSlide.java
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/slides/AccountSetupCoreSlide.java
@@ -24,6 +24,7 @@ package de.kuschku.quasseldroid_ng.ui.setup.slides;
 import android.os.Bundle;
 import android.support.annotation.Nullable;
 import android.support.annotation.StringRes;
+import android.support.design.widget.TextInputEditText;
 import android.support.v7.widget.AppCompatEditText;
 import android.text.Editable;
 import android.text.TextWatcher;
@@ -37,9 +38,9 @@ import de.kuschku.quasseldroid_ng.R;
 
 public class AccountSetupCoreSlide extends SlideFragment {
     @Bind(R.id.host)
-    AppCompatEditText hostField;
+    TextInputEditText hostField;
     @Bind(R.id.port)
-    AppCompatEditText portField;
+    TextInputEditText portField;
     TextWatcher watcher = new TextWatcher() {
         @Override
         public void beforeTextChanged(CharSequence s, int start, int count, int after) {
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/slides/AccountSetupNameSlide.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/slides/AccountSetupNameSlide.java
index c6eaaa34c9d7cd8f6f24ab3c4de9def8e431538b..b51e1d726129d97e4d2afdc386f1f0bc39b1d3fc 100644
--- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/slides/AccountSetupNameSlide.java
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/slides/AccountSetupNameSlide.java
@@ -24,6 +24,7 @@ package de.kuschku.quasseldroid_ng.ui.setup.slides;
 import android.os.Bundle;
 import android.support.annotation.Nullable;
 import android.support.annotation.StringRes;
+import android.support.design.widget.TextInputEditText;
 import android.support.v7.widget.AppCompatEditText;
 import android.text.Editable;
 import android.text.TextWatcher;
@@ -37,7 +38,7 @@ import de.kuschku.quasseldroid_ng.R;
 
 public class AccountSetupNameSlide extends SlideFragment {
     @Bind(R.id.name)
-    AppCompatEditText nameField;
+    TextInputEditText nameField;
     TextWatcher watcher = new TextWatcher() {
         @Override
         public void beforeTextChanged(CharSequence s, int start, int count, int after) {
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/slides/AccountSetupUserSlide.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/slides/AccountSetupUserSlide.java
index d740d9e5d0e4812b2d3f562f866995ccca8b088d..75d90be878022d7d92a155da11594d23de9ea531 100644
--- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/slides/AccountSetupUserSlide.java
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/slides/AccountSetupUserSlide.java
@@ -24,6 +24,7 @@ package de.kuschku.quasseldroid_ng.ui.setup.slides;
 import android.os.Bundle;
 import android.support.annotation.Nullable;
 import android.support.annotation.StringRes;
+import android.support.design.widget.TextInputEditText;
 import android.support.v7.widget.AppCompatEditText;
 import android.text.Editable;
 import android.text.TextWatcher;
@@ -37,9 +38,9 @@ import de.kuschku.quasseldroid_ng.R;
 
 public class AccountSetupUserSlide extends SlideFragment {
     @Bind(R.id.user)
-    AppCompatEditText userField;
+    TextInputEditText userField;
     @Bind(R.id.pass)
-    AppCompatEditText passField;
+    TextInputEditText passField;
     TextWatcher watcher = new TextWatcher() {
         @Override
         public void beforeTextChanged(CharSequence s, int start, int count, int after) {
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/slides/CoreBackendSelectSlide.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/slides/CoreBackendSelectSlide.java
new file mode 100644
index 0000000000000000000000000000000000000000..4f72c3c32d42c61a82414d797ea6e74ec846f938
--- /dev/null
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/slides/CoreBackendSelectSlide.java
@@ -0,0 +1,110 @@
+/*
+ * QuasselDroid - Quassel client for Android
+ * Copyright (C) 2016 Janne Koschinski
+ * Copyright (C) 2016 Ken Børge Viktil
+ * Copyright (C) 2016 Magnus Fjell
+ * Copyright (C) 2016 Martin Sandsmark <martin.sandsmark@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 3 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package de.kuschku.quasseldroid_ng.ui.setup.slides;
+
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.support.v7.widget.DefaultItemAnimator;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.mikepenz.fastadapter.FastAdapter;
+import com.mikepenz.fastadapter.IItem;
+import com.mikepenz.fastadapter.adapters.ItemAdapter;
+import com.mikepenz.materialdrawer.model.PrimaryDrawerItem;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import de.kuschku.quasseldroid_ng.R;
+import de.kuschku.quasseldroid_ng.ui.setup.AccountItem;
+import de.kuschku.quasseldroid_ng.ui.setup.StorageBackendItem;
+import de.kuschku.util.accounts.AccountManager;
+import de.kuschku.util.backports.Optional;
+import de.kuschku.util.backports.Optionals;
+
+public class CoreBackendSelectSlide extends SlideFragment {
+    private FastAdapter<IItem> fastAdapter;
+
+    private List<Bundle> storageBackends;
+    private String selectedBackend;
+
+    @Override
+    public void setArguments(Bundle args) {
+        storageBackends = args.getParcelableArrayList("storageBackends");
+    }
+
+    @Override
+    public Bundle getData(Bundle in) {
+        in.putString("selectedBackend", selectedBackend);
+        return in;
+    }
+
+    @Override
+    public boolean isValid() {
+        return fastAdapter != null && fastAdapter.getSelections().size() == 1;
+    }
+
+    @Override
+    protected View onCreateContent(LayoutInflater inflater, ViewGroup container, @Nullable Bundle savedInstanceState) {
+        RecyclerView recyclerView = (RecyclerView) inflater.inflate(R.layout.slide_select, container, false);
+
+        fastAdapter = new FastAdapter<>();
+        ItemAdapter<IItem> itemAdapter = new ItemAdapter<>();
+        itemAdapter.wrap(fastAdapter);
+        recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
+        recyclerView.setItemAnimator(new DefaultItemAnimator());
+
+        for (Bundle backend : storageBackends) {
+            itemAdapter.add(new StorageBackendItem(backend.getString("displayName"), backend.getString("description")));
+        }
+
+        recyclerView.setAdapter(fastAdapter);
+
+        fastAdapter.withSelectWithItemUpdate(true);
+        fastAdapter.withOnClickListener((v, adapter, item, position) -> {
+            fastAdapter.deselect();
+            fastAdapter.select(position);
+            selectedBackend = ((StorageBackendItem) item).getDisplayName();
+            updateValidity();
+            return false;
+        });
+
+
+        return recyclerView;
+    }
+
+    @Override
+    protected int getTitle() {
+        return R.string.slideAccountselectTitle;
+    }
+
+    @Override
+    protected int getDescription() {
+        return R.string.slideAccountselectDescription;
+    }
+
+}
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/slides/CoreBackendSetupSlide.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/slides/CoreBackendSetupSlide.java
new file mode 100644
index 0000000000000000000000000000000000000000..fd175ece93ff6f8ab4d355c758cbe03836f98a07
--- /dev/null
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/slides/CoreBackendSetupSlide.java
@@ -0,0 +1,408 @@
+/*
+ * QuasselDroid - Quassel client for Android
+ * Copyright (C) 2016 Janne Koschinski
+ * Copyright (C) 2016 Ken Børge Viktil
+ * Copyright (C) 2016 Magnus Fjell
+ * Copyright (C) 2016 Martin Sandsmark <martin.sandsmark@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 3 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package de.kuschku.quasseldroid_ng.ui.setup.slides;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.os.Parcelable;
+import android.support.annotation.Nullable;
+import android.support.annotation.StringRes;
+import android.support.design.widget.TextInputEditText;
+import android.support.design.widget.TextInputLayout;
+import android.support.v7.widget.AppCompatCheckBox;
+import android.support.v7.widget.AppCompatEditText;
+import android.text.Editable;
+import android.text.InputType;
+import android.text.TextWatcher;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.EditText;
+import android.widget.LinearLayout;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+
+import butterknife.Bind;
+import butterknife.ButterKnife;
+import de.kuschku.quasseldroid_ng.R;
+
+public class CoreBackendSetupSlide extends SlideFragment {
+    private Map<String, InputItemWrapper> items = new HashMap<>();
+
+    @Bind(R.id.container)
+    LinearLayout container;
+
+    private Map<String, Bundle> storageBackends = new HashMap<>();
+    Bundle storageBackend;
+
+    TextWatcher watcher = new TextWatcher() {
+        @Override
+        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+        }
+
+        @Override
+        public void onTextChanged(CharSequence s, int start, int before, int count) {
+            updateValidity();
+        }
+
+        @Override
+        public void afterTextChanged(Editable s) {
+        }
+    };
+
+    @Override
+    public void setArguments(Bundle args) {
+        ArrayList<Bundle> storageBackends = args.getParcelableArrayList("storageBackends");
+        if (storageBackends != null) {
+            for (Bundle bundle : storageBackends) {
+                this.storageBackends.put(bundle.getString("displayName"), bundle);
+            }
+        }
+    }
+
+    @Override
+    public void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+    }
+
+    @Override
+    protected View onCreateContent(LayoutInflater inflater, ViewGroup container, @Nullable Bundle savedInstanceState) {
+        View view = inflater.inflate(R.layout.slide_core_setup_backend, container, false);
+        ButterKnife.bind(this, view);
+
+        updateContent();
+
+        return view;
+    }
+
+    private void updateContent() {
+        Log.d("DEBUG", "Backend is: " + storageBackend);
+
+        container.removeAllViews();
+
+        for (InputItemWrapper wrapper : items.values()) {
+            wrapper.onDestroy();
+        }
+        items.clear();
+
+        if (storageBackend == null)
+            return;
+
+        Bundle types = storageBackend.getBundle("types");
+        Bundle defaults = storageBackend.getBundle("defaults");
+
+        if (types == null || defaults == null)
+            return;
+
+        for (String key : types.keySet()) {
+            String type = types.getString(key);
+            Object defValue = defaults.get(key);
+            InputItemWrapper wrapper = getInputItemWrapper(key, type, defValue);
+            items.put(key, wrapper);
+            container.addView(wrapper.getView(container.getContext(), container));
+            Log.d("DEBUG", "Adding config: " + type + " " + key + " = " + defValue + ";");
+        }
+    }
+
+    @Override
+    public void setData(Bundle in) {
+        storageBackend = storageBackends.get(in.getString("selectedBackend"));
+        updateContent();
+        updateValidity();
+    }
+
+    @Override
+    public Bundle getData(Bundle in) {
+        Bundle config = new Bundle();
+        for (InputItemWrapper inputItemWrapper : items.values()) {
+            if (inputItemWrapper.isValid())
+                inputItemWrapper.putValue(config);
+        }
+        in.putBundle("config", config);
+        return in;
+    }
+
+    @Override
+    public boolean isValid() {
+        for (InputItemWrapper inputItemWrapper : items.values()) {
+            if (!inputItemWrapper.isValid())
+                return false;
+        }
+        return true;
+    }
+
+    @Override
+    @StringRes
+    public int getTitle() {
+        return R.string.slideAccountcoreTitle;
+    }
+
+    @Override
+    @StringRes
+    public int getDescription() {
+        return R.string.slideAccountcoreDescription;
+    }
+
+    private interface InputItemWrapper<T> {
+        String key();
+        T getValue();
+        boolean isValid();
+        View getView(Context context, ViewGroup parent);
+        void onDestroy();
+        void putValue(Bundle in);
+    }
+
+    private <T> InputItemWrapper<T> getInputItemWrapper(String key, String type, T defValue) {
+        InputItemWrapper result;
+        switch (type) {
+            case "boolean": {
+                result = new BooleanInputItem(key, (Boolean) defValue);
+            } break;
+            case "short":
+            case "int":
+            case "long":
+            case "float":
+            case "double": {
+                result = new NumberInputItem(key, (Number) defValue, type);
+            } break;
+            default:
+            case "string": {
+                result = new StringInputItem(key, (String) defValue);
+            } break;
+        }
+        return result;
+    }
+
+    class BooleanInputItem implements InputItemWrapper<Boolean> {
+        private final String key;
+        private final Boolean defValue;
+
+        private View view;
+
+        @Bind(R.id.checkBox)
+        AppCompatCheckBox checkBox;
+
+        public BooleanInputItem(String key, Boolean defValue) {
+            this.key = key;
+            this.defValue = defValue;
+        }
+
+        @Override
+        public String key() {
+            return key;
+        }
+
+        @Override
+        public Boolean getValue() {
+            return checkBox.isChecked();
+        }
+
+        @Override
+        public boolean isValid() {
+            return true;
+        }
+
+        @Override
+        public View getView(Context context, ViewGroup parent) {
+            if (view == null) {
+                view = LayoutInflater.from(context).inflate(R.layout.widget_input_boolean, parent, false);
+                ButterKnife.bind(this, view);
+                checkBox.setText(key);
+                if (defValue != null)
+                    checkBox.setChecked(defValue);
+            }
+            return view;
+        }
+
+        @Override
+        public void onDestroy() {
+
+        }
+
+        @Override
+        public void putValue(Bundle in) {
+            in.putBoolean(key, getValue());
+        }
+    }
+
+    class NumberInputItem implements InputItemWrapper<Number> {
+        private final String key;
+        private final Number defValue;
+        private String type;
+
+        private View view;
+
+        @Bind(R.id.inputLayout)
+        TextInputLayout inputLayout;
+
+        @Bind(R.id.editText)
+        TextInputEditText editText;
+
+        public NumberInputItem(String key, Number defValue, String type) {
+            this.key = key;
+            this.defValue = defValue;
+            this.type = type;
+        }
+
+        @Override
+        public String key() {
+            return key;
+        }
+
+        @Override
+        public Number getValue() {
+            String text = editText.getText().toString();
+            try {
+                switch (type) {
+                    case "short":
+                        return Short.parseShort(text);
+                    case "int":
+                        return Integer.parseInt(text);
+                    case "long":
+                        return Long.parseLong(text);
+                    case "float":
+                        return Float.parseFloat(text);
+                    case "double":
+                        return Double.parseDouble(text);
+                    default:
+                        return null;
+                }
+            } catch (NumberFormatException e) {
+                return null;
+            }
+        }
+
+        @Override
+        public boolean isValid() {
+            return getValue() != null;
+        }
+
+        @Override
+        public View getView(Context context, ViewGroup parent) {
+            if (view == null) {
+                view = LayoutInflater.from(context).inflate(R.layout.widget_input_string, parent, false);
+                ButterKnife.bind(this, view);
+                if (defValue != null)
+                    editText.setText(defValue.toString());
+                editText.addTextChangedListener(watcher);
+                switch (type) {
+                    case "short":
+                    case "int":
+                    case "long":
+                        editText.setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_SIGNED);
+                        break;
+                    case "float":
+                    case "double":
+                        editText.setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_SIGNED | InputType.TYPE_NUMBER_FLAG_DECIMAL);
+                        break;
+                }
+                inputLayout.setHint(key);
+            }
+            return view;
+        }
+
+        @Override
+        public void onDestroy() {
+            editText.removeTextChangedListener(watcher);
+        }
+
+        @Override
+        public void putValue(Bundle in) {
+            switch (type) {
+                case "short": {
+                    in.putShort(key, (short) getValue());
+                } break;
+                case "int": {
+                    in.putInt(key, (int) getValue());
+                } break;
+                case "long": {
+                    in.putLong(key, (long) getValue());
+                } break;
+                case "float": {
+                    in.putFloat(key, (float) getValue());
+                } break;
+                case "double": {
+                    in.putDouble(key, (double) getValue());
+                } break;
+            }
+        }
+    }
+
+    class StringInputItem implements InputItemWrapper<String> {
+        private final String key;
+        private final String defValue;
+
+        private View view;
+
+        @Bind(R.id.inputLayout)
+        TextInputLayout inputLayout;
+
+        @Bind(R.id.editText)
+        TextInputEditText editText;
+
+        public StringInputItem(String key, String defValue) {
+            this.key = key;
+            this.defValue = defValue;
+        }
+
+        @Override
+        public String key() {
+            return key;
+        }
+
+        @Override
+        public String getValue() {
+            return editText.getText().toString();
+        }
+
+        @Override
+        public boolean isValid() {
+            return !editText.getText().toString().isEmpty();
+        }
+
+        @Override
+        public View getView(Context context, ViewGroup parent) {
+            if (view == null) {
+                view = LayoutInflater.from(context).inflate(R.layout.widget_input_string, parent, false);
+                ButterKnife.bind(this, view);
+                if (defValue != null)
+                    editText.setText(defValue);
+                editText.addTextChangedListener(watcher);
+                inputLayout.setHint(key);
+            }
+            return view;
+        }
+
+        @Override
+        public void onDestroy() {
+            editText.removeTextChangedListener(watcher);
+        }
+
+        @Override
+        public void putValue(Bundle in) {
+            in.putString(key, getValue());
+        }
+    }
+}
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/slides/SlideFragment.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/slides/SlideFragment.java
index e37960ce73554e58ec572cb28ed3ca56712433a7..62d1bd3f24e09f12891ea8041c784ec087eda95d 100644
--- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/slides/SlideFragment.java
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/setup/slides/SlideFragment.java
@@ -82,4 +82,8 @@ public abstract class SlideFragment extends Fragment {
 
     @StringRes
     protected abstract int getDescription();
+
+    public void setData(Bundle in) {
+
+    }
 }
diff --git a/app/src/main/java/de/kuschku/util/servicebound/BoundActivity.java b/app/src/main/java/de/kuschku/util/servicebound/BoundActivity.java
index 3729fca0994ff41dccd56afa7f1e646350c8772a..16d191919826620cbc8e4527be23738be31f9ef7 100644
--- a/app/src/main/java/de/kuschku/util/servicebound/BoundActivity.java
+++ b/app/src/main/java/de/kuschku/util/servicebound/BoundActivity.java
@@ -104,7 +104,7 @@ public abstract class BoundActivity extends AppCompatActivity {
         if (oldProvider != null)
             oldProvider.event.unregister(this);
         if (provider != null)
-            provider.event.registerSticky(this);
+            provider.event.register(this);
         context.withProvider(provider);
     }
 
diff --git a/app/src/main/java/de/kuschku/util/servicebound/BoundFragment.java b/app/src/main/java/de/kuschku/util/servicebound/BoundFragment.java
index 006e052403ff140b7cc339a6eb062f0055846b33..59b298f7eec04f2e6a8469b490a8dd5eaa3b1e52 100644
--- a/app/src/main/java/de/kuschku/util/servicebound/BoundFragment.java
+++ b/app/src/main/java/de/kuschku/util/servicebound/BoundFragment.java
@@ -94,7 +94,7 @@ public abstract class BoundFragment extends Fragment {
         if (oldProvider != null)
             oldProvider.event.unregister(this);
         if (provider != null)
-            provider.event.registerSticky(this);
+            provider.event.register(this);
         context.withProvider(provider);
     }
 
diff --git a/app/src/main/res/layout/slide_account_core.xml b/app/src/main/res/layout/slide_account_core.xml
index 6783884843514080e572060b52b1a444c1ef7955..7918dd1e2677cfacc8317fb0426cdf1709e23371 100644
--- a/app/src/main/res/layout/slide_account_core.xml
+++ b/app/src/main/res/layout/slide_account_core.xml
@@ -31,7 +31,7 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:hint="@string/labelHostname">
-        <android.support.v7.widget.AppCompatEditText
+        <android.support.design.widget.TextInputEditText
             android:id="@+id/host"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
@@ -42,7 +42,7 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:hint="@string/labelPort">
-        <android.support.v7.widget.AppCompatEditText
+        <android.support.design.widget.TextInputEditText
             android:id="@+id/port"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
diff --git a/app/src/main/res/layout/slide_account_name.xml b/app/src/main/res/layout/slide_account_name.xml
index 49c8e4a5a240026ab637badd2cbab6be293413a9..5fcd81ce6b34f2499a0d236b5a8674d36ee91409 100644
--- a/app/src/main/res/layout/slide_account_name.xml
+++ b/app/src/main/res/layout/slide_account_name.xml
@@ -31,7 +31,7 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:hint="Account Name">
-        <android.support.v7.widget.AppCompatEditText
+        <android.support.design.widget.TextInputEditText
             android:id="@+id/name"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
diff --git a/app/src/main/res/layout/slide_account_user.xml b/app/src/main/res/layout/slide_account_user.xml
index 88a9fcba80ed8ab193858c05626a089b8542ec54..add3a0edd7c824e7ad9557a26b75ceff4679afdc 100644
--- a/app/src/main/res/layout/slide_account_user.xml
+++ b/app/src/main/res/layout/slide_account_user.xml
@@ -31,7 +31,7 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:hint="Username">
-        <android.support.v7.widget.AppCompatEditText
+        <android.support.design.widget.TextInputEditText
             android:id="@+id/user"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
@@ -42,7 +42,7 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:hint="Password">
-        <android.support.v7.widget.AppCompatEditText
+        <android.support.design.widget.TextInputEditText
             android:id="@+id/pass"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
diff --git a/app/src/main/res/layout/slide_core_select_backend.xml b/app/src/main/res/layout/slide_core_select_backend.xml
new file mode 100644
index 0000000000000000000000000000000000000000..6e39a33fa66c7181f4e6c19cd9594e4c77033204
--- /dev/null
+++ b/app/src/main/res/layout/slide_core_select_backend.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ QuasselDroid - Quassel client for Android
+  ~ Copyright (C) 2016 Janne Koschinski
+  ~ Copyright (C) 2016 Ken Børge Viktil
+  ~ Copyright (C) 2016 Magnus Fjell
+  ~ Copyright (C) 2016 Martin Sandsmark <martin.sandsmark@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 3 of the License, or (at your option)
+  ~ any later version.
+  ~
+  ~ This program is distributed in the hope that it will be useful,
+  ~ but WITHOUT ANY WARRANTY; without even the implied warranty of
+  ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  ~ GNU General Public License for more details.
+  ~
+  ~ You should have received a copy of the GNU General Public License along
+  ~ with this program.  If not, see <http://www.gnu.org/licenses/>.
+  -->
+
+<android.support.v7.widget.RecyclerView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="400dp" />
\ No newline at end of file
diff --git a/app/src/main/res/layout/slide_core_setup_backend.xml b/app/src/main/res/layout/slide_core_setup_backend.xml
new file mode 100644
index 0000000000000000000000000000000000000000..d58df4afafc983d923a60827647a96668b30babd
--- /dev/null
+++ b/app/src/main/res/layout/slide_core_setup_backend.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ QuasselDroid - Quassel client for Android
+  ~ Copyright (C) 2016 Janne Koschinski
+  ~ Copyright (C) 2016 Ken Børge Viktil
+  ~ Copyright (C) 2016 Magnus Fjell
+  ~ Copyright (C) 2016 Martin Sandsmark <martin.sandsmark@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 3 of the License, or (at your option)
+  ~ any later version.
+  ~
+  ~ This program is distributed in the hope that it will be useful,
+  ~ but WITHOUT ANY WARRANTY; without even the implied warranty of
+  ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  ~ GNU General Public License for more details.
+  ~
+  ~ You should have received a copy of the GNU General Public License along
+  ~ with this program.  If not, see <http://www.gnu.org/licenses/>.
+  -->
+
+<ScrollView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="400dp"
+    android:padding="32dp">
+    <LinearLayout
+        android:id="@+id/container"
+        android:orientation="vertical"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content" />
+</ScrollView>
\ No newline at end of file
diff --git a/app/src/main/res/layout/widget_core_backend.xml b/app/src/main/res/layout/widget_core_backend.xml
new file mode 100644
index 0000000000000000000000000000000000000000..97b2fe08f02f563b83dbc0280b520b44bb05bb24
--- /dev/null
+++ b/app/src/main/res/layout/widget_core_backend.xml
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ QuasselDroid - Quassel client for Android
+  ~ Copyright (C) 2016 Janne Koschinski
+  ~ Copyright (C) 2016 Ken Børge Viktil
+  ~ Copyright (C) 2016 Magnus Fjell
+  ~ Copyright (C) 2016 Martin Sandsmark <martin.sandsmark@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 3 of the License, or (at your option)
+  ~ any later version.
+  ~
+  ~ This program is distributed in the hope that it will be useful,
+  ~ but WITHOUT ANY WARRANTY; without even the implied warranty of
+  ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  ~ GNU General Public License for more details.
+  ~
+  ~ You should have received a copy of the GNU General Public License along
+  ~ with this program.  If not, see <http://www.gnu.org/licenses/>.
+  -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:background="?attr/selectableItemBackground"
+    android:clickable="true"
+    android:orientation="horizontal">
+
+    <android.support.v7.widget.AppCompatRadioButton
+        android:id="@+id/backend_select"
+        android:layout_width="@dimen/material_drawer_item_profile_icon_width"
+        android:layout_height="@dimen/material_drawer_item_profile_icon_width"
+        android:layout_gravity="top"
+        android:layout_marginTop="12dp"
+        android:layout_marginBottom="12dp"
+        android:background="@android:color/transparent" />
+
+    <LinearLayout
+        android:layout_width="0dip"
+        android:layout_height="wrap_content"
+        android:layout_margin="@dimen/material_drawer_item_profile_icon_padding_right"
+        android:layout_weight="1"
+        android:minHeight="56dp"
+        android:gravity="center_vertical|start"
+        android:orientation="vertical">
+
+        <TextView
+            android:id="@+id/backend_name"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:fontFamily="sans-serif-medium"
+            android:gravity="center_vertical|start"
+            android:lines="1"
+            android:singleLine="true"
+            android:textSize="@dimen/material_drawer_item_profile_text" />
+
+        <TextView
+            android:id="@+id/backend_description"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:fontFamily="sans-serif"
+            android:gravity="center_vertical|start"
+            android:textSize="@dimen/material_drawer_item_profile_description" />
+    </LinearLayout>
+</LinearLayout>
diff --git a/app/src/main/res/layout/widget_input_boolean.xml b/app/src/main/res/layout/widget_input_boolean.xml
new file mode 100644
index 0000000000000000000000000000000000000000..61734a309f02eef4678565a0308bde924be90dfb
--- /dev/null
+++ b/app/src/main/res/layout/widget_input_boolean.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ QuasselDroid - Quassel client for Android
+  ~ Copyright (C) 2016 Janne Koschinski
+  ~ Copyright (C) 2016 Ken Børge Viktil
+  ~ Copyright (C) 2016 Magnus Fjell
+  ~ Copyright (C) 2016 Martin Sandsmark <martin.sandsmark@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 3 of the License, or (at your option)
+  ~ any later version.
+  ~
+  ~ This program is distributed in the hope that it will be useful,
+  ~ but WITHOUT ANY WARRANTY; without even the implied warranty of
+  ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  ~ GNU General Public License for more details.
+  ~
+  ~ You should have received a copy of the GNU General Public License along
+  ~ with this program.  If not, see <http://www.gnu.org/licenses/>.
+  -->
+
+<android.support.v7.widget.AppCompatCheckBox
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/checkBox"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"/>
\ No newline at end of file
diff --git a/app/src/main/res/layout/widget_input_string.xml b/app/src/main/res/layout/widget_input_string.xml
new file mode 100644
index 0000000000000000000000000000000000000000..828c97647c23470d0836ec61a391c99e3cf0be4a
--- /dev/null
+++ b/app/src/main/res/layout/widget_input_string.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ QuasselDroid - Quassel client for Android
+  ~ Copyright (C) 2016 Janne Koschinski
+  ~ Copyright (C) 2016 Ken Børge Viktil
+  ~ Copyright (C) 2016 Magnus Fjell
+  ~ Copyright (C) 2016 Martin Sandsmark <martin.sandsmark@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 3 of the License, or (at your option)
+  ~ any later version.
+  ~
+  ~ This program is distributed in the hope that it will be useful,
+  ~ but WITHOUT ANY WARRANTY; without even the implied warranty of
+  ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  ~ GNU General Public License for more details.
+  ~
+  ~ You should have received a copy of the GNU General Public License along
+  ~ with this program.  If not, see <http://www.gnu.org/licenses/>.
+  -->
+
+<android.support.design.widget.TextInputLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/inputLayout"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content">
+    <android.support.design.widget.TextInputEditText
+        android:id="@+id/editText"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"/>
+</android.support.design.widget.TextInputLayout>
\ No newline at end of file
diff --git a/app/src/main/res/values/ids.xml b/app/src/main/res/values/ids.xml
index f5667ed02f62737dad37805116bf5cb501cd4094..6f8df7cd61f518913cb19e1912ed550bda1d7406 100644
--- a/app/src/main/res/values/ids.xml
+++ b/app/src/main/res/values/ids.xml
@@ -25,4 +25,5 @@
     <item name="custom_channel_span" type="id" />
     <item name="item_create_account" type="id" />
     <item name="item_account" type="id" />
+    <item name="item_backend" type="id"/>
 </resources>