diff --git a/.gitignore b/.gitignore
index 6e52fa4522039a6336bc278f9d2b6217f194a35e..7ff4882a41ca87f23f0d46663f615bc66a0adaba 100644
--- a/.gitignore
+++ b/.gitignore
@@ -46,3 +46,4 @@ res/i18n/lang-*
 out
 .directory
 temp
+*_uic.py
\ No newline at end of file
diff --git a/gen_resources.py b/gen_resources.py
index 2a269dfe5b9d6c49d537caea6dd20b9eb3d92d4b..cfa45fd9918bf98dc408f1416efbc18a742419a0 100644
--- a/gen_resources.py
+++ b/gen_resources.py
@@ -2,8 +2,10 @@
 # -*- coding: utf-8 -*-
 import sys, os, multiprocessing, subprocess
 
+
+sakia = os.path.abspath(os.path.join(os.path.dirname(__file__)))
 resources = os.path.abspath(os.path.join(os.path.dirname(__file__), 'res'))
-gen_ui = os.path.abspath(os.path.join(os.path.dirname(__file__), 'src', 'sakia', 'gen_resources'))
+gen_ui = os.path.abspath(os.path.join(os.path.dirname(__file__), 'src', 'sakia', 'presentation'))
 gen_resources = os.path.abspath(os.path.join(os.path.dirname(__file__), 'src'))
 
 def convert_ui(args, **kwargs):
@@ -12,11 +14,15 @@ def convert_ui(args, **kwargs):
 def build_resources():
     try:
         to_process = []
-        for root, dirs, files in os.walk(resources):
+        for root, dirs, files in os.walk(sakia):
             for f in files:
                 if f.endswith('.ui'):
                     source = os.path.join(root, f)
-                    dest = os.path.join(gen_ui, os.path.splitext(os.path.basename(source))[0]+'_uic.py')
+                    if os.path.commonpath([resources, root]) == resources:
+                        dest = os.path.join(gen_ui, os.path.splitext(os.path.basename(source))[0]+'_uic.py')
+                    else:
+                        dest = os.path.join(root, os.path.splitext(os.path.basename(source))[0]+'_uic.py')
+
                     exe = 'pyuic5'
                 elif f.endswith('.qrc'):
                     source = os.path.join(root, f)
diff --git a/res/ui/community_view.ui b/res/ui/community_view.ui
index 213060dc7294aa314a1b2b10781c79ac7865d500..8827fe266a1f83882dcac7b74cab8c299502e0db 100644
--- a/res/ui/community_view.ui
+++ b/res/ui/community_view.ui
@@ -14,125 +14,6 @@
    <string>Form</string>
   </property>
   <layout class="QVBoxLayout" name="verticalLayout">
-   <item>
-    <widget class="QFrame" name="frame">
-     <property name="frameShape">
-      <enum>QFrame::StyledPanel</enum>
-     </property>
-     <property name="frameShadow">
-      <enum>QFrame::Raised</enum>
-     </property>
-     <layout class="QHBoxLayout" name="horizontalLayout">
-      <item>
-       <widget class="QPushButton" name="button_home">
-        <property name="sizePolicy">
-         <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
-          <horstretch>0</horstretch>
-          <verstretch>0</verstretch>
-         </sizepolicy>
-        </property>
-        <property name="text">
-         <string/>
-        </property>
-        <property name="icon">
-         <iconset resource="../icons/icons.qrc">
-          <normaloff>:/icons/home_icon</normaloff>:/icons/home_icon</iconset>
-        </property>
-        <property name="iconSize">
-         <size>
-          <width>32</width>
-          <height>32</height>
-         </size>
-        </property>
-       </widget>
-      </item>
-      <item>
-       <widget class="QLabel" name="label_currency">
-        <property name="text">
-         <string/>
-        </property>
-       </widget>
-      </item>
-      <item>
-       <widget class="QPushButton" name="button_send_money">
-        <property name="text">
-         <string>Send money</string>
-        </property>
-        <property name="icon">
-         <iconset resource="../icons/icons.qrc">
-          <normaloff>:/icons/payment_icon</normaloff>:/icons/payment_icon</iconset>
-        </property>
-        <property name="iconSize">
-         <size>
-          <width>32</width>
-          <height>32</height>
-         </size>
-        </property>
-       </widget>
-      </item>
-      <item>
-       <widget class="QPushButton" name="button_certification">
-        <property name="text">
-         <string>Certification</string>
-        </property>
-        <property name="icon">
-         <iconset resource="../icons/icons.qrc">
-          <normaloff>:/icons/certification_icon</normaloff>:/icons/certification_icon</iconset>
-        </property>
-        <property name="iconSize">
-         <size>
-          <width>32</width>
-          <height>32</height>
-         </size>
-        </property>
-       </widget>
-      </item>
-      <item>
-       <widget class="QPushButton" name="button_membership">
-        <property name="text">
-         <string>Renew membership</string>
-        </property>
-        <property name="icon">
-         <iconset resource="../icons/icons.qrc">
-          <normaloff>:/icons/renew_membership</normaloff>:/icons/renew_membership</iconset>
-        </property>
-        <property name="iconSize">
-         <size>
-          <width>32</width>
-          <height>32</height>
-         </size>
-        </property>
-       </widget>
-      </item>
-      <item>
-       <widget class="QToolButton" name="toolbutton_menu">
-        <property name="text">
-         <string/>
-        </property>
-        <property name="icon">
-         <iconset resource="../icons/icons.qrc">
-          <normaloff>:/icons/menu_icon</normaloff>:/icons/menu_icon</iconset>
-        </property>
-        <property name="iconSize">
-         <size>
-          <width>32</width>
-          <height>32</height>
-         </size>
-        </property>
-        <property name="popupMode">
-         <enum>QToolButton::InstantPopup</enum>
-        </property>
-        <property name="autoRaise">
-         <bool>false</bool>
-        </property>
-        <property name="arrowType">
-         <enum>Qt::NoArrow</enum>
-        </property>
-       </widget>
-      </item>
-     </layout>
-    </widget>
-   </item>
    <item>
     <widget class="QTabWidget" name="tabs"/>
    </item>
diff --git a/src/sakia/gui/agent/__init__.py b/src/sakia/gui/agent/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..03eacd239fc9b25aa6e2df24779250abd78e79cd
--- /dev/null
+++ b/src/sakia/gui/agent/__init__.py
@@ -0,0 +1 @@
+__all__ = ['controller', 'model']
diff --git a/src/sakia/gui/agent/controller.py b/src/sakia/gui/agent/controller.py
new file mode 100644
index 0000000000000000000000000000000000000000..645bda03bbb7e18cb686665deb599b56804ceb25
--- /dev/null
+++ b/src/sakia/gui/agent/controller.py
@@ -0,0 +1,22 @@
+from PyQt5.QtCore import QObject
+
+
+class AgentController(QObject):
+    """
+    The navigation panel
+    """
+
+    def __init__(self, parent, view, model):
+        """
+        Constructor of the navigation agent
+
+        :param PyQt5.QtWidgets.QWidget presentation: the presentation
+        :param sakia.core.gui.navigation.model.NavigationModel model: the model
+        """
+        super().__init__(parent)
+        self.view = view
+        self.model = model
+
+    def attach(self, controller):
+        controller.setParent(self)
+        return controller
diff --git a/src/sakia/gui/agent/model.py b/src/sakia/gui/agent/model.py
new file mode 100644
index 0000000000000000000000000000000000000000..61a2d366bd93c60c1ed4ec9d386983fcdf822511
--- /dev/null
+++ b/src/sakia/gui/agent/model.py
@@ -0,0 +1,19 @@
+from PyQt5.QtCore import QObject
+
+
+class AgentModel(QObject):
+    """
+    An agent
+    """
+
+    def __init__(self, parent):
+        """
+        Constructor of an agent
+
+        :param sakia.core.gui.agent.controller.AbstractAgentController controller: the controller
+        """
+        super().__init__(parent)
+
+    @property
+    def account(self):
+        return self.app.current_account
diff --git a/src/sakia/gui/certification.py b/src/sakia/gui/certification.py
index f19a2840f8edd3c566ff446b065525db639b87ae..b50d9d5e110d141b6ca7eb2931f0e17d5a29cad4 100644
--- a/src/sakia/gui/certification.py
+++ b/src/sakia/gui/certification.py
@@ -14,7 +14,8 @@ from .widgets.dialogs import QAsyncMessageBox
 from .member import MemberDialog
 from ..tools.decorators import asyncify, once_at_a_time
 from ..tools.exceptions import NoPeerAvailable
-from ..gen_resources.certification_uic import Ui_CertificationDialog
+from ..presentation.certification_uic import Ui_CertificationDialog
+
 
 class CertificationDialog(QObject):
     """
diff --git a/src/sakia/gui/community_view.py b/src/sakia/gui/community_view.py
index 53f47851bb33874355621ab45729821b67fc6e20..1255e5570900db94a87a1c5a6ad321e8e25bbd90 100644
--- a/src/sakia/gui/community_view.py
+++ b/src/sakia/gui/community_view.py
@@ -13,13 +13,12 @@ from PyQt5.QtWidgets import QWidget, QMessageBox, QDialog, QPushButton, QTabBar,
 
 from .graphs.wot_tab import WotTabWidget
 from .widgets import toast
-from .widgets.dialogs import QAsyncMessageBox, QAsyncFileDialog, dialog_async_exec
 from .identities_tab import IdentitiesTabWidget
 from .informations_tab import InformationsTabWidget
 from .network_tab import NetworkTabWidget
 from .transactions_tab import TransactionsTabWidget
 from .graphs.explorer_tab import ExplorerTabWidget
-from ..gen_resources.community_view_uic import Ui_CommunityWidget
+from ..presentation.community_view_uic import Ui_CommunityWidget
 from ..tools.decorators import asyncify, once_at_a_time, cancel_once_task
 from ..tools.exceptions import MembershipNotFoundError, LookupFailureError, NoPeerAvailable
 
@@ -35,10 +34,6 @@ class CommunityWidget(QWidget, Ui_CommunityWidget):
     _tab_identities_label = QT_TRANSLATE_NOOP("CommunityWidget", "Search Identities")
     _tab_network_label = QT_TRANSLATE_NOOP("CommunityWidget", "Network")
     _tab_informations_label = QT_TRANSLATE_NOOP("CommunityWidget", "Informations")
-    _action_showinfo_text = QT_TRANSLATE_NOOP("CommunityWidget", "Show informations")
-    _action_explore_text = QT_TRANSLATE_NOOP("CommunityWidget", "Explore the Web of Trust")
-    _action_publish_uid_text = QT_TRANSLATE_NOOP("CommunityWidget", "Publish UID")
-    _action_revoke_uid_text = QT_TRANSLATE_NOOP("CommunityWidget", "Revoke UID")
 
     def __init__(self, app, status_label, label_icon):
         """
@@ -61,16 +56,8 @@ class CommunityWidget(QWidget, Ui_CommunityWidget):
         self.tab_network = NetworkTabWidget(self.app)
         self.tab_explorer = ExplorerTabWidget(self.app)
 
-        self.action_publish_uid = QAction(self.tr(CommunityWidget._action_publish_uid_text), self)
-        self.action_revoke_uid = QAction(self.tr(CommunityWidget._action_revoke_uid_text), self)
-        self.action_showinfo = QAction(self.tr(CommunityWidget._action_showinfo_text), self)
-        self.action_explorer = QAction(self.tr(CommunityWidget._action_explore_text), self)
-
         super().setupUi(self)
 
-        tool_menu = QMenu(self.tr("Tools"), self.toolbutton_menu)
-        self.toolbutton_menu.setMenu(tool_menu)
-
         self.tab_identities.view_in_wot.connect(self.tab_wot.draw_graph)
         self.tab_identities.view_in_wot.connect(lambda: self.tabs.setCurrentWidget(self.tab_wot.widget))
         self.tab_history.view_in_wot.connect(self.tab_wot.draw_graph)
@@ -94,27 +81,6 @@ class CommunityWidget(QWidget, Ui_CommunityWidget):
                                  QIcon(":/icons/network_icon"),
                                  self.tr("Network"))
 
-        action_showinfo = QAction(self.tr("Show informations"), self.toolbutton_menu)
-        action_showinfo.triggered.connect(lambda : self.show_closable_tab(self.tab_informations,
-                                    QIcon(":/icons/informations_icon"), self.tr("Informations")))
-        tool_menu.addAction(action_showinfo)
-
-        action_showexplorer = QAction(self.tr("Show explorer"), self.toolbutton_menu)
-        action_showexplorer.triggered.connect(lambda : self.show_closable_tab(self.tab_explorer.widget,
-                                    QIcon(":/icons/explorer_icon"), self.tr("Explorer")))
-        tool_menu.addAction(action_showexplorer)
-
-        menu_advanced = QMenu(self.tr("Advanced"), self.toolbutton_menu)
-        action_gen_revokation = QAction(self.tr("Save revokation document"), menu_advanced)
-        action_gen_revokation.triggered.connect(self.action_save_revokation)
-        menu_advanced.addAction(action_gen_revokation)
-        tool_menu.addMenu(menu_advanced)
-
-        self.action_publish_uid.triggered.connect(self.publish_uid)
-        tool_menu.addAction(self.action_publish_uid)
-
-        self.button_membership.clicked.connect(self.send_membership_demand)
-
     def show_closable_tab(self, tab, icon, title):
         if self.tabs.indexOf(tab) == -1:
             self.tabs.addTab(tab, icon, title)
@@ -175,31 +141,6 @@ class CommunityWidget(QWidget, Ui_CommunityWidget):
                     error,
                     QMessageBox.Ok)
 
-    @asyncify
-    async def action_save_revokation(self, checked=False):
-        password = await self.password_asker.async_exec()
-        if self.password_asker.result() == QDialog.Rejected:
-            return
-
-        raw_document = await self.account.generate_revokation(self.community, password)
-        # Testable way of using a QFileDialog
-        selected_files = await QAsyncFileDialog.get_save_filename(self, self.tr("Save a revokation document"),
-                                                "",  self.tr("All text files (*.txt)"))
-        if selected_files:
-            path = selected_files[0]
-            if not path.endswith('.txt'):
-                path = "{0}.txt".format(path)
-            with open(path, 'w') as save_file:
-                save_file.write(raw_document)
-
-        dialog = QMessageBox(QMessageBox.Information, self.tr("Revokation file"),
-                                           self.tr("""<div>Your revokation document has been saved.</div>
-<div><b>Please keep it in a safe place.</b></div>
-The publication of this document will remove your identity from the network.</p>"""), QMessageBox.Ok,
-                             self)
-        dialog.setTextFormat(Qt.RichText)
-        await dialog_async_exec(dialog)
-
     @once_at_a_time
     @asyncify
     async def refresh_block(self, block_number):
@@ -317,40 +258,6 @@ The publication of this document will remove your identity from the network.</p>
             self.status_label.setText(label_text)
             self.label_icon.setPixmap(QPixmap(icon).scaled(24, 24, Qt.KeepAspectRatio, Qt.SmoothTransformation))
 
-    @once_at_a_time
-    @asyncify
-    async def refresh_quality_buttons(self):
-        if self.account and self.community:
-            try:
-                account_identity = await self.account.identity(self.community)
-                published_uid = await account_identity.published_uid(self.community)
-                uid_is_revokable = await account_identity.uid_is_revokable(self.community)
-                if published_uid:
-                    logging.debug("UID Published")
-                    self.action_revoke_uid.setEnabled(uid_is_revokable)
-                    is_member = await account_identity.is_member(self.community)
-                    if is_member:
-                        self.button_membership.setText(self.tr("Renew membership"))
-                        self.button_membership.setEnabled(True)
-                        self.button_certification.setEnabled(True)
-                        self.action_publish_uid.setEnabled(False)
-                    else:
-                        logging.debug("Not a member")
-                        self.button_membership.setText(self.tr("Send membership demand"))
-                        self.button_membership.setEnabled(True)
-                        self.action_publish_uid.setEnabled(False)
-                        if await self.community.get_block(0) is not None:
-                            self.button_certification.setEnabled(False)
-                else:
-                    logging.debug("UID not published")
-                    self.button_membership.setEnabled(False)
-                    self.button_certification.setEnabled(False)
-                    self.action_publish_uid.setEnabled(True)
-            except LookupFailureError:
-                self.button_membership.setEnabled(False)
-                self.button_certification.setEnabled(False)
-                self.action_publish_uid.setEnabled(False)
-
     def showEvent(self, event):
         self.refresh_status()
 
@@ -360,69 +267,6 @@ The publication of this document will remove your identity from the network.</p>
             self.tab_history.refresh_balance()
             self.tab_informations.refresh()
 
-    @asyncify
-    async def send_membership_demand(self, checked=False):
-        password = await self.password_asker.async_exec()
-        if self.password_asker.result() == QDialog.Rejected:
-            return
-        result = await self.account.send_membership(password, self.community, 'IN')
-        if result[0]:
-            if self.app.preferences['notifications']:
-                toast.display(self.tr("Membership"), self.tr("Success sending Membership demand"))
-            else:
-                await QAsyncMessageBox.information(self, self.tr("Membership"),
-                                                        self.tr("Success sending Membership demand"))
-        else:
-            if self.app.preferences['notifications']:
-                toast.display(self.tr("Membership"), result[1])
-            else:
-                await QAsyncMessageBox.critical(self, self.tr("Membership"),
-                                                        result[1])
-
-    @asyncify
-    async def send_membership_leaving(self):
-        reply = await QAsyncMessageBox.warning(self, self.tr("Warning"),
-                             self.tr("""Are you sure ?
-Sending a leaving demand  cannot be canceled.
-The process to join back the community later will have to be done again.""")
-.format(self.account.pubkey), QMessageBox.Ok | QMessageBox.Cancel)
-        if reply == QMessageBox.Ok:
-            password = self.password_asker.exec_()
-            if self.password_asker.result() == QDialog.Rejected:
-                return
-            result = await self.account.send_membership(password, self.community, 'OUT')
-            if result[0]:
-                if self.app.preferences['notifications']:
-                    toast.display(self.tr("Revoke"), self.tr("Success sending Revoke demand"))
-                else:
-                    await QAsyncMessageBox.information(self, self.tr("Revoke"),
-                                                            self.tr("Success sending Revoke demand"))
-            else:
-                if self.app.preferences['notifications']:
-                    toast.display(self.tr("Revoke"), result[1])
-                else:
-                    await QAsyncMessageBox.critical(self, self.tr("Revoke"),
-                                                         result[1])
-
-    @asyncify
-    async def publish_uid(self, checked=False):
-        password = await self.password_asker.async_exec()
-        if self.password_asker.result() == QDialog.Rejected:
-            return
-        result = await self.account.send_selfcert(password, self.community)
-        if result[0]:
-            if self.app.preferences['notifications']:
-                toast.display(self.tr("UID"), self.tr("Success publishing your UID"))
-            else:
-                await QAsyncMessageBox.information(self, self.tr("Membership"),
-                                                        self.tr("Success publishing your UID"))
-        else:
-            if self.app.preferences['notifications']:
-                toast.display(self.tr("UID"), result[1])
-            else:
-                await QAsyncMessageBox.critical(self, self.tr("UID"),
-                                                        result[1])
-
     def retranslateUi(self, widget):
         """
         Method to complete translations missing from generated code
@@ -434,9 +278,6 @@ The process to join back the community later will have to be done again.""")
         self.tabs.setTabText(self.tabs.indexOf(self.tab_informations), self.tr(CommunityWidget._tab_informations_label))
         self.tabs.setTabText(self.tabs.indexOf(self.tab_history.widget), self.tr(CommunityWidget._tab_history_label))
         self.tabs.setTabText(self.tabs.indexOf(self.tab_identities.widget), self.tr(CommunityWidget._tab_identities_label))
-        self.action_publish_uid.setText(self.tr(CommunityWidget._action_publish_uid_text))
-        self.action_revoke_uid.setText(self.tr(CommunityWidget._action_revoke_uid_text))
-        self.action_showinfo.setText(self.tr(CommunityWidget._action_showinfo_text))
         super().retranslateUi(self)
 
     def showEvent(self, QShowEvent):
diff --git a/src/sakia/gui/contact.py b/src/sakia/gui/contact.py
index 8d3036b91222e6f993f91173a9294fdad1bc6a0b..0cac15ad5b289543e4e0265b1cf23d7eca2af600 100644
--- a/src/sakia/gui/contact.py
+++ b/src/sakia/gui/contact.py
@@ -9,7 +9,7 @@ import logging
 from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QMessageBox
 from ..core.registry import IdentitiesRegistry
 from ..tools.exceptions import ContactAlreadyExists
-from ..gen_resources.contact_uic import Ui_ConfigureContactDialog
+from ..presentation.contact_uic import Ui_ConfigureContactDialog
 
 
 class ConfigureContactDialog(QDialog, Ui_ConfigureContactDialog):
diff --git a/src/sakia/gui/graphs/explorer_tab.py b/src/sakia/gui/graphs/explorer_tab.py
index 78da13791d23c561ea03600e5662c2fcfcb54993..66ac4c7bd9abce3c904305633afd593b130593d5 100644
--- a/src/sakia/gui/graphs/explorer_tab.py
+++ b/src/sakia/gui/graphs/explorer_tab.py
@@ -7,7 +7,7 @@ from ...tools.exceptions import NoPeerAvailable
 from ...tools.decorators import asyncify, once_at_a_time, cancel_once_task
 from ...core.graph import ExplorerGraph
 from .graph_tab import GraphTabWidget
-from ...gen_resources.explorer_tab_uic import Ui_ExplorerTabWidget
+from ...presentation.explorer_tab_uic import Ui_ExplorerTabWidget
 
 
 class ExplorerTabWidget(GraphTabWidget, Ui_ExplorerTabWidget):
diff --git a/src/sakia/gui/graphs/wot_tab.py b/src/sakia/gui/graphs/wot_tab.py
index 31eedfdce5b7470cc8343bc5ee1dce59ec012c56..6ee4ff1213a3a040ba7dc822ff5dc3eecd8b00a5 100644
--- a/src/sakia/gui/graphs/wot_tab.py
+++ b/src/sakia/gui/graphs/wot_tab.py
@@ -5,7 +5,7 @@ from PyQt5.QtCore import QEvent, pyqtSignal, QT_TRANSLATE_NOOP, QObject
 from PyQt5.QtWidgets import QWidget
 from ...tools.decorators import asyncify, once_at_a_time, cancel_once_task
 from ...core.graph import WoTGraph
-from ...gen_resources.wot_tab_uic import Ui_WotTabWidget
+from ...presentation.wot_tab_uic import Ui_WotTabWidget
 from ...gui.widgets.busy import Busy
 from .graph_tab import GraphTabWidget
 
diff --git a/src/sakia/gui/homescreen.py b/src/sakia/gui/homescreen.py
index 3eb44eadf63bb86595608e6baabae20bf93c3714..0f0618b11f6ff38018cccc0dbd64ed634ddc364b 100644
--- a/src/sakia/gui/homescreen.py
+++ b/src/sakia/gui/homescreen.py
@@ -6,7 +6,7 @@ Created on 31 janv. 2015
 
 from PyQt5.QtWidgets import QWidget, QFrame, QGridLayout, QAction
 from PyQt5.QtCore import QEvent, Qt, pyqtSlot, pyqtSignal
-from ..gen_resources.homescreen_uic import Ui_HomescreenWidget
+from ..presentation.homescreen_uic import Ui_HomescreenWidget
 from .community_tile import CommunityTile
 from ..core.community import Community
 import logging
diff --git a/src/sakia/gui/identities_tab.py b/src/sakia/gui/identities_tab.py
index 21e5ab64e61f2f5ee56208bfdee97bfcfc56c90d..10b0f0cc4afee5cb276f3d9532c84b52ef83451e 100644
--- a/src/sakia/gui/identities_tab.py
+++ b/src/sakia/gui/identities_tab.py
@@ -14,7 +14,7 @@ from duniterpy.api import bma, errors
 from duniterpy.documents import BlockUID
 
 from ..models.identities import IdentitiesFilterProxyModel, IdentitiesTableModel
-from ..gen_resources.identities_tab_uic import Ui_IdentitiesTab
+from ..presentation.identities_tab_uic import Ui_IdentitiesTab
 from ..core.registry import Identity, BlockchainState
 from ..tools.exceptions import NoPeerAvailable
 from ..tools.decorators import asyncify, once_at_a_time, cancel_once_task
diff --git a/src/sakia/gui/import_account.py b/src/sakia/gui/import_account.py
index 59d73ff48fd9b2839406094b297ecd2b5c0ed25d..3c3d6e361fec88bfbe4d3fb31d84bce4fa47a004 100644
--- a/src/sakia/gui/import_account.py
+++ b/src/sakia/gui/import_account.py
@@ -7,7 +7,7 @@ import re
 from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QMessageBox, QFileDialog
 
 from ..tools.exceptions import Error
-from ..gen_resources.import_account_uic import Ui_ImportAccountDialog
+from ..presentation.import_account_uic import Ui_ImportAccountDialog
 
 
 class ImportAccountDialog(QDialog, Ui_ImportAccountDialog):
diff --git a/src/sakia/gui/informations_tab.py b/src/sakia/gui/informations_tab.py
index af6be48e89a9534237fa120560e25c2ea6355819..c46342aa596fb70478435d7a76c9511626bc80eb 100644
--- a/src/sakia/gui/informations_tab.py
+++ b/src/sakia/gui/informations_tab.py
@@ -8,7 +8,7 @@ import logging
 import math
 from PyQt5.QtCore import QLocale, QDateTime, QEvent
 from PyQt5.QtWidgets import QWidget
-from ..gen_resources.informations_tab_uic import Ui_InformationsTabWidget
+from ..presentation.informations_tab_uic import Ui_InformationsTabWidget
 from ..tools.decorators import asyncify, once_at_a_time, cancel_once_task
 from ..tools.exceptions import NoPeerAvailable
 from .widgets import Busy
diff --git a/src/sakia/gen_resources/__init__.py b/src/sakia/gui/main_window/__init__.py
similarity index 100%
rename from src/sakia/gen_resources/__init__.py
rename to src/sakia/gui/main_window/__init__.py
diff --git a/src/sakia/gui/main_window/controller.py b/src/sakia/gui/main_window/controller.py
new file mode 100644
index 0000000000000000000000000000000000000000..b80d1713c0727aab4f09c6c070468151e20494ae
--- /dev/null
+++ b/src/sakia/gui/main_window/controller.py
@@ -0,0 +1,119 @@
+"""
+Created on 1 févr. 2014
+
+@author: inso
+"""
+import aiohttp
+import logging
+import traceback
+
+from PyQt5.QtWidgets import QMessageBox, QApplication
+from PyQt5.QtCore import QEvent, pyqtSlot, QObject
+from PyQt5.QtGui import QIcon
+
+from ..password_asker import PasswordAskerDialog
+from ...__init__ import __version__
+from ..widgets import toast
+from ..agent.controller import AgentController
+from .view import MainWindowView
+from .model import MainWindowModel
+from ..status_bar.controller import StatusBarController
+
+
+class MainWindowController(AgentController):
+    """
+    classdocs
+    """
+
+    def __init__(self, view, model, password_asker, status_bar):
+        """
+        Init
+        :param MainWindowView view: the ui of the mainwindow agent
+        :param sakia.gui.main_window.model.MainWindowModel: the model of the mainwindow agent
+        :param sakia.gui.status_bar.controller.StatusBarController: the controller of the status bar agent
+
+        :param PasswordAsker password_asker: the password asker of the application
+        :type: sakia.core.app.Application
+        """
+        # Set up the user interface from Designer.
+        super().__init__(None, view, model)
+        self.initialized = False
+        self.password_asker = password_asker
+        if status_bar:
+            self.status_bar = self.attach(status_bar)
+
+        QApplication.setWindowIcon(QIcon(":/icons/sakia_logo"))
+
+    @classmethod
+    def startup(cls, app):
+        view = MainWindowView(None)
+        model = MainWindowModel(None, app)
+        main_window = cls(view, model,PasswordAskerDialog(None), None)
+        main_window.status_bar = main_window.attach(StatusBarController.create(main_window, app))
+        main_window.view.setStatusBar(main_window.status_bar.view)
+        #app.version_requested.connect(main_window.latest_version_requested)
+        #app.account_imported.connect(main_window.import_account_accepted)
+        #app.account_changed.connect(main_window.change_account)
+
+        view.showMaximized()
+        main_window.refresh()
+        return main_window
+
+    def change_account(self):
+        if self.account:
+            self.account.contacts_changed.disconnect(self.refresh_contacts)
+        self.account = self.app.current_account
+        self.password_asker.change_account(self.account)
+        self.refresh()
+
+    @pyqtSlot(str)
+    def display_error(self, error):
+        QMessageBox.critical(self, ":(",
+                             error,
+                             QMessageBox.Ok)
+
+    @pyqtSlot(int)
+    def referential_changed(self, index):
+        if self.account:
+            self.account.set_display_referential(index)
+            if self.community_view:
+                self.community_view.referential_changed()
+                self.homescreen.referential_changed()
+
+    @pyqtSlot()
+    def latest_version_requested(self):
+        latest = self.app.available_version
+        logging.debug("Latest version requested")
+        if not latest[0]:
+            version_info = self.tr("Please get the latest release {version}") \
+                .format(version=latest[1])
+            version_url = latest[2]
+
+            if self.app.preferences['notifications']:
+                toast.display("sakia", """{version_info}""".format(
+                version_info=version_info,
+                version_url=version_url))
+
+    def refresh(self):
+        """
+        Refresh main window
+        When the selected account changes, all the widgets
+        in the window have to be refreshed
+        """
+        self.status_bar.refresh()
+        self.view.setWindowTitle(self.tr("sakia {0}").format(__version__))
+
+    def eventFilter(self, target, event):
+        """
+        Event filter on the widget
+        :param QObject target: the target of the event
+        :param QEvent event: the event
+        :return: bool
+        """
+        if target == self.widget:
+            if event.type() == QEvent.LanguageChange:
+                self.ui.retranslateUi(self)
+                self.refresh()
+            return self.widget.eventFilter(target, event)
+        return False
+
diff --git a/res/ui/mainwindow.ui b/src/sakia/gui/main_window/mainwindow.ui
similarity index 63%
rename from res/ui/mainwindow.ui
rename to src/sakia/gui/main_window/mainwindow.ui
index d92357d930a1c8257d97ae0eaa38dbe2dfe9b4f5..b689d2b854e5d7d6aa43169d0b80ea013feedc32 100644
--- a/res/ui/mainwindow.ui
+++ b/src/sakia/gui/main_window/mainwindow.ui
@@ -14,76 +14,11 @@
    <string notr="true">Sakia</string>
   </property>
   <widget class="QWidget" name="centralwidget">
-   <layout class="QVBoxLayout" name="verticalLayout_6"/>
-  </widget>
-  <widget class="QMenuBar" name="menubar">
-   <property name="geometry">
-    <rect>
-     <x>0</x>
-     <y>0</y>
-     <width>900</width>
-     <height>30</height>
-    </rect>
-   </property>
-   <widget class="QMenu" name="menu_file">
-    <property name="title">
-     <string>Fi&amp;le</string>
-    </property>
-    <addaction name="action_import"/>
-    <addaction name="action_export"/>
-    <addaction name="separator"/>
-    <addaction name="actionPreferences"/>
-    <addaction name="action_quit"/>
-   </widget>
-   <widget class="QMenu" name="menu_account">
-    <property name="title">
-     <string>Acco&amp;unt</string>
-    </property>
-    <widget class="QMenu" name="menu_contacts_list">
-     <property name="title">
-      <string>Co&amp;ntacts</string>
-     </property>
-     <addaction name="separator"/>
-    </widget>
-    <widget class="QMenu" name="menu_change_account">
-     <property name="title">
-      <string>&amp;Open</string>
-     </property>
-    </widget>
-    <widget class="QMenu" name="menuAdvanced">
-     <property name="title">
-      <string>Advanced</string>
-     </property>
-     <addaction name="action_revoke_identity"/>
-    </widget>
-    <addaction name="menu_change_account"/>
-    <addaction name="action_configure_parameters"/>
-    <addaction name="action_add_account"/>
-    <addaction name="separator"/>
-    <addaction name="actionCertification"/>
-    <addaction name="actionTransfer_money"/>
-    <addaction name="separator"/>
-    <addaction name="action_add_a_contact"/>
-    <addaction name="menu_contacts_list"/>
-    <addaction name="separator"/>
-    <addaction name="menuAdvanced"/>
-   </widget>
-   <widget class="QMenu" name="menu_help">
-    <property name="title">
-     <string>&amp;Help</string>
-    </property>
-    <addaction name="actionAbout"/>
-   </widget>
-   <widget class="QMenu" name="menu_duniter">
-    <property name="title">
-     <string>&amp;Duniter</string>
-    </property>
-    <addaction name="actionManage_local_node"/>
-   </widget>
-   <addaction name="menu_file"/>
-   <addaction name="menu_account"/>
-   <addaction name="menu_duniter"/>
-   <addaction name="menu_help"/>
+   <layout class="QVBoxLayout" name="verticalLayout_6">
+    <item>
+     <layout class="QHBoxLayout" name="horizontalLayout"/>
+    </item>
+   </layout>
   </widget>
   <widget class="QStatusBar" name="statusbar"/>
   <action name="actionManage_accounts">
@@ -198,7 +133,7 @@
   </action>
   <action name="action_revoke_identity">
    <property name="text">
-    <string>Revoke an identity</string>
+    <string>&amp;Revoke an identity</string>
    </property>
   </action>
  </widget>
diff --git a/src/sakia/gui/main_window/model.py b/src/sakia/gui/main_window/model.py
new file mode 100644
index 0000000000000000000000000000000000000000..32af1551002eed101f94c0f0999ac086ffc1e217
--- /dev/null
+++ b/src/sakia/gui/main_window/model.py
@@ -0,0 +1,15 @@
+from sakia.gui.agent.model import AgentModel
+from sakia.core.money import Referentials
+
+
+class MainWindowModel(AgentModel):
+    """
+    The model of Navigation agent
+    """
+
+    def __init__(self, parent, app):
+        super().__init__(parent)
+        self.app = app
+
+    def referentials(self):
+        return Referentials
diff --git a/src/sakia/gui/main_window/view.py b/src/sakia/gui/main_window/view.py
new file mode 100644
index 0000000000000000000000000000000000000000..784bc7ddeb257be8d18997ff08728bf027998cea
--- /dev/null
+++ b/src/sakia/gui/main_window/view.py
@@ -0,0 +1,12 @@
+from PyQt5.QtWidgets import QMainWindow
+from .mainwindow_uic import Ui_MainWindow
+
+
+class MainWindowView(QMainWindow, Ui_MainWindow):
+    """
+    The model of Navigation agent
+    """
+
+    def __init__(self, parent):
+        super().__init__(parent)
+        self.setupUi(self)
diff --git a/src/sakia/gui/mainwindow.py b/src/sakia/gui/mainwindow.py
deleted file mode 100644
index 5d66b78e060f2d8ad39799d10ec09d94e7944b9a..0000000000000000000000000000000000000000
--- a/src/sakia/gui/mainwindow.py
+++ /dev/null
@@ -1,460 +0,0 @@
-"""
-Created on 1 févr. 2014
-
-@author: inso
-"""
-import aiohttp
-import logging
-import traceback
-
-from PyQt5.QtWidgets import QMainWindow, QAction, QFileDialog, \
-    QMessageBox, QLabel, QComboBox, QDialog, QApplication, QErrorMessage
-from PyQt5.QtCore import QLocale, QEvent, \
-    pyqtSlot, QDateTime, QTimer, Qt, QObject, QUrl
-from PyQt5.QtGui import QIcon
-
-from ..gen_resources.mainwindow_uic import Ui_MainWindow
-from ..gen_resources.about_uic import Ui_AboutPopup
-from .process_cfg_account import ProcessConfigureAccount
-from .transfer import TransferMoneyDialog
-from .community_view import CommunityWidget
-from .contact import ConfigureContactDialog
-from .import_account import ImportAccountDialog
-from .certification import CertificationDialog
-from .revocation import RevocationDialog
-from .password_asker import PasswordAskerDialog
-from .preferences import PreferencesDialog
-from .process_cfg_community import ProcessConfigureCommunity
-from .homescreen import HomeScreenWidget
-from .node_manager import NodeManager
-from ..core import money
-from ..core.community import Community
-from ..tools.decorators import asyncify
-from ..__init__ import __version__
-from .widgets import toast
-from .widgets.dialogs import QAsyncMessageBox
-
-
-class MainWindow(QObject):
-    """
-    classdocs
-    """
-
-    def __init__(self, app, account, homescreen, community_view, node_manager,
-                 widget, ui,
-                 label_icon, label_status, label_time, combo_referential,
-                 password_asker):
-        """
-        Init
-        :param sakia.core.app.Application app: application
-        :param sakia.core.Account account: the account
-        :param HomeScreenWidgetcreen homescreen: the homescreen
-        :param CommunityView community_view: the community view
-        :param NodeManager node_manager: the local node manager dialog
-        :param QMainWindow widget: the widget of the main window
-        :param Ui_MainWindow ui: the ui of the widget
-        :param QLabel label_icon: the label of the icon in the statusbar
-        :param QLabel label_status: the label of the status in the statusbar
-        :param QLabel label_time: the label of the time in the statusbar
-        :param QCombobox combo_referential: the combo of the referentials in the statusbar
-        :param PasswordAsker password_asker: the password asker of the application
-        :type: sakia.core.app.Application
-        """
-        # Set up the user interface from Designer.
-        super().__init__()
-        self.app = app
-        self.account = account
-        self.initialized = False
-        self.password_asker = password_asker
-        self.import_dialog = None
-        self.widget = widget
-        self.ui = ui
-        self.ui.setupUi(self.widget)
-        self.widget.installEventFilter(self)
-
-        QApplication.setWindowIcon(QIcon(":/icons/sakia_logo"))
-
-        self.label_icon = label_icon
-
-        self.status_label = label_status
-        self.status_label.setTextFormat(Qt.RichText)
-
-        self.label_time = label_time
-
-        self.combo_referential = combo_referential
-        self.combo_referential.setEnabled(False)
-        self.combo_referential.currentIndexChanged[int].connect(self.referential_changed)
-
-        self.homescreen = homescreen
-
-        self.community_view = community_view
-
-        self.node_manager = node_manager
-
-
-    def _init_ui(self):
-        """
-        Connects elements of the UI to the local slots
-        """
-        self.ui.statusbar.addPermanentWidget(self.label_icon, 1)
-        self.ui.statusbar.addPermanentWidget(self.status_label, 2)
-        self.ui.statusbar.addPermanentWidget(self.label_time)
-        self.ui.statusbar.addPermanentWidget(self.combo_referential)
-
-        self.ui.action_add_account.triggered.connect(self.open_add_account_dialog)
-        self.ui.action_quit.triggered.connect(self.widget.close)
-        self.ui.actionTransfer_money.triggered.connect(self.open_transfer_money_dialog)
-        self.ui.action_add_a_contact.triggered.connect(self.open_add_contact_dialog)
-        self.ui.action_configure_parameters.triggered.connect(self.open_configure_account_dialog)
-        self.ui.action_import.triggered.connect(self.import_account)
-        self.ui.action_export.triggered.connect(self.export_account)
-        self.ui.actionCertification.triggered.connect(self.open_certification_dialog)
-        self.ui.actionPreferences.triggered.connect(self.open_preferences_dialog)
-        self.ui.actionAbout.triggered.connect(self.open_about_popup)
-        self.ui.action_revoke_identity.triggered.connect(self.open_revocation_dialog)
-
-        self.ui.actionManage_local_node.triggered.connect(self.open_duniter_ui)
-        self.ui.menu_duniter.setDisabled(True)
-
-    def _init_homescreen(self):
-        """
-        Initialize homescreen signals/slots and data
-        :return:
-        """
-        self.homescreen.status_label = self.status_label
-        self.homescreen.frame_communities.community_tile_clicked.connect(self.change_community)
-        self.homescreen.toolbutton_new_account.clicked.connect(self.open_add_account_dialog)
-        self.homescreen.toolbutton_new_account.addAction(self.ui.action_add_account)
-        self.homescreen.toolbutton_new_account.addAction(self.ui.action_import)
-        self.homescreen.button_add_community.clicked.connect(self.action_open_add_community)
-        self.homescreen.button_disconnect.clicked.connect(lambda :self.action_change_account(""))
-        self.widget.centralWidget().layout().addWidget(self.homescreen)
-        self.homescreen.toolbutton_connect.setMenu(self.ui.menu_change_account)
-
-    def _init_community_view(self):
-        """
-        Initialize the community view signals/slots and data
-        :return:
-        """
-        self.community_view.status_label = self.status_label
-        self.community_view.label_icon = self.label_icon
-        self.community_view.button_home.clicked.connect(lambda: self.change_community(None))
-        self.community_view.button_certification.clicked.connect(self.open_certification_dialog)
-        self.community_view.button_send_money.clicked.connect(self.open_transfer_money_dialog)
-        self.widget.centralWidget().layout().addWidget(self.community_view)
-
-    @classmethod
-    def startup(cls, app):
-        qmainwindow = QMainWindow()
-
-        main_window = cls(app, None, HomeScreenWidget(app, None),
-                          CommunityWidget(app, None, None),
-                          None, #NodeManager.create(qmainwindow),
-                          qmainwindow, Ui_MainWindow(),
-                          QLabel("", qmainwindow), QLabel("", qmainwindow),
-                          QLabel("", qmainwindow), QComboBox(qmainwindow),
-                          PasswordAskerDialog(None))
-        app.version_requested.connect(main_window.latest_version_requested)
-        app.account_imported.connect(main_window.import_account_accepted)
-        app.account_changed.connect(main_window.change_account)
-        main_window._init_ui()
-        main_window._init_homescreen()
-        main_window._init_community_view()
-
-        main_window.update_time()
-        if app.preferences['maximized']:
-            main_window.widget.showMaximized()
-        else:
-            main_window.widget.show()
-        if app.current_account:
-            main_window.password_asker = PasswordAskerDialog(app.current_account)
-            main_window.community_view.change_account(app.current_account, main_window.password_asker)
-            main_window.app.current_account.contacts_changed.connect(main_window.refresh_contacts)
-        main_window.refresh()
-        return main_window
-
-    def change_account(self):
-        if self.account:
-            self.account.contacts_changed.disconnect(self.refresh_contacts)
-        self.account = self.app.current_account
-        self.password_asker.change_account(self.account)
-        self.community_view.change_account(self.account, self.password_asker)
-        if self.account:
-            self.account.contacts_changed.connect(self.refresh_contacts)
-        self.refresh()
-
-    @asyncify
-    async def open_add_account_dialog(self, checked=False):
-        dialog = ProcessConfigureAccount(self.app, None)
-        result = await dialog.async_exec()
-        if result == QDialog.Accepted:
-            self.action_change_account(self.account.name)
-
-    @asyncify
-    async def open_configure_account_dialog(self, checked=False):
-        dialog = ProcessConfigureAccount(self.app, self.account)
-        result = await dialog.async_exec()
-        if result == QDialog.Accepted:
-            if self.account:
-                self.action_change_account(self.account.name)
-            else:
-                self.refresh()
-
-    @pyqtSlot(str)
-    def display_error(self, error):
-        QMessageBox.critical(self, ":(",
-                             error,
-                             QMessageBox.Ok)
-
-    @pyqtSlot(int)
-    def referential_changed(self, index):
-        if self.account:
-            self.account.set_display_referential(index)
-            if self.community_view:
-                self.community_view.referential_changed()
-                self.homescreen.referential_changed()
-
-    @pyqtSlot()
-    def update_time(self):
-        dateTime = QDateTime.currentDateTime()
-        self.label_time.setText("{0}".format(QLocale.toString(
-                        QLocale(),
-                        QDateTime.currentDateTime(),
-                        QLocale.dateTimeFormat(QLocale(), QLocale.NarrowFormat)
-                    )))
-        timer = QTimer()
-        timer.timeout.connect(self.update_time)
-        timer.start(1000)
-
-    @pyqtSlot()
-    def delete_contact(self):
-        contact = self.sender().data()
-        self.account.remove_contact(contact)
-
-    @pyqtSlot()
-    def edit_contact(self):
-        index = self.sender().data()
-        dialog = ConfigureContactDialog.edit_contact(self.app, self.account, self.widget, index)
-        dialog.exec_()
-
-    def action_change_account(self, account_name):
-        self.app.change_current_account(self.app.get_account(account_name))
-
-    @pyqtSlot()
-    def action_open_add_community(self):
-        dialog = ProcessConfigureCommunity(self.app,
-                                           self.account, None,
-                                           self.password_asker)
-        if dialog.exec_() == QDialog.Accepted:
-            self.app.save(self.account)
-            dialog.community.start_coroutines()
-            self.homescreen.refresh()
-
-    def open_transfer_money_dialog(self):
-        dialog = TransferMoneyDialog(self.app,
-                                     self.account,
-                                     self.password_asker,
-                                     self.community_view.community,
-                                     None)
-        if dialog.exec() == QDialog.Accepted:
-            self.community_view.tab_history.table_history.model().sourceModel().refresh_transfers()
-
-    def open_certification_dialog(self):
-        CertificationDialog.open_dialog(self.app,
-                                     self.account,
-                                     self.community_view.community,
-                                     self.password_asker)
-
-    def open_revocation_dialog(self):
-        RevocationDialog.open_dialog(self.app,
-                                     self.account)
-
-    def open_add_contact_dialog(self):
-        dialog = ConfigureContactDialog.new_contact(self.app, self.account, self.widget)
-        dialog.exec_()
-
-    def open_preferences_dialog(self):
-        dialog = PreferencesDialog(self.app)
-        dialog.exec_()
-
-    def open_about_popup(self):
-        """
-        Open about popup window
-        """
-        aboutDialog = QDialog(self.widget)
-        aboutUi = Ui_AboutPopup()
-        aboutUi.setupUi(aboutDialog)
-
-        latest = self.app.available_version
-        version_info = ""
-        version_url = ""
-        if not latest[0]:
-            version_info = self.tr("Latest release : {version}") \
-                .format(version=latest[1])
-            version_url = latest[2]
-
-            new_version_text = """
-                <p><b>{version_info}</b></p>
-                <p><a href="{version_url}">{link_text}</a></p>
-                """.format(version_info=version_info,
-                            version_url=version_url,
-                            link_text=self.tr("Download link"))
-        else:
-            new_version_text = ""
-
-        text = self.tr("""
-        <h1>sakia</h1>
-
-        <p>Python/Qt duniter client</p>
-        <p><a href="https://github.com/duniter/sakia">https://github.com/duniter/sakia</a></p>
-
-        <p>Version : {:}</p>
-        {new_version_text}
-
-        <p>License : GPLv3</p>
-
-        <p><b>Authors</b></p>
-
-        <p>inso</p>
-        <p>vit</p>
-        <p>Moul</p>
-        <p>canercandan</p>
-        """).format(__version__, new_version_text=new_version_text)
-
-        aboutUi.label.setText(text)
-        aboutDialog.show()
-
-    @pyqtSlot()
-    def latest_version_requested(self):
-        latest = self.app.available_version
-        logging.debug("Latest version requested")
-        if not latest[0]:
-            version_info = self.tr("Please get the latest release {version}") \
-                .format(version=latest[1])
-            version_url = latest[2]
-
-            if self.app.preferences['notifications']:
-                toast.display("sakia", """{version_info}""".format(
-                version_info=version_info,
-                version_url=version_url))
-
-    @pyqtSlot(Community)
-    def change_community(self, community):
-        if community:
-            self.homescreen.hide()
-            self.community_view.show()
-        else:
-            self.community_view.hide()
-            self.homescreen.show()
-
-        self.community_view.change_community(community)
-
-    def refresh_accounts(self):
-        self.ui.menu_change_account.clear()
-        for account_name in sorted(self.app.accounts.keys()):
-            action = QAction(account_name, self.widget)
-            action.triggered.connect(lambda checked, account_name=account_name: self.action_change_account(account_name))
-            self.ui.menu_change_account.addAction(action)
-
-    def refresh_contacts(self):
-        self.ui.menu_contacts_list.clear()
-        if self.account:
-            for index, contact in enumerate(self.account.contacts):
-                contact_menu = self.ui.menu_contacts_list.addMenu(contact['name'])
-                edit_action = contact_menu.addAction(self.tr("Edit"))
-                edit_action.triggered.connect(self.edit_contact)
-                edit_action.setData(index)
-                delete_action = contact_menu.addAction(self.tr("Delete"))
-                delete_action.setData(contact)
-                delete_action.triggered.connect(self.delete_contact)
-
-    @asyncify
-    async def open_duniter_ui(self, checked=False):
-        if not self.node_manager.widget.isVisible():
-            self.node_manager.open_home_page()
-
-    def refresh(self):
-        """
-        Refresh main window
-        When the selected account changes, all the widgets
-        in the window have to be refreshed
-        """
-        logging.debug("Refresh started")
-        self.refresh_accounts()
-        self.community_view.hide()
-        self.homescreen.show()
-        self.homescreen.refresh()
-
-        if self.account is None:
-            self.widget.setWindowTitle(self.tr("sakia {0}").format(__version__))
-            self.ui.action_add_a_contact.setEnabled(False)
-            self.ui.actionCertification.setEnabled(False)
-            self.ui.actionTransfer_money.setEnabled(False)
-            self.ui.action_configure_parameters.setEnabled(False)
-            self.ui.action_set_as_default.setEnabled(False)
-            self.ui.menu_contacts_list.setEnabled(False)
-            self.combo_referential.setEnabled(False)
-            self.status_label.setText(self.tr(""))
-        else:
-            self.combo_referential.blockSignals(True)
-            self.combo_referential.clear()
-            for ref in money.Referentials:
-                self.combo_referential.addItem(ref.translated_name())
-            logging.debug(self.app.preferences)
-
-            self.combo_referential.setEnabled(True)
-            self.combo_referential.blockSignals(False)
-            self.combo_referential.setCurrentIndex(self.app.preferences['ref'])
-            self.ui.action_add_a_contact.setEnabled(True)
-            self.ui.actionCertification.setEnabled(True)
-            self.ui.actionTransfer_money.setEnabled(True)
-            self.ui.menu_contacts_list.setEnabled(True)
-            self.ui.action_configure_parameters.setEnabled(True)
-            self.widget.setWindowTitle(self.tr("sakia {0} - Account : {1}").format(__version__,
-                                                                               self.account.name))
-
-        self.refresh_contacts()
-
-    def import_account(self):
-        import_dialog = ImportAccountDialog(self.app, self.widget)
-        import_dialog.exec_()
-
-    def import_account_accepted(self, account_name):
-        # open account after import
-        self.action_change_account(account_name)
-
-    def export_account(self):
-        # Testable way of using a QFileDialog
-        export_dialog = QFileDialog(self.widget)
-        export_dialog.setObjectName('ExportFileDialog')
-        export_dialog.setWindowTitle(self.tr("Export an account"))
-        export_dialog.setNameFilter(self.tr("All account files (*.acc)"))
-        export_dialog.setLabelText(QFileDialog.Accept, self.tr('Export'))
-        export_dialog.setOption(QFileDialog.DontUseNativeDialog, True)
-        export_dialog.accepted.connect(self.export_account_accepted)
-        export_dialog.show()
-
-    def export_account_accepted(self):
-        export_dialog = self.sender()
-        selected_file = export_dialog.selectedFiles()
-        if selected_file:
-            if selected_file[0][-4:] == ".acc":
-                path = selected_file[0]
-            else:
-                path = selected_file[0] + ".acc"
-            self.app.export_account(path, self.account)
-
-    def eventFilter(self, target, event):
-        """
-        Event filter on the widget
-        :param QObject target: the target of the event
-        :param QEvent event: the event
-        :return: bool
-        """
-        if target == self.widget:
-            if event.type() == QEvent.LanguageChange:
-                self.ui.retranslateUi(self)
-                self.refresh()
-            return self.widget.eventFilter(target, event)
-        return False
-
diff --git a/src/sakia/gui/member.py b/src/sakia/gui/member.py
index 5d2744dea1d3e3e9953e514727da816f423814bd..d81d312ccc11eadb7cb73292a38fac71b38992f2 100644
--- a/src/sakia/gui/member.py
+++ b/src/sakia/gui/member.py
@@ -6,7 +6,7 @@ from PyQt5.QtWidgets import QDialog, QWidget
 from ..core.graph import WoTGraph
 from .widgets.busy import Busy
 from ..tools.decorators import asyncify
-from ..gen_resources.member_uic import Ui_MemberView
+from ..presentation.member_uic import Ui_MemberView
 from ..tools.exceptions import MembershipNotFoundError, LookupFailureError, NoPeerAvailable
 from ..core.registry import LocalState
 
@@ -25,7 +25,7 @@ class MemberDialog(QObject):
         :param sakia.core.community.Community community: Community instance
         :param sakia.core.registry.identity.Identity identity: Identity instance
         :param PyQt5.QtWidget widget: The class of the widget
-        :param sakia.gen_resources.member_uic.Ui_DialogMember ui: the class of the ui applyed to the widget
+        :param sakia.presentation.member_uic.Ui_DialogMember ui: the class of the ui applyed to the widget
         :return:
         """
         super().__init__()
diff --git a/src/sakia/gui/navigation/__init__.py b/src/sakia/gui/navigation/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/src/sakia/gui/navigation/controller.py b/src/sakia/gui/navigation/controller.py
new file mode 100644
index 0000000000000000000000000000000000000000..3e94d470e1ea9bbdbe18c0d9fee31734ffdbfcd0
--- /dev/null
+++ b/src/sakia/gui/navigation/controller.py
@@ -0,0 +1,34 @@
+from PyQt5.QtWidgets import QTreeView
+from .model import NavigationModel
+from ..agent.controller import AgentController
+from ..agent.model import AgentModel
+
+
+class NavigationController(AgentController):
+    """
+    The navigation panel
+    """
+
+    def __init__(self, parent, presentation, model):
+        """
+        Constructor of the navigation agent
+
+        :param PyQt5.QtWidgets.QTreeView presentation: the presentation
+        :param sakia.core.gui.navigation.model.NavigationModel model: the model
+        """
+        super().__init__(parent, presentation, model)
+
+    @classmethod
+    def create(cls, parent, app):
+        """
+        Instanciate a navigation agent
+        :param sakia.gui.agent.controller.AgentController parent:
+        :return: a new Navigation controller
+        :rtype: NavigationController
+        """
+        presentation = QTreeView(parent.presentation)
+        model = NavigationModel(None, app)
+        navigation = cls(presentation, model)
+        model.setParent(navigation)
+        return navigation
+
diff --git a/src/sakia/gui/navigation/model.py b/src/sakia/gui/navigation/model.py
new file mode 100644
index 0000000000000000000000000000000000000000..bfe30093d7b51ad1f300470195de005489c2822f
--- /dev/null
+++ b/src/sakia/gui/navigation/model.py
@@ -0,0 +1,75 @@
+from PyQt5.QtCore import QAbstractItemModel, Qt, QVariant
+
+
+class NavigationModel(QAbstractItemModel):
+    """
+    The model of Navigation agent
+    """
+    def __init__(self, parent, app):
+        super().__init__(parent)
+        self.app = app
+
+    def tree(self):
+        navigation = {'profile': {
+                        'node': {
+                            'title': self.account.name
+                        },
+                        'children': {}
+                        }
+                    }
+        for c in self.account.communities:
+            navigation['profile']['children'].append({
+                'node': {
+                    'title': c.currency
+                },
+                'children': {
+                    'transfers': {
+                        'node': {
+                            'title': self.tr('Transfers')
+                        }
+                    },
+                    'network': {
+                        'node': {
+                            'title': self.tr('Network')
+                        }
+                    },
+                    'network': {
+                        'node': {
+                            'title': self.tr('Network')
+                        }
+                    }
+                }
+            })
+
+    def rowCount(self, parent):
+        return len(self.nodes_data)
+
+    def columnCount(self, parent):
+        return len(self.columns_types)
+
+    def headerData(self, section, orientation, role):
+        if role != Qt.DisplayRole:
+            return QVariant()
+
+        return self.columns_types[section]
+
+    def data(self, index, role):
+        row = index.row()
+        col = index.column()
+
+        if not index.isValid():
+            return QVariant()
+
+        node = self.nodes_data[row]
+        if role == Qt.DisplayRole:
+            return node[col]
+        if role == Qt.BackgroundColorRole:
+            return self.node_colors[node[self.columns_types.index('state')]]
+        if role == Qt.ToolTipRole:
+            return self.node_states[node[self.columns_types.index('state')]]()
+
+        return QVariant()
+
+    def flags(self, index):
+        return Qt.ItemIsSelectable | Qt.ItemIsEnabled
+
diff --git a/src/sakia/gui/network_tab.py b/src/sakia/gui/network_tab.py
index ace7c59e9a5febad3462debcbb5a8735c9ebcc3a..95ba687e44af709c1ad61cddd41f832b60b7ce80 100644
--- a/src/sakia/gui/network_tab.py
+++ b/src/sakia/gui/network_tab.py
@@ -12,7 +12,7 @@ from PyQt5.QtWidgets import QWidget, QMenu, QAction
 from PyQt5.QtCore import Qt, QModelIndex, pyqtSlot, QUrl, QEvent
 from ..models.network import NetworkTableModel, NetworkFilterProxyModel
 from duniterpy.api import bma
-from ..gen_resources.network_tab_uic import Ui_NetworkTabWidget
+from ..presentation.network_tab_uic import Ui_NetworkTabWidget
 
 
 class NetworkTabWidget(QWidget, Ui_NetworkTabWidget):
diff --git a/src/sakia/gui/node_manager.py b/src/sakia/gui/node_manager.py
index 7dd8432442563ffc58754f7c52ccc8a2102f0ace..ffbe8067de8659fa33e933561c73b3589ca18e38 100644
--- a/src/sakia/gui/node_manager.py
+++ b/src/sakia/gui/node_manager.py
@@ -18,7 +18,7 @@ class NodeManager(QObject):
         Init MemberDialog
 
         :param PyQt5.QtWidget widget: The class of the widget
-        :param sakia.gen_resources.member_uic.Ui_DialogMember ui: the class of the ui applyed to the widget
+        :param sakia.presentation.member_uic.Ui_DialogMember ui: the class of the ui applyed to the widget
         :return:
         """
         super().__init__()
diff --git a/src/sakia/gui/password_asker.py b/src/sakia/gui/password_asker.py
index be1b97c3a64a2e4e09ff76e638f8797f94aeb707..ecb926688e3f22bd70acf152ff3a0de6895c9ccc 100644
--- a/src/sakia/gui/password_asker.py
+++ b/src/sakia/gui/password_asker.py
@@ -10,7 +10,7 @@ import asyncio
 from PyQt5.QtCore import QEvent
 from PyQt5.QtWidgets import QDialog, QMessageBox
 
-from ..gen_resources.password_asker_uic import Ui_PasswordAskerDialog
+from ..presentation.password_asker_uic import Ui_PasswordAskerDialog
 
 
 class PasswordAskerDialog(QDialog, Ui_PasswordAskerDialog):
diff --git a/src/sakia/gui/preferences.py b/src/sakia/gui/preferences.py
index 6f04bc1d4a8d245fc525c6d6c646f871c3006c65..9d00fc555c37974bd95319c2603094111ee05f4c 100644
--- a/src/sakia/gui/preferences.py
+++ b/src/sakia/gui/preferences.py
@@ -8,7 +8,7 @@ from PyQt5.QtCore import QCoreApplication
 from PyQt5.QtWidgets import QDialog
 
 from ..core import money
-from ..gen_resources.preferences_uic import Ui_PreferencesDialog
+from ..presentation.preferences_uic import Ui_PreferencesDialog
 
 
 class PreferencesDialog(QDialog, Ui_PreferencesDialog):
diff --git a/src/sakia/gui/process_cfg_account.py b/src/sakia/gui/process_cfg_account.py
index 57cc4d54907b79b3de173289cffcb13ddaa7926b..023d726dcd8e33294a4dd74aae61443006f07c71 100644
--- a/src/sakia/gui/process_cfg_account.py
+++ b/src/sakia/gui/process_cfg_account.py
@@ -6,7 +6,7 @@ Created on 6 mars 2014
 import logging
 import asyncio
 from duniterpy.key import SigningKey
-from ..gen_resources.account_cfg_uic import Ui_AccountConfigurationDialog
+from ..presentation.account_cfg_uic import Ui_AccountConfigurationDialog
 from ..gui.process_cfg_community import ProcessConfigureCommunity
 from ..gui.password_asker import PasswordAskerDialog, detect_non_printable
 from ..gui.widgets.dialogs import QAsyncMessageBox
diff --git a/src/sakia/gui/process_cfg_community.py b/src/sakia/gui/process_cfg_community.py
index 5717579fb5dac384cc8501a94bd48e9f9578c64e..4f437e380c7ffba363b84030aab166dac87bbddd 100644
--- a/src/sakia/gui/process_cfg_community.py
+++ b/src/sakia/gui/process_cfg_community.py
@@ -15,7 +15,7 @@ from PyQt5.QtWidgets import QDialog, QMenu, QApplication
 from PyQt5.QtGui import QCursor
 from PyQt5.QtCore import pyqtSignal, QObject
 
-from ..gen_resources.community_cfg_uic import Ui_CommunityConfigurationDialog
+from ..presentation.community_cfg_uic import Ui_CommunityConfigurationDialog
 from ..models.peering import PeeringTreeModel
 from ..core import Community
 from ..core.net import Node
diff --git a/src/sakia/gui/revocation.py b/src/sakia/gui/revocation.py
index 5de30bf1ef1e64d9a3601ad49fb4340e345da408..31b3d6b31beb8d14df7a67f1372334eb5bf3911b 100644
--- a/src/sakia/gui/revocation.py
+++ b/src/sakia/gui/revocation.py
@@ -11,7 +11,7 @@ from PyQt5.QtCore import QObject
 
 from .widgets.dialogs import QAsyncMessageBox
 from ..tools.decorators import asyncify
-from ..gen_resources.revocation_uic import Ui_RevocationDialog
+from ..presentation.revocation_uic import Ui_RevocationDialog
 
 
 class RevocationDialog(QObject):
diff --git a/src/sakia/gui/status_bar/__init__.py b/src/sakia/gui/status_bar/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/src/sakia/gui/status_bar/controller.py b/src/sakia/gui/status_bar/controller.py
new file mode 100644
index 0000000000000000000000000000000000000000..24c1d7062ddf566a66965f2fb54ed6ac13464206
--- /dev/null
+++ b/src/sakia/gui/status_bar/controller.py
@@ -0,0 +1,76 @@
+from PyQt5.QtCore import QLocale, pyqtSlot, QDateTime, QTimer
+from ..agent.controller import AgentController
+from .model import StatusBarModel
+from .view import StatusBarView
+import logging
+
+
+class StatusBarController(AgentController):
+    """
+    The navigation panel
+    """
+
+    def __init__(self, parent, view, model):
+        """
+        Constructor of the navigation agent
+
+        :param sakia.gui.status_bar.view.StatusBarView view: the presentation
+        :param sakia.core.status_bar.model.StatusBarModel model: the model
+        """
+        super().__init__(parent, view, model)
+        view.combo_referential.currentIndexChanged[int].connect(self.referential_changed)
+        self.update_time()
+
+    @classmethod
+    def create(cls, parent, app):
+        """
+        Instanciate a navigation agent
+        :param sakia.gui.main_window.controller.MainWindowController parent:
+        :return: a new Navigation controller
+        :rtype: NavigationController
+        """
+        view = StatusBarView(parent.view)
+
+        model = StatusBarModel(None, app)
+        status_bar = cls(parent, view, model)
+        model.setParent(status_bar)
+        return status_bar
+
+    @pyqtSlot()
+    def update_time(self):
+        dateTime = QDateTime.currentDateTime()
+        self.view.label_time.setText("{0}".format(QLocale.toString(
+                        QLocale(),
+                        QDateTime.currentDateTime(),
+                        QLocale.dateTimeFormat(QLocale(), QLocale.NarrowFormat)
+                    )))
+        timer = QTimer()
+        timer.timeout.connect(self.update_time)
+        timer.start(1000)
+
+    def refresh(self):
+        """
+        Refresh main window
+        When the selected account changes, all the widgets
+        in the window have to be refreshed
+        """
+        logging.debug("Refresh started")
+
+        if self.model.account is None:
+            self.view.combo_referential.setEnabled(False)
+            self.view.status_label.setText(self.tr(""))
+        else:
+            self.view.combo_referential.blockSignals(True)
+            self.view.combo_referential.clear()
+            for ref in self.model.referentials():
+                self.view.combo_referential.addItem(ref.translated_name())
+            logging.debug(self.app.preferences)
+
+            self.view.combo_referential.setEnabled(True)
+            self.view.combo_referential.blockSignals(False)
+            self.view.combo_referential.setCurrentIndex(self.app.preferences['ref'])
+
+    @pyqtSlot(int)
+    def referential_changed(self, index):
+        if self.model.account:
+            self.model.account.set_display_referential(index)
\ No newline at end of file
diff --git a/src/sakia/gui/status_bar/model.py b/src/sakia/gui/status_bar/model.py
new file mode 100644
index 0000000000000000000000000000000000000000..b1ef970936ea787d9b1c6adaba2f267880940f30
--- /dev/null
+++ b/src/sakia/gui/status_bar/model.py
@@ -0,0 +1,11 @@
+from sakia.gui.agent.model import AgentModel
+
+
+class StatusBarModel(AgentModel):
+    """
+    The model of Navigation agent
+    """
+
+    def __init__(self, parent, app):
+        super().__init__(parent)
+        self.app = app
diff --git a/src/sakia/gui/status_bar/view.py b/src/sakia/gui/status_bar/view.py
new file mode 100644
index 0000000000000000000000000000000000000000..5f631e69bdcdaf93df00beb6eca243608e9176ce
--- /dev/null
+++ b/src/sakia/gui/status_bar/view.py
@@ -0,0 +1,26 @@
+from PyQt5.QtWidgets import QStatusBar
+from PyQt5.QtWidgets import QLabel, QComboBox
+from PyQt5.QtCore import Qt
+
+
+class StatusBarView(QStatusBar):
+    """
+    The model of Navigation agent
+    """
+
+    def __init__(self, parent):
+        super().__init__(parent)
+        self.label_icon = QLabel("", parent)
+
+        self.status_label = QLabel("", parent)
+        self.status_label.setTextFormat(Qt.RichText)
+
+        self.label_time = QLabel("", parent)
+
+        self.combo_referential = QComboBox(parent)
+        self.combo_referential.setEnabled(False)
+
+        self.addPermanentWidget(self.label_icon, 1)
+        self.addPermanentWidget(self.status_label, 2)
+        self.addPermanentWidget(self.label_time)
+        self.addPermanentWidget(self.combo_referential)
\ No newline at end of file
diff --git a/src/sakia/gui/toolbar/__init__.py b/src/sakia/gui/toolbar/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/src/sakia/gui/toolbar/controller.py b/src/sakia/gui/toolbar/controller.py
new file mode 100644
index 0000000000000000000000000000000000000000..78b4ab0bfa7368c0457ba5b23e5ebaaeb31a3618
--- /dev/null
+++ b/src/sakia/gui/toolbar/controller.py
@@ -0,0 +1,254 @@
+from PyQt5.QtWidgets import QFrame, QAction, QMenu, QDialog, QMessageBox
+from PyQt5.QtGui import QIcon
+from PyQt5.QtCore import QObject, QT_TRANSLATE_NOOP, Qt
+from .model import ToolbarModel
+from .view import ToolbarView
+from .toolbar_uic import Ui_SakiaToolbar
+from ...tools.decorators import asyncify, once_at_a_time, cancel_once_task
+from ..widgets.dialogs import QAsyncMessageBox, QAsyncFileDialog, dialog_async_exec
+from ..widgets import toast
+import logging
+
+
+class ToolbarController(QObject):
+    """
+    The navigation panel
+    """
+    _action_showinfo_text = QT_TRANSLATE_NOOP("CommunityWidget", "Show informations")
+    _action_explore_text = QT_TRANSLATE_NOOP("CommunityWidget", "Explore the Web of Trust")
+    _action_publish_uid_text = QT_TRANSLATE_NOOP("CommunityWidget", "Publish UID")
+    _action_revoke_uid_text = QT_TRANSLATE_NOOP("CommunityWidget", "Revoke UID")
+
+    def __init__(self, view, model, account, community, password_asker):
+        """
+
+        :param sakia.gui.toolbar.view.ToolbarView view:
+        :param sakia.gui.toolbar.model.ToolbarModel model:
+        """
+        self.view = view
+        self.model = model
+        self.account = account
+        self.community = community
+        self.password_asker = password_asker
+
+        tool_menu = QMenu(self.tr("Tools"), self.toolbutton_menu)
+        self.toolbutton_menu.setMenu(tool_menu)
+
+        self.action_publish_uid = QAction(self.tr(ToolbarController._action_publish_uid_text), self)
+        self.action_revoke_uid = QAction(self.tr(ToolbarController._action_revoke_uid_text), self)
+        self.action_showinfo = QAction(self.tr(ToolbarController._action_showinfo_text), self)
+        self.action_explorer = QAction(self.tr(ToolbarController._action_explore_text), self)
+
+        action_showinfo = QAction(self.tr("Show informations"), self.toolbutton_menu)
+        action_showinfo.triggered.connect(lambda: self.show_closable_tab(self.tab_informations,
+                                                                         QIcon(":/icons/informations_icon"),
+                                                                         self.tr("Informations")))
+        tool_menu.addAction(action_showinfo)
+
+        action_showexplorer = QAction(self.tr("Show explorer"), self.toolbutton_menu)
+        action_showexplorer.triggered.connect(lambda: self.show_closable_tab(self.tab_explorer.widget,
+                                                                             QIcon(":/icons/explorer_icon"),
+                                                                             self.tr("Explorer")))
+        tool_menu.addAction(action_showexplorer)
+
+        menu_advanced = QMenu(self.tr("Advanced"), self.toolbutton_menu)
+        action_gen_revokation = QAction(self.tr("Save revokation document"), menu_advanced)
+        action_gen_revokation.triggered.connect(self.action_save_revokation)
+        menu_advanced.addAction(action_gen_revokation)
+        tool_menu.addMenu(menu_advanced)
+
+        self.action_publish_uid.triggered.connect(self.publish_uid)
+        tool_menu.addAction(self.action_publish_uid)
+
+        self.button_membership.clicked.connect(self.send_membership_demand)
+
+        self.community_view.button_certification.clicked.connect(self.open_certification_dialog)
+        self.community_view.button_send_money.clicked.connect(self.open_transfer_money_dialog)
+
+    @classmethod
+    def create(cls, parent):
+        """
+        Instanciate a navigation agent
+        :param sakia.gui.agent.controller.AgentController parent:
+        :return: a new Toolbar controller
+        :rtype: ToolbarController
+        """
+        view = ToolbarView(parent.view)
+        model = ToolbarModel(None)
+        toolbar = cls(view, model)
+        model.setParent(toolbar)
+        return toolbar
+
+    def cancel_once_tasks(self):
+        cancel_once_task(self, self.refresh_block)
+        cancel_once_task(self, self.refresh_status)
+        logging.debug("Cancelled status")
+        cancel_once_task(self, self.refresh_quality_buttons)
+
+    def change_account(self, account, password_asker):
+        self.cancel_once_tasks()
+        self.account = account
+        self.password_asker = password_asker
+
+    def change_community(self, community):
+        self.cancel_once_tasks()
+
+        logging.debug("Changed community to {0}".format(community))
+        self.button_membership.setText(self.tr("Membership"))
+        self.button_membership.setEnabled(False)
+        self.button_certification.setEnabled(False)
+        self.action_publish_uid.setEnabled(False)
+        self.community = community
+        self.refresh_quality_buttons()
+
+    @asyncify
+    async def action_save_revokation(self, checked=False):
+        password = await self.password_asker.async_exec()
+        if self.password_asker.result() == QDialog.Rejected:
+            return
+
+        raw_document = await self.account.generate_revokation(self.community, password)
+        # Testable way of using a QFileDialog
+        selected_files = await QAsyncFileDialog.get_save_filename(self, self.tr("Save a revokation document"),
+                                                                  "", self.tr("All text files (*.txt)"))
+        if selected_files:
+            path = selected_files[0]
+            if not path.endswith('.txt'):
+                path = "{0}.txt".format(path)
+            with open(path, 'w') as save_file:
+                save_file.write(raw_document)
+
+        dialog = QMessageBox(QMessageBox.Information, self.tr("Revokation file"),
+                             self.tr("""<div>Your revokation document has been saved.</div>
+<div><b>Please keep it in a safe place.</b></div>
+The publication of this document will remove your identity from the network.</p>"""), QMessageBox.Ok,
+                             self)
+        dialog.setTextFormat(Qt.RichText)
+        await dialog_async_exec(dialog)
+
+    @asyncify
+    async def send_membership_demand(self, checked=False):
+        password = await self.password_asker.async_exec()
+        if self.password_asker.result() == QDialog.Rejected:
+            return
+        result = await self.account.send_membership(password, self.community, 'IN')
+        if result[0]:
+            if self.app.preferences['notifications']:
+                toast.display(self.tr("Membership"), self.tr("Success sending Membership demand"))
+            else:
+                await QAsyncMessageBox.information(self, self.tr("Membership"),
+                                                        self.tr("Success sending Membership demand"))
+        else:
+            if self.app.preferences['notifications']:
+                toast.display(self.tr("Membership"), result[1])
+            else:
+                await QAsyncMessageBox.critical(self, self.tr("Membership"),
+                                                        result[1])
+
+    @asyncify
+    async def send_membership_leaving(self):
+        reply = await QAsyncMessageBox.warning(self, self.tr("Warning"),
+                             self.tr("""Are you sure ?
+Sending a leaving demand  cannot be canceled.
+The process to join back the community later will have to be done again.""")
+.format(self.account.pubkey), QMessageBox.Ok | QMessageBox.Cancel)
+        if reply == QMessageBox.Ok:
+            password = self.password_asker.exec_()
+            if self.password_asker.result() == QDialog.Rejected:
+                return
+            result = await self.account.send_membership(password, self.community, 'OUT')
+            if result[0]:
+                if self.app.preferences['notifications']:
+                    toast.display(self.tr("Revoke"), self.tr("Success sending Revoke demand"))
+                else:
+                    await QAsyncMessageBox.information(self, self.tr("Revoke"),
+                                                            self.tr("Success sending Revoke demand"))
+            else:
+                if self.app.preferences['notifications']:
+                    toast.display(self.tr("Revoke"), result[1])
+                else:
+                    await QAsyncMessageBox.critical(self, self.tr("Revoke"),
+                                                         result[1])
+
+    @asyncify
+    async def publish_uid(self, checked=False):
+        password = await self.password_asker.async_exec()
+        if self.password_asker.result() == QDialog.Rejected:
+            return
+        result = await self.account.send_selfcert(password, self.community)
+        if result[0]:
+            if self.app.preferences['notifications']:
+                toast.display(self.tr("UID"), self.tr("Success publishing your UID"))
+            else:
+                await QAsyncMessageBox.information(self, self.tr("Membership"),
+                                                        self.tr("Success publishing your UID"))
+        else:
+            if self.app.preferences['notifications']:
+                toast.display(self.tr("UID"), result[1])
+            else:
+                await QAsyncMessageBox.critical(self, self.tr("UID"),
+                                                        result[1])
+
+    @once_at_a_time
+    @asyncify
+    async def refresh_quality_buttons(self):
+        if self.account and self.community:
+            try:
+                account_identity = await self.account.identity(self.community)
+                published_uid = await account_identity.published_uid(self.community)
+                uid_is_revokable = await account_identity.uid_is_revokable(self.community)
+                if published_uid:
+                    logging.debug("UID Published")
+                    self.action_revoke_uid.setEnabled(uid_is_revokable)
+                    is_member = await account_identity.is_member(self.community)
+                    if is_member:
+                        self.button_membership.setText(self.tr("Renew membership"))
+                        self.button_membership.setEnabled(True)
+                        self.button_certification.setEnabled(True)
+                        self.action_publish_uid.setEnabled(False)
+                    else:
+                        logging.debug("Not a member")
+                        self.button_membership.setText(self.tr("Send membership demand"))
+                        self.button_membership.setEnabled(True)
+                        self.action_publish_uid.setEnabled(False)
+                        if await self.community.get_block(0) is not None:
+                            self.button_certification.setEnabled(False)
+                else:
+                    logging.debug("UID not published")
+                    self.button_membership.setEnabled(False)
+                    self.button_certification.setEnabled(False)
+                    self.action_publish_uid.setEnabled(True)
+            except LookupFailureError:
+                self.button_membership.setEnabled(False)
+                self.button_certification.setEnabled(False)
+                self.action_publish_uid.setEnabled(False)
+
+    def open_certification_dialog(self):
+        CertificationDialog.open_dialog(self.app,
+                                     self.account,
+                                     self.community_view.community,
+                                     self.password_asker)
+
+    def open_revocation_dialog(self):
+        RevocationDialog.open_dialog(self.app,
+                                     self.account)
+
+    def open_transfer_money_dialog(self):
+        dialog = TransferMoneyDialog(self.app,
+                                     self.account,
+                                     self.password_asker,
+                                     self.community_view.community,
+                                     None)
+        if dialog.exec() == QDialog.Accepted:
+            self.community_view.tab_history.table_history.model().sourceModel().refresh_transfers()
+
+    def retranslateUi(self, widget):
+        """
+        Method to complete translations missing from generated code
+        :param widget:
+        :return:
+        """
+        self.action_publish_uid.setText(self.tr(ToolbarController.action_publish_uid_text))
+        self.action_revoke_uid.setText(self.tr(ToolbarController.action_revoke_uid_text))
+        self.action_showinfo.setText(self.tr(ToolbarController.action_showinfo_text))
+        super().retranslateUi(self)
diff --git a/src/sakia/gui/toolbar/model.py b/src/sakia/gui/toolbar/model.py
new file mode 100644
index 0000000000000000000000000000000000000000..5e6250e96c61d883494e47c8b6f0daffbd69e666
--- /dev/null
+++ b/src/sakia/gui/toolbar/model.py
@@ -0,0 +1,10 @@
+from sakia.gui.agent.model import AgentModel
+
+
+class ToolbarModel(AgentModel):
+    """
+    The model of Navigation agent
+    """
+
+    def __init__(self, parent):
+        super().__init__(parent)
diff --git a/src/sakia/gui/toolbar/toolbar.ui b/src/sakia/gui/toolbar/toolbar.ui
new file mode 100644
index 0000000000000000000000000000000000000000..b90226b937cf566c22bb009f306d835036056ef5
--- /dev/null
+++ b/src/sakia/gui/toolbar/toolbar.ui
@@ -0,0 +1,119 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>SakiaToolbar</class>
+ <widget class="QFrame" name="SakiaToolbar">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>690</width>
+    <height>240</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Frame</string>
+  </property>
+  <property name="frameShape">
+   <enum>QFrame::StyledPanel</enum>
+  </property>
+  <property name="frameShadow">
+   <enum>QFrame::Raised</enum>
+  </property>
+  <layout class="QHBoxLayout" name="horizontalLayout">
+   <item>
+    <widget class="QPushButton" name="button_send_money">
+     <property name="text">
+      <string>Send money</string>
+     </property>
+     <property name="icon">
+      <iconset resource="../icons/icons.qrc">
+       <normaloff>:/icons/payment_icon</normaloff>:/icons/payment_icon</iconset>
+     </property>
+     <property name="iconSize">
+      <size>
+       <width>32</width>
+       <height>32</height>
+      </size>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QPushButton" name="button_certification">
+     <property name="text">
+      <string>Certification</string>
+     </property>
+     <property name="icon">
+      <iconset resource="../icons/icons.qrc">
+       <normaloff>:/icons/certification_icon</normaloff>:/icons/certification_icon</iconset>
+     </property>
+     <property name="iconSize">
+      <size>
+       <width>32</width>
+       <height>32</height>
+      </size>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QPushButton" name="button_membership">
+     <property name="text">
+      <string>Renew membership</string>
+     </property>
+     <property name="icon">
+      <iconset resource="../icons/icons.qrc">
+       <normaloff>:/icons/renew_membership</normaloff>:/icons/renew_membership</iconset>
+     </property>
+     <property name="iconSize">
+      <size>
+       <width>32</width>
+       <height>32</height>
+      </size>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <spacer name="horizontalSpacer">
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <property name="sizeHint" stdset="0">
+      <size>
+       <width>169</width>
+       <height>221</height>
+      </size>
+     </property>
+    </spacer>
+   </item>
+   <item>
+    <widget class="QToolButton" name="toolbutton_menu">
+     <property name="text">
+      <string/>
+     </property>
+     <property name="icon">
+      <iconset resource="../icons/icons.qrc">
+       <normaloff>:/icons/menu_icon</normaloff>:/icons/menu_icon</iconset>
+     </property>
+     <property name="iconSize">
+      <size>
+       <width>32</width>
+       <height>32</height>
+      </size>
+     </property>
+     <property name="popupMode">
+      <enum>QToolButton::InstantPopup</enum>
+     </property>
+     <property name="autoRaise">
+      <bool>false</bool>
+     </property>
+     <property name="arrowType">
+      <enum>Qt::NoArrow</enum>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources>
+  <include location="../icons/icons.qrc"/>
+ </resources>
+ <connections/>
+</ui>
diff --git a/src/sakia/gui/toolbar/view.py b/src/sakia/gui/toolbar/view.py
new file mode 100644
index 0000000000000000000000000000000000000000..99787a63fa983113c1059e530c4923824b7c910a
--- /dev/null
+++ b/src/sakia/gui/toolbar/view.py
@@ -0,0 +1,12 @@
+from PyQt5.QtWidgets import QFrame
+from .toolbar_uic import Ui_SakiaToolbar
+
+
+class ToolbarView(QFrame, Ui_SakiaToolbar):
+    """
+    The model of Navigation agent
+    """
+
+    def __init__(self, parent):
+        super().__init__(parent)
+        self.setupUi(self)
diff --git a/src/sakia/gui/transactions_tab.py b/src/sakia/gui/transactions_tab.py
index a498c54944e80d7fa78313ad712d9e67dd26783c..656b855b7658946c130d81882301e1c48b522144 100644
--- a/src/sakia/gui/transactions_tab.py
+++ b/src/sakia/gui/transactions_tab.py
@@ -5,7 +5,7 @@ from PyQt5.QtWidgets import QWidget, QAbstractItemView, QHeaderView
 from PyQt5.QtCore import Qt, QObject, QDateTime, QTime, QModelIndex, pyqtSignal, pyqtSlot, QEvent
 from PyQt5.QtGui import QCursor
 
-from ..gen_resources.transactions_tab_uic import Ui_transactionsTabWidget
+from ..presentation.transactions_tab_uic import Ui_transactionsTabWidget
 from ..models.txhistory import HistoryTableModel, TxFilterProxyModel
 from ..tools.exceptions import NoPeerAvailable
 from ..tools.decorators import asyncify, once_at_a_time, cancel_once_task
diff --git a/src/sakia/gui/transfer.py b/src/sakia/gui/transfer.py
index 80fe8b4d6d05854e9f505ea1d1d10f4729645d59..90a07f08822ad102b97e95a926fec53a4ff90df8 100644
--- a/src/sakia/gui/transfer.py
+++ b/src/sakia/gui/transfer.py
@@ -11,7 +11,7 @@ from PyQt5.QtCore import QRegExp, Qt, QObject
 
 from PyQt5.QtGui import QRegExpValidator
 
-from ..gen_resources.transfer_uic import Ui_TransferMoneyDialog
+from ..presentation.transfer_uic import Ui_TransferMoneyDialog
 from .widgets import toast
 from .widgets.dialogs import QAsyncMessageBox, QMessageBox
 from ..tools.decorators import asyncify
diff --git a/src/sakia/gui/widgets/search_user.py b/src/sakia/gui/widgets/search_user.py
index 6f4a0195e13294bdb5ca850ec9ee2667a8df15d3..21860415ac5cf5e67bf5d29e284d96fd9aa5eb7a 100644
--- a/src/sakia/gui/widgets/search_user.py
+++ b/src/sakia/gui/widgets/search_user.py
@@ -8,7 +8,7 @@ from duniterpy.api import bma, errors
 from ...tools.decorators import asyncify
 from ...tools.exceptions import NoPeerAvailable
 from ...core.registry import BlockchainState, Identity
-from ...gen_resources.search_user_view_uic import Ui_SearchUserWidget
+from ...presentation.search_user_view_uic import Ui_SearchUserWidget
 
 
 class SearchUserWidget(QWidget, Ui_SearchUserWidget):
diff --git a/src/sakia/gui/widgets/toast.py b/src/sakia/gui/widgets/toast.py
index fd50cf8f8edcb900778f0b2f87c776ba1d4cad78..2e1aa124b01cc0a594796c1616441006a72a4ba7 100644
--- a/src/sakia/gui/widgets/toast.py
+++ b/src/sakia/gui/widgets/toast.py
@@ -8,7 +8,7 @@ import logging
 from PyQt5.QtCore import Qt, QThread
 from PyQt5.QtWidgets import QMainWindow, QApplication
 from PyQt5.QtGui import QImage, QPixmap
-from ...gen_resources.toast_uic import Ui_Toast
+from ...presentation.toast_uic import Ui_Toast
 
 window = None   # global
 
diff --git a/src/sakia/main.py b/src/sakia/main.py
index 6e55dbf2bd773098c02a18ba0839864ca7a079b8..5e1c15803b334721788b770bd65fb2bd59b78f38 100755
--- a/src/sakia/main.py
+++ b/src/sakia/main.py
@@ -20,7 +20,7 @@ import PyQt5.QtSvg
 from quamash import QSelectorEventLoop
 from PyQt5.QtWidgets import QApplication, QMessageBox
 from PyQt5.QtCore import Qt
-from sakia.gui.mainwindow import MainWindow
+from sakia.gui.main_window.controller import MainWindowController
 from sakia.core.app import Application
 
 
@@ -97,7 +97,7 @@ if __name__ == '__main__':
 
     with loop:
         app = Application.startup(sys.argv, sakia, loop)
-        window = MainWindow.startup(app)
+        window = MainWindowController.startup(app)
         loop.run_forever()
         try:
             loop.set_exception_handler(None)
diff --git a/src/sakia/models/generic_tree.py b/src/sakia/models/generic_tree.py
new file mode 100644
index 0000000000000000000000000000000000000000..4703d03b9ff3ddeaa8acc55c06da51fd6e07b95d
--- /dev/null
+++ b/src/sakia/models/generic_tree.py
@@ -0,0 +1,154 @@
+"""
+Created on 5 févr. 2014
+
+@author: inso
+"""
+
+from PyQt5.QtCore import QAbstractItemModel, QModelIndex, Qt
+from PyQt5.QtGui import QIcon
+import logging
+
+
+class NodeItem(QAbstractItemModel):
+    def __init__(self, node, parent_item):
+        super().__init__(parent_item)
+        self.children = []
+        self.node = node
+        self.parent_item = parent_item
+
+    def appendChild(self, node_item):
+        self.children.append(node_item)
+
+    def child(self, row):
+        return self.children[row]
+
+    def childCount(self):
+        return len(self.children)
+
+    def columnCount(self):
+        return 1
+
+    def data(self, index, role):
+        if role == Qt.DisplayRole and 'title' in self.node:
+            return self.node['title']
+
+        if role == Qt.ToolTipRole and 'tooltip' in self.node:
+            return self.node['tooltip']
+
+        if role == Qt.DecorationRole and 'icon' in self.node:
+            return QIcon(self.node['icon'])
+
+    def row(self):
+        if self.parent_item:
+            return self.parent_item.row() + self.parent_item.children.index(self)
+        return 0
+
+
+class GenericTreeModel(QAbstractItemModel):
+
+    """
+    A Qt abstract item model to display nodes from a dict
+
+
+    dict_format = {
+        'root_node': {
+            'node': ["title", "icon", "tooltip", "action"],
+            'children': {}
+        }
+    }
+
+    """
+
+    def __init__(self, title, root_item):
+        """
+        Constructor
+        """
+        super().__init__(None)
+        self.title = title
+        self.root_item = root_item
+
+    @classmethod
+    def create(cls, title, data):
+        def parse_node(node_data, parent_item):
+            node = NodeItem(node_data['node'], parent_item)
+            if parent_item:
+                parent_item.appendChild(node)
+            if 'children' in node_data:
+                for child in node_data['children']:
+                    parse_node(child, node)
+            return node
+
+        root_item = NodeItem({}, None)
+        for node in data:
+            parse_node(node, root_item)
+
+        return cls(title, root_item)
+
+    def columnCount(self, parent):
+        return 1
+
+    def data(self, index, role):
+        if not index.isValid():
+            return None
+
+        item = index.internalPointer()
+
+        if role == Qt.DisplayRole and index.column() == 0:
+            return item.data(0, role)
+
+        return None
+
+    def flags(self, index):
+        if not index.isValid():
+            return Qt.NoItemFlags
+
+        if index.column() == 0:
+            return Qt.ItemIsEnabled | Qt.ItemIsSelectable
+
+    def headerData(self, section, orientation, role):
+        if orientation == Qt.Horizontal \
+        and role == Qt.DisplayRole and section == 0:
+            return self.title
+        return None
+
+    def index(self, row, column, parent):
+        if not self.hasIndex(row, column, parent):
+            return QModelIndex()
+
+        if not parent.isValid():
+            parent_item = self.root_item
+        else:
+            parent_item = parent.internalPointer()
+
+        child_item = parent_item.child(row)
+        if child_item:
+            return self.createIndex(row, column, child_item)
+        else:
+            return QModelIndex()
+
+    def parent(self, index):
+        if not index.isValid():
+            return QModelIndex()
+
+        child_item = index.internalPointer()
+        parent_item = child_item.parent()
+
+        if parent_item == self.root_item:
+            return QModelIndex()
+
+        return self.createIndex(parent_item.row(), 0, parent_item)
+
+    def rowCount(self, parent):
+        if parent.column() > 0:
+            return 0
+
+        if not parent.isValid():
+            parent_item = self.root_item
+        else:
+            parent_item = parent.internalPointer()
+
+        return parent_item.childCount()
+
+    def setData(self, index, value, role=Qt.EditRole):
+        if index.column() == 0:
+            return True
diff --git a/src/sakia/tests/unit/gui/test_generic_tree.py b/src/sakia/tests/unit/gui/test_generic_tree.py
new file mode 100644
index 0000000000000000000000000000000000000000..d26ebc96bbab00cafb8c2fd0e58c442c29a33236
--- /dev/null
+++ b/src/sakia/tests/unit/gui/test_generic_tree.py
@@ -0,0 +1,66 @@
+import unittest
+from unittest.mock import patch, MagicMock, Mock, PropertyMock
+from PyQt5.QtCore import QLocale
+from sakia.tests import QuamashTest
+from sakia.models.generic_tree import GenericTreeModel
+from PyQt5.QtWidgets import QTreeView, QDialog
+
+
+class TestGenericTree(unittest.TestCase, QuamashTest):
+    def setUp(self):
+        self.setUpQuamash()
+        QLocale.setDefault(QLocale("en_GB"))
+
+    def tearDown(self):
+        self.tearDownQuamash()
+
+    def test_generic_tree(self):
+        data = [
+            {
+                'node': {
+                    'title': "Default Profile"
+                },
+                'children': [
+                    {
+                        'node': {
+                            'title': "Test net (inso)"
+                        },
+                        'children': [
+                            {
+                                'node': {
+                                    'title': "Transactions"
+                                },
+                                'children': []
+                            },
+                            {
+                                'node': {
+                                    'title': "Network"
+                                },
+                                'children': []
+                            }
+                        ]
+                    },
+                    {
+                        'node': {
+                            'title': "Le sou"
+                        },
+                        'children': [
+                            {
+                                'node': {
+                                    'title': "Transactions"
+                                },
+                                'children': {}
+                            },
+                            {
+                                'node': {
+                                    'title': "Network"
+                                },
+                                'children': {
+                                }
+                            }
+                        ]
+                    }
+                ],
+            }
+        ]
+        tree_model = GenericTreeModel.create("Test", data)
\ No newline at end of file
diff --git a/src/sakia/tests/unit/gui/test_main_window.py b/src/sakia/tests/unit/gui/test_main_window.py
index 0227edd5086c265d2ca1846af40cd21b8c68238c..b9ac850b1b972d7160c04fd7b5b3cfc2e924de75 100644
--- a/src/sakia/tests/unit/gui/test_main_window.py
+++ b/src/sakia/tests/unit/gui/test_main_window.py
@@ -42,7 +42,7 @@ class TestMainWindow(unittest.TestCase, QuamashTest):
     def test_change_account(self):
         widget = Mock(spec='PyQt5.QtWidgets.QMainWindow', create=True)
         widget.installEventFilter = Mock()
-        ui = Mock(spec='sakia.gen_resources.mainwindow_uic.Ui_MainWindow', create=True)
+        ui = Mock(spec='sakia.presentation.mainwindow_uic.Ui_MainWindow', create=True)
         ui.setupUi = Mock()
         label_icon = Mock()
         label_status = Mock()
@@ -67,7 +67,7 @@ class TestMainWindow(unittest.TestCase, QuamashTest):
     def test_change_account_from_none(self):
         widget = Mock(spec='PyQt5.QtWidgets.QMainWindow', create=True)
         widget.installEventFilter = Mock()
-        ui = Mock(spec='sakia.gen_resources.mainwindow_uic.Ui_MainWindow', create=True)
+        ui = Mock(spec='sakia.presentation.mainwindow_uic.Ui_MainWindow', create=True)
         ui.setupUi = Mock()
         label_icon = Mock()
         label_status = Mock()