This is only on a best-effort basis; the code will be in a broken state after this patch and need to be fixed manually. The purpose of committing the intermediate, non-working output is to make it reproducible. It's impractical to manually review the changes. The exact version used was 4f637212f13b197a95c824967a58496b9e3b877c from the main pygobject repository [1] plus a custom patch [2] that hasn't been sent upstream yet. [1] git://git.gnome.org/pygobject [2] https://sascha.silbe.org/patches/pygobject-convert-sugar-20111122.patch Signed-off-by: Sascha Silbe <silbe@activitycentral.com>
		
			
				
	
	
		
			305 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			305 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
# Copyright (C) 2009 One Laptop Per Child
 | 
						|
#
 | 
						|
# This library is free software; you can redistribute it and/or
 | 
						|
# modify it under the terms of the GNU Lesser General Public
 | 
						|
# License as published by the Free Software Foundation; either
 | 
						|
# version 2 of the License, or (at your option) any later version.
 | 
						|
#
 | 
						|
# This library 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
 | 
						|
# Lesser General Public License for more details.
 | 
						|
#
 | 
						|
# You should have received a copy of the GNU Lesser General Public
 | 
						|
# License along with this library; if not, write to the
 | 
						|
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 | 
						|
# Boston, MA 02111-1307, USA.
 | 
						|
 | 
						|
import gettext
 | 
						|
import os
 | 
						|
 | 
						|
from gi.repository import Gio
 | 
						|
from gi.repository import Gtk
 | 
						|
from gi.repository import GObject
 | 
						|
from gi.repository import GConf
 | 
						|
 | 
						|
from sugar3.graphics import style
 | 
						|
from sugar3.graphics.icon import Icon
 | 
						|
from sugar3.graphics.xocolor import XoColor
 | 
						|
from sugar3.graphics.icon import get_icon_file_name
 | 
						|
from sugar3.graphics.toolbutton import ToolButton
 | 
						|
 | 
						|
from sugar3.bundle.activitybundle import ActivityBundle
 | 
						|
 | 
						|
 | 
						|
_ = lambda msg: gettext.dgettext('sugar-toolkit', msg)
 | 
						|
 | 
						|
 | 
						|
def _get_icon_name(metadata):
 | 
						|
    file_name = None
 | 
						|
 | 
						|
    mime_type = metadata.get('mime_type', '')
 | 
						|
    if not file_name and mime_type:
 | 
						|
        icons = Gio.content_type_get_icon(mime_type)
 | 
						|
        for icon_name in icons.props.names:
 | 
						|
            file_name = get_icon_file_name(icon_name)
 | 
						|
            if file_name is not None:
 | 
						|
                break
 | 
						|
 | 
						|
    if file_name is None or not os.path.exists(file_name):
 | 
						|
        file_name = get_icon_file_name('application-octet-stream')
 | 
						|
 | 
						|
    return file_name
 | 
						|
 | 
						|
 | 
						|
class NamingToolbar(Gtk.Toolbar):
 | 
						|
    """ Toolbar of the naming alert
 | 
						|
    """
 | 
						|
 | 
						|
    __gtype_name__ = 'SugarNamingToolbar'
 | 
						|
 | 
						|
    __gsignals__ = {
 | 
						|
        'keep-clicked': (GObject.SignalFlags.RUN_FIRST, None, ([])),
 | 
						|
    }
 | 
						|
 | 
						|
    def __init__(self):
 | 
						|
        Gtk.Toolbar.__init__(self)
 | 
						|
 | 
						|
        client = GConf.Client.get_default()
 | 
						|
        color = XoColor(client.get_string('/desktop/sugar/user/color'))
 | 
						|
        icon = Icon()
 | 
						|
        icon.set_from_icon_name('activity-journal',
 | 
						|
                                Gtk.IconSize.LARGE_TOOLBAR)
 | 
						|
        icon.props.xo_color = color
 | 
						|
        self._add_widget(icon)
 | 
						|
 | 
						|
        self._add_separator()
 | 
						|
 | 
						|
        self._title = Gtk.Label(label=_('Name this entry'))
 | 
						|
        self._add_widget(self._title)
 | 
						|
 | 
						|
        self._add_separator(True)
 | 
						|
 | 
						|
        self._keep_button = ToolButton('dialog-ok', tooltip=_('Keep'))
 | 
						|
        self._keep_button.props.accelerator = 'Return'
 | 
						|
        self._keep_button.connect('clicked', self.__keep_button_clicked_cb)
 | 
						|
        self.insert(self._keep_button, -1)
 | 
						|
        self._keep_button.show()
 | 
						|
 | 
						|
    def _add_separator(self, expand=False):
 | 
						|
        separator = Gtk.SeparatorToolItem()
 | 
						|
        separator.props.draw = False
 | 
						|
        if expand:
 | 
						|
            separator.set_expand(True)
 | 
						|
        else:
 | 
						|
            separator.set_size_request(style.DEFAULT_SPACING, -1)
 | 
						|
        self.insert(separator, -1)
 | 
						|
        separator.show()
 | 
						|
 | 
						|
    def _add_widget(self, widget, expand=False):
 | 
						|
        tool_item = Gtk.ToolItem()
 | 
						|
        tool_item.set_expand(expand)
 | 
						|
 | 
						|
        tool_item.add(widget)
 | 
						|
        widget.show()
 | 
						|
 | 
						|
        self.insert(tool_item, -1)
 | 
						|
        tool_item.show()
 | 
						|
 | 
						|
    def __keep_button_clicked_cb(self, widget, data=None):
 | 
						|
        self.emit('keep-clicked')
 | 
						|
 | 
						|
 | 
						|
class FavoriteIcon(Gtk.ToggleButton):
 | 
						|
 | 
						|
    def __init__(self):
 | 
						|
        GObject.GObject.__init__(self)
 | 
						|
        self.set_relief(Gtk.ReliefStyle.NONE)
 | 
						|
        self.set_focus_on_click(False)
 | 
						|
 | 
						|
        self._icon = Icon(icon_name='emblem-favorite',
 | 
						|
                          pixel_size=style.SMALL_ICON_SIZE)
 | 
						|
        self.set_image(self._icon)
 | 
						|
 | 
						|
        self.connect('toggled', self.__toggled_cb)
 | 
						|
        self.connect('leave-notify-event', self.__leave_notify_event_cb)
 | 
						|
        self.connect('enter-notify-event', self.__enter_notify_event_cb)
 | 
						|
 | 
						|
    def __toggled_cb(self, widget):
 | 
						|
        if self.get_active():
 | 
						|
            client = GConf.Client.get_default()
 | 
						|
            color = XoColor(client.get_string('/desktop/sugar/user/color'))
 | 
						|
            self._icon.props.xo_color = color
 | 
						|
        else:
 | 
						|
            self._icon.props.stroke_color = style.COLOR_BUTTON_GREY.get_svg()
 | 
						|
            self._icon.props.fill_color = style.COLOR_WHITE.get_svg()
 | 
						|
 | 
						|
    def __enter_notify_event_cb(self, icon, event):
 | 
						|
        if not self.get_active():
 | 
						|
            self._icon.props.fill_color = style.COLOR_BUTTON_GREY.get_svg()
 | 
						|
 | 
						|
    def __leave_notify_event_cb(self, icon, event):
 | 
						|
        if not self.get_active():
 | 
						|
            self._icon.props.fill_color = style.COLOR_TRANSPARENT.get_svg()
 | 
						|
 | 
						|
 | 
						|
class NamingAlert(Gtk.Window):
 | 
						|
 | 
						|
    __gtype_name__ = 'SugarNamingAlert'
 | 
						|
 | 
						|
    def __init__(self, activity, bundle_path):
 | 
						|
        GObject.GObject.__init__(self)
 | 
						|
 | 
						|
        self._bundle_path = bundle_path
 | 
						|
        self._favorite_icon = None
 | 
						|
        self._title = None
 | 
						|
        self._description = None
 | 
						|
        self._tags = None
 | 
						|
 | 
						|
        accel_group = Gtk.AccelGroup()
 | 
						|
        self.set_data('sugar-accel-group', accel_group)
 | 
						|
        self.add_accel_group(accel_group)
 | 
						|
 | 
						|
        self.set_border_width(style.LINE_WIDTH)
 | 
						|
        offset = style.GRID_CELL_SIZE
 | 
						|
        width = Gdk.Screen.width() - offset * 2
 | 
						|
        height = Gdk.Screen.height() - offset * 2
 | 
						|
        self.set_size_request(width, height)
 | 
						|
        self.set_position(Gtk.WindowPosition.CENTER_ALWAYS)
 | 
						|
        self.set_decorated(False)
 | 
						|
        self.set_resizable(False)
 | 
						|
        self.set_modal(True)
 | 
						|
        self.connect('realize', self.__realize_cb)
 | 
						|
 | 
						|
        self._activity = activity
 | 
						|
 | 
						|
        vbox = Gtk.VBox()
 | 
						|
        self.add(vbox)
 | 
						|
        vbox.show()
 | 
						|
 | 
						|
        toolbar = NamingToolbar()
 | 
						|
        toolbar.connect('keep-clicked', self.__keep_cb)
 | 
						|
        vbox.pack_start(toolbar, False, False, 0)
 | 
						|
        toolbar.show()
 | 
						|
 | 
						|
        body = self._create_body()
 | 
						|
        vbox.pack_start(body, True, True, 0)
 | 
						|
        body.show()
 | 
						|
 | 
						|
        self._title.grab_focus()
 | 
						|
 | 
						|
    def _create_body(self):
 | 
						|
        body = Gtk.VBox(spacing=style.DEFAULT_SPACING)
 | 
						|
        body.set_border_width(style.DEFAULT_SPACING * 3)
 | 
						|
        header = self._create_header()
 | 
						|
        body.pack_start(header, False, False, style.DEFAULT_PADDING)
 | 
						|
 | 
						|
        body.pack_start(self._create_separator(style.DEFAULT_SPACING, True, True, 0), False, False, 0)
 | 
						|
 | 
						|
        body.pack_start(self._create_label(_('Description:', True, True, 0)), False, False, 0)
 | 
						|
 | 
						|
        description = self._activity.metadata.get('description', '')
 | 
						|
        description_box, self._description = self._create_text_view(description)
 | 
						|
        body.pack_start(description_box, True, True, 0)
 | 
						|
 | 
						|
        body.pack_start(self._create_separator(style.DEFAULT_PADDING, True, True, 0), False, False, 0)
 | 
						|
 | 
						|
 | 
						|
        body.pack_start(self._create_label(_('Tags:', True, True, 0)), False, False, 0)
 | 
						|
 | 
						|
        tags = self._activity.metadata.get('tags', '')
 | 
						|
        tags_box, self._tags = self._create_text_view(tags)
 | 
						|
        body.pack_start(tags_box, True, True, 0)
 | 
						|
 | 
						|
        body.show_all()
 | 
						|
        return body
 | 
						|
 | 
						|
    def _create_label(self, text):
 | 
						|
        text = Gtk.Label(label=text)
 | 
						|
        text.set_alignment(0, 0.5)
 | 
						|
        text.modify_fg(Gtk.StateType.NORMAL,
 | 
						|
                       style.COLOR_BUTTON_GREY.get_gdk_color())
 | 
						|
        return text
 | 
						|
 | 
						|
    def _create_separator(self, height):
 | 
						|
        separator = Gtk.HSeparator()
 | 
						|
        separator.modify_bg(Gtk.StateType.NORMAL, style.COLOR_WHITE.get_gdk_color())
 | 
						|
        separator.set_size_request(-1, height)
 | 
						|
        return separator
 | 
						|
 | 
						|
    def _create_header(self):
 | 
						|
        header = Gtk.HBox(spacing=style.DEFAULT_SPACING)
 | 
						|
 | 
						|
        self._favorite_icon = FavoriteIcon()
 | 
						|
        header.pack_start(self._favorite_icon, False, True, 0)
 | 
						|
 | 
						|
        entry_icon = self._create_entry_icon()
 | 
						|
        header.pack_start(entry_icon, False, True, 0)
 | 
						|
 | 
						|
        self._title = self._create_title()
 | 
						|
        header.pack_start(self._title, True, True, 0)
 | 
						|
 | 
						|
        return header
 | 
						|
 | 
						|
    def _create_entry_icon(self):
 | 
						|
        bundle_id = self._activity.metadata.get('activity', '')
 | 
						|
        if not bundle_id:
 | 
						|
            bundle_id = self._activity.metadata.get('bundle_id', '')
 | 
						|
 | 
						|
        if bundle_id == '':
 | 
						|
            file_name = _get_icon_name(self._activity.metadata)
 | 
						|
        else:
 | 
						|
            activity_bundle = ActivityBundle(self._bundle_path)
 | 
						|
            file_name = activity_bundle.get_icon()
 | 
						|
        entry_icon = Icon(file=file_name, icon_size=Gtk.IconSize.LARGE_TOOLBAR)
 | 
						|
        if self._activity.metadata.get('icon-color'):
 | 
						|
            entry_icon.props.xo_color = XoColor( \
 | 
						|
                self._activity.metadata['icon-color'])
 | 
						|
        return entry_icon
 | 
						|
 | 
						|
    def _create_title(self):
 | 
						|
        title = Gtk.Entry()
 | 
						|
        title.set_text(self._activity.metadata.get('title', _('Untitled')))
 | 
						|
        return title
 | 
						|
 | 
						|
    def _create_text_view(self, text):
 | 
						|
        scrolled_window = Gtk.ScrolledWindow()
 | 
						|
        scrolled_window.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC)
 | 
						|
        scrolled_window.set_border_width(style.LINE_WIDTH)
 | 
						|
        scrolled_window.set_shadow_type(Gtk.ShadowType.IN)
 | 
						|
 | 
						|
        text_view = Gtk.TextView()
 | 
						|
        text_view.set_left_margin(style.DEFAULT_PADDING)
 | 
						|
        text_view.set_wrap_mode(Gtk.WrapMode.WORD_CHAR)
 | 
						|
        text_view.set_accepts_tab(False)
 | 
						|
        text_view.get_buffer().set_text(text)
 | 
						|
        scrolled_window.add(text_view)
 | 
						|
 | 
						|
        return scrolled_window, text_view
 | 
						|
 | 
						|
    def __realize_cb(self, widget):
 | 
						|
        self.set_type_hint(Gdk.WindowTypeHint.DIALOG)
 | 
						|
        self.window.set_accept_focus(True)
 | 
						|
 | 
						|
    def __keep_cb(self, widget):
 | 
						|
        if self._favorite_icon.get_active():
 | 
						|
            self._activity.metadata['keep'] = 1
 | 
						|
        else:
 | 
						|
            self._activity.metadata['keep'] = 0
 | 
						|
 | 
						|
        self._activity.metadata['title'] = self._title.get_text()
 | 
						|
 | 
						|
        text_buffer = self._tags.get_buffer()
 | 
						|
        start, end = text_buffer.get_bounds()
 | 
						|
        new_tags = text_buffer.get_text(start, end, False)
 | 
						|
        self._activity.metadata['tags'] = new_tags
 | 
						|
 | 
						|
        text_buffer = self._description.get_buffer()
 | 
						|
        start, end = text_buffer.get_bounds()
 | 
						|
        new_description = text_buffer.get_text(start, end, False)
 | 
						|
        self._activity.metadata['description'] = new_description
 | 
						|
 | 
						|
        self._activity.metadata['title_set_by_user'] = '1'
 | 
						|
        self._activity.close()
 | 
						|
        self.destroy()
 |