From af354463e4111ad16c3a05163ef03b6aba9b1d1a Mon Sep 17 00:00:00 2001 From: flavio Date: Mon, 28 May 2012 22:42:41 +0000 Subject: Sugar3 Base --- diff --git a/activity.py b/activity.py index d84e194..ecec32c 100644 --- a/activity.py +++ b/activity.py @@ -1,4 +1,4 @@ -# Copyright 2007-2008 One Laptop Per Child +#Copyright 2007-2008 One Laptop Per Child # # 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 @@ -14,7 +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 gtk +from gi.repository import Gtk, Gdk, GdkPixbuf import logging import cjson import math @@ -28,14 +28,14 @@ from telepathy.constants import ( CHANNEL_TEXT_MESSAGE_TYPE_NORMAL) from telepathy.client import Connection, Channel -from sugar.graphics import style -from sugar.graphics.alert import NotifyAlert -from sugar.graphics.palette import Palette -from sugar.graphics.toolbarbox import ToolbarBox -from sugar.activity import activity -from sugar.presence import presenceservice -from sugar.activity.widgets import ActivityButton, TitleEntry -from sugar.activity.widgets import StopButton, ShareButton, RadioMenuButton +from sugar3.graphics import style +from sugar3.graphics.alert import NotifyAlert +from sugar3.graphics.palette import Palette +from sugar3.graphics.toolbarbox import ToolbarBox +from sugar3.activity import activity +from sugar3.presence import presenceservice +from sugar3.activity.widgets import ActivityButton, TitleEntry +from sugar3.activity.widgets import StopButton, ShareButton, RadioMenuButton from chat import smilies from chat.box import ChatBox @@ -68,10 +68,10 @@ class Chat(activity.Activity): toolbar_box.toolbar.insert(TitleEntry(self), -1) try: - from sugar.activity.widgets import DescriptionItem + from sugar3.activity.widgets import DescriptionItem except ImportError: logger.debug('DescriptionItem button is not available, ' \ - 'toolkit version < 0.96') + 'toolkit version < 0.96') else: description_item = DescriptionItem(self) toolbar_box.toolbar.insert(description_item, -1) @@ -80,7 +80,7 @@ class Chat(activity.Activity): share_button = ShareButton(self) toolbar_box.toolbar.insert(share_button, -1) - separator = gtk.SeparatorToolItem() + separator = Gtk.SeparatorToolItem() toolbar_box.toolbar.insert(separator, -1) self._smiley = RadioMenuButton(icon_name='smilies') @@ -92,7 +92,7 @@ class Chat(activity.Activity): table.show_all() self._smiley.palette.set_content(table) - separator = gtk.SeparatorToolItem() + separator = Gtk.SeparatorToolItem() separator.props.draw = False separator.set_expand(True) toolbar_box.toolbar.insert(separator, -1) @@ -113,37 +113,35 @@ class Chat(activity.Activity): # we have already joined self._joined_cb(self) elif handle.uri: - # XMPP non-Sugar incoming chat, not sharable + # XMPP non-sugar3 incoming chat, not sharable share_button.props.visible = False self._one_to_one_connection(handle.uri) else: # we are creating the activity if not self.metadata or self.metadata.get('share-scope', - activity.SCOPE_PRIVATE) == activity.SCOPE_PRIVATE: + activity.SCOPE_PRIVATE) == activity.SCOPE_PRIVATE: # if we are in private session self._alert(_('Off-line'), _('Share, or invite someone.')) self.connect('shared', self._shared_cb) def _create_pallete_smiley_table(self): row_count = int(math.ceil(len(smilies.THEME) / float(SMILIES_COLUMNS))) - table = gtk.Table(rows=row_count, columns=SMILIES_COLUMNS) + table = Gtk.Table(rows=row_count, columns=SMILIES_COLUMNS) index = 0 for y in range(row_count): for x in range(SMILIES_COLUMNS): if index >= len(smilies.THEME): break - path, hint, codes = smilies.THEME[index] - image = gtk.image_new_from_file(path) - button = gtk.ToolButton(icon_widget=image) - button.set_tooltip(gtk.Tooltips(), codes[0] + ' ' + hint) + image = Gtk.Image() + image.set_from_file(path) + button = Gtk.ToolButton() + button.set_icon_widget(image) button.connect('clicked', self._add_smiley_to_entry, codes[0]) table.attach(button, x, x + 1, y, y + 1) button.show() - index = index + 1 - return table def _add_smiley_to_entry(self, button, text): @@ -158,15 +156,13 @@ class Chat(activity.Activity): self._setup() def _one_to_one_connection(self, tp_channel): - """Handle a private invite from a non-Sugar XMPP client.""" + """Handle a private invite from a non-sugar3 XMPP client.""" if self.shared_activity or self.text_channel: return bus_name, connection, channel = cjson.decode(tp_channel) - logger.debug('GOT XMPP: %s %s %s', bus_name, connection, - channel) - Connection( - bus_name, connection, ready_handler=lambda conn: \ - self._one_to_one_connection_ready_cb(bus_name, channel, conn)) + logger.debug('GOT XMPP: %s %s %s', bus_name, connection,channel) + Connection( bus_name, connection, ready_handler=lambda conn: \ + self._one_to_one_connection_ready_cb(bus_name, channel, conn)) def _one_to_one_connection_ready_cb(self, bus_name, channel, conn): """Callback for Connection for one to one connection""" @@ -237,52 +233,52 @@ class Chat(activity.Activity): if buddy == self.owner: return self.chatbox.add_text(buddy, - buddy.props.nick + ' ' + _('joined the chat'), - status_message=True) + buddy.props.nick + ' ' + _('joined the chat'), + status_message=True) def _buddy_left_cb(self, sender, buddy): """Show a buddy who joined""" if buddy == self.owner: return self.chatbox.add_text(buddy, - buddy.props.nick + ' ' + _('left the chat'), - status_message=True) + buddy.props.nick + ' ' + _('left the chat'), + status_message=True) def _buddy_already_exists(self, buddy): """Show a buddy already in the chat.""" if buddy == self.owner: return self.chatbox.add_text(buddy, buddy.props.nick + ' ' + _('is here'), - status_message=True) + status_message=True) def can_close(self): """Perform cleanup before closing. - Close text channel of a one to one XMPP chat. + Close text channel of a one to one XMPP chat. - """ + """ if self._chat_is_room is False: if self.text_channel is not None: self.text_channel.close() return True def make_root(self): - entry = gtk.Entry() - entry.modify_bg(gtk.STATE_INSENSITIVE, - style.COLOR_WHITE.get_gdk_color()) - entry.modify_base(gtk.STATE_INSENSITIVE, - style.COLOR_WHITE.get_gdk_color()) + entry = Gtk.Entry() + entry.modify_bg(Gtk.StateType.INSENSITIVE, + style.COLOR_WHITE.get_gdk_color()) + entry.modify_base(Gtk.StateType.INSENSITIVE, + style.COLOR_WHITE.get_gdk_color()) entry.set_sensitive(False) entry.connect('activate', self.entry_activate_cb) entry.connect('key-press-event', self.entry_key_press_cb) self.entry = entry - hbox = gtk.HBox() + hbox = Gtk.HBox() hbox.add(entry) - box = gtk.VBox(homogeneous=False) - box.pack_start(self.chatbox) - box.pack_start(hbox, expand=False) + box = Gtk.VBox(homogeneous=False) + box.pack_start(self.chatbox, True, True, 0) + box.pack_start(hbox, False, True, 0) return box @@ -293,18 +289,18 @@ class Chat(activity.Activity): scroll the window according the pressed key. """ vadj = self.chatbox.get_vadjustment() - if event.keyval == gtk.keysyms.Page_Down: + if event.keyval == Gdk.KEY_Page_Down: value = vadj.get_value() + vadj.page_size if value > vadj.upper - vadj.page_size: value = vadj.upper - vadj.page_size vadj.set_value(value) - elif event.keyval == gtk.keysyms.Page_Up: + elif event.keyval == Gdk.KEY_Page_Up: vadj.set_value(vadj.get_value() - vadj.page_size) - elif event.keyval == gtk.keysyms.Home and \ - event.state & gtk.gdk.CONTROL_MASK: + elif event.keyval == Gdk.KEY_Home and \ + event.get_state() & Gdk.ModifierType.CONTROL_MASK: vadj.set_value(vadj.lower) - elif event.keyval == gtk.keysyms.End and \ - event.state & gtk.gdk.CONTROL_MASK: + elif event.keyval == Gdk.KEY_End and \ + event.get_state() & Gdk.ModifierType.CONTROL_MASK: vadj.set_value(vadj.upper - vadj.page_size) def entry_activate_cb(self, entry): @@ -338,7 +334,6 @@ class Chat(activity.Activity): def read_file(self, file_path): """Load a chat log from the Journal. - Handling the Journal is provided by Activity - we only need to define this method. """ @@ -355,10 +350,9 @@ class Chat(activity.Activity): timestamp, nick, color, status, text = line.strip().split('\t') status_message = bool(int(status)) self.chatbox.add_text({'nick': nick, 'color': color}, - text, status_message) + text, status_message) last_line_was_timestamp = False - class TextChannelWrapper(object): """Wrap a telepathy Text Channel to make usage simpler.""" @@ -439,7 +433,7 @@ class TextChannelWrapper(object): CONN_INTERFACE_ALIASING].RequestAliases([sender])[0] buddy = {'nick': nick, 'color': '#000000,#808080'} else: - # Normal sugar MUC chat + # Normal sugar3 MUC chat # XXX: cache these buddy = self._get_buddy(sender) self._activity_cb(buddy, text) diff --git a/chat/box.py b/chat/box.py index bd8625b..98dae8d 100644 --- a/chat/box.py +++ b/chat/box.py @@ -22,19 +22,18 @@ import time import logging from datetime import datetime from gettext import gettext as _ -from os.path import join -import gtk -import pango +from gi.repository import Gtk, Gdk, GObject, GdkPixbuf +from gi.repository import Pango -from sugar.graphics import style -from sugar.graphics.palette import Palette, MouseSpeedDetector -from sugar.presence import presenceservice -from sugar.graphics.menuitem import MenuItem -from sugar.activity.activity import get_activity_root, show_object_in_journal -from sugar.util import timestamp_to_elapsed_string -from sugar.datastore import datastore -from sugar import profile +from sugar3.graphics import style +from sugar3.graphics.palette import Palette, MouseSpeedDetector +from sugar3.presence import presenceservice +from sugar3.graphics.menuitem import MenuItem +from sugar3.activity.activity import get_activity_root, show_object_in_journal +from sugar3.util import timestamp_to_elapsed_string +from sugar3.datastore import datastore +from sugar3 import profile from chat import smilies from chat.roundbox import RoundBox @@ -45,37 +44,37 @@ _URL_REGEXP = re.compile('((http|ftp)s?://)?' '(:[1-9][0-9]{0,4})?(/[-a-zA-Z0-9/%~@&_+=;:,.?#]*[a-zA-Z0-9/])?') -class TextBox(gtk.TextView): +class TextBox(Gtk.TextView): - hand_cursor = gtk.gdk.Cursor(gtk.gdk.HAND2) + hand_cursor = Gdk.Cursor.new(Gdk.CursorType.HAND2) def __init__(self, color, bg_color, lang_rtl): self._lang_rtl = lang_rtl - gtk.TextView.__init__(self) + GObject.GObject.__init__(self) self.set_editable(False) self.set_cursor_visible(False) - self.set_wrap_mode(gtk.WRAP_WORD_CHAR) + self.set_wrap_mode(Gtk.WrapMode.WORD_CHAR) self.get_buffer().set_text("", 0) self.iter_text = self.get_buffer().get_iter_at_offset(0) self.fg_tag = self.get_buffer().create_tag("foreground_color", foreground=color.get_html()) self._subscript_tag = self.get_buffer().create_tag('subscript', - rise=-7 * pango.SCALE) # in pixels + rise=-7 * Pango.SCALE) # in pixels self._empty = True self.palette = None - self._mouse_detector = MouseSpeedDetector(self, 200, 5) + self._mouse_detector = MouseSpeedDetector(200, 5) self._mouse_detector.connect('motion-slow', self.__mouse_slow_cb) - self.modify_base(gtk.STATE_NORMAL, bg_color.get_gdk_color()) + self.modify_bg(0, bg_color.get_gdk_color()) - self.add_events(gtk.gdk.POINTER_MOTION_MASK | \ - gtk.gdk.BUTTON_PRESS_MASK | \ - gtk.gdk.BUTTON_RELEASE_MASK | \ - gtk.gdk.LEAVE_NOTIFY_MASK) + self.add_events(Gdk.EventMask.POINTER_MOTION_MASK | \ + Gdk.EventMask.BUTTON_PRESS_MASK | \ + Gdk.EventMask.BUTTON_RELEASE_MASK | \ + Gdk.EventMask.LEAVE_NOTIFY_MASK) self.connect('event-after', self.__event_after_cb) self.connect('button-press-event', self.__button_press_cb) self.motion_notify_id = self.connect('motion-notify-event', \ - self.__motion_notify_cb) + self.__motion_notify_cb) self.connect('visibility-notify-event', self.__visibility_notify_cb) self.connect('leave-notify-event', self.__leave_notify_event_cb) @@ -83,16 +82,16 @@ class TextBox(gtk.TextView): self._mouse_detector.stop() def __button_press_cb(self, widget, event): - if event.type == gtk.gdk.BUTTON_PRESS and event.button == 3: + if event.type == Gdk.EventType.BUTTON_PRESS and event.button == 3: # To disable the standard textview popup return True # Links can be activated by clicking. def __event_after_cb(self, widget, event): - if event.type != gtk.gdk.BUTTON_RELEASE: + if event.type.value_name != 'GDK_BUTTON_RELEASE': return False - x, y = self.window_to_buffer_coords(gtk.TEXT_WINDOW_WIDGET, + x, y = self.window_to_buffer_coords(Gtk.TextWindowType.WIDGET, int(event.x), int(event.y)) iter_tags = self.get_iter_at_location(x, y) @@ -122,7 +121,7 @@ class TextBox(gtk.TextView): } for k, v in metadata.items(): jobject.metadata[k] = v - file_path = join(get_activity_root(), 'instance', '%i_' % time.time()) + file_path = os.path.join(get_activity_root(), 'instance', '%i_' % time.time()) open(file_path, 'w').write(url + '\r\n') os.chmod(file_path, 0755) jobject.set_file_path(file_path) @@ -158,7 +157,7 @@ class TextBox(gtk.TextView): # and if one of them is a link, change the cursor to the "hands" cursor hovering_over_link = self.check_url_hovering(x, y) - win = self.get_window(gtk.TEXT_WINDOW_TEXT) + win = self.get_window(Gtk.TextWindowType.TEXT) if hovering_over_link: win.set_cursor(self.hand_cursor) self._mouse_detector.start() @@ -170,29 +169,27 @@ class TextBox(gtk.TextView): x, y = self.get_pointer() hovering_over_link = self.check_url_hovering(x, y) if hovering_over_link: - if self.palette is not None: + if self.palette != None: xw, yw = self.get_toplevel().get_pointer() self.palette.move(xw, yw) self.palette.popup() self._mouse_detector.stop() else: - if self.palette is not None: + if self.palette != None: self.palette.popdown() # Update the cursor image if the pointer moved. def __motion_notify_cb(self, widget, event): - x, y = self.window_to_buffer_coords(gtk.TEXT_WINDOW_WIDGET, + x, y = self.window_to_buffer_coords(Gtk.TextWindowType.WIDGET, int(event.x), int(event.y)) self.set_cursor_if_appropriate(x, y) - self.window.get_pointer() + self.get_pointer() return False def __visibility_notify_cb(self, widget, event): # Also update the cursor image if the window becomes visible # (e.g. when a window covering it got iconified). - - wx, wy, __ = self.window.get_pointer() - bx, by = self.window_to_buffer_coords(gtk.TEXT_WINDOW_WIDGET, wx, wy) + bx, by = self.window_to_buffer_coords(Gtk.TextWindowType.WIDGET, 200, 200) self.set_cursor_if_appropriate(bx, by) return False @@ -212,50 +209,44 @@ class TextBox(gtk.TextView): for word in words: if _URL_REGEXP.match(word) is not None: tag = buf.create_tag(None, - foreground="blue", underline=pango.UNDERLINE_SINGLE) + foreground="blue", underline=Pango.Underline.SINGLE) tag.set_data("url", word) palette = _URLMenu(word) palette.connect('enter-notify-event', - self.__palette_mouse_enter_cb) + self.__palette_mouse_enter_cb) palette.connect('leave-notify-event', - self.__palette_mouse_leave_cb) + self.__palette_mouse_leave_cb) tag.set_data('palette', palette) buf.insert_with_tags(self.iter_text, word, tag, - self.fg_tag) + self.fg_tag) else: for i in smilies.parse(word): - if isinstance(i, gtk.gdk.Pixbuf): + if isinstance(i, GdkPixbuf.Pixbuf): start = self.iter_text.get_offset() buf.insert_pixbuf(self.iter_text, i) buf.apply_tag(self._subscript_tag, - buf.get_iter_at_offset(start), self.iter_text) + buf.get_iter_at_offset(start), self.iter_text) else: buf.insert_with_tags(self.iter_text, i, self.fg_tag) - buf.insert_with_tags(self.iter_text, ' ', - self.fg_tag) + buf.insert_with_tags(self.iter_text, ' ', self.fg_tag) self._empty = False - -class ColorLabel(gtk.Label): - +class ColorLabel(Gtk.Label): def __init__(self, text, color=None): - self._color = color - if self._color is not None: - text = '' % self._color.get_html() + \ - text + '' - gtk.Label.__init__(self) - self.set_use_markup(True) - self.set_markup(text) - - -class ChatBox(gtk.ScrolledWindow): - + GObject.GObject.__init__(self) + self.set_use_markup(True) + self._color = color + if self._color != None: + text = '%s' % (self._color.get_html(), text) + self.set_markup(text) + +class ChatBox(Gtk.ScrolledWindow): def __init__(self): - gtk.ScrolledWindow.__init__(self) + GObject.GObject.__init__(self) self.owner = presenceservice.get_instance().get_owner() - + # Auto vs manual scrolling: self._scroll_auto = True self._scroll_value = 0.0 @@ -263,32 +254,31 @@ class ChatBox(gtk.ScrolledWindow): # Track last message, to combine several messages: self._last_msg = None self._chat_log = '' - - self._conversation = gtk.VBox() + + self._conversation = Gtk.VBox() self._conversation.set_homogeneous(False) - evbox = gtk.EventBox() - evbox.modify_bg(gtk.STATE_NORMAL, style.COLOR_WHITE.get_gdk_color()) + evbox = Gtk.EventBox() + evbox.modify_bg(Gtk.StateType.NORMAL, style.COLOR_WHITE.get_gdk_color()) evbox.add(self._conversation) - - self.set_policy(gtk.POLICY_NEVER, gtk.POLICY_ALWAYS) + + self.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.ALWAYS) self.add_with_viewport(evbox) vadj = self.get_vadjustment() vadj.connect('changed', self._scroll_changed_cb) vadj.connect('value-changed', self._scroll_value_changed_cb) - + def get_log(self): return self._chat_log def add_text(self, buddy, text, status_message=False): """Display text on screen, with name and colors. - buddy -- buddy object or dict {nick: string, color: string} - (The dict is for loading the chat log from the journal, - when we don't have the buddy object any more.) + (The dict is for loading the chat log from the journal, + when we don't have the buddy object any more.) text -- string, what the buddy said status_message -- boolean - False: show what buddy said - True: show what buddy did + False: show what buddy said + True: show what buddy did .------------- rb ---------------. | +name_vbox+ +----align-----+ | @@ -301,7 +291,7 @@ class ChatBox(gtk.ScrolledWindow): """ if not buddy: buddy = self.owner - + if type(buddy) is dict: # dict required for loading chat log from journal nick = buddy['nick'] @@ -313,27 +303,27 @@ class ChatBox(gtk.ScrolledWindow): color_stroke_html, color_fill_html = color.split(',') except ValueError: color_stroke_html, color_fill_html = ('#000000', '#888888') - + # Select text color based on fill color: color_fill_rgba = style.Color(color_fill_html).get_rgba() color_fill_gray = (color_fill_rgba[0] + color_fill_rgba[1] + - color_fill_rgba[2]) / 3 + color_fill_rgba[2]) / 3 color_stroke = style.Color(color_stroke_html) color_fill = style.Color(color_fill_html) - + if color_fill_gray < 0.5: text_color = style.COLOR_WHITE else: text_color = style.COLOR_BLACK - + self._add_log(nick, color, text, status_message) - + # Check for Right-To-Left languages: - if pango.find_base_dir(nick, -1) == pango.DIRECTION_RTL: + if Pango.find_base_dir(nick, -1) == Pango.Direction.RTL: lang_rtl = True else: lang_rtl = False - + # Check if new message box or add text to previous: new_msg = True if self._last_msg_sender: @@ -341,62 +331,59 @@ class ChatBox(gtk.ScrolledWindow): if buddy == self._last_msg_sender: # Add text to previous message new_msg = False - + if not new_msg: message = self._last_msg else: - rb = RoundBox() - screen_width = gtk.gdk.screen_width() - # keep space to the scrollbar - rb.set_size_request(screen_width - 50, -1) - rb.background_color = color_fill - rb.border_color = color_stroke - self._last_msg_sender = buddy - if not status_message: - name = ColorLabel(text=nick + ': ', color=text_color) - name_vbox = gtk.VBox() - name_vbox.pack_start(name, False, False) - rb.pack_start(name_vbox, False, False, padding=5) - - message = TextBox(text_color, color_fill, lang_rtl) - vbox = gtk.VBox() - vbox.pack_start(message, True, True, padding=5) - rb.pack_start(vbox, True, True, padding=5) - self._last_msg = message - self._conversation.pack_start(rb, False, False, padding=2) - + rb = RoundBox() + screen_width = Gdk.Screen.width() + # keep space to the scrollbar + rb.background_color = color_fill + rb.border_color = color_stroke + self._last_msg_sender = buddy + if not status_message: + name = ColorLabel(text='%s: ' % (nick), color=text_color) + name_vbox = Gtk.VBox() + name_vbox.pack_start(name, False, False, 0) + rb.pack_start(name_vbox, False, False,0) + + message = TextBox(text_color, color_fill, lang_rtl) + vbox = Gtk.VBox() + vbox.pack_start(message, True, True,0) + rb.pack_start(vbox, True, True,0) + self._last_msg = message + self._conversation.pack_start(rb, False, False, 2) + if status_message: self._last_msg_sender = None message.add_text(text) self._conversation.show_all() - + def add_separator(self, timestamp): - """Add whitespace and timestamp between chat sessions.""" - time_with_current_year = (time.localtime(time.time())[0],) +\ + """Add whitespace and timestamp between chat sessions.""" + time_with_current_year = (time.localtime(time.time())[0],) +\ time.strptime(timestamp, "%b %d %H:%M:%S")[1:] - - timestamp_seconds = time.mktime(time_with_current_year) - if timestamp_seconds > time.time(): - time_with_previous_year = (time.localtime(time.time())[0] - 1,) +\ + + timestamp_seconds = time.mktime(time_with_current_year) + if timestamp_seconds > time.time(): + time_with_previous_year = (time.localtime(time.time())[0] - 1,) +\ time.strptime(timestamp, "%b %d %H:%M:%S")[1:] - timestamp_seconds = time.mktime(time_with_previous_year) - - message = ColorLabel( - text=timestamp_to_elapsed_string(timestamp_seconds), - color=style.COLOR_BUTTON_GREY) - - box = gtk.HBox() - box.show() - align = gtk.Alignment(xalign=0.5, yalign=0.0, xscale=0.0, yscale=0.0) - box.pack_start(align, True, True) - align.add(message) - box.show_all() - self._conversation.pack_start(box, False, False) - self.add_log_timestamp(timestamp) - - self._last_msg_sender = None - + timestamp_seconds = time.mktime(time_with_previous_year) + + message = ColorLabel( + text=timestamp_to_elapsed_string(timestamp_seconds), + color=style.COLOR_BUTTON_GREY) + box = Gtk.HBox() + box.show() + align = Gtk.Alignment.new(xalign=0.5, yalign=0.0, xscale=0.0, yscale=0.0) + box.pack_start(align, True, True, 0) + align.add(message) + box.show_all() + self._conversation.pack_start(box, False, False, 0) + self.add_log_timestamp(timestamp) + self._last_msg_sender = None + def add_log_timestamp(self, existing_timestamp=None): """Add a timestamp entry to the chat log.""" if existing_timestamp is not None: @@ -404,10 +391,9 @@ class ChatBox(gtk.ScrolledWindow): else: self._chat_log += '%s\t\t\n' % ( datetime.strftime(datetime.now(), '%b %d %H:%M:%S')) - + def _add_log(self, nick, color, text, status_message): """Add the text to the chat log. - nick -- string, buddy nickname color -- string, buddy.props.color text -- string, body of message @@ -424,33 +410,28 @@ class ChatBox(gtk.ScrolledWindow): self._chat_log += '%s\t%s\t%s\t%d\t%s\n' % ( datetime.strftime(datetime.now(), '%b %d %H:%M:%S'), nick, color, status_message, text) - + def _scroll_value_changed_cb(self, adj, scroll=None): """Turn auto scrolling on or off. - If the user scrolled up, turn it off. If the user scrolled to the bottom, turn it back on. """ if adj.get_value() < self._scroll_value: self._scroll_auto = False - elif adj.get_value() == adj.upper - adj.page_size: + elif adj.get_value() == adj.get_upper() - adj.get_page_size(): self._scroll_auto = True - + def _scroll_changed_cb(self, adj, scroll=None): """Scroll the chat window to the bottom""" if self._scroll_auto: - adj.set_value(adj.upper - adj.page_size) + adj.set_value(adj.get_upper() - adj.get_page_size()) self._scroll_value = adj.get_value() - - + class _URLMenu(Palette): - def __init__(self, url): Palette.__init__(self, url) - self.owns_clipboard = False self.url = _url_check_protocol(url) - menu_item = MenuItem(_('Copy to Clipboard'), 'edit-copy') menu_item.connect('activate', self._copy_to_clipboard_cb) self.menu.append(menu_item) @@ -461,21 +442,21 @@ class _URLMenu(Palette): def _copy_to_clipboard_cb(self, menuitem): logging.debug('Copy %s to clipboard', self.url) - clipboard = gtk.clipboard_get() + clipboard = Gtk.clipboard_get() targets = [("text/uri-list", 0, 0), - ("UTF8_STRING", 0, 1)] - + ("UTF8_STRING", 0, 1)] + if not clipboard.set_with_data(targets, - self._clipboard_data_get_cb, - self._clipboard_clear_cb, - (self.url)): + self._clipboard_data_get_cb, + self._clipboard_clear_cb, + (self.url)): logging.debug('GtkClipboard.set_with_data failed!') else: self.owns_clipboard = True - + def _clipboard_data_get_cb(self, clipboard, selection, info, data): logging.debug('_clipboard_data_get_cb data=%s target=%s', data, - selection.target) + selection.target) if selection.target in ['text/uri-list']: if not selection.set_uris([data]): logging.debug('failed to set_uris') @@ -483,24 +464,22 @@ class _URLMenu(Palette): logging.debug('not uri') if not selection.set_text(data): logging.debug('failed to set_text') - + def _clipboard_clear_cb(self, clipboard, data): logging.debug('clipboard_clear_cb') self.owns_clipboard = False - -def _url_check_protocol(url): - """Check that the url has a protocol, otherwise prepend https:// - - url -- string - - Returns url -- string - """ - protocols = ['http://', 'https://', 'ftp://', 'ftps://'] - no_protocol = True - for protocol in protocols: - if url.startswith(protocol): - no_protocol = False - if no_protocol: - url = 'http://' + url - return url + def _url_check_protocol(url): + """Check that the url has a protocol, otherwise prepend https:// + url -- string + Returns url -- string + """ + protocols = ['http://', 'https://', 'ftp://', 'ftps://'] + no_protocol = True + for protocol in protocols: + if url.startswith(protocol): + no_protocol = False + if no_protocol: + url = 'http://' + url + return url + diff --git a/chat/roundbox.py b/chat/roundbox.py index 35d5f7c..ae5a4bb 100644 --- a/chat/roundbox.py +++ b/chat/roundbox.py @@ -1,100 +1,50 @@ import math -import gtk -from sugar.graphics import style +from gi.repository import Gtk, GObject, cairo +from sugar3.graphics import style +BORDER_DEFAULT = style.LINE_WIDTH -class RoundBox(gtk.HBox): +class RoundBox(Gtk.HBox): __gtype_name__ = 'RoundBox' - - _BORDER_DEFAULT = style.LINE_WIDTH - + def __init__(self, **kwargs): - gtk.HBox.__init__(self, **kwargs) - - self._x = None - self._y = None - self._width = None - self._height = None + GObject.GObject.__init__(self, **kwargs) self._radius = style.zoom(10) - self.border = self._BORDER_DEFAULT self.border_color = style.COLOR_BLACK self.background_color = None - self.set_reallocate_redraws(True) - self.set_resize_mode(gtk.RESIZE_PARENT) - self.connect("expose_event", self.__expose_cb) + self.set_resize_mode(Gtk.ResizeMode.PARENT) + self.connect("draw", self.__expose_cb) self.connect("add", self.__add_cb) - + def __add_cb(self, child, params): child.set_border_width(style.zoom(5)) - - def __size_allocate_cb(self, widget, allocation): - self._x = allocation.x - self._y = allocation.y - self._width = allocation.width - self._height = allocation.height - - def __expose_cb(self, widget, event): - context = widget.window.cairo_create() - - # set a clip region for the expose event - context.rectangle(event.area.x, event.area.y, - event.area.width, event.area.height) - context.clip() - self.draw(context) - return False - - def draw(self, cr): + + def __expose_cb(self, widget, cr): rect = self.get_allocation() - x = rect.x + self._BORDER_DEFAULT / 2 - y = rect.y + self._BORDER_DEFAULT / 2 - width = rect.width - self._BORDER_DEFAULT - height = rect.height - self._BORDER_DEFAULT + x = rect.x + y = rect.y + width = rect.width - BORDER_DEFAULT + height = rect.height - BORDER_DEFAULT - cr.move_to(x + self._radius, y) + cr.move_to(x, y) cr.arc(x + width - self._radius, y + self._radius, - self._radius, math.pi * 1.5, math.pi * 2) + self._radius, math.pi * 1.5, math.pi * 2) cr.arc(x + width - self._radius, y + height - self._radius, - self._radius, 0, math.pi * 0.5) + self._radius, 0, math.pi * 0.5) cr.arc(x + self._radius, y + height - self._radius, - self._radius, math.pi * 0.5, math.pi) + self._radius, math.pi * 0.5, math.pi) cr.arc(x + self._radius, y + self._radius, self._radius, - math.pi, math.pi * 1.5) + math.pi, math.pi * 1.5) cr.close_path() - if self.background_color is not None: + if self.background_color != None: r, g, b, __ = self.background_color.get_rgba() cr.set_source_rgb(r, g, b) cr.fill_preserve() - if self.border_color is not None: + if self.border_color != None: r, g, b, __ = self.border_color.get_rgba() cr.set_source_rgb(r, g, b) - cr.set_line_width(self.border) + cr.set_line_width(BORDER_DEFAULT) cr.stroke() - -if __name__ == '__main__': - - win = gtk.Window() - win.connect('destroy', gtk.main_quit) - win.set_default_size(450, 550) - vbox = gtk.VBox() - - box1 = RoundBox() - vbox.add(box1) - label1 = gtk.Label("Test 1") - box1.add(label1) - - rbox = RoundBox() - rbox.background_color = style.Color('#FF0000') - vbox.add(rbox) - label2 = gtk.Label("Test 2") - rbox.add(label2) - - bbox = RoundBox() - bbox.background_color = style.Color('#aaff33') - bbox.border_color = style.Color('#ff3300') - vbox.add(bbox) - - win.add(vbox) - win.show_all() - gtk.main() + return False diff --git a/chat/smilies.py b/chat/smilies.py index c3e4025..bf2740c 100644 --- a/chat/smilies.py +++ b/chat/smilies.py @@ -16,14 +16,10 @@ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA import os -from os.path import join, exists from gettext import gettext as _ - -import gtk -import cairo - -from sugar.graphics import style -from sugar.activity.activity import get_activity_root, get_bundle_path +from gi.repository import Gtk, GdkPixbuf, Rsvg +from sugar3.graphics import style +from sugar3.activity.activity import get_bundle_path THEME = [ # TRANS: A smiley (http://en.wikipedia.org/wiki/Smiley) explanation @@ -90,27 +86,24 @@ THEME = [ # TRANS: ASCII-art equivalents are /:) ('eyebrow', _('Raised eyebrows'), ['/:)']), ] - + SMILIES_SIZE = int(style.STANDARD_ICON_SIZE * 0.75) - _catalog = {} - def parse(text): """Parse text and find smiles. - :param text: - string to parse for smilies + string to parse for smilies :returns: - array of string parts and pixbufs - + array of string parts and pixbufs """ + result = [text] - + for smiley in sorted(_catalog.keys(), lambda x, y: cmp(len(y), len(x))): new_result = [] for word in result: - if isinstance(word, gtk.gdk.Pixbuf): + if isinstance(word, GdkPixbuf.Pixbuf): new_result.append(word) else: parts = word.split(smiley) @@ -119,68 +112,19 @@ def parse(text): new_result.append(_catalog[smiley]) new_result.append(parts[-1]) result = new_result - + return result - def init(): if _catalog: return - - png_dir = join(get_activity_root(), 'data', 'icons', 'smilies') - svg_dir = join(get_bundle_path(), 'icons', 'smilies') - - if not exists(png_dir): - os.makedirs(png_dir) - + + svg_dir = os.path.join(get_bundle_path(), 'icons', 'smilies') + for index, (name, hint, codes) in enumerate(THEME): - png_path = join(png_dir, name + '.png') - if exists(png_path): - pixbuf = gtk.gdk.pixbuf_new_from_file(png_path) - else: - pixbuf = _from_svg_at_size( - join(svg_dir, name + '.svg'), - SMILIES_SIZE, SMILIES_SIZE, None, True) - pixbuf.save(png_path, 'png') + archivo = os.path.join(svg_dir, '%s.svg' % (name)) + pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(archivo, SMILIES_SIZE, SMILIES_SIZE) for i in codes: _catalog[i] = pixbuf - THEME[index] = (png_path, hint, codes) - - -def _from_svg_at_size(filename=None, width=None, height=None, handle=None, - keep_ratio=True): - """Scale and load SVG into pixbuf.""" - import rsvg - - if not handle: - handle = rsvg.Handle(filename) - - dimensions = handle.get_dimension_data() - icon_width = dimensions[0] - icon_height = dimensions[1] - if icon_width != width or icon_height != height: - ratio_width = float(width) / icon_width - ratio_height = float(height) / icon_height - - if keep_ratio: - ratio = min(ratio_width, ratio_height) - if ratio_width != ratio: - ratio_width = ratio - width = int(icon_width * ratio) - elif ratio_height != ratio: - ratio_height = ratio - height = int(icon_height * ratio) - else: - ratio_width = 1 - ratio_height = 1 - - surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height) - context = cairo.Context(surface) - context.scale(ratio_width, ratio_height) - handle.render_cairo(context) - - loader = gtk.gdk.pixbuf_loader_new_with_mime_type('image/png') - surface.write_to_png(loader) - loader.close() - - return loader.get_pixbuf() + THEME[index] = (archivo, hint, codes) + diff --git a/setup.py b/setup.py index 530f97c..c60f4d0 100755 --- a/setup.py +++ b/setup.py @@ -16,6 +16,6 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -from sugar.activity import bundlebuilder +from sugar3.activity import bundlebuilder bundlebuilder.start() -- cgit v0.9.1