Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWalter Bender <walter@sugarlabs.org>2013-06-09 22:06:54 (GMT)
committer Walter Bender <walter@sugarlabs.org>2013-06-09 22:06:54 (GMT)
commit208a68e451635883d0c6f58e56c8308bafe8b16c (patch)
tree042c5c1b888c2ec49d14af5d041fcbf350785365
parent2db9dee01ab0e12a6b53c0da844b285a9312cab1 (diff)
refactoring based on lasted commits upstream
-rw-r--r--extensions/cpsection/webservices/services/facebook/service.py10
-rw-r--r--extensions/cpsection/webservices/services/twitter/service.py2
-rw-r--r--extensions/web/facebook/account.py85
-rw-r--r--extensions/web/twitter/account.py84
-rw-r--r--src/jarabe/journal/detailview.py2
-rw-r--r--src/jarabe/journal/expandedentry.py82
-rw-r--r--src/jarabe/journal/journalactivity.py11
-rw-r--r--src/jarabe/journal/journalentrybundle.py6
-rw-r--r--src/jarabe/journal/journaltoolbox.py55
-rw-r--r--src/jarabe/journal/keepicon.py2
-rw-r--r--src/jarabe/journal/listmodel.py19
-rw-r--r--src/jarabe/journal/listview.py32
-rw-r--r--src/jarabe/journal/misc.py18
-rw-r--r--src/jarabe/journal/modalalert.py7
-rw-r--r--src/jarabe/journal/model.py38
-rw-r--r--src/jarabe/journal/objectchooser.py3
-rw-r--r--src/jarabe/journal/palettes.py7
-rw-r--r--src/jarabe/journal/volumestoolbar.py21
-rw-r--r--src/jarabe/web/Makefile.am6
-rw-r--r--src/jarabe/web/__init__.py15
-rw-r--r--src/jarabe/web/account.py118
-rw-r--r--src/jarabe/web/accountsmanager.py18
22 files changed, 334 insertions, 307 deletions
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('<span foreground="%s">%s</span>' % (
- 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('<span foreground="%s">%s</span>' % (
- 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('<span foreground="%s">%s</span>' % (
- 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('<span weight="bold" color="%s">%s</span>' % ( \
- color, GLib.markup_escape_text(message)))
+ label.set_markup('<span weight="bold" color="%s">%s</span>' % (
+ 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]