From 208a68e451635883d0c6f58e56c8308bafe8b16c Mon Sep 17 00:00:00 2001 From: Walter Bender Date: Sun, 09 Jun 2013 22:06:54 +0000 Subject: refactoring based on lasted commits upstream --- diff --git a/extensions/cpsection/webservices/services/facebook/service.py b/extensions/cpsection/webservices/services/facebook/service.py index 5f5a183..3b840ca 100644 --- a/extensions/cpsection/webservices/services/facebook/service.py +++ b/extensions/cpsection/webservices/services/facebook/service.py @@ -26,11 +26,11 @@ from gi.repository import GObject from gi.repository import WebKit from gettext import gettext as _ from jarabe import config -from web.facebook import account as fboa +from web.facebook import account from cpsection.webservices.web_service import WebService -class FacebookService(WebService): +class WebService(WebService): FB_APP_ID = "172917389475707" FB_REDIRECT_URI = "http://www.sugarlabs.org" @@ -77,14 +77,14 @@ class FacebookService(WebService): def _fb_save_access_token(self, access_token, expires_in): client = GConf.Client.get_default() - client.set_string(fboa.FacebookOnlineAccount.ACCESS_TOKEN_KEY, + client.set_string(account.Account.ACCESS_TOKEN_KEY, access_token) expiry_time = int(time.time()) + expires_in client.set_int( - fboa.FacebookOnlineAccount.ACCESS_TOKEN_KEY_EXPIRATION_DATE, + account.Account.ACCESS_TOKEN_KEY_EXPIRATION_DATE, expiry_time) def get_service(): - return FacebookService() + return WebService() diff --git a/extensions/cpsection/webservices/services/twitter/service.py b/extensions/cpsection/webservices/services/twitter/service.py index c7884b9..0914a59 100644 --- a/extensions/cpsection/webservices/services/twitter/service.py +++ b/extensions/cpsection/webservices/services/twitter/service.py @@ -23,7 +23,7 @@ from gettext import gettext as _ from web.twitter.twitter.twr_oauth import TwrOauth from web.twitter.twitter.twr_account import TwrAccount -from web.twitter.account import TwitterOnlineAccount as twr +from web.twitter.account import Account as twr from cpsection.webservices.web_service import WebService diff --git a/extensions/web/facebook/account.py b/extensions/web/facebook/account.py index f105fdb..a97e565 100644 --- a/extensions/web/facebook/account.py +++ b/extensions/web/facebook/account.py @@ -35,6 +35,7 @@ from gi.repository import GObject from sugar3.datastore import datastore from sugar3.graphics.alert import NotifyAlert from sugar3.graphics.icon import Icon +from sugar3.graphics.menuitem import MenuItem from jarabe.journal import journalwindow from jarabe.web import account @@ -47,7 +48,8 @@ ACCOUNT_NAME = _('Facebook') COMMENTS = 'comments' COMMENT_IDS = 'fb_comment_ids' -class FacebookAccount(account.Account): + +class Account(account.Account): ACCESS_TOKEN_KEY = "/desktop/sugar/collaboration/facebook_access_token" ACCESS_TOKEN_KEY_EXPIRATION_DATE = \ @@ -56,29 +58,51 @@ class FacebookAccount(account.Account): def __init__(self): self._client = GConf.Client.get_default() facebook.FbAccount.set_access_token(self._access_token()) - self._alert = None + self._shared_journal_entry = None def get_description(self): return ACCOUNT_NAME - def is_configured(self): - return self._access_token() is not None - - def is_active(self): + def get_token_state(self): + if self._access_token() is None: + return self.STATE_NONE expiration_date = \ self._client.get_int(self.ACCESS_TOKEN_KEY_EXPIRATION_DATE) - return expiration_date != 0 and expiration_date > time.time() + if expiration_date != 0 and expiration_date > time.time(): + return self.STATE_VALID + else: + return self.STATE_EXPIRED + + def _access_token(self): + return self._client.get_string(self.ACCESS_TOKEN_KEY) + + def get_shared_journal_entry(self): + if self._shared_journal_entry is None: + self._shared_journal_entry = _SharedJournalEntry(self) + return self._shared_journal_entry + + +class _SharedJournalEntry(account.SharedJournalEntry): + __gsignals__ = { + 'transfer-state-changed': (GObject.SignalFlags.RUN_FIRST, None, + ([str])), + } + def __init__(self, fbaccount): + self._account = fbaccount + self._alert = None def get_share_menu(self, journal_entry_metadata): - fb_share_menu = _FacebookShareMenu(journal_entry_metadata, - self.is_active()) - self._connect_transfer_signals(fb_share_menu) - return fb_share_menu + menu = _ShareMenu( + journal_entry_metadata, + self._account.get_token_state() == self._account.STATE_VALID) + self._connect_transfer_signals(menu) + return menu def get_refresh_menu(self): - fb_refresh_menu = _FacebookRefreshMenu(self.is_active()) - self._connect_transfer_signals(fb_refresh_menu) - return fb_refresh_menu + menu = _RefreshMenu( + self._account.get_token_state() == self._account.STATE_VALID) + self._connect_transfer_signals(menu) + return menu def _connect_transfer_signals(self, transfer_widget): transfer_widget.connect('transfer-state-changed', @@ -89,7 +113,6 @@ class FacebookAccount(account.Account): # First, remove any existing alert if self._alert is None: - logging.debug('creating new alert') self._alert = NotifyAlert() self._alert.props.title = ACCOUNT_NAME self._alert.connect('response', self._alert_response_cb) @@ -103,15 +126,15 @@ class FacebookAccount(account.Account): 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(account.MenuItem): - __gtype_name__ = 'JournalFacebookMenu' +class _ShareMenu(MenuItem): + __gsignals__ = { + 'transfer-state-changed': (GObject.SignalFlags.RUN_FIRST, None, + ([str])), + } def __init__(self, metadata, is_active): - account.MenuItem.__init__(self, ACCOUNT_NAME) + MenuItem.__init__(self, ACCOUNT_NAME) if is_active: icon_name = 'facebook-share' @@ -143,8 +166,6 @@ class _FacebookShareMenu(account.MenuItem): photo.connect('photo-create-failed', self._photo_create_failed_cb, tmp_file) - photo.connect('transfer-state-changed', - self._transfer_state_changed_cb) GObject.idle_add(photo.create, tmp_file) @@ -163,8 +184,8 @@ class _FacebookShareMenu(account.MenuItem): ds_object.metadata['fb_object_id'] = fb_object_id datastore.write(ds_object, update_mtime=False) except Exception as ex: - logging.debug("_photo_created_cb failed to write to datastore: " % \ - str(ex)) + logging.debug("_photo_created_cb failed to write to datastore: " % + str(ex)) def _photo_create_failed_cb(self, fb_photo, failed_reason, tmp_file): logging.debug("_photo_create_failed_cb") @@ -195,9 +216,15 @@ class _FacebookShareMenu(account.MenuItem): pixbuf.savev(image_path, 'png', [], []) -class _FacebookRefreshMenu(account.MenuItem): +class _RefreshMenu(MenuItem): + __gsignals__ = { + 'transfer-state-changed': (GObject.SignalFlags.RUN_FIRST, None, + ([str])), + 'comments-changed': (GObject.SignalFlags.RUN_FIRST, None, ([str])) + } + def __init__(self, is_active): - account.MenuItem.__init__(self, ACCOUNT_NAME) + MenuItem.__init__(self, ACCOUNT_NAME) self._is_active = is_active self._metadata = None @@ -242,8 +269,6 @@ class _FacebookRefreshMenu(account.MenuItem): 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) GObject.idle_add(fb_photo.refresh_comments) def _fb_comments_downloaded_cb(self, fb_photo, comments): @@ -278,4 +303,4 @@ class _FacebookRefreshMenu(account.MenuItem): logging.debug('_fb_comments_download_failed_cb: %s' % (failed_reason)) def get_account(): - return FacebookAccount() + return Account() diff --git a/extensions/web/twitter/account.py b/extensions/web/twitter/account.py index a2e4bf0..934396d 100644 --- a/extensions/web/twitter/account.py +++ b/extensions/web/twitter/account.py @@ -35,6 +35,7 @@ from gi.repository import GObject from sugar3.datastore import datastore from sugar3.graphics.alert import NotifyAlert from sugar3.graphics.icon import Icon +from sugar3.graphics.menuitem import MenuItem from jarabe.journal import journalwindow from jarabe.web import account @@ -51,7 +52,7 @@ COMMENT_IDS = 'twr_comment_ids' COMMENT_LAST_ID = 'last_comment_id' -class TwitterAccount(account.Account): +class Account(account.Account): CONSUMER_TOKEN_KEY = "/desktop/sugar/collaboration/twitter_consumer_token" CONSUMER_SECRET_KEY = "/desktop/sugar/collaboration/twitter_consumer_secret" @@ -62,37 +63,56 @@ class TwitterAccount(account.Account): self._client = GConf.Client.get_default() ctoken, csecret, atoken, asecret = self._access_tokens() TwrAccount.set_secrets(ctoken, csecret, atoken, asecret) - self._alert = None + self._shared_journal_entry = None def get_description(self): return ACCOUNT_NAME - def is_configured(self): - return None not in self._access_tokens() + def get_token_state(self): + if None in self._access_tokens(): + return self.STATE_NONE + else: + # No expiration date + return self.STATE_VALID + + def _access_tokens(self): + return (self._client.get_string(self.CONSUMER_TOKEN_KEY), + self._client.get_string(self.CONSUMER_SECRET_KEY), + self._client.get_string(self.ACCESS_TOKEN_KEY), + self._client.get_string(self.ACCESS_SECRET_KEY)) - def is_active(self): - # No expiration date - return None not in self._access_tokens() + def get_shared_journal_entry(self): + if self._shared_journal_entry is None: + self._shared_journal_entry = _SharedJournalEntry(self) + return self._shared_journal_entry + +class _SharedJournalEntry(account.SharedJournalEntry): + __gsignals__ = { + 'transfer-state-changed': (GObject.SignalFlags.RUN_FIRST, None, + ([str])), + } + def __init__(self, twaccount): + self._account = twaccount + self._alert = None def get_share_menu(self, journal_entry_metadata): - twr_share_menu = _TwitterShareMenu(journal_entry_metadata, - self.is_active()) - self._connect_transfer_signals(twr_share_menu) - return twr_share_menu + menu = _ShareMenu( + journal_entry_metadata, + self._account.get_token_state() == self._account.STATE_VALID) + self._connect_transfer_signals(menu) + return menu def get_refresh_menu(self): - twr_refresh_menu = _TwitterRefreshMenu(self.is_active()) - self._connect_transfer_signals(twr_refresh_menu) - return twr_refresh_menu + menu = _RefreshMenu( + self._account.get_token_state() == self._account.STATE_VALID) + self._connect_transfer_signals(menu) + return menu 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') - - # First, remove any existing alert if self._alert is None: self._alert = NotifyAlert() self._alert.props.title = ACCOUNT_NAME @@ -107,18 +127,11 @@ class TwitterAccount(account.Account): journalwindow.get_journal_window().remove_alert(alert) self._alert = None - def _access_tokens(self): - return (self._client.get_string(self.CONSUMER_TOKEN_KEY), - self._client.get_string(self.CONSUMER_SECRET_KEY), - self._client.get_string(self.ACCESS_TOKEN_KEY), - self._client.get_string(self.ACCESS_SECRET_KEY)) - -class _TwitterShareMenu(account.MenuItem): - __gtype_name__ = 'JournalTwitterMenu' +class _ShareMenu(MenuItem): def __init__(self, metadata, is_active): - account.MenuItem.__init__(self, ACCOUNT_NAME) + MenuItem.__init__(self, ACCOUNT_NAME) if is_active: icon_name = 'twitter-share' @@ -183,9 +196,9 @@ class _TwitterShareMenu(account.MenuItem): pixbuf.savev(image_path, 'png', [], []) -class _TwitterRefreshMenu(account.MenuItem): +class _RefreshMenu(MenuItem): def __init__(self, is_active): - account.MenuItem.__init__(self, ACCOUNT_NAME) + MenuItem.__init__(self, ACCOUNT_NAME) self._is_active = is_active self._metadata = None @@ -217,11 +230,14 @@ class _TwitterRefreshMenu(account.MenuItem): logging.debug('_twr_refresh_menu_clicked_cb') if self._metadata is None: - logging.debug('_twr_refresh_menu_clicked_cb called without metadata') + logging.debug( + '_twr_refresh_menu_clicked_cb called without metadata') return if 'twr_object_id' not in self._metadata: - logging.debug('_twr_refresh_menu_clicked_cb called without twr_object_id in metadata') + logging.debug( + '_twr_refresh_menu_clicked_cb called without twr_object_id \ +in metadata') return self.emit('transfer-state-changed', _('Download started')) @@ -234,7 +250,8 @@ class _TwitterRefreshMenu(account.MenuItem): status_id = ds_object.metadata[COMMENT_LAST_ID] timeline = TwrTimeline() - timeline.connect('mentions-downloaded', self._twr_mentions_downloaded_cb) + timeline.connect('mentions-downloaded', + self._twr_mentions_downloaded_cb) timeline.mentions_timeline(since_id=status_id) def _twr_mentions_downloaded_cb(self, timeline, comments): @@ -254,7 +271,8 @@ class _TwitterRefreshMenu(account.MenuItem): new_comment = False for comment in comments: # XXX hope for a better API - if comment['in_reply_to_status_id_str'] != self._metadata['twr_object_id']: + if comment['in_reply_to_status_id_str'] != \ + self._metadata['twr_object_id']: continue if comment['id_str'] not in ds_comment_ids: @@ -280,4 +298,4 @@ class _TwitterRefreshMenu(account.MenuItem): logging.debug('_twr_comments_download_failed_cb: %s' % (failed_reason)) def get_account(): - return TwitterAccount() + return Account() diff --git a/src/jarabe/journal/detailview.py b/src/jarabe/journal/detailview.py index ade8718..9d474ec 100644 --- a/src/jarabe/journal/detailview.py +++ b/src/jarabe/journal/detailview.py @@ -76,7 +76,7 @@ class DetailView(Gtk.VBox): self._update_view() metadata = GObject.property( - type=object, getter=get_metadata, setter=set_metadata) + type=object, getter=get_metadata, setter=set_metadata) class BackBar(Gtk.EventBox): diff --git a/src/jarabe/journal/expandedentry.py b/src/jarabe/journal/expandedentry.py index ebf3385..7ffded2 100644 --- a/src/jarabe/journal/expandedentry.py +++ b/src/jarabe/journal/expandedentry.py @@ -26,7 +26,7 @@ from gi.repository import GObject from gi.repository import GLib from gi.repository import Gtk from gi.repository import Gdk -import simplejson +import json from sugar3.graphics import style from sugar3.graphics.xocolor import XoColor @@ -45,7 +45,8 @@ from jarabe.journal import journalwindow class Separator(Gtk.VBox): def __init__(self, orientation): Gtk.VBox.__init__(self, - background_color=style.COLOR_PANEL_GREY.get_gdk_color()) + background_color= + style.COLOR_PANEL_GREY.get_gdk_color()) class BuddyList(Gtk.Alignment): @@ -92,14 +93,16 @@ class CommentsView(Gtk.TreeView): def __init__(self): Gtk.TreeView.__init__(self) + self.set_headers_visible(False) self._store = Gtk.ListStore(str, object, str, str, str, object) self._comments = [] self._init_model() def update_comments(self, comments): self._store.clear() + if comments: - self._comments = simplejson.loads(comments) + self._comments = json.loads(comments) for comment in self._comments: self._add_row(comment.get(self.FROM, ''), comment.get(self.MESSAGE, ''), @@ -120,7 +123,7 @@ class CommentsView(Gtk.TreeView): def _init_model(self): self.set_model(self._store) - col = Gtk.TreeViewColumn(_('Comments:')) + col = Gtk.TreeViewColumn() who_icon = CellRendererCommentIcon(self) col.pack_start(who_icon, False) @@ -139,7 +142,8 @@ class CommentsView(Gtk.TreeView): erase_icon.connect('clicked', self._erase_comment_cb) col.pack_start(erase_icon, False) col.add_attribute(erase_icon, 'file-name', self.COMMENT_ERASE_ICON) - col.add_attribute(erase_icon, 'xo-color', self.COMMENT_ERASE_ICON_COLOR) + col.add_attribute( + erase_icon, 'xo-color', self.COMMENT_ERASE_ICON_COLOR) self.append_column(col) @@ -167,19 +171,22 @@ class CommentsView(Gtk.TreeView): def _erase_alert_response_cb(self, alert, response_id, entry): journalwindow.get_journal_window().remove_alert(alert) + if response_id is Gtk.ResponseType.OK: self._store.remove(entry) + # Regenerate comments from current contents of store self._comments = [] for entry in self._store: self._comments.append({ - self.FROM: entry[self.COMMENT_FROM], - self.MESSAGE: entry[self.COMMENT_MESSAGE], - self.ICON: entry[self.COMMENT_ICON], - self.ICON_COLOR: '[%s]' % ( - entry[self.COMMENT_ICON_COLOR].to_string()), - }) - self.emit('comments-changed', simplejson.dumps(self._comments)) + self.FROM: entry[self.COMMENT_FROM], + self.MESSAGE: entry[self.COMMENT_MESSAGE], + self.ICON: entry[self.COMMENT_ICON], + self.ICON_COLOR: '[%s]' % ( + entry[self.COMMENT_ICON_COLOR].to_string()), + }) + + self.emit('comments-changed', json.dumps(self._comments)) class CellRendererCommentIcon(CellRendererIcon): @@ -195,7 +202,6 @@ class CellRendererCommentIcon(CellRendererIcon): class ExpandedEntry(Gtk.EventBox): - def __init__(self): Gtk.EventBox.__init__(self) self._vbox = Gtk.VBox() @@ -282,7 +288,7 @@ class ExpandedEntry(Gtk.EventBox): self._icon = self._create_icon() for child in self._icon_box.get_children(): self._icon_box.remove(child) - #FIXME: self._icon_box.foreach(self._icon_box.remove) + # FIXME: self._icon_box.foreach(self._icon_box.remove) self._icon_box.pack_start(self._icon, False, False, 0) self._date.set_text(misc.get_date(metadata)) @@ -295,13 +301,13 @@ class ExpandedEntry(Gtk.EventBox): for child in self._technical_box.get_children(): self._technical_box.remove(child) - #FIXME: self._technical_box.foreach(self._technical_box.remove) + # FIXME: self._technical_box.foreach(self._technical_box.remove) self._technical_box.pack_start(self._create_technical(), False, False, style.DEFAULT_SPACING) for child in self._buddy_list.get_children(): self._buddy_list.remove(child) - #FIXME: self._buddy_list.foreach(self._buddy_list.remove) + # FIXME: self._buddy_list.foreach(self._buddy_list.remove) self._buddy_list.pack_start(self._create_buddy_list(), False, False, style.DEFAULT_SPACING) @@ -312,14 +318,6 @@ class ExpandedEntry(Gtk.EventBox): comments = metadata.get('comments', '') self._comments.update_comments(comments) - def set_comments(self, comments): - self._metadata['comments'] = comments - self._comments.update_comments(comments) - self._write_entry() - - def get_comments(self): - return self._metadata.get('comments', None) - def _create_keep_icon(self): keep_icon = KeepIcon() keep_icon.connect('toggled', self._keep_icon_toggled_cb) @@ -364,7 +362,7 @@ class ExpandedEntry(Gtk.EventBox): # TODO: We are close to be able to drop this. import base64 preview_data = base64.b64decode( - self._metadata['preview']) + self._metadata['preview']) png_file = StringIO.StringIO(preview_data) try: @@ -422,10 +420,11 @@ class ExpandedEntry(Gtk.EventBox): lines = [ _('Kind: %s') % (self._metadata.get('mime_type') or _('Unknown'),), _('Date: %s') % (self._format_date(),), - _('Size: %s') % (format_size(int(self._metadata.get( - 'filesize', - model.get_file_size(self._metadata['uid']))))) - ] + _('Size: %s') % (format_size( + int(self._metadata.get( + 'filesize', + model.get_file_size(self._metadata['uid']))))) + ] for line in lines: linebox = Gtk.HBox() @@ -433,7 +432,7 @@ class ExpandedEntry(Gtk.EventBox): text = Gtk.Label() text.set_markup('%s' % ( - style.COLOR_BUTTON_GREY.get_html(), line)) + style.COLOR_BUTTON_GREY.get_html(), line)) linebox.pack_start(text, False, False, 0) return vbox @@ -457,13 +456,13 @@ class ExpandedEntry(Gtk.EventBox): text = Gtk.Label() text.set_markup('%s' % ( - style.COLOR_BUTTON_GREY.get_html(), _('Participants:'))) + style.COLOR_BUTTON_GREY.get_html(), _('Participants:'))) halign = Gtk.Alignment.new(0, 0, 0, 0) halign.add(text) vbox.pack_start(halign, False, False, 0) if self._metadata.get('buddies'): - buddies = simplejson.loads(self._metadata['buddies']).values() + buddies = json.loads(self._metadata['buddies']).values() vbox.pack_start(BuddyList(buddies), False, False, 0) return vbox else: @@ -476,7 +475,7 @@ class ExpandedEntry(Gtk.EventBox): if label is not None: text = Gtk.Label() text.set_markup('%s' % ( - style.COLOR_BUTTON_GREY.get_html(), label)) + style.COLOR_BUTTON_GREY.get_html(), label)) halign = Gtk.Alignment.new(0, 0, 0, 0) halign.add(text) @@ -505,13 +504,14 @@ class ExpandedEntry(Gtk.EventBox): def _create_comments(self): widget = CommentsView() - widget.connect('comments-changed', self._update_comments_cb) - return self._create_scrollable(widget), widget + widget.connect('comments-changed', self._comments_changed_cb) + return self._create_scrollable(widget, label=_('Comments:')), widget def _title_notify_text_cb(self, entry, pspec): if not self._update_title_sid: - self._update_title_sid = GObject.timeout_add_seconds(1, - self._update_title_cb) + self._update_title_sid = \ + GObject.timeout_add_seconds(1, + self._update_title_cb) def _title_focus_out_event_cb(self, entry, event): self._update_entry() @@ -519,8 +519,9 @@ class ExpandedEntry(Gtk.EventBox): def _description_tags_focus_out_event_cb(self, text_view, event): self._update_entry() - def _update_comments_cb(self, event, comments): - self.set_comments(comments) + def _comments_changed_cb(self, event, comments): + self._metadata['comments'] = comments + self._write_entry() def _update_entry(self, needs_update=False): if not model.is_editable(self._metadata): @@ -563,7 +564,8 @@ class ExpandedEntry(Gtk.EventBox): else: old_file_path = os.path.join( self._metadata['mountpoint'], - model.get_file_name(old_title, self._metadata['mime_type'])) + model.get_file_name(self._metadata['title'], + self._metadata['mime_type'])) model.write(self._metadata, file_path=old_file_path, update_mtime=False) diff --git a/src/jarabe/journal/journalactivity.py b/src/jarabe/journal/journalactivity.py index 4bb68fd..d1afe12 100644 --- a/src/jarabe/journal/journalactivity.py +++ b/src/jarabe/journal/journalactivity.py @@ -26,7 +26,6 @@ import dbus import statvfs import os -from sugar3.graphics.window import Window from sugar3.graphics.alert import ErrorAlert from sugar3.bundle.bundle import ZipExtractException, RegistrationException @@ -63,12 +62,14 @@ class JournalActivityDBusService(dbus.service.Object): self._parent = parent session_bus = dbus.SessionBus() bus_name = dbus.service.BusName(J_DBUS_SERVICE, - bus=session_bus, replace_existing=False, allow_replacement=False) + bus=session_bus, + replace_existing=False, + allow_replacement=False) logging.debug('bus_name: %r', bus_name) dbus.service.Object.__init__(self, bus_name, J_DBUS_PATH) @dbus.service.method(J_DBUS_INTERFACE, - in_signature='s', out_signature='') + in_signature='s', out_signature='') def ShowObject(self, object_id): """Pop-up journal and show object with object_id""" @@ -93,7 +94,7 @@ class JournalActivityDBusService(dbus.service.Object): chooser_id = uuid.uuid4().hex if parent_xid > 0: display = Gdk.Display.get_default() - parent = GdkX11.X11Window.foreign_new_for_display( \ + parent = GdkX11.X11Window.foreign_new_for_display( display, parent_xid) else: parent = None @@ -324,7 +325,7 @@ class JournalActivity(JournalWindow): registry.install(bundle, metadata['uid']) except (ZipExtractException, RegistrationException): logging.exception('Could not install bundle %s', - bundle.get_path()) + bundle.get_path()) return try: diff --git a/src/jarabe/journal/journalentrybundle.py b/src/jarabe/journal/journalentrybundle.py index 87ae74b..79666b8 100644 --- a/src/jarabe/journal/journalentrybundle.py +++ b/src/jarabe/journal/journalentrybundle.py @@ -18,7 +18,7 @@ import os import tempfile import shutil -import simplejson +import json import dbus from sugar3.bundle.bundle import Bundle, MalformedBundleException @@ -70,13 +70,13 @@ class JournalEntryBundle(Bundle): metadata_path = os.path.join(bundle_dir, '_metadata.json') if not os.path.exists(metadata_path): raise MalformedBundleException( - 'Bundle must contain the file "_metadata.json"') + 'Bundle must contain the file "_metadata.json"') f = open(metadata_path, 'r') try: json_data = f.read() finally: f.close() - return simplejson.loads(json_data) + return json.loads(json_data) def _read_preview(self, uid, bundle_dir): preview_path = os.path.join(bundle_dir, 'preview', uid) diff --git a/src/jarabe/journal/journaltoolbox.py b/src/jarabe/journal/journaltoolbox.py index bdd16c3..6d2cf33 100644 --- a/src/jarabe/journal/journaltoolbox.py +++ b/src/jarabe/journal/journaltoolbox.py @@ -71,7 +71,7 @@ class MainToolbox(ToolbarBox): __gsignals__ = { 'query-changed': (GObject.SignalFlags.RUN_FIRST, None, ([object])), - } + } def __init__(self): ToolbarBox.__init__(self) @@ -98,7 +98,7 @@ class MainToolbox(ToolbarBox): self._what_search_combo = ComboBox() self._what_combo_changed_sid = self._what_search_combo.connect( - 'changed', self._combo_changed_cb) + 'changed', self._combo_changed_cb) tool_item = ToolComboBox(self._what_search_combo) self.toolbar.insert(tool_item, -1) tool_item.show() @@ -115,10 +115,10 @@ class MainToolbox(ToolbarBox): self._sorting_button.show() # TODO: enable it when the DS supports saving the buddies. - #self._with_search_combo = self._get_with_search_combo() - #tool_item = ToolComboBox(self._with_search_combo) - #self.insert(tool_item, -1) - #tool_item.show() + # self._with_search_combo = self._get_with_search_combo() + # tool_item = ToolComboBox(self._with_search_combo) + # self.insert(tool_item, -1) + # tool_item.show() self._query = self._build_query() @@ -130,7 +130,7 @@ class MainToolbox(ToolbarBox): when_search.append_separator() when_search.append_item(_ACTION_TODAY, _('Today')) when_search.append_item(_ACTION_SINCE_YESTERDAY, - _('Since yesterday')) + _('Since yesterday')) # TRANS: Filter entries modified during the last 7 days. when_search.append_item(_ACTION_PAST_WEEK, _('Past week')) # TRANS: Filter entries modified during the last 30 days. @@ -299,7 +299,7 @@ class MainToolbox(ToolbarBox): generic_type.type_id, generic_type.name, generic_type.icon) if generic_type.type_id == current_value: current_value_index = \ - len(self._what_search_combo.get_model()) - 1 + len(self._what_search_combo.get_model()) - 1 self._what_search_combo.set_active(current_value_index) @@ -317,9 +317,10 @@ class MainToolbox(ToolbarBox): # try activity-provided icon if os.path.exists(activity_info.get_icon()): try: - self._what_search_combo.append_item(service_name, - activity_info.get_name(), - file_name=activity_info.get_icon()) + self._what_search_combo.append_item( + service_name, + activity_info.get_name(), + file_name=activity_info.get_icon()) except GObject.GError, exception: logging.warning('Falling back to default icon for' ' "what" filter because %r (%r) has an' @@ -330,13 +331,14 @@ class MainToolbox(ToolbarBox): continue # fall back to generic icon - self._what_search_combo.append_item(service_name, - activity_info.get_name(), - icon_name='application-octet-stream') + self._what_search_combo.append_item( + service_name, + activity_info.get_name(), + icon_name='application-octet-stream') finally: self._what_search_combo.handler_unblock( - self._what_combo_changed_sid) + self._what_combo_changed_sid) def __favorite_button_toggled_cb(self, favorite_button): self._update_if_needed() @@ -352,13 +354,14 @@ class DetailToolbox(ToolbarBox): __gsignals__ = { 'volume-error': (GObject.SignalFlags.RUN_FIRST, None, ([str, str])), - } + } def __init__(self): ToolbarBox.__init__(self) self._metadata = None self._temp_file_path = None + self._refresh = None self._resume = ToolButton('activity-start') self._resume.connect('clicked', self._resume_clicked_cb) @@ -384,8 +387,9 @@ class DetailToolbox(ToolbarBox): self.toolbar.insert(self._duplicate, -1) if len(accountsmanager.get_configured_accounts()) > 0: + logging.debug('CONFIGURED ACCOUNTS: creating _refresh') self._refresh = ToolButton() - icon = Icon(icon_name='refresh', xo_color=color) + icon = Icon(icon_name='refresh-web-account-menu', xo_color=color) self._refresh.set_icon_widget(icon) icon.show() @@ -393,6 +397,8 @@ class DetailToolbox(ToolbarBox): self._refresh.connect('clicked', self._refresh_clicked_cb) self.toolbar.insert(self._refresh, -1) self._refresh.show() + else: + logging.debug('NO CONFIGURED ACCOUNTS') separator = Gtk.SeparatorToolItem() self.toolbar.insert(separator, -1) @@ -408,7 +414,8 @@ class DetailToolbox(ToolbarBox): self._metadata = metadata self._refresh_copy_palette() self._refresh_duplicate_palette() - self._refresh_refresh_palette() + if self._refresh is not None: + self._refresh_refresh_palette() self._refresh_resume_palette() def _resume_clicked_cb(self, button): @@ -421,7 +428,6 @@ class DetailToolbox(ToolbarBox): button.palette.popup(immediate=True, state=Palette.SECONDARY) def _duplicate_clicked_cb(self, button): - file_path = model.get_file(self._metadata['uid']) try: model.copy(self._metadata, '/') except IOError, e: @@ -511,7 +517,8 @@ class DetailToolbox(ToolbarBox): volume_menu.show() for account in accountsmanager.get_configured_accounts(): - menu = account.get_share_menu(self._metadata) + menu = account.get_shared_journal_entry().get_share_menu( + self._metadata) palette.menu.append(menu) def _refresh_duplicate_palette(self): @@ -533,7 +540,7 @@ class DetailToolbox(ToolbarBox): palette.menu.remove(menu_item) for account in accountsmanager.get_configured_accounts(): - menu = account.get_refresh_menu() + menu = account.get_shared_journal_entry().get_refresh_menu() palette.menu.append(menu) menu.set_metadata(self._metadata) @@ -557,9 +564,9 @@ class DetailToolbox(ToolbarBox): for activity_info in misc.get_activities(self._metadata): menu_item = MenuItem(activity_info.get_name()) menu_item.set_image(Icon(file=activity_info.get_icon(), - icon_size=Gtk.IconSize.MENU)) + icon_size=Gtk.IconSize.MENU)) menu_item.connect('activate', self._resume_menu_item_activate_cb, - activity_info.get_bundle_id()) + activity_info.get_bundle_id()) palette.menu.append(menu_item) menu_item.show() @@ -609,7 +616,7 @@ class SortingButton(ToolButton): def __sort_type_changed_cb(self, widget, property_, icon_name): self._property = property_ - #FIXME: Implement sorting order + # FIXME: Implement sorting order self._order = Gtk.SortType.ASCENDING self.emit('sort-property-changed') diff --git a/src/jarabe/journal/keepicon.py b/src/jarabe/journal/keepicon.py index 3515194..6062296 100644 --- a/src/jarabe/journal/keepicon.py +++ b/src/jarabe/journal/keepicon.py @@ -41,7 +41,7 @@ class KeepIcon(Gtk.ToggleButton): client = GConf.Client.get_default() self._xo_color = XoColor(client.get_string( - '/desktop/sugar/user/color')) + '/desktop/sugar/user/color')) def do_get_preferred_width(self): return 0, style.GRID_CELL_SIZE diff --git a/src/jarabe/journal/listmodel.py b/src/jarabe/journal/listmodel.py index b98d01c..dad0c76 100644 --- a/src/jarabe/journal/listmodel.py +++ b/src/jarabe/journal/listmodel.py @@ -16,7 +16,7 @@ import logging -import simplejson +import json from gi.repository import GObject from gi.repository import Gtk from gettext import gettext as _ @@ -109,7 +109,7 @@ class ListModel(GObject.GObject, Gtk.TreeModel, Gtk.TreeDragSource): return ListModel._COLUMN_TYPES[index] def do_iter_n_children(self, iterator): - if iterator == None: + if iterator is None: return self._result_set.length else: return 0 @@ -176,8 +176,8 @@ class ListModel(GObject.GObject, Gtk.TreeModel, Gtk.TreeDragSource): buddies = [] if metadata.get('buddies'): try: - buddies = simplejson.loads(metadata['buddies']).values() - except simplejson.decoder.JSONDecodeError, exception: + buddies = json.loads(metadata['buddies']).values() + except json.decoder.JSONDecodeError, exception: logging.warning('Cannot decode buddies for %r: %s', metadata['uid'], exception) @@ -237,14 +237,17 @@ class ListModel(GObject.GObject, Gtk.TreeModel, Gtk.TreeDragSource): def do_drag_data_get(self, path, selection): uid = self[path][ListModel.COLUMN_UID] - if selection.target == 'text/uri-list': + target_atom = selection.get_target() + target_name = target_atom.name() + if target_name == 'text/uri-list': # Get hold of a reference so the temp file doesn't get deleted self._temp_drag_file_path = model.get_file(uid) logging.debug('putting %r in selection', self._temp_drag_file_path) - selection.set(selection.target, 8, self._temp_drag_file_path) + selection.set(target_atom, 8, self._temp_drag_file_path) return True - elif selection.target == 'journal-object-id': - selection.set(selection.target, 8, uid) + elif target_name == 'journal-object-id': + # uid is unicode but Gtk.SelectionData.set() needs str + selection.set(target_atom, 8, str(uid)) return True return False diff --git a/src/jarabe/journal/listview.py b/src/jarabe/journal/listview.py index 3005d2f..ade324b 100644 --- a/src/jarabe/journal/listview.py +++ b/src/jarabe/journal/listview.py @@ -172,7 +172,6 @@ class BaseListView(Gtk.Bin): ListModel.COLUMN_TITLE) self.tree_view.append_column(self._title_column) - for column_index in [ListModel.COLUMN_BUDDY_1, ListModel.COLUMN_BUDDY_2, ListModel.COLUMN_BUDDY_3]: @@ -193,7 +192,7 @@ class BaseListView(Gtk.Bin): cell_progress.props.ypad = style.GRID_CELL_SIZE / 4 buddies_column.pack_start(cell_progress, True) buddies_column.add_attribute(cell_progress, 'value', - ListModel.COLUMN_PROGRESS) + ListModel.COLUMN_PROGRESS) buddies_column.set_cell_data_func(cell_progress, self.__progress_data_cb) @@ -289,8 +288,10 @@ class BaseListView(Gtk.Bin): property_ = query_dict['order_by'][0][1:] cell_text = self.sort_column.get_cells()[0] self.sort_column.set_attributes(cell_text, - text=getattr(ListModel, 'COLUMN_' + property_.upper(), - ListModel.COLUMN_TIMESTAMP)) + text=getattr( + ListModel, 'COLUMN_' + + property_.upper(), + ListModel.COLUMN_TIMESTAMP)) self._query = query_dict self.refresh() @@ -332,11 +333,12 @@ class BaseListView(Gtk.Bin): self.tree_view.get_bin_window().show() if len(tree_model) == 0: + documents_path = model.get_documents_path() if self._is_query_empty(): if self._query['mountpoints'] == ['/']: self._show_message(_('Your Journal is empty')) - elif self._query['mountpoints'] == \ - [model.get_documents_path()]: + elif documents_path and self._query['mountpoints'] == \ + [documents_path]: self._show_message(_('Your documents folder is empty')) else: self._show_message(_('The device is empty')) @@ -412,8 +414,8 @@ class BaseListView(Gtk.Bin): label = Gtk.Label() color = style.COLOR_BUTTON_GREY.get_html() - label.set_markup('%s' % ( \ - color, GLib.markup_escape_text(message))) + label.set_markup('%s' % ( + color, GLib.markup_escape_text(message))) box.pack_start(label, expand=True, fill=False, padding=0) if show_clear_query: @@ -483,8 +485,8 @@ class BaseListView(Gtk.Bin): if self._update_dates_timer is None: logging.debug('Adding date updating timer') self._update_dates_timer = \ - GObject.timeout_add_seconds(UPDATE_INTERVAL, - self.__update_dates_timer_cb) + GObject.timeout_add_seconds(UPDATE_INTERVAL, + self.__update_dates_timer_cb) else: self._fully_obscured = True if self._update_dates_timer is not None: @@ -517,7 +519,7 @@ class ListView(BaseListView): self.tree_view.connect('drag-begin', self.__drag_begin_cb) self.tree_view.connect('button-release-event', - self.__button_release_event_cb) + self.__button_release_event_cb) self.cell_title.connect('edited', self.__cell_title_edited_cb) self.cell_title.connect('editing-canceled', self.__editing_canceled_cb) @@ -631,7 +633,7 @@ class CellRendererActivityIcon(CellRendererIcon): 'detail-clicked': (GObject.SignalFlags.RUN_FIRST, None, ([str])), 'volume-error': (GObject.SignalFlags.RUN_FIRST, None, - ([str, str])), + ([str, str])), } def __init__(self, tree_view): @@ -696,8 +698,10 @@ class CellRendererBuddy(CellRendererIcon): # if row[self._model_column_index] is not None: # nick, xo_color = row[self._model_column_index] - if row.model.do_get_value(row.iter, self._model_column_index) is not None: - nick, xo_color = row.model.do_get_value(row.iter, self._model_column_index) + if row.model.do_get_value(row.iter, self._model_column_index) \ + is not None: + nick, xo_color = row.model.do_get_value( + row.iter, self._model_column_index) return BuddyPalette((nick, xo_color.to_string())) else: return None diff --git a/src/jarabe/journal/misc.py b/src/jarabe/journal/misc.py index efd0dbe..30556a3 100644 --- a/src/jarabe/journal/misc.py +++ b/src/jarabe/journal/misc.py @@ -216,7 +216,7 @@ def resume(metadata, bundle_id=None): activities = get_activities(metadata) if not activities: logging.warning('No activity can open this object, %s.', - metadata.get('mime_type', None)) + metadata.get('mime_type', None)) return bundle_id = activities[0].get_bundle_id() @@ -228,19 +228,19 @@ def resume(metadata, bundle_id=None): object_id = model.copy(metadata, '/') launch(bundle, activity_id=activity_id, object_id=object_id, - color=get_icon_color(metadata)) + color=get_icon_color(metadata)) def _launch_bundle(bundle): registry = bundleregistry.get_registry() logging.debug('activityfactory.creating bundle with id %r', - bundle.get_bundle_id()) + bundle.get_bundle_id()) installed_bundle = registry.get_bundle(bundle.get_bundle_id()) if installed_bundle: launch(installed_bundle) else: logging.error('Bundle %r is not installed.', - bundle.get_bundle_id()) + bundle.get_bundle_id()) def launch(bundle, activity_id=None, object_id=None, uri=None, color=None, @@ -249,7 +249,7 @@ def launch(bundle, activity_id=None, object_id=None, uri=None, color=None, activity_id = activityfactory.create_activity_id() logging.debug('launch bundle_id=%s activity_id=%s object_id=%s uri=%s', - bundle.get_bundle_id(), activity_id, object_id, uri) + bundle.get_bundle_id(), activity_id, object_id, uri) shell_model = shell.get_model() activity = shell_model.get_activity_by_id(activity_id) @@ -264,7 +264,9 @@ def launch(bundle, activity_id=None, object_id=None, uri=None, color=None, launcher.add_launcher(activity_id, bundle.get_icon(), color) activity_handle = ActivityHandle(activity_id=activity_id, - object_id=object_id, uri=uri, invited=invited) + object_id=object_id, + uri=uri, + invited=invited) activityfactory.create(bundle, activity_handle) @@ -272,7 +274,7 @@ def _downgrade_option_alert(bundle): alert = ConfirmationAlert() alert.props.title = _('Older Version Of %s Activity') % (bundle.get_name()) alert.props.msg = _('Do you want to downgrade to version %s') % \ - bundle.get_activity_version() + bundle.get_activity_version() alert.connect('response', _downgrade_alert_response_cb, bundle) journalwindow.get_journal_window().add_alert(alert) alert.show() @@ -303,7 +305,7 @@ def is_journal_bundle(metadata): def is_bundle(metadata): return is_activity_bundle(metadata) or is_content_bundle(metadata) or \ - is_journal_bundle(metadata) + is_journal_bundle(metadata) def get_icon_color(metadata): diff --git a/src/jarabe/journal/modalalert.py b/src/jarabe/journal/modalalert.py index db7a81f..b911c0b 100644 --- a/src/jarabe/journal/modalalert.py +++ b/src/jarabe/journal/modalalert.py @@ -66,10 +66,11 @@ class ModalAlert(Gtk.Window): self._vbox.pack_start(self._title, expand=False, fill=False, padding=0) self._title.show() - self._message = Gtk.Label(label=_('Please delete some old Journal' - ' entries to make space for new ones.')) + self._message = Gtk.Label( + label=_('Please delete some old Journal' + ' entries to make space for new ones.')) self._message.modify_fg(Gtk.StateType.NORMAL, - style.COLOR_WHITE.get_gdk_color()) + style.COLOR_WHITE.get_gdk_color()) self._vbox.pack_start(self._message, expand=False, fill=False, padding=0) self._message.show() diff --git a/src/jarabe/journal/model.py b/src/jarabe/journal/model.py index 0a5b354..07c34ac 100644 --- a/src/jarabe/journal/model.py +++ b/src/jarabe/journal/model.py @@ -25,13 +25,15 @@ import tempfile from stat import S_IFLNK, S_IFMT, S_IFDIR, S_IFREG import re from operator import itemgetter -import simplejson +import json from gettext import gettext as _ -from gi.repository import GObject import dbus from gi.repository import Gio from gi.repository import GConf +from gi.repository import GLib + +from gi.repository import SugarExt from sugar3 import dispatch from sugar3 import mime @@ -130,7 +132,7 @@ class BaseResultSet(object): remaining_forward_entries = 0 else: remaining_forward_entries = self._offset + len(self._cache) - \ - self._position + self._position if self._position > self._offset + len(self._cache): remaining_backwards_entries = 0 @@ -145,7 +147,7 @@ class BaseResultSet(object): limit = self._page_size * MIN_PAGES_TO_CACHE offset = max(0, self._position - limit / 2) logging.debug('remaking cache, offset: %r limit: %r', offset, - limit) + limit) query = self._query.copy() query['limit'] = limit query['offset'] = offset @@ -160,7 +162,7 @@ class BaseResultSet(object): # Add one page to the end of cache logging.debug('appending one more page, offset: %r', - last_cached_entry) + last_cached_entry) query = self._query.copy() query['limit'] = self._page_size query['offset'] = last_cached_entry @@ -184,7 +186,7 @@ class BaseResultSet(object): self._offset = max(0, self._offset - limit) logging.debug('prepending one more page, offset: %r limit: %r', - self._offset, limit) + self._offset, limit) query = self._query.copy() query['limit'] = limit query['offset'] = self._offset @@ -269,7 +271,7 @@ class InplaceResultSet(BaseResultSet): self._pending_directories = [self._mount_point] self._visited_directories = [] self._pending_files = [] - GObject.idle_add(self._scan) + GLib.idle_add(self._scan) def stop(self): self._stopped = True @@ -395,7 +397,7 @@ class InplaceResultSet(BaseResultSet): if self._mime_types: mime_type, uncertain_result_ = \ - Gio.content_type_guess(filename=full_path, data=None) + Gio.content_type_guess(filename=full_path, data=None) if mime_type not in self._mime_types: return @@ -467,7 +469,7 @@ def _get_file_metadata_from_json(dir_path, filename, fetch_preview): return None try: - metadata = simplejson.load(open(metadata_path)) + metadata = json.load(open(metadata_path)) except (ValueError, EnvironmentError): os.unlink(metadata_path) if os.path.exists(preview_path): @@ -638,7 +640,7 @@ def write(metadata, file_path='', update_mtime=True, transfer_ownership=True): """Creates or updates an entry for that id """ logging.debug('model.write %r %r %r', metadata.get('uid', ''), file_path, - update_mtime) + update_mtime) if update_mtime: metadata['mtime'] = datetime.now().isoformat() metadata['timestamp'] = int(time.time()) @@ -646,13 +648,13 @@ def write(metadata, file_path='', update_mtime=True, transfer_ownership=True): if metadata.get('mountpoint', '/') == '/': if metadata.get('uid', ''): object_id = _get_datastore().update(metadata['uid'], - dbus.Dictionary(metadata), - file_path, - transfer_ownership) + dbus.Dictionary(metadata), + file_path, + transfer_ownership) else: object_id = _get_datastore().create(dbus.Dictionary(metadata), - file_path, - transfer_ownership) + file_path, + transfer_ownership) else: object_id = _write_entry_on_external_device(metadata, file_path) @@ -720,6 +722,10 @@ def _write_entry_on_external_device(metadata, file_path): if not os.path.exists(metadata_dir_path): os.mkdir(metadata_dir_path) + if SugarExt.fat_set_hidden_attrib(metadata_dir_path) == 0: + logging.error('Could not set hidden attribute on %s' % + (metadata_dir_path)) + preview = None if 'preview' in metadata_copy: preview = metadata_copy['preview'] @@ -727,7 +733,7 @@ def _write_entry_on_external_device(metadata, file_path): metadata_copy.pop('preview', None) try: - metadata_json = simplejson.dumps(metadata_copy) + metadata_json = json.dumps(metadata_copy) except (UnicodeDecodeError, EnvironmentError): logging.error('Could not convert metadata to json.') else: diff --git a/src/jarabe/journal/objectchooser.py b/src/jarabe/journal/objectchooser.py index 8a664c4..9315192 100644 --- a/src/jarabe/journal/objectchooser.py +++ b/src/jarabe/journal/objectchooser.py @@ -45,6 +45,7 @@ class ObjectChooser(Gtk.Window): self.set_decorated(False) self.set_position(Gtk.WindowPosition.CENTER_ALWAYS) self.set_border_width(style.LINE_WIDTH) + self.set_has_resize_grip(False) self._selected_object_id = None @@ -100,7 +101,7 @@ class ObjectChooser(Gtk.Window): self._toolbar.set_what_filter(what_filter) def __realize_cb(self, chooser, parent): - self.set_transient_for(parent) + self.get_window().set_transient_for(parent) # TODO: Should we disconnect the signal here? def __window_closed_cb(self, screen, window, parent): diff --git a/src/jarabe/journal/palettes.py b/src/jarabe/journal/palettes.py index cc604dc..fb49dd4 100644 --- a/src/jarabe/journal/palettes.py +++ b/src/jarabe/journal/palettes.py @@ -121,7 +121,7 @@ class ObjectPalette(Palette): friends_menu.connect('friend-selected', self.__friend_selected_cb) menu_item.set_submenu(friends_menu) - if detail == True: + if detail is True: menu_item = MenuItem(_('View Details'), 'go-right') menu_item.connect('activate', self.__detail_activate_cb) self.menu.append(menu_item) @@ -136,7 +136,6 @@ class ObjectPalette(Palette): misc.resume(self._metadata) def __duplicate_activate_cb(self, menu_item): - file_path = model.get_file(self._metadata['uid']) try: model.copy(self._metadata, '/') except IOError, e: @@ -242,7 +241,7 @@ class CopyMenu(Gtk.Menu): if self._metadata['mountpoint'] == mount.get_root().get_path(): continue volume_menu = VolumeMenu(self._metadata, mount.get_name(), - mount.get_root().get_path()) + mount.get_root().get_path()) for name in mount.get_icon().props.names: if icon_theme.has_icon(name): volume_menu.set_image(Icon(icon_name=name, @@ -253,7 +252,7 @@ class CopyMenu(Gtk.Menu): volume_menu.show() for account in accountsmanager.get_configured_accounts(): - menu = account.get_share_menu(metadata) + menu = account.get_shared_journal_entry().get_share_menu(metadata) self.append(menu) def __volume_error_cb(self, menu_item, message, severity): diff --git a/src/jarabe/journal/volumestoolbar.py b/src/jarabe/journal/volumestoolbar.py index e1e6331..8b7f212 100644 --- a/src/jarabe/journal/volumestoolbar.py +++ b/src/jarabe/journal/volumestoolbar.py @@ -27,7 +27,7 @@ from gi.repository import Gdk from gi.repository import GConf import cPickle import xapian -import simplejson +import json import tempfile import shutil @@ -74,7 +74,7 @@ def _convert_entries(root): 'index')) except xapian.DatabaseError: logging.exception('Convert DS-0 Journal entries: error reading db: %s', - os.path.join(root, _JOURNAL_0_METADATA_DIR, 'index')) + os.path.join(root, _JOURNAL_0_METADATA_DIR, 'index')) return metadata_dir_path = os.path.join(root, model.JOURNAL_METADATA_DIR) @@ -151,7 +151,7 @@ def _convert_entry(root, document): metadata_fname) if not os.path.exists(metadata_path): (fh, fn) = tempfile.mkstemp(dir=root) - os.write(fh, simplejson.dumps(metadata)) + os.write(fh, json.dumps(metadata)) os.close(fh) os.rename(fn, metadata_path) @@ -183,7 +183,7 @@ class VolumesToolbar(Gtk.Toolbar): self.connect('destroy', self.__destroy_cb) - GObject.idle_add(self._set_up_volumes) + GLib.idle_add(self._set_up_volumes) def __destroy_cb(self, widget): volume_monitor = Gio.VolumeMonitor.get() @@ -196,7 +196,8 @@ class VolumesToolbar(Gtk.Toolbar): volume_monitor = Gio.VolumeMonitor.get() self._mount_added_hid = volume_monitor.connect('mount-added', self.__mount_added_cb) - self._mount_removed_hid = volume_monitor.connect('mount-removed', + self._mount_removed_hid = volume_monitor.connect( + 'mount-removed', self.__mount_removed_cb) for mount in volume_monitor.get_mounts(): @@ -229,7 +230,7 @@ class VolumesToolbar(Gtk.Toolbar): if os.path.exists(os.path.join(mount.get_root().get_path(), _JOURNAL_0_METADATA_DIR)): logging.debug('Convert DS-0 Journal entries: starting conversion') - GObject.idle_add(_convert_entries, mount.get_root().get_path()) + GLib.idle_add(_convert_entries, mount.get_root().get_path()) button = VolumeButton(mount) button.props.group = self._volume_buttons[0] @@ -291,7 +292,7 @@ class BaseButton(RadioToolButton): def _drag_data_received_cb(self, widget, drag_context, x, y, selection_data, info, timestamp): - object_id = selection_data.data + object_id = selection_data.get_data() metadata = model.get(object_id) file_path = model.get_file(metadata['uid']) if not file_path or not os.path.exists(file_path): @@ -336,8 +337,8 @@ class VolumeButton(BaseButton): def create_palette(self): palette = VolumePalette(self._mount) - #palette.props.invoker = FrameWidgetInvoker(self) - #palette.set_group_id('frame') + # palette.props.invoker = FrameWidgetInvoker(self) + # palette.set_group_id('frame') return palette @@ -383,7 +384,7 @@ class JournalButtonPalette(Palette): fraction = (total_space - free_space) / float(total_space) self._progress_bar.props.fraction = fraction self._free_space_label.props.label = _('%(free_space)d MB Free') % \ - {'free_space': free_space / (1024 * 1024)} + {'free_space': free_space / (1024 * 1024)} class DocumentsButton(BaseButton): diff --git a/src/jarabe/web/Makefile.am b/src/jarabe/web/Makefile.am index a2caada..b51b5a9 100644 --- a/src/jarabe/web/Makefile.am +++ b/src/jarabe/web/Makefile.am @@ -1,5 +1,5 @@ sugardir = $(pythondir)/jarabe/web -sugar_PYTHON = \ - __init__.py \ - account.py \ +sugar_PYTHON = \ + __init__.py \ + account.py \ accountsmanager.py diff --git a/src/jarabe/web/__init__.py b/src/jarabe/web/__init__.py index 85f6a24..e69de29 100644 --- a/src/jarabe/web/__init__.py +++ b/src/jarabe/web/__init__.py @@ -1,15 +0,0 @@ -# Copyright (C) 2006-2007, Red Hat, Inc. -# -# 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA diff --git a/src/jarabe/web/account.py b/src/jarabe/web/account.py index 2e55f25..c089cbc 100644 --- a/src/jarabe/web/account.py +++ b/src/jarabe/web/account.py @@ -1,4 +1,5 @@ # Copyright (c) 2013 Walter Bender, Raul Gutierrez Segales +# Copyright (c) 2013 SugarLabs # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public @@ -15,19 +16,18 @@ # Free Software Foundation, Inc., 59 Temple Place - Suite 330, # Boston, MA 02111-1307, USA. -import logging - from gi.repository import GObject -from sugar3.graphics.menuitem import MenuItem -from sugar3.graphics.toolbutton import ToolButton - class Account(): ''' Account is a prototype class for online accounts. It provides - stubs for five public methods that are used by online services + stubs for public methods that are used by online services. ''' + STATE_NONE = 0 + STATE_VALID = 1 + STATE_EXPIRED = 2 + def get_description(self): ''' get_description returns a brief description of the online service. The description is used in palette menuitems and on @@ -38,25 +38,49 @@ class Account(): ''' raise NotImplementedError - def is_configured(self): - ''' is_configured returns True if the service has been - configured for use, e.g., an access token has been acquired. - - :returns: configuration status - :rtype: bool + def get_token_state(self): + ''' get_token_state returns an enum to describe the state of + the online service: + State.NONE means there is no token, e.g., the service is not + configured. + State.VALID means there is a valid token, e.g., the service is + available for use. + State.EXPIRED means the token is no longer valid. + + :returns: token state + :rtype: enum ''' raise NotImplementedError - def is_active(self): - ''' is_active returns True if the service is currently - available, e.g., the access token has not expired. + def get_shared_journal_entry(self): + ''' get_shared_journal_entry returns a class used to + intermediate between the online service and the Sugar UI + elements. - :returns: active status - :rtype: bool + :returns: SharedJournalEntry() + :rtype: SharedJournalEntry ''' - raise NotImplementedError + return NotImplemented + - def get_share_menu(self): +class SharedJournalEntry(): + ''' SharedJournalEntry is a class used to intermediate between the + online service and the Sugar UI elements (MenuItems used in the + Journal UI) for online accounts. It provides stubs for public + methods that are used by online services. + + The comments-changed signal is emitted by the online service if + changes to the 'comments' metadata have been made. + + :emits: metadata['comments'] + :type: string + ''' + + __gsignals__ = { + 'comments-changed': (GObject.SignalFlags.RUN_FIRST, None, ([str])) + } + + def get_share_menu(self, metadata): ''' get_share_menu returns a menu item used on the Copy To palette in the Journal and on the Journal detail-view toolbar. @@ -71,67 +95,11 @@ class Account(): ''' get_refresh_menu returns a menu item used on the Journal detail-view toolbar. - :param: journal_entry_metadata - :type: dict :returns: MenuItem :rtype: MenuItem ''' raise NotImplementedError - -class MenuItem(MenuItem): - ''' This is a subclass of sugar3.graphics.menuitem.MenuItem - - The transfer signals are used to update progress of data transfer - between Sugar and the online service. Signal handlers in the - journaltoolbox manage a Notification Alert of this progress. - - 'transfer-started' is emitted at the beginning of a transfer. - - 'transfer-progress' is emitted periodically to indicate progress. - - :emits: total data to transfer - :type: float - :emits: quantity of data transfered - :type: float - :emits: message string - :type: string - - 'transfer-completed' is emitted at the successful completion of a - transfer. - - :emits: message string - :type: string - - 'transfer-failed' is emitted at if the transfer fails. - - :emits: message string - :type: string - - 'transfer-state-changed' is emitted when the account manager wants - to indicate a change in state. - - :emits: message string - :type: string - - The comments-changed signal is emitted by the online service if - changes to the 'comments' metadata have been made. The - expandedentry of the Journal detail view displays these comments. - - :emits: metadata['comments'] - :type: string - ''' - __gsignals__ = { - 'transfer-started': (GObject.SignalFlags.RUN_FIRST, None, ([])), - 'transfer-progress': (GObject.SignalFlags.RUN_FIRST, None, - ([int, int, str])), - 'transfer-completed': (GObject.SignalFlags.RUN_FIRST, None, ([str])), - 'transfer-failed': (GObject.SignalFlags.RUN_FIRST, None, ([str])), - 'transfer-state-changed': (GObject.SignalFlags.RUN_FIRST, None, - ([str])), - 'comments-changed': (GObject.SignalFlags.RUN_FIRST, None, ([str])) - } - def set_metadata(self, metadata): ''' The online account uses this method to set metadata in the Sugar journal and provide a means of updating menuitem status, diff --git a/src/jarabe/web/accountsmanager.py b/src/jarabe/web/accountsmanager.py index cd1da83..fb7b632 100644 --- a/src/jarabe/web/accountsmanager.py +++ b/src/jarabe/web/accountsmanager.py @@ -21,13 +21,14 @@ import logging from gi.repository import Gtk from jarabe import config +from jarabe.web.account import Account _accounts = [] def get_all_accounts(): ''' Returns a list of all installed online account managers ''' - global _accounts # No need to do this every time. + global _accounts if len(_accounts) > 0: return _accounts @@ -54,8 +55,8 @@ def _load_module(dir_path): for f in os.listdir(dir_path): if f == 'account.py': module_name = f[:-3] - logging.debug('OnlineAccountsManager loading %s' % ( - module_name)) + logging.debug('OnlineAccountsManager loading %s' % + (module_name)) module_path = 'web.%s.%s' % (os.path.basename(dir_path), module_name) try: @@ -65,8 +66,8 @@ def _load_module(dir_path): module = mod.get_account() except Exception as e: - logging.exception('Exception while loading %s: %s' % ( - module_name, str(e))) + logging.exception('Exception while loading %s: %s' % + (module_name, str(e))) return module @@ -90,8 +91,11 @@ def _extend_icon_theme_search_path(dir_path): def get_configured_accounts(): - return [a for a in get_all_accounts() if a.is_configured()] + return [a for a in get_all_accounts() + if a.get_token_state() in (Account.STATE_VALID, + Account.STATE_EXPIRED)] def get_active_accounts(): - return [a for a in get_all_accounts() if a.is_active()] + return [a for a in get_all_accounts() + if a.get_token_state() == Account.STATE_VALID] -- cgit v0.9.1