diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 411f4d3c00d7df580462d739ea8a83e6eeef116a..8ab43ed4bc5a8df0532cdf43a569f05f8e186322 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -144,6 +144,20 @@
             android:parentActivityName=".ui.coresettings.network.server.NetworkServerListActivity"
             android:theme="@style/AppTheme.Light"/>
 
+        <activity
+            android:name=".ui.coresettings.ignore.IgnoreListActivity"
+            android:label="@string/titleEditIgnoreList"
+            android:launchMode="singleTask"
+            android:parentActivityName=".ui.chat.MainActivity"
+            android:theme="@style/AppTheme.Light"/>
+
+        <activity
+            android:name=".ui.coresettings.ignore.IgnoreRuleEditActivity"
+            android:label="@string/titleEditIgnoreRule"
+            android:launchMode="singleTask"
+            android:parentActivityName=".ui.coresettings.ignore.IgnoreListActivity"
+            android:theme="@style/AppTheme.Light"/>
+
         <activity
             android:name=".ui.setup.AccountSetupActivity"
             android:label="@string/titleAccountSetup"
diff --git a/app/src/main/java/de/kuschku/libquassel/ProtocolHandler.java b/app/src/main/java/de/kuschku/libquassel/ProtocolHandler.java
index 8b8abd9d6b9bfc10f283c8491b8712410d8c9b8c..187185b9134a9d2b45e5787e95a31bc9e77bc668 100644
--- a/app/src/main/java/de/kuschku/libquassel/ProtocolHandler.java
+++ b/app/src/main/java/de/kuschku/libquassel/ProtocolHandler.java
@@ -49,6 +49,7 @@ 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;
+import de.kuschku.libquassel.syncables.types.invokers.InvokerRegistry;
 import de.kuschku.util.ReflectionUtils;
 
 import static de.kuschku.util.AndroidAssert.assertNotNull;
@@ -110,7 +111,8 @@ public class ProtocolHandler implements IProtocolHandler {
                 if (syncable instanceof SyncableObject && !((SyncableObject) syncable).initialized()) {
                     client.initObject(packedFunc.className, packedFunc.objectName, (SyncableObject) syncable);
                 } else {
-                    ReflectionUtils.invokeMethod(syncable, "_" + packedFunc.methodName, packedFunc.params);
+                    //ReflectionUtils.invokeMethod(syncable, "_" + packedFunc.methodName, packedFunc.params);
+                    InvokerRegistry.invoke(packedFunc, syncable);
                 }
             }
         } catch (Exception e) {
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 5bae42e86f981e1418030aa1251488ce310ea9a9..0b737f8a8d8e83273c0b2c770fe76ba2ff1d4318 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
@@ -25,6 +25,7 @@ import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -33,6 +34,7 @@ import de.kuschku.libquassel.functions.types.PackedFunction;
 import de.kuschku.libquassel.functions.types.SerializedFunction;
 import de.kuschku.libquassel.functions.types.UnpackedFunction;
 import de.kuschku.libquassel.objects.serializers.ObjectSerializer;
+import de.kuschku.libquassel.primitives.QMetaType;
 import de.kuschku.libquassel.primitives.types.QVariant;
 import de.kuschku.libquassel.syncables.types.impl.IgnoreListManager;
 
@@ -56,14 +58,14 @@ public class IgnoreListManagerSerializer implements ObjectSerializer<IgnoreListM
     @Override
     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()) {
+        List<Integer> scope = new ArrayList<>(data.ignoreList().size());
+        List<Integer> ignoreType = new ArrayList<>(data.ignoreList().size());
+        List<Boolean> isActive = new ArrayList<>(data.ignoreList().size());
+        List<String> scopeRule = new ArrayList<>(data.ignoreList().size());
+        List<Boolean> isRegEx = new ArrayList<>(data.ignoreList().size());
+        List<Integer> strictness = new ArrayList<>(data.ignoreList().size());
+        List<String> ignoreRule = new ArrayList<>(data.ignoreList().size());
+        for (IgnoreListManager.IgnoreListItem item : data.ignoreList()) {
             scope.add(item.getScope().value);
             ignoreType.add(item.getType().value);
             isActive.add(item.isActive());
@@ -80,7 +82,9 @@ public class IgnoreListManagerSerializer implements ObjectSerializer<IgnoreListM
         map.put("isRegEx", new QVariant(isRegEx));
         map.put("strictness", new QVariant(strictness));
         map.put("ignoreRule", new QVariant(ignoreRule));
-        return map;
+
+
+        return Collections.singletonMap("IgnoreList", new QVariant<>(QMetaType.Type.QVariantMap, map));
     }
 
     @NonNull
@@ -92,16 +96,17 @@ public class IgnoreListManagerSerializer implements ObjectSerializer<IgnoreListM
     @NonNull
     @Override
     public IgnoreListManager fromLegacy(@NonNull Map<String, QVariant> map) {
-        Map<String, QVariant> internalMap = (Map<String, QVariant>) map.get("IgnoreList").data;
-        assertNotNull(internalMap);
+        if (map.containsKey("IgnoreList"))
+            map = (Map<String, QVariant>) map.get("IgnoreList").data;
+        assertNotNull(map);
         return new IgnoreListManager(
-                (List<Integer>) internalMap.get("scope").data,
-                (List<Integer>) internalMap.get("ignoreType").data,
-                (List<Boolean>) internalMap.get("isActive").data,
-                (List<String>) internalMap.get("scopeRule").data,
-                (List<Boolean>) internalMap.get("isRegEx").data,
-                (List<Integer>) internalMap.get("strictness").data,
-                (List<String>) internalMap.get("ignoreRule").data
+                (List<Integer>) map.get("scope").data,
+                (List<Integer>) map.get("ignoreType").data,
+                (List<Boolean>) map.get("isActive").data,
+                (List<String>) map.get("scopeRule").data,
+                (List<Boolean>) map.get("isRegEx").data,
+                (List<Integer>) map.get("strictness").data,
+                (List<String>) map.get("ignoreRule").data
         );
     }
 
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 260db1f7f7566ec1a46fa2f2ac985abcaaf4c9c8..da4b77785bb6c27d66e56cf61fd6a780d0f24cf6 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
@@ -263,6 +263,11 @@ public class BufferViewConfig extends ABufferViewConfig {
         _update();
     }
 
+    @Override
+    public void _setMinimumActivity(int activity) {
+        _setMinimumActivity(MinimumActivity.fromId(activity));
+    }
+
     @Override
     public boolean hideInactiveBuffers() {
         return hideInactiveBuffers;
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 ce232172cd7375e50c4c1a7b3fa0624b26cdfb04..9414a84d6d6c60b1217d07db6a976ddb892b6d32 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
@@ -24,7 +24,6 @@ package de.kuschku.libquassel.syncables.types.impl;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 
-import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
@@ -38,13 +37,30 @@ import de.kuschku.libquassel.primitives.types.QVariant;
 import de.kuschku.libquassel.syncables.serializers.IgnoreListManagerSerializer;
 import de.kuschku.libquassel.syncables.types.abstracts.AIgnoreListManager;
 import de.kuschku.libquassel.syncables.types.interfaces.QIgnoreListManager;
+import de.kuschku.util.observables.lists.ObservableSortedList;
 import de.kuschku.util.regex.SmartRegEx;
 
 import static de.kuschku.util.AndroidAssert.assertEquals;
 
 public class IgnoreListManager extends AIgnoreListManager {
     @NonNull
-    private final List<IgnoreListItem> ignoreList = new ArrayList<>();
+    private final ObservableSortedList<IgnoreListItem> ignoreList = new ObservableSortedList<>(IgnoreListItem.class, new ObservableSortedList.ItemComparator<IgnoreListItem>() {
+        @Override
+        public int compare(IgnoreListItem o1, IgnoreListItem o2) {
+            return o1.ignoreRule.rule().compareTo(o2.ignoreRule.rule());
+        }
+
+        @Override
+        public boolean areContentsTheSame(IgnoreListItem oldItem, IgnoreListItem newItem) {
+            return oldItem.equals(newItem);
+        }
+
+        @Override
+        public boolean areItemsTheSame(IgnoreListItem item1, IgnoreListItem item2) {
+            return item1.ignoreRule.rule().equals(item2.ignoreRule.rule());
+        }
+    });
+
 
     public IgnoreListManager(@NonNull List<Integer> scope, @NonNull List<Integer> ignoreType,
                              @NonNull List<Boolean> isActive, @NonNull List<String> scopeRule, @NonNull List<Boolean> isRegEx,
@@ -94,6 +110,15 @@ public class IgnoreListManager extends AIgnoreListManager {
         _update();
     }
 
+    @Override
+    public void _addIgnoreListItem(IgnoreListItem item) {
+        if (contains(item.ignoreRule.rule()))
+            return;
+
+        ignoreList.add(item);
+        _update();
+    }
+
     private boolean contains(String ignoreRule) {
         return indexOf(ignoreRule) != -1;
     }
@@ -127,7 +152,7 @@ public class IgnoreListManager extends AIgnoreListManager {
 
     @Override
     public void _update(QIgnoreListManager from) {
-        this.ignoreList.clear();
+        this.ignoreList.retainAll(from.ignoreList());
         this.ignoreList.addAll(from.ignoreList());
         this._update();
     }
@@ -153,21 +178,22 @@ public class IgnoreListManager extends AIgnoreListManager {
         return String.valueOf(ignoreList);
     }
 
-    public List<IgnoreListItem> ignoreRules() {
-        return ignoreList;
-    }
-
     @Override
     public void requestUpdate() {
         requestUpdate(IgnoreListManagerSerializer.get().toVariantMap(this));
     }
 
     @Override
-    public List<? extends IgnoreListItem> ignoreList() {
+    public ObservableSortedList<? extends IgnoreListItem> ignoreList() {
         return ignoreList;
     }
 
-    public class IgnoreListItem {
+    @Override
+    public void _toggleIgnoreRule(IgnoreListItem ignoreRule, boolean active) {
+        ignoreRule.isActive = active;
+    }
+
+    public static class IgnoreListItem {
         private final IgnoreType type;
         @NonNull
         private final SmartRegEx ignoreRule;
@@ -270,5 +296,37 @@ public class IgnoreListManager extends AIgnoreListManager {
                     ", isActive=" + isActive +
                     '}';
         }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (!(o instanceof IgnoreListItem)) return false;
+
+            IgnoreListItem item = (IgnoreListItem) o;
+
+            if (isRegEx() != item.isRegEx()) return false;
+            if (isActive() != item.isActive()) return false;
+            if (getType() != item.getType()) return false;
+            if (!getIgnoreRule().equals(item.getIgnoreRule())) return false;
+            if (getStrictness() != item.getStrictness()) return false;
+            if (getScope() != item.getScope()) return false;
+            // Probably incorrect - comparing Object[] arrays with Arrays.equals
+            if (!Arrays.equals(scopeRules, item.scopeRules)) return false;
+            return getScopeRule() != null ? getScopeRule().equals(item.getScopeRule()) : item.getScopeRule() == null;
+
+        }
+
+        @Override
+        public int hashCode() {
+            int result = getType() != null ? getType().hashCode() : 0;
+            result = 31 * result + getIgnoreRule().hashCode();
+            result = 31 * result + (isRegEx() ? 1 : 0);
+            result = 31 * result + (getStrictness() != null ? getStrictness().hashCode() : 0);
+            result = 31 * result + (getScope() != null ? getScope().hashCode() : 0);
+            result = 31 * result + Arrays.hashCode(scopeRules);
+            result = 31 * result + (getScopeRule() != null ? getScopeRule().hashCode() : 0);
+            result = 31 * result + (isActive() ? 1 : 0);
+            return result;
+        }
     }
 }
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/Network.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/Network.java
index 2083fa9773014b4523479123a0a6c6d674ac6bf4..d1b2e780c4f8ce57c1d0115f3304a3fbe149bca2 100644
--- a/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/Network.java
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/impl/Network.java
@@ -29,6 +29,7 @@ import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
+import java.util.Locale;
 import java.util.Map;
 import java.util.Observable;
 import java.util.Observer;
@@ -45,7 +46,7 @@ import de.kuschku.libquassel.syncables.types.interfaces.QIrcChannel;
 import de.kuschku.libquassel.syncables.types.interfaces.QIrcUser;
 import de.kuschku.libquassel.syncables.types.interfaces.QNetwork;
 import de.kuschku.util.CompatibilityUtils;
-import de.kuschku.util.irc.IrcCaseMapper;
+import de.kuschku.util.irc.IrcCaseMappers;
 import de.kuschku.util.irc.IrcUserUtils;
 import de.kuschku.util.irc.ModeUtils;
 import de.kuschku.util.irc.chanmodes.IrcModeProvider;
@@ -72,6 +73,7 @@ public class Network extends ANetwork implements Observer {
     private List<String> prefixes;
     private List<String> prefixModes;
     private IrcModeProvider modeProvider;
+    private IrcCaseMappers.IrcCaseMapper caseMapper;
 
     public Network(Map<String, QIrcChannel> channels,
                    Map<String, QIrcUser> nicks,
@@ -88,6 +90,8 @@ public class Network extends ANetwork implements Observer {
         this.myNick = myNick;
         _setNetworkInfo(networkInfo);
         this.networkInfo._setServerList(serverList);
+
+        updateCaseMapper();
     }
 
     public Network(Map<String, QIrcChannel> channels, Map<String, QIrcUser> users, Map<String, String> supports, int connectionState, String currentServer, boolean isConnected, int latency, String myNick, NetworkInfo networkInfo) {
@@ -97,7 +101,7 @@ public class Network extends ANetwork implements Observer {
     public Network(Map<String, QIrcChannel> channels, Map<String, QIrcUser> nicks, List<NetworkServer> serverList, Map<String, String> supports, ConnectionState connectionState, String currentServer, boolean isConnected, int latency, String myNick, NetworkInfo networkInfo) {
         this.channels = new HashMap<>(channels);
         this.nicks = new HashMap<>(nicks);
-        this.supports = supports;
+        this.supports = new HashMap<>(supports);
         this.connectionState = connectionState;
         this.currentServer = currentServer;
         this.isConnected = isConnected;
@@ -105,6 +109,8 @@ public class Network extends ANetwork implements Observer {
         this.myNick = myNick;
         _setNetworkInfo(networkInfo);
         this.networkInfo._setServerList(serverList);
+
+        updateCaseMapper();
     }
 
     @NonNull
@@ -130,12 +136,12 @@ public class Network extends ANetwork implements Observer {
 
     @Override
     public boolean isMyNick(String nick) {
-        return IrcCaseMapper.equalsIgnoreCase(myNick, nick);
+        return caseMapper.equalsIgnoreCase(myNick, nick);
     }
 
     @Override
     public boolean isMe(@NonNull QIrcUser ircuser) {
-        return IrcCaseMapper.equalsIgnoreCase(ircuser.nick(), myNick());
+        return caseMapper.equalsIgnoreCase(ircuser.nick(), myNick());
     }
 
     @Override
@@ -403,7 +409,7 @@ public class Network extends ANetwork implements Observer {
 
     @Override
     public String support(@NonNull String param) {
-        String key = IrcCaseMapper.toUpperCase(param);
+        String key = param.toUpperCase(Locale.US);
         if (supports.containsKey(key))
             return supports.get(key);
         else
@@ -428,18 +434,18 @@ public class Network extends ANetwork implements Observer {
 
     @Override
     public QIrcChannel newIrcChannel(@NonNull String channelname) {
-        if (!channels.containsKey(IrcCaseMapper.toLowerCase(channelname))) {
+        if (!channels.containsKey(caseMapper.toLowerCase(channelname))) {
             QIrcChannel channel = IrcChannel.create(channelname);
-            channels.put(IrcCaseMapper.toLowerCase(channelname), channel);
+            channels.put(caseMapper.toLowerCase(channelname), channel);
             channel.init(this, client);
         }
-        return channels.get(IrcCaseMapper.toLowerCase(channelname));
+        return channels.get(caseMapper.toLowerCase(channelname));
     }
 
     @Nullable
     @Override
     public QIrcChannel ircChannel(String channelname) {
-        channelname = IrcCaseMapper.toLowerCase(channelname);
+        channelname = caseMapper.toLowerCase(channelname);
         if (channels.containsKey(channelname)) {
             return channels.get(channelname);
         } else {
@@ -649,12 +655,35 @@ public class Network extends ANetwork implements Observer {
     public void _addSupport(String param, String value) {
         supports.put(param, value);
         _update();
+        updateCaseMapper();
+    }
+
+    @Override
+    public IrcCaseMappers.IrcCaseMapper caseMapper() {
+        return caseMapper;
+    }
+
+    private void updateCaseMapper() {
+        String mapping = support("CASEMAPPING");
+        if (mapping == null) {
+            caseMapper = IrcCaseMappers.unicode;
+        } else {
+            switch (mapping.toLowerCase(Locale.US)) {
+                case "rfc1459":
+                case "strict-rfc1459":
+                    caseMapper = IrcCaseMappers.irc;
+                case "ascii":
+                default:
+                    caseMapper = IrcCaseMappers.unicode;
+            }
+        }
     }
 
     @Override
     public void _removeSupport(String param) {
         supports.remove(param);
         _update();
+        updateCaseMapper();
     }
 
     @Override
@@ -669,7 +698,7 @@ public class Network extends ANetwork implements Observer {
 
     @Override
     public QIrcUser _updateNickFromMask(@NonNull String mask) {
-        String nick = IrcCaseMapper.toLowerCase(IrcUserUtils.getNick(mask));
+        String nick = caseMapper.toLowerCase(IrcUserUtils.getNick(mask));
         QIrcUser user;
 
         if (nicks.containsKey(nick)) {
@@ -694,7 +723,7 @@ public class Network extends ANetwork implements Observer {
 
     @Override
     public void _ircUserNickChanged(@NonNull String oldNick, @NonNull String newNick) {
-        if (!IrcCaseMapper.equalsIgnoreCase(oldNick, newNick)) {
+        if (!caseMapper.equalsIgnoreCase(oldNick, newNick)) {
             nicks.put(newNick, nicks.remove(oldNick));
             for (QIrcChannel channel : channels.values()) {
                 channel._ircUserNickChanged(oldNick, newNick);
@@ -702,7 +731,7 @@ public class Network extends ANetwork implements Observer {
             _update();
         }
 
-        if (IrcCaseMapper.equalsIgnoreCase(myNick(), oldNick))
+        if (caseMapper.equalsIgnoreCase(myNick(), oldNick))
             _setMyNick(newNick);
     }
 
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/interfaces/QAliasManager.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/interfaces/QAliasManager.java
index 94ef963ee5f8e0786b4e24b8e630a9577e904ff3..4e05f12e6cb86b3d4725ea34fe258f66c51afb04 100644
--- a/app/src/main/java/de/kuschku/libquassel/syncables/types/interfaces/QAliasManager.java
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/interfaces/QAliasManager.java
@@ -24,9 +24,11 @@ package de.kuschku.libquassel.syncables.types.interfaces;
 import android.support.annotation.NonNull;
 
 import java.util.List;
+import java.util.Map;
 
 import de.kuschku.libquassel.objects.types.Command;
 import de.kuschku.libquassel.primitives.types.BufferInfo;
+import de.kuschku.libquassel.primitives.types.QVariant;
 import de.kuschku.libquassel.syncables.Synced;
 
 public interface QAliasManager extends QObservable<QAliasManager> {
@@ -48,6 +50,10 @@ public interface QAliasManager extends QObservable<QAliasManager> {
     @NonNull
     List<Command> processInput(final BufferInfo info, final String message);
 
+    void _update(Map<String, QVariant> from);
+
+    void _update(QAliasManager from);
+
     @Synced
     void addAlias(final String name, final String expansion);
 
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 2377b60bc43ba00044a6ac7bdff694c3396d5b32..434e55c02d5d79518ce4255fba6e437a5044a69d 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
@@ -86,6 +86,8 @@ public interface QBufferViewConfig extends QSyncableObject<QBufferViewConfig> {
 
     void _setMinimumActivity(MinimumActivity activity);
 
+    void _setMinimumActivity(int activity);
+
     boolean hideInactiveBuffers();
 
     @Synced
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/interfaces/QIdentity.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/interfaces/QIdentity.java
index d859077137d5bac0c8c1b33235b078710cf613a8..cff83ed0452ffc69b545cd723cedea6622a93bab 100644
--- a/app/src/main/java/de/kuschku/libquassel/syncables/types/interfaces/QIdentity.java
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/interfaces/QIdentity.java
@@ -24,7 +24,9 @@ package de.kuschku.libquassel.syncables.types.interfaces;
 import android.support.annotation.Nullable;
 
 import java.util.List;
+import java.util.Map;
 
+import de.kuschku.libquassel.primitives.types.QVariant;
 import de.kuschku.libquassel.syncables.Synced;
 import de.kuschku.libquassel.syncables.types.impl.Identity;
 
@@ -193,4 +195,8 @@ public interface QIdentity extends QObservable<QIdentity> {
 
     @Synced
     void update(Identity identity);
+
+    void _update(QIdentity identity);
+
+    void _update(Map<String, QVariant> identity);
 }
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 743c31c9bfae6b588eba60ae1ffb1e968fef7435..302cac7822840c8b19229cfba1c5f1b0ed270f20 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,13 +23,13 @@ package de.kuschku.libquassel.syncables.types.interfaces;
 
 import android.support.annotation.NonNull;
 
-import java.util.List;
 import java.util.Map;
 
 import de.kuschku.libquassel.message.Message;
 import de.kuschku.libquassel.primitives.types.QVariant;
 import de.kuschku.libquassel.syncables.Synced;
 import de.kuschku.libquassel.syncables.types.impl.IgnoreListManager;
+import de.kuschku.util.observables.lists.ObservableSortedList;
 
 public interface QIgnoreListManager extends QObservable<QIgnoreListManager> {
     @Synced
@@ -50,15 +50,23 @@ public interface QIgnoreListManager extends QObservable<QIgnoreListManager> {
 
     void _addIgnoreListItem(int type, final String ignoreRule, boolean isRegEx, int strictness, int scope, final String scopeRule, boolean isActive);
 
+    void _addIgnoreListItem(IgnoreListManager.IgnoreListItem item);
+
     StrictnessType match(String msgContents, String msgSender, Message.Type msgType, String network, String bufferName);
 
     boolean matches(Message message, QNetwork network);
 
+    void _update(Map<String, QVariant> from);
+
+    void _update(QIgnoreListManager from);
+
     void requestUpdate(Map<String, QVariant<Object>> variantMap);
 
     void requestUpdate();
 
-    List<? extends IgnoreListManager.IgnoreListItem> ignoreList();
+    ObservableSortedList<? extends IgnoreListManager.IgnoreListItem> ignoreList();
+
+    void _toggleIgnoreRule(IgnoreListManager.IgnoreListItem ignoreRule, boolean active);
 
     enum IgnoreType {
         SenderIgnore(0),
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/interfaces/QNetwork.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/interfaces/QNetwork.java
index aae02c82fd5307828f4fd8788c0488ed204670f6..9e4fa1af3b31bbdab33be952feba1c56e329f06f 100644
--- a/app/src/main/java/de/kuschku/libquassel/syncables/types/interfaces/QNetwork.java
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/interfaces/QNetwork.java
@@ -30,6 +30,7 @@ import de.kuschku.libquassel.objects.types.NetworkServer;
 import de.kuschku.libquassel.syncables.Synced;
 import de.kuschku.libquassel.syncables.types.impl.IrcChannel;
 import de.kuschku.libquassel.syncables.types.impl.NetworkInfo;
+import de.kuschku.util.irc.IrcCaseMappers;
 import de.kuschku.util.irc.chanmodes.IrcModeProvider;
 
 public interface QNetwork extends QObservable<QNetwork> {
@@ -231,6 +232,7 @@ public interface QNetwork extends QObservable<QNetwork> {
     @Synced
     void setUseSasl(boolean useSasl);
 
+    void setSaslPassword(final String saslPassword);
     void _setUseSasl(boolean useSasl);
 
     @Synced
@@ -239,7 +241,6 @@ public interface QNetwork extends QObservable<QNetwork> {
     void _setSaslAccount(final String saslAccount);
 
     @Synced
-    void setSaslPassword(final String saslPassword);
 
     void _setSaslPassword(final String saslPassword);
 
@@ -350,6 +351,8 @@ public interface QNetwork extends QObservable<QNetwork> {
 
     void _addIrcChannel(IrcChannel ircChannel);
 
+    IrcCaseMappers.IrcCaseMapper caseMapper();
+
     enum ConnectionState {
         Disconnected(0),
         Connecting(1),
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/IAliasManager.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/IAliasManager.java
new file mode 100644
index 0000000000000000000000000000000000000000..43f225d3178ba29028b5c846a3388f3d92f3ab56
--- /dev/null
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/IAliasManager.java
@@ -0,0 +1,52 @@
+/*
+ * 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.libquassel.syncables.types.invokers;
+
+import android.support.annotation.NonNull;
+
+import de.kuschku.libquassel.functions.types.SyncFunction;
+import de.kuschku.libquassel.syncables.types.interfaces.QAliasManager;
+
+public class IAliasManager implements Invoker<QAliasManager> {
+    @NonNull
+    private static final IAliasManager invoker = new IAliasManager();
+
+    private IAliasManager() {
+    }
+
+    @NonNull
+    public static IAliasManager get() {
+        return invoker;
+    }
+
+    @Override
+    public void invoke(SyncFunction function, QAliasManager obj) {
+        switch (function.methodName) {
+            case "addAlias": {
+                obj._addAlias((String) function.params.get(0), (String) function.params.get(1));
+            } break;
+            case "update": {
+                InvokerHelper.update(obj, function.params.get(0));
+            } break;
+        }
+    }
+}
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/IBacklogManager.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/IBacklogManager.java
new file mode 100644
index 0000000000000000000000000000000000000000..b06d6ea86c6617ba37cf22ca0c1504623fb3dc35
--- /dev/null
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/IBacklogManager.java
@@ -0,0 +1,58 @@
+/*
+ * 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.libquassel.syncables.types.invokers;
+
+import android.support.annotation.NonNull;
+
+import java.util.List;
+
+import de.kuschku.libquassel.functions.types.SyncFunction;
+import de.kuschku.libquassel.message.Message;
+import de.kuschku.libquassel.syncables.types.interfaces.QBacklogManager;
+
+public class IBacklogManager implements Invoker<QBacklogManager> {
+    @NonNull
+    private static final IBacklogManager invoker = new IBacklogManager();
+
+    private IBacklogManager() {
+    }
+
+    @NonNull
+    public static IBacklogManager get() {
+        return invoker;
+    }
+
+    @Override
+    public void invoke(SyncFunction function, QBacklogManager obj) {
+        switch (function.methodName) {
+            case "receiveBacklog": {
+                obj._receiveBacklog((int) function.params.get(0), (int) function.params.get(1), (int) function.params.get(2), (int) function.params.get(3), (int) function.params.get(4), (List<Message>) function.params.get(5));
+            } break;
+            case "receiveBacklogAll": {
+                obj._receiveBacklogAll((int) function.params.get(0), (int) function.params.get(1), (int) function.params.get(2), (int) function.params.get(3), (List<Message>) function.params.get(4));
+            } break;
+            case "update": {
+                InvokerHelper.update(obj, function.params.get(0));
+            } break;
+        }
+    }
+}
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/IBufferSyncer.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/IBufferSyncer.java
new file mode 100644
index 0000000000000000000000000000000000000000..716eca8118f89623f48d2f260f4fd58339f88ea1
--- /dev/null
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/IBufferSyncer.java
@@ -0,0 +1,67 @@
+/*
+ * 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.libquassel.syncables.types.invokers;
+
+import android.support.annotation.NonNull;
+
+import de.kuschku.libquassel.functions.types.SyncFunction;
+import de.kuschku.libquassel.syncables.types.interfaces.QBufferSyncer;
+
+public class IBufferSyncer implements Invoker<QBufferSyncer> {
+    @NonNull
+    private static final IBufferSyncer invoker = new IBufferSyncer();
+
+    private IBufferSyncer() {
+    }
+
+    @NonNull
+    public static IBufferSyncer get() {
+        return invoker;
+    }
+
+    @Override
+    public void invoke(SyncFunction function, QBufferSyncer obj) {
+        switch (function.methodName) {
+            case "setLastSeenMsg": {
+                obj._setLastSeenMsg((int) function.params.get(0), (int) function.params.get(1));
+            } break;
+            case "setMarkerLine": {
+                obj._setMarkerLine((int) function.params.get(0), (int) function.params.get(1));
+            } break;
+            case "removeBuffer": {
+                obj._removeBuffer((int) function.params.get(0));
+            } break;
+            case "renameBuffer": {
+                obj._renameBuffer((int) function.params.get(0), (String) function.params.get(1));
+            } break;
+            case "mergeBuffersPermanently": {
+                obj._mergeBuffersPermanently((int) function.params.get(0), (int) function.params.get(1));
+            } break;
+            case "markBufferAsRead": {
+                obj._markBufferAsRead((int) function.params.get(0));
+            } break;
+            case "update": {
+                InvokerHelper.update(obj, function.params.get(0));
+            } break;
+        }
+    }
+}
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/IBufferViewConfig.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/IBufferViewConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..d775f37738f12e253d95f700d03d5fd1c874f3e9
--- /dev/null
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/IBufferViewConfig.java
@@ -0,0 +1,88 @@
+/*
+ * 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.libquassel.syncables.types.invokers;
+
+import android.support.annotation.NonNull;
+
+import de.kuschku.libquassel.functions.types.SyncFunction;
+import de.kuschku.libquassel.syncables.types.interfaces.QBufferViewConfig;
+
+public class IBufferViewConfig implements Invoker<QBufferViewConfig> {
+    @NonNull
+    private static final IBufferViewConfig invoker = new IBufferViewConfig();
+
+    private IBufferViewConfig() {
+    }
+
+    @NonNull
+    public static IBufferViewConfig get() {
+        return invoker;
+    }
+
+    @Override
+    public void invoke(SyncFunction function, QBufferViewConfig obj) {
+        switch (function.methodName) {
+            case "setBufferViewName": {
+                obj._setBufferViewName((String) function.params.get(0));
+            } break;
+            case "setNetworkId": {
+                obj._setNetworkId((int) function.params.get(0));
+            } break;
+            case "setAddNewBuffersAutomatically": {
+                obj._setAddNewBuffersAutomatically((boolean) function.params.get(0));
+            } break;
+            case "setSortAlphabetically": {
+                obj._setSortAlphabetically((boolean) function.params.get(0));
+            } break;
+            case "setDisableDecoration": {
+                obj._setDisableDecoration((boolean) function.params.get(0));
+            } break;
+            case "setAllowedBufferTypes": {
+                obj._setAllowedBufferTypes((int) function.params.get(0));
+            } break;
+            case "setMinimumActivity": {
+                obj._setMinimumActivity((int) function.params.get(0));
+            } break;
+            case "setHideInactiveBuffers": {
+                obj._setHideInactiveBuffers((boolean) function.params.get(0));
+            } break;
+            case "setHideInactiveNetworks": {
+                obj._setHideInactiveNetworks((boolean) function.params.get(0));
+            } break;
+            case "addBuffer": {
+                obj._addBuffer((int) function.params.get(0), (int) function.params.get(1));
+            } break;
+            case "moveBuffer": {
+                obj._moveBuffer((int) function.params.get(0), (int) function.params.get(1));
+            } break;
+            case "removeBuffer": {
+                obj._removeBuffer((int) function.params.get(0));
+            } break;
+            case "removeBufferPermanently": {
+                obj._removeBufferPermanently((int) function.params.get(0));
+            } break;
+            case "update": {
+                InvokerHelper.update(obj, function.params.get(0));
+            } break;
+        }
+    }
+}
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/IBufferViewManager.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/IBufferViewManager.java
new file mode 100644
index 0000000000000000000000000000000000000000..042f705f5f55336806e7b80b6d2e009bf7a0997c
--- /dev/null
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/IBufferViewManager.java
@@ -0,0 +1,55 @@
+/*
+ * 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.libquassel.syncables.types.invokers;
+
+import android.support.annotation.NonNull;
+
+import de.kuschku.libquassel.functions.types.SyncFunction;
+import de.kuschku.libquassel.syncables.types.interfaces.QBufferViewManager;
+
+public class IBufferViewManager implements Invoker<QBufferViewManager> {
+    @NonNull
+    private static final IBufferViewManager invoker = new IBufferViewManager();
+
+    private IBufferViewManager() {
+    }
+
+    @NonNull
+    public static IBufferViewManager get() {
+        return invoker;
+    }
+
+    @Override
+    public void invoke(SyncFunction function, QBufferViewManager obj) {
+        switch (function.methodName) {
+            case "addBufferViewConfig": {
+                obj._addBufferViewConfig((int) function.params.get(0));
+            } break;
+            case "deleteBufferViewConfig": {
+                obj._deleteBufferViewConfig((int) function.params.get(0));
+            } break;
+            case "update": {
+                InvokerHelper.update(obj, function.params.get(0));
+            } break;
+        }
+    }
+}
diff --git a/app/src/main/java/de/kuschku/util/irc/IrcCaseMapper.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/ICertManager.java
similarity index 50%
rename from app/src/main/java/de/kuschku/util/irc/IrcCaseMapper.java
rename to app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/ICertManager.java
index f487dd22f6a1c4661a92068beebd411eb0b1e994..959cc69e4a6d8299a8d25ec3caee062c9d182386 100644
--- a/app/src/main/java/de/kuschku/util/irc/IrcCaseMapper.java
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/ICertManager.java
@@ -19,38 +19,34 @@
  * with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-package de.kuschku.util.irc;
+package de.kuschku.libquassel.syncables.types.invokers;
 
 import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
 
-import java.util.Locale;
+import de.kuschku.libquassel.functions.types.SyncFunction;
+import de.kuschku.libquassel.syncables.types.interfaces.QCertManager;
 
-import de.kuschku.util.backports.Objects;
-
-public class IrcCaseMapper {
-    private IrcCaseMapper() {
+public class ICertManager implements Invoker<QCertManager> {
+    @NonNull
+    private static final ICertManager invoker = new ICertManager();
 
+    private ICertManager() {
     }
 
-    public static String toLowerCase(@NonNull String s) {
-        return s.toLowerCase(Locale.US)
-                .replaceAll("\\[", "{")
-                .replaceAll("\\]", "}")
-                .replaceAll("\\^", "~");
+    @NonNull
+    public static ICertManager get() {
+        return invoker;
     }
 
-    public static String toUpperCase(@NonNull String s) {
-        return s.toUpperCase(Locale.US)
-                .replaceAll("\\{", "[")
-                .replaceAll("\\}", "]")
-                .replaceAll("~", "^");
-    }
+    @Override
+    public void invoke(SyncFunction function, QCertManager obj) {
+        switch (function.methodName) {
+            case "": {
 
-    public static boolean equalsIgnoreCase(@Nullable String a, @Nullable String b) {
-        if (a == null || b == null)
-            return (Objects.equals(a, b));
-        else
-            return toLowerCase(a).equals(toLowerCase(b)) || toUpperCase(a).equals(toUpperCase(b));
+            } break;
+            case "update": {
+                InvokerHelper.update(obj, function.params.get(0));
+            } break;
+        }
     }
 }
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/ICoreInfo.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/ICoreInfo.java
new file mode 100644
index 0000000000000000000000000000000000000000..03fd4c59143c024bc3f72cd5a469e47ab0c1d6c4
--- /dev/null
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/ICoreInfo.java
@@ -0,0 +1,55 @@
+/*
+ * 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.libquassel.syncables.types.invokers;
+
+import android.support.annotation.NonNull;
+
+import java.util.Map;
+
+import de.kuschku.libquassel.functions.types.SyncFunction;
+import de.kuschku.libquassel.primitives.types.QVariant;
+import de.kuschku.libquassel.syncables.types.interfaces.QCoreInfo;
+
+public class ICoreInfo implements Invoker<QCoreInfo> {
+    @NonNull
+    private static final ICoreInfo invoker = new ICoreInfo();
+
+    private ICoreInfo() {
+    }
+
+    @NonNull
+    public static ICoreInfo get() {
+        return invoker;
+    }
+
+    @Override
+    public void invoke(SyncFunction function, QCoreInfo obj) {
+        switch (function.methodName) {
+            case "setCoreData": {
+                obj._setCoreData((Map<String, QVariant>) function.params.get(0));
+            } break;
+            case "update": {
+                InvokerHelper.update(obj, function.params.get(0));
+            } break;
+        }
+    }
+}
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/IIdentity.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/IIdentity.java
new file mode 100644
index 0000000000000000000000000000000000000000..71cb0e8ffeab888ae991eae98217cf43f595e5c5
--- /dev/null
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/IIdentity.java
@@ -0,0 +1,114 @@
+/*
+ * 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.libquassel.syncables.types.invokers;
+
+import android.support.annotation.NonNull;
+
+import java.util.List;
+
+import de.kuschku.libquassel.functions.types.SyncFunction;
+import de.kuschku.libquassel.syncables.types.interfaces.QIdentity;
+
+public class IIdentity implements Invoker<QIdentity> {
+    @NonNull
+    private static final IIdentity invoker = new IIdentity();
+
+    private IIdentity() {
+    }
+
+    @NonNull
+    public static IIdentity get() {
+        return invoker;
+    }
+
+    @Override
+    public void invoke(SyncFunction function, QIdentity obj) {
+        switch (function.methodName) {
+            case "setId": {
+                obj._setId((int) function.params.get(0));
+            } break;
+            case "setIdentityName": {
+                obj._setIdentityName((String) function.params.get(0));
+            } break;
+            case "setRealName": {
+                obj._setRealName((String) function.params.get(0));
+            } break;
+            case "setNicks": {
+                obj._setNicks((List<String>) function.params.get(0));
+            } break;
+            case "setAwayNick": {
+                obj._setAwayNick((String) function.params.get(0));
+            } break;
+            case "setAwayNickEnabled": {
+                obj._setAwayNickEnabled((boolean) function.params.get(0));
+            } break;
+            case "setAwayReason": {
+                obj._setAwayReason((String) function.params.get(0));
+            } break;
+            case "setAwayReasonEnabled": {
+                obj._setAwayReasonEnabled((boolean) function.params.get(0));
+            } break;
+            case "setAutoAwayEnabled": {
+                obj._setAutoAwayEnabled((boolean) function.params.get(0));
+            } break;
+            case "setAutoAwayTime": {
+                obj._setAutoAwayTime((int) function.params.get(0));
+            } break;
+            case "setAutoAwayReason": {
+                obj._setAutoAwayReason((String) function.params.get(0));
+            } break;
+            case "setAutoAwayReasonEnabled": {
+                obj._setAutoAwayReasonEnabled((boolean) function.params.get(0));
+            } break;
+            case "setDetachAwayEnabled": {
+                obj._setDetachAwayEnabled((boolean) function.params.get(0));
+            } break;
+            case "setDetachAwayReason": {
+                obj._setDetachAwayReason((String) function.params.get(0));
+            } break;
+            case "setDetachAwayReasonEnabled": {
+                obj._setDetachAwayReasonEnabled((boolean) function.params.get(0));
+            } break;
+            case "setIdent": {
+                obj._setIdent((String) function.params.get(0));
+            } break;
+            case "setKickReason": {
+                obj._setKickReason((String) function.params.get(0));
+            } break;
+            case "setPartReason": {
+                obj._setPartReason((String) function.params.get(0));
+            } break;
+            case "setQuitReason": {
+                obj._setQuitReason((String) function.params.get(0));
+            } break;
+            case "setSslKey": {
+                obj._setSslKey((String) function.params.get(0));
+            } break;
+            case "setSslCert": {
+                obj._setSslCert((String) function.params.get(0));
+            } break;
+            case "update": {
+                InvokerHelper.update(obj, function.params.get(0));
+            } break;
+        }
+    }
+}
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/IIgnoreListManager.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/IIgnoreListManager.java
new file mode 100644
index 0000000000000000000000000000000000000000..92bd78a899995528196d9e0e839af28d3008e042
--- /dev/null
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/IIgnoreListManager.java
@@ -0,0 +1,57 @@
+/*
+ * 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.libquassel.syncables.types.invokers;
+
+import android.support.annotation.NonNull;
+
+import de.kuschku.libquassel.functions.types.SyncFunction;
+import de.kuschku.libquassel.syncables.types.interfaces.QIgnoreListManager;
+
+public class IIgnoreListManager implements Invoker<QIgnoreListManager> {
+    @NonNull
+    private static final IIgnoreListManager invoker = new IIgnoreListManager();
+
+    private IIgnoreListManager() {
+    }
+
+    @NonNull
+    public static IIgnoreListManager get() {
+        return invoker;
+    }
+
+    public void invoke(SyncFunction function, QIgnoreListManager object) {
+        switch (function.methodName) {
+            case "removeIgnoreListItem": {
+                object._removeIgnoreListItem((String) function.params.get(0));
+            } break;
+            case "toggleIgnoreRule": {
+                object._toggleIgnoreRule((String) function.params.get(0));
+            } break;
+            case "addIgnoreListItem": {
+                object._addIgnoreListItem((int) function.params.get(0), (String) function.params.get(1), (boolean) function.params.get(2), (int) function.params.get(3), (int) function.params.get(4), (String) function.params.get(5), (boolean) function.params.get(6));
+            } break;
+            case "update": {
+                InvokerHelper.update(object, function.params.get(0));
+            } break;
+        }
+    }
+}
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/IIrcChannel.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/IIrcChannel.java
new file mode 100644
index 0000000000000000000000000000000000000000..d2dd9ccf6b7e82a53e7d3270e90c8389feb535b5
--- /dev/null
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/IIrcChannel.java
@@ -0,0 +1,84 @@
+/*
+ * 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.libquassel.syncables.types.invokers;
+
+import android.support.annotation.NonNull;
+
+import java.util.List;
+
+import de.kuschku.libquassel.functions.types.SyncFunction;
+import de.kuschku.libquassel.syncables.types.interfaces.QIrcChannel;
+
+public class IIrcChannel implements Invoker<QIrcChannel> {
+    @NonNull
+    private static final IIrcChannel invoker = new IIrcChannel();
+
+    private IIrcChannel() {
+    }
+
+    @NonNull
+    public static IIrcChannel get() {
+        return invoker;
+    }
+
+    @Override
+    public void invoke(SyncFunction function, QIrcChannel obj) {
+        switch (function.methodName) {
+            case "setTopic": {
+                obj._setTopic((String) function.params.get(0));
+            } break;
+            case "setPassword": {
+                obj._setPassword((String) function.params.get(0));
+            } break;
+            case "setEncrypted": {
+                obj._setEncrypted((boolean) function.params.get(0));
+            } break;
+            case "joinIrcUsers": {
+                obj._joinIrcUsers((List<String>) function.params.get(0), (List<String>) function.params.get(1));
+            } break;
+            case "part": {
+                obj._part((String) function.params.get(0));
+            } break;
+            case "setUserModes": {
+                obj._setUserModes((String) function.params.get(0), (String) function.params.get(1));
+            } break;
+            case "addUserMode": {
+                obj._addUserMode((String) function.params.get(0), (String) function.params.get(1));
+            } break;
+            case "removeUserMode": {
+                obj._removeUserMode((String) function.params.get(0), (String) function.params.get(1));
+            } break;
+            case "addChannelMode": {
+                obj._addChannelMode((char) function.params.get(0), (String) function.params.get(1));
+            } break;
+            case "removeChannelMode": {
+                obj._removeChannelMode((char) function.params.get(0), (String) function.params.get(1));
+            } break;
+            case "ircUserNickChanged": {
+                obj._ircUserNickChanged((String) function.params.get(0), (String) function.params.get(1));
+            } break;
+            case "update": {
+                InvokerHelper.update(obj, function.params.get(0));
+            } break;
+        }
+    }
+}
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/IIrcUser.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/IIrcUser.java
new file mode 100644
index 0000000000000000000000000000000000000000..eb3b3d66e94c6e3ef56fc05c1c0e92909ae4286e
--- /dev/null
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/IIrcUser.java
@@ -0,0 +1,117 @@
+/*
+ * 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.libquassel.syncables.types.invokers;
+
+import android.support.annotation.NonNull;
+
+import org.joda.time.DateTime;
+
+import de.kuschku.libquassel.functions.types.SyncFunction;
+import de.kuschku.libquassel.syncables.types.interfaces.QIrcUser;
+
+public class IIrcUser implements Invoker<QIrcUser> {
+    @NonNull
+    private static final IIrcUser invoker = new IIrcUser();
+
+    private IIrcUser() {
+    }
+
+    @NonNull
+    public static IIrcUser get() {
+        return invoker;
+    }
+
+    @Override
+    public void invoke(SyncFunction function, QIrcUser obj) {
+        switch (function.methodName) {
+            case "setAway": {
+                obj._setAway((boolean) function.params.get(0));
+            } break;
+            case "setUser": {
+                obj._setUser((String) function.params.get(0));
+            } break;
+            case "setHost": {
+                obj._setHost((String) function.params.get(0));
+            } break;
+            case "setNick": {
+                obj._setNick((String) function.params.get(0));
+            } break;
+            case "setRealName": {
+                obj._setRealName((String) function.params.get(0));
+            } break;
+            case "setAccount": {
+                obj._setAccount((String) function.params.get(0));
+            } break;
+            case "setAwayMessage": {
+                obj._setAwayMessage((String) function.params.get(0));
+            } break;
+            case "setIdleTime": {
+                obj._setIdleTime((DateTime) function.params.get(0));
+            } break;
+            case "setLoginTime": {
+                obj._setLoginTime((DateTime) function.params.get(0));
+            } break;
+            case "setServer": {
+                obj._setServer((String) function.params.get(0));
+            } break;
+            case "setIrcOperator": {
+                obj._setIrcOperator((String) function.params.get(0));
+            } break;
+            case "setLastAwayMessage": {
+                obj._setLastAwayMessage((int) function.params.get(0));
+            } break;
+            case "setWhoisServiceReply": {
+                obj._setWhoisServiceReply((String) function.params.get(0));
+            } break;
+            case "setSuserHost": {
+                obj._setSuserHost((String) function.params.get(0));
+            } break;
+            case "setEncrypted": {
+                obj._setEncrypted((boolean) function.params.get(0));
+            } break;
+            case "updateHostmask": {
+                obj._updateHostmask((String) function.params.get(0));
+            } break;
+            case "setUserModes": {
+                obj._setUserModes((String) function.params.get(0));
+            } break;
+            case "joinChannel": {
+                obj._joinChannel((String) function.params.get(0));
+            } break;
+            case "partChannel": {
+                obj._partChannel((String) function.params.get(0));
+            } break;
+            case "addUserModes": {
+                obj._addUserModes((String) function.params.get(0));
+            } break;
+            case "removeUserModes": {
+                obj._removeUserModes((String) function.params.get(0));
+            } break;
+            case "quit": {
+                obj._quit();
+            } break;
+            case "update": {
+                InvokerHelper.update(obj, function.params.get(0));
+            } break;
+        }
+    }
+}
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/INetwork.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/INetwork.java
new file mode 100644
index 0000000000000000000000000000000000000000..f5d797014348c969551202a67663c388c0f8d1f5
--- /dev/null
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/INetwork.java
@@ -0,0 +1,161 @@
+/*
+ * 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.libquassel.syncables.types.invokers;
+
+import android.support.annotation.NonNull;
+
+import java.util.List;
+
+import de.kuschku.libquassel.functions.types.SyncFunction;
+import de.kuschku.libquassel.objects.types.NetworkServer;
+import de.kuschku.libquassel.syncables.types.impl.NetworkInfo;
+import de.kuschku.libquassel.syncables.types.interfaces.QNetwork;
+
+public class INetwork implements Invoker<QNetwork> {
+    @NonNull
+    private static final INetwork invoker = new INetwork();
+
+    private INetwork() {
+    }
+
+    @NonNull
+    public static INetwork get() {
+        return invoker;
+    }
+
+    @Override
+    public void invoke(SyncFunction function, QNetwork obj) {
+        switch (function.methodName) {
+            case "setAutoAwayActive": {
+                obj._setAutoAwayActive((boolean) function.params.get(0));
+            } break;
+            case "setNetworkName": {
+                obj._setNetworkName((String) function.params.get(0));
+            } break;
+            case "setCurrentServer": {
+                obj._setCurrentServer((String) function.params.get(0));
+            } break;
+            case "setConnected": {
+                obj._setConnected((boolean) function.params.get(0));
+            } break;
+            case "setConnectionState": {
+                obj._setConnectionState((int) function.params.get(0));
+            } break;
+            case "setMyNick": {
+                obj._setMyNick((String) function.params.get(0));
+            } break;
+            case "setLatency": {
+                obj._setLatency((int) function.params.get(0));
+            } break;
+            case "setIdentity": {
+                obj._setIdentity((int) function.params.get(0));
+            } break;
+            case "setServerList": {
+                obj._setServerList((List<NetworkServer>) function.params.get(0));
+            } break;
+            case "setUseRandomServer": {
+                obj._setUseRandomServer((boolean) function.params.get(0));
+            } break;
+            case "setPerform": {
+                obj._setPerform((List<String>) function.params.get(0));
+            } break;
+            case "setUseAutoIdentify": {
+                obj._setUseAutoIdentify((boolean) function.params.get(0));
+            } break;
+            case "setAutoIdentifyService": {
+                obj._setAutoIdentifyService((String) function.params.get(0));
+            } break;
+            case "setAutoIdentifyPassword": {
+                obj._setAutoIdentifyPassword((String) function.params.get(0));
+            } break;
+            case "setUseSasl": {
+                obj._setUseSasl((boolean) function.params.get(0));
+            } break;
+            case "setSaslAccount": {
+                obj._setSaslAccount((String) function.params.get(0));
+            } break;
+            case "setSaslPassword": {
+                obj._setSaslPassword((String) function.params.get(0));
+            } break;
+            case "setUseAutoReconnect": {
+                obj._setUseAutoReconnect((boolean) function.params.get(0));
+            } break;
+            case "setAutoReconnectInterval": {
+                obj._setAutoReconnectInterval((int) function.params.get(0));
+            } break;
+            case "setAutoReconnectRetries": {
+                obj._setAutoReconnectRetries((short) function.params.get(0));
+            } break;
+            case "setUnlimitedReconnectRetries": {
+                obj._setUnlimitedReconnectRetries((boolean) function.params.get(0));
+            } break;
+            case "setRejoinChannels": {
+                obj._setRejoinChannels((boolean) function.params.get(0));
+            } break;
+            case "setCodecForServer": {
+                obj._setCodecForServer((String) function.params.get(0));
+            } break;
+            case "setCodecForEncoding": {
+                obj._setCodecForEncoding((String) function.params.get(0));
+            } break;
+            case "setCodecForDecoding": {
+                obj._setCodecForDecoding((String) function.params.get(0));
+            } break;
+            case "addSupport": {
+                if (function.params.size() == 1)
+                    obj._addSupport((String) function.params.get(0));
+                else if (function.params.size() == 2)
+                    obj._addSupport((String) function.params.get(0), (String) function.params.get(1));
+            } break;
+            case "removeSupport": {
+                obj._removeSupport((String) function.params.get(0));
+            } break;
+            case "addIrcUser": {
+                obj._addIrcUser((String) function.params.get(0));
+            } break;
+            case "addIrcChannel": {
+                obj._addIrcChannel((String) function.params.get(0));
+            } break;
+            case "updateNickFromMask": {
+                obj._updateNickFromMask((String) function.params.get(0));
+            } break;
+            case "setNetworkInfo": {
+                obj._setNetworkInfo((NetworkInfo) function.params.get(0));
+            } break;
+            case "ircUserNickChanged": {
+                obj._ircUserNickChanged((String) function.params.get(0), (String) function.params.get(1));
+            } break;
+            case "connect": {
+                obj._connect();
+            } break;
+            case "disconnect": {
+                obj._disconnect();
+            } break;
+            case "removeChansAndUsers": {
+                obj._removeChansAndUsers();
+            } break;
+            case "update": {
+                InvokerHelper.update(obj, function.params.get(0));
+            } break;
+        }
+    }
+}
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/INetworkConfig.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/INetworkConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..c7b9fdbb9f60429849f984ab2b2c5d9437e1993c
--- /dev/null
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/INetworkConfig.java
@@ -0,0 +1,73 @@
+/*
+ * 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.libquassel.syncables.types.invokers;
+
+import android.support.annotation.NonNull;
+
+import de.kuschku.libquassel.functions.types.SyncFunction;
+import de.kuschku.libquassel.syncables.types.interfaces.QNetworkConfig;
+
+public class INetworkConfig implements Invoker<QNetworkConfig> {
+    @NonNull
+    private static final INetworkConfig invoker = new INetworkConfig();
+
+    private INetworkConfig() {
+    }
+
+    @NonNull
+    public static INetworkConfig get() {
+        return invoker;
+    }
+
+    @Override
+    public void invoke(SyncFunction function, QNetworkConfig obj) {
+        switch (function.methodName) {
+            case "setPingTimeoutEnabled": {
+                obj._setPingTimeoutEnabled((boolean) function.params.get(0));
+            } break;
+            case "setPingInterval": {
+                obj._setPingInterval((int) function.params.get(0));
+            } break;
+            case "setMaxPingCount": {
+                obj._setMaxPingCount((int) function.params.get(0));
+            } break;
+            case "setAutoWhoEnabled": {
+                obj._setAutoWhoEnabled((boolean) function.params.get(0));
+            } break;
+            case "setAutoWhoInterval": {
+                obj._setAutoWhoInterval((int) function.params.get(0));
+            } break;
+            case "setAutoWhoNickLimit": {
+                obj._setAutoWhoNickLimit((int) function.params.get(0));
+            } break;
+            case "setAutoWhoDelay": {
+                obj._setAutoWhoDelay((int) function.params.get(0));
+            } break;
+            case "setStandardCtcp": {
+                obj._setStandardCtcp((boolean) function.params.get(0));
+            } break;
+            case "update": {
+                InvokerHelper.update(obj, function.params.get(0));
+            } break;
+        }
+    }
+}
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/Invoker.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/Invoker.java
new file mode 100644
index 0000000000000000000000000000000000000000..56f1fb88f903a433f95890d7043af0398416129a
--- /dev/null
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/Invoker.java
@@ -0,0 +1,28 @@
+/*
+ * 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.libquassel.syncables.types.invokers;
+
+import de.kuschku.libquassel.functions.types.SyncFunction;
+
+public interface Invoker<T> {
+    void invoke(SyncFunction function, T obj);
+}
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/InvokerHelper.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/InvokerHelper.java
new file mode 100644
index 0000000000000000000000000000000000000000..020f56d1ba3d64b706f7678755b339bc77591d83
--- /dev/null
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/InvokerHelper.java
@@ -0,0 +1,45 @@
+/*
+ * 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.libquassel.syncables.types.invokers;
+
+import java.util.Map;
+
+import de.kuschku.libquassel.syncables.types.interfaces.QSyncableObject;
+
+public class InvokerHelper {
+    private InvokerHelper() {
+
+    }
+
+    public static void update(Object object, Object parameter) {
+        if (object instanceof QSyncableObject) {
+            QSyncableObject syncableObject = (QSyncableObject) object;
+            if (parameter instanceof QSyncableObject) {
+                QSyncableObject parameter1 = (QSyncableObject) parameter;
+                syncableObject._update(parameter1);
+            } else if (parameter instanceof Map) {
+                Map parameter1 = (Map) parameter;
+                syncableObject._update(parameter1);
+            }
+        }
+    }
+}
diff --git a/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/InvokerRegistry.java b/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/InvokerRegistry.java
new file mode 100644
index 0000000000000000000000000000000000000000..bd460558efb62a52a66ef6440b2a2935e112b8aa
--- /dev/null
+++ b/app/src/main/java/de/kuschku/libquassel/syncables/types/invokers/InvokerRegistry.java
@@ -0,0 +1,67 @@
+/*
+ * 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.libquassel.syncables.types.invokers;
+
+import de.kuschku.libquassel.functions.types.SyncFunction;
+
+public class InvokerRegistry {
+    private InvokerRegistry() {
+
+    }
+
+    public static <T> Invoker<T> getInvoker(SyncFunction function) {
+        switch (function.className) {
+            case "AliasManager":
+                return (Invoker<T>) IAliasManager.get();
+            case "BufferSyncer":
+                return (Invoker<T>) IBufferSyncer.get();
+            case "BufferViewManager":
+                return (Invoker<T>) IBufferViewManager.get();
+            case "Identity":
+                return (Invoker<T>) IIdentity.get();
+            case "IrcChannel":
+                return (Invoker<T>) IIrcChannel.get();
+            case "Network":
+                return (Invoker<T>) INetwork.get();
+            case "BacklogManager":
+                return (Invoker<T>) IBacklogManager.get();
+            case "BufferViewConfig":
+                return (Invoker<T>) IBufferViewConfig.get();
+            case "CoreInfo":
+                return (Invoker<T>) ICoreInfo.get();
+            case "IgnoreListManager":
+                return (Invoker<T>) IIgnoreListManager.get();
+            case "IrcUser":
+                return (Invoker<T>) IIrcUser.get();
+            case "INetworkConfig":
+                return (Invoker<T>) INetworkConfig.get();
+            default:
+                return null;
+        }
+    }
+
+    public static void invoke(SyncFunction function, Object obj) {
+        Invoker invoker = getInvoker(function);
+        if (invoker != null)
+            invoker.invoke(function, obj);
+    }
+}
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 7bc08f800f943acea8c9a6683d475695f957fe3e..bac7bccdd924b8a4aca1e4f5f72c20b56998be16 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
@@ -87,6 +87,7 @@ import de.kuschku.quasseldroid_ng.ui.chat.fragment.LoadingFragment;
 import de.kuschku.quasseldroid_ng.ui.chat.util.Status;
 import de.kuschku.quasseldroid_ng.ui.coresettings.chatlist.ChatListListActivity;
 import de.kuschku.quasseldroid_ng.ui.coresettings.identity.IdentityListActivity;
+import de.kuschku.quasseldroid_ng.ui.coresettings.ignore.IgnoreListActivity;
 import de.kuschku.quasseldroid_ng.ui.coresettings.network.NetworkListActivity;
 import de.kuschku.quasseldroid_ng.ui.settings.SettingsActivity;
 import de.kuschku.quasseldroid_ng.ui.setup.CoreSetupActivity;
@@ -282,6 +283,9 @@ public class MainActivity extends BoundActivity {
             case R.id.action_networks:
                 startActivity(new Intent(this, NetworkListActivity.class));
                 return true;
+            case R.id.action_ignorelist:
+                startActivity(new Intent(this, IgnoreListActivity.class));
+                return true;
             default:
                 return super.onOptionsItemSelected(item);
         }
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 88e7a4db3476c082a710da6d4c24fbf5363d53d4..aa299fc059c3eaa9517d067caae61f8f2389f84d 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
@@ -32,7 +32,6 @@ import de.kuschku.libquassel.primitives.types.BufferInfo;
 import de.kuschku.libquassel.syncables.types.interfaces.QBufferViewConfig;
 import de.kuschku.libquassel.syncables.types.interfaces.QNetwork;
 import de.kuschku.quasseldroid_ng.ui.theme.AppContext;
-import de.kuschku.util.irc.IrcCaseMapper;
 import de.kuschku.util.observables.callbacks.ElementCallback;
 import de.kuschku.util.observables.callbacks.UICallback;
 import de.kuschku.util.observables.lists.ObservableSet;
@@ -46,7 +45,7 @@ public class NetworkItem implements ParentListItem {
         @Override
         public int compare(Buffer o1, Buffer o2) {
             if (o1.getInfo().type == o2.getInfo().type) {
-                return IrcCaseMapper.toLowerCase(o1.getName()).compareTo(IrcCaseMapper.toLowerCase(o2.getName()));
+                return network.caseMapper().toLowerCase(o1.getName()).compareTo(network.caseMapper().toLowerCase(o2.getName()));
             } else {
                 if (o1.getInfo().type == BufferInfo.Type.STATUS)
                     return -1;
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/coresettings/chatlist/MinimumActivityAdapter.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/coresettings/chatlist/MinimumActivityAdapter.java
index d24225b4ad91fb57da0ec42850c67bbd40d429aa..3db708bff75f89577bf8a7618e45662726521a14 100644
--- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/coresettings/chatlist/MinimumActivityAdapter.java
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/coresettings/chatlist/MinimumActivityAdapter.java
@@ -36,12 +36,7 @@ import de.kuschku.quasseldroid_ng.R;
 import de.kuschku.quasseldroid_ng.ui.theme.AppContext;
 
 class MinimumActivityAdapter implements SpinnerAdapter {
-    final List<QBufferViewConfig.MinimumActivity> list = Arrays.asList(
-            QBufferViewConfig.MinimumActivity.NONE,
-            QBufferViewConfig.MinimumActivity.OTHER,
-            QBufferViewConfig.MinimumActivity.MESSAGE,
-            QBufferViewConfig.MinimumActivity.HIGHLIGHT
-    );
+    final List<QBufferViewConfig.MinimumActivity> list = Arrays.asList(QBufferViewConfig.MinimumActivity.values());
     private final AppContext context;
 
     public MinimumActivityAdapter(AppContext context) {
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/coresettings/ignore/IgnoreListActivity.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/coresettings/ignore/IgnoreListActivity.java
new file mode 100644
index 0000000000000000000000000000000000000000..da244a80810b5d6743b9cc313772ccd25ce5cfed
--- /dev/null
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/coresettings/ignore/IgnoreListActivity.java
@@ -0,0 +1,180 @@
+/*
+ * 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.coresettings.ignore;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.support.design.widget.FloatingActionButton;
+import android.support.v7.widget.DefaultItemAnimator;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.support.v7.widget.SwitchCompat;
+import android.support.v7.widget.Toolbar;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+import butterknife.Bind;
+import butterknife.ButterKnife;
+import de.kuschku.libquassel.syncables.types.impl.IgnoreListManager;
+import de.kuschku.libquassel.syncables.types.interfaces.QIgnoreListManager;
+import de.kuschku.quasseldroid_ng.R;
+import de.kuschku.quasseldroid_ng.ui.coresettings.ignore.helper.IgnoreRuleSerializerHelper;
+import de.kuschku.util.observables.callbacks.wrappers.AdapterUICallbackWrapper;
+import de.kuschku.util.servicebound.BoundActivity;
+import de.kuschku.util.ui.DividerItemDecoration;
+
+public class IgnoreListActivity extends BoundActivity {
+    final OnIgnoreRuleClickListener clickListener = ignoreRule -> {
+        if (ignoreRule != null) {
+            Intent intent = new Intent(this, IgnoreRuleEditActivity.class);
+            intent.putExtra("rule", IgnoreRuleSerializerHelper.serialize(ignoreRule));
+            startActivityForResult(intent, 0, null);
+        }
+    };
+    QIgnoreListManager manager;
+    final OnIgnoreRuleActiveListener activeListener = (ignoreRule, active) -> {
+        if (ignoreRule != null) {
+            manager._toggleIgnoreRule(ignoreRule, active);
+            manager.requestUpdate();
+        }
+    };
+
+    @Bind(R.id.list)
+    RecyclerView list;
+    @Bind(R.id.add)
+    FloatingActionButton add;
+    @Bind(R.id.toolbar)
+    Toolbar toolbar;
+    IgnoreRuleAdapter adapter;
+
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_network_list);
+        ButterKnife.bind(this);
+
+        list.setLayoutManager(new LinearLayoutManager(this));
+        list.setItemAnimator(new DefaultItemAnimator());
+        list.addItemDecoration(new DividerItemDecoration(this));
+        adapter = new IgnoreRuleAdapter();
+        list.setAdapter(adapter);
+
+        add.setOnClickListener(view -> startActivityForResult(new Intent(this, IgnoreRuleEditActivity.class), 0, null));
+
+        setSupportActionBar(toolbar);
+        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+    }
+
+    @Override
+    protected void onConnected() {
+        manager = context.client().ignoreListManager();
+        adapter.setManager(manager);
+    }
+
+    @Override
+    protected void onDisconnected() {
+        manager = null;
+        adapter.setManager(null);
+    }
+
+    @Override
+    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+        if (data != null) {
+            if (resultCode == RESULT_OK) {
+                IgnoreListManager.IgnoreListItem item = IgnoreRuleSerializerHelper.deserialize(data.getBundleExtra("rule"));
+                if (data.getStringExtra("original") != null)
+                    manager._removeIgnoreListItem(data.getStringExtra("original"));
+                manager._addIgnoreListItem(item);
+                manager.requestUpdate();
+            } else if (resultCode == IgnoreRuleEditActivity.RESULT_DELETE) {
+                manager._removeIgnoreListItem(data.getStringExtra("original"));
+                manager.requestUpdate();
+            }
+        }
+    }
+
+    interface OnIgnoreRuleClickListener {
+        void onClick(IgnoreListManager.IgnoreListItem network);
+    }
+
+    interface OnIgnoreRuleActiveListener {
+        void onChange(IgnoreListManager.IgnoreListItem network, boolean active);
+    }
+
+    private class IgnoreRuleAdapter extends RecyclerView.Adapter<IgnoreRuleViewHolder> {
+        final AdapterUICallbackWrapper wrapper = new AdapterUICallbackWrapper(this);
+        QIgnoreListManager manager;
+
+        public void setManager(QIgnoreListManager manager) {
+            if (this.manager != null)
+                this.manager.ignoreList().addCallback(wrapper);
+
+            this.manager = manager;
+
+            if (this.manager != null)
+                this.manager.ignoreList().addCallback(wrapper);
+        }
+
+        @Override
+        public IgnoreRuleViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+            LayoutInflater inflater = LayoutInflater.from(parent.getContext());
+            View view = inflater.inflate(R.layout.widget_settings_ignorerule, parent, false);
+            return new IgnoreRuleViewHolder(view);
+        }
+
+        @Override
+        public void onBindViewHolder(IgnoreRuleViewHolder holder, int position) {
+            holder.bind(manager != null ? manager.ignoreList().get(position) : null);
+        }
+
+        @Override
+        public int getItemCount() {
+            return manager == null ? 0 : manager.ignoreList().size();
+        }
+    }
+
+    class IgnoreRuleViewHolder extends RecyclerView.ViewHolder {
+        @Bind(R.id.text)
+        TextView name;
+
+        @Bind(R.id.active)
+        SwitchCompat active;
+
+        private IgnoreListManager.IgnoreListItem ignoreRule;
+
+        public IgnoreRuleViewHolder(View itemView) {
+            super(itemView);
+            ButterKnife.bind(this, itemView);
+            itemView.setOnClickListener(view -> clickListener.onClick(ignoreRule));
+            active.setOnCheckedChangeListener((view, checked) -> activeListener.onChange(ignoreRule, checked));
+        }
+
+        public void bind(IgnoreListManager.IgnoreListItem ignoreRule) {
+            this.ignoreRule = ignoreRule;
+            name.setText(ignoreRule == null ? "" : ignoreRule.getIgnoreRule().rule());
+            active.setChecked(ignoreRule.isActive());
+        }
+    }
+}
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/coresettings/ignore/IgnoreRuleEditActivity.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/coresettings/ignore/IgnoreRuleEditActivity.java
new file mode 100644
index 0000000000000000000000000000000000000000..7320566e61d103a8aa4227fa4db1f5ab57401384
--- /dev/null
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/coresettings/ignore/IgnoreRuleEditActivity.java
@@ -0,0 +1,194 @@
+/*
+ * 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.coresettings.ignore;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.support.v7.widget.AppCompatSpinner;
+import android.support.v7.widget.Toolbar;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.widget.CheckBox;
+import android.widget.EditText;
+
+import com.afollestad.materialdialogs.MaterialDialog;
+
+import butterknife.Bind;
+import butterknife.ButterKnife;
+import de.kuschku.libquassel.syncables.types.impl.IgnoreListManager;
+import de.kuschku.quasseldroid_ng.R;
+import de.kuschku.quasseldroid_ng.ui.coresettings.ignore.helper.IgnoreRuleSerializerHelper;
+import de.kuschku.quasseldroid_ng.ui.coresettings.ignore.helper.IgnoreTypeAdapter;
+import de.kuschku.quasseldroid_ng.ui.coresettings.ignore.helper.ScopeTypeAdapter;
+import de.kuschku.quasseldroid_ng.ui.coresettings.ignore.helper.StrictnessTypeAdapter;
+import de.kuschku.util.servicebound.BoundActivity;
+
+public class IgnoreRuleEditActivity extends BoundActivity {
+    public static final int RESULT_DELETE = -2;
+
+    @Bind(R.id.toolbar)
+    Toolbar toolbar;
+
+    @Bind(R.id.strictness)
+    AppCompatSpinner strictness;
+
+    @Bind(R.id.type)
+    AppCompatSpinner type;
+
+    @Bind(R.id.ignoreRule)
+    EditText ignoreRule;
+
+    @Bind(R.id.isRegEx)
+    CheckBox isRegEx;
+
+    @Bind(R.id.scopeType)
+    AppCompatSpinner scopeType;
+
+    @Bind(R.id.scope)
+    EditText scope;
+
+    private IgnoreListManager.IgnoreListItem item;
+    private Bundle original;
+
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        setContentView(R.layout.activity_ignorerule_edit);
+        ButterKnife.bind(this);
+
+        setSupportActionBar(toolbar);
+        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+
+        StrictnessTypeAdapter strictnessTypeAdapter = new StrictnessTypeAdapter(context);
+        strictness.setAdapter(strictnessTypeAdapter);
+
+        IgnoreTypeAdapter ignoreTypeAdapter = new IgnoreTypeAdapter(context);
+        type.setAdapter(ignoreTypeAdapter);
+
+        ScopeTypeAdapter scopeTypeAdapter = new ScopeTypeAdapter(context);
+        scopeType.setAdapter(scopeTypeAdapter);
+
+        Intent intent = getIntent();
+        if (intent != null) {
+            original = intent.getBundleExtra("rule");
+            if (original != null) {
+                item = IgnoreRuleSerializerHelper.deserialize(original);
+
+                strictness.setSelection(strictnessTypeAdapter.indexOf(item.getStrictness()));
+                type.setSelection(ignoreTypeAdapter.indexOf(item.getType()));
+                ignoreRule.setText(item.getIgnoreRule().rule());
+                isRegEx.setChecked(item.isRegEx());
+                scopeType.setSelection(scopeTypeAdapter.indexOf(item.getScope()));
+                scope.setText(item.getScopeRule());
+            }
+        }
+    }
+
+    @Override
+    public boolean onCreateOptionsMenu(Menu menu) {
+        if (original != null) {
+            getMenuInflater().inflate(R.menu.confirm_delete, menu);
+        } else {
+            getMenuInflater().inflate(R.menu.confirm, menu);
+        }
+        return super.onCreateOptionsMenu(menu);
+    }
+
+    @Override
+    public void onBackPressed() {
+        if (hasChanged(build())) {
+            new MaterialDialog.Builder(this)
+                    .content(R.string.confirmationUnsavedChanges)
+                    .positiveText(R.string.actionYes)
+                    .negativeText(R.string.actionNo)
+                    .positiveColor(context.themeUtil().res.colorAccent)
+                    .negativeColor(context.themeUtil().res.colorForeground)
+                    .onPositive((dialog, which) -> {
+                        save();
+                        super.onBackPressed();
+                    })
+                    .onNegative((dialog, which) -> super.onBackPressed())
+                    .show();
+        } else {
+            super.onBackPressed();
+        }
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        switch (item.getItemId()) {
+            case R.id.action_delete: {
+                new MaterialDialog.Builder(this)
+                        .content(getString(R.string.confirmationDelete, this.item.getIgnoreRule().rule()))
+                        .positiveText(R.string.actionYes)
+                        .negativeText(R.string.actionNo)
+                        .positiveColor(context.themeUtil().res.colorAccent)
+                        .negativeColor(context.themeUtil().res.colorForeground)
+                        .onPositive((dialog, which) -> {
+                            delete();
+                            finish();
+                        })
+                        .build()
+                        .show();
+            }
+            return true;
+            case R.id.action_confirm: {
+                save();
+                finish();
+            }
+            return true;
+            default:
+                return super.onOptionsItemSelected(item);
+        }
+    }
+
+    private void delete() {
+        Intent intent = new Intent();
+        intent.putExtra("original", original.getString("ignoreRule"));
+        setResult(RESULT_DELETE, intent);
+    }
+
+    private void save() {
+        Intent intent = new Intent();
+        if (original != null)
+            intent.putExtra("original", original.getString("ignoreRule"));
+        intent.putExtra("rule", build());
+        setResult(RESULT_OK, intent);
+    }
+
+    private boolean hasChanged(Bundle bundle) {
+        return this.original != null && bundle != null && !this.original.equals(bundle);
+    }
+
+    private Bundle build() {
+        Bundle bundle = new Bundle();
+        bundle.putInt("strictness", (int) strictness.getSelectedItemId());
+        bundle.putInt("type", (int) type.getSelectedItemId());
+        bundle.putString("ignoreRule", ignoreRule.getText().toString());
+        bundle.putBoolean("isRegEx", isRegEx.isChecked());
+        bundle.putInt("scopeType", (int) scopeType.getSelectedItemId());
+        bundle.putString("scope", scope.getText().toString());
+        return bundle;
+    }
+}
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/coresettings/ignore/helper/IgnoreRuleSerializerHelper.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/coresettings/ignore/helper/IgnoreRuleSerializerHelper.java
new file mode 100644
index 0000000000000000000000000000000000000000..dfb90ef05c1aa0d88a48fc459ad23d5593bec014
--- /dev/null
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/coresettings/ignore/helper/IgnoreRuleSerializerHelper.java
@@ -0,0 +1,55 @@
+/*
+ * 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.coresettings.ignore.helper;
+
+import android.os.Bundle;
+
+import de.kuschku.libquassel.syncables.types.impl.IgnoreListManager;
+
+public class IgnoreRuleSerializerHelper {
+    private IgnoreRuleSerializerHelper() {
+    }
+
+    public static Bundle serialize(IgnoreListManager.IgnoreListItem ignoreRule) {
+        Bundle bundle = new Bundle();
+        bundle.putInt("type", ignoreRule.getType().value);
+        bundle.putString("ignoreRule", ignoreRule.getIgnoreRule().rule());
+        bundle.putBoolean("isRegEx", ignoreRule.isRegEx());
+        bundle.putInt("strictness", ignoreRule.getStrictness().value);
+        bundle.putInt("scope", ignoreRule.getScope().value);
+        bundle.putString("scopeRule", ignoreRule.getScopeRule());
+        bundle.putBoolean("isActive", ignoreRule.isActive());
+        return bundle;
+    }
+
+    public static IgnoreListManager.IgnoreListItem deserialize(Bundle bundle) {
+        return new IgnoreListManager.IgnoreListItem(
+                bundle.getInt("type"),
+                bundle.getString("ignoreRule"),
+                bundle.getBoolean("isRegEx"),
+                bundle.getInt("strictness"),
+                bundle.getInt("scope"),
+                bundle.getString("scopeRule"),
+                bundle.getBoolean("isActive")
+        );
+    }
+}
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/coresettings/ignore/helper/IgnoreTypeAdapter.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/coresettings/ignore/helper/IgnoreTypeAdapter.java
new file mode 100644
index 0000000000000000000000000000000000000000..9bf3e16a9e2709b2080ae417f9ee2046d76c17b5
--- /dev/null
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/coresettings/ignore/helper/IgnoreTypeAdapter.java
@@ -0,0 +1,112 @@
+/*
+ * 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.coresettings.ignore.helper;
+
+import android.database.DataSetObserver;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.SpinnerAdapter;
+import android.widget.TextView;
+
+import java.util.Arrays;
+import java.util.List;
+
+import de.kuschku.libquassel.syncables.types.interfaces.QIgnoreListManager;
+import de.kuschku.quasseldroid_ng.R;
+import de.kuschku.quasseldroid_ng.ui.theme.AppContext;
+
+public class IgnoreTypeAdapter implements SpinnerAdapter {
+    final List<QIgnoreListManager.IgnoreType> list = Arrays.asList(QIgnoreListManager.IgnoreType.values());
+    private final AppContext context;
+
+    public IgnoreTypeAdapter(AppContext context) {
+        this.context = context;
+    }
+
+    @Override
+    public View getDropDownView(int position, View convertView, ViewGroup parent) {
+        LayoutInflater inflater = LayoutInflater.from(parent.getContext());
+        TextView view = (TextView) inflater.inflate(R.layout.widget_spinner_item_toolbar, parent, false);
+        QIgnoreListManager.IgnoreType minimumActivity = getItem(position);
+        view.setText(minimumActivity == null ? "" : context.themeUtil().translations.ignoreType(minimumActivity));
+        return view;
+    }
+
+    @Override
+    public void registerDataSetObserver(DataSetObserver observer) {
+
+    }
+
+    @Override
+    public void unregisterDataSetObserver(DataSetObserver observer) {
+
+    }
+
+    @Override
+    public int getCount() {
+        return list.size();
+    }
+
+    @Override
+    public QIgnoreListManager.IgnoreType getItem(int position) {
+        return list.get(position);
+    }
+
+    @Override
+    public long getItemId(int position) {
+        return getItem(position).value;
+    }
+
+    @Override
+    public boolean hasStableIds() {
+        return true;
+    }
+
+    @Override
+    public View getView(int position, View convertView, ViewGroup parent) {
+        LayoutInflater inflater = LayoutInflater.from(parent.getContext());
+        TextView view = (TextView) inflater.inflate(R.layout.widget_spinner_item_inline, parent, false);
+        QIgnoreListManager.IgnoreType ignoreType = getItem(position);
+        view.setText(ignoreType == null ? "" : context.themeUtil().translations.ignoreType(ignoreType));
+        return view;
+    }
+
+    @Override
+    public int getItemViewType(int position) {
+        return 0;
+    }
+
+    @Override
+    public int getViewTypeCount() {
+        return 1;
+    }
+
+    @Override
+    public boolean isEmpty() {
+        return list.isEmpty();
+    }
+
+    public int indexOf(QIgnoreListManager.IgnoreType ignoreType) {
+        return list.indexOf(ignoreType);
+    }
+}
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/coresettings/ignore/helper/ScopeTypeAdapter.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/coresettings/ignore/helper/ScopeTypeAdapter.java
new file mode 100644
index 0000000000000000000000000000000000000000..6a12181ff4c60de9076d21e337b75270e1eabecf
--- /dev/null
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/coresettings/ignore/helper/ScopeTypeAdapter.java
@@ -0,0 +1,112 @@
+/*
+ * 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.coresettings.ignore.helper;
+
+import android.database.DataSetObserver;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.SpinnerAdapter;
+import android.widget.TextView;
+
+import java.util.Arrays;
+import java.util.List;
+
+import de.kuschku.libquassel.syncables.types.interfaces.QIgnoreListManager;
+import de.kuschku.quasseldroid_ng.R;
+import de.kuschku.quasseldroid_ng.ui.theme.AppContext;
+
+public class ScopeTypeAdapter implements SpinnerAdapter {
+    final List<QIgnoreListManager.ScopeType> list = Arrays.asList(QIgnoreListManager.ScopeType.values());
+    private final AppContext context;
+
+    public ScopeTypeAdapter(AppContext context) {
+        this.context = context;
+    }
+
+    @Override
+    public View getDropDownView(int position, View convertView, ViewGroup parent) {
+        LayoutInflater inflater = LayoutInflater.from(parent.getContext());
+        TextView view = (TextView) inflater.inflate(R.layout.widget_spinner_item_toolbar, parent, false);
+        QIgnoreListManager.ScopeType minimumActivity = getItem(position);
+        view.setText(minimumActivity == null ? "" : context.themeUtil().translations.scopeType(minimumActivity));
+        return view;
+    }
+
+    @Override
+    public void registerDataSetObserver(DataSetObserver observer) {
+
+    }
+
+    @Override
+    public void unregisterDataSetObserver(DataSetObserver observer) {
+
+    }
+
+    @Override
+    public int getCount() {
+        return list.size();
+    }
+
+    @Override
+    public QIgnoreListManager.ScopeType getItem(int position) {
+        return list.get(position);
+    }
+
+    @Override
+    public long getItemId(int position) {
+        return getItem(position).value;
+    }
+
+    @Override
+    public boolean hasStableIds() {
+        return true;
+    }
+
+    @Override
+    public View getView(int position, View convertView, ViewGroup parent) {
+        LayoutInflater inflater = LayoutInflater.from(parent.getContext());
+        TextView view = (TextView) inflater.inflate(R.layout.widget_spinner_item_inline, parent, false);
+        QIgnoreListManager.ScopeType scopeType = getItem(position);
+        view.setText(scopeType == null ? "" : context.themeUtil().translations.scopeType(scopeType));
+        return view;
+    }
+
+    @Override
+    public int getItemViewType(int position) {
+        return 0;
+    }
+
+    @Override
+    public int getViewTypeCount() {
+        return 1;
+    }
+
+    @Override
+    public boolean isEmpty() {
+        return list.isEmpty();
+    }
+
+    public int indexOf(QIgnoreListManager.ScopeType scopeType) {
+        return list.indexOf(scopeType);
+    }
+}
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/coresettings/ignore/helper/StrictnessTypeAdapter.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/coresettings/ignore/helper/StrictnessTypeAdapter.java
new file mode 100644
index 0000000000000000000000000000000000000000..ef22f8e5fdfc2e34f605cbbdef772ba86ed2bc61
--- /dev/null
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/coresettings/ignore/helper/StrictnessTypeAdapter.java
@@ -0,0 +1,115 @@
+/*
+ * 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.coresettings.ignore.helper;
+
+import android.database.DataSetObserver;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.SpinnerAdapter;
+import android.widget.TextView;
+
+import java.util.Arrays;
+import java.util.List;
+
+import de.kuschku.libquassel.syncables.types.interfaces.QIgnoreListManager;
+import de.kuschku.quasseldroid_ng.R;
+import de.kuschku.quasseldroid_ng.ui.theme.AppContext;
+
+public class StrictnessTypeAdapter implements SpinnerAdapter {
+    final List<QIgnoreListManager.StrictnessType> list = Arrays.asList(
+            QIgnoreListManager.StrictnessType.SoftStrictness,
+            QIgnoreListManager.StrictnessType.HardStrictness
+    );
+    private final AppContext context;
+
+    public StrictnessTypeAdapter(AppContext context) {
+        this.context = context;
+    }
+
+    @Override
+    public View getDropDownView(int position, View convertView, ViewGroup parent) {
+        LayoutInflater inflater = LayoutInflater.from(parent.getContext());
+        TextView view = (TextView) inflater.inflate(R.layout.widget_spinner_item_toolbar, parent, false);
+        QIgnoreListManager.StrictnessType minimumActivity = getItem(position);
+        view.setText(minimumActivity == null ? "" : context.themeUtil().translations.strictnessType(minimumActivity));
+        return view;
+    }
+
+    @Override
+    public void registerDataSetObserver(DataSetObserver observer) {
+
+    }
+
+    @Override
+    public void unregisterDataSetObserver(DataSetObserver observer) {
+
+    }
+
+    @Override
+    public int getCount() {
+        return list.size();
+    }
+
+    @Override
+    public QIgnoreListManager.StrictnessType getItem(int position) {
+        return list.get(position);
+    }
+
+    @Override
+    public long getItemId(int position) {
+        return getItem(position).value;
+    }
+
+    @Override
+    public boolean hasStableIds() {
+        return true;
+    }
+
+    @Override
+    public View getView(int position, View convertView, ViewGroup parent) {
+        LayoutInflater inflater = LayoutInflater.from(parent.getContext());
+        TextView view = (TextView) inflater.inflate(R.layout.widget_spinner_item_inline, parent, false);
+        QIgnoreListManager.StrictnessType strictnessType = getItem(position);
+        view.setText(strictnessType == null ? "" : context.themeUtil().translations.strictnessType(strictnessType));
+        return view;
+    }
+
+    @Override
+    public int getItemViewType(int position) {
+        return 0;
+    }
+
+    @Override
+    public int getViewTypeCount() {
+        return 1;
+    }
+
+    @Override
+    public boolean isEmpty() {
+        return list.isEmpty();
+    }
+
+    public int indexOf(QIgnoreListManager.StrictnessType strictnessType) {
+        return list.indexOf(strictnessType);
+    }
+}
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/coresettings/network/AllNetworksItem.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/coresettings/network/AllNetworksItem.java
index 9e8c374dd7f54fd7e1ae5fd5d222dff48454110a..c8fca222cc7a1a456122b195aa162ec915eb9547 100644
--- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/coresettings/network/AllNetworksItem.java
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/coresettings/network/AllNetworksItem.java
@@ -34,6 +34,7 @@ import de.kuschku.libquassel.syncables.types.interfaces.QIrcChannel;
 import de.kuschku.libquassel.syncables.types.interfaces.QIrcUser;
 import de.kuschku.libquassel.syncables.types.interfaces.QNetwork;
 import de.kuschku.quasseldroid_ng.R;
+import de.kuschku.util.irc.IrcCaseMappers;
 import de.kuschku.util.irc.chanmodes.IrcModeProvider;
 import de.kuschku.util.observables.callbacks.GeneralCallback;
 
@@ -731,6 +732,11 @@ class AllNetworksItem implements QNetwork {
 
     }
 
+    @Override
+    public IrcCaseMappers.IrcCaseMapper caseMapper() {
+        return null;
+    }
+
     @Override
     public void addObserver(GeneralCallback<QNetwork> o) {
 
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/coresettings/network/server/NetworkServerEditActivity.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/coresettings/network/server/NetworkServerEditActivity.java
index 808af7c19d3add840b99831dc9eddb52108b71ee..22dfc87d0b0a6ab3c28c991bfd560236f997da73 100644
--- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/coresettings/network/server/NetworkServerEditActivity.java
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/coresettings/network/server/NetworkServerEditActivity.java
@@ -53,6 +53,8 @@ import de.kuschku.util.ui.AnimationHelper;
 
 public class NetworkServerEditActivity extends BoundActivity {
 
+    public static final int RESULT_DELETE = -2;
+
     @Bind(R.id.toolbar)
     Toolbar toolbar;
 
@@ -158,13 +160,23 @@ public class NetworkServerEditActivity extends BoundActivity {
 
     @Override
     public boolean onCreateOptionsMenu(Menu menu) {
-        getMenuInflater().inflate(R.menu.confirm, menu);
+        if (id == -1)
+            getMenuInflater().inflate(R.menu.confirm, menu);
+        else
+            getMenuInflater().inflate(R.menu.confirm_delete, menu);
         return super.onCreateOptionsMenu(menu);
     }
 
     @Override
     public boolean onOptionsItemSelected(MenuItem item) {
         switch (item.getItemId()) {
+            case R.id.action_delete: {
+                Intent intent = new Intent();
+                intent.putExtra("id", id);
+                setResult(RESULT_DELETE, intent);
+                finish();
+            }
+            return true;
             case R.id.action_confirm: {
                 Intent intent = new Intent();
                 intent.putExtra("server", NetworkServerSerializeHelper.serialize(new NetworkServer(
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/coresettings/network/server/NetworkServerListActivity.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/coresettings/network/server/NetworkServerListActivity.java
index 816adac5cd81f5fce4c403a526db522f2ad08b94..4c6c5f5ac8c55cdd9aaae2353fe99eff0624978c 100644
--- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/coresettings/network/server/NetworkServerListActivity.java
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/coresettings/network/server/NetworkServerListActivity.java
@@ -135,6 +135,11 @@ public class NetworkServerListActivity extends BoundActivity implements OnStartD
             } else {
                 servers.set(id, server);
             }
+        } else if (resultCode == NetworkServerEditActivity.RESULT_DELETE && data != null) {
+            int id = data.getIntExtra("id", -1);
+            if (id != -1) {
+                servers.remove(id);
+            }
         }
         super.onActivityResult(requestCode, resultCode, data);
     }
diff --git a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/theme/ThemeUtil.java b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/theme/ThemeUtil.java
index 3f812902b80b3f1c9cf2b495ee8f63ec5176b69c..11c2f7910980d7bc0c807bf87db1db0689e7b881 100644
--- a/app/src/main/java/de/kuschku/quasseldroid_ng/ui/theme/ThemeUtil.java
+++ b/app/src/main/java/de/kuschku/quasseldroid_ng/ui/theme/ThemeUtil.java
@@ -36,6 +36,7 @@ import de.kuschku.libquassel.events.ConnectionChangeEvent;
 import de.kuschku.libquassel.objects.types.NetworkServer;
 import de.kuschku.libquassel.primitives.types.BufferInfo;
 import de.kuschku.libquassel.syncables.types.interfaces.QBufferViewConfig;
+import de.kuschku.libquassel.syncables.types.interfaces.QIgnoreListManager;
 import de.kuschku.quasseldroid_ng.R;
 import de.kuschku.util.annotationbind.AutoBinder;
 import de.kuschku.util.annotationbind.AutoColor;
@@ -628,6 +629,54 @@ public class ThemeUtil {
         @AutoString(R.string.statusWelcome)
         public String statusWelcome;
 
+        @AutoString(R.string.labelNetworkServerProxyDefault)
+        public String labelNetworkServerProxyDefault;
+
+        @AutoString(R.string.labelNetworkServerProxySocks5)
+        public String labelNetworkServerProxySocks5;
+
+        @AutoString(R.string.labelNetworkServerProxyHttp)
+        public String labelNetworkServerProxyHttp;
+
+        @AutoString(R.string.labelChatlistMinimumActivityNone)
+        public String labelChatlistMinimumActivityNone;
+
+        @AutoString(R.string.labelChatlistMinimumActivityOther)
+        public String labelChatlistMinimumActivityOther;
+
+        @AutoString(R.string.labelChatlistMinimumActivityMessage)
+        public String labelChatlistMinimumActivityMessage;
+
+        @AutoString(R.string.labelChatlistMinimumActivityHighlight)
+        public String labelChatlistMinimumActivityHighlight;
+
+        @AutoString(R.string.labelIgnoreStrictnessUnmatched)
+        public String labelIgnoreStrictnessUnmatched;
+
+        @AutoString(R.string.labelIgnoreStrictnessSoft)
+        public String labelIgnoreStrictnessSoft;
+
+        @AutoString(R.string.labelIgnoreStrictnessHard)
+        public String labelIgnoreStrictnessHard;
+
+        @AutoString(R.string.labelIgnoreRuleSender)
+        public String labelIgnoreRuleSender;
+
+        @AutoString(R.string.labelIgnoreRuleMessage)
+        public String labelIgnoreRuleMessage;
+
+        @AutoString(R.string.labelIgnoreRuleCtcp)
+        public String labelIgnoreRuleCtcp;
+
+        @AutoString(R.string.labelIgnoreScopeGlobal)
+        public String labelIgnoreScopeGlobal;
+
+        @AutoString(R.string.labelIgnoreScopeNetwork)
+        public String labelIgnoreScopeNetwork;
+
+        @AutoString(R.string.labelIgnoreScopeChannel)
+        public String labelIgnoreScopeChannel;
+
         @NonNull
         public CharSequence formatUsername(@NonNull CharSequence nick, @NonNull CharSequence hostmask) {
             return SpanFormatter.format(usernameHostmask, nick, hostmask);
@@ -720,11 +769,11 @@ public class ThemeUtil {
             switch (type) {
                 default:
                 case DefaultProxy:
-                    return "No Proxy";
+                    return labelNetworkServerProxyDefault;
                 case Socks5Proxy:
-                    return "Socks5";
+                    return labelNetworkServerProxySocks5;
                 case HttpProxy:
-                    return "Http";
+                    return labelNetworkServerProxyHttp;
             }
         }
 
@@ -732,13 +781,49 @@ public class ThemeUtil {
             switch (minimumActivity) {
                 default:
                 case NONE:
-                    return "No Activity";
+                    return labelChatlistMinimumActivityNone;
                 case OTHER:
-                    return "Other Activity";
+                    return labelChatlistMinimumActivityOther;
                 case MESSAGE:
-                    return "Message";
+                    return labelChatlistMinimumActivityMessage;
                 case HIGHLIGHT:
-                    return "Highlight";
+                    return labelChatlistMinimumActivityHighlight;
+            }
+        }
+
+        public String strictnessType(QIgnoreListManager.StrictnessType strictnessType) {
+            switch (strictnessType) {
+                default:
+                case UnmatchedStrictness:
+                    return labelIgnoreStrictnessUnmatched;
+                case SoftStrictness:
+                    return labelIgnoreStrictnessSoft;
+                case HardStrictness:
+                    return labelIgnoreStrictnessHard;
+            }
+        }
+
+        public String ignoreType(QIgnoreListManager.IgnoreType ignoreType) {
+            switch (ignoreType) {
+                default:
+                case SenderIgnore:
+                    return labelIgnoreRuleSender;
+                case MessageIgnore:
+                    return labelIgnoreRuleMessage;
+                case CtcpIgnore:
+                    return labelIgnoreRuleCtcp;
+            }
+        }
+
+        public String scopeType(QIgnoreListManager.ScopeType scopeType) {
+            switch (scopeType) {
+                default:
+                case GlobalScope:
+                    return labelIgnoreScopeGlobal;
+                case NetworkScope:
+                    return labelIgnoreScopeNetwork;
+                case ChannelScope:
+                    return labelIgnoreScopeChannel;
             }
         }
     }
diff --git a/app/src/main/java/de/kuschku/util/irc/IrcCaseMappers.java b/app/src/main/java/de/kuschku/util/irc/IrcCaseMappers.java
new file mode 100644
index 0000000000000000000000000000000000000000..cd3dd28cc3bdb1faf9f5ebdb712c77f05e0cdf1b
--- /dev/null
+++ b/app/src/main/java/de/kuschku/util/irc/IrcCaseMappers.java
@@ -0,0 +1,94 @@
+/*
+ * 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.util.irc;
+
+import android.support.annotation.Nullable;
+
+import java.util.Locale;
+
+public class IrcCaseMappers {
+    public static IrcCaseMapper irc = new UnicodeCaseMapper();
+    public static IrcCaseMapper unicode = new ClassicalIrcCaseMapper();
+
+    private IrcCaseMappers() {
+
+    }
+
+    public interface IrcCaseMapper {
+        boolean equalsIgnoreCase(@Nullable String a, @Nullable String b);
+
+        @Nullable
+        String toLowerCase(@Nullable String in);
+
+        @Nullable
+        String toUpperCase(@Nullable String in);
+    }
+
+    static class UnicodeCaseMapper implements IrcCaseMapper {
+
+        @Override
+        public boolean equalsIgnoreCase(@Nullable String a, @Nullable String b) {
+            if (a == null || b == null)
+                return a == null && b == null;
+            else
+                return a.equalsIgnoreCase(b);
+        }
+
+        @Nullable
+        @Override
+        public String toLowerCase(@Nullable String in) {
+            return in != null ? in.toLowerCase(Locale.US) : null;
+        }
+
+        @Nullable
+        @Override
+        public String toUpperCase(@Nullable String in) {
+            return in != null ? in.toUpperCase(Locale.US) : null;
+        }
+    }
+
+    static class ClassicalIrcCaseMapper implements IrcCaseMapper {
+        @Nullable
+        public String toLowerCase(@Nullable String s) {
+            return s != null ? s.toLowerCase(Locale.US)
+                    .replace('[', '{')
+                    .replace(']', '}')
+                    .replace('^', '~') : null;
+        }
+
+        @Nullable
+        public String toUpperCase(@Nullable String s) {
+            return s != null ? s.toUpperCase(Locale.US)
+                    .replace('{', '[')
+                    .replace('}', ']')
+                    .replace('~', '^') : null;
+        }
+
+        @Override
+        public boolean equalsIgnoreCase(@Nullable String a, @Nullable String b) {
+            if (a == null || b == null)
+                return a == null && b == null;
+            else
+                return toLowerCase(a).equals(toLowerCase(b)) || toUpperCase(a).equals(toUpperCase(b));
+        }
+    }
+}
diff --git a/app/src/main/java/de/kuschku/util/observables/lists/ObservableSortedList.java b/app/src/main/java/de/kuschku/util/observables/lists/ObservableSortedList.java
index 3ce351543a23f011c741a23a11ecb1740569a185..eb8155929433b4b620db3f81a059731cde955fdd 100644
--- a/app/src/main/java/de/kuschku/util/observables/lists/ObservableSortedList.java
+++ b/app/src/main/java/de/kuschku/util/observables/lists/ObservableSortedList.java
@@ -25,8 +25,6 @@ import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 import android.support.v7.util.SortedList;
 
-import com.afollestad.materialdialogs.MaterialDialog;
-
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -232,8 +230,19 @@ public class ObservableSortedList<T> implements IObservableList<UICallback, T> {
 
     @NonNull
     @Override
-    public <T1> T1[] toArray(@NonNull T1[] array) {
-        throw new MaterialDialog.NotImplementedException("Not implemented");
+    public <T1> T1[] toArray(@NonNull T1[] a) {
+        try {
+            Object[] elements = toArray();
+            if (a.length < elements.length)
+                // Make a new array of a's runtime type, but my contents:
+                return (T1[]) Arrays.copyOf(elements, elements.length, a.getClass());
+            System.arraycopy(elements, 0, a, 0, elements.length);
+            if (a.length > elements.length)
+                a[elements.length] = null;
+            return a;
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
     }
 
     public void notifyItemChanged(int position) {
diff --git a/app/src/main/res/layout/activity_ignorerule_edit.xml b/app/src/main/res/layout/activity_ignorerule_edit.xml
new file mode 100644
index 0000000000000000000000000000000000000000..744d02d33b446a982c5e55f544922ed0636db723
--- /dev/null
+++ b/app/src/main/res/layout/activity_ignorerule_edit.xml
@@ -0,0 +1,166 @@
+<?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"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical">
+
+    <android.support.design.widget.AppBarLayout
+        android:id="@+id/appBar"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:theme="?attr/actionBarTheme">
+
+        <android.support.v7.widget.Toolbar
+            android:id="@+id/toolbar"
+            android:layout_width="match_parent"
+            android:layout_height="?attr/actionBarSize"/>
+
+    </android.support.design.widget.AppBarLayout>
+
+    <ScrollView
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="vertical"
+            android:padding="16dp">
+
+            <LinearLayout
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:orientation="vertical"
+                android:paddingTop="16dp">
+
+                <TextView
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:layout_gravity="center_vertical"
+                    android:paddingBottom="8dp"
+                    android:paddingLeft="3dp"
+                    android:paddingRight="3dp"
+                    android:text="@string/labelIgnoreRuleStrictness"
+                    android:textSize="12sp"/>
+
+                <android.support.v7.widget.AppCompatSpinner
+                    android:id="@+id/strictness"
+                    style="@style/Base.Widget.AppCompat.Spinner.Underlined"
+                    android:layout_width="match_parent"
+                    android:layout_height="48dp"
+                    android:layout_gravity="center_vertical"
+                    android:layout_marginBottom="8dp"
+                    app:popupTheme="@style/AppTheme.PopupOverlay"/>
+
+            </LinearLayout>
+
+            <LinearLayout
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:orientation="vertical"
+                android:paddingTop="16dp">
+
+                <TextView
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:layout_gravity="center_vertical"
+                    android:paddingBottom="8dp"
+                    android:paddingLeft="3dp"
+                    android:paddingRight="3dp"
+                    android:text="@string/labelIgnoreRuleType"
+                    android:textSize="12sp"/>
+
+                <android.support.v7.widget.AppCompatSpinner
+                    android:id="@+id/type"
+                    style="@style/Base.Widget.AppCompat.Spinner.Underlined"
+                    android:layout_width="match_parent"
+                    android:layout_height="48dp"
+                    android:layout_gravity="center_vertical"
+                    android:layout_marginBottom="8dp"
+                    app:popupTheme="@style/AppTheme.PopupOverlay"/>
+
+            </LinearLayout>
+
+            <android.support.design.widget.TextInputLayout
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content">
+
+                <android.support.design.widget.TextInputEditText
+                    android:id="@+id/ignoreRule"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:hint="@string/labelIgnoreRule"/>
+
+            </android.support.design.widget.TextInputLayout>
+
+            <android.support.v7.widget.AppCompatCheckBox
+                android:id="@+id/isRegEx"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:text="@string/labelIgnoreRuleIsRegEx"/>
+
+            <TextView
+                android:layout_width="match_parent"
+                android:layout_height="48dp"
+                android:gravity="center_vertical"
+                android:text="@string/labelIgnoreRuleScope"
+                android:textColor="?attr/colorAccent"
+                android:textSize="14sp"/>
+
+            <LinearLayout
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:orientation="vertical"
+                android:paddingTop="16dp">
+
+                <android.support.v7.widget.AppCompatSpinner
+                    android:id="@+id/scopeType"
+                    style="@style/Base.Widget.AppCompat.Spinner.Underlined"
+                    android:layout_width="match_parent"
+                    android:layout_height="48dp"
+                    android:layout_gravity="center_vertical"
+                    android:layout_marginBottom="8dp"
+                    app:popupTheme="@style/AppTheme.PopupOverlay"/>
+
+            </LinearLayout>
+
+            <android.support.design.widget.TextInputLayout
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content">
+
+                <android.support.design.widget.TextInputEditText
+                    android:id="@+id/scope"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"/>
+
+            </android.support.design.widget.TextInputLayout>
+
+        </LinearLayout>
+
+    </ScrollView>
+
+</LinearLayout>
\ No newline at end of file
diff --git a/app/src/main/res/layout/widget_settings_ignorerule.xml b/app/src/main/res/layout/widget_settings_ignorerule.xml
new file mode 100644
index 0000000000000000000000000000000000000000..649420af2f1d9fbd10ab3bea03ab1282aebf7e76
--- /dev/null
+++ b/app/src/main/res/layout/widget_settings_ignorerule.xml
@@ -0,0 +1,51 @@
+<?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="56dp"
+              android:background="?selectableItemBackground"
+              android:clickable="true"
+              android:orientation="horizontal"
+              android:paddingLeft="?listPreferredItemPaddingLeft"
+              android:paddingRight="?listPreferredItemPaddingRight">
+
+    <TextView
+        android:id="@+id/text"
+        android:layout_width="0dip"
+        android:layout_height="match_parent"
+        android:layout_marginLeft="16dp"
+        android:layout_marginRight="16dp"
+        android:layout_weight="1"
+        android:gravity="center_vertical|start"
+        android:lines="1"
+        android:singleLine="true"
+        android:textSize="16sp"/>
+
+    <android.support.v7.widget.SwitchCompat
+        android:id="@+id/active"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_vertical"/>
+
+</LinearLayout>
+
diff --git a/app/src/main/res/values/strings_coresettings.xml b/app/src/main/res/values/strings_coresettings.xml
index 617883996e26da5fee0abced4ee4b33fb7baa7d4..a68570b6a32ede51671642b7806031792e4d2f81 100644
--- a/app/src/main/res/values/strings_coresettings.xml
+++ b/app/src/main/res/values/strings_coresettings.xml
@@ -32,6 +32,11 @@
     <string name="labelChatlistShowQueries">Show queries</string>
     <string name="labelChatlistSortAlphabetically">Sort alphabetically</string>
 
+    <string name="labelChatlistMinimumActivityNone">labelChatlistMinimumActivityNone</string>
+    <string name="labelChatlistMinimumActivityOther">labelChatlistMinimumActivityOther</string>
+    <string name="labelChatlistMinimumActivityMessage">labelChatlistMinimumActivityMessage</string>
+    <string name="labelChatlistMinimumActivityHighlight">labelChatlistMinimumActivityHighlight</string>
+
     <string name="labelIdentityAway">Away</string>
     <string name="labelIdentityAwayReason">Reason</string>
     <string name="labelIdentityDetachAway">Away on Detach</string>
@@ -44,6 +49,24 @@
     <string name="labelIdentityQuitReason">Quit Reason</string>
     <string name="labelIdentityRealName">Real Name</string>
 
+    <string name="labelIgnoreRule">Ignore Rule</string>
+    <string name="labelIgnoreRuleIsRegEx">Regular Expression</string>
+    <string name="labelIgnoreRuleScope">Scope</string>
+    <string name="labelIgnoreRuleStrictness">Strictness</string>
+    <string name="labelIgnoreRuleType">Rule Type</string>
+
+    <string name="labelIgnoreStrictnessUnmatched">Unmatched</string>
+    <string name="labelIgnoreStrictnessSoft">Dynamic</string>
+    <string name="labelIgnoreStrictnessHard">Permanent</string>
+
+    <string name="labelIgnoreRuleSender">Sender</string>
+    <string name="labelIgnoreRuleMessage">Message</string>
+    <string name="labelIgnoreRuleCtcp">CTCP</string>
+
+    <string name="labelIgnoreScopeGlobal">Global</string>
+    <string name="labelIgnoreScopeNetwork">Network</string>
+    <string name="labelIgnoreScopeChannel">Channel</string>
+
     <string name="labelNetworkAutoIdentify">Auto Identify</string>
     <string name="labelNetworkAutoIdentifyPassword">Password</string>
     <string name="labelNetworkAutoIdentifyService">Service</string>
@@ -72,4 +95,8 @@
     <string name="labelNetworkServerProxyType">Type</string>
     <string name="labelNetworkServerProxyUser">User</string>
     <string name="labelNetworkServerUseSSL">SSL</string>
+
+    <string name="labelNetworkServerProxyDefault">Default Proxy</string>
+    <string name="labelNetworkServerProxySocks5">Socks5</string>
+    <string name="labelNetworkServerProxyHttp">Http</string>
 </resources>
\ No newline at end of file
diff --git a/app/src/main/res/values/strings_titles.xml b/app/src/main/res/values/strings_titles.xml
index 141b26294652927240dbcdbe2088f14c954f5c70..18355311bfbb7b45c89ca5f7648031c65ae687d8 100644
--- a/app/src/main/res/values/strings_titles.xml
+++ b/app/src/main/res/values/strings_titles.xml
@@ -33,6 +33,8 @@
     <string name="titleEditChatLists">Edit Chat Lists</string>
     <string name="titleEditIdentities">Edit Identities</string>
     <string name="titleEditIdentity">Edit Identity</string>
+    <string name="titleEditIgnoreRule">Edit Ignore Rule</string>
+    <string name="titleEditIgnoreList">Edit Ignore List</string>
     <string name="titleEditNetwork">Edit Network</string>
     <string name="titleEditNetworkServer">Edit NetworkServer</string>
     <string name="titleEditNetworkServers">Edit NetworkServers</string>