From 3026f89036412dbebca23b575a07efff6ac25582 Mon Sep 17 00:00:00 2001 From: Walter Bender Date: Mon, 04 Feb 2013 00:22:27 +0000 Subject: minor fixes and a major refactoring of signals for alerts --- diff --git a/extensions/web/fb/facebook/facebook.py b/extensions/web/fb/facebook/facebook.py index 48d5921..c9d2476 100644 --- a/extensions/web/fb/facebook/facebook.py +++ b/extensions/web/fb/facebook/facebook.py @@ -45,6 +45,21 @@ class FbObjectNotCreatedException(Exception): class FbBadCall(Exception): pass +FB_TRANSFER_DOWNLOAD = 0 +FB_TRANSFER_UPLOAD = 1 + +FB_PHOTO = 0 +FB_COMMENT = 1 +FB_LIKE = 2 +FB_STATUS = 3 + +FB_TYPES = { + FB_PHOTO: "photo", + FB_COMMENT: "comment", + FB_LIKE: "like", + FB_STATUS: "status", +} + class FbPhoto(GObject.GObject): PHOTOS_URL = "https://graph.facebook.com/me/photos?access_token=%s" COMMENTS_URL = "https://graph.facebook.com/%s/comments" @@ -57,6 +72,11 @@ class FbPhoto(GObject.GObject): 'comments-downloaded': (GObject.SignalFlags.RUN_FIRST, None, ([object])), 'comments-download-failed': (GObject.SignalFlags.RUN_FIRST, None, ([str])), 'likes-downloaded': (GObject.SignalFlags.RUN_FIRST, None, ([object])), + 'transfer-started': (GObject.SignalFlags.RUN_FIRST, None, ([int, int])), + 'transfer-progress': (GObject.SignalFlags.RUN_FIRST, None, ([int, int, float])), + 'transfer-completed': (GObject.SignalFlags.RUN_FIRST, None, ([int, int])), + 'transfer-failed': (GObject.SignalFlags.RUN_FIRST, None, ([int, int, str])), + 'transfer-state-changed': (GObject.SignalFlags.RUN_FIRST, None, ([str])), } def __init__(self, fb_object_id=None): @@ -87,7 +107,8 @@ class FbPhoto(GObject.GObject): def write_cb(buf): response.append(buf) - res = self._http_call(url, [('message', comment)], write_cb, post=True) + res = self._http_call(url, [('message', comment)], write_cb, True, + FB_COMMENT) if res == 200: try: comment_id = self._id_from_response("".join(response)) @@ -107,7 +128,7 @@ class FbPhoto(GObject.GObject): def write_cb(buf): response.append(buf) - result = self._http_call(url, params, write_cb, post=True) + result = self._http_call(url, params, write_cb, True, FB_PHOTO) if result == 200: photo_id = self._id_from_response("".join(response)) self.fb_object_id = photo_id @@ -145,7 +166,7 @@ class FbPhoto(GObject.GObject): def write_cb(buf): response_comments.append(buf) - ret = self._http_call(url, [], write_cb, post=False) + ret = self._http_call(url, [], write_cb, False, FB_COMMENT) if ret != 200: logging.debug("_refresh_comments failed, HTTP resp code: %d" % ret) self.emit('comments-download-failed', @@ -181,29 +202,82 @@ class FbPhoto(GObject.GObject): else: self.emit('comments-download-failed', 'No comments found') - def _http_call(self, url, params, write_cb, post=False): + def _http_call(self, url, params, write_cb, post, fb_type): + logging.debug('_http_call') + app_auth_params = [('access_token', FbAccount.access_token())] + def f(*args): + logging.debug('will call _http_progress_cb') + try: + args = list(args) + [fb_type] + self._http_progress_cb(*args) + except Exception as ex: + logging.debug("oops %s" % (str(ex))) + c = pycurl.Curl() + c.setopt(c.NOPROGRESS, 0) + c.setopt(c.PROGRESSFUNCTION, f) c.setopt(c.WRITEFUNCTION, write_cb) if post: c.setopt(c.POST, 1) c.setopt(c.HTTPPOST, app_auth_params + params) + transfer_type = FB_TRANSFER_UPLOAD + transfer_str = "Upload" else: c.setopt(c.HTTPGET, 1) params_str = urllib.urlencode(app_auth_params + params) url = "%s?%s" % (url, params_str) + transfer_type = FB_TRANSFER_DOWNLOAD + transfer_str = "Download" logging.debug("_http_call: %s" % (url)) c.setopt(c.URL, url) c.perform() + result = c.getinfo(c.HTTP_CODE) + if result != 200: + error_reason = "HTTP Code %d" % (result) + self.emit('transfer-failed', fb_type, transfer_type, error_reason) + self.emit('transfer-state-changed', "%s failed: %s" % (transfer_str, error_reason)) + c.close() return result + def _http_progress_cb(self, download_total, download_done, + upload_total, upload_done, fb_type): + logging.debug('_http_progress_cb') + + if download_total != 0: + total = download_total + done = download_done + transfer_type = FB_TRANSFER_DOWNLOAD + transfer_str = "Download" + else: + total = upload_total + done = upload_done + transfer_type = FB_TRANSFER_UPLOAD + transfer_str = "Upload" + + if done == 0: + self.emit('transfer-started', fb_type, transfer_type) + state = "started" + elif done == total: + self.emit('transfer-completed', fb_type, transfer_type) + self.emit('transfer-state-changed', "%s completed" % (transfer_str)) + state = "completed" + else: + if total != 0: + self.emit('transfer-progress', fb_type, transfer_type, + float(done) / float(total)) + perc = int((float(done) / float(total))*100) + state = "%d% done" % (perc) + + self.emit('transfer-state-changed', "%s %s" % (transfer_str, state)) + if __name__ == '__main__': import sys diff --git a/extensions/web/fb/facebook_online_account.py b/extensions/web/fb/facebook_online_account.py index 969a0a7..ea31370 100644 --- a/extensions/web/fb/facebook_online_account.py +++ b/extensions/web/fb/facebook_online_account.py @@ -42,6 +42,7 @@ from jarabe.web import online_account ACCOUNT_NEEDS_ATTENTION = 0 ACCOUNT_ACTIVE = 1 +ONLINE_ACCOUNT_NAME = _('Facebook') class FacebookOnlineAccount(online_account.OnlineAccount): @@ -54,6 +55,10 @@ class FacebookOnlineAccount(online_account.OnlineAccount): online_account.OnlineAccount.__init__(self) self._client = GConf.Client.get_default() facebook.FbAccount.set_access_token(self._access_token()) + self._alert = None + + def get_description(self): + return ONLINE_ACCOUNT_NAME def is_configured(self): return self._access_token() is not None @@ -64,32 +69,53 @@ class FacebookOnlineAccount(online_account.OnlineAccount): return expiration_date != 0 and expiration_date > time.time() def get_share_menu(self, journal_entry_metadata): - # TODO: - # this logic belongs inside FacebookShareMenu - # we should set this menu to insensitive if !is_active() - if self.is_active(): - icon_name = 'facebook-share' - else: - icon_name = 'facebook-share-insensitive' - fb_share_menu = FacebookShareMenu(journal_entry_metadata) - fb_share_menu.set_image(Icon(icon_name=icon_name, - icon_size=Gtk.IconSize.MENU)) - fb_share_menu.show() + fb_share_menu = _FacebookShareMenu(journal_entry_metadata, + self.is_active()) + self._connect_transfer_signals(fb_share_menu) return fb_share_menu def get_refresh_button(self): - return FacebookRefreshButton(self.is_active()) + fb_refresh_button = _FacebookRefreshButton(self.is_active()) + self._connect_transfer_signals(fb_refresh_button) + return fb_refresh_button + + def _connect_transfer_signals(self, transfer_widget): + transfer_widget.connect('transfer-state-changed', + self._transfer_state_changed_cb) + + def _transfer_state_changed_cb(self, widget, state_message): + logging.debug('_transfer_state_changed_cb') + + if self._alert is None: + self._alert = NotifyAlert() + self._alert.props.title = ONLINE_ACCOUNT_NAME + self._alert.connect('response', self._alert_response_cb) + + journalwindow.get_journal_window().add_alert(self._alert) + self._alert.props.msg = state_message + self._alert.show() + + def _alert_response_cb(self, alert, response_id): + journalwindow.get_journal_window().remove_alert(alert) + self._alert = None def _access_token(self): return self._client.get_string(self.ACCESS_TOKEN_KEY) -class FacebookShareMenu(online_account.OnlineShareMenu): +class _FacebookShareMenu(online_account.OnlineShareMenu): __gtype_name__ = 'JournalFacebookMenu' - def __init__(self, metadata): - online_account.OnlineShareMenu.__init__(self, _('Facebook')) + def __init__(self, metadata, is_active): + online_account.OnlineShareMenu.__init__(self, ONLINE_ACCOUNT_NAME) + if is_active: + icon_name = 'facebook-share' + else: + icon_name = 'facebook-share-insensitive' + self.set_image(Icon(icon_name=icon_name, + icon_size=Gtk.IconSize.MENU)) + self.show() self._metadata = metadata self._comment = '%s: %s' % (self._get_metadata_by_key('title'), self._get_metadata_by_key('description')) @@ -112,6 +138,8 @@ class FacebookShareMenu(online_account.OnlineShareMenu): photo.connect('photo-create-failed', self._photo_create_failed_cb, tmp_file) + photo.connect('transfer-state-changed', self._transfer_state_changed_cb) + result = photo.create(tmp_file) def _photo_created_cb(self, fb_photo, fb_object_id, tmp_file): @@ -138,27 +166,11 @@ class FacebookShareMenu(online_account.OnlineShareMenu): if os.path.exists(tmp_file): os.unlink(tmp_file) - self._fb_notify(failed_reason) - def _comment_added_cb(self, fb_photo, fb_comment_id): logging.debug("_comment_added_cb") - self._fb_notify(_('Upload successful')) def _comment_add_failed_cb(self, fb_photo, failed_reason): logging.debug("_comment_add_failed_cb") - self._fb_notify(failed_reason) - - def _fb_notify(self, message): - alert = NotifyAlert() - title_string = _('Facebook') - alert.props.title = title_string - alert.props.msg = message - alert.connect('response', self._facebook_alert_response_cb) - journalwindow.get_journal_window().add_alert(alert) - alert.show() - - def _facebook_alert_response_cb(self, alert, response_id): - journalwindow.get_journal_window().remove_alert(alert) def _image_file_from_metadata(self, image_path): """ Load a pixbuf from a Journal object. """ @@ -177,7 +189,7 @@ class FacebookShareMenu(online_account.OnlineShareMenu): pixbuf.savev(image_path, 'png', [], []) -class FacebookRefreshButton(online_account.OnlineRefreshButton): +class _FacebookRefreshButton(online_account.OnlineRefreshButton): def __init__(self, is_active): online_account.OnlineRefreshButton.__init__(self, 'facebook-refresh-insensitive') @@ -207,6 +219,7 @@ class FacebookRefreshButton(online_account.OnlineRefreshButton): self._fb_comments_downloaded_cb) fb_photo.connect('comments-download-failed', self._fb_comments_download_failed_cb) + fb_photo.connect('transfer-state-changed', self._transfer_state_changed_cb) fb_photo.refresh_comments() def _fb_comments_downloaded_cb(self, fb_photo, comments): @@ -223,15 +236,6 @@ class FacebookRefreshButton(online_account.OnlineRefreshButton): def _fb_comments_download_failed_cb(self, fb_photo, failed_reason): logging.debug('_fb_comments_download_failed_cb: %s' % (failed_reason)) - alert = NotifyAlert() - alert.props.title = _('Comments download') - alert.props.msg = failed_reason - alert.connect('response', self.__fb_refresh_offline_response_cb) - journalwindow.get_journal_window().add_alert(alert) - alert.show() - - def __fb_refresh_offline_response_cb(self, alert, alert_id): - pass def get_account(): return FacebookOnlineAccount() diff --git a/src/jarabe/journal/journaltoolbox.py b/src/jarabe/journal/journaltoolbox.py index ce09500..f69f78b 100644 --- a/src/jarabe/journal/journaltoolbox.py +++ b/src/jarabe/journal/journaltoolbox.py @@ -506,7 +506,7 @@ class DetailToolbox(ToolbarBox): volume_menu.show() for account in oam.OnlineAccountsManager.configured_accounts(): - menu = account.get_share_menu(metadata) + menu = account.get_share_menu(self._metadata) palette.menu.append(menu) def _refresh_duplicate_palette(self): diff --git a/src/jarabe/web/online_account.py b/src/jarabe/web/online_account.py index b908538..77d9c8e 100644 --- a/src/jarabe/web/online_account.py +++ b/src/jarabe/web/online_account.py @@ -20,12 +20,17 @@ #OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN #THE SOFTWARE. +import logging + from gi.repository import GObject from sugar3.graphics.menuitem import MenuItem from sugar3.graphics.toolbutton import ToolButton class OnlineAccount(GObject.GObject): + def get_description(self): + raise Exception("Not defined") + def is_configured(self): raise Exception("Not defined") @@ -39,10 +44,46 @@ class OnlineAccount(GObject.GObject): raise Exception("Not defined") +''' +class _TransferWidget(GObject.GObject): + __gsignals__ = { + 'transfer-started': (GObject.SignalFlags.RUN_FIRST, None, ([int, int])), + 'transfer-progress': (GObject.SignalFlags.RUN_FIRST, None, ([int, int, float])), + 'transfer-completed': (GObject.SignalFlags.RUN_FIRST, None, ([int, int])), + 'transfer-failed': (GObject.SignalFlags.RUN_FIRST, None, ([int, int, str])), + 'transfer-state-changed': (GObject.SignalFlags.RUN_FIRST, None, ([str])), + } + + def _transfer_state_changed_cb(self, transfer_object, state): + self.emit('transfer-state-changed', state) +''' + class OnlineShareMenu(MenuItem): - pass + __gsignals__ = { + 'transfer-started': (GObject.SignalFlags.RUN_FIRST, None, ([int, int])), + 'transfer-progress': (GObject.SignalFlags.RUN_FIRST, None, ([int, int, float])), + 'transfer-completed': (GObject.SignalFlags.RUN_FIRST, None, ([int, int])), + 'transfer-failed': (GObject.SignalFlags.RUN_FIRST, None, ([int, int, str])), + 'transfer-state-changed': (GObject.SignalFlags.RUN_FIRST, None, ([str])), + } + + def _transfer_state_changed_cb(self, transfer_object, state): + logging.debug('_transfer_state_changed_cb') + self.emit('transfer-state-changed', state) class OnlineRefreshButton(ToolButton): + __gsignals__ = { + 'transfer-started': (GObject.SignalFlags.RUN_FIRST, None, ([int, int])), + 'transfer-progress': (GObject.SignalFlags.RUN_FIRST, None, ([int, int, float])), + 'transfer-completed': (GObject.SignalFlags.RUN_FIRST, None, ([int, int])), + 'transfer-failed': (GObject.SignalFlags.RUN_FIRST, None, ([int, int, str])), + 'transfer-state-changed': (GObject.SignalFlags.RUN_FIRST, None, ([str])), + } + + def _transfer_state_changed_cb(self, transfer_object, state): + logging.debug('_transfer_state_changed_cb') + self.emit('transfer-state-changed', state) + def set_metadata(self, metadata): raise Exception("Not defined") -- cgit v0.9.1