From 3c0365075fb72932929dc732a7cce31b18e7c7f8 Mon Sep 17 00:00:00 2001 From: Luca Dariz Date: Tue, 22 Sep 2009 12:59:52 +0200 Subject: [PATCH] [core, gtk] use aMSNAccount to set the dp, change the UI API (dp chooser) Fix creating the directory in backend Use backend to update dp in personalinfo --- amsn2/backend/defaultaccountbackend.py | 4 +-- amsn2/core/account_manager.py | 41 +++++++++++++++++++++++ amsn2/core/amsn.py | 38 +--------------------- amsn2/core/personalinfo_manager.py | 7 ++-- amsn2/gui/base/choosers.py | 19 ++--------- amsn2/gui/front_ends/gtk/choosers.py | 45 +++++++++++++++++--------- 6 files changed, 81 insertions(+), 73 deletions(-) diff --git a/amsn2/backend/defaultaccountbackend.py b/amsn2/backend/defaultaccountbackend.py index fafcb835..5adef552 100644 --- a/amsn2/backend/defaultaccountbackend.py +++ b/amsn2/backend/defaultaccountbackend.py @@ -174,8 +174,8 @@ def removeAccount(self, email): """ DPs """ def getFileLocationDP(self, email, uid, shac): dir = os.path.join(self.dps_dir, self._getDir(email)) - if not os.path.isdir(self.dps_dir): - os.makedirs(self.dps_dir, 0700) + if not os.path.isdir(dir): + os.makedirs(dir, 0700) return os.path.join(dir, shac+".img") def _getDir(self, email): diff --git a/amsn2/core/account_manager.py b/amsn2/core/account_manager.py index 084c6b62..80a523ed 100644 --- a/amsn2/core/account_manager.py +++ b/amsn2/core/account_manager.py @@ -1,8 +1,13 @@ import os +import Image +import logging +import papyon import __builtin__ from views import AccountView from views import StringView +logger = logging.getLogger('amsn2.core.account_manager') + class aMSNAccount(object): """ aMSNAccount : a Class to represent an aMSN account This class will contain all settings relative to an account @@ -20,6 +25,7 @@ def __init__(self, core, accountview): self.personalinfoview = core._personalinfo_manager._personalinfoview self.do_save = accountview.save self.backend_manager = core._backend_manager + self.client = None self.lock() self.load() @@ -47,6 +53,41 @@ def save(self): self.view.dp = self.personalinfoview.dp self.backend_manager.saveAccount(self) + def set_dp(self, path): + if path: + try: + im = Image.open(path) + im.resize((96, 96), Image.BILINEAR) + + # Write the file and rename it instead of creating a tmpfile + profile = self.client.profile + dp_path_tmp = self.backend_manager.getFileLocationDP(self.view.email, profile.id, 'tmp') + im.save(dp_path_tmp, "PNG") + f = open(dp_path_tmp) + dp_object = papyon.p2p.MSNObject(self.client.profile, + os.path.getsize(dp_path_tmp), + papyon.p2p.MSNObjectType.DISPLAY_PICTURE, + os.path.basename(path), + os.path.basename(path), + data=f) + f.close() + + dp_path = self.backend_manager.getFileLocationDP(self.view.email, profile.id, dp_object._data_sha) + os.rename(dp_path_tmp, dp_path) + + except OSError, e: + # FIXME: on Windows, it's raised if dp_path already exists + # http://docs.python.org/library/os.html#os.rename + logger.error('Trying to overwrite a saved dp') + return + + except IOError, e: + logger.error(e) + return + + self.client.msn_object_store.publish(dp_object) + self.personalinfoview.dp = dp_object + class aMSNAccountManager(object): """ aMSNAccountManager : The account manager that takes care of storing and retreiving all the account. diff --git a/amsn2/core/amsn.py b/amsn2/core/amsn.py index 0e0930d7..083b0ab1 100644 --- a/amsn2/core/amsn.py +++ b/amsn2/core/amsn.py @@ -33,9 +33,6 @@ import papyon import logging -import Image -import tempfile - # Top-level loggers papyon_logger = logging.getLogger("papyon") logger = logging.getLogger("amsn2") @@ -246,40 +243,7 @@ def contactCB(account): self._gui.gui.aMSNContactDeleteWindow('Contact to remove: ', contactCB, ()) def changeDP(self): - def set_dp(view): - path = view.imgs[0][1] - f = open(path) - dp_obj = papyon.p2p.MSNObject(self._account.client.profile, - os.path.getsize(path), - papyon.p2p.MSNObjectType.DISPLAY_PICTURE, - f.name, f.name, data=f) - self._account.client.msn_object_store.publish(dp_obj) - self._personalinfo_manager._personalinfoview.dp = dp_obj - - def open_file(): - def update_dplist(file_path): - # TODO: fire up a window to choose the dp size and a friendly name - # TODO: save the new image in a local cache instead of a temp file - im = Image.open(file_path) - im.resize((96, 96), Image.BILINEAR) - fd, path = tempfile.mkstemp() - im.save(path, "PNG") - dp_view = ImageView('Filename', path) - dpwin.update_dp_list((dp_view, )) - filters = {'Image files':("*.png", "*.jpeg", "*.jpg", "*.gif", "*.bmp"), - 'All files':('*.*')} - directory = os.path.join("amsn2", "themes", "displaypic", "default") - self._gui.gui.aMSNFileChooserWindow(filters, directory, update_dplist) - - def capture(): - pass - - default_dps = ('dp_amsn', 'dp_female', 'dp_male', 'dp_nopic') - user_dps = [ImageView('Filename', self._theme_manager.get_dp(dp)[1]) for dp in default_dps] - dpwin = self._gui.gui.aMSNDPChooserWindow(user_dps, - (('Capture', capture), - ('Open file', open_file)), - set_dp) + self._gui.gui.aMSNDPChooserWindow(self._account.set_dp ,self._backend_manager) def createMainMenuView(self): menu = MenuView() diff --git a/amsn2/core/personalinfo_manager.py b/amsn2/core/personalinfo_manager.py index 08cc0898..8c00ba6e 100644 --- a/amsn2/core/personalinfo_manager.py +++ b/amsn2/core/personalinfo_manager.py @@ -7,6 +7,7 @@ def __init__(self, core): """ self._core = core + self._backend_manager = core._backend_manager self._em = core._event_manager self._personalinfoview = PersonalInfoView(self) self._papyon_profile = None @@ -73,8 +74,10 @@ def onPSMUpdated(self, psm): def onDPUpdated(self, dp_msnobj): self._personalinfoview._image.reset() - # TODO: use backend manager - self._personalinfoview._image.load('Filename', dp_msnobj._data.name) + path = self._backend_manager.getFileLocationDP(self._papyon_profile.account, + self._papyon_profile.id, + dp_msnobj._data_sha) + self._personalinfoview._image.load('Filename', path) self._em.emit(self._em.events.PERSONALINFO_UPDATED, self._personalinfoview) def onPresenceUpdated(self, presence): diff --git a/amsn2/gui/base/choosers.py b/amsn2/gui/base/choosers.py index e0d36a4f..1678426c 100644 --- a/amsn2/gui/base/choosers.py +++ b/amsn2/gui/base/choosers.py @@ -26,30 +26,15 @@ class aMSNDPChooserWindow(object): This Interface represent a window used to choose a display picture, should show a list of default dps and the possibility to catch a picture from a webcam. """ - def __init__(self, default_dps, actions, callback): + def __init__(self, callback, backend_manager): """ - @type default_dps: list - @params default_dps: a list containing strings representing the paths of the default dps. - @type actions: tuple - @param actions: A tuple containing the options between - which the user can choose. Every option is a tuple itself, of the form (name, callback), - where callback is the function that will be called if the option is selected. @type callback: function @param callback: The function called when the dp has been choosed. Its prototype is callback(dp_path) + @type backend_manager: aMSNBackendManager This will eventually call the related show() method, so the window is displayed when created. """ raise NotImplementedError - def update_dp_list(self, default_dps): - """ - @type default_dps: tuple - @params default_dps: a tuple containing strings representing the paths of the default dps. - - This function updated the list of the dps that can be chosen, - for example after opening a file or taking a picture. - """ - raise NotImplementedError - diff --git a/amsn2/gui/front_ends/gtk/choosers.py b/amsn2/gui/front_ends/gtk/choosers.py index bbc2aaf3..12a3d777 100644 --- a/amsn2/gui/front_ends/gtk/choosers.py +++ b/amsn2/gui/front_ends/gtk/choosers.py @@ -10,12 +10,13 @@ def __init__(self, filters, directory, callback): buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, gtk.RESPONSE_OK)) - for name in filters.keys(): - filefilter = gtk.FileFilter() - filefilter.set_name(name) - for ext in filters[name]: - filefilter.add_pattern(ext) - self.add_filter(filefilter) + if filters: + for name in filters.keys(): + filefilter = gtk.FileFilter() + filefilter.set_name(name) + for ext in filters[name]: + filefilter.add_pattern(ext) + self.add_filter(filefilter) toggle = gtk.CheckButton("Show hidden files") toggle.show() @@ -28,7 +29,8 @@ def __init__(self, filters, directory, callback): self.callback = callback #self.set_size_request(500, 400) - self.set_current_folder_uri(directory) + if directory: + self.set_current_folder_uri(directory) self.connect('selection-changed', self.activatePreview) self.connect('response', self.onResponse) @@ -56,7 +58,7 @@ def onResponse(self, chooser, id): class aMSNDPChooserWindow(base.aMSNDPChooserWindow, gtk.Window): - def __init__(self, default_dps, actions, callback): + def __init__(self, callback, backend_manager): gtk.Window.__init__(self, gtk.WINDOW_TOPLEVEL) self.showed = False self.set_default_size(550, 450) @@ -64,14 +66,22 @@ def __init__(self, default_dps, actions, callback): self.set_title("aMSN - Choose a Display Picture") self.callback = callback self.view = None - self.child = None + + actions = (('Open file', self._open_file), ) + default_dps = [] self._setup_boxes(actions) - self.update_dp_list(default_dps) + for dp in default_dps: + self._update_dp_list(default_dps) self.show() self.show_all() + def _open_file(self): + filters = {'Image files':("*.png", "*.jpeg", "*.jpg", "*.gif", "*.bmp"), + 'All files':('*.*')} + aMSNFileChooserWindow(filters, None, self._update_dp_list) + def _setup_boxes(self, actions): tscroll = gtk.ScrolledWindow() tscroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) @@ -136,9 +146,14 @@ def __on_dp_click(self, source, event): else: return False - def update_dp_list(self, default_dps): - for dp in default_dps: - im = image.Image(None, dp) - self._model.append((im.to_pixbuf(96, 96), dp)) - + def _update_dp_list(self, dp_path): + im = gtk.Image() + try: + im.set_from_file(dp_path) + except: + return + self._model.prepend((gtk.gdk.pixbuf_new_from_file_at_size(dp_path, 96, 96), dp_path)) + path = self._model.get_path(self._model.get_iter_first()) + self.iconview.select_path(path) + self.iconview.grab_focus()