Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/shell/view
diff options
context:
space:
mode:
authorTomeu Vizoso <tomeu@tomeuvizoso.net>2006-12-13 21:36:05 (GMT)
committer Tomeu Vizoso <tomeu@tomeuvizoso.net>2006-12-13 21:36:05 (GMT)
commite68f0e00e95416c696ecc08895b1a29463c989f8 (patch)
treee6f9b82880efecf155c1281bb3bdf95502e388af /shell/view
parent474313ffdebb066e8e6891cfc362aa2edf3cf5c3 (diff)
Added c&v and dnd support to the clipboard.
Diffstat (limited to 'shell/view')
-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
9 files changed, 298 insertions, 74 deletions
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)