diff --git a/omemo/CHANGELOG b/omemo/CHANGELOG
index 1e588f03de3362d02426adbd68e6d25b1ad366ae..9e332dde132a37ab6f58614d0d5461647f1ea6a4 100644
--- a/omemo/CHANGELOG
+++ b/omemo/CHANGELOG
@@ -1,3 +1,8 @@
+0.9.5 / 2016-10-10
+- Add GroupChat BETA
+- Add Option to delete Fingerprints
+- Add Option to deactivate Accounts for OMEMO
+
 0.9.0 / 2016-08-28
 - Send INFO message to resources who dont support OMEMO
 - Check dependencys and give correct error message
diff --git a/omemo/README.md b/omemo/README.md
index 7196020f9de64a12aefb289d56faabafa6c510af..8b1095cf40dfc3fbe20f3a61a795e333dac94159 100644
--- a/omemo/README.md
+++ b/omemo/README.md
@@ -57,6 +57,13 @@ you have to trust at least **one** fingerprint to send messages.
 you can receive messages from fingerprints where you didnt made a trust decision, but you cant
 receive Messages from *not trusted* fingerprints
 
+## Filetransfer
+
+For Filetransfer use the **httpupload** plugin.
+
+For decrypting and showing pictures in chat use the **url_image_preview** plugin.
+
+If you want to use these plugins together with *OMEMO* you have to install the `python-cryptography` package
 
 ## Debugging
 To see OMEMO related debug output start Gajim with the parameter `-l
diff --git a/omemo/__init__.py b/omemo/__init__.py
index 50dd68f20d9f8a11d0b1614900b3b29afefa01e0..943bc231e0b68d9a21209249161645e7d3819176 100644
--- a/omemo/__init__.py
+++ b/omemo/__init__.py
@@ -21,14 +21,15 @@
 import logging
 import os
 import sqlite3
-import os
+import shutil
+import message_control
 
-from common import caps_cache, gajim, ged
+from common import caps_cache, gajim, ged, configpaths
 from common.pep import SUPPORTED_PERSONAL_USER_EVENTS
 from plugins import GajimPlugin
 from plugins.helpers import log_calls
 from nbxmpp.simplexml import Node
-from nbxmpp import NS_CORRECT
+from nbxmpp import NS_CORRECT, NS_ADDRESS
 
 from . import ui
 from .ui import Ui
@@ -40,7 +41,7 @@ from .xmpp import (
 
 from common import demandimport
 demandimport.enable()
-demandimport.ignore += ['_imp']
+demandimport.ignore += ['_imp', '_thread', 'axolotl']
 
 
 IQ_CALLBACK = {}
@@ -54,42 +55,51 @@ ERROR_MSG = ''
 
 NS_HINTS = 'urn:xmpp:hints'
 NS_PGP = 'urn:xmpp:openpgp:0'
-DB_DIR = gajim.gajimpaths.data_root
+DB_DIR_OLD = gajim.gajimpaths.data_root
+DB_DIR_NEW = configpaths.gajimpaths['MY_DATA']
 
 log = logging.getLogger('gajim.plugin_system.omemo')
 
 try:
-    from .omemo.state import OmemoState
-except Exception as e:
-    log.error(e)
-    ERROR_MSG = 'Error: ' + str(e)
-
-try:
-    import google.protobuf
+    prototest = __import__('google.protobuf')
 except Exception as e:
     log.error(e)
     ERROR_MSG = PROTOBUF_MISSING
 
 try:
-    import axolotl
+    axolotltest = __import__('axolotl')
 except Exception as e:
     log.error(e)
     ERROR_MSG = AXOLOTL_MISSING
 
+if not ERROR_MSG:
+    try:
+        from .omemo.state import OmemoState
+    except Exception as e:
+        log.error(e)
+        ERROR_MSG = 'Error: ' + str(e)
+
 GAJIM_VER = gajim.config.get('version')
+GROUPCHAT = False
 
 if os.name != 'nt':
     try:
         SETUPTOOLS_MISSING = False
-        from pkg_resources import parse_version
+        pkg = __import__('pkg_resources')
     except Exception as e:
         log.error(e)
         SETUPTOOLS_MISSING = True
         ERROR_MSG = 'You are missing the Setuptools package.'
 
     if not SETUPTOOLS_MISSING:
-        if parse_version(GAJIM_VER) < parse_version('0.16.5'):
+        if pkg.parse_version(GAJIM_VER) < pkg.parse_version('0.16.5'):
             ERROR_MSG = GAJIM_VERSION
+        if pkg.parse_version(GAJIM_VER) > pkg.parse_version('0.16.5'):
+            GROUPCHAT = True
+else:
+    # if GAJIM_VER < 0.16.5, the Plugin fails on missing dependencys earlier
+    if not GAJIM_VER == '0.16.5':
+        GROUPCHAT = True
 
 # pylint: disable=no-init
 # pylint: disable=attribute-defined-outside-init
@@ -99,6 +109,8 @@ class OmemoPlugin(GajimPlugin):
 
     omemo_states = {}
     ui_list = {}
+    groupchat = {}
+    temp_groupchat = {}
 
     @log_calls('OmemoPlugin')
     def init(self):
@@ -116,15 +128,48 @@ class OmemoPlugin(GajimPlugin):
             'stanza-message-outgoing':
             (ged.PRECORE, self.handle_outgoing_stanza),
             'message-outgoing':
-            (ged.PRECORE, self.handle_outgoing_event),
-        }
+            (ged.PRECORE, self.handle_outgoing_event)}
+        if GROUPCHAT:
+            self.events_handlers['gc-stanza-message-outgoing'] =\
+                (ged.PRECORE, self.handle_outgoing_gc_stanza)
+            self.events_handlers['gc-presence-received'] =\
+                (ged.PRECORE, self.gc_presence_received)
+            self.events_handlers['gc-config-changed-received'] =\
+                (ged.PRECORE, self.gc_config_changed_received)
+            self.events_handlers['muc-admin-received'] =\
+                (ged.PRECORE, self.room_memberlist_received)
+
         self.config_dialog = ui.OMEMOConfigDialog(self)
         self.gui_extension_points = {'chat_control': (self.connect_ui,
-                                                      self.disconnect_ui)}
+                                                      self.disconnect_ui),
+                                     'groupchat_control': (self.connect_ui,
+                                                           self.disconnect_ui)}
         SUPPORTED_PERSONAL_USER_EVENTS.append(DevicelistPEP)
         self.plugin = self
         self.announced = []
         self.query_for_bundles = []
+        self.disabled_accounts = []
+        self.gc_message = {}
+
+        self.config_default_values = {'DISABLED_ACCOUNTS': ([], ''), }
+
+        for account in self.plugin.config['DISABLED_ACCOUNTS']:
+            self.disabled_accounts.append(account)
+
+    def migrate_dbpath(self, account, my_jid):
+        old_dbpath = os.path.join(DB_DIR_OLD, 'omemo_' + account + '.db')
+        new_dbpath = os.path.join(DB_DIR_NEW, 'omemo_' + my_jid + '.db')
+
+        if os.path.exists(old_dbpath):
+            log.debug('Migrating DBName and Path ..')
+            try:
+                shutil.move(old_dbpath, new_dbpath)
+                return new_dbpath
+            except Exception:
+                log.exception('Migration Error:')
+                return old_dbpath
+
+        return new_dbpath
 
     @log_calls('OmemoPlugin')
     def get_omemo_state(self, account):
@@ -140,13 +185,14 @@ class OmemoPlugin(GajimPlugin):
             -------
             OmemoState
         """
+        if account in self.disabled_accounts:
+            return
         if account not in self.omemo_states:
             self.deactivate_gajim_e2e(account)
-            db_path = os.path.join(DB_DIR, 'omemo_' + account + '.db')
-            conn = sqlite3.connect(db_path, check_same_thread=False)
-
             my_jid = gajim.get_jid_from_account(account)
+            db_path = self.migrate_dbpath(account, my_jid)
 
+            conn = sqlite3.connect(db_path, check_same_thread=False)
             self.omemo_states[account] = OmemoState(my_jid, conn, account,
                                                     self.plugin)
 
@@ -170,6 +216,8 @@ class OmemoPlugin(GajimPlugin):
             event : SignedInEvent
         """
         account = event.conn.name
+        if account in self.disabled_accounts:
+            return
         log.debug(account +
                   ' => Announce Support after Sign In')
         self.query_for_bundles = []
@@ -183,11 +231,15 @@ class OmemoPlugin(GajimPlugin):
         """ Method called when the Plugin is activated in the PluginManager
         """
         self.query_for_bundles = []
-        if NS_NOTIFY not in gajim.gajim_common_features:
-            gajim.gajim_common_features.append(NS_NOTIFY)
-        self._compute_caps_hash()
-        # Publish bundle information
+        # Publish bundle information and Entity Caps
         for account in gajim.connections:
+            if account in self.disabled_accounts:
+                log.debug(account +
+                          ' => Account is disabled')
+                continue
+            if NS_NOTIFY not in gajim.gajim_optional_features[account]:
+                gajim.gajim_optional_features[account].append(NS_NOTIFY)
+            self._compute_caps_hash(account)
             if account not in self.announced:
                 if gajim.account_is_connected(account):
                     log.debug(account +
@@ -202,23 +254,25 @@ class OmemoPlugin(GajimPlugin):
 
             Removes OMEMO from the Entity Capabilities list
         """
-        if NS_NOTIFY in gajim.gajim_common_features:
-            gajim.gajim_common_features.remove(NS_NOTIFY)
-        self._compute_caps_hash()
+        for account in gajim.connections:
+            if account in self.disabled_accounts:
+                continue
+            if NS_NOTIFY in gajim.gajim_optional_features[account]:
+                gajim.gajim_optional_features[account].remove(NS_NOTIFY)
+            self._compute_caps_hash(account)
 
     @staticmethod
-    def _compute_caps_hash():
+    def _compute_caps_hash(account):
         """ Computes the hash for Entity Capabilities and publishes it """
-        for acc in gajim.connections:
-            gajim.caps_hash[acc] = caps_cache.compute_caps_hash(
-                [gajim.gajim_identity],
-                gajim.gajim_common_features +
-                gajim.gajim_optional_features[acc])
-            # re-send presence with new hash
-            connected = gajim.connections[acc].connected
-            if connected > 1 and gajim.SHOW_LIST[connected] != 'invisible':
-                gajim.connections[acc].change_status(
-                    gajim.SHOW_LIST[connected], gajim.connections[acc].status)
+        gajim.caps_hash[account] = caps_cache.compute_caps_hash(
+            [gajim.gajim_identity],
+            gajim.gajim_common_features +
+            gajim.gajim_optional_features[account])
+        # re-send presence with new hash
+        connected = gajim.connections[account].connected
+        if connected > 1 and gajim.SHOW_LIST[connected] != 'invisible':
+            gajim.connections[account].change_status(
+                gajim.SHOW_LIST[connected], gajim.connections[account].status)
 
     @log_calls('OmemoPlugin')
     def mam_message_received(self, msg):
@@ -235,12 +289,15 @@ class OmemoPlugin(GajimPlugin):
             -------
             Return means that the Event is passed on to Gajim
         """
+        account = msg.conn.name
+        if account in self.disabled_accounts:
+            return
+
         if msg.msg_.getTag('openpgp', namespace=NS_PGP):
             return
 
         omemo_encrypted_tag = msg.msg_.getTag('encrypted', namespace=NS_OMEMO)
         if omemo_encrypted_tag:
-            account = msg.conn.name
             log.debug(account + ' => OMEMO MAM msg received')
 
             state = self.get_omemo_state(account)
@@ -293,12 +350,14 @@ class OmemoPlugin(GajimPlugin):
             -------
             Return means that the Event is passed on to Gajim
         """
+        account = msg.conn.name
+        if account in self.disabled_accounts:
+            return
+
         if msg.stanza.getTag('openpgp', namespace=NS_PGP):
             return
 
-        if msg.stanza.getTag('encrypted', namespace=NS_OMEMO) and \
-                msg.mtype == 'chat':
-            account = msg.conn.name
+        if msg.stanza.getTag('encrypted', namespace=NS_OMEMO):
             log.debug(account + ' => OMEMO msg received')
 
             state = self.get_omemo_state(account)
@@ -307,27 +366,63 @@ class OmemoPlugin(GajimPlugin):
                 log.debug('message was forwarded doing magic')
             else:
                 from_jid = str(msg.stanza.getFrom())
+
             self.print_msg_to_log(msg.stanza)
             msg_dict = unpack_encrypted(msg.stanza.getTag
                                         ('encrypted', namespace=NS_OMEMO))
-            msg_dict['sender_jid'] = gajim.get_jid_without_resource(from_jid)
-            plaintext = state.decrypt_msg(msg_dict)
+
+            if msg.mtype == 'groupchat':
+                address_tag = msg.stanza.getTag('addresses',
+                                                namespace=NS_ADDRESS)
+                if address_tag:  # History Message from MUC
+                    from_jid = address_tag.getTag(
+                        'address', attrs={'type': 'ofrom'}).getAttr('jid')
+                else:
+                    try:
+                        from_jid = self.groupchat[msg.jid][msg.resource]
+                    except KeyError:
+                        log.debug('Groupchat: Last resort trying to '
+                                  'find SID in DB')
+                        from_jid = state.store. \
+                            getJidFromDevice(msg_dict['sid'])
+                        if not from_jid:
+                            log.error(account +
+                                      ' => Cant decrypt GroupChat Message '
+                                      'from ' + msg.resource)
+                            return True
+                        self.groupchat[msg.jid][msg.resource] = from_jid
+
+                log.debug('GroupChat Message from: %s', from_jid)
+
+            plaintext = ''
+            if msg_dict['sid'] == state.own_device_id:
+                if msg_dict['payload'] in self.gc_message:
+                    plaintext = self.gc_message[msg_dict['payload']]
+                    del self.gc_message[msg_dict['payload']]
+                else:
+                    log.error(account + ' => Cant decrypt own GroupChat '
+                              'Message')
+            else:
+                msg_dict['sender_jid'] = gajim. \
+                    get_jid_without_resource(from_jid)
+                plaintext = state.decrypt_msg(msg_dict)
 
             if not plaintext:
-                return
+                return True
 
             msg.msgtxt = plaintext
             # Gajim bug: there must be a body or the message
             # gets dropped from history
             msg.stanza.setBody(plaintext)
 
-            contact_jid = gajim.get_jid_without_resource(from_jid)
-            if account in self.ui_list and \
-                    contact_jid in self.ui_list[account]:
-                self.ui_list[account][contact_jid].activate_omemo()
+            if msg.mtype != 'groupchat':
+                contact_jid = gajim.get_jid_without_resource(from_jid)
+                if account in self.ui_list and \
+                        contact_jid in self.ui_list[account]:
+                    self.ui_list[account][contact_jid].activate_omemo()
             return False
 
-        elif msg.stanza.getTag('body') and msg.mtype == 'chat':
+        elif msg.stanza.getTag('body'):
             account = msg.conn.name
 
             from_jid = str(msg.stanza.getFrom())
@@ -347,6 +442,157 @@ class OmemoPlugin(GajimPlugin):
                     log.debug('No Ui present for ' + jid +
                               ', Ui Warning not shown')
 
+    def room_memberlist_received(self, event):
+        account = event.conn.name
+        if account in self.disabled_accounts:
+            return
+        log.debug('Room %s Memberlist received: %s',
+                  event.fjid, event.users_dict)
+        room = event.fjid
+
+        def jid_known(jid):
+            for nick in self.groupchat[room]:
+                if self.groupchat[room][nick] == jid:
+                    return True
+            return False
+
+        for jid in event.users_dict:
+            if not jid_known(jid):
+                # Add JID with JID because we have no Nick yet
+                self.groupchat[room][jid] = jid
+                log.debug('JID Added: ' + jid)
+
+    @log_calls('OmemoPlugin')
+    def gc_presence_received(self, event):
+        account = event.conn.name
+        if account in self.disabled_accounts:
+            return
+        if not hasattr(event, 'real_jid') or not event.real_jid:
+            return
+
+        room = event.room_jid
+        jid = gajim.get_jid_without_resource(event.real_jid)
+        nick = event.nick
+
+        if '303' in event.status_code:  # Nick Changed
+            if room in self.groupchat:
+                if nick in self.groupchat[room]:
+                    del self.groupchat[room][nick]
+                self.groupchat[room][event.new_nick] = jid
+                log.debug('Nick Change: old: %s, new: %s, jid: %s ',
+                          nick, event.new_nick, jid)
+                log.debug('Members after Change:  %s', self.groupchat[room])
+            else:
+                if nick in self.temp_groupchat[room]:
+                    del self.temp_groupchat[room][nick]
+                self.temp_groupchat[room][event.new_nick] = jid
+
+            return
+
+        if room not in self.groupchat:
+
+            if room not in self.temp_groupchat:
+                self.temp_groupchat[room] = {}
+
+            if nick not in self.temp_groupchat[room]:
+                self.temp_groupchat[room][nick] = jid
+
+        else:
+            # Check if we received JID over Memberlist
+            if jid in self.groupchat[room]:
+                del self.groupchat[room][jid]
+
+            # Add JID with Nick
+            if nick not in self.groupchat[room]:
+                self.groupchat[room][nick] = jid
+                log.debug('JID Added: ' + jid)
+
+        if '100' in event.status_code:  # non-anonymous Room (Full JID)
+
+            if room not in self.groupchat:
+                self.groupchat[room] = self.temp_groupchat[room]
+
+            log.debug('OMEMO capable Room found: %s', room)
+
+            gajim.connections[account].get_affiliation_list(room, 'owner')
+            gajim.connections[account].get_affiliation_list(room, 'admin')
+            gajim.connections[account].get_affiliation_list(room, 'member')
+
+            self.ui_list[account][room].sensitive(True)
+
+    @log_calls('OmemoPlugin')
+    def gc_config_changed_received(self, event):
+        account = event.conn.name
+        if account in self.disabled_accounts:
+            return
+        log.debug('CONFIG CHANGE')
+        log.debug(event.room_jid)
+        log.debug(event.status_code)
+
+    def handle_outgoing_gc_stanza(self, event):
+        """ Manipulates the outgoing groupchat stanza
+
+            The body is getting encrypted
+
+            Parameters
+            ----------
+            event : StanzaMessageOutgoingEvent
+
+            Returns
+            -------
+            Return if encryption is not activated or any other
+            exception or error occurs
+        """
+        account = event.conn.name
+        if account in self.disabled_accounts:
+            return
+        try:
+            if not event.msg_iq.getTag('body'):
+                return
+            state = self.get_omemo_state(account)
+            full_jid = str(event.msg_iq.getAttr('to'))
+            to_jid = gajim.get_jid_without_resource(full_jid)
+            if to_jid not in self.groupchat:
+                return
+            if not state.encryption.is_active(to_jid):
+                return
+            # Delete previous Message out of Correction Message Stanza
+            if event.msg_iq.getTag('replace', namespace=NS_CORRECT):
+                event.msg_iq.delChild('encrypted', attrs={'xmlns': NS_OMEMO})
+
+            plaintext = event.msg_iq.getBody()
+            msg_dict = state.create_gc_msg(
+                gajim.get_jid_from_account(account),
+                to_jid,
+                plaintext.encode('utf8'))
+            if not msg_dict:
+                return True
+
+            self.gc_message[msg_dict['payload']] = plaintext
+            encrypted_node = OmemoMessage(msg_dict)
+            event.msg_iq.delChild('body')
+            event.msg_iq.addChild(node=encrypted_node)
+
+            # XEP-xxxx: Explicit Message Encryption
+            if not event.msg_iq.getTag('encrypted', attrs={'xmlns': NS_EME}):
+                eme_node = Node('encrypted', attrs={'xmlns': NS_EME,
+                                                    'name': 'OMEMO',
+                                                    'namespace': NS_OMEMO})
+                event.msg_iq.addChild(node=eme_node)
+
+            # Add Message for devices that dont support OMEMO
+            support_msg = 'You received a message encrypted with ' \
+                          'OMEMO but your client doesnt support OMEMO.'
+            event.msg_iq.setBody(support_msg)
+
+            # Store Hint for MAM
+            store = Node('store', attrs={'xmlns': NS_HINTS})
+            event.msg_iq.addChild(node=store)
+            self.print_msg_to_log(event.msg_iq)
+        except Exception as e:
+            log.debug(e)
+            return True
+
     @log_calls('OmemoPlugin')
     def handle_outgoing_event(self, event):
         """ Handles a message outgoing event
@@ -363,6 +609,8 @@ class OmemoPlugin(GajimPlugin):
             Return if encryption is not activated
         """
         account = event.account
+        if account in self.disabled_accounts:
+            return
         state = self.get_omemo_state(account)
 
         if not state.encryption.is_active(event.jid):
@@ -385,11 +633,13 @@ class OmemoPlugin(GajimPlugin):
             Return if encryption is not activated or any other
             exception or error occurs
         """
+        account = event.conn.name
+        if account in self.disabled_accounts:
+            return
         try:
             if not event.msg_iq.getTag('body'):
                 return
 
-            account = event.conn.name
             state = self.get_omemo_state(account)
             full_jid = str(event.msg_iq.getAttr('to'))
             to_jid = gajim.get_jid_without_resource(full_jid)
@@ -463,6 +713,11 @@ class OmemoPlugin(GajimPlugin):
             4.2 Discovering peer support
                 http://conversations.im/xeps/multi-end.html#usecases-discovering
         """
+
+        account = event.conn.name
+        if account in self.disabled_accounts:
+            return False
+
         if event.pep_type != 'headline':
             return False
 
@@ -470,7 +725,6 @@ class OmemoPlugin(GajimPlugin):
                                                           event.conn.name)))
         if len(devices_list) == 0:
             return False
-        account = event.conn.name
         contact_jid = gajim.get_jid_without_resource(event.fjid)
         state = self.get_omemo_state(account)
         my_jid = gajim.get_jid_from_account(account)
@@ -557,6 +811,8 @@ class OmemoPlugin(GajimPlugin):
                 Gajim ChatControl object
         """
         account = chat_control.contact.account.name
+        if account in self.disabled_accounts:
+            return
         contact_jid = chat_control.contact.jid
         if account not in self.ui_list:
             self.ui_list[account] = {}
@@ -577,6 +833,11 @@ class OmemoPlugin(GajimPlugin):
         else:
             log.warning(account + " => No devices for " + contact_jid)
 
+        if chat_control.type_id == message_control.TYPE_GC:
+            self.ui_list[account][contact_jid] = Ui(self, chat_control,
+                                                    omemo_enabled, state)
+            self.ui_list[account][contact_jid].sensitive(False)
+
     @log_calls('OmemoPlugin')
     def disconnect_ui(self, chat_control):
         """ Calls the removeUi method to remove all relatad UI objects.
@@ -588,6 +849,8 @@ class OmemoPlugin(GajimPlugin):
         """
         contact_jid = chat_control.contact.jid
         account = chat_control.contact.account.name
+        if account in self.disabled_accounts:
+            return
         self.ui_list[account][contact_jid].removeUi()
 
     def are_keys_missing(self, account, contact_jid):
@@ -613,7 +876,7 @@ class OmemoPlugin(GajimPlugin):
         if my_jid not in self.query_for_bundles:
 
             devices_without_session = state \
-                    .devices_without_sessions(my_jid)
+                .devices_without_sessions(my_jid)
 
             self.query_for_bundles.append(my_jid)
 
diff --git a/omemo/config_dialog.ui b/omemo/config_dialog.ui
index 648e4b7f3ee79e1a4e53906ddf45c8ccfe4e894d..fb8e197de856708ee55f64ea9fa0b6cffa852d70 100644
--- a/omemo/config_dialog.ui
+++ b/omemo/config_dialog.ui
@@ -4,7 +4,7 @@
   <!-- interface-naming-policy toplevel-contextual -->
   <object class="GtkListStore" id="account_store">
     <columns>
-      <!-- column-name accountname -->
+      <!-- column-name accounts -->
       <column type="gchararray"/>
     </columns>
   </object>
@@ -14,6 +14,12 @@
       <column type="gchararray"/>
     </columns>
   </object>
+  <object class="GtkListStore" id="disabled_account_store">
+    <columns>
+      <!-- column-name accounts -->
+      <column type="gchararray"/>
+    </columns>
+  </object>
   <object class="GtkListStore" id="fingerprint_store">
     <columns>
       <!-- column-name id -->
@@ -24,6 +30,8 @@
       <column type="gchararray"/>
       <!-- column-name fingerprint -->
       <column type="gchararray"/>
+      <!-- column-name deviceid -->
+      <column type="gint"/>
     </columns>
   </object>
   <object class="GtkNotebook" id="notebook1">
@@ -104,7 +112,6 @@
               <object class="GtkLabel" id="fingerprint_label">
                 <property name="visible">True</property>
                 <property name="can_focus">False</property>
-                <property name="label">&lt;tt&gt;-------- -------- -------- -------- --------	&lt;/tt&gt;</property>
                 <property name="use_markup">True</property>
                 <property name="selectable">True</property>
               </object>
@@ -147,7 +154,6 @@
                 <property name="visible">True</property>
                 <property name="can_focus">False</property>
                 <property name="xalign">0</property>
-                <property name="label" translatable="yes">0</property>
               </object>
               <packing>
                 <property name="expand">False</property>
@@ -200,6 +206,9 @@
                   <object class="GtkTreeViewColumn" id="name_column">
                     <property name="resizable">True</property>
                     <property name="title">Name</property>
+                    <property name="clickable">True</property>
+                    <property name="sort_indicator">True</property>
+                    <property name="sort_column_id">1</property>
                     <child>
                       <object class="GtkCellRendererText" id="cellrenderertext2"/>
                       <attributes>
@@ -261,6 +270,21 @@
                 <property name="position">0</property>
               </packing>
             </child>
+            <child>
+              <object class="GtkButton" id="delfprbutton">
+                <property name="label" translatable="yes">Delete Fingerprint</property>
+                <property name="width_request">200</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <signal name="clicked" handler="delfpr_button_clicked" swapped="no"/>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
           </object>
           <packing>
             <property name="expand">False</property>
@@ -400,6 +424,170 @@
         <property name="tab_fill">False</property>
       </packing>
     </child>
+    <child>
+      <object class="GtkVBox" id="vbox2">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <child>
+          <object class="GtkLabel" id="label6">
+            <property name="height_request">30</property>
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="label" translatable="yes">You have to restart Gajim for changes to take effect !</property>
+            <attributes>
+              <attribute name="weight" value="bold"/>
+              <attribute name="foreground" value="#ffff00000000"/>
+            </attributes>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkHBox" id="hbox6">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="border_width">12</property>
+            <property name="spacing">5</property>
+            <child>
+              <object class="GtkVBox" id="vbox5">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <child>
+                  <object class="GtkScrolledWindow" id="scrolledwindow3">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="hscrollbar_policy">automatic</property>
+                    <property name="vscrollbar_policy">automatic</property>
+                    <child>
+                      <object class="GtkTreeView" id="active_accounts_view">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="model">account_store</property>
+                        <child>
+                          <object class="GtkTreeViewColumn" id="treeviewcolumn1">
+                            <property name="title" translatable="yes">Active Accounts</property>
+                            <property name="alignment">0.5</property>
+                            <child>
+                              <object class="GtkCellRendererText" id="cellrenderertext5"/>
+                              <attributes>
+                                <attribute name="text">0</attribute>
+                              </attributes>
+                            </child>
+                          </object>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">True</property>
+                    <property name="fill">True</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkButton" id="disable_accounts_btn">
+                    <property name="label" translatable="yes">Disable Account</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">True</property>
+                    <signal name="clicked" handler="disable_accounts_btn_clicked" swapped="no"/>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">False</property>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">True</property>
+                <property name="fill">True</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkVBox" id="vbox6">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <child>
+                  <object class="GtkScrolledWindow" id="scrolledwindow4">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="hscrollbar_policy">automatic</property>
+                    <property name="vscrollbar_policy">automatic</property>
+                    <child>
+                      <object class="GtkTreeView" id="disabled_accounts_view">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="model">disabled_account_store</property>
+                        <child>
+                          <object class="GtkTreeViewColumn" id="treeviewcolumn2">
+                            <property name="title" translatable="yes">Disabled Accounts</property>
+                            <property name="alignment">0.5</property>
+                            <child>
+                              <object class="GtkCellRendererText" id="cellrenderertext6"/>
+                              <attributes>
+                                <attribute name="text">0</attribute>
+                              </attributes>
+                            </child>
+                          </object>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">True</property>
+                    <property name="fill">True</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkButton" id="activate_accounts_btn">
+                    <property name="label" translatable="yes">Activate Account</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">True</property>
+                    <signal name="clicked" handler="activate_accounts_btn_clicked" swapped="no"/>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">False</property>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">True</property>
+                <property name="fill">True</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">True</property>
+            <property name="fill">True</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+      <packing>
+        <property name="position">3</property>
+      </packing>
+    </child>
+    <child type="tab">
+      <object class="GtkLabel" id="disable_accounts">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="label" translatable="yes">Disable Accounts</property>
+      </object>
+      <packing>
+        <property name="position">3</property>
+        <property name="tab_fill">False</property>
+      </packing>
+    </child>
   </object>
   <object class="GtkMenu" id="fprclipboard_menu">
     <property name="visible">True</property>
diff --git a/omemo/fpr_dialog.ui b/omemo/fpr_dialog.ui
index fb2f61ddfbb3ebb1fa71bc12d5528710ac7d5084..b46cb462a13520d34010d74a8fa5825f9cc24223 100644
--- a/omemo/fpr_dialog.ui
+++ b/omemo/fpr_dialog.ui
@@ -2,12 +2,6 @@
 <interface>
   <requires lib="gtk+" version="2.16"/>
   <!-- interface-naming-policy toplevel-contextual -->
-  <object class="GtkListStore" id="account_store">
-    <columns>
-      <!-- column-name accountname -->
-      <column type="gchararray"/>
-    </columns>
-  </object>
   <object class="GtkListStore" id="fingerprint_store">
     <columns>
       <!-- column-name id -->
@@ -18,6 +12,8 @@
       <column type="gchararray"/>
       <!-- column-name fingerprint -->
       <column type="gchararray"/>
+      <!-- column-name deviceid -->
+      <column type="gint"/>
     </columns>
   </object>
   <object class="GtkNotebook" id="notebook1">
@@ -41,7 +37,9 @@
               <object class="GtkTreeView" id="fingerprint_view">
                 <property name="visible">True</property>
                 <property name="can_focus">True</property>
+                <property name="has_tooltip">True</property>
                 <property name="model">fingerprint_store</property>
+                <property name="headers_clickable">False</property>
                 <property name="search_column">0</property>
                 <property name="tooltip_column">3</property>
                 <signal name="button-press-event" handler="fpr_button_pressed_cb" swapped="no"/>
@@ -49,8 +47,11 @@
                   <object class="GtkTreeViewColumn" id="name_column">
                     <property name="resizable">True</property>
                     <property name="title">Name</property>
+                    <property name="clickable">True</property>
+                    <property name="sort_indicator">True</property>
+                    <property name="sort_column_id">1</property>
                     <child>
-                      <object class="GtkCellRendererText" id="cellrenderertext2"/>
+                      <object class="GtkCellRendererText" id="NameCell"/>
                       <attributes>
                         <attribute name="text">1</attribute>
                       </attributes>
@@ -62,7 +63,7 @@
                     <property name="resizable">True</property>
                     <property name="title">Trust</property>
                     <child>
-                      <object class="GtkCellRendererText" id="cellrenderertoggle1"/>
+                      <object class="GtkCellRendererText" id="TrustCell"/>
                       <attributes>
                         <attribute name="text">2</attribute>
                       </attributes>
@@ -74,7 +75,7 @@
                     <property name="resizable">True</property>
                     <property name="title">Fingerprint</property>
                     <child>
-                      <object class="GtkCellRendererText" id="cellrenderertext4"/>
+                      <object class="GtkCellRendererText" id="FingerprintCell"/>
                       <attributes>
                         <attribute name="markup">3</attribute>
                       </attributes>
@@ -198,7 +199,7 @@
                     <property name="resizable">True</property>
                     <property name="title">Name</property>
                     <child>
-                      <object class="GtkCellRendererText" id="cellrenderertext1"/>
+                      <object class="GtkCellRendererText" id="NameCell1"/>
                       <attributes>
                         <attribute name="text">1</attribute>
                       </attributes>
@@ -210,7 +211,7 @@
                     <property name="resizable">True</property>
                     <property name="title">Trust</property>
                     <child>
-                      <object class="GtkCellRendererText" id="cellrenderertoggle2"/>
+                      <object class="GtkCellRendererText" id="TrustCell2"/>
                       <attributes>
                         <attribute name="text">2</attribute>
                       </attributes>
@@ -222,7 +223,7 @@
                     <property name="resizable">True</property>
                     <property name="title">Fingerprint</property>
                     <child>
-                      <object class="GtkCellRendererText" id="cellrenderertext3"/>
+                      <object class="GtkCellRendererText" id="FingerprintCell1"/>
                       <attributes>
                         <attribute name="markup">3</attribute>
                       </attributes>
@@ -289,8 +290,6 @@
       <object class="GtkMenuItem" id="copyfprclipboard_item">
         <property name="visible">True</property>
         <property name="can_focus">False</property>
-        <property name="label" translatable="yes" comments="Context menu item">Copy to clipboard</property>
-        <property name="use_underline">True</property>
         <signal name="activate" handler="clipboard_button_cb" swapped="no"/>
       </object>
     </child>
diff --git a/omemo/manifest.ini b/omemo/manifest.ini
index 5bf7f33113c5c8d3e9bb16551459c0e6f7f020fd..1a89a7e22ba1e6378690ccabb60d915d7aa3a5cd 100644
--- a/omemo/manifest.ini
+++ b/omemo/manifest.ini
@@ -1,7 +1,7 @@
 [info]
 name: OMEMO
 short_name: omemo
-version: 0.9.0
+version: 0.9.5
 description: OMEMO is an XMPP Extension Protocol (XEP) for secure multi-client end-to-end encryption based on Axolotl and PEP. You need to install some dependencys, you can find install instructions for your system in the Github Wiki.
 authors: Bahtiar `kalkin-` Gadimov <bahtiar@gadimov.de>
  Daniel Gultsch <daniel@gultsch.de>
diff --git a/omemo/omemo/liteaxolotlstore.py b/omemo/omemo/liteaxolotlstore.py
index 90502979444e50d08453c3ec4a5bb7e9b9ef8954..4ee00d17df18dc19428a7cd4d62423fa3618c718 100644
--- a/omemo/omemo/liteaxolotlstore.py
+++ b/omemo/omemo/liteaxolotlstore.py
@@ -83,10 +83,16 @@ class LiteAxolotlStore(AxolotlStore):
     def saveIdentity(self, recepientId, identityKey):
         self.identityKeyStore.saveIdentity(recepientId, identityKey)
 
+    def deleteIdentity(self, recipientId, identityKey):
+        self.identityKeyStore.deleteIdentity(recipientId, identityKey)
+
     def isTrustedIdentity(self, recepientId, identityKey):
         return self.identityKeyStore.isTrustedIdentity(recepientId,
                                                        identityKey)
 
+    def setTrust(self, identityKey, trust):
+        return self.identityKeyStore.setTrust(identityKey, trust)
+
     def getTrustedFingerprints(self, jid):
         return self.identityKeyStore.getTrustedFingerprints(jid)
 
@@ -127,6 +133,9 @@ class LiteAxolotlStore(AxolotlStore):
         # TODO Reuse this
         return self.sessionStore.getSubDeviceSessions(recepientId)
 
+    def getJidFromDevice(self, device_id):
+        return self.sessionStore.getJidFromDevice(device_id)
+
     def storeSession(self, recepientId, deviceId, sessionRecord):
         self.sessionStore.storeSession(recepientId, deviceId, sessionRecord)
 
@@ -139,6 +148,15 @@ class LiteAxolotlStore(AxolotlStore):
     def deleteAllSessions(self, recepientId):
         self.sessionStore.deleteAllSessions(recepientId)
 
+    def getSessionsFromJid(self, recipientId):
+        return self.sessionStore.getSessionsFromJid(recipientId)
+
+    def getSessionsFromJids(self, recipientId):
+        return self.sessionStore.getSessionsFromJids(recipientId)
+
+    def getAllSessions(self):
+        return self.sessionStore.getAllSessions()
+
     def loadSignedPreKey(self, signedPreKeyId):
         return self.signedPreKeyStore.loadSignedPreKey(signedPreKeyId)
 
diff --git a/omemo/omemo/liteidentitykeystore.py b/omemo/omemo/liteidentitykeystore.py
index d644fa05c4f5edd6d864a7f9cf44b8d2f8b41a37..1e02e638e74f8cdb3fdb04e3ac7fbaac0f1cfac2 100644
--- a/omemo/omemo/liteidentitykeystore.py
+++ b/omemo/omemo/liteidentitykeystore.py
@@ -86,6 +86,13 @@ class LiteIdentityKeyStore(IdentityKeyStore):
 
         return result is not None
 
+    def deleteIdentity(self, recipientId, identityKey):
+        q = "DELETE FROM identities WHERE recipient_id = ? AND public_key = ?"
+        c = self.dbConn.cursor()
+        c.execute(q, (recipientId,
+                      identityKey.getPublicKey().serialize()))
+        self.dbConn.commit()
+
     def isTrustedIdentity(self, recipientId, identityKey):
         q = "SELECT trust FROM identities WHERE recipient_id = ? " \
             "AND public_key = ?"
@@ -160,8 +167,8 @@ class LiteIdentityKeyStore(IdentityKeyStore):
         c.execute(q, fingerprints)
         self.dbConn.commit()
 
-    def setTrust(self, _id, trust):
-        q = "UPDATE identities SET trust = ? WHERE _id = ?"
+    def setTrust(self, identityKey, trust):
+        q = "UPDATE identities SET trust = ? WHERE public_key = ?"
         c = self.dbConn.cursor()
-        c.execute(q, (trust, _id))
+        c.execute(q, (trust, identityKey.getPublicKey().serialize()))
         self.dbConn.commit()
diff --git a/omemo/omemo/litesessionstore.py b/omemo/omemo/litesessionstore.py
index 0de1e5e6fcad3dacf075769239d0196a5a7a2f85..13e469e78607affd3e86600bb1b37414a6a0e3c3 100644
--- a/omemo/omemo/litesessionstore.py
+++ b/omemo/omemo/litesessionstore.py
@@ -48,6 +48,14 @@ class LiteSessionStore(SessionStore):
         deviceIds = [r[0] for r in result]
         return deviceIds
 
+    def getJidFromDevice(self, device_id):
+        q = "SELECT recipient_id from sessions WHERE device_id = ?"
+        c = self.dbConn.cursor()
+        c.execute(q, (device_id, ))
+        result = c.fetchone()
+
+        return result[0]
+
     def getActiveDeviceTuples(self):
         q = "SELECT recipient_id, device_id FROM sessions WHERE active = 1"
         c = self.dbConn.cursor()
@@ -82,6 +90,33 @@ class LiteSessionStore(SessionStore):
         self.dbConn.cursor().execute(q, (recipientId, ))
         self.dbConn.commit()
 
+    def getAllSessions(self):
+        q = "SELECT _id, recipient_id, device_id, record, active from sessions"
+        c = self.dbConn.cursor()
+        result = []
+        for row in c.execute(q):
+            result.append((row[0], row[1], row[2], row[3], row[4]))
+        return result
+
+    def getSessionsFromJid(self, recipientId):
+        q = "SELECT _id, recipient_id, device_id, record, active from sessions" \
+            " WHERE recipient_id = ?"
+        c = self.dbConn.cursor()
+        result = []
+        for row in c.execute(q, (recipientId,)):
+            result.append((row[0], row[1], row[2], row[3], row[4]))
+        return result
+
+    def getSessionsFromJids(self, recipientId):
+        q = "SELECT _id, recipient_id, device_id, record, active from sessions" \
+            " WHERE recipient_id IN ({})" \
+            .format(', '.join(['?'] * len(recipientId)))
+        c = self.dbConn.cursor()
+        result = []
+        for row in c.execute(q, recipientId):
+            result.append((row[0], row[1], row[2], row[3], row[4]))
+        return result
+
     def setActiveState(self, deviceList, jid):
         c = self.dbConn.cursor()
 
@@ -96,28 +131,6 @@ class LiteSessionStore(SessionStore):
         c.execute(q, deviceList)
         self.dbConn.commit()
 
-    def getActiveSessionsKeys(self, recipientId):
-        q = "SELECT record FROM sessions WHERE active = 1 AND recipient_id = ?"
-        c = self.dbConn.cursor()
-        result = []
-        for row in c.execute(q, (recipientId,)):
-            public_key = (SessionRecord(serialized=row[0]).
-                          getSessionState().getRemoteIdentityKey().
-                          getPublicKey())
-            result.append(public_key.serialize())
-        return result
-
-    def getAllActiveSessionsKeys(self):
-        q = "SELECT record FROM sessions WHERE active = 1"
-        c = self.dbConn.cursor()
-        result = []
-        for row in c.execute(q):
-            public_key = (SessionRecord(serialized=row[0]).
-                          getSessionState().getRemoteIdentityKey().
-                          getPublicKey())
-            result.append(public_key.serialize())
-        return result
-
     def getInactiveSessionsKeys(self, recipientId):
         q = "SELECT record FROM sessions WHERE active = 0 AND recipient_id = ?"
         c = self.dbConn.cursor()
diff --git a/omemo/omemo/state.py b/omemo/omemo/state.py
index fe79796ebaa8ce92402f16cce5ccb5d09dbf70a1..6db7f1a42f55ac15856b155c79313fab5e7df17f 100644
--- a/omemo/omemo/state.py
+++ b/omemo/omemo/state.py
@@ -201,7 +201,7 @@ class OmemoState:
             except (NoSessionException, InvalidMessageException) as e:
                 log.warning('No Session found ' + e.message)
                 log.warning('sender_jid =>  ' + str(sender_jid) + ' sid =>' +
-                          str(sid))
+                            str(sid))
                 return
             except (DuplicateMessageException) as e:
                 log.warning('Duplicate message found ' + str(e.args))
@@ -226,24 +226,82 @@ class OmemoState:
             log.error('No known devices')
             return
 
-        for dev in devices_list:
-            self.get_session_cipher(jid, dev)
-        session_ciphers = self.session_ciphers[jid]
-        if not session_ciphers:
-            log.warning('No session ciphers for ' + jid)
-            return
-
         # Encrypt the message key with for each of receivers devices
-        for rid, cipher in session_ciphers.items():
+        for device in devices_list:
             try:
-                if self.isTrusted(cipher) == TRUSTED:
-                    encrypted_keys[rid] = cipher.encrypt(key).serialize()
+                if self.isTrusted(jid, device) == TRUSTED:
+                    cipher = self.get_session_cipher(jid, device)
+                    encrypted_keys[device] = cipher.encrypt(key).serialize()
                 else:
                     log.debug('Skipped Device because Trust is: ' +
-                              str(self.isTrusted(cipher)))
+                              str(self.isTrusted(jid, device)))
             except:
-                log.warning('Failed to find key for device ' + str(rid))
+                log.warning('Failed to find key for device ' + str(device))
+
+        if len(encrypted_keys) == 0:
+            log.error('Encrypted keys empty')
+            raise NoValidSessions('Encrypted keys empty')
+
+        my_other_devices = set(self.own_devices) - set({self.own_device_id})
+        # Encrypt the message key with for each of our own devices
+        for device in my_other_devices:
+            try:
+                if self.isTrusted(from_jid, device) == TRUSTED:
+                    cipher = self.get_session_cipher(from_jid, device)
+                    encrypted_keys[device] = cipher.encrypt(key).serialize()
+                else:
+                    log.debug('Skipped own Device because Trust is: ' +
+                              str(self.isTrusted(from_jid, device)))
+            except:
+                log.warning('Failed to find key for device ' + str(device))
+
+        payload = encrypt(key, iv, plaintext)
+
+        result = {'sid': self.own_device_id,
+                  'keys': encrypted_keys,
+                  'jid': jid,
+                  'iv': iv,
+                  'payload': payload}
+
+        log.debug('Finished encrypting message')
+        return result
+
+    def create_gc_msg(self, from_jid, jid, plaintext):
+        key = get_random_bytes(16)
+        iv = get_random_bytes(16)
+        encrypted_keys = {}
+        room = jid
+        encrypted_jids = []
+
+        devices_list = self.device_list_for(jid, True)
+
+        if len(devices_list) == 0:
+            log.error('No known devices')
+            return
+
+        for tup in devices_list:
+            self.get_session_cipher(tup[0], tup[1])
 
+        # Encrypt the message key with for each of receivers devices
+        for nick in self.plugin.groupchat[room]:
+            jid_to = self.plugin.groupchat[room][nick]
+            if jid_to == self.own_jid:
+                continue
+            if jid_to in encrypted_jids:  # We already encrypted to this JID
+                continue
+            for rid, cipher in self.session_ciphers[jid_to].items():
+                try:
+                    if self.isTrusted(jid_to, rid) == TRUSTED:
+                        encrypted_keys[rid] = cipher.encrypt(key). \
+                            serialize()
+                    else:
+                        log.debug('Skipped Device because Trust is: ' +
+                                  str(self.isTrusted(jid_to, rid)))
+                except:
+                    log.exception('ERROR:')
+                    log.warning('Failed to find key for device ' +
+                                str(rid))
+            encrypted_jids.append(jid_to)
         if len(encrypted_keys) == 0:
             log_msg = 'Encrypted keys empty'
             log.error(log_msg)
@@ -254,12 +312,13 @@ class OmemoState:
         for dev in my_other_devices:
             try:
                 cipher = self.get_session_cipher(from_jid, dev)
-                if self.isTrusted(cipher) == TRUSTED:
+                if self.isTrusted(from_jid, dev) == TRUSTED:
                     encrypted_keys[dev] = cipher.encrypt(key).serialize()
                 else:
                     log.debug('Skipped own Device because Trust is: ' +
-                              str(self.isTrusted(cipher)))
+                              str(self.isTrusted(from_jid, dev)))
             except:
+                log.exception('ERROR:')
                 log.warning('Failed to find key for device ' + str(dev))
 
         payload = encrypt(key, iv, plaintext)
@@ -273,14 +332,36 @@ class OmemoState:
         log.debug('Finished encrypting message')
         return result
 
-    def isTrusted(self, cipher):
-        self.cipher = cipher
-        self.state = self.cipher.sessionStore. \
-            loadSession(self.cipher.recipientId, self.cipher.deviceId). \
-            getSessionState()
-        self.key = self.state.getRemoteIdentityKey()
-        return self.store.identityKeyStore. \
-            isTrustedIdentity(self.cipher.recipientId, self.key)
+    def device_list_for(self, jid, gc=False):
+        """ Return a list of known device ids for the specified jid.
+            Parameters
+            ----------
+            jid : string
+                The contacts jid
+            gc : bool
+                Groupchat Message
+        """
+        if gc:
+            room = jid
+            devicelist = []
+            for nick in self.plugin.groupchat[room]:
+                jid_to = self.plugin.groupchat[room][nick]
+                if jid_to == self.own_jid:
+                    continue
+                for device in self.device_ids[jid_to]:
+                    devicelist.append((jid_to, device))
+            return devicelist
+
+        if jid == self.own_jid:
+            return set(self.own_devices) - set({self.own_device_id})
+        if jid not in self.device_ids:
+            return set()
+        return set(self.device_ids[jid])
+
+    def isTrusted(self, recipient_id, device_id):
+        record = self.store.loadSession(recipient_id, device_id)
+        identity_key = record.getSessionState().getRemoteIdentityKey()
+        return self.store.isTrustedIdentity(recipient_id, identity_key)
 
     def getTrustedFingerprints(self, recipient_id):
         inactive = self.store.getInactiveSessionsKeys(recipient_id)
@@ -296,20 +377,6 @@ class OmemoState:
 
         return undecided
 
-    def device_list_for(self, jid):
-        """ Return a list of known device ids for the specified jid.
-
-            Parameters
-            ----------
-            jid : string
-                The contacts jid
-        """
-        if jid == self.own_jid:
-            return set(self.own_devices) - set({self.own_device_id})
-        if jid not in self.device_ids:
-            return set()
-        return set(self.device_ids[jid])
-
     def devices_without_sessions(self, jid):
         """ List device_ids for the given jid which have no axolotl session.
 
@@ -364,10 +431,10 @@ class OmemoState:
 
     def handleWhisperMessage(self, recipient_id, device_id, key):
         whisperMessage = WhisperMessage(serialized=key)
-        sessionCipher = self.get_session_cipher(recipient_id, device_id)
         log.debug(self.account + " => Received WhisperMessage from " +
                   recipient_id)
-        if self.isTrusted(sessionCipher) >= TRUSTED:
+        if self.isTrusted(recipient_id, device_id):
+            sessionCipher = self.get_session_cipher(recipient_id, device_id)
             key = sessionCipher.decryptMsg(whisperMessage)
             return key
         else:
diff --git a/omemo/pkgs/PKGBUILD b/omemo/pkgs/PKGBUILD
index 62ead0db7d7c053c0d4aea98d2e9caf341ea577c..fcda983d5c4c7754bd0775b1def3f68e509b1dd2 100644
--- a/omemo/pkgs/PKGBUILD
+++ b/omemo/pkgs/PKGBUILD
@@ -2,8 +2,8 @@
 
 pkgname=gajim-plugin-omemo
 _pkgname=gajim-omemo
-pkgver=0.8.1
-pkgrel=2
+pkgver=0.9
+pkgrel=1
 pkgdesc="Gajim plugin for OMEMO Multi-End Message and Object Encryption."
 arch=(any)
 url="https://github.com/omemo/${_pkgname}"
@@ -12,7 +12,7 @@ depends=("gajim" "python2-setuptools" "python2-cryptography" "python2-axolotl-gi
 provides=('gajim-plugin-omemo')
 conflicts=('gajim-plugin-omemo-git')
 source=("https://github.com/omemo/${_pkgname}/archive/${pkgver}.tar.gz")
-sha512sums=('e9280033fbe111f5010f2e9e8fa32c5b8c0abe308000f9a043a1c5e8215c96f8be434876b1d72cc8d68aed4ddaebe9655c70f9648a2db718cba71d90434fee2e')
+sha512sums=('536d0a9e368dadefefba34b02e74194c314eb0fc6343fcbb64390b7e447fb8be0214e921359959f831d0bcfaef09ae6825110ebeea947ac5a5ef3bc73da72541')
 
 package() {
   cd $srcdir/gajim-omemo-${pkgver}
diff --git a/omemo/ui.py b/omemo/ui.py
index 7701c6b245e7478336a4bb1bab142dc977db227d..180de55daaf75bd033b918990bde3ccfbaac8142 100644
--- a/omemo/ui.py
+++ b/omemo/ui.py
@@ -23,11 +23,14 @@ import logging
 
 import gobject
 import gtk
+import message_control
 
 # pylint: disable=import-error
 import gtkgui_helpers
 from common import gajim
+from dialogs import YesNoDialog
 from plugins.gui import GajimPluginConfigDialog
+from axolotl.state.sessionrecord import SessionRecord
 # pylint: enable=import-error
 
 log = logging.getLogger('gajim.plugin_system.omemo')
@@ -106,6 +109,12 @@ class Ui(object):
         self.account = self.contact.account.name
         self.windowinstances = {}
 
+        self.groupchat = False
+        if chat_control.type_id == message_control.TYPE_GC:
+            self.groupchat = True
+            self.omemo_capable = False
+            self.room = self.chat_control.room_jid
+
         self.display_omemo_state()
         self.refresh_auth_lock_icon()
 
@@ -134,6 +143,9 @@ class Ui(object):
             item.set_image(gtk.image_new_from_file(icon_path))
             item.set_submenu(submenu)
 
+            if self.groupchat:
+                item.set_sensitive(self.omemo_capable)
+
             # at index 8 is the separator after the esession encryption entry
             menu.insert(item, 8)
             return menu
@@ -160,7 +172,38 @@ class Ui(object):
                 log.debug(self.account + ' => Sending Message to ' +
                           self.contact.jid)
 
-        self.chat_control.send_message = omemo_send_message
+        def omemo_send_gc_message(message, xhtml=None, process_commands=True):
+            self.new_fingerprints_available()
+            if self.encryption_active():
+                missing = True
+                own_jid = gajim.get_jid_from_account(self.account)
+                for nick in self.plugin.groupchat[self.room]:
+                    real_jid = self.plugin.groupchat[self.room][nick]
+                    if real_jid == own_jid:
+                        continue
+                    if not self.plugin.are_keys_missing(self.account,
+                                                        real_jid):
+                        missing = False
+                if missing:
+                    log.debug(self.account +
+                              ' => No Trusted Fingerprints for ' +
+                              self.room)
+                    self.no_trusted_fingerprints_warning()
+                else:
+                    self.chat_control.orig_send_message(message, xhtml,
+                                                        process_commands)
+                    log.debug(self.account + ' => Sending Message to ' +
+                              self.room)
+            else:
+                self.chat_control.orig_send_message(message, xhtml,
+                                                    process_commands)
+                log.debug(self.account + ' => Sending Message to ' +
+                          self.room)
+
+        if self.groupchat:
+            self.chat_control.send_message = omemo_send_gc_message
+        else:
+            self.chat_control.send_message = omemo_send_message
 
     def set_omemo_state(self, enabled):
         """
@@ -183,6 +226,12 @@ class Ui(object):
         self.omemobutton.set_omemo_state(enabled)
         self.display_omemo_state()
 
+    def sensitive(self, value):
+        self.omemobutton.set_sensitive(value)
+        self.omemo_capable = value
+        if value:
+            self.chat_control.prepare_context_menu
+
     def encryption_active(self):
         return self.state.encryption.is_active(self.contact.jid)
 
@@ -191,16 +240,31 @@ class Ui(object):
             self.set_omemo_state(True)
 
     def new_fingerprints_available(self):
-        fingerprints = self.state.store.getNewFingerprints(self.contact.jid)
-        if fingerprints:
-            self.show_fingerprint_window(fingerprints)
+        jid = self.contact.jid
+        if self.groupchat and self.room in self.plugin.groupchat:
+            for nick in self.plugin.groupchat[self.room]:
+                real_jid = self.plugin.groupchat[self.room][nick]
+                fingerprints = self.state.store. \
+                    getNewFingerprints(real_jid)
+                if fingerprints:
+                    self.show_fingerprint_window(fingerprints)
+        elif not self.groupchat:
+            fingerprints = self.state.store.getNewFingerprints(jid)
+            if fingerprints:
+                self.show_fingerprint_window(fingerprints)
 
     def show_fingerprint_window(self, fingerprints=None):
         if 'dialog' not in self.windowinstances:
-            self.windowinstances['dialog'] = \
-                FingerprintWindow(self.plugin, self.contact,
-                                  self.chat_control.parent_win.window,
-                                  self.windowinstances)
+            if self.groupchat:
+                self.windowinstances['dialog'] = \
+                    FingerprintWindow(self.plugin, self.contact,
+                                      self.chat_control.parent_win.window,
+                                      self.windowinstances, groupchat=True)
+            else:
+                self.windowinstances['dialog'] = \
+                    FingerprintWindow(self.plugin, self.contact,
+                                      self.chat_control.parent_win.window,
+                                      self.windowinstances)
             self.windowinstances['dialog'].show_all()
             if fingerprints:
                 log.debug(self.account +
@@ -226,10 +290,12 @@ class Ui(object):
 
     def no_trusted_fingerprints_warning(self):
         msg = "To send an encrypted message, you have to " \
-                          "first trust the fingerprint of your contact!"
+              "first trust the fingerprint of your contact!"
         self.chat_control.print_conversation_line(msg, 'status', '', None)
 
     def refresh_auth_lock_icon(self):
+        if self.groupchat:
+            return
         if self.encryption_active():
             if self.state.getUndecidedFingerprints(self.contact.jid):
                 self.chat_control._show_lock_image(True, 'OMEMO', True, True,
@@ -257,39 +323,130 @@ class OMEMOConfigDialog(GajimPluginConfigDialog):
         self.B.set_translation_domain('gajim_plugins')
         self.B.add_from_file(self.GTK_BUILDER_FILE_PATH)
 
-        self.fpr_model = gtk.ListStore(gobject.TYPE_INT,
-                                       gobject.TYPE_STRING,
-                                       gobject.TYPE_STRING,
-                                       gobject.TYPE_STRING)
+        try:
+            self.disabled_accounts = self.plugin.config['DISABLED_ACCOUNTS']
+        except KeyError:
+            self.plugin.config['DISABLED_ACCOUNTS'] = []
+            self.disabled_accounts = self.plugin.config['DISABLED_ACCOUNTS']
 
-        self.device_model = gtk.ListStore(gobject.TYPE_STRING)
+        log.debug('Disabled Accounts:')
+        log.debug(self.disabled_accounts)
 
-        self.account_store = self.B.get_object('account_store')
-
-        for account in sorted(gajim.contacts.get_accounts()):
-            self.account_store.append(row=(account,))
+        self.fpr_model = self.B.get_object('fingerprint_store')
+        self.device_model = self.B.get_object('deviceid_store')
 
         self.fpr_view = self.B.get_object('fingerprint_view')
-        self.fpr_view.set_model(self.fpr_model)
-        self.fpr_view.get_selection().set_mode(gtk.SELECTION_MULTIPLE)
 
-        self.device_view = self.B.get_object('deviceid_view')
-        self.device_view.set_model(self.device_model)
+        self.disabled_acc_store = self.B.get_object('disabled_account_store')
+        self.account_store = self.B.get_object('account_store')
 
-        if len(self.account_store) > 0:
-            self.B.get_object('account_combobox').set_active(0)
+        self.active_acc_view = self.B.get_object('active_accounts_view')
+        self.disabled_acc_view = self.B.get_object('disabled_accounts_view')
 
         self.child.pack_start(self.B.get_object('notebook1'))
 
         self.B.connect_signals(self)
 
+        self.plugin_active = False
+
     def on_run(self):
-        self.update_context_list()
-        self.account_combobox_changed_cb(self.B.get_object('account_combobox'))
+        for plugin in gajim.plugin_manager.active_plugins:
+            log.debug(type(plugin))
+            if type(plugin).__name__ == 'OmemoPlugin':
+                self.plugin_active = True
+                break
+        self.update_account_store()
+        self.update_account_combobox()
+        self.update_disabled_account_view()
+
+        if len(self.account_store) > 0 and \
+                self.plugin_active is True:
+            self.account_combobox_changed_cb(
+                self.B.get_object('account_combobox'))
+
+    def is_in_accountstore(self, account):
+        for row in self.account_store:
+            if row[0] == account:
+                return True
+        return False
+
+    def update_account_store(self):
+        for account in sorted(gajim.contacts.get_accounts()):
+            if account not in self.disabled_accounts and \
+                    not self.is_in_accountstore(account):
+                self.account_store.append(row=(account,))
+
+    def update_account_combobox(self):
+        if self.plugin_active is False:
+            return
+        if len(self.account_store) > 0:
+            self.B.get_object('account_combobox').set_active(0)
+        else:
+            self.account_combobox_changed_cb(
+                self.B.get_object('account_combobox'))
 
     def account_combobox_changed_cb(self, box, *args):
         self.update_context_list()
 
+    def update_disabled_account_view(self):
+        self.disabled_acc_store.clear()
+        for account in self.disabled_accounts:
+            self.disabled_acc_store.append(row=(account,))
+
+    def activate_accounts_btn_clicked(self, button, *args):
+        mod, paths = self.disabled_acc_view.get_selection().get_selected_rows()
+        for path in paths:
+            it = mod.get_iter(path)
+            account = mod.get(it, 0)
+            if account[0] in self.disabled_accounts and \
+                    not self.is_in_accountstore(account[0]):
+                self.account_store.append(row=(account[0],))
+                self.disabled_accounts.remove(account[0])
+        self.update_disabled_account_view()
+        self.plugin.config['DISABLED_ACCOUNTS'] = self.disabled_accounts
+        self.update_account_combobox()
+
+    def disable_accounts_btn_clicked(self, button, *args):
+        mod, paths = self.active_acc_view.get_selection().get_selected_rows()
+        for path in paths:
+            it = mod.get_iter(path)
+            account = mod.get(it, 0)
+            if account[0] not in self.disabled_accounts and \
+                    self.is_in_accountstore(account[0]):
+                self.disabled_accounts.append(account[0])
+                self.account_store.remove(it)
+        self.update_disabled_account_view()
+        self.plugin.config['DISABLED_ACCOUNTS'] = self.disabled_accounts
+        self.update_account_combobox()
+
+    def delfpr_button_clicked(self, button, *args):
+        active = self.B.get_object('account_combobox').get_active()
+        account = self.account_store[active][0]
+
+        state = self.plugin.get_omemo_state(account)
+
+        mod, paths = self.fpr_view.get_selection().get_selected_rows()
+
+        def on_yes(checked):
+            record = state.store.loadSession(jid, deviceid)
+            identity_key = record.getSessionState().getRemoteIdentityKey()
+
+            state.store.deleteSession(jid, deviceid)
+            state.store.deleteIdentity(jid, identity_key)
+            self.update_context_list()
+
+        for path in paths:
+            it = mod.get_iter(path)
+            jid, fpr, deviceid = mod.get(it, 1, 3, 4)
+            fpr = fpr[31:-12]
+
+            YesNoDialog(
+                'Delete Fingerprint?',
+                'Do you want to delete the '
+                'fingerprint of <b>{}</b> on your account <b>{}</b>?'
+                '\n\n<tt>{}</tt>'.format(jid, account, fpr),
+                on_response_yes=on_yes, transient_for=self)
+
     def trust_button_clicked_cb(self, button, *args):
         active = self.B.get_object('account_combobox').get_active()
         account = self.account_store[active][0]
@@ -298,41 +455,42 @@ class OMEMOConfigDialog(GajimPluginConfigDialog):
 
         mod, paths = self.fpr_view.get_selection().get_selected_rows()
 
+        def on_yes(checked, identity_key):
+            state.store.setTrust(identity_key, TRUSTED)
+            try:
+                if self.plugin.ui_list[account]:
+                    self.plugin.ui_list[account][jid]. \
+                        refresh_auth_lock_icon()
+            except:
+                log.debug('UI not available')
+            self.update_context_list()
+
+        def on_no(identity_key):
+            state.store.setTrust(identity_key, UNTRUSTED)
+            try:
+                if jid in self.plugin.ui_list[account]:
+                    self.plugin.ui_list[account][jid]. \
+                        refresh_auth_lock_icon()
+            except:
+                log.debug('UI not available')
+            self.update_context_list()
+
         for path in paths:
             it = mod.get_iter(path)
-            _id, user, fpr = mod.get(it, 0, 1, 3)
+            jid, fpr, deviceid = mod.get(it, 1, 3, 4)
             fpr = fpr[31:-12]
-            dlg = gtk.Dialog('Trust / Revoke Fingerprint', self,
-                             gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
-                             (gtk.STOCK_YES, gtk.RESPONSE_YES,
-                              gtk.STOCK_NO, gtk.RESPONSE_NO))
-            l = gtk.Label()
-            l.set_markup('Do you want to trust the '
-                         'fingerprint of <b>%s</b> on your account <b>%s</b>?'
-                         '\n\n<tt>%s</tt>' % (user, account, fpr))
-            l.set_line_wrap(True)
-            l.set_padding(12, 12)
-            dlg.vbox.pack_start(l)
-            dlg.show_all()
-
-            response = dlg.run()
-            if response == gtk.RESPONSE_YES:
-                state.store.identityKeyStore.setTrust(_id, TRUSTED)
-                try:
-                    if self.plugin.ui_list[account]:
-                        self.plugin.ui_list[account][user].refresh_auth_lock_icon()
-                except:
-                    dlg.destroy()
-            else:
-                if response == gtk.RESPONSE_NO:
-                    state.store.identityKeyStore.setTrust(_id, UNTRUSTED)
-                    try:
-                        if user in self.plugin.ui_list[account]:
-                            self.plugin.ui_list[account][user].refresh_auth_lock_icon()
-                    except:
-                        dlg.destroy()
 
-        self.update_context_list()
+            record = state.store.loadSession(jid, deviceid)
+            identity_key = record.getSessionState().getRemoteIdentityKey()
+
+            YesNoDialog(
+                'Trust / Revoke Fingerprint?',
+                'Do you want to trust the fingerprint of <b>{}</b> '
+                'on your account <b>{}</b>?\n\n'
+                '<tt>{}</tt>'.format(jid, account, fpr),
+                on_response_yes=(on_yes, identity_key),
+                on_response_no=(on_no, identity_key),
+                transient_for=self)
 
     def cleardevice_button_clicked_cb(self, button, *args):
         active = self.B.get_object('account_combobox').get_active()
@@ -376,68 +534,84 @@ class OMEMOConfigDialog(GajimPluginConfigDialog):
         gtk.Clipboard(selection='PRIMARY').set_text('\n'.join(fprs))
 
     def update_context_list(self):
+        log.debug('update_context_list')
         self.fpr_model.clear()
         self.device_model.clear()
+        if len(self.account_store) == 0:
+            self.B.get_object('ID').set_markup('')
+            self.B.get_object('fingerprint_label').set_markup('')
+            self.B.get_object('trust_button').set_sensitive(False)
+            self.B.get_object('delfprbutton').set_sensitive(False)
+            self.B.get_object('refresh').set_sensitive(False)
+            self.B.get_object('cleardevice_button').set_sensitive(False)
+            return
         active = self.B.get_object('account_combobox').get_active()
         account = self.account_store[active][0]
-        state = self.plugin.get_omemo_state(account)
 
+        # Set buttons active
+        self.B.get_object('trust_button').set_sensitive(True)
+        self.B.get_object('delfprbutton').set_sensitive(True)
+        self.B.get_object('refresh').set_sensitive(True)
+        if account == 'Local':
+            self.B.get_object('cleardevice_button').set_sensitive(False)
+        else:
+            self.B.get_object('cleardevice_button').set_sensitive(True)
+
+        # Set FPR Label and DeviceID
+        state = self.plugin.get_omemo_state(account)
         deviceid = state.own_device_id
         self.B.get_object('ID').set_markup('<tt>%s</tt>' % deviceid)
 
         ownfpr = binascii.hexlify(state.store.getIdentityKeyPair()
                                   .getPublicKey().serialize())
-        ownfpr = self.human_hash(ownfpr[2:])
+        ownfpr = human_hash(ownfpr[2:])
         self.B.get_object('fingerprint_label').set_markup('<tt>%s</tt>'
                                                           % ownfpr)
 
-        fprDB = state.store.identityKeyStore.getAllFingerprints()
-        activeSessions = state.store.sessionStore. \
-            getAllActiveSessionsKeys()
-        for item in fprDB:
-            _id, jid, fpr, tr = item
-            active = fpr in activeSessions
-            fpr = binascii.hexlify(fpr)
-            fpr = self.human_hash(fpr[2:])
-            if tr == UNTRUSTED:
-                if active:
-                    self.fpr_model.append((_id, jid, 'False',
-                                           '<tt><span foreground="#FF0040">%s</span></tt>' % fpr))
-                else:
-                    self.fpr_model.append((_id, jid, 'False',
-                                           '<tt><span foreground="#585858">%s</span></tt>' % fpr))
-            elif tr == TRUSTED:
-                if active:
-                    self.fpr_model.append((_id, jid, 'True',
-                                           '<tt><span foreground="#2EFE2E">%s</span></tt>' % fpr))
-                else:
-                    self.fpr_model.append((_id, jid, 'True',
-                                           '<tt><span foreground="#585858">%s</span></tt>' % fpr))
-            else:
-                if active:
-                    self.fpr_model.append((_id, jid, 'Undecided',
-                                           '<tt><span foreground="#FF8000">%s</span></tt>' % fpr))
-                else:
-                    self.fpr_model.append((_id, jid, 'Undecided',
-                                           '<tt><span foreground="#585858">%s</span></tt>' % fpr))
+        # Set Fingerprint List
+        trust_str = {0: 'False', 1: 'True', 2: 'Undecided'}
+        session_db = state.store.getAllSessions()
+
+        for item in session_db:
+            color = {0: '#FF0040',  # red
+                     1: '#2EFE2E',  # green
+                     2: '#FF8000'}  # orange
+
+            _id, jid, deviceid, record, active = item
+
+            active = bool(active)
+
+            identity_key = SessionRecord(serialized=record). \
+                getSessionState().getRemoteIdentityKey()
+            fpr = binascii.hexlify(identity_key.getPublicKey().serialize())
+            fpr = human_hash(fpr[2:])
+
+            trust = state.store.isTrustedIdentity(jid, identity_key)
+
+            if not active:
+                color[trust] = '#585858'  # grey
 
+            self.fpr_model.append(
+                (_id, jid, trust_str[trust],
+                 '<tt><span foreground="{}">{}</span></tt>'.
+                 format(color[trust], fpr),
+                 deviceid))
+
+        # Set Device ID List
         for item in state.own_devices:
             self.device_model.append([item])
 
-    def human_hash(self, fpr):
-        fpr = fpr.upper()
-        fplen = len(fpr)
-        wordsize = fplen // 8
-        buf = ''
-        for w in range(0, fplen, wordsize):
-            buf += '{0} '.format(fpr[w:w + wordsize])
-        return buf.rstrip()
-
 
 class FingerprintWindow(gtk.Dialog):
-    def __init__(self, plugin, contact, parent, windowinstances):
+    def __init__(self, plugin, contact, parent, windowinstances,
+                 groupchat=False):
+        self.groupchat = groupchat
         self.contact = contact
         self.windowinstances = windowinstances
+        self.account = self.contact.account.name
+        self.plugin = plugin
+        self.omemostate = self.plugin.get_omemo_state(self.account)
+        self.own_jid = gajim.get_jid_from_account(self.account)
         gtk.Dialog.__init__(self,
                             title=('Fingerprints for %s') % contact.jid,
                             parent=parent,
@@ -445,44 +619,33 @@ class FingerprintWindow(gtk.Dialog):
         close_button = self.add_button(gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE)
         close_button.connect('clicked', self.on_close_button_clicked)
         self.connect('delete-event', self.on_window_delete)
-        self.plugin = plugin
+
         self.GTK_BUILDER_FILE_PATH = \
             self.plugin.local_file_path('fpr_dialog.ui')
-        self.B = gtk.Builder()
-        self.B.set_translation_domain('gajim_plugins')
-        self.B.add_from_file(self.GTK_BUILDER_FILE_PATH)
+        self.xml = gtk.Builder()
+        self.xml.add_from_file(self.GTK_BUILDER_FILE_PATH)
+        self.xml.set_translation_domain('gajim_plugins')
 
-        self.fpr_model = gtk.ListStore(gobject.TYPE_INT,
-                                       gobject.TYPE_STRING,
-                                       gobject.TYPE_STRING,
-                                       gobject.TYPE_STRING)
+        self.fpr_model = self.xml.get_object('fingerprint_store')
 
-        self.fpr_view = self.B.get_object('fingerprint_view')
-        self.fpr_view.set_model(self.fpr_model)
-        self.fpr_view.get_selection().set_mode(gtk.SELECTION_MULTIPLE)
-
-        self.fpr_view_own = self.B.get_object('fingerprint_view_own')
-        self.fpr_view_own.set_model(self.fpr_model)
-        self.fpr_view_own.get_selection().set_mode(gtk.SELECTION_MULTIPLE)
-
-        self.notebook = self.B.get_object('notebook1')
+        self.fpr_view = self.xml.get_object('fingerprint_view')
+        self.fpr_view_own = self.xml.get_object('fingerprint_view_own')
 
+        self.notebook = self.xml.get_object('notebook1')
         self.child.pack_start(self.notebook)
 
-        self.B.connect_signals(self)
-
-        self.account = self.contact.account.name
-        self.omemostate = self.plugin.get_omemo_state(self.account)
+        self.xml.connect_signals(self)
 
+        # Set own Fingerprint Label
         ownfpr = binascii.hexlify(self.omemostate.store.getIdentityKeyPair()
                                   .getPublicKey().serialize())
-        ownfpr = self.human_hash(ownfpr[2:])
-
-        self.B.get_object('fingerprint_label_own').set_markup('<tt>%s</tt>'
-                                                              % ownfpr)
-
+        ownfpr = human_hash(ownfpr[2:])
+        self.xml.get_object('fingerprint_label_own').set_markup('<tt>%s</tt>'
+                                                                % ownfpr)
         self.update_context_list()
 
+        self.show_all()
+
     def on_close_button_clicked(self, widget):
         del self.windowinstances['dialog']
         self.hide()
@@ -492,41 +655,43 @@ class FingerprintWindow(gtk.Dialog):
         self.hide()
 
     def trust_button_clicked_cb(self, button, *args):
+        state = self.omemostate
+
         if self.notebook.get_current_page() == 1:
             mod, paths = self.fpr_view_own.get_selection().get_selected_rows()
         else:
             mod, paths = self.fpr_view.get_selection().get_selected_rows()
 
+        def on_yes(checked, identity_key):
+            state.store.setTrust(identity_key, TRUSTED)
+            if not self.groupchat:
+                self.plugin.ui_list[self.account][self.contact.jid]. \
+                    refresh_auth_lock_icon()
+            self.update_context_list()
+
+        def on_no(identity_key):
+            state.store.setTrust(identity_key, UNTRUSTED)
+            if not self.groupchat:
+                self.plugin.ui_list[self.account][self.contact.jid]. \
+                    refresh_auth_lock_icon()
+            self.update_context_list()
+
         for path in paths:
             it = mod.get_iter(path)
-            _id, user, fpr = mod.get(it, 0, 1, 3)
+            jid, fpr, deviceid = mod.get(it, 1, 3, 4)
             fpr = fpr[31:-12]
-            dlg = gtk.Dialog('Trust / Revoke Fingerprint', self,
-                             gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
-                             (gtk.STOCK_YES, gtk.RESPONSE_YES,
-                              gtk.STOCK_NO, gtk.RESPONSE_NO))
-            l = gtk.Label()
-            l.set_markup('Do you want to trust the '
-                         'fingerprint of <b>%s</b> on your account <b>%s</b>?'
-                         '\n\n<tt>%s</tt>' % (user, self.account, fpr))
-            l.set_line_wrap(True)
-            l.set_padding(12, 12)
-            dlg.vbox.pack_start(l)
-            dlg.show_all()
-            response = dlg.run()
-            if response == gtk.RESPONSE_YES:
-                self.omemostate.store.identityKeyStore.setTrust(_id, TRUSTED)
-                self.plugin.ui_list[self.account][self.contact.jid]. \
-                    refresh_auth_lock_icon()
-                dlg.destroy()
-            else:
-                if response == gtk.RESPONSE_NO:
-                    self.omemostate.store.identityKeyStore.setTrust(_id, UNTRUSTED)
-                    self.plugin.ui_list[self.account][self.contact.jid]. \
-                        refresh_auth_lock_icon()
-            dlg.destroy()
 
-        self.update_context_list()
+            record = state.store.loadSession(jid, deviceid)
+            identity_key = record.getSessionState().getRemoteIdentityKey()
+
+            YesNoDialog(
+                'Trust / Revoke Fingerprint?',
+                'Do you want to trust the fingerprint of <b>{}</b> '
+                'on your account <b>{}</b>?\n\n'
+                '<tt>{}</tt>'.format(jid, self.account, fpr),
+                on_response_yes=(on_yes, identity_key),
+                on_response_no=(on_no, identity_key),
+                transient_for=self)
 
     def fpr_button_pressed_cb(self, tw, event):
         if event.button == 3:
@@ -541,7 +706,7 @@ class FingerprintWindow(gtk.Dialog):
             # selection, otherwise we only select the new item
             keep_selection = tw.get_selection().path_is_selected(pthinfo[0])
 
-            pop = self.B.get_object('fprclipboard_menu')
+            pop = self.xml.get_object('fprclipboard_menu')
             pop.popup(None, None, None, event.button, event.time)
 
             # keep_selection=True -> no further processing of click event
@@ -565,48 +730,56 @@ class FingerprintWindow(gtk.Dialog):
 
     def update_context_list(self, *args):
         self.fpr_model.clear()
+        state = self.omemostate
 
         if self.notebook.get_current_page() == 1:
-            jid = gajim.get_jid_from_account(self.account)
+            contact_jid = self.own_jid
         else:
-            jid = self.contact.jid
-
-        fprDB = self.omemostate.store.identityKeyStore.getFingerprints(jid)
-        activeSessions = self.omemostate.store.sessionStore. \
-            getActiveSessionsKeys(jid)
-
-        for item in fprDB:
-            _id, jid, fpr, tr = item
-            active = fpr in activeSessions
-            fpr = binascii.hexlify(fpr)
-            fpr = self.human_hash(fpr[2:])
-            if tr == UNTRUSTED:
-                if active:
-                    self.fpr_model.append((_id, jid, 'False',
-                                           '<tt><span foreground="#FF0040">%s</span></tt>' % fpr))
-                else:
-                    self.fpr_model.append((_id, jid, 'False',
-                                           '<tt><span foreground="#585858">%s</span></tt>' % fpr))
-            elif tr == TRUSTED:
-                if active:
-                    self.fpr_model.append((_id, jid, 'True',
-                                           '<tt><span foreground="#2EFE2E">%s</span></tt>' % fpr))
-                else:
-                    self.fpr_model.append((_id, jid, 'True',
-                                           '<tt><span foreground="#585858">%s</span></tt>' % fpr))
-            else:
-                if active:
-                    self.fpr_model.append((_id, jid, 'Undecided',
-                                           '<tt><span foreground="#FF8000">%s</span></tt>' % fpr))
-                else:
-                    self.fpr_model.append((_id, jid, 'Undecided',
-                                           '<tt><span foreground="#585858">%s</span></tt>' % fpr))
-
-    def human_hash(self, fpr):
-        fpr = fpr.upper()
-        fplen = len(fpr)
-        wordsize = fplen // 8
-        buf = ''
-        for w in range(0, fplen, wordsize):
-            buf += '{0} '.format(fpr[w:w + wordsize])
-        return buf.rstrip()
+            contact_jid = self.contact.jid
+
+        trust_str = {0: 'False', 1: 'True', 2: 'Undecided'}
+        if self.groupchat and self.notebook.get_current_page() == 0:
+            contact_jids = []
+            for nick in self.plugin.groupchat[contact_jid]:
+                real_jid = self.plugin.groupchat[contact_jid][nick]
+                if real_jid == self.own_jid:
+                    continue
+                contact_jids.append(real_jid)
+            session_db = state.store.getSessionsFromJids(contact_jids)
+        else:
+            session_db = state.store.getSessionsFromJid(contact_jid)
+
+        for item in session_db:
+            color = {0: '#FF0040',  # red
+                     1: '#2EFE2E',  # green
+                     2: '#FF8000'}  # orange
+
+            _id, jid, deviceid, record, active = item
+
+            active = bool(active)
+
+            identity_key = SessionRecord(serialized=record). \
+                getSessionState().getRemoteIdentityKey()
+            fpr = binascii.hexlify(identity_key.getPublicKey().serialize())
+            fpr = human_hash(fpr[2:])
+
+            trust = state.store.isTrustedIdentity(jid, identity_key)
+
+            if not active:
+                color[trust] = '#585858'  # grey
+
+            self.fpr_model.append(
+                (_id, jid, trust_str[trust],
+                 '<tt><span foreground="{}">{}</span></tt>'.
+                 format(color[trust], fpr),
+                 deviceid))
+
+
+def human_hash(fpr):
+    fpr = fpr.upper()
+    fplen = len(fpr)
+    wordsize = fplen // 8
+    buf = ''
+    for w in range(0, fplen, wordsize):
+        buf += '{0} '.format(fpr[w:w + wordsize])
+    return buf.rstrip()