Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--services/clipboard/ClipboardService.py76
-rw-r--r--services/clipboard/Makefile.am4
-rw-r--r--services/clipboard/clipboardobject.py38
-rw-r--r--services/clipboard/clipboardservice.py119
-rwxr-xr-xservices/clipboard/sugar-clipboard2
-rw-r--r--shell/view/Makefile.am4
-rw-r--r--shell/view/clipboardicon.py (renamed from shell/view/ClipboardIcon.py)22
-rw-r--r--shell/view/clipboardmenu.py (renamed from shell/view/ClipboardMenu.py)3
-rw-r--r--shell/view/frame/ClipboardBox.py42
-rw-r--r--shell/view/frame/Frame.py46
-rw-r--r--shell/view/frame/Makefile.am3
-rw-r--r--shell/view/frame/PanelWindow.py5
-rw-r--r--shell/view/frame/clipboardbox.py183
-rw-r--r--shell/view/frame/clipboardpanelwindow.py64
-rw-r--r--sugar/clipboard/Makefile.am2
-rw-r--r--sugar/clipboard/clipboardservice.py (renamed from sugar/clipboard/ClipboardService.py)50
16 files changed, 496 insertions, 167 deletions
diff --git a/services/clipboard/ClipboardService.py b/services/clipboard/ClipboardService.py
deleted file mode 100644
index d8a151d..0000000
--- a/services/clipboard/ClipboardService.py
+++ /dev/null
@@ -1,76 +0,0 @@
-# vi: ts=4 ai noet
-#
-# 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 gobject
-import dbus
-import dbus.service
-from sugar import env
-
-class ClipboardDBusServiceHelper(dbus.service.Object):
-
- _CLIPBOARD_DBUS_INTERFACE = "org.laptop.Clipboard"
- _CLIPBOARD_OBJECT_PATH = "/org/laptop/Clipboard"
-
- def __init__(self, parent):
- self._parent = parent
-
- bus = dbus.SessionBus()
- bus_name = dbus.service.BusName(self._CLIPBOARD_DBUS_INTERFACE, bus=bus)
- dbus.service.Object.__init__(self, bus_name, self._CLIPBOARD_OBJECT_PATH)
-
- @dbus.service.method(_CLIPBOARD_DBUS_INTERFACE,
- in_signature="sss", out_signature="")
- def add_object(self, name, mimeType, fileName):
- self.object_added(name, mimeType, fileName)
- logging.debug('Added object of type ' + mimeType + ' with path at ' + fileName)
-
- @dbus.service.method(_CLIPBOARD_DBUS_INTERFACE,
- in_signature="s", out_signature="")
- def delete_object(self, fileName):
- self.object_deleted(fileName)
- logging.debug('Deleted object with path at ' + fileName)
-
- @dbus.service.method(_CLIPBOARD_DBUS_INTERFACE,
- in_signature="si", out_signature="")
- def set_object_state(self, fileName, percent):
- logging.debug('Changed object with path at ' + fileName + ' with percent ' + str(percent))
- self.object_state_changed(fileName, percent)
-
- @dbus.service.signal(_CLIPBOARD_DBUS_INTERFACE, signature="sss")
- def object_added(self, name, mimeType, fileName):
- pass
-
- @dbus.service.signal(_CLIPBOARD_DBUS_INTERFACE, signature="s")
- def object_deleted(self, fileName):
- pass
-
- @dbus.service.signal(_CLIPBOARD_DBUS_INTERFACE, signature="si")
- def object_state_changed(self, fileName, percent):
- pass
-
-class ClipboardService(object):
- def __init__(self):
- self._dbus_helper = ClipboardDBusServiceHelper(self)
-
- def run(self):
- loop = gobject.MainLoop()
- try:
- loop.run()
- except KeyboardInterrupt:
- print 'Ctrl+C pressed, exiting...'
diff --git a/services/clipboard/Makefile.am b/services/clipboard/Makefile.am
index 4f4d8a3..130a33c 100644
--- a/services/clipboard/Makefile.am
+++ b/services/clipboard/Makefile.am
@@ -8,7 +8,9 @@ $(service_DATA): $(service_in_files) Makefile
sugardir = $(pkgdatadir)/services/clipboard
sugar_PYTHON = \
__init__.py \
- ClipboardService.py
+ clipboardobject.py \
+ clipboardservice.py
+
bin_SCRIPTS = sugar-clipboard
diff --git a/services/clipboard/clipboardobject.py b/services/clipboard/clipboardobject.py
new file mode 100644
index 0000000..fd15363
--- /dev/null
+++ b/services/clipboard/clipboardobject.py
@@ -0,0 +1,38 @@
+class ClipboardObject:
+
+ def __init__(self, id, name):
+ self._id = id
+ self._name = name
+ self._percent = 0
+ self._formats = {}
+
+ def get_id(self):
+ return self._id
+
+ def get_name(self):
+ return self._name
+
+ 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
+
+class Format:
+
+ def __init__(self, type, data, on_disk):
+ self._type = type
+ self._data = data
+ self._on_disk = on_disk
+
+ def get_type(self):
+ return self._type
+
+ def get_data(self):
+ return self._data
diff --git a/services/clipboard/clipboardservice.py b/services/clipboard/clipboardservice.py
new file mode 100644
index 0000000..02ee7ac
--- /dev/null
+++ b/services/clipboard/clipboardservice.py
@@ -0,0 +1,119 @@
+# 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 gobject
+import dbus
+import dbus.service
+from sugar import env
+from clipboardobject import ClipboardObject, Format
+
+class ClipboardDBusServiceHelper(dbus.service.Object):
+
+ _CLIPBOARD_DBUS_INTERFACE = "org.laptop.Clipboard"
+ _CLIPBOARD_OBJECT_PATH = "/org/laptop/Clipboard"
+
+ def __init__(self, parent):
+ self._parent = parent
+ self._objects = {}
+
+ bus = dbus.SessionBus()
+ bus_name = dbus.service.BusName(self._CLIPBOARD_DBUS_INTERFACE, bus=bus)
+ dbus.service.Object.__init__(self, bus_name, self._CLIPBOARD_OBJECT_PATH)
+
+ # dbus methods
+ @dbus.service.method(_CLIPBOARD_DBUS_INTERFACE,
+ in_signature="ss", out_signature="")
+ def add_object(self, object_id, name):
+ self._objects[object_id] = ClipboardObject(object_id, name)
+ self.object_added(object_id, name)
+ logging.debug('Added object ' + object_id + ' with name ' + name)
+
+ @dbus.service.method(_CLIPBOARD_DBUS_INTERFACE,
+ in_signature="ssayb", out_signature="")
+ def add_object_format(self, object_id, format_type, data, on_disk):
+
+ # FIXME: Take it out when using the 0.80 dbus bindings
+ s = ""
+ for i in data:
+ s += chr(i)
+
+ cb_object = self._objects[object_id]
+ cb_object.add_format(Format(format_type, s, on_disk))
+
+ if on_disk:
+ logging.debug('Added format of type ' + format_type + ' with path at ' + s)
+ else:
+ logging.debug('Added in-memory format of type ' + format_type + '.')
+
+ @dbus.service.method(_CLIPBOARD_DBUS_INTERFACE,
+ in_signature="s", out_signature="")
+ def delete_object(self, object_id):
+ del self._objects[object_id]
+ self.object_deleted(object_id)
+ logging.debug('Deleted object with object_id ' + object_id)
+
+ @dbus.service.method(_CLIPBOARD_DBUS_INTERFACE,
+ in_signature="si", out_signature="")
+ def set_object_state(self, object_id, percent):
+ cb_object = self._objects[object_id]
+ cb_object.set_percent(percent)
+ self.object_state_changed(object_id, percent)
+ logging.debug('Changed object with object_id ' + object_id + ' with percent ' + str(percent))
+
+ @dbus.service.method(_CLIPBOARD_DBUS_INTERFACE,
+ in_signature="s", out_signature="as")
+ def get_object_format_types(self, object_id):
+ cb_object = self._objects[object_id]
+ formats = cb_object.get_formats()
+ array = []
+
+ for type, format in formats.iteritems():
+ array.append(type)
+
+ return array
+
+ @dbus.service.method(_CLIPBOARD_DBUS_INTERFACE,
+ in_signature="ss", out_signature="ay")
+ def get_object_data(self, object_id, format_type):
+ cb_object = self._objects[object_id]
+ formats = cb_object.get_formats()
+
+ return formats[format_type].get_data()
+
+ # dbus signals
+ @dbus.service.signal(_CLIPBOARD_DBUS_INTERFACE, signature="ss")
+ def object_added(self, object_id, name):
+ pass
+
+ @dbus.service.signal(_CLIPBOARD_DBUS_INTERFACE, signature="s")
+ def object_deleted(self, object_id):
+ pass
+
+ @dbus.service.signal(_CLIPBOARD_DBUS_INTERFACE, signature="si")
+ def object_state_changed(self, object_id, percent):
+ pass
+
+class ClipboardService(object):
+ def __init__(self):
+ self._dbus_helper = ClipboardDBusServiceHelper(self)
+
+ def run(self):
+ loop = gobject.MainLoop()
+ try:
+ loop.run()
+ except idboardInterrupt:
+ print 'Ctrl+C pressed, exiting...'
diff --git a/services/clipboard/sugar-clipboard b/services/clipboard/sugar-clipboard
index bcbd280..3f7ef9f 100755
--- a/services/clipboard/sugar-clipboard
+++ b/services/clipboard/sugar-clipboard
@@ -33,7 +33,7 @@ from sugar import env
sys.path.insert(0, env.get_services_dir())
-from clipboard.ClipboardService import ClipboardService
+from clipboard.clipboardservice import ClipboardService
logging.info('Starting clipboard service.')
diff --git a/shell/view/Makefile.am b/shell/view/Makefile.am
index bd90a2d..0f9573a 100644
--- a/shell/view/Makefile.am
+++ b/shell/view/Makefile.am
@@ -7,8 +7,8 @@ sugar_PYTHON = \
FirstTimeDialog.py \
BuddyIcon.py \
BuddyMenu.py \
- ClipboardIcon.py \
- ClipboardMenu.py \
+ clipboardicon.py \
+ clipboardmenu.py \
OverlayWindow.py \
Shell.py \
dconmanager.py \
diff --git a/shell/view/ClipboardIcon.py b/shell/view/clipboardicon.py
index 41f3e09..25a14e9 100644
--- a/shell/view/ClipboardIcon.py
+++ b/shell/view/clipboardicon.py
@@ -1,14 +1,14 @@
from sugar.graphics.menuicon import MenuIcon
-from view.ClipboardMenu import ClipboardMenu
+from view.clipboardmenu import ClipboardMenu
from sugar.activity import ActivityFactory
-from sugar.clipboard import ClipboardService
+from sugar.clipboard import clipboardservice
class ClipboardIcon(MenuIcon):
- def __init__(self, menu_shell, name, file_name):
+ def __init__(self, menu_shell, object_id, name):
MenuIcon.__init__(self, menu_shell, icon_name='activity-xbook')
+ self._object_id = object_id
self._name = name
- self._file_name = file_name
self._percent = 0
self.connect('activated', self._icon_activated_cb)
self._menu = None
@@ -25,8 +25,11 @@ class ClipboardIcon(MenuIcon):
def _icon_activated_cb(self, icon):
if self._percent == 100:
- activity = ActivityFactory.create("org.laptop.sugar.Xbook")
- activity.execute("open_document", [self._file_name])
+ cb_service = clipboardservice.get_instance()
+ format_types = cb_service.get_object_format_types(self._object_id)
+ if len(format_types) > 0 and format_types[0] == "application/pdf":
+ activity = ActivityFactory.create("org.laptop.sugar.Xbook")
+ activity.execute("open_document", [self._object_id])
def _popup_action_cb(self, popup, action):
self.popdown()
@@ -34,5 +37,8 @@ class ClipboardIcon(MenuIcon):
if action == ClipboardMenu.ACTION_STOP_DOWNLOAD:
raise "Stopping downloads still not implemented."
elif action == ClipboardMenu.ACTION_DELETE:
- cb_service = ClipboardService.get_instance()
- cb_service.delete_object(self._file_name)
+ cb_service = clipboardservice.get_instance()
+ cb_service.delete_object(self._object_id)
+
+ def get_object_id(self):
+ return self._object_id
diff --git a/shell/view/ClipboardMenu.py b/shell/view/clipboardmenu.py
index 625c897..cd521e0 100644
--- a/shell/view/ClipboardMenu.py
+++ b/shell/view/clipboardmenu.py
@@ -24,9 +24,6 @@ class ClipboardMenu(Menu):
self._progress_bar = ClipboardMenuItem(percent)
self._root.append(self._progress_bar)
-
- #icon = CanvasIcon(icon_name='stock-share-mesh')
- #self.add_action(icon, ClipboardMenu.ACTION_SHARE)
self._remove_icon = None
self._stop_icon = None
diff --git a/shell/view/frame/ClipboardBox.py b/shell/view/frame/ClipboardBox.py
deleted file mode 100644
index 82dccb6..0000000
--- a/shell/view/frame/ClipboardBox.py
+++ /dev/null
@@ -1,42 +0,0 @@
-import logging
-import dbus
-import hippo
-
-from sugar.graphics import style
-from view.ClipboardIcon import ClipboardIcon
-from sugar.clipboard import ClipboardService
-
-class ClipboardBox(hippo.CanvasBox):
-
- def __init__(self, frame, menu_shell):
- hippo.CanvasBox.__init__(self)
- self._frame = frame
- self._menu_shell = menu_shell
- self._icons = {}
-
- cb_service = ClipboardService.get_instance()
- cb_service.connect('object-added', self._object_added_cb)
- cb_service.connect('object-deleted', self._object_deleted_cb)
- cb_service.connect('object-state-changed', self._object_state_changed_cb)
-
- def _object_added_cb(self, cb_service, name, mimeType, fileName):
- icon = ClipboardIcon(self._menu_shell, name, fileName)
- style.apply_stylesheet(icon, 'frame.BuddyIcon')
- self.append(icon)
- self._icons[fileName] = icon
-
- if not self._frame.is_visible():
- self._frame.show_and_hide(0.1)
-
- logging.debug('ClipboardBox: ' + fileName + ' was added.')
-
- def _object_deleted_cb(self, cb_service, fileName):
- icon = self._icons[fileName]
- self.remove(icon)
- del self._icons[fileName]
- logging.debug('ClipboardBox: ' + fileName + ' was deleted.')
-
- def _object_state_changed_cb(self, cb_service, fileName, percent):
- icon = self._icons[fileName]
- icon.set_percent(percent)
- logging.debug('ClipboardBox: ' + fileName + ' state was changed.')
diff --git a/shell/view/frame/Frame.py b/shell/view/frame/Frame.py
index c865219..f2c6312 100644
--- a/shell/view/frame/Frame.py
+++ b/shell/view/frame/Frame.py
@@ -14,6 +14,7 @@
# 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 gtk
import gobject
import hippo
@@ -23,8 +24,8 @@ from view.frame.ActivitiesBox import ActivitiesBox
from view.frame.ZoomBox import ZoomBox
from view.frame.overlaybox import OverlayBox
from view.frame.FriendsBox import FriendsBox
-from view.frame.ClipboardBox import ClipboardBox
from view.frame.PanelWindow import PanelWindow
+from view.frame.clipboardpanelwindow import ClipboardPanelWindow
from view.frame.notificationtray import NotificationTray
from view.frame.shutdownicon import ShutdownIcon
from sugar.graphics.timeline import Timeline
@@ -154,7 +155,10 @@ class Frame:
grid = Grid()
# Top panel
- [menu_shell, root] = self._create_panel(grid, 0, 0, 16, 1)
+ panel = self._create_panel(grid, 0, 0, 16, 1)
+ menu_shell = panel.get_menu_shell()
+ root = panel.get_root()
+
menu_shell.set_position(MenuShell.BOTTOM)
box = ZoomBox(self._shell, menu_shell)
@@ -189,7 +193,10 @@ class Frame:
root.move(shutdown_icon, x, y)
# Bottom panel
- [menu_shell, root] = self._create_panel(grid, 0, 11, 16, 1)
+ panel = self._create_panel(grid, 0, 11, 16, 1)
+ menu_shell = panel.get_menu_shell()
+ root = panel.get_root()
+
menu_shell.set_position(MenuShell.TOP)
box = ActivitiesBox(self._shell)
@@ -199,21 +206,35 @@ class Frame:
root.move(box, x, y)
# Right panel
- [menu_shell, root] = self._create_panel(grid, 15, 1, 1, 10)
+ panel = self._create_panel(grid, 15, 1, 1, 10)
+ menu_shell = panel.get_menu_shell()
+ root = panel.get_root()
+
menu_shell.set_position(MenuShell.LEFT)
box = FriendsBox(self._shell, menu_shell)
root.append(box)
# Left panel
- [menu_shell, root] = self._create_panel(grid, 0, 1, 1, 10)
+ panel = self._create_clipboard_panel(grid, 0, 1, 1, 10)
+
+ def _create_clipboard_panel(self, grid, x, y, width, height):
+ [x, y, width, height] = grid.rectangle(x, y, width, height)
+ panel = ClipboardPanelWindow(x, y, width, height)
+ self._connect_to_panel(panel)
+ self._windows.append(panel)
- box = ClipboardBox(self, menu_shell)
- root.append(box)
+ return panel
def _create_panel(self, grid, x, y, width, height):
- panel = PanelWindow()
+ [x, y, width, height] = grid.rectangle(x, y, width, height)
+ panel = PanelWindow(x, y, width, height)
+ self._connect_to_panel(panel)
+ self._windows.append(panel)
+
+ return panel
+ def _connect_to_panel(self, panel):
panel.connect('enter-notify-event', self._enter_notify_cb)
panel.connect('leave-notify-event', self._leave_notify_cb)
@@ -221,15 +242,6 @@ class Frame:
menu_shell.connect('activated', self._menu_shell_activated_cb)
menu_shell.connect('deactivated', self._menu_shell_deactivated_cb)
- [x, y, width, height] = grid.rectangle(x, y, width, height)
-
- panel.move(x, y)
- panel.resize(width, height)
-
- self._windows.append(panel)
-
- return [panel.get_menu_shell(), panel.get_root()]
-
def _menu_shell_activated_cb(self, menu_shell):
self._active_menus += 1
self._timeline.goto('slide_in', True)
diff --git a/shell/view/frame/Makefile.am b/shell/view/frame/Makefile.am
index 5d96a23..4b51ece 100644
--- a/shell/view/frame/Makefile.am
+++ b/shell/view/frame/Makefile.am
@@ -2,7 +2,8 @@ sugardir = $(pkgdatadir)/shell/view/frame
sugar_PYTHON = \
__init__.py \
ActivitiesBox.py \
- ClipboardBox.py \
+ clipboardbox.py \
+ clipboardpanelwindow.py \
FriendsBox.py \
PanelWindow.py \
Frame.py \
diff --git a/shell/view/frame/PanelWindow.py b/shell/view/frame/PanelWindow.py
index 8fd8145..a690b80 100644
--- a/shell/view/frame/PanelWindow.py
+++ b/shell/view/frame/PanelWindow.py
@@ -20,7 +20,7 @@ import hippo
from sugar.graphics.menushell import MenuShell
class PanelWindow(gtk.Window):
- def __init__(self):
+ def __init__(self, x, y, width, height):
gtk.Window.__init__(self)
self.set_decorated(False)
@@ -36,6 +36,9 @@ class PanelWindow(gtk.Window):
self._menu_shell = MenuShell(canvas)
+ self.move(x, y)
+ self.resize(width, height)
+
def get_menu_shell(self):
return self._menu_shell
diff --git a/shell/view/frame/clipboardbox.py b/shell/view/frame/clipboardbox.py
new file mode 100644
index 0000000..98a30a0
--- /dev/null
+++ b/shell/view/frame/clipboardbox.py
@@ -0,0 +1,183 @@
+import logging
+import hippo
+import gtk
+
+from sugar import util
+from sugar.graphics import style
+from view.clipboardicon import ClipboardIcon
+from sugar.clipboard import clipboardservice
+
+class _ContextMap:
+ """Maps a drag context to the clipboard object involved in the dragging."""
+ def __init__(self):
+ self._context_map = {}
+
+ def add_context(self, context, object_id, data_types):
+ """Establishes the mapping. data_types will serve us for reference-
+ counting this mapping.
+ """
+ self._context_map[context] = [object_id, data_types]
+
+ def get_object_id(self, context):
+ """Retrieves the object_id associated with context.
+ Will release the association when this function was called as many times
+ as the number of data_types that this clipboard object contains.
+ """
+ [object_id, data_types_left] = self._context_map[context]
+
+ data_types_left = data_types_left - 1
+ if data_types_left == 0:
+ del self._context_map[context]
+ else:
+ self._context_map[context] = [object_id, data_types_left]
+
+ return object_id
+
+class ClipboardBox(hippo.CanvasBox):
+
+ def __init__(self, menu_shell):
+ hippo.CanvasBox.__init__(self)
+ self._menu_shell = menu_shell
+ self._icons = {}
+ self._context_map = _ContextMap()
+
+ self._pressed_button = None
+ self._press_start_x = None
+ self._press_start_y = None
+
+ cb_service = clipboardservice.get_instance()
+ cb_service.connect('object-added', self._object_added_cb)
+ cb_service.connect('object-deleted', self._object_deleted_cb)
+ cb_service.connect('object-state-changed', self._object_state_changed_cb)
+
+ def _get_icon_at_coords(self, x, y):
+ for object_id, icon in self._icons.iteritems():
+ [icon_x, icon_y] = self.get_position(icon)
+ [icon_width, icon_height] = icon.get_allocation()
+
+ if (x >= icon_x ) and (x <= icon_x + icon_width) and \
+ (y >= icon_y ) and (y <= icon_y + icon_height):
+ return icon
+
+ return None
+
+ def _add_selection(self, object_id, selection):
+ if selection.data:
+ logging.debug('ClipboardBox: adding type ' + selection.type + '.')
+
+ cb_service = clipboardservice.get_instance()
+ cb_service.add_object_format(object_id,
+ selection.type,
+ selection.data,
+ on_disk = False)
+
+ def _object_added_cb(self, cb_service, object_id, name):
+ icon = ClipboardIcon(self._menu_shell, object_id, name)
+ style.apply_stylesheet(icon, 'frame.BuddyIcon')
+ self.append(icon)
+ self._icons[object_id] = icon
+
+ logging.debug('ClipboardBox: ' + object_id + ' was added.')
+
+ def _object_deleted_cb(self, cb_service, object_id):
+ icon = self._icons[object_id]
+ self.remove(icon)
+ del self._icons[object_id]
+ logging.debug('ClipboardBox: ' + object_id + ' was deleted.')
+
+ def _object_state_changed_cb(self, cb_service, object_id, percent):
+ icon = self._icons[object_id]
+ icon.set_percent(percent)
+ logging.debug('ClipboardBox: ' + object_id + ' state was changed.')
+
+ def drag_motion_cb(self, widget, context, x, y, time):
+ context.drag_status(gtk.gdk.ACTION_COPY, time)
+ return True
+
+ def drag_drop_cb(self, widget, context, x, y, time):
+ object_id = util.unique_id()
+ self._context_map.add_context(context, object_id, len(context.targets))
+
+ cb_service = clipboardservice.get_instance()
+ cb_service.add_object(object_id, "name")
+
+ for target in context.targets:
+ if str(target) not in ('TIMESTAMP', 'TARGETS', 'MULTIPLE'):
+ widget.drag_get_data(context, target, time)
+
+ cb_service.set_object_state(object_id, percent = 100)
+
+ return True
+
+ def drag_data_received_cb(self, widget, context, x, y, selection, targetType, time):
+ logging.debug('ClipboardBox: got data for target ' + selection.target)
+ if selection:
+ object_id = self._context_map.get_object_id(context)
+ self._add_selection(object_id, selection)
+ else:
+ logging.warn('ClipboardBox: empty selection for target ' + selection.target)
+
+ def drag_data_get_cb(self, widget, context, selection, targetType, eventTime):
+ logging.debug("drag_data_get_cb: requested target " + selection.target)
+
+ object_id = self._last_clicked_icon.get_object_id()
+ cb_service = clipboardservice.get_instance()
+ data = cb_service.get_object_data(object_id, selection.target)
+
+ selection.set(selection.target, 8, data)
+
+ def button_press_event_cb(self, widget, event):
+ logging.debug("button_press_event_cb")
+
+ if event.button == 1 and event.type == gtk.gdk.BUTTON_PRESS:
+ self._last_clicked_icon = self._get_icon_at_coords(event.x, event.y)
+ if self._last_clicked_icon:
+ self._pressed_button = event.button
+ self._press_start_x = event.x
+ self._press_start_y = event.y
+
+ return True;
+
+ def motion_notify_event_cb(self, widget, event):
+
+ if not self._pressed_button:
+ return True
+
+ logging.debug("motion_notify_event_cb")
+
+ if event.is_hint:
+ x, y, state = event.window.get_pointer()
+ else:
+ x = event.x
+ y = event.y
+ state = event.state
+
+ if widget.drag_check_threshold(self._press_start_x,
+ self._press_start_y,
+ x,
+ y):
+ targets = self._get_targets_for_dnd(
+ self._last_clicked_icon.get_object_id())
+
+ context = widget.drag_begin(targets,
+ gtk.gdk.ACTION_COPY,
+ 1,
+ event);
+
+ return True
+
+ def drag_end_cb(self, widget, drag_context):
+ logging.debug("drag_end_cb")
+ self._pressed_button = None
+
+ def _get_targets_for_dnd(self, object_id):
+ cb_service = clipboardservice.get_instance()
+ format_types = cb_service.get_object_format_types(object_id)
+ targets = []
+
+ for format_type in format_types:
+ targets.append((format_type, 0, 0))
+
+ logging.debug(str(targets))
+
+ return targets
diff --git a/shell/view/frame/clipboardpanelwindow.py b/shell/view/frame/clipboardpanelwindow.py
new file mode 100644
index 0000000..08344c9
--- /dev/null
+++ b/shell/view/frame/clipboardpanelwindow.py
@@ -0,0 +1,64 @@
+import logging
+import gtk
+import hippo
+
+from view.frame.PanelWindow import PanelWindow
+from view.frame.clipboardbox import ClipboardBox
+from sugar.clipboard import clipboardservice
+from sugar import util
+
+class ClipboardPanelWindow(PanelWindow):
+ def __init__(self, x, y, width, height):
+ PanelWindow.__init__(self, x, y, width, height)
+
+ # Listening for new clipboard objects
+ clipboard = gtk.Clipboard()
+ clipboard.connect("owner-change", self._owner_change_cb)
+
+ menu_shell = self.get_menu_shell()
+ root = self.get_root()
+
+ box = ClipboardBox(menu_shell)
+ root.append(box)
+
+ # Receiving dnd drops
+ self.drag_dest_set(0, [], 0)
+ self.connect("drag_motion", box.drag_motion_cb)
+ self.connect("drag_drop", box.drag_drop_cb)
+ self.connect("drag_data_received", box.drag_data_received_cb)
+
+ # Offering dnd drags
+ self.drag_source_set(0, [], 0)
+ self.add_events(gtk.gdk.BUTTON_PRESS_MASK |
+ gtk.gdk.POINTER_MOTION_MASK |
+ gtk.gdk.POINTER_MOTION_HINT_MASK)
+ self.connect("motion_notify_event", box.motion_notify_event_cb)
+ self.connect("button_press_event", box.button_press_event_cb)
+ self.connect("drag_end", box.drag_end_cb)
+ self.connect("drag_data_get", box.drag_data_get_cb)
+
+ def _owner_change_cb(self, clipboard, event):
+ logging.debug("owner_change_cb")
+
+ key = util.unique_id()
+
+ cb_service = clipboardservice.get_instance()
+ cb_service.add_object(key, "name")
+ cb_service.set_object_state(key, percent = 100)
+
+ targets = clipboard.wait_for_targets()
+ for target in targets:
+ if target not in ('TIMESTAMP', 'TARGETS', 'MULTIPLE'):
+ selection = clipboard.wait_for_contents(target)
+ if selection:
+ self._add_selection(key, selection)
+
+ def _add_selection(self, key, selection):
+ if selection.data:
+ logging.debug('adding type ' + selection.type + '.')
+
+ cb_service = clipboardservice.get_instance()
+ cb_service.add_object_format(key,
+ selection.type,
+ selection.data,
+ on_disk = False)
diff --git a/sugar/clipboard/Makefile.am b/sugar/clipboard/Makefile.am
index dbfabe9..0d61c29 100644
--- a/sugar/clipboard/Makefile.am
+++ b/sugar/clipboard/Makefile.am
@@ -1,5 +1,5 @@
sugardir = $(pythondir)/sugar/clipboard
sugar_PYTHON = \
__init__.py \
- ClipboardService.py
+ clipboardservice.py
diff --git a/sugar/clipboard/ClipboardService.py b/sugar/clipboard/clipboardservice.py
index 254d6b2..425a16d 100644
--- a/sugar/clipboard/ClipboardService.py
+++ b/sugar/clipboard/clipboardservice.py
@@ -1,6 +1,9 @@
+import logging
import dbus
import gobject
+from sugar import util
+
DBUS_SERVICE = "org.laptop.Clipboard"
DBUS_INTERFACE = "org.laptop.Clipboard"
DBUS_PATH = "/org/laptop/Clipboard"
@@ -9,7 +12,7 @@ class ClipboardService(gobject.GObject):
__gsignals__ = {
'object-added': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
- ([str, str, str])),
+ ([str, str])),
'object-deleted': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
([str])),
'object-state-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
@@ -49,24 +52,43 @@ class ClipboardService(gobject.GObject):
# ClipboardService started up
self._connect_clipboard_signals()
- def _object_added_cb(self, name, mimeType, fileName):
- self.emit('object-added', name, mimeType, fileName)
+ def _object_added_cb(self, object_id, name):
+ self.emit('object-added', object_id, name)
- def _object_deleted_cb(self, fileName):
- self.emit('object-deleted', fileName)
+ def _object_deleted_cb(self, object_id):
+ self.emit('object-deleted', object_id)
- def _object_state_changed_cb(self, fileName, percent):
- self.emit('object-state-changed', fileName, percent)
-
- def add_object(self, name, mimeType, fileName):
- self._dbus_service.add_object(name, mimeType, fileName)
+ def _object_state_changed_cb(self, object_id, percent):
+ self.emit('object-state-changed', object_id, percent)
- def delete_object(self, fileName):
- self._dbus_service.delete_object(fileName)
+ def add_object(self, object_id, name):
+ self._dbus_service.add_object(object_id, name)
+
+ def add_object_format(self, object_id, formatType, data, on_disk):
+ self._dbus_service.add_object_format(object_id,
+ formatType,
+ dbus.types.ByteArray(data),
+ on_disk)
+
+ def delete_object(self, object_id):
+ self._dbus_service.delete_object(object_id)
- def set_object_state(self, fileName, percent):
- self._dbus_service.set_object_state(fileName, percent)
+ def set_object_state(self, object_id, percent):
+ self._dbus_service.set_object_state(object_id, percent)
+ def get_object_format_types(self, object_id):
+ return self._dbus_service.get_object_format_types(object_id)
+
+ def get_object_data(self, object_id, formatType):
+ data = self._dbus_service.get_object_data(object_id, formatType)
+
+ # FIXME: Take it out when using the 0.80 dbus bindings
+ s = ""
+ for i in data:
+ s += chr(i)
+
+ return s
+
_clipboard_service = None
def get_instance():
global _clipboard_service