#3045: Fix issues with the clipboard icons and palettes.

This commit is contained in:
Tomeu Vizoso 2007-08-31 14:53:59 +02:00
parent bd9bd2d020
commit 3dc8505ec5
5 changed files with 111 additions and 206 deletions

1
NEWS
View File

@ -1,3 +1,4 @@
* #3045: Fix issues with the clipboard icons and palettes. (tomeu)
* Get invites back to work in the UI. (marco) * Get invites back to work in the UI. (marco)
* Get the title on activity palette in the mesh to work. (marco) * Get the title on activity palette in the mesh to work. (marco)

View File

@ -19,65 +19,95 @@ import logging
from gettext import gettext as _ from gettext import gettext as _
import gobject import gobject
import gtk
from sugar.graphics.icon import CanvasIcon from sugar.graphics.radiotoolbutton import RadioToolButton
from view.clipboardmenu import ClipboardMenu
from sugar.graphics.xocolor import XoColor from sugar.graphics.xocolor import XoColor
from sugar.graphics.icon import Icon
from sugar.graphics import style from sugar.graphics import style
from sugar.clipboard import clipboardservice from sugar.clipboard import clipboardservice
from sugar import util from sugar import util
from sugar import profile from sugar import profile
class ClipboardIcon(CanvasIcon): from view.clipboardmenu import ClipboardMenu
from view.frame.frameinvoker import FrameWidgetInvoker
class ClipboardIcon(RadioToolButton):
__gtype_name__ = 'SugarClipboardIcon' __gtype_name__ = 'SugarClipboardIcon'
__gproperties__ = { def __init__(self, object_id, name, group):
'selected' : (bool, None, None, False, RadioToolButton.__init__(self, group=group)
gobject.PARAM_READWRITE)
}
def __init__(self, object_id, name):
CanvasIcon.__init__(self)
self._object_id = object_id self._object_id = object_id
self._name = name self._name = name
self._percent = 0 self._percent = 0
self._preview = None self._preview = None
self._activity = None self._activity = None
self._selected = False self.owns_clipboard = False
self._hover = False
self.props.size = style.STANDARD_ICON_SIZE self._icon = Icon()
self.props.xo_color = XoColor(profile.get_color().to_string()) self._icon.props.xo_color = profile.get_color()
self.set_icon_widget(self._icon)
self._icon.show()
self.props.sensitive = False
cb_service = clipboardservice.get_instance() cb_service = clipboardservice.get_instance()
cb_service.connect('object-state-changed', self._object_state_changed_cb)
obj = cb_service.get_object(self._object_id) obj = cb_service.get_object(self._object_id)
formats = obj['FORMATS'] formats = obj['FORMATS']
self.palette = ClipboardMenu(self._object_id, self._name, self._percent, self.palette = ClipboardMenu(self._object_id, self._name, self._percent,
self._preview, self._activity, self._preview, self._activity,
formats and formats[0] == 'application/vnd.olpc-sugar') formats and formats[0] == 'application/vnd.olpc-sugar')
self.palette.props.invoker = FrameWidgetInvoker(self)
self.child.connect('drag_data_get', self._drag_data_get_cb)
self.connect('notify::active', self._notify_active_cb)
def do_set_property(self, pspec, value): def get_object_id(self):
if pspec.name == 'selected': return self._object_id
self._set_selected(value)
self.emit_paint_needed(0, 0, -1, -1)
else:
CanvasIcon.do_set_property(self, pspec, value)
def do_get_property(self, pspec): def _drag_data_get_cb(self, widget, context, selection, targetType, eventTime):
if pspec.name == 'selected': logging.debug('_drag_data_get_cb: requested target ' + selection.target)
return self._selected
else: cb_service = clipboardservice.get_instance()
return CanvasIcon.do_get_property(self, pspec) data = cb_service.get_object_data(self._object_id, selection.target)['DATA']
selection.set(selection.target, 8, data)
def _set_selected(self, selected): def _put_in_clipboard(self):
self._selected = selected logging.debug('ClipboardIcon._put_in_clipboard')
if selected: targets = self._get_targets()
if not self._hover: if targets:
self.props.background_color = style.COLOR_SELECTION_GREY.get_int() clipboard = gtk.Clipboard()
else: if not clipboard.set_with_data(targets,
self.props.background_color = style.COLOR_PANEL_GREY.get_int() self._clipboard_data_get_cb,
self._clipboard_clear_cb,
targets):
logging.error('GtkClipboard.set_with_data failed!')
else:
self.owns_clipboard = True
def _clipboard_data_get_cb(self, 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']
selection.set(selection.target, 8, data)
def _clipboard_clear_cb(self, 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:
return
def set_state(self, name, percent, icon_name, preview, activity):
cb_service = clipboardservice.get_instance() cb_service = clipboardservice.get_instance()
obj = cb_service.get_object(self._object_id) obj = cb_service.get_object(self._object_id)
if obj['FORMATS'] and obj['FORMATS'][0] == 'application/vnd.olpc-sugar': if obj['FORMATS'] and obj['FORMATS'][0] == 'application/vnd.olpc-sugar':
@ -86,32 +116,41 @@ class ClipboardIcon(CanvasIcon):
installable = False installable = False
if icon_name: if icon_name:
self.props.icon_name = icon_name self._icon.props.icon_name = icon_name
else: else:
self.props.icon_name = 'application-octet-stream' self._icon.props.icon_name = 'application-octet-stream'
self.child.drag_source_set(gtk.gdk.BUTTON1_MASK,
self._get_targets(),
gtk.gdk.ACTION_COPY)
self.child.drag_source_set_icon_name(self._icon.props.icon_name)
self._name = name self._name = name
self._percent = percent self._percent = percent
self._preview = preview self._preview = preview
self._activity = activity self._activity = activity
self.palette.set_state(name, percent, preview, activity, installable) self.palette.set_state(name, percent, preview, activity, installable)
if (activity or installable) and percent < 100: self.props.sensitive = (percent == 100)
self.props.xo_color = XoColor("#000000,#424242")
if self.props.active:
self._put_in_clipboard()
def _notify_active_cb(self, widget, pspec):
if self.props.active:
self._put_in_clipboard()
else: else:
self.props.xo_color = XoColor(profile.get_color().to_string()) self.owns_clipboard = False
def get_object_id(self): def _get_targets(self):
return self._object_id cb_service = clipboardservice.get_instance()
def prelight(self, enter): attrs = cb_service.get_object(self._object_id)
if enter: format_types = attrs[clipboardservice.FORMATS_KEY]
self._hover = True
self.props.background_color = style.COLOR_BLACK.get_int() targets = []
else: for format_type in format_types:
self._hover = False targets.append((format_type, 0, 0))
if self._selected:
self.props.background_color = style.COLOR_SELECTION_GREY.get_int() return targets
else:
self.props.background_color = style.COLOR_PANEL_GREY.get_int()

View File

@ -37,7 +37,6 @@ class ClipboardMenu(Palette):
def __init__(self, object_id, name, percent, preview, activities, installable): def __init__(self, object_id, name, percent, preview, activities, installable):
Palette.__init__(self, name) Palette.__init__(self, name)
self.props.position = Palette.RIGHT
self._object_id = object_id self._object_id = object_id
self._percent = percent self._percent = percent
self._activities = activities self._activities = activities

View File

@ -21,8 +21,10 @@ import hippo
import gtk import gtk
from sugar import util from sugar import util
from view.clipboardicon import ClipboardIcon
from sugar.clipboard import clipboardservice from sugar.clipboard import clipboardservice
from sugar.graphics.tray import VTray
from view.clipboardicon import ClipboardIcon
class _ContextMap: class _ContextMap:
"""Maps a drag context to the clipboard object involved in the dragging.""" """Maps a drag context to the clipboard object involved in the dragging."""
@ -60,33 +62,20 @@ class ClipboardBox(hippo.CanvasBox):
self._icons = {} self._icons = {}
self._context_map = _ContextMap() self._context_map = _ContextMap()
self._selected_icon = None self._selected_icon = None
self._owns_clipboard = False
self._pressed_button = None self._tray = VTray()
self._press_start_x = None self.append(hippo.CanvasWidget(widget=self._tray), hippo.PACK_EXPAND)
self._press_start_y = None self._tray.show()
cb_service = clipboardservice.get_instance() cb_service = clipboardservice.get_instance()
cb_service.connect('object-added', self._object_added_cb) cb_service.connect('object-added', self._object_added_cb)
cb_service.connect('object-deleted', self._object_deleted_cb) cb_service.connect('object-deleted', self._object_deleted_cb)
cb_service.connect('object-state-changed', self._object_state_changed_cb)
def owns_clipboard(self): def owns_clipboard(self):
return self._owns_clipboard for icon in self._icons.values():
if icon.owns_clipboard:
def _get_icon_at_coords(self, x, y): return True
box_x, box_y = self.get_context().translate_to_widget(self) return False
x -= box_x
y -= box_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): def _add_selection(self, object_id, selection):
if not selection.data: if not selection.data:
@ -111,73 +100,33 @@ class ClipboardBox(hippo.CanvasBox):
on_disk=False) on_disk=False)
def _object_added_cb(self, cb_service, object_id, name): def _object_added_cb(self, cb_service, object_id, name):
icon = ClipboardIcon(object_id, name) if self._icons:
icon.connect('button-release-event', self._icon_button_release_event_cb) group = self._icons.values()[0]
self._set_icon_selected(icon) else:
group = None
self.prepend(icon) icon = ClipboardIcon(object_id, name, group)
self._tray.add_item(icon, 0)
icon.show()
self._set_icon_selected(icon)
self._icons[object_id] = icon self._icons[object_id] = icon
logging.debug('ClipboardBox: ' + object_id + ' was added.') logging.debug('ClipboardBox: ' + object_id + ' was added.')
def _set_icon_selected(self, icon): def _set_icon_selected(self, icon):
logging.debug('_set_icon_selected') logging.debug('_set_icon_selected')
icon.props.selected = True icon.props.active = True
if self._selected_icon:
self._selected_icon.props.selected = False
self._selected_icon = icon self._selected_icon = icon
def _put_in_clipboard(self, object_id):
logging.debug('ClipboardBox._put_in_clipboard')
targets = self._get_object_targets(object_id)
if targets:
clipboard = gtk.Clipboard()
if not clipboard.set_with_data(targets,
self._clipboard_data_get_cb,
self._clipboard_clear_cb,
targets):
logging.error('GtkClipboard.set_with_data failed!')
else:
self._owns_clipboard = True
def _clipboard_data_get_cb(self, clipboard, selection, info, targets):
if not selection.target in [target[0] for target in targets]:
logging.warning('ClipboardBox._clipboard_data_get_cb: asked %s but' \
' only have %r.' % (selection.target, targets))
return
object_id = self._selected_icon.get_object_id()
cb_service = clipboardservice.get_instance()
data = cb_service.get_object_data(object_id, selection.target)['DATA']
selection.set(selection.target, 8, data)
def _clipboard_clear_cb(self, clipboard, targets):
logging.debug('ClipboardBox._clipboard_clear_cb')
self._owns_clipboard = False
def _icon_button_release_event_cb(self, icon, event):
logging.debug('ClipboardBox._icon_button_release_event_cb: %r' % icon.props.selected)
if not icon.props.selected:
self._set_icon_selected(icon)
def _object_deleted_cb(self, cb_service, object_id): def _object_deleted_cb(self, cb_service, object_id):
icon = self._icons[object_id] icon = self._icons[object_id]
position = self.get_children().index(icon) position = self.get_children().index(icon)
self.remove(icon) self.remove(icon)
if icon.props.selected and self.get_children():
self._set_icon_selected(self.get_children()[position])
del self._icons[object_id] del self._icons[object_id]
logging.debug('ClipboardBox: ' + object_id + ' was deleted.') logging.debug('ClipboardBox: ' + object_id + ' was deleted.')
def _object_state_changed_cb(self, cb_service, object_id, name, percent,
icon_name, preview, activity):
icon = self._icons[object_id]
icon.set_state(name, percent, icon_name, preview, activity)
if icon.props.selected and percent == 100:
self._put_in_clipboard(object_id)
def drag_motion_cb(self, widget, context, x, y, time): def drag_motion_cb(self, widget, context, x, y, time):
logging.debug('ClipboardBox._drag_motion_cb') logging.debug('ClipboardBox._drag_motion_cb')
context.drag_status(gtk.gdk.ACTION_COPY, time) context.drag_status(gtk.gdk.ACTION_COPY, time)
@ -211,72 +160,3 @@ class ClipboardBox(hippo.CanvasBox):
if not self._context_map.has_context(context): if not self._context_map.has_context(context):
context.drop_finish(True, gtk.get_current_event_time()) context.drop_finish(True, gtk.get_current_event_time())
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)['DATA']
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 False
def motion_notify_event_cb(self, widget, event):
if not self._pressed_button:
return True
# if the mouse button is not pressed, no drag should occurr
if not event.state & gtk.gdk.BUTTON1_MASK:
self._pressed_button = None
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(int(self._press_start_x),
int(self._press_start_y),
int(x),
int(y)):
targets = self._get_object_targets(
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_object_targets(self, object_id):
cb_service = clipboardservice.get_instance()
attrs = cb_service.get_object(object_id)
format_types = attrs[clipboardservice.FORMATS_KEY]
targets = []
for format_type in format_types:
targets.append((format_type, 0, 0))
return targets

View File

@ -37,7 +37,7 @@ class ClipboardPanelWindow(FrameWindow):
self._clipboard.connect("owner-change", self._owner_change_cb) self._clipboard.connect("owner-change", self._owner_change_cb)
self._clipboard_box = ClipboardBox() self._clipboard_box = ClipboardBox()
self.append(self._clipboard_box) self.append(self._clipboard_box, hippo.PACK_EXPAND)
# Receiving dnd drops # Receiving dnd drops
self.drag_dest_set(0, [], 0) self.drag_dest_set(0, [], 0)
@ -45,20 +45,6 @@ class ClipboardPanelWindow(FrameWindow):
self.connect("drag_drop", self._clipboard_box.drag_drop_cb) self.connect("drag_drop", self._clipboard_box.drag_drop_cb)
self.connect("drag_data_received", self.connect("drag_data_received",
self._clipboard_box.drag_data_received_cb) self._clipboard_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_HINT_MASK)
self.connect("motion_notify_event",
self._clipboard_box.motion_notify_event_cb)
# FIXME I'm not sure we should expose the canvas in the Window API
self._canvas.connect("button_press_event",
self._clipboard_box.button_press_event_cb)
self.connect("drag_end", self._clipboard_box.drag_end_cb)
self.connect("drag_data_get", self._clipboard_box.drag_data_get_cb)
def _owner_change_cb(self, clipboard, event): def _owner_change_cb(self, clipboard, event):
logging.debug("owner_change_cb") logging.debug("owner_change_cb")