Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMarco Pesenti Gritti <mpgritti@gmail.com>2008-09-17 02:31:06 (GMT)
committer Marco Pesenti Gritti <mpgritti@gmail.com>2008-09-17 02:31:06 (GMT)
commit1f95a1575d8b4508683109dc0e1cf4d782bf4fcd (patch)
tree17352f5c71288c859f1e959128622309999220c5 /src
parentefad564146a8b70c834b4bc128ad729144006f71 (diff)
parenta2db7381f0f82c271565ab221da8dcfd3c0e4b4b (diff)
Merge branch 'master' of git+ssh://dev.laptop.org/git/sugar
Diffstat (limited to 'src')
-rw-r--r--src/intro/Makefile.am1
-rw-r--r--src/intro/glive.py200
-rw-r--r--src/journal/palettes.py4
-rw-r--r--src/model/Makefile.am2
-rw-r--r--src/model/clipboard.py149
-rw-r--r--src/model/clipboardobject.py117
-rw-r--r--src/view/Shell.py25
-rw-r--r--src/view/clipboardicon.py85
-rw-r--r--src/view/clipboardmenu.py109
-rw-r--r--src/view/frame/clipboardpanelwindow.py13
-rw-r--r--src/view/frame/clipboardtray.py28
-rw-r--r--src/view/home/favoritesview.py8
12 files changed, 388 insertions, 353 deletions
diff --git a/src/intro/Makefile.am b/src/intro/Makefile.am
index 025f4e6..089c84a 100644
--- a/src/intro/Makefile.am
+++ b/src/intro/Makefile.am
@@ -6,5 +6,4 @@ sugardir = $(pkgdatadir)/shell/intro
sugar_PYTHON = \
__init__.py \
colorpicker.py \
- glive.py \
window.py
diff --git a/src/intro/glive.py b/src/intro/glive.py
deleted file mode 100644
index a2ddbae..0000000
--- a/src/intro/glive.py
+++ /dev/null
@@ -1,200 +0,0 @@
-# -*- Mode: Python -*-
-# vi:si:et:sw=4:sts=4:ts=4
-
-import gtk
-import pygtk
-pygtk.require('2.0')
-
-import pygst
-pygst.require('0.10')
-import gst
-import gst.interfaces
-
-import gobject
-gobject.threads_init()
-
-class Glive(gobject.GObject):
- __gsignals__ = {
- 'new-picture': (gobject.SIGNAL_RUN_FIRST,
- gobject.TYPE_NONE,
- ([gobject.TYPE_PYOBJECT])),
- 'sink' : (gobject.SIGNAL_RUN_FIRST,
- gobject.TYPE_NONE,
- ([gobject.TYPE_PYOBJECT]))
- }
-
- def __init__(self, parent, width, height):
- gobject.GObject.__init__(self)
- self._parent = parent
-
- #check out the halfpipe, d00d.
- self.pipeline = gst.Pipeline()
-
- self.v4l2src = gst.element_factory_make("v4l2src", "v4l2src")
- self.t = gst.element_factory_make("tee", "tee")
- self.t_src_pad = self.t.get_request_pad( "src%d" )
- self.vscale = gst.element_factory_make("videoscale", "videoscale")
- self.ximagesink = gst.element_factory_make("ximagesink", "ximagesink")
-
- self.pipeline.add(self.v4l2src)
- self.pipeline.add(self.t)
- self.pipeline.add(self.vscale)
- self.pipeline.add(self.ximagesink)
-
- self.v4l2src.link(self.t)
-
- videoscale_structure = gst.Structure("video/x-raw-rgb")
- videoscale_structure['width'] = width
- videoscale_structure['height'] = height
- videoscale_structure['bpp'] = 16
- videoscale_structure['depth'] = 16
- videoscale_caps = gst.Caps(videoscale_structure)
- self.t_src_pad.link(self.vscale.get_pad("sink"))
- self.vscale.link(self.ximagesink, videoscale_caps)
- #self.vscale.link(self.ximagesink)
-
- self.queue = gst.element_factory_make("queue", "queue")
- self.queue.set_property("leaky", True)
- self.queue.set_property("max-size-buffers", 1)
- self.qsrc = self.queue.get_pad( "src" )
- self.qsink = self.queue.get_pad("sink")
- self.ffmpeg = gst.element_factory_make( \
- "ffmpegcolorspace", "ffmpegcolorspace")
- self.jpgenc = gst.element_factory_make("jpegenc", "jpegenc")
- self.filesink = gst.element_factory_make("fakesink", "fakesink")
- self.filesink.connect( "handoff", self.copyframe )
- self.filesink.set_property("signal-handoffs", True)
- self.pipeline.add(self.queue, self.ffmpeg, self.jpgenc, self.filesink)
-
- #only link at snapshot time
- #self.t.link(self.queue)
- self.queue.link(self.ffmpeg)
- self.ffmpeg.link(self.jpgenc)
- self.jpgenc.link(self.filesink)
- self.exposureOpen = False
-
- self._bus = self.pipeline.get_bus()
- self._CONNECT_SYNC = -1
- self._CONNECT_MSG = -1
- self.doPostBusStuff()
-
- def copyframe(self, fsink, buf, pad, user_data=None):
- #for some reason, we get two back to back buffers, even though we
- #ask for only one.
- if (self.exposureOpen):
- self.exposureOpen = False
- piccy = gtk.gdk.pixbuf_loader_new_with_mime_type("image/jpeg")
- piccy.write(buf)
- piccy.close()
- pixbuf = piccy.get_pixbuf()
- del piccy
-
- self.t.unlink(self.queue)
- self.queue.set_property("leaky", True)
-
- gobject.idle_add(self.loadPic, pixbuf)
-
- def loadPic( self, pixbuf ):
- self.emit('new-picture', pixbuf)
-
- def takeSnapshot( self ):
- if (self.exposureOpen):
- return
- else:
- self.exposureOpen = True
- self.t.link(self.queue)
-
- def doPostBusStuff(self):
- self._bus.enable_sync_message_emission()
- self._bus.add_signal_watch()
- self._CONNECT_SYNC = self._bus.connect('sync-message::element',
- self.on_sync_message)
- self._CONNECT_MSG = self._bus.connect('message', self.on_message)
-
- def on_sync_message(self, bus, message):
- if message.structure is None:
- return
- if message.structure.get_name() == 'prepare-xwindow-id':
- self.emit('sink', message.src)
- message.src.set_property('force-aspect-ratio', True)
-
- def on_message(self, bus, message):
- t = message.type
- if (t == gst.MESSAGE_ERROR):
- if (self.on_eos):
- self.on_eos()
- elif (t == gst.MESSAGE_EOS):
- if (self.on_eos):
- self.on_eos()
-
- def on_eos( self ):
- pass
-
- def stop(self):
- self.pipeline.set_state(gst.STATE_NULL)
-
- def play(self):
- self.pipeline.set_state(gst.STATE_PLAYING)
-
- def pause(self):
- self.pipeline.set_state(gst.STATE_PAUSED)
-
-
-class LiveVideoSlot(gtk.EventBox):
- __gsignals__ = {
- 'pixbuf': (gobject.SIGNAL_RUN_FIRST,
- gobject.TYPE_NONE,
- ([gobject.TYPE_PYOBJECT]))
- }
-
- def __init__(self, width, height):
- gtk.EventBox.__init__(self)
-
- self.imagesink = None
- self.playa = None
- self._width = width
- self._height = height
-
- self.unset_flags(gtk.DOUBLE_BUFFERED)
- self.connect('focus-in-event', self.focus_in)
- self.connect('focus-out-event', self.focus_out)
- self.connect("button-press-event", self._button_press_event_cb)
- self.connect("expose-event", self._expose_event_cb)
-
- def _expose_event_cb(self, widget, event):
- if not self.playa:
- self.playa = Glive(self, self._width, self._height)
- self.playa.connect('new-picture', self._new_picture_cb)
- self.playa.connect('sink', self._new_sink_cb)
-
- def _new_picture_cb(self, playa, pixbuf):
- self.emit('pixbuf', pixbuf)
-
- def _new_sink_cb(self, playa, sink):
- if (self.imagesink != None):
- assert self.window.xid
- self.imagesink = None
- del self.imagesink
- self.imagesink = sink
- self.imagesink.set_xwindow_id(self.window.xid)
-
- def _button_press_event_cb(self, widget, event):
- self.takeSnapshot()
-
- def focus_in(self, widget, event, args=None):
- self.play()
-
- def focus_out(self, widget, event, args=None):
- self.stop()
-
- def play( self ):
- self.playa.play()
-
- def pause( self ):
- self.playa.pause()
-
- def stop( self ):
- self.playa.stop()
-
- def takeSnapshot( self ):
- self.playa.takeSnapshot()
diff --git a/src/journal/palettes.py b/src/journal/palettes.py
index f186c68..81efc03 100644
--- a/src/journal/palettes.py
+++ b/src/journal/palettes.py
@@ -15,7 +15,8 @@
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
from gettext import gettext as _
-
+import logging
+
import gtk
from sugar import profile
@@ -86,6 +87,7 @@ class ObjectPalette(Palette):
self.__clipboard_clear_func_cb)
def __clipboard_get_func_cb(self, clipboard, selection_data, info, data):
+ logging.debug('__clipboard_get_func_cb %r' % self._jobject.file_path)
selection_data.set_uris(['file://' + self._jobject.file_path])
def __clipboard_clear_func_cb(self, clipboard, data):
diff --git a/src/model/Makefile.am b/src/model/Makefile.am
index 0b7d14c..9447b03 100644
--- a/src/model/Makefile.am
+++ b/src/model/Makefile.am
@@ -5,6 +5,8 @@ sugar_PYTHON = \
__init__.py \
accesspointmodel.py \
BuddyModel.py \
+ clipboard.py \
+ clipboardobject.py \
Friends.py \
Invites.py \
Owner.py \
diff --git a/src/model/clipboard.py b/src/model/clipboard.py
new file mode 100644
index 0000000..bde6535
--- /dev/null
+++ b/src/model/clipboard.py
@@ -0,0 +1,149 @@
+# Copyright (C) 2006, 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
+
+import logging
+import os
+import shutil
+import urlparse
+import tempfile
+
+import gobject
+
+from sugar import mime
+
+from model.clipboardobject import ClipboardObject, Format
+
+class Clipboard(gobject.GObject):
+
+ __gsignals__ = {
+ 'object-added': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
+ ([object])),
+ 'object-deleted': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
+ ([int])),
+ 'object-state-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
+ ([object])),
+ }
+
+ def __init__(self):
+ gobject.GObject.__init__(self)
+
+ self._objects = {}
+ self._next_id = 0
+
+ def _get_next_object_id(self):
+ self._next_id += 1
+ return self._next_id
+
+ def add_object(self, name):
+ logging.debug('Clipboard.add_object')
+ object_id = self._get_next_object_id()
+ self._objects[object_id] = ClipboardObject(object_id, name)
+ self.emit('object-added', self._objects[object_id])
+ return object_id
+
+ def add_object_format(self, object_id, format_type, data, on_disk):
+ logging.debug('Clipboard.add_object_format')
+ cb_object = self._objects[object_id]
+
+ if format_type == 'XdndDirectSave0':
+ format = Format('text/uri-list', data + '\r\n', on_disk)
+ format.owns_disk_data = True
+ cb_object.add_format(format)
+ elif on_disk and cb_object.get_percent() == 100:
+ new_uri = self._copy_file(data)
+ cb_object.add_format(Format(format_type, new_uri, on_disk))
+ logging.debug('Added format of type ' + format_type
+ + ' with path at ' + new_uri)
+ else:
+ cb_object.add_format(Format(format_type, data, on_disk))
+ logging.debug('Added in-memory format of type ' + format_type + '.')
+
+ self.emit('object-state-changed', cb_object)
+
+ def delete_object(self, object_id):
+ cb_object = self._objects.pop(object_id)
+ cb_object.destroy()
+ self.emit('object-deleted', object_id)
+ logging.debug('Deleted object with object_id %r' % object_id)
+
+ def set_object_percent(self, object_id, percent):
+ cb_object = self._objects[object_id]
+ if percent < 0 or percent > 100:
+ raise ValueError("invalid percentage")
+ if cb_object.get_percent() > percent:
+ raise ValueError("invalid percentage; less than current percent")
+ if cb_object.get_percent() == percent:
+ # ignore setting same percentage
+ return
+
+ cb_object.set_percent(percent)
+
+ if percent == 100:
+ self._process_object(cb_object)
+
+ self.emit('object-state-changed', cb_object)
+
+ def _process_object(self, cb_object):
+ formats = cb_object.get_formats()
+ for format_name, format in formats.iteritems():
+ if format.is_on_disk() and not format.owns_disk_data:
+ new_uri = self._copy_file(format.get_data())
+ format.set_data(new_uri)
+
+ # Add a text/plain format to objects that are text but lack it
+ if 'text/plain' not in formats.keys():
+ if 'UTF8_STRING' in formats.keys():
+ self.add_object_format(
+ cb_object.get_id(), 'text/plain',
+ data=formats['UTF8_STRING'].get_data(), on_disk=False)
+ elif 'text/unicode' in formats.keys():
+ self.add_object_format(
+ cb_object.get_id(), 'text/plain',
+ data=formats['UTF8_STRING'].get_data(), on_disk=False)
+
+ def get_object(self, object_id):
+ logging.debug('Clipboard.get_object')
+ return self._objects[object_id]
+
+ def get_object_data(self, object_id, format_type):
+ logging.debug('Clipboard.get_object_data')
+ cb_object = self._objects[object_id]
+ format = cb_object.get_formats()[format_type]
+ return format
+
+ def _copy_file(self, original_uri):
+ uri = urlparse.urlparse(original_uri)
+ path_, file_name = os.path.split(uri.path)
+
+ root, ext = os.path.splitext(file_name)
+ if not ext or ext == '.':
+ mime_type = mime.get_for_file(uri.path)
+ ext = '.' + mime.get_primary_extension(mime_type)
+
+ f_, new_file_path = tempfile.mkstemp(ext, root)
+ del f_
+ shutil.copyfile(uri.path, new_file_path)
+ os.chmod(new_file_path, 0644)
+
+ return 'file://' + new_file_path
+
+_instance = None
+
+def get_instance():
+ global _instance
+ if not _instance:
+ _instance = Clipboard()
+ return _instance
diff --git a/src/model/clipboardobject.py b/src/model/clipboardobject.py
new file mode 100644
index 0000000..a4cd388
--- /dev/null
+++ b/src/model/clipboardobject.py
@@ -0,0 +1,117 @@
+# Copyright (C) 2007, One Laptop Per Child
+#
+# 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
+
+import os
+import logging
+import urlparse
+
+from sugar import mime
+from sugar.bundle.activitybundle import ActivityBundle
+
+class ClipboardObject(object):
+
+ def __init__(self, object_path, name):
+ self._id = object_path
+ self._name = name
+ self._percent = 0
+ self._formats = {}
+
+ def destroy(self):
+ for format in self._formats.itervalues():
+ format.destroy()
+
+ def get_id(self):
+ return self._id
+
+ def get_name(self):
+ name = self._name
+ if not name:
+ name = mime.get_mime_description(self.get_mime_type())
+ if not name:
+ name = ''
+ return name
+
+ def get_icon(self):
+ return mime.get_mime_icon(self.get_mime_type())
+
+ def get_preview(self):
+ # TODO: should previews really be here?
+ #return self._get_type_info().get_preview()
+ return ''
+
+ def is_bundle(self):
+ # A bundle will have only one format.
+ if not self._formats:
+ return False
+ else:
+ return self._formats.keys()[0] in [ActivityBundle.MIME_TYPE,
+ ActivityBundle.DEPRECATED_MIME_TYPE]
+
+ def get_percent(self):
+ return self._percent
+
+ def set_percent(self, percent):
+ self._percent = percent
+
+ def add_format(self, format):
+ self._formats[format.get_type()] = format
+
+ def get_formats(self):
+ return self._formats
+
+ def get_mime_type(self):
+ if not self._formats:
+ return ''
+
+ format = mime.choose_most_significant(self._formats.keys())
+ if format == 'text/uri-list':
+ data = self._formats['text/uri-list'].get_data()
+ uri = urlparse.urlparse(mime.split_uri_list(data)[0], 'file')
+ if uri.scheme == 'file':
+ if os.path.exists(uri.path):
+ format = mime.get_for_file(uri.path)
+ else:
+ format = mime.get_from_file_name(uri.path)
+ logging.debug('Choosed %r!' % format)
+
+ return format
+
+class Format(object):
+
+ def __init__(self, mime_type, data, on_disk):
+ self.owns_disk_data = False
+
+ self._type = mime_type
+ self._data = data
+ self._on_disk = on_disk
+
+ def destroy(self):
+ if self._on_disk:
+ uri = urlparse.urlparse(self._data)
+ if os.path.isfile(uri.path):
+ os.remove(uri.path)
+
+ def get_type(self):
+ return self._type
+
+ def get_data(self):
+ return self._data
+
+ def set_data(self, data):
+ self._data = data
+
+ def is_on_disk(self):
+ return self._on_disk
diff --git a/src/view/Shell.py b/src/view/Shell.py
index 33dcbc0..26a66e6 100644
--- a/src/view/Shell.py
+++ b/src/view/Shell.py
@@ -251,22 +251,19 @@ class Shell(gobject.GObject):
screenshot.get_from_drawable(window, window.get_colormap(), x_orig,
y_orig, 0, 0, width, height)
screenshot.save(file_path, "png")
+ jobject = datastore.create()
try:
- jobject = datastore.create()
- try:
- jobject.metadata['title'] = _('Screenshot')
- jobject.metadata['keep'] = '0'
- jobject.metadata['buddies'] = ''
- jobject.metadata['preview'] = ''
- jobject.metadata['icon-color'] = profile.get_color().to_string()
- jobject.metadata['mime_type'] = 'image/png'
- jobject.file_path = file_path
- datastore.write(jobject)
- finally:
- jobject.destroy()
- del jobject
+ jobject.metadata['title'] = _('Screenshot')
+ jobject.metadata['keep'] = '0'
+ jobject.metadata['buddies'] = ''
+ jobject.metadata['preview'] = ''
+ jobject.metadata['icon-color'] = profile.get_color().to_string()
+ jobject.metadata['mime_type'] = 'image/png'
+ jobject.file_path = file_path
+ datastore.write(jobject, transfer_ownership=True)
finally:
- os.remove(file_path)
+ jobject.destroy()
+ del jobject
_instance = None
diff --git a/src/view/clipboardicon.py b/src/view/clipboardicon.py
index 729b97d..c5b6ae7 100644
--- a/src/view/clipboardicon.py
+++ b/src/view/clipboardicon.py
@@ -21,10 +21,9 @@ import gtk
from sugar.graphics.radiotoolbutton import RadioToolButton
from sugar.graphics.icon import Icon
from sugar.graphics.xocolor import XoColor
-from sugar.clipboard import clipboardservice
-from sugar.bundle.activitybundle import ActivityBundle
from sugar import profile
+from model import clipboard
from view.clipboardmenu import ClipboardMenu
from view.frame.frameinvoker import FrameWidgetInvoker
from view.frame.notification import NotificationIcon
@@ -33,66 +32,51 @@ import view.frame.frame
class ClipboardIcon(RadioToolButton):
__gtype_name__ = 'SugarClipboardIcon'
- def __init__(self, object_id, name, group):
+ def __init__(self, cb_object, group):
RadioToolButton.__init__(self, group=group)
- self._object_id = object_id
- self._name = name
- self._percent = 0
- self._preview = None
- self._activity = None
+ self._cb_object = cb_object
self.owns_clipboard = False
self.props.sensitive = False
self.props.active = False
self._notif_icon = None
+ self._current_percent = None
self._icon = Icon()
self._icon.props.xo_color = profile.get_color()
self.set_icon_widget(self._icon)
self._icon.show()
- cb_service = clipboardservice.get_instance()
+ cb_service = clipboard.get_instance()
cb_service.connect('object-state-changed',
self._object_state_changed_cb)
- obj = cb_service.get_object(self._object_id)
- self.palette = ClipboardMenu(self._object_id, self._name, self._percent,
- self._preview, self._activity,
- self._is_bundle(obj['FORMATS']))
+ self.palette = ClipboardMenu(cb_object)
self.palette.props.invoker = FrameWidgetInvoker(self)
child = self.get_child()
child.connect('drag_data_get', self._drag_data_get_cb)
self.connect('notify::active', self._notify_active_cb)
- def _is_bundle(self, formats):
- # A bundle will have only one format.
- return formats and formats[0] in [ActivityBundle.MIME_TYPE,
- ActivityBundle.DEPRECATED_MIME_TYPE]
-
def get_object_id(self):
- return self._object_id
+ return self._cb_object.get_id()
- def _drag_data_get_cb(self, widget, context, selection,
- targetType, eventTime):
+ def _drag_data_get_cb(self, widget, context, selection, target_type,
+ event_time):
logging.debug('_drag_data_get_cb: requested target ' + selection.target)
-
- cb_service = clipboardservice.get_instance()
- data = cb_service.get_object_data(self._object_id,
- selection.target)['DATA']
-
+ data = self._cb_object.get_formats()[selection.target].get_data()
selection.set(selection.target, 8, data)
def _put_in_clipboard(self):
logging.debug('ClipboardIcon._put_in_clipboard')
- if self._percent < 100:
+ if self._cb_object.get_percent() < 100:
raise ValueError('Object is not complete,' \
' cannot be put into the clipboard.')
targets = self._get_targets()
if targets:
- clipboard = gtk.Clipboard()
- if not clipboard.set_with_data(targets,
+ x_clipboard = gtk.Clipboard()
+ if not x_clipboard.set_with_data(targets,
self._clipboard_data_get_cb,
self._clipboard_clear_cb,
targets):
@@ -100,32 +84,24 @@ class ClipboardIcon(RadioToolButton):
else:
self.owns_clipboard = True
- def _clipboard_data_get_cb(self, clipboard, selection, info, targets):
+ def _clipboard_data_get_cb(self, x_clipboard, selection, info, targets):
if not selection.target in [target[0] for target in targets]:
logging.warning('ClipboardIcon._clipboard_data_get_cb: asked %s' \
' but only have %r.' % (selection.target, targets))
return
- cb_service = clipboardservice.get_instance()
- data = cb_service.get_object_data(self._object_id,
- selection.target)['DATA']
-
+ data = self._cb_object.get_formats()[selection.target].get_data()
selection.set(selection.target, 8, data)
- def _clipboard_clear_cb(self, clipboard, targets):
+ def _clipboard_clear_cb(self, x_clipboard, targets):
logging.debug('ClipboardIcon._clipboard_clear_cb')
self.owns_clipboard = False
- def _object_state_changed_cb(self, cb_service, object_id, name, percent,
- icon_name, preview, activity):
-
- if object_id != self._object_id:
+ def _object_state_changed_cb(self, cb_service, cb_object):
+ if cb_object != self._cb_object:
return
- cb_service = clipboardservice.get_instance()
- obj = cb_service.get_object(self._object_id)
-
- if icon_name:
- self._icon.props.icon_name = icon_name
+ if cb_object.get_icon():
+ self._icon.props.icon_name = cb_object.get_icon()
else:
self._icon.props.icon_name = 'application-octet-stream'
@@ -135,19 +111,11 @@ class ClipboardIcon(RadioToolButton):
gtk.gdk.ACTION_COPY)
child.drag_source_set_icon_name(self._icon.props.icon_name)
- self._name = name
- self._preview = preview
- self._activity = activity
- self.palette.update_state(name, percent, preview, activity,
- self._is_bundle(obj['FORMATS']))
-
- old_percent = self._percent
- self._percent = percent
- if self._percent == 100:
+ if cb_object.get_percent() == 100:
self.props.sensitive = True
# Clipboard object became complete. Make it the active one.
- if old_percent < 100 and self._percent == 100:
+ if self._current_percent < 100 and cb_object.get_percent() == 100:
self.props.active = True
self._notif_icon = NotificationIcon()
@@ -158,6 +126,7 @@ class ClipboardIcon(RadioToolButton):
frame = view.frame.frame.get_instance()
frame.add_notification(self._notif_icon,
view.frame.frame.BOTTOM_LEFT)
+ self._current_percent = cb_object.get_percent()
def _notify_active_cb(self, widget, pspec):
if self.props.active:
@@ -166,14 +135,8 @@ class ClipboardIcon(RadioToolButton):
self.owns_clipboard = False
def _get_targets(self):
- cb_service = clipboardservice.get_instance()
-
- attrs = cb_service.get_object(self._object_id)
- format_types = attrs[clipboardservice.FORMATS_KEY]
-
targets = []
- for format_type in format_types:
+ for format_type in self._cb_object.get_formats().keys():
targets.append((format_type, 0, 0))
-
return targets
diff --git a/src/view/clipboardmenu.py b/src/view/clipboardmenu.py
index f036aeb..c5e4cef 100644
--- a/src/view/clipboardmenu.py
+++ b/src/view/clipboardmenu.py
@@ -25,24 +25,26 @@ import gtk
from sugar.graphics.palette import Palette
from sugar.graphics.menuitem import MenuItem
from sugar.graphics.icon import Icon
-from sugar.clipboard import clipboardservice
from sugar.datastore import datastore
from sugar import mime
from sugar import profile
from sugar import activity
+from model import clipboard
+
class ClipboardMenu(Palette):
- def __init__(self, object_id, name, percent, preview,
- activities, installable):
- Palette.__init__(self, name)
+ def __init__(self, cb_object):
+ Palette.__init__(self, cb_object.get_name())
- self._object_id = object_id
- self._percent = percent
- self._activities = activities
+ self._cb_object = cb_object
self.set_group_id('frame')
+ cb_service = clipboard.get_instance()
+ cb_service.connect('object-state-changed',
+ self._object_state_changed_cb)
+
self._progress_bar = None
self._remove_item = MenuItem(_('Remove'), 'list-remove')
@@ -55,11 +57,6 @@ class ClipboardMenu(Palette):
self.menu.append(self._open_item)
self._open_item.show()
- #self._stop_item = MenuItem(_('Stop download'), 'stock-close')
- # TODO: Implement stopping downloads
- #self._stop_item.connect('activate', self._stop_item_activate_cb)
- #self.append_menu_item(self._stop_item)
-
self._journal_item = MenuItem(_('Keep'))
icon = Icon(icon_name='document-save', icon_size=gtk.ICON_SIZE_MENU,
xo_color=profile.get_color())
@@ -69,13 +66,14 @@ class ClipboardMenu(Palette):
self.menu.append(self._journal_item)
self._journal_item.show()
- self._update_items_visibility(installable)
+ self._update_items_visibility()
self._update_open_submenu()
def _update_open_submenu(self):
- logging.debug('_update_open_submenu: %r' % self._activities)
+ activities = self._get_activities()
+ logging.debug('_update_open_submenu: %r' % activities)
child = self._open_item.get_child()
- if self._activities is None or len(self._activities) <= 1:
+ if activities is None or len(activities) <= 1:
child.set_text(_('Open'))
if self._open_item.get_submenu() is not None:
self._open_item.remove_submenu()
@@ -91,7 +89,7 @@ class ClipboardMenu(Palette):
for item in submenu.get_children():
submenu.remove(item)
- for service_name in self._activities:
+ for service_name in activities:
registry = activity.get_registry()
activity_info = registry.get_activity(service_name)
@@ -104,29 +102,41 @@ class ClipboardMenu(Palette):
submenu.append(item)
item.show()
- def _update_items_visibility(self, installable):
- if self._percent == 100 and (self._activities or installable):
+ def _update_items_visibility(self):
+ activities = self._get_activities()
+ installable = self._cb_object.is_bundle()
+ percent = self._cb_object.get_percent()
+
+ if percent == 100 and (activities or installable):
self._remove_item.props.sensitive = True
self._open_item.props.sensitive = True
- #self._stop_item.props.sensitive = False
self._journal_item.props.sensitive = True
- elif self._percent == 100 and \
- (not self._activities and not installable):
+ elif percent == 100 and (not activities and not installable):
self._remove_item.props.sensitive = True
self._open_item.props.sensitive = False
- #self._stop_item.props.sensitive = False
self._journal_item.props.sensitive = True
else:
self._remove_item.props.sensitive = True
self._open_item.props.sensitive = False
- # TODO: reenable the stop item when we implement stoping downloads.
- #self._stop_item.props.sensitive = True
self._journal_item.props.sensitive = False
self._update_progress_bar()
+ def _get_activities(self):
+ mime_type = self._cb_object.get_mime_type()
+ if not mime_type:
+ return ''
+
+ registry = activity.get_registry()
+ activities = registry.get_activities_for_type(mime_type)
+ if activities:
+ return [activity_info.bundle_id for activity_info in activities]
+ else:
+ return ''
+
def _update_progress_bar(self):
- if self._percent == 100.0:
+ percent = self._cb_object.get_percent()
+ if percent == 100.0:
if self._progress_bar:
self._progress_bar = None
self.set_content(None)
@@ -136,20 +146,21 @@ class ClipboardMenu(Palette):
self._progress_bar.show()
self.set_content(self._progress_bar)
- self._progress_bar.props.fraction = self._percent / 100.0
- self._progress_bar.props.text = '%.2f %%' % self._percent
+ self._progress_bar.props.fraction = percent / 100.0
+ self._progress_bar.props.text = '%.2f %%' % percent
- def update_state(self, name, percent, preview, activities, installable):
- self.set_primary_text(name)
- self._percent = percent
- self._activities = activities
+ def _object_state_changed_cb(self, cb_service, cb_object):
+ if cb_object != self._cb_object:
+ return
+ self.set_primary_text(cb_object.get_name())
self._update_progress_bar()
- self._update_items_visibility(installable)
+ self._update_items_visibility()
self._update_open_submenu()
def _open_item_activate_cb(self, menu_item):
logging.debug('_open_item_activate_cb')
- if self._percent < 100 or menu_item.get_submenu() is not None:
+ percent = self._cb_object.get_percent()
+ if percent < 100 or menu_item.get_submenu() is not None:
return
jobject = self._copy_to_journal()
jobject.resume(self._activities[0])
@@ -157,15 +168,16 @@ class ClipboardMenu(Palette):
def _open_submenu_item_activate_cb(self, menu_item, service_name):
logging.debug('_open_submenu_item_activate_cb')
- if self._percent < 100:
+ percent = self._cb_object.get_percent()
+ if percent < 100:
return
jobject = self._copy_to_journal()
jobject.resume(service_name)
jobject.destroy()
def _remove_item_activate_cb(self, menu_item):
- cb_service = clipboardservice.get_instance()
- cb_service.delete_object(self._object_id)
+ cb_service = clipboard.get_instance()
+ cb_service.delete_object(self._cb_object.get_id())
def _journal_item_activate_cb(self, menu_item):
logging.debug('_journal_item_activate_cb')
@@ -181,39 +193,38 @@ class ClipboardMenu(Palette):
return file_path
def _copy_to_journal(self):
- cb_service = clipboardservice.get_instance()
- obj = cb_service.get_object(self._object_id)
-
- format = mime.choose_most_significant(obj['FORMATS'])
- data = cb_service.get_object_data(self._object_id, format)
+ formats = self._cb_object.get_formats().keys()
+ most_significant_mime_type = mime.choose_most_significant(formats)
+ format = self._cb_object.get_formats()[most_significant_mime_type]
transfer_ownership = False
- if format == 'text/uri-list':
- uris = mime.split_uri_list(data['DATA'])
+ if most_significant_mime_type == 'text/uri-list':
+ uris = mime.split_uri_list(format.get_data())
if len(uris) == 1 and uris[0].startswith('file://'):
file_path = urlparse.urlparse(uris[0]).path
transfer_ownership = False
mime_type = mime.get_for_file(file_path)
else:
- file_path = self._write_to_temp_file(data['DATA'])
+ file_path = self._write_to_temp_file(format.get_data())
transfer_ownership = True
mime_type = 'text/uri-list'
else:
- if data['ON_DISK']:
- file_path = urlparse.urlparse(data['DATA']).path
+ if format.is_on_disk():
+ file_path = urlparse.urlparse(format.get_data()).path
transfer_ownership = False
mime_type = mime.get_for_file(file_path)
else:
- file_path = self._write_to_temp_file(data['DATA'])
+ file_path = self._write_to_temp_file(format.get_data())
transfer_ownership = True
sniffed_mime_type = mime.get_for_file(file_path)
if sniffed_mime_type == 'application/octet-stream':
- mime_type = format
+ mime_type = most_significant_mime_type
else:
mime_type = sniffed_mime_type
+ name = self._cb_object.get_name()
jobject = datastore.create()
- jobject.metadata['title'] = _('Clipboard object: %s.') % obj['NAME']
+ jobject.metadata['title'] = _('%s clipping') % name
jobject.metadata['keep'] = '0'
jobject.metadata['buddies'] = ''
jobject.metadata['preview'] = ''
diff --git a/src/view/frame/clipboardpanelwindow.py b/src/view/frame/clipboardpanelwindow.py
index 10b234b..08794b8 100644
--- a/src/view/frame/clipboardpanelwindow.py
+++ b/src/view/frame/clipboardpanelwindow.py
@@ -22,7 +22,8 @@ import hippo
from view.frame.framewindow import FrameWindow
from view.frame.clipboardtray import ClipboardTray
-from sugar.clipboard import clipboardservice
+
+from model import clipboard
class ClipboardPanelWindow(FrameWindow):
def __init__(self, frame, orientation):
@@ -47,22 +48,22 @@ class ClipboardPanelWindow(FrameWindow):
self.connect("drag_data_received",
self._clipboard_tray.drag_data_received_cb)
- def _owner_change_cb(self, clipboard, event):
+ def _owner_change_cb(self, x_clipboard, event):
logging.debug("owner_change_cb")
if self._clipboard_tray.owns_clipboard():
return
- cb_service = clipboardservice.get_instance()
+ cb_service = clipboard.get_instance()
key = cb_service.add_object(name="")
cb_service.set_object_percent(key, percent=0)
- targets = clipboard.wait_for_targets()
+ targets = x_clipboard.wait_for_targets()
for target in targets:
if target not in ('TIMESTAMP', 'TARGETS',
'MULTIPLE', 'SAVE_TARGETS'):
logging.debug('Asking for target %s.' % target)
- selection = clipboard.wait_for_contents(target)
+ selection = x_clipboard.wait_for_contents(target)
if not selection:
logging.warning('no data for selection target %s.' % target)
continue
@@ -77,7 +78,7 @@ class ClipboardPanelWindow(FrameWindow):
logging.debug('adding type ' + selection.type + '.')
- cb_service = clipboardservice.get_instance()
+ cb_service = clipboard.get_instance()
if selection.type == 'text/uri-list':
uris = selection.get_uris()
diff --git a/src/view/frame/clipboardtray.py b/src/view/frame/clipboardtray.py
index b5ba093..8c3939f 100644
--- a/src/view/frame/clipboardtray.py
+++ b/src/view/frame/clipboardtray.py
@@ -21,13 +21,13 @@ import tempfile
import gtk
from sugar import util
-from sugar.clipboard import clipboardservice
from sugar.graphics import tray
from sugar.graphics import style
+from model import clipboard
from view.clipboardicon import ClipboardIcon
-class _ContextMap:
+class _ContextMap(object):
"""Maps a drag context to the clipboard object involved in the dragging."""
def __init__(self):
self._context_map = {}
@@ -65,7 +65,7 @@ class ClipboardTray(tray.VTray):
self._icons = {}
self._context_map = _ContextMap()
- cb_service = clipboardservice.get_instance()
+ cb_service = clipboard.get_instance()
cb_service.connect('object-added', self._object_added_cb)
cb_service.connect('object-deleted', self._object_deleted_cb)
@@ -79,9 +79,9 @@ class ClipboardTray(tray.VTray):
if not selection.data:
return
- logging.debug('ClipboardTray: adding type ' + selection.type)
+ logging.debug('ClipboardTray: adding type %r' % selection.type)
- cb_service = clipboardservice.get_instance()
+ cb_service = clipboard.get_instance()
if selection.type == 'text/uri-list':
uris = selection.data.split('\n')
if len(uris) > 1:
@@ -98,30 +98,30 @@ class ClipboardTray(tray.VTray):
selection.data,
on_disk=False)
- def _object_added_cb(self, cb_service, object_id, name):
+ def _object_added_cb(self, cb_service, cb_object):
if self._icons:
group = self._icons.values()[0]
else:
group = None
- icon = ClipboardIcon(object_id, name, group)
+ icon = ClipboardIcon(cb_object, group)
self.add_item(icon)
icon.show()
- self._icons[object_id] = icon
+ self._icons[cb_object.get_id()] = icon
objects_to_delete = self.get_children()[:-self.MAX_ITEMS]
for icon in objects_to_delete:
logging.debug('ClipboardTray: deleting surplus object')
- cb_service = clipboardservice.get_instance()
+ cb_service = clipboard.get_instance()
cb_service.delete_object(icon.get_object_id())
- logging.debug('ClipboardTray: ' + object_id + ' was added.')
+ logging.debug('ClipboardTray: %r was added' % cb_object.get_id())
def _object_deleted_cb(self, cb_service, object_id):
icon = self._icons[object_id]
self.remove_item(icon)
del self._icons[object_id]
- logging.debug('ClipboardTray: ' + object_id + ' was deleted.')
+ logging.debug('ClipboardTray: %r was deleted' % object_id)
def drag_motion_cb(self, widget, context, x, y, time):
logging.debug('ClipboardTray._drag_motion_cb')
@@ -130,7 +130,7 @@ class ClipboardTray(tray.VTray):
def drag_drop_cb(self, widget, context, x, y, time):
logging.debug('ClipboardTray._drag_drop_cb')
- cb_service = clipboardservice.get_instance()
+ cb_service = clipboard.get_instance()
object_id = cb_service.add_object(name="")
self._context_map.add_context(context, object_id, len(context.targets))
@@ -179,8 +179,8 @@ class ClipboardTray(tray.VTray):
prop_type, format_, dest = \
window.property_get('XdndDirectSave0', 'text/plain')
- clipboard = clipboardservice.get_instance()
- clipboard.add_object_format( \
+ clipboardservice = clipboard.get_instance()
+ clipboardservice.add_object_format( \
object_id, 'XdndDirectSave0', dest, on_disk=True)
else:
self._add_selection(object_id, selection)
diff --git a/src/view/home/favoritesview.py b/src/view/home/favoritesview.py
index 409504c..d66649f 100644
--- a/src/view/home/favoritesview.py
+++ b/src/view/home/favoritesview.py
@@ -404,13 +404,7 @@ class _MyIcon(MyIcon):
#secondary_text='Sample secondary label',
icon=palette_icon)
- item = MenuItem(_('Control Panel'))
-
- icon = Icon(icon_name='computer-xo', icon_size=gtk.ICON_SIZE_MENU,
- xo_color=self._profile.color)
- item.set_image(icon)
- icon.show()
-
+ item = MenuItem(_('Settings'), 'preferences-system')
item.connect('activate', self.__controlpanel_activate_cb)
palette.menu.append(item)
item.show()