diff options
author | Tomeu Vizoso <tomeu@tomeuvizoso.net> | 2006-12-13 21:36:05 (GMT) |
---|---|---|
committer | Tomeu Vizoso <tomeu@tomeuvizoso.net> | 2006-12-13 21:36:05 (GMT) |
commit | e68f0e00e95416c696ecc08895b1a29463c989f8 (patch) | |
tree | e6f9b82880efecf155c1281bb3bdf95502e388af /shell/view | |
parent | 474313ffdebb066e8e6891cfc362aa2edf3cf5c3 (diff) |
Added c&v and dnd support to the clipboard.
Diffstat (limited to 'shell/view')
-rw-r--r-- | shell/view/Makefile.am | 4 | ||||
-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.py | 42 | ||||
-rw-r--r-- | shell/view/frame/Frame.py | 46 | ||||
-rw-r--r-- | shell/view/frame/Makefile.am | 3 | ||||
-rw-r--r-- | shell/view/frame/PanelWindow.py | 5 | ||||
-rw-r--r-- | shell/view/frame/clipboardbox.py | 183 | ||||
-rw-r--r-- | shell/view/frame/clipboardpanelwindow.py | 64 |
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) |