<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>.gitmodules</filename>
    </added>
    <added>
      <filename>amsn2/backend/__init__.py</filename>
    </added>
    <added>
      <filename>amsn2/backend/backend.py</filename>
    </added>
    <added>
      <filename>amsn2/backend/basebackend.py</filename>
    </added>
    <added>
      <filename>amsn2/backend/defaultbackend.py</filename>
    </added>
    <added>
      <filename>amsn2/backend/nullbackend.py</filename>
    </added>
    <added>
      <filename>amsn2/core/account_manager.py</filename>
    </added>
    <added>
      <filename>amsn2/core/config.py</filename>
    </added>
    <added>
      <filename>amsn2/core/event_manager.py</filename>
    </added>
    <added>
      <filename>amsn2/core/personalinfo_manager.py</filename>
    </added>
    <added>
      <filename>amsn2/core/views/accountview.py</filename>
    </added>
    <added>
      <filename>amsn2/core/views/personalinfoview.py</filename>
    </added>
    <added>
      <filename>amsn2/gui/front_ends/cocoa/skins.py</filename>
    </added>
    <added>
      <filename>amsn2/gui/front_ends/curses/command.py</filename>
    </added>
    <added>
      <filename>amsn2/gui/front_ends/curses/splash.py</filename>
    </added>
    <added>
      <filename>amsn2/protocol/events/__init__.py</filename>
    </added>
    <added>
      <filename>amsn2/protocol/events/addressbook.py</filename>
    </added>
    <added>
      <filename>amsn2/protocol/events/client.py</filename>
    </added>
    <added>
      <filename>amsn2/protocol/events/contact.py</filename>
    </added>
    <added>
      <filename>amsn2/protocol/events/conversation.py</filename>
    </added>
    <added>
      <filename>amsn2/protocol/events/invite.py</filename>
    </added>
    <added>
      <filename>amsn2/protocol/events/mailbox.py</filename>
    </added>
    <added>
      <filename>amsn2/protocol/events/oim.py</filename>
    </added>
    <added>
      <filename>amsn2/protocol/events/profile.py</filename>
    </added>
    <added>
      <filename>papyon</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -5,6 +5,9 @@ python-pyopenssl
 python-crypto
 maybe some other stuff...
 
+Before launching amsn2 you have to fetch the submodules (papyon). Instructions can be found on the aMSN forum:
+http://www.amsn-project.net/forums/viewtopic.php?t=5994
+
 If you launch ./amsn2.py and it gives an error, that error probably tells you which dependency you need...
 You can type ./amsn2.py --help for more info... and the front ends can be selected with -f :
 ./amsn2.py -f efl
@@ -21,6 +24,7 @@ Once done, go to ./e17_src/BINDINGS/python and type
 PKG_CONFIG_PATH=/opt/e17/lib/pkgconfig ./build-all.sh /usr
 (this will build and install the python extensions into /usr/python2.X/...)
 Then the efl front end should become available...
+If it's not, fire up a python shell and try to import the ecore module; diagnose from there the problem.
 
 
 If you have the following error with the qt4 front-end:
@@ -31,3 +35,7 @@ If you have the following error with the qt4 front-end:
 	self._loop = self._gui.gui.aMSNMainLoop(self)
 	AttributeError: 'NoneType' object has no attribute 'aMSNMainLoop'
 try moving into the amsn2/gui/front_ends/qt4 directory and calling generateFiles.sh
+
+If the backspace is not working as expected with the ncurses front-end it is probably because your TERM is not set to the correct value. Try to launch amsn2 with some other setting for TERM, like:
+TERM=konsole ./amsn2.py -f curses
+If it works with some other value it means that your terminal emulator is not set correctly.</diff>
      <filename>README</filename>
    </modified>
    <modified>
      <diff>@@ -2,38 +2,17 @@
 import sys
 import os
 import optparse
-sys.path.insert(0, &quot;./pymsn&quot;)
+os.chdir(os.path.dirname(os.path.abspath(sys.argv[0])))
+sys.path.insert(0, &quot;./papyon&quot;)
+import locale
+locale.setlocale(locale.LC_ALL, '')
 
 from amsn2.core import aMSNCore
 
 if __name__ == '__main__':
     account = None
     passwd = None
-    default_front_end = &quot;console&quot;
-
-    # Detect graphical toolkit available.
-    # Format - 'default_front_end : module name'
-    # cocoa &gt; efl &gt; qt4 &gt; gtk &gt; console
-    toolkits = {'cocoa' : '????',
-                'elf' : 'ecore',
-                'qt4' : 'PyQt4.QtGui',
-                'gtk' : 'gtk',
-                'console' : None}
-    for toolkit in toolkits:
-        try:
-            default_front_end = toolkit
-            module_name = toolkits[toolkit]
-            module = __import__(module_name)
-            vars()[module_name] = module
-            # Debug
-            # print 'Imported toolkit &quot;%s&quot; with module &quot;%s&quot;' % (toolkit, module)
-            break
-        except ImportError:
-        	# Debug
-            # print 'Couldn\'t import %s - doesn\'t exist!' % module_name
-            pass
-        except TypeError:
-            pass
+    default_front_end = &quot;gtk&quot;
 
     parser = optparse.OptionParser()
     parser.add_option(&quot;-a&quot;, &quot;--account&quot;, dest=&quot;account&quot;,</diff>
      <filename>amsn2.py</filename>
    </modified>
    <modified>
      <diff>@@ -1,5 +1,5 @@
-
 import core
+import backend
 import gui
 import protocol
 import gui.front_ends</diff>
      <filename>amsn2/__init__.py</filename>
    </modified>
    <modified>
      <diff>@@ -1,6 +1,8 @@
 
 from amsn import *
-from profile import *
 from views import *
 from lang import *
+from config import *
 from contactlist_manager import *
+from account_manager import *
+from personalinfo_manager import *</diff>
      <filename>amsn2/core/__init__.py</filename>
    </modified>
    <modified>
      <diff>@@ -18,16 +18,18 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
-import profile
 from amsn2 import gui
 from amsn2 import protocol
-import pymsn
+from amsn2.backend import aMSNBackendManager
+import papyon
 from views import *
+from account_manager import *
 from contactlist_manager import *
 from conversation_manager import *
 from oim_manager import *
 from theme_manager import *
-
+from personalinfo_manager import *
+from event_manager import *
 
 class aMSNCore(object):
     def __init__(self, options):
@@ -41,39 +43,68 @@ class aMSNCore(object):
            options.front_end = the front end's name to use
            options.debug = whether or not to enable debug output
         &quot;&quot;&quot;
-        self._profile_manager = profile.aMSNProfileManager()
+        self._event_manager = aMSNEventManager(self)
         self._options = options
-        self._gui_name = self._options.front_end
-        self._gui = gui.GUIManager(self, self._gui_name)
-        self._loop = self._gui.gui.aMSNMainLoop(self)
-        self._main = self._gui.gui.aMSNMainWindow(self)
-        self._skin_manager = self._gui.gui.SkinManager(self)
+
+        self._gui_name = None
+        self._gui = None
+        self._loop = None
+        self._main = None
+        self.loadUI(self._options.front_end)
+
+        self._backend_manager = aMSNBackendManager()
+        self._account_manager = aMSNAccountManager(self, options)
+        self._account = None
         self._theme_manager = aMSNThemeManager()
         self._contactlist_manager = aMSNContactListManager(self)
         self._oim_manager = aMSNOIMManager(self)
         self._conversation_manager = aMSNConversationManager(self)
+        self._personalinfo_manager = aMSNPersonalInfoManager(self)
 
-        self.p2s = {pymsn.Presence.ONLINE:&quot;online&quot;,
-                    pymsn.Presence.BUSY:&quot;busy&quot;,
-                    pymsn.Presence.IDLE:&quot;idle&quot;,
-                    pymsn.Presence.AWAY:&quot;away&quot;,
-                    pymsn.Presence.BE_RIGHT_BACK:&quot;brb&quot;,
-                    pymsn.Presence.ON_THE_PHONE:&quot;phone&quot;,
-                    pymsn.Presence.OUT_TO_LUNCH:&quot;lunch&quot;,
-                    pymsn.Presence.INVISIBLE:&quot;hidden&quot;,
-                    pymsn.Presence.OFFLINE:&quot;offline&quot;}
 
+        self.p2s = {papyon.Presence.ONLINE:&quot;online&quot;,
+                    papyon.Presence.BUSY:&quot;busy&quot;,
+                    papyon.Presence.IDLE:&quot;idle&quot;,
+                    papyon.Presence.AWAY:&quot;away&quot;,
+                    papyon.Presence.BE_RIGHT_BACK:&quot;brb&quot;,
+                    papyon.Presence.ON_THE_PHONE:&quot;phone&quot;,
+                    papyon.Presence.OUT_TO_LUNCH:&quot;lunch&quot;,
+                    papyon.Presence.INVISIBLE:&quot;hidden&quot;,
+                    papyon.Presence.OFFLINE:&quot;offline&quot;}
+
+        import logging
         if self._options.debug:
-            import logging
             logging.basicConfig(level=logging.DEBUG)
+        else:
+            logging.basicConfig(level=logging.WARNING)
 
     def run(self):
         self._main.show();
         self._loop.run();
 
+    def loadUI(self, ui_name):
+        &quot;&quot;&quot;
+        @type ui_name: str
+        @param ui_name: The name of the User Interface
+        &quot;&quot;&quot;
+
+        self._gui_name = ui_name
+        self._gui = gui.GUIManager(self, self._gui_name)
+        self._loop = self._gui.gui.aMSNMainLoop(self)
+        self._main = self._gui.gui.aMSNMainWindow(self)
+        self._skin_manager = self._gui.gui.SkinManager(self)
+
+    def switchToUI(self, ui_name):
+        &quot;&quot;&quot;
+        @type ui_name: str
+        @param ui_name: The name of the User Interface
+        &quot;&quot;&quot;
+
+        #TODO: unloadUI + stop loops??? + loadUI + run
+        pass
 
     def mainWindowShown(self):
-        # TODO : load the profiles from disk and all settings
+        # TODO : load the accounts from disk and all settings
         # then show the login window if autoconnect is disabled
 
         self._main.setTitle(&quot;aMSN 2 - Loading&quot;)
@@ -89,27 +120,7 @@ class aMSNCore(object):
 
         login = self._gui.gui.aMSNLoginWindow(self, self._main)
 
-        profile = None
-        if self._options.account is not None:
-            if self._profile_manager.profileExists(self._options.account):
-                profile = self._profile_manager.getProfile(self._options.account)
-            else:
-                profile = self._profile_manager.addProfile(self._options.account)
-                profile.save = False
-            if self._options.password is not None:
-                profile.password = self._options.password
-
-        else:
-            for prof in self._profile_manager.getAllProfiles():
-                if prof.isLocked() is False:
-                    profile = prof
-                    break
-
-        if profile is None:
-            profile = self._profile_manager.addProfile(&quot;&quot;)
-            profile.password = &quot;&quot;
-
-        login.switch_to_profile(profile)
+        login.setAccounts(self._account_manager.getAvailableAccountViews())
 
         splash.hide()
         self._main.setTitle(&quot;aMSN 2 - Login&quot;)
@@ -121,48 +132,68 @@ class aMSNCore(object):
     def getMainWindow(self):
         return self._main
 
-    def addProfile(self, account):
-        return self._profile_manager.addProfile(account)
+    def signinToAccount(self, login_window, accountview):
+        &quot;&quot;&quot;
+        @type login_window: aMSNLoginWindow
+        @type accountview: AccountView
+        &quot;&quot;&quot;
 
-    def signinToAccount(self, login_window, profile):
-        print &quot;Signing in to account %s&quot; % (profile.email)
-        profile.login = login_window
-        profile.client = protocol.Client(self, profile)
-        self._profile = profile
-        profile.client.connect()
+        print &quot;Signing in to account %s&quot; % (accountview.email)
+        self._account = self._account_manager.signinToAccount(accountview)
+        self._account.login = login_window
+        self._account.client = protocol.Client(self, self._account)
+        self._account.client.connect(accountview.email, accountview.password)
 
-    def connectionStateChanged(self, profile, state):
+    def connectionStateChanged(self, account, state):
+        &quot;&quot;&quot;
+        @type account: aMSNAccount
+        @type state: L{papyon.event.ClientState}
+        @param state: New state of the Client.
+        &quot;&quot;&quot;
 
         status_str = \
         {
-            pymsn.event.ClientState.CONNECTING : 'Connecting to server...',
-            pymsn.event.ClientState.CONNECTED : 'Connected',
-            pymsn.event.ClientState.AUTHENTICATING : 'Authentificating...',
-            pymsn.event.ClientState.AUTHENTICATED : 'Password accepted',
-            pymsn.event.ClientState.SYNCHRONIZING : 'Please wait while your contact list\nis being downloaded...',
-            pymsn.event.ClientState.SYNCHRONIZED : 'Contact list downloaded successfully\nHappy Chatting'
+            papyon.event.ClientState.CONNECTING : 'Connecting to server...',
+            papyon.event.ClientState.CONNECTED : 'Connected',
+            papyon.event.ClientState.AUTHENTICATING : 'Authenticating...',
+            papyon.event.ClientState.AUTHENTICATED : 'Password accepted',
+            papyon.event.ClientState.SYNCHRONIZING : 'Please wait while your contact list\nis being downloaded...',
+            papyon.event.ClientState.SYNCHRONIZED : 'Contact list downloaded successfully.\nHappy Chatting'
         }
 
         if state in status_str:
-            profile.login.onConnecting((state + 1)/ 7., status_str[state])
-        elif state == pymsn.event.ClientState.OPEN:
+            account.login.onConnecting((state + 1)/ 7., status_str[state])
+        elif state == papyon.event.ClientState.OPEN:
             clwin = self._gui.gui.aMSNContactListWindow(self, self._main)
-            clwin.profile = profile
-            profile.clwin = clwin
-            profile.login.hide()
+            clwin.account = account
+            account.clwin = clwin
+            account.login.hide()
             self._main.setTitle(&quot;aMSN 2&quot;)
-            profile.clwin.show()
-            profile.login = None
+            account.clwin.show()
+            account.login = None
 
-            self._contactlist_manager.onCLDownloaded(profile.client.address_book)
+            self._personalinfo_manager.setAccount(account)
+            self._contactlist_manager.onCLDownloaded(account.client.address_book)
 
     def idlerAdd(self, func):
+        &quot;&quot;&quot;
+        @type func: function
+        &quot;&quot;&quot;
+
         self._loop.idlerAdd(func)
 
     def timerAdd(self, delay, func):
+        &quot;&quot;&quot;
+        @type delay: int
+        @param delay: delay in seconds?
+        @type func: function
+        &quot;&quot;&quot;
+
         self._loop.timerAdd(delay, func)
 
     def quit(self):
+        if self._account is not None:
+            self._account.signOut()
         self._loop.quit()
 
     def createMainMenuView(self):</diff>
      <filename>amsn2/core/amsn.py</filename>
    </modified>
    <modified>
      <diff>@@ -1,68 +1,58 @@
 from views import *
 import os
 import tempfile
-import pymsn
+import papyon
 
 
 class aMSNContactListManager:
     def __init__(self, core):
-        self._core = core
-
-        #TODO: have only one event manager?
-        #TODO: describe the events:
-        self.CONTACTVIEW_UPDATED = 0
-        self.GROUPVIEW_UPDATED = 1
-        self.CLVIEW_UPDATED = 2
-        self.AMSNCONTACT_UPDATED = 3
-        self._events_cbs = [[], [], [], []]
+        &quot;&quot;&quot;
+        @type core: aMSNCore
+        &quot;&quot;&quot;
 
-        self._contacts = {}
+        self._core = core
+        self._em = core._event_manager
+        self._contacts = {} #Dictionary where every contact_uid has an associated aMSNContact
         self._groups = {}
-        self._pymsn_addressbook = None
+        self._papyon_addressbook = None
 
     #TODO: sorting contacts &amp; groups
 
-    def emit(self, event, *args):
-        &quot;&quot;&quot; emit the event &quot;&quot;&quot;
-        for cb in self._events_cbs[event]:
-            #TODO: try except
-            cb(*args)
-
-    def register(self, event, callback, pos=None):
-        &quot;&quot;&quot; register a callback for an event &quot;&quot;&quot;
-        #TODO: try except
-        if pos is None:
-            self._events_cbs[event].append(callback)
-        else:
-            self._events_cbs[event].insert(pos,callback)
-
-    def unregister(self, event, callback):
-        &quot;&quot;&quot; unregister a callback for an event &quot;&quot;&quot;
-        #TODO: try except
-        self._events_cbs[event].remove(callback)
-
-
-
+    def onContactChanged(self, papyon_contact):
+        &quot;&quot;&quot; Called when a contact changes either its presence, nick, psm or current media.&quot;&quot;&quot;
 
-    def onContactPresenceChanged(self, pymsn_contact):
         #1st/ update the aMSNContact object
-        c = self.getContact(pymsn_contact.id, pymsn_contact)
-        c.fill(self._core, pymsn_contact)
+        c = self.getContact(papyon_contact.id, papyon_contact)
+        c.fill(self._core, papyon_contact)
         #2nd/ update the ContactView
         cv = ContactView(self._core, c)
-        self.emit(self.CONTACTVIEW_UPDATED, cv)
+        self._em.emit(self._em.events.CONTACTVIEW_UPDATED, cv)
 
         #TODO: update the group view
 
+    def onContactDPChanged(self, papyon_contact):
+        &quot;&quot;&quot; Called when a contact changes its Display Picture. &quot;&quot;&quot;
+
+        #TODO: add local cache for DPs
         #Request the DP...
-        if (pymsn_contact.presence is not pymsn.Presence.OFFLINE and
-            pymsn_contact.msn_object):
-                self._core._profile.client._msn_object_store.request(pymsn_contact.msn_object,
+        c = self.getContact(papyon_contact.id, papyon_contact)
+        if (&quot;Theme&quot;, &quot;dp_nopic&quot;) in c.dp.imgs:
+            c.dp.load(&quot;Theme&quot;, &quot;dp_loading&quot;)
+        elif papyon_contact.msn_object is None:
+            c.dp.load(&quot;Theme&quot;, &quot;dp_nopic&quot;)
+            self._em.emit(self._em.events.AMSNCONTACT_UPDATED, c)
+            cv = ContactView(self._core, c)
+            self._em.emit(self._em.events.CONTACTVIEW_UPDATED, cv)
+            return
+
+        if (papyon_contact.presence is not papyon.Presence.OFFLINE and
+            papyon_contact.msn_object):
+                self._core._account.client._msn_object_store.request(papyon_contact.msn_object,
                                                                      (self.onDPdownloaded,
-                                                                      pymsn_contact.id))
+                                                                      papyon_contact.id))
 
     def onCLDownloaded(self, address_book):
-        self._pymsn_addressbook = address_book
+        self._papyon_addressbook = address_book
         grpviews = []
         cviews = []
         clv = ContactListView()
@@ -80,7 +70,7 @@ class aMSNContactListManager:
             grpviews.append(gv)
             clv.group_ids.append(group.id)
 
-        contacts = address_book.contacts.search_by_memberships(pymsn.Membership.FORWARD)
+        contacts = address_book.contacts.search_by_memberships(papyon.Membership.FORWARD)
         no_group_ids= []
         for contact in contacts:
             if len(contact.groups) == 0:
@@ -95,11 +85,11 @@ class aMSNContactListManager:
             clv.group_ids.append(0)
 
         #Emit the events
-        self.emit(self.CLVIEW_UPDATED, clv)
+        self._em.emit(self._em.events.CLVIEW_UPDATED, clv)
         for g in grpviews:
-            self.emit(self.GROUPVIEW_UPDATED, g)
+            self._em.emit(self._em.events.GROUPVIEW_UPDATED, g)
         for c in cviews:
-            self.emit(self.CONTACTVIEW_UPDATED, c)
+            self._em.emit(self._em.events.CONTACTVIEW_UPDATED, c)
 
     def onDPdownloaded(self, msn_object, uid):
         #1st/ update the aMSNContact object
@@ -110,21 +100,30 @@ class aMSNContactListManager:
         f.write(msn_object._data.read())
         f.close()
         c.dp.load(&quot;Filename&quot;, tf)
-        self.emit(self.AMSNCONTACT_UPDATED, c)
+        self._em.emit(self._em.events.AMSNCONTACT_UPDATED, c)
         #2nd/ update the ContactView
         cv = ContactView(self._core, c)
-        self.emit(self.CONTACTVIEW_UPDATED, cv)
+        self._em.emit(self._em.events.CONTACTVIEW_UPDATED, cv)
+
 
+    def getContact(self, uid, papyon_contact=None):
+        &quot;&quot;&quot;
+        @param uid: uid of the contact
+        @type uid: str
+        @param papyon_contact:
+        @type papyon_contact:
+        @return: aMSNContact of that contact
+        @rtype: aMSNContact
+        &quot;&quot;&quot;
 
-    def getContact(self, cid, pymsn_contact=None):
         #TODO: should raise UnknownContact or sthg like that
         try:
-            return self._contacts[cid]
+            return self._contacts[uid]
         except KeyError:
-            if pymsn_contact is not None:
-                c = aMSNContact(self._core, pymsn_contact)
-                self._contacts[cid] = c
-                self.emit(self.AMSNCONTACT_UPDATED, c)
+            if papyon_contact is not None:
+                c = aMSNContact(self._core, papyon_contact)
+                self._contacts[uid] = c
+                self._em.emit(self._em.events.AMSNCONTACT_UPDATED, c)
                 return c
             else:
                 raise ValueError
@@ -135,29 +134,45 @@ class aMSNContactListManager:
     everytime
 &quot;&quot;&quot;
 class aMSNContact():
-    def __init__(self, core, pymsn_contact):
-        self.uid = pymsn_contact.id
-        self.fill(core, pymsn_contact)
+    def __init__(self, core, papyon_contact):
+        &quot;&quot;&quot;
+        @type core: aMSNCore
+        @param papyon_contact:
+        @type papyon_contact: papyon.profile.Contact
+        &quot;&quot;&quot;
+
+        self.uid = papyon_contact.id
+        self.dp = ImageView()
+        if papyon_contact.msn_object is None:
+            self.dp.load(&quot;Theme&quot;, &quot;dp_nopic&quot;)
+        else:
+            self.dp.load(&quot;Theme&quot;, &quot;dp_loading&quot;)
+        self.fill(core, papyon_contact)
+
+    def fill(self, core, papyon_contact):
+        &quot;&quot;&quot;
+        Fills the aMSNContact structure.
+
+        @type core: aMSNCore
+        @type papyon_contact: papyon.profile.Contact
+        &quot;&quot;&quot;
 
-    def fill(self, core, pymsn_contact):
         self.icon = ImageView()
-        self.icon.load(&quot;Theme&quot;,&quot;buddy_&quot; + core.p2s[pymsn_contact.presence])
-        self.dp = ImageView()
-        #TODO: for the moment, use default dp
-        self.dp.load(&quot;Theme&quot;, &quot;dp_nopic&quot;)
+        self.icon.load(&quot;Theme&quot;,&quot;buddy_&quot; + core.p2s[papyon_contact.presence])
         self.emblem = ImageView()
-        self.emblem.load(&quot;Theme&quot;, &quot;emblem_&quot; + core.p2s[pymsn_contact.presence])
+        self.emblem.load(&quot;Theme&quot;, &quot;emblem_&quot; + core.p2s[papyon_contact.presence])
         #TODO: PARSE ONLY ONCE
         self.nickname = StringView()
-        self.nickname.appendText(pymsn_contact.display_name)
+        self.nickname.appendText(papyon_contact.display_name)
         self.personal_message = StringView()
-        self.personal_message.appendText(pymsn_contact.personal_message)
+        self.personal_message.appendText(papyon_contact.personal_message)
         self.current_media = StringView()
-        self.current_media.appendText(pymsn_contact.current_media)
+        self.current_media.appendText(papyon_contact.current_media)
         self.status = StringView()
-        self.status.appendText(core.p2s[pymsn_contact.presence])
-        #for the moment, we store the pymsn_contact object, but we shouldn't have to
-        #TODO: getPymsnContact(self, core...) or _pymsn_contact?
-        self._pymsn_contact = pymsn_contact
+        self.status.appendText(core.p2s[papyon_contact.presence])
+        #for the moment, we store the papyon_contact object, but we shouldn't have to
+
+        #TODO: getPapyonContact(self, core...) or _papyon_contact?
+        self._papyon_contact = papyon_contact
 
 </diff>
      <filename>amsn2/core/contactlist_manager.py</filename>
    </modified>
    <modified>
      <diff>@@ -18,13 +18,20 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
-from amsn2.protocol import conversation
+from amsn2.protocol.events import conversation
 from amsn2.core.contactlist_manager import *
 from amsn2.core.views import *
-import pymsn
+import papyon
 
 class aMSNConversation:
     def __init__(self, core, conv_manager, conv = None, contacts_uid = None):
+        &quot;&quot;&quot;
+        @type core: aMSNCore
+        @type conv_manager: aMSNConversationManager
+        @type conv:
+        @type contacts_uid:
+        &quot;&quot;&quot;
+
         if (contacts_uid is None):
             raise ValueError, InvalidArgument
 
@@ -33,10 +40,10 @@ class aMSNConversation:
         self._contacts_uid = contacts_uid
         if conv is None:
             #New conversation
-            pymsn_contacts = [core._contactlist_manager.getContact(uid) for uid in contacts_uid]
-            pymsn_contacts = [c._pymsn_contact for c in pymsn_contacts if c is not None]
+            papyon_contacts = [core._contactlist_manager.getContact(uid) for uid in contacts_uid]
+            papyon_contacts = [c._papyon_contact for c in papyon_contacts if c is not None]
             #if c was None.... wtf?
-            self._conv = pymsn.Conversation(self._core._profile.client, pymsn_contacts)
+            self._conv = papyon.Conversation(self._core._account.client, papyon_contacts)
         else:
             #From an existing conversation
             self._conv = conv
@@ -71,8 +78,7 @@ class aMSNConversation:
         #TODO: messageView
         mv = MessageView()
         if sender_uid is None:
-            #TODO
-            mv.sender.appendText(&quot;/me&quot;)
+            mv.sender.appendStringView(self._core._personalinfo_manager._personalinfoview.nick)
         else:
             c = self._core._contactlist_manager.getContact(sender_uid)
             mv.sender_icon = c.icon
@@ -90,7 +96,7 @@ class aMSNConversation:
         # for the moment, no formatting, no smiley substitution... (TODO)
         # peacey: Added formatting of styles
         self.onMessageReceived(msg, formatting=formatting)
-        message = pymsn.ConversationMessage(msg.toString(), formatting)
+        message = papyon.ConversationMessage(str(msg), formatting)
         self._conv.send_text_message(message)
 
     def sendNudge(self):
@@ -105,6 +111,6 @@ class aMSNConversation:
     def inviteContact(self, contact_uid):
         &quot;&quot;&quot; contact_uid is the Id of the contact to invite &quot;&quot;&quot;
         c = self._core._contactlist_manager.getContact(contact_uid)
-        self._conv.invite_user(contact.pymsn_contact)
+        self._conv.invite_user(contact.papyon_contact)
 
     #TODO: ...</diff>
      <filename>amsn2/core/conversation.py</filename>
    </modified>
    <modified>
      <diff>@@ -3,6 +3,10 @@ from conversation import aMSNConversation
 
 class aMSNConversationManager:
     def __init__(self, core):
+        &quot;&quot;&quot;
+        @type core: aMSNCore
+        &quot;&quot;&quot;
+
         self._core = core
         self._convs = []
         self._wins = []</diff>
      <filename>amsn2/core/conversation_manager.py</filename>
    </modified>
    <modified>
      <diff>@@ -7,37 +7,37 @@ class aMSNLang(object):
     lang_dirs = []
     base_lang = 'en'
     lang_code = base_lang
-    
+
     default_encoding = 'utf-8'
-    
+
     lineRe  = re.compile('\s*([^\s]+)\s+(.+)', re.UNICODE)  # whitespace? + key + whitespace + value
     langRe  = re.compile('(.+)-.+', re.UNICODE)             # code or code-variant
-    
+
     def loadLang(self, lang_code, force_reload=False):
         if self.lang_code is lang_code and force_reload is False:
             # Don't reload the same lang unless forced.
             return
-        
-        hasVariant = bool(self.langRe.match(lang_code) is not None)
-        
+
+        hasVariant = (self.langRe.match(lang_code) is not None)
+
         # Check for lang variants.
-        if hasVariant is True:
+        if hasVariant:
             root = str(self.langRe.split(lang_code)[1])
         else:
-            root = str(lang_code)
-        
+            root = lang_code
+
         if lang_code is self.base_lang:
             # Clear the keys if we're loading the base lang.
             self.clearKeys()
-        
+
         if root is not self.base_lang:
             # If it's not the default lang, load the base first.
             self.loadLang(self.base_lang)
-        
-        if hasVariant is True:
+
+        if hasVariant:
             # Then we have a variant, so load the root.
             self.loadLang(root)
-        
+
         # Load the langfile from each langdir.
         fileWasLoaded = False
         for dir in self.getLangDirs():
@@ -47,26 +47,26 @@ class aMSNLang(object):
             except IOError:
                 # file doesn't exist.
                 continue
-            
+
             line = f.readline()
             while line:
                 if self.lineRe.match(line) is not None:
                     components = self.lineRe.split(line)
                     self.setKey(unicode(components[1], self.default_encoding), unicode(components[2], self.default_encoding))
-                
+
                 # Get the next line...
                 line = f.readline()
-            
+
             f.close()
-        
+
         # If we've loaded a lang file, set the new lang code.
-        if fileWasLoaded is True:
-            self.lang_code = str(lang_code)
-        
+        if fileWasLoaded:
+            self.lang_code = lang_code
+
     def addLangDir(self, lang_dir):
         self.lang_dirs.append(str(lang_dir))
         self.reloadKeys()
-    
+
     def removeLangDir(self, lang_dir):
         try:
             # Remove the lang_dir from the lang_dirs list, and reload keys.
@@ -76,7 +76,7 @@ class aMSNLang(object):
         except ValueError:
             # Dir not in list.
             return False
-    
+
     def getLangDirs(self):
         # Return a copy for them to play with.
         return self.lang_dirs[:]
@@ -90,16 +90,16 @@ class aMSNLang(object):
 
     def setKey(self, key, val):
         self.lang_keys[key] = val
-    
+
     def getKey(self, key, replacements=[]):
         try:
             r = self.lang_keys[key]
         except KeyError:
             # Key doesn't exist.
             return key
-        
+
         # Perform any replacements necessary.
-        if self._isDict(replacements):
+        if type(replacements) is dict:
             # Replace from a dictionary.
             for key, val in replacements.iteritems():
                 r = r.replace(key, val)
@@ -109,19 +109,12 @@ class aMSNLang(object):
             for replacement in replacements:
                 r = r.replace('$' + str(i), replacement)
                 i += 1
-        
+
         return r
-        
-    def _isDict(self, test):
-        try:
-            test.keys()
-            return True
-        except AttributeError:
-            return False
-    
+
     def clearKeys(self):
         self.lang_keys = {}
-    
+
     def printKeys(self):
         print self.lang_code
         print '{'</diff>
      <filename>amsn2/core/lang.py</filename>
    </modified>
    <modified>
      <diff>@@ -20,5 +20,9 @@
 
 class aMSNOIMManager:
     def __init__(self, core):
+        &quot;&quot;&quot;
+        @type core: aMSNCore
+        &quot;&quot;&quot;
+
         self._core = core
-        
\ No newline at end of file
+</diff>
      <filename>amsn2/core/oim_manager.py</filename>
    </modified>
    <modified>
      <diff>@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 #===================================================
-# 
+#
 # theme_manager.py - This file is part of the amsn2 package
 #
 # Copyright (C) 2008  Wil Alvarez &lt;wil_alejandro@yahoo.com&gt;
@@ -29,16 +29,16 @@ class aMSNThemeManager:
         self._statusicons = {}
         self._displaypic = {}
         self._emblems = {}
-        
+
         self.load()
-        
+
     def __get(self, var, key):
         # TODO: evaluate if should be returned None when key is not valid
         if key in var.keys():
             return var[key]
         else:
             return (None, None)
-        
+
     def load(self):
         # Here aMSNThemeManager should read user's files to know what theme
         # will be loaded to each aspect
@@ -46,7 +46,7 @@ class aMSNThemeManager:
         self._statusicons = aMSNStatusIconLoader().load('default')
         self._displaypic = aMSNDisplayPicLoader().load('default')
         self._emblems = aMSNEmblemLoader().load('default')
-        
+
     def get_value(self, key):
         if (key.startswith('button_')):
             return self.get_button(key)
@@ -59,7 +59,7 @@ class aMSNThemeManager:
         else:
             # TODO: This should raise a exception
             return (None, None)
-            
+
     def get_button(self, key):
         return self.__get(self._buttons, key)
 
@@ -81,36 +81,36 @@ class aMSNGenericLoader:
         # Should be initialized after creating the class
         self._keys = []
         self._dict = {}
-        
+
     def load(self, theme='default'):
         self.theme = theme
         self._theme_dir = os.path.join(self._basedir, theme)
-        
+
         for key in self._keys.keys():
             image = self._keys[key]
             filepath = os.path.join(self._theme_dir, image)
-            
+
             # Verificating
             if (not os.path.isfile(filepath)):
                 filepath = os.path.join(self._defaultdir, image)
-                
+
             self._dict[key] = (&quot;Filename&quot;, filepath)
-            
+
         return self._dict
-    
+
 class aMSNButtonLoader(aMSNGenericLoader):
     def __init__(self):
         aMSNGenericLoader.__init__(self, &quot;buttons&quot;)
         self._keys = {
-            'button_nudge': 'nudge.png', 
+            'button_nudge': 'nudge.png',
             'button_smile': 'smile.png',
         }
-        
+
 class aMSNStatusIconLoader(aMSNGenericLoader):
     def __init__(self):
         aMSNGenericLoader.__init__(self, &quot;status_icons&quot;)
         self._keys = {
-            'buddy_online': 'online.png', 
+            'buddy_online': 'online.png',
             'buddy_away': 'away.png',
             'buddy_brb': 'away.png',
             'buddy_idle': 'away.png',
@@ -123,7 +123,7 @@ class aMSNStatusIconLoader(aMSNGenericLoader):
             'buddy_blocked_off': 'blocked_off.png',
             'buddy_webmsn': 'webmsn.png',
         }
-        
+
 class aMSNDisplayPicLoader(aMSNGenericLoader):
     def __init__(self):
         aMSNGenericLoader.__init__(self, &quot;displaypic&quot;)
@@ -134,12 +134,12 @@ class aMSNDisplayPicLoader(aMSNGenericLoader):
             'dp_male': 'male.png',
             'dp_nopic': 'nopic.png',
         }
-        
+
 class aMSNEmblemLoader(aMSNGenericLoader):
     def __init__(self):
         aMSNGenericLoader.__init__(self, &quot;emblems&quot;)
         self._keys = {
-            'emblem_online': 'plain_emblem.png', 
+            'emblem_online': 'plain_emblem.png',
             'emblem_away': 'away_emblem.png',
             'emblem_brb': 'away_emblem.png',
             'emblem_idle': 'away_emblem.png',
@@ -149,4 +149,4 @@ class aMSNEmblemLoader(aMSNGenericLoader):
             'emblem_offline': 'offline_emblem.png',
             'emblem_hidden': 'offline_emblem.png',
             'emblem_blocked': 'blocked_emblem.png',
-        }
\ No newline at end of file
+        }</diff>
      <filename>amsn2/core/theme_manager.py</filename>
    </modified>
    <modified>
      <diff>@@ -5,3 +5,5 @@ from stringview import *
 from tooltipview import *
 from messageview import *
 from imageview import *
+from accountview import *
+from personalinfoview import *</diff>
      <filename>amsn2/core/views/__init__.py</filename>
    </modified>
    <modified>
      <diff>@@ -31,6 +31,10 @@ class GroupView:
 &quot;&quot;&quot; a view of a contact on the contact list &quot;&quot;&quot;
 class ContactView:
     def __init__(self, core, amsn_contact):
+        &quot;&quot;&quot;
+        @type core: aMSNCore
+        @type amsn_contact: aMSNContact
+        &quot;&quot;&quot;
 
         self.uid = amsn_contact.uid
 
@@ -38,7 +42,6 @@ class ContactView:
         #TODO: apply emblem on dp
         self.dp = amsn_contact.dp.clone()
         self.dp.appendImageView(amsn_contact.emblem)
-        self.name = StringView
         self.name = StringView() # TODO : default colors
         self.name.openTag(&quot;nickname&quot;)
         self.name.appendStringView(amsn_contact.nickname) # TODO parse</diff>
      <filename>amsn2/core/views/contactlistview.py</filename>
    </modified>
    <modified>
      <diff>@@ -5,6 +5,10 @@ class ImageView(object):
             - Theme
             - None
     &quot;&quot;&quot;
+
+    FILENAME = &quot;Filename&quot;
+    THEME = &quot;Theme&quot;
+
     def __init__(self, resource_type=None, value=None):
         self.imgs = []
         if resource_type is not None and value is not None:
@@ -30,4 +34,6 @@ class ImageView(object):
     def prependImageView(self, iv):
         self.imgs = iv.imgs[:].extend(self.imgs)
 
+    def reset(self):
+        self.imgs = []
 </diff>
      <filename>amsn2/core/views/imageview.py</filename>
    </modified>
    <modified>
      <diff>@@ -14,13 +14,13 @@ class KeyBindingView(object):
     PAGEDOWN = &quot;PageDown&quot;
     INSERT = &quot;Insert&quot;
     DELETE = &quot;Delete&quot;
-    
+
     def __init__(self, key = None, control = False, alt = False, shift = False):
         self.key = key
         self.control = control
         self.alt = alt
         self.shift = shift
-        
+
     def __repr__(self):
         out = &quot;&quot;
         if self.control:
@@ -30,6 +30,6 @@ class KeyBindingView(object):
         if self.shift:
             out += &quot;Shift-&quot;
         out += self.key
-        
+
         return out
-    
+</diff>
      <filename>amsn2/core/views/keybindingview.py</filename>
    </modified>
    <modified>
      <diff>@@ -6,22 +6,24 @@ class MenuItemView(object):
     RADIOBUTTONGROUP = &quot;radiobuttongroup&quot;
     SEPARATOR = &quot;separator&quot;
     COMMAND = &quot;command&quot;
-    
+
     def __init__(self, type, label = None, icon = None, accelerator = None,
                  radio_value = None, checkbox_value = False, disabled = False,  command = None):
         &quot;&quot;&quot; Create a new MenuItemView
-        @type : the type of item, can be cascade, checkbutton, radiobutton,
+        @param type: the type of item, can be cascade, checkbutton, radiobutton,
         radiogroup, separator or command
-        @label : the label for the item, unused for separator items
-        @accelerator : the accelerator (KeyBindingView) to access this item.
+        @param label: the label for the item, unused for separator items
+        @param icon: an optional icon to show next to the menu item, unused for separator items
+        @param accelerator: the accelerator (KeyBindingView) to access this item.
                        If None, an '&amp;' preceding a character of the menu label will set that key with Ctrl- as an accelerator
-        @icon : an optional icon to show next to the menu item, unused for separator items
-        @radio_value : the value to set when the radiobutton is enabled
-        @checkbox_value : whether the checkbox/radiobutton is set or not
-        @disabled : true if the item's state should be disabled
-        @command : the command to call for setting the value for checkbutton and radiobutton items, or the command in case of a 'command' item
+        @param radio_value: the value to set when the radiobutton is enabled
+        @type checkbox_value: bool
+        @param checkbox_value: whether the checkbox/radiobutton is set or not
+        @type disabled: bool
+        @param disabled: true if the item's state should be disabled
+        @param command: the command to call for setting the value for checkbutton and radiobutton items, or the command in case of a 'command' item
 
-        TODO: dynamic menus (use 'command' in CASCADE_MENU)
+        @todo: dynamic menus (use 'command' in CASCADE_MENU)
         &quot;&quot;&quot;
 
         if ((type is MenuItemView.SEPARATOR and
@@ -48,7 +50,7 @@ class MenuItemView(object):
              (radio_value is not None or
               checkbox_value is not False or
               icon is not None or
-              command is not None))):              
+              command is not None))):
             raise ValueError, InvalidArgument
 
         new_label = label
@@ -71,7 +73,7 @@ class MenuItemView(object):
                         done = True
                 else:
                     done = True
-        
+
 
         self.type = type
         self.label = new_label
@@ -84,7 +86,7 @@ class MenuItemView(object):
 
     def addItem(self, item):
         self.items.append(item)
-        
+
 
 class MenuView(object):
 
@@ -93,4 +95,4 @@ class MenuView(object):
 
     def addItem(self, item):
         self.items.append(item)
-        
+</diff>
      <filename>amsn2/core/views/menuview.py</filename>
    </modified>
    <modified>
      <diff>@@ -140,13 +140,6 @@ class StringView (object):
         # TODO: Not so easy... maybe there is a python HTML parser we can use?
         pass
 
-    def toString(self):
-        out = &quot;&quot;
-        for x in self._elements:
-            if x.getType() == StringView.TEXT_ELEMENT:
-                out += x.getValue()
-        return out
-
     def toHtmlString(self):
         &quot;&quot;&quot; This method returns a formatted html string with all
         the data in the stringview &quot;&quot;&quot;
@@ -180,7 +173,11 @@ class StringView (object):
         return out
 
     def __str__(self):
-        return self.toString()
+        out = &quot;&quot;
+        for x in self._elements:
+            if x.getType() == StringView.TEXT_ELEMENT:
+                out += x.getValue()
+        return out
 
     def __repr__(self):
         out = &quot;{&quot;</diff>
      <filename>amsn2/core/views/stringview.py</filename>
    </modified>
    <modified>
      <diff>@@ -4,4 +4,3 @@ class TooltipView (object):
         self.name = None
         self.icon = None
 
-    </diff>
      <filename>amsn2/core/views/tooltipview.py</filename>
    </modified>
    <modified>
      <diff>@@ -6,4 +6,3 @@ from main import *
 from splash import *
 from chat_window import *
 from skins import *
-from image import *</diff>
      <filename>amsn2/gui/base/__init__.py</filename>
    </modified>
    <modified>
      <diff>@@ -13,7 +13,8 @@ class aMSNContactListWindow(object):
     &quot;&quot;&quot;
 
     def __init__(self, amsn_core, parent):
-        raise NotImplementedError
+        em = amsn_core._event_manager
+        em.register(em.events.PERSONALINFO_UPDATED, self.myInfoUpdated)
 
     def show(self):
         &quot;&quot;&quot; Show the contact list window &quot;&quot;&quot;
@@ -25,30 +26,31 @@ class aMSNContactListWindow(object):
 
     def setTitle(self, text):
         &quot;&quot;&quot; This will allow the core to change the current window's title
-        @text : a string
+        @type text: str
         &quot;&quot;&quot;
         raise NotImplementedError
 
     def setMenu(self, menu):
         &quot;&quot;&quot; This will allow the core to change the current window's main menu
-        @menu : a MenuView
+        @type menu: MenuView
         &quot;&quot;&quot;
         raise NotImplementedError
 
     def myInfoUpdated(self, view):
         &quot;&quot;&quot; This will allow the core to change pieces of information about
         ourself, such as DP, nick, psm, the current media being played,...
-        @view: the contactView of the ourself (contains DP, nick, psm,
+        @type view: PersonalInfoView
+        @param view: the PersonalInfoView of the ourself (contains DP, nick, psm,
         currentMedia,...)&quot;&quot;&quot;
         raise NotImplementedError
 
 class aMSNContactListWidget(object):
     &quot;&quot;&quot; This interface implements the contact list of the UI &quot;&quot;&quot;
     def __init__(self, amsn_core, parent):
-        clm = amsn_core._contactlist_manager
-        clm.register(clm.CLVIEW_UPDATED, self.contactListUpdated)
-        clm.register(clm.GROUPVIEW_UPDATED, self.groupUpdated)
-        clm.register(clm.CONTACTVIEW_UPDATED, self.contactUpdated)
+        em = amsn_core._event_manager
+        em.register(em.events.CLVIEW_UPDATED, self.contactListUpdated)
+        em.register(em.events.GROUPVIEW_UPDATED, self.groupUpdated)
+        em.register(em.events.CONTACTVIEW_UPDATED, self.contactUpdated)
 
     def show(self):
         &quot;&quot;&quot; Show the contact list widget &quot;&quot;&quot;
@@ -65,7 +67,9 @@ class aMSNContactListWidget(object):
         It will be called initially to feed the contact list with the groups
         that the CL should contain.
         It will also be called to remove any group that needs to be removed.
-        @cl : a ContactListView containing the list of groups contained in
+
+        @type clView: ContactListView
+        @param clView : contains the list of groups contained in
         the contact list which will contain the list of ContactViews
         for all the contacts to show in the group.&quot;&quot;&quot;
         raise NotImplementedError</diff>
      <filename>amsn2/gui/base/contact_list.py</filename>
    </modified>
    <modified>
      <diff>@@ -8,13 +8,18 @@ class aMSNLoginWindow(object):
     def show(self):
         &quot;&quot;&quot; Draw the login window &quot;&quot;&quot;
         raise NotImplementedError
-    
+
     def hide(self):
         &quot;&quot;&quot; Hide the login window &quot;&quot;&quot;
         raise NotImplementedError
 
-    def switch_to_profile(self, profile):
-        &quot;&quot;&quot; This method will be called when the core needs the login window to switch to a different profile &quot;&quot;&quot;
+    def setAccounts(self, accountviews):
+        &quot;&quot;&quot; This method will be called when the core needs the login window to
+        let the user select among some accounts.
+
+        @param accountviews: list of accountviews describing accounts
+        The first one in the list
+        should be considered as default. &quot;&quot;&quot;
         raise NotImplementedError
 
     def signin(self):
@@ -23,9 +28,11 @@ class aMSNLoginWindow(object):
 
     def onConnecting(self, progress, message):
         &quot;&quot;&quot; This method will be called to notify the UI that we are connecting.
-        @progress: the current progress (as float) of the connexion (to be
+
+        @type progress: float
+        @param progress: the current progress of the connexion (to be
         exploited as a progress bar, for example)
-        @message: the message to show while loging in &quot;&quot;&quot;
+        @param message: the message to show while loging in &quot;&quot;&quot;
         raise NotImplementedError
 
 </diff>
      <filename>amsn2/gui/base/login.py</filename>
    </modified>
    <modified>
      <diff>@@ -6,8 +6,12 @@ class aMSNMainWindow(object):
     &quot;&quot;&quot;
 
     def __init__(self, amsn_core):
+        &quot;&quot;&quot;
+        @type amsn_core: aMSNCore
+        &quot;&quot;&quot;
+
         pass
-    
+
     def show(self):
         raise NotImplementedError
 
@@ -16,6 +20,6 @@ class aMSNMainWindow(object):
 
     def setTitle(self,title):
         raise NotImplementedError
-    
+
     def setMenu(self,menu):
         raise NotImplementedError</diff>
      <filename>amsn2/gui/base/main.py</filename>
    </modified>
    <modified>
      <diff>@@ -3,6 +3,10 @@ class aMSNMainLoop(object):
     &quot;&quot;&quot; This Interface represents the main loop abstraction of the application.
     Everythin related to the main loop will be delegates here &quot;&quot;&quot;
     def __init__(self, amsn_core):
+        &quot;&quot;&quot;
+        @type amsn_core: aMSNCore
+        &quot;&quot;&quot;
+
         raise NotImplementedError
 
     def run(self):
@@ -10,14 +14,23 @@ class aMSNMainLoop(object):
         raise NotImplementedError
 
     def idlerAdd(self, func):
-        &quot;&quot;&quot; This will add an idler function into the main loop's idler &quot;&quot;&quot;
+        &quot;&quot;&quot;
+        This will add an idler function into the main loop's idler
+
+        @type func: function
+        &quot;&quot;&quot;
         raise NotImplementedError
 
     def timerAdd(self, delay, func):
-        &quot;&quot;&quot; This will add a timer into the main loop which will call a function&quot;&quot;&quot;
+        &quot;&quot;&quot;
+        This will add a timer into the main loop which will call a function
+
+        @type delay:
+        @type func: function
+        &quot;&quot;&quot;
         raise NotImplementedError
 
     def quit(self):
         &quot;&quot;&quot; This will be called when the core wants to exit &quot;&quot;&quot;
         raise NotImplementedError
-    
+</diff>
      <filename>amsn2/gui/base/main_loop.py</filename>
    </modified>
    <modified>
      <diff>@@ -2,6 +2,11 @@ import os.path
 
 class Skin(object):
     def __init__(self, core, path):
+        &quot;&quot;&quot;
+        @type core: aMSNCore
+        @type path:
+        &quot;&quot;&quot;
+
         self._path = path
         pass
 
@@ -15,6 +20,9 @@ class Skin(object):
 
 class SkinManager(object):
     def __init__(self, core):
+        &quot;&quot;&quot;
+        @type core: aMSNCore
+        &quot;&quot;&quot;
         self._core = core
         self.skin = Skin(core, &quot;skins&quot;)
 </diff>
      <filename>amsn2/gui/base/skins.py</filename>
    </modified>
    <modified>
      <diff>@@ -2,6 +2,10 @@
 class aMSNWindow(object):
     &quot;&quot;&quot; This Interface represents a window of the application. Everything will be done from here &quot;&quot;&quot;
     def __init__(self, amsn_core):
+        &quot;&quot;&quot;
+        @type amsn_core: aMSNCore
+        &quot;&quot;&quot;
+
         raise NotImplementedError
 
     def show(self):
@@ -13,13 +17,19 @@ class aMSNWindow(object):
         raise NotImplementedError
 
     def setTitle(self, text):
-        &quot;&quot;&quot; This will allow the core to change the current window's title
-        @text : a string
         &quot;&quot;&quot;
+        This will allow the core to change the current window's title
+
+        @type text: str
+        &quot;&quot;&quot;
+
         raise NotImplementedError
-    
+
     def setMenu(self, menu):
-        &quot;&quot;&quot; This will allow the core to change the current window's main menu
-        @menu : a MenuView
         &quot;&quot;&quot;
+        This will allow the core to change the current window's main menu
+
+        @type menu: MenuView
+        &quot;&quot;&quot;
+
         raise NotImplementedError</diff>
      <filename>amsn2/gui/base/window.py</filename>
    </modified>
    <modified>
      <diff>@@ -1,6 +1,5 @@
 import efl
 import cocoa
-import console
 import curses
 import gtk
 import qt4</diff>
      <filename>amsn2/gui/front_ends/__init__.py</filename>
    </modified>
    <modified>
      <diff>@@ -16,9 +16,9 @@ try:
     imp.find_module('objc')
     imp.find_module('Foundation')
     imp.find_module('AppKit')
-    
+
     gui.GUIManager.registerFrontEnd(&quot;cocoa&quot;, sys.modules[__name__])
-    
+
 except ImportError:
     pass
-        
+</diff>
      <filename>amsn2/gui/front_ends/cocoa/__init__.py</filename>
    </modified>
    <modified>
      <diff>@@ -4,11 +4,11 @@ from amsn2.gui import base
 from amsn2.core.views import StringView
 from amsn2.core.views import GroupView
 from amsn2.core.views import ContactView
-            
+
 
 class aMSNContactList(base.aMSNContactListWindow):
     def __init__(self, amsn_core, parent):
-		pass
+        pass
 
     def show(self):
         pass
@@ -17,14 +17,14 @@ class aMSNContactList(base.aMSNContactListWindow):
         pass
 
     def contactStateChange(self, contact):
-		pass
+        pass
 
     def contactNickChange(self, contact):
         pass
-        
+
     def contactPSMChange(self, contact):
         pass
-    
+
     def contactAlarmChange(self, contact):
         pass
 
@@ -33,7 +33,7 @@ class aMSNContactList(base.aMSNContactListWindow):
 
     def contactSpaceChange(self, contact):
         pass
-    
+
     def contactSpaceFetched(self, contact):
         pass
 
@@ -48,7 +48,7 @@ class aMSNContactList(base.aMSNContactListWindow):
 
     def contactAdded(self, group, contact):
         pass
-    
+
     def contactRemoved(self, group, contact):
         pass
 </diff>
      <filename>amsn2/gui/front_ends/cocoa/contact_list.py</filename>
    </modified>
    <modified>
      <diff>@@ -5,8 +5,8 @@ from amsn2.gui import base
 class Image(object):
     &quot;&quot;&quot; This interface will represent an image to be used by the UI&quot;&quot;&quot;
     def __init__(self, amsn_core, parent):
-		&quot;&quot;&quot;Initialize the interface. You should store the reference to the core in here &quot;&quot;&quot;
-		self._img = NSImage.alloc().initWithSize_((1,1))
+        &quot;&quot;&quot;Initialize the interface. You should store the reference to the core in here &quot;&quot;&quot;
+        self._img = NSImage.alloc().initWithSize_((1,1))
 
     def load(self, resource_name, value):
         &quot;&quot;&quot; This method is used to load an image using the name of a resource and a value for that resource
@@ -16,7 +16,7 @@ class Image(object):
                 - some more :)
         &quot;&quot;&quot;
         self._img.release()
-        
+
         if (resource_name == 'File'):
             self._img = NSImage.alloc().initWithContentsOfFile_(str(value))
 </diff>
      <filename>amsn2/gui/front_ends/cocoa/image.py</filename>
    </modified>
    <modified>
      <diff>@@ -5,30 +5,30 @@ import main
 class aMSNLoginWindow(object):
     loginView = None
     loggingInView = None
-    
+
     def __init__(self, amsn_core, parent):
         self.amsn_core = amsn_core
         self.parent = parent
-        
+
         self.switch_to_profile(None)
-        
+
         # Save the cocoa views that can be loaded in the main window.
         self.loginView = CocoaLoginView.getView()
         self.loggingInView = CocoaLoggingInView.getView()
-        
+
         # Save a call back method for when the cocoa login: message is sent.
         self.loginView.setParent(self)
         self.loggingInView.setParent(self)
-        
+
     def show(self):
         # Load the login view into the main window.
         self.parent._loadView(self.loginView)
-    
+
     # Call back method.
     def login(self, username, password):
         self._username = username
         self._password = password
-        
+
         # Load loggingInView into main window.
         self.parent._loadView(self.loggingInView)
         self.signin()
@@ -47,7 +47,7 @@ class aMSNLoginWindow(object):
         self.current_profile.email = self._username
         self.current_profile.password = self._password
         self.amsn_core.signinToAccount(self, self.current_profile)
-        
+
     # Set the status message in the login window.
     def onConnecting(self, progress, message):
         self.loggingInView.setStatus(message)</diff>
      <filename>amsn2/gui/front_ends/cocoa/login.py</filename>
    </modified>
    <modified>
      <diff>@@ -4,32 +4,32 @@ from amsn2.gui import base
 
 class aMSNMainWindow(base.aMSNMainWindow):
     cocoaWin = None
-    
+
     def __init__(self, amsn_core):
         self._amsn_core = amsn_core
-        
+
         # Load our window.
         self.cocoaWin = CocoaMainWindow.aMSNCocoaMainWindow.alloc().init()
-    
+
     def setMenu(self, menu_view):
         pass
-    
+
     def setTitle(self, title):
         self.cocoaWin.setTitle_(title)
-    
+
     def show(self):
         self.cocoaWin.makeKeyAndOrderFront_(self.cocoaWin)
         self._amsn_core.idlerAdd(self.__on_show)
 
     def hide(self):
         self.cocoaWin.orderOut_(self.cocoaWin)
-    
+
     def _loadView(self, view, resize=False):
         prevFrame = self.cocoaWin.frame()
         frame = self.cocoaWin.frameRectForContentRect_(view.frame())
         self.cocoaWin.setFrame_display_animate_((prevFrame.origin, frame.size), True, bool(resize))
         self.cocoaWin.setContentView_(view)
         self.cocoaWin.orderFront_(self.cocoaWin)
-    
+
     def __on_show(self):
         self._amsn_core.mainWindowShown()</diff>
      <filename>amsn2/gui/front_ends/cocoa/main.py</filename>
    </modified>
    <modified>
      <diff>@@ -14,16 +14,16 @@ class aMSNMainLoop(base.aMSNMainLoop):
     def run(self):
         self._mainloop = gobject.MainLoop(is_running=True)
         self._context = self._mainloop.get_context()
-        
+
         self._app = aMSNCocoaNSApplication.sharedApplication()
         self._app.finishLaunching()
-        
+
         def glib_context_iterate():
             iters = 0
             while iters &lt; 10 and self._context.pending():
                 self._context.iteration()
             return True
-        
+
         while True:
             try:
                 # This hangs for at most 100ms, or until an event is fired.
@@ -33,7 +33,7 @@ class aMSNMainLoop(base.aMSNMainLoop):
             except KeyboardInterrupt:
                 self.quit()
 
-        
+
     def idlerAdd(self, func):
         gobject.idle_add(func)
 
@@ -43,20 +43,20 @@ class aMSNMainLoop(base.aMSNMainLoop):
     def quit(self):
         self._mainloop.quit()
         sys.exit()
-        
+
 class aMSNCocoaNSApplication(NSApplication):
     def init(self):
         super(aMSNCocoaNSApplication, self).init()
         self.setDelegate_(self)
         return self
-    
-    # Override run so that it doesn't hang. We'll process events ourself thanks! 
+
+    # Override run so that it doesn't hang. We'll process events ourself thanks!
     def run(self):
         return Null
-    
+
     # Looks at the events stack and processes the topmost.
     # return:   True    - An event was processed.
-    #           False   - No events in queue.    
+    #           False   - No events in queue.
     def processEvents(self, timeout=100):
         # Get the next event from the queue.
         if timeout &lt; 0:
@@ -65,19 +65,19 @@ class aMSNCocoaNSApplication(NSApplication):
             eventTimeout = NSDate.distantFuture()
         else:
             eventTimeout = NSDate.dateWithTimeIntervalSinceNow_(float(timeout/1000.0))
-    
+
         # NSAnyEventMask = 0xffffffff - http://osdir.com/ml/python.pyobjc.devel/2003-10/msg00130.html
         event = self.nextEventMatchingMask_untilDate_inMode_dequeue_( \
             0xffffffff, \
             eventTimeout, \
             NSDefaultRunLoopMode , \
             True)
-        
+
         # Process event if we have one. (python None == cocoa nil)
         if event != None:
             self.sendEvent_(event)
             return True
-        
+
         return False
 
 # We call this so that the if someone calls NSApplication.sharedApplication again, they get an aMSNCocoaNSApplication instance rather than a new NSApplication.</diff>
      <filename>amsn2/gui/front_ends/cocoa/main_loop.py</filename>
    </modified>
    <modified>
      <diff>@@ -12,15 +12,15 @@ def getView():
 class aMSNCocoaLoggingInView(NSView):
     statusText =        IBOutlet('statusText')          # Text field with status text.
     progressIndicator = IBOutlet('progressIndicator')   # Spinner.
-    
+
     def setParent(self, parent):
         self.parent = parent
-    
+
     def awakeFromNib(self):
         global view
         view = self
         self.progressIndicator.startAnimation_(self)
-    
+
     def setStatus(self, newText):
         self.statusText.setStringValue_(newText)
 </diff>
      <filename>amsn2/gui/front_ends/cocoa/nibs/CocoaLoggingInView.py</filename>
    </modified>
    <modified>
      <diff>@@ -18,14 +18,14 @@ class aMSNCocoaLoginView(NSView):
     passwordLabel =     IBOutlet('passwordLabel')       # Text label next to passwordField.
     rememberMe =        IBOutlet('rememberMe')          # Check box for save profile.
     rememberPassword =  IBOutlet('rememberPassword')    # Check box for save password.
-    
+
     def awakeFromNib(self):
         global loginView
         loginView = self
-    
+
     def setParent(self, parent):
         self.parent = parent
-    
+
     def login_(self):
         username = str(self.usernameField.stringValue())
         password = str(self.passwordField.stringValue())</diff>
      <filename>amsn2/gui/front_ends/cocoa/nibs/CocoaLoginView.py</filename>
    </modified>
    <modified>
      <diff>@@ -10,12 +10,12 @@ def getView():
 
 class aMSNCocoaSplashScreenView(NSView):
     statusText = IBOutlet('statusText')  # Text field with status text.
-    
+
     def awakeFromNib(self):
         global view
         view = self
-    
+
     def setStatus(self, text):
         self.statusText.setStringValue_(text)
 
-NSBundle.loadNibNamed_owner_('aMSNCocoaSplashScreenView', NSApplication.sharedApplication())
\ No newline at end of file
+NSBundle.loadNibNamed_owner_('aMSNCocoaSplashScreenView', NSApplication.sharedApplication())</diff>
      <filename>amsn2/gui/front_ends/cocoa/nibs/CocoaSplashScreenView.py</filename>
    </modified>
    <modified>
      <diff>@@ -6,7 +6,7 @@ from objc import *
 from Foundation import *
 from AppKit import *
 
-#import 
+#import
 
 #NibClassBuilder.extractClasses('aMSNCocoaMainWindow')
 
@@ -16,6 +16,6 @@ class aMSNCocoaMainWindow(NSWindow):
         pass
 
     def awakeFromNib_(self):
-	    print 'hello world'
+        print 'hello world'
 
 NSBundle.loadNibNamed_owner_('aMSNCocoaMainWindow.nib', currentBundle())</diff>
      <filename>amsn2/gui/front_ends/cocoa/nibs/files/aMSNCocoaLoginView.nib/CocoaLoginWindow.py</filename>
    </modified>
    <modified>
      <diff>@@ -8,12 +8,13 @@ Building
 We use NIB files to build our interface, in order to load the NIB's correctly, we require aMSN 2 to be run from inside an application bundle. To build the bundle you need (from macports):
 
 python25
-py-openssl (see note)
+py25-openssl
 py25-gobject
+py25-crypto
+py25-hashlib
+py25-py2app-devel
 py25-pyobjc2-cocoa
-	- py25-pyobjc2
-	- py25-py2app-devel
-		- py25-py2app (see note)
+
 
 After they have been installed, you will need to run this inside the root folder of amsn2:
 $ /opt/local/bin/python2.5 setupCocoa.py py2app -A
@@ -23,11 +24,11 @@ $ dist/aMSN2.app/Contents/MacOS/aMSN2
 
 py-openssl - Note
 =================
-It is recommended to use the 0.7 version of py-openssl. An updated portfile can be found at: http://hosting.notjustanothermacuser.com/macports/py-openssl/Portfiles/0.7_0.tar.gz
+It is recommended to use the 0.7 version of py-openssl. Last version of Macports is using version 0.7. You can also use an updated portfile that can be found at: http://hosting.notjustanothermacuser.com/macports/py-openssl/Portfiles/0.7_0.tar.gz
 
 py2app - Note
 =============
-The current py2app on mac ports is out of date, they have 0.3.6, while py25-pyobjc2-cooca requires &gt; 0.4.0. No &quot;official&quot; releases of py2app have been made since 0.3.6, however the current trunk from SVN gives version 0.4.2. If you wish to use macports' python25, and you wish to build the bundle then you will need to update the Portfile for py25-py2app. The updated portfile can be found at: http://hosting.notjustanothermacuser.com/macports/py25-py2app/Portfiles/0.4.2_0.tar.gz
+Be sure to use py25-py2app-devel and not py25-py2app from Macports, because py25-py2app is outdated and does not work with pyobjc2-cocoa. 
 
 =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 </diff>
      <filename>amsn2/gui/front_ends/cocoa/readme.txt</filename>
    </modified>
    <modified>
      <diff>@@ -9,13 +9,13 @@ class aMSNSplashScreen(base.aMSNSplashScreen):
 
     def show(self):
         self.parent._loadView(self.view)
-    
+
     def hide(self):
         pass
-    
+
     def setText(self, text):
         self.view.setStatus(text)
-        
+
     def setImage(self, image):
         pass
 </diff>
      <filename>amsn2/gui/front_ends/cocoa/splash.py</filename>
    </modified>
    <modified>
      <diff>@@ -16,7 +16,7 @@ try:
 
     imp.find_module(&quot;curses&quot;)
     gui.GUIManager.registerFrontEnd(&quot;curses&quot;, sys.modules[__name__])
-    
+
 except ImportError:
     pass
-        
+</diff>
      <filename>amsn2/gui/front_ends/curses/__init__.py</filename>
    </modified>
    <modified>
      <diff>@@ -1,130 +1,172 @@
+from __future__ import with_statement
 from amsn2.gui import base
-import pymsn
 import curses
+from threading import Thread
+from threading import Condition
+import time
 
-class Contact(object):
-    def __init__(self, name, presence):
-        self.name = name
-        self.presence = presence
-        self.p2s = {pymsn.Presence.ONLINE:&quot;online&quot;,
-                    pymsn.Presence.BUSY:&quot;busy&quot;,
-                    pymsn.Presence.IDLE:&quot;idle&quot;,
-                    pymsn.Presence.AWAY:&quot;away&quot;,
-                    pymsn.Presence.BE_RIGHT_BACK:&quot;brb&quot;,
-                    pymsn.Presence.ON_THE_PHONE:&quot;phone&quot;,
-                    pymsn.Presence.OUT_TO_LUNCH:&quot;lunch&quot;,
-                    pymsn.Presence.INVISIBLE:&quot;hidden&quot;,
-                    pymsn.Presence.OFFLINE:&quot;offline&quot;}
-        
-
-    def is_online(self):
-        return self.presence != pymsn.Presence.OFFLINE
-
-    def status(self):
-        return self.p2s[self.presence]
-
-class Group(object):
-    def __init__(self, name):
-        self.contacts = {}
-        self.name = name
-
-    def count(self):
-        online = 0
-        total = 0
-        for c in self.contacts:
-            total += 1
-            if self.contacts[c].is_online():
-                online +=1
-
-        return (online, total)
-            
-
-class aMSNContactList(base.aMSNContactList):
-    def __init__(self, amsn_core):
+class aMSNContactListWindow(base.aMSNContactListWindow):
+    def __init__(self, amsn_core, parent):
         self._amsn_core = amsn_core
-        self.groups = {}
-        self.contacts = {}
-	self._stdscr = self._amsn_core.getMainWindow()._stdscr
-        self._win = curses.newwin(100, 100, 3, 3)
+        self._stdscr = parent._stdscr
+        parent.setFocusedWindow(self)
+        (y,x) = self._stdscr.getmaxyx()
+        # TODO: Use a pad instead
+        self._win = curses.newwin(y, int(0.25*x), 0, 0)
+        self._win.bkgd(curses.color_pair(0))
+        self._win.border()
+        self._clwidget = aMSNContactListWidget(amsn_core, self)
 
     def show(self):
-        pass
-
-    def hide(self):
-        pass
-
-    def contactStateChange(self, contact):
-        for group in contact.groups:
-            self.groups[group.id].contacts[contact.id].presence = contact.presence
-            
-        self.__update_view()
-
-    def contactNickChange(self, contact):
-        pass
-        
-    def contactPSMChange(self, contact):
-        pass
-    
-    def contactAlarmChange(self, contact):
-        pass
-
-    def contactDisplayPictureChange(self, contact):
-        pass
-
-    def contactSpaceChange(self, contact):
-        pass
-    
-    def contactSpaceFetched(self, contact):
-        pass
-
-    def contactBlocked(self, contact):
-        pass
-
-    def contactUnblocked(self, contact):
-        pass
-
-    def contactMoved(self, from_group, to_group, contact):
-        pass
-
-    def contactAdded(self, group, contact):
-        self.groups[group.id].contacts[contact.id] = Contact(contact.display_name, contact.presence)
-        self.__update_view()
-    
-    def contactRemoved(self, group, contact):
-        pass
-
-    def contactRenamed(self, contact):
-        pass
-
-    def groupRenamed(self, group):
-        pass
-
-    def groupAdded(self, group):
-        self.groups[group.id] = Group(group.name)
-        self.__update_view()
-
-    def groupRemoved(self, group):
-        pass
-
-    def configure(self, option, value):
-        pass
-
-    def cget(self, option, value):
-        pass
-
-        
-    def __update_view(self):
-        self._win.clear()
-        row = 0
-        for g in self.groups:
-            count = self.groups[g].count()
-            self._win.addstr(row, 0, &quot;%s (%d/%d)&quot; % (self.groups[g].name, count[0], count[1]), curses.A_BOLD | curses.A_UNDERLINE)
-            row += 1
-            for c in self.groups[g].contacts:
-                 self._win.addstr(row, 2, &quot;%s (%s)&quot; % (self.groups[g].contacts[c].name, self.groups[g].contacts[c].status()), curses.A_BOLD)
-                 row += 1
-            row += 1
-
         self._win.refresh()
-                             
 
+    def hide(self):
+        self._stdscr.clear()
+        self._stdscr.refresh()
+
+    def _on_char_cb(self, ch):
+        import sys
+        print &gt;&gt; sys.stderr, &quot;Length is %d&quot; % len(ch)
+        print &gt;&gt; sys.stderr, &quot;Received %s in Contact List&quot; % ch.encode(&quot;UTF-8&quot;)
+        if ch == &quot;KEY_UP&quot;:
+            self._clwidget.move(-1)
+        elif ch == &quot;KEY_DOWN&quot;:
+            self._clwidget.move(1)
+        elif ch == &quot;KEY_NPAGE&quot;:
+            self._clwidget.move(10)
+        elif ch == &quot;KEY_PPAGE&quot;:
+            self._clwidget.move(-10)
+
+class aMSNContactListWidget(base.aMSNContactListWidget):
+
+    def __init__(self, amsn_core, parent):
+        super(aMSNContactListWidget, self).__init__(amsn_core, parent)
+        self._groups_order = []
+        self._groups = {}
+        self._contacts = {}
+        self._win = parent._win
+        self._stdscr = parent._stdscr
+        self._mod_lock = Condition()
+        self._modified = False
+        self._thread = Thread(target=self.__thread_run)
+        self._thread.daemon = True
+        self._thread.setDaemon(True)
+        self._thread.start()
+        self._selected = 1
+
+    def move(self, num):
+        self._selected += num
+        if self._selected &lt; 1:
+            self._selected = 1
+        self.__repaint()
+
+
+    def contactListUpdated(self, clView):
+        # Acquire the lock to do modifications
+        with self._mod_lock:
+            # TODO: Implement it to sort groups
+            for g in self._groups_order:
+                if g not in clView.group_ids:
+                    self._groups.delete(g)
+            for g in clView.group_ids:
+                if not g in self._groups_order:
+                    self._groups[g] = None
+            self._groups_order = clView.group_ids
+            self._modified = True
+
+            # Notify waiting threads that we modified something
+            self._mod_lock.notify()
+
+    def groupUpdated(self, gView):
+        # Acquire the lock to do modifications
+        with self._mod_lock:
+            if self._groups.has_key(gView.uid):
+                if self._groups[gView.uid] is not None:
+                    #Delete contacts
+                    for c in self._groups[gView.uid].contact_ids:
+                        if c not in gView.contact_ids:
+                            if self._contacts[c]['refs'] == 1:
+                                self._contacts.delete(c)
+                            else:
+                                self._contacts[c]['refs'] -= 1
+                #Add contacts
+                for c in gView.contact_ids:
+                    if not self._contacts.has_key(c):
+                        self._contacts[c] = {'cView': None, 'refs': 1}
+                        continue
+                    #If contact wasn't already there, increment reference count
+                    if self._groups[gView.uid] is None or c not in self._groups[gView.uid].contact_ids:
+                        self._contacts[c]['refs'] += 1
+                self._groups[gView.uid] = gView
+                self._modified = True
+
+                # Notify waiting threads that we modified something
+                self._mod_lock.notify()
+
+    def contactUpdated(self, cView):
+        # Acquire the lock to do modifications
+        with self._mod_lock:
+            if self._contacts.has_key(cView.uid):
+                self._contacts[cView.uid]['cView'] = cView
+                self._modified = True
+
+                # Notify waiting threads that we modified something
+                self._mod_lock.notify()
+
+    def __repaint(self):
+        # Acquire the lock to do modifications
+        with self._mod_lock:
+            self._win.clear()
+            (y, x) = self._stdscr.getmaxyx()
+            self._win.move(0,1)
+            available = y
+            gso = []
+            for g in self._groups_order:
+                available -= 1
+                available -= len(self._groups[g].contact_ids)
+                gso.append(g)
+                if available &lt;= 0:
+                    break
+            gso.reverse()
+            available = y
+            i = 0
+            for g in gso:
+                if self._groups[g] is not None:
+                    available -= 1
+                    cids = self._groups[g].contact_ids
+                    cids = cids[:available]
+                    cids.reverse()
+                    for c in cids:
+                        if self._contacts.has_key(c) and self._contacts[c]['cView'] is not None:
+                            if i == y - self._selected:
+                                self._win.bkgdset(curses.color_pair(1))
+                            self._win.insstr(str(self._contacts[c]['cView'].name))
+                            self._win.bkgdset(curses.color_pair(0))
+                            self._win.insch(' ')
+                            self._win.insch(curses.ACS_HLINE)
+                            self._win.insch(curses.ACS_HLINE)
+                            self._win.insch(curses.ACS_LLCORNER)
+                            self._win.insertln()
+                            self._win.bkgdset(curses.color_pair(0))
+                            i += 1
+                    if i == y - self._selected:
+                        self._win.bkgdset(curses.color_pair(1))
+                    self._win.insstr(str(self._groups[g].name))
+                    self._win.bkgdset(curses.color_pair(0))
+                    self._win.insch(' ')
+                    self._win.insch(curses.ACS_LLCORNER)
+                    self._win.insertln()
+                    i += 1
+            self._win.border()
+            self._win.refresh()
+            self._modified = False
+
+
+    def __thread_run(self):
+        while True:
+            # We don't want to repaint too often, once every half second is cool
+            time.sleep(0.5)
+            with self._mod_lock:
+                while not self._modified:
+                    self._mod_lock.wait(timeout=1)
+                self.__repaint()</diff>
      <filename>amsn2/gui/front_ends/curses/contact_list.py</filename>
    </modified>
    <modified>
      <diff>@@ -2,4 +2,5 @@ from main_loop import *
 from main import *
 from contact_list import *
 from login import *
-    
+from amsn2.gui.base import SkinManager
+from splash import *</diff>
      <filename>amsn2/gui/front_ends/curses/curses_.py</filename>
    </modified>
    <modified>
      <diff>@@ -4,47 +4,87 @@ import curses.textpad
 
 class TextBox(object):
     def __init__(self, win, y, x, txt):
-	self._win = win.derwin(1, 30, y, x)
-	self._win.clear()
-	self._txtbox = curses.textpad.Textbox(self._win)
-	self._txtbox.stripspaces = True
+        self._win = win.derwin(1, 30, y, x)
+        self._win.bkgd(' ', curses.color_pair(0))
+        self._win.clear()
+        self._txtbox = curses.textpad.Textbox(self._win)
+        self._txtbox.stripspaces = True
 
         if txt is not None:
-            for x in txt:
-                self._txtbox.do_command(x)
+            self._insert(txt)
 
     def edit(self):
-	return self._txtbox.edit()
+        return self._txtbox.edit()
 
     def value(self):
         return self._txtbox.gather()
-    
+
+    def _insert(self, txt):
+        for ch in txt:
+            self._txtbox.do_command(ch)
+
+class PasswordBox(TextBox):
+    def __init__(self, win, y, x, txt):
+        self._password = ''
+        super(PasswordBox, self).__init__(win, y, x, txt)
+
+    def edit(self, cb=None):
+        return self._txtbox.edit(self._validateInput)
+
+    def value(self):
+        return self._password
+
+    def _validateInput(self, ch):
+        if ch in (curses.KEY_BACKSPACE, curses.ascii.BS):
+            self._password = self._password[0:-1]
+            return ch
+        elif curses.ascii.isprint(ch):
+            self._password += chr(ch)
+            return '*'
+        else:
+            return ch
+
+    def _insert(self, str):
+        for ch in str:
+            self._password += ch
+            self._txtbox.do_command('*')
+
 class aMSNLoginWindow(object):
-    def __init__(self, amsn_core):
+    def __init__(self, amsn_core, parent):
         self._amsn_core = amsn_core
         self.switch_to_profile(None)
-	self._stdscr = self._amsn_core.getMainWindow()._stdscr
-        self._win = curses.newwin(20, 100, 5, 5)
-        
+        self._stdscr = parent._stdscr
+
+        (y, x) = self._stdscr.getmaxyx()
+        wy = int(y * 0.8)
+        wx = int(x * 0.8)
+        sy = int((y - wy)/2)
+        sx = int((x - wx)/2)
+        self._win = curses.newwin(wy, wx, sy, sx)
+
     def show(self):
+        self._win.border()
+        self._win.bkgd(' ', curses.color_pair(1))
         self._win.addstr(5, 5, &quot;Account : &quot;, curses.A_BOLD)
         self._username_t = TextBox(self._win, 5, 17, self._username)
 
         self._win.addstr(8, 5, &quot;Password : &quot;, curses.A_BOLD)
-        self._password_t = TextBox(self._win, 8, 17, self._password)
-        
+        self._password_t = PasswordBox(self._win, 8, 17, self._password)
+
         self._win.refresh()
-        
+
         self._username_t.edit()
         self._password_t.edit()
 
+        curses.curs_set(0)
         self.signin()
 
     def hide(self):
         self._username_t = None
         self._password_t = None
-        self._win.clear()
-        self._win.refresh()
+        self._win = None
+        self._stdscr.clear()
+        self._stdscr.refresh()
 
     def switch_to_profile(self, profile):
         self.current_profile = profile
@@ -57,54 +97,12 @@ class aMSNLoginWindow(object):
         self.current_profile.email = self._username_t.value()
         self.current_profile.password = self._password_t.value()
         self._amsn_core.signinToAccount(self, self.current_profile)
-        
 
-    def onConnecting(self, progress, message):
-        self._username_t = None
-        self._password_t = None
-        self._win.clear()
-        
-        self._win.addstr(10, 25, &quot;Connecting...&quot;, curses.A_BOLD | curses.A_STANDOUT)
-        self._win.refresh()
 
-    def onConnected(self):
-        self._username_t = None
-        self._password_t = None
-        self._win.clear()
-        
-        self._win.addstr(10, 25, &quot;Connected...&quot;, curses.A_BOLD | curses.A_STANDOUT)
-        self._win.refresh()
-
-    def onAuthenticating(self):
-        self._username_t = None
-        self._password_t = None
-        self._win.clear()
-        
-        self._win.addstr(10, 25, &quot;Authenticating...&quot;, curses.A_BOLD | curses.A_STANDOUT)
-        self._win.refresh()
-
-    def onAuthenticated(self):
-        self._username_t = None
-        self._password_t = None
-        self._win.clear()
-        
-        self._win.addstr(10, 25, &quot;Authenticated...&quot;, curses.A_BOLD | curses.A_STANDOUT)
-        self._win.refresh()
-
-    def onSynchronizing(self):
+    def onConnecting(self, progress, message):
         self._username_t = None
         self._password_t = None
         self._win.clear()
-        
-        self._win.addstr(10, 25, &quot;Fetching contact list...&quot;, curses.A_BOLD | curses.A_STANDOUT)
-        self._win.refresh()
 
-    def onSynchronized(self):
-        self._username_t = None
-        self._password_t = None
-        self._win.clear()
-        
-        self._win.addstr(10, 25, &quot;Synchronized!&quot;, curses.A_BOLD | curses.A_STANDOUT)
+        self._win.addstr(10, 25, message, curses.A_BOLD | curses.A_STANDOUT)
         self._win.refresh()
-
-</diff>
      <filename>amsn2/gui/front_ends/curses/login.py</filename>
    </modified>
    <modified>
      <diff>@@ -1,5 +1,6 @@
 
 from amsn2.gui import base
+import command
 
 import curses
 class aMSNMainWindow(base.aMSNMainWindow):
@@ -7,20 +8,36 @@ class aMSNMainWindow(base.aMSNMainWindow):
         self._amsn_core = amsn_core
 
     def show(self):
-	self._stdscr = curses.initscr()
-	curses.noecho()
-	curses.cbreak()
-	self._stdscr.keypad(1)
+        self._stdscr = curses.initscr()
+        self._command_line = command.CommandLine(self._stdscr, None)
+        self.__init_colors()
+        curses.noecho()
+        curses.cbreak()
+        self._stdscr.keypad(1)
         self._stdscr.box()
         self._stdscr.refresh()
         self._amsn_core.idlerAdd(self.__on_show)
-        
+
     def hide(self):
-	curses.nocbreak()
-	self._stdscr.keypad(0)
-	curses.echo()
-	curses.endwin()
-    
+        curses.nocbreak()
+        self._stdscr.keypad(0)
+        curses.echo()
+        curses.endwin()
+
     def __on_show(self):
         self._amsn_core.mainWindowShown()
-       
+
+    def setTitle(self,title):
+        self._title = title
+
+    def setMenu(self,menu):
+        pass
+
+    def setFocusedWindow(self, window):
+        self._command_line.setCharCb(window._on_char_cb)
+
+    def __init_colors(self):
+        curses.start_color()
+        curses.init_pair(1, curses.COLOR_YELLOW, curses.COLOR_WHITE)
+        curses.init_pair(2, curses.COLOR_BLACK, curses.COLOR_BLUE)
+</diff>
      <filename>amsn2/gui/front_ends/curses/main.py</filename>
    </modified>
    <modified>
      <diff>@@ -1,10 +1,12 @@
 
 from amsn2.gui import base
 import gobject
+gobject.threads_init()
 
 class aMSNMainLoop(base.aMSNMainLoop):
     def __init__(self, amsn_core):
         self._amsn_core = amsn_core
+
     def run(self):
         self._mainloop = gobject.MainLoop(is_running=True)
 
@@ -14,7 +16,6 @@ class aMSNMainLoop(base.aMSNMainLoop):
             except KeyboardInterrupt:
                 self.quit()
 
-        
     def idlerAdd(self, func):
         gobject.idle_add(func)
 
@@ -24,9 +25,9 @@ class aMSNMainLoop(base.aMSNMainLoop):
     def quit(self):
         import curses
         stdscr = self._amsn_core.getMainWindow()._stdscr
-	curses.nocbreak()
-	stdscr.keypad(0)
-	curses.echo()
-	curses.endwin()
+        curses.nocbreak()
+        stdscr.keypad(0)
+        curses.echo()
+        curses.endwin()
         self._mainloop.quit()
-        
+</diff>
      <filename>amsn2/gui/front_ends/curses/main_loop.py</filename>
    </modified>
    <modified>
      <diff>@@ -20,10 +20,10 @@ try:
     imp.find_module(&quot;evas&quot;)
     imp.find_module(&quot;edje&quot;)
     imp.find_module(&quot;ecore&quot;)
-    imp.find_module(&quot;etk&quot;)
+    imp.find_module(&quot;elementary&quot;)
 
     gui.GUIManager.registerFrontEnd(&quot;efl&quot;, sys.modules[__name__])
-    
+
 except ImportError:
     pass
-        
+</diff>
      <filename>amsn2/gui/front_ends/efl/__init__.py</filename>
    </modified>
    <modified>
      <diff>@@ -89,7 +89,7 @@ class aMSNChatWidget(etk.VPaned, base.aMSNChatWidget):
         print &quot;%s is typing&quot; % (contact,)
 
     def onMessageReceived(self, messageview):
-        self.__outputAppendMsg(messageview.toStringView().toString())
+        self.__outputAppendMsg(str(messageview.toStringView()))
 
     def nudge(self):
         #TODO</diff>
      <filename>amsn2/gui/front_ends/efl/chat_window.py</filename>
    </modified>
    <modified>
      <diff>@@ -4,30 +4,31 @@ import evas
 import edje
 import ecore
 import ecore.evas
-import etk
+import elementary
 
 from image import *
 
 from amsn2.core.views import StringView
 from amsn2.gui import base
-import pymsn
+import papyon
 
-class aMSNContactListWindow(base.aMSNContactListWindow):
+class aMSNContactListWindow(elementary.Box, base.aMSNContactListWindow):
     def __init__(self, amsn_core, parent):
         self._core = amsn_core
         self._evas = parent._evas
         self._parent = parent
         self._skin = amsn_core._skin_manager.skin
-        self._clwidget = aMSNContactListWidget(amsn_core, self)
-        parent.setChild(self._clwidget)
-        self._clwidget.show()
+        elementary.Box.__init__(self, parent)
+        self._parent.resize_object_add(self)
+        self.size_hint_weight_set(1.0, 1.0)
+        self.show()
 
-    def show(self):
+        self._clwidget = aMSNContactListWidget(amsn_core, self._parent)
+        self.pack_start(self._clwidget)
+        self._parent.resize_object_add(self._clwidget)
+        self._parent.resize_object_add(self._clwidget._edje)
         self._clwidget.show()
 
-    def hide(self):
-        self._clwidget.hide()
-
     def setTitle(self, text):
         self._parent.setTitle(text)
 
@@ -38,36 +39,29 @@ class aMSNContactListWindow(base.aMSNContactListWindow):
         pass #TODO
 
 
-class aMSNContactListWidget(etk.ScrolledView, base.aMSNContactListWidget):
+class aMSNContactListWidget(elementary.Scroller, base.aMSNContactListWidget):
     def __init__(self, amsn_core, parent):
         base.aMSNContactListWidget.__init__(self, amsn_core, parent)
         self._core = amsn_core
         self._evas = parent._evas
-        self._skin = parent._skin
-
-        self._etk_evas_object = etk.EvasObject()
-        etk.ScrolledView.__init__(self)
-
-        edje.frametime_set(1.0 / 30)
-        try:
-            self._edje = edje.Edje(self._evas, file=THEME_FILE,
-                                group=&quot;contact_list&quot;)
-        except edje.EdjeLoadError, e:
-            raise SystemExit(&quot;error loading %s: %s&quot; % (THEME_FILE, e))
-
-
-        self.group_holder = GroupHolder(self._evas, self)
+        self._skin = amsn_core._skin_manager.skin
+        elementary.Scroller.__init__(self, parent)
+        self.size_hint_weight_set(1.0, 1.0)
 
-        self._etk_evas_object.evas_object = self._edje
-        self.add_with_viewport(self._etk_evas_object)
+        self._edje = elementary.Layout(self)
+        self._edje.file_set(filename=THEME_FILE,
+                            group=&quot;contact_list&quot;)
+        self.group_holder = GroupHolder(self._evas, self._edje, self._skin)
 
-        self._edje.part_swallow(&quot;groups&quot;, self.group_holder);
 
+        self._edje.content_set(&quot;groups&quot;, self.group_holder);
+        self._edje.size_hint_weight_set(1.0, 1.0)
         self._edje.show()
-        self._etk_evas_object.show()
+        self.content_set(self._edje)
 
 
     def contactUpdated(self, contact):
+        print contact
         for gi in self.group_holder.group_items_list:
             if contact.uid in gi.contact_holder.contacts_dict:
                 gi.contact_holder.contact_updated(contact)
@@ -81,11 +75,6 @@ class aMSNContactListWidget(etk.ScrolledView, base.aMSNContactListWidget):
         self.group_holder.viewUpdated(clview)
 
 
-
-    def size_request_set(self, w,h):
-        self._etk_evas_object.size_request_set(w,h)
-
-
 class ContactHolder(evas.SmartObject):
 
     def __init__(self, ecanvas, parent):
@@ -102,7 +91,7 @@ class ContactHolder(evas.SmartObject):
             c = self.contacts_dict[contactview.uid]
         except KeyError:
             return
-        c.part_text_set(&quot;contact_data&quot;, contactview.name.toString())
+        c.part_text_set(&quot;contact_data&quot;, str(contactview.name))
 
         if DP_IN_CL:
             # add the dp
@@ -238,7 +227,7 @@ class GroupItem(edje.Edje):
             return self.contact_holder.num_contacts()
 
     def group_updated(self, groupview):
-        self.part_text_set(&quot;group_name&quot;, groupview.name.toString())
+        self.part_text_set(&quot;group_name&quot;, str(groupview.name))
         self.contact_holder.groupViewUpdated(groupview)
 
     # Private methods
@@ -266,13 +255,13 @@ class GroupItem(edje.Edje):
 
 class GroupHolder(evas.SmartObject):
 
-    def __init__(self, ecanvas, parent):
+    def __init__(self, ecanvas, parent, skin):
         evas.SmartObject.__init__(self, ecanvas)
         self.evas_obj = ecanvas
         self.group_items_list = []
         self.group_items_dict = {}
         self._parent = parent
-        self._skin = parent._skin
+        self._skin = skin
 
     def add_group(self, uid):
         new_group = GroupItem(self, self.evas_obj, uid)
@@ -297,13 +286,14 @@ class GroupHolder(evas.SmartObject):
         self.update_widget(w, h)
 
     def show(self):
+        &quot;&quot;&quot;
         #FIXME:
         #ugly fix to get the correct clip
-        self.clip_set(self._parent._edje.clip_get())
+        self.clip_set(self._parent.clip_get())
         self.update_widget(self.size[0], self.size[1])
+        &quot;&quot;&quot;
         for g in self.group_items_list:
             g.show()
-
     def hide(self):
         for g in self.group_items_list:
             g.hide()
@@ -338,7 +328,7 @@ class GroupHolder(evas.SmartObject):
                 i.move(x, y)
                 i.size = (w, item_height)
                 y += item_height + spacing
-        self._parent.size_request_set(w,y)
+        self._parent.size_hint_request_set(w,y)
 
     def clip_set(self, obj):
         for g in self.group_items_list:</diff>
      <filename>amsn2/gui/front_ends/efl/contact_list.py</filename>
    </modified>
    <modified>
      <diff>@@ -1,8 +1,8 @@
 from main_loop import *
 from main import *
-from contact_list import *
 from login import *
+from contact_list import *
 from image import *
 from splash import *
 from skins import *
-from chat_window import *
+#from chat_window import *</diff>
      <filename>amsn2/gui/front_ends/efl/efl.py</filename>
    </modified>
    <modified>
      <diff>@@ -62,7 +62,7 @@ class Image(evas.SmartObject):
         self._loadFromFilename(tf, pos, view, i)
 
 
-    def _loadFromSkin(self, resource_name, pos=0, view=None, i=0):
+    def _loadFromTheme(self, resource_name, pos=0, view=None, i=0):
         res = self._skin.getKey(resource_name)
         if res is not None:
             (type, value) = res</diff>
      <filename>amsn2/gui/front_ends/efl/image.py</filename>
    </modified>
    <modified>
      <diff>@@ -2,72 +2,64 @@ from constants import *
 import edje
 import ecore
 import ecore.x
-import etk
+import elementary
 
 from amsn2.gui import base
+from amsn2.core.views import accountview
 
 class aMSNLoginWindow(base.aMSNLoginWindow):
     def __init__(self, amsn_core, parent):
         self._amsn_core = amsn_core
         self._evas = parent._evas
         self._parent = parent
+        self._account_views = []
 
         edje.frametime_set(1.0 / 30)
 
-        mainChild = etk.EvasObject()
-
         try:
             self._edje = edje.Edje(self._evas, file=THEME_FILE,
                                 group=&quot;login_screen&quot;)
         except edje.EdjeLoadError, e:
             raise SystemExit(&quot;error loading %s: %s&quot; % (THEME_FILE, e))
 
-        mainChild.evas_object = self._edje
+        self._parent.resize_object_add(self._edje)
+        self._edje.size_hint_weight_set(1.0, 1.0)
+        self.show()
 
-        self.password = etk.Entry()
-        embed = etk.Embed(self._evas)
-        embed.add(self.password)
-        embed.show_all()
-        self.password.password_mode = True
-        self._edje.part_swallow(&quot;login_screen.password&quot;, embed.object)
+        self.password = elementary.Entry(self._edje)
+        self.password.single_line_set(1)
+        self.password.password_set(1)
+        self.password.size_hint_weight_set(1.0, 1.0)
+        self.password.show()
+        self._edje.part_swallow(&quot;login_screen.password&quot;, self.password)
+        self.password.show()
 
-        self.status = etk.Entry()
-        embed = etk.Embed(self._evas)
-        embed.add(self.status)
-        embed.show_all()
-        self._edje.part_swallow(&quot;login_screen.status&quot;, embed.object)
+        #TODO: login_screen.status
 
-        self.username = etk.Entry()
-        embed = etk.Embed(self._evas)
-        embed.add(self.username)
-        embed.show_all()
-        self._edje.part_swallow(&quot;login_screen.username&quot;, embed.object)
+        self.username = elementary.Entry(self._edje)
+        self.username.single_line_set(1)
+        self.username.show()
+        self._edje.part_swallow(&quot;login_screen.username&quot;, self.username)
 
         if self._edje.part_exists(&quot;login_screen.signin&quot;):
-           self.signin_b = etk.Button()
-           embed = etk.Embed(self._evas)
-           embed.add(self.signin_b)
-           embed.show_all()
-           self._edje.part_swallow(&quot;login_screen.signin&quot;, embed.object)
-           self.signin_b.label = &quot;Sign in&quot;
-           self.signin_b.connect(&quot;clicked&quot;, self.__signin_button_cb)
+           self.signin_b = elementary.Button(self._edje)
+           self.signin_b.label_set(&quot;Sign in&quot;)
+           self.signin_b.clicked = self.__signin_button_cb
+           self.signin_b.show()
+           self._edje.part_swallow(&quot;login_screen.signin&quot;, self.signin_b)
         else:
            self._edje.signal_callback_add(&quot;signin&quot;, &quot;*&quot;, self.__signin_cb)
 
 
-        # We start with no profile set up, we let the Core set our starting profile
-        self.switch_to_profile(None)
-
-        parent.setChild(mainChild)
-
     def show(self):
+        self._parent.resize_object_add(self._edje)
         self._edje.show()
 
     def hide(self):
+        self._parent.resize_object_del(self._edje)
         self._edje.hide()
-        #FIXME: those are not hidden by self._edje.hide() 
+        #FIXME: those are not hidden by self._edje.hide()
         self.password.hide()
-        self.status.hide()
         self.username.hide()
         try:
             getattr(self, &quot;signin_b&quot;)
@@ -76,19 +68,29 @@ class aMSNLoginWindow(base.aMSNLoginWindow):
         else:
             self.signin_b.hide()
 
-    def switch_to_profile(self, profile):
-        self.current_profile = profile
-        if self.current_profile is not None:
-            self.username.text = self.current_profile.username
-            self.password.text = self.current_profile.password
+
+    def setAccounts(self, accountviews):
+        self._account_views = accountviews
+        if accountviews:
+            #Only select the first one
+            acc = accountviews[0]
+            self.username.entry_set(acc.email)
+            self.password.entry_set(acc.password)
 
 
     def signin(self):
-        # TODO : get/set the username/password and other options from the login screen
-        self.current_profile.username = self.username.text
-        self.current_profile.email = self.username.text
-        self.current_profile.password = self.password.text
-        self._amsn_core.signinToAccount(self, self.current_profile)
+        email = elementary.Entry.markup_to_utf8(self.username.entry_get()).strip()
+        password = elementary.Entry.markup_to_utf8(self.password.entry_get()).strip()
+
+        accv = [accv for accv in self._account_views if accv.email == email]
+        if not accv:
+            accv = AccountView()
+            accv.email = email
+        else:
+            accv = accv[0]
+        accv.password = password
+
+        self._amsn_core.signinToAccount(self, accv)
 
     def onConnecting(self, progress, message):
         self._edje.signal_emit(&quot;connecting&quot;, &quot;&quot;)
@@ -110,6 +112,5 @@ class aMSNLoginWindow(base.aMSNLoginWindow):
     def __signin_cb(self, edje_obj, signal, source):
         self.signin()
 
-    def __signin_button_cb(self, button):
-        print &quot;clicked %s - %s&quot; % (self, button)
+    def __signin_button_cb(self, button, event, data):
         self.signin()</diff>
      <filename>amsn2/gui/front_ends/efl/login.py</filename>
    </modified>
    <modified>
      <diff>@@ -2,7 +2,6 @@ from constants import *
 import ecore
 import ecore.evas
 import ecore.x
-import etk
 import skins
 import window
 from amsn2.gui import base
@@ -11,9 +10,9 @@ from amsn2.core.views import MenuView, MenuItemView
 class aMSNMainWindow(window.aMSNWindow, base.aMSNMainWindow):
     def __init__(self, amsn_core):
         window.aMSNWindow.__init__(self, amsn_core)
-        self.on_destroyed(self.__on_delete_request)
-        self.on_shown(self.__on_show)
-        self.on_key_down(self.__on_key_down)
+        self.destroy = self.__on_delete_request
+        self.on_show_add(self.__on_show)
+        self.on_key_down_add(self.__on_key_down)
 
     &quot;&quot;&quot; Private methods
         thoses methods shouldn't be called by outside or by an inherited class
@@ -22,7 +21,7 @@ class aMSNMainWindow(window.aMSNWindow, base.aMSNMainWindow):
     def __on_show(self, evas_obj):
         self._amsn_core.mainWindowShown()
 
-    def __on_delete_request(self, evas_obj):
+    def __on_delete_request(self, evas_obj, emission, data):
         self._amsn_core.quit()
 
     def __on_key_down(self, obj, event):</diff>
      <filename>amsn2/gui/front_ends/efl/main.py</filename>
    </modified>
    <modified>
      <diff>@@ -2,11 +2,12 @@
 from amsn2.gui import base
 import gobject
 import ecore
+import elementary
 
 class aMSNMainLoop(base.aMSNMainLoop):
     def __init__(self, amsn_core):
-        pass
-    
+        elementary.init()
+
     def run(self):
         mainloop = gobject.MainLoop(is_running=True)
         context = mainloop.get_context()
@@ -21,8 +22,9 @@ class aMSNMainLoop(base.aMSNMainLoop):
         # to allow the protocol context loop to work
         ecore.timer_add(0.1, glib_context_iterate)
 
+        #equals elementary.run()
         ecore.main_loop_begin()
-        
+
     def idlerAdd(self, func):
         ecore.idler_add(func)
 
@@ -31,4 +33,4 @@ class aMSNMainLoop(base.aMSNMainLoop):
 
     def quit(self):
         ecore.main_loop_quit()
-        
+</diff>
      <filename>amsn2/gui/front_ends/efl/main_loop.py</filename>
    </modified>
    <modified>
      <diff>@@ -1,6 +1,7 @@
 import os.path
+from amsn2.gui import base
 
-class Skin(object):
+class Skin(base.Skin):
     def __init__(self, core, path):
         self._path = path
         self._dict = {}
@@ -45,7 +46,7 @@ class Skin(object):
 
 
 
-class SkinManager(object):
+class SkinManager(base.SkinManager):
     def __init__(self, core):
         self._core = core
         self.skin = Skin(core, &quot;skins&quot;)</diff>
      <filename>amsn2/gui/front_ends/efl/skins.py</filename>
    </modified>
    <modified>
      <diff>@@ -7,12 +7,12 @@ class aMSNSplashScreen(base.aMSNSplashScreen):
 
     def show(self):
         pass
-    
+
     def hide(self):
         pass
-    
+
     def setText(self, text):
         pass
-        
+
     def setImage(self, image):
         pass</diff>
      <filename>amsn2/gui/front_ends/efl/splash.py</filename>
    </modified>
    <modified>
      <diff>@@ -3,115 +3,43 @@ from constants import *
 import ecore
 import ecore.evas
 import ecore.x
-import etk
+import elementary
 
 from amsn2.gui import base
 from amsn2.core.views import MenuView, MenuItemView
 
-class aMSNWindow(etk.Window, base.aMSNWindow):
+class aMSNWindow(elementary.Window, base.aMSNWindow):
     def __init__(self, amsn_core):
         self._amsn_core = amsn_core
-        self._vbox = etk.VBox()
-        etk.Window.__init__(self,title=&quot;aMSN&quot;,
-                               size_request=(MIN_WIDTH,MIN_HEIGHT),
-                               child=self._vbox)
-        self.on_key_down(self._on_key_down)
-        self.fullscreen = False
-        self.wmclass_set(WM_NAME, WM_CLASS)
+        elementary.Window.__init__(self, &quot;aMSN&quot;, elementary.ELM_WIN_BASIC)
         self.resize(WIDTH, HEIGHT)
-        self._has_menu = False
-        self._vbox.show()
+        self.on_key_down_add(self._on_key_down)
+        self.fullscreen = False
+        self.name_class_set = (WM_NAME, WM_CLASS)
+        #self._has_menu = False
 
     @property
     def _evas(self):
-        return self.toplevel_evas_get()
-
-    def show(self):
-        self.show_all()
+        return self.canvas
 
     def hide(self):
-        self.hide()
+        pass
 
     def setTitle(self, text):
         self.title_set(text)
 
     def setMenu(self, menu):
-        if menu is None:
-            if self._has_menu:
-                #Remove the menubar
-                menu_bar = self._vbox.child_get_at(etk.VBox.START, 0)
-                menu_bar.parent = None
-                self._has_menu = False
-        else:
-            if self._has_menu:
-                menu_bar = self._vbox.child_get_at(etk.VBox.START, 0)
-                #Clear the menubar:
-                for menu_item in menu_bar.items_get:
-                    menu_bar.remove(menu_item)
-            else:
-                menu_bar = etk.MenuBar()
-                self._vbox.prepend(menu_bar, etk.VBox.START, etk.VBox.FILL, 0)
-                self._has_menu = True
-            createEtkMenuFromMenuView(menu.items, menu_bar)
-
+        pass
 
     def setChild(self, child):
-        obj = self.getChild()
-        if obj is not None:
-            obj.parent = None
-        self._vbox.append(child, etk.VBox.START, etk.VBox.EXPAND_FILL, 0)
+        pass
 
     def getChild(self):
-        if self._has_menu:
-            pos = 1
-        else:
-            pos = 0
         pass
-        return self._vbox.child_get_at(etk.VBox.START, pos)
 
     def toggleMenu(self):
-        if self._has_menu:
-            menu_bar = self._vbox.child_get_at(etk.VBox.START, 0)
-            if menu_bar.is_visible():
-                menu_bar.hide()
-            else:
-                menu_bar.show()
+        pass
 
     def _on_key_down(self, obj, event):
-        if (event.keyname == &quot;F6&quot; or
-            (event.keyname is &quot;f&quot; and event.modifiers is
-             etk.c_etk.EventEnums.MODIFIER_CTRL)):
-            self.fullscreen = not self.fullscreen
-        elif (event.keyname == &quot;F5&quot; or
-              (event.keyname is &quot;b&quot; and event.modifiers is
-               etk.c_etk.EventEnums.MODIFIER_CTRL)):
-            self.decorated = not self.decorated
-        elif (event.keyname == &quot;m&quot; and
-              event.modifiers == etk.c_etk.EventEnums.MODIFIER_CTRL):
-            self.toggleMenu()
-
-def createEtkMenuFromMenuView(items, etkmenu):
-    for item in items:
-        if item.type is MenuItemView.CASCADE_MENU:
-            m = etk.Menu()
-            mi = etk.MenuItem(label=item.label)
-            createEtkMenuFromMenuView(item.items, m)
-            mi.submenu = m
-            etkmenu.append(mi)
-        elif item.type is MenuItemView.COMMAND:
-            if item.icon is None:
-                mi = etk.MenuItem(label=item.label)
-            else:
-                #TODO: icon
-                mi = etk.MenuItemImage(label=item.label)
-            #TODO: define the prototype of item.command
-            #=&gt; for the moment, it's item.command() i.e. no argument
-            def cb(obj):
-                item.command()
-            mi.on_activated(cb)
-            etkmenu.append(mi)
-        elif item.type is MenuItemView.SEPARATOR:
-            mi = etk.MenuItemSeparator()
-            etkmenu.append(mi)
+        pass
 
-        #TODO: CHECKBUTTON, RADIOBUTTON, RADIOBUTTONGROUP</diff>
      <filename>amsn2/gui/front_ends/efl/window.py</filename>
    </modified>
    <modified>
      <diff>@@ -16,7 +16,7 @@ try:
 
     imp.find_module(&quot;gtk&quot;)
     gui.GUIManager.registerFrontEnd(&quot;gtk&quot;, sys.modules[__name__])
-    
+
 except ImportError:
     pass
-        
+</diff>
      <filename>amsn2/gui/front_ends/gtk/__init__.py</filename>
    </modified>
    <modified>
      <diff>@@ -30,7 +30,7 @@ from htmltextview import *
 from amsn2.gui import base
 from amsn2.core.views import StringView
 import gtk_extras
-import pymsn
+import papyon
 
 class aMSNChatWindow(base.aMSNChatWindow, gtk.Window):
     def __init__(self, amsn_core):
@@ -41,18 +41,18 @@ class aMSNChatWindow(base.aMSNChatWindow, gtk.Window):
         self.set_default_size(550, 450)
         self.set_position(gtk.WIN_POS_CENTER)
         self.set_title(&quot;aMSN - Chatwindow&quot;)
-        
+
         #leave
 
     def addChatWidget(self, chat_widget):
         print 'addedChatWidget'
         #if self.child is not None: self.remove(self.child)
-        #if self.child is not None: 
+        #if self.child is not None:
         #    self.show_all()
         #    return
         if self.child is None: self.add(chat_widget)
         self.child = chat_widget
-        
+
         self.show_all()
         self.child.entry.grab_focus()
 
@@ -60,7 +60,7 @@ class aMSNChatWindow(base.aMSNChatWindow, gtk.Window):
 class aMSNChatWidget(base.aMSNChatWidget, gtk.VBox):
     def __init__(self, amsn_conversation, parent):
         gtk.VBox.__init__(self, False, 0)
-        
+
         self._parent = parent
         self._amsn_conversation = amsn_conversation
         self._amsn_core = amsn_conversation._core
@@ -71,24 +71,24 @@ class aMSNChatWidget(base.aMSNChatWidget, gtk.VBox):
         self.nickstyle = &quot;color:#555555; margin-left:2px&quot;
         self.msgstyle = &quot;margin-left:15px&quot;
         self.infostyle = &quot;margin-left:2px; font-style:italic; color:#6d6d6d&quot;
-        
+
         self.chatheader = aMSNChatHeader()
-        
+
         # Middle
         self.textview = HtmlTextView()
         tscroll = gtk.ScrolledWindow()
         tscroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
         tscroll.set_shadow_type(gtk.SHADOW_ETCHED_IN)
         tscroll.add(self.textview)
-        
+
         #self.chat_roster = ChatRoster()
-        
+
         self.middle_box = gtk.HPaned()
         self.middle_box.pack1(tscroll, True, True)
-        
+
         # Bottom
         self.entry = MessageTextView()
-        
+
         # Tags for entry
         tag = self.entry.get_buffer().create_tag(&quot;bold&quot;)
         tag.set_property(&quot;weight&quot;, pango.WEIGHT_BOLD)
@@ -102,14 +102,14 @@ class aMSNChatWidget(base.aMSNChatWidget, gtk.VBox):
         tag.set_property(&quot;foreground_gdk&quot;, gtk.gdk.Color(0,0,0))
         tag = self.entry.get_buffer().create_tag(&quot;family&quot;)
         tag.set_property(&quot;family&quot;, &quot;MS Sans Serif&quot;)
-        
+
         escroll = gtk.ScrolledWindow()
         escroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
         escroll.set_placement(gtk.CORNER_TOP_LEFT)
         escroll.set_shadow_type(gtk.SHADOW_IN)
         escroll.set_size_request(-1, 40)
         escroll.add(self.entry)
-        
+
         # Register button icons as stock icons
         iconfactory = gtk.IconFactory()
         icons = ['button_smile', 'button_nudge']
@@ -131,10 +131,10 @@ class aMSNChatWidget(base.aMSNChatWidget, gtk.VBox):
         self.button_color = gtk_extras.ColorToolButton()
         self.button_font = gtk_extras.FontToolButton()
         self.button8 = gtk.ToolButton(gtk.STOCK_CLEAR)
-        
+
         self.button_font.set_show_size(0)
         self.button_font.set_show_style(0)
-        
+
         bbox = gtk.Toolbar()
         bbox.set_style(gtk.TOOLBAR_ICONS)
         bbox.insert(self.button1, -1)
@@ -148,44 +148,44 @@ class aMSNChatWidget(base.aMSNChatWidget, gtk.VBox):
         bbox.insert(self.button_strikethrough, -1)
         bbox.insert(gtk.SeparatorToolItem(), -1)
         bbox.insert(self.button8, -1)
-        
+
         bottom_box = gtk.VBox(False, 0)
         bottom_box.pack_start(bbox, False, False, 0)
         bottom_box.pack_start(escroll, True,True, 0)
-        
+
         self.statusbar = gtk.Statusbar()
         self.statusbar.set_has_resize_grip(False)
         self.statusbar.set_spacing(0)
-        
+
         self.__set_statusbar_text('Welcome to aMSN2')
-        
+
         vpaned = gtk.VPaned()
         vpaned.pack1(self.middle_box, True, True)
         vpaned.pack2(bottom_box, False, True)
-        
+
         self.pack_start(self.chatheader, False, False, self.padding)
         self.pack_start(vpaned, True, True, self.padding)
         self.pack_start(self.statusbar, False, False)
-        
+
         #Connections
         #========
-        '''        
+        '''
         self.entrytextview.connect('focus-in-event', self.chatman.setUrgencyHint, False)
         self.entrytextview.get_buffer().connect(&quot;changed&quot;,self.__updateTextFormat)
         self.textview.connect(&quot;button-press-event&quot;, self.__rightClick)
-        
+
         '''
         '''
         self.textview.connect(&quot;url-clicked&quot;, self.__on_url_clicked)
-        
+
         self.button1.connect(&quot;clicked&quot;, self.__create_smiles_window)
-        self.button3.connect(&quot;clicked&quot;, 
+        self.button3.connect(&quot;clicked&quot;,
             self.__on_changed_text_effect, 'bold')
-        self.button4.connect(&quot;clicked&quot;, 
+        self.button4.connect(&quot;clicked&quot;,
             self.__on_changed_text_effect, 'italic')
-        self.button5.connect(&quot;clicked&quot;, 
+        self.button5.connect(&quot;clicked&quot;,
             self.__on_changed_text_effect, 'underline')
-        self.button6.connect(&quot;clicked&quot;, 
+        self.button6.connect(&quot;clicked&quot;,
             self.__on_changed_text_effect, 'strikethrough')
         self.button7.connect(&quot;clicked&quot;, self.__on_changed_text_color)
         '''
@@ -200,31 +200,31 @@ class aMSNChatWidget(base.aMSNChatWidget, gtk.VBox):
         self.button8.connect(&quot;clicked&quot;, self.__on_clear_textview)
         self.entry.connect('mykeypress', self.__on_chat_send)
         self.entry.connect('key-press-event', self.__on_typing_event)
-        
+
     def __updateTextFormat(self, textbuffer):
         self.reapply_text_effects();
         self.__on_changed_text_color(self.button_color)
         self.__on_changed_text_font(self.button_font)
-        
+
     def __on_changed_text_effect(self, button, tag_type):
         buffer = self.entry.get_buffer();
         if button.get_active():
             buffer.apply_tag_by_name(tag_type, buffer.get_start_iter(), buffer.get_end_iter())
         else:
             buffer.remove_tag_by_name(tag_type, buffer.get_start_iter(), buffer.get_end_iter())
-    
+
     def reapply_text_effects(self):
         self.__on_changed_text_effect(self.button_bold, &quot;bold&quot;)
         self.__on_changed_text_effect(self.button_italic, &quot;italic&quot;)
         self.__on_changed_text_effect(self.button_underline, &quot;underline&quot;)
         self.__on_changed_text_effect(self.button_strikethrough, &quot;strikethrough&quot;)
-            
+
     def __on_changed_text_color(self, button):
         buffer = self.entry.get_buffer();
         tag = buffer.get_tag_table().lookup(&quot;foreground&quot;)
         tag.set_property(&quot;foreground_gdk&quot;, button.get_color())
         buffer.apply_tag_by_name(&quot;foreground&quot;, buffer.get_start_iter(), buffer.get_end_iter())
-        
+
     def __on_changed_text_font(self, button):
         buffer = self.entry.get_buffer();
         font_name = self.button_font.get_font_name()
@@ -232,10 +232,10 @@ class aMSNChatWidget(base.aMSNChatWidget, gtk.VBox):
         tag = buffer.get_tag_table().lookup(&quot;family&quot;)
         tag.set_property(&quot;family&quot;, font_family)
         buffer.apply_tag_by_name(&quot;family&quot;, buffer.get_start_iter(), buffer.get_end_iter())
-        
+
     def __clean_string(self, str):
         return cgi.escape(str)
-        
+
     def __on_chat_send(self, entry, event_keyval, event_keymod):
         if (event_keyval == gtk.keysyms.Return):
             buffer = entry.get_buffer()
@@ -244,63 +244,66 @@ class aMSNChatWidget(base.aMSNChatWidget, gtk.VBox):
             entry.clear()
             entry.grab_focus()
             if (msg == ''): return False
-        
-        color = self.button_color.get_color()
-        hex8 = &quot;%.2x%.2x%.2x&quot; % ((color.red/0x101), (color.green/0x101), (color.blue/0x101))
-        style = pymsn.TextFormat.NO_EFFECT
-        if self.button_bold.get_active(): style |= pymsn.TextFormat.BOLD
-        if self.button_italic.get_active():  style |= pymsn.TextFormat.ITALIC
-        if self.button_underline.get_active(): style |= pymsn.TextFormat.UNDERLINE
-        if self.button_strikethrough.get_active(): style |= pymsn.TextFormat.STRIKETHROUGH
-        font_name = self.button_font.get_font_name()
-        font_family = pango.FontDescription(font_name).get_family()
-        format = pymsn.TextFormat(font=font_family, color=hex8, style=style)
-        strv = StringView()
-        strv.appendText(msg)
-        self._amsn_conversation.sendMessage(strv, format)
-        
+
+            color = self.button_color.get_color()
+            hex8 = &quot;%.2x%.2x%.2x&quot; % ((color.red/0x101), (color.green/0x101), (color.blue/0x101))
+            style = papyon.TextFormat.NO_EFFECT
+            if self.button_bold.get_active(): style |= papyon.TextFormat.BOLD
+            if self.button_italic.get_active():  style |= papyon.TextFormat.ITALIC
+            if self.button_underline.get_active(): style |= papyon.TextFormat.UNDERLINE
+            if self.button_strikethrough.get_active(): style |= papyon.TextFormat.STRIKETHROUGH
+            font_name = self.button_font.get_font_name()
+            font_family = pango.FontDescription(font_name).get_family()
+            format = papyon.TextFormat(font=font_family, color=hex8, style=style)
+            strv = StringView()
+            strv.appendText(msg)
+            self._amsn_conversation.sendMessage(strv, format)
+
+        elif event_keyval == gtk.keysyms.Escape:
+            self._parent.destroy()
+
     def __on_clear_textview(self, widget):
         buffer = self.textview.get_buffer()
         start = buffer.get_start_iter()
         end = buffer.get_end_iter()
         buffer.delete(start, end)
-        
+
     def __on_typing_event(self, widget, event):
         self._amsn_conversation.sendTypingNotification()
-        
+
     def __on_nudge_send(self, widget):
         self.__print_info('Nudge sent')
         self._amsn_conversation.sendNudge()
-    
+
     def __print_chat(self, nick, msg, sender):
         html = '&lt;div&gt;'
         if (self.last_sender != sender):
-            html += '&lt;span style=&quot;%s&quot;&gt;%s&lt;/span&gt;&lt;br/&gt;' % (self.nickstyle, 
+            html += '&lt;span style=&quot;%s&quot;&gt;%s&lt;/span&gt;&lt;br/&gt;' % (self.nickstyle,
                 nick)
         html += '&lt;span style=&quot;%s&quot;&gt;[%s] %s&lt;/span&gt;&lt;/div&gt;' % (self.msgstyle,
             time.strftime('%X'), msg)
-        
+
         self.textview.display_html(html)
         self.textview.scroll_to_bottom()
-        
+
     def __print_info(self, msg):
         html = '&lt;div&gt;&lt;span style=&quot;%s&quot;&gt;%s&lt;/span&gt;&lt;/div&gt;' % (self.infostyle, msg)
         self.textview.display_html(html)
         self.textview.scroll_to_bottom()
-        
+
     def __set_statusbar_text(self, msg):
         context = self.statusbar.get_context_id('msg')
         self.statusbar.pop(context)
         self.statusbar.push(context, msg)
-        
+
     def onMessageReceived(self, messageview, formatting=None):
         text = messageview.toStringView().toHtmlString()
         text = self.__clean_string(text)
         nick, msg = text.split('\n', 1)
         nick = str(nick.replace('\n', '&lt;br/&gt;'))
         msg = str(msg.replace('\n', '&lt;br/&gt;'))
-        sender = messageview.sender.toString()
-        
+        sender = str(messageview.sender)
+
         # peacey: Check formatting of styles and perform the required changes
         if formatting:
             fmsg = '''&lt;span style=&quot;'''
@@ -308,27 +311,27 @@ class aMSNChatWidget(base.aMSNChatWidget, gtk.VBox):
                 fmsg += &quot;font-family: %s;&quot; % formatting.font
             if formatting.color:
                 fmsg += &quot;color: %s;&quot; % (&quot;#&quot;+formatting.color)
-            if formatting.style &amp; pymsn.TextFormat.BOLD == pymsn.TextFormat.BOLD:
+            if formatting.style &amp; papyon.TextFormat.BOLD == papyon.TextFormat.BOLD:
                 fmsg += &quot;font-weight: bold;&quot;
-            if formatting.style &amp; pymsn.TextFormat.ITALIC == pymsn.TextFormat.ITALIC:
+            if formatting.style &amp; papyon.TextFormat.ITALIC == papyon.TextFormat.ITALIC:
                 fmsg += &quot;font-style: italic;&quot;
-            if formatting.style &amp; pymsn.TextFormat.UNDERLINE == pymsn.TextFormat.UNDERLINE:
+            if formatting.style &amp; papyon.TextFormat.UNDERLINE == papyon.TextFormat.UNDERLINE:
                 fmsg += &quot;text-decoration: underline;&quot;
-            if formatting.style &amp; pymsn.TextFormat.STRIKETHROUGH == pymsn.TextFormat.STRIKETHROUGH:
+            if formatting.style &amp; papyon.TextFormat.STRIKETHROUGH == papyon.TextFormat.STRIKETHROUGH:
                 fmsg += &quot;text-decoration: line-through;&quot;
             if formatting.right_alignment:
-                fmsg += &quot;text-align: right;&quot;    
+                fmsg += &quot;text-align: right;&quot;
             fmsg = fmsg.rstrip(&quot;;&quot;)
             fmsg += '''&quot;&gt;'''
             fmsg += msg
             fmsg += &quot;&lt;/span&gt;&quot;
         else:
             fmsg = msg
-                
+
         self.__print_chat(nick, fmsg, sender)
-        
+
         self.last_sender = sender
-        
+
     def onUserJoined(self, contact):
         print &quot;%s joined the conversation&quot; % (contact,)
         self.__print_info(&quot;%s joined the conversation&quot; % (contact,))
@@ -348,41 +351,41 @@ class aMSNChatWidget(base.aMSNChatWidget, gtk.VBox):
 class aMSNChatHeader(gtk.EventBox):
     def __init__(self, cview=None):
         gtk.EventBox.__init__(self)
-        
+
         self.buddy_icon = gtk.Image()
         self.title = gtk.Label()
         self.dp = gtk.Image()
         self.title_color = gtk.gdk.color_parse('#dadada')
         self.psm_color = '#999999'
-        
+
         self.title.set_use_markup(True)
         self.title.set_justify(gtk.JUSTIFY_LEFT)
         self.title.set_ellipsize(pango.ELLIPSIZE_END)
         self.title.set_alignment(xalign=0, yalign=0.5)
         self.title.set_padding(xpad=2, ypad=2)
-        
+
         self.dp.set_size_request(50,50)
-        
+
         hbox = gtk.HBox(False,0)
         hbox.pack_start(self.buddy_icon, False,False,0)
         hbox.pack_start(self.title, True,True,0)
         hbox.pack_start(self.dp, False,False,0)
-        
+
         self.modify_bg(gtk.STATE_NORMAL, self.title_color)
         self.add(hbox)
-        
+
         self.update(cview)
-        
+
     def update(self, cview):
         if cview is None:
             nickname = 'Me'
             psm = 'Testing aMSN'
-        
+
         title = '&lt;span size=&quot;large&quot;&gt;&lt;b&gt;%s&lt;/b&gt;&lt;/span&gt;' % (nickname, )
-        
+
         if(psm != ''): 
-            title += '\n&lt;span size=&quot;small&quot; foreground=&quot;%s&quot;&gt;%s&lt;/span&gt;' % ( 
+            title += '\n&lt;span size=&quot;small&quot; foreground=&quot;%s&quot;&gt;%s&lt;/span&gt;' % (
             self.psm_color, psm)
-        
+
         self.title.set_markup(title)
-        
+</diff>
      <filename>amsn2/gui/front_ends/gtk/chat_window.py</filename>
    </modified>
    <modified>
      <diff>@@ -5,18 +5,18 @@ import gobject, pango
 GUI_FONT = pango.FontDescription('normal 8')
 
 def stringvToHtml(stringv):
-	out = ''
-	for x in stringv._elements:
-		if x.getType() == StringView.TEXT_ELEMENT:
-			out += x.getValue()
-		elif x.getType() == StringView.ITALIC_ELEMENT:
-			if x.getValue():
-				out += '&lt;i&gt;'
-			else:
-				out += '&lt;/i&gt;'
-	return out
+    out = ''
+    for x in stringv._elements:
+        if x.getType() == StringView.TEXT_ELEMENT:
+            out += x.getValue()
+        elif x.getType() == StringView.ITALIC_ELEMENT:
+            if x.getValue():
+                out += '&lt;i&gt;'
+            else:
+                out += '&lt;/i&gt;'
+    return out
 
 def escape_pango(str):
     str = gobject.markup_escape_text(str)
     str = str.replace('\n',' ')
-    return str
\ No newline at end of file
+    return str</diff>
      <filename>amsn2/gui/front_ends/gtk/common.py</filename>
    </modified>
    <modified>
      <diff>@@ -1,21 +1,21 @@
 # -*- coding: utf-8 -*-
 #===================================================
-# 
+#
 # contact_list.py - This file is part of the amsn2 package
 #
 # Copyright (C) 2008  Wil Alvarez &lt;wil_alejandro@yahoo.com&gt;
 #
 # This script is free software; you can redistribute it and/or modify it under
-# the terms of the GNU General Public License as published by the Free Software 
+# the terms of the GNU General Public License as published by the Free Software
 # Foundation; either version 3 of the License, or (at your option) any later
 # version.
 #
-# This script is distributed in the hope that it will be useful, but WITHOUT 
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
-# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License 
+# This script is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 # for more details.
 #
-# You should have received a copy of the GNU General Public License along with 
+# You should have received a copy of the GNU General Public License along with
 # this script (see COPYING); if not, write to the Free Software
 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 #
@@ -27,12 +27,13 @@ import gtk
 import pango
 import gobject
 
-#import pymsn
+#import papyon
 from image import *
 from amsn2.core.views import StringView
 from amsn2.core.views import GroupView
 from amsn2.core.views import ContactView
 from amsn2.core.views import ImageView
+from amsn2.core.views import PersonalInfoView
 from amsn2.gui import base
 
 import common
@@ -42,57 +43,68 @@ class aMSNContactListWindow(base.aMSNContactListWindow, gtk.VBox):
     def __init__(self, amsn_core, parent):
         '''Constructor'''
         gtk.VBox.__init__(self)
-        
+        base.aMSNContactListWindow.__init__(self, amsn_core, parent)
+
         self._amsn_core = amsn_core
         self._main_win = parent
         self._skin = amsn_core._skin_manager.skin
         self._theme_manager = self._amsn_core._theme_manager
-        
+        self._myview = amsn_core._personalinfo_manager._personalinfoview
+
         self._clwidget = aMSNContactListWidget(amsn_core, self)
-        
+
         self.__create_controls()
         self.__create_box()
-        
+
         self._main_win.set_view(self)
-        
+
         self.show_all()
         self.__setup_window()
-        
+
     def __create_controls(self):
         ###self.psmlabel.modify_font(common.GUI_FONT)
         # Main Controls
         self.display = gtk.Image()
         self.display.set_size_request(64,64)
         
+        self.btnDisplay = gtk.Button()
+        self.btnDisplay.set_relief(gtk.RELIEF_NONE)
+        self.btnDisplay.add(self.display)
+        self.btnDisplay.set_alignment(0,0)
+        self.btnDisplay.connect(&quot;clicked&quot;, self.__onDisplayClicked)
+        
         self.nicklabel = gtk.Label()
         self.nicklabel.set_alignment(0, 0)
         self.nicklabel.set_use_markup(True)
         self.nicklabel.set_ellipsize(pango.ELLIPSIZE_END)
         self.nicklabel.set_markup('Loading...')
-        
+
         self.btnNickname = gtk.Button()
         self.btnNickname.set_relief(gtk.RELIEF_NONE)
         self.btnNickname.add(self.nicklabel)
         self.btnNickname.set_alignment(0,0)
-        
-        self.psm = gtk.Entry()
-        
+        self.btnNickname.connect(&quot;clicked&quot;,self.__on_btnNicknameClicked)
+
         self.psmlabel = gtk.Label()
+        self.psmlabel.set_alignment(0, 0)
         self.psmlabel.set_use_markup(True)
         self.psmlabel.set_ellipsize(pango.ELLIPSIZE_END)
         self.psmlabel.set_markup('&lt;i&gt;&amp;lt;Personal message&amp;gt;&lt;/i&gt;')
-        
+
         self.btnPsm = gtk.Button()
         self.btnPsm.add(self.psmlabel)
         self.btnPsm.set_relief(gtk.RELIEF_NONE)
         self.btnPsm.set_alignment(0,0)
-        
+        self.btnPsm.connect(&quot;clicked&quot;, self.__on_btnPsmClicked)
+
         # status list
+        self.status_values = {}
         status_list = gtk.ListStore(gtk.gdk.Pixbuf, str, str)
         for key in self._amsn_core.p2s:
             name = self._amsn_core.p2s[key]
+            self.status_values[name] = self._amsn_core.p2s.values().index(name)
             _, path = self._theme_manager.get_statusicon(&quot;buddy_%s&quot; % name)
-            if (name == 'offline'): continue
+            #if (name == 'offline'): continue
             #iv = ImageView(&quot;Skin&quot;, &quot;buddy_%s&quot; % name)
             #img = Image(self._skin, iv)
             #icon = img.to_pixbuf(28)
@@ -100,12 +112,12 @@ class aMSNContactListWindow(base.aMSNContactListWindow, gtk.VBox):
             status_list.append([icon, name, key])
             del icon
             gc.collect()
-        
+
         iconCell = gtk.CellRendererPixbuf()
         iconCell.set_property('xalign', 0.0)
         txtCell = gtk.CellRendererText()
         txtCell.set_property('xalign', 0.0)
-        
+
         self.status = gtk.ComboBox()
         self.status.set_model(status_list)
         self.status.set_active(0)
@@ -113,10 +125,11 @@ class aMSNContactListWindow(base.aMSNContactListWindow, gtk.VBox):
         self.status.pack_start(txtCell, False)
         self.status.add_attribute(iconCell, 'pixbuf',0)
         self.status.add_attribute(txtCell, 'markup',1)
-        
+        self.status.connect('changed', self.onStatusChanged)
+
     def __create_box(self):
         frameDisplay = gtk.Frame()
-        frameDisplay.add(self.display)
+        frameDisplay.add(self.btnDisplay)
         self.evdisplay = gtk.EventBox()
         self.evdisplay.add(frameDisplay)
 
@@ -129,7 +142,6 @@ class aMSNContactListWindow(base.aMSNContactListWindow, gtk.VBox):
 
         boxPsm = gtk.HBox(False, 0)
         boxPsm.pack_start(self.btnPsm, True, True)
-        boxPsm.pack_start(self.psm, True, True)
 
         headerRight = gtk.VBox(False, 0)
         headerRight.pack_start(boxNick, False, False)
@@ -139,98 +151,203 @@ class aMSNContactListWindow(base.aMSNContactListWindow, gtk.VBox):
         header = gtk.HBox(False, 1)
         header.pack_start(headerLeft, False, False, 0)
         header.pack_start(headerRight, True, True, 0)
-        
+
         scrollwindow = gtk.ScrolledWindow()
         scrollwindow.set_shadow_type(gtk.SHADOW_ETCHED_IN)
         scrollwindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)	
         scrollwindow.add(self._clwidget)
-        
+
         bottom = gtk.HBox(False, 0)
         bottom.pack_start(self.status, True, True, 0)
-        
+
         self.pack_start(header, False, False, 2)
         self.pack_start(scrollwindow, True, True, 2)
         self.pack_start(bottom, False, False, 2)
-        
+
     def __setup_window(self):
-        self.psm.hide()
-        self.btnPsm.show()
-        
         _, filename = self._theme_manager.get_dp('dp_nopic')
         pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(filename, 64, 64)
         self.display.set_from_pixbuf(pixbuf)
         del pixbuf
         gc.collect()
-        
+
 
     def show(self):
-        pass 
+        pass
 
     def hide(self):
-        pass 
-        
+        pass
+
     def setTitle(self, text):
         self._main_win.set_title(text)
-    
+
     def setMenu(self, menu):
         &quot;&quot;&quot; This will allow the core to change the current window's main menu
-        @menu : a MenuView
+        @type menu: MenuView
         &quot;&quot;&quot;
         pass
 
     def myInfoUpdated(self, view):
         &quot;&quot;&quot; This will allow the core to change pieces of information about
         ourself, such as DP, nick, psm, the current media being played,...
-        @view: the contactView of the ourself (contains DP, nick, psm,
-        currentMedia,...)&quot;&quot;&quot;
-        print view.name.toString()
+        @type view: PersonalInfoView
+        @param view: ourself (contains DP, nick, psm, currentMedia,...)
+        &quot;&quot;&quot;
+        # TODO: image, ...
+        self._myview = view
+        nk = view.nick
+        self.nicklabel.set_markup(str(nk))
+        psm = view.psm
+        cm = view.current_media
+        message = str(psm)+' '+str(cm)
+        self.psmlabel.set_markup('&lt;i&gt;'+message+'&lt;/i&gt;')
+        self.status.set_active(self.status_values[view.presence])
+
+    def onStatusChanged(self, combobox):
+        status = combobox.get_active()
+        for key in self.status_values:
+            if self.status_values[key] == status:
+                break
+        # FIXME: changing status to 'offline' will disconnect, so return to login window
+        # also fix papyon, gives an error on setting 'offline'
+        if key != self._myview.presence:
+            self._myview.presence = key
+
+    def __on_btnNicknameClicked(self, source):
+        self.__switchToInput(source)
+
+    def __on_btnPsmClicked(self, source):
+        self.__switchToInput(source)
+        
+    def __switchToInput(self, source):
+        &quot;&quot;&quot; Switches the nick and psm buttons into a text area for editing them.&quot;&quot;&quot;
+        #label = self.btnNickname.get_child()
+        source.remove(source.get_child())
+        entry = gtk.Entry()
+
+        if source is self.btnNickname:
+            entry.set_text(str(self._myview.nick))
+        elif source is self.btnPsm:
+            entry.set_text(str(self._myview.psm))
+
+        source.add(entry)
+        entry.show()
+        entry.grab_focus()
+        source.set_relief(gtk.RELIEF_NORMAL) # Add cool elevated effect
+        entry.connect(&quot;activate&quot;, self.__switchFromInput, True)
+        entry.connect(&quot;key-press-event&quot;, self.__handleInput)
+        self.focusOutId = entry.connect(&quot;focus-out-event&quot;, self.__handleInput)
+        
+    def __handleInput(self, source, event):
+        &quot;&quot;&quot; Handle various inputs from the nicknameEntry-box &quot;&quot;&quot;
+        if(event.type == gtk.gdk.FOCUS_CHANGE): #user clicked outside textfield
+            self.__switchFromInput(source, True)
+        elif (event.type == gtk.gdk.KEY_PRESS): #user wrote something, esc perhaps?
+            if event.keyval == gtk.keysyms.Escape:
+                self.__switchFromInput(source, False)
+
+    def __switchFromInput(self, source, isNew):
+        &quot;&quot;&quot; When in the editing state of nickname and psm, change back
+        to the uneditable label state.
+        &quot;&quot;&quot;
+        if(isNew):
+            if source is self.btnNickname.get_child():
+                newText = source.get_text()
+                strv = StringView()
+                strv.appendText(newText)
+                self._myview.nick = strv
+            elif source is self.btnPsm.get_child():
+                newText = source.get_text()
+                strv = StringView()
+                strv.appendText(newText)
+                self._myview.psm = strv
+        else:
+            if source is self.btnNickname.get_child(): # User discards input
+                newText = self.nicklabel.get_text() # Old nickname
+            elif source is self.btnPsm.get_child():
+                newText = self.psmlabel.get_text()
+
+        parentWidget = source.get_parent()
+        currWidget = parentWidget.get_child()
+        currWidget.disconnect(self.focusOutId) # Else we trigger focus-out-event; segfault.
+
+        parentWidget.remove(currWidget)
+        entry = gtk.Label()
+        entry.set_markup(newText)
+
+        parentWidget.add(entry)
+        entry.show()
+        parentWidget.set_relief(gtk.RELIEF_NONE) # remove cool elevated effect
+        
+    def __onDisplayClicked(self, source):
+        print &quot;Display clicked!&quot;
+        chooser = gtk.FileChooserDialog(title=None,action=gtk.FILE_CHOOSER_ACTION_OPEN,
+                    buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OPEN,gtk.RESPONSE_OK))
+        
+        chooser.set_default_response(gtk.RESPONSE_OK)
+        
+        filter = gtk.FileFilter()
+        filter.set_name(&quot;All files&quot;)
+        filter.add_pattern(&quot;*&quot;)
+        chooser.add_filter(filter)
+
+        response = chooser.run()
+        if(response == gtk.RESPONSE_OK):
+            pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(chooser.get_filename(), 64, 64)
+            self.display.set_from_pixbuf(pixbuf)
+            del pixbuf
+            gc.collect()
+        elif (response == gtk.RESPONSE_CANCEL):
+            pass
+        chooser.destroy()
+
 
 class aMSNContactListWidget(base.aMSNContactListWidget, gtk.TreeView):
     def __init__(self, amsn_core, parent):
         &quot;&quot;&quot;Constructor&quot;&quot;&quot;
         base.aMSNContactListWidget.__init__(self, amsn_core, parent)
         gtk.TreeView.__init__(self)
-        
+
         self._amsn_core = amsn_core
         self._cwin = parent
         self.groups = []
         self.contacts = {}
-        
+
         nick = gtk.CellRendererText()
         nick.set_property('ellipsize-set',True)
         nick.set_property('ellipsize', pango.ELLIPSIZE_END)
         pix = gtk.CellRendererPixbuf()
-        
+
         column = gtk.TreeViewColumn()
         column.set_expand(True)
         column.set_alignment(0.0)
         column.pack_start(pix, False)
         column.pack_start(nick, True)
-        
+
         #column.add_attribute(pix, 'pixbuf', 0)
         column.set_attributes(pix, pixbuf=0, visible=4)
         column.add_attribute(nick, 'markup', 2)
-        
+
         exp_column = gtk.TreeViewColumn()
-        exp_column.set_max_width(16)       
-        
+        exp_column.set_max_width(16)
+
         self.append_column(exp_column)
         self.append_column(column)
         self.set_expander_column(exp_column)
-        
+
         self.set_search_column(2)
         self.set_headers_visible(False)
         self.set_level_indentation(0)
-        
-        # the image (None for groups) the object (group or contact) and 
+
+        # the image (None for groups) the object (group or contact) and
         # the string to display
         self._model = gtk.TreeStore(gtk.gdk.Pixbuf, object, str, str, bool)
         self.model = self._model.filter_new(root=None)
         #self.model.set_visible_func(self._visible_func)
-        
+
         self.set_model(self.model)
         self.connect(&quot;row-activated&quot;, self.__on_contact_dblclick)
-        
+
     def __on_contact_dblclick(self, widget, path, column):
         model, row = widget.get_selection().get_selected()
         if (row is None): return False
@@ -238,10 +355,10 @@ class aMSNContactListWidget(base.aMSNContactListWidget, gtk.TreeView):
 
         contactview = model.get_value(row, 1)
         contactview.on_click(contactview.uid)
-        
+
     def __search_by_id(self, id):
         parent = self._model.get_iter_first()
-        
+
         while (parent is not None):
             obj = self._model.get_value(parent, 3)
             if (obj == id): return parent
@@ -251,9 +368,9 @@ class aMSNContactListWidget(base.aMSNContactListWidget, gtk.TreeView):
                 if (cobj == id): return child
                 child = self._model.iter_next(child)
             parent = self._model.iter_next(parent)
-            
+
         return None
-        
+
     def show(self):
         pass
 
@@ -263,64 +380,66 @@ class aMSNContactListWidget(base.aMSNContactListWidget, gtk.TreeView):
     def contactListUpdated(self, clview):
         guids = self.groups
         self.groups = []
-        
+
         # New groups
         for gid in clview.group_ids:
             if (gid == 0): gid = '0'
             if gid not in guids:
                 self.groups.append(gid)
                 self._model.append(None, [None, None, gid, gid, False])
-                
+
         # Remove unused groups
         for gid in guids:
             if gid not in self.groups:
                 giter = self.__search_by_id(gid)
                 self._model.remove(giter)
                 self.groups.remove(gid)
-        
+
     def groupUpdated(self, groupview):
         if (groupview.uid == 0): groupview.uid = '0'
         if groupview.uid not in self.groups: return
-        
+
         giter = self.__search_by_id(groupview.uid)
         self._model.set_value(giter, 1, groupview)
         self._model.set_value(giter, 2, '&lt;b&gt;%s&lt;/b&gt;' % common.escape_pango(
-            groupview.name.toString()))
-        
+            str(groupview.name)))
+
         try:
             cuids = self.contacts[groupview.uid]
         except:
             cuids = []
         self.contacts[groupview.uid] = []
-        
+
         for cid in groupview.contact_ids:
             if cid not in cuids:
                 giter = self.__search_by_id(groupview.uid)
                 self.contacts[groupview.uid].append(cid)
                 self._model.append(giter, [None, None, cid, cid, True])
-        
+
         # Remove unused contacts
         for cid in cuids:
             if cid not in self.contacts[groupview.uid]:
                 citer = self.__search_by_id(cid)
                 self._model.remove(citer)
                 self.contacts[groupview.uid].remove(cid)
-        
+
 
     def contactUpdated(self, contactview):
+        &quot;&quot;&quot;
+        @type contactview: ContactView
+        &quot;&quot;&quot;
+
         citer = self.__search_by_id(contactview.uid)
         if citer is None: return
-        
-        # TODO: Verify if DP exist
-        #img = Image(self._cwin._theme_manager, contactview.dp)
-        #dp = img.to_pixbuf(28, 28)
-        img = Image(self._cwin._theme_manager, contactview.icon)
+
+        img = Image(self._cwin._theme_manager, contactview.dp)
+        #img = Image(self._cwin._theme_manager, contactview.icon)
         dp = img.to_pixbuf(28, 28)
-        
+
         self._model.set_value(citer, 0, dp)
         self._model.set_value(citer, 1, contactview)
         self._model.set_value(citer, 2, common.escape_pango(
-            contactview.name.toString()))
+            str(contactview.name)))
         del dp
         gc.collect()
-        
+</diff>
      <filename>amsn2/gui/front_ends/gtk/contact_list.py</filename>
    </modified>
    <modified>
      <diff>@@ -5,217 +5,217 @@
 import gtk
 import gobject
 
-# This not ideal. It would be better to subclass gtk.ToolButton, however 
-# the python bindings do not seem to be powerfull enough for that. 
-# (As we need to change a variable in the class structure.) 
+# This not ideal. It would be better to subclass gtk.ToolButton, however
+# the python bindings do not seem to be powerfull enough for that.
+# (As we need to change a variable in the class structure.)
 class ColorToolButton(gtk.ToolItem):
-    __gtype_name__ = 'ColorToolButton'  
-    __gsignals__ = { 'color-set' : (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,  tuple())} 
+    __gtype_name__ = 'ColorToolButton'
+    __gsignals__ = { 'color-set' : (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,  tuple())}
 
     def __init__(self, icon_name='color-preview', **kwargs):
-        self._accelerator = None  
-        self._tooltip = None  
-        #self._palette_invoker = ToolInvoker()  
-        self._palette = None   
-        gobject.GObject.__init__(self, **kwargs)   
-        # The gtk.ToolButton has already added a normal button.  
-        # Replace it with a ColorButton  
-        color_button = gtk.ColorButton()  
-        self.add(color_button)   
+        self._accelerator = None
+        self._tooltip = None
+        #self._palette_invoker = ToolInvoker()
+        self._palette = None
+        gobject.GObject.__init__(self, **kwargs)
+        # The gtk.ToolButton has already added a normal button.
+        # Replace it with a ColorButton
+        color_button = gtk.ColorButton()
+        self.add(color_button)
         # The following is so that the behaviour on the toolbar is correct.
-        color_button.set_relief(gtk.RELIEF_NONE)  
-        color_button.icon_size = gtk.ICON_SIZE_LARGE_TOOLBAR   
-        #self._palette_invoker.attach_tool(self)   
-        # This widget just proxies the following properties to the colorbutton  
-        color_button.connect('notify::color', self.__notify_change)  
-        color_button.connect('notify::icon-name', self.__notify_change)  
-        color_button.connect('notify::icon-size', self.__notify_change)  
-        color_button.connect('notify::title', self.__notify_change)  
-        color_button.connect('color-set', self.__color_set_cb)  
+        color_button.set_relief(gtk.RELIEF_NONE)
+        color_button.icon_size = gtk.ICON_SIZE_LARGE_TOOLBAR
+        #self._palette_invoker.attach_tool(self)
+        # This widget just proxies the following properties to the colorbutton
+        color_button.connect('notify::color', self.__notify_change)
+        color_button.connect('notify::icon-name', self.__notify_change)
+        color_button.connect('notify::icon-size', self.__notify_change)
+        color_button.connect('notify::title', self.__notify_change)
+        color_button.connect('color-set', self.__color_set_cb)
         color_button.connect('can-activate-accel',  self.__button_can_activate_accel_cb)
 
     def __button_can_activate_accel_cb(self, button, signal_id):
-        # Accept activation via accelerators regardless of this widget's state  
+        # Accept activation via accelerators regardless of this widget's state
         return True
 
     def set_accelerator(self, accelerator):
-        self._accelerator = accelerator  
+        self._accelerator = accelerator
         setup_accelerator(self)
 
     def get_accelerator(self):
         return self._accelerator
-    
-    accelerator = gobject.property(type=str, setter=set_accelerator,  getter=get_accelerator) 
-    
+
+    accelerator = gobject.property(type=str, setter=set_accelerator,  getter=get_accelerator)
+
     def create_palette(self):
-        self._palette = self.get_child().create_palette()  
+        self._palette = self.get_child().create_palette()
         return self._palette
 
     #def get_palette_invoker(self):
      #   return self._palette_invoker
 
     #def set_palette_invoker(self, palette_invoker):
-      #  self._palette_invoker.detach()  
+      #  self._palette_invoker.detach()
      #   self._palette_invoker = palette_invoker
-    #palette_invoker = gobject.property(  type=object, setter=set_palette_invoker, getter=get_palette_invoker) 
-    
+    #palette_invoker = gobject.property(  type=object, setter=set_palette_invoker, getter=get_palette_invoker)
+
     def set_color(self, color):
         self.get_child().props.color = color
 
     def get_color(self):
         return self.get_child().props.color
-    
-    color = gobject.property(type=object, getter=get_color, setter=set_color) 
-    
+
+    color = gobject.property(type=object, getter=get_color, setter=set_color)
+
     def set_icon_name(self, icon_name):
         self.get_child().props.icon_name = icon_name
 
     def get_icon_name(self):
         return self.get_child().props.icon_name
-    
-    icon_name = gobject.property(type=str,  getter=get_icon_name, setter=set_icon_name) 
-    
+
+    icon_name = gobject.property(type=str,  getter=get_icon_name, setter=set_icon_name)
+
     def set_icon_size(self, icon_size):
         self.get_child().props.icon_size = icon_size
 
     def get_icon_size(self):
         return self.get_child().props.icon_size
-    
-    icon_size = gobject.property(type=int,  getter=get_icon_size, setter=set_icon_size) 
-    
+
+    icon_size = gobject.property(type=int,  getter=get_icon_size, setter=set_icon_size)
+
     def set_title(self, title):
         self.get_child().props.title = title
 
     def get_title(self):
         return self.get_child().props.title
-    
-    title = gobject.property(type=str, getter=get_title, setter=set_title) 
-    
+
+    title = gobject.property(type=str, getter=get_title, setter=set_title)
+
     def do_expose_event(self, event):
-        child = self.get_child()  
-        allocation = self.get_allocation()  
-        if self._palette and self._palette.is_up():  
-            invoker = self._palette.props.invoker  
-            invoker.draw_rectangle(event, self._palette)  
-        elif child.state == gtk.STATE_PRELIGHT:  
-            child.style.paint_box(event.window, gtk.STATE_PRELIGHT,  gtk.SHADOW_NONE, event.area,  child, 'toolbutton-prelight',  allocation.x, allocation.y,  allocation.width, allocation.height)   
-        
+        child = self.get_child()
+        allocation = self.get_allocation()
+        if self._palette and self._palette.is_up():
+            invoker = self._palette.props.invoker
+            invoker.draw_rectangle(event, self._palette)
+        elif child.state == gtk.STATE_PRELIGHT:
+            child.style.paint_box(event.window, gtk.STATE_PRELIGHT,  gtk.SHADOW_NONE, event.area,  child, 'toolbutton-prelight',  allocation.x, allocation.y,  allocation.width, allocation.height)
+
         gtk.ToolButton.do_expose_event(self, event)
 
     def __notify_change(self, widget, pspec):
         self.notify(pspec.name)
 
     def __color_set_cb(self, widget):
-        self.emit('color-set') 
+        self.emit('color-set')
 
 class FontToolButton(gtk.ToolItem):
-    __gtype_name__ = 'FontToolButton'  
-    __gsignals__ = { 'font-set' : (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,  tuple())} 
-    
+    __gtype_name__ = 'FontToolButton'
+    __gsignals__ = { 'font-set' : (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,  tuple())}
+
     def __init__(self, icon_name='font-preview', **kwargs):
-        self._accelerator = None  
-        self._tooltip = None  
-        #self._palette_invoker = ToolInvoker()  
-        self._palette = None   
-        gobject.GObject.__init__(self, **kwargs)   
-        # The gtk.ToolButton has already added a normal button.  
-        # Replace it with a ColorButton  
-        font_button = gtk.FontButton()  
-        self.add(font_button)   
+        self._accelerator = None
+        self._tooltip = None
+        #self._palette_invoker = ToolInvoker()
+        self._palette = None
+        gobject.GObject.__init__(self, **kwargs)
+        # The gtk.ToolButton has already added a normal button.
+        # Replace it with a ColorButton
+        font_button = gtk.FontButton()
+        self.add(font_button)
         # The following is so that the behaviour on the toolbar is correct.
-        font_button.set_relief(gtk.RELIEF_NONE)  
-        font_button.icon_size = gtk.ICON_SIZE_LARGE_TOOLBAR   
-        #self._palette_invoker.attach_tool(self)   
-        # This widget just proxies the following properties to the colorbutton  
+        font_button.set_relief(gtk.RELIEF_NONE)
+        font_button.icon_size = gtk.ICON_SIZE_LARGE_TOOLBAR
+        #self._palette_invoker.attach_tool(self)
+        # This widget just proxies the following properties to the colorbutton
         font_button.connect('notify::font-name', self.__notify_change)
-        font_button.connect('notify::show-style', self.__notify_change)  
-        font_button.connect('notify::show-size', self.__notify_change)  
-        font_button.connect('notify::icon-name', self.__notify_change)  
-        font_button.connect('notify::icon-size', self.__notify_change)  
-        font_button.connect('notify::title', self.__notify_change)  
-        font_button.connect('font-set', self.__font_set_cb)  
+        font_button.connect('notify::show-style', self.__notify_change)
+        font_button.connect('notify::show-size', self.__notify_change)
+        font_button.connect('notify::icon-name', self.__notify_change)
+        font_button.connect('notify::icon-size', self.__notify_change)
+        font_button.connect('notify::title', self.__notify_change)
+        font_button.connect('font-set', self.__font_set_cb)
         font_button.connect('can-activate-accel',  self.__button_can_activate_accel_cb)
 
     def __button_can_activate_accel_cb(self, button, signal_id):
-        # Accept activation via accelerators regardless of this widget's state  
+        # Accept activation via accelerators regardless of this widget's state
         return True
 
     def set_accelerator(self, accelerator):
-        self._accelerator = accelerator  
+        self._accelerator = accelerator
         setup_accelerator(self)
 
     def get_accelerator(self):
         return self._accelerator
-    
-    accelerator = gobject.property(type=str, setter=set_accelerator,  getter=get_accelerator) 
-    
+
+    accelerator = gobject.property(type=str, setter=set_accelerator,  getter=get_accelerator)
+
     def create_palette(self):
-        self._palette = self.get_child().create_palette()  
+        self._palette = self.get_child().create_palette()
         return self._palette
-        
+
     def set_font_name(self, font_name):
         self.get_child().props.font_name = font_name
 
     def get_font_name(self):
         return self.get_child().props.font_name
-    
-    font_name = gobject.property(type=object, getter=get_font_name, setter=set_font_name) 
-    
+
+    font_name = gobject.property(type=object, getter=get_font_name, setter=set_font_name)
+
     def set_show_size(self, show_size):
         self.get_child().props.show_size = show_size
 
     def get_show_size(self):
         return self.get_child().props.show_size
-    
-    show_size = gobject.property(type=object, getter=get_show_size, setter=set_show_size) 
-    
+
+    show_size = gobject.property(type=object, getter=get_show_size, setter=set_show_size)
+
     def set_show_style(self, show_style):
         self.get_child().props.show_style = show_style
 
     def get_show_style(self):
         return self.get_child().props.show_style
-    
-    show_style = gobject.property(type=object, getter=get_show_style, setter=set_show_style) 
-    
-    
+
+    show_style = gobject.property(type=object, getter=get_show_style, setter=set_show_style)
+
+
     def set_icon_name(self, icon_name):
         self.get_child().props.icon_name = icon_name
 
     def get_icon_name(self):
         return self.get_child().props.icon_name
-    
-    icon_name = gobject.property(type=str,  getter=get_icon_name, setter=set_icon_name) 
-    
+
+    icon_name = gobject.property(type=str,  getter=get_icon_name, setter=set_icon_name)
+
     def set_icon_size(self, icon_size):
         self.get_child().props.icon_size = icon_size
 
     def get_icon_size(self):
         return self.get_child().props.icon_size
-    
-    icon_size = gobject.property(type=int,  getter=get_icon_size, setter=set_icon_size) 
-    
+
+    icon_size = gobject.property(type=int,  getter=get_icon_size, setter=set_icon_size)
+
     def set_title(self, title):
         self.get_child().props.title = title
 
     def get_title(self):
         return self.get_child().props.title
-    
-    title = gobject.property(type=str, getter=get_title, setter=set_title) 
-    
+
+    title = gobject.property(type=str, getter=get_title, setter=set_title)
+
     def do_expose_event(self, event):
-        child = self.get_child()  
-        allocation = self.get_allocation()  
-        if self._palette and self._palette.is_up():  
-            invoker = self._palette.props.invoker  
-            invoker.draw_rectangle(event, self._palette)  
-        elif child.state == gtk.STATE_PRELIGHT:  
-            child.style.paint_box(event.window, gtk.STATE_PRELIGHT,  gtk.SHADOW_NONE, event.area,  child, 'toolbutton-prelight',  allocation.x, allocation.y,  allocation.width, allocation.height)   
-        
+        child = self.get_child()
+        allocation = self.get_allocation()
+        if self._palette and self._palette.is_up():
+            invoker = self._palette.props.invoker
+            invoker.draw_rectangle(event, self._palette)
+        elif child.state == gtk.STATE_PRELIGHT:
+            child.style.paint_box(event.window, gtk.STATE_PRELIGHT,  gtk.SHADOW_NONE, event.area,  child, 'toolbutton-prelight',  allocation.x, allocation.y,  allocation.width, allocation.height)
+
         gtk.ToolButton.do_expose_event(self, event)
 
     def __notify_change(self, widget, pspec):
         self.notify(pspec.name)
 
     def __font_set_cb(self, widget):
-        self.emit('font-set') 
-        
+        self.emit('font-set')
+</diff>
      <filename>amsn2/gui/front_ends/gtk/gtk_extras.py</filename>
    </modified>
    <modified>
      <diff>@@ -43,10 +43,10 @@ def _parse_css_color(color):
         return gtk.gdk.Color(r, g, b)
     else:
         return gtk.gdk.color_parse(color)
-    
+
 
 class HtmlHandler(xml.sax.handler.ContentHandler):
-    
+
     def __init__(self, textview, startiter):
         xml.sax.handler.ContentHandler.__init__(self)
         self.textbuf = textview.get_buffer()
@@ -76,9 +76,9 @@ class HtmlHandler(xml.sax.handler.ContentHandler):
             self.iter.get_attributes(attrs)
             self.iter.forward_char()
             return attrs
-        
+
     else:
-        
+
         ## Workaround http://bugzilla.gnome.org/show_bug.cgi?id=317455
         def _get_current_style_attr(self, propname, comb_oper=None):
             tags = [tag for tag in self.styles if tag is not None]
@@ -155,7 +155,7 @@ class HtmlHandler(xml.sax.handler.ContentHandler):
 
         else:
             warnings.warn(&quot;Unable to parse length value '%s'&quot; % value)
-        
+
     def __parse_font_size_cb(length, tag):
         tag.set_property(&quot;size-points&quot;, length/display_resolution)
     __parse_font_size_cb = staticmethod(__parse_font_size_cb)
@@ -200,7 +200,7 @@ class HtmlHandler(xml.sax.handler.ContentHandler):
     def __frac_length_tag_cb(length, tag, propname):
         tag.set_property(propname, length)
     __frac_length_tag_cb = staticmethod(__frac_length_tag_cb)
-        
+
     def _parse_style_margin_left(self, tag, value):
         self._parse_length(value, False, self.__frac_length_tag_cb,
                            tag, &quot;left-margin&quot;)
@@ -245,7 +245,7 @@ class HtmlHandler(xml.sax.handler.ContentHandler):
             warnings.warn(&quot;Invalid text-align:%s requested&quot; % value)
         else:
             tag.set_property(&quot;justification&quot;, align)
-    
+
     def _parse_style_text_decoration(self, tag, value):
         if value == &quot;none&quot;:
             tag.set_property(&quot;underline&quot;, pango.UNDERLINE_NONE)
@@ -268,7 +268,7 @@ class HtmlHandler(xml.sax.handler.ContentHandler):
             warnings.warn(&quot;text-decoration:blink not implemented&quot;)
         else:
             warnings.warn(&quot;text-decoration:%s not implemented&quot; % value)
-        
+
 
     ## build a dictionary mapping styles to methods, for greater speed
     __style_methods = dict()
@@ -315,7 +315,7 @@ class HtmlHandler(xml.sax.handler.ContentHandler):
             self.textbuf.insert_with_tags(self.iter, text, *tags)
         else:
             self.textbuf.insert(self.iter, text)
-    
+
     def _flush_text(self):
         if not self.text: return
         self._insert_text(self.text.replace('\n', ''))
@@ -326,7 +326,7 @@ class HtmlHandler(xml.sax.handler.ContentHandler):
             self.textview.emit(&quot;url-clicked&quot;, href, type_)
             return True
         return False
-        
+
     def characters(self, content):
         if allwhitespace_rx.match(content) is not None:
             return
@@ -351,7 +351,7 @@ class HtmlHandler(xml.sax.handler.ContentHandler):
                 type_ = None
             tag.connect('event', self._anchor_event, attrs['href'], type_)
             tag.is_anchor = True
-        
+
         self._begin_span(style, tag)
 
         if name == 'br':
@@ -451,7 +451,7 @@ class HtmlTextView(gtk.TextView):
     __gsignals__ = {
         'url-clicked': (gobject.SIGNAL_RUN_LAST, None, (str, str)), # href, type
     }
-    
+
     def __init__(self):
         gtk.TextView.__init__(self)
         self.set_wrap_mode(gtk.WRAP_CHAR)
@@ -472,7 +472,7 @@ class HtmlTextView(gtk.TextView):
             window = widget.get_window(gtk.TEXT_WINDOW_TEXT)
             window.set_cursor(gtk.gdk.Cursor(gtk.gdk.XTERM))
             self._changed_cursor = False
-    
+
     def __motion_notify_event(self, widget, event):
         x, y, _ = widget.window.get_pointer()
         x, y = widget.window_to_buffer_coords(gtk.TEXT_WINDOW_TEXT, x, y)
@@ -501,10 +501,10 @@ class HtmlTextView(gtk.TextView):
         # parser.setFeature(xml.sax.handler.feature_validation, True)
         parser.setContentHandler(HtmlHandler(self, eob))
         parser.parse(StringIO(html))
-        
+
         if not eob.starts_line():
             buffer.insert(eob, &quot;\n&quot;)
-            
+
     def scroll_to_bottom(self):
         textbuffer = self.get_buffer()
         textiter = textbuffer.get_end_iter()
@@ -518,7 +518,7 @@ class MessageTextView(gtk.TextView):
     for chat/groupchat windows'''
     __gtype_name__ = 'MessageTextView'
     __gsignals__ = dict(mykeypress = (gobject.SIGNAL_RUN_LAST | gobject.SIGNAL_ACTION, None, (int, gtk.gdk.ModifierType )))
-        
+
     def __init__(self):
         gtk.TextView.__init__(self)
 </diff>
      <filename>amsn2/gui/front_ends/gtk/htmltextview.py</filename>
    </modified>
    <modified>
      <diff>@@ -1,21 +1,21 @@
 # -*- coding: utf-8 -*-
 #===================================================
-# 
+#
 # image.py - This file is part of the amsn2 package
 #
 # Copyright (C) 2008  Wil Alvarez &lt;wil_alejandro@yahoo.com&gt;
 #
 # This script is free software; you can redistribute it and/or modify it under
-# the terms of the GNU General Public License as published by the Free Software 
+# the terms of the GNU General Public License as published by the Free Software
 # Foundation; either version 3 of the License, or (at your option) any later
 # version.
 #
-# This script is distributed in the hope that it will be useful, but WITHOUT 
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
-# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License 
+# This script is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 # for more details.
 #
-# You should have received a copy of the GNU General Public License along with 
+# You should have received a copy of the GNU General Public License along with
 # this script (see COPYING); if not, write to the Free Software
 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 #
@@ -24,11 +24,23 @@
 import gtk
 from amsn2.gui import base
 from amsn2.core.views import imageview
-    
-class Image(gtk.Image, base.aMSNImage):
+
+class Image(gtk.Image):
     def __init__(self, theme_manager, view):
         gtk.Image.__init__(self)
-        base.aMSNImage.__init__(self, theme_manager, view)
+        self._theme_manager = theme_manager
+        self.load(view)
+
+    def load(self, view):
+        i = 0
+        for (resource_type, value) in view.imgs:
+            try:
+                loadMethod = getattr(self, &quot;_loadFrom%s&quot; % resource_type)
+            except AttributeError, e:
+                print &quot;From load in gtk/image.py:\n\t(resource_type, value) = (%s, %s)\n\tAttributeError: %s&quot; % (resource_type, value, e)
+            else:
+                loadMethod(value, view, i)
+                i += 1
 
     def _loadFromFilename(self, filename, view, index):
         # TODO: Implement support for emblems and other embedded images
@@ -40,7 +52,18 @@ class Image(gtk.Image, base.aMSNImage):
         except Exception, e:
             print e
             print &quot;Error loading image %s&quot; % filename
-        
+
+    def _loadFromTheme(self, resource_name, view, index):
+        # TODO: Implement support for emblems and other embedded images
+        if (index != 0): return
+
+        _, filename = self._theme_manager.get_value(resource_name)
+
+        if filename is not None:
+            self._loadFromFilename(filename, view, index)
+        else:
+            print 'Error loading image %s from theme' %resource_name
+
     def to_pixbuf(self, width, height):
         #print 'image.py -&gt; to_pixbuf: filename=%s' % self._filename
         try:
@@ -50,4 +73,4 @@ class Image(gtk.Image, base.aMSNImage):
         except:
             print 'Error converting to pixbuf image %s' % self._filename
             return None
-        
\ No newline at end of file
+</diff>
      <filename>amsn2/gui/front_ends/gtk/image.py</filename>
    </modified>
    <modified>
      <diff>@@ -24,18 +24,18 @@
 import os
 import gtk
 import gobject
+import string
 
 from image import *
-from amsn2.core.views import ImageView
+from amsn2.core.views import AccountView, ImageView
 
-class aMSNLoginWindow(gtk.VBox):
+class aMSNLoginWindow(gtk.VBox, base.aMSNLoginWindow):
 
     def __init__(self, amsn_core, parent):
 
         gtk.VBox.__init__(self, spacing=10)
 
         self._amsn_core = amsn_core
-        #self.switch_to_profile(None)
         self._main_win = parent
         self._skin = amsn_core._skin_manager.skin
         self._theme_manager = self._amsn_core._theme_manager
@@ -73,7 +73,9 @@ class aMSNLoginWindow(gtk.VBox):
         userCompletion.add_attribute(userPixbufCell, 'pixbuf', 1)
         userCompletion.set_text_column(0)
         #userCompletion.connect('match-selected', self.matchSelected)
-        #self.user.connect(&quot;changed&quot;, self.on_comboxEntry_changed)
+        self.user.connect(&quot;key-press-event&quot;, self.__on_user_comboxEntry_changed)
+        #FIXME: focus-out-event not working, i don't know why
+        self.user.connect(&quot;focus-out-event&quot;, self.__on_user_comboxEntry_changed)
         #self.user.connect(&quot;key-release-event&quot;, self.on_comboxEntry_keyrelease)
         userbox.pack_start(userlabel, False, False)
         userbox.pack_start(self.user, False, False)
@@ -85,18 +87,25 @@ class aMSNLoginWindow(gtk.VBox):
         self.password = gtk.Entry(128)
         self.password.set_visibility(False)
         self.password.connect('activate' , self.__login_clicked)
+        self.password.connect(&quot;changed&quot;, self.__on_passwd_comboxEntry_changed)
         passbox.pack_start(passlabel, False, False)
         passbox.pack_start(self.password, False, False)
 
         # status list
+        self.status_values = {}
+        status_n = 0
         status_list = gtk.ListStore(gtk.gdk.Pixbuf, str, str)
         for key in self._amsn_core.p2s:
             name = self._amsn_core.p2s[key]
             _, path = self._theme_manager.get_statusicon(&quot;buddy_%s&quot; % name)
             if (name == 'offline'): continue
+            self.status_values[name] = status_n
+            status_n = status_n +1
             icon = gtk.gdk.pixbuf_new_from_file(path)
+            name = string.capitalize(name)
             status_list.append([icon, name, key])
-            
+
+
         iconCell = gtk.CellRendererPixbuf()
         iconCell.set_property('xalign', 0.0)
         txtCell = gtk.CellRendererText()
@@ -105,7 +114,7 @@ class aMSNLoginWindow(gtk.VBox):
         # status combobox
         self.statusCombo = gtk.ComboBox()
         self.statusCombo.set_model(status_list)
-        self.statusCombo.set_active(0)
+        self.statusCombo.set_active(4) # Set status to 'online'
         self.statusCombo.pack_start(iconCell, False)
         self.statusCombo.pack_start(txtCell, False)
         self.statusCombo.add_attribute(iconCell, 'pixbuf',0)
@@ -133,6 +142,10 @@ class aMSNLoginWindow(gtk.VBox):
         self.rememberPass = gtk.CheckButton('Remember password', True)
         self.autoLogin = gtk.CheckButton('Auto-Login', True)
 
+        self.rememberMe.connect(&quot;toggled&quot;, self.__on_toggled_cb)
+        self.rememberPass.connect(&quot;toggled&quot;, self.__on_toggled_cb)
+        self.autoLogin.connect(&quot;toggled&quot;, self.__on_toggled_cb)
+
         checkboxes.pack_start(self.rememberMe, False, False)
         checkboxes.pack_start(self.rememberPass, False, False)
         checkboxes.pack_start(self.autoLogin, False, False)
@@ -154,11 +167,8 @@ class aMSNLoginWindow(gtk.VBox):
         self.pack_start(checkAlign, True, False)
         self.pack_start(button_box, True, False)
 
-        self.show_all()
         self._main_win.set_view(self)
-        self.user.grab_focus()        
-        #self.switch_to_profile(None)
-        
+
     def __animation(self):
         path = os.path.join(&quot;amsn2&quot;, &quot;themes&quot;, &quot;default&quot;, &quot;images&quot;,
         &quot;login_screen&quot;, &quot;cube&quot;)
@@ -181,30 +191,123 @@ class aMSNLoginWindow(gtk.VBox):
         self.signin()
 
     def show(self):
-        pass
+        if self.user.get_active_text() == &quot;&quot;:
+            self.user.grab_focus()
+        elif self.password.get_text() == &quot;&quot;:
+            self.password.grab_focus()
+
+        self.show_all()
 
     def hide(self):
         if (self.timer is not None):
             gobject.source_remove(self.timer)
 
-    def switch_to_profile(self, profile):
-        self.current_profile = profile
-        if profile is not None:
-            self._username = self.current_profile.username
-            self._password = self.current_profile.password
-            
-            
+    def __switch_to_account(self, email):
+        print &quot;Switching to account&quot;, email
+
+        accv = self.getAccountViewFromEmail(email)
+
+        if accv is None:
+            accv = AccountView()
+            accv.email = email
+
+        self.user.get_children()[0].set_text(accv.email)
+        if accv.password:
+            self.password.set_text(accv.password)
+
+        self.rememberMe.set_active(accv.save)
+        self.rememberPass.set_active(accv.save_password)
+        self.autoLogin.set_active(accv.autologin)
+
+    def setAccounts(self, accountviews):
+        self._account_views = accountviews
+
+        for accv in self._account_views:
+            self.user.append_text(accv.email)
+
+        if len(accountviews)&gt;0 :
+            # first in the list, default
+            self.__switch_to_account(self._account_views[0].email)
+
+            if self._account_views[0].autologin:
+                self.signin()
 
     def signin(self):
-        self.current_profile.username = self.user.get_active_text()
-        self.current_profile.email = self.user.get_active_text()
-        self.current_profile.password = self.password.get_text()
-        i = self.statusCombo.get_active()
-        self.current_profile.presence = self._amsn_core.p2s.keys()[i]
-        self._amsn_core.signinToAccount(self, self.current_profile)
+
+        if self.user.get_active_text() == &quot;&quot;:
+            self.user.grab_focus()
+            return
+        elif self.password.get_text() == &quot;&quot;:
+            self.password.grab_focus()
+            return
+
+        email = self.user.get_active_text()
+        accv = self.getAccountViewFromEmail(email)
+
+        if accv is None:
+            accv = AccountView()
+            accv.email = email
+
+        accv.password = self.password.get_text()
+        status = self.statusCombo.get_active()
+        for key in self.status_values:
+            if self.status_values[key] == status:
+                break
+        accv.presence = key
+
+        self._amsn_core.signinToAccount(self, accv)
         self.timer = gobject.timeout_add(40, self.__animation)
 
     def onConnecting(self, progress, message):
         self.status.set_text(message)
         self.pgbar.set_fraction(progress)
 
+    def __on_user_comboxEntry_changed(self, entry, event):
+        if event.type == gtk.gdk.FOCUS_CHANGE or \
+            (event.type == gtk.gdk.KEY_PRESS and event.keyval == gtk.keysyms.Tab):
+            self.__switch_to_account(entry.get_active_text())
+
+    def __on_passwd_comboxEntry_changed(self, entry):
+        if len(entry.get_text()) == 0:
+            self.rememberPass.set_sensitive(False)
+            self.autoLogin.set_sensitive(False)
+        else:
+            self.rememberPass.set_sensitive(True)
+            self.autoLogin.set_sensitive(True)
+
+    def __on_toggled_cb(self, source):
+
+        email = self.user.get_active_text()
+        accv = self.getAccountViewFromEmail(email)
+
+        if accv is None:
+            accv = AccountView()
+            accv.email = email
+
+        if source is self.rememberMe:
+            accv.save = source.get_active()
+            self.rememberPass.set_sensitive(source.get_active())
+            self.autoLogin.set_sensitive(source.get_active())
+        elif source is self.rememberPass:
+            accv.save_password = source.get_active()
+            self.autoLogin.set_sensitive(source.get_active())
+        elif source is self.autoLogin:
+            accv.autologin = source.get_active()
+
+
+    def getAccountViewFromEmail(self, email):
+        &quot;&quot;&quot;
+        Search in the list of account views and return the view of the given email
+
+        @type email: str
+        @param email: email to find
+        @rtype: AccountView
+        @return: Returns AccountView if it was found, otherwise return None
+        &quot;&quot;&quot;
+
+        accv = [accv for accv in self._account_views if accv.email == email]
+
+        if len(accv) == 0:
+            return None
+        else:
+            return accv[0]</diff>
      <filename>amsn2/gui/front_ends/gtk/login.py</filename>
    </modified>
    <modified>
      <diff>@@ -1,47 +1,93 @@
 
 from amsn2.gui import base
+from amsn2.core.views import MenuItemView
 
 import skins
 import gtk
 
 class aMSNMainWindow(base.aMSNMainWindow):
+    &quot;&quot;&quot;
+    @ivar main_win:
+    @type main_win: gtk.Window
+    &quot;&quot;&quot;
     main_win = None
-    
+
     def __init__(self, amsn_core):
         self._amsn_core = amsn_core
         self.main_win = gtk.Window()
         self.main_win.set_default_size(250, 500)
         self.main_win.connect('delete-event', self.__on_close)
+        self.main_menu = gtk.MenuBar()
+        inner = gtk.VBox()
+        inner.pack_start(self.main_menu, False, False)
+        self.main_win.add(inner)
         self.view = None
-        
+
     def __on_show(self):
         self._amsn_core.mainWindowShown()
-        
+
     def __on_close(self, widget, event):
-        exit(0)
+        self._amsn_core.quit()
 
     def show(self):
         self.main_win.show()
         self._amsn_core.idlerAdd(self.__on_show)
-        
+
     def setTitle(self, title):
         self.main_win.set_title(title)
-        
+
     def hide(self):
         self.main_win.hide()
-    
+
     def setMenu(self, menu):
         &quot;&quot;&quot; This will allow the core to change the current window's main menu
-        @menu : a MenuView
+        @type menu: MenuView
         &quot;&quot;&quot;
-        pass
-        
+        chldn = self.main_menu.get_children()
+        if len(chldn) is not 0:
+            for chl in chldn:
+                self.main_menu.remove(chl)
+        self._createMenuItemsFromView(self.main_menu, menu.items)
+        self.main_menu.show()
+
+    def _createMenuItemsFromView(self, menu, items):
+        # TODO: images &amp; radio groups, for now only basic representation
+        for item in items:
+            if item.type is MenuItemView.COMMAND:
+                it = gtk.MenuItem(item.label)
+                it.connect(&quot;activate&quot;, lambda i, item: item.command(), item )
+                it.show()
+                menu.append(it)
+            elif item.type is MenuItemView.CASCADE_MENU:
+                men = gtk.Menu()
+                it = gtk.MenuItem(item.label)
+                self._createMenuItemsFromView(men, item.items)
+                it.set_submenu(men)
+                it.show()
+                menu.append(it)
+            elif item.type is MenuItemView.SEPARATOR:
+                it = gtk.SeperatorMenuItem()
+                it.show()
+                menu.append(it)
+            elif item.type is MenuItemView.CHECKBUTTON:
+                it = gtk.CheckMenuItem(item.label)
+                if item.checkbox:
+                    it.set_active()
+                it.show()
+                menu.append(it)
+            elif item.type is MenuItemView.RADIOBUTTON:
+                it = gtk.RadioMenuItem(item.label)
+                it.show()
+                menu.append(it)
+            elif item.type is MenuItemView.RADIOBUTTONGROUP:
+                pass
     def set_view(self, view):
-        current = self.main_win.get_child()
-        
-        if current:
-            self.main_win.remove(current)
-        
-        self.main_win.add(view)
+        inner = self.main_win.get_child()
+        chldn = inner.get_children()
+        for c in chldn:
+            if isinstance(c, base.aMSNLoginWindow) or isinstance(c, base.aMSNContactListWindow):
+                inner.remove(c)
+
+        inner.pack_start(view)
         self.main_win.show_all()
-       
+</diff>
      <filename>amsn2/gui/front_ends/gtk/main.py</filename>
    </modified>
    <modified>
      <diff>@@ -5,7 +5,7 @@ import gobject
 class aMSNMainLoop(base.aMSNMainLoop):
     def __init__(self, amsn_core):
         self._amsn_core = amsn_core
-    
+
     def run(self):
         self._mainloop = gobject.MainLoop(is_running=True)
 
@@ -15,7 +15,7 @@ class aMSNMainLoop(base.aMSNMainLoop):
             except KeyboardInterrupt:
                 self.quit()
 
-        
+
     def idlerAdd(self, func):
         gobject.idle_add(func)
 
@@ -24,4 +24,4 @@ class aMSNMainLoop(base.aMSNMainLoop):
 
     def quit(self):
         self._mainloop.quit()
-        
+</diff>
      <filename>amsn2/gui/front_ends/gtk/main_loop.py</filename>
    </modified>
    <modified>
      <diff>@@ -1,69 +1,71 @@
 # -*- coding: utf-8 -*-
 #===================================================
-# 
+#
 # contact_list.py - This file is part of the amsn2 package
 #
 # Copyright (C) 2008  Wil Alvarez &lt;wil_alejandro@yahoo.com&gt;
 #
 # This script is free software; you can redistribute it and/or modify it under
-# the terms of the GNU General Public License as published by the Free Software 
+# the terms of the GNU General Public License as published by the Free Software
 # Foundation; either version 3 of the License, or (at your option) any later
 # version.
 #
-# This script is distributed in the hope that it will be useful, but WITHOUT 
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
-# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License 
+# This script is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 # for more details.
 #
-# You should have received a copy of the GNU General Public License along with 
+# You should have received a copy of the GNU General Public License along with
 # this script (see COPYING); if not, write to the Free Software
 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 #
 #===================================================
 
+from amsn2.gui import base
+
 import os
 
-class Skin(object):
+class Skin(base.Skin):
     def __init__(self, core, path):
         self._path = path
         self._dict = {}
         #TODO : remove, it's just here for test purpose
         #TODO : explain a bit :D
-        self.setKey(&quot;buddy_online&quot;, (&quot;Filename&quot;, os.path.join(&quot;amsn2&quot;, 
+        self.setKey(&quot;buddy_online&quot;, (&quot;Filename&quot;, os.path.join(&quot;amsn2&quot;,
             &quot;themes&quot;, &quot;default&quot;, &quot;images&quot;, &quot;online.png&quot;)))
         #self.setKey(&quot;emblem_online&quot;, (&quot;Filename&quot;, &quot;amsn2/themes/default/images/contact_list/plain_emblem.png&quot;))
 
-        self.setKey(&quot;buddy_away&quot;, (&quot;Filename&quot;, os.path.join(&quot;amsn2&quot;, 
+        self.setKey(&quot;buddy_away&quot;, (&quot;Filename&quot;, os.path.join(&quot;amsn2&quot;,
             &quot;themes&quot;, &quot;default&quot;, &quot;images&quot;, &quot;away.png&quot;)))
-            
+
         #self.setKey(&quot;emblem_away&quot;, (&quot;Filename&quot;, &quot;amsn2/themes/default/images/contact_list/away_emblem.png&quot;))
-        self.setKey(&quot;buddy_brb&quot;, (&quot;Filename&quot;, os.path.join(&quot;amsn2&quot;, 
+        self.setKey(&quot;buddy_brb&quot;, (&quot;Filename&quot;, os.path.join(&quot;amsn2&quot;,
             &quot;themes&quot;, &quot;default&quot;, &quot;images&quot;, &quot;away.png&quot;)))
         #self.setKey(&quot;emblem_brb&quot;, (&quot;Filename&quot;, &quot;amsn2/themes/default/images/contact_list/away_emblem.png&quot;))
-        self.setKey(&quot;buddy_idle&quot;, (&quot;Filename&quot;, os.path.join(&quot;amsn2&quot;, 
+        self.setKey(&quot;buddy_idle&quot;, (&quot;Filename&quot;, os.path.join(&quot;amsn2&quot;,
             &quot;themes&quot;, &quot;default&quot;, &quot;images&quot;, &quot;away.png&quot;)))
         #self.setKey(&quot;emblem_idle&quot;, (&quot;Filename&quot;, &quot;amsn2/themes/default/images/contact_list/away_emblem.png&quot;))
-        self.setKey(&quot;buddy_lunch&quot;, (&quot;Filename&quot;, os.path.join(&quot;amsn2&quot;, 
+        self.setKey(&quot;buddy_lunch&quot;, (&quot;Filename&quot;, os.path.join(&quot;amsn2&quot;,
             &quot;themes&quot;, &quot;default&quot;, &quot;images&quot;, &quot;away.png&quot;)))
         #self.setKey(&quot;emblem_lunch&quot;, (&quot;Filename&quot;, &quot;amsn2/themes/default/images/contact_list/away_emblem.png&quot;))
 
         # Just to show you can use an image from the edj file
-        self.setKey(&quot;buddy_busy&quot;, (&quot;Filename&quot;, os.path.join(&quot;amsn2&quot;, 
+        self.setKey(&quot;buddy_busy&quot;, (&quot;Filename&quot;, os.path.join(&quot;amsn2&quot;,
             &quot;themes&quot;, &quot;default&quot;, &quot;images&quot;,&quot;busy.png&quot;)))
         #self.setKey(&quot;emblem_busy&quot;, (&quot;Filename&quot;, &quot;amsn2/themes/default/images/contact_list/busy_emblem.png&quot;))
-        self.setKey(&quot;buddy_phone&quot;, (&quot;Filename&quot;, os.path.join(&quot;amsn2&quot;, 
+        self.setKey(&quot;buddy_phone&quot;, (&quot;Filename&quot;, os.path.join(&quot;amsn2&quot;,
             &quot;themes&quot;, &quot;default&quot;, &quot;images&quot;, &quot;busy.png&quot;)))
         #self.setKey(&quot;emblem_phone&quot;, (&quot;Filename&quot;, &quot;amsn2/themes/default/images/contact_list/busy_emblem.png&quot;))
 
-        self.setKey(&quot;buddy_offline&quot;, (&quot;Filename&quot;, os.path.join(&quot;amsn2&quot;, 
+        self.setKey(&quot;buddy_offline&quot;, (&quot;Filename&quot;, os.path.join(&quot;amsn2&quot;,
             &quot;themes&quot;, &quot;default&quot;, &quot;images&quot;, &quot;offline.png&quot;)))
-        
+
         #self.setKey(&quot;emblem_offline&quot;, (&quot;Filename&quot;, &quot;amsn2/themes/default/images/contact_list/offline_emblem.png&quot;))
-        self.setKey(&quot;buddy_hidden&quot;, (&quot;Filename&quot;, os.path.join(&quot;amsn2&quot;, 
+        self.setKey(&quot;buddy_hidden&quot;, (&quot;Filename&quot;, os.path.join(&quot;amsn2&quot;,
             &quot;themes&quot;, &quot;default&quot;, &quot;images&quot;, &quot;offline.png&quot;)))
         #self.setKey(&quot;emblem_hidden&quot;, (&quot;Filename&quot;, &quot;amsn2/themes/default/images/contact_list/offline_emblem.png&quot;))
 
-        self.setKey(&quot;default_dp&quot;, (&quot;Filename&quot;, os.path.join(&quot;amsn2&quot;, &quot;themes&quot;, 
+        self.setKey(&quot;default_dp&quot;, (&quot;Filename&quot;, os.path.join(&quot;amsn2&quot;, &quot;themes&quot;,
             &quot;default&quot;, &quot;images&quot;, &quot;contact_list&quot;, &quot;nopic.png&quot;)))
 
     def getKey(self, key, default=None):
@@ -76,7 +78,7 @@ class Skin(object):
         self._dict[key] = value
 
 
-class SkinManager(object):
+class SkinManager(base.SkinManager):
     def __init__(self, core):
         self._core = core
         self.skin = Skin(core, &quot;skins&quot;)</diff>
      <filename>amsn2/gui/front_ends/gtk/skins.py</filename>
    </modified>
    <modified>
      <diff>@@ -7,12 +7,12 @@ class aMSNSplashScreen(base.aMSNSplashScreen):
 
     def show(self):
         pass
-    
+
     def hide(self):
         pass
-    
+
     def setText(self, text):
         pass
-        
+
     def setImage(self, image):
         pass</diff>
      <filename>amsn2/gui/front_ends/gtk/splash.py</filename>
    </modified>
    <modified>
      <diff>@@ -36,7 +36,7 @@ def load():
 try:
     import imp
     imp.find_module(&quot;PyQt4&quot;)
-    
+
     gui.GUIManager.registerFrontEnd(&quot;qt4&quot;, sys.modules[__name__])
 except ImportError:
     pass</diff>
      <filename>amsn2/gui/front_ends/qt4/__init__.py</filename>
    </modified>
    <modified>
      <diff>@@ -23,14 +23,19 @@ from amsn2.gui import base
 from PyQt4.QtCore import *
 from PyQt4.QtGui import *
 from PyQt4 import *
-from ui_chatWindow import Ui_ChatWindow
+try:
+    from ui_chatWindow import Ui_ChatWindow
+except ImportError, e:
+    # FIXME: Should do that with logging...
+    print &quot;WARNING: To use the QT4 you need to run the generateFiles.sh, check the README&quot;
+    raise e
 from amsn2.core.views import ContactView, StringView
 
 class InputWidget(QTextEdit):
     def __init__(self, Parent = None):
         QTextEdit.__init__(self, Parent)
         self.setTextInteractionFlags(Qt.TextEditorInteraction)
-    
+
     def keyPressEvent(self, event):
         print &quot;key pressed:&quot; + str(event.key())
         if event.key() == Qt.Key_Enter or event.key() == Qt.Key_Return:
@@ -38,21 +43,21 @@ class InputWidget(QTextEdit):
             self.emit(SIGNAL(&quot;enterKeyTriggered()&quot;))
         else:
             QTextEdit.keyPressEvent(self, event)
-    
+
 class aMSNChatWindow(QTabWidget, base.aMSNChatWindow):
     def __init__(self, amsn_core, Parent=None):
         QTabWidget.__init__(self, Parent)
-        
+
         self._core = amsn_core
-        
+
     def addChatWidget(self, chat_widget):
         self.addTab(chat_widget, &quot;test&quot;)
-        
-    
+
+
 class aMSNChatWidget(QWidget, base.aMSNChatWidget):
     def __init__(self, amsn_conversation, Parent=None):
         QWidget.__init__(self, Parent)
-        
+
         self._amsn_conversation = amsn_conversation
         self.ui = Ui_ChatWindow()
         self.ui.setupUi(self)
@@ -60,102 +65,102 @@ class aMSNChatWidget(QWidget, base.aMSNChatWidget):
         self.ui.inputLayout.addWidget(self.ui.inputWidget)
         self._statusBar = QStatusBar(self)
         self.layout().addWidget(self._statusBar)
-        
+
         self.loadEmoticonList()
-        
+
         QObject.connect(self.ui.inputWidget, SIGNAL(&quot;textChanged()&quot;), self.processInput)
         QObject.connect(self.ui.inputWidget, SIGNAL(&quot;enterKeyTriggered()&quot;), self.__sendMessage)
         QObject.connect(self.ui.actionInsert_Emoticon, SIGNAL(&quot;triggered()&quot;), self.showEmoticonList)
         self.enterShortcut = QShortcut(QKeySequence(&quot;Enter&quot;), self.ui.inputWidget)
         self.nudgeShortcut = QShortcut(QKeySequence(&quot;Ctrl+G&quot;), self)
         QObject.connect(self.enterShortcut, SIGNAL(&quot;activated()&quot;), self.__sendMessage)
-        QObject.connect(self.nudgeShortcut, SIGNAL(&quot;activated()&quot;), self.__sendNudge)        
+        QObject.connect(self.nudgeShortcut, SIGNAL(&quot;activated()&quot;), self.__sendNudge)
         QObject.connect(self.ui.actionNudge, SIGNAL(&quot;triggered()&quot;), self.__sendNudge)
-        
+
 
     def processInput(self):
         &quot;&quot;&quot; Here we process what is inside the widget... so showing emoticon
         and similar stuff&quot;&quot;&quot;
-        
+
         QObject.disconnect(self.ui.inputWidget, SIGNAL(&quot;textChanged()&quot;), self.processInput)
-        
+
         self.text = QString(self.ui.inputWidget.toHtml())
-                
+
         for emoticon in self.emoticonList:
             if self.text.contains(emoticon) == True:
                 print emoticon
                 self.text.replace(emoticon, &quot;&lt;img src=\&quot;throbber.gif\&quot; /&gt;&quot;)
-                
+
         self.ui.inputWidget.setHtml(self.text)
         self.ui.inputWidget.moveCursor(QTextCursor.End)
         self.__typingNotification()
-        
+
         QObject.connect(self.ui.inputWidget, SIGNAL(&quot;textChanged()&quot;), self.processInput)
-        
+
     def loadEmoticonList(self):
         self.emoticonList = QStringList()
-        
+
         &quot;&quot;&quot; TODO: Request emoticon list from amsn core, maybe use a QMap to get the image URL? &quot;&quot;&quot;
-        
+
         &quot;&quot;&quot; TODO: Discuss how to handle custom emoticons. We have to provide an option
         to change the default icon theme, this includes standard emoticons too.
         Maybe qrc? &quot;&quot;&quot;
-        
+
         #self.emoticonList &lt;&lt; &quot;;)&quot; &lt;&lt; &quot;:)&quot; &lt;&lt; &quot;EmOtIcOn&quot;
-	#We want :) and ;) to work for now :p
-	self.emoticonList &lt;&lt; &quot;EmOtIcOn&quot;
-        
+        #We want :) and ;) to work for now :p
+        self.emoticonList &lt;&lt; &quot;EmOtIcOn&quot;
+
     def showEmoticonList(self):
         &quot;&quot;&quot; Let's popup emoticon selection here &quot;&quot;&quot;
         print &quot;Guess what? No emoticons. But I'll put in a random one for you&quot;
         self.appendImageAtCursor(&quot;throbber.gif&quot;)
-        
+
     def __sendMessage(self):
         # TODO: Switch to this when implemented
         &quot;&quot;&quot; msg = self.ui.inputWidget.toHtml()
         self.ui.inputWidget.clear()
         strv = StringView()
         strv.appendElementsFromHtml(msg) &quot;&quot;&quot;
-        
+
         msg = self.ui.inputWidget.toPlainText()
         self.ui.inputWidget.clear()
         strv = StringView()
         strv.appendText(unicode(msg))
         self._amsn_conversation.sendMessage(strv)
         self.ui.textEdit.append(&quot;&lt;b&gt;/me says:&lt;/b&gt;&lt;br&gt;&quot;+unicode(msg)+&quot;&quot;)
-        
+
     def __sendNudge(self):
         self._amsn_conversation.sendNudge()
         self.ui.textEdit.append(&quot;&lt;b&gt;/me sent a nudge&lt;/b&gt;&quot;)
-        
+
     def __typingNotification(self):
         self._amsn_conversation.sendTypingNotification()
-        
+
     def appendTextAtCursor(self, text):
         self.ui.inputWidget.textCursor().insertHtml(unicode(text))
-        
+
     def appendImageAtCursor(self, image):
         self.ui.inputWidget.textCursor().insertHtml(QString(&quot;&lt;img src=\&quot;&quot; + str(image) + &quot;\&quot; /&gt;&quot;))
-        
+
     def onUserJoined(self, contact):
-        self.ui.textEdit.append(unicode(&quot;&lt;b&gt;&quot;+QString.fromUtf8(contact.name.toString())+&quot; &quot;+self.tr(&quot;has joined the conversation&quot;)+(&quot;&lt;/b&gt;&quot;)))
+        self.ui.textEdit.append(unicode(&quot;&lt;b&gt;&quot;+QString.fromUtf8(str(contact.name))+&quot; &quot;+self.tr(&quot;has joined the conversation&quot;)+(&quot;&lt;/b&gt;&quot;)))
         pass
 
     def onUserLeft(self, contact):
-        self.ui.textEdit.append(unicode(&quot;&lt;b&gt;&quot;+QString.fromUtf8(contact.name.toString())+&quot; &quot;+self.tr(&quot;has left the conversation&quot;)+(&quot;&lt;/b&gt;&quot;)))
+        self.ui.textEdit.append(unicode(&quot;&lt;b&gt;&quot;+QString.fromUtf8(str(contact.name))+&quot; &quot;+self.tr(&quot;has left the conversation&quot;)+(&quot;&lt;/b&gt;&quot;)))
         pass
 
     def onUserTyping(self, contact):
-        self._statusBar.showMessage(unicode(QString.fromUtf8(contact.name.toString()) + &quot; is typing&quot;), 7000)
+        self._statusBar.showMessage(unicode(QString.fromUtf8(str(contact.name)) + &quot; is typing&quot;), 7000)
 
     def onMessageReceived(self, sender, message):
         print &quot;Ding!&quot;
-        self.ui.textEdit.append(unicode(&quot;&lt;b&gt;&quot;+QString.fromUtf8(sender.name.toString())+&quot; &quot;+self.tr(&quot;writes:&quot;)+(&quot;&lt;/b&gt;&quot;)))
+        self.ui.textEdit.append(unicode(&quot;&lt;b&gt;&quot;+QString.fromUtf8(str(sender.name))+&quot; &quot;+self.tr(&quot;writes:&quot;)+(&quot;&lt;/b&gt;&quot;)))
         self.ui.textEdit.append(unicode(message.toHtmlString()))
         pass
 
     def onNudgeReceived(self, sender):
-        self.ui.textEdit.append(unicode(&quot;&lt;b&gt;&quot;+sender.name.toString()+&quot; &quot;+self.tr(&quot;sent you a nudge!&quot;)+(&quot;&lt;/b&gt;&quot;)))
+        self.ui.textEdit.append(unicode(&quot;&lt;b&gt;&quot;+str(sender.name)+&quot; &quot;+self.tr(&quot;sent you a nudge!&quot;)+(&quot;&lt;/b&gt;&quot;)))
         pass
-    
-        
+
+</diff>
      <filename>amsn2/gui/front_ends/qt4/chat_window.py</filename>
    </modified>
    <modified>
      <diff>@@ -24,6 +24,6 @@ from PyQt4.QtCore import *
 class ContactItem(QStandardItem):
     def __init__(self):
         QStandardItem.__init__(self)
-        
+
     def setContactName(self, name):
-        self.setText(name)
\ No newline at end of file
+        self.setText(name)</diff>
      <filename>amsn2/gui/front_ends/qt4/contact_item.py</filename>
    </modified>
    <modified>
      <diff>@@ -24,7 +24,12 @@ from PyQt4.QtCore import *
 from PyQt4.QtGui import *
 from contact_model import ContactModel
 from contact_item import ContactItem
-from ui_contactlist import Ui_ContactList
+try:
+    from ui_contactlist import Ui_ContactList
+except ImportError, e:
+    # FIXME: Should do that with logging...
+    print &quot;WARNING: To use the QT4 you need to run the generateFiles.sh, check the README&quot;
+    raise e
 from styledwidget import StyledWidget
 from amsn2.core.views import StringView, ContactView
 from amsn2.gui import base
@@ -38,7 +43,7 @@ class aMSNContactListWindow(base.aMSNContactListWindow):
 
     def show(self):
         self._clwidget.show()
-    
+
     def hide(self):
         self._clwidget.hide()
 
@@ -53,8 +58,8 @@ class aMSNContactListWindow(base.aMSNContactListWindow):
 
     def myInfoUpdated(self, view):
         pass #TODO
-    
-            
+
+
 class aMSNContactListWidget(StyledWidget, base.aMSNContactListWidget):
     def __init__(self, amsn_core, parent):
         base.aMSNContactListWidget.__init__(self, amsn_core, parent)
@@ -69,10 +74,10 @@ class aMSNContactListWidget(StyledWidget, base.aMSNContactListWidget):
         self._proxyModel.setSourceModel(self._model)
         self.ui.cList.setModel(self._proxyModel)
         self._contactDict = dict()
-        
+
         self._proxyModel.setFilterCaseSensitivity(Qt.CaseInsensitive)
         self._proxyModel.setFilterKeyColumn(-1)
-        
+
         self.connect(self.ui.searchLine, SIGNAL('textChanged(QString)'),
                      self._proxyModel, SLOT('setFilterFixedString(QString)'))
         QObject.connect(self.ui.nickName, SIGNAL('textChanged(QString)'),
@@ -83,55 +88,55 @@ class aMSNContactListWidget(StyledWidget, base.aMSNContactListWidget):
 
     def hide(self):
         pass
-    
+
     def __slotChangeNick(self):
         sv = StringView()
         sv.appendText(str(self.ui.nickName.text()))
         self._amsn_core._profile.client.changeNick(sv)
-        
+
     def contactListUpdated(self, view):
         pass
-    
+
     def contactUpdated(self, contact):
-        print unicode(&quot;Contact Updated: &quot; + QString.fromUtf8(contact.name.toString()))
+        print unicode(&quot;Contact Updated: &quot; + QString.fromUtf8(str(contact.name)))
         l = self._model.findItems(&quot;*&quot;, Qt.MatchWildcard | Qt.MatchRecursive)
-        
+
         for itm in l:
-            if itm.data(40).toString() == contact.uid:
-                itm.setText(QString.fromUtf8(contact.name.toString()))
+            if str(itm.data(40)) == contact.uid:
+                itm.setText(QString.fromUtf8(str(contact.name)))
                 break
 
     def groupUpdated(self, group):
         print &quot;GroupUpdated&quot;
         l = self._model.findItems(&quot;*&quot;, Qt.MatchWildcard)
-        
+
         for itm in l:
-            
-            if itm.data(40).toString() == group.uid:
-                
-                itm.setText(QString.fromUtf8(group.name.toString()))
-            
+
+            if str(itm.data(40)) == group.uid:
+
+                itm.setText(QString.fromUtf8(str(group.name)))
+
                 for contact in group.contacts:
-                    
+
                     for ent in l:
-                        
-                        if ent.data(40).toString() == contact.uid:
-                            itm.setText(QString.fromUtf8(contact.name.toString()))
+
+                        if str(ent.data(40)) == contact.uid:
+                            itm.setText(QString.fromUtf8(str(contact.name)))
                             continue
-                        
-                    print &quot;  * &quot; + contact.name.toString()
-            
+
+                    print &quot;  * &quot; + contact.name
+
                     contactItem = ContactItem()
-                    contactItem.setContactName(QString.fromUtf8(contact.name.toString()))
+                    contactItem.setContactName(QString.fromUtf8(str(contact.name)))
                     contactItem.setData(QVariant(contact.uid), 40)
-            
+
                     itm.appendRow(contactItem)
 
                 break
 
     def groupRemoved(self, group):
         l = self._model.findItems(&quot;&quot;, Qt.MatchWildcard)
-        
+
         for itm in l:
             if itm.data(40) == group.uid:
                 row = self._model.indexFromItem(itm)
@@ -154,7 +159,7 @@ class aMSNContactListWidget(StyledWidget, base.aMSNContactListWidget):
                          self.__slotContactCallback)
 
     def __slotContactCallback(self, index):
-        data = str(index.data(40).toString())
+        data = str(str(index.data(40)))
         if self._callback is not None:
             self._callback(self._contactDict[data])
 
@@ -163,24 +168,24 @@ class aMSNContactListWidget(StyledWidget, base.aMSNContactListWidget):
         pass
 
     def groupAdded(self, group):
-        print group.name.toString()
-        
+        print group.name
+
         pi = self._model.invisibleRootItem();
-        
+
         # Adding Group Item
-        
+
         groupItem = QStandardItem()
-        groupItem.setText(QString.fromUtf8(group.name.toString()))
+        groupItem.setText(QString.fromUtf8(str(group.name)))
         groupItem.setData(QVariant(group.uid), 40)
         pi.appendRow(groupItem)
-        
+
         for contact in group.contacts:
-            print &quot;  * &quot; + contact.name.toString()
-            
+            print &quot;  * &quot; + contact.name
+
             contactItem = ContactItem()
-            contactItem.setContactName(QString.fromUtf8(contact.name.toString()))
+            contactItem.setContactName(QString.fromUtf8(str(contact.name)))
             contactItem.setData(QVariant(contact.uid), 40)
-            
+
             groupItem.appendRow(contactItem)
-            
+
             self._contactDict[contact.uid] = contact</diff>
      <filename>amsn2/gui/front_ends/qt4/contact_list.py</filename>
    </modified>
    <modified>
      <diff>@@ -24,6 +24,6 @@ from PyQt4.QtCore import *
 class ContactModel(QStandardItemModel):
     def __init__(self, parent):
         QStandardItemModel.__init__(self, parent)
-        
+
     def test(self):
-        self.test = &quot;test&quot;        
+        self.test = &quot;test&quot;</diff>
      <filename>amsn2/gui/front_ends/qt4/contact_model.py</filename>
    </modified>
    <modified>
      <diff>@@ -2,6 +2,12 @@
 
 #pyrcc4 -o src/faigaresource_rc.py ui/faigaresource.qrc
 
+which pyuic4&gt;/dev/null
+if [ $? != 0 ]; then
+ echo &gt;&amp;2 &quot;This script requires pyuic4 installed.&quot;
+ exit 255
+fi
+
 pyuic4 -o ui_login.py login.ui
 pyuic4 -o ui_contactlist.py contactlist.ui
 pyuic4 -o ui_chatWindow.py chatWindow.ui</diff>
      <filename>amsn2/gui/front_ends/qt4/generateFiles.sh</filename>
    </modified>
    <modified>
      <diff>@@ -23,7 +23,7 @@ from amsn2.gui import base
 from PyQt4.QtCore import *
 from PyQt4.QtGui import *
 from amsn2.core.views import imageview
-    
+
 class Image(QPixmap):
     def __init__(self):
         QPixmap.__init__(self)
@@ -37,7 +37,7 @@ class Image(QPixmap):
         &quot;&quot;&quot;
         if resource_name == &quot;File&quot;:
             self._loadFromFilename(value)
-            
+
     def loadFromImageView(self, view):
         for (resource_type, value) in view.imgs:
             try:
@@ -46,7 +46,7 @@ class Image(QPixmap):
                 print &quot;From append in qt4/image.py:\n\t(resource_type, value) = (%s, %s)\n\tAttributeError: %s&quot; % (resource_type, value, e)
             else:
                 loadMethod(value)
-            
+
     def getAsFilename(self):
         return self._fileName
 
@@ -63,15 +63,15 @@ class Image(QPixmap):
         &quot;&quot;&quot;
         if resource_name == &quot;File&quot;:
             self.load(value)
-            
+
     def _loadFromFilename(self, filename):
         QPixmap.load(self, filename)
         self._fileName = filename
-        
+
     def _loadFromSkin(self, skin):
         pass
-    
+
     def _loadFromFileObject(self, obj):
         pass
-        
-            
+
+</diff>
      <filename>amsn2/gui/front_ends/qt4/image.py</filename>
    </modified>
    <modified>
      <diff>@@ -2,7 +2,12 @@ from amsn2.gui import base
 
 from PyQt4.QtCore import *
 from PyQt4.QtGui import *
-from ui_login import Ui_Login
+try:
+    from ui_login import Ui_Login
+except ImportError, e:
+    # FIXME: Should do that with logging...
+    print &quot; WARNING: To use the QT4 you need to run the generateFiles.sh, check the README&quot;
+    raise e
 from styledwidget import StyledWidget
 
 </diff>
      <filename>amsn2/gui/front_ends/qt4/login.py</filename>
    </modified>
    <modified>
      <diff>@@ -39,7 +39,7 @@ class aMSNMainWindow(QMainWindow, base.aMSNMainWindow):
         QObject.connect(self.opaqLayer, SIGNAL(&quot;fadeInCompleted()&quot;), self.__activateNewWidget)
         QObject.connect(self.opaqLayer, SIGNAL(&quot;fadeOutCompleted()&quot;), self.__fadeIn)
         self.resize(230, 550)
-        
+
     def closeEvent(self, event):
         self._amsn_core.quit()
 
@@ -76,14 +76,14 @@ class aMSNMainWindow(QMainWindow, base.aMSNMainWindow):
 
     def set_view(self, view):
         print &quot;set_view request&quot;
-        
+
     def setMenu(self, menu):
         mb = QMenuBar()
-        
+
         for item in menu.items:
             if item.type == &quot;cascade&quot;:
                 menu = mb.addMenu(item.label)
                 for subitem in item.items:
                     menu.addAction(subitem.label)
-                
-        self.setMenuBar(mb)
\ No newline at end of file
+
+        self.setMenuBar(mb)</diff>
      <filename>amsn2/gui/front_ends/qt4/main.py</filename>
    </modified>
    <modified>
      <diff>@@ -19,8 +19,9 @@
 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
 import os.path
+from amsn2.gui import base
 
-class Skin(object):
+class Skin(base.Skin):
     def __init__(self, core, path):
         self._path = path
         pass
@@ -33,7 +34,7 @@ class Skin(object):
 
 
 
-class SkinManager(object):
+class SkinManager(base.SkinManager):
     def __init__(self, core):
         self._core = core
         self.skin = Skin(core, &quot;skins&quot;)</diff>
      <filename>amsn2/gui/front_ends/qt4/skins.py</filename>
    </modified>
    <modified>
      <diff>@@ -24,7 +24,7 @@ from PyQt4.QtCore import *
 from PyQt4.QtGui import *
 from fadingwidget import FadingWidget
 from image import *
-    
+
 class aMSNSplashScreen(QSplashScreen, base.aMSNSplashScreen):
 
     def __init__(self, amsn_core, parent):
@@ -33,15 +33,15 @@ class aMSNSplashScreen(QSplashScreen, base.aMSNSplashScreen):
     def show(self):
         self.setVisible(True)
         qApp.processEvents()
-    
+
     def hide(self):
         self.setVisible(False)
         qApp.processEvents()
-    
+
     def setText(self, text):
         self.showMessage(text)
         qApp.processEvents()
-        
+
     def setImage(self, image):
         img = Image()
         img.loadFromImageView(image)</diff>
      <filename>amsn2/gui/front_ends/qt4/splash.py</filename>
    </modified>
    <modified>
      <diff>@@ -14,7 +14,7 @@ def load():
 try:
     import imp
     gui.GUIManager.registerFrontEnd(&quot;web&quot;, sys.modules[__name__])
-    
+
 except ImportError:
     pass
-        
+</diff>
      <filename>amsn2/gui/front_ends/web/__init__.py</filename>
    </modified>
    <modified>
      <diff>@@ -37,9 +37,9 @@ class Backend(object):
             pass
         # Return true to continue checking events
         return True
-        
+
     def event(self,event,values):
-        # The JS client sent a message to the backend 
+        # The JS client sent a message to the backend
         # select the function to call depending on the type of event
         if self.listeners[event] is not None:
             for func in self.listeners[event]:</diff>
      <filename>amsn2/gui/front_ends/web/bend.py</filename>
    </modified>
    <modified>
      <diff>@@ -1,39 +1,52 @@
+import md5
+import random
+from amsn2.core.views import ContactView, StringView
 
 class aMSNChatWindow(object):
     &quot;&quot;&quot; This interface will represent a chat window of the UI
         It can have many aMSNChatWidgets&quot;&quot;&quot;
     def __init__(self, amsn_core):
         self._amsn_core = amsn_core
+        self._uid = md5.new(str(random.random())).hexdigest()
+        self._main = amsn_core._core._main
+        self._main.send(&quot;newChatWindow&quot;,[self._uid])
 
     def addChatWidget(self, chat_widget):
         &quot;&quot;&quot; add an aMSNChatWidget to the window &quot;&quot;&quot;
-        pass
+        self._main.send(&quot;addChatWidget&quot;,[self._uid,chat_widget._uid])
 
     def show(self):
-        pass
+        self._main.send(&quot;showChatWindow&quot;,[self._uid])
 
     def hide(self):
-        pass
+        self._main.send(&quot;hideChatWindow&quot;,[self._uid])
 
     def add(self):
+        print &quot;aMSNChatWindow.add&quot;
         pass
 
     def move(self):
+        print &quot;aMSNChatWindow.move&quot;
         pass
 
     def remove(self):
+        print &quot;aMSNChatWindow.remove&quot;
         pass
 
     def attach(self):
+        print &quot;aMSNChatWindow.attach&quot;
         pass
 
     def detach(self):
+        print &quot;aMSNChatWindow.detach&quot;
         pass
 
     def close(self):
+        print &quot;aMSNChatWindow.close&quot;
         pass
 
     def flash(self):
+        print &quot;aMSNChatWindow.flash&quot;
         pass
     &quot;&quot;&quot;TODO: move, remove, detach, attach (shouldn't we use add ?), close,
         flash...&quot;&quot;&quot;
@@ -44,13 +57,26 @@ class aMSNChatWidget(object):
     def __init__(self, amsn_conversation, parent):
         &quot;&quot;&quot; create the chat widget for the 'parent' window, but don't attach to
         it.&quot;&quot;&quot;
-        pass
+        self._main=parent._main
+        self._uid=md5.new(str(random.random())).hexdigest()
+        self._main.send(&quot;newChatWidget&quot;,[self._uid])
+        self._main.addListener(&quot;sendMessage&quot;,self.sendMessage)
+        self._amsn_conversation=amsn_conversation
+    
+    def sendMessage(self,smL):
+        if smL[0]==self._uid:
+            stmess = StringView()
+            stmess.appendText(smL[1])
+            self._amsn_conversation.sendMessage(stmess)
+        return True
+        
+        
 
     def onMessageReceived(self, messageview):
         &quot;&quot;&quot; Called for incoming and outgoing messages
             message: a MessageView of the message&quot;&quot;&quot;
-        pass
+        self._main.send(&quot;onMessageReceivedChatWidget&quot;, [self._uid, str(messageview.toStringView())])
 
     def nudge(self):
-        pass
+        self._main.send(&quot;nudgeChatWidget&quot;,[self._uid])
 </diff>
      <filename>amsn2/gui/front_ends/web/chat_window.py</filename>
    </modified>
    <modified>
      <diff>@@ -31,13 +31,14 @@ class aMSNContactListWindow(object):
         &quot;&quot;&quot; This will allow the core to change the current window's title
         @text : a string
         &quot;&quot;&quot;
-        self._main.send(&quot;setTitle&quot;,[text])
+        self._main.send(&quot;setContactListTitle&quot;,[text])
         pass
 
     def setMenu(self, menu):
         &quot;&quot;&quot; This will allow the core to change the current window's main menu
         @menu : a MenuView
         &quot;&quot;&quot;
+        self._main.send(&quot;setMenu&quot;)
         pass
 
     def myInfoUpdated(self, view):
@@ -45,7 +46,7 @@ class aMSNContactListWindow(object):
         ourself, such as DP, nick, psm, the current media being played,...
         @view: the contactView of the ourself (contains DP, nick, psm,
         currentMedia,...)&quot;&quot;&quot;
-        self._main.send(&quot;myInfoUpdated&quot;,[view.name.toString()])
+        self._main.send(&quot;myInfoUpdated&quot;,[str(view.name)])
         pass
 
 class aMSNContactListWidget(object):
@@ -53,11 +54,20 @@ class aMSNContactListWidget(object):
     def __init__(self, amsn_core, parent):
         self._main = parent._main
         self.contacts = {}
-        self.groups = []
+        self.groups = {}
+        self._main.addListener(&quot;contactClicked&quot;,self.contactClicked)
         clm = amsn_core._contactlist_manager
         clm.register(clm.CLVIEW_UPDATED, self.contactListUpdated)
         clm.register(clm.GROUPVIEW_UPDATED, self.groupUpdated)
         clm.register(clm.CONTACTVIEW_UPDATED, self.contactUpdated)
+        
+    def contactClicked(self,uidL):
+        uid = uidL.pop()
+        try:
+            self.contacts[uid].on_click(uid)
+        except Exception, inst:
+            print inst
+        return True
 
     def show(self):
         &quot;&quot;&quot; Show the contact list widget &quot;&quot;&quot;
@@ -90,7 +100,8 @@ class aMSNContactListWidget(object):
         may be changed, in which case the UI should update itself accordingly.
         A contact can also be added or removed from a group using this method
         &quot;&quot;&quot;
-        self._main.send(&quot;groupUpdated&quot;,[groupView.uid,&quot;,&quot;.join(groupView.contact_ids),groupView.name.toString()])
+        self.groups[groupView.uid]=groupView
+        self._main.send(&quot;groupUpdated&quot;,[groupView.uid,&quot;,&quot;.join(groupView.contact_ids),str(groupView.name)])
         pass
 
     def contactUpdated(self, contactView):
@@ -103,6 +114,7 @@ class aMSNContactListWidget(object):
         call will be made with the new order of the contacts
         in the affects groups.
         &quot;&quot;&quot;
-        self._main.send(&quot;contactUpdated&quot;,[contactView.uid,contactView.name.toString()])
+        self.contacts[contactView.uid]=contactView
+        self._main.send(&quot;contactUpdated&quot;, [contactView.uid, str(contactView.name)])
         pass
 </diff>
      <filename>amsn2/gui/front_ends/web/contact_list.py</filename>
    </modified>
    <modified>
      <diff>@@ -3,7 +3,7 @@ class aMSNLoginWindow(object):
         self._main = main
         self._amsn_core = amsn_core
         self.switch_to_profile(None)
-        
+
     def show(self):
         self._main.send(&quot;showLogin&quot;,[]);
         self._main.addListener(&quot;setUsername&quot;,self.setUsername)
@@ -30,6 +30,6 @@ class aMSNLoginWindow(object):
         self.current_profile.email = self._username
         self.current_profile.password = self._password
         self._amsn_core.signinToAccount(self, self.current_profile)
-        
+
     def onConnecting(self,mess):
         self._main.send(&quot;onConnecting&quot;,[mess])</diff>
      <filename>amsn2/gui/front_ends/web/login.py</filename>
    </modified>
    <modified>
      <diff>@@ -20,17 +20,21 @@ class aMSNMainWindow(base.aMSNMainWindow,Backend):
         Backend.__init__(self,&quot;/tmp/test.in&quot;,&quot;/tmp/test.out&quot;)
         self._amsn_core = amsn_core
         self._amsn_core.timerAdd(1,self.checkEvent)
- 
+
     def show(self):
+        self.send(&quot;showMainWindow&quot;,[])
         self._amsn_core.idlerAdd(self.__on_show)
 
     def hide(self):
+        self.send(&quot;hideMainWindow&quot;,[])
         pass
-    
+
     def setTitle(self,title):
+        self.send(&quot;setMainWindowTitle&quot;,[title])
         pass
 
     def setMenu(self,menu):
+        print &quot;aMSNMainWindow.setMenu&quot;
         pass
 
     def __on_show(self):</diff>
      <filename>amsn2/gui/front_ends/web/main.py</filename>
    </modified>
    <modified>
      <diff>@@ -5,7 +5,7 @@ import gobject
 class aMSNMainLoop(base.aMSNMainLoop):
     def __init__(self, amsn_core):
         self._amsn_core = amsn_core
-    
+
     def run(self):
         self._mainloop = gobject.MainLoop(is_running=True)
         while self._mainloop.is_running():
@@ -14,7 +14,7 @@ class aMSNMainLoop(base.aMSNMainLoop):
             except KeyboardInterrupt:
                 self.quit()
 
-        
+
     def idlerAdd(self, func):
         gobject.idle_add(func)
 
@@ -23,4 +23,4 @@ class aMSNMainLoop(base.aMSNMainLoop):
 
     def quit(self):
         self._mainloop.quit()
-        
+</diff>
      <filename>amsn2/gui/front_ends/web/main_loop.py</filename>
    </modified>
    <modified>
      <diff>@@ -1,6 +1,7 @@
 import os.path
+from amsn2.gui import base
 
-class Skin(object):
+class Skin(base.Skin):
     def __init__(self, core, path):
         self._path = path
         pass
@@ -13,7 +14,7 @@ class Skin(object):
 
 
 
-class SkinManager(object):
+class SkinManager(base.SkinManager):
     def __init__(self, core):
         self._core = core
         self.skin = Skin(core, &quot;skins&quot;)</diff>
      <filename>amsn2/gui/front_ends/web/skins.py</filename>
    </modified>
    <modified>
      <diff>@@ -5,23 +5,28 @@ class aMSNSplashScreen(object):
         &quot;&quot;&quot;Initialize the interface. You should store the reference to the core in here
         as well as a reference to the window where you will show the splash screen
         &quot;&quot;&quot;
+        self._amsn_core=amsn_core
+        self._main=parent
         pass
 
     def show(self):
         &quot;&quot;&quot; Draw the splashscreen &quot;&quot;&quot;
+        self._main.send(&quot;showSplashScreen&quot;,[])
         pass
 
     def hide(self):
         &quot;&quot;&quot; Hide the splashscreen &quot;&quot;&quot;
+        self._main.send(&quot;hideSplashScreen&quot;,[])
         pass
 
     def setText(self, text):
         &quot;&quot;&quot; Shows a different text inside the splashscreen &quot;&quot;&quot;
+        self._main.send(&quot;setTextSplashScreen&quot;,[text])
         pass
 
     def setImage(self, image):
         &quot;&quot;&quot; Set the image to show in the splashscreen. This is an ImageView object &quot;&quot;&quot;
-
+        self._main.send(&quot;setImageSplashScreen&quot;,[&quot;...&quot;])
         pass
 
 </diff>
      <filename>amsn2/gui/front_ends/web/splash.py</filename>
    </modified>
    <modified>
      <diff>@@ -6,20 +6,24 @@ class aMSNWindow(object):
 
     def show(self):
         &quot;&quot;&quot; This launches the window, creates it, etc..&quot;&quot;&quot;
+        print &quot;aMSNWindow.show&quot;
         pass
 
     def hide(self):
         &quot;&quot;&quot; This should hide the window&quot;&quot;&quot;
+        print &quot;aMSNWindow.hide&quot;
         pass
 
     def setTitle(self, text):
         &quot;&quot;&quot; This will allow the core to change the current window's title
         @text : a string
         &quot;&quot;&quot;
+        print &quot;aMSNWindow.setTitle&quot;
         pass
-    
+
     def setMenu(self, menu):
         &quot;&quot;&quot; This will allow the core to change the current window's main menu
         @menu : a MenuView
         &quot;&quot;&quot;
+        print &quot;aMSNWindow.setMenu&quot;
         pass</diff>
      <filename>amsn2/gui/front_ends/web/window.py</filename>
    </modified>
    <modified>
      <diff>@@ -10,29 +10,34 @@ class InvalidFrontEndException(Exception):
 
 class GUIManager(object):
     front_ends = {}
-    
+
     def __init__(self, core, gui_name):
+        &quot;&quot;&quot;
+        @type core: aMSNCore
+        @type gui_name: str
+        &quot;&quot;&quot;
+
         self._core = core
         self._name = gui_name
-        
+   		
         if GUIManager.frontEndExists(self._name) is False:
             raise InvalidFrontEndException(&quot;Invalid Front End. Available front ends are : &quot; + str(GUIManager.listFrontEnds()))
         else:
             self.gui = GUIManager.front_ends[self._name]
             self.gui = self.gui.load()
-        
+
     @staticmethod
     def registerFrontEnd(name, module):
         GUIManager.front_ends[name] = module
-        
+
     @staticmethod
     def listFrontEnds():
-        return GUIManager.front_ends.keys();
-    
+        return GUIManager.front_ends.keys()
+
     @staticmethod
     def frontEndExists(front_end):
         return front_end in GUIManager.listFrontEnds()
-   
+
 
 
 </diff>
      <filename>amsn2/gui/gui.py</filename>
    </modified>
    <modified>
      <diff>@@ -5,20 +5,24 @@
 # To register for an event call self.registerForEvent(event, callback)
 # To de-register call self.unRegisterForEvent(event)
 class aMSNPlugin(object):
-	# These are called when the plugin is loaded or un-loaded.
-	def load(self): pass
-	def unload(self): pass
-	
-	# Used to access the _name or _dir private variables.
-	def getName(self):
-		return str(self._name)
-	def getDir(self):
-		return str(self._dir)
-	
-	# Used to log data.
-	def log(self, message):
-		plugins.log(self._name, message)
-	
-	# Used to register/de-register for events.
-	def registerForEvent(self, event, callback): pass
-	def unRegisterForEvent(self, event): pass
+    # These are called when the plugin is loaded or un-loaded.
+    def load(self):
+        pass
+    def unload(self):
+        pass
+
+    # Used to access the _name or _dir private variables.
+    def getName(self):
+        return str(self._name)
+    def getDir(self):
+        return str(self._dir)
+
+    # Used to log data.
+    def log(self, message):
+        plugins.log(self._name, message)
+
+    # Used to register/de-register for events.
+    def registerForEvent(self, event, callback):
+        pass
+    def unRegisterForEvent(self, event):
+        pass</diff>
      <filename>amsn2/plugins/developers.py</filename>
    </modified>
    <modified>
      <diff>@@ -1,41 +1,53 @@
 import plugins
 
 class aMSNPluginSelectorWindow(object):
-	def drawWindow(self): pass
-	def showWindow(self): pass
-	def closeWindow(self): pass
-	def getPlugins(self):
-		return plugins.getPlugins()
-	def getPluginsWithStatus(self): 
-		return plugins.getPluginsWithStatus()
-	def loadPlugin(self, plugin_name): pass
-	def unLoadPlugin(self, plugin_name): pass
-	def configurePlugin(self, plugin_name): pass
+    def drawWindow(self):
+        pass
+    def showWindow(self):
+        pass
+    def closeWindow(self):
+        pass
+    def getPlugins(self):
+        return plugins.getPlugins()
+    def getPluginsWithStatus(self):
+        return plugins.getPluginsWithStatus()
+    def loadPlugin(self, plugin_name):
+        pass
+    def unLoadPlugin(self, plugin_name):
+        pass
+    def configurePlugin(self, plugin_name):
+        pass
 
 class aMSNPluginConfigurationWindow(object):
-	# __init__(self, plugin_name)
-	# Calls plugins.findPlugin(plugin_name) to get a plugin.
-	# If the plugin is found and is loaded then save an instance of it in self._plugin.
-	# We cannot configure unloaded plugins so do not show the window if the plugin isn't found.
-	# Then draw the window and show it.
-	def __init__(self, plugin_name): pass
-	
-	# drawWindow(self)
-	# Handles pre-loading the window contents before the window is shown.
-	def drawWindow(self): pass
-	
-	# showWindow(self)
-	# If the window is drawn then simply show the window.
-	def showWindow(self): pass
-	
-	# closeWindow(self)
-	# Handles closing the window. Shouldn't just hide it.
-	def closeWindow(self): pass
-	
-	# getConfig(self)
-	# Returns a copy of the plugins config as a keyed array.
-	def getConfig(self): pass
-	
-	# saveConfig(self): pass
-	# Saves the config via plugins.saveConfig(plugin_name, data)
-	def saveConfig(self, config): pass
+    # __init__(self, plugin_name)
+    # Calls plugins.findPlugin(plugin_name) to get a plugin.
+    # If the plugin is found and is loaded then save an instance of it in self._plugin.
+    # We cannot configure unloaded plugins so do not show the window if the plugin isn't found.
+    # Then draw the window and show it.
+    def __init__(self, plugin_name):
+        pass
+
+    # drawWindow(self)
+    # Handles pre-loading the window contents before the window is shown.
+    def drawWindow(self):
+        pass
+
+    # showWindow(self)
+    # If the window is drawn then simply show the window.
+    def showWindow(self):
+        pass
+
+    # closeWindow(self)
+    # Handles closing the window. Shouldn't just hide it.
+    def closeWindow(self):
+        pass
+
+    # getConfig(self)
+    # Returns a copy of the plugins config as a keyed array.
+    def getConfig(self):
+        pass
+
+    # saveConfig(self): pass
+    # Saves the config via plugins.saveConfig(plugin_name, data)
+    def saveConfig(self, config):
+        pass</diff>
      <filename>amsn2/plugins/gui.py</filename>
    </modified>
    <modified>
      <diff>@@ -1 +1 @@
-from protocol import *
+from client import *</diff>
      <filename>amsn2/protocol/__init__.py</filename>
    </modified>
    <modified>
      <diff>@@ -1,23 +1,54 @@
+# -*- coding: utf-8 -*-
+#
+# amsn - a python client for the WLM Network
+#
+# Copyright (C) 2008 Dario Freddi &lt;drf54321@gmail.com&gt;
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
-import pymsn
-import pymsn.event
+import papyon
+import papyon.event
+from events.client import *
+from events.contact import *
+from events.invite import *
+from events.oim import *
+from events.addressbook import *
+from events.profile import *
+from events.mailbox import *
 
-
-class ClientEvents(pymsn.event.ClientEventInterface):
-    def __init__(self, client, amsn_core):
+class Client(papyon.Client):
+    def __init__(self, amsn_core, account):
+        self._amsn_account = account
         self._amsn_core = amsn_core
-        pymsn.event.ClientEventInterface.__init__(self, client)
+        server = (self._amsn_account.config.getKey(&quot;ns_server&quot;, &quot;messenger.hotmail.com&quot;),
+                  self._amsn_account.config.getKey(&quot;ns_port&quot;, 1863))
+        papyon.Client.__init__(self, server)
+
+        self._client_events_handler = ClientEvents(self, self._amsn_core)
+        self._contact_events_handler = ContactEvents(self, self._amsn_core._contactlist_manager)
+        self._invite_events_handler = InviteEvents(self, self._amsn_core)
+        self._oim_events_handler = OIMEvents(self, self._amsn_core._oim_manager)
+        self._addressbook_events_handler = AddressBookEvents(self, self._amsn_core)
+        self._profile_events_handler = ProfileEvents(self, self._amsn_core._personalinfo_manager)
+        self._mailbox_events_handler = MailboxEvents(self, self._amsn_core)
+
+    def connect(self, email, password):
+        self.login(email, password)
 
-    def on_client_state_changed(self, state):
-        self._amsn_core.connectionStateChanged(self._client._amsn_profile, state)
-        
-        if state == pymsn.event.ClientState.OPEN:
-            self._client.profile.display_name = &quot;aMSN2&quot;
-            self._client.profile.presence = pymsn.Presence.ONLINE
-            self._client.profile.current_media = (&quot;I listen to&quot;, &quot;Nothing&quot;)
-            self._client.profile.personal_message = &quot;Testing aMSN2!&quot;
+    def changeNick(self, nick):
+        self.profile.display_name = str(nick)
 
-    def on_client_error(self, error_type, error):
-        print &quot;ERROR :&quot;, error_type, &quot; -&gt;&quot;, error
-    
-    
+    def changeMessage(self, message):
+        self.profile.personal_message = str(message)</diff>
      <filename>amsn2/protocol/client.py</filename>
    </modified>
    <modified>
      <diff></diff>
      <filename>amsn2/themes/default.edj</filename>
    </modified>
    <modified>
      <diff>@@ -1 +1,8 @@
-find . -name &quot;*.pyc&quot; | xargs rm
+find . -name &quot;*.pyc&quot; -exec rm '{}' \;
+find . -name &quot;*.pyo&quot; -exec rm '{}' \;
+
+#Remove compiled Qt4 user interfaces
+rm amsn2/gui/front_ends/qt4/ui_login.py
+rm amsn2/gui/front_ends/qt4/ui_contactlist.py
+rm amsn2/gui/front_ends/qt4/ui_chatWindow.py
+</diff>
      <filename>clean</filename>
    </modified>
    <modified>
      <diff>@@ -5,7 +5,7 @@ import py2app
 from dircache import listdir
 
 # A list of files to include in the bundle.
-files = ['amsn2', 'pymsn']
+files = ['amsn2', 'papyon']
 
 # Nibs need to be appened individually because they they need to be in the root of the bundle.
 for f in listdir('amsn2/gui/front_ends/cocoa/nibs/files/'):</diff>
      <filename>setupCocoa.py</filename>
    </modified>
  </modified>
  <removed type="array">
    <removed>
      <filename>amsn2/core/profile.py</filename>
    </removed>
    <removed>
      <filename>amsn2/gui/base/image.py</filename>
    </removed>
    <removed>
      <filename>amsn2/gui/front_ends/console/__init__.py</filename>
    </removed>
    <removed>
      <filename>amsn2/gui/front_ends/console/console.py</filename>
    </removed>
    <removed>
      <filename>amsn2/gui/front_ends/console/contact_list.py</filename>
    </removed>
    <removed>
      <filename>amsn2/gui/front_ends/console/login.py</filename>
    </removed>
    <removed>
      <filename>amsn2/gui/front_ends/console/main.py</filename>
    </removed>
    <removed>
      <filename>amsn2/gui/front_ends/console/main_loop.py</filename>
    </removed>
    <removed>
      <filename>amsn2/gui/front_ends/mine/__init__.py</filename>
    </removed>
    <removed>
      <filename>amsn2/gui/front_ends/mine/contact_list.py</filename>
    </removed>
    <removed>
      <filename>amsn2/gui/front_ends/mine/login.py</filename>
    </removed>
    <removed>
      <filename>amsn2/gui/front_ends/mine/main.py</filename>
    </removed>
    <removed>
      <filename>amsn2/gui/front_ends/mine/main_loop.py</filename>
    </removed>
    <removed>
      <filename>amsn2/gui/front_ends/mine/mine.py</filename>
    </removed>
    <removed>
      <filename>amsn2/gui/front_ends/mine/skins.py</filename>
    </removed>
    <removed>
      <filename>amsn2/gui/front_ends/mine/splash.py</filename>
    </removed>
    <removed>
      <filename>amsn2/protocol/addressbook.py</filename>
    </removed>
    <removed>
      <filename>amsn2/protocol/contact.py</filename>
    </removed>
    <removed>
      <filename>amsn2/protocol/conversation.py</filename>
    </removed>
    <removed>
      <filename>amsn2/protocol/invite.py</filename>
    </removed>
    <removed>
      <filename>amsn2/protocol/oim.py</filename>
    </removed>
    <removed>
      <filename>amsn2/protocol/protocol.py</filename>
    </removed>
    <removed>
      <filename>pymsn/AUTHORS</filename>
    </removed>
    <removed>
      <filename>pymsn/COPYING</filename>
    </removed>
    <removed>
      <filename>pymsn/MANIFEST.in</filename>
    </removed>
    <removed>
      <filename>pymsn/NEWS</filename>
    </removed>
    <removed>
      <filename>pymsn/README</filename>
    </removed>
    <removed>
      <filename>pymsn/doc.py</filename>
    </removed>
    <removed>
      <filename>pymsn/doc/user-api.conf</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/__init__.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/client.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/conversation.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/event/__init__.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/event/address_book.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/event/client.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/event/contact.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/event/conversation.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/event/invite.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/event/offline_messages.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/event/profile.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/gnet/__init__.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/gnet/constants.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/gnet/io/__init__.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/gnet/io/abstract.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/gnet/io/iochannel.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/gnet/io/sock.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/gnet/io/ssl_socket.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/gnet/io/ssl_tcp.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/gnet/io/tcp.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/gnet/message/HTTP.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/gnet/message/SOAP.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/gnet/message/__init__.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/gnet/parser.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/gnet/protocol/HTTP.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/gnet/protocol/HTTPS.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/gnet/protocol/__init__.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/gnet/proxy/HTTPConnect.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/gnet/proxy/SOCKS4.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/gnet/proxy/__init__.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/gnet/proxy/abstract.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/gnet/proxy/proxy_infos.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/gnet/proxy/proxyfiable.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/gnet/resolver.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/msnp/__init__.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/msnp/base.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/msnp/challenge.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/msnp/command.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/msnp/constants.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/msnp/message.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/msnp/notification.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/msnp/switchboard.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/msnp2p/SLP.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/msnp2p/__init__.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/msnp2p/constants.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/msnp2p/exceptions.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/msnp2p/session.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/msnp2p/session_manager.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/msnp2p/test.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/msnp2p/transport/TLP.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/msnp2p/transport/__init__.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/msnp2p/transport/base.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/msnp2p/transport/switchboard.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/msnp2p/transport/transport_manager.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/p2p.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/profile.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/AddressBook/__init__.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/AddressBook/ab.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/AddressBook/address_book.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/AddressBook/common.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/AddressBook/constants.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/AddressBook/scenario/__init__.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/AddressBook/scenario/base.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/AddressBook/scenario/contacts/__init__.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/AddressBook/scenario/contacts/accept_invite.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/AddressBook/scenario/contacts/block_contact.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/AddressBook/scenario/contacts/check_pending_invite.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/AddressBook/scenario/contacts/contact_delete.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/AddressBook/scenario/contacts/contact_update_properties.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/AddressBook/scenario/contacts/decline_invite.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/AddressBook/scenario/contacts/email_contact_add.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/AddressBook/scenario/contacts/external_contact_add.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/AddressBook/scenario/contacts/messenger_contact_add.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/AddressBook/scenario/contacts/mobile_contact_add.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/AddressBook/scenario/contacts/unblock_contact.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/AddressBook/scenario/contacts/update_memberships.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/AddressBook/scenario/groups/__init__.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/AddressBook/scenario/groups/group_add.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/AddressBook/scenario/groups/group_contact_add.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/AddressBook/scenario/groups/group_contact_delete.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/AddressBook/scenario/groups/group_delete.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/AddressBook/scenario/groups/group_rename.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/AddressBook/scenario/sync/__init__.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/AddressBook/scenario/sync/initial_sync.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/AddressBook/sharing.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/ContentRoaming/__init__.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/ContentRoaming/constants.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/ContentRoaming/content_roaming.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/ContentRoaming/scenario/__init__.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/ContentRoaming/scenario/base.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/ContentRoaming/scenario/get_stored_profile.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/ContentRoaming/scenario/store_profile.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/ContentRoaming/storage.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/OfflineIM/__init__.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/OfflineIM/constants.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/OfflineIM/offline_messages_box.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/OfflineIM/oim.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/OfflineIM/rsi.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/OfflineIM/scenario/__init__.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/OfflineIM/scenario/base.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/OfflineIM/scenario/delete_messages.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/OfflineIM/scenario/fetch_messages.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/OfflineIM/scenario/send_message.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/OfflineIM/scenario/sync_headers.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/SOAPService.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/SOAPUtils.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/SingleSignOn.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/Spaces/__init__.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/Spaces/contactcardservice.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/Spaces/scenario/__init__.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/Spaces/scenario/base.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/Spaces/scenario/get_contact_card.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/Spaces/spaces.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/__init__.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/description/AB/ABAdd.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/description/AB/ABContactAdd.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/description/AB/ABContactDelete.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/description/AB/ABContactUpdate.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/description/AB/ABFindAll.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/description/AB/ABGroupAdd.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/description/AB/ABGroupContactAdd.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/description/AB/ABGroupContactDelete.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/description/AB/ABGroupDelete.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/description/AB/ABGroupUpdate.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/description/AB/__init__.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/description/AB/common.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/description/AB/constants.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/description/OIM/Store2.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/description/OIM/__init__.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/description/RSI/DeleteMessages.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/description/RSI/GetMessage.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/description/RSI/GetMetadata.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/description/RSI/__init__.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/description/RSI/common.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/description/SchematizedStore/CreateDocument.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/description/SchematizedStore/CreateRelationships.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/description/SchematizedStore/DeleteRelationships.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/description/SchematizedStore/FindDocuments.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/description/SchematizedStore/GetProfile.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/description/SchematizedStore/UpdateProfile.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/description/SchematizedStore/__init__.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/description/SchematizedStore/common.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/description/Sharing/AddMember.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/description/Sharing/DeleteMember.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/description/Sharing/FindMembership.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/description/Sharing/__init__.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/description/Sharing/common.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/description/SingleSignOn/RequestMultipleSecurityTokens.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/description/SingleSignOn/__init__.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/description/Spaces/GetXmlFeed.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/description/Spaces/__init__.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/service/description/__init__.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/storage.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/switchboard_manager.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/transport.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/util/__init__.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/util/debug.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/util/decorator.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/util/element_tree.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/util/guid.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/util/iso8601/LICENSE</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/util/iso8601/README</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/util/iso8601/__init__.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/util/iso8601/iso8601.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/util/iso8601/test_iso8601.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/util/queue.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/util/string_io.py</filename>
    </removed>
    <removed>
      <filename>pymsn/pymsn/util/weak.py</filename>
    </removed>
    <removed>
      <filename>pymsn/setup.py</filename>
    </removed>
    <removed>
      <filename>pymsn/test.py</filename>
    </removed>
  </removed>
  <parents type="array">
    <parent>
      <id>f3e3784ee76eed5f041ed75baa4b41255c7d3d80</id>
    </parent>
    <parent>
      <id>d86a6a0b3240863278445b9e1fc7686c7ff4f9ac</id>
    </parent>
  </parents>
  <author>
    <name>Youness Alaoui</name>
    <email>youness.alaoui@collabora.co.uk</email>
  </author>
  <url>http://github.com/drf/amsn2/commit/3d325ffea1350cd7cea6fb469f18464ad56474bd</url>
  <id>3d325ffea1350cd7cea6fb469f18464ad56474bd</id>
  <committed-date>2009-06-26T11:21:08-07:00</committed-date>
  <authored-date>2009-06-26T11:21:08-07:00</authored-date>
  <message>Merge branch 'master' of git@github.com:drf/amsn2

Conflicts:
	README</message>
  <tree>6bc3b563244aea86dd2035602043ce742b96cbcf</tree>
  <committer>
    <name>Youness Alaoui</name>
    <email>youness.alaoui@collabora.co.uk</email>
  </committer>
</commit>
