commit-gnuradio
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Commit-gnuradio] [gnuradio] 01/101: grc: Main window opens with pygobje


From: git
Subject: [Commit-gnuradio] [gnuradio] 01/101: grc: Main window opens with pygobject and gtk3. Still throws tons of errors.
Date: Thu, 16 Mar 2017 14:57:55 +0000 (UTC)

This is an automated email from the git hooks/post-receive script.

jcorgan pushed a commit to branch python3
in repository gnuradio.

commit e66cfa31ff52b95a9c3df27c8a1f3b02bef6db3d
Author: Seth Hitefield <address@hidden>
Date:   Mon Apr 11 22:09:16 2016 -0400

    grc: Main window opens with pygobject and gtk3. Still throws tons of errors.
---
 grc/checks.py                 |   8 +-
 grc/core/Platform.py          |   5 +-
 grc/gui/ActionHandler.py      |  26 +++---
 grc/gui/Actions.py            | 182 +++++++++++++++++++++---------------------
 grc/gui/Bars.py               |  63 ++++++++-------
 grc/gui/Block.py              |  16 ++--
 grc/gui/BlockTreeWindow.py    |  63 ++++++++-------
 grc/gui/Colors.py             |  32 +++++---
 grc/gui/Connection.py         |  12 ++-
 grc/gui/Constants.py          |   6 +-
 grc/gui/Dialogs.py            |  73 +++++++++--------
 grc/gui/DrawingArea.py        |  57 ++++++-------
 grc/gui/Element.py            |  13 ++-
 grc/gui/Executor.py           |   9 ++-
 grc/gui/FileDialogs.py        |  46 ++++++-----
 grc/gui/FlowGraph.py          |   6 +-
 grc/gui/MainWindow.py         |  55 +++++++------
 grc/gui/NotebookPage.py       |  46 ++++++-----
 grc/gui/Param.py              |  69 ++++++++--------
 grc/gui/ParserErrorsDialog.py |  29 +++----
 grc/gui/Port.py               |   8 +-
 grc/gui/PropsDialog.py        |  82 +++++++++----------
 grc/gui/Utils.py              |  19 +++--
 grc/main.py                   |   9 ++-
 24 files changed, 497 insertions(+), 437 deletions(-)

diff --git a/grc/checks.py b/grc/checks.py
index fd0e5de..cfff10e 100755
--- a/grc/checks.py
+++ b/grc/checks.py
@@ -51,10 +51,10 @@ def die(error, message):
 def check_gtk():
     try:
         warnings.filterwarnings("error")
-        import pygtk
-        pygtk.require('2.0')
-        import gtk
-        gtk.init_check()
+        import gi
+        gi.require_version('Gtk', '3.0')
+        from gi.repository import Gtk
+        Gtk.init_check()
         warnings.filterwarnings("always")
     except Exception as err:
         die(err, "Failed to initialize GTK. If you are running over ssh, "
diff --git a/grc/core/Platform.py b/grc/core/Platform.py
index 5bcf79c..dfb60ee 100644
--- a/grc/core/Platform.py
+++ b/grc/core/Platform.py
@@ -219,8 +219,9 @@ class Platform(Element):
 
         color = n.find('color') or ''
         try:
-            import gtk  # ugly but handy
-            gtk.gdk.color_parse(color)
+            import gi # ugly but handy
+            from gi.repository import Gdk
+            Gdk.color_parse(color)
         except (ValueError, ImportError):
             if color:  # no color is okay, default set in GUI
                 print >> sys.stderr, 'Warning: Can\'t parse color code "{}" 
for domain "{}" '.format(color, key)
diff --git a/grc/gui/ActionHandler.py b/grc/gui/ActionHandler.py
index 2b39079..96f7080 100644
--- a/grc/gui/ActionHandler.py
+++ b/grc/gui/ActionHandler.py
@@ -18,11 +18,12 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
MA  02110-1301, USA
 """
 
 
-import gobject
-import gtk
 import os
 import subprocess
 
+from gi.repository import Gtk
+from gi.repository import GObject
+
 from . import Dialogs, Preferences, Actions, Executor, Constants
 from .FileDialogs import (OpenFlowGraphFileDialog, SaveFlowGraphFileDialog,
                           SaveConsoleFileDialog, SaveScreenShotDialog,
@@ -33,8 +34,6 @@ from .PropsDialog import PropsDialog
 
 from ..core import ParseXML, Messages
 
-gobject.threads_init()
-
 
 class ActionHandler:
     """
@@ -85,7 +84,7 @@ class ActionHandler:
         # prevent key event stealing while the search box is active
         # .has_focus() only in newer versions 2.17+?
         # .is_focus() seems to work, but exactly the same
-        if self.main_window.btwin.search_entry.flags() & gtk.HAS_FOCUS:
+        if self.main_window.btwin.search_entry.flags() & Gtk.HAS_FOCUS:
             return False
         if not self.get_focus_flag(): return False
         return Actions.handle_key_press(event)
@@ -159,7 +158,7 @@ class ActionHandler:
             self.init = True
         elif action == Actions.APPLICATION_QUIT:
             if main.close_pages():
-                gtk.main_quit()
+                Gtk.main_quit()
                 exit(0)
         ##################################################
         # Selections
@@ -464,10 +463,10 @@ class ActionHandler:
                 selected_block = flow_graph.get_selected_block()
             if selected_block:
                 self.dialog = PropsDialog(selected_block)
-                response = gtk.RESPONSE_APPLY
-                while response == gtk.RESPONSE_APPLY:  # rerun the dialog if 
Apply was hit
+                response = Gtk.ResponseType.APPLY
+                while response == Gtk.ResponseType.APPLY:  # rerun the dialog 
if Apply was hit
                     response = self.dialog.run()
-                    if response in (gtk.RESPONSE_APPLY, gtk.RESPONSE_ACCEPT):
+                    if response in (Gtk.ResponseType.APPLY, 
Gtk.ResponseType.ACCEPT):
                         flow_graph_update()
                         
page.get_state_cache().save_new_state(flow_graph.export_data())
                         page.set_saved(False)
@@ -475,7 +474,7 @@ class ActionHandler:
                         n = page.get_state_cache().get_current_state()
                         flow_graph.import_data(n)
                         flow_graph_update()
-                    if response == gtk.RESPONSE_APPLY:
+                    if response == Gtk.ResponseType.APPLY:
                         # null action, that updates the main window
                         Actions.ELEMENT_SELECT()
                 self.dialog.destroy()
@@ -521,15 +520,18 @@ class ActionHandler:
                 
flow_graph._options_block.get_param('generate_options').set_value(args[0])
                 flow_graph_update()
         elif action == Actions.FLOW_GRAPH_OPEN:
+            # TODO: Disable opening the flowgraph
+            pass
+            '''
             file_paths = args if args else 
OpenFlowGraphFileDialog(page.get_file_path()).run()
-            if file_paths: #open a new page for each file, show only the first
+            if file_paths: # Open a new page for each file, show only the first
                 for i,file_path in enumerate(file_paths):
                     main.new_page(file_path, show=(i==0))
                     Preferences.add_recent_file(file_path)
                     main.tool_bar.refresh_submenus()
                     main.menu_bar.refresh_submenus()
                     main.vars.update_gui()
-
+            '''
         elif action == Actions.FLOW_GRAPH_OPEN_QSS_THEME:
             file_paths = OpenQSSFileDialog(self.platform.config.install_prefix 
+
                                            '/share/gnuradio/themes/').run()
diff --git a/grc/gui/Actions.py b/grc/gui/Actions.py
index 9b2af36..b2745c9 100644
--- a/grc/gui/Actions.py
+++ b/grc/gui/Actions.py
@@ -17,9 +17,11 @@ along with this program; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 """
 
-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 Preferences
 
@@ -29,7 +31,7 @@ NO_MODS_MASK = 0
 # Actions API
 ########################################################################
 _actions_keypress_dict = dict()
-_keymap = gtk.gdk.keymap_get_default()
+_keymap = Gdk.Keymap.get_default()
 _used_mods_mask = NO_MODS_MASK
 
 
@@ -47,9 +49,9 @@ def handle_key_press(event):
     _used_mods_mask = reduce(lambda x, y: x | y, [mod_mask for keyval, 
mod_mask in _actions_keypress_dict], NO_MODS_MASK)
     # extract the key value and the consumed modifiers
     keyval, egroup, level, consumed = _keymap.translate_keyboard_state(
-        event.hardware_keycode, event.state, event.group)
+        event.hardware_keycode, event.get_state(), event.group)
     # get the modifier mask and ignore irrelevant modifiers
-    mod_mask = event.state & ~consumed & _used_mods_mask
+    mod_mask = event.get_state() & ~consumed & _used_mods_mask
     # look up the keypress and call the action
     try:
         _actions_keypress_dict[(keyval, mod_mask)]()
@@ -64,7 +66,7 @@ _all_actions_list = list()
 def get_all_actions():
     return _all_actions_list
 
-_accel_group = gtk.AccelGroup()
+_accel_group = Gtk.AccelGroup()
 
 
 def get_accel_group():
@@ -91,7 +93,7 @@ class _ActionBase(object):
             accel_path = '<main>/' + self.get_name()
             self.set_accel_group(get_accel_group())
             self.set_accel_path(accel_path)
-            gtk.accel_map_add_entry(accel_path, keyval, mod_mask)
+            Gtk.AccelMap.add_entry(accel_path, keyval, mod_mask)
         self.args = None
 
     def __str__(self):
@@ -114,9 +116,9 @@ class _ActionBase(object):
         self.emit('activate')
 
 
-class Action(gtk.Action, _ActionBase):
+class Action(Gtk.Action, _ActionBase):
     """
-    A custom Action class based on gtk.Action.
+    A custom Action class based on Gtk.Action.
     Pass additional arguments such as keypresses.
     """
 
@@ -127,18 +129,18 @@ class Action(gtk.Action, _ActionBase):
 
         Args:
             key_presses: a tuple of (keyval1, mod_mask1, keyval2, mod_mask2, 
...)
-            the: regular gtk.Action parameters (defaults to None)
+            the: regular Gtk.Action parameters (defaults to None)
         """
         if name is None:
             name = label
-        gtk.Action.__init__(self, name=name, label=label, tooltip=tooltip,
+        GObject.GObject.__init__(self, name=name, label=label, tooltip=tooltip,
                             stock_id=stock_id)
         _ActionBase.__init__(self, label, keypresses)
 
 
-class ToggleAction(gtk.ToggleAction, _ActionBase):
+class ToggleAction(Gtk.ToggleAction, _ActionBase):
     """
-    A custom Action class based on gtk.ToggleAction.
+    A custom Action class based on Gtk.ToggleAction.
     Pass additional arguments such as keypresses.
     """
 
@@ -149,11 +151,11 @@ class ToggleAction(gtk.ToggleAction, _ActionBase):
 
         Args:
             key_presses: a tuple of (keyval1, mod_mask1, keyval2, mod_mask2, 
...)
-            the: regular gtk.Action parameters (defaults to None)
+            the: regular Gtk.Action parameters (defaults to None)
         """
         if name is None:
             name = label
-        gtk.ToggleAction.__init__(self, name=name, label=label,
+        GObject.GObject.__init__(self, name=name, label=label,
                                   tooltip=tooltip, stock_id=stock_id)
         _ActionBase.__init__(self, label, keypresses)
         self.preference_name = preference_name
@@ -177,84 +179,84 @@ VARIABLE_EDITOR_UPDATE = Action()
 FLOW_GRAPH_NEW = Action(
     label='_New',
     tooltip='Create a new flow graph',
-    stock_id=gtk.STOCK_NEW,
-    keypresses=(gtk.keysyms.n, gtk.gdk.CONTROL_MASK),
+    stock_id=Gtk.STOCK_NEW,
+    keypresses=(Gdk.KEY_n, Gdk.ModifierType.CONTROL_MASK),
 )
 FLOW_GRAPH_OPEN = Action(
     label='_Open',
     tooltip='Open an existing flow graph',
-    stock_id=gtk.STOCK_OPEN,
-    keypresses=(gtk.keysyms.o, gtk.gdk.CONTROL_MASK),
+    stock_id=Gtk.STOCK_OPEN,
+    keypresses=(Gdk.KEY_o, Gdk.ModifierType.CONTROL_MASK),
 )
 FLOW_GRAPH_OPEN_RECENT = Action(
     label='Open _Recent',
     tooltip='Open a recently used flow graph',
-    stock_id=gtk.STOCK_OPEN,
+    stock_id=Gtk.STOCK_OPEN,
 )
 FLOW_GRAPH_SAVE = Action(
     label='_Save',
     tooltip='Save the current flow graph',
-    stock_id=gtk.STOCK_SAVE,
-    keypresses=(gtk.keysyms.s, gtk.gdk.CONTROL_MASK),
+    stock_id=Gtk.STOCK_SAVE,
+    keypresses=(Gdk.KEY_s, Gdk.ModifierType.CONTROL_MASK),
 )
 FLOW_GRAPH_SAVE_AS = Action(
     label='Save _As',
     tooltip='Save the current flow graph as...',
-    stock_id=gtk.STOCK_SAVE_AS,
-    keypresses=(gtk.keysyms.s, gtk.gdk.CONTROL_MASK | gtk.gdk.SHIFT_MASK),
+    stock_id=Gtk.STOCK_SAVE_AS,
+    keypresses=(Gdk.KEY_s, Gdk.ModifierType.CONTROL_MASK | 
Gdk.ModifierType.SHIFT_MASK),
 )
 FLOW_GRAPH_CLOSE = Action(
     label='_Close',
     tooltip='Close the current flow graph',
-    stock_id=gtk.STOCK_CLOSE,
-    keypresses=(gtk.keysyms.w, gtk.gdk.CONTROL_MASK),
+    stock_id=Gtk.STOCK_CLOSE,
+    keypresses=(Gdk.KEY_w, Gdk.ModifierType.CONTROL_MASK),
 )
 APPLICATION_INITIALIZE = Action()
 APPLICATION_QUIT = Action(
     label='_Quit',
     tooltip='Quit program',
-    stock_id=gtk.STOCK_QUIT,
-    keypresses=(gtk.keysyms.q, gtk.gdk.CONTROL_MASK),
+    stock_id=Gtk.STOCK_QUIT,
+    keypresses=(Gdk.KEY_q, Gdk.ModifierType.CONTROL_MASK),
 )
 FLOW_GRAPH_UNDO = Action(
     label='_Undo',
     tooltip='Undo a change to the flow graph',
-    stock_id=gtk.STOCK_UNDO,
-    keypresses=(gtk.keysyms.z, gtk.gdk.CONTROL_MASK),
+    stock_id=Gtk.STOCK_UNDO,
+    keypresses=(Gdk.KEY_z, Gdk.ModifierType.CONTROL_MASK),
 )
 FLOW_GRAPH_REDO = Action(
     label='_Redo',
     tooltip='Redo a change to the flow graph',
-    stock_id=gtk.STOCK_REDO,
-    keypresses=(gtk.keysyms.y, gtk.gdk.CONTROL_MASK),
+    stock_id=Gtk.STOCK_REDO,
+    keypresses=(Gdk.KEY_y, Gdk.ModifierType.CONTROL_MASK),
 )
 NOTHING_SELECT = Action()
 SELECT_ALL = Action(
     label='Select _All',
     tooltip='Select all blocks and connections in the flow graph',
-    stock_id=gtk.STOCK_SELECT_ALL,
-    keypresses=(gtk.keysyms.a, gtk.gdk.CONTROL_MASK),
+    stock_id=Gtk.STOCK_SELECT_ALL,
+    keypresses=(Gdk.KEY_a, Gdk.ModifierType.CONTROL_MASK),
 )
 ELEMENT_SELECT = Action()
 ELEMENT_CREATE = Action()
 ELEMENT_DELETE = Action(
     label='_Delete',
     tooltip='Delete the selected blocks',
-    stock_id=gtk.STOCK_DELETE,
-    keypresses=(gtk.keysyms.Delete, NO_MODS_MASK),
+    stock_id=Gtk.STOCK_DELETE,
+    keypresses=(Gdk.KEY_Delete, NO_MODS_MASK),
 )
 BLOCK_MOVE = Action()
 BLOCK_ROTATE_CCW = Action(
     label='Rotate Counterclockwise',
     tooltip='Rotate the selected blocks 90 degrees to the left',
-    stock_id=gtk.STOCK_GO_BACK,
-    keypresses=(gtk.keysyms.Left, NO_MODS_MASK),
+    stock_id=Gtk.STOCK_GO_BACK,
+    keypresses=(Gdk.KEY_Left, NO_MODS_MASK),
 )
 BLOCK_ROTATE_CW = Action(
     label='Rotate Clockwise',
     tooltip='Rotate the selected blocks 90 degrees to the right',
-    stock_id=gtk.STOCK_GO_FORWARD,
-    keypresses=(gtk.keysyms.Right, NO_MODS_MASK),
+    stock_id=Gtk.STOCK_GO_FORWARD,
+    keypresses=(Gdk.KEY_Right, NO_MODS_MASK),
 )
 BLOCK_VALIGN_TOP = Action(
     label='Vertical Align Top',
@@ -298,26 +300,26 @@ BLOCK_ALIGNMENTS = [
 BLOCK_PARAM_MODIFY = Action(
     label='_Properties',
     tooltip='Modify params for the selected block',
-    stock_id=gtk.STOCK_PROPERTIES,
-    keypresses=(gtk.keysyms.Return, NO_MODS_MASK),
+    stock_id=Gtk.STOCK_PROPERTIES,
+    keypresses=(Gdk.KEY_Return, NO_MODS_MASK),
 )
 BLOCK_ENABLE = Action(
     label='E_nable',
     tooltip='Enable the selected blocks',
-    stock_id=gtk.STOCK_CONNECT,
-    keypresses=(gtk.keysyms.e, NO_MODS_MASK),
+    stock_id=Gtk.STOCK_CONNECT,
+    keypresses=(Gdk.KEY_e, NO_MODS_MASK),
 )
 BLOCK_DISABLE = Action(
     label='D_isable',
     tooltip='Disable the selected blocks',
-    stock_id=gtk.STOCK_DISCONNECT,
-    keypresses=(gtk.keysyms.d, NO_MODS_MASK),
+    stock_id=Gtk.STOCK_DISCONNECT,
+    keypresses=(Gdk.KEY_d, NO_MODS_MASK),
 )
 BLOCK_BYPASS = Action(
     label='_Bypass',
     tooltip='Bypass the selected block',
-    stock_id=gtk.STOCK_MEDIA_FORWARD,
-    keypresses=(gtk.keysyms.b, NO_MODS_MASK),
+    stock_id=Gtk.STOCK_MEDIA_FORWARD,
+    keypresses=(Gdk.KEY_b, NO_MODS_MASK),
 )
 TOGGLE_SNAP_TO_GRID = ToggleAction(
     label='_Snap to grid',
@@ -327,8 +329,8 @@ TOGGLE_SNAP_TO_GRID = ToggleAction(
 TOGGLE_HIDE_DISABLED_BLOCKS = ToggleAction(
     label='Hide _Disabled Blocks',
     tooltip='Toggle visibility of disabled blocks and connections',
-    stock_id=gtk.STOCK_MISSING_IMAGE,
-    keypresses=(gtk.keysyms.d, gtk.gdk.CONTROL_MASK),
+    stock_id=Gtk.STOCK_MISSING_IMAGE,
+    keypresses=(Gdk.KEY_d, Gdk.ModifierType.CONTROL_MASK),
 )
 TOGGLE_HIDE_VARIABLES = ToggleAction(
     label='Hide Variables',
@@ -376,42 +378,42 @@ TOGGLE_SHOW_FLOWGRAPH_COMPLEXITY = ToggleAction(
 BLOCK_CREATE_HIER = Action(
     label='C_reate Hier',
     tooltip='Create hier block from selected blocks',
-    stock_id=gtk.STOCK_CONNECT,
-#   keypresses=(gtk.keysyms.c, NO_MODS_MASK),
+    stock_id=Gtk.STOCK_CONNECT,
+#   keypresses=(Gdk.KEY_c, NO_MODS_MASK),
 )
 BLOCK_CUT = Action(
     label='Cu_t',
     tooltip='Cut',
-    stock_id=gtk.STOCK_CUT,
-    keypresses=(gtk.keysyms.x, gtk.gdk.CONTROL_MASK),
+    stock_id=Gtk.STOCK_CUT,
+    keypresses=(Gdk.KEY_x, Gdk.ModifierType.CONTROL_MASK),
 )
 BLOCK_COPY = Action(
     label='_Copy',
     tooltip='Copy',
-    stock_id=gtk.STOCK_COPY,
-    keypresses=(gtk.keysyms.c, gtk.gdk.CONTROL_MASK),
+    stock_id=Gtk.STOCK_COPY,
+    keypresses=(Gdk.KEY_c, Gdk.ModifierType.CONTROL_MASK),
 )
 BLOCK_PASTE = Action(
     label='_Paste',
     tooltip='Paste',
-    stock_id=gtk.STOCK_PASTE,
-    keypresses=(gtk.keysyms.v, gtk.gdk.CONTROL_MASK),
+    stock_id=Gtk.STOCK_PASTE,
+    keypresses=(Gdk.KEY_v, Gdk.ModifierType.CONTROL_MASK),
 )
 ERRORS_WINDOW_DISPLAY = Action(
     label='Flowgraph _Errors',
     tooltip='View flow graph errors',
-    stock_id=gtk.STOCK_DIALOG_ERROR,
+    stock_id=Gtk.STOCK_DIALOG_ERROR,
 )
 TOGGLE_CONSOLE_WINDOW = ToggleAction(
     label='Show _Console Panel',
     tooltip='Toggle visibility of the console',
-    keypresses=(gtk.keysyms.r, gtk.gdk.CONTROL_MASK),
+    keypresses=(Gdk.KEY_c, Gdk.ModifierType.CONTROL_MASK),
     preference_name='console_window_visible'
 )
 TOGGLE_BLOCKS_WINDOW = ToggleAction(
     label='Show _Block Tree Panel',
     tooltip='Toggle visibility of the block tree widget',
-    keypresses=(gtk.keysyms.b, gtk.gdk.CONTROL_MASK),
+    keypresses=(Gdk.KEY_b, Gdk.ModifierType.CONTROL_MASK),
     preference_name='blocks_window_visible'
 )
 TOGGLE_SCROLL_LOCK = ToggleAction(
@@ -422,106 +424,106 @@ TOGGLE_SCROLL_LOCK = ToggleAction(
 ABOUT_WINDOW_DISPLAY = Action(
     label='_About',
     tooltip='About this program',
-    stock_id=gtk.STOCK_ABOUT,
+    stock_id=Gtk.STOCK_ABOUT,
 )
 HELP_WINDOW_DISPLAY = Action(
     label='_Help',
     tooltip='Usage tips',
-    stock_id=gtk.STOCK_HELP,
-    keypresses=(gtk.keysyms.F1, NO_MODS_MASK),
+    stock_id=Gtk.STOCK_HELP,
+    keypresses=(Gdk.KEY_F1, NO_MODS_MASK),
 )
 TYPES_WINDOW_DISPLAY = Action(
     label='_Types',
     tooltip='Types color mapping',
-    stock_id=gtk.STOCK_DIALOG_INFO,
+    stock_id=Gtk.STOCK_DIALOG_INFO,
 )
 FLOW_GRAPH_GEN = Action(
     label='_Generate',
     tooltip='Generate the flow graph',
-    stock_id=gtk.STOCK_CONVERT,
-    keypresses=(gtk.keysyms.F5, NO_MODS_MASK),
+    stock_id=Gtk.STOCK_CONVERT,
+    keypresses=(Gdk.KEY_F5, NO_MODS_MASK),
 )
 FLOW_GRAPH_EXEC = Action(
     label='_Execute',
     tooltip='Execute the flow graph',
-    stock_id=gtk.STOCK_MEDIA_PLAY,
-    keypresses=(gtk.keysyms.F6, NO_MODS_MASK),
+    stock_id=Gtk.STOCK_MEDIA_PLAY,
+    keypresses=(Gdk.KEY_F6, NO_MODS_MASK),
 )
 FLOW_GRAPH_KILL = Action(
     label='_Kill',
     tooltip='Kill the flow graph',
-    stock_id=gtk.STOCK_STOP,
-    keypresses=(gtk.keysyms.F7, NO_MODS_MASK),
+    stock_id=Gtk.STOCK_STOP,
+    keypresses=(Gdk.KEY_F7, NO_MODS_MASK),
 )
 FLOW_GRAPH_SCREEN_CAPTURE = Action(
     label='Screen Ca_pture',
     tooltip='Create a screen capture of the flow graph',
-    stock_id=gtk.STOCK_PRINT,
-    keypresses=(gtk.keysyms.Print, NO_MODS_MASK),
+    stock_id=Gtk.STOCK_PRINT,
+    keypresses=(Gdk.KEY_Print, NO_MODS_MASK),
 )
 PORT_CONTROLLER_DEC = Action(
-    keypresses=(gtk.keysyms.minus, NO_MODS_MASK, gtk.keysyms.KP_Subtract, 
NO_MODS_MASK),
+    keypresses=(Gdk.KEY_minus, NO_MODS_MASK, Gdk.KEY_KP_Subtract, 
NO_MODS_MASK),
 )
 PORT_CONTROLLER_INC = Action(
-    keypresses=(gtk.keysyms.plus, NO_MODS_MASK, gtk.keysyms.KP_Add, 
NO_MODS_MASK),
+    keypresses=(Gdk.KEY_plus, NO_MODS_MASK, Gdk.KEY_KP_Add, NO_MODS_MASK),
 )
 BLOCK_INC_TYPE = Action(
-    keypresses=(gtk.keysyms.Down, NO_MODS_MASK),
+    keypresses=(Gdk.KEY_Down, NO_MODS_MASK),
 )
 BLOCK_DEC_TYPE = Action(
-    keypresses=(gtk.keysyms.Up, NO_MODS_MASK),
+    keypresses=(Gdk.KEY_Up, NO_MODS_MASK),
 )
 RELOAD_BLOCKS = Action(
     label='Reload _Blocks',
     tooltip='Reload Blocks',
-    stock_id=gtk.STOCK_REFRESH
+    stock_id=Gtk.STOCK_REFRESH
 )
 FIND_BLOCKS = Action(
     label='_Find Blocks',
     tooltip='Search for a block by name (and key)',
-    stock_id=gtk.STOCK_FIND,
-    keypresses=(gtk.keysyms.f, gtk.gdk.CONTROL_MASK,
-                gtk.keysyms.slash, NO_MODS_MASK),
+    stock_id=Gtk.STOCK_FIND,
+    keypresses=(Gdk.KEY_f, Gdk.ModifierType.CONTROL_MASK,
+                Gdk.KEY_slash, NO_MODS_MASK),
 )
 CLEAR_CONSOLE = Action(
     label='_Clear Console',
     tooltip='Clear Console',
-    stock_id=gtk.STOCK_CLEAR,
+    stock_id=Gtk.STOCK_CLEAR,
 )
 SAVE_CONSOLE = Action(
     label='_Save Console',
     tooltip='Save Console',
-    stock_id=gtk.STOCK_SAVE,
+    stock_id=Gtk.STOCK_SAVE,
 )
 OPEN_HIER = Action(
     label='Open H_ier',
     tooltip='Open the source of the selected hierarchical block',
-    stock_id=gtk.STOCK_JUMP_TO,
+    stock_id=Gtk.STOCK_JUMP_TO,
 )
 BUSSIFY_SOURCES = Action(
     label='Toggle So_urce Bus',
     tooltip='Gang source ports into a single bus port',
-    stock_id=gtk.STOCK_JUMP_TO,
+    stock_id=Gtk.STOCK_JUMP_TO,
 )
 BUSSIFY_SINKS = Action(
     label='Toggle S_ink Bus',
     tooltip='Gang sink ports into a single bus port',
-    stock_id=gtk.STOCK_JUMP_TO,
+    stock_id=Gtk.STOCK_JUMP_TO,
 )
 XML_PARSER_ERRORS_DISPLAY = Action(
     label='_Parser Errors',
     tooltip='View errors that occurred while parsing XML files',
-    stock_id=gtk.STOCK_DIALOG_ERROR,
+    stock_id=Gtk.STOCK_DIALOG_ERROR,
 )
 FLOW_GRAPH_OPEN_QSS_THEME = Action(
     label='Set Default QT GUI _Theme',
     tooltip='Set a default QT Style Sheet file to use for QT GUI',
-    stock_id=gtk.STOCK_OPEN,
+    stock_id=Gtk.STOCK_OPEN,
 )
 TOOLS_RUN_FDESIGN = Action(
     label='Filter Design Tool',
     tooltip='Execute gr_filter_design',
-    stock_id=gtk.STOCK_EXECUTE,
+    stock_id=Gtk.STOCK_EXECUTE,
 )
 TOOLS_MORE_TO_COME = Action(
     label='More to come',
diff --git a/grc/gui/Bars.py b/grc/gui/Bars.py
index a4819b9..2d07093 100644
--- a/grc/gui/Bars.py
+++ b/grc/gui/Bars.py
@@ -17,9 +17,10 @@ along with this program; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 """
 
-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 . import Actions
 
@@ -62,7 +63,7 @@ TOOLBAR_LIST = (
 
 # The list of actions and categories for the menu bar.
 MENU_BAR_LIST = (
-    (gtk.Action('File', '_File', None, None), [
+    (Gtk.Action(name='File', label='_File'), [
         'flow_graph_new',
         Actions.FLOW_GRAPH_OPEN,
         'flow_graph_recent',
@@ -75,7 +76,7 @@ MENU_BAR_LIST = (
         Actions.FLOW_GRAPH_CLOSE,
         Actions.APPLICATION_QUIT,
     ]),
-    (gtk.Action('Edit', '_Edit', None, None), [
+    (Gtk.Action(name='Edit', label='_Edit'), [
         Actions.FLOW_GRAPH_UNDO,
         Actions.FLOW_GRAPH_REDO,
         None,
@@ -95,7 +96,7 @@ MENU_BAR_LIST = (
         None,
         Actions.BLOCK_PARAM_MODIFY,
     ]),
-    (gtk.Action('View', '_View', None, None), [
+    (Gtk.Action(name='View', label='_View'), [
         Actions.TOGGLE_BLOCKS_WINDOW,
         None,
         Actions.TOGGLE_CONSOLE_WINDOW,
@@ -117,12 +118,12 @@ MENU_BAR_LIST = (
         Actions.ERRORS_WINDOW_DISPLAY,
         Actions.FIND_BLOCKS,
     ]),
-    (gtk.Action('Run', '_Run', None, None), [
+    (Gtk.Action(name='Run', label='_Run'), [
         Actions.FLOW_GRAPH_GEN,
         Actions.FLOW_GRAPH_EXEC,
         Actions.FLOW_GRAPH_KILL,
     ]),
-    (gtk.Action('Tools', '_Tools', None, None), [
+    (Gtk.Action(name='Tools', label='_Tools'), [
         Actions.TOOLS_RUN_FDESIGN,
         Actions.FLOW_GRAPH_OPEN_QSS_THEME,
         None,
@@ -130,7 +131,7 @@ MENU_BAR_LIST = (
         None,
         Actions.TOOLS_MORE_TO_COME,
     ]),
-    (gtk.Action('Help', '_Help', None, None), [
+    (Gtk.Action(name='Help', label='_Help'), [
         Actions.HELP_WINDOW_DISPLAY,
         Actions.TYPES_WINDOW_DISPLAY,
         Actions.XML_PARSER_ERRORS_DISPLAY,
@@ -152,7 +153,7 @@ CONTEXT_MENU_LIST = [
     Actions.BLOCK_DISABLE,
     Actions.BLOCK_BYPASS,
     None,
-    (gtk.Action('More', '_More', None, None), [
+    (Gtk.Action(name='More', label='_More'), [
         Actions.BLOCK_CREATE_HIER,
         Actions.OPEN_HIER,
         None,
@@ -189,13 +190,13 @@ class SubMenuCreator(object):
 
     def _fill_flow_graph_new_submenu(self, action):
         """Sub menu to create flow-graph with pre-set generate mode"""
-        menu = gtk.Menu()
+        menu = Gtk.Menu()
         for key, name, default in self.generate_modes:
             if default:
                 item = Actions.FLOW_GRAPH_NEW.create_menu_item()
                 item.set_label(name)
             else:
-                item = gtk.MenuItem(name, use_underline=False)
+                item = Gtk.MenuItem(name=name, use_underline=False)
                 item.connect('activate', self.callback_adaptor, (action, key))
             menu.append(item)
         menu.show_all()
@@ -204,11 +205,11 @@ class SubMenuCreator(object):
     def _fill_flow_graph_recent_submenu(self, action):
         """menu showing recent flow-graphs"""
         import Preferences
-        menu = gtk.Menu()
+        menu = Gtk.Menu()
         recent_files = Preferences.get_recent_files()
         if len(recent_files) > 0:
             for i, file_name in enumerate(recent_files):
-                item = gtk.MenuItem("%d. %s" % (i+1, file_name), 
use_underline=False)
+                item = Gtk.MenuItem(name="%d. %s" % (i+1, file_name), 
use_underline=False)
                 item.connect('activate', self.callback_adaptor,
                              (action, file_name))
                 menu.append(item)
@@ -217,7 +218,7 @@ class SubMenuCreator(object):
         return None
 
 
-class Toolbar(gtk.Toolbar, SubMenuCreator):
+class Toolbar(Gtk.Toolbar, SubMenuCreator):
     """The gtk toolbar with actions added from the toolbar list."""
 
     def __init__(self, generate_modes, action_handler_callback):
@@ -226,23 +227,25 @@ class Toolbar(gtk.Toolbar, SubMenuCreator):
         Look up the action for each name in the action list and add it to the
         toolbar.
         """
-        gtk.Toolbar.__init__(self)
-        self.set_style(gtk.TOOLBAR_ICONS)
+        GObject.GObject.__init__(self)
+        self.set_style(Gtk.ToolbarStyle.ICONS)
         SubMenuCreator.__init__(self, generate_modes, action_handler_callback)
 
         for action in TOOLBAR_LIST:
             if isinstance(action, tuple) and isinstance(action[1], str):
                 # create a button with a sub-menu
-                action[0].set_tool_item_type(gtk.MenuToolButton)
+                # TODO: Fix later
+                #action[0].set_tool_item_type(Gtk.MenuToolButton)
                 item = action[0].create_tool_item()
-                self.create_submenu(action, item)
-                self.refresh_submenus()
+                #self.create_submenu(action, item)
+                #self.refresh_submenus()
 
             elif action is None:
-                item = gtk.SeparatorToolItem()
+                item = Gtk.SeparatorToolItem()
 
             else:
-                action.set_tool_item_type(gtk.ToolButton)
+                #TODO: Fix later
+                #action.set_tool_item_type(Gtk.ToolButton)
                 item = action.create_tool_item()
                 # this reset of the tooltip property is required
                 # (after creating the tool item) for the tooltip to show
@@ -255,14 +258,14 @@ class MenuHelperMixin(object):
 
     def _fill_menu(self, actions, menu=None):
         """Create a menu from list of actions"""
-        menu = menu or gtk.Menu()
+        menu = menu or Gtk.Menu()
         for item in actions:
             if isinstance(item, tuple):
                 menu_item = self._make_sub_menu(*item)
             elif isinstance(item, str):
                 menu_item = getattr(self, 'create_' + item)()
             elif item is None:
-                menu_item = gtk.SeparatorMenuItem()
+                menu_item = Gtk.SeparatorMenuItem()
             else:
                 menu_item = item.create_menu_item()
             menu.append(menu_item)
@@ -276,7 +279,7 @@ class MenuHelperMixin(object):
         return main
 
 
-class MenuBar(gtk.MenuBar, MenuHelperMixin, SubMenuCreator):
+class MenuBar(Gtk.MenuBar, MenuHelperMixin, SubMenuCreator):
     """The gtk menu bar with actions added from the menu bar list."""
 
     def __init__(self, generate_modes, action_handler_callback):
@@ -286,13 +289,13 @@ class MenuBar(gtk.MenuBar, MenuHelperMixin, 
SubMenuCreator):
         Look up the action for each name in the action list and add it to the
         submenu. Add the submenu to the menu bar.
         """
-        gtk.MenuBar.__init__(self)
+        GObject.GObject.__init__(self)
         SubMenuCreator.__init__(self, generate_modes, action_handler_callback)
         for main_action, actions in MENU_BAR_LIST:
             self.append(self._make_sub_menu(main_action, actions))
 
     def create_flow_graph_new(self):
-        main = gtk.ImageMenuItem(gtk.STOCK_NEW)
+        main = Gtk.ImageMenuItem(Gtk.STOCK_NEW)
         main.set_label(Actions.FLOW_GRAPH_NEW.get_label())
         func = self._fill_flow_graph_new_submenu
         self.submenus.append((Actions.FLOW_GRAPH_NEW, func, main))
@@ -300,7 +303,7 @@ class MenuBar(gtk.MenuBar, MenuHelperMixin, SubMenuCreator):
         return main
 
     def create_flow_graph_recent(self):
-        main = gtk.ImageMenuItem(gtk.STOCK_OPEN)
+        main = Gtk.ImageMenuItem(Gtk.STOCK_OPEN)
         main.set_label(Actions.FLOW_GRAPH_OPEN_RECENT.get_label())
         func = self._fill_flow_graph_recent_submenu
         self.submenus.append((Actions.FLOW_GRAPH_OPEN, func, main))
@@ -310,9 +313,9 @@ class MenuBar(gtk.MenuBar, MenuHelperMixin, SubMenuCreator):
         return main
 
 
-class ContextMenu(gtk.Menu, MenuHelperMixin):
+class ContextMenu(Gtk.Menu, MenuHelperMixin):
     """The gtk menu with actions added from the context menu list."""
 
     def __init__(self):
-        gtk.Menu.__init__(self)
+        GObject.GObject.__init__(self)
         self._fill_menu(CONTEXT_MENU_LIST, self)
diff --git a/grc/gui/Block.py b/grc/gui/Block.py
index a0a5f26..64c9e02 100644
--- a/grc/gui/Block.py
+++ b/grc/gui/Block.py
@@ -17,10 +17,10 @@ along with this program; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 """
 
-import pygtk
-pygtk.require('2.0')
-import gtk
-import pango
+import gi
+gi.require_version('Gtk', '3.0')
+from gi.repository import Gtk
+from gi.repository import Pango
 
 from . import Actions, Colors, Utils
 
@@ -202,7 +202,7 @@ class Block(Element, _Block):
 
         layouts = list()
         #create the main layout
-        layout = gtk.DrawingArea().create_pango_layout('')
+        layout = Gtk.DrawingArea().create_pango_layout('')
         layouts.append(layout)
         layout.set_markup(Utils.parse_template(BLOCK_MARKUP_TMPL, block=self, 
font=BLOCK_FONT))
         self.label_width, self.label_height = layout.get_pixel_size()
@@ -214,8 +214,8 @@ class Block(Element, _Block):
         else:
             markups = [param.get_markup() for param in self.get_params() if 
param.get_hide() not in ('all', 'part')]
         if markups:
-            layout = gtk.DrawingArea().create_pango_layout('')
-            layout.set_spacing(LABEL_SEPARATION*pango.SCALE)
+            layout = Gtk.DrawingArea().create_pango_layout('')
+            layout.set_spacing(LABEL_SEPARATION*Pango.SCALE)
             layout.set_markup('\n'.join(markups))
             layouts.append(layout)
             w, h = layout.get_pixel_size()
@@ -279,7 +279,7 @@ class Block(Element, _Block):
             complexity = calculate_flowgraph_complexity(self.get_parent())
             complexity = "Complexity: {}bal".format(num_to_str(complexity))
 
-        layout = gtk.DrawingArea().create_pango_layout('')
+        layout = Gtk.DrawingArea().create_pango_layout('')
         layout.set_markup(Utils.parse_template(COMMENT_COMPLEXITY_MARKUP_TMPL,
                                                block=self,
                                                comment=comment,
diff --git a/grc/gui/BlockTreeWindow.py b/grc/gui/BlockTreeWindow.py
index 4279e8c..a68d093 100644
--- a/grc/gui/BlockTreeWindow.py
+++ b/grc/gui/BlockTreeWindow.py
@@ -17,10 +17,11 @@ along with this program; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 """
 
-import pygtk
-pygtk.require('2.0')
-import gtk
-import gobject
+import gi
+gi.require_version('Gtk', '3.0')
+from gi.repository import Gtk
+from gi.repository import Gdk
+from gi.repository import GObject
 
 from . import Actions, Utils
 from .Constants import DEFAULT_BLOCKS_WINDOW_WIDTH, DND_TARGETS
@@ -57,7 +58,7 @@ undocumented#slurp
 CAT_MARKUP_TMPL = """Category: $cat"""
 
 
-class BlockTreeWindow(gtk.VBox):
+class BlockTreeWindow(Gtk.VBox):
     """The block selection panel."""
 
     def __init__(self, platform, get_flow_graph):
@@ -71,38 +72,38 @@ class BlockTreeWindow(gtk.VBox):
             platform: the particular platform will all block prototypes
             get_flow_graph: get the selected flow graph
         """
-        gtk.VBox.__init__(self)
+        GObject.GObject.__init__(self)
         self.platform = platform
         self.get_flow_graph = get_flow_graph
 
         # search entry
-        self.search_entry = gtk.Entry()
+        self.search_entry = Gtk.Entry()
         try:
-            self.search_entry.set_icon_from_stock(gtk.ENTRY_ICON_PRIMARY, 
gtk.STOCK_FIND)
-            self.search_entry.set_icon_activatable(gtk.ENTRY_ICON_PRIMARY, 
False)
-            self.search_entry.set_icon_from_stock(gtk.ENTRY_ICON_SECONDARY, 
gtk.STOCK_CLOSE)
+            
self.search_entry.set_icon_from_stock(Gtk.EntryIconPosition.PRIMARY, 
Gtk.STOCK_FIND)
+            
self.search_entry.set_icon_activatable(Gtk.EntryIconPosition.PRIMARY, False)
+            
self.search_entry.set_icon_from_stock(Gtk.EntryIconPosition.SECONDARY, 
Gtk.STOCK_CLOSE)
             self.search_entry.connect('icon-release', self._handle_icon_event)
         except AttributeError:
             pass  # no icon for old pygtk
         self.search_entry.connect('changed', self._update_search_tree)
         self.search_entry.connect('key-press-event', 
self._handle_search_key_press)
-        self.pack_start(self.search_entry, False)
+        self.pack_start(self.search_entry, False, False, 0)
 
         # make the tree model for holding blocks and a temporary one for 
search results
-        self.treestore = gtk.TreeStore(gobject.TYPE_STRING, 
gobject.TYPE_STRING, gobject.TYPE_STRING)
-        self.treestore_search = gtk.TreeStore(gobject.TYPE_STRING, 
gobject.TYPE_STRING, gobject.TYPE_STRING)
+        self.treestore = Gtk.TreeStore(GObject.TYPE_STRING, 
GObject.TYPE_STRING, GObject.TYPE_STRING)
+        self.treestore_search = Gtk.TreeStore(GObject.TYPE_STRING, 
GObject.TYPE_STRING, GObject.TYPE_STRING)
 
-        self.treeview = gtk.TreeView(self.treestore)
+        self.treeview = Gtk.TreeView(self.treestore)
         self.treeview.set_enable_search(False)  # disable pop up search box
         self.treeview.set_search_column(-1)  # really disable search
         self.treeview.set_headers_visible(False)
-        self.treeview.add_events(gtk.gdk.BUTTON_PRESS_MASK)
+        self.treeview.add_events(Gdk.EventMask.BUTTON_PRESS_MASK)
         self.treeview.connect('button-press-event', 
self._handle_mouse_button_press)
         self.treeview.connect('key-press-event', self._handle_search_key_press)
 
-        self.treeview.get_selection().set_mode('single')
-        renderer = gtk.CellRendererText()
-        column = gtk.TreeViewColumn('Blocks', renderer, text=NAME_INDEX)
+        self.treeview.get_selection().set_mode(Gtk.SelectionMode.SINGLE)
+        renderer = Gtk.CellRendererText()
+        column = Gtk.TreeViewColumn('Blocks', renderer, text=NAME_INDEX)
         self.treeview.append_column(column)
         # try to enable the tooltips (available in pygtk 2.12 and above)
         try:
@@ -111,16 +112,16 @@ class BlockTreeWindow(gtk.VBox):
             pass
         # setup sort order
         column.set_sort_column_id(0)
-        self.treestore.set_sort_column_id(0, gtk.SORT_ASCENDING)
+        self.treestore.set_sort_column_id(0, Gtk.SortType.ASCENDING)
         # setup drag and drop
-        self.treeview.enable_model_drag_source(gtk.gdk.BUTTON1_MASK, 
DND_TARGETS, gtk.gdk.ACTION_COPY)
+        self.treeview.enable_model_drag_source(Gdk.ModifierType.BUTTON1_MASK, 
DND_TARGETS, Gdk.DragAction.COPY)
         self.treeview.connect('drag-data-get', self._handle_drag_get_data)
         # make the scrolled window to hold the tree view
-        scrolled_window = gtk.ScrolledWindow()
-        scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
+        scrolled_window = Gtk.ScrolledWindow()
+        scrolled_window.set_policy(Gtk.PolicyType.AUTOMATIC, 
Gtk.PolicyType.AUTOMATIC)
         scrolled_window.add_with_viewport(self.treeview)
         scrolled_window.set_size_request(DEFAULT_BLOCKS_WINDOW_WIDTH, -1)
-        self.pack_start(scrolled_window)
+        self.pack_start(scrolled_window, True, True, 0)
         # map categories to iters, automatic mapping for root
         self._categories = {tuple(): None}
         self._categories_search = {tuple(): None}
@@ -216,9 +217,9 @@ class BlockTreeWindow(gtk.VBox):
     ## Event Handlers
     ############################################################
     def _handle_icon_event(self, widget, icon, event):
-        if icon == gtk.ENTRY_ICON_PRIMARY:
+        if icon == Gtk.EntryIconPosition.PRIMARY:
             pass
-        elif icon == gtk.ENTRY_ICON_SECONDARY:
+        elif icon == Gtk.EntryIconPosition.SECONDARY:
             widget.set_text('')
             self.search_entry.hide()
 
@@ -241,7 +242,7 @@ class BlockTreeWindow(gtk.VBox):
 
     def _handle_search_key_press(self, widget, event):
         """Handle Return and Escape key events in search entry and treeview"""
-        if event.keyval == gtk.keysyms.Return:
+        if event.keyval == Gdk.KEY_Return:
             # add block on enter
 
             if widget == self.search_entry:
@@ -257,18 +258,18 @@ class BlockTreeWindow(gtk.VBox):
             else:
                 return False  # propagate event
 
-        elif event.keyval == gtk.keysyms.Escape:
+        elif event.keyval == Gdk.KEY_Escape:
             # reset the search
             self.search_entry.set_text('')
             self.search_entry.hide()
 
-        elif (event.state & gtk.gdk.CONTROL_MASK and event.keyval == 
gtk.keysyms.f) \
-             or event.keyval == gtk.keysyms.slash:
+        elif (event.get_state() & Gdk.ModifierType.CONTROL_MASK and 
event.keyval == Gdk.KEY_f) \
+             or event.keyval == Gdk.KEY_slash:
             # propagation doesn't work although treeview search is disabled =(
             # manually trigger action...
             Actions.FIND_BLOCKS.activate()
 
-        elif event.state & gtk.gdk.CONTROL_MASK and event.keyval == 
gtk.keysyms.b:
+        elif event.get_state() & Gdk.ModifierType.CONTROL_MASK and 
event.keyval == Gdk.KEY_b:
             # ugly...
             Actions.TOGGLE_BLOCKS_WINDOW.activate()
 
@@ -291,5 +292,5 @@ class BlockTreeWindow(gtk.VBox):
         Handle the mouse button press.
         If a left double click is detected, call add selected block.
         """
-        if event.button == 1 and event.type == gtk.gdk._2BUTTON_PRESS:
+        if event.button == 1 and event.type == Gdk._2BUTTON_PRESS:
             self._add_selected_block()
diff --git a/grc/gui/Colors.py b/grc/gui/Colors.py
index d322afa..2c5c730 100644
--- a/grc/gui/Colors.py
+++ b/grc/gui/Colors.py
@@ -17,34 +17,44 @@ along with this program; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 """
 try:
-    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
 
-    _COLORMAP = gtk.gdk.colormap_get_system() #create all of the colors
-    def get_color(color_code): return _COLORMAP.alloc_color(color_code, True, 
True)
+    def get_color(color_code):
+        color = Gdk.RGBA()
+        color.parse(color_code)
+        return color
 
     HIGHLIGHT_COLOR = get_color('#00FFFF')
     BORDER_COLOR = get_color('#444444')
-    # missing blocks stuff
+
+    # Missing blocks stuff
     MISSING_BLOCK_BACKGROUND_COLOR = get_color('#FFF2F2')
     MISSING_BLOCK_BORDER_COLOR = get_color('red')
-    #param entry boxes
+
+    # Param entry boxes
     PARAM_ENTRY_TEXT_COLOR = get_color('black')
     ENTRYENUM_CUSTOM_COLOR = get_color('#EEEEEE')
-    #flow graph color constants
+
+    # Flow graph color constants
     FLOWGRAPH_BACKGROUND_COLOR = get_color('#FFFFFF')
     COMMENT_BACKGROUND_COLOR = get_color('#F3F3F3')
     FLOWGRAPH_EDGE_COLOR = COMMENT_BACKGROUND_COLOR
-    #block color constants
+
+    # Block color constants
     BLOCK_ENABLED_COLOR = get_color('#F1ECFF')
     BLOCK_DISABLED_COLOR = get_color('#CCCCCC')
     BLOCK_BYPASSED_COLOR = get_color('#F4FF81')
-    #connection color constants
+
+    # Connection color constants
     CONNECTION_ENABLED_COLOR = get_color('black')
     CONNECTION_DISABLED_COLOR = get_color('#BBBBBB')
     CONNECTION_ERROR_COLOR = get_color('red')
-except:
+
+except Exception as e:
     print 'Unable to import Colors'
 
+
 DEFAULT_DOMAIN_COLOR_CODE = '#777777'
diff --git a/grc/gui/Connection.py b/grc/gui/Connection.py
index 50361c1..356a55d 100644
--- a/grc/gui/Connection.py
+++ b/grc/gui/Connection.py
@@ -17,7 +17,11 @@ along with this program; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 """
 
-import gtk
+import gi
+gi.require_version('Gtk', '3.0')
+from gi.repository import Gtk
+from gi.repository import Gdk
+
 
 import Colors
 import Utils
@@ -88,9 +92,9 @@ class Connection(Element, _Connection):
         source_domain = self.get_source().get_domain()
         sink_domain = self.get_sink().get_domain()
         self.line_attributes[0] = 2 if source_domain != sink_domain else 0
-        self.line_attributes[1] = gtk.gdk.LINE_DOUBLE_DASH \
+        self.line_attributes[1] = Gdk.LINE_DOUBLE_DASH \
             if not source_domain == sink_domain == GR_MESSAGE_DOMAIN \
-            else gtk.gdk.LINE_ON_OFF_DASH
+            else Gdk.LINE_ON_OFF_DASH
         get_domain_color = lambda d: Colors.get_color((
             self.get_parent().get_parent().domains.get(d, {})
         ).get('color') or Colors.DEFAULT_DOMAIN_COLOR_CODE)
@@ -175,7 +179,7 @@ class Connection(Element, _Connection):
         # draw arrow on sink port
         try:
             gc.set_foreground(mod_color(self._arrow_color))
-            gc.set_line_attributes(0, gtk.gdk.LINE_SOLID, gtk.gdk.CAP_BUTT, 
gtk.gdk.JOIN_MITER)
+            gc.set_line_attributes(0, Gdk.LINE_SOLID, Gdk.CAP_BUTT, 
Gdk.JOIN_MITER)
             window.draw_polygon(gc, True, self._arrow)
         except:
             pass
diff --git a/grc/gui/Constants.py b/grc/gui/Constants.py
index 022564c..4508efc 100644
--- a/grc/gui/Constants.py
+++ b/grc/gui/Constants.py
@@ -17,7 +17,9 @@ along with this program; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 """
 
-import gtk
+import gi
+gi.require_version('Gtk', '3.0')
+from gi.repository import Gtk
 
 from ..core.Constants import *
 
@@ -53,7 +55,7 @@ PARAM_FONT = "Sans 7.5"
 STATE_CACHE_SIZE = 42
 
 # Shared targets for drag and drop of blocks
-DND_TARGETS = [('STRING', gtk.TARGET_SAME_APP, 0)]
+DND_TARGETS = [('STRING', Gtk.TargetFlags.SAME_APP, 0)]
 
 # label constraint dimensions
 LABEL_SEPARATION = 3
diff --git a/grc/gui/Dialogs.py b/grc/gui/Dialogs.py
index 1d11435..a7bc121 100644
--- a/grc/gui/Dialogs.py
+++ b/grc/gui/Dialogs.py
@@ -17,7 +17,11 @@ along with this program; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 """
 
-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 sys
 from distutils.spawn import find_executable
@@ -26,7 +30,7 @@ from . import Utils, Actions
 from ..core import Messages
 
 
-class SimpleTextDisplay(gtk.TextView):
+class SimpleTextDisplay(Gtk.TextView):
     """A non editable gtk text view."""
 
     def __init__(self, text=''):
@@ -36,13 +40,13 @@ class SimpleTextDisplay(gtk.TextView):
         Args:
             text: the text to display (string)
         """
-        text_buffer = gtk.TextBuffer()
+        text_buffer = Gtk.TextBuffer()
         text_buffer.set_text(text)
         self.set_text = text_buffer.set_text
-        gtk.TextView.__init__(self, text_buffer)
+        GObject.GObject.__init__(self)
         self.set_editable(False)
         self.set_cursor_visible(False)
-        self.set_wrap_mode(gtk.WRAP_WORD_CHAR)
+        self.set_wrap_mode(Gtk.WrapMode.WORD_CHAR)
 
 
 class TextDisplay(SimpleTextDisplay):
@@ -85,7 +89,8 @@ class TextDisplay(SimpleTextDisplay):
         if self.scroll_lock:
             buffer = self.get_buffer()
             buffer.move_mark(buffer.get_insert(), buffer.get_end_iter())
-            self.scroll_to_mark(buffer.get_insert(), 0.0)
+            # TODO: Fix later
+            #self.scroll_to_mark(buffer.get_insert(), 0.0)
 
     def clear(self):
         buffer = self.get_buffer()
@@ -110,18 +115,18 @@ class TextDisplay(SimpleTextDisplay):
 
     def populate_popup(self, view, menu):
         """Create a popup menu for the scroll lock and clear functions"""
-        menu.append(gtk.SeparatorMenuItem())
+        menu.append(Gtk.SeparatorMenuItem())
 
-        lock = gtk.CheckMenuItem("Scroll Lock")
+        lock = Gtk.CheckMenuItem("Scroll Lock")
         menu.append(lock)
         lock.set_active(self.scroll_lock)
         lock.connect('activate', self.scroll_back_cb, view)
 
-        save = gtk.ImageMenuItem(gtk.STOCK_SAVE)
+        save = Gtk.ImageMenuItem(Gtk.STOCK_SAVE)
         menu.append(save)
         save.connect('activate', self.save_cb, view)
 
-        clear = gtk.ImageMenuItem(gtk.STOCK_CLEAR)
+        clear = Gtk.ImageMenuItem(Gtk.STOCK_CLEAR)
         menu.append(clear)
         clear.connect('activate', self.clear_cb, view)
         menu.show_all()
@@ -133,9 +138,9 @@ def MessageDialogHelper(type, buttons, title=None, 
markup=None, default_response
     Create a modal message dialog and run it.
 
     Args:
-        type: the type of message: gtk.MESSAGE_INFO, gtk.MESSAGE_WARNING, 
gtk.MESSAGE_QUESTION or gtk.MESSAGE_ERROR
+        type: the type of message: Gtk.MessageType.INFO, 
Gtk.MessageType.WARNING, Gtk.MessageType.QUESTION or Gtk.MessageType.ERROR
         buttons: the predefined set of buttons to use:
-        gtk.BUTTONS_NONE, gtk.BUTTONS_OK, gtk.BUTTONS_CLOSE, 
gtk.BUTTONS_CANCEL, gtk.BUTTONS_YES_NO, gtk.BUTTONS_OK_CANCEL
+        Gtk.ButtonsType.NONE, Gtk.ButtonsType.OK, Gtk.ButtonsType.CLOSE, 
Gtk.ButtonsType.CANCEL, Gtk.ButtonsType.YES_NO, Gtk.ButtonsType.OK_CANCEL
 
     Args:
         title: the title of the window (string)
@@ -146,7 +151,7 @@ def MessageDialogHelper(type, buttons, title=None, 
markup=None, default_response
     Returns:
         the gtk response from run()
     """
-    message_dialog = gtk.MessageDialog(None, gtk.DIALOG_MODAL, type, buttons)
+    message_dialog = Gtk.MessageDialog(None, Gtk.DialogFlags.MODAL, type, 
buttons)
     if title: message_dialog.set_title(title)
     if markup: message_dialog.set_markup(markup)
     if extra_buttons: message_dialog.add_buttons(*extra_buttons)
@@ -165,19 +170,19 @@ $encode($err_msg.replace('\t', '  '))
 
 
 def ErrorsDialog(flowgraph): MessageDialogHelper(
-    type=gtk.MESSAGE_ERROR,
-    buttons=gtk.BUTTONS_CLOSE,
+    type=Gtk.MessageType.ERROR,
+    buttons=Gtk.ButtonsType.CLOSE,
     title='Flow Graph Errors',
     markup=Utils.parse_template(ERRORS_MARKUP_TMPL, 
errors=flowgraph.get_error_messages()),
 )
 
 
-class AboutDialog(gtk.AboutDialog):
+class AboutDialog(Gtk.AboutDialog):
     """A cute little about dialog."""
 
     def __init__(self, config):
         """AboutDialog constructor."""
-        gtk.AboutDialog.__init__(self)
+        GObject.GObject.__init__(self)
         self.set_name(config.name)
         self.set_version(config.version)
         self.set_license(config.license)
@@ -188,8 +193,8 @@ class AboutDialog(gtk.AboutDialog):
 
 
 def HelpDialog(): MessageDialogHelper(
-    type=gtk.MESSAGE_INFO,
-    buttons=gtk.BUTTONS_CLOSE,
+    type=Gtk.MessageType.INFO,
+    buttons=Gtk.ButtonsType.CLOSE,
     title='Help',
     markup="""\
 <b>Usage Tips</b>
@@ -217,8 +222,8 @@ COLORS_DIALOG_MARKUP_TMPL = """\
 
 def TypesDialog(platform):
     MessageDialogHelper(
-        type=gtk.MESSAGE_INFO,
-        buttons=gtk.BUTTONS_CLOSE,
+        type=Gtk.MessageType.INFO,
+        buttons=Gtk.ButtonsType.CLOSE,
         title='Types',
         markup=Utils.parse_template(COLORS_DIALOG_MARKUP_TMPL,
                                     colors=platform.get_colors())
@@ -227,8 +232,8 @@ def TypesDialog(platform):
 
 def MissingXTermDialog(xterm):
     MessageDialogHelper(
-        type=gtk.MESSAGE_WARNING,
-        buttons=gtk.BUTTONS_OK,
+        type=Gtk.MessageType.WARNING,
+        buttons=Gtk.ButtonsType.OK,
         title='Warning: missing xterm executable',
         markup=("The xterm executable {0!r} is missing.\n\n"
                 "You can change this setting in your gnuradio.conf, in "
@@ -242,28 +247,28 @@ def ChooseEditorDialog(config):
     # Give the option to either choose an editor or use the default
     # Always return true/false so the caller knows it was successful
     buttons = (
-        'Choose Editor', gtk.RESPONSE_YES,
-        'Use Default', gtk.RESPONSE_NO,
-        gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL
+        'Choose Editor', Gtk.ResponseType.YES,
+        'Use Default', Gtk.ResponseType.NO,
+        Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL
     )
     response = MessageDialogHelper(
-        gtk.MESSAGE_QUESTION, gtk.BUTTONS_NONE, 'Choose Editor',
-        'Would you like to choose the editor to use?', gtk.RESPONSE_YES, 
buttons
+        Gtk.MessageType.QUESTION, Gtk.ButtonsType.NONE, 'Choose Editor',
+        'Would you like to choose the editor to use?', Gtk.ResponseType.YES, 
buttons
     )
 
     # Handle the inital default/choose/cancel response
     # User wants to choose the editor to use
-    if response == gtk.RESPONSE_YES:
-        file_dialog = gtk.FileChooserDialog(
+    if response == Gtk.ResponseType.YES:
+        file_dialog = Gtk.FileChooserDialog(
             'Select an Editor...', None,
-            gtk.FILE_CHOOSER_ACTION_OPEN,
-            ('gtk-cancel', gtk.RESPONSE_CANCEL, 'gtk-open', gtk.RESPONSE_OK)
+            Gtk.FileChooserAction.OPEN,
+            ('gtk-cancel', Gtk.ResponseType.CANCEL, 'gtk-open', 
Gtk.ResponseType.OK)
         )
         file_dialog.set_select_multiple(False)
         file_dialog.set_local_only(True)
         file_dialog.set_current_folder('/usr/bin')
         try:
-            if file_dialog.run() == gtk.RESPONSE_OK:
+            if file_dialog.run() == Gtk.ResponseType.OK:
                 config.editor = file_path = file_dialog.get_filename()
                 file_dialog.destroy()
                 return file_path
@@ -271,7 +276,7 @@ def ChooseEditorDialog(config):
             file_dialog.destroy()
 
     # Go with the default editor
-    elif response == gtk.RESPONSE_NO:
+    elif response == Gtk.ResponseType.NO:
         # Determine the platform
         try:
             process = None
diff --git a/grc/gui/DrawingArea.py b/grc/gui/DrawingArea.py
index 6a1df27..f91fb2a 100644
--- a/grc/gui/DrawingArea.py
+++ b/grc/gui/DrawingArea.py
@@ -17,15 +17,18 @@ along with this program; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 """
 
-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 Constants import MIN_WINDOW_WIDTH, MIN_WINDOW_HEIGHT, DND_TARGETS
 import Colors
 
 
-class DrawingArea(gtk.DrawingArea):
+class DrawingArea(Gtk.DrawingArea):
     """
     DrawingArea is the gtk pixel map that graphical elements may draw 
themselves on.
     The drawing area also responds to mouse and key events.
@@ -42,7 +45,7 @@ class DrawingArea(gtk.DrawingArea):
         self.ctrl_mask = False
         self.mod1_mask = False
         self._flow_graph = flow_graph
-        gtk.DrawingArea.__init__(self)
+        GObject.GObject.__init__(self)
         self.set_size_request(MIN_WINDOW_WIDTH, MIN_WINDOW_HEIGHT)
         self.connect('realize', self._handle_window_realize)
         self.connect('configure-event', self._handle_window_configure)
@@ -52,15 +55,15 @@ class DrawingArea(gtk.DrawingArea):
         self.connect('button-release-event', self._handle_mouse_button_release)
         self.connect('scroll-event', self._handle_mouse_scroll)
         self.add_events(
-            gtk.gdk.BUTTON_PRESS_MASK | \
-            gtk.gdk.POINTER_MOTION_MASK | \
-            gtk.gdk.BUTTON_RELEASE_MASK | \
-            gtk.gdk.LEAVE_NOTIFY_MASK | \
-            gtk.gdk.ENTER_NOTIFY_MASK | \
-            gtk.gdk.FOCUS_CHANGE_MASK
+            Gdk.EventMask.BUTTON_PRESS_MASK | \
+            Gdk.EventMask.POINTER_MOTION_MASK | \
+            Gdk.EventMask.BUTTON_RELEASE_MASK | \
+            Gdk.EventMask.LEAVE_NOTIFY_MASK | \
+            Gdk.EventMask.ENTER_NOTIFY_MASK | \
+            Gdk.EventMask.FOCUS_CHANGE_MASK
         )
         #setup drag and drop
-        self.drag_dest_set(gtk.DEST_DEFAULT_ALL, DND_TARGETS, 
gtk.gdk.ACTION_COPY)
+        self.drag_dest_set(Gtk.DestDefaults.ALL, DND_TARGETS, 
Gdk.DragAction.COPY)
         self.connect('drag-data-received', self._handle_drag_data_received)
         #setup the focus flag
         self._focus_flag = False
@@ -68,16 +71,16 @@ class DrawingArea(gtk.DrawingArea):
         def _handle_notify_event(widget, event, focus_flag): self._focus_flag 
= focus_flag
         self.connect('leave-notify-event', _handle_notify_event, False)
         self.connect('enter-notify-event', _handle_notify_event, True)
-        self.set_flags(gtk.CAN_FOCUS)  # self.set_can_focus(True)
+        self.set_flags(Gtk.CAN_FOCUS)  # self.set_can_focus(True)
         self.connect('focus-out-event', self._handle_focus_lost_event)
 
     def new_pixmap(self, width, height):
-        return gtk.gdk.Pixmap(self.window, width, height, -1)
+        return Gdk.Pixmap(self.window, width, height, -1)
 
     def get_screenshot(self, transparent_bg=False):
         pixmap = self._pixmap
         W, H = pixmap.get_size()
-        pixbuf = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, 0, 8, W, H)
+        pixbuf = GdkPixbuf.Pixbuf(GdkPixbuf.Colorspace.RGB, 0, 8, W, H)
         pixbuf.fill(0xFF + Colors.FLOWGRAPH_BACKGROUND_COLOR.pixel << 8)
         pixbuf.get_from_drawable(pixmap, pixmap.get_colormap(), 0, 0, 0, 0, 
W-1, H-1)
         if transparent_bg:
@@ -96,21 +99,21 @@ class DrawingArea(gtk.DrawingArea):
         self._flow_graph.add_new_block(selection_data.data, (x, y))
 
     def _handle_mouse_scroll(self, widget, event):
-        if event.state & gtk.gdk.SHIFT_MASK:
-           if event.direction == gtk.gdk.SCROLL_UP:
-               event.direction = gtk.gdk.SCROLL_LEFT
+        if event.get_state() & Gdk.ModifierType.SHIFT_MASK:
+           if event.direction == Gdk.ScrollDirection.UP:
+               event.direction = Gdk.ScrollDirection.LEFT
            else:
-               event.direction = gtk.gdk.SCROLL_RIGHT
+               event.direction = Gdk.ScrollDirection.RIGHT
 
     def _handle_mouse_button_press(self, widget, event):
         """
         Forward button click information to the flow graph.
         """
         self.grab_focus()
-        self.ctrl_mask = event.state & gtk.gdk.CONTROL_MASK
-        self.mod1_mask = event.state & gtk.gdk.MOD1_MASK
+        self.ctrl_mask = event.get_state() & Gdk.ModifierType.CONTROL_MASK
+        self.mod1_mask = event.get_state() & Gdk.ModifierType.MOD1_MASK
         if event.button == 1: self._flow_graph.handle_mouse_selector_press(
-            double_click=(event.type == gtk.gdk._2BUTTON_PRESS),
+            double_click=(event.type == Gdk._2BUTTON_PRESS),
             coordinate=(event.x, event.y),
         )
         if event.button == 3: self._flow_graph.handle_mouse_context_press(
@@ -122,8 +125,8 @@ class DrawingArea(gtk.DrawingArea):
         """
         Forward button release information to the flow graph.
         """
-        self.ctrl_mask = event.state & gtk.gdk.CONTROL_MASK
-        self.mod1_mask = event.state & gtk.gdk.MOD1_MASK
+        self.ctrl_mask = event.get_state() & Gdk.ModifierType.CONTROL_MASK
+        self.mod1_mask = event.get_state() & Gdk.ModifierType.MOD1_MASK
         if event.button == 1: self._flow_graph.handle_mouse_selector_release(
             coordinate=(event.x, event.y),
         )
@@ -132,8 +135,8 @@ class DrawingArea(gtk.DrawingArea):
         """
         Forward mouse motion information to the flow graph.
         """
-        self.ctrl_mask = event.state & gtk.gdk.CONTROL_MASK
-        self.mod1_mask = event.state & gtk.gdk.MOD1_MASK
+        self.ctrl_mask = event.get_state() & Gdk.ModifierType.CONTROL_MASK
+        self.mod1_mask = event.get_state() & Gdk.ModifierType.MOD1_MASK
         self._flow_graph.handle_mouse_motion(
             coordinate=(event.x, event.y),
         )
@@ -169,7 +172,7 @@ class DrawingArea(gtk.DrawingArea):
 
     def _handle_focus_lost_event(self, widget, event):
         # don't clear selection while context menu is active
-        if not self._flow_graph.get_context_menu().flags() & gtk.VISIBLE:
+        if not self._flow_graph.get_context_menu().flags() & Gtk.VISIBLE:
             self._flow_graph.unselect()
             self._flow_graph.update_selected()
             self._flow_graph.queue_draw()
diff --git a/grc/gui/Element.py b/grc/gui/Element.py
index 9385424..3f6017d 100644
--- a/grc/gui/Element.py
+++ b/grc/gui/Element.py
@@ -20,7 +20,10 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
MA  02110-1301, USA
 from Constants import LINE_SELECT_SENSITIVITY
 from Constants import POSSIBLE_ROTATIONS
 
-import gtk
+import gi
+gi.require_version('Gtk', '3.0')
+from gi.repository import Gtk
+from gi.repository import Gdk
 
 
 class Element(object):
@@ -38,9 +41,11 @@ class Element(object):
         self.set_coordinate((0, 0))
         self.clear()
         self.set_highlighted(False)
-        self.line_attributes = [
-            0, gtk.gdk.LINE_SOLID, gtk.gdk.CAP_BUTT, gtk.gdk.JOIN_MITER
-        ]
+        self.line_attributes = []
+        """ # No idea where this is in pygobject
+           0, Gdk.LINE_SOLID, Gdk.CAP_BUTT, Gdk.JOIN_MITER
+        ]"""
+
 
     def is_horizontal(self, rotation=None):
         """
diff --git a/grc/gui/Executor.py b/grc/gui/Executor.py
index bf9eecb..9ed5f9d 100644
--- a/grc/gui/Executor.py
+++ b/grc/gui/Executor.py
@@ -15,7 +15,6 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
USA
 
-import gobject
 import os
 import threading
 import shlex
@@ -24,6 +23,8 @@ import sys
 import re
 from distutils.spawn import find_executable
 
+from gi.repository import GObject
+
 from ..core import Messages
 
 
@@ -86,15 +87,15 @@ class ExecFlowGraphThread(threading.Thread):
     def run(self):
         """
         Wait on the executing process by reading from its stdout.
-        Use gobject.idle_add when calling functions that modify gtk objects.
+        Use GObject.idle_add when calling functions that modify gtk objects.
         """
         # handle completion
         r = "\n"
         while r:
-            gobject.idle_add(Messages.send_verbose_exec, r)
+            GObject.idle_add(Messages.send_verbose_exec, r)
             r = os.read(self.process.stdout.fileno(), 1024)
         self.process.poll()
-        gobject.idle_add(self.done)
+        GObject.idle_add(self.done)
 
     def done(self):
         """Perform end of execution tasks."""
diff --git a/grc/gui/FileDialogs.py b/grc/gui/FileDialogs.py
index e9430b1..479f13b 100644
--- a/grc/gui/FileDialogs.py
+++ b/grc/gui/FileDialogs.py
@@ -17,9 +17,11 @@ along with this program; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 """
 
-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 Dialogs import MessageDialogHelper
 from Constants import \
     DEFAULT_FILE_PATH, IMAGE_FILE_EXTENSION, TEXT_FILE_EXTENSION, \
@@ -47,42 +49,42 @@ File <b>$encode($filename)</b> Does not Exist!"""
 
 # File Filters
 def get_flow_graph_files_filter():
-    filter = gtk.FileFilter()
+    filter = Gtk.FileFilter()
     filter.set_name('Flow Graph Files')
     filter.add_pattern('*'+Preferences.file_extension())
     return filter
 
 
 def get_text_files_filter():
-    filter = gtk.FileFilter()
+    filter = Gtk.FileFilter()
     filter.set_name('Text Files')
     filter.add_pattern('*'+TEXT_FILE_EXTENSION)
     return filter
 
 
 def get_image_files_filter():
-    filter = gtk.FileFilter()
+    filter = Gtk.FileFilter()
     filter.set_name('Image Files')
     filter.add_pattern('*'+IMAGE_FILE_EXTENSION)
     return filter
 
 
 def get_all_files_filter():
-    filter = gtk.FileFilter()
+    filter = Gtk.FileFilter()
     filter.set_name('All Files')
     filter.add_pattern('*')
     return filter
 
 
 def get_qss_themes_filter():
-    filter = gtk.FileFilter()
+    filter = Gtk.FileFilter()
     filter.set_name('QSS Themes')
     filter.add_pattern('*.qss')
     return filter
 
 
 # File Dialogs
-class FileDialogHelper(gtk.FileChooserDialog):
+class FileDialogHelper(Gtk.FileChooserDialog):
     """
     A wrapper class for the gtk file chooser dialog.
     Implement a file chooser dialog with only necessary parameters.
@@ -95,11 +97,11 @@ class FileDialogHelper(gtk.FileChooserDialog):
         Use standard settings: no multiple selection, local files only, and 
the * filter.
 
         Args:
-            action: gtk.FILE_CHOOSER_ACTION_OPEN or 
gtk.FILE_CHOOSER_ACTION_SAVE
+            action: Gtk.FileChooserAction.OPEN or Gtk.FileChooserAction.SAVE
             title: the title of the dialog (string)
         """
-        ok_stock = {gtk.FILE_CHOOSER_ACTION_OPEN : 'gtk-open', 
gtk.FILE_CHOOSER_ACTION_SAVE : 'gtk-save'}[action]
-        gtk.FileChooserDialog.__init__(self, title, None, action, 
('gtk-cancel', gtk.RESPONSE_CANCEL, ok_stock, gtk.RESPONSE_OK))
+        ok_stock = {Gtk.FileChooserAction.OPEN : 'gtk-open', 
Gtk.FileChooserAction.SAVE : 'gtk-save'}[action]
+        GObject.GObject.__init__(self, title, None, action, ('gtk-cancel', 
Gtk.ResponseType.CANCEL, ok_stock, Gtk.ResponseType.OK))
         self.set_select_multiple(False)
         self.set_local_only(True)
         self.add_filter(get_all_files_filter())
@@ -117,25 +119,25 @@ class FileDialog(FileDialogHelper):
         """
         if not current_file_path: current_file_path = 
path.join(DEFAULT_FILE_PATH, NEW_FLOGRAPH_TITLE + Preferences.file_extension())
         if self.type == OPEN_FLOW_GRAPH:
-            FileDialogHelper.__init__(self, gtk.FILE_CHOOSER_ACTION_OPEN, 
'Open a Flow Graph from a File...')
+            FileDialogHelper.__init__(self, Gtk.FileChooserAction.OPEN, 'Open 
a Flow Graph from a File...')
             self.add_and_set_filter(get_flow_graph_files_filter())
             self.set_select_multiple(True)
         elif self.type == SAVE_FLOW_GRAPH:
-            FileDialogHelper.__init__(self, gtk.FILE_CHOOSER_ACTION_SAVE, 
'Save a Flow Graph to a File...')
+            FileDialogHelper.__init__(self, Gtk.FileChooserAction.SAVE, 'Save 
a Flow Graph to a File...')
             self.add_and_set_filter(get_flow_graph_files_filter())
             self.set_current_name(path.basename(current_file_path))
         elif self.type == SAVE_CONSOLE:
-            FileDialogHelper.__init__(self, gtk.FILE_CHOOSER_ACTION_SAVE, 
'Save Console to a File...')
+            FileDialogHelper.__init__(self, Gtk.FileChooserAction.SAVE, 'Save 
Console to a File...')
             self.add_and_set_filter(get_text_files_filter())
             file_path = path.splitext(path.basename(current_file_path))[0]
             self.set_current_name(file_path) #show the current filename
         elif self.type == SAVE_IMAGE:
-            FileDialogHelper.__init__(self, gtk.FILE_CHOOSER_ACTION_SAVE, 
'Save a Flow Graph Screen Shot...')
+            FileDialogHelper.__init__(self, Gtk.FileChooserAction.SAVE, 'Save 
a Flow Graph Screen Shot...')
             self.add_and_set_filter(get_image_files_filter())
             current_file_path = current_file_path + IMAGE_FILE_EXTENSION
             self.set_current_name(path.basename(current_file_path)) #show the 
current filename
         elif self.type == OPEN_QSS_THEME:
-            FileDialogHelper.__init__(self, gtk.FILE_CHOOSER_ACTION_OPEN, 
'Open a QSS theme...')
+            FileDialogHelper.__init__(self, Gtk.FileChooserAction.OPEN, 'Open 
a QSS theme...')
             self.add_and_set_filter(get_qss_themes_filter())
             self.set_select_multiple(False)
         self.set_current_folder(path.dirname(current_file_path)) #current 
directory
@@ -160,7 +162,7 @@ class FileDialog(FileDialogHelper):
         Returns:
             the complete file path
         """
-        if gtk.FileChooserDialog.run(self) != gtk.RESPONSE_OK: return None 
#response was cancel
+        if Gtk.FileChooserDialog.run(self) != Gtk.ResponseType.OK: return None 
#response was cancel
         #############################################
         # Handle Save Dialogs
         #############################################
@@ -176,9 +178,9 @@ class FileDialog(FileDialogHelper):
             self.set_current_name(path.basename(filename)) #show the filename 
with extension
             if path.exists(filename): #ask the user to confirm overwrite
                 if MessageDialogHelper(
-                    gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO, 'Confirm 
Overwrite!',
+                    Gtk.MessageType.QUESTION, Gtk.ButtonsType.YES_NO, 'Confirm 
Overwrite!',
                     Utils.parse_template(FILE_OVERWRITE_MARKUP_TMPL, 
filename=filename),
-                ) == gtk.RESPONSE_NO: return self.get_rectified_filename()
+                ) == Gtk.ResponseType.NO: return self.get_rectified_filename()
             return filename
         #############################################
         # Handle Open Dialogs
@@ -188,7 +190,7 @@ class FileDialog(FileDialogHelper):
             for filename in filenames:
                 if not path.exists(filename): #show a warning and re-run
                     MessageDialogHelper(
-                        gtk.MESSAGE_WARNING, gtk.BUTTONS_CLOSE, 'Cannot Open!',
+                        Gtk.MessageType.WARNING, Gtk.ButtonsType.CLOSE, 
'Cannot Open!',
                         Utils.parse_template(FILE_DNE_MARKUP_TMPL, 
filename=filename),
                     )
                     return self.get_rectified_filename()
@@ -230,7 +232,7 @@ class SaveScreenShotDialog(SaveImageFileDialog):
 
     def __init__(self, current_file_path=''):
         SaveImageFileDialog.__init__(self, current_file_path)
-        self._button = button = gtk.CheckButton('_Background transparent')
+        self._button = button = Gtk.CheckButton('_Background transparent')
         
self._button.set_active(Preferences.screen_shot_background_transparent())
         self.set_extra_widget(button)
 
diff --git a/grc/gui/FlowGraph.py b/grc/gui/FlowGraph.py
index 02d5197..f7af93f 100644
--- a/grc/gui/FlowGraph.py
+++ b/grc/gui/FlowGraph.py
@@ -23,7 +23,7 @@ from distutils.spawn import find_executable
 from itertools import chain, count
 from operator import methodcaller
 
-import gobject
+from gi.repository import GObject
 
 from . import Actions, Colors, Constants, Utils, Bars, Dialogs
 from .Constants import SCROLL_PROXIMITY_SENSITIVITY, SCROLL_DISTANCE
@@ -98,7 +98,7 @@ class FlowGraph(Element, _Flowgraph):
             editor = self._external_updaters[target] = ExternalEditor(
                 editor=editor,
                 name=target[0], value=param.get_value(),
-                callback=functools.partial(gobject.idle_add, updater)
+                callback=functools.partial(GObject.idle_add, updater)
             )
             editor.start()
         try:
@@ -706,7 +706,7 @@ class FlowGraph(Element, _Flowgraph):
         Auto-scroll the scroll bars at the boundaries.
         """
         #to perform a movement, the mouse must be pressed
-        # (no longer checking pending events via gtk.events_pending() - always 
true in Windows)
+        # (no longer checking pending events via Gtk.events_pending() - always 
true in Windows)
         if not self.mouse_pressed:
             # only continue if mouse-over stuff is enabled (just the auto-hide 
port label stuff for now)
             if not Actions.TOGGLE_AUTO_HIDE_PORT_LABELS.get_active(): return
diff --git a/grc/gui/MainWindow.py b/grc/gui/MainWindow.py
index 1437391..649b8b2 100644
--- a/grc/gui/MainWindow.py
+++ b/grc/gui/MainWindow.py
@@ -19,7 +19,12 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
MA  02110-1301, USA
 
 import os
 
-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 . import Bars, Actions, Preferences, Utils
 from .BlockTreeWindow import BlockTreeWindow
@@ -62,7 +67,7 @@ PAGE_TITLE_MARKUP_TMPL = """\
 # Main window
 ############################################################
 
-class MainWindow(gtk.Window):
+class MainWindow(Gtk.Window):
     """The topmost window with menus, the tool bar, and other major windows."""
 
     # Constants the action handler can use to indicate which panel visibility 
to change.
@@ -87,23 +92,23 @@ class MainWindow(gtk.Window):
         Preferences.load(platform)
 
         # Setup window
-        gtk.Window.__init__(self, gtk.WINDOW_TOPLEVEL)
-        vbox = gtk.VBox()
+        GObject.GObject.__init__(self)
+        vbox = Gtk.VBox()
         self.add(vbox)
 
         # Create the menu bar and toolbar
         self.add_accel_group(Actions.get_accel_group())
         self.menu_bar = Bars.MenuBar(generate_modes, action_handler_callback)
-        vbox.pack_start(self.menu_bar, False)
+        vbox.pack_start(self.menu_bar, False, False, 0)
         self.tool_bar = Bars.Toolbar(generate_modes, action_handler_callback)
-        vbox.pack_start(self.tool_bar, False)
+        vbox.pack_start(self.tool_bar, False, False, 0)
 
         # Main parent container for the different panels
-        self.container = gtk.HPaned()
+        self.container = Gtk.HPaned()
         vbox.pack_start(self.container)
 
         # Create the notebook
-        self.notebook = gtk.Notebook()
+        self.notebook = Gtk.Notebook()
         self.page_to_be_closed = None
         self.current_page = None
         self.notebook.set_show_border(False)
@@ -112,8 +117,8 @@ class MainWindow(gtk.Window):
 
         # Create the console window
         self.text_display = TextDisplay()
-        self.console_window = gtk.ScrolledWindow()
-        self.console_window.set_policy(gtk.POLICY_AUTOMATIC, 
gtk.POLICY_AUTOMATIC)
+        self.console_window = Gtk.ScrolledWindow()
+        self.console_window.set_policy(Gtk.PolicyType.AUTOMATIC, 
Gtk.PolicyType.AUTOMATIC)
         self.console_window.add(self.text_display)
         self.console_window.set_size_request(-1, DEFAULT_CONSOLE_WINDOW_WIDTH)
 
@@ -122,9 +127,9 @@ class MainWindow(gtk.Window):
         self.vars = VariableEditor(platform, self.get_flow_graph)
 
         # Figure out which place to put the variable editor
-        self.left = gtk.VPaned()
-        self.right = gtk.VPaned()
-        self.left_subpanel = gtk.HPaned()
+        self.left = Gtk.VPaned()
+        self.right = Gtk.VPaned()
+        self.left_subpanel = Gtk.HPaned()
 
         self.variable_panel_sidebar = Preferences.variable_editor_sidebar()
         if self.variable_panel_sidebar:
@@ -145,7 +150,7 @@ class MainWindow(gtk.Window):
         self.container.pack1(self.left)
         self.container.pack2(self.right, False)
 
-        # load preferences and show the main window
+        # Load preferences and show the main window
         self.resize(*Preferences.main_window_size())
         self.container.set_position(Preferences.blocks_window_position())
         self.left.set_position(Preferences.console_window_position())
@@ -273,7 +278,7 @@ class MainWindow(gtk.Window):
         self.notebook.append_page(page, page.get_tab())
         try: self.notebook.set_tab_reorderable(page, True)
         except: pass #gtk too old
-        self.notebook.set_tab_label_packing(page, False, False, gtk.PACK_START)
+        self.notebook.set_tab_label_packing(page, False, False, Gtk.PACK_START)
         #only show if blank or manual
         if not file_path or show: self._set_page(page)
 
@@ -322,12 +327,12 @@ class MainWindow(gtk.Window):
         #unsaved? ask the user
         if not self.page_to_be_closed.get_saved():
             response = self._save_changes() # return value is either OK, 
CLOSE, or CANCEL
-            if response == gtk.RESPONSE_OK:
+            if response == Gtk.ResponseType.OK:
                 Actions.FLOW_GRAPH_SAVE() #try to save
                 if not self.page_to_be_closed.get_saved(): #still unsaved?
                     self.page_to_be_closed = None #set the page to be closed 
back to None
                     return False
-            elif response == gtk.RESPONSE_CANCEL:
+            elif response == Gtk.ResponseType.CANCEL:
                 self.page_to_be_closed = None
                 return False
         #stop the flow graph if executing
@@ -351,7 +356,7 @@ class MainWindow(gtk.Window):
         Args:
             title: the window title
         """
-        gtk.Window.set_title(self, Utils.parse_template(MAIN_WINDOW_TITLE_TMPL,
+        Gtk.Window.set_title(self, Utils.parse_template(MAIN_WINDOW_TITLE_TMPL,
                 basename=os.path.basename(self.get_page().get_file_path()),
                 dirname=os.path.dirname(self.get_page().get_file_path()),
                 new_flowgraph_title=NEW_FLOGRAPH_TITLE,
@@ -400,7 +405,9 @@ class MainWindow(gtk.Window):
         Returns:
             the selected flow graph
         """
-        return self.get_page().get_flow_graph()
+        return None
+        # TODO: Issues with flowgraphs
+        #return self.get_page().get_flow_graph()
 
     def get_focus_flag(self):
         """
@@ -433,13 +440,13 @@ class MainWindow(gtk.Window):
             the response_id (see buttons variable below)
         """
         buttons = (
-            'Close without saving', gtk.RESPONSE_CLOSE,
-            gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
-            gtk.STOCK_SAVE, gtk.RESPONSE_OK
+            'Close without saving', Gtk.ResponseType.CLOSE,
+            Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
+            Gtk.STOCK_SAVE, Gtk.ResponseType.OK
         )
         return MessageDialogHelper(
-            gtk.MESSAGE_QUESTION, gtk.BUTTONS_NONE, 'Unsaved Changes!',
-            'Would you like to save changes before closing?', gtk.RESPONSE_OK, 
buttons
+            Gtk.MessageType.QUESTION, Gtk.ButtonsType.NONE, 'Unsaved Changes!',
+            'Would you like to save changes before closing?', 
Gtk.ResponseType.OK, buttons
         )
 
     def _get_files(self):
diff --git a/grc/gui/NotebookPage.py b/grc/gui/NotebookPage.py
index c9e8d0f..3f49cd0 100644
--- a/grc/gui/NotebookPage.py
+++ b/grc/gui/NotebookPage.py
@@ -17,9 +17,11 @@ along with this program; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 """
 
-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
+
 import Actions
 from StateCache import StateCache
 from Constants import MIN_WINDOW_WIDTH, MIN_WINDOW_HEIGHT
@@ -27,7 +29,7 @@ from DrawingArea import DrawingArea
 import os
 
 
-class NotebookPage(gtk.HBox):
+class NotebookPage(Gtk.HBox):
     """A page in the notebook."""
 
     def __init__(self, main_window, flow_graph, file_path=''):
@@ -49,39 +51,39 @@ class NotebookPage(gtk.HBox):
         #import the data to the flow graph
         self.get_flow_graph().import_data(initial_state)
         #initialize page gui
-        gtk.HBox.__init__(self, False, 0)
+        GObject.GObject.__init__(self)
         self.show()
         #tab box to hold label and close button
-        self.tab = gtk.HBox(False, 0)
+        self.tab = Gtk.HBox(False, 0)
         #setup tab label
-        self.label = gtk.Label()
-        self.tab.pack_start(self.label, False)
+        self.label = Gtk.Label()
+        self.tab.pack_start(self.label, False, False, 0)
         #setup button image
-        image = gtk.Image()
-        image.set_from_stock('gtk-close', gtk.ICON_SIZE_MENU)
+        image = Gtk.Image()
+        image.set_from_stock('gtk-close', Gtk.IconSize.MENU)
         #setup image box
-        image_box = gtk.HBox(False, 0)
+        image_box = Gtk.HBox(False, 0)
         image_box.pack_start(image, True, False, 0)
         #setup the button
-        button = gtk.Button()
+        button = Gtk.Button()
         button.connect("clicked", self._handle_button)
-        button.set_relief(gtk.RELIEF_NONE)
+        button.set_relief(Gtk.ReliefStyle.NONE)
         button.add(image_box)
         #button size
-        w, h = gtk.icon_size_lookup_for_settings(button.get_settings(), 
gtk.ICON_SIZE_MENU)
-        button.set_size_request(w+6, h+6)
-        self.tab.pack_start(button, False)
+        #w, h = Gtk.icon_size_lookup_for_settings(button.get_settings(), 
Gtk.IconSize.MENU)
+        #button.set_size_request(w+6, h+6)
+        self.tab.pack_start(button, False, False, 0)
         self.tab.show_all()
         #setup scroll window and drawing area
-        self.scrolled_window = gtk.ScrolledWindow()
+        self.scrolled_window = Gtk.ScrolledWindow()
         self.scrolled_window.set_size_request(MIN_WINDOW_WIDTH, 
MIN_WINDOW_HEIGHT)
-        self.scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, 
gtk.POLICY_AUTOMATIC)
+        self.scrolled_window.set_policy(Gtk.PolicyType.AUTOMATIC, 
Gtk.PolicyType.AUTOMATIC)
         self.scrolled_window.connect('key-press-event', 
self._handle_scroll_window_key_press)
-        self.drawing_area = DrawingArea(self.get_flow_graph())
-        self.scrolled_window.add_with_viewport(self.get_drawing_area())
-        self.pack_start(self.scrolled_window)
+        #self.drawing_area = DrawingArea(self.get_flow_graph())
+        #self.scrolled_window.add_with_viewport(self.get_drawing_area())
+        self.pack_start(self.scrolled_window, True, True, 0)
         #inject drawing area into flow graph
-        self.get_flow_graph().drawing_area = self.get_drawing_area()
+        #self.get_flow_graph().drawing_area = self.get_drawing_area()
         self.show_all()
 
     def get_drawing_area(self): return self.drawing_area
diff --git a/grc/gui/Param.py b/grc/gui/Param.py
index 4b5a3c2..fe5da8b 100644
--- a/grc/gui/Param.py
+++ b/grc/gui/Param.py
@@ -19,9 +19,12 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
MA  02110-1301, USA
 
 import os
 
-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 . import Colors, Utils, Constants
 from .Element import Element
@@ -29,16 +32,16 @@ from .Element import Element
 from ..core.Param import Param as _Param
 
 
-class InputParam(gtk.HBox):
+class InputParam(Gtk.HBox):
     """The base class for an input parameter inside the input parameters 
dialog."""
     expand = False
 
     def __init__(self, param, changed_callback=None, editing_callback=None):
-        gtk.HBox.__init__(self)
+        GObject.GObject.__init__(self)
         self.param = param
         self._changed_callback = changed_callback
         self._editing_callback = editing_callback
-        self.label = gtk.Label() #no label, markup is added by set_markup
+        self.label = Gtk.Label() #no label, markup is added by set_markup
         self.label.set_size_request(150, -1)
         self.pack_start(self.label, False)
         self.set_markup = lambda m: self.label.set_markup(m)
@@ -103,7 +106,7 @@ class InputParam(gtk.HBox):
         self._update_gui()
 
     def _handle_key_press(self, widget, event):
-        if event.keyval == gtk.keysyms.Return and event.state & 
gtk.gdk.CONTROL_MASK:
+        if event.keyval == Gdk.KEY_Return and event.get_state() & 
Gdk.ModifierType.CONTROL_MASK:
             self._apply_change(widget, event)
             return True
         return False
@@ -118,7 +121,7 @@ class EntryParam(InputParam):
 
     def __init__(self, *args, **kwargs):
         InputParam.__init__(self, *args, **kwargs)
-        self._input = gtk.Entry()
+        self._input = Gtk.Entry()
         self._input.set_text(self.param.get_value())
         self._input.connect('changed', self._mark_changed)
         self._input.connect('focus-out-event', self._apply_change)
@@ -140,8 +143,8 @@ class EntryParam(InputParam):
             if need_status_color and not self.param.get_parent().get_enabled()
             else gtk.gdk.color_parse(color)
         )
-        self._input.modify_base(gtk.STATE_NORMAL, base_color)
-        self._input.modify_text(gtk.STATE_NORMAL, text_color)
+        self._input.modify_base(Gtk.StateType.NORMAL, base_color)
+        self._input.modify_text(Gtk.StateType.NORMAL, text_color)
 
     def set_tooltip_text(self, text):
         try:
@@ -156,16 +159,16 @@ class MultiLineEntryParam(InputParam):
 
     def __init__(self, *args, **kwargs):
         InputParam.__init__(self, *args, **kwargs)
-        self._buffer = gtk.TextBuffer()
+        self._buffer = Gtk.TextBuffer()
         self._buffer.set_text(self.param.get_value())
         self._buffer.connect('changed', self._mark_changed)
 
-        self._view = gtk.TextView(self._buffer)
+        self._view = Gtk.TextView(self._buffer)
         self._view.connect('focus-out-event', self._apply_change)
         self._view.connect('key-press-event', self._handle_key_press)
 
-        self._sw = gtk.ScrolledWindow()
-        self._sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
+        self._sw = Gtk.ScrolledWindow()
+        self._sw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
         self._sw.add_with_viewport(self._view)
 
         self.pack_start(self._sw, True)
@@ -176,8 +179,8 @@ class MultiLineEntryParam(InputParam):
                             buf.get_end_iter()).strip()
 
     def set_color(self, color):
-        self._view.modify_base(gtk.STATE_NORMAL, gtk.gdk.color_parse(color))
-        self._view.modify_text(gtk.STATE_NORMAL, Colors.PARAM_ENTRY_TEXT_COLOR)
+        self._view.modify_base(Gtk.StateType.NORMAL, Gdk.color_parse(color))
+        self._view.modify_text(Gtk.StateType.NORMAL, 
Colors.PARAM_ENTRY_TEXT_COLOR)
 
     def set_tooltip_text(self, text):
         try:
@@ -211,8 +214,8 @@ class MultiLineEntryParam(InputParam):
 #             view.set_auto_indent(True)
 #             view.set_border_width(2)
 #
-#             scroll = gtk.ScrolledWindow()
-#             scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
+#             scroll = Gtk.ScrolledWindow()
+#             scroll.set_policy(Gtk.PolicyType.AUTOMATIC, 
Gtk.PolicyType.AUTOMATIC)
 #             scroll.add_with_viewport(view)
 #             self.pack_start(scroll, True)
 #
@@ -229,7 +232,7 @@ class PythonEditorParam(InputParam):
 
     def __init__(self, *args, **kwargs):
         InputParam.__init__(self, *args, **kwargs)
-        button = self._button = gtk.Button('Open in Editor')
+        button = self._button = Gtk.Button('Open in Editor')
         button.connect('clicked', self.open_editor)
         self.pack_start(button, True)
 
@@ -241,8 +244,8 @@ class PythonEditorParam(InputParam):
         pass  # we never update the value from here
 
     def set_color(self, color):
-        # self._button.modify_base(gtk.STATE_NORMAL, 
gtk.gdk.color_parse(color))
-        self._button.modify_text(gtk.STATE_NORMAL, 
Colors.PARAM_ENTRY_TEXT_COLOR)
+        # self._button.modify_base(Gtk.StateType.NORMAL, 
Gdk.color_parse(color))
+        self._button.modify_text(Gtk.StateType.NORMAL, 
Colors.PARAM_ENTRY_TEXT_COLOR)
 
     def _apply_change(self, *args):
         pass
@@ -253,7 +256,7 @@ class EnumParam(InputParam):
 
     def __init__(self, *args, **kwargs):
         InputParam.__init__(self, *args, **kwargs)
-        self._input = gtk.combo_box_new_text()
+        self._input = Gtk.ComboBoxText()
         for option in self.param.get_options(): 
self._input.append_text(option.get_name())
         
self._input.set_active(self.param.get_option_keys().index(self.param.get_value()))
         self._input.connect('changed', self._editing_callback)
@@ -275,7 +278,7 @@ class EnumEntryParam(InputParam):
 
     def __init__(self, *args, **kwargs):
         InputParam.__init__(self, *args, **kwargs)
-        self._input = gtk.combo_box_entry_new_text()
+        self._input = Gtk.combo_box_entry_new_text()
         for option in self.param.get_options(): 
self._input.append_text(option.get_name())
         try: 
self._input.set_active(self.param.get_option_keys().index(self.param.get_value()))
         except:
@@ -302,11 +305,11 @@ class EnumEntryParam(InputParam):
 
     def set_color(self, color):
         if self._input.get_active() == -1: #custom entry, use color
-            self._input.get_child().modify_base(gtk.STATE_NORMAL, 
gtk.gdk.color_parse(color))
-            self._input.get_child().modify_text(gtk.STATE_NORMAL, 
Colors.PARAM_ENTRY_TEXT_COLOR)
+            self._input.get_child().modify_base(Gtk.StateType.NORMAL, 
Gdk.color_parse(color))
+            self._input.get_child().modify_text(Gtk.StateType.NORMAL, 
Colors.PARAM_ENTRY_TEXT_COLOR)
         else: #from enum, make pale background
-            self._input.get_child().modify_base(gtk.STATE_NORMAL, 
Colors.ENTRYENUM_CUSTOM_COLOR)
-            self._input.get_child().modify_text(gtk.STATE_NORMAL, 
Colors.PARAM_ENTRY_TEXT_COLOR)
+            self._input.get_child().modify_base(Gtk.StateType.NORMAL, 
Colors.ENTRYENUM_CUSTOM_COLOR)
+            self._input.get_child().modify_text(Gtk.StateType.NORMAL, 
Colors.PARAM_ENTRY_TEXT_COLOR)
 
 
 class FileParam(EntryParam):
@@ -314,7 +317,7 @@ class FileParam(EntryParam):
 
     def __init__(self, *args, **kwargs):
         EntryParam.__init__(self, *args, **kwargs)
-        input = gtk.Button('...')
+        input = Gtk.Button('...')
         input.connect('clicked', self._handle_clicked)
         self.pack_start(input, False)
 
@@ -338,11 +341,11 @@ class FileParam(EntryParam):
 
         #build the dialog
         if self.param.get_type() == 'file_open':
-            file_dialog = gtk.FileChooserDialog('Open a Data File...', None,
-                gtk.FILE_CHOOSER_ACTION_OPEN, 
('gtk-cancel',gtk.RESPONSE_CANCEL,'gtk-open',gtk.RESPONSE_OK))
+            file_dialog = Gtk.FileChooserDialog('Open a Data File...', None,
+                Gtk.FileChooserAction.OPEN, 
('gtk-cancel',Gtk.ResponseType.CANCEL,'gtk-open',Gtk.ResponseType.OK))
         elif self.param.get_type() == 'file_save':
-            file_dialog = gtk.FileChooserDialog('Save a Data File...', None,
-                gtk.FILE_CHOOSER_ACTION_SAVE, 
('gtk-cancel',gtk.RESPONSE_CANCEL, 'gtk-save',gtk.RESPONSE_OK))
+            file_dialog = Gtk.FileChooserDialog('Save a Data File...', None,
+                Gtk.FileChooserAction.SAVE, 
('gtk-cancel',Gtk.ResponseType.CANCEL, 'gtk-save',Gtk.ResponseType.OK))
             file_dialog.set_do_overwrite_confirmation(True)
             file_dialog.set_current_name(basename) #show the current filename
         else:
@@ -350,7 +353,7 @@ class FileParam(EntryParam):
         file_dialog.set_current_folder(dirname) #current directory
         file_dialog.set_select_multiple(False)
         file_dialog.set_local_only(True)
-        if gtk.RESPONSE_OK == file_dialog.run(): #run the dialog
+        if Gtk.ResponseType.OK == file_dialog.run(): #run the dialog
             file_path = file_dialog.get_filename() #get the file path
             self._input.set_text(file_path)
             self._editing_callback()
diff --git a/grc/gui/ParserErrorsDialog.py b/grc/gui/ParserErrorsDialog.py
index 68ee459..f49e692 100644
--- a/grc/gui/ParserErrorsDialog.py
+++ b/grc/gui/ParserErrorsDialog.py
@@ -17,14 +17,15 @@ along with this program; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 """
 
-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 Constants import MIN_DIALOG_WIDTH, MIN_DIALOG_HEIGHT
 
 
-class ParserErrorsDialog(gtk.Dialog):
+class ParserErrorsDialog(Gtk.Dialog):
     """
     A dialog for viewing parser errors
     """
@@ -36,31 +37,31 @@ class ParserErrorsDialog(gtk.Dialog):
         Args:
             block: a block instance
         """
-        gtk.Dialog.__init__(self, title='Parser Errors', 
buttons=(gtk.STOCK_CLOSE, gtk.RESPONSE_ACCEPT))
+        GObject.GObject.__init__(self, title='Parser Errors', 
buttons=(Gtk.STOCK_CLOSE, Gtk.ResponseType.ACCEPT))
 
         self._error_logs = None
-        self.tree_store = gtk.TreeStore(str)
+        self.tree_store = Gtk.TreeStore(str)
         self.update_tree_store(error_logs)
 
-        column = gtk.TreeViewColumn('XML Parser Errors by Filename')
-        renderer = gtk.CellRendererText()
+        column = Gtk.TreeViewColumn('XML Parser Errors by Filename')
+        renderer = Gtk.CellRendererText()
         column.pack_start(renderer, True)
         column.add_attribute(renderer, 'text', 0)
         column.set_sort_column_id(0)
 
-        self.tree_view = tree_view = gtk.TreeView(self.tree_store)
+        self.tree_view = tree_view = Gtk.TreeView(self.tree_store)
         tree_view.set_enable_search(False)  # disable pop up search box
         tree_view.set_search_column(-1)  # really disable search
         tree_view.set_reorderable(False)
         tree_view.set_headers_visible(False)
-        tree_view.get_selection().set_mode(gtk.SELECTION_NONE)
+        tree_view.get_selection().set_mode(Gtk.SelectionMode.NONE)
         tree_view.append_column(column)
 
         for row in self.tree_store:
             tree_view.expand_row(row.path, False)
 
-        scrolled_window = gtk.ScrolledWindow()
-        scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
+        scrolled_window = Gtk.ScrolledWindow()
+        scrolled_window.set_policy(Gtk.PolicyType.AUTOMATIC, 
Gtk.PolicyType.AUTOMATIC)
         scrolled_window.add_with_viewport(tree_view)
 
         self.vbox.pack_start(scrolled_window, True)
@@ -95,6 +96,6 @@ class ParserErrorsDialog(gtk.Dialog):
         Returns:
             true if the response was accept
         """
-        response = gtk.Dialog.run(self)
+        response = Gtk.Dialog.run(self)
         self.destroy()
-        return response == gtk.RESPONSE_ACCEPT
+        return response == Gtk.ResponseType.ACCEPT
diff --git a/grc/gui/Port.py b/grc/gui/Port.py
index 6314b7e..02cef5d 100644
--- a/grc/gui/Port.py
+++ b/grc/gui/Port.py
@@ -17,9 +17,9 @@ along with this program; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 """
 
-import pygtk
-pygtk.require('2.0')
-import gtk
+import gi
+gi.require_version('Gtk', '3.0')
+from gi.repository import Gtk
 
 from . import Actions, Colors, Utils
 from .Constants import (
@@ -115,7 +115,7 @@ class Port(_Port, Element):
         Element.create_labels(self)
         self._bg_color = Colors.get_color(self.get_color())
         # create the layout
-        layout = gtk.DrawingArea().create_pango_layout('')
+        layout = Gtk.DrawingArea().create_pango_layout('')
         layout.set_markup(Utils.parse_template(PORT_MARKUP_TMPL, port=self, 
font=PORT_FONT))
         self.w, self.h = layout.get_pixel_size()
         self.W = 2 * PORT_LABEL_PADDING + self.w
diff --git a/grc/gui/PropsDialog.py b/grc/gui/PropsDialog.py
index 7c66a77..8367f87 100644
--- a/grc/gui/PropsDialog.py
+++ b/grc/gui/PropsDialog.py
@@ -17,15 +17,17 @@ along with this program; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 """
 
-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 Actions
 from Dialogs import SimpleTextDisplay
 from Constants import MIN_DIALOG_WIDTH, MIN_DIALOG_HEIGHT, FONT_SIZE
 import Utils
-import pango
+from gi.repository import Pango
 
 TAB_LABEL_MARKUP_TMPL="""\
 #set $foreground = $valid and 'black' or 'red'
@@ -43,14 +45,14 @@ def get_title_label(title):
     Returns:
         a gtk object
     """
-    label = gtk.Label()
+    label = Gtk.Label()
     label.set_markup('\n<b><span underline="low">%s</span>:</b>\n'%title)
-    hbox = gtk.HBox()
+    hbox = Gtk.HBox()
     hbox.pack_start(label, False, False, padding=11)
     return hbox
 
 
-class PropsDialog(gtk.Dialog):
+class PropsDialog(Gtk.Dialog):
     """
     A dialog to set block parameters, view errors, and view documentation.
     """
@@ -64,64 +66,64 @@ class PropsDialog(gtk.Dialog):
         """
         self._hash = 0
 
-        gtk.Dialog.__init__(
+        GObject.GObject.__init__(
             self,
             title='Properties: %s' % block.get_name(),
-            buttons=(gtk.STOCK_OK, gtk.RESPONSE_ACCEPT,
-                     gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT,
-                     gtk.STOCK_APPLY, gtk.RESPONSE_APPLY)
+            buttons=(Gtk.STOCK_OK, Gtk.ResponseType.ACCEPT,
+                     Gtk.STOCK_CANCEL, Gtk.ResponseType.REJECT,
+                     Gtk.STOCK_APPLY, Gtk.ResponseType.APPLY)
         )
-        self.set_response_sensitive(gtk.RESPONSE_APPLY, False)
+        self.set_response_sensitive(Gtk.ResponseType.APPLY, False)
         self.set_size_request(MIN_DIALOG_WIDTH, MIN_DIALOG_HEIGHT)
         self._block = block
 
-        vpaned = gtk.VPaned()
-        self.vbox.pack_start(vpaned)
+        vpaned = Gtk.VPaned()
+        self.vbox.pack_start(vpaned, True, True, 0)
 
         # Notebook to hold param boxes
-        notebook = gtk.Notebook()
+        notebook = Gtk.Notebook()
         notebook.set_show_border(False)
         notebook.set_scrollable(True)  # scroll arrows for page tabs
-        notebook.set_tab_pos(gtk.POS_TOP)
+        notebook.set_tab_pos(Gtk.PositionType.TOP)
         vpaned.pack1(notebook, True)
 
         # Params boxes for block parameters
         self._params_boxes = list()
         for tab in block.get_param_tab_labels():
-            label = gtk.Label()
-            vbox = gtk.VBox()
-            scroll_box = gtk.ScrolledWindow()
-            scroll_box.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
+            label = Gtk.Label()
+            vbox = Gtk.VBox()
+            scroll_box = Gtk.ScrolledWindow()
+            scroll_box.set_policy(Gtk.PolicyType.AUTOMATIC, 
Gtk.PolicyType.AUTOMATIC)
             scroll_box.add_with_viewport(vbox)
             notebook.append_page(scroll_box, label)
             self._params_boxes.append((tab, label, vbox))
 
         # Docs for the block
         self._docs_text_display = doc_view = SimpleTextDisplay()
-        doc_view.get_buffer().create_tag('b', weight=pango.WEIGHT_BOLD)
-        self._docs_box = gtk.ScrolledWindow()
-        self._docs_box.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
+        doc_view.get_buffer().create_tag('b', weight=Pango.Weight.BOLD)
+        self._docs_box = Gtk.ScrolledWindow()
+        self._docs_box.set_policy(Gtk.PolicyType.AUTOMATIC, 
Gtk.PolicyType.AUTOMATIC)
         self._docs_box.add_with_viewport(self._docs_text_display)
-        notebook.append_page(self._docs_box, gtk.Label("Documentation"))
+        notebook.append_page(self._docs_box, Gtk.Label(label="Documentation"))
 
         # Generated code for the block
         if Actions.TOGGLE_SHOW_CODE_PREVIEW_TAB.get_active():
             self._code_text_display = code_view = SimpleTextDisplay()
-            code_view.set_wrap_mode(gtk.WRAP_NONE)
-            code_view.get_buffer().create_tag('b', weight=pango.WEIGHT_BOLD)
-            code_view.modify_font(pango.FontDescription(
+            code_view.set_wrap_mode(Gtk.WrapMode.NONE)
+            code_view.get_buffer().create_tag('b', weight=Pango.Weight.BOLD)
+            code_view.modify_font(Pango.FontDescription(
                 'monospace %d' % FONT_SIZE))
-            code_box = gtk.ScrolledWindow()
-            code_box.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
+            code_box = Gtk.ScrolledWindow()
+            code_box.set_policy(Gtk.PolicyType.AUTOMATIC, 
Gtk.PolicyType.AUTOMATIC)
             code_box.add_with_viewport(self._code_text_display)
-            notebook.append_page(code_box, gtk.Label("Generated Code"))
+            notebook.append_page(code_box, Gtk.Label(label="Generated Code"))
         else:
             self._code_text_display = None
 
         # Error Messages for the block
         self._error_messages_text_display = SimpleTextDisplay()
-        self._error_box = gtk.ScrolledWindow()
-        self._error_box.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
+        self._error_box = Gtk.ScrolledWindow()
+        self._error_box.set_policy(Gtk.PolicyType.AUTOMATIC, 
Gtk.PolicyType.AUTOMATIC)
         self._error_box.add_with_viewport(self._error_messages_text_display)
         vpaned.pack2(self._error_box)
         vpaned.set_position(int(0.65 * MIN_DIALOG_HEIGHT))
@@ -162,7 +164,7 @@ class PropsDialog(gtk.Dialog):
         self.update_gui()
 
     def _activate_apply(self, *args):
-        self.set_response_sensitive(gtk.RESPONSE_APPLY, True)
+        self.set_response_sensitive(Gtk.ResponseType.APPLY, True)
 
     def update_gui(self, widget=None, force=False):
         """
@@ -275,21 +277,19 @@ class PropsDialog(gtk.Dialog):
         Returns:
             false to forward the keypress
         """
-        if (event.keyval == gtk.keysyms.Return and
-            event.state & gtk.gdk.CONTROL_MASK == 0 and
-            not isinstance(widget.get_focus(), gtk.TextView)
+        if (event.keyval == Gdk.KEY_Return and
+            event.get_state() & Gdk.ModifierType.CONTROL_MASK == 0 and
+            not isinstance(widget.get_focus(), Gtk.TextView)
         ):
-            self.response(gtk.RESPONSE_ACCEPT)
+            self.response(Gtk.ResponseType.ACCEPT)
             return True  # handled here
         return False  # forward the keypress
 
     def _handle_response(self, widget, response):
-        if response in (gtk.RESPONSE_APPLY, gtk.RESPONSE_ACCEPT):
+        if response in (Gtk.ResponseType.APPLY, Gtk.ResponseType.ACCEPT):
             for tab, label, vbox in self._params_boxes:
                 for child in vbox.get_children():
                     child.apply_pending_changes()
-            self.set_response_sensitive(gtk.RESPONSE_APPLY, False)
+            self.set_response_sensitive(Gtk.ResponseType.APPLY, False)
             return True
         return False
-
-
diff --git a/grc/gui/Utils.py b/grc/gui/Utils.py
index 51b9b19..054af57 100644
--- a/grc/gui/Utils.py
+++ b/grc/gui/Utils.py
@@ -17,17 +17,20 @@ along with this program; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 """
 
-import pygtk
-pygtk.require('2.0')
-import gtk
-import gobject
+import gi
+gi.require_version('Gtk', '3.0')
+from gi.repository import Gtk
+from gi.repository import Gdk
+from gi.repository import GdkPixbuf
+from gi.repository import GObject
+from gi.repository import GLib
 
 from Cheetah.Template import Template
 
 from Constants import POSSIBLE_ROTATIONS, CANVAS_GRID_SIZE
 
 
-def rotate_pixmap(gc, src_pixmap, dst_pixmap, 
angle=gtk.gdk.PIXBUF_ROTATE_COUNTERCLOCKWISE):
+def rotate_pixmap(gc, src_pixmap, dst_pixmap, 
angle=GdkPixbuf.PixbufRotation.COUNTERCLOCKWISE):
     """
     Load the destination pixmap with a rotated version of the source pixmap.
     The source pixmap will be loaded into a pixbuf, rotated, and drawn to the 
destination pixmap.
@@ -40,8 +43,8 @@ def rotate_pixmap(gc, src_pixmap, dst_pixmap, 
angle=gtk.gdk.PIXBUF_ROTATE_COUNTE
         angle: the angle to rotate by
     """
     width, height = src_pixmap.get_size()
-    pixbuf = gtk.gdk.Pixbuf(
-        colorspace=gtk.gdk.COLORSPACE_RGB,
+    pixbuf = GdkPixbuf.Pixbuf(
+        colorspace=GdkPixbuf.Colorspace.RGB,
         has_alpha=False, bits_per_sample=8,
         width=width, height=height,
     )
@@ -98,7 +101,7 @@ def encode(value):
     """
 
     valid_utf8 = value.decode('utf-8', errors='replace').encode('utf-8')
-    return gobject.markup_escape_text(valid_utf8)
+    return GLib.markup_escape_text(valid_utf8)
 
 
 class TemplateParser(object):
diff --git a/grc/main.py b/grc/main.py
index ae7a0ce..cd98637 100755
--- a/grc/main.py
+++ b/grc/main.py
@@ -17,7 +17,10 @@
 
 import optparse
 
-import gtk
+import gi
+gi.require_version('Gtk', '3.0')
+from gi.repository import Gtk
+
 from gnuradio import gr
 
 from .gui.Platform import Platform
@@ -40,7 +43,7 @@ def main():
     options, args = parser.parse_args()
 
     try:
-        gtk.window_set_default_icon(gtk.IconTheme().load_icon('gnuradio-grc', 
256, 0))
+        Gtk.window_set_default_icon(Gtk.IconTheme().load_icon('gnuradio-grc', 
256, 0))
     except:
         pass
 
@@ -51,5 +54,5 @@ def main():
         install_prefix=gr.prefix()
     )
     ActionHandler(args, platform)
-    gtk.main()
+    Gtk.main()
 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]