Package: reportbug
Version: 7.0.1
Followup-For: Bug #651590

Here are some patches that seem to basically work. They aren't
perfectly broken up to do one thing per commit, but they're as close to that
as I had the patience for.

There are probably still bugs in this implementation, but it works a lot
better than failing to import completely (I'm sending this report using it).

-- System Information:
Debian Release: stretch/sid
  APT prefers unstable-debug
  APT policy: (500, 'unstable-debug'), (500, 'unstable'), (500, 'testing'), 
(500, 'stable'), (1, 'experimental-debug'), (1, 'experimental')
Architecture: amd64 (x86_64)
Foreign Architectures: i386

Kernel: Linux 4.9.0-rc8-amd64 (SMP w/4 CPU cores)
Locale: LANG=en_GB.utf8, LC_CTYPE=en_GB.utf8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
Init: systemd (via /run/systemd/system)

Versions of packages reportbug depends on:
ii  apt                1.4~beta2
ii  python3-reportbug  7.0.1+nmu1
pn  python3:any        <none>

reportbug recommends no packages.

Versions of packages reportbug suggests:
pn  claws-mail                               <none>
ii  debconf-utils                            1.5.59
ii  debsums                                  2.1.3
pn  dlocate                                  <none>
pn  emacs23-bin-common | emacs24-bin-common  <none>
ii  file                                     1:5.29-2
ii  gir1.2-gtk-3.0                           3.22.5-1
ii  gir1.2-vte-2.91                          0.46.1-1
ii  gnupg                                    2.1.16-3
ii  postfix [mail-transport-agent]           3.1.3-6
ii  python3-gi                               3.22.0-2
ii  python3-gtkspellcheck                    4.0.5-1
pn  python3-urwid                            <none>
ii  xdg-utils                                1.1.1-1

Versions of packages python-reportbug depends on:
ii  apt               1.4~beta2
ii  file              1:5.29-2
ii  python-debian     0.1.29
ii  python-debianbts  2.6.1
pn  python:any        <none>

python-reportbug suggests no packages.

-- no debconf information
>From 0b319293b14da1af6c8803391adf93d0b8f0f858 Mon Sep 17 00:00:00 2001
From: Simon McVittie <[email protected]>
Date: Wed, 14 Dec 2016 14:44:14 +0000
Subject: [PATCH 01/21] gtk2_ui: correct UINotImportable message for Python 3
 and g-i

---
 reportbug/ui/gtk2_ui.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/reportbug/ui/gtk2_ui.py b/reportbug/ui/gtk2_ui.py
index 95f70c5..62deecf 100644
--- a/reportbug/ui/gtk2_ui.py
+++ b/reportbug/ui/gtk2_ui.py
@@ -34,7 +34,7 @@ try:
     import gobject
     import pango
 except ImportError:
-    raise UINotImportable('Please install the python-gtk2 package to use this interface.')
+    raise UINotImportable('Please install the python3-gi and gir1.2-gtk-3.0 packages to use this interface.')
 
 global vte
 
-- 
2.11.0

>From db4756064f57a20cc91aa196ba46b0ba38c2807f Mon Sep 17 00:00:00 2001
From: Simon McVittie <[email protected]>
Date: Wed, 14 Dec 2016 14:44:55 +0000
Subject: [PATCH 02/21] gtk2_ui: use VTE via g-i

The legacy static bindings are not available under Python 3.
---
 reportbug/ui/gtk2_ui.py | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/reportbug/ui/gtk2_ui.py b/reportbug/ui/gtk2_ui.py
index 62deecf..89d9efc 100644
--- a/reportbug/ui/gtk2_ui.py
+++ b/reportbug/ui/gtk2_ui.py
@@ -23,6 +23,8 @@
 from reportbug.exceptions import UINotImportable
 
 try:
+    import gi
+
     # use a PyGTK compatibility layer
     # https://wiki.gnome.org/Projects/PyGObject/IntrospectionPorting
     from gi import pygtkcompat
@@ -36,7 +38,7 @@ try:
 except ImportError:
     raise UINotImportable('Please install the python3-gi and gir1.2-gtk-3.0 packages to use this interface.')
 
-global vte
+global Vte
 
 try:
     import gtkspellcheck
@@ -1299,7 +1301,7 @@ class SystemPage(Page):
     def create_widget(self):
         hbox = gtk.HBox()
 
-        self.terminal = vte.Terminal()
+        self.terminal = Vte.Terminal()
         self.terminal.set_cursor_blinks(True)
         self.terminal.set_emulation("xterm")
         self.terminal.connect('child-exited', self.on_child_exited)
@@ -1564,16 +1566,17 @@ def forward_operations(parent, operations):
 
 
 def initialize():
-    global application, assistant, vte
+    global application, assistant, Vte
 
     try:
-        vte = __import__("vte")
+        gi.require_version('Vte', '2.91')
+        from gi.repository import Vte
     except ImportError:
         message = """Please install the %s package to use the GTK+(known as 'gtk2' in reportbug) interface.
 Falling back to 'text' interface."""
         dialog = gtk.MessageDialog(None, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
                                    gtk.MESSAGE_INFO, gtk.BUTTONS_CLOSE, None)
-        dialog.set_markup(message % "<b>python-vte</b>")
+        dialog.set_markup(message % "<b>gir1.2-vte-2.91</b>")
         dialog.run()
         dialog.destroy()
         while gtk.events_pending():
-- 
2.11.0

>From 4175ed4c351e5f170415578eabc3bfb1394e4ccc Mon Sep 17 00:00:00 2001
From: Simon McVittie <[email protected]>
Date: Wed, 14 Dec 2016 14:46:11 +0000
Subject: [PATCH 03/21] control: Update dependencies for Gtk and Vte g-i
 bindings

---
 debian/control | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/debian/control b/debian/control
index c1a58b1..8f77a2f 100644
--- a/debian/control
+++ b/debian/control
@@ -13,7 +13,7 @@ Homepage: http://alioth.debian.org/projects/reportbug/
 Package: reportbug
 Architecture: all
 Depends: ${misc:Depends}, ${python3:Depends}, apt, python3-reportbug (= ${source:Version})
-Suggests: postfix | exim4 | mail-transport-agent, gnupg | pgp, debconf-utils (>> 1.1.0), debsums (>= 2.0.47), file (>> 1.30), dlocate, python3-urwid, python3-gi, python3-gtkspellcheck, xdg-utils, emacs23-bin-common | emacs24-bin-common, claws-mail (>= 3.8.0)
+Suggests: postfix | exim4 | mail-transport-agent, gnupg | pgp, debconf-utils (>> 1.1.0), debsums (>= 2.0.47), file (>> 1.30), dlocate, python3-urwid, python3-gi, gir1.2-gtk-3.0, gir1.2-vte-2.91, python3-gtkspellcheck, xdg-utils, emacs23-bin-common | emacs24-bin-common, claws-mail (>= 3.8.0)
 Description: reports bugs in the Debian distribution
  reportbug is a tool designed to make the reporting of bugs in Debian
  and derived distributions relatively painless.  Its features include:
-- 
2.11.0

>From e0d219b6b55a0685d9d10adc4c112e85444caa5c Mon Sep 17 00:00:00 2001
From: Simon McVittie <[email protected]>
Date: Wed, 14 Dec 2016 15:00:05 +0000
Subject: [PATCH 04/21] gtk2_ui: use the g-i spelling for class method
 set_default_icon_from_file

---
 reportbug/ui/gtk2_ui.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/reportbug/ui/gtk2_ui.py b/reportbug/ui/gtk2_ui.py
index 89d9efc..7d28b6f 100644
--- a/reportbug/ui/gtk2_ui.py
+++ b/reportbug/ui/gtk2_ui.py
@@ -1590,7 +1590,7 @@ Falling back to 'text' interface."""
     sys.excepthook = ExceptionDialog.create_excepthook(oldhook)
 
     # GTK settings
-    gtk.window_set_default_icon_from_file(DEBIAN_LOGO)
+    gtk.Window.set_default_icon_from_file(DEBIAN_LOGO)
     gtk.link_button_set_uri_hook(lambda button, uri: launch_browser(uri))
 
     application = ReportbugApplication()
-- 
2.11.0

>From c84547f7047d0997e08910cdda11ab2adc265a23 Mon Sep 17 00:00:00 2001
From: Simon McVittie <[email protected]>
Date: Wed, 14 Dec 2016 15:01:22 +0000
Subject: [PATCH 05/21] gtk2_ui: let GTK choose how to open a web browser

It uses freedesktop.org mechanisms to do so, and is at least as good
at it as xdg-open, which is what launch_browser uses.
---
 reportbug/ui/gtk2_ui.py | 1 -
 1 file changed, 1 deletion(-)

diff --git a/reportbug/ui/gtk2_ui.py b/reportbug/ui/gtk2_ui.py
index 7d28b6f..1673c79 100644
--- a/reportbug/ui/gtk2_ui.py
+++ b/reportbug/ui/gtk2_ui.py
@@ -1591,7 +1591,6 @@ Falling back to 'text' interface."""
 
     # GTK settings
     gtk.Window.set_default_icon_from_file(DEBIAN_LOGO)
-    gtk.link_button_set_uri_hook(lambda button, uri: launch_browser(uri))
 
     application = ReportbugApplication()
     assistant = ReportbugAssistant(application)
-- 
2.11.0

>From 5a0b165039387853ddea8ab25e31739ab48f0ad6 Mon Sep 17 00:00:00 2001
From: Simon McVittie <[email protected]>
Date: Wed, 14 Dec 2016 15:04:18 +0000
Subject: [PATCH 06/21] gtk2_ui: use string values for string-valued columns

PyGI has less "do what I mean" than PyGTK did.
---
 reportbug/ui/gtk2_ui.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/reportbug/ui/gtk2_ui.py b/reportbug/ui/gtk2_ui.py
index 1673c79..1c951f1 100644
--- a/reportbug/ui/gtk2_ui.py
+++ b/reportbug/ui/gtk2_ui.py
@@ -1056,7 +1056,7 @@ class HandleBTSQueryPage(TreePage):
             row[3] = category[0]
             iter = self.model.append(None, row)
             for bug in category[1]:
-                self.model.append(iter, list(bug))
+                self.model.append(iter, list(map(str, bug)))
 
         self.selection.set_mode(gtk.SELECTION_MULTIPLE)
 
-- 
2.11.0

>From f0d879da32b048eaf33968ba5103ba98b1737b9a Mon Sep 17 00:00:00 2001
From: Simon McVittie <[email protected]>
Date: Wed, 14 Dec 2016 15:06:13 +0000
Subject: [PATCH 07/21] gtk2_ui: filter_visible_func now gets a user_data
 argument

---
 reportbug/ui/gtk2_ui.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/reportbug/ui/gtk2_ui.py b/reportbug/ui/gtk2_ui.py
index 1c951f1..65e0679 100644
--- a/reportbug/ui/gtk2_ui.py
+++ b/reportbug/ui/gtk2_ui.py
@@ -1034,7 +1034,7 @@ class HandleBTSQueryPage(TreePage):
                 return True
         return False
 
-    def filter_visible_func(self, model, iter):
+    def filter_visible_func(self, model, iter, user_data=None):
         matches = self.match_filter(iter)
         if not self.model.iter_parent(iter) and not matches:
             # If no children are visible, hide it
-- 
2.11.0

>From 371ca9e97c5663d495063089ffaa432f5194c18f Mon Sep 17 00:00:00 2001
From: Simon McVittie <[email protected]>
Date: Wed, 14 Dec 2016 15:10:30 +0000
Subject: [PATCH 08/21] gtk2_ui: adjust signature of CellRendererText.do_render

The GTK+ 3 version takes a cairo_t instead of a window, and no longer
receives an expose_area.
---
 reportbug/ui/gtk2_ui.py | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/reportbug/ui/gtk2_ui.py b/reportbug/ui/gtk2_ui.py
index 65e0679..d857d97 100644
--- a/reportbug/ui/gtk2_ui.py
+++ b/reportbug/ui/gtk2_ui.py
@@ -806,9 +806,9 @@ class GetListPage(TreePage):
 
 
 class WrapRendererText(gtk.CellRendererText):
-    def do_render(self, window, widget, background_area, cell_area, expose_area, flags):
+    def do_render(self, cr, widget, background_area, cell_area, flags):
         self.set_property('wrap-width', cell_area.width)
-        gtk.CellRendererText.do_render(self, window, widget, background_area, cell_area, expose_area, flags)
+        gtk.CellRendererText.do_render(self, cr, widget, background_area, cell_area, flags)
 
 
 gobject.type_register(WrapRendererText)
-- 
2.11.0

>From 7e56a5f91fbd3fc499c259fb2ac0e66ff9104659 Mon Sep 17 00:00:00 2001
From: Simon McVittie <[email protected]>
Date: Wed, 14 Dec 2016 15:13:30 +0000
Subject: [PATCH 09/21] gtk2_ui: use properties, which replace widget flags

---
 reportbug/ui/gtk2_ui.py | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/reportbug/ui/gtk2_ui.py b/reportbug/ui/gtk2_ui.py
index d857d97..f4f11b6 100644
--- a/reportbug/ui/gtk2_ui.py
+++ b/reportbug/ui/gtk2_ui.py
@@ -1253,7 +1253,8 @@ class SelectOptionsPage(Page):
 
     def setup_focus(self):
         if self.default:
-            self.default.set_flags(gtk.CAN_DEFAULT | gtk.HAS_DEFAULT)
+            self.default.props.can_default = True
+            self.default.props.has_default = True
             self.default.grab_default()
             self.default.grab_focus()
 
-- 
2.11.0

>From b92668f41d066ccdf342f1730107fe7e434c8f7c Mon Sep 17 00:00:00 2001
From: Simon McVittie <[email protected]>
Date: Wed, 14 Dec 2016 15:20:06 +0000
Subject: [PATCH 10/21] gtk2_ui: modernize syntax of direct Pango uses

---
 reportbug/ui/gtk2_ui.py | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/reportbug/ui/gtk2_ui.py b/reportbug/ui/gtk2_ui.py
index f4f11b6..8f4cf36 100644
--- a/reportbug/ui/gtk2_ui.py
+++ b/reportbug/ui/gtk2_ui.py
@@ -34,7 +34,9 @@ try:
 
     import gtk
     import gobject
-    import pango
+
+    gi.require_version('Pango', '1.0')
+    from gi.repository import Pango
 except ImportError:
     raise UINotImportable('Please install the python3-gi and gir1.2-gtk-3.0 packages to use this interface.')
 
@@ -848,7 +850,7 @@ class MenuPage(TreePage):
 
         self.view.append_column(gtk.TreeViewColumn('Option', gtk.CellRendererText(), markup=0))
         rend = WrapRendererText()
-        rend.set_property('wrap-mode', pango.WRAP_WORD)
+        rend.set_property('wrap-mode', Pango.WrapMode.WORD)
         rend.set_property('wrap-width', 300)
         self.view.append_column(gtk.TreeViewColumn('Description', rend, text=1))
 
@@ -1155,7 +1157,7 @@ class EditorPage(Page):
         vbox.pack_start(hbox, expand=False)
 
         self.view = gtk.TextView()
-        self.view.modify_font(pango.FontDescription("Monospace"))
+        self.view.modify_font(Pango.FontDescription("Monospace"))
         self.view.set_wrap_mode(gtk.WRAP_WORD)
         if has_spell:
             gtkspellcheck.SpellChecker(self.view)
-- 
2.11.0

>From 824feb57c00c1609c52d19ac362efd8883bada05 Mon Sep 17 00:00:00 2001
From: Simon McVittie <[email protected]>
Date: Wed, 14 Dec 2016 15:24:40 +0000
Subject: [PATCH 11/21] gtk2_ui: modernize syntax of uses of Gdk and GdkPixbuf

---
 reportbug/ui/gtk2_ui.py | 16 +++++++++++-----
 1 file changed, 11 insertions(+), 5 deletions(-)

diff --git a/reportbug/ui/gtk2_ui.py b/reportbug/ui/gtk2_ui.py
index 8f4cf36..15effd5 100644
--- a/reportbug/ui/gtk2_ui.py
+++ b/reportbug/ui/gtk2_ui.py
@@ -37,6 +37,12 @@ try:
 
     gi.require_version('Pango', '1.0')
     from gi.repository import Pango
+
+    gi.require_version('Gdk', '3.0')
+    from gi.repository import Gdk
+
+    gi.require_version('GdkPixbuf', '2.0')
+    from gi.repository import GdkPixbuf
 except ImportError:
     raise UINotImportable('Please install the python3-gi and gir1.2-gtk-3.0 packages to use this interface.')
 
@@ -49,7 +55,7 @@ except:
     has_spell = False
 
 #gtk.set_interactive(0)
-gtk.gdk.threads_init()
+Gdk.threads_init()
 
 import sys
 import re
@@ -476,9 +482,9 @@ class ReportbugApplication(threading.Thread):
         self.next_value = None
 
     def run(self):
-        gtk.gdk.threads_enter()
+        Gdk.threads_enter()
         gtk.main()
-        gtk.gdk.threads_leave()
+        Gdk.threads_leave()
 
     def get_last_value(self):
         return self.queue.get()
@@ -526,7 +532,7 @@ class Page(ReportbugConnector):
     page_type = gtk.ASSISTANT_PAGE_CONTENT
     default_complete = False
     side_image = DEBIAN_LOGO
-    WARNING_COLOR = gtk.gdk.color_parse("#fff8ae")
+    WARNING_COLOR = Gdk.color_parse("#fff8ae")
 
     def __init__(self, assistant):
         self.assistant = assistant
@@ -565,7 +571,7 @@ class Page(ReportbugConnector):
         self.assistant.insert_page(self.widget, self.page_num)
         self.set_page_complete(self.default_complete)
         self.set_page_type(self.page_type)
-        self.assistant.set_page_side_image(self.widget, gtk.gdk.pixbuf_new_from_file(self.side_image))
+        self.assistant.set_page_side_image(self.widget, GdkPixbuf.Pixbuf.new_from_file(self.side_image))
         self.assistant.set_next_page(self)
         self.set_page_title("Reportbug")
 
-- 
2.11.0

>From 5cde72ec28ab4e84e60a7d41c7898f6917babb05 Mon Sep 17 00:00:00 2001
From: Simon McVittie <[email protected]>
Date: Wed, 14 Dec 2016 15:26:52 +0000
Subject: [PATCH 12/21] gtk2_ui: modernize syntax of GObject uses

Several of these are in fact GLib functions.
---
 reportbug/ui/gtk2_ui.py | 33 +++++++++++++++++++--------------
 1 file changed, 19 insertions(+), 14 deletions(-)

diff --git a/reportbug/ui/gtk2_ui.py b/reportbug/ui/gtk2_ui.py
index 15effd5..2f19d78 100644
--- a/reportbug/ui/gtk2_ui.py
+++ b/reportbug/ui/gtk2_ui.py
@@ -33,7 +33,12 @@ try:
     pygtkcompat.enable_gtk(version='3.0')
 
     import gtk
-    import gobject
+
+    gi.require_version('GLib', '2.0')
+    from gi.repository import GLib
+
+    gi.require_version('GObject', '2.0')
+    from gi.repository import GObject
 
     gi.require_version('Pango', '1.0')
     from gi.repository import Pango
@@ -373,7 +378,7 @@ class BugPage(gtk.EventBox, threading.Thread):
 
     def run(self):
         # Start the progress bar
-        gobject.timeout_add(10, self.pulse)
+        GLib.timeout_add(10, self.pulse)
 
         info = debbugs.get_report(int(self.number), self.timeout,
                                   self.bts, mirrors=self.mirrors,
@@ -504,7 +509,7 @@ class ReportbugApplication(threading.Thread):
         return callback
 
     def run_once_in_main_thread(self, func, *args, **kwargs):
-        gobject.idle_add(self.create_idle_callback(func, *args, **kwargs))
+        GLib.idle_add(self.create_idle_callback(func, *args, **kwargs))
 
 
 # Connection with reportbug
@@ -652,7 +657,7 @@ class GetStringPage(Page):
 
     def execute(self, prompt, options=None, force_prompt=False, default=''):
         # Hackish: remove the text needed for textual UIs...
-        gobject.idle_add(self.label.set_text, prompt.replace('(enter Ctrl+c to exit reportbug without reporting a bug)', ''))
+        GLib.idle_add(self.label.set_text, prompt.replace('(enter Ctrl+c to exit reportbug without reporting a bug)', ''))
         self.entry.set_text(default)
 
         if options:
@@ -711,7 +716,7 @@ class GetMultilinePage(Page):
     def execute(self, prompt):
         self.empty_ok = True
         # The result must be iterable for reportbug even if it's empty and not modified
-        gobject.idle_add(self.label.set_text, prompt)
+        GLib.idle_add(self.label.set_text, prompt)
         self.buffer.set_text("")
         self.buffer.emit('changed')
 
@@ -802,7 +807,7 @@ class GetListPage(TreePage):
     def execute(self, prompt):
         self.empty_ok = True
 
-        gobject.idle_add(self.label.set_text, prompt)
+        GLib.idle_add(self.label.set_text, prompt)
 
         self.model = gtk.ListStore(str)
         self.model.connect('row-changed', self.validate)
@@ -819,7 +824,7 @@ class WrapRendererText(gtk.CellRendererText):
         gtk.CellRendererText.do_render(self, cr, widget, background_area, cell_area, flags)
 
 
-gobject.type_register(WrapRendererText)
+GObject.type_register(WrapRendererText)
 
 
 class MenuPage(TreePage):
@@ -846,7 +851,7 @@ class MenuPage(TreePage):
 
     def execute(self, par, options, prompt, default=None, any_ok=False,
                 order=None, extras=None, multiple=False):
-        gobject.idle_add(self.label.set_text, par)
+        GLib.idle_add(self.label.set_text, par)
 
         self.model = gtk.ListStore(str, str)
         self.view.set_model(self.model)
@@ -1056,7 +1061,7 @@ class HandleBTSQueryPage(TreePage):
         return matches
 
     def execute(self, buglist, sectitle):
-        gobject.idle_add(self.label.set_text, "%s. Double-click a bug to retrieve and submit more information." % sectitle)
+        GLib.idle_add(self.label.set_text, "%s. Double-click a bug to retrieve and submit more information." % sectitle)
 
         self.model = gtk.TreeStore(*([str] * len(self.columns)))
         for category in buglist:
@@ -1137,7 +1142,7 @@ class LongMessagePage(Page):
         message = message % args
         # make it all on one line, it will be wrapped at display-time
         message = ' '.join(message.split())
-        gobject.idle_add(self.label.set_text, message)
+        GLib.idle_add(self.label.set_text, message)
         # Reportbug should use final_message, so emulate it
         if('999999' in message):
             self.set_page_type(gtk.ASSISTANT_PAGE_CONFIRM)
@@ -1269,7 +1274,7 @@ class SelectOptionsPage(Page):
     def execute(self, prompt, menuopts, options):
         # remove text UI indication
         prompt = prompt.replace('(e to edit)', '')
-        gobject.idle_add(self.label.set_text, prompt)
+        GLib.idle_add(self.label.set_text, prompt)
 
         buttons = []
         for menuopt in menuopts:
@@ -1346,11 +1351,11 @@ class ProgressPage(Page):
         self.progress.set_pulse_step(0.01)
         vbox.pack_start(self.label, expand=False)
         vbox.pack_start(self.progress, expand=False)
-        gobject.timeout_add(10, self.pulse)
+        GLib.timeout_add(10, self.pulse)
         return vbox
 
     def set_label(self, text):
-        gobject.idle_add(self.label.set_text, text)
+        GLib.idle_add(self.label.set_text, text)
 
     def reset_label(self):
         self.set_label("This operation may take a while")
@@ -1423,7 +1428,7 @@ class ReportbugAssistant(gtk.Assistant):
         if self.showing_page == self.progress_page:
             self.progress_page.reset_label()
 
-        gobject.idle_add(self.showing_page.setup_focus)
+        GLib.idle_add(self.showing_page.setup_focus)
 
     def close(self, *args):
         sys.exit(0)
-- 
2.11.0

>From ff07d32eb854861f1654fbb78a7f3e9e2caf50e9 Mon Sep 17 00:00:00 2001
From: Simon McVittie <[email protected]>
Date: Wed, 14 Dec 2016 16:06:39 +0000
Subject: [PATCH 13/21] gtk2_ui: Use g-i constructor convention for Gtk.Image

---
 reportbug/ui/gtk2_ui.py | 17 ++++++++++-------
 1 file changed, 10 insertions(+), 7 deletions(-)

diff --git a/reportbug/ui/gtk2_ui.py b/reportbug/ui/gtk2_ui.py
index 2f19d78..562f623 100644
--- a/reportbug/ui/gtk2_ui.py
+++ b/reportbug/ui/gtk2_ui.py
@@ -48,6 +48,9 @@ try:
 
     gi.require_version('GdkPixbuf', '2.0')
     from gi.repository import GdkPixbuf
+
+    gi.require_version('Gtk', '3.0')
+    from gi.repository import Gtk
 except ImportError:
     raise UINotImportable('Please install the python3-gi and gir1.2-gtk-3.0 packages to use this interface.')
 
@@ -146,7 +149,7 @@ class CustomDialog(gtk.Dialog):
         align = gtk.Alignment(0.5, 0.5, 1.0, 1.0)
         hbox.pack_start(align, expand=False)
 
-        image = gtk.image_new_from_stock(stock_image, gtk.ICON_SIZE_DIALOG)
+        image = Gtk.Image.new_from_stock(stock_image, Gtk.IconSize.DIALOG)
         hbox.pack_start(image)
 
         label = gtk.Label(message)
@@ -434,7 +437,7 @@ class BugPage(gtk.EventBox, threading.Thread):
         bbox.pack_start(button)
         if not self.queryonly:
             button = gtk.Button("Reply")
-            button.set_image(gtk.image_new_from_stock(gtk.STOCK_EDIT, gtk.ICON_SIZE_BUTTON))
+            button.set_image(Gtk.Image.new_from_stock(Gtk.STOCK_EDIT, Gtk.IconSize.BUTTON))
             button.connect('clicked', self.on_reply)
             bbox.pack_start(button)
         vbox.pack_start(bbox, expand=False)
@@ -979,7 +982,7 @@ class HandleBTSQueryPage(TreePage):
         self.entry = gtk.Entry()
         hbox.pack_start(self.entry)
         button = gtk.Button()
-        button.set_image(gtk.image_new_from_stock(gtk.STOCK_CLEAR, gtk.ICON_SIZE_MENU))
+        button.set_image(Gtk.Image.new_from_stock(Gtk.STOCK_CLEAR, Gtk.IconSize.MENU))
         button.set_relief(gtk.RELIEF_NONE)
         button.connect('clicked', self.on_filter_clear)
         hbox.pack_start(button, expand=False)
@@ -997,7 +1000,7 @@ class HandleBTSQueryPage(TreePage):
         vbox.pack_start(scrolled)
 
         button = gtk.Button("Retrieve and submit bug information")
-        button.set_image(gtk.image_new_from_stock(gtk.STOCK_INFO, gtk.ICON_SIZE_BUTTON))
+        button.set_image(Gtk.Image.new_from_stock(Gtk.STOCK_INFO, Gtk.IconSize.BUTTON))
         button.connect('clicked', self.on_retrieve_info)
         vbox.pack_start(button, expand=False)
         return vbox
@@ -1388,13 +1391,13 @@ class ReportbugAssistant(gtk.Assistant):
                 widget.connect('show', self.on_back_show)
                 return
             if widget.get_label() == 'gtk-cancel':
-                image = gtk.image_new_from_stock(gtk.STOCK_QUIT,
-                                                 gtk.ICON_SIZE_BUTTON)
+                image = Gtk.Image.new_from_stock(Gtk.STOCK_QUIT,
+                                                 Gtk.IconSize.BUTTON)
                 widget.set_label("_Quit")
                 widget.set_image(image)
                 return
             if widget.get_label() == 'gtk-go-forward':
-                image = gtk.image_new_from_stock(gtk.STOCK_GO_FORWARD, gtk.ICON_SIZE_BUTTON)
+                image = Gtk.Image.new_from_stock(Gtk.STOCK_GO_FORWARD, Gtk.IconSize.BUTTON)
                 widget.set_label("_Continue")
                 widget.set_image(image)
                 return
-- 
2.11.0

>From 01aca401fe793bd6a49c835cccdc148ed763761b Mon Sep 17 00:00:00 2001
From: Simon McVittie <[email protected]>
Date: Wed, 14 Dec 2016 16:15:56 +0000
Subject: [PATCH 14/21] gtk2_ui: don't rely on pygtkcompat for dialog
 flags/responses

Enums and flags from "typedef enum { GTK_FOO_BAR } GtkFooType"
are consistently represented as Gtk.FooType.BAR, members of a
Gtk.FooType type.
---
 reportbug/ui/gtk2_ui.py | 84 ++++++++++++++++++++++++-------------------------
 1 file changed, 42 insertions(+), 42 deletions(-)

diff --git a/reportbug/ui/gtk2_ui.py b/reportbug/ui/gtk2_ui.py
index 562f623..02d82cf 100644
--- a/reportbug/ui/gtk2_ui.py
+++ b/reportbug/ui/gtk2_ui.py
@@ -114,25 +114,25 @@ def create_scrollable(widget, with_viewport=False):
 
 
 def info_dialog(message):
-    dialog = gtk.MessageDialog(assistant, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
-                               gtk.MESSAGE_INFO, gtk.BUTTONS_CLOSE, message)
+    dialog = Gtk.MessageDialog(assistant, Gtk.DialogFlags.MODAL | Gtk.DialogFlags.DESTROY_WITH_PARENT,
+                               Gtk.MessageType.INFO, Gtk.ButtonsType.CLOSE, message)
     dialog.connect('response', lambda d, *args: d.destroy())
     dialog.set_title('Reportbug')
     dialog.show_all()
 
 
 def error_dialog(message):
-    dialog = gtk.MessageDialog(assistant, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
-                               gtk.MESSAGE_ERROR, gtk.BUTTONS_CLOSE, message)
+    dialog = Gtk.MessageDialog(assistant, Gtk.DialogFlags.MODAL | Gtk.DialogFlags.DESTROY_WITH_PARENT,
+                               Gtk.MessageType.ERROR, Gtk.ButtonsType.CLOSE, message)
     dialog.connect('response', lambda d, *args: d.destroy())
     dialog.set_title('Reportbug')
     dialog.show_all()
 
 
-class CustomDialog(gtk.Dialog):
+class CustomDialog(Gtk.Dialog):
     def __init__(self, stock_image, message, buttons, *args, **kwargs):
-        gtk.Dialog.__init__(self, "Reportbug", assistant,
-                            gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
+        Gtk.Dialog.__init__(self, "Reportbug", assistant,
+                            Gtk.DialogFlags.MODAL | Gtk.DialogFlags.DESTROY_WITH_PARENT,
                             buttons)
         # Try following the HIG
         self.set_default_response(buttons[-1])  # this is the response of the last button
@@ -164,9 +164,9 @@ class CustomDialog(gtk.Dialog):
 
 class InputStringDialog(CustomDialog):
     def __init__(self, message):
-        CustomDialog.__init__(self, gtk.STOCK_DIALOG_INFO, message,
-                              (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
-                               gtk.STOCK_OK, gtk.RESPONSE_ACCEPT))
+        CustomDialog.__init__(self, Gtk.STOCK_DIALOG_INFO, message,
+                              (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
+                               Gtk.STOCK_OK, Gtk.ResponseType.ACCEPT))
 
     def setup_dialog(self, vbox):
         self.entry = gtk.Entry()
@@ -196,7 +196,7 @@ class ExceptionDialog(CustomDialog):
             sys.exit(1)
 
     def __init__(self, tb):
-        CustomDialog.__init__(self, gtk.STOCK_DIALOG_ERROR, "An error has occurred while doing an operation in Reportbug.\nPlease report the bug.", (gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE), tb)
+        CustomDialog.__init__(self, Gtk.STOCK_DIALOG_ERROR, "An error has occurred while doing an operation in Reportbug.\nPlease report the bug.", (Gtk.STOCK_CLOSE, Gtk.ResponseType.CLOSE), tb)
 
     def setup_dialog(self, vbox, tb):
         # The traceback
@@ -215,16 +215,16 @@ class ExceptionDialog(CustomDialog):
         sys.exit(1)
 
 
-class ReportViewerDialog(gtk.Dialog):
+class ReportViewerDialog(Gtk.Dialog):
     def __init__(self, message):
-        gtk.Dialog.__init__(self, "Reportbug", assistant,
-                            gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
-                            (gtk.STOCK_COPY, gtk.RESPONSE_APPLY,
-                             gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE))
+        Gtk.Dialog.__init__(self, "Reportbug", assistant,
+                            Gtk.DialogFlags.MODAL | Gtk.DialogFlags.DESTROY_WITH_PARENT,
+                            (Gtk.STOCK_COPY, Gtk.ResponseType.APPLY,
+                             Gtk.STOCK_CLOSE, Gtk.ResponseType.CLOSE))
         self.message = message
 
         self.set_default_size(400, 400)
-        self.set_default_response(gtk.RESPONSE_CLOSE)
+        self.set_default_response(Gtk.ResponseType.CLOSE)
         self.set_border_width(6)
         self.connect('response', self.on_response)
 
@@ -235,9 +235,9 @@ class ReportViewerDialog(gtk.Dialog):
         self.show_all()
 
     def on_response(self, dialog, res):
-        # ok gtk.RESPONSE_APPLY is ugly for gtk.STOCK_COPY, but who cares?
+        # ok Gtk.ResponseType.APPLY is ugly for Gtk.STOCK_COPY, but who cares?
         # maybe adding it as a secondary button or such is better
-        if res == gtk.RESPONSE_APPLY:
+        if res == Gtk.ResponseType.APPLY:
             clipboard = gtk.clipboard_get()
             clipboard.set_text(self.message)
         else:
@@ -458,11 +458,11 @@ class BugPage(gtk.EventBox, threading.Thread):
         self.dialog.destroy()
 
 
-class BugsDialog(gtk.Dialog):
+class BugsDialog(Gtk.Dialog):
     def __init__(self, assistant, queryonly):
-        gtk.Dialog.__init__(self, "Reportbug: bug information", assistant,
-                            gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
-                            (gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE))
+        Gtk.Dialog.__init__(self, "Reportbug: bug information", assistant,
+                            Gtk.DialogFlags.MODAL | Gtk.DialogFlags.DESTROY_WITH_PARENT,
+                            (Gtk.STOCK_CLOSE, Gtk.ResponseType.CLOSE))
         self.assistant = assistant
         self.queryonly = queryonly
         self.application = assistant.application
@@ -794,7 +794,7 @@ class GetListPage(TreePage):
         dialog.connect('response', self.on_add_dialog_response)
 
     def on_add_dialog_response(self, dialog, res):
-        if res == gtk.RESPONSE_ACCEPT:
+        if res == Gtk.ResponseType.ACCEPT:
             self.model.append([dialog.get_value()])
         dialog.destroy()
 
@@ -1437,12 +1437,12 @@ class ReportbugAssistant(gtk.Assistant):
         sys.exit(0)
 
     def confirm_exit(self, *args):
-        dialog = gtk.MessageDialog(None, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
-                                   gtk.MESSAGE_WARNING, gtk.BUTTONS_YES_NO,
+        dialog = Gtk.MessageDialog(None, Gtk.DialogFlags.MODAL | Gtk.DialogFlags.DESTROY_WITH_PARENT,
+                                   Gtk.MessageType.WARNING, Gtk.ButtonsType.YES_NO,
                                    "Are you sure you want to quit Reportbug?")
         response = dialog.run()
         dialog.destroy()
-        if response == gtk.RESPONSE_YES:
+        if response == Gtk.ResponseType.YES:
             sys.exit(0)
 
     def forward(self, page_num):
@@ -1471,31 +1471,31 @@ class ReportbugAssistant(gtk.Assistant):
 
 
 # Dialogs
-class YesNoDialog(ReportbugConnector, gtk.MessageDialog):
+class YesNoDialog(ReportbugConnector, Gtk.MessageDialog):
     def __init__(self, application):
-        gtk.MessageDialog.__init__(self, assistant, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
-                                   gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO)
+        Gtk.MessageDialog.__init__(self, assistant, Gtk.DialogFlags.MODAL | Gtk.DialogFlags.DESTROY_WITH_PARENT,
+                                   Gtk.MessageType.QUESTION, Gtk.ButtonsType.YES_NO)
         self.application = application
         self.connect('response', self.on_response)
 
     def on_response(self, dialog, res):
-        self.application.set_next_value(res == gtk.RESPONSE_YES)
+        self.application.set_next_value(res == Gtk.ResponseType.YES)
         self.application.put_next_value()
         self.destroy()
 
     def execute_operation(self, msg, yeshelp=None, nohelp=None, default=True, nowrap=False):
         self.set_markup(msg)
         if default:
-            self.set_default_response(gtk.RESPONSE_YES)
+            self.set_default_response(Gtk.ResponseType.YES)
         else:
-            self.set_default_response(gtk.RESPONSE_NO)
+            self.set_default_response(Gtk.ResponseType.NO)
         self.show_all()
 
 
-class DisplayFailureDialog(ReportbugConnector, gtk.MessageDialog):
+class DisplayFailureDialog(ReportbugConnector, Gtk.MessageDialog):
     def __init__(self, application):
-        gtk.MessageDialog.__init__(self, assistant, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
-                                   gtk.MESSAGE_WARNING, gtk.BUTTONS_CLOSE)
+        Gtk.MessageDialog.__init__(self, assistant, Gtk.DialogFlags.MODAL | Gtk.DialogFlags.DESTROY_WITH_PARENT,
+                                   Gtk.MessageType.WARNING, Gtk.ButtonsType.CLOSE)
         self.application = application
         self.connect('response', self.on_response)
 
@@ -1508,16 +1508,16 @@ class DisplayFailureDialog(ReportbugConnector, gtk.MessageDialog):
         self.show_all()
 
 
-class GetFilenameDialog(ReportbugConnector, gtk.FileChooserDialog):
+class GetFilenameDialog(ReportbugConnector, Gtk.FileChooserDialog):
     def __init__(self, application):
-        gtk.FileChooserDialog.__init__(self, '', assistant, buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
-                                                                     gtk.STOCK_OPEN, gtk.RESPONSE_OK))
+        Gtk.FileChooserDialog.__init__(self, '', assistant, buttons=(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
+                                                                     Gtk.STOCK_OPEN, Gtk.ResponseType.OK))
         self.application = application
         self.connect('response', self.on_response)
 
     def on_response(self, dialog, res):
         value = None
-        if res == gtk.RESPONSE_OK:
+        if res == Gtk.ResponseType.OK:
             value = self.get_filename()
 
         self.application.set_next_value(value)
@@ -1591,8 +1591,8 @@ def initialize():
     except ImportError:
         message = """Please install the %s package to use the GTK+(known as 'gtk2' in reportbug) interface.
 Falling back to 'text' interface."""
-        dialog = gtk.MessageDialog(None, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
-                                   gtk.MESSAGE_INFO, gtk.BUTTONS_CLOSE, None)
+        dialog = Gtk.MessageDialog(None, Gtk.DialogFlags.MODAL | Gtk.DialogFlags.DESTROY_WITH_PARENT,
+                                   Gtk.MessageType.INFO, Gtk.ButtonsType.CLOSE, None)
         dialog.set_markup(message % "<b>gir1.2-vte-2.91</b>")
         dialog.run()
         dialog.destroy()
-- 
2.11.0

>From b7fd7fded05e8c80dff0e13a12883a44bc722009 Mon Sep 17 00:00:00 2001
From: Simon McVittie <[email protected]>
Date: Wed, 14 Dec 2016 16:23:14 +0000
Subject: [PATCH 15/21] gtk2_ui: import various objects from Gtk, not from gtk
 compat shim

---
 reportbug/ui/gtk2_ui.py | 169 ++++++++++++++++++++++++------------------------
 1 file changed, 84 insertions(+), 85 deletions(-)

diff --git a/reportbug/ui/gtk2_ui.py b/reportbug/ui/gtk2_ui.py
index 02d82cf..646a356 100644
--- a/reportbug/ui/gtk2_ui.py
+++ b/reportbug/ui/gtk2_ui.py
@@ -103,7 +103,7 @@ def ask_free(s):
 
 
 def create_scrollable(widget, with_viewport=False):
-    scrolled = gtk.ScrolledWindow()
+    scrolled = Gtk.ScrolledWindow()
     scrolled.set_shadow_type(gtk.SHADOW_ETCHED_IN)
     scrolled.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
     if with_viewport:
@@ -138,21 +138,21 @@ class CustomDialog(Gtk.Dialog):
         self.set_default_response(buttons[-1])  # this is the response of the last button
         self.set_border_width(5)
 
-        vbox = gtk.VBox(spacing=10)
+        vbox = Gtk.VBox(spacing=10)
         vbox.set_border_width(6)
         self.vbox.pack_start(vbox)
 
         # The header image + label
-        hbox = gtk.HBox(spacing=10)
+        hbox = Gtk.HBox(spacing=10)
         vbox.pack_start(hbox, expand=False)
 
-        align = gtk.Alignment(0.5, 0.5, 1.0, 1.0)
+        align = Gtk.Alignment(0.5, 0.5, 1.0, 1.0)
         hbox.pack_start(align, expand=False)
 
         image = Gtk.Image.new_from_stock(stock_image, Gtk.IconSize.DIALOG)
         hbox.pack_start(image)
 
-        label = gtk.Label(message)
+        label = Gtk.Label(message)
         label.set_line_wrap(True)
         label.set_justify(gtk.JUSTIFY_FILL)
         label.set_selectable(True)
@@ -169,7 +169,7 @@ class InputStringDialog(CustomDialog):
                                Gtk.STOCK_OK, Gtk.ResponseType.ACCEPT))
 
     def setup_dialog(self, vbox):
-        self.entry = gtk.Entry()
+        self.entry = Gtk.Entry()
         vbox.pack_start(self.entry, expand=False)
 
     def get_value(self):
@@ -200,10 +200,10 @@ class ExceptionDialog(CustomDialog):
 
     def setup_dialog(self, vbox, tb):
         # The traceback
-        expander = gtk.Expander("More details")
+        expander = Gtk.Expander("More details")
         vbox.pack_start(expander, True)
 
-        view = gtk.TextView()
+        view = Gtk.TextView()
         view.set_editable(False)
         view.get_buffer().set_text(tb)
         scrolled = create_scrollable(view)
@@ -228,7 +228,7 @@ class ReportViewerDialog(Gtk.Dialog):
         self.set_border_width(6)
         self.connect('response', self.on_response)
 
-        view = gtk.TextView()
+        view = Gtk.TextView()
         view.get_buffer().set_text(self.message)
         self.vbox.pack_start(create_scrollable(view))
 
@@ -351,10 +351,10 @@ class BugReport(object):
 
 
 # BTS GUI
-class BugPage(gtk.EventBox, threading.Thread):
+class BugPage(Gtk.EventBox, threading.Thread):
     def __init__(self, assistant, dialog, number, queryonly, bts, mirrors, http_proxy, timeout, archived):
         threading.Thread.__init__(self)
-        gtk.EventBox.__init__(self)
+        Gtk.EventBox.__init__(self)
         self.setDaemon(True)
 
         self.dialog = dialog
@@ -370,10 +370,10 @@ class BugPage(gtk.EventBox, threading.Thread):
 
         self.bug_status = None
 
-        vbox = gtk.VBox(spacing=12)
+        vbox = Gtk.VBox(spacing=12)
         vbox.pack_start(gtk.Label("Retrieving bug information."), expand=False)
 
-        self.progress = gtk.ProgressBar()
+        self.progress = Gtk.ProgressBar()
         self.progress.set_pulse_step(0.01)
         vbox.pack_start(self.progress, expand=False)
 
@@ -404,24 +404,24 @@ class BugPage(gtk.EventBox, threading.Thread):
 
     def not_found(self):
         self.drop_progressbar()
-        self.add(gtk.Label("The bug can't be fetched or it doesn't exist."))
+        self.add(Gtk.Label("The bug can't be fetched or it doesn't exist."))
         self.show_all()
 
     def found(self, info):
         self.drop_progressbar()
         desc = info[0].subject
         bodies = info[1]
-        vbox = gtk.VBox(spacing=12)
+        vbox = Gtk.VBox(spacing=12)
         vbox.set_border_width(12)
-        label = gtk.Label('Description: ' + desc)
+        label = Gtk.Label('Description: ' + desc)
         label.set_line_wrap(True)
         label.set_justify(gtk.JUSTIFY_FILL)
         vbox.pack_start(label, expand=False)
 
-        views = gtk.VBox()
+        views = Gtk.VBox()
         odd = False
         for body in bodies:
-            view = gtk.TextView()
+            view = Gtk.TextView()
             view.set_editable(False)
             view.get_buffer().set_text(body)
             if odd:
@@ -431,12 +431,12 @@ class BugPage(gtk.EventBox, threading.Thread):
         scrolled = create_scrollable(views, True)
         vbox.pack_start(scrolled)
 
-        bbox = gtk.HButtonBox()
-        button = gtk.Button("Open in browser")
+        bbox = Gtk.HButtonBox()
+        button = Gtk.Button("Open in browser")
         button.connect('clicked', self.on_open_browser)
         bbox.pack_start(button)
         if not self.queryonly:
-            button = gtk.Button("Reply")
+            button = Gtk.Button("Reply")
             button.set_image(Gtk.Image.new_from_stock(Gtk.STOCK_EDIT, Gtk.IconSize.BUTTON))
             button.connect('clicked', self.on_reply)
             bbox.pack_start(button)
@@ -466,7 +466,7 @@ class BugsDialog(Gtk.Dialog):
         self.assistant = assistant
         self.queryonly = queryonly
         self.application = assistant.application
-        self.notebook = gtk.Notebook()
+        self.notebook = Gtk.Notebook()
         self.vbox.pack_start(self.notebook)
         self.connect('response', self.on_response)
         self.set_default_size(600, 600)
@@ -476,7 +476,7 @@ class BugsDialog(Gtk.Dialog):
 
     def show_bug(self, number, *args):
         page = BugPage(self.assistant, self, number, self.queryonly, *args)
-        self.notebook.append_page(page, gtk.Label(number))
+        self.notebook.append_page(page, Gtk.Label(number))
         page.start()
 
 
@@ -491,7 +491,7 @@ class ReportbugApplication(threading.Thread):
 
     def run(self):
         Gdk.threads_enter()
-        gtk.main()
+        Gtk.main()
         Gdk.threads_leave()
 
     def get_last_value(self):
@@ -616,9 +616,9 @@ class IntroPage(Page):
     default_complete = True
 
     def create_widget(self):
-        vbox = gtk.VBox(spacing=24)
+        vbox = Gtk.VBox(spacing=24)
 
-        label = gtk.Label("""
+        label = Gtk.Label("""
 <b>Reportbug</b> is a tool designed to make the reporting of bugs in Debian and derived distributions relatively painless.
 
 This wizard will guide you through the bug reporting process step by step.
@@ -629,7 +629,7 @@ This wizard will guide you through the bug reporting process step by step.
         label.set_justify(gtk.JUSTIFY_FILL)
         vbox.pack_start(label, expand=False)
 
-        link = gtk.LinkButton("http://alioth.debian.org/projects/reportbug";,
+        link = Gtk.LinkButton("http://alioth.debian.org/projects/reportbug";,
                               "Homepage of reportbug project")
         vbox.pack_start(link, expand=False)
         return vbox
@@ -640,13 +640,13 @@ class GetStringPage(Page):
         self.entry.grab_focus()
 
     def create_widget(self):
-        vbox = gtk.VBox(spacing=12)
-        self.label = gtk.Label()
+        vbox = Gtk.VBox(spacing=12)
+        self.label = Gtk.Label()
         self.label.set_line_wrap(True)
         self.label.set_justify(gtk.JUSTIFY_FILL)
         self.label.set_selectable(True)
         self.label.set_property("can-focus", False)
-        self.entry = gtk.Entry()
+        self.entry = Gtk.Entry()
         vbox.pack_start(self.label, expand=False)
         vbox.pack_start(self.entry, expand=False)
         return vbox
@@ -665,8 +665,8 @@ class GetStringPage(Page):
 
         if options:
             options.sort()
-            completion = gtk.EntryCompletion()
-            model = gtk.ListStore(str)
+            completion = Gtk.EntryCompletion()
+            model = Gtk.ListStore(str)
             for option in options:
                 model.append([option])
             completion.set_model(model)
@@ -691,15 +691,15 @@ class GetMultilinePage(Page):
         self.view.grab_focus()
 
     def create_widget(self):
-        vbox = gtk.VBox(spacing=12)
-        self.label = gtk.Label()
+        vbox = Gtk.VBox(spacing=12)
+        self.label = Gtk.Label()
         self.label.set_line_wrap(True)
         self.label.set_justify(gtk.JUSTIFY_FILL)
         self.label.set_selectable(True)
         self.label.set_property("can-focus", False)
         vbox.pack_start(self.label, expand=False)
 
-        self.view = gtk.TextView()
+        self.view = Gtk.TextView()
         self.buffer = view.get_buffer()
         scrolled = create_scrollable(self.view)
         vbox.pack_start(scrolled)
@@ -754,27 +754,27 @@ class GetListPage(TreePage):
     value_column = 0
 
     def create_widget(self):
-        vbox = gtk.VBox(spacing=12)
-        self.label = gtk.Label()
+        vbox = Gtk.VBox(spacing=12)
+        self.label = Gtk.Label()
         self.label.set_line_wrap(True)
         self.label.set_justify(gtk.JUSTIFY_FILL)
         vbox.pack_start(self.label, expand=False)
 
-        hbox = gtk.HBox(spacing=6)
+        hbox = Gtk.HBox(spacing=6)
 
-        self.view = gtk.TreeView()
+        self.view = Gtk.TreeView()
         self.view.set_rules_hint(True)
         self.view.get_selection().set_mode(gtk.SELECTION_MULTIPLE)
         scrolled = create_scrollable(self.view)
         hbox.pack_start(scrolled)
 
-        bbox = gtk.VButtonBox()
+        bbox = Gtk.VButtonBox()
         bbox.set_spacing(6)
         bbox.set_layout(gtk.BUTTONBOX_START)
-        button = gtk.Button(stock=gtk.STOCK_ADD)
+        button = Gtk.Button(stock=Gtk.STOCK_ADD)
         button.connect('clicked', self.on_add)
         bbox.pack_start(button, expand=False)
-        button = gtk.Button(stock=gtk.STOCK_REMOVE)
+        button = Gtk.Button(stock=Gtk.STOCK_REMOVE)
         button.connect('clicked', self.on_remove)
         bbox.pack_start(button, expand=False)
         hbox.pack_start(bbox, expand=False)
@@ -812,19 +812,19 @@ class GetListPage(TreePage):
 
         GLib.idle_add(self.label.set_text, prompt)
 
-        self.model = gtk.ListStore(str)
+        self.model = Gtk.ListStore(str)
         self.model.connect('row-changed', self.validate)
         self.view.set_model(self.model)
 
         self.selection.set_mode(gtk.SELECTION_MULTIPLE)
 
-        self.view.append_column(gtk.TreeViewColumn('Item', gtk.CellRendererText(), text=0))
+        self.view.append_column(Gtk.TreeViewColumn('Item', Gtk.CellRendererText(), text=0))
 
 
-class WrapRendererText(gtk.CellRendererText):
+class WrapRendererText(Gtk.CellRendererText):
     def do_render(self, cr, widget, background_area, cell_area, flags):
         self.set_property('wrap-width', cell_area.width)
-        gtk.CellRendererText.do_render(self, cr, widget, background_area, cell_area, flags)
+        Gtk.CellRendererText.do_render(self, cr, widget, background_area, cell_area, flags)
 
 
 GObject.type_register(WrapRendererText)
@@ -834,13 +834,13 @@ class MenuPage(TreePage):
     value_column = 0
 
     def create_widget(self):
-        vbox = gtk.VBox(spacing=12)
-        self.label = gtk.Label()
+        vbox = Gtk.VBox(spacing=12)
+        self.label = Gtk.Label()
         self.label.set_line_wrap(True)
         self.label.set_justify(gtk.JUSTIFY_FILL)
         vbox.pack_start(self.label, expand=False)
 
-        self.view = gtk.TreeView()
+        self.view = Gtk.TreeView()
         self.view.set_rules_hint(True)
         scrolled = create_scrollable(self.view)
         scrolled.set_policy(gtk.POLICY_NEVER, gtk.POLICY_ALWAYS)
@@ -856,17 +856,17 @@ class MenuPage(TreePage):
                 order=None, extras=None, multiple=False):
         GLib.idle_add(self.label.set_text, par)
 
-        self.model = gtk.ListStore(str, str)
+        self.model = Gtk.ListStore(str, str)
         self.view.set_model(self.model)
 
         if multiple:
             self.selection.set_mode(gtk.SELECTION_MULTIPLE)
 
-        self.view.append_column(gtk.TreeViewColumn('Option', gtk.CellRendererText(), markup=0))
+        self.view.append_column(Gtk.TreeViewColumn('Option', Gtk.CellRendererText(), markup=0))
         rend = WrapRendererText()
         rend.set_property('wrap-mode', Pango.WrapMode.WORD)
         rend.set_property('wrap-width', 300)
-        self.view.append_column(gtk.TreeViewColumn('Description', rend, text=1))
+        self.view.append_column(Gtk.TreeViewColumn('Description', rend, text=1))
 
         default_iter = None
         # here below, 'text' is the value of the description of the item, but
@@ -972,10 +972,9 @@ class HandleBTSQueryPage(TreePage):
         self.entry.grab_focus()
 
     def create_widget(self):
-        vbox = gtk.VBox(spacing=6)
-        self.label = gtk.Label("List of bugs. Select a bug to retrieve and submit more information.")
+        vbox = Gtk.VBox(spacing=6)
+        self.label = Gtk.Label("List of bugs. Select a bug to retrieve and submit more information.")
         vbox.pack_start(self.label, expand=False, padding=6)
-
         hbox = gtk.HBox(spacing=6)
         label = gtk.Label("Filter:")
         hbox.pack_start(label, expand=False)
@@ -988,18 +987,18 @@ class HandleBTSQueryPage(TreePage):
         hbox.pack_start(button, expand=False)
         vbox.pack_start(hbox, expand=False)
 
-        self.view = gtk.TreeView()
+        self.view = Gtk.TreeView()
         self.view.set_rules_hint(True)
         scrolled = create_scrollable(self.view)
         self.columns = ['ID', 'Tag', 'Package', 'Description', 'Status', 'Submitter', 'Date', 'Severity', 'Version',
                         'Filed date', 'Modified date']
         for col in zip(self.columns, list(range(len(self.columns)))):
-            column = gtk.TreeViewColumn(col[0], gtk.CellRendererText(), text=col[1])
+            column = Gtk.TreeViewColumn(col[0], Gtk.CellRendererText(), text=col[1])
             column.set_reorderable(True)
             self.view.append_column(column)
         vbox.pack_start(scrolled)
 
-        button = gtk.Button("Retrieve and submit bug information")
+        button = Gtk.Button("Retrieve and submit bug information")
         button.set_image(Gtk.Image.new_from_stock(Gtk.STOCK_INFO, Gtk.IconSize.BUTTON))
         button.connect('clicked', self.on_retrieve_info)
         vbox.pack_start(button, expand=False)
@@ -1066,7 +1065,7 @@ class HandleBTSQueryPage(TreePage):
     def execute(self, buglist, sectitle):
         GLib.idle_add(self.label.set_text, "%s. Double-click a bug to retrieve and submit more information." % sectitle)
 
-        self.model = gtk.TreeStore(*([str] * len(self.columns)))
+        self.model = Gtk.TreeStore(*([str] * len(self.columns)))
         for category in buglist:
             row = [None] * len(self.columns)
             row[3] = category[0]
@@ -1116,7 +1115,7 @@ class DisplayReportPage(Page):
     default_complete = True
 
     def create_widget(self):
-        self.view = gtk.TextView()
+        self.view = Gtk.TextView()
         self.view.set_editable(False)
         scrolled = create_scrollable(self.view)
         return scrolled
@@ -1132,12 +1131,12 @@ class LongMessagePage(Page):
     default_complete = True
 
     def create_widget(self):
-        self.label = gtk.Label()
+        self.label = Gtk.Label()
         self.label.set_line_wrap(True)
         self.label.set_justify(gtk.JUSTIFY_FILL)
         self.label.set_selectable(True)
         self.label.set_property("can-focus", False)
-        eb = gtk.EventBox()
+        eb = Gtk.EventBox()
         eb.add(self.label)
         return eb
 
@@ -1179,8 +1178,8 @@ class EditorPage(Page):
         scrolled = create_scrollable(self.view)
         vbox.pack_start(scrolled)
 
-        expander = gtk.Expander("Other system information")
-        view = gtk.TextView()
+        expander = Gtk.Expander("Other system information")
+        view = Gtk.TextView()
         view.set_editable(False)
         self.others_buffer = view.get_buffer()
         scrolled = create_scrollable(view)
@@ -1188,8 +1187,8 @@ class EditorPage(Page):
         vbox.pack_start(expander, False)
 
         if not has_spell:
-            box = gtk.EventBox()
-            label = gtk.Label("Please install <b>python-gtkspellcheck</b> to enable spell checking")
+            box = Gtk.EventBox()
+            label = Gtk.Label("Please install <b>python-gtkspellcheck</b> to enable spell checking")
             label.set_use_markup(True)
             label.set_line_wrap(True)
             label.set_selectable(True)
@@ -1251,10 +1250,10 @@ class SelectOptionsPage(Page):
     default_complete = False
 
     def create_widget(self):
-        self.label = gtk.Label()
+        self.label = Gtk.Label()
         self.label.set_line_wrap(True)
         self.label.set_justify(gtk.JUSTIFY_FILL)
-        self.vbox = gtk.VBox(spacing=6)
+        self.vbox = Gtk.VBox(spacing=6)
         self.vbox.pack_start(self.label, expand=False, padding=6)
         self.default = None
         return self.vbox
@@ -1290,18 +1289,18 @@ class SelectOptionsPage(Page):
                 continue
             # stdout is a textview for us
             if 'Print message to stdout' in desc:
-                button = gtk.Button("Display message in a text view")
+                button = Gtk.Button("Display message in a text view")
                 button.connect('clicked', self.on_display_clicked)
                 buttons.append(button)
             else:
-                button = gtk.Button()
-                label = gtk.Label(options[menuopt.lower()])
+                button = Gtk.Button()
+                label = Gtk.Label(options[menuopt.lower()])
                 button.add(label)
                 button.connect('clicked', self.on_clicked, menuopt.lower())
                 if menuopt.isupper():
                     label.set_markup("<b>%s</b>" % label.get_text())
                     self.default = button
-                    buttons.insert(0, gtk.HSeparator())
+                    buttons.insert(0, Gtk.HSeparator())
                     buttons.insert(0, button)
                 else:
                     buttons.append(button)
@@ -1316,7 +1315,7 @@ class SystemPage(Page):
     default_complete = False
 
     def create_widget(self):
-        hbox = gtk.HBox()
+        hbox = Gtk.HBox()
 
         self.terminal = Vte.Terminal()
         self.terminal.set_cursor_blinks(True)
@@ -1324,7 +1323,7 @@ class SystemPage(Page):
         self.terminal.connect('child-exited', self.on_child_exited)
         hbox.pack_start(self.terminal)
 
-        scrollbar = gtk.VScrollbar()
+        scrollbar = Gtk.VScrollbar()
         scrollbar.set_adjustment(self.terminal.get_adjustment())
         hbox.pack_start(scrollbar)
 
@@ -1339,18 +1338,18 @@ class SystemPage(Page):
 
 
 class ProgressPage(Page):
-    page_type = gtk.ASSISTANT_PAGE_PROGRESS
+    page_type = Gtk.AssistantPageType.PROGRESS
 
     def pulse(self):
         self.progress.pulse()
         return True
 
     def create_widget(self):
-        vbox = gtk.VBox(spacing=6)
-        self.label = gtk.Label()
+        vbox = Gtk.VBox(spacing=6)
+        self.label = Gtk.Label()
         self.label.set_line_wrap(True)
         self.label.set_justify(gtk.JUSTIFY_FILL)
-        self.progress = gtk.ProgressBar()
+        self.progress = Gtk.ProgressBar()
         self.progress.set_pulse_step(0.01)
         vbox.pack_start(self.label, expand=False)
         vbox.pack_start(self.progress, expand=False)
@@ -1364,9 +1363,9 @@ class ProgressPage(Page):
         self.set_label("This operation may take a while")
 
 
-class ReportbugAssistant(gtk.Assistant):
+class ReportbugAssistant(Gtk.Assistant):
     def __init__(self, application):
-        gtk.Assistant.__init__(self)
+        Gtk.Assistant.__init__(self)
         self.application = application
 
         self.set_title('Reportbug')
@@ -1383,7 +1382,7 @@ class ReportbugAssistant(gtk.Assistant):
         # This is a real hack for two reasons:
         # 1. There's no other way to access action area but inspecting the assistant and searching for the back button
         # 2. Hide back button on show, because it can be shown-hidden by the assistant depending on the page
-        if isinstance(widget, gtk.Button):
+        if isinstance(widget, Gtk.Button):
             if widget.get_label() == 'gtk-go-back':
                 widget.connect('show', self.on_back_show)
                 return
@@ -1402,7 +1401,7 @@ class ReportbugAssistant(gtk.Assistant):
                 widget.set_image(image)
                 return
 
-        if isinstance(widget, gtk.Container):
+        if isinstance(widget, Gtk.Container):
             widget.forall(self._hack_buttons)
 
     def hack_buttons(self):
@@ -1596,8 +1595,8 @@ Falling back to 'text' interface."""
         dialog.set_markup(message % "<b>gir1.2-vte-2.91</b>")
         dialog.run()
         dialog.destroy()
-        while gtk.events_pending():
-            gtk.main_iteration()
+        while Gtk.events_pending():
+            Gtk.main_iteration()
         if not sys.stdout.isatty():
             os.execlp('x-terminal-emulator', 'x-terminal-emulator', '-e', 'reportbug -u text')
         return False
@@ -1607,7 +1606,7 @@ Falling back to 'text' interface."""
     sys.excepthook = ExceptionDialog.create_excepthook(oldhook)
 
     # GTK settings
-    gtk.Window.set_default_icon_from_file(DEBIAN_LOGO)
+    Gtk.Window.set_default_icon_from_file(DEBIAN_LOGO)
 
     application = ReportbugApplication()
     assistant = ReportbugAssistant(application)
-- 
2.11.0

>From 791c9147731e5c8b7cfa42341dec21dc347e39f2 Mon Sep 17 00:00:00 2001
From: Simon McVittie <[email protected]>
Date: Wed, 14 Dec 2016 16:27:55 +0000
Subject: [PATCH 16/21] gtk2_ui: pack widgets using positional parameters

Because PyGI's API is generated programmatically from the C API, it
doesn't have the special case for keyword arguments that PyGTK did.
---
 reportbug/ui/gtk2_ui.py | 119 ++++++++++++++++++++++++------------------------
 1 file changed, 60 insertions(+), 59 deletions(-)

diff --git a/reportbug/ui/gtk2_ui.py b/reportbug/ui/gtk2_ui.py
index 646a356..facc625 100644
--- a/reportbug/ui/gtk2_ui.py
+++ b/reportbug/ui/gtk2_ui.py
@@ -140,24 +140,24 @@ class CustomDialog(Gtk.Dialog):
 
         vbox = Gtk.VBox(spacing=10)
         vbox.set_border_width(6)
-        self.vbox.pack_start(vbox)
+        self.vbox.pack_start(vbox, True, True, 0)
 
         # The header image + label
         hbox = Gtk.HBox(spacing=10)
-        vbox.pack_start(hbox, expand=False)
+        vbox.pack_start(hbox, False, True, 0)
 
         align = Gtk.Alignment(0.5, 0.5, 1.0, 1.0)
-        hbox.pack_start(align, expand=False)
+        hbox.pack_start(align, False, True, 0)
 
         image = Gtk.Image.new_from_stock(stock_image, Gtk.IconSize.DIALOG)
-        hbox.pack_start(image)
+        hbox.pack_start(image, True, True, 0)
 
         label = Gtk.Label(message)
         label.set_line_wrap(True)
         label.set_justify(gtk.JUSTIFY_FILL)
         label.set_selectable(True)
         label.set_property("can-focus", False)
-        hbox.pack_start(label, expand=False)
+        hbox.pack_start(label, False, True, 0)
 
         self.setup_dialog(vbox, *args, **kwargs)
 
@@ -170,7 +170,7 @@ class InputStringDialog(CustomDialog):
 
     def setup_dialog(self, vbox):
         self.entry = Gtk.Entry()
-        vbox.pack_start(self.entry, expand=False)
+        vbox.pack_start(self.entry, False, True, 0)
 
     def get_value(self):
         return self.entry.get_text()
@@ -201,7 +201,7 @@ class ExceptionDialog(CustomDialog):
     def setup_dialog(self, vbox, tb):
         # The traceback
         expander = Gtk.Expander("More details")
-        vbox.pack_start(expander, True)
+        vbox.pack_start(expander, True, True, 0)
 
         view = Gtk.TextView()
         view.set_editable(False)
@@ -230,7 +230,7 @@ class ReportViewerDialog(Gtk.Dialog):
 
         view = Gtk.TextView()
         view.get_buffer().set_text(self.message)
-        self.vbox.pack_start(create_scrollable(view))
+        self.vbox.pack_start(create_scrollable(view), True, True, 0)
 
         self.show_all()
 
@@ -371,11 +371,11 @@ class BugPage(Gtk.EventBox, threading.Thread):
         self.bug_status = None
 
         vbox = Gtk.VBox(spacing=12)
-        vbox.pack_start(gtk.Label("Retrieving bug information."), expand=False)
+        vbox.pack_start(Gtk.Label("Retrieving bug information."), False, True, 0)
 
         self.progress = Gtk.ProgressBar()
         self.progress.set_pulse_step(0.01)
-        vbox.pack_start(self.progress, expand=False)
+        vbox.pack_start(self.progress, False, True, 0)
 
         self.add(vbox)
 
@@ -416,7 +416,7 @@ class BugPage(Gtk.EventBox, threading.Thread):
         label = Gtk.Label('Description: ' + desc)
         label.set_line_wrap(True)
         label.set_justify(gtk.JUSTIFY_FILL)
-        vbox.pack_start(label, expand=False)
+        vbox.pack_start(label, False, True, 0)
 
         views = Gtk.VBox()
         odd = False
@@ -426,21 +426,21 @@ class BugPage(Gtk.EventBox, threading.Thread):
             view.get_buffer().set_text(body)
             if odd:
                 view.set_state(gtk.STATE_PRELIGHT)
-            views.pack_start(view, False)
+            views.pack_start(view, False, True, 0)
             odd = not odd
         scrolled = create_scrollable(views, True)
-        vbox.pack_start(scrolled)
+        vbox.pack_start(scrolled, True, True, 0)
 
         bbox = Gtk.HButtonBox()
         button = Gtk.Button("Open in browser")
         button.connect('clicked', self.on_open_browser)
-        bbox.pack_start(button)
+        bbox.pack_start(button, True, True, 0)
         if not self.queryonly:
             button = Gtk.Button("Reply")
             button.set_image(Gtk.Image.new_from_stock(Gtk.STOCK_EDIT, Gtk.IconSize.BUTTON))
             button.connect('clicked', self.on_reply)
-            bbox.pack_start(button)
-        vbox.pack_start(bbox, expand=False)
+            bbox.pack_start(button, True, True, 0)
+        vbox.pack_start(bbox, False, True, 0)
 
         self.add(vbox)
         self.show_all()
@@ -467,7 +467,7 @@ class BugsDialog(Gtk.Dialog):
         self.queryonly = queryonly
         self.application = assistant.application
         self.notebook = Gtk.Notebook()
-        self.vbox.pack_start(self.notebook)
+        self.vbox.pack_start(self.notebook, True, True, 0)
         self.connect('response', self.on_response)
         self.set_default_size(600, 600)
 
@@ -627,11 +627,11 @@ This wizard will guide you through the bug reporting process step by step.
         label.set_use_markup(True)
         label.set_line_wrap(True)
         label.set_justify(gtk.JUSTIFY_FILL)
-        vbox.pack_start(label, expand=False)
+        vbox.pack_start(label, False, True, 0)
 
         link = Gtk.LinkButton("http://alioth.debian.org/projects/reportbug";,
                               "Homepage of reportbug project")
-        vbox.pack_start(link, expand=False)
+        vbox.pack_start(link, False, True, 0)
         return vbox
 
 
@@ -647,8 +647,8 @@ class GetStringPage(Page):
         self.label.set_selectable(True)
         self.label.set_property("can-focus", False)
         self.entry = Gtk.Entry()
-        vbox.pack_start(self.label, expand=False)
-        vbox.pack_start(self.entry, expand=False)
+        vbox.pack_start(self.label, False, True, 0)
+        vbox.pack_start(self.entry, False, True, 0)
         return vbox
 
     def connect_signals(self):
@@ -697,12 +697,12 @@ class GetMultilinePage(Page):
         self.label.set_justify(gtk.JUSTIFY_FILL)
         self.label.set_selectable(True)
         self.label.set_property("can-focus", False)
-        vbox.pack_start(self.label, expand=False)
+        vbox.pack_start(self.label, False, True, 0)
 
         self.view = Gtk.TextView()
         self.buffer = view.get_buffer()
         scrolled = create_scrollable(self.view)
-        vbox.pack_start(scrolled)
+        vbox.pack_start(scrolled, True, True, 0)
         return vbox
 
     def connect_signals(self):
@@ -758,7 +758,7 @@ class GetListPage(TreePage):
         self.label = Gtk.Label()
         self.label.set_line_wrap(True)
         self.label.set_justify(gtk.JUSTIFY_FILL)
-        vbox.pack_start(self.label, expand=False)
+        vbox.pack_start(self.label, False, True, 0)
 
         hbox = Gtk.HBox(spacing=6)
 
@@ -766,20 +766,20 @@ class GetListPage(TreePage):
         self.view.set_rules_hint(True)
         self.view.get_selection().set_mode(gtk.SELECTION_MULTIPLE)
         scrolled = create_scrollable(self.view)
-        hbox.pack_start(scrolled)
+        hbox.pack_start(scrolled, True, True, 0)
 
         bbox = Gtk.VButtonBox()
         bbox.set_spacing(6)
         bbox.set_layout(gtk.BUTTONBOX_START)
         button = Gtk.Button(stock=Gtk.STOCK_ADD)
         button.connect('clicked', self.on_add)
-        bbox.pack_start(button, expand=False)
+        bbox.pack_start(button, False, True, 0)
         button = Gtk.Button(stock=Gtk.STOCK_REMOVE)
         button.connect('clicked', self.on_remove)
-        bbox.pack_start(button, expand=False)
-        hbox.pack_start(bbox, expand=False)
+        bbox.pack_start(button, False, True, 0)
+        hbox.pack_start(bbox, False, True, 0)
 
-        vbox.pack_start(hbox)
+        vbox.pack_start(hbox, True, True, 0)
         return vbox
 
     def get_value(self):
@@ -838,13 +838,13 @@ class MenuPage(TreePage):
         self.label = Gtk.Label()
         self.label.set_line_wrap(True)
         self.label.set_justify(gtk.JUSTIFY_FILL)
-        vbox.pack_start(self.label, expand=False)
+        vbox.pack_start(self.label, False, True, 0)
 
         self.view = Gtk.TreeView()
         self.view.set_rules_hint(True)
         scrolled = create_scrollable(self.view)
         scrolled.set_policy(gtk.POLICY_NEVER, gtk.POLICY_ALWAYS)
-        vbox.pack_start(scrolled)
+        vbox.pack_start(scrolled, True, True, 0)
         vbox.show_all()
         return vbox
 
@@ -974,18 +974,19 @@ class HandleBTSQueryPage(TreePage):
     def create_widget(self):
         vbox = Gtk.VBox(spacing=6)
         self.label = Gtk.Label("List of bugs. Select a bug to retrieve and submit more information.")
-        vbox.pack_start(self.label, expand=False, padding=6)
-        hbox = gtk.HBox(spacing=6)
-        label = gtk.Label("Filter:")
-        hbox.pack_start(label, expand=False)
-        self.entry = gtk.Entry()
-        hbox.pack_start(self.entry)
-        button = gtk.Button()
+        vbox.pack_start(self.label, False, True, 6)
+
+        hbox = Gtk.HBox(spacing=6)
+        label = Gtk.Label("Filter:")
+        hbox.pack_start(label, False, True, 0)
+        self.entry = Gtk.Entry()
+        hbox.pack_start(self.entry, True, True, 0)
+        button = Gtk.Button()
         button.set_image(Gtk.Image.new_from_stock(Gtk.STOCK_CLEAR, Gtk.IconSize.MENU))
         button.set_relief(gtk.RELIEF_NONE)
         button.connect('clicked', self.on_filter_clear)
-        hbox.pack_start(button, expand=False)
-        vbox.pack_start(hbox, expand=False)
+        hbox.pack_start(button, False, True, 0)
+        vbox.pack_start(hbox, False, True, 0)
 
         self.view = Gtk.TreeView()
         self.view.set_rules_hint(True)
@@ -996,12 +997,12 @@ class HandleBTSQueryPage(TreePage):
             column = Gtk.TreeViewColumn(col[0], Gtk.CellRendererText(), text=col[1])
             column.set_reorderable(True)
             self.view.append_column(column)
-        vbox.pack_start(scrolled)
+        vbox.pack_start(scrolled, True, True, 0)
 
         button = Gtk.Button("Retrieve and submit bug information")
         button.set_image(Gtk.Image.new_from_stock(Gtk.STOCK_INFO, Gtk.IconSize.BUTTON))
         button.connect('clicked', self.on_retrieve_info)
-        vbox.pack_start(button, expand=False)
+        vbox.pack_start(button, False, True, 0)
         return vbox
 
     def connect_signals(self):
@@ -1162,21 +1163,21 @@ class FinalMessagePage(LongMessagePage):
 
 class EditorPage(Page):
     def create_widget(self):
-        vbox = gtk.VBox(spacing=6)
-        hbox = gtk.HBox(spacing=12)
-        hbox.pack_start(gtk.Label("Subject: "), expand=False)
-        self.subject = gtk.Entry()
-        hbox.pack_start(self.subject)
-        vbox.pack_start(hbox, expand=False)
-
-        self.view = gtk.TextView()
+        vbox = Gtk.VBox(spacing=6)
+        hbox = Gtk.HBox(spacing=12)
+        hbox.pack_start(Gtk.Label("Subject: "), False, True, 0)
+        self.subject = Gtk.Entry()
+        hbox.pack_start(self.subject, True, True, 0)
+        vbox.pack_start(hbox, False, True, 0)
+
+        self.view = Gtk.TextView()
         self.view.modify_font(Pango.FontDescription("Monospace"))
         self.view.set_wrap_mode(gtk.WRAP_WORD)
         if has_spell:
             gtkspellcheck.SpellChecker(self.view)
         self.info_buffer = self.view.get_buffer()
         scrolled = create_scrollable(self.view)
-        vbox.pack_start(scrolled)
+        vbox.pack_start(scrolled, True, True, 0)
 
         expander = Gtk.Expander("Other system information")
         view = Gtk.TextView()
@@ -1184,7 +1185,7 @@ class EditorPage(Page):
         self.others_buffer = view.get_buffer()
         scrolled = create_scrollable(view)
         expander.add(scrolled)
-        vbox.pack_start(expander, False)
+        vbox.pack_start(expander, False, True, 0)
 
         if not has_spell:
             box = Gtk.EventBox()
@@ -1196,7 +1197,7 @@ class EditorPage(Page):
             box.add(label)
             box.modify_bg(gtk.STATE_NORMAL, self.WARNING_COLOR)
             box.connect('button-press-event', lambda *args: box.destroy())
-            vbox.pack_start(box, False)
+            vbox.pack_start(box, False, True, 0)
         return vbox
 
     def switch_out(self):
@@ -1254,7 +1255,7 @@ class SelectOptionsPage(Page):
         self.label.set_line_wrap(True)
         self.label.set_justify(gtk.JUSTIFY_FILL)
         self.vbox = Gtk.VBox(spacing=6)
-        self.vbox.pack_start(self.label, expand=False, padding=6)
+        self.vbox.pack_start(self.label, False, True, 6)
         self.default = None
         return self.vbox
 
@@ -1306,7 +1307,7 @@ class SelectOptionsPage(Page):
                     buttons.append(button)
 
         for button in buttons:
-            self.vbox.pack_start(button, expand=False)
+            self.vbox.pack_start(button, False, True, 0)
 
         self.vbox.show_all()
 
@@ -1321,11 +1322,11 @@ class SystemPage(Page):
         self.terminal.set_cursor_blinks(True)
         self.terminal.set_emulation("xterm")
         self.terminal.connect('child-exited', self.on_child_exited)
-        hbox.pack_start(self.terminal)
+        hbox.pack_start(self.terminal, True, True, 0)
 
         scrollbar = Gtk.VScrollbar()
         scrollbar.set_adjustment(self.terminal.get_adjustment())
-        hbox.pack_start(scrollbar)
+        hbox.pack_start(scrollbar, True, True, 0)
 
         return hbox
 
@@ -1351,8 +1352,8 @@ class ProgressPage(Page):
         self.label.set_justify(gtk.JUSTIFY_FILL)
         self.progress = Gtk.ProgressBar()
         self.progress.set_pulse_step(0.01)
-        vbox.pack_start(self.label, expand=False)
-        vbox.pack_start(self.progress, expand=False)
+        vbox.pack_start(self.label, False, True, 0)
+        vbox.pack_start(self.progress, False, True, 0)
         GLib.timeout_add(10, self.pulse)
         return vbox
 
-- 
2.11.0

>From 3d4ba304633b5acc4e9cd4f832f019a46187da1b Mon Sep 17 00:00:00 2001
From: Simon McVittie <[email protected]>
Date: Wed, 14 Dec 2016 16:29:26 +0000
Subject: [PATCH 17/21] gtk2_ui: use more PyGI-style enums

---
 reportbug/ui/gtk2_ui.py | 56 ++++++++++++++++++++++++-------------------------
 1 file changed, 28 insertions(+), 28 deletions(-)

diff --git a/reportbug/ui/gtk2_ui.py b/reportbug/ui/gtk2_ui.py
index facc625..aad0e96 100644
--- a/reportbug/ui/gtk2_ui.py
+++ b/reportbug/ui/gtk2_ui.py
@@ -104,8 +104,8 @@ def ask_free(s):
 
 def create_scrollable(widget, with_viewport=False):
     scrolled = Gtk.ScrolledWindow()
-    scrolled.set_shadow_type(gtk.SHADOW_ETCHED_IN)
-    scrolled.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
+    scrolled.set_shadow_type(Gtk.ShadowType.ETCHED_IN)
+    scrolled.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
     if with_viewport:
         scrolled.add_with_viewport(widget)
     else:
@@ -154,7 +154,7 @@ class CustomDialog(Gtk.Dialog):
 
         label = Gtk.Label(message)
         label.set_line_wrap(True)
-        label.set_justify(gtk.JUSTIFY_FILL)
+        label.set_justify(Gtk.Justification.FILL)
         label.set_selectable(True)
         label.set_property("can-focus", False)
         hbox.pack_start(label, False, True, 0)
@@ -415,7 +415,7 @@ class BugPage(Gtk.EventBox, threading.Thread):
         vbox.set_border_width(12)
         label = Gtk.Label('Description: ' + desc)
         label.set_line_wrap(True)
-        label.set_justify(gtk.JUSTIFY_FILL)
+        label.set_justify(Gtk.Justification.FILL)
         vbox.pack_start(label, False, True, 0)
 
         views = Gtk.VBox()
@@ -537,7 +537,7 @@ class ReportbugConnector(object):
 # Assistant
 class Page(ReportbugConnector):
     next_page_num = 0
-    page_type = gtk.ASSISTANT_PAGE_CONTENT
+    page_type = Gtk.AssistantPageType.CONTENT
     default_complete = False
     side_image = DEBIAN_LOGO
     WARNING_COLOR = Gdk.color_parse("#fff8ae")
@@ -612,7 +612,7 @@ class Page(ReportbugConnector):
 
 
 class IntroPage(Page):
-    page_type = gtk.ASSISTANT_PAGE_INTRO
+    page_type = Gtk.AssistantPageType.INTRO
     default_complete = True
 
     def create_widget(self):
@@ -626,7 +626,7 @@ This wizard will guide you through the bug reporting process step by step.
 <b>Note:</b> bug reports are publicly archived(including the email address of the submitter).""")
         label.set_use_markup(True)
         label.set_line_wrap(True)
-        label.set_justify(gtk.JUSTIFY_FILL)
+        label.set_justify(Gtk.Justification.FILL)
         vbox.pack_start(label, False, True, 0)
 
         link = Gtk.LinkButton("http://alioth.debian.org/projects/reportbug";,
@@ -643,7 +643,7 @@ class GetStringPage(Page):
         vbox = Gtk.VBox(spacing=12)
         self.label = Gtk.Label()
         self.label.set_line_wrap(True)
-        self.label.set_justify(gtk.JUSTIFY_FILL)
+        self.label.set_justify(Gtk.Justification.FILL)
         self.label.set_selectable(True)
         self.label.set_property("can-focus", False)
         self.entry = Gtk.Entry()
@@ -694,7 +694,7 @@ class GetMultilinePage(Page):
         vbox = Gtk.VBox(spacing=12)
         self.label = Gtk.Label()
         self.label.set_line_wrap(True)
-        self.label.set_justify(gtk.JUSTIFY_FILL)
+        self.label.set_justify(Gtk.Justification.FILL)
         self.label.set_selectable(True)
         self.label.set_property("can-focus", False)
         vbox.pack_start(self.label, False, True, 0)
@@ -739,7 +739,7 @@ class TreePage(Page):
 
     def get_value(self):
         model, paths = self.selection.get_selected_rows()
-        multiple = self.selection.get_mode() == gtk.SELECTION_MULTIPLE
+        multiple = self.selection.get_mode() == Gtk.SelectionMode.MULTIPLE
         result = []
         for path in paths:
             value = model.get_value(model.get_iter(path), self.value_column)
@@ -757,20 +757,20 @@ class GetListPage(TreePage):
         vbox = Gtk.VBox(spacing=12)
         self.label = Gtk.Label()
         self.label.set_line_wrap(True)
-        self.label.set_justify(gtk.JUSTIFY_FILL)
+        self.label.set_justify(Gtk.Justification.FILL)
         vbox.pack_start(self.label, False, True, 0)
 
         hbox = Gtk.HBox(spacing=6)
 
         self.view = Gtk.TreeView()
         self.view.set_rules_hint(True)
-        self.view.get_selection().set_mode(gtk.SELECTION_MULTIPLE)
+        self.view.get_selection().set_mode(Gtk.SelectionMode.MULTIPLE)
         scrolled = create_scrollable(self.view)
         hbox.pack_start(scrolled, True, True, 0)
 
         bbox = Gtk.VButtonBox()
         bbox.set_spacing(6)
-        bbox.set_layout(gtk.BUTTONBOX_START)
+        bbox.set_layout(Gtk.ButtonBoxStyle.START)
         button = Gtk.Button(stock=Gtk.STOCK_ADD)
         button.connect('clicked', self.on_add)
         bbox.pack_start(button, False, True, 0)
@@ -816,7 +816,7 @@ class GetListPage(TreePage):
         self.model.connect('row-changed', self.validate)
         self.view.set_model(self.model)
 
-        self.selection.set_mode(gtk.SELECTION_MULTIPLE)
+        self.selection.set_mode(Gtk.SelectionMode.MULTIPLE)
 
         self.view.append_column(Gtk.TreeViewColumn('Item', Gtk.CellRendererText(), text=0))
 
@@ -837,13 +837,13 @@ class MenuPage(TreePage):
         vbox = Gtk.VBox(spacing=12)
         self.label = Gtk.Label()
         self.label.set_line_wrap(True)
-        self.label.set_justify(gtk.JUSTIFY_FILL)
+        self.label.set_justify(Gtk.Justification.FILL)
         vbox.pack_start(self.label, False, True, 0)
 
         self.view = Gtk.TreeView()
         self.view.set_rules_hint(True)
         scrolled = create_scrollable(self.view)
-        scrolled.set_policy(gtk.POLICY_NEVER, gtk.POLICY_ALWAYS)
+        scrolled.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.ALWAYS)
         vbox.pack_start(scrolled, True, True, 0)
         vbox.show_all()
         return vbox
@@ -860,7 +860,7 @@ class MenuPage(TreePage):
         self.view.set_model(self.model)
 
         if multiple:
-            self.selection.set_mode(gtk.SELECTION_MULTIPLE)
+            self.selection.set_mode(Gtk.SelectionMode.MULTIPLE)
 
         self.view.append_column(Gtk.TreeViewColumn('Option', Gtk.CellRendererText(), markup=0))
         rend = WrapRendererText()
@@ -911,7 +911,7 @@ class HandleBTSQueryPage(TreePage):
 
         self.queryonly = queryonly
         if queryonly:
-            self.page_type = gtk.ASSISTANT_PAGE_CONFIRM
+            self.page_type = Gtk.AssistantPageType.CONFIRM
 
         sysinfo = debbugs.SYSTEMS[bts]
         root = sysinfo.get('btsroot')
@@ -983,7 +983,7 @@ class HandleBTSQueryPage(TreePage):
         hbox.pack_start(self.entry, True, True, 0)
         button = Gtk.Button()
         button.set_image(Gtk.Image.new_from_stock(Gtk.STOCK_CLEAR, Gtk.IconSize.MENU))
-        button.set_relief(gtk.RELIEF_NONE)
+        button.set_relief(Gtk.ReliefStyle.NONE)
         button.connect('clicked', self.on_filter_clear)
         hbox.pack_start(button, False, True, 0)
         vbox.pack_start(hbox, False, True, 0)
@@ -1074,7 +1074,7 @@ class HandleBTSQueryPage(TreePage):
             for bug in category[1]:
                 self.model.append(iter, list(map(str, bug)))
 
-        self.selection.set_mode(gtk.SELECTION_MULTIPLE)
+        self.selection.set_mode(Gtk.SelectionMode.MULTIPLE)
 
         self.model.filter_text = ""
         self.filter = self.model.filter_new()
@@ -1097,7 +1097,7 @@ class ShowReportPage(Page):
 
     def sync_pre_operation(self, *args, **kwargs):
         if kwargs.get('queryonly'):
-            self.page_type = gtk.ASSISTANT_PAGE_CONFIRM
+            self.page_type = Gtk.AssistantPageType.CONFIRM
         return args, kwargs
 
     def execute(self, number, system, mirrors, http_proxy, timeout, queryonly=False, title='', archived='no', mbox_reader_cmd=None):
@@ -1134,7 +1134,7 @@ class LongMessagePage(Page):
     def create_widget(self):
         self.label = Gtk.Label()
         self.label.set_line_wrap(True)
-        self.label.set_justify(gtk.JUSTIFY_FILL)
+        self.label.set_justify(Gtk.Justification.FILL)
         self.label.set_selectable(True)
         self.label.set_property("can-focus", False)
         eb = Gtk.EventBox()
@@ -1148,12 +1148,12 @@ class LongMessagePage(Page):
         GLib.idle_add(self.label.set_text, message)
         # Reportbug should use final_message, so emulate it
         if('999999' in message):
-            self.set_page_type(gtk.ASSISTANT_PAGE_CONFIRM)
+            self.set_page_type(Gtk.AssistantPageType.CONFIRM)
             self.set_page_title("Thanks for your report")
 
 
 class FinalMessagePage(LongMessagePage):
-    page_type = gtk.ASSISTANT_PAGE_CONFIRM
+    page_type = Gtk.AssistantPageType.CONFIRM
     default_complete = True
 
     def execute(self, *args, **kwargs):
@@ -1172,7 +1172,7 @@ class EditorPage(Page):
 
         self.view = Gtk.TextView()
         self.view.modify_font(Pango.FontDescription("Monospace"))
-        self.view.set_wrap_mode(gtk.WRAP_WORD)
+        self.view.set_wrap_mode(Gtk.WrapMode.WORD)
         if has_spell:
             gtkspellcheck.SpellChecker(self.view)
         self.info_buffer = self.view.get_buffer()
@@ -1195,7 +1195,7 @@ class EditorPage(Page):
             label.set_selectable(True)
             label.set_property("can-focus", False)
             box.add(label)
-            box.modify_bg(gtk.STATE_NORMAL, self.WARNING_COLOR)
+            box.modify_bg(Gtk.StateType.NORMAL, self.WARNING_COLOR)
             box.connect('button-press-event', lambda *args: box.destroy())
             vbox.pack_start(box, False, True, 0)
         return vbox
@@ -1253,7 +1253,7 @@ class SelectOptionsPage(Page):
     def create_widget(self):
         self.label = Gtk.Label()
         self.label.set_line_wrap(True)
-        self.label.set_justify(gtk.JUSTIFY_FILL)
+        self.label.set_justify(Gtk.Justification.FILL)
         self.vbox = Gtk.VBox(spacing=6)
         self.vbox.pack_start(self.label, False, True, 6)
         self.default = None
@@ -1349,7 +1349,7 @@ class ProgressPage(Page):
         vbox = Gtk.VBox(spacing=6)
         self.label = Gtk.Label()
         self.label.set_line_wrap(True)
-        self.label.set_justify(gtk.JUSTIFY_FILL)
+        self.label.set_justify(Gtk.Justification.FILL)
         self.progress = Gtk.ProgressBar()
         self.progress.set_pulse_step(0.01)
         vbox.pack_start(self.label, False, True, 0)
-- 
2.11.0

>From e5818ec805b9720efe0e8b51230e71c9ff4e3e81 Mon Sep 17 00:00:00 2001
From: Simon McVittie <[email protected]>
Date: Wed, 14 Dec 2016 16:30:31 +0000
Subject: [PATCH 18/21] gtk2_ui: use set_state_flags instead of deprecated
 set_state

---
 reportbug/ui/gtk2_ui.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/reportbug/ui/gtk2_ui.py b/reportbug/ui/gtk2_ui.py
index aad0e96..61785bc 100644
--- a/reportbug/ui/gtk2_ui.py
+++ b/reportbug/ui/gtk2_ui.py
@@ -425,7 +425,7 @@ class BugPage(Gtk.EventBox, threading.Thread):
             view.set_editable(False)
             view.get_buffer().set_text(body)
             if odd:
-                view.set_state(gtk.STATE_PRELIGHT)
+                view.set_state_flags(Gtk.StateFlags.PRELIGHT, False)
             views.pack_start(view, False, True, 0)
             odd = not odd
         scrolled = create_scrollable(views, True)
-- 
2.11.0

>From 78e896c6c39abb3d6d6d67d7c13d6449243a1ee4 Mon Sep 17 00:00:00 2001
From: Simon McVittie <[email protected]>
Date: Wed, 14 Dec 2016 16:32:02 +0000
Subject: [PATCH 19/21] gtk2_ui: use PyGI clipboard API

clipboard_get() is a pygtkcompat shim around Gtk.Clipboard.Get(),
which has one mandatory parameter.
---
 reportbug/ui/gtk2_ui.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/reportbug/ui/gtk2_ui.py b/reportbug/ui/gtk2_ui.py
index 61785bc..88eecf4 100644
--- a/reportbug/ui/gtk2_ui.py
+++ b/reportbug/ui/gtk2_ui.py
@@ -238,7 +238,7 @@ class ReportViewerDialog(Gtk.Dialog):
         # ok Gtk.ResponseType.APPLY is ugly for Gtk.STOCK_COPY, but who cares?
         # maybe adding it as a secondary button or such is better
         if res == Gtk.ResponseType.APPLY:
-            clipboard = gtk.clipboard_get()
+            clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)
             clipboard.set_text(self.message)
         else:
             self.destroy()
-- 
2.11.0

>From b686cfc75a2f068b704a25a7995422f4550a7000 Mon Sep 17 00:00:00 2001
From: Simon McVittie <[email protected]>
Date: Wed, 14 Dec 2016 16:32:11 +0000
Subject: [PATCH 20/21] gtk2_ui: stop using pygtkcompat

---
 reportbug/ui/gtk2_ui.py | 9 ---------
 1 file changed, 9 deletions(-)

diff --git a/reportbug/ui/gtk2_ui.py b/reportbug/ui/gtk2_ui.py
index 88eecf4..2829cf0 100644
--- a/reportbug/ui/gtk2_ui.py
+++ b/reportbug/ui/gtk2_ui.py
@@ -25,15 +25,6 @@ from reportbug.exceptions import UINotImportable
 try:
     import gi
 
-    # use a PyGTK compatibility layer
-    # https://wiki.gnome.org/Projects/PyGObject/IntrospectionPorting
-    from gi import pygtkcompat
-
-    pygtkcompat.enable()
-    pygtkcompat.enable_gtk(version='3.0')
-
-    import gtk
-
     gi.require_version('GLib', '2.0')
     from gi.repository import GLib
 
-- 
2.11.0

_______________________________________________
Reportbug-maint mailing list
[email protected]
http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/reportbug-maint

Reply via email to