[Sugar-devel] [PATCH InfoSlicer] Port to Gtk3 SL #3742

Manuel Kaufmann humitos at gmail.com
Thu Jul 12 14:53:37 EDT 2012


The activity is almost ported but there are some issues that should be
solved in the future. Some of them are bugs already reported into
pygobject bug tracker.

 - Drag and Drop Images from the Edit View is not working
 - The arrow after drag-n-drop an image to the article is not added
 - On "Home View" we are not able to move the articles up or down

Signed-off-by: Manuel Kaufmann <humitos at gmail.com>
---
 activity.py                            |  138 +++++++++++++------------------
 book.py                                |   20 ++---
 bookview.py                            |  140 ++++++++++++++++++--------------
 edit.py                                |   14 ++--
 infoslicer/processing/Article.py       |   22 ++---
 infoslicer/processing/Paragraph.py     |    4 +-
 infoslicer/processing/Section.py       |    4 +-
 infoslicer/processing/Sentence.py      |   12 +--
 infoslicer/widgets/Edit_Pane.py        |   38 +++++----
 infoslicer/widgets/Editable_Textbox.py |   40 +++++----
 infoslicer/widgets/Editing_View.py     |   26 +++---
 infoslicer/widgets/Format_Pane.py      |   14 ++--
 infoslicer/widgets/Gallery_View.py     |   84 ++++++++++---------
 infoslicer/widgets/Image_Pane.py       |   30 +++----
 infoslicer/widgets/Reading_View.py     |   17 ++--
 infoslicer/widgets/Readonly_Textbox.py |   33 +++++---
 infoslicer/widgets/Textbox.py          |   22 ++---
 library.py                             |  121 +++++++++++++--------------
 net.py                                 |    2 +-
 setup.py                               |    2 +-
 toolbar.py                             |   26 +++---
 xol.py                                 |   64 ++++++++-------
 22 files changed, 455 insertions(+), 418 deletions(-)

diff --git a/activity.py b/activity.py
index 46cf2ad..fa94eab 100644
--- a/activity.py
+++ b/activity.py
@@ -12,34 +12,27 @@
 # 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
+from gi.repository import GObject
 from gettext import gettext as _
 
-from sugar.graphics.toolbutton import ToolButton
-from sugar.graphics.toggletoolbutton import ToggleToolButton
-from sugar.activity.activity import ActivityToolbox
-from sugar.activity import activity
+GObject.threads_init()
 
-OLD_TOOLBAR = False
-try:
-    from sugar.graphics.toolbarbox import ToolbarBox, ToolbarButton
-    from sugar.activity.widgets import StopButton
-    from sugar.graphics.radiotoolbutton import RadioToolButton
-    from sugar.activity.widgets import ActivityToolbarButton
-except ImportError:
-    OLD_TOOLBAR = True
+from sugar3.graphics.toolbutton import ToolButton
+from sugar3.graphics.toggletoolbutton import ToggleToolButton
+from sugar3.graphics.toolbarbox import ToolbarBox, ToolbarButton
+from sugar3.activity.widgets import StopButton
+from sugar3.activity import activity
+from sugar3.graphics.radiotoolbutton import RadioToolButton
+from sugar3.activity.widgets import ActivityToolbarButton
 
 import library
 import edit
 import book
 
-gtk.gdk.threads_init()
-gtk.gdk.threads_enter()
-
-
 class InfoslicerActivity(activity.Activity):
     def __init__(self, handle):
-        self.notebook = gtk.Notebook()
+        self.notebook = Gtk.Notebook()
         self.notebook.show()
         self.notebook.props.show_border = False
         self.notebook.props.show_tabs = False
@@ -60,71 +53,52 @@ class InfoslicerActivity(activity.Activity):
         self.edit = edit.View()
         self.library = library.View(self)
 
-        if OLD_TOOLBAR:
-            self.edit_toolbar = gtk.Toolbar()
-            self.edit_bar = edit.ToolbarBuilder(self.edit, self.edit_toolbar)
-            self.edit_toolbar.show_all()
-
-            self.library_toolbar = gtk.Toolbar()
-            self.library_bar = library.ToolbarBuilder(self.library,
-                    self.library_toolbar)
-            self.library_toolbar.show_all()
-
-            toolbox = ActivityToolbox(self)
-            toolbox.connect('current-toolbar-changed',
-                    self._toolbar_changed_cb)
-            self.set_toolbox(toolbox)
-            toolbox.add_toolbar(_('Library'), self.library_toolbar)
-            toolbox.add_toolbar(_('Edit'), self.edit_toolbar)
-            toolbox.set_current_toolbar(1)
-        else:
-            toolbar_box = ToolbarBox()
-            activity_button = ActivityToolbarButton(self)
-            toolbar_box.toolbar.insert(activity_button, 0)
-            self.set_toolbar_box(toolbar_box)
-            self._toolbar = toolbar_box.toolbar
-
-            tool_group = None
-            search_button = RadioToolButton()
-            search_button.props.group = tool_group
-            tool_group = search_button
-            search_button.props.icon_name = 'white-search'
-            search_button.set_tooltip(_('Library'))
-            search_button.mode = 'search'
-            search_button.connect('clicked', self.__mode_button_clicked)
-            self._toolbar.insert(search_button, -1)
-
-            edit_button = RadioToolButton()
-            edit_button.props.group = tool_group
-            edit_button.props.icon_name = 'toolbar-edit'
-            edit_button.set_tooltip(_('Edit'))
-            edit_button.mode = 'edit'
-            edit_button.connect('clicked', self.__mode_button_clicked)
-            self._toolbar.insert(edit_button, -1)
-            self._toolbar.insert(gtk.SeparatorToolItem(), -1)
-            self.edit_bar = edit.ToolbarBuilder(self.edit, self._toolbar)
-            self.library_bar = library.ToolbarBuilder(self.library,
-                                                      activity_button)
-            self.library_bar.publish.show()
-
-        edit_fake = gtk.EventBox()
-
-        self.notebook.append_page(self.library)
-        self.notebook.append_page(self.edit)
-        self.notebook.append_page(edit_fake)
+        toolbar_box = ToolbarBox()
+        activity_button = ActivityToolbarButton(self)
+        toolbar_box.toolbar.insert(activity_button, 0)
+        self.set_toolbar_box(toolbar_box)
+        self._toolbar = toolbar_box.toolbar
+
+        tool_group = None
+        search_button = RadioToolButton()
+        search_button.props.group = tool_group
+        tool_group = search_button
+        search_button.props.icon_name = 'white-search'
+        search_button.set_tooltip(_('Library'))
+        search_button.mode = 'search'
+        search_button.connect('clicked', self.__mode_button_clicked)
+        self._toolbar.insert(search_button, -1)
+
+        edit_button = RadioToolButton()
+        edit_button.props.group = tool_group
+        edit_button.props.icon_name = 'toolbar-edit'
+        edit_button.set_tooltip(_('Edit'))
+        edit_button.mode = 'edit'
+        edit_button.connect('clicked', self.__mode_button_clicked)
+        self._toolbar.insert(edit_button, -1)
+        self._toolbar.insert(Gtk.SeparatorToolItem(), -1)
+        self.edit_bar = edit.ToolbarBuilder(self.edit, self._toolbar)
+        self.library_bar = library.ToolbarBuilder(self.library,
+                                                  activity_button)
+        self.library_bar.publish.show()
+
+        edit_fake = Gtk.EventBox()
+
+        self.notebook.append_page(self.library, None)
+        self.notebook.append_page(self.edit, None)
+        self.notebook.append_page(edit_fake, None)
 
         self.show_all()
 
-        if not OLD_TOOLBAR:
-            self.__mode_button_clicked(search_button)
-            separator = gtk.SeparatorToolItem()
-            separator.props.draw = False
-            separator.set_expand(True)
-            separator.show()
-            self._toolbar.insert(separator, -1)
-            stop_button = StopButton(self)
-            stop_button.show()
-            self._toolbar.insert(stop_button, -1)
+        self.__mode_button_clicked(search_button)
+        separator = Gtk.SeparatorToolItem()
+        separator.props.draw = False
+        separator.set_expand(True)
+        separator.show()
+        self._toolbar.insert(separator, -1)
+        stop_button = StopButton(self)
+        stop_button.show()
+        self._toolbar.insert(stop_button, -1)
 
     def new_instance(self):
         self.instance()
@@ -138,9 +112,7 @@ class InfoslicerActivity(activity.Activity):
         book.custom.sync(filepath)
 
     def set_edit_sensitive(self, enable):
-        if OLD_TOOLBAR:
-            #self.edit_toolbar.props.sensitive = enable
-            self.edit_page = (enable and 1 or 2)
+        pass
 
     def _toolbar_changed_cb(self, widget, index):
         if index > 0:
diff --git a/book.py b/book.py
index f28ff99..02b13a6 100644
--- a/book.py
+++ b/book.py
@@ -13,17 +13,15 @@
 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
 import os
-import gtk
 import uuid
 import logging
-import gobject
+from gi.repository import GObject
 import cjson
 import shutil
 import zipfile
-from gobject import SIGNAL_RUN_FIRST, TYPE_PYOBJECT
 from gettext import gettext as _
 
-from sugar.activity.activity import get_bundle_path, get_activity_root
+from sugar3.activity.activity import get_bundle_path, get_activity_root
 
 import net
 from infoslicer.processing.Article import Article
@@ -36,11 +34,11 @@ custom = None
 
 image_root = os.path.join(get_activity_root(), 'data', 'book')
 
-class Book(gobject.GObject):
+class Book(GObject.GObject):
     __gsignals__ = {
-        'article-selected' : (SIGNAL_RUN_FIRST, None, [TYPE_PYOBJECT]),
-        'article-added'    : (SIGNAL_RUN_FIRST, None, [TYPE_PYOBJECT]),
-        'article-deleted'  : (SIGNAL_RUN_FIRST, None, [TYPE_PYOBJECT]) } 
+        'article-selected' : (GObject.SignalFlags.RUN_FIRST, None, [object]),
+        'article-added'    : (GObject.SignalFlags.RUN_FIRST, None, [object]),
+        'article-deleted'  : (GObject.SignalFlags.RUN_FIRST, None, [object])}
 
     def get_article(self):
         return self._article
@@ -71,9 +69,9 @@ class Book(gobject.GObject):
 
         self._article.uid = entry['uid']
         self._article.article_title = title
-        gobject.idle_add(self._emit_article_selected)
+        GObject.idle_add(self._emit_article_selected)
 
-    article = gobject.property(type=object,
+    article = GObject.property(type=object,
             getter=get_article, setter=set_article)
 
     def _emit_article_selected(self):
@@ -132,7 +130,7 @@ class Book(gobject.GObject):
         self.sync_index()
 
     def __init__(self, preinstalled, root):
-        gobject.GObject.__init__(self)
+        GObject.GObject.__init__(self)
         self.root = root
         self.index = []
         self.uid = None
diff --git a/bookview.py b/bookview.py
index e38662b..e165c19 100644
--- a/bookview.py
+++ b/bookview.py
@@ -13,75 +13,74 @@
 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
 import os
-import gtk
+from gi.repository import Gtk
 import logging
-import gobject
+from gi.repository import GObject
 from gettext import gettext as _
 
-from sugar.graphics.toolbutton import ToolButton
-from sugar.activity.activity import get_bundle_path, get_activity_root
-from sugar.graphics.style import *
+from sugar3.graphics.toolbutton import ToolButton
+from sugar3.activity.activity import get_bundle_path, get_activity_root
+from sugar3.graphics.style import *
 
 logger = logging.getLogger('infoslicer')
 
 PUBLISH  = 0
 TITLE    = 1
 
-class BookView(gtk.VBox):
+class BookView(Gtk.VBox):
     def sync(self):
         if not self._changing:
             return
-        gobject.source_remove(self._changing)
+        GObject.source_remove(self._changing)
         index, column = self.tree.get_cursor()
         self._cursor_changed(index)
 
     def __init__(self, book, name, tooltip, custom):
-        gtk.VBox.__init__(self)
+        GObject.GObject.__init__(self)
         self.book = book
         self._changing = None
         self._check = None
 
-        title = gtk.Toolbar()
+        title = Gtk.Toolbar()
 
         # title checkbox
 
         if custom:
-            self._check = gtk.CheckButton()
+            self._check = Gtk.CheckButton()
             self._check.props.can_focus = False
             self._check.props.tooltip_text = \
                     _('Articles are ready to be published')
             self._check.connect('toggled', self._check_toggled_cb)
-            check_box = gtk.HBox()
+            check_box = Gtk.HBox()
             check_box.set_size_request(50, -1)
-            check_box.pack_start(self._check, True, False)
-            tool_item = gtk.ToolItem()
+            check_box.pack_start(self._check, True, False, 0)
+            tool_item = Gtk.ToolItem()
             tool_item.add(check_box)
             tool_item.show()
             title.insert(tool_item, -1)
         else:
-            tool_item = gtk.ToolItem()
-            tool_item.add(gtk.Label('  '))
+            tool_item = Gtk.ToolItem()
+            tool_item.add(Gtk.Label(label='  '))
             tool_item.show()
             title.insert(tool_item, -1)
 
         # title caption
 
-        caption_label = gtk.Label(name)
+        caption_label = Gtk.Label(label=name)
         caption_label.props.tooltip_text = tooltip
-        caption_label.modify_fg(gtk.STATE_NORMAL, COLOR_WHITE.get_gdk_color())
-        caption_box = gtk.HBox()
-        caption_box.pack_start(caption_label, False)
-        caption = gtk.EventBox()
+        caption_label.modify_fg(Gtk.StateType.NORMAL, COLOR_WHITE.get_gdk_color())
+        caption_box = Gtk.HBox()
+        caption_box.pack_start(caption_label, False, False, 0)
+        caption = Gtk.EventBox()
         caption.add(caption_box)
-        caption.modify_bg(gtk.STATE_NORMAL, COLOR_TOOLBAR_GREY.get_gdk_color())
+        caption.modify_bg(Gtk.StateType.NORMAL, COLOR_TOOLBAR_GREY.get_gdk_color())
 
-        tool_item = gtk.ToolItem()
+        tool_item = Gtk.ToolItem()
         tool_item.add(caption)
         tool_item.show()
-
         title.insert(tool_item, -1)
 
-        separator = gtk.SeparatorToolItem()
+        separator = Gtk.SeparatorToolItem()
         separator.props.draw = False
         separator.set_expand(True)
         title.insert(separator, -1)
@@ -118,36 +117,52 @@ class BookView(gtk.VBox):
 
         # tree
 
-        self.store = gtk.ListStore(bool, str)
-        self.tree = gtk.TreeView(self.store)
+        self.store = Gtk.ListStore(bool, str)
+        self.tree = Gtk.TreeView(self.store)
         self.tree.props.headers_visible = False
         self.tree.connect('cursor-changed', self._cursor_changed_cb)
 
-        cell = gtk.CellRendererToggle()
+        cell = Gtk.CellRendererToggle()
         cell.connect('toggled', self._cell_toggled_cb)
         cell.props.activatable = True
 
-        column = self.tree.insert_column_with_attributes(0, '', cell, active=0)
-        column.props.sizing = gtk.TREE_VIEW_COLUMN_FIXED
+        # FIXME: insert_column_with_attributes does not exist on pygobject
+        # column = self.tree.insert_column_with_attributes(0, '', cell, active=0)
+
+        logging.debug('TODO: this is a workaround due '
+                      'https://bugzilla.gnome.org/show_bug.cgi?id=679415')
+
+        column = Gtk.TreeViewColumn('Wiki', cell)
+        column.props.sizing = Gtk.TreeViewColumnSizing.FIXED
         column.props.fixed_width = 50
         column.props.visible = custom
 
-        cell = gtk.CellRendererText()
+        self.tree.insert_column(column, 0)
+
+        cell = Gtk.CellRendererText()
         cell.connect('edited', self._cell_edited_cb)
         cell.props.editable = True
-        self.tree.insert_column_with_attributes(1, '', cell, text=1)
+
+        # FIXME: insert_column_with_attributes does not exist on pygobject
+        # self.tree.insert_column_with_attributes(1, '', cell, text=1)
+
+        logging.debug('TODO: this is a workaround due '
+                      'https://bugzilla.gnome.org/show_bug.cgi?id=679415')
+
+        column = Gtk.TreeViewColumn('Custom', cell, text=1)
+        self.tree.insert_column(column, 1)
 
         for i in self.book.index:
             self.store.append((i['ready'], i['title']))
 
         # scrolled tree
 
-        tree_scroll = gtk.ScrolledWindow()
-        tree_scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
+        tree_scroll = Gtk.ScrolledWindow()
+        tree_scroll.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
         tree_scroll.add(self.tree)
 
-        self.pack_start(title, False)
-        self.pack_start(tree_scroll)
+        self.pack_start(title, False, False, 0)
+        self.pack_start(tree_scroll, True, True, 0)
 
         if len(self.store):
             self.tree.set_cursor(0, self.tree.get_column(1), False)
@@ -170,7 +185,7 @@ class BookView(gtk.VBox):
             return find_name(list, prefix, uniq+1)
 
         if self._changing:
-            gobject.source_remove(self._changing)
+            GObject.source_remove(self._changing)
             self._changing = None
 
         name = find_name(self.store, _('New article'), 0)
@@ -183,38 +198,45 @@ class BookView(gtk.VBox):
         index, column = self.tree.get_cursor()
         if not index:
             return
-        index = index[0]
 
-        if self._changing:
-            gobject.source_remove(self._changing)
-            self._changing = None
+        logging.debug('TODO: This is not working because of the port to Gtk3. '
+                      'TreePath object does not support indexing')
 
-        self.book.remove(self.store[index][TITLE])
-        self.store.remove(self.tree.props.model.get_iter(index))
+        # index = index[0]
 
-        if len(self.store):
-            if index >= len(self.store):
-                index -= 1
-            self.tree.set_cursor(index, self.tree.get_column(1), False)
-            self._update_check(self.store[index][PUBLISH])
+        # if self._changing:
+        #     GObject.source_remove(self._changing)
+        #     self._changing = None
+
+        # self.book.remove(self.store[index][TITLE])
+        # self.store.remove(self.tree.props.model.get_iter(index))
+
+        # if len(self.store):
+        #     if index >= len(self.store):
+        #         index -= 1
+        #     self.tree.set_cursor(index, self.tree.get_column(1), False)
+        #     self._update_check(self.store[index][PUBLISH])
 
     def _swap_cb(self, widget, delta):
         old_index, column = self.tree.get_cursor()
         if not old_index:
             return
 
-        old_index = old_index[0]
-        new_index = old_index + delta
+        logging.debug('TODO: This is not working because of the port to Gtk3. '
+                      'TreePath object does not support indexing')
+
+        # old_index = old_index[0]
+        # new_index = old_index + delta
 
-        if new_index < 0:
-            new_index = len(self.store)-1
-        elif new_index >= len(self.store):
-            new_index = 0
+        # if new_index < 0:
+        #     new_index = len(self.store)-1
+        # elif new_index >= len(self.store):
+        #     new_index = 0
 
-        self.book.index[old_index], self.book.index[new_index] = \
-                self.book.index[new_index], self.book.index[old_index]
-        self.store.swap(self.tree.props.model.get_iter(old_index),
-                self.tree.props.model.get_iter(new_index))
+        # self.book.index[old_index], self.book.index[new_index] = \
+        #         self.book.index[new_index], self.book.index[old_index]
+        # self.store.swap(self.tree.props.model.get_iter(old_index),
+        #         self.tree.props.model.get_iter(new_index))
 
     def _check_toggled_cb(self, widget):
         for i, entry in enumerate(self.store):
@@ -241,12 +263,12 @@ class BookView(gtk.VBox):
 
     def _cursor_changed_cb(self, widget):
         if self._changing:
-            gobject.source_remove(self._changing)
+            GObject.source_remove(self._changing)
 
         index, column = self.tree.get_cursor()
 
         if index != None:
-            self._changing = gobject.timeout_add(500, self._cursor_changed,
+            self._changing = GObject.timeout_add(500, self._cursor_changed,
                     index)
 
     def _cursor_changed(self, index):
diff --git a/edit.py b/edit.py
index d21a989..e48509e 100644
--- a/edit.py
+++ b/edit.py
@@ -12,12 +12,12 @@
 # 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
+from gi.repository import GObject
 from gettext import gettext as _
 
-from sugar.graphics.toolbutton import ToolButton
-from sugar.graphics.toggletoolbutton import ToggleToolButton
-from sugar.activity.activity import ActivityToolbox
+from sugar3.graphics.toolbutton import ToolButton
+from sugar3.graphics.toggletoolbutton import ToggleToolButton
 
 from infoslicer.widgets.Edit_Pane import Edit_Pane
 from infoslicer.widgets.Format_Pane import Format_Pane
@@ -28,14 +28,14 @@ TABS = (Edit_Pane(),
         Image_Pane(),
         Format_Pane())
 
-class View(gtk.Notebook):
+class View(Gtk.Notebook):
     def __init__(self):
-        gtk.Notebook.__init__(self)
+        GObject.GObject.__init__(self)
         self.props.show_border = False
         self.props.show_tabs = False
 
         for i in TABS:
-            self.append_page(i)
+            self.append_page(i, None)
             i.show()
 
         self.connect('map', self._map_cb)
diff --git a/infoslicer/processing/Article.py b/infoslicer/processing/Article.py
index 157b3c8..b3311b0 100644
--- a/infoslicer/processing/Article.py
+++ b/infoslicer/processing/Article.py
@@ -1,8 +1,8 @@
 # Copyright (C) IBM Corporation 2008
 
-import pygtk
-pygtk.require('2.0')
-import gtk
+from gi.repository import Gtk
+from gi.repository import GdkPixbuf
+
 from random import Random
 from Article_Data import *
 from Section import *
@@ -35,9 +35,9 @@ class Article:
     """ 
     Created by Jonathan Mace
 
-    The Article class maintains a concrete representation of the article, in the form of a gtk.TextBuffer
+    The Article class maintains a concrete representation of the article, in the form of a Gtk.TextBuffer
 
-    Positions within the text are represented by gtk.TextIter
+    Positions within the text are represented by Gtk.TextIter
 
     The class contains methods for inserting and deleting new sentences, paragraphs and sections.
 
@@ -56,7 +56,7 @@ class Article:
         """
         Create default text buffer and set to empty 
         """
-        self.__buf = gtk.TextBuffer()
+        self.__buf = Gtk.TextBuffer()
         self.__buf.set_text("")
         insertionpoint = self.__buf.get_end_iter()
         insertionmark = self.__buf.create_mark(None, insertionpoint, False)        
@@ -149,7 +149,7 @@ class Article:
             nextsection = self.__sections[i+1]
             
             if section.getStart().compare(nextsection.getStart()) == -1:
-                text = self.__buf.get_slice(section.getStart(), nextsection.getStart())
+                text = self.__buf.get_slice(section.getStart(), nextsection.getStart(), True)
                 if len(text) > 2 and text[-2] != "\n":
                     nextsection.paragraphs = section.paragraphs + nextsection.paragraphs
                 else:
@@ -468,7 +468,7 @@ class Article:
         
     def getBuffer(self):
         """
-        This method simply returns the gtk.TextBuffer being maintained by this instance of the Article class.
+        This method simply returns the Gtk.TextBuffer being maintained by this instance of the Article class.
         """
         return self.__buf
 
@@ -638,8 +638,10 @@ class Article:
         self.markmark = self.__buf.create_mark(None, lociter, True)
         self.__buf.insert(lociter, " ")
         lociter = self.__buf.get_iter_at_mark(self.markmark)        
-        arrow = gtk.gdk.pixbuf_new_from_xpm_data(arrow_xpm)
-        self.__buf.insert_pixbuf(lociter, arrow)
+        # FIXME: I don't know what the arrow_xpm type should be
+        # https://bugzilla.gnome.org/show_bug.cgi?id=651962
+        # arrow = GdkPixbuf.Pixbuf.new_from_xpm_data(arrow_xpm)
+        # self.__buf.insert_pixbuf(lociter, arrow)
         
         
     def clearArrow(self):
diff --git a/infoslicer/processing/Paragraph.py b/infoslicer/processing/Paragraph.py
index 7c743c7..563fd16 100644
--- a/infoslicer/processing/Paragraph.py
+++ b/infoslicer/processing/Paragraph.py
@@ -152,7 +152,7 @@ class RawParagraph:
     def mark(self):
         markiter = self.getStart()
         self.markmark = self.buf.create_mark(None, markiter, True)
-        arrow = gtk.gdk.pixbuf_new_from_xpm_data(arrow_xpm)
+        arrow = GdkPixbuf.Pixbuf.new_from_xpm_data(arrow_xpm)
         self.buf.insert_pixbuf(markiter, arrow)
         
     def unmark(self):
@@ -165,7 +165,7 @@ class RawParagraph:
         return self.sentences
     
     def getText(self):
-        return self.buf.get_slice(self.getStart(), self.getEnd())
+        return self.buf.get_slice(self.getStart(), self.getEnd(), True)
     
     def clean(self):
         if len(self.sentences) > 1:
diff --git a/infoslicer/processing/Section.py b/infoslicer/processing/Section.py
index 30e3dad..bc5f847 100644
--- a/infoslicer/processing/Section.py
+++ b/infoslicer/processing/Section.py
@@ -214,7 +214,7 @@ class RawSection:
     def mark(self):
         markiter = self.getStart()
         self.markmark = self.buf.create_mark(None, markiter, True)
-        arrow = gtk.gdk.pixbuf_new_from_xpm_data(arrow_xpm)
+        arrow = GdkPixbuf.Pixbuf.new_from_xpm_data(arrow_xpm)
         self.buf.insert_pixbuf(markiter, arrow)
         
     def unmark(self):
@@ -260,7 +260,7 @@ class RawSection:
             nextparagraph = self.paragraphs[i+1]
             
             if paragraph.getStart().compare(nextparagraph.getStart()) == -1:
-                text = self.buf.get_slice(paragraph.getStart(), nextparagraph.getStart())
+                text = self.buf.get_slice(paragraph.getStart(), nextparagraph.getStart(), True)
                 if len(text) > 0 and text[-1] != "\n":
                     logger.debug("concatenating paragraphs")
                     nextparagraph.sentences = paragraph.sentences + nextparagraph.sentences
diff --git a/infoslicer/processing/Sentence.py b/infoslicer/processing/Sentence.py
index 09c31f4..1903a9c 100644
--- a/infoslicer/processing/Sentence.py
+++ b/infoslicer/processing/Sentence.py
@@ -1,9 +1,9 @@
 # Copyright (C) IBM Corporation 2008
 
-import pygtk
-pygtk.require('2.0')
+import gi
+gi.require_version('Gtk', '3.0')
 import os
-import gtk
+from gi.repository import Gtk
 import logging
 
 from Article_Data import *
@@ -83,10 +83,10 @@ class RawSentence:
         return data
     
     def getText(self):
-        return self.buf.get_slice(self.getStart(), self.getEnd())
+        return self.buf.get_slice(self.getStart(), self.getEnd(), True)
     
     def checkIntegrity(self, nextiter):
-        text = unicode(self.buf.get_slice(self.getStart(), nextiter))
+        text = unicode(self.buf.get_slice(self.getStart(), nextiter, True))
         lines = text.splitlines(True)
         sentencestartoffset = self.getStart().get_offset()
         sentences = []
@@ -159,7 +159,7 @@ class Picture( RawSentence ):
         leftmark = buf.create_mark(None, insertioniter, False)
         
         if os.path.isfile(picture_data.text):
-            pixbuf = gtk.gdk.pixbuf_new_from_file(picture_data.text) 
+            pixbuf = GdkPixbuf.Pixbuf.new_from_file(picture_data.text) 
             buf.insert_pixbuf(insertioniter, pixbuf)
         else:
             logger.warning('cannot open image %s' % picture_data.text)
diff --git a/infoslicer/widgets/Edit_Pane.py b/infoslicer/widgets/Edit_Pane.py
index 8da2ad9..d7ab056 100644
--- a/infoslicer/widgets/Edit_Pane.py
+++ b/infoslicer/widgets/Edit_Pane.py
@@ -1,11 +1,13 @@
 # Copyright (C) IBM Corporation 2008 
-import pygtk
-pygtk.require('2.0')
-import gtk
+import gi
+gi.require_version('Gtk', '3.0')
+from gi.repository import Gtk
+from gi.repository import Gdk
+from gi.repository import GObject
 import logging
 from gettext import gettext as _
 
-from sugar.graphics.toolcombobox import ToolComboBox
+from sugar3.graphics.toolcombobox import ToolComboBox
 
 from Reading_View import Reading_View
 from Editing_View import Editing_View
@@ -13,7 +15,7 @@ from infoslicer.processing.Article import Article
 
 logger = logging.getLogger('infoslicer')
 
-class Edit_Pane(gtk.HBox):
+class Edit_Pane(Gtk.HBox):
     """
     Created by Jonathan Mace
     
@@ -30,23 +32,23 @@ class Edit_Pane(gtk.HBox):
     """
     
     def __init__(self):
-        gtk.HBox.__init__(self)
+        GObject.GObject.__init__(self)
         self.toolitems = []
 
-        readarticle_box = gtk.VBox()
+        readarticle_box = Gtk.VBox()
         readarticle_box.show()
 
-        labeleb = gtk.EventBox()
-        labeleb.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse("#EEEEEE"))
+        labeleb = Gtk.EventBox()
+        labeleb.modify_bg(Gtk.StateType.NORMAL, Gdk.color_parse("#EEEEEE"))
         readarticle_box.pack_start(labeleb, False, False, 0)
         labeleb.show()
         
-        self.articletitle = gtk.Label()
-        self.articletitle.set_justify(gtk.JUSTIFY_CENTER)
+        self.articletitle = Gtk.Label()
+        self.articletitle.set_justify(Gtk.Justification.CENTER)
         labeleb.add(self.articletitle)
         self.articletitle.show()
 
-        vbox = gtk.VBox()
+        vbox = Gtk.VBox()
 
         snap = ToolComboBox(label_text=_('Snap selection to:'))
         snap.combo.append_item(0, _("Nothing"))
@@ -54,21 +56,21 @@ class Edit_Pane(gtk.HBox):
         snap.combo.append_item(2, _("Paragraphs"))
         snap.combo.append_item(3, _("Sections"))
         snap.combo.set_active(1)
-        vbox.pack_start(snap, False)
+        vbox.pack_start(snap, False, False, 0)
 
         """
         Create reading and editing panels
         """
         self.readarticle = Reading_View()  
-        self.readarticle.set_size_request(gtk.gdk.screen_width()/2, -1)
+        self.readarticle.set_size_request(Gdk.Screen.width()/2, -1)
         self.readarticle.show()
-        readarticle_box.pack_start(self.readarticle)
-        vbox.pack_start(readarticle_box)
+        readarticle_box.pack_start(self.readarticle, True, True, 0)
+        vbox.pack_start(readarticle_box, True, True, 0)
 
-        self.pack_start(vbox, False)
+        self.pack_start(vbox, False, False, 0)
 
         self.editarticle = Editing_View()
-        self.pack_start(self.editarticle)
+        self.pack_start(self.editarticle, True, True, 0)
         self.editarticle.show()
 
         snap.combo.connect("changed", self.selection_mode_changed, None)
diff --git a/infoslicer/widgets/Editable_Textbox.py b/infoslicer/widgets/Editable_Textbox.py
index fd8711f..b5efd68 100644
--- a/infoslicer/widgets/Editable_Textbox.py
+++ b/infoslicer/widgets/Editable_Textbox.py
@@ -1,12 +1,16 @@
 # Copyright (C) IBM Corporation 2008 
-import pygtk
-pygtk.require('2.0')
-import gtk
+import gi
+gi.require_version('Gtk', '3.0')
+from gi.repository import Gtk
+from gi.repository import Gdk
+from gi.repository import GObject
+from gi.repository import Pango
 import cPickle
-import pango
 import copy
 from Textbox import Textbox
 
+import logging
+
 SNAP_SENTENCE, SNAP_PARAGRAPH, SNAP_SECTION, SNAP_NONE = range(4)
 
 class Editable_Textbox( Textbox ):
@@ -18,11 +22,11 @@ class Editable_Textbox( Textbox ):
     """
     
     def __init__(self): 
-        gtk.TextView.__init__(self)
+        GObject.GObject.__init__(self)
         self.set_border_width(1)
         self.set_cursor_visible(True)
         self.set_editable(True)  
-        self.set_wrap_mode(gtk.WRAP_WORD)
+        self.set_wrap_mode(Gtk.WrapMode.WORD)
         self.article = None
         self.set_mode(SNAP_SENTENCE)
         self.changed = False
@@ -30,12 +34,15 @@ class Editable_Textbox( Textbox ):
         
         self.selecting = False
         self.handlers = []
-        self.modify_font(pango.FontDescription('arial 9'))
+        self.modify_font(Pango.FontDescription('arial 9'))
         self.ignore_snap_self = True
         self.drag_source = False
         self.edited = False
         self.set_property("left-margin", 5)
 
+        logging.debug('########### Editable_Textbox.drag_dest_set')
+        self.drag_dest_set(Gtk.DestDefaults.ALL, [], Gdk.DragAction.COPY)
+
     def set_article(self, article):
         self.article = article
         self.set_buffer(article.getBuffer())
@@ -47,7 +54,7 @@ class Editable_Textbox( Textbox ):
         self.article.delete()
         
     def get_mouse_iter(self, x, y):
-        click_coords = self.window_to_buffer_coords(gtk.TEXT_WINDOW_TEXT, x, y)
+        click_coords = self.window_to_buffer_coords(Gtk.TextWindowType.TEXT, x, y)
         mouseClickPositionIter = self.get_iter_at_location(click_coords[0], click_coords[1])
         return mouseClickPositionIter
     
@@ -59,7 +66,7 @@ class Editable_Textbox( Textbox ):
             self.disconnect(handler)
         
         buffer.connect("changed", self.text_changed, None)
-        gtk.TextView.set_buffer(self, buffer)
+        Gtk.TextView.set_buffer(self, buffer)
         
         self.handlers = []
         
@@ -143,7 +150,7 @@ class Editable_Textbox( Textbox ):
                 self.block = True
         
     def clicked_event(self, widget, event, data):
-        if event.type == gtk.gdk._2BUTTON_PRESS or event.type == gtk.gdk._3BUTTON_PRESS:
+        if event.type == Gdk.EventType._2BUTTON_PRESS or event.type == Gdk.EventType._3BUTTON_PRESS:
             self.stop_emission("button_press_event")
             return
         if event.button == 3:
@@ -202,6 +209,7 @@ class Editable_Textbox( Textbox ):
             return False
         
     def drag_begin_event(self, widget, context, data):
+        logging.debug('############ Editable_Textbox.drag_begin_event')
         self.grab_focus()
         if self.snapto != SNAP_NONE:
             a = self.article
@@ -256,11 +264,12 @@ class Editable_Textbox( Textbox ):
             self.changed = False
         
     def drag_data_received_event(self, widget, context, x, y, selection_data, info, time, data):
+        logging.debug('################ Editable_Textbox.drag_data_received_event')
         if self.snapto != SNAP_NONE and not self.ignore_snap_self or (not self.drag_source and self.ignore_snap_self):    
             a = self.article
             insert_loc = self.get_mouse_iter(x, y)
-            data_received_type = str(selection_data.type)    
-            data = cPickle.loads(str(selection_data.data))
+            data_received_type = str(selection_data.get_data_type())    
+            data = cPickle.loads(str(selection_data.get_data()))
             
             if data_received_type == "sentence":
                 bestpoint = insert_loc  
@@ -276,15 +285,16 @@ class Editable_Textbox( Textbox ):
             self.grab_focus()
         
     def drag_data_get_event(self, widget, context, selection_data, info, time, data):
+        logging.debug('############### Editable_Textbox.drag_data_get_event')
         if not self.ignore_snap_self and self.snapto != SNAP_NONE:
             a = self.article
             
             if self.snapto == SNAP_SENTENCE:
-                atom = gtk.gdk.atom_intern("sentence")
+                atom = Gdk.atom_intern("sentence", only_if_exists=False)
             if self.snapto == SNAP_PARAGRAPH:
-                atom = gtk.gdk.atom_intern("paragraph")
+                atom = Gdk.atom_intern("paragraph", only_if_exists=False)
             if self.snapto == SNAP_SECTION:
-                atom = gtk.gdk.atom_intern("section")
+                atom = Gdk.atom_intern("section", only_if_exists=False)
                 
             string = cPickle.dumps(a.getSelection())
             selection_data.set(atom, 8, string)
diff --git a/infoslicer/widgets/Editing_View.py b/infoslicer/widgets/Editing_View.py
index 5506a7f..3f9ecdc 100644
--- a/infoslicer/widgets/Editing_View.py
+++ b/infoslicer/widgets/Editing_View.py
@@ -1,33 +1,35 @@
 # Copyright (C) IBM Corporation 2008 
-import pygtk
-pygtk.require('2.0')
-import gtk
+import gi
+gi.require_version('Gtk', '3.0')
+from gi.repository import Gtk
+from gi.repository import Gdk
+from gi.repository import GObject
 from Editable_Textbox import Editable_Textbox
 
-class Editing_View( gtk.VBox ): 
+class Editing_View( Gtk.VBox ): 
     """
     Created by Jonathan Mace
     This class wraps an editable textbox into a scrollable window and 
     gives it a title.
     """
     def __init__(self):
-        gtk.VBox.__init__(self)
+        GObject.GObject.__init__(self)
         self.set_border_width(0)
         self.set_spacing(2)
         
-        labeleb = gtk.EventBox()
-        labeleb.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse("#EEEEEE"))
+        labeleb = Gtk.EventBox()
+        labeleb.modify_bg(Gtk.StateType.NORMAL, Gdk.color_parse("#EEEEEE"))
         self.pack_start(labeleb, False, False, 0)
         labeleb.show()
         
-        self.articletitle = gtk.Label()
-        self.articletitle.set_justify(gtk.JUSTIFY_CENTER)
+        self.articletitle = Gtk.Label()
+        self.articletitle.set_justify(Gtk.Justification.CENTER)
         labeleb.add(self.articletitle)
         self.articletitle.show()
         
-        self.textwindow = gtk.ScrolledWindow()
-        self.textwindow.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
-        self.pack_start(self.textwindow)
+        self.textwindow = Gtk.ScrolledWindow()
+        self.textwindow.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC)
+        self.pack_start(self.textwindow, True, True, 0)
         self.textwindow.show()
         
         self.textbox = Editable_Textbox()
diff --git a/infoslicer/widgets/Format_Pane.py b/infoslicer/widgets/Format_Pane.py
index ef8c2f5..1be64f2 100644
--- a/infoslicer/widgets/Format_Pane.py
+++ b/infoslicer/widgets/Format_Pane.py
@@ -1,7 +1,7 @@
 # Copyright (C) IBM Corporation 2008 
-import pygtk
-pygtk.require('2.0')
-import gtk
+import gi
+gi.require_version('Gtk', '3.0')
+from gi.repository import Gtk
 from gettext import gettext as _
 
 from Editing_View import Editing_View
@@ -22,22 +22,22 @@ class Format_Pane(Editing_View):
         self.toolitems = []
         
         """
-        self.combocontainer = gtk.ToolItem()
+        self.combocontainer = Gtk.ToolItem()
         self.combocontainer.add(self.combobox)
         self.toolbar.insert(self.combocontainer, -1)
         self.combocontainer.show()
         
-        self.boldbutton = gtk.ToolButton(gtk.STOCK_BOLD)
+        self.boldbutton = Gtk.ToolButton(Gtk.STOCK_BOLD)
         self.boldbutton.set_expand(False)
         self.toolbar.insert(self.boldbutton, -1)
         self.boldbutton.show()
         
-        self.italicbutton = gtk.ToolButton(gtk.STOCK_ITALIC)
+        self.italicbutton = Gtk.ToolButton(Gtk.STOCK_ITALIC)
         self.italicbutton.set_expand(False)
         self.toolbar.insert(self.italicbutton, -1)
         self.italicbutton.show()
         
-        self.underlinebutton = gtk.ToolButton(gtk.STOCK_UNDERLINE)
+        self.underlinebutton = Gtk.ToolButton(Gtk.STOCK_UNDERLINE)
         self.underlinebutton.set_expand(False)
         self.toolbar.insert(self.underlinebutton, -1)
         self.underlinebutton.show()
diff --git a/infoslicer/widgets/Gallery_View.py b/infoslicer/widgets/Gallery_View.py
index 4464088..7cc59b9 100644
--- a/infoslicer/widgets/Gallery_View.py
+++ b/infoslicer/widgets/Gallery_View.py
@@ -1,7 +1,8 @@
 # Copyright (C) IBM Corporation 2008 
-import pygtk
-pygtk.require('2.0')
-import gtk
+from gi.repository import Gtk
+from gi.repository import Gdk
+from gi.repository import GObject
+from gi.repository import GdkPixbuf
 import os
 import cPickle
 import logging
@@ -13,7 +14,7 @@ import book
 
 logger = logging.getLogger('infoslicer')
 
-class Gallery_View( gtk.HBox ): 
+class Gallery_View( Gtk.HBox ): 
     """ 
     Created by Christopher Leonard
     Drag-and-drop methods added by Jonathan Mace
@@ -33,52 +34,56 @@ class Gallery_View( gtk.HBox ):
     
     def __init__(self):
         self.image_list = []
-        gtk.HBox.__init__(self)
+        GObject.GObject.__init__(self)
         
         self.current_index = -1
         
-        left_button = gtk.Button(label="\n\n << \n\n")
+        left_button = Gtk.Button(label="\n\n << \n\n")
         
-        right_button = gtk.Button(label="\n\n >> \n\n")
+        right_button = Gtk.Button(label="\n\n >> \n\n")
         
-        self.imagenumberlabel = gtk.Label()
+        self.imagenumberlabel = Gtk.Label()
         
-        self.image = gtk.Image()
+        self.image = Gtk.Image()
         
-        self.imagebox = gtk.EventBox()
+        self.imagebox = Gtk.EventBox()
         self.imagebox.add(self.image)
         
-        self.imagebox.drag_source_set(gtk.gdk.BUTTON1_MASK, [("text/plain", gtk.TARGET_SAME_APP, 80)], gtk.gdk.ACTION_COPY)
+        self.imagebox.drag_source_set(Gdk.ModifierType.BUTTON1_MASK,
+                                      [],
+                                      Gdk.DragAction.COPY)
+        self.imagebox.drag_source_add_image_targets()
         self.imagebox.connect("drag-begin", self.drag_begin_event, None)
         self.imagebox.connect("drag-data-get", self.drag_data_get_event, None)
         
-        self.caption = gtk.Label("")
+        self.caption = Gtk.Label(label="")
         self.caption.set_line_wrap(True)
         
-        self.image_drag_container = gtk.VBox()
-        self.image_drag_container.pack_start(self.imagenumberlabel, expand = False)
-        self.image_drag_container.pack_start(self.imagebox, expand=False)
-        self.image_drag_container.pack_start(self.caption, expand=False)
-        
-        image_container = gtk.VBox()
-        image_container.pack_start(gtk.Label(" "))
-        image_container.pack_start(self.image_drag_container, expand=False)
-        image_container.pack_start(gtk.Label(" "))
-        
-        left_button_container = gtk.VBox()
-        left_button_container.pack_start(gtk.Label(" "))
-        left_button_container.pack_start(left_button, expand=False)
-        left_button_container.pack_start(gtk.Label(" "))
-        
-        right_button_container = gtk.VBox()
-        right_button_container.pack_start(gtk.Label(" "))
-        right_button_container.pack_start(right_button, expand=False)
-        right_button_container.pack_start(gtk.Label(" "))
+        self.image_drag_container = Gtk.VBox()
+        self.image_drag_container.pack_start(self.imagenumberlabel, expand=False,
+                                             fill=False, padding=0)
+        self.image_drag_container.pack_start(self.imagebox, False, True, 0)
+        self.image_drag_container.pack_start(self.caption, False, True, 0)
+        
+        image_container = Gtk.VBox()
+        image_container.pack_start(Gtk.Label(" "), True, True, 0)
+        image_container.pack_start(self.image_drag_container, False, True, 0)
+        image_container.pack_start(Gtk.Label(" "), True, True, 0)
+        
+        left_button_container = Gtk.VBox()
+        left_button_container.pack_start(Gtk.Label(" "), True, True, 0)
+        left_button_container.pack_start(left_button, False, True, 0)
+        left_button_container.pack_start(Gtk.Label(" "), True, True, 0)
+        
+        right_button_container = Gtk.VBox()
+        right_button_container.pack_start(Gtk.Label(" "), True, True, 0)
+        right_button_container.pack_start(right_button, False, True, 0)
+        right_button_container.pack_start(Gtk.Label(" "), True, True, 0)
 
         
-        self.pack_start(left_button_container, expand=False)
-        self.pack_start(image_container)
-        self.pack_start(right_button_container, expand=False)
+        self.pack_start(left_button_container, False, True, 0)
+        self.pack_start(image_container, True, True, 0)
+        self.pack_start(right_button_container, False, True, 0)
    
         self._source_article = None
         self.show_all()
@@ -99,7 +104,7 @@ class Gallery_View( gtk.HBox ):
         self.current_index += 1
         if self.current_index == len(self.image_list):
             self.current_index = 0
-        self.imagebuf = gtk.gdk.pixbuf_new_from_file(self.image_list[self.current_index][0])
+        self.imagebuf = GdkPixbuf.Pixbuf.new_from_file(self.image_list[self.current_index][0])
         self.image.set_from_pixbuf(self.imagebuf)
         self.caption.set_text("\n" + self.image_list[self.current_index][1])
         self.imagenumberlabel.set_text("(%d / %d)\n" % (self.current_index+1, len(self.image_list)))   
@@ -115,7 +120,7 @@ class Gallery_View( gtk.HBox ):
         if self.current_index == 0:
             self.current_index = len(self.image_list)
         self.current_index -= 1
-        self.imagebuf = gtk.gdk.pixbuf_new_from_file(self.image_list[self.current_index][0])
+        self.imagebuf = GdkPixbuf.Pixbuf.new_from_file(self.image_list[self.current_index][0])
         self.image.set_from_pixbuf(self.imagebuf)
         self.caption.set_text("\n" + self.image_list[self.current_index][1])
         self.imagenumberlabel.set_text("(%d / %d)\n" % (self.current_index+1, len(self.image_list)))   
@@ -129,7 +134,7 @@ class Gallery_View( gtk.HBox ):
             self.image.clear()
             return        
         self.current_index = 0
-        self.imagebuf = gtk.gdk.pixbuf_new_from_file(self.image_list[self.current_index][0])
+        self.imagebuf = GdkPixbuf.Pixbuf.new_from_file(self.image_list[self.current_index][0])
         self.image.set_from_pixbuf(self.imagebuf)
         self.caption.set_text("\n" + self.image_list[self.current_index][1])    
         logger.debug("setting text to:")
@@ -143,11 +148,12 @@ class Gallery_View( gtk.HBox ):
         logger.debug(self.image_list)
         
     def drag_begin_event(self, widget, context, data):
+        logging.debug('########### Gallery_View.drag_begin_event called')
         self.imagebox.drag_source_set_icon_pixbuf(self.imagebuf)
         
     def drag_data_get_event(self, widget, context, selection_data, info, timestamp, data):
-        logger.debug("getting data")
-        atom = gtk.gdk.atom_intern("section")
+        logger.debug('############# Gallery_View.drag_data_get_event')
+        atom = Gdk.atom_intern("section", only_if_exists=False)
         imagedata = Picture_Data(self.source_article_id,
                 self.image_list[self.current_index][0],
                 self.image_list[self.current_index][2])
diff --git a/infoslicer/widgets/Image_Pane.py b/infoslicer/widgets/Image_Pane.py
index 99026f0..473253c 100644
--- a/infoslicer/widgets/Image_Pane.py
+++ b/infoslicer/widgets/Image_Pane.py
@@ -1,7 +1,9 @@
 # Copyright (C) IBM Corporation 2008 
-import pygtk
-pygtk.require('2.0')
-import gtk
+import gi
+gi.require_version('Gtk', '3.0')
+from gi.repository import Gtk
+from gi.repository import Gdk
+from gi.repository import GObject
 import logging
 from gettext import gettext as _
 
@@ -11,7 +13,7 @@ from infoslicer.processing.Article import Article
 
 logger = logging.getLogger('infoslicer')
 
-class Image_Pane(gtk.HBox):
+class Image_Pane(Gtk.HBox):
     """
     Created by Christopher Leonard
     
@@ -23,29 +25,29 @@ class Image_Pane(gtk.HBox):
     """
     
     def __init__(self):
-        gtk.HBox.__init__(self)
+        GObject.GObject.__init__(self)
         self.toolitems = []
         
-        gallery_box = gtk.VBox()
+        gallery_box = Gtk.VBox()
         gallery_box.show()
 
-        labeleb = gtk.EventBox()
-        labeleb.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse("#EEEEEE"))
+        labeleb = Gtk.EventBox()
+        labeleb.modify_bg(Gtk.StateType.NORMAL, Gdk.color_parse("#EEEEEE"))
         gallery_box.pack_start(labeleb, False, False, 0)
         labeleb.show()
         
-        self.articletitle = gtk.Label()
-        self.articletitle.set_justify(gtk.JUSTIFY_CENTER)
+        self.articletitle = Gtk.Label()
+        self.articletitle.set_justify(Gtk.Justification.CENTER)
         labeleb.add(self.articletitle)
         self.articletitle.show()
         
         self.gallery = Gallery_View()
-        self.gallery.set_size_request(gtk.gdk.screen_width()/2, -1)
-        gallery_box.pack_start(self.gallery)
+        self.gallery.set_size_request(Gdk.Screen.width()/2, -1)
+        gallery_box.pack_start(self.gallery, True, True, 0)
 
-        self.pack_start(gallery_box, False)
+        self.pack_start(gallery_box, False, False, 0)
         self.editarticle = Editing_View()
-        self.pack_start(self.editarticle)
+        self.pack_start(self.editarticle, True, True, 0)
         self.editarticle.show_all()
 
         self.gallery._source_article = None
diff --git a/infoslicer/widgets/Reading_View.py b/infoslicer/widgets/Reading_View.py
index 55609c9..3c40757 100644
--- a/infoslicer/widgets/Reading_View.py
+++ b/infoslicer/widgets/Reading_View.py
@@ -1,14 +1,15 @@
 # Copyright (C) IBM Corporation 2008 
-import pygtk
-pygtk.require('2.0')
-import gtk
+import gi
+gi.require_version('Gtk', '3.0')
+from gi.repository import Gtk
+from gi.repository import GObject
 from Readonly_Textbox import Readonly_Textbox
 import logging
 
 logger = logging.getLogger('infoslicer')
 elogger = logging.getLogger('infoslicer::except')
 
-class Reading_View( gtk.VBox ):
+class Reading_View( Gtk.VBox ):
     """ 
     Created by Jonathan Mace
     
@@ -21,11 +22,11 @@ class Reading_View( gtk.VBox ):
     """
      
     def __init__(self):
-        gtk.VBox.__init__(self)
+        GObject.GObject.__init__(self)
         
-        self.articlewindow = gtk.ScrolledWindow()
-        self.articlewindow.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
-        self.pack_start(self.articlewindow)
+        self.articlewindow = Gtk.ScrolledWindow()
+        self.articlewindow.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC)
+        self.pack_start(self.articlewindow, True, True, 0)
         self.articlewindow.show()
         
         self.textbox = Readonly_Textbox()
diff --git a/infoslicer/widgets/Readonly_Textbox.py b/infoslicer/widgets/Readonly_Textbox.py
index 958cfcd..638cf77 100644
--- a/infoslicer/widgets/Readonly_Textbox.py
+++ b/infoslicer/widgets/Readonly_Textbox.py
@@ -1,9 +1,9 @@
 # Copyright (C) IBM Corporation 2008 
-import pygtk
-pygtk.require('2.0')
-import gtk
-import pango
+from gi.repository import Gtk
+from gi.repository import Gdk
+from gi.repository import Pango
 import cPickle
+import logging
 from Textbox import Textbox
 
 SELECT_SENTENCE, SELECT_PARAGRAPH, SELECT_SECTION, FULL_EDIT = range(4)
@@ -24,7 +24,7 @@ class Readonly_Textbox( Textbox ):
         self.use_as_drag_source = use_as_drag_source
         self.set_mode(SELECT_SENTENCE)
         self.block = True
-        self.modify_font(pango.FontDescription('arial 9'))
+        self.modify_font(Pango.FontDescription('arial 9'))
         
     
     def set_mode(self, mode):
@@ -45,11 +45,12 @@ class Readonly_Textbox( Textbox ):
         self.event_handlers.append(self.connect("drag-motion", self.drag_motion, None))
         
     def drag_motion(self, widget, context, x, y, timestamp, data):
-        context.drag_status(gtk.gdk.ACTION_COPY, timestamp)
+        logging.debug('############ Readonly_Textbox.drag_motion')
+        Gdk.drag_status(context, Gdk.DragAction.COPY, timestamp)
         return True
         
     def clicked_event(self, widget, event, data):
-        if event.type == gtk.gdk._2BUTTON_PRESS or event.type == gtk.gdk._3BUTTON_PRESS:
+        if event.type == Gdk.EventType._2BUTTON_PRESS or event.type == Gdk.EventType._3BUTTON_PRESS:
             self.stop_emission("button_press_event")
             return
         if event.button == 3:
@@ -114,7 +115,13 @@ class Readonly_Textbox( Textbox ):
             if self.block == True:
                 self.stop_emission("motion-notify-event")
                 self.block = False
-                self.emit("motion-notify-event", event)
+                logging.debug('FIXME: this is a workaround due '
+                              'https://bugzilla.gnome.org/show_bug.cgi?id=679795')
+                # I was getting this error:
+                #   TypeError: could not convert type EventMotion
+                #   to GdkEvent required for parameter 0
+                # self.emit("motion-notify-event", event)
+                self.emit("motion-notify-event", Gdk.Event())
                 
                 buf = self.get_buffer()            
                 mouseiter = self.get_mouse_iter(int(event.x), int(event.y))
@@ -139,7 +146,7 @@ class Readonly_Textbox( Textbox ):
                     if self.selectionmode == SELECT_SECTION:
                         selectionstart = article.getSection(mouseiter).getStart()
                         selectionend = article.getSection(self.selectionstart).getEnd()
-                self.scroll_to_iter(mouseiter, 0)
+                self.scroll_to_iter(mouseiter, 0, False, 0.5, 0.5)
                 article.highlight(selectionstart, selectionend)                
                     
             else:
@@ -152,15 +159,15 @@ class Readonly_Textbox( Textbox ):
         self.stop_emission("button-release-event")
         
     def drag_data_get_event(self, widget, context, selection_data, info, time, data):
-        
+        logging.debug('######## Readonly_Textbox.drag_data_get_event')
         a = self.article
         
         if self.selectionmode == SELECT_SENTENCE:
-            atom = gtk.gdk.atom_intern("sentence")
+            atom = Gdk.atom_intern("sentence", only_if_exists=False)
         if self.selectionmode == SELECT_PARAGRAPH:
-            atom = gtk.gdk.atom_intern("paragraph")
+            atom = Gdk.atom_intern("paragraph", only_if_exists=False)
         if self.selectionmode == SELECT_SECTION:
-            atom = gtk.gdk.atom_intern("section")
+            atom = Gdk.atom_intern("section", only_if_exists=False)
             
         string = cPickle.dumps(a.getSelection())
         selection_data.set(atom, 8, string)
diff --git a/infoslicer/widgets/Textbox.py b/infoslicer/widgets/Textbox.py
index 95f0681..634f967 100644
--- a/infoslicer/widgets/Textbox.py
+++ b/infoslicer/widgets/Textbox.py
@@ -1,13 +1,15 @@
 # Copyright (C) IBM Corporation 2008 
-import pygtk
-pygtk.require('2.0')
-import gtk
+import gi
+gi.require_version('Gtk', '3.0')
+from gi.repository import Gtk
+from gi.repository import GObject
+from gi.repository import Pango
 import cPickle
 import pango
 
 SELECT_SENTENCE, SELECT_PARAGRAPH, SELECT_SECTION, FULL_EDIT = range(4)
 
-class Textbox( gtk.TextView ):
+class Textbox( Gtk.TextView ):
     """ 
     Created by Jonathan Mace
     The Textbox class is the base class for our own custom textboxes which implement
@@ -19,13 +21,13 @@ class Textbox( gtk.TextView ):
     
     
     def __init__(self): 
-        gtk.TextView.__init__(self)
+        GObject.GObject.__init__(self)
         self.set_border_width(1)
         self.event_handlers = []
-        self.set_wrap_mode(gtk.WRAP_WORD)
+        self.set_wrap_mode(Gtk.WrapMode.WORD)
         self.set_cursor_visible(False)
         self.set_editable(False)  
-        self.modify_font(pango.FontDescription('arial 9'))
+        self.modify_font(Pango.FontDescription('arial 9'))
         self.article = None
         self.set_property("left-margin", 5)
         
@@ -37,7 +39,7 @@ class Textbox( gtk.TextView ):
         return self.article
         
     def show(self):
-        gtk.TextView.show(self)  
+        Gtk.TextView.show(self)  
         
     def clear(self):
         self.article.delete()     
@@ -51,6 +53,6 @@ class Textbox( gtk.TextView ):
         
     def get_mouse_iter(self, x, y):
         # Convenience method to get the iter in the buffer of x, y coords.
-        click_coords = self.window_to_buffer_coords(gtk.TEXT_WINDOW_TEXT, x, y)
+        click_coords = self.window_to_buffer_coords(Gtk.TextWindowType.TEXT, x, y)
         mouseClickPositionIter = self.get_iter_at_location(click_coords[0], click_coords[1])
-        return mouseClickPositionIter
\ No newline at end of file
+        return mouseClickPositionIter
diff --git a/library.py b/library.py
index 325ed49..3087072 100644
--- a/library.py
+++ b/library.py
@@ -12,20 +12,22 @@
 # 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
+from gi.repository import Gdk
+from gi.repository import GObject
 import logging
 from threading import Timer
 from datetime import datetime
 from gettext import gettext as _
 import locale
 
-from sugar.graphics.toolbutton import ToolButton
-from sugar.graphics.toggletoolbutton import ToggleToolButton
-from sugar.activity.activity import ActivityToolbox
-from sugar.graphics.toolcombobox import ToolComboBox
-from sugar.graphics.icon import Icon
-from sugar.datastore import datastore
-import sugar.graphics.style as style
+from sugar3.graphics.toolbutton import ToolButton
+from sugar3.graphics.toggletoolbutton import ToggleToolButton
+from sugar3.graphics.toolcombobox import ToolComboBox
+from sugar3.graphics.icon import Icon
+from sugar3.datastore import datastore
+from sugar3.graphics.alert import Alert
+import sugar3.graphics.style as style
 
 import xol
 import net
@@ -35,13 +37,13 @@ from infoslicer.widgets.Reading_View import Reading_View
 
 logger = logging.getLogger('infoslicer')
 
-class View(gtk.EventBox):
+class View(Gtk.EventBox):
     def sync(self):
         self.wiki.sync()
         self.custom.sync()
 
     def __init__(self, activity):
-        gtk.EventBox.__init__(self)
+        GObject.GObject.__init__(self)
         self.activity = activity
 
         self.wiki = BookView(book.wiki,
@@ -52,18 +54,18 @@ class View(gtk.EventBox):
         # stubs for empty articles
 
         def create_stub(icon_name, head_text, tail_text):
-            head_label = gtk.Label(head_text)
-            head_label_a = gtk.Alignment(0.5, 1, 0, 0)
+            head_label = Gtk.Label(label=head_text)
+            head_label_a = Gtk.Alignment.new(0.5, 1, 0, 0)
             head_label_a.add(head_label)
             icon = Icon(icon_name=icon_name,
-                    icon_size=gtk.ICON_SIZE_LARGE_TOOLBAR)
-            tail_label = gtk.Label(tail_text)
-            tail_label_a = gtk.Alignment(0.5, 0, 0, 0)
+                    icon_size=Gtk.IconSize.LARGE_TOOLBAR)
+            tail_label = Gtk.Label(label=tail_text)
+            tail_label_a = Gtk.Alignment.new(0.5, 0, 0, 0)
             tail_label_a.add(tail_label)
-            stub = gtk.VBox()
-            stub.pack_start(head_label_a)
-            stub.pack_start(icon, False)
-            stub.pack_start(tail_label_a)
+            stub = Gtk.VBox()
+            stub.pack_start(head_label_a, True, True, 0)
+            stub.pack_start(icon, False, False, 0)
+            stub.pack_start(tail_label_a, True, True, 0)
             return stub
 
         wiki_stub = create_stub('white-search',
@@ -78,7 +80,7 @@ class View(gtk.EventBox):
         wiki_prefix = lang_code[0:2] + '.'
         language_order = 0
         order = 0
-        search_box = gtk.HBox()
+        search_box = Gtk.HBox()
         self.wikimenu = ToolComboBox(label_text=_('Get article from:'))
         for i in sorted(WIKI.keys()):
             self.wikimenu.combo.append_item(WIKI[i], i)
@@ -86,66 +88,66 @@ class View(gtk.EventBox):
                 language_order = order
             order = order + 1
         self.wikimenu.combo.set_active(language_order)
-        search_box.pack_start(self.wikimenu, False)
+        search_box.pack_start(self.wikimenu, False, False, 0)
 
-        self.searchentry = gtk.Entry()
-        self.searchentry.set_size_request(int(gtk.gdk.screen_width() / 4), -1)
+        self.searchentry = Gtk.Entry()
+        self.searchentry.set_size_request(int(Gdk.Screen.width() / 4), -1)
         self.searchentry.set_text(_("Article name"))
         self.searchentry.select_region(0, -1)
         self.searchentry.connect('activate', self._search_activate_cb)
-        search_box.pack_start(self.searchentry)
+        search_box.pack_start(self.searchentry, True, True, 0)
         search_box.show_all()
 
-        self.searchbutton = gtk.Button(label=_('Search'))
+        self.searchbutton = Gtk.Button(label=_('Search'))
         self.searchbutton.connect('clicked', self._search_clicked_cb)
-        search_box.pack_start(self.searchbutton, False)
+        search_box.pack_start(self.searchbutton, False, False, 0)
 
         wiki_widget = Reading_View()
-        wiki = gtk.Notebook()
+        wiki = Gtk.Notebook()
         wiki.props.show_border = False
         wiki.props.show_tabs = False
-        wiki.append_page(wiki_stub)
-        wiki.append_page(wiki_widget)
+        wiki.append_page(wiki_stub, None)
+        wiki.append_page(wiki_widget, None)
 
-        self.progress = gtk.Label()
+        self.progress = Gtk.Label()
         #self.progress.set_size_request(-1, style.SMALL_ICON_SIZE+4)
-        #progress_box = gtk.HBox()
-        #progress_box.pack_start(gtk.HSeparator(), False)
+        #progress_box = Gtk.HBox()
+        #progress_box.pack_start(Gtk.HSeparator(, True, True, 0), False)
         #progress_box.pack_start(self.progress, False)
 
-        wiki_box = gtk.VBox()
-        wiki_box.pack_start(search_box, False)
-        wiki_box.pack_start(wiki)
-        wiki_box.pack_start(self.progress, False)
-        wiki_box.set_size_request(gtk.gdk.screen_width()/4*3,
-                gtk.gdk.screen_height()/2 - style.GRID_CELL_SIZE / 2)
+        wiki_box = Gtk.VBox()
+        wiki_box.pack_start(search_box, False, False, 0)
+        wiki_box.pack_start(wiki, True, True, 0)
+        wiki_box.pack_start(self.progress, False, False, 0)
+        wiki_box.set_size_request(Gdk.Screen.width()/4*3,
+                Gdk.Screen.height()/2 - style.GRID_CELL_SIZE / 2)
 
         custom_widget = Reading_View()
-        custom = gtk.Notebook()
+        custom = Gtk.Notebook()
         custom.props.show_border = False
         custom.props.show_tabs = False
-        custom.append_page(custom_stub)
-        custom.append_page(custom_widget)
-        # custom.set_size_request(gtk.gdk.screen_width()/4*3,
-        #         gtk.gdk.screen_height()/2 - 55)
-        custom.set_size_request(gtk.gdk.screen_width()/4*3,
-                gtk.gdk.screen_height()/2 - style.GRID_CELL_SIZE / 2)
+        custom.append_page(custom_stub, None)
+        custom.append_page(custom_widget, None)
+        # custom.set_size_request(Gdk.Screen.width()/4*3,
+        #         Gdk.Screen.height()/2 - 55)
+        custom.set_size_request(Gdk.Screen.width()/4*3,
+                Gdk.Screen.height()/2 - style.GRID_CELL_SIZE / 2)
 
         # workspace
 
-        articles_box = gtk.HBox()
-        articles_box.pack_start(self.wiki)
-        articles_box.pack_start(gtk.VSeparator(), False)
-        articles_box.pack_start(wiki_box, False)
+        articles_box = Gtk.HBox()
+        articles_box.pack_start(self.wiki, True, True, 0)
+        articles_box.pack_start(Gtk.VSeparator(), False, False, 0)
+        articles_box.pack_start(wiki_box, False, False, 0)
 
-        custom_box = gtk.HBox()
-        custom_box.pack_start(self.custom)
-        custom_box.pack_start(gtk.VSeparator(), False)
-        custom_box.pack_start(custom, False)
+        custom_box = Gtk.HBox()
+        custom_box.pack_start(self.custom, True, True, 0)
+        custom_box.pack_start(Gtk.VSeparator(), False, False, 0)
+        custom_box.pack_start(custom, False, False, 0)
 
-        workspace = gtk.VBox()
-        workspace.pack_start(articles_box, False)
-        workspace.pack_start(custom_box, False)
+        workspace = Gtk.VBox()
+        workspace.pack_start(articles_box, False, False, 0)
+        workspace.pack_start(custom_box, False, False, 0)
         workspace.show_all()
 
         self.add(workspace)
@@ -199,9 +201,10 @@ class View(gtk.EventBox):
             return
 
         if book.wiki.find('%s (from %s)' % (title, wiki))[0]:
-            self.activity.notify_alert(
-                    _('Exists'),
-                    _('"%s" article already exists') % title)
+            alert = Alert()
+            alert.props.title = _('Exists')
+            alert.props.msg = _('"%s" article already exists' % title)
+            alert.show()
         else:
             Timer(0, self._download, [title, wiki]).start()
 
diff --git a/net.py b/net.py
index e3a13cf..968f407 100644
--- a/net.py
+++ b/net.py
@@ -18,7 +18,7 @@ import urllib
 import logging
 from gettext import gettext as _
 
-from sugar.activity.activity import get_bundle_path
+from sugar3.activity.activity import get_bundle_path
 
 import book
 from infoslicer.processing.NewtifulSoup import NewtifulStoneSoup \
diff --git a/setup.py b/setup.py
index bb74f5a..83abd2a 100755
--- a/setup.py
+++ b/setup.py
@@ -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
 
-from sugar.activity import bundlebuilder
+from sugar3.activity import bundlebuilder
 if __name__ == "__main__":
     bundlebuilder.start()
 
diff --git a/toolbar.py b/toolbar.py
index 811f93a..dbb2101 100644
--- a/toolbar.py
+++ b/toolbar.py
@@ -12,29 +12,29 @@
 # 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
-import gobject
+from gi.repository import Gtk
+from gi.repository import GObject
 
-from sugar.graphics.icon import Icon
-import sugar.graphics.style as style
+from sugar3.graphics.icon import Icon
+import sugar3.graphics.style as style
 
-class WidgetItem(gtk.ToolItem):
+class WidgetItem(Gtk.ToolItem):
     def __init__(self, widget):
-        gtk.ToolItem.__init__(self)
+        GObject.GObject.__init__(self)
         self.add(widget)
         widget.show()
 
-class ButtonItem(gtk.ToolButton):
-    def __init__(self, icon_name, size=gtk.ICON_SIZE_SMALL_TOOLBAR, **kwargs):
-        gobject.GObject.__init__(self, **kwargs)
+class ButtonItem(Gtk.ToolButton):
+    def __init__(self, icon_name, size=Gtk.IconSize.SMALL_TOOLBAR, **kwargs):
+        GObject.GObject.__init__(self, **kwargs)
 
         icon = Icon(icon_name=icon_name, icon_size=size)
-        # The alignment is a hack to work around gtk.ToolButton code
-        # that sets the icon_size when the icon_widget is a gtk.Image
-        alignment = gtk.Alignment(0.5, 0.5)
+        # The alignment is a hack to work around Gtk.ToolButton code
+        # that sets the icon_size when the icon_widget is a Gtk.Image
+        alignment = Gtk.Alignment.new(0.5, 0.5)
         alignment.add(icon)
         self.set_icon_widget(alignment)
 
-        if size == gtk.ICON_SIZE_SMALL_TOOLBAR:
+        if size == Gtk.IconSize.SMALL_TOOLBAR:
             button_size = style.SMALL_ICON_SIZE + 8
             self.set_size_request(button_size, button_size)
diff --git a/xol.py b/xol.py
index f9eeb73..79763de 100644
--- a/xol.py
+++ b/xol.py
@@ -15,7 +15,7 @@
 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
 import os
-import gtk
+from gi.repository import Gtk
 import zipfile
 import uuid
 import logging
@@ -23,9 +23,10 @@ import parse
 from glob import glob
 from gettext import gettext as _
 
-from sugar.activity.activity import get_bundle_path, get_activity_root, get_bundle_name
-from sugar.datastore import datastore
-from sugar import activity
+from sugar3.activity.activity import get_bundle_path, get_activity_root, get_bundle_name
+from sugar3.datastore import datastore
+from sugar3 import activity
+from sugar3.graphics.alert import NotifyAlert, ConfirmationAlert
 
 from infoslicer.processing.NewtifulSoup import NewtifulStoneSoup \
         as BeautifulStoneSoup
@@ -33,11 +34,25 @@ import book
 
 logger = logging.getLogger('infoslicer')
 
+
+def __alert_notify_response_cb(alert, response_id, activity):
+    activity.remove_alert(alert)
+
+
+def __alert_response_cb(alert, response_id, activity, force):
+    activity.remove_alert(alert)
+    publish(activity, force)
+
+
 def publish(activity, force=False):
     if not [i for i in book.custom.index if i['ready']]:
-        activity.notify_alert(
-                _('Nothing to publish'),
-                _('Mark arcticles from "Custom" panel and try again.'))
+        alert = NotifyAlert(5)
+        alert.props.title = _('Nothing to publish')
+        alert.props.msg = _('Mark arcticles from "Custom" '
+                            'panel and try again.')
+        alert.connect('response', __alert_notify_response_cb, activity)
+        activity.add_alert(alert)
+        alert.show()
         return
 
     title = activity.metadata['title']
@@ -52,24 +67,13 @@ def publish(activity, force=False):
         if force:
             jobject = jobject[0]
         else:
-            try:
-                # check for 0.84 code
-                from jarabe import config
-            except:
-                # 0.82 couldn't override .xol bundles
-                activity.notify_alert(
-                        _('Bundle exists'),
-                        _('A bundle by "%s" name already exists. Please ' \
-                        'click "Erase" in the Journal. You can click ' \
-                        '"Publish" again afterwards.') % \
-                        jobject[0].metadata['title'])
-                return
-
-            activity.confirmation_alert(
-                    _('Overwrite existed bundle?'),
-                    _('A bundle for current object was already created. ' \
-                          'Click "OK" to overwrite it.'),
-                    publish, activity, True)
+            alert = ConfirmationAlert()
+            alert.props.title = _('Overwrite existed bundle?')
+            alert.props.msg = _('A bundle for current object was already created. '
+                                'Click "OK" to overwrite it.')
+            alert.connect('response', __alert_response_cb, activity, True)
+            activity.add_alert(alert)
+            alert.show()
             jobject[0].destroy()
             return
     else:
@@ -91,9 +95,13 @@ def publish(activity, force=False):
 
     book.custom.sync_index()
 
-    activity.notify_alert(_('Book published to your Journal'),
-                          _('You can read the book in Browse or ' \
-                                'access the .xol file from your Journal'))
+    alert = NotifyAlert()
+    alert.props.title = _('Book published to your Journal')
+    alert.props.msg = _('You can read the book in Browse or '
+                        'access the .xol file from your Journal')
+    alert.connect('response', __alert_notify_response_cb, activity)
+    activity.add_alert(alert)
+    alert.show()
 
 """
 @author: Matthew Bailey
-- 
1.7.10.4



More information about the Sugar-devel mailing list