chiark / gitweb /
mon/tripemon.in: Support the new-style bindings for Gtk and friends.
authorMark Wooding <mdw@distorted.org.uk>
Sat, 24 May 2014 13:00:03 +0000 (14:00 +0100)
committerMark Wooding <mdw@distorted.org.uk>
Sun, 20 Jul 2014 00:42:30 +0000 (01:42 +0100)
This is a fair amount of tedious work, especially if we want to keep
compatibility with the old versions of things.

Highlights:

  * There are separate modules now for GLib and GObject, as in the
    underlying C libraries; the old Python bindings merged the two
    together.

  * Gtk enumerations and flags now live in their own classes, so we dig
    them out for compatibility.

  * Because the new bindings are dynamically generated from
    introspection data, they don't make allowances for (say) `raise'
    being a Python reserved word.

  * Some functions which used to have default arguments no longer do, so
    we have to call them the hard way.

mon/tripemon.in
svc/conntrack.in

index 42bad2b..b7c5024 100644 (file)
@@ -40,11 +40,33 @@ import time as TIME
 import re as RX
 from cStringIO import StringIO
 
-import pygtk
-pygtk.require('2.0')
-import gtk as G
-import gobject as GO
-import gtk.gdk as GDK
+try:
+  if OS.getenv('TRIPEMON_FORCE_GI'): raise ImportError
+  import pygtk
+  pygtk.require('2.0')
+  import gtk as G
+  import gobject as GO
+  import gtk.gdk as GDK
+  GL = GO
+  def raise_window(w): w.window.raise_()
+  combo_box_text = G.combo_box_new_text
+  def set_entry_bg(e, c): e.modify_base(G.STATE_NORMAL, c)
+except ImportError:
+  from gi.repository import GObject as GO, GLib as GL, Gtk as G, Gdk as GDK
+  G.WINDOW_TOPLEVEL = G.WindowType.TOPLEVEL
+  G.EXPAND = G.AttachOptions.EXPAND
+  G.SHRINK = G.AttachOptions.SHRINK
+  G.FILL = G.AttachOptions.FILL
+  G.SORT_ASCENDING = G.SortType.ASCENDING
+  G.POLICY_AUTOMATIC = G.PolicyType.AUTOMATIC
+  G.SHADOW_IN = G.ShadowType.IN
+  G.SELECTION_NONE = G.SelectionMode.NONE
+  G.DIALOG_MODAL = G.DialogFlags.MODAL
+  G.RESPONSE_CANCEL = G.ResponseType.CANCEL
+  G.RESPONSE_NONE = G.ResponseType.NONE
+  def raise_window(w): getattr(w.get_window(), 'raise')()
+  combo_box_text = G.ComboBoxText
+  def set_entry_bg(e, c): e.modify_bg(G.StateType.NORMAL, c)
 
 if OS.getenv('TRIPE_DEBUG_MONITOR') is not None:
   T._debug = 1
@@ -175,15 +197,15 @@ class GIOWatcher (object):
   """
   Monitor I/O events using glib.
   """
-  def __init__(me, conn, mc = GO.main_context_default()):
+  def __init__(me, conn, mc = GL.main_context_default()):
     me._conn = conn
     me._watch = None
     me._mc = mc
   def connected(me, sock):
-    me._watch = GO.io_add_watch(sock, GO.IO_IN,
+    me._watch = GL.io_add_watch(sock, GL.IO_IN,
                                 lambda *hunoz: me._conn.receive())
   def disconnected(me):
-    GO.source_remove(me._watch)
+    GL.source_remove(me._watch)
     me._watch = None
   def iterate(me):
     me._mc.iteration(True)
@@ -664,7 +686,7 @@ class WindowSlot (HookClient):
   def open(me):
     """Opens the window, creating it if necessary."""
     if me.window:
-      me.window.window.raise_()
+      raise_window(me.window)
     else:
       me.window = me.createfunc()
       me.hook(me.window.closehook, me.closed)
@@ -728,10 +750,10 @@ class ValidatingEntry (G.Entry):
     """Check the current text and update validp and the text colour."""
     if me.validate(G.Entry.get_text(me)):
       me.validp = True
-      me.modify_base(G.STATE_NORMAL, None)
+      set_entry_bg(me, None)
     else:
       me.validp = False
-      me.modify_base(G.STATE_NORMAL, me.is_sensitive() and c_red or None)
+      set_entry_bg(me, me.is_sensitive() and c_red or None)
 
   def get_text(me):
     """
@@ -795,7 +817,7 @@ def moanbox(msg):
                buttons = ((G.STOCK_OK, G.RESPONSE_NONE)))
   label = G.Label(msg)
   label.set_padding(20, 20)
-  d.vbox.pack_start(label)
+  d.vbox.pack_start(label, True, True, 0)
   label.show()
   d.run()
   d.destroy()
@@ -938,7 +960,7 @@ class Pinger (T.Coroutine, HookClient):
 
   def _connected(me):
     """Respond to connection: start pinging thngs."""
-    me._timer = GO.timeout_add(1000, me._timerfunc)
+    me._timer = GL.timeout_add(1000, me._timerfunc)
 
   def _timerfunc(me):
     """Timer function: put a timer event on the queue."""
@@ -947,7 +969,7 @@ class Pinger (T.Coroutine, HookClient):
 
   def _disconnected(me, reason):
     """Respond to disconnection: stop pinging."""
-    GO.source_remove(me._timer)
+    GL.source_remove(me._timer)
 
   def run(me):
     """
@@ -1019,7 +1041,7 @@ class AddPeerDialog (MyDialog):
   def _setup(me):
     """Coroutine function: background setup for AddPeerDialog."""
     table = GridPacker()
-    me.vbox.pack_start(table)
+    me.vbox.pack_start(table, True, True, 0)
     me.e_name = table.labelled('Name',
                                ValidatingEntry(r'^[^\s.:]+$', '', 16),
                                width = 3)
@@ -1031,8 +1053,7 @@ class AddPeerDialog (MyDialog):
                                                '4070',
                                                5))
     me.c_keepalive = G.CheckButton('Keepalives')
-    me.l_tunnel = table.labelled('Tunnel',
-                                 G.combo_box_new_text(),
+    me.l_tunnel = table.labelled('Tunnel', combo_box_text(),
                                  newlinep = True, width = 3)
     me.tuns = conn.tunnels()
     for t in me.tuns:
@@ -1147,7 +1168,7 @@ class TraceOptions (MyDialog):
       text = desc[0].upper() + desc[1:]
       ticky = G.CheckButton(text)
       ticky.set_active(st == '+')
-      me.vbox.pack_start(ticky)
+      me.vbox.pack_start(ticky, True, True, 0)
       me.opts.append((ch, ticky))
     me.show_all()
   def ok(me):
@@ -1294,7 +1315,7 @@ class PeerWindow (MyWindow):
         stat[s] = trans(stat[s])
       for label, format in statslayout:
         me.e[label].set_text(format % stat)
-      GO.timeout_add(1000, lambda: me.cr.switch() and False)
+      GL.timeout_add(1000, lambda: me.cr.switch() and False)
       me.cr.parent.switch()
     me.cr = None
 
@@ -1490,7 +1511,7 @@ class MonitorWindow (MyWindow):
     me.ui.add_ui_from_string(uidef)
 
     ## Construct the menu bar.
-    vbox.pack_start(me.ui.get_widget('/menubar'), expand = False)
+    vbox.pack_start(me.ui.get_widget('/menubar'), False, True, 0)
     me.add_accel_group(me.ui.get_accel_group())
 
     ## Construct and attach the auto-peers menu.  (This is a horrible bodge
@@ -1531,12 +1552,12 @@ class MonitorWindow (MyWindow):
     me.list.set_reorderable(True)
     me.list.get_selection().set_mode(G.SELECTION_NONE)
     scr.add(me.list)
-    vbox.pack_start(scr)
+    vbox.pack_start(scr, True, True, 0)
 
     ## Construct the status bar, and listen on hooks which report changes to
     ## connection status.
     me.status = G.Statusbar()
-    vbox.pack_start(me.status, expand = False)
+    vbox.pack_start(me.status, False, True, 0)
     me.hook(conn.connecthook, cr(me.connected))
     me.hook(conn.disconnecthook, me.disconnected)
     me.hook(conn.notehook, me.notify)
index c86a7d8..f4b717b 100644 (file)
@@ -39,7 +39,8 @@ import tripe as T
 import dbus as D
 for i in ['mainloop', 'mainloop.glib']:
   __import__('dbus.%s' % i)
-import gobject as G
+try: from gi.repository import GLib as G
+except ImportError: import gobject as G
 from struct import pack, unpack
 
 SM = T.svcmgr