Index: .hgignore
===================================================================
--- .hgignore	(revision 758)
+++ .hgignore	(revision 976)
@@ -12,2 +12,3 @@
 debug.log
 moodlesetup.txt
+docker/msys/id_rsa
Index: MANIFEST.in
===================================================================
--- MANIFEST.in	(revision 916)
+++ MANIFEST.in	(revision 939)
@@ -1,5 +1,4 @@
 include mlx.nsi
-include makeinst.bat
-include winemakeinst.bat
+include makeinst.sh
 include license.txt
 include runmlx.py
Index: TODO
===================================================================
--- TODO	(revision 285)
+++ TODO	(revision 1009)
@@ -0,0 +1,5 @@
+- Python 3:
+  - icons besides menus
+  - X-Plane on Linux and Windows
+  - streamline distribution (remove unnecessary stuff)
+  - check some colours on Windows (e.g. the tab background)
Index: dcdatagen.py
===================================================================
--- dcdatagen.py	(revision 599)
+++ dcdatagen.py	(revision 932)
@@ -1,3 +1,3 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 # -*- coding: utf-8 -*-
 
@@ -764,12 +764,12 @@
     numLines = len(lines)
     if numLines==0:
-        print >> file, "msgstr \"\""
+        print("msgstr \"\"", file=file)
     elif numLines==1:
-        print >> file, "msgstr \"%s\"" % (lines[0])
+        print("msgstr \"%s\"" % (lines[0]), file=file)
     else:
-        print >> file, "msgstr \"\""
+        print("msgstr \"\"", file=file)
         for i in range(0, numLines):
-            print >> file, "\"%s%s\"" % (lines[i], "" if i==(numLines-1) else "\\n")
-    print >> file
+            print("\"%s%s\"" % (lines[i], "" if i==(numLines-1) else "\\n"), file=file)
+    print(file=file)
 
 #-------------------------------------------------------------------------------
@@ -789,8 +789,8 @@
             poFile = open(poPath, "wt")
             poFiles.append(poFile)
-            print >> poFile, "msgid \"\""
-            print >> poFile, "msgstr \"\""
-            print >> poFile, "\"Content-Type: text/plain; charset=utf-8\\n\""
-            print >> poFile, "\"Content-Transfer-Encoding: 8bit\\n\""
+            print("msgid \"\"", file=poFile)
+            print("msgstr \"\"", file=poFile)
+            print("\"Content-Type: text/plain; charset=utf-8\\n\"", file=poFile)
+            print("\"Content-Transfer-Encoding: 8bit\\n\"", file=poFile)
 
         (baseData, headings, headingFlags, rows) = table
@@ -801,5 +801,5 @@
             for j in range(0, numLanguages):
                 poFile = poFiles[j]
-                print >> poFile, "msgid \"%sheading%d\"" % (poPrefix, i)
+                print("msgid \"%sheading%d\"" % (poPrefix, i), file=poFile)
                 generateMsgStr(poFile, heading[j])
 
@@ -810,5 +810,5 @@
                 for i in range(0, numLanguages):
                     poFile = poFiles[i]
-                    print >> poFile, "msgid \"%srow%d\"" % (poPrefix, rowIndex)
+                    print("msgid \"%srow%d\"" % (poPrefix, rowIndex), file=poFile)
                     generateMsgStr(poFile, columns[i])
             elif type==DELAYCODE:
@@ -819,20 +819,20 @@
                             if column[i]:
                                 poFile = poFiles[i]
-                                print >> poFile, "msgid \"%srow%d_col%d\"" % \
-                                  (poPrefix, rowIndex, columnIndex)
+                                print("msgid \"%srow%d_col%d\"" % \
+                                  (poPrefix, rowIndex, columnIndex), file=poFile)
                                 generateMsgStr(poFile, column[i])
                     columnIndex += 1
             rowIndex += 1
 
-        print >> dcdata, "import mlx.const as const"
-        print >> dcdata, "from mlx.i18n import xstr"
-        print >> dcdata
-        print >> dcdata, "CAPTION = 1"
-        print >> dcdata, "DELAYCODE = 2"
-        print >> dcdata
+        print("import mlx.const as const", file=dcdata)
+        print("from mlx.i18n import xstr", file=dcdata)
+        print(file=dcdata)
+        print("CAPTION = 1", file=dcdata)
+        print("DELAYCODE = 2", file=dcdata)
+        print(file=dcdata)
 
         tableMask = 1
         for i in range(0, len(tablePrefixes)):
-            print >> dcdata, "_%s_code2meaning = {" % (tablePrefixes[i],)
+            print("_%s_code2meaning = {" % (tablePrefixes[i],), file=dcdata)
 
             columnIndexes = []
@@ -850,25 +850,25 @@
 
                 if type==DELAYCODE:
-                    print >> dcdata, "    \"%s\": \"%s\"," % \
-                      (str(columns[codeIndex]).strip(), columns[meaningIndex][0].replace("\n", ""))
-
-            print >> dcdata, "}"
-            print >> dcdata
+                    print("    \"%s\": \"%s\"," % \
+                      (str(columns[codeIndex]).strip(), columns[meaningIndex][0].replace("\n", "")), file=dcdata)
+
+            print("}", file=dcdata)
+            print(file=dcdata)
 
             tableMask <<= 1
 
-        print >> dcdata, "def _extract(table, row):"
-        print >> dcdata, "    code = row[0].strip()"
-        print >> dcdata, "    meaning = table[code] if code in table else None"
-        print >> dcdata, "    return code + ((\" (\" + meaning + \")\") if meaning else \"\")"
-        print >> dcdata
+        print("def _extract(table, row):", file=dcdata)
+        print("    code = row[0].strip()", file=dcdata)
+        print("    meaning = table[code] if code in table else None", file=dcdata)
+        print("    return code + ((\" (\" + meaning + \")\") if meaning else \"\")", file=dcdata)
+        print(file=dcdata)
 
         tableMask = 1
         for i in range(0, len(tablePrefixes)):
 
-            print >> dcdata, "_%s_data = (" % (tablePrefixes[i],)
-            print >> dcdata, "    lambda row: _extract(_%s_code2meaning, row)," % \
-              (tablePrefixes[i],)
-            print >> dcdata, "    [",
+            print("_%s_data = (" % (tablePrefixes[i],), file=dcdata)
+            print("    lambda row: _extract(_%s_code2meaning, row)," % \
+              (tablePrefixes[i],), file=dcdata)
+            print("    [", end=' ', file=dcdata)
 
             columnIndexes = []
@@ -876,11 +876,11 @@
                 if ( (headingFlags[j]&tableMask)==tableMask ):
                     if columnIndexes:
-                        print >> dcdata, ",",
-                    print >> dcdata, "xstr(\"%sheading%d\")" % (poPrefix, j),
+                        print(",", end=' ', file=dcdata)
+                    print("xstr(\"%sheading%d\")" % (poPrefix, j), end=' ', file=dcdata)
                     columnIndexes.append(j)
 
-            print >> dcdata, "],"
-
-            print >> dcdata, "    ["
+            print("],", file=dcdata)
+
+            print("    [", file=dcdata)
 
             rowIndex = 0
@@ -891,43 +891,43 @@
 
                 if type==CAPTION:
-                    print >> dcdata, "        (CAPTION, xstr(\"%srow%d\"))," % \
-                      (poPrefix, rowIndex)
+                    print("        (CAPTION, xstr(\"%srow%d\"))," % \
+                      (poPrefix, rowIndex), file=dcdata)
                 elif type==DELAYCODE:
-                    print >> dcdata, "        (DELAYCODE, ["
+                    print("        (DELAYCODE, [", file=dcdata)
                     for j in columnIndexes:
                         column = columns[j]
                         if j!=columnIndexes[0]:
-                            print >> dcdata, ","
+                            print(",", file=dcdata)
                         if isinstance(column, list):
                             if column[0]:
-                                print >> dcdata, "            xstr(\"%srow%d_col%d\")"  % \
-                                (poPrefix, rowIndex, j),
+                                print("            xstr(\"%srow%d_col%d\")"  % \
+                                (poPrefix, rowIndex, j), end=' ', file=dcdata)
                             else:
-                                print >> dcdata, "            \"\"",
+                                print("            \"\"", end=' ', file=dcdata)
                         else:
-                            print >> dcdata, "            \"%s\""  % \
-                              (column,),
-                    print >> dcdata, "] ),"
+                            print("            \"%s\""  % \
+                              (column,), end=' ', file=dcdata)
+                    print("] ),", file=dcdata)
                 rowIndex += 1
 
-            print >> dcdata, "    ]"
-
-            print >> dcdata, ")"
-            print >> dcdata
+            print("    ]", file=dcdata)
+
+            print(")", file=dcdata)
+            print(file=dcdata)
 
             tableMask <<= 1
 
-        print >> dcdata, "def getTable(aircraftType):"
+        print("def getTable(aircraftType):", file=dcdata)
         first = True
         for i in range(0, len(tablePrefixes)):
             tablePrefix = tablePrefixes[i]
             for typeSuffix in typeGroups[i]:
-                print >> dcdata, "    %s aircraftType==const.AIRCRAFT_%s:" % \
-                  ("if" if first else "elif", typeSuffix)
-                print >> dcdata, "        return _%s_data" % (tablePrefix,)
+                print("    %s aircraftType==const.AIRCRAFT_%s:" % \
+                  ("if" if first else "elif", typeSuffix), file=dcdata)
+                print("        return _%s_data" % (tablePrefix,), file=dcdata)
                 first = False
 
-        print >> dcdata, "    else:"
-        print >> dcdata, "        return None"
+        print("    else:", file=dcdata)
+        print("        return None", file=dcdata)
     finally:
         for poFile in poFiles:
Index: diffdist.py
===================================================================
--- diffdist.py	(revision 310)
+++ diffdist.py	(revision 919)
@@ -18,5 +18,5 @@
 def usage():
     """Print a usage message."""
-    print "Usage: %s <old dist dir> <new dist dir>" % (sys.argv[0],)
+    print("Usage: %s <old dist dir> <new dist dir>" % (sys.argv[0],))
 
 #--------------------------------------------------------------------------
@@ -62,11 +62,11 @@
 
                 if numDiffs<=4:
-                    print "File %s is considered to be the same in both versions with %d changes" % \
-                          (path, numDiffs)
+                    print("File %s is considered to be the same in both versions with %d changes" % \
+                          (path, numDiffs))
                     finalManifest.addFile(path, oldSize, oldSum)
                     copyOld = True
 
         if not copyOld:
-            print ">>> File %s is being copied" % (path,)
+            print(">>> File %s is being copied" % (path,))
             tarFile.add(os.path.join(newDirectory, path), arcname = path)
             
@@ -74,5 +74,5 @@
     with os.fdopen(fd, "wt") as f:
         finalManifest.writeInto(f)
-    os.chmod(path, 0644)
+    os.chmod(path, 0o644)
     tarFile.add(path, arcname = manifestName)
     tarFile.close()
@@ -80,10 +80,10 @@
     os.remove(path)
 
-    print
-    print "%s created" % (tarName,)
+    print()
+    print("%s created" % (tarName,))
     if removed:
-        print
-        print "Files to remove:"
-        print
+        print()
+        print("Files to remove:")
+        print()
         for path in removed:
-            print "  ", path
+            print("  ", path)
Index: diffdist.sh
===================================================================
--- diffdist.sh	(revision 189)
+++ diffdist.sh	(revision 966)
@@ -6,3 +6,3 @@
 export PYTHONPATH
 
-exec python "${scriptdir}/diffdist.py" "$@"
+exec python3 "${scriptdir}/diffdist.py" "$@"
Index: cker/build-mlxwinebuild.sh
===================================================================
--- docker/build-mlxwinebuild.sh	(revision 916)
+++ 	(revision )
@@ -1,9 +1,0 @@
-#!/bin/bash
-
-set -e -u
-
-sdistfile="${1}"
-sdistdir=$(cd $(dirname "${sdistfile}") && pwd)
-
-docker run --rm -v "${sdistdir}:/root/dist" mlxwinebuild build $(basename "${sdistfile}") $(id -u) $(id -g)
-#docker run -it --rm -v "${sdistdir}:/root/dist" mlxwinebuild bash
Index: cker/context/Dockerfile
===================================================================
--- docker/context/Dockerfile	(revision 916)
+++ 	(revision )
@@ -1,17 +1,0 @@
-FROM ubuntu:cosmic
-
-RUN dpkg --add-architecture i386 && \
-    apt-get update -y && \
-    /usr/bin/env DEBIAN_FRONTEND=noninteractive apt-get install -y \
-        tzdata \
-        wget \
-        wine \
-        wine32 && \
-    echo "Europe/Budapest" > /etc/timezone && \
-    rm -f /etc/localtime && \
-    dpkg-reconfigure -f noninteractive tzdata
-
-ADD entrypoint.sh setup.sh build.sh /root/
-
-ENTRYPOINT ["/root/entrypoint.sh"]
-CMD ["bash"]
Index: cker/context/build.sh
===================================================================
--- docker/context/build.sh	(revision 916)
+++ 	(revision )
@@ -1,37 +1,0 @@
-#!/bin/bash
-
-set -e -u
-
-scriptdir=$(cd $(dirname $0) && pwd)
-
-sdistname="${1}"
-uid="${2}"
-gid="${3}"
-
-mlxdirname=$(basename "${sdistname}" .tar.gz)
-version=$(echo "${mlxdirname}" | sed "s:mlx-::")
-
-cd "${scriptdir}"
-
-tar xf "dist/${sdistname}"
-
-cd "${mlxdirname}"
-
-echo "winemakeinst.bat" | wine cmd
-
-echo
-echo "Copying the 'dist' directory..."
-destdistdir="../dist/dist-${version}"
-
-rm -rf "${destdistdir}"
-cp -a dist "${destdistdir}"
-chown -R ${uid}:${gid} "${destdistdir}"
-
-echo
-echo "Copying the setup program..."
-
-cp "MAVA Logger X-${version}-Setup.exe" ../dist
-chown ${uid}:${gid} "../dist/MAVA Logger X-${version}-Setup.exe"
-
-echo
-echo "Done."
Index: cker/context/entrypoint.sh
===================================================================
--- docker/context/entrypoint.sh	(revision 916)
+++ 	(revision )
@@ -1,12 +1,0 @@
-#!/bin/bash
-
-scriptdir=$(cd $(dirname $0) && pwd)
-
-if test "$1" = "initialize"; then
-    "${scriptdir}/setup.sh"
-elif test "$1" = "build"; then
-    shift
-    "${scriptdir}/build.sh" "$@"
-else
-    exec "$@"
-fi
Index: cker/context/setup.sh
===================================================================
--- docker/context/setup.sh	(revision 916)
+++ 	(revision )
@@ -1,52 +1,0 @@
-#!/bin/bash
-
-set -e -u
-
-cdrive="${HOME}/.wine/drive_c"
-ctmpdir="${cdrive}/tmp"
-cpythondir="${cdrive}/Python27"
-cwinsysdir="${cdrive}/windows/system32"
-
-if test -f "${cpythondir}/python.exe"; then
-    echo "Image already configured, not doing anything!"
-    exit 1
-fi
-
-echo "Preparing image to be able to build MAVA Logger X for Windows"
-echo
-
-echo "Downloading and extracting the extra packages..."
-
-wget -O - mlx.varadiistvan.hu/update/winepkgs.tar | tar xf -
-
-echo
-echo "Installing extra packages..."
-
-export WINEARCH=win32
-
-echo "exit" | wine cmd
-wine msiexec /i python-2.7.2.msi
-wine msiexec /i cefpython3-31.2.py2.7-win32.msi
-wine msiexec /i pygtk-all-in-one-2.24.1.win32-py2.7.msi
-wine msiexec /i pyuipc-0.4.win32-py2.7.msi
-wine msiexec /i xplra-0.2.win32.msi
-
-wine pywin32-217.win32-py2.7.exe
-wine py2exe-0.6.9.win32-py2.7.exe
-wine nsis-2.46-setup.exe
-
-mkdir "${ctmpdir}"
-cp chromedriver.exe "${ctmpdir}"
-
-tar xzf Python27.extra.tar.gz -C "${cpythondir}"
-
-touch -d "2015-02-22 14:50:07" "${cpythondir}/Lib/site-packages/win32/lib/win32con.py"
-touch -d "2015-02-22 14:50:07" "${cpythondir}/Lib/site-packages/win32/lib/winerror.py"
-
-cp python27.dll WINHTTP.dll "${cwinsysdir}"
-
-echo
-echo "Removing extra packages..."
-rm -f *.msi *.exe Python27.extra.tar.gz python27.dll WINHTTP.dll
-echo
-echo "Done."
Index: cker/initialize-mlxwinebuild.sh
===================================================================
--- docker/initialize-mlxwinebuild.sh	(revision 916)
+++ 	(revision )
@@ -1,23 +1,0 @@
-#!/bin/bash
-
-set -e -u
-
-scriptdir=`dirname $0`
-scriptdir=`cd "${scriptdir}" && pwd`
-
-docker build -t mlxwinebuild-base "${scriptdir}/context"
-
-if test -z "${XAUTHORITY:-}"; then
-    XAUTHORITY="${HOME}/.Xauthority"
-fi
-
-docker run -it --name mlxwinebuildinit -v /tmp/.X11-unix:/tmp/.X11-unix -v "${XAUTHORITY}":/root/.Xauthority -v /usr/lib/x86_64-linux-gnu/vdpau:/usr/lib/x86_64-linux-gnu/vdpau --device /dev/nvidiactl --device /dev/nvidia0 --security-opt=apparmor:unconfined  --env DISPLAY mlxwinebuild-base initialize
-
-echo "Committing new image..."
-
-docker commit --change='CMD ["bash"]' mlxwinebuildinit mlxwinebuild
-
-echo "Removing container..."
-docker rm mlxwinebuildinit
-
-echo "Done."
Index: docker/virtualairlines.hu/build-virtualairlines.hu.sh
===================================================================
--- docker/virtualairlines.hu/build-virtualairlines.hu.sh	(revision 1007)
+++ docker/virtualairlines.hu/build-virtualairlines.hu.sh	(revision 1007)
@@ -0,0 +1,5 @@
+#!/bin/bash
+
+scriptdir=$(cd $(dirname $0) && pwd)
+
+docker build -t virtualairlines.hu "${scriptdir}/context"
Index: docker/virtualairlines.hu/context/Dockerfile
===================================================================
--- docker/virtualairlines.hu/context/Dockerfile	(revision 1007)
+++ docker/virtualairlines.hu/context/Dockerfile	(revision 1007)
@@ -0,0 +1,21 @@
+FROM ubuntu:18.04
+
+RUN apt-get update -y && \
+    /usr/bin/env DEBIAN_FRONTEND=noninteractive apt-get install -y \
+    software-properties-common && \
+    add-apt-repository -y ppa:ondrej/php && \
+    apt-get update -y && \
+    /usr/bin/env DEBIAN_FRONTEND=noninteractive apt-get install -y \
+    patch \
+    mysql-client \
+    mysql-server \
+    apache2 \
+    php5.6 \
+    php5.6-mysql \
+    php5.6-xml && \
+    apt-get clean -y
+
+COPY entrypoint.sh init.sql php.ini.patch /
+
+ENTRYPOINT ["/entrypoint.sh"]
+CMD ["mava"]
Index: docker/virtualairlines.hu/context/entrypoint.sh
===================================================================
--- docker/virtualairlines.hu/context/entrypoint.sh	(revision 1007)
+++ docker/virtualairlines.hu/context/entrypoint.sh	(revision 1007)
@@ -0,0 +1,45 @@
+#!/bin/bash
+
+if test "$1" = "mava"; then
+    if test ! -f /root/initialized; then
+        echo "Initial run, setting up some directories and symlinks"
+        if test ! -d /var/run/apache2; then
+            mkdir /var/run/apache2
+        fi
+
+        if test ! -d /var/run/mysqld; then
+            install -m 755 -o mysql -g root -d /var/run/mysqld
+        fi
+
+        mv /var/www/html /var/www/html.orig
+        ln -s /data/public_html/www /var/www/html
+
+        mkdir -p /home/ftp/virtualmalev
+        ln -s /data/public_html /home/ftp/virtualmalev/public_html
+
+        mkdir -p /home/mavasyst/public_html
+        ln -s /data/public_html /home/mavasyst/public_html/mava_old
+
+        cd /etc/php/5.6/apache2
+        patch -p0 < /php.ini.patch
+    fi
+
+    echo "Starting MySQL"
+    su - mysql -s /bin/sh -c "/usr/bin/mysqld_safe" &
+
+    if test ! -f /root/initialized; then
+        echo "Sleeping to let MySQL start up properly"
+        sleep 5
+
+        echo "Loading database into MySQL"
+        cat /init.sql | mysql
+        cat /data/uvirtualmalev.sql | mysql mavasyst_mavaold
+
+        touch /root/initialized
+    fi
+
+    source /etc/apache2/envvars
+    exec apache2 -DFOREGROUND
+else
+    exec "$@"
+fi
Index: docker/virtualairlines.hu/context/init.sql
===================================================================
--- docker/virtualairlines.hu/context/init.sql	(revision 1007)
+++ docker/virtualairlines.hu/context/init.sql	(revision 1007)
@@ -0,0 +1,7 @@
+SET GLOBAL sql_mode = '';
+
+CREATE DATABASE mavasyst_mavaold;
+
+CREATE USER mavasyst_mavasql IDENTIFIED BY 'zp3D1Hz4JJP7';
+
+GRANT ALL ON mavasyst_mavaold.* TO mavasyst_mavasql;
Index: docker/virtualairlines.hu/context/php.ini.patch
===================================================================
--- docker/virtualairlines.hu/context/php.ini.patch	(revision 1007)
+++ docker/virtualairlines.hu/context/php.ini.patch	(revision 1007)
@@ -0,0 +1,20 @@
+-- php.ini.orig 2019-07-07 11:52:31.501011566 +0000
++++ php.ini     2019-07-07 11:53:38.813227611 +0000
+@@ -199,7 +199,7 @@
+ ; Development Value: Off
+ ; Production Value: Off
+ ; http://php.net/short-open-tag
+-short_open_tag = Off
++short_open_tag = On
+
+ ; Allow ASP-style <% %> tags.
+ ; http://php.net/asp-tags
+@@ -741,7 +741,7 @@
+ ; properly in multithreaded servers, such as IIS or Zeus, and is automatically
+ ; disabled on them.
+ ; http://php.net/enable-dl
+-enable_dl = Off
++enable_dl = On
+
+ ; cgi.force_redirect is necessary to provide security running PHP as a CGI under
+ ; most web servers.  Left undefined, PHP turns this on by default.  You can
Index: docker/virtualairlines.hu/run-virtualairlines.hu.sh
===================================================================
--- docker/virtualairlines.hu/run-virtualairlines.hu.sh	(revision 1007)
+++ docker/virtualairlines.hu/run-virtualairlines.hu.sh	(revision 1007)
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+docker run -d --name virtualairlines.hu -p 40080:80 -v "${HOME}/sources/mlx/virtualairlines.hu":/data:ro virtualairlines.hu
Index: docker/virtualairlines.hu/start-virtualairlines.hu.sh
===================================================================
--- docker/virtualairlines.hu/start-virtualairlines.hu.sh	(revision 1007)
+++ docker/virtualairlines.hu/start-virtualairlines.hu.sh	(revision 1007)
@@ -0,0 +1,1 @@
+#!/usr/bin/bash
Index: license.txt
===================================================================
--- license.txt	(revision 874)
+++ license.txt	(revision 1010)
@@ -1,3 +1,3 @@
-Copyright ©  2012 - 2017 István Váradi
+Copyright ©  2012 - 2019 István Váradi
 
 This software is placed in the public domain. In no event should the author should be held liable for any damages arising from the use of this software.
Index: keinst.bat
===================================================================
--- makeinst.bat	(revision 682)
+++ 	(revision )
@@ -1,14 +1,0 @@
-set MSVCRDIR=c:\windows\winsxs\x86_Microsoft.VC90.CRT*9.0.21022.8*
-set GTKRTDIR=c:\Python27\Lib\site-packages\gtk-2.0\runtime
-set CEFDIR=c:\Python27\Lib\site-packages\cefpython3
-set CHROMEDRIVER=c:\tmp\chromedriver.exe
-set NSISDIR=C:\Program Files\NSIS
-
-python setup.py py2exe
-
-del dist\library\selenium\webdriver\chrome\service.pyc
-copy patches\library\selenium\webdriver\chrome\service.py dist\library\selenium\webdriver\chrome\service.py
-python -m compileall dist\library\selenium\webdriver\chrome\service.py
-del dist\library\selenium\webdriver\chrome\service.py
-
-"%NSISDIR%\makensis" mlx.nsi
Index: makeinst.sh
===================================================================
--- makeinst.sh	(revision 937)
+++ makeinst.sh	(revision 937)
@@ -0,0 +1,31 @@
+#!/bin/bash
+
+#set MSVCRDIR=c:\windows\winsxs\x86_Microsoft.VC90.CRT*9.0.21022.8*
+if test "${WINE}" = "yes"; then
+    cdrive="/root/.wine/drive_c/"
+    MINGW32DIR="c:/msys64/mingw32"
+
+    export GTKRTDIR="${MINGW32DIR}"
+    export CEFDIR="${MINGW32DIR}/lib/python3.7/site-packages/cefpython3"
+
+    export PYTHONHASHSEED=1234
+    export PYTHONIOENCODING=utf8
+    export PYTHONUTF8=1
+
+    wine "${cdrive}/msys64/mingw32/bin/python3.exe" setup.py py2exe
+
+    wine "${cdrive}/Program Files/NSIS/makensis.exe" mlx.nsi
+else
+    export GTKRTDIR=/mingw32
+    export CEFDIR=/mingw32/lib/python3.7/site-packages/cefpython3
+#set CHROMEDRIVER=c:\tmp\chromedriver.exe
+    export NSISDIR=/c/Program Files/NSIS
+
+    python3 setup.py py2exe
+    "$NSISDIR/makensis.exe" mlx.nsi
+fi
+
+#del dist\library\selenium\webdriver\chrome\service.pyc
+#copy patches\library\selenium\webdriver\chrome\service.py dist\library\selenium\webdriver\chrome\service.py
+#python -m compileall dist\library\selenium\webdriver\chrome\service.py
+#del dist\library\selenium\webdriver\chrome\service.py
Index: makesdist.sh
===================================================================
--- makesdist.sh	(revision 281)
+++ makesdist.sh	(revision 940)
@@ -2,3 +2,3 @@
 
 make
-python setup.py sdist
+python3 setup.py sdist
Index: misc/fs9.CFG
===================================================================
--- misc/fs9.CFG	(revision 972)
+++ misc/fs9.CFG	(revision 972)
@@ -0,0 +1,548 @@
+[DISPLAY]
+DisableSoftwareWarning=1
+UPPER_FRAMERATE_LIMIT=20
+TEXTURE_BANDWIDTH_MULT=20
+[PANELS]
+IMAGE_QUALITY=1
+UNITS_OF_MEASURE=1
+QUICKTIPS=1
+PANEL_MASKING=1
+PANEL_STRETCHING=1
+[Weather]
+WindshieldPrecipitationEffects=1
+MinGustTime=10
+MaxGustTime=500
+MinGustRampSpeed=1
+MaxGustRampSpeed=200
+MinVarTime=5
+MaxVarTime=50
+MinVarRampSpeed=10
+MaxVarRampSpeed=75
+TurbulenceScale=1.000000
+DefaultVisibility=0
+DynWx_MedianDewPointSpread=10.000000
+DynWx_ProbCloudFormForMedianDewPoint=0.000500
+DynWx_MaxDewPointSpread=50.000000
+DynWx_ProbCloudFormForMaxDewPoint=0.000125
+DynWx_ProbCloudFormForMinDewPoint=0.100000
+DynWx_DryTempLapsePer1000Meters=9.000000
+DynWx_ProbCloudFormForDryTempLapse=0.000500
+DynWx_MoistTempLapsePer1000Meters=3.300000
+DynWx_ProbCloudFormForMoistTempLapse=0.040000
+DynWx_MaxProbCloudChangePerMinute=0.040000
+DynWx_MultiplierForDynamicWeatherLevelMild=0.500000
+DynWx_MultiplierForDynamicWeatherLevelNormal=1.000000
+DynWx_MultiplierForDynamicWeatherLevelHigh=3.000000
+DynWx_MultiplierForDynamicWeatherLevelExtreme=10.000000
+DynWx_TempChangePercentageForOvercastClouds=0.750000
+DynWx_TempChangePercentageForMinDewPoint=0.700000
+DynWx_MaxTempChangePerMinute=0.060000
+WeatherServerAddress=fs2k.zone.com
+WeatherServerPort=80
+WeatherGraphDataInDialog=0
+DynamicWeather=2
+LOADWEATHER=1
+MAX_UNLIMITED_VIS=96560
+CLOUD_DRAW_DISTANCE=3
+3D_CLOUD_PERCENT=20
+DETAILED_CLOUDS=0
+CLOUD_COVERAGE_DENSITY=5
+CloudsImpostorRingRadius=9600.000000
+DownloadWindsAloft=0
+DisableTurbulence=0
+[INTERNATIONAL]
+ASLAT=2
+ASLON=0
+MEASURE=1
+[MISC]
+COM_RATE=7
+LOG_TIME=0
+FOREIGN_TRANSLATOR=0
+LOG_FILE=
+[STARTUP]
+DEMO=0
+LOADSIM=1
+LOADWINDOW=1
+SHOW_OPENING_SCREEN=1
+STARTUP_DEMO=
+[GRAPHICS]
+FULL_SCREEN=0
+PERFORMANCE_MODE=2
+DEF_PERF_MODE=2
+TEXT_SCROLL=0
+AUTO_LOD=0
+DETAIL_TEXTURE=0
+WATER_EFFECTS=0
+TERRAIN_USE_VECTOR_MAP=1
+TERRAIN_USE_VECTOR_OBJECTS=1
+EFFECTS_QUALITY=0
+GROUND_SHADOWS=0
+SMOOTH_VIEW=1
+IMAGE_SMOOTHING=1
+TEXTURE_MAX_LOAD=128
+COCKPIT_HIGH_LOD=0
+AIRCRAFT_SHADOWS=0
+LANDING_LIGHTS=1
+IMAGE_QUALITY=0
+TEXTURE_BLDG=1
+TEXTURE_GND=1
+TEXTURE_WATER=1
+AIRCRAFT_TEXTURE=1
+SEE_SELF=1
+TEXTURE_QUALITY=3
+LOD_TARGET_FPS=14
+NUM_LIGHTS=6
+[REALISM]
+INDASPD=0
+PFactor=1.000000
+Torque=1.000000
+GyroEffect=1.000000
+CrashTolerance=1.000000
+General=1.000000
+UnlimitedFuel=False
+TrueAirspeed=False
+AutoCoord=True
+RealMixture=True
+StressDamage=False
+GEffect=True
+ManualLights=True
+GyroDrift=True
+CrashWithDyn=False
+CrashDetection=0
+[CONTROLS]
+KBDAIL=64
+KBDELEV=64
+KBDRUD=64
+PAN_RATE=400
+[USERINTERFACE]
+MAP_ORIENTATION=2
+PAUSE_ON_LOST_FOCUS=0
+PROMPT_ON_EXIT=1
+SelectFlightLevel=0
+SelectFlightTitle=0
+PageID=4
+OpenATCOnCreate=0
+SITUATION=C:\Documents and Settings\vi\My Documents\Flight Simulator Files\Default
+DisplayFuelAsWeight=1
+[SOUND]
+SOUND=1
+SOUND_FADER1=0.680000
+SOUND_FADER2=0.000000
+SOUND_FADER3=0.420000
+SOUND_FADER4=0.000000
+SOUND_FADER5=0.390000
+SOUND_FADER6=0.000000
+SOUND_QUALITY=0
+[TERRAIN]
+TERRAIN_ERROR_FACTOR=20.000000
+TERRAIN_MIN_DEM_AREA=10.000000
+TERRAIN_MAX_DEM_AREA=100.000000
+TERRAIN_MAX_VERTEX_LEVEL=19
+TERRAIN_TEXTURE_SIZE_EXP=7
+TERRAIN_AUTOGEN_DENSITY=0
+TERRAIN_USE_GRADIENT_MAP=1
+TERRAIN_EXTENDED_TEXTURES=0
+TERRAIN_DEFAULT_RADIUS=0.000000
+TERRAIN_EXTENDED_RADIUS=0.000000
+TERRAIN_EXTENDED_LEVELS=0
+[SCENERY]
+IMAGE_COMPLEXITY=1
+DYNAMIC_SCENERY=0
+DYN_SCN_DENSITY=0
+DAWN_DUSK_SMOOTHING=0
+SUNGLARE=1
+LENSFLARE=1
+[AIRtoCONTAINER]
+SIM1=Cessna Skylane 182R RG
+SIM2=Learjet 45
+SIM3=Schweizer 2-32 Sailplane
+SIM4=Sopwith Camel
+SIM5=Extra 300S
+SIM6=Boeing 737-400
+[APL]
+CACHE_WAV_FILES=1
+[TrafficManager]
+TrafficDensity=0
+IFROnly=0
+EnableAirline=1
+EnableGeneralAviation=1
+[AContain]
+ShowLabels=1
+ShowUserLabel=0
+ShowLabelManufacturer=1
+ShowLabelModel=1
+ShowLabelTailNumber=0
+ShowLabelDistance=1
+ShowLabelAltitude=1
+ShowLabelAirline=0
+ShowLabelAirlineAndFlightNumber=0
+ShowLabelFlightPlan=0
+ShowLabelContainerId=0
+ShowLabelAirspeed=0
+ShowLabelHeading=0
+LabelDelay=1000
+LabelColor=FFFF0000
+[SLEW]
+MaxLateralRate=40000.000000
+MaxVerticalRate=1000.000000
+MaxPitchRate=360.000000
+MaxBankRate=360.000000
+MaxHeadingRate=360.000000
+[VirtualCopilot]
+VirtualCopilotActive=0
+[MAIN]
+Location=5,3,977,788
+HideMenuNormal=0
+HideMenuFullscreen=1
+Maximized=0
+[MULTIPLAYER]
+ALWAYS_SHOW_INITIAL_DIALOG=1
+SESSION_NAME=My Session
+PLAYER_NAME=Unnamed Pilot
+GUARANTEED_MESSAGES=0
+MAX_PLAYERS=8
+MAX_OBSERVERS=0
+TICKS_PER_SYNC=90
+PACKETS_PER_SEC=4
+COLLISION_SECS=2
+FOLLOWING_MULTIPLIER=5
+ALLOW_PLANE_MODEL_SEND=0
+ALLOW_PLANE_MODEL_RECEIVE=0
+ALLOW_TEXTURE_SEND=0
+ALLOW_TEXTURE_RECEIVE=0
+MAX_SEGMENT_SIZE=100
+MAX_SEGMENTS_PER_SEC=1
+CONNECTION_TYPE=0
+PROTOCOL_SELECTION=0
+ALLOW_DESCRIPTIVE_SEND=1
+ALLOW_DESCRIPTIVE_RECEIVE=1
+AUTOPILOT_LOCK=0
+DISTANCE_DISPLAY=0
+ADF_TRACK=0
+ALLOW_NAME_TAG_DISPLAY=1
+CLIENT_CONNECT_USE_CUSTOM_PORT=0
+CLIENT_CONNECT_PORT=23456
+CLIENT_HOST_USE_CUSTOM_PORT=0
+CLIENT_HOST_PORT=23456
+HOST_CONNECT_USE_CUSTOM_PORT=0
+HOST_CONNECT_PORT=23456
+[SIM]
+SYSCLOCK=0
+[ATC]
+AutoOpenAirTrafficWindow=1
+UsePilotVoice=1
+ShowATCText=1
+PilotVoice=1
+[FACILITIES]
+COUNTRY=
+STATE=
+CITY=
+GTL_BUTTON=6225
+[DISPLAY.Device.]
+Mode=
+MipBias=8
+Disable=1
+Filter=0
+Dither=0
+MipMap=0
+Stencil=0
+Fog=0
+ExpFog=0
+TnL=0
+DriverValidate=0
+DXTn=0
+TextureForce=0
+PanelAsTexture=0
+TexGen=0
+MultiTexture=0
+TEXBEM=0
+RenderToTexture=0
+UseShaders=0
+TableFog=0
+[WEATHER_MAP]
+SHOW_AIRPORTS=0
+SHOW_VORS=0
+SHOW_NDBS=0
+SHOW_APPROACHES=0
+SHOW_INTERSECTIONS=0
+SHOW_VICTOR=0
+SHOW_JET=0
+SHOW_AIRSPACE=0
+SHOW_FLIGHTPLAN=1
+SHOW_WEATHERSTATIONS=1
+SHOW_WEATHERSYSTEMS=1
+SHOW_DATATAGS=1
+SHOW_TERRAIN=1
+[WeatherAreaMap]
+show_airports=0
+show_waypoints=0
+show_airways=1
+show_vors=0
+show_ndbs=0
+show_markers=0
+show_volume_boundaries=0
+show_ac_twr=1
+[STATION_MAP]
+SHOW_AIRPORTS=0
+SHOW_VORS=0
+SHOW_NDBS=0
+SHOW_APPROACHES=0
+SHOW_INTERSECTIONS=0
+SHOW_VICTOR=0
+SHOW_JET=0
+SHOW_AIRSPACE=0
+SHOW_FLIGHTPLAN=1
+SHOW_WEATHERSTATIONS=1
+SHOW_WEATHERSYSTEMS=0
+SHOW_DATATAGS=1
+SHOW_TERRAIN=1
+[JOYSTICK_MAIN {A3D60A20-8B68-11E3-8001-444553540000}]
+AXIS_EVENT_00=AXIS_FLAPS_SET
+AXIS_SCALE_00=127
+AXIS_NULL_00=1
+BUTTON_DOWN_EVENT_00=BRAKES
+BUTTON_DOWN_REPEAT_00=1
+BUTTON_DOWN_EVENT_01=VIEW_MODE
+BUTTON_DOWN_EVENT_02=ELEV_TRIM_DN
+BUTTON_DOWN_REPEAT_02=1
+BUTTON_DOWN_EVENT_03=ELEV_TRIM_UP
+BUTTON_DOWN_REPEAT_03=1
+BUTTON_DOWN_EVENT_04=FLAPS_INCR
+BUTTON_DOWN_EVENT_05=FLAPS_DECR
+BUTTON_DOWN_EVENT_06=KNEEBOARD_VIEW
+BUTTON_DOWN_EVENT_07=GEAR_TOGGLE
+BUTTON_DOWN_EVENT_08=VIEW_MODE
+BUTTON_DOWN_EVENT_09=GEAR_TOGGLE
+[JOYSTICK_SLEW {A3D60A20-8B68-11E3-8001-444553540000}]
+AXIS_EVENT_00=AXIS_SLEW_SIDEWAYS_SET
+AXIS_SCALE_00=127
+AXIS_NULL_00=1
+AXIS_EVENT_01=AXIS_SLEW_AHEAD_SET
+AXIS_SCALE_01=64
+AXIS_NULL_01=36
+BUTTON_DOWN_EVENT_00=SLEW_RESET
+BUTTON_DOWN_EVENT_01=VIEW_MODE
+BUTTON_DOWN_EVENT_02=SLEW_ALTIT_PLUS
+BUTTON_DOWN_EVENT_03=SLEW_ALTIT_MINUS
+BUTTON_DOWN_EVENT_04=SLEW_PITCH_PLUS
+BUTTON_DOWN_EVENT_05=SLEW_PITCH_MINUS
+BUTTON_DOWN_EVENT_06=SLEW_BANK_MINUS
+BUTTON_DOWN_EVENT_07=SLEW_BANK_PLUS
+BUTTON_DOWN_EVENT_08=SLEW_FREEZE
+BUTTON_DOWN_EVENT_09=SLEW_RESET
+[KEYBOARD_MAIN]
+SELECT_1=49,8
+SELECT_2=50,8
+SELECT_3=51,8
+SELECT_4=52,8
+MINUS=189,8
+PLUS=187,8
+ZOOM_1X=8,8
+SOUND_TOGGLE=81,8
+ENGINE=69,8
+SIM_RATE=82,8
+XPNDR=84,8
+SLEW_TOGGLE=89,8
+EGT=85,8
+SMOKE_TOGGLE=73,8
+STROBES_TOGGLE=79,8
+PAUSE_TOGGLE=80,8
+ATC=192,8
+ADF=65,8
+VIEW_MODE=83,8
+HEADING_GYRO_SET=68,8
+DME=70,8
+GEAR_TOGGLE=71,8
+ANTI_ICE_TOGGLE=72,8
+JET_STARTER=74,8
+JOYSTICK_CALIBRATE=75,10
+ALL_LIGHTS_TOGGLE=76,8
+SITUATION_SAVE=186,8
+VIEW_WINDOW_TO_FRONT=222,8
+AP_MASTER=90,8
+FREQUENCY_SWAP=88,8
+COM_RADIO=67,8
+VOR_OBS=86,8
+BAROMETRIC=66,8
+NAV_RADIO=78,8
+MAGNETO=77,8
+BRAKES=190,8
+SPOILERS_TOGGLE=191,8
+SITUATION_RESET=186,10
+FLAPS_UP=116,8
+THROTTLE_FULL=115,8
+THROTTLE_INCR_SMALL=114,8
+THROTTLE_DECR=113,8
+FLAPS_DOWN=119,8
+THROTTLE_CUT=112,8
+VIEW=111,8
+ELEV_TRIM_DN=36,8
+ELEV_DOWN=38,8
+INCREASE_THROTTLE=33,8
+AILERONS_LEFT=37,8
+CENTER_AILER_RUDDER=12,8
+AILERONS_RIGHT=39,8
+ELEV_TRIM_UP=35,8
+ELEV_UP=40,8
+DECREASE_THROTTLE=34,8
+VIEW_FORWARD=38,41
+VIEW_FORWARD_RIGHT=33,41
+VIEW_RIGHT=39,41
+VIEW_REAR_RIGHT=34,41
+VIEW_REAR=40,41
+VIEW_REAR_LEFT=35,41
+VIEW_LEFT=37,41
+VIEW_FORWARD_LEFT=36,41
+VIEW_DOWN=12,41
+RUDDER_LEFT=45,8
+RUDDER_RIGHT=135,8
+BRAKES_LEFT=122,8
+BRAKES_RIGHT=123,8
+AP_ATT_HOLD=84,10
+AP_LOC_HOLD=79,10
+AP_APR_HOLD=65,10
+AP_HDG_HOLD=72,10
+AP_ALT_HOLD=90,10
+AP_WING_LEVELER=86,10
+AP_BC_HOLD=66,10
+AP_NAV1_HOLD=78,10
+EXIT=67,10
+ABORT=3,10
+READOUTS_FLIGHT=90,9
+PANEL_TOGGLE=219,9
+VIEW_MODE_REV=83,9
+PANEL_LIGHTS_TOGGLE=76,9
+LANDING_LIGHTS_TOGGLE=76,10
+PARKING_BRAKES=190,10
+MINUS_SHIFT=189,9
+PLUS_SHIFT=187,9
+FLAPS_INCR=118,8
+FLAPS_DECR=117,8
+PROP_PITCH_LO=115,10
+PROP_PITCH_INCR_SMALL=114,10
+PROP_PITCH_DECR=113,10
+PROP_PITCH_HI=112,10
+MIXTURE_RICH=115,11
+MIXTURE_INCR_SMALL=114,11
+MIXTURE_DECR=113,11
+MIXTURE_LEAN=112,11
+SCRIPT_EVENT_1=219,10
+SCRIPT_EVENT_2=221,10
+YAW_DAMPER_TOGGLE=68,10
+CENTER_NT361_CHECK=57,11
+CLOSE_VIEW=221,8
+NEW_VIEW=219,8
+NEW_MAP=221,9
+NEXT_VIEW=9,10
+PREV_VIEW=9,11
+VIEW_TYPE=83,10
+VIEW_TYPE_REV=83,11
+RADIO_VOR1_IDENT_TOGGLE=49,10
+RADIO_VOR2_IDENT_TOGGLE=50,10
+RADIO_DME1_IDENT_TOGGLE=52,10
+RADIO_ADF_IDENT_TOGGLE=53,10
+GEAR_PUMP=71,10
+SPOILERS_ARM_TOGGLE=191,9
+PITOT_HEAT_TOGGLE=72,9
+AP_AIRSPEED_HOLD=82,10
+AUTO_THROTTLE_ARM=82,9
+AUTO_THROTTLE_TO_GA=71,11
+LANDING_LIGHT_UP=38,11
+LANDING_LIGHT_DOWN=40,11
+LANDING_LIGHT_LEFT=37,11
+LANDING_LIGHT_RIGHT=39,11
+LANDING_LIGHT_HOME=12,11
+PAN_RESET=46,9
+KNEEBOARD_VIEW=121,8
+MP_PLAYER_CYCLE=84,11
+MP_PLAYER_SNAP=70,11
+MP_GO_OBSERVER=79,11
+MP_CHAT=221,11
+MP_ACTIVATE_CHAT=13,8
+PANEL_1=49,9
+PANEL_2=50,9
+PANEL_3=51,9
+PANEL_4=52,9
+PANEL_5=53,9
+PANEL_6=54,9
+PANEL_7=55,9
+PANEL_8=56,9
+PANEL_9=57,9
+AP_MACH_HOLD=77,10
+VIEW_FORWARD_UP=38,42
+VIEW_FORWARD_RIGHT_UP=33,42
+VIEW_REAR_RIGHT_UP=34,42
+VIEW_REAR_UP=40,42
+VIEW_REAR_LEFT_UP=35,42
+VIEW_FORWARD_LEFT_UP=36,42
+VIEW_UP=12,42
+INVOKE_HELP=191,10
+TOGGLE_AIRCRAFT_LABELS=76,11
+ENGINE_AUTO_START=69,10
+INC_COWL_FLAPS=86,11
+DEC_COWL_FLAPS=67,11
+USER_INTERRUPT=27,8
+AILERON_TRIM_LEFT=37,10
+AILERON_TRIM_RIGHT=39,10
+RUDDER_TRIM_LEFT=45,10
+RUDDER_TRIM_RIGHT=135,10
+TOGGLE_FLIGHT_DIRECTOR=70,10
+TOGGLE_AFTERBURNER=115,9
+TOGGLE_MASTER_BATTERY_ALTERNATOR=77,9
+TOGGLE_AIRCRAFT_EXIT=69,9
+PANEL_HUD_TOGGLE=87,8
+SNAP_TO_PANEL=45,41
+MARKER_SOUND_TOGGLE=51,10
+TOGGLE_WATER_RUDDER=87,9
+TOGGLE_PUSHBACK=80,9
+KEY_CHASE_VIEW_NEXT=87,10
+KEY_CHASE_VIEW_PREV=87,11
+HEADING_BUG_SELECT=72,11
+ALTITUDE_BUG_SELECT=90,11
+CHASE_VIEW_TOGGLE=81,10
+EYEPOINT_UP=13,9
+EYEPOINT_DOWN=8,9
+EYEPOINT_RIGHT=13,11
+EYEPOINT_LEFT=8,11
+EYEPOINT_FORWARD=8,10
+EYEPOINT_BACK=13,10
+EYEPOINT_RESET=32,8
+AIRSPEED_BUG_SELECT=82,11
+TOGGLE_TAILWHEEL_LOCK=71,9
+ROTOR_BRAKE=66,9
+ROTOR_CLUTCH_SWITCH_TOGGLE=190,9
+ROTOR_GOV_SWITCH_TOGGLE=188,9
+VIRTUAL_COPILOT_TOGGLE=88,11
+VIRTUAL_COPILOT_ACTION=88,10
+[KEYBOARD_SLEW]
+SLEW_TOGGLE=89,8
+SLEW_ALTIT_UP_FAST=115,8
+SLEW_ALTIT_UP_SLOW=114,8
+SLEW_ALTIT_FREEZE=113,8
+SLEW_ALTIT_DN_FAST=112,8
+SLEW_ALTIT_PLUS=81,8
+SLEW_ALTIT_MINUS=65,8
+SLEW_PITCH_DN_FAST=119,8
+SLEW_PITCH_DN_SLOW=118,8
+SLEW_PITCH_FREEZE=117,8
+SLEW_PITCH_UP_FAST=116,8
+SLEW_PITCH_PLUS=57,8
+SLEW_PITCH_MINUS=48,8
+READOUTS_SLEW=90,9
+SLEW_BANK_MINUS=36,8
+SLEW_AHEAD_PLUS=38,8
+SLEW_BANK_PLUS=33,8
+SLEW_LEFT=37,8
+SLEW_FREEZE=12,8
+SLEW_RIGHT=39,8
+SLEW_HEADING_MINUS=35,8
+SLEW_AHEAD_MINUS=40,8
+SLEW_HEADING_PLUS=34,8
+SLEW_RESET=32,8
+TOGGLE_AIRCRAFT_LABELS=76,11
+EYEPOINT_UP=13,9
+EYEPOINT_DOWN=8,9
+EYEPOINT_RIGHT=13,11
+EYEPOINT_LEFT=8,11
+EYEPOINT_FORWARD=8,10
+EYEPOINT_BACK=13,10
Index: runmlx.sh
===================================================================
--- runmlx.sh	(revision 577)
+++ runmlx.sh	(revision 933)
@@ -8,3 +8,6 @@
 https_proxy=
 
-exec python -m runmlx "$@"
+FORCE_PYGOBJECT=true
+export FORCE_PYGOBJECT
+
+exec python3 -m runmlx "$@"
Index: setup.py
===================================================================
--- setup.py	(revision 916)
+++ setup.py	(revision 981)
@@ -5,4 +5,5 @@
 from glob import glob
 from distutils.core import setup
+from pathlib import Path
 
 scriptdir=os.path.dirname(sys.argv[0])
@@ -11,4 +12,33 @@
 import mlx.const
 import mlx.update
+
+defaultManifest="""<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
+  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
+    <security>
+      <requestedPrivileges>
+        <requestedExecutionLevel level="asInvoker"/>
+      </requestedPrivileges>
+    </security>
+  </trustInfo>
+  <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
+    <application>
+      <!--The ID below indicates application support for Windows Vista -->
+      <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
+      <!--The ID below indicates application support for Windows 7 -->
+      <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
+      <!--The ID below indicates application support for Windows 8 -->
+      <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
+      <!--The ID below indicates application support for Windows 8.1 -->
+      <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
+      <!--The ID below indicates application support for Windows 10 -->
+      <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
+    </application>
+  </compatibility>
+</assembly>"""
+
+adminManifest=defaultManifest.replace("asInvoker", "requireAdministrator")
+
+RT_MANIFEST=24
 
 data_files = [("sounds", glob(os.path.join("sounds", "*.*")))]
@@ -37,70 +67,133 @@
         os.environ["PATH"] = os.environ["PATH"] + ";" + glob(os.path.join(msvcrDir))[0]
 
-
     gtkRuntimeDir = os.environ["GTKRTDIR"] if "GTKRTDIR" in os.environ else None
     if gtkRuntimeDir:
-        path = os.path.join("lib", "gtk-2.0", "2.10.0", "engines")
-        data_files.append((os.path.join("library", path),
-                           [os.path.join(gtkRuntimeDir, path, "libwimp.dll")]))
-
-        path = os.path.join("share", "themes", "MS-Windows", "gtk-2.0")
-        data_files.append((os.path.join("library", path),
-                           glob(os.path.join(gtkRuntimeDir, path, "*"))))
-
-        path = os.path.join("share", "locale", "hu", "LC_MESSAGES")
-        data_files.append((os.path.join("library", path),
-                           glob(os.path.join(gtkRuntimeDir, path, "*"))))
-        path = os.path.join("share", "icons", "hicolor")
-        data_files.append((os.path.join("library", path),
-                           glob(os.path.join(gtkRuntimeDir, path, "*"))))
+        if gtkRuntimeDir.endswith("/mingw32"):
+            files = {}
+
+            for components in [ ["lib", "girepository-1.0"],
+                                ["lib", "gdk-pixbuf-2.0", "2.10.0", "loaders.cache"],
+                                ["lib", "gdk-pixbuf-2.0", "2.10.0", "loaders", "libpixbufloader-ico.dll"],
+                                ["lib", "gdk-pixbuf-2.0", "2.10.0", "loaders", "libpixbufloader-png.dll"],
+                                ["lib", "gdk-pixbuf-2.0", "2.10.0", "loaders", "libpixbufloader-svg.dll"],
+                                ["share", "icons", "Adwaita", "icon-theme.cache"],
+                                ["share", "icons", "Adwaita", "index.theme"],
+                                ["share", "icons", "Adwaita", "16x16"],
+                                ["share", "locale", "hu"],
+                                ["share", "locale", "en"],
+                                ["share", "themes"],
+                                ["share", "glib-2.0", "schemas"]]:
+                 path = os.path.join(*components)
+                 p = Path(os.path.join(gtkRuntimeDir, path))
+                 if p.is_file():
+                     d = os.path.dirname(path)
+                     if d in files:
+                         files[d].append(str(p))
+                     else:
+                         files[d] = [str(p)]
+                 else:
+                     for f in p.glob("**/*"):
+                         if f.is_file():
+                             d = os.path.join(path, str(f.parent.relative_to(p)))
+                             if d in files:
+                                 files[d].append(str(f))
+                             else:
+                                 files[d] = [str(f)]
+
+            for path in files:
+                data_files.append((path, files[path]))
+            data_files.append(("",
+                               [os.path.join(gtkRuntimeDir, "bin", "librsvg-2-2.dll"),
+                                os.path.join(gtkRuntimeDir, "bin", "libcroco-0.6-3.dll")]))
+        else:
+            path = os.path.join("lib", "gtk-2.0", "2.10.0", "engines")
+            data_files.append((os.path.join("library", path),
+                               [os.path.join(gtkRuntimeDir, path, "libwimp.dll")]))
+
+            path = os.path.join("share", "themes", "MS-Windows", "gtk-2.0")
+            data_files.append((os.path.join("library", path),
+                               glob(os.path.join(gtkRuntimeDir, path, "*"))))
+
+            path = os.path.join("share", "locale", "hu", "LC_MESSAGES")
+            data_files.append((os.path.join("library", path),
+                               glob(os.path.join(gtkRuntimeDir, path, "*"))))
+            path = os.path.join("share", "icons", "hicolor")
+            data_files.append((os.path.join("library", path),
+                               glob(os.path.join(gtkRuntimeDir, path, "*"))))
 
     cefDir = os.environ.get("CEFDIR")
     if cefDir:
-        for fileName in ["icudt.dll", "subprocess.exe"]:
+        for fileName in ["icudtl.dat", "subprocess.exe", "natives_blob.bin",
+                         "snapshot_blob.bin", "v8_context_snapshot.bin",
+                         "cef.pak", "cef_100_percent.pak",
+                         "cef_200_percent.pak", "cef_extensions.pak"]:
             data_files.append(("", [os.path.join(cefDir, fileName)]))
 
         data_files.append(("locales",
-                           glob(os.path.join(cefDir, "locales", "*"))))
+                           [os.path.join(cefDir, "locales", "hu.pak"),
+                            os.path.join(cefDir, "locales", "en-GB.pak"),
+                            os.path.join(cefDir, "locales", "en-US.pak"),
+                            os.path.join(cefDir, "locales", "ru.pak")]))
 
     if os.getenv("WINE")=="yes":
         winsysdir=os.getenv("WINSYSDIR")
-        data_files.append(("", [os.path.join(winsysdir, "python27.dll")]))
-        data_files.append(("library", [
-                            os.path.join(winsysdir, "pywintypes27.dll"),
-                            os.path.join(winsysdir, "WINHTTP.dll")]))
 
         if gtkRuntimeDir:
             gtkBinDir = os.path.join(gtkRuntimeDir, "bin")
-            data_files.append(("library", [
-                                os.path.join(gtkBinDir, "freetype6.dll"),
-                                os.path.join(gtkBinDir, "intl.dll"),
-                                os.path.join(gtkBinDir, "zlib1.dll"),
+            data_files.append(("", [
+                                os.path.join(gtkBinDir, "libatk-1.0-0.dll"),
+                                os.path.join(gtkBinDir, "libbz2-1.dll"),
+                                os.path.join(gtkBinDir, "libcairo-2.dll"),
+                                os.path.join(gtkBinDir, "libcairo-gobject-2.dll"),
+                                os.path.join(gtkBinDir, "libcroco-0.6-3.dll"),
+                                os.path.join(gtkBinDir, "libcrypto-1_1.dll"),
+                                os.path.join(gtkBinDir, "libdatrie-1.dll"),
+                                os.path.join(gtkBinDir, "libepoxy-0.dll"),
+                                os.path.join(gtkBinDir, "libexpat-1.dll"),
+                                os.path.join(gtkBinDir, "libexslt-0.dll"),
+                                os.path.join(gtkBinDir, "libffi-6.dll"),
+                                os.path.join(gtkBinDir, "libfontconfig-1.dll"),
+                                os.path.join(gtkBinDir, "libfreetype-6.dll"),
+                                os.path.join(gtkBinDir, "libfribidi-0.dll"),
+                                os.path.join(gtkBinDir, "libgcc_s_dw2-1.dll"),
+                                os.path.join(gtkBinDir, "libgdk_pixbuf-2.0-0.dll"),
+                                os.path.join(gtkBinDir, "libgio-2.0-0.dll"),
+                                os.path.join(gtkBinDir, "libgirepository-1.0-1.dll"),
                                 os.path.join(gtkBinDir, "libglib-2.0-0.dll"),
-                                os.path.join(gtkBinDir, "libatk-1.0-0.dll"),
-                                os.path.join(gtkBinDir, "libcairo-2.dll"),
-                                os.path.join(gtkBinDir, "libexpat-1.dll"),
-                                os.path.join(gtkBinDir, "libpangowin32-1.0-0.dll"),
-                                os.path.join(gtkBinDir, "libgio-2.0-0.dll"),
-                                os.path.join(gtkBinDir, "libgdk-win32-2.0-0.dll"),
-                                os.path.join(gtkBinDir, "libpng14-14.dll"),
+                                os.path.join(gtkBinDir, "libgmodule-2.0-0.dll"),
                                 os.path.join(gtkBinDir, "libgobject-2.0-0.dll"),
-                                os.path.join(gtkBinDir, "libgdk_pixbuf-2.0-0.dll"),
-                                os.path.join(gtkBinDir, "libfontconfig-1.dll"),
-                                os.path.join(gtkBinDir, "libpangoft2-1.0-0.dll"),
-                                os.path.join(gtkBinDir, "libgmodule-2.0-0.dll"),
+                                os.path.join(gtkBinDir, "libgraphite2.dll"),
+                                os.path.join(gtkBinDir, "libharfbuzz-0.dll"),
+                                os.path.join(gtkBinDir, "libiconv-2.dll"),
+                                os.path.join(gtkBinDir, "libintl-8.dll"),
+                                os.path.join(gtkBinDir, "liblzma-5.dll"),
+                                os.path.join(gtkBinDir, "libmpdec-2.dll"),
                                 os.path.join(gtkBinDir, "libpango-1.0-0.dll"),
                                 os.path.join(gtkBinDir, "libpangocairo-1.0-0.dll"),
-                                os.path.join(gtkBinDir, "libgtk-win32-2.0-0.dll"),
-                                os.path.join(gtkBinDir, "libgthread-2.0-0.dll")
+                                os.path.join(gtkBinDir, "libpangoft2-1.0-0.dll"),
+                                os.path.join(gtkBinDir, "libpangowin32-1.0-0.dll"),
+                                os.path.join(gtkBinDir, "libpcre-1.dll"),
+                                os.path.join(gtkBinDir, "libpixman-1-0.dll"),
+                                os.path.join(gtkBinDir, "libpng16-16.dll"),
+                                os.path.join(gtkBinDir, "librsvg-2-2.dll"),
+                                os.path.join(gtkBinDir, "libssl-1_1.dll"),
+                                os.path.join(gtkBinDir, "libssp-0.dll"),
+                                os.path.join(gtkBinDir, "libstdc++-6.dll"),
+                                os.path.join(gtkBinDir, "libthai-0.dll"),
+                                os.path.join(gtkBinDir, "libwinpthread-1.dll"),
+                                os.path.join(gtkBinDir, "libxml2-2.dll"),
+                                os.path.join(gtkBinDir, "libxslt-1.dll"),
+                                os.path.join(gtkBinDir, "zlib1.dll"),
                               ]))
         if cefDir:
-            data_files.append(("library", [
-                                os.path.join(cefDir, "libcef.dll")
+            data_files.append(("", [
+                                os.path.join(cefDir, "libcef.dll"),
+                                os.path.join(cefDir, "chrome_elf.dll")
                               ]))
 
-    print data_files
+    print(data_files)
 
     with open("mlx-common.nsh", "wt") as f:
-            print >>f, '!define MLX_VERSION "%s"' % (mlx.const.VERSION)
+            print('!define MLX_VERSION "%s"' % (mlx.const.VERSION), file=f)
             f.close()
 else:
@@ -129,10 +222,11 @@
       requires = ["pyuipc", "xplra"],
       windows = [{ "script" : "runmlx.py",
-                   "icon_resources" : [(1, "logo.ico")]},
+                   "icon_resources" : [(1, "logo.ico")],
+                   "other_resources": [(RT_MANIFEST, 1, defaultManifest)]},
                  { "script" : "mlxupdate.py",
-                   "uac_info" : "requireAdministrator"}],
-      options = { "py2exe" : { "includes": "gio, pango, atk, pangocairo, lxml._elementpath",
+                   "other_resources": [(RT_MANIFEST, 1, adminManifest)]}],
+      options = { "py2exe" : { "packages" : "gi, lxml",
                                "skip_archive": True} },
-      zipfile = "library/.",
+      zipfile = "library",
       data_files = data_files,
       platforms = ["Win32", "Linux"],
@@ -141,8 +235,6 @@
 
 if os.name=="nt":
-    os.rename(os.path.join(scriptdir, "dist", "library", "libcef.dll"),
-              os.path.join(scriptdir, "dist", "libcef.dll"))
     mlx.update.buildManifest(os.path.join(scriptdir, "dist"))
     with open(os.path.join(scriptdir, "dist", "Uninstall.conf"), "wt") as f:
-        print >> f, "StartMenuFolder=MAVA Logger X"
-        print >> f, "LinkName=MAVA Logger X"
+        print("StartMenuFolder=MAVA Logger X", file=f)
+        print("LinkName=MAVA Logger X", file=f)
Index: src/mlx/acars.py
===================================================================
--- src/mlx/acars.py	(revision 743)
+++ src/mlx/acars.py	(revision 919)
@@ -1,4 +1,4 @@
 
-import const
+from . import const
 
 #------------------------------------------------------------------------------
Index: src/mlx/acft.py
===================================================================
--- src/mlx/acft.py	(revision 905)
+++ src/mlx/acft.py	(revision 919)
@@ -1,9 +1,9 @@
 
-import const
-import gates
-import checks
-import fs
-from i18n import xstr
-import util
+from . import const
+from . import gates
+from . import checks
+from . import fs
+from .i18n import xstr
+from . import util
 
 import sys
@@ -308,5 +308,5 @@
               ("-" if value is None else "enabled" if value else "disabled",)
         elif dt!=DERATE_NONE:
-            print "mlx.acft.getDerateLine: invalid derate type: " + dt
+            print("mlx.acft.getDerateLine: invalid derate type: " + dt)
 
         return None
@@ -343,5 +343,5 @@
                                   self._aircraftState, aircraftState)
                 except:
-                    print >> sys.stderr, "Checker", checker, "failed"
+                    print("Checker", checker, "failed", file=sys.stderr)
                     traceback.print_exc()
 
@@ -351,5 +351,5 @@
             self._minVS = min(self._minVS, aircraftState.vs)
         except:
-            print >> sys.stderr, "Failed to handle the state"
+            print("Failed to handle the state", file=sys.stderr)
             traceback.print_exc()
         finally:
@@ -403,5 +403,5 @@
                     self._logQNH(aircraftState)
             elif newStage==const.STAGE_GOAROUND:
-                from logger import Logger
+                from .logger import Logger
                 self._flight.handleFault("goaround",
                                          aircraftState.timestamp,
@@ -1284,47 +1284,47 @@
     value = SmoothedValue()
 
-    print "Adding 1, 12.0"
+    print("Adding 1, 12.0")
     value.add(1, 12.0)
-    print value.get()
-
-    print "Adding 1, 15.0"
+    print(value.get())
+
+    print("Adding 1, 15.0")
     value.add(1, 15.0)
-    print value.get()
-
-    print "Adding 2, 18.0"
+    print(value.get())
+
+    print("Adding 2, 18.0")
     value.add(2, 18.0)
-    print value.get()
-
-    print "Adding 2, 20.0"
+    print(value.get())
+
+    print("Adding 2, 20.0")
     value.add(2, 20.0)
-    print value.get()
-
-    print "Adding 5, 22.0"
+    print(value.get())
+
+    print("Adding 5, 22.0")
     value.add(5, 22.0)
-    print value.get()
-
-    print "Adding 5, 25.0"
+    print(value.get())
+
+    print("Adding 5, 25.0")
     value.add(5, 25.0)
-    print value.get()
-
-    print "Adding 5, 29.0"
+    print(value.get())
+
+    print("Adding 5, 29.0")
     value.add(5, 29.0)
-    print value.get()
-
-    print "Adding 5, 21.0"
+    print(value.get())
+
+    print("Adding 5, 21.0")
     value.add(5, 21.0)
-    print value.get()
-
-    print "Adding 5, 26.0"
+    print(value.get())
+
+    print("Adding 5, 26.0")
     value.add(5, 26.0)
-    print value.get()
-
-    print "Adding 2, 30.0"
+    print(value.get())
+
+    print("Adding 2, 30.0")
     value.add(2, 30.0)
-    print value.get()
-
-    print "Adding 2, 55.0"
+    print(value.get())
+
+    print("Adding 2, 55.0")
     value.add(2, 55.0)
-    print value.get()
-
-#---------------------------------------------------------------------------------------
+    print(value.get())
+
+#---------------------------------------------------------------------------------------
Index: src/mlx/airports.py
===================================================================
--- src/mlx/airports.py	(revision 325)
+++ src/mlx/airports.py	(revision 919)
@@ -88,11 +88,11 @@
 
 if __name__ == "__main__":
-    for (town, airport) in airportNames.itervalues():
-        print town, airport
-    print getWelcomeMessage("LIRF")
-    print getWelcomeMessage("LHDC")
-    print getWelcomeMessage("LIRN")
-    print getWelcomeMessage("LHBP")
-    print getWelcomeMessage("EDDF")
+    for (town, airport) in airportNames.values():
+        print(town, airport)
+    print(getWelcomeMessage("LIRF"))
+    print(getWelcomeMessage("LHDC"))
+    print(getWelcomeMessage("LIRN"))
+    print(getWelcomeMessage("LHBP"))
+    print(getWelcomeMessage("EDDF"))
 
 #-----------------------------------------------------------------------------
Index: src/mlx/checks.py
===================================================================
--- src/mlx/checks.py	(revision 912)
+++ src/mlx/checks.py	(revision 919)
@@ -1,8 +1,8 @@
 
-import fs
-import const
-import util
-from acars import ACARS
-from sound import startSound
+from . import fs
+from . import const
+from . import util
+from .acars import ACARS
+from .sound import startSound
 
 import time
@@ -129,9 +129,9 @@
         """Callback for ACARS sending."""
         if returned:
-            print "Sent online ACARS"
+            print("Sent online ACARS")
             self._lastSent = time.time() if self._lastSent is None \
                              else self._lastSent + ACARSSender.INTERVAL
         else:
-            print "Failed to send the ACARS"
+            print("Failed to send the ACARS")
         self._sending = False
 
@@ -517,6 +517,6 @@
     def getMessage(logName, frequency, obs):
         """Get the message for the given NAV radio setting."""
-        message = u"%-5s %s" % (logName + ":", frequency)
-        if obs is not None: message += u" (%03d\u00b0)" % (obs,)
+        message = "%-5s %s" % (logName + ":", frequency)
+        if obs is not None: message += " (%03d\u00b0)" % (obs,)
         return message
 
@@ -747,7 +747,7 @@
         message = what
         if value is None:
-            message += u" cannot be detected, will not log"
+            message += " cannot be detected, will not log"
         else:
-            message += u": " + format % (value,)
+            message += ": " + format % (value,)
         logger.message(timestamp, message)
 
@@ -767,6 +767,6 @@
     def _logAPHeading(logger, timestamp, state):
         """Log the AP heading."""
-        APLogger._logNumeric(logger, timestamp, u"AP heading",
-                             u"%03.0f\u00b0", state.apHeading)
+        APLogger._logNumeric(logger, timestamp, "AP heading",
+                             "%03.0f\u00b0", state.apHeading)
 
     @staticmethod
@@ -779,6 +779,6 @@
     def _logAPAltitude(logger, timestamp, state):
         """Log the AP heading."""
-        APLogger._logNumeric(logger, timestamp, u"AP altitude",
-                             u"%.0f ft", state.apAltitude)
+        APLogger._logNumeric(logger, timestamp, "AP altitude",
+                             "%.0f ft", state.apAltitude)
 
     def __init__(self):
Index: src/mlx/common.py
===================================================================
--- src/mlx/common.py	(revision 800)
+++ src/mlx/common.py	(revision 995)
@@ -7,13 +7,4 @@
 # Common definitions to be used by both the GUI and possible other parts
 #
-# The main purpose of this module is to import Gtk+2 or 3 and related modules
-# and provide common names for them. There is a similator module in the GUI
-# part (\ref mlx.gui.common), which contains the GUI-specific names. This one
-# contains only what is used by other modules as well.
-# The variable \c pygobject tells which version of Gtk is being used. If it is
-# \c True, Gtk+ 3 is used via the PyGObject interface. Otherwise Gtk+ 2 is
-# used, which is the default on Windows or when the \c FORCE_PYGTK environment
-# variable is set.
-
 #---------------------------------------------------------------------------------------
 
@@ -22,12 +13,33 @@
 #-------------------------------------------------------------------------------
 
-# Due to CEF, PyGTK is the default
-if "FORCE_PYGOBJECT" not in os.environ:
-    print "Using PyGTK"
-    pygobject = False
-    import gobject
-else:
-    print "Using PyGObject"
-    pygobject = True
+from gi.repository import GObject
 
-    from gi.repository import GObject as gobject
+#-------------------------------------------------------------------------------
+
+def fixUnpickledValue(value):
+    """Fix the given unpickled value.
+
+    It handles some basic data, like scalars, lists and tuples. If it
+    encounters byte arrays, they are decoded as 'utf-8' strings."""
+    if isinstance(value, bytes):
+        return str(value, "utf-8")
+    elif isinstance(value, list):
+        return [fixUnpickledValue(v) for v in value]
+    elif isinstance(value, tuple):
+        return tuple([fixUnpickledValue(v) for v in value])
+    else:
+        return value
+
+#-------------------------------------------------------------------------------
+
+def fixUnpickled(state):
+    """Fix the given unpickled state.
+
+    It checks keys and values, and if it encounters any byte arrays, they are
+    decoded with the encoding 'utf-8'. It returns a new dictionary.
+    """
+    newDict = {}
+    for (key, value) in iter(state.items()):
+        newDict[fixUnpickledValue(key)] = fixUnpickledValue(value)
+
+    return newDict
Index: src/mlx/config.py
===================================================================
--- src/mlx/config.py	(revision 738)
+++ src/mlx/config.py	(revision 1011)
@@ -1,11 +1,11 @@
 # -*- encoding: utf-8 -*-
 
-import const
-from util import secondaryInstallation, utf2unicode
+from . import const
+from .util import secondaryInstallation, utf2unicode
 
 import os
 import sys
 import traceback
-import ConfigParser
+import configparser
 
 ## @package mlx.config
@@ -163,5 +163,5 @@
         baseName = "callouts." + const.icaoCodes[aircraftType] + "."
         index = 0
-        for (altitude, path) in self._mapping.iteritems():
+        for (altitude, path) in self._mapping.items():
             option = baseName + str(index)
             config.set(ApproachCallouts.SECTION, option,
@@ -171,9 +171,9 @@
     def getAltitudes(self, descending = True):
         """Get the altitudes in decreasing order by default."""
-        altitudes = self._mapping.keys()
+        altitudes = list(self._mapping.keys())
         altitudes.sort(reverse = descending)
         return altitudes
 
-    def __nonzero__(self):
+    def __bool__(self):
         """Return if there is anything in the mapping."""
         return not not self._mapping
@@ -211,5 +211,5 @@
 class Config(object):
     """Our configuration."""
-    DEFAULT_UPDATE_URL = "http://mlx.varadiistvan.hu/update"
+    DEFAULT_UPDATE_URL = "https://mlx.varadiistvan.hu/update"
 
     _messageTypesSection = "messageTypes"
@@ -258,4 +258,5 @@
         if secondaryInstallation:
             self._updateURL += "/exp"
+        self._updateURLUpdated = True
         self._useRPC = True
 
@@ -703,6 +704,8 @@
     def load(self):
         """Load the configuration from its default location."""
+        self._updateURLUpdated = False
+
         try:
-            config = ConfigParser.RawConfigParser()
+            config = configparser.RawConfigParser()
             config.read(configPath)
         except:
@@ -788,4 +791,10 @@
                                     Config.DEFAULT_UPDATE_URL +
                                     ("/exp" if secondaryInstallation else ""))
+        self._updateURLUpdated = self._getBoolean(config, "update",
+                                                  "urlUpdated", False)
+        if self._updateURL.startswith("http://") and not self._updateURLUpdated:
+            self._updateURL = "https://" + self._updateURL[7:]
+            self._updateURLUpdated = True
+
         self._useRPC = self._getBoolean(config, "general", "useRPC", True)
 
@@ -806,5 +815,5 @@
             return
 
-        config = ConfigParser.RawConfigParser()
+        config = configparser.RawConfigParser()
 
         config.add_section("login")
@@ -880,4 +889,5 @@
                    "yes" if self._autoUpdate else "no")
         config.set("update", "url", self._updateURL)
+        config.set("update", "urlUpdated", self._updateURLUpdated)
 
         config.set("general", "useRPC",
@@ -892,15 +902,15 @@
         try:
             fd = os.open(configPath, os.O_CREAT|os.O_TRUNC|os.O_WRONLY,
-                         0600)
+                         0o600)
             with os.fdopen(fd, "wt") as f:
                 config.write(f)
             self._modified = False
 
-            print "Configuration saved:"
+            print("Configuration saved:")
             self.log()
 
-        except Exception, e:
-            print >> sys.stderr, "Failed to update config: " + \
-                                 utf2unicode(str(e))
+        except Exception as e:
+            print("Failed to update config: " + \
+                                 utf2unicode(str(e)), file=sys.stderr)
 
     def _getBoolean(self, config, section, option, default):
@@ -945,5 +955,5 @@
         import locale
         if self._language:
-            print "Setting up locale for", self._language
+            print("Setting up locale for", self._language)
             os.environ["LANGUAGE"] = self._language
             langAndEncoding = self._language + "." + locale.getpreferredencoding()
@@ -978,62 +988,63 @@
     def log(self):
         """Log the configuration by printing the values"""
-        print "  pilot ID:", self._pilotID
-        print "  rememberPassword:", self._rememberPassword
-
-        print "  language:", self._language
-
-        print "  hideMinimizedWindow:", self._hideMinimizedWindow
-        print "  quitOnClose:", self._quitOnClose
-
-        print "  onlineGateSystem:", self._onlineGateSystem
-        print "  onlineACARS:", self._onlineACARS
-
-        print "  flareTimeFromFS:", self._flareTimeFromFS
-        print "  syncFSTime:", self._syncFSTime
-        print "  usingFS2Crew:", self._usingFS2Crew
-
-        print "  iasSmoothingLength:", self._iasSmoothingLength
-        print "  vsSmoothingLength:", self._vsSmoothingLength
-
-        print "  useSimBrief:", self._useSimBrief
-        print "  simBriefUserName:", self._simBriefUserName
-        print "  rememberSimBriefPassword:", self._rememberSimBriefPassword
-
-        print "  pirepDirectory:", self._pirepDirectory
-        print "  pirepAutoSave:", self._pirepAutoSave
-
-        print "  defaultMSFS:", self._defaultMSFS
-
-        print "  enableSounds:", self._enableSounds
-
-        print "  pilotControlsSounds:", self._pilotControlsSounds
-        print "  pilotHotkey:", str(self._pilotHotkey)
-
-        print "  enableApproachCallouts:", self._enableApproachCallouts
-        print "  speedbrakeAtTD:", self._speedbrakeAtTD
-
-        print "  enableChecklists:", self._enableChecklists
-        print "  checklistHotkey:", str(self._checklistHotkey)
-
-        print "  autoUpdate:", self._autoUpdate
-        print "  updateURL:", self._updateURL
-        print "  useRPC:", self._useRPC
-
-        print "  messageTypeLevels:"
-        for (type, level) in self._messageTypeLevels.iteritems():
-            print "    %s: %s" % (const.messageType2string(type),
-                                  const.messageLevel2string(level))
-
-        print "  checklists:"
-        for (type, checklist) in self._checklists.iteritems():
-            print "    %s:" % (const.icaoCodes[type],)
+        print("  pilot ID:", self._pilotID)
+        print("  rememberPassword:", self._rememberPassword)
+
+        print("  language:", self._language)
+
+        print("  hideMinimizedWindow:", self._hideMinimizedWindow)
+        print("  quitOnClose:", self._quitOnClose)
+
+        print("  onlineGateSystem:", self._onlineGateSystem)
+        print("  onlineACARS:", self._onlineACARS)
+
+        print("  flareTimeFromFS:", self._flareTimeFromFS)
+        print("  syncFSTime:", self._syncFSTime)
+        print("  usingFS2Crew:", self._usingFS2Crew)
+
+        print("  iasSmoothingLength:", self._iasSmoothingLength)
+        print("  vsSmoothingLength:", self._vsSmoothingLength)
+
+        print("  useSimBrief:", self._useSimBrief)
+        print("  simBriefUserName:", self._simBriefUserName)
+        print("  rememberSimBriefPassword:", self._rememberSimBriefPassword)
+
+        print("  pirepDirectory:", self._pirepDirectory)
+        print("  pirepAutoSave:", self._pirepAutoSave)
+
+        print("  defaultMSFS:", self._defaultMSFS)
+
+        print("  enableSounds:", self._enableSounds)
+
+        print("  pilotControlsSounds:", self._pilotControlsSounds)
+        print("  pilotHotkey:", str(self._pilotHotkey))
+
+        print("  enableApproachCallouts:", self._enableApproachCallouts)
+        print("  speedbrakeAtTD:", self._speedbrakeAtTD)
+
+        print("  enableChecklists:", self._enableChecklists)
+        print("  checklistHotkey:", str(self._checklistHotkey))
+
+        print("  autoUpdate:", self._autoUpdate)
+        print("  updateURL:", self._updateURL)
+        print("  updateURLUpdated:", self._updateURLUpdated)
+        print("  useRPC:", self._useRPC)
+
+        print("  messageTypeLevels:")
+        for (type, level) in self._messageTypeLevels.items():
+            print("    %s: %s" % (const.messageType2string(type),
+                                  const.messageLevel2string(level)))
+
+        print("  checklists:")
+        for (type, checklist) in self._checklists.items():
+            print("    %s:" % (const.icaoCodes[type],))
             for path in checklist:
-                print "      " + path
-
-        print "  approachCallouts:"
-        for (type, approachCallouts) in self._approachCallouts.iteritems():
-            print "    %s:" % (const.icaoCodes[type],)
+                print("      " + path)
+
+        print("  approachCallouts:")
+        for (type, approachCallouts) in self._approachCallouts.items():
+            print("    %s:" % (const.icaoCodes[type],))
             for (altitude, path) in approachCallouts:
-                print "      %d: %s" % (altitude, path)
+                print("      %d: %s" % (altitude, path))
 
 #-------------------------------------------------------------------------------
Index: src/mlx/const.py
===================================================================
--- src/mlx/const.py	(revision 1016)
+++ src/mlx/const.py	(revision 1014)
@@ -12,5 +12,5 @@
 
 ## The version of the program
-VERSION="0.39.7"
+VERSION="0.39.6-py3-1"
 
 #-------------------------------------------------------------------------------
@@ -193,5 +193,5 @@
 def aircraftType2Family(aircraftType):
     """Get the family for the given aircraft type."""
-    for (family, types) in aircraftFamily2Types.iteritems():
+    for (family, types) in aircraftFamily2Types.items():
         if aircraftType in types:
             return family
@@ -424,5 +424,5 @@
 def string2messageLevel(str):
     """Get the message level for the given string."""
-    for (value, s) in _messageLevelStrings.iteritems():
+    for (value, s) in _messageLevelStrings.items():
         if str==s:
             return value
Index: src/mlx/flight.py
===================================================================
--- src/mlx/flight.py	(revision 846)
+++ src/mlx/flight.py	(revision 919)
@@ -1,8 +1,8 @@
 
-from soundsched import SoundScheduler, ChecklistScheduler
-from checks import SpeedChecker
-
-import const
-import util
+from .soundsched import SoundScheduler, ChecklistScheduler
+from .checks import SpeedChecker
+
+from . import const
+from . import util
 import time
 
Index: src/mlx/fs.py
===================================================================
--- src/mlx/fs.py	(revision 909)
+++ src/mlx/fs.py	(revision 919)
@@ -1,10 +1,10 @@
 
-import const
-from sound import startSound
+from . import const
+from .sound import startSound
 
 import os
 
-import fsuipc
-import xplane
+from . import fsuipc
+from . import xplane
 
 import threading
@@ -36,13 +36,13 @@
         """Called when a connection has been established to the flight
         simulator of the given type."""
-        print "fs.ConnectionListener.connected, fsType:", fsType, ", descriptor:", descriptor
+        print("fs.ConnectionListener.connected, fsType:", fsType, ", descriptor:", descriptor)
 
     def connectionFailed(self):
         """Called when the connection could not be established."""
-        print "fs.ConnectionListener.connectionFailed"
+        print("fs.ConnectionListener.connectionFailed")
 
     def disconnected(self):
         """Called when a connection to the flight simulator has been broken."""
-        print "fs.ConnectionListener.disconnected"
+        print("fs.ConnectionListener.disconnected")
 
 #-------------------------------------------------------------------------------
Index: src/mlx/fsuipc.py
===================================================================
--- src/mlx/fsuipc.py	(revision 1018)
+++ src/mlx/fsuipc.py	(revision 1015)
@@ -1,8 +1,8 @@
 
-import fs
-import const
-import util
-import acft
-from watchdog import Watchdog
+from . import fs
+from . import const
+from . import util
+from . import acft
+from .watchdog import Watchdog
 
 import threading
@@ -13,9 +13,10 @@
 import codecs
 import math
+from functools import total_ordering
 
 if os.name == "nt" and "FORCE_PYUIPC_SIM" not in os.environ:
     import pyuipc
 else:
-    import pyuipc_sim as pyuipc
+    from . import pyuipc_sim as pyuipc
 
 #------------------------------------------------------------------------------
@@ -104,6 +105,6 @@
         try:
             return fun()
-        except Exception, e:
-            print >> sys.stderr, util.utf2unicode(str(e))
+        except Exception as e:
+            print(util.utf2unicode(str(e)), file=sys.stderr)
             return None
 
@@ -133,5 +134,5 @@
             try:
                 values = pyuipc.read(data)
-            except TypeError, e:
+            except TypeError as e:
                 exception = e
 
@@ -174,5 +175,5 @@
                 try:
                     pyuipc.write(self._data)
-                except TypeError, e:
+                except TypeError as e:
                     exception = e
 
@@ -197,4 +198,5 @@
                 Handler._callSafe(lambda: self._callback(None, self._extra))
 
+    @total_ordering
     class PeriodicRequest(object):
         """A periodic request."""
@@ -250,8 +252,15 @@
             pass
 
-        def __cmp__(self, other):
-            """Compare two periodic requests. They are ordered by their next
-            firing times."""
-            return cmp(self._nextFire, other._nextFire)
+        def __eq__(self, other):
+            """Equality comparison by the firing times"""
+            return self._nextFire == other._nextFire
+
+        def __ne__(self, other):
+            """Non-equality comparison by the firing times"""
+            return self._nextFire != other._nextFire
+
+        def __lt__(self, other):
+            """Less-than comparison by the firing times"""
+            return self._nextFire < other._nextFire
 
     def __init__(self, connectionListener,
@@ -420,8 +429,8 @@
                 self._connected = True
                 return attempts
-            except Exception, e:
-                print "fsuipc.Handler._connect: connection failed: " + \
+            except Exception as e:
+                print("fsuipc.Handler._connect: connection failed: " + \
                       util.utf2unicode(str(e)) + \
-                      " (attempts: %d)" % (attempts,)
+                      " (attempts: %d)" % (attempts,))
                 if attempts<self.NUM_CONNECTATTEMPTS:
                     time.sleep(self.CONNECT_INTERVAL)
@@ -454,5 +463,5 @@
     def _disconnect(self):
         """Disconnect from the flight simulator."""
-        print "fsuipc.Handler._disconnect"
+        print("fsuipc.Handler._disconnect")
         if self._connected:
             pyuipc.close()
@@ -479,16 +488,16 @@
             try:
                 if not request.process(time):
-                    print "fsuipc.Handler._processRequest: FSUIPC returned invalid data too many times, reconnecting"
+                    print("fsuipc.Handler._processRequest: FSUIPC returned invalid data too many times, reconnecting")
                     needReconnect = True
             except TypeError as e:
-                print "fsuipc.Handler._processRequest: type error: " + \
+                print("fsuipc.Handler._processRequest: type error: " + \
                       util.utf2unicode(str(e)) + \
                       ("." if request.unimportant else
-                       (", reconnecting (attempts=%d)." % (attempts,)))
+                       (", reconnecting (attempts=%d)." % (attempts,))))
                 needReconnect = not request.unimportant
             except Exception as e:
-                print "fsuipc.Handler._processRequest: FSUIPC connection failed (" + \
+                print("fsuipc.Handler._processRequest: FSUIPC connection failed (" + \
                       util.utf2unicode(str(e)) + \
-                      "), reconnecting (attempts=%d)." % (attempts,)
+                      "), reconnecting (attempts=%d)." % (attempts,))
                 needReconnect = True
 
@@ -648,5 +657,4 @@
         self._hotkeyCallback = None
 
-        self._latin1decoder = codecs.getdecoder("iso-8859-1")
         self._fuelCallback = None
 
@@ -723,5 +731,5 @@
         duration is the number of seconds to keep the message displayed."""
 
-        print "fsuipc.Simulator.sendMessage:", message
+        print("fsuipc.Simulator.sendMessage:", message)
 
         if self._scroll:
@@ -731,7 +739,7 @@
 
         try:
-            message = str(message)
-        except Exception, e:
-            print "fsuipc.Simulator.sendMessage: failed to convert the message to a string:", e
+            message = bytes(str(message), "iso-8859-1")
+        except Exception as e:
+            print("fsuipc.Simulator.sendMessage: failed to convert the message to a string:", e)
 
         data = [(0x3380, -1 - len(message), message),
@@ -822,5 +830,5 @@
         assert not self._monitoringRequested
 
-        print "fsuipc.Simulator.disconnect", closingMessage, duration
+        print("fsuipc.Simulator.disconnect", closingMessage, duration)
 
         self._stopNormal()
@@ -887,5 +895,8 @@
         timestamp = Simulator._getTimestamp(data)
 
-        createdNewModel = self._setAircraftName(timestamp, data[5], data[6])
+        aircraftName = str(data[5], "iso-8859-1")
+        aircraftPath = str(data[6], "iso-8859-1")
+
+        createdNewModel = self._setAircraftName(timestamp, aircraftName, aircraftPath)
         if self._fuelCallback is not None:
             self._aircraftModel.getFuel(self._handler, self._fuelCallback)
@@ -946,13 +957,10 @@
 
         Return if a new model was created."""
-        name = self._latin1decoder(name)[0]
-        airPath = self._latin1decoder(airPath)[0]
-
         aircraftName = (name, airPath)
         if aircraftName==self._aircraftName:
             return False
 
-        print "fsuipc.Simulator: new aircraft name and air file path: %s, %s" % \
-              (name, airPath)
+        print("fsuipc.Simulator: new aircraft name and air file path: %s, %s" % \
+              (name, airPath))
 
         self._aircraftName = aircraftName
@@ -1088,13 +1096,14 @@
             self._handler.disconnect()
 
-    def _handleNumHotkeys(self, data, (id, generation)):
+    def _handleNumHotkeys(self, data, hotkeySet):
         """Handle the result of the query of the number of hotkeys"""
+        (id, generation) = hotkeySet
         with self._hotkeyLock:
             if id==self._hotkeySetID and generation==self._hotkeySetGeneration:
                 numHotkeys = data[0]
-                print "fsuipc.Simulator._handleNumHotkeys: numHotkeys:", numHotkeys
+                print("fsuipc.Simulator._handleNumHotkeys: numHotkeys:", numHotkeys)
                 data = [(0x3210 + i*4, "d") for i in range(0, numHotkeys)]
                 self._handler.requestRead(data, self._handleHotkeyTable,
-                                          (id, generation))
+                                          hotkeySet)
 
     def _setupHotkeys(self, data):
@@ -1135,10 +1144,11 @@
 
         for offset in oldHotkeyOffsets:
-            writeData.append((offset, "u", long(0)))
+            writeData.append((offset, "u", int(0)))
 
         return writeData
 
-    def _handleHotkeyTable(self, data, (id, generation)):
+    def _handleHotkeyTable(self, data, hotkeySet):
         """Handle the result of the query of the hotkey table."""
+        (id, generation) = hotkeySet
         with self._hotkeyLock:
             if id==self._hotkeySetID and generation==self._hotkeySetGeneration:
@@ -1146,8 +1156,9 @@
                 self._handler.requestWrite(writeData,
                                            self._handleHotkeysWritten,
-                                           (id, generation))
-
-    def _handleHotkeysWritten(self, success, (id, generation)):
+                                           hotkeySet)
+
+    def _handleHotkeysWritten(self, success, hotkeySet):
         """Handle the result of the hotkeys having been written."""
+        (id, generation) = hotkeySet
         with self._hotkeyLock:
             if success and id==self._hotkeySetID and \
@@ -1158,8 +1169,9 @@
                     self._handler.requestPeriodicRead(0.5, data,
                                                       self._handleHotkeys,
-                                                      (id, generation))
-
-    def _handleHotkeys(self, data, (id, generation)):
+                                                      hotkeySet)
+
+    def _handleHotkeys(self, data, hotkeySet):
         """Handle the hotkeys."""
+        (id, generation) = hotkeySet
         with self._hotkeyLock:
             if id!=self._hotkeySetID or generation!=self._hotkeySetGeneration:
@@ -1397,7 +1409,7 @@
 
         numNotchesM1 = len(self._flapsNotches) - 1
-        flapsIncrement = 16383 / numNotchesM1
+        flapsIncrement = 16383 // numNotchesM1
         flapsControl = data[self._monidx_flapsControl]
-        flapsIndex = flapsControl / flapsIncrement
+        flapsIndex = flapsControl // flapsIncrement
         if flapsIndex < numNotchesM1:
             if (flapsControl - (flapsIndex*flapsIncrement) >
@@ -1406,8 +1418,8 @@
         state.flapsSet = self._flapsNotches[flapsIndex]
         if state.flapsSet != self._flapsSet:
-            print "flapsControl: %d, flapsLeft: %d, flapsRight: %d, flapsAxis: %d, flapsIncrement: %d, flapsSet: %d, numNotchesM1: %d" % \
+            print("flapsControl: %d, flapsLeft: %d, flapsRight: %d, flapsAxis: %d, flapsIncrement: %d, flapsSet: %d, numNotchesM1: %d" % \
                   (flapsControl, data[self._monidx_flapsLeft],
                    data[self._monidx_flapsRight], data[self._monidx_flapsAxis],
-                   data[self._monidx_flapsIncrement], state.flapsSet, numNotchesM1)
+                   data[self._monidx_flapsIncrement], state.flapsSet, numNotchesM1))
             self._flapsSet = state.flapsSet
 
@@ -1588,5 +1600,5 @@
         for (tank, level) in levels:
             offset = _tank2offset[tank]
-            value = long(level * 128.0 * 65536.0)
+            value = int(level * 128.0 * 65536.0)
             data.append( (offset, "u", value) )
 
@@ -1698,7 +1710,8 @@
     """A model handler for the PMDG Boeing 737NG model."""
     @staticmethod
-    def doesHandle(aircraft, (name, airPath)):
+    def doesHandle(aircraft, aircraftName):
         """Determine if this model handler handles the aircraft with the given
         name."""
+        (name, airPath) = aircraftName
         return aircraft.type in [const.AIRCRAFT_B736,
                                  const.AIRCRAFT_B737,
@@ -1730,6 +1743,6 @@
 
         if fsType==const.SIM_MSFSX or fsType==const.SIM_P3D:
-            print "%s detected, adding PMDG 737 NGX-specific offsets" % \
-                  ("FSX" if fsType==const.SIM_MSFSX else "P3D",)
+            print("%s detected, adding PMDG 737 NGX-specific offsets" % \
+                  ("FSX" if fsType==const.SIM_MSFSX else "P3D",))
             self._addOffsetWithIndexMember(data, 0x6500, "b",
                                            "_pmdgidx_lts_positionsw")
@@ -1741,5 +1754,5 @@
             self._addOffsetWithIndexMember(data, 0x65cd, "b", "_pmdgidx_xpdr")
         else:
-            print "FS9 detected, adding PMDG 737 NG-specific offsets"
+            print("FS9 detected, adding PMDG 737 NG-specific offsets")
             self._addOffsetWithIndexMember(data, 0x6202, "b", "_pmdgidx_switches")
             self._addOffsetWithIndexMember(data, 0x6216, "b", "_pmdgidx_xpdr")
@@ -1786,5 +1799,5 @@
 
         if gearControl!=self._lastGearControl or noseGear!=self._lastNoseGear:
-            print "gearControl:", gearControl, " noseGear:", noseGear
+            print("gearControl:", gearControl, " noseGear:", noseGear)
             self._lastGearControl = gearControl
             self._lastNoseGear = noseGear
@@ -1833,7 +1846,8 @@
     """Model handler for the Dreamwings Dash 8-Q400."""
     @staticmethod
-    def doesHandle(aircraft, (name, airPath)):
+    def doesHandle(aircraft, aircraftName):
         """Determine if this model handler handles the aircraft with the given
         name."""
+        (name, airPath) = aircraftName
         return aircraft.type==const.AIRCRAFT_DH8D and \
             (name.find("Dreamwings")!=-1 or airPath.find("Dreamwings")!=-1) and \
@@ -1870,7 +1884,8 @@
     """Model handler for the Majestic Dash 8-Q400."""
     @staticmethod
-    def doesHandle(aircraft, (name, airPath)):
+    def doesHandle(aircraft, aircraftName):
         """Determine if this model handler handles the aircraft with the given
         name."""
+        (name, airPath) = aircraftName
         return aircraft.type==const.AIRCRAFT_DH8D and \
             (name.find("MJC8Q400")!=-1 or \
@@ -1948,7 +1963,8 @@
     """Model for the Digital Aviation F70 implementation on FS9."""
     @staticmethod
-    def doesHandle(aircraft, (name, airPath)):
+    def doesHandle(aircraft, aircraftName):
         """Determine if this model handler handles the aircraft with the given
         name."""
+        (name, airPath) = aircraftName
         return aircraft.type == const.AIRCRAFT_F70 and \
                (airPath.endswith("fokker70_2k4_v4.1.air") or
@@ -2137,8 +2153,9 @@
     """Project Tupolev Tu-154."""
     @staticmethod
-    def doesHandle(aircraft, (name, airPath)):
+    def doesHandle(aircraft, aircraftName):
         """Determine if this model handler handles the aircraft with the given
         name."""
-        print "PTT154Model.doesHandle", aircraft.type, name, airPath
+        (name, airPath) = aircraftName
+        print("PTT154Model.doesHandle", aircraft.type, name, airPath)
         return aircraft.type==const.AIRCRAFT_T154 and \
                (name.find("Tu-154")!=-1 or name.find("Tu154B")!=-1) and \
Index: src/mlx/gui/acars.py
===================================================================
--- src/mlx/gui/acars.py	(revision 747)
+++ src/mlx/gui/acars.py	(revision 996)
@@ -1,9 +1,9 @@
 
-from common import *
+from .common import *
 
 from mlx.i18n import xstr
 import mlx.const as const
 
-import cef
+from . import cef
 
 #------------------------------------------------------------------------------
@@ -18,5 +18,5 @@
 #------------------------------------------------------------------------------
 
-class ACARS(gtk.VBox):
+class ACARS(Gtk.VBox):
     """The flight info tab."""
     # The URL of the ACARS map
Index: src/mlx/gui/bugreport.py
===================================================================
--- src/mlx/gui/bugreport.py	(revision 492)
+++ src/mlx/gui/bugreport.py	(revision 999)
@@ -1,4 +1,4 @@
 
-from common import *
+from .common import *
 
 from mlx.i18n import xstr
@@ -18,5 +18,5 @@
 #------------------------------------------------------------------------------
 
-class BugReportDialog(gtk.Dialog):
+class BugReportDialog(Gtk.Dialog):
     """The dialog to report a bug."""
     def __init__(self, gui):
@@ -24,8 +24,8 @@
                                               xstr("bugreport_title"),
                                               gui.mainWindow,
-                                              DIALOG_MODAL)
+                                              Gtk.DialogFlags.MODAL)
 
-        self.add_button(xstr("button_cancel"), RESPONSETYPE_REJECT)
-        self._sendButton = self.add_button(xstr("button_send"), RESPONSETYPE_ACCEPT)
+        self.add_button(xstr("button_cancel"), Gtk.ResponseType.REJECT)
+        self._sendButton = self.add_button(xstr("button_send"), Gtk.ResponseType.ACCEPT)
         self._sendButton.set_can_default(True)
         self._gui = gui
@@ -33,5 +33,5 @@
         contentArea = self.get_content_area()
 
-        contentAlignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
+        contentAlignment = Gtk.Alignment(xalign = 0.5, yalign = 0.5,
                                          xscale = 0.0, yscale = 0.0)
         contentAlignment.set_padding(padding_top = 4, padding_bottom = 16,
@@ -40,8 +40,8 @@
         contentArea.pack_start(contentAlignment, False, False, 0)
 
-        contentVBox = gtk.VBox()
+        contentVBox = Gtk.VBox()
         contentAlignment.add(contentVBox)
 
-        label = gtk.Label(xstr("bugreport_summary"))
+        label = Gtk.Label(xstr("bugreport_summary"))
         label.set_use_underline(True)
         label.set_alignment(0.0, 0.5)
@@ -49,5 +49,5 @@
         contentVBox.pack_start(label, False, False, 4)
 
-        self._summary = summary = gtk.Entry()
+        self._summary = summary = Gtk.Entry()
         summary.connect("changed", self._summaryChanged)
         summary.set_tooltip_text(xstr("bugreport_summary_tooltip"))
@@ -56,5 +56,5 @@
         contentVBox.pack_start(summary, True, True, 4)
 
-        label = gtk.Label(xstr("bugreport_description"))
+        label = Gtk.Label(xstr("bugreport_description"))
         label.set_use_underline(True)
         label.set_alignment(0.0, 0.5)
@@ -62,24 +62,25 @@
         contentVBox.pack_start(label, False, False, 4)
 
-        self._description = description = gtk.TextView()
+        self._description = description = Gtk.TextView()
         description.set_tooltip_text(xstr("bugreport_description_tooltip"))
-        description.set_wrap_mode(WRAP_WORD)
+        description.set_wrap_mode(Gtk.WrapMode.WORD)
         label.set_mnemonic_widget(description)
 
-        scrolledWindow = gtk.ScrolledWindow()
+        scrolledWindow = Gtk.ScrolledWindow()
         scrolledWindow.add(description)
         scrolledWindow.set_size_request(-1, 200)
-        scrolledWindow.set_policy(POLICY_AUTOMATIC, POLICY_AUTOMATIC)
-        scrolledWindow.set_shadow_type(SHADOW_IN)
+        scrolledWindow.set_policy(Gtk.PolicyType.AUTOMATIC,
+                                  Gtk.PolicyType.AUTOMATIC)
+        scrolledWindow.set_shadow_type(Gtk.ShadowType.IN)
 
-        alignment = gtk.Alignment(xalign = 0.5, yalign = 0.0, xscale = 1.0, yscale = 1.0)
+        alignment = Gtk.Alignment(xalign = 0.5, yalign = 0.0, xscale = 1.0, yscale = 1.0)
         alignment.add(scrolledWindow)
 
         contentVBox.pack_start(alignment, True, True, 4)
 
-        emailBox = gtk.HBox()
+        emailBox = Gtk.HBox()
         contentVBox.pack_start(emailBox, False, False, 4)
 
-        label = gtk.Label(xstr("bugreport_email"))
+        label = Gtk.Label(xstr("bugreport_email"))
         label.set_use_underline(True)
         label.set_alignment(0.0, 0.5)
@@ -87,8 +88,8 @@
         emailBox.pack_start(label, False, False, 0)
 
-        alignment = gtk.Alignment()
+        alignment = Gtk.Alignment()
         emailBox.pack_start(alignment, False, False, 8)
 
-        self._email = email = gtk.Entry()
+        self._email = email = Gtk.Entry()
         email.set_tooltip_text(xstr("bugreport_email_tooltip"))
         label.set_mnemonic_widget(email)
@@ -105,6 +106,6 @@
         response = super(BugReportDialog, self).run()
 
-        print "response", response, RESPONSETYPE_ACCEPT
-        if response==RESPONSETYPE_ACCEPT:
+        print("response", response, Gtk.ResponseType.ACCEPT)
+        if response==Gtk.ResponseType.ACCEPT:
             self._send()
         else:
@@ -126,9 +127,8 @@
                                      descriptionBuffer.get_end_iter(),
                                      False)
-        description = text2unicode(description)
         self.set_sensitive(False)
-        self._gui.sendBugReport(text2unicode(self._summary.get_text()),
+        self._gui.sendBugReport(self._summary.get_text(),
                                 description,
-                                text2unicode(self._email.get_text()),
+                                self._email.get_text(),
                                 self._bugReportSent)
 
Index: src/mlx/gui/callouts.py
===================================================================
--- src/mlx/gui/callouts.py	(revision 300)
+++ src/mlx/gui/callouts.py	(revision 999)
@@ -1,4 +1,4 @@
 
-from common import *
+from .common import *
 
 from mlx.i18n import xstr
@@ -27,5 +27,5 @@
 #------------------------------------------------------------------------------
 
-class ApproachCalloutsEditor(gtk.Dialog):
+class ApproachCalloutsEditor(Gtk.Dialog):
     """The dialog to edit the approach callouts."""
     integerRE = re.compile("[0-9]+")
@@ -54,8 +54,8 @@
                                                      xstr("callouts_title"),
                                                      gui.mainWindow,
-                                                     DIALOG_MODAL)
-
-        self.add_button(xstr("button_cancel"), RESPONSETYPE_REJECT)
-        self.add_button(xstr("button_ok"), RESPONSETYPE_ACCEPT)
+                                                     Gtk.DialogFlags.MODAL)
+
+        self.add_button(xstr("button_cancel"), Gtk.ResponseType.REJECT)
+        self.add_button(xstr("button_ok"), Gtk.ResponseType.ACCEPT)
 
         self._gui = gui
@@ -67,18 +67,18 @@
 
         # FIXME: common code with the checklist editor
-        typeBox = gtk.HBox()
-
-        label = gtk.Label(xstr("callouts_aircraftType"))
+        typeBox = Gtk.HBox()
+
+        label = Gtk.Label(xstr("callouts_aircraftType"))
         label.set_use_underline(True)
 
         typeBox.pack_start(label, False, False, 4)
 
-        self._aircraftTypeModel = gtk.ListStore(str, int)
+        self._aircraftTypeModel = Gtk.ListStore(str, int)
         for type in const.aircraftTypes:
             name = aircraftNames[type] if type in aircraftNames \
                    else "Aircraft type #%d" % (type,)
             self._aircraftTypeModel.append([name, type])
-        self._aircraftType = gtk.ComboBox(model = self._aircraftTypeModel)
-        renderer = gtk.CellRendererText()
+        self._aircraftType = Gtk.ComboBox(model = self._aircraftTypeModel)
+        renderer = Gtk.CellRendererText()
         self._aircraftType.pack_start(renderer, True)
         self._aircraftType.add_attribute(renderer, "text", 0)
@@ -90,5 +90,5 @@
         typeBox.pack_start(self._aircraftType, True, True, 4)
 
-        typeBoxAlignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
+        typeBoxAlignment = Gtk.Alignment(xalign = 0.5, yalign = 0.5,
                                          xscale = 0.0, yscale = 0.0)
         typeBoxAlignment.set_size_request(400, -1)
@@ -98,8 +98,8 @@
         # FIXME: common code until here, but note that some texts are different
 
-        contentBox = gtk.HBox()        
-
-        controlBox = gtk.VBox()
-        controlAlignment = gtk.Alignment(xalign = 0.0, yalign = 0.0,
+        contentBox = Gtk.HBox()        
+
+        controlBox = Gtk.VBox()
+        controlAlignment = Gtk.Alignment(xalign = 0.0, yalign = 0.0,
                                          xscale = 0.0, yscale = 0.0)
         controlAlignment.set_padding(padding_top = 0, padding_bottom = 0,
@@ -108,9 +108,9 @@
         contentBox.pack_start(controlAlignment, False, False, 0)
 
-        self._addButton = gtk.Button(xstr("callouts_add"))
+        self._addButton = Gtk.Button(xstr("callouts_add"))
         self._addButton.set_use_underline(True)
         self._addButton.set_tooltip_text(xstr("callouts_add_tooltip"))
         self._addButton.connect("clicked", self._addButtonClicked)
-        addAlignment = gtk.Alignment(xalign = 0.5, yalign = 0.0,
+        addAlignment = Gtk.Alignment(xalign = 0.5, yalign = 0.0,
                                      xscale = 0.0, yscale = 0.0)
         addAlignment.set_padding(padding_top = 24, padding_bottom = 0,
@@ -119,5 +119,5 @@
         controlBox.pack_start(addAlignment, False, False, 0)
 
-        self._removeButton = gtk.Button(xstr("callouts_remove"))
+        self._removeButton = Gtk.Button(xstr("callouts_remove"))
         self._removeButton.set_use_underline(True)
         self._removeButton.set_tooltip_text(xstr("callouts_remove_tooltip"))
@@ -125,5 +125,5 @@
         self._removeButton.connect("clicked", self._removeButtonClicked)
 
-        removeAlignment = gtk.Alignment(xalign = 0.5, yalign = 0.0,
+        removeAlignment = Gtk.Alignment(xalign = 0.5, yalign = 0.0,
                                         xscale = 0.0, yscale = 0.0)
         removeAlignment.set_padding(padding_top = 24, padding_bottom = 0,
@@ -132,6 +132,6 @@
         controlBox.pack_start(removeAlignment, False, False, 0)
 
-        self._fileListModel = gtk.ListStore(int, str, str)
-        self._fileListModel.set_sort_column_id(0, SORT_DESCENDING)
+        self._fileListModel = Gtk.ListStore(int, str, str)
+        self._fileListModel.set_sort_column_id(0, Gtk.SortType.DESCENDING)
 
         self._addingFile = False
@@ -139,14 +139,14 @@
         self._lastAddedAltitude = None
         
-        self._fileList = gtk.TreeView(model = self._fileListModel)
-
-        renderer = gtk.CellRendererSpin()
+        self._fileList = Gtk.TreeView(model = self._fileListModel)
+
+        renderer = Gtk.CellRendererSpin()
         renderer.set_property("editable", True)
 
-        adjustment = gtk.Adjustment(0, 0, 5000, 10, 100)
+        adjustment = Gtk.Adjustment(0, 0, 5000, 10, 100)
         renderer.set_property("adjustment", adjustment);
         renderer.connect("edited", self._altitudeEdited)
         
-        column = gtk.TreeViewColumn(xstr("callouts_header_altitude"),
+        column = Gtk.TreeViewColumn(xstr("callouts_header_altitude"),
                                     renderer, text = 0)
         self._fileList.append_column(column)
@@ -156,9 +156,9 @@
         column.set_sort_indicator(True)
         column.set_sort_column_id(0)
-        column.set_sort_order(SORT_DESCENDING)
+        column.set_sort_order(Gtk.SortType.DESCENDING)
         column.set_expand(False)
 
-        column = gtk.TreeViewColumn(xstr("callouts_header_path"),
-                                    gtk.CellRendererText(), text = 1)
+        column = Gtk.TreeViewColumn(xstr("callouts_header_path"),
+                                    Gtk.CellRendererText(), text = 1)
         self._fileList.append_column(column)
         column.set_expand(True)
@@ -173,16 +173,17 @@
                                self._fileListButtonPressed)
         selection = self._fileList.get_selection()
-        selection.set_mode(SELECTION_MULTIPLE)
+        selection.set_mode(Gtk.SelectionMode.MULTIPLE)
         selection.connect("changed", self._fileListSelectionChanged)
 
         self._buildFileListPopupMenu()
 
-        scrolledWindow = gtk.ScrolledWindow()
+        scrolledWindow = Gtk.ScrolledWindow()
         scrolledWindow.add(self._fileList)
         scrolledWindow.set_size_request(300, -1)
-        scrolledWindow.set_policy(POLICY_AUTOMATIC, POLICY_AUTOMATIC)
-        scrolledWindow.set_shadow_type(SHADOW_IN)
-        
-        fileListAlignment = gtk.Alignment(xscale=1.0, yscale=1.0, 
+        scrolledWindow.set_policy(Gtk.PolicyType.AUTOMATIC,
+                                  Gtk.PolicyType.AUTOMATIC)
+        scrolledWindow.set_shadow_type(Gtk.ShadowType.IN)
+        
+        fileListAlignment = Gtk.Alignment(xscale=1.0, yscale=1.0, 
                                           xalign=0.5, yalign=0.5)
         fileListAlignment.set_padding(padding_top = 0, padding_bottom = 16,
@@ -204,9 +205,9 @@
         self.hide()
 
-        if response==RESPONSETYPE_ACCEPT:
+        if response==Gtk.ResponseType.ACCEPT:
             self._saveApproachCallouts()
             config = self._gui.config
             for (aircraftType, approachCallouts) in \
-                    self._approachCallouts.iteritems():
+                    self._approachCallouts.items():
                 config.setApproachCallouts(aircraftType, approachCallouts)
             config.save()
@@ -225,5 +226,5 @@
         dialog.hide()
 
-        if result==RESPONSETYPE_OK:
+        if result==Gtk.ResponseType.OK:
             filePath = dialog.get_filename()
             baseName = os.path.basename(filePath)
@@ -239,5 +240,5 @@
         Makes the treeview to edit the altitude in the given row."""
         if self._addingFile:
-            gobject.idle_add(self._selectFile)
+            GObject.idle_add(self._selectFile)
             self._fileList.grab_focus()
             self.grab_focus()
@@ -292,11 +293,11 @@
         otherPath = self._hasAltitude(newAltitude, ignorePath = editedPath)
         if otherPath is not None:
-            dialog = gtk.MessageDialog(parent = self,
-                                       type = MESSAGETYPE_QUESTION,
+            dialog = Gtk.MessageDialog(parent = self,
+                                       type = Gtk.MessageType.QUESTION,
                                        message_format =
                                        xstr("callouts_altitude_clash"))
             dialog.format_secondary_markup(xstr("callouts_altitude_clash_sec"))
-            dialog.add_button(xstr("button_no"), RESPONSETYPE_NO)
-            dialog.add_button(xstr("button_yes"), RESPONSETYPE_YES)
+            dialog.add_button(xstr("button_no"), Gtk.ResponseType.NO)
+            dialog.add_button(xstr("button_yes"), Gtk.ResponseType.YES)
             dialog.set_title(WINDOW_TITLE_BASE)
 
@@ -304,5 +305,5 @@
             dialog.hide()
 
-            if result!=RESPONSETYPE_YES:
+            if result!=Gtk.ResponseType.YES:
                 newAltitude = None
                 
@@ -346,10 +347,10 @@
         If it does not exist yet, it will be created."""
         if self._fileOpenDialog is None:
-            dialog = gtk.FileChooserDialog(title = WINDOW_TITLE_BASE + " - " +
+            dialog = Gtk.FileChooserDialog(title = WINDOW_TITLE_BASE + " - " +
                                            xstr("callouts_open_title"),
-                                           action = FILE_CHOOSER_ACTION_OPEN,
-                                           buttons = (gtk.STOCK_CANCEL,
-                                                      RESPONSETYPE_CANCEL,
-                                                      gtk.STOCK_OK, RESPONSETYPE_OK),
+                                           action = Gtk.FileChooserAction.OPEN,
+                                           buttons = (Gtk.STOCK_CANCEL,
+                                                      Gtk.ResponseType.CANCEL,
+                                                      Gtk.STOCK_OK, Gtk.ResponseType.OK),
                                            parent = self)
             dialog.set_modal(True)            
@@ -358,5 +359,5 @@
             # FIXME: create the filters in one location and use them
             # from there
-            filter = gtk.FileFilter()
+            filter = Gtk.FileFilter()
             filter.set_name(xstr("file_filter_audio"))
             filter.add_pattern("*.wav")
@@ -364,5 +365,5 @@
             dialog.add_filter(filter)
 
-            filter = gtk.FileFilter()
+            filter = Gtk.FileFilter()
             filter.set_name(xstr("file_filter_all"))
             filter.add_pattern("*.*")
@@ -389,5 +390,5 @@
         if altitude is not None: return altitude
 
-        descending = self._fileList.get_column(0).get_sort_order()==SORT_DESCENDING
+        descending = self._fileList.get_column(0).get_sort_order()==Gtk.SortType.DESCENDING
         model = self._fileListModel
         numEntries = model.iter_n_children(None)
@@ -473,18 +474,15 @@
     def _fileListButtonPressed(self, widget, event):
         """Called when a mouse button is pressed on the file list."""
-        if event.type!=EVENT_BUTTON_PRESS or event.button!=3:
+        if event.type!=Gdk.EventType.BUTTON_PRESS or event.button!=3:
             return
 
         menu = self._fileListPopupMenu
-        if pygobject:
-            menu.popup(None, None, None, None, event.button, event.time)
-        else:
-            menu.popup(None, None, None, event.button, event.time)
+        menu.popup(None, None, None, None, event.button, event.time)
 
     def _buildFileListPopupMenu(self):
         """Build the file list popup menu."""
-        menu = gtk.Menu()
-
-        menuItem = gtk.MenuItem()
+        menu = Gtk.Menu()
+
+        menuItem = Gtk.MenuItem()
         menuItem.set_label(xstr("callouts_remove"))
         menuItem.set_use_underline(True)
Index: src/mlx/gui/cef.py
===================================================================
--- src/mlx/gui/cef.py	(revision 915)
+++ src/mlx/gui/cef.py	(revision 997)
@@ -1,3 +1,3 @@
-from common import *
+from .common import *
 
 from mlx.util import secondaryInstallation
@@ -10,11 +10,12 @@
 import os
 import re
-import thread
+import _thread
 import threading
 import tempfile
 import traceback
-import urllib2
+import ctypes
+import urllib.request, urllib.error, urllib.parse
 from lxml import etree
-from StringIO import StringIO
+from io import StringIO
 import lxml.html
 
@@ -100,5 +101,5 @@
     def call(self, plan, getCredentials, updateProgress, htmlFilePath):
         """Call SimBrief with the given plan."""
-        self._timeoutID = gobject.timeout_add(120*1000, self._timedOut)
+        self._timeoutID = GObject.timeout_add(120*1000, self._timedOut)
 
         self._plan = plan
@@ -112,9 +113,9 @@
                              SIMBRIEF_RESULT_NONE, None)
 
-    def _onLoadEnd(self, browser, frame, httpCode):
+    def _onLoadEnd(self, browser, frame, http_code):
         """Called when a page has been loaded in the SimBrief browser."""
         url = frame.GetUrl()
-        print "gui.cef.SimBriefHandler._onLoadEnd", httpCode, url
-        if httpCode>=300:
+        print("gui.cef.SimBriefHandler._onLoadEnd", http_code, url)
+        if http_code>=300:
             self._updateProgress(self._lastProgress,
                                  SIMBRIEF_RESULT_ERROR_OTHER, None)
@@ -127,7 +128,7 @@
 
             js = "form=document.getElementById(\"sbapiform\");"
-            for (name, value) in self._plan.iteritems():
+            for (name, value) in self._plan.items():
                 js += "form." + name + ".value=\"" + value + "\";"
-            for (name, value) in SimBriefHandler._querySettings.iteritems():
+            for (name, value) in SimBriefHandler._querySettings.items():
                 if isinstance(value, bool):
                     js += "form." + name + ".checked=" + \
@@ -175,6 +176,6 @@
 
             thread = threading.Thread(target = self._getResults, args = (link,))
-            thread.daemon = True
-            thread.start()
+            _thread.daemon = True
+            _thread.start()
         else:
             self._updateProgress(SIMBRIEF_PROGRESS_RETRIEVING_BRIEFING,
@@ -194,8 +195,10 @@
         self._lastProgress = progress
         if results!=SIMBRIEF_RESULT_NONE:
-            gobject.source_remove(self._timeoutID)
+            if self._timeoutID is not None:
+                GObject.source_remove(self._timeoutID)
             self._plan = None
 
-        self._updateProgressFn(progress, results, flightInfo)
+        if self._updateProgressFn is not None:
+            self._updateProgressFn(progress, results, flightInfo)
 
     def _timedOut(self):
@@ -219,5 +222,5 @@
 
         # Obtaining the xml
-        response = urllib2.urlopen(link)
+        response = urllib.request.urlopen(link)
         xmlContent = response.read()
         # Processing xml
@@ -242,5 +245,5 @@
                     imageLinks.append(imageLink[2])
         flightInfo["image_links"] = imageLinks
-        print(sorted(availableInfo.keys()))
+        print((sorted(availableInfo.keys())))
         htmlFilePath = "simbrief_plan.html" if self._htmlFilePath is None \
           else self._htmlFilePath
@@ -248,5 +251,5 @@
             f.write(availableInfo["plan_html"])
 
-        gobject.idle_add(self._resultsAvailable, flightInfo)
+        GObject.idle_add(self._resultsAvailable, flightInfo)
 
 #------------------------------------------------------------------------------
@@ -257,5 +260,5 @@
     _toQuit = False
 
-    gobject.threads_init()
+    GObject.threads_init()
 
     _simBriefHandler = SimBriefHandler()
@@ -266,5 +269,5 @@
 def _initializeCEF(args, initializedCallback):
     """Perform the actual initialization of CEF using the given arguments."""
-    print "Initializing CEF with args:", args
+    print("Initializing CEF with args:", args)
 
     settings = {
@@ -290,11 +293,11 @@
                     switches[arg[2:assignIndex]] = arg[assignIndex+1:]
         else:
-            print "Unhandled switch", arg
+            print("Unhandled switch", arg)
 
     cefpython.Initialize(settings, switches)
 
-    gobject.timeout_add(10, _handleTimeout)
-
-    print "Initialized, executing callback..."
+    GObject.timeout_add(10, _handleTimeout)
+
+    print("Initialized, executing callback...")
     initializedCallback()
 
@@ -305,9 +308,9 @@
     within."""
     if os.name=="nt":
-        container = gtk.DrawingArea()
+        container = Gtk.DrawingArea()
         container.set_property("can-focus", True)
         container.connect("size-allocate", _handleSizeAllocate)
     else:
-        container = gtk.DrawingArea()
+        container = Gtk.DrawingArea()
 
     container.show()
@@ -320,12 +323,17 @@
     """Start a browser instance in the given container with the given URL."""
     if os.name=="nt":
-        window = container.get_window()
-        if window is None:
-            print "mlx.gui.cef.startInContainer: no window found!"
-            windowID = None
-        else:
-            windowID = window.handle
+        Gdk.threads_enter()
+        ctypes.pythonapi.PyCapsule_GetPointer.restype = ctypes.c_void_p
+        ctypes.pythonapi.PyCapsule_GetPointer.argtypes = \
+            [ctypes.py_object]
+        gpointer = ctypes.pythonapi.PyCapsule_GetPointer(
+            container.get_property("window").__gpointer__, None)
+        libgdk = ctypes.CDLL("libgdk-3-0.dll")
+        windowID = libgdk.gdk_win32_window_get_handle(gpointer)
+        container.windowID = windowID
+        Gdk.threads_leave()
     else:
-        windowID = container.window.xid
+        container.set_visual(container.get_screen().lookup_visual(0x21))
+        windowID = container.get_window().get_xid()
 
     windowInfo = cefpython.WindowInfo()
@@ -340,12 +348,12 @@
 
 class OffscreenRenderHandler(object):
-    def GetRootScreenRect(self, browser, rect):
+    def GetRootScreenRect(self, browser, rect_out):
         #print "GetRootScreenRect"
-        rect += [0, 0, 800, 600]
+        rect_out += [0, 0, 800, 600]
         return True
 
-    def GetViewRect(self, browser, rect):
+    def GetViewRect(self, browser, rect_out):
         #print "GetViewRect"
-        rect += [0, 0, 800, 600]
+        rect_out += [0, 0, 800, 600]
         return True
 
@@ -367,5 +375,5 @@
         pass
 
-    def OnPaint(self, browser, paintElementType, dirtyRects, buffer, width, height):
+    def OnPaint(self, browser, element_type, dirty_rects, paint_buffer, width, height):
         #print "OnPaint", paintElementType, dirtyRects, buffer, width, height
         pass
@@ -424,6 +432,5 @@
 
 def _handleSizeAllocate(widget, sizeAlloc):
-    """Handle the size-allocate event."""
-    window = widget.get_window()
+    """Handle the size-allocate event on Windows."""
     if widget is not None:
-        cefpython.WindowUtils.OnSize(window.handle, 0, 0, 0)
+        cefpython.WindowUtils.OnSize(widget.windowID, 0, 0, 0)
Index: src/mlx/gui/checklist.py
===================================================================
--- src/mlx/gui/checklist.py	(revision 300)
+++ src/mlx/gui/checklist.py	(revision 999)
@@ -1,4 +1,4 @@
 
-from common import *
+from .common import *
 
 from mlx.i18n import xstr
@@ -22,5 +22,5 @@
 #------------------------------------------------------------------------------
 
-class ChecklistEditor(gtk.Dialog):
+class ChecklistEditor(Gtk.Dialog):
     """The dialog to edit the checklists."""
     def __init__(self, gui):
@@ -28,8 +28,8 @@
                                               xstr("chklst_title"),
                                               gui.mainWindow,
-                                              DIALOG_MODAL)
-
-        self.add_button(xstr("button_cancel"), RESPONSETYPE_REJECT)
-        self.add_button(xstr("button_ok"), RESPONSETYPE_ACCEPT)
+                                              Gtk.DialogFlags.MODAL)
+
+        self.add_button(xstr("button_cancel"), Gtk.ResponseType.REJECT)
+        self.add_button(xstr("button_ok"), Gtk.ResponseType.ACCEPT)
 
         self._gui = gui
@@ -39,18 +39,18 @@
         contentArea = self.get_content_area()
 
-        typeBox = gtk.HBox()
-
-        label = gtk.Label(xstr("chklst_aircraftType"))
+        typeBox = Gtk.HBox()
+
+        label = Gtk.Label(xstr("chklst_aircraftType"))
         label.set_use_underline(True)
 
         typeBox.pack_start(label, False, False, 4)
 
-        self._aircraftTypeModel = gtk.ListStore(str, int)
+        self._aircraftTypeModel = Gtk.ListStore(str, int)
         for type in const.aircraftTypes:
             name = aircraftNames[type] if type in aircraftNames \
                    else "Aircraft type #%d" % (type,)
             self._aircraftTypeModel.append([name, type])
-        self._aircraftType = gtk.ComboBox(model = self._aircraftTypeModel)
-        renderer = gtk.CellRendererText()
+        self._aircraftType = Gtk.ComboBox(model = self._aircraftTypeModel)
+        renderer = Gtk.CellRendererText()
         self._aircraftType.pack_start(renderer, True)
         self._aircraftType.add_attribute(renderer, "text", 0)
@@ -62,5 +62,5 @@
         typeBox.pack_start(self._aircraftType, True, True, 4)
 
-        typeBoxAlignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
+        typeBoxAlignment = Gtk.Alignment(xalign = 0.5, yalign = 0.5,
                                          xscale = 0.0, yscale = 0.0)
         typeBoxAlignment.set_size_request(400, -1)
@@ -69,10 +69,10 @@
         contentArea.pack_start(typeBoxAlignment, False, False, 12)
 
-        fileBox = gtk.HBox()        
-
-        self._fileChooser = gtk.FileChooserWidget()
+        fileBox = Gtk.HBox()        
+
+        self._fileChooser = Gtk.FileChooserWidget()
         self._fileChooser.set_select_multiple(True)
         
-        filter = gtk.FileFilter()
+        filter = Gtk.FileFilter()
         filter.set_name(xstr("file_filter_audio"))
         filter.add_pattern("*.wav")
@@ -80,5 +80,5 @@
         self._fileChooser.add_filter(filter)
             
-        filter = gtk.FileFilter()
+        filter = Gtk.FileFilter()
         filter.set_name(xstr("file_filter_all"))
         filter.add_pattern("*.*")
@@ -90,6 +90,6 @@
         fileBox.pack_start(self._fileChooser, True, True, 4)
 
-        controlBox = gtk.VBox()
-        controlAlignment = gtk.Alignment(xalign = 0.0, yalign = 0.0,
+        controlBox = Gtk.VBox()
+        controlAlignment = Gtk.Alignment(xalign = 0.0, yalign = 0.0,
                                          xscale = 0.0, yscale = 0.0)
         controlAlignment.set_padding(padding_top = 0, padding_bottom = 0,
@@ -98,9 +98,9 @@
         fileBox.pack_start(controlAlignment, False, False, 0)
 
-        self._addButton = gtk.Button(xstr("chklst_add"))
+        self._addButton = Gtk.Button(xstr("chklst_add"))
         self._addButton.set_use_underline(True)
         self._addButton.set_tooltip_text(xstr("chklst_add_tooltip"))
         self._addButton.connect("clicked", self._addButtonClicked)
-        addAlignment = gtk.Alignment(xalign = 0.5, yalign = 0.0,
+        addAlignment = Gtk.Alignment(xalign = 0.5, yalign = 0.0,
                                      xscale = 0.0, yscale = 0.0)
         addAlignment.set_padding(padding_top = 64, padding_bottom = 0,
@@ -109,5 +109,5 @@
         controlBox.pack_start(addAlignment, False, False, 0)
 
-        self._removeButton = gtk.Button(xstr("chklst_remove"))
+        self._removeButton = Gtk.Button(xstr("chklst_remove"))
         self._removeButton.set_use_underline(True)
         self._removeButton.set_tooltip_text(xstr("chklst_remove_tooltip"))
@@ -115,5 +115,5 @@
         self._removeButton.connect("clicked", self._removeButtonClicked)
 
-        removeAlignment = gtk.Alignment(xalign = 0.5, yalign = 0.0,
+        removeAlignment = Gtk.Alignment(xalign = 0.5, yalign = 0.0,
                                         xscale = 0.0, yscale = 0.0)
         removeAlignment.set_padding(padding_top = 64, padding_bottom = 0,
@@ -122,5 +122,5 @@
         controlBox.pack_start(removeAlignment, False, False, 0)
 
-        self._moveUpButton = gtk.Button(xstr("chklst_moveUp"))
+        self._moveUpButton = Gtk.Button(xstr("chklst_moveUp"))
         self._moveUpButton.set_use_underline(True)
         self._moveUpButton.set_tooltip_text(xstr("chklst_moveUp_tooltip"))
@@ -128,5 +128,5 @@
         self._moveUpButton.connect("clicked", self._moveUpButtonClicked)
 
-        moveUpAlignment = gtk.Alignment(xalign = 0.5, yalign = 0.0,
+        moveUpAlignment = Gtk.Alignment(xalign = 0.5, yalign = 0.0,
                                         xscale = 0.0, yscale = 0.0)
         moveUpAlignment.set_padding(padding_top = 16, padding_bottom = 0,
@@ -135,5 +135,5 @@
         controlBox.pack_start(moveUpAlignment, False, False, 0)
 
-        self._moveDownButton = gtk.Button(xstr("chklst_moveDown"))
+        self._moveDownButton = Gtk.Button(xstr("chklst_moveDown"))
         self._moveDownButton.set_use_underline(True)
         self._moveDownButton.set_tooltip_text(xstr("chklst_moveDown_tooltip"))
@@ -141,5 +141,5 @@
         self._moveDownButton.connect("clicked", self._moveDownButtonClicked)
 
-        moveDownAlignment = gtk.Alignment(xalign = 0.5, yalign = 0.0,
+        moveDownAlignment = Gtk.Alignment(xalign = 0.5, yalign = 0.0,
                                         xscale = 0.0, yscale = 0.0)
         moveDownAlignment.set_padding(padding_top = 4, padding_bottom = 0,
@@ -148,10 +148,10 @@
         controlBox.pack_start(moveDownAlignment, False, False, 0)
 
-        self._fileListModel = gtk.ListStore(str, str)
-        self._fileList = gtk.TreeView(model = self._fileListModel)
+        self._fileListModel = Gtk.ListStore(str, str)
+        self._fileList = Gtk.TreeView(model = self._fileListModel)
         self._fileList.connect("button-press-event",
                                self._fileListButtonPressed)
-        column = gtk.TreeViewColumn(xstr("chklst_header"),
-                                    gtk.CellRendererText(), text = 0)
+        column = Gtk.TreeViewColumn(xstr("chklst_header"),
+                                    Gtk.CellRendererText(), text = 0)
         column.set_expand(True)
         column.set_clickable(False)
@@ -162,14 +162,15 @@
         self._fileListPopupMenu = None
         selection = self._fileList.get_selection()
-        selection.set_mode(SELECTION_MULTIPLE)
+        selection.set_mode(Gtk.SelectionMode.MULTIPLE)
         selection.connect("changed", self._fileListSelectionChanged)
 
         self._buildFileListPopupMenu()
 
-        scrolledWindow = gtk.ScrolledWindow()
+        scrolledWindow = Gtk.ScrolledWindow()
         scrolledWindow.add(self._fileList)
         scrolledWindow.set_size_request(200, -1)
-        scrolledWindow.set_policy(POLICY_AUTOMATIC, POLICY_AUTOMATIC)
-        scrolledWindow.set_shadow_type(SHADOW_IN)
+        scrolledWindow.set_policy(Gtk.PolicyType.AUTOMATIC,
+                                  Gtk.PolicyType.AUTOMATIC)
+        scrolledWindow.set_shadow_type(Gtk.ShadowType.IN)
 
         fileBox.pack_start(scrolledWindow, False, False, 4)
@@ -187,8 +188,8 @@
         self.hide()
 
-        if response==RESPONSETYPE_ACCEPT:
+        if response==Gtk.ResponseType.ACCEPT:
             self._saveChecklist()
             config = self._gui.config
-            for (aircraftType, checklist) in self._checklists.iteritems():
+            for (aircraftType, checklist) in self._checklists.items():
                 config.setChecklist(aircraftType, checklist)
             config.save()
@@ -204,5 +205,4 @@
         numSelected = 0
         for path in fileChooser.get_filenames():
-            path = text2unicode(path)
             numSelected += 1
             if os.path.isfile(path): numFiles += 1
@@ -213,5 +213,4 @@
         """Called when the Add button is clicked."""
         for path in self._fileChooser.get_filenames():
-            path = text2unicode(path)
             self._fileListModel.append([os.path.basename(path),
                                         path])
@@ -245,6 +244,5 @@
         selection = self._fileList.get_selection()
         (model, paths) = selection.get_selected_rows()
-        indexes = [(path.get_indices() if pygobject else path)[0]
-                   for path in paths]        
+        indexes = [path.get_indices()[0] for path in paths]
         indexes.sort()
         if not up:
@@ -275,5 +273,5 @@
             maxIndex = None
             for path in paths:
-                [index] = path.get_indices() if pygobject else path
+                [index] = path.get_indices()
                 if minIndex is None or index<minIndex: minIndex = index
                 if maxIndex is None or index>maxIndex: maxIndex = index
@@ -324,18 +322,15 @@
     def _fileListButtonPressed(self, widget, event):
         """Called when a mouse button is pressed on the file list."""
-        if event.type!=EVENT_BUTTON_PRESS or event.button!=3:
+        if event.type!=Gdk.EventType.BUTTON_PRESS or event.button!=3:
             return
 
         menu = self._fileListPopupMenu
-        if pygobject:
-            menu.popup(None, None, None, None, event.button, event.time)
-        else:
-            menu.popup(None, None, None, event.button, event.time)
+        menu.popup(None, None, None, None, event.button, event.time)
 
     def _buildFileListPopupMenu(self):
         """Build the file list popup menu."""
-        menu = gtk.Menu()
-
-        menuItem = gtk.MenuItem()
+        menu = Gtk.Menu()
+
+        menuItem = Gtk.MenuItem()
         menuItem.set_label(xstr("chklst_remove"))
         menuItem.set_use_underline(True)
@@ -346,5 +341,5 @@
         menu.append(menuItem)
 
-        menuItem = gtk.MenuItem()
+        menuItem = Gtk.MenuItem()
         menuItem.set_label(xstr("chklst_moveUp"))
         menuItem.set_use_underline(True)
@@ -355,5 +350,5 @@
         menu.append(menuItem)
 
-        menuItem = gtk.MenuItem()
+        menuItem = Gtk.MenuItem()
         menuItem.set_label(xstr("chklst_moveDown"))
         menuItem.set_use_underline(True)
Index: src/mlx/gui/common.py
===================================================================
--- src/mlx/gui/common.py	(revision 863)
+++ src/mlx/gui/common.py	(revision 1002)
@@ -16,13 +16,4 @@
 #
 # Common definitions and utilities for the GUI
-#
-# The main purpose of this module is to provide common definitions for things
-# that are named differently in Gtk+ 2 and 3. This way the other parts of the
-# GUI have to check the version in use very rarely. The variable \c pygobject
-# tells which version is being used. If it is \c True, Gtk+ 3 is used via the
-# PyGObject interface. Otherwise Gtk+ 2 is used, which is the default on
-# Windows or when the \c FORCE_PYGTK environment variable is set.
-#
-# Besides this there are some common utility classes and functions.
 
 #-----------------------------------------------------------------------------
@@ -30,174 +21,21 @@
 appIndicator = False
 
-if not pygobject:
-    print "Using PyGTK"
-    pygobject = False
-    import pygtk
-    pygtk.require("2.0")
-    import gtk.gdk as gdk
-    import gtk
-    import pango
-
-    try:
-        import appindicator
-        appIndicator = True
-    except Exception, e:
-        pass
-
-    MESSAGETYPE_ERROR = gtk.MESSAGE_ERROR
-    MESSAGETYPE_QUESTION = gtk.MESSAGE_QUESTION
-    MESSAGETYPE_INFO = gtk.MESSAGE_INFO
-
-    RESPONSETYPE_NONE = gtk.RESPONSE_NONE
-    RESPONSETYPE_OK = gtk.RESPONSE_OK
-    RESPONSETYPE_YES = gtk.RESPONSE_YES
-    RESPONSETYPE_NO = gtk.RESPONSE_NO
-    RESPONSETYPE_ACCEPT = gtk.RESPONSE_ACCEPT
-    RESPONSETYPE_REJECT = gtk.RESPONSE_REJECT
-    RESPONSETYPE_CANCEL = gtk.RESPONSE_CANCEL
-
-    ACCEL_VISIBLE = gtk.ACCEL_VISIBLE
-    CONTROL_MASK = gdk.CONTROL_MASK
-    DIALOG_MODAL = gtk.DIALOG_MODAL
-    WRAP_WORD = gtk.WRAP_WORD
-
-    JUSTIFY_CENTER = gtk.JUSTIFY_CENTER
-    JUSTIFY_LEFT = gtk.JUSTIFY_LEFT
-
-    CONTROL_MASK = gdk.CONTROL_MASK
-    SHIFT_MASK = gdk.SHIFT_MASK
-    BUTTON1_MASK = gdk.BUTTON1_MASK
-
-    SCROLL_UP = gdk.SCROLL_UP
-    SCROLL_DOWN = gdk.SCROLL_DOWN
-
-    SPIN_USER_DEFINED = gtk.SPIN_USER_DEFINED
-
-    FILE_CHOOSER_ACTION_SELECT_FOLDER = gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER
-    FILE_CHOOSER_ACTION_OPEN = gtk.FILE_CHOOSER_ACTION_OPEN
-    FILE_CHOOSER_ACTION_SAVE = gtk.FILE_CHOOSER_ACTION_SAVE
-
-    SELECTION_MULTIPLE = gtk.SELECTION_MULTIPLE
-
-    SHADOW_IN = gtk.SHADOW_IN
-    SHADOW_NONE = gtk.SHADOW_NONE
-
-    POLICY_AUTOMATIC = gtk.POLICY_AUTOMATIC
-    POLICY_NEVER = gtk.POLICY_NEVER
-    POLICY_ALWAYS = gtk.POLICY_ALWAYS
-
-    WEIGHT_NORMAL = pango.WEIGHT_NORMAL
-    WEIGHT_BOLD = pango.WEIGHT_BOLD
-
-    WINDOW_STATE_ICONIFIED = gdk.WINDOW_STATE_ICONIFIED
-    WINDOW_STATE_WITHDRAWN = gdk.WINDOW_STATE_WITHDRAWN
-
-    SORT_ASCENDING = gtk.SORT_ASCENDING
-    SORT_DESCENDING = gtk.SORT_DESCENDING
-
-    EVENT_BUTTON_PRESS = gdk.BUTTON_PRESS
-
-    TREE_VIEW_COLUMN_FIXED = gtk.TREE_VIEW_COLUMN_FIXED
-
-    FILL = gtk.FILL
-    EXPAND = gtk.EXPAND
-
-    UPDATE_IF_VALID = gtk.UPDATE_IF_VALID
-
-    SELECTION_MULTIPLE = gtk.SELECTION_MULTIPLE
-
-    WINDOW_POPUP = gtk.WINDOW_POPUP
-
-    pixbuf_new_from_file = gdk.pixbuf_new_from_file
-
-    def text2unicode(text):
-        """Convert the given text, returned by a Gtk widget, to Unicode."""
-        return unicode(text)
-
-    def text2str(text):
-        """Convert the given text, returned by xstr to a string."""
-        return str(text)
-
-else: # pygobject
-    from gi.repository import Gdk as gdk
-    from gi.repository import GdkPixbuf as gdkPixbuf
-    from gi.repository import Gtk as gtk
-    from gi.repository import AppIndicator3 as appindicator
-    from gi.repository import Pango as pango
-
+import gi
+gi.require_version("Gdk", "3.0")
+from gi.repository import Gdk
+from gi.repository import GdkPixbuf
+gi.require_version("Gtk", "3.0")
+from gi.repository import Gtk
+try:
+    gi.require_version("AppIndicator3", "0.1")
+    from gi.repository import AppIndicator3
     appIndicator = True
-
-
-    MESSAGETYPE_ERROR = gtk.MessageType.ERROR
-    MESSAGETYPE_QUESTION = gtk.MessageType.QUESTION
-    MESSAGETYPE_INFO = gtk.MessageType.INFO
-    RESPONSETYPE_NONE = gtk.ResponseType.NONE
-    RESPONSETYPE_OK = gtk.ResponseType.OK
-    RESPONSETYPE_YES = gtk.ResponseType.YES
-    RESPONSETYPE_NO = gtk.ResponseType.NO
-    RESPONSETYPE_ACCEPT = gtk.ResponseType.ACCEPT
-    RESPONSETYPE_REJECT = gtk.ResponseType.REJECT
-    RESPONSETYPE_CANCEL = gtk.ResponseType.CANCEL
-    ACCEL_VISIBLE = gtk.AccelFlags.VISIBLE
-    CONTROL_MASK = gdk.ModifierType.CONTROL_MASK
-    DIALOG_MODAL = gtk.DialogFlags.MODAL
-    WRAP_WORD = gtk.WrapMode.WORD
-    JUSTIFY_CENTER = gtk.Justification.CENTER
-    JUSTIFY_LEFT = gtk.Justification.LEFT
-
-    CONTROL_MASK = gdk.ModifierType.CONTROL_MASK
-    SHIFT_MASK = gdk.ModifierType.SHIFT_MASK
-    BUTTON1_MASK = gdk.ModifierType.BUTTON1_MASK
-
-    SCROLL_UP = gdk.ScrollDirection.UP
-    SCROLL_DOWN = gdk.ScrollDirection.DOWN
-
-    SPIN_USER_DEFINED = gtk.SpinType.USER_DEFINED
-
-    FILE_CHOOSER_ACTION_SELECT_FOLDER = gtk.FileChooserAction.SELECT_FOLDER
-    FILE_CHOOSER_ACTION_OPEN = gtk.FileChooserAction.OPEN
-    FILE_CHOOSER_ACTION_SAVE = gtk.FileChooserAction.SAVE
-
-    SELECTION_MULTIPLE = gtk.SelectionMode.MULTIPLE
-
-    SHADOW_IN = gtk.ShadowType.IN
-    SHADOW_NONE = gtk.ShadowType.NONE
-
-    POLICY_AUTOMATIC = gtk.PolicyType.AUTOMATIC
-    POLICY_NEVER = gtk.PolicyType.NEVER
-    POLICY_ALWAYS = gtk.PolicyType.ALWAYS
-
-    WEIGHT_NORMAL = pango.Weight.NORMAL
-    WEIGHT_BOLD = pango.Weight.BOLD
-
-    WINDOW_STATE_ICONIFIED = gdk.WindowState.ICONIFIED
-    WINDOW_STATE_WITHDRAWN = gdk.WindowState.WITHDRAWN
-
-    SORT_ASCENDING = gtk.SortType.ASCENDING
-    SORT_DESCENDING = gtk.SortType.DESCENDING
-
-    EVENT_BUTTON_PRESS = gdk.EventType.BUTTON_PRESS
-
-    TREE_VIEW_COLUMN_FIXED = gtk.TreeViewColumnSizing.FIXED
-
-    FILL = gtk.AttachOptions.FILL
-    EXPAND = gtk.AttachOptions.EXPAND
-
-    UPDATE_IF_VALID = gtk.SpinButtonUpdatePolicy.IF_VALID
-
-    SELECTION_MULTIPLE = gtk.SelectionMode.MULTIPLE
-
-    pixbuf_new_from_file = gdkPixbuf.Pixbuf.new_from_file
-
-    import codecs
-    _utf8Decoder = codecs.getdecoder("utf-8")
-
-    def text2unicode(str):
-        """Convert the given text, returned by a Gtk widget, to Unicode."""
-        return _utf8Decoder(str)[0]
-
-    def text2str(text):
-        """Convert the given text, returned by xstr to a string."""
-        return _utf8Decoder(text)[0]
+except:
+    pass
+from gi.repository import Pango
+from gi.repository import PangoCairo
+
+import codecs
+_utf8Decoder = codecs.getdecoder("utf-8")
 
 import cairo
@@ -240,9 +78,9 @@
 #------------------------------------------------------------------------------
 
-class IntegerEntry(gtk.Entry):
+class IntegerEntry(Gtk.Entry):
     """An entry that allows only either an empty value, or an integer."""
     def __init__(self, defaultValue = None):
         """Construct the entry."""
-        gtk.Entry.__init__(self)
+        Gtk.Entry.__init__(self)
 
         self.set_alignment(1.0)
@@ -292,9 +130,10 @@
 #------------------------------------------------------------------------------
 
-class TimeEntry(gtk.Entry):
+class TimeEntry(Gtk.Entry):
     """Widget to display and edit a time value in HH:MM format."""
     def __init__(self):
         """Construct the entry"""
-        super(TimeEntry, self).__init__(max = 5)
+        super(TimeEntry, self).__init__()
+        self.set_max_width_chars(5)
 
         self.connect("insert-text", self._insertText)
@@ -396,10 +235,10 @@
             pass
         else:
-            gtk.gdk.display_get_default().beep()
+            Gtk.gdk.display_get_default().beep()
             self.stop_emission(signal)
 
 #------------------------------------------------------------------------------
 
-class CredentialsDialog(gtk.Dialog):
+class CredentialsDialog(Gtk.Dialog):
     """A dialog window to ask for a user name and a password."""
     def __init__(self, gui, userName, password,
@@ -414,11 +253,11 @@
                                                 titleLabel,
                                                 gui.mainWindow,
-                                                DIALOG_MODAL)
-        self.add_button(cancelButtonLabel, RESPONSETYPE_CANCEL)
-        self.add_button(okButtonLabel, RESPONSETYPE_OK)
+                                                Gtk.DialogFlags.MODAL)
+        self.add_button(cancelButtonLabel, Gtk.ResponseType.CANCEL)
+        self.add_button(okButtonLabel, Gtk.ResponseType.OK)
 
         contentArea = self.get_content_area()
 
-        contentAlignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
+        contentAlignment = Gtk.Alignment(xalign = 0.5, yalign = 0.5,
                                          xscale = 0.0, yscale = 0.0)
         contentAlignment.set_padding(padding_top = 4, padding_bottom = 16,
@@ -427,19 +266,19 @@
         contentArea.pack_start(contentAlignment, False, False, 0)
 
-        contentVBox = gtk.VBox()
+        contentVBox = Gtk.VBox()
         contentAlignment.add(contentVBox)
 
         if infoText is not None:
-            label = gtk.Label(infoText)
+            label = Gtk.Label(infoText)
             label.set_alignment(0.0, 0.0)
 
             contentVBox.pack_start(label, False, False, 0)
 
-        tableAlignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
+        tableAlignment = Gtk.Alignment(xalign = 0.5, yalign = 0.5,
                                        xscale = 0.0, yscale = 0.0)
         tableAlignment.set_padding(padding_top = 24, padding_bottom = 0,
                                    padding_left = 0, padding_right = 0)
 
-        table = gtk.Table(3, 2)
+        table = Gtk.Table(3, 2)
         table.set_row_spacings(4)
         table.set_col_spacings(16)
@@ -449,10 +288,10 @@
         contentVBox.pack_start(tableAlignment, True, True, 0)
 
-        label = gtk.Label(userNameLabel)
+        label = Gtk.Label(userNameLabel)
         label.set_use_underline(True)
         label.set_alignment(0.0, 0.5)
         table.attach(label, 0, 1, 0, 1)
 
-        self._userName = gtk.Entry()
+        self._userName = Gtk.Entry()
         self._userName.set_width_chars(16)
         # FIXME: enabled the OK button only when there is something in thr
@@ -465,10 +304,10 @@
         label.set_mnemonic_widget(self._userName)
 
-        label = gtk.Label(passwordLabel)
+        label = Gtk.Label(passwordLabel)
         label.set_use_underline(True)
         label.set_alignment(0.0, 0.5)
         table.attach(label, 0, 1, 1, 2)
 
-        self._password = gtk.Entry()
+        self._password = Gtk.Entry()
         self._password.set_visibility(False)
         #self._password.connect("changed",
@@ -480,5 +319,5 @@
 
         if rememberPassword is not None:
-            self._rememberButton = gtk.CheckButton(rememberLabel)
+            self._rememberButton = Gtk.CheckButton(rememberLabel)
             self._rememberButton.set_use_underline(True)
             self._rememberButton.set_tooltip_text(rememberTooltip)
@@ -516,5 +355,5 @@
 #------------------------------------------------------------------------------
 
-gobject.signal_new("integer-changed", IntegerEntry, gobject.SIGNAL_RUN_FIRST,
+GObject.signal_new("integer-changed", IntegerEntry, GObject.SIGNAL_RUN_FIRST,
                    None, (object,))
 
@@ -588,5 +427,5 @@
 def addFaultTag(buffer):
     """Add a tag named 'fault' to the given buffer."""
-    buffer.create_tag("fault", foreground="red", weight=WEIGHT_BOLD)
+    buffer.create_tag("fault", foreground="red", weight=Pango.Weight.BOLD)
 
 #------------------------------------------------------------------------------
@@ -622,10 +461,10 @@
 
     Return a boolean indicating the answer."""
-    dialog = gtk.MessageDialog(parent = parent,
-                               type = MESSAGETYPE_QUESTION,
+    dialog = Gtk.MessageDialog(parent = parent,
+                               type = Gtk.MessageType.QUESTION,
                                message_format = question)
 
-    dialog.add_button(xstr("button_no"), RESPONSETYPE_NO)
-    dialog.add_button(xstr("button_yes"), RESPONSETYPE_YES)
+    dialog.add_button(xstr("button_no"), Gtk.ResponseType.NO)
+    dialog.add_button(xstr("button_yes"), Gtk.ResponseType.YES)
 
     dialog.set_title(title)
@@ -633,5 +472,5 @@
     dialog.hide()
 
-    return result==RESPONSETYPE_YES
+    return result==Gtk.ResponseType.YES
 
 #------------------------------------------------------------------------------
@@ -640,8 +479,8 @@
                 title = WINDOW_TITLE_BASE):
     """Display an error dialog box with the given message."""
-    dialog = gtk.MessageDialog(parent = parent,
-                               type = MESSAGETYPE_ERROR,
+    dialog = Gtk.MessageDialog(parent = parent,
+                               type = Gtk.MessageType.ERROR,
                                message_format = message)
-    dialog.add_button(xstr("button_ok"), RESPONSETYPE_OK)
+    dialog.add_button(xstr("button_ok"), Gtk.ResponseType.OK)
     dialog.set_title(title)
     if secondary is not None:
@@ -662,11 +501,11 @@
 
 def createFlightTypeComboBox():
-        flightTypeModel = gtk.ListStore(str, int)
+        flightTypeModel = Gtk.ListStore(str, int)
         for type in _const.flightTypes:
             name = "flighttype_" + _const.flightType2string(type)
             flightTypeModel.append([xstr(name), type])
 
-        flightType = gtk.ComboBox(model = flightTypeModel)
-        renderer = gtk.CellRendererText()
+        flightType = Gtk.ComboBox(model = flightTypeModel)
+        renderer = Gtk.CellRendererText()
         flightType.pack_start(renderer, True)
         flightType.add_attribute(renderer, "text", 0)
Index: src/mlx/gui/delaycodes.py
===================================================================
--- src/mlx/gui/delaycodes.py	(revision 840)
+++ src/mlx/gui/delaycodes.py	(revision 999)
@@ -3,5 +3,5 @@
 #------------------------------------------------------------------------------
 
-from dcdata import CAPTION, DELAYCODE, getTable
+from .dcdata import CAPTION, DELAYCODE, getTable
 
 from mlx.gui.common import *
@@ -11,181 +11,124 @@
 #------------------------------------------------------------------------------
 
-if pygobject:
-
-#------------------------------------------------------------------------------
-
-    class Viewport(gtk.Viewport):
-        """Viewport implementation that alleviates the problem with improper
-        resizing by the VBox."""
-        def __init__(self):
-            """Construct the viewport."""
-            gtk.Viewport.__init__(self)
-            self._recursive = False
+class Viewport(Gtk.Viewport):
+    """Viewport implementation that alleviates the problem with improper
+    resizing by the VBox."""
+    def __init__(self):
+        """Construct the viewport."""
+        Gtk.Viewport.__init__(self)
+        self._recursive = False
+        self._vboxHeight = None
+
+    def setVBOXHeight(self, vboxHeight):
+        """Set the height of the VBox which will be used to calculate the
+        viewport's height."""
+        self._vboxHeight = vboxHeight
+
+    def do_size_allocate(self, allocation):
+        """Called when the viewport's size is allocated.
+
+        The height in the allocation object is modified so that it is only
+        so high to fit into the VBox."""
+        if self._vboxHeight is not None:
+            allocation.y += 1
+            allocation.height = self._vboxHeight - allocation.y
             self._vboxHeight = None
-
-        def setVBOXHeight(self, vboxHeight):
-            """Set the height of the VBox which will be used to calculate the
-            viewport's height."""
-            self._vboxHeight = vboxHeight
-
-        def do_size_allocate(self, allocation):
-            """Called when the viewport's size is allocated.
-
-            The height in the allocation object is modified so that it is only
-            so high to fit into the VBox."""
-            if self._vboxHeight is not None:
-                allocation.height = self._vboxHeight - allocation.y
-                self._vboxHeight = None
-            gtk.Viewport.do_size_allocate(self, allocation)
-
-    class DelayCodeTableBase(gtk.VBox, gtk.Scrollable):
-        """PyGObject-specific base class for the delay code table."""
-        __gproperties__ = {
-            "vscroll-policy" : ( gtk.ScrollablePolicy,
-                                 "vscroll-policy",
-                                 "The vertical scrolling policy",
-                                 gtk.ScrollablePolicy.MINIMUM,
-                                 gobject.PARAM_READWRITE ),
-            "vadjustment" : ( gtk.Adjustment,
-                              "vadjustment",
-                              "The vertical adjustment",
-                              gobject.PARAM_READWRITE ),
-            "hscroll-policy" : ( gtk.ScrollablePolicy,
-                                 "hscroll-policy",
-                                 "The horizontal scrolling policy",
-                                 gtk.ScrollablePolicy.MINIMUM,
-                                 gobject.PARAM_READWRITE ),
-            "hadjustment" : ( gtk.Adjustment,
-                              "hadjustment",
-                              "The horizontal adjustment",
-                              gobject.PARAM_READWRITE )  }
-
-
-        @staticmethod
-        def _createViewport():
-            """Create an instance of the viewport class used by this base class."""
-            return Viewport()
-
-        def __init__(self):
-            """Construct the delay code table."""
-            super(DelayCodeTableBase, self).__init__()
-
-        def do_size_allocate(self, allocation):
-            """Allocate the size for the table and its children.
-
-            This sets up the VBox height in the viewport and then calls the
-            do_size_allocate() function of VBox()."""
-            self._viewport.setVBOXHeight(allocation.height)
-            gtk.VBox.do_size_allocate(self, allocation)
-            self.allocate_column_sizes(allocation)
-
-        def do_get_property(self, prop):
-            """Get the value of one of the properties defined above.
-
-            The request is forwarded to the viewport."""
-            if prop.name=="vscroll-policy":
-                return self._viewport.get_vscroll_policy()
-            elif prop.name=="hscroll-policy":
-                return self._viewport.get_hscroll_policy()
-            elif prop.name=="vadjustment":
-                return self._viewport.get_vadjustment()
-            elif prop.name=="hadjustment":
-                return self._viewport.get_hadjustment()
-            else:
-                raise AttributeError("mlx.gui.delaycodes.DelayCodeTableBase: property %s is not handled in do_get_property" %
-                                     (prop.name,))
-
-        def do_set_property(self, prop, value):
-            """Set the value of the adjustment properties defined above.
-
-            The adjustments are forwarded to the viewport."""
-            if prop.name=="vadjustment":
-                self._viewport.set_vadjustment(value)
-            elif prop.name=="hadjustment":
-                self._viewport.set_hadjustment(value)
-                self._treeView.set_hadjustment(value)
-            else:
-                raise AttributeError("mlx.gui.delaycodes.DelayCodeTableBase: property %s is not handled in do_set_property" %
-                                     (prop.name,))
-
-        def setStyle(self):
-            """Set the style of the event box from the treeview."""
-
-    class Alignment(gtk.Alignment):
-        """An alignment that remembers the width it was given."""
-        def __init__(self, xalign = 0.0, yalign=0.0,
-                     xscale = 0.0, yscale = 0.0 ):
-            """Construct the alignment."""
-            super(Alignment, self).__init__(xalign = xalign, yalign = yalign,
-                                            xscale = xscale, yscale = yscale)
-            self.allocatedWidth = 0
-
-        def do_size_allocate(self, allocation):
-            """Called with the new size allocation."""
-            self.allocatedWidth = allocation.width
-            gtk.Alignment.do_size_allocate(self, allocation)
-
-#------------------------------------------------------------------------------
-
-else: # pygobject
-
-#------------------------------------------------------------------------------
-
-    class DelayCodeTableBase (gtk.VBox):
-        """Base class of the delay code table for PyGtk."""
-
-        __gsignals__ = {
-            "set-scroll-adjustments": (
-                gobject.SIGNAL_RUN_LAST,
-                gobject.TYPE_NONE, (gtk.Adjustment, gtk.Adjustment))
-                }
-
-        @staticmethod
-        def _createViewport():
-            """Create an instance of the viewport class used by this base class."""
-            return gtk.Viewport()
-
-        def __init__(self):
-            """Construct the base class."""
-            super(DelayCodeTableBase, self).__init__()
-            self.set_set_scroll_adjustments_signal("set-scroll-adjustments")
-            self.connect("size-allocate", self._do_size_allocate)
-
-        def do_set_scroll_adjustments(self, hAdjustment, vAdjustment):
-            """Set the adjustments on the viewport."""
-            self._viewport.set_hadjustment(hAdjustment)
-            self._viewport.set_vadjustment(vAdjustment)
-            self._treeView.set_hadjustment(hAdjustment)
-
-        def _do_size_allocate(self, widget, allocation):
-            """Handler of the size-allocate signal.
-
-            Calls allocate_column_sizes()."""
-            self.allocate_column_sizes(allocation)
-
-        def setStyle(self):
-            """Set the style of the event box from the treeview."""
-            if self._treeView is not None:
-                style = self._treeView.rc_get_style()
-                self._eventBox.modify_bg(0, style.bg[2])
-                self._eventBox.modify_fg(0, style.fg[2])
-
-    class Alignment(gtk.Alignment):
-        """An alignment that remembers the width it was given."""
-        def __init__(self, xalign = 0.0, yalign=0.0,
-                     xscale = 0.0, yscale = 0.0 ):
-            """Construct the alignment."""
-            super(Alignment, self).__init__(xalign = xalign, yalign = yalign,
-                                            xscale = xscale, yscale = yscale)
-            self.allocatedWidth = 0
-            self.connect("size-allocate", self._do_size_allocate)
-
-        def _do_size_allocate(self, widget, allocation):
-            """Called with the new size allocation."""
-            self.allocatedWidth = allocation.width
-
-#------------------------------------------------------------------------------
-
-class CheckButton(gtk.CheckButton):
+        Gtk.Viewport.do_size_allocate(self, allocation)
+
+class DelayCodeTableBase(Gtk.VBox, Gtk.Scrollable):
+    """PyGObject-specific base class for the delay code table."""
+    __gproperties__ = {
+        "vscroll-policy" : ( Gtk.ScrollablePolicy,
+                             "vscroll-policy",
+                             "The vertical scrolling policy",
+                             Gtk.ScrollablePolicy.MINIMUM,
+                             GObject.PARAM_READWRITE ),
+        "vadjustment" : ( Gtk.Adjustment,
+                          "vadjustment",
+                          "The vertical adjustment",
+                          GObject.PARAM_READWRITE ),
+        "hscroll-policy" : ( Gtk.ScrollablePolicy,
+                             "hscroll-policy",
+                             "The horizontal scrolling policy",
+                             Gtk.ScrollablePolicy.MINIMUM,
+                             GObject.PARAM_READWRITE ),
+        "hadjustment" : ( Gtk.Adjustment,
+                          "hadjustment",
+                          "The horizontal adjustment",
+                          GObject.PARAM_READWRITE )  }
+
+
+    @staticmethod
+    def _createViewport():
+        """Create an instance of the viewport class used by this base class."""
+        return Viewport()
+
+    def __init__(self):
+        """Construct the delay code table."""
+        super(DelayCodeTableBase, self).__init__()
+
+    def do_size_allocate(self, allocation):
+        """Allocate the size for the table and its children.
+
+        This sets up the VBox height in the viewport and then calls the
+        do_size_allocate() function of VBox()."""
+        self._viewport.setVBOXHeight(allocation.height)
+        Gtk.VBox.do_size_allocate(self, allocation)
+        self.allocate_column_sizes(allocation)
+
+    def do_get_property(self, prop):
+        """Get the value of one of the properties defined above.
+
+        The request is forwarded to the viewport."""
+        if prop.name=="vscroll-policy":
+            return self._viewport.get_vscroll_policy()
+        elif prop.name=="hscroll-policy":
+            return self._viewport.get_hscroll_policy()
+        elif prop.name=="vadjustment":
+            return self._viewport.get_vadjustment()
+        elif prop.name=="hadjustment":
+            return self._viewport.get_hadjustment()
+        else:
+            raise AttributeError("mlx.gui.delaycodes.DelayCodeTableBase: property %s is not handled in do_get_property" %
+                                 (prop.name,))
+
+    def do_set_property(self, prop, value):
+        """Set the value of the adjustment properties defined above.
+
+        The adjustments are forwarded to the viewport."""
+        if prop.name=="vadjustment":
+            self._viewport.set_vadjustment(value)
+        elif prop.name=="hadjustment":
+            self._viewport.set_hadjustment(value)
+            self._treeView.set_hadjustment(value)
+        else:
+            raise AttributeError("mlx.gui.delaycodes.DelayCodeTableBase: property %s is not handled in do_set_property" %
+                                 (prop.name,))
+
+    def setStyle(self):
+        """Set the style of the event box from the treeview."""
+
+class Alignment(Gtk.Alignment):
+    """An alignment that remembers the width it was given."""
+    def __init__(self, xalign = 0.0, yalign=0.0,
+                 xscale = 0.0, yscale = 0.0 ):
+        """Construct the alignment."""
+        super(Alignment, self).__init__(xalign = xalign, yalign = yalign,
+                                        xscale = xscale, yscale = yscale)
+        self.allocatedWidth = 0
+
+    def do_size_allocate(self, allocation):
+        """Called with the new size allocation."""
+        self.allocatedWidth = allocation.width
+        Gtk.Alignment.do_size_allocate(self, allocation)
+
+class TreeView(Gtk.TreeView):
+    def do_size_allocate(self, allocation):
+        allocation.height += 1
+        Gtk.TreeView.do_size_allocate(self, allocation)
+
+#------------------------------------------------------------------------------
+
+class CheckButton(Gtk.CheckButton):
     """A check button that contains a reference to a row in the delay code
     data table."""
@@ -241,5 +184,5 @@
         self._delayCodeData = None
 
-        self._treeView = gtk.TreeView(gtk.ListStore(str, str))
+        self._treeView = TreeView(Gtk.ListStore(str, str))
         self._treeView.set_rules_hint(True)
 
@@ -249,5 +192,5 @@
         self._checkButtons = []
 
-        self._eventBox = gtk.EventBox()
+        self._eventBox = Gtk.EventBox()
 
         self._table = None
@@ -255,5 +198,5 @@
         self._viewport = self._createViewport()
         self._viewport.add(self._eventBox)
-        self._viewport.set_shadow_type(SHADOW_NONE)
+        self._viewport.set_shadow_type(Gtk.ShadowType.NONE)
 
         self.pack_start(self._viewport, True, True, 0)
@@ -311,14 +254,14 @@
         numRows = len(rows)
 
-        column = gtk.TreeViewColumn("", gtk.CellRendererText())
-        column.set_sizing(TREE_VIEW_COLUMN_FIXED)
+        column = Gtk.TreeViewColumn("", Gtk.CellRendererText())
+        column.set_sizing(Gtk.TreeViewColumnSizing.FIXED)
         self._treeView.append_column(column)
 
         for header in headers:
-            column = gtk.TreeViewColumn(header, gtk.CellRendererText())
-            column.set_sizing(TREE_VIEW_COLUMN_FIXED)
+            column = Gtk.TreeViewColumn(header, Gtk.CellRendererText())
+            column.set_sizing(Gtk.TreeViewColumnSizing.FIXED)
             self._treeView.append_column(column)
 
-        self._table = gtk.Table(numRows, numColumns)
+        self._table = Gtk.Table(numRows, numColumns)
         self._table.set_homogeneous(False)
         self._table.set_col_spacings(16)
@@ -333,12 +276,12 @@
             (type, elements) = rows[i]
             if type==CAPTION:
-                alignment = gtk.Alignment(xalign = 0.0, yalign = 0.5,
+                alignment = Gtk.Alignment(xalign = 0.0, yalign = 0.5,
                                           xscale = 1.0)
-                label = gtk.Label("<b>" + elements + "</b>")
+                label = Gtk.Label("<b>" + elements + "</b>")
                 label.set_use_markup(True)
                 label.set_alignment(0.0, 0.5)
                 alignment.add(label)
                 self._table.attach(alignment, 1, numColumns, i, i+1,
-                                   yoptions = FILL)
+                                   yoptions = Gtk.AttachOptions.FILL)
                 self._table.set_row_spacing(i, 8)
             elif type==DELAYCODE:
@@ -349,18 +292,20 @@
                 alignment.add(checkButton)
                 self._table.attach(alignment, 0, 1, i, i+1,
-                                   xoptions = FILL, yoptions = FILL)
+                                   xoptions = Gtk.AttachOptions.FILL,
+                                   yoptions = Gtk.AttachOptions.FILL)
                 if firstDelayCodeRow:
                     self._alignments.append(alignment)
 
                 for j in range(0, numColumns-1):
-                    label = gtk.Label(elements[j])
+                    label = Gtk.Label(elements[j])
                     label.set_alignment(0.0, 0.5)
                     alignment = Alignment(xalign = 0.5, yalign = 0.5,
                                           xscale = 1.0)
                     alignment.add(label)
-                    xoptions = FILL
-                    if j==(numColumns-2): xoptions |= EXPAND
+                    xoptions = Gtk.AttachOptions.FILL
+                    if j==(numColumns-2): xoptions |= Gtk.AttachOptions.EXPAND
                     self._table.attach(alignment, j+1, j+2, i, i+1,
-                                       xoptions = xoptions, yoptions = FILL)
+                                       xoptions = xoptions,
+                                       yoptions = Gtk.AttachOptions.FILL)
                     if firstDelayCodeRow:
                         self._alignments.append(alignment)
Index: src/mlx/gui/faultexplain.py
===================================================================
--- src/mlx/gui/faultexplain.py	(revision 842)
+++ src/mlx/gui/faultexplain.py	(revision 999)
@@ -19,5 +19,5 @@
 #-------------------------------------------------------------------------------
 
-class FaultFrame(gtk.Frame):
+class FaultFrame(Gtk.Frame):
     """A frame containing the information about a single fault.
 
@@ -26,21 +26,18 @@
     def __init__(self, faultText):
         """Construct the frame."""
-        gtk.Frame.__init__(self)
+        Gtk.Frame.__init__(self)
 
         self._faultText = faultText
 
-        vbox = gtk.VBox()
-
-        self._fault = fault = gtk.TextView()
-        fault.set_editable(False)
-        fault.set_can_focus(False)
-        fault.set_wrap_mode(WRAP_WORD)
-
-        buffer = fault.get_buffer()
-        self._faultTag  = buffer.create_tag("fault", weight=WEIGHT_BOLD)
+        vbox = Gtk.VBox()
+
+        self._fault = fault = Gtk.Label()
+        fault.set_xalign(0.0)
+        fault.set_justify(Gtk.Justification.LEFT)
+        fault.set_line_wrap(True)
 
         self.faultText = faultText
 
-        faultAlignment = gtk.Alignment(xalign = 0.0, yalign = 0.0,
+        faultAlignment = Gtk.Alignment(xalign = 0.0, yalign = 0.0,
                                        xscale = 1.0, yscale = 0.0)
         faultAlignment.set_padding(padding_top = 0, padding_bottom = 0,
@@ -49,6 +46,6 @@
         vbox.pack_start(faultAlignment, True, True, 4)
 
-        self._explanation = explanation = gtk.TextView()
-        explanation.set_wrap_mode(WRAP_WORD)
+        self._explanation = explanation = Gtk.TextView()
+        explanation.set_wrap_mode(Gtk.WrapMode.WORD)
         explanation.set_accepts_tab(False)
         explanation.set_size_request(-1, 100)
@@ -62,11 +59,7 @@
         self.show_all()
 
-        if pygobject:
-            styleContext = self.get_style_context()
-            color = styleContext.get_background_color(gtk.StateFlags.NORMAL)
-            fault.override_background_color(0, color)
-        else:
-            style = self.rc_get_style()
-            fault.modify_base(0, style.bg[0])
+        styleContext = self.get_style_context()
+        color = styleContext.get_background_color(Gtk.StateFlags.NORMAL)
+        fault.override_background_color(0, color)
 
         self._hasExplanation = False
@@ -81,9 +74,5 @@
         """Update the text of the fault."""
         self._faultText = faultText
-
-        buffer = self._fault.get_buffer()
-        buffer.set_text(faultText)
-        buffer.apply_tag(self._faultTag,
-                         buffer.get_start_iter(), buffer.get_end_iter())
+        self._fault.set_markup("<b>" + faultText + "</b>")
 
     @property
@@ -125,10 +114,10 @@
 #-------------------------------------------------------------------------------
 
-gobject.signal_new("explanation-changed", FaultFrame, gobject.SIGNAL_RUN_FIRST,
+GObject.signal_new("explanation-changed", FaultFrame, GObject.SIGNAL_RUN_FIRST,
                    None, (bool,))
 
 #-------------------------------------------------------------------------------
 
-class FaultExplainWidget(gtk.Frame):
+class FaultExplainWidget(Gtk.Frame):
     """The widget for the faults and their explanations."""
     @staticmethod
@@ -138,5 +127,5 @@
 
     def __init__(self, gui):
-        gtk.Frame.__init__(self)
+        Gtk.Frame.__init__(self)
 
         self._gui = gui
@@ -145,16 +134,16 @@
         label.set_use_underline(True)
 
-        alignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
+        alignment = Gtk.Alignment(xalign = 0.5, yalign = 0.5,
                                   xscale = 1.0, yscale = 1.0)
         alignment.set_padding(padding_top = 4, padding_bottom = 4,
                               padding_left = 4, padding_right = 4)
 
-        self._outerBox = outerBox = gtk.EventBox()
+        self._outerBox = outerBox = Gtk.EventBox()
         outerBox.add(alignment)
 
-        self._innerBox = innerBox = gtk.EventBox()
+        self._innerBox = innerBox = Gtk.EventBox()
         alignment.add(self._innerBox)
 
-        alignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
+        alignment = Gtk.Alignment(xalign = 0.5, yalign = 0.5,
                                   xscale = 1.0, yscale = 1.0)
         alignment.set_padding(padding_top = 0, padding_bottom = 0,
@@ -163,11 +152,11 @@
         innerBox.add(alignment)
 
-        scroller = gtk.ScrolledWindow()
-        scroller.set_policy(POLICY_AUTOMATIC, POLICY_AUTOMATIC)
-        scroller.set_shadow_type(SHADOW_NONE)
-
-        self._faults = gtk.VBox()
+        scroller = Gtk.ScrolledWindow()
+        scroller.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
+        scroller.set_shadow_type(Gtk.ShadowType.NONE)
+
+        self._faults = Gtk.VBox()
         self._faults.set_homogeneous(False)
-        scroller.add_with_viewport(self._faults)
+        scroller.add(self._faults)
 
         alignment.add(scroller)
@@ -200,5 +189,5 @@
         """Add a fault with the given ID and text."""
 
-        alignment = gtk.Alignment(xalign = 0.0, yalign = 0.0,
+        alignment = Gtk.Alignment(xalign = 0.0, yalign = 0.0,
                                       xscale = 1.0, yscale = 0.0)
         alignment.set_padding(padding_top = 2, padding_bottom = 2,
@@ -247,5 +236,5 @@
     def reset(self):
         """Reset the widget by removing all faults."""
-        for (alignment, faultFrame) in self._faultWidgets.itervalues():
+        for (alignment, faultFrame) in self._faultWidgets.values():
             self._faults.remove(alignment)
         self._faults.show_all()
@@ -292,24 +281,20 @@
         not."""
         allExplained = self._numExplanations >= self._numFaults
-        if pygobject:
-            styleContext = self.get_style_context()
-            if allExplained:
-                outerColour = innerColour = gdk.RGBA(red = 0.0, green=0.0,
-                                                     blue=0.0, alpha=0.0)
-            else:
-                outerColour = \
-                  styleContext.get_background_color(gtk.StateFlags.SELECTED)
-                innerColour = self._gui.backgroundColour
-
-            self._outerBox.override_background_color(gtk.StateFlags.NORMAL,
-                                                     outerColour)
-            self._innerBox.override_background_color(gtk.StateFlags.NORMAL,
-                                                     innerColour)
+        styleContext = self.get_style_context()
+        if allExplained:
+            outerColour = innerColour = Gdk.RGBA(red = 0.0, green=0.0,
+                                                 blue=0.0, alpha=0.0)
         else:
-            style = self.rc_get_style()
-            self._outerBox.modify_bg(0, style.bg[0 if allExplained else 3])
-
-#-------------------------------------------------------------------------------
-
-gobject.signal_new("explanations-changed", FaultExplainWidget,
-                   gobject.SIGNAL_RUN_FIRST, None, (bool,))
+            outerColour = \
+                styleContext.get_border_color(Gtk.StateFlags.DROP_ACTIVE)
+            innerColour = self._gui.backgroundColour
+
+        self._outerBox.override_background_color(Gtk.StateFlags.NORMAL,
+                                                 outerColour)
+        self._innerBox.override_background_color(Gtk.StateFlags.NORMAL,
+                                                 innerColour)
+
+#-------------------------------------------------------------------------------
+
+GObject.signal_new("explanations-changed", FaultExplainWidget,
+                   GObject.SIGNAL_RUN_FIRST, None, (bool,))
Index: src/mlx/gui/flight.py
===================================================================
--- src/mlx/gui/flight.py	(revision 872)
+++ src/mlx/gui/flight.py	(revision 1008)
@@ -57,5 +57,5 @@
 #-----------------------------------------------------------------------------
 
-comboModel = gtk.ListStore(gobject.TYPE_STRING)
+comboModel = Gtk.ListStore(GObject.TYPE_STRING)
 comboModel.append(("N/A",))
 comboModel.append(("VECTORS",))
@@ -63,5 +63,5 @@
 #-----------------------------------------------------------------------------
 
-class Page(gtk.Alignment):
+class Page(Gtk.Alignment):
     """A page in the flight wizard."""
     def __init__(self, wizard, id, title, help, completedHelp = None):
@@ -72,17 +72,17 @@
                          padding_left = 12, padding_right = 12)
 
-        frame = gtk.Frame()
+        frame = Gtk.Frame()
         self.add(frame)
 
-        self._vbox = gtk.VBox()
+        self._vbox = Gtk.VBox()
         self._vbox.set_homogeneous(False)
         frame.add(self._vbox)
 
-        eventBox = gtk.EventBox()
-
-        alignment = gtk.Alignment(xalign = 0.0, xscale = 0.0)
-
-        titleLabel = gtk.Label(title)
-        titleLabel.modify_font(pango.FontDescription("bold 24"))
+        eventBox = Gtk.EventBox()
+
+        alignment = Gtk.Alignment(xalign = 0.0, xscale = 0.0)
+
+        titleLabel = Gtk.Label(title)
+        titleLabel.modify_font(Pango.FontDescription("bold 24"))
         alignment.set_padding(padding_top = 4, padding_bottom = 4,
                               padding_left = 6, padding_right = 0)
@@ -96,7 +96,7 @@
         self._titleLabel = titleLabel
 
-        mainBox = gtk.VBox()
-
-        alignment = gtk.Alignment(xalign = 0.0, yalign = 0.0,
+        mainBox = Gtk.VBox()
+
+        alignment = Gtk.Alignment(xalign = 0.0, yalign = 0.0,
                                   xscale = 1.0, yscale = 1.0)
         alignment.set_padding(padding_top = 16, padding_bottom = 16,
@@ -105,5 +105,5 @@
         self._vbox.pack_start(alignment, True, True, 0)
 
-        alignment = gtk.Alignment(xalign = 0.5, yalign = 0.0,
+        alignment = Gtk.Alignment(xalign = 0.5, yalign = 0.0,
                                   xscale = 0.0, yscale = 0.0)
         alignment.set_padding(padding_top = 0, padding_bottom = 16,
@@ -119,21 +119,20 @@
             longerHelp = completedHelp
 
-        self._helpLabel = gtk.Label(longerHelp)
+        self._helpLabel = Gtk.Label(longerHelp)
         # FIXME: should be a constant in common
-        self._helpLabel.set_justify(gtk.Justification.CENTER if pygobject
-                                    else gtk.JUSTIFY_CENTER)
+        self._helpLabel.set_justify(Gtk.Justification.CENTER)
         self._helpLabel.set_use_markup(True)
         alignment.add(self._helpLabel)
         mainBox.pack_start(alignment, False, False, 0)
 
-        self._mainAlignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
+        self._mainAlignment = Gtk.Alignment(xalign = 0.5, yalign = 0.5,
                                             xscale = 1.0, yscale = 1.0)
         mainBox.pack_start(self._mainAlignment, True, True, 0)
 
-        buttonAlignment =  gtk.Alignment(xalign = 1.0, xscale=0.0, yscale = 0.0)
+        buttonAlignment =  Gtk.Alignment(xalign = 1.0, xscale=0.0, yscale = 0.0)
         buttonAlignment.set_padding(padding_top = 4, padding_bottom = 10,
                                     padding_left = 16, padding_right = 16)
 
-        self._buttonBox = gtk.HBox()
+        self._buttonBox = Gtk.HBox()
         self._buttonBox.set_homogeneous(False)
         self._defaultButton = None
@@ -176,5 +175,5 @@
 
         Return the button object created."""
-        button = gtk.Button(label)
+        button = Gtk.Button(label)
         self._buttonBox.pack_start(button, False, False, padding)
         button.set_use_underline(True)
@@ -220,14 +219,9 @@
     def setStyle(self):
         """Set the styles of some of the items on the page."""
-        if pygobject:
-            context = self.get_style_context()
-            color = context.get_background_color(gtk.StateFlags.SELECTED)
-            self._titleEventBox.modify_bg(0, color.to_color())
-            color = context.get_color(gtk.StateFlags.SELECTED)
-            self._titleLabel.modify_fg(0, color.to_color())
-        else:
-            style = self.rc_get_style()
-            self._titleEventBox.modify_bg(0, style.bg[3])
-            self._titleLabel.modify_fg(0, style.fg[3])
+        context = self.get_style_context()
+        color = context.get_background_color(Gtk.StateFlags.SELECTED)
+        self._titleEventBox.modify_bg(0, color.to_color())
+        color = context.get_color(Gtk.StateFlags.SELECTED)
+        self._titleLabel.modify_fg(0, color.to_color())
 
     def initialize(self):
@@ -305,8 +299,8 @@
                                         xstr("login"), xstr("loginHelp"))
 
-        alignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
+        alignment = Gtk.Alignment(xalign = 0.5, yalign = 0.5,
                                   xscale = 0.0, yscale = 0.0)
 
-        table = gtk.Table(3, 2)
+        table = Gtk.Table(3, 2)
         table.set_row_spacings(4)
         table.set_col_spacings(32)
@@ -314,12 +308,12 @@
         self.setMainWidget(alignment)
 
-        labelAlignment = gtk.Alignment(xalign = 1.0, yalign = 0.5,
+        labelAlignment = Gtk.Alignment(xalign = 1.0, yalign = 0.5,
                                        xscale = 0.0, yscale = 0.0)
-        label = gtk.Label(xstr("label_pilotID"))
+        label = Gtk.Label(xstr("label_pilotID"))
         label.set_use_underline(True)
         labelAlignment.add(label)
         table.attach(labelAlignment, 0, 1, 0, 1)
 
-        self._pilotID = gtk.Entry()
+        self._pilotID = Gtk.Entry()
         self._pilotID.connect("changed", self._pilotIDChanged)
         self._pilotID.set_tooltip_text(xstr("login_pilotID_tooltip"))
@@ -327,12 +321,12 @@
         label.set_mnemonic_widget(self._pilotID)
 
-        labelAlignment = gtk.Alignment(xalign = 1.0, yalign = 0.5,
+        labelAlignment = Gtk.Alignment(xalign = 1.0, yalign = 0.5,
                                        xscale = 0.0, yscale = 0.0)
-        label = gtk.Label(xstr("label_password"))
+        label = Gtk.Label(xstr("label_password"))
         label.set_use_underline(True)
         labelAlignment.add(label)
         table.attach(labelAlignment, 0, 1, 1, 2)
 
-        self._password = gtk.Entry()
+        self._password = Gtk.Entry()
         self._password.set_visibility(False)
         self._password.connect("changed", self._setControls)
@@ -341,5 +335,5 @@
         label.set_mnemonic_widget(self._password)
 
-        self._rememberButton = gtk.CheckButton(xstr("remember_password"))
+        self._rememberButton = Gtk.CheckButton(xstr("remember_password"))
         self._rememberButton.set_use_underline(True)
         self._rememberButton.set_tooltip_text(xstr("login_remember_tooltip"))
@@ -405,10 +399,10 @@
     def _offlineClicked(self, button):
         """Called when the offline button was clicked."""
-        print "mlx.flight.LoginPage: offline flight selected"
+        print("mlx.flight.LoginPage: offline flight selected")
         self._wizard.nextPage()
 
     def _loginClicked(self, button):
         """Called when the login button was clicked."""
-        print "mlx.flight.LoginPage: logging in"
+        print("mlx.flight.LoginPage: logging in")
         self._wizard.login(self._handleLoginResult,
                            self._pilotID.get_text(),
@@ -446,10 +440,10 @@
                                                   help, completedHelp = completedHelp)
 
-        mainBox = gtk.HBox()
+        mainBox = Gtk.HBox()
         mainBox.set_homogeneous(False)
 
-        leftVBox = gtk.VBox()
-
-        alignment = gtk.Alignment(xscale = 1.0)
+        leftVBox = Gtk.VBox()
+
+        alignment = Gtk.Alignment(xscale = 1.0)
         alignment.set_size_request(100, 0)
 
@@ -466,11 +460,11 @@
         mainBox.pack_start(self._flightList, False, False, 8)
 
-        flightButtonBox = gtk.VBox()
-
-        alignment = gtk.Alignment(xscale = 1.0)
+        flightButtonBox = Gtk.VBox()
+
+        alignment = Gtk.Alignment(xscale = 1.0)
         alignment.set_size_request(100, 0)
         flightButtonBox.pack_start(alignment, False, False, 0)
 
-        flightButtonWidthAlignment = gtk.Alignment(xscale=1.0, yscale=0.0,
+        flightButtonWidthAlignment = Gtk.Alignment(xscale=1.0, yscale=0.0,
                                                    xalign=0.0, yalign=0.0)
         flightButtonWidthAlignment.set_padding(padding_top = 0,
@@ -478,7 +472,7 @@
                                                padding_left = 8,
                                                padding_right = 0)
-        flightButtonWidthBox = gtk.VBox()
-
-        self._saveButton = gtk.Button(xstr("flightsel_save"))
+        flightButtonWidthBox = Gtk.VBox()
+
+        self._saveButton = Gtk.Button(xstr("flightsel_save"))
         self._saveButton.set_use_underline(True)
         self._saveButton.set_sensitive(False)
@@ -488,5 +482,5 @@
         flightButtonWidthBox.pack_start(self._saveButton, True, True, 4)
 
-        self._printButton = gtk.Button(xstr("flightsel_print"))
+        self._printButton = Gtk.Button(xstr("flightsel_print"))
         self._printButton.set_use_underline(True)
         self._printButton.set_sensitive(False)
@@ -496,5 +490,5 @@
         flightButtonWidthBox.pack_start(self._printButton, True, True, 4)
 
-        self._deleteButton = gtk.Button(xstr("flightsel_delete"))
+        self._deleteButton = Gtk.Button(xstr("flightsel_delete"))
         self._deleteButton.set_use_underline(True)
         self._deleteButton.set_sensitive(False)
@@ -647,17 +641,17 @@
         dialog.hide()
 
-        if response==RESPONSETYPE_OK:
-            fileName = text2unicode(dialog.get_filename())
-            print "Saving", fileName
+        if response==Gtk.ResponseType.OK:
+            fileName = dialog.get_filename()
+            print("Saving", fileName)
             try:
                 with open(fileName, "wt") as f:
                     flight.writeIntoFile(f)
-            except Exception, e:
-                print "Failed to save flight:", util.utf2unicode(str(e))
-                dialog = gtk.MessageDialog(parent = self._wizard.gui.mainWindow,
-                                           type = MESSAGETYPE_ERROR,
+            except Exception as e:
+                print("Failed to save flight:", util.utf2unicode(str(e)))
+                dialog = Gtk.MessageDialog(parent = self._wizard.gui.mainWindow,
+                                           type = Gtk.MessageType.ERROR,
                                            message_format =
                                            xstr("flightsel_save_failed"))
-                dialog.add_button(xstr("button_ok"), RESPONSETYPE_OK)
+                dialog.add_button(xstr("button_ok"), Gtk.ResponseType.OK)
                 dialog.set_title(WINDOW_TITLE_BASE)
                 secondary = xstr("flightsel_save_failed_sec")
@@ -675,5 +669,5 @@
         flight = self._getSelectedFlight()
 
-        printOperation = gtk.PrintOperation()
+        printOperation = Gtk.PrintOperation()
         if self._printSettings is not None:
             printOperation.set_print_settings(self._printSettings)
@@ -690,10 +684,10 @@
         printOperation.set_use_full_page(False)
 
-        result = printOperation.run(gtk.PRINT_OPERATION_ACTION_PRINT_DIALOG,
+        result = printOperation.run(Gtk.PrintOperationAction.PRINT_DIALOG,
                                     wizard.gui.mainWindow)
 
-        if result == gtk.PRINT_OPERATION_RESULT_APPLY:
+        if result == Gtk.PrintOperationResult.APPLY:
             self._printSettings = printOperation.get_print_settings()
-        elif result == gtk.PRINT_OPERATION_RESULT_ERROR:
+        elif result == Gtk.PrintOperationResult.ERROR:
             errorDialog(xstr("flightsel_print_failed",
                              wizard.gui.mainWindow,
@@ -706,9 +700,10 @@
         flight=self._getSelectedFlight()
 
-        print "DPI", context.get_dpi_x(), context.get_dpi_y()
+        print("DPI", context.get_dpi_x(), context.get_dpi_y())
 
         scale = context.get_dpi_x() / 72.0
 
         cr = context.get_cairo_context()
+
         cr.set_antialias(cairo.ANTIALIAS_GRAY)
 
@@ -718,13 +713,15 @@
         cr.stroke()
 
-        layout = cr.create_layout()
-        layout.set_text(u"Malév VA official briefing")
-        font = pango.FontDescription("sans")
-        font.set_size(int(32 * scale * pango.SCALE))
-        font.set_weight(pango.WEIGHT_NORMAL)
+        pcr = context.create_pango_context()
+
+        layout = Pango.Layout(pcr)
+        layout.set_text("Malév VA official briefing")
+        font = Pango.FontDescription("sans")
+        font.set_size(int(32 * Pango.SCALE))
+        font.set_weight(Pango.Weight.NORMAL)
         layout.set_font_description(font)
 
-        (_ink, (x0, y0, x1, y1)) = layout.get_extents()
-        width = float(x1 + 1 - x0) / pango.SCALE
+        (_ink, logical) = layout.get_extents()
+        width = logical.width / Pango.SCALE
 
         y = 25 * scale
@@ -732,28 +729,28 @@
         cr.move_to((context.get_width() - width)/2.0, y)
         cr.set_line_width(0.1 * scale)
-        cr.layout_path(layout)
+        PangoCairo.layout_path(cr, layout)
         cr.stroke_preserve()
         cr.fill()
 
-        y += float(y1 + 1 - y0) / pango.SCALE
+        y += logical.height / Pango.SCALE
         y += 6 * scale
 
-        layout = cr.create_layout()
-        layout.set_text(u"%s (%s) részére" %
+        layout = Pango.Layout(pcr)
+        layout.set_text("%s (%s) részére" %
                         (loginResult.pilotName, loginResult.pilotID))
-        font = pango.FontDescription("sans")
-        font.set_size(int(16 * scale * pango.SCALE))
-        font.set_weight(450)
+        font = Pango.FontDescription("sans")
+        font.set_size(int(16 * Pango.SCALE))
+        font.set_weight(Pango.Weight.MEDIUM)
         layout.set_font_description(font)
-        (_ink, (x0, y0, x1, y1)) = layout.get_extents()
-        width = float(x1 + 1 - x0) / pango.SCALE
+        (_ink, logical) = layout.get_extents()
+        width = logical.width / Pango.SCALE
 
         cr.move_to((context.get_width() - width)/2.0, y)
         cr.set_line_width(0.1 * scale)
-        cr.layout_path(layout)
+        PangoCairo.layout_path(cr, layout)
         cr.stroke_preserve()
         cr.fill()
 
-        y += float(y1 + 1 - y0) / pango.SCALE
+        y += logical.height / Pango.SCALE
         y += 4 * scale
 
@@ -765,7 +762,7 @@
         y += 20 * scale
 
-        font = pango.FontDescription("sans")
-        font.set_size(int(7 * scale * pango.SCALE))
-        font.set_weight(150)
+        font = Pango.FontDescription("sans")
+        font.set_size(int(7 * Pango.SCALE))
+        font.set_weight(Pango.Weight.ULTRALIGHT)
 
         table = []
@@ -799,13 +796,13 @@
         totalHeight = 0
         for (label, value) in table:
-            labelLayout = cr.create_layout()
+            labelLayout = Pango.Layout(pcr)
             labelLayout.set_text(label)
             labelLayout.set_font_description(font)
 
-            (_ink, (x0, y0, x1, y1)) = labelLayout.get_extents()
-            maxLabelWidth = max(maxLabelWidth, x1 + 1 - x0)
-            labelHeight = y1 + 1 - y0
-
-            valueLayout = cr.create_layout()
+            (_ink, logical) = labelLayout.get_extents()
+            maxLabelWidth = max(maxLabelWidth, logical.width)
+            labelHeight = logical.height
+
+            valueLayout = Pango.Layout(pcr)
             valueLayout.set_text(value)
             valueLayout.set_font_description(font)
@@ -813,5 +810,5 @@
             labelLayouts.append((labelLayout, valueLayout, labelHeight))
 
-        maxLabelWidth = maxLabelWidth / pango.SCALE
+        maxLabelWidth = maxLabelWidth / Pango.SCALE
 
         valueX = labelX + labelValueFill + maxLabelWidth
@@ -821,10 +818,10 @@
             (labelFill + maxLabelWidth + labelValueFill + valueFill)
         for (labelLayout, valueLayout, labelHeight) in labelLayouts:
-            valueLayout.set_width(int(valueWidth * pango.SCALE))
-
-            (_ink, (x0, y0, x1, y1)) = valueLayout.get_extents()
-            valueHeight = y1 + 1 - y0
-
-            height = float(max(labelHeight, valueHeight))/pango.SCALE
+            valueLayout.set_width(int(valueWidth * Pango.SCALE))
+
+            (_ink, logical) = valueLayout.get_extents()
+            valueHeight = logical.height
+
+            height = float(max(labelHeight, valueHeight))/Pango.SCALE
             layouts.append((labelLayout, valueLayout, height))
 
@@ -843,5 +840,5 @@
             cr.move_to(labelX, y)
             cr.set_line_width(0.1)
-            cr.layout_path(labelLayout)
+            PangoCairo.layout_path(cr, labelLayout)
             cr.stroke_preserve()
             cr.fill()
@@ -849,5 +846,5 @@
             cr.move_to(valueX, y)
             cr.set_line_width(0.1)
-            cr.layout_path(valueLayout)
+            PangoCairo.layout_path(cr, valueLayout)
             cr.stroke_preserve()
             cr.fill()
@@ -884,5 +881,5 @@
     def _deleteResultCallback(self, returned, result):
         """Called when the deletion result is available."""
-        gobject.idle_add(self._handleDeleteResult, returned, result)
+        GObject.idle_add(self._handleDeleteResult, returned, result)
 
     def _handleDeleteResult(self, returned, result):
@@ -938,7 +935,7 @@
         dialog.hide()
 
-        if response==RESPONSETYPE_OK:
-            fileName = text2unicode(dialog.get_filename())
-            print "Loading", fileName
+        if response==Gtk.ResponseType.OK:
+            fileName = dialog.get_filename()
+            print("Loading", fileName)
             bookedFlight = web.BookedFlight()
             try:
@@ -946,11 +943,11 @@
                     bookedFlight.readFromFile(f)
                 self.addFlight(bookedFlight)
-            except Exception, e:
-                print "Failed to load flight:", util.utf2unicode(str(e))
-                dialog = gtk.MessageDialog(parent = self._wizard.gui.mainWindow,
-                                           type = MESSAGETYPE_ERROR,
+            except Exception as e:
+                print("Failed to load flight:", util.utf2unicode(str(e)))
+                dialog = Gtk.MessageDialog(parent = self._wizard.gui.mainWindow,
+                                           type = Gtk.MessageType.ERROR,
                                            message_format =
                                            xstr("flightsel_load_failed"))
-                dialog.add_button(xstr("button_ok"), RESPONSETYPE_OK)
+                dialog.add_button(xstr("button_ok"), Gtk.ResponseType.OK)
                 dialog.set_title(WINDOW_TITLE_BASE)
                 secondary = xstr("flightsel_load_failed_sec")
@@ -1030,20 +1027,20 @@
 
         gui = self._wizard.gui
-        dialog = gtk.FileChooserDialog(title = WINDOW_TITLE_BASE + " - " +
+        dialog = Gtk.FileChooserDialog(title = WINDOW_TITLE_BASE + " - " +
                                        xstr("flightsel_save_title"),
-                                       action = FILE_CHOOSER_ACTION_SAVE,
-                                       buttons = (gtk.STOCK_CANCEL,
-                                                  RESPONSETYPE_CANCEL,
-                                                  gtk.STOCK_OK, RESPONSETYPE_OK),
+                                       action = Gtk.FileChooserAction.SAVE,
+                                       buttons = (Gtk.STOCK_CANCEL,
+                                                  Gtk.ResponseType.CANCEL,
+                                                  Gtk.STOCK_OK, Gtk.ResponseType.OK),
                                        parent = gui.mainWindow)
         dialog.set_modal(True)
         dialog.set_do_overwrite_confirmation(True)
 
-        filter = gtk.FileFilter()
+        filter = Gtk.FileFilter()
         filter.set_name(xstr("flightsel_filter_flights"))
         filter.add_pattern("*.vaflight")
         dialog.add_filter(filter)
 
-        filter = gtk.FileFilter()
+        filter = Gtk.FileFilter()
         filter.set_name(xstr("file_filter_all"))
         filter.add_pattern("*.*")
@@ -1060,19 +1057,19 @@
 
         gui = self._wizard.gui
-        dialog = gtk.FileChooserDialog(title = WINDOW_TITLE_BASE + " - " +
+        dialog = Gtk.FileChooserDialog(title = WINDOW_TITLE_BASE + " - " +
                                        xstr("flightsel_load_title"),
-                                       action = FILE_CHOOSER_ACTION_OPEN,
-                                       buttons = (gtk.STOCK_CANCEL,
-                                                  RESPONSETYPE_CANCEL,
-                                                  gtk.STOCK_OK, RESPONSETYPE_OK),
+                                       action = Gtk.FileChooserAction.OPEN,
+                                       buttons = (Gtk.STOCK_CANCEL,
+                                                  Gtk.ResponseType.CANCEL,
+                                                  Gtk.STOCK_OK, Gtk.ResponseType.OK),
                                        parent = gui.mainWindow)
         dialog.set_modal(True)
 
-        filter = gtk.FileFilter()
+        filter = Gtk.FileFilter()
         filter.set_name(xstr("flightsel_filter_flights"))
         filter.add_pattern("*.vaflight")
         dialog.add_filter(filter)
 
-        filter = gtk.FileFilter()
+        filter = Gtk.FileFilter()
         filter.set_name(xstr("file_filter_all"))
         filter.add_pattern("*.*")
@@ -1085,7 +1082,7 @@
     def _createListPopupMenu(self):
         """Get the flight list popup menu."""
-        menu = gtk.Menu()
-
-        menuItem = gtk.MenuItem()
+        menu = Gtk.Menu()
+
+        menuItem = Gtk.MenuItem()
         menuItem.set_label(xstr("flightsel_popup_select"))
         menuItem.set_use_underline(True)
@@ -1095,5 +1092,5 @@
         menu.append(menuItem)
 
-        menuItem = gtk.MenuItem()
+        menuItem = Gtk.MenuItem()
         menuItem.set_label(xstr("flightsel_popup_save"))
         menuItem.set_use_underline(True)
@@ -1103,5 +1100,5 @@
         menu.append(menuItem)
 
-        menuItem = gtk.MenuItem()
+        menuItem = Gtk.MenuItem()
         menuItem.set_label(xstr("flightsel_popup_print"))
         menuItem.set_use_underline(True)
@@ -1111,5 +1108,5 @@
         menu.append(menuItem)
 
-        menuItem = gtk.MenuItem()
+        menuItem = Gtk.MenuItem()
         menuItem.set_label(xstr("flightsel_popup_delete"))
         menuItem.set_use_underline(True)
@@ -1152,7 +1149,7 @@
                                                 xstr("gatesel_help"))
 
-        self._listStore = gtk.ListStore(str)
-        self._gateList = gtk.TreeView(self._listStore)
-        column = gtk.TreeViewColumn(None, gtk.CellRendererText(),
+        self._listStore = Gtk.ListStore(str)
+        self._gateList = Gtk.TreeView(self._listStore)
+        column = Gtk.TreeViewColumn(None, Gtk.CellRendererText(),
                                     text = 0)
         column.set_expand(True)
@@ -1164,15 +1161,12 @@
         gateSelection.connect("changed", self._selectionChanged)
 
-        scrolledWindow = gtk.ScrolledWindow()
+        scrolledWindow = Gtk.ScrolledWindow()
         scrolledWindow.add(self._gateList)
         scrolledWindow.set_size_request(50, -1)
-        scrolledWindow.set_policy(gtk.PolicyType.AUTOMATIC if pygobject
-                                  else gtk.POLICY_AUTOMATIC,
-                                  gtk.PolicyType.AUTOMATIC if pygobject
-                                  else gtk.POLICY_AUTOMATIC)
-        scrolledWindow.set_shadow_type(gtk.ShadowType.IN if pygobject
-                                       else gtk.SHADOW_IN)
-
-        alignment = gtk.Alignment(xalign = 0.5, yalign = 0.0, xscale = 0.0, yscale = 1.0)
+        scrolledWindow.set_policy(Gtk.PolicyType.AUTOMATIC,
+                                  Gtk.PolicyType.AUTOMATIC)
+        scrolledWindow.set_shadow_type(Gtk.ShadowType.IN)
+
+        alignment = Gtk.Alignment(xalign = 0.5, yalign = 0.0, xscale = 0.0, yscale = 1.0)
         alignment.add(scrolledWindow)
 
@@ -1236,8 +1230,8 @@
             self._wizard.jumpPage("connect")
         else:
-            dialog = gtk.MessageDialog(parent = self._wizard.gui.mainWindow,
-                                       type = MESSAGETYPE_ERROR,
+            dialog = Gtk.MessageDialog(parent = self._wizard.gui.mainWindow,
+                                       type = Gtk.MessageType.ERROR,
                                        message_format = xstr("gatesel_conflict"))
-            dialog.add_button(xstr("button_ok"), RESPONSETYPE_OK)
+            dialog.add_button(xstr("button_ok"), Gtk.ResponseType.OK)
             dialog.set_title(WINDOW_TITLE_BASE)
             dialog.format_secondary_markup(xstr("gatesel_conflict_sec"))
@@ -1274,10 +1268,10 @@
                                            xstr("register_help"))
 
-        alignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
+        alignment = Gtk.Alignment(xalign = 0.5, yalign = 0.5,
                                   xscale = 0.0, yscale = 0.0)
 
-        table = gtk.Table(12, 3)
+        table = Gtk.Table(12, 4)
         table.set_row_spacings(4)
-        table.set_col_spacings(32)
+        table.set_col_spacings(24)
         alignment.add(table)
         self.setMainWidget(alignment)
@@ -1285,12 +1279,12 @@
         row = 0
 
-        labelAlignment = gtk.Alignment(xalign = 1.0, yalign = 0.5,
+        labelAlignment = Gtk.Alignment(xalign = 1.0, yalign = 0.5,
                                        xscale = 0.0, yscale = 0.0)
-        label = gtk.Label(xstr("register_name1"))
+        label = Gtk.Label(xstr("register_name1"))
         label.set_use_underline(True)
         labelAlignment.add(label)
         table.attach(labelAlignment, 0, 1, row, row+1)
 
-        self._name1 = gtk.Entry()
+        self._name1 = Gtk.Entry()
         self._name1.connect("changed", self._updateButtons)
         self._name1.set_tooltip_text(xstr("register_name1_tooltip"))
@@ -1299,33 +1293,31 @@
         label.set_mnemonic_widget(self._name1)
 
+        labelAlignment = Gtk.Alignment(xalign = 1.0, yalign = 0.5,
+                                       xscale = 0.0, yscale = 0.0)
+        label = Gtk.Label(xstr("register_name2"))
+        label.set_use_underline(True)
+        labelAlignment.add(label)
+        table.attach(labelAlignment, 2, 3, row, row+1)
+
+        self._name2 = Gtk.Entry()
+        self._name2.connect("changed", self._updateButtons)
+        self._name2.set_tooltip_text(xstr("register_name2_tooltip"))
+        self._name2.set_width_chars(15)
+        table.attach(self._name2, 3, 4, row, row+1)
+        label.set_mnemonic_widget(self._name2)
+
         row += 1
 
-        labelAlignment = gtk.Alignment(xalign = 1.0, yalign = 0.5,
+        labelAlignment = Gtk.Alignment(xalign = 1.0, yalign = 0.5,
                                        xscale = 0.0, yscale = 0.0)
-        label = gtk.Label(xstr("register_name2"))
+        label = Gtk.Label(xstr("register_year_of_birth"))
         label.set_use_underline(True)
         labelAlignment.add(label)
         table.attach(labelAlignment, 0, 1, row, row+1)
 
-        self._name2 = gtk.Entry()
-        self._name2.connect("changed", self._updateButtons)
-        self._name2.set_tooltip_text(xstr("register_name2_tooltip"))
-        self._name2.set_width_chars(15)
-        table.attach(self._name2, 1, 2, row, row+1)
-        label.set_mnemonic_widget(self._name2)
-
-        row += 1
-
-        labelAlignment = gtk.Alignment(xalign = 1.0, yalign = 0.5,
-                                       xscale = 0.0, yscale = 0.0)
-        label = gtk.Label(xstr("register_year_of_birth"))
-        label.set_use_underline(True)
-        labelAlignment.add(label)
-        table.attach(labelAlignment, 0, 1, row, row+1)
-
-        alignment = gtk.Alignment(xalign = 0.0, yalign = 0.0,
+        alignment = Gtk.Alignment(xalign = 0.0, yalign = 0.0,
                                   xscale = 0.0, yscale = 0.0)
 
-        self._yearOfBirth = gtk.SpinButton()
+        self._yearOfBirth = Gtk.SpinButton()
         self._yearOfBirth.set_increments(step = 1, page = 10)
         self._yearOfBirth.set_range(min = RegisterPage._minYearOfBirth,
@@ -1342,12 +1334,12 @@
         row += 1
 
-        labelAlignment = gtk.Alignment(xalign = 1.0, yalign = 0.5,
+        labelAlignment = Gtk.Alignment(xalign = 1.0, yalign = 0.5,
                                        xscale = 0.0, yscale = 0.0)
-        label = gtk.Label(xstr("register_email"))
+        label = Gtk.Label(xstr("register_email"))
         label.set_use_underline(True)
         labelAlignment.add(label)
         table.attach(labelAlignment, 0, 1, row, row+1)
 
-        self._emailAddress = gtk.Entry()
+        self._emailAddress = Gtk.Entry()
         self._emailAddress.connect("changed", self._updateButtons)
         self._emailAddress.set_tooltip_text(xstr("register_email_tooltip"))
@@ -1355,19 +1347,19 @@
         label.set_mnemonic_widget(self._emailAddress)
 
-        self._emailAddressPublic = gtk.CheckButton(xstr("register_email_public"))
+        self._emailAddressPublic = Gtk.CheckButton(xstr("register_email_public"))
         self._emailAddressPublic.set_use_underline(True)
         self._emailAddressPublic.set_tooltip_text(xstr("register_email_public_tooltip"))
-        table.attach(self._emailAddressPublic, 2, 3, row, row+1)
+        table.attach(self._emailAddressPublic, 2, 4, row, row+1)
 
         row += 1
 
-        labelAlignment = gtk.Alignment(xalign = 1.0, yalign = 0.5,
+        labelAlignment = Gtk.Alignment(xalign = 1.0, yalign = 0.5,
                                        xscale = 0.0, yscale = 0.0)
-        label = gtk.Label(xstr("register_vatsim_id"))
+        label = Gtk.Label(xstr("register_vatsim_id"))
         label.set_use_underline(True)
         labelAlignment.add(label)
         table.attach(labelAlignment, 0, 1, row, row+1)
 
-        alignment = gtk.Alignment(xalign = 0.0, yalign = 0.0,
+        alignment = Gtk.Alignment(xalign = 0.0, yalign = 0.0,
                                   xscale = 0.0, yscale = 0.0)
         self._vatsimID = IntegerEntry()
@@ -1379,14 +1371,12 @@
         label.set_mnemonic_widget(self._vatsimID)
 
-        row += 1
-
-        labelAlignment = gtk.Alignment(xalign = 1.0, yalign = 0.5,
+        labelAlignment = Gtk.Alignment(xalign = 0.0, yalign = 0.5,
                                        xscale = 0.0, yscale = 0.0)
-        label = gtk.Label(xstr("register_ivao_id"))
+        label = Gtk.Label(xstr("register_ivao_id"))
         label.set_use_underline(True)
         labelAlignment.add(label)
-        table.attach(labelAlignment, 0, 1, row, row+1)
-
-        alignment = gtk.Alignment(xalign = 0.0, yalign = 0.0,
+        table.attach(labelAlignment, 2, 3, row, row+1)
+
+        alignment = Gtk.Alignment(xalign = 0.0, yalign = 0.0,
                                   xscale = 0.0, yscale = 0.0)
         self._ivaoID = IntegerEntry()
@@ -1395,12 +1385,12 @@
         self._ivaoID.set_width_chars(7)
         alignment.add(self._ivaoID)
-        table.attach(alignment, 1, 2, row, row+1)
+        table.attach(alignment, 3, 4, row, row+1)
         label.set_mnemonic_widget(self._ivaoID)
 
         row += 1
 
-        labelAlignment = gtk.Alignment(xalign = 1.0, yalign = 0.5,
+        labelAlignment = Gtk.Alignment(xalign = 1.0, yalign = 0.5,
                                        xscale = 0.0, yscale = 0.0)
-        label = gtk.Label(xstr("register_phone_num"))
+        label = Gtk.Label(xstr("register_phone_num"))
         label.set_use_underline(True)
         label.set_use_markup(True)
@@ -1408,5 +1398,5 @@
         table.attach(labelAlignment, 0, 1, row, row+1)
 
-        self._phoneNumber = gtk.Entry()
+        self._phoneNumber = Gtk.Entry()
         self._phoneNumber.set_tooltip_text(xstr("register_phone_num_tooltip"))
         table.attach(self._phoneNumber, 1, 2, row, row+1)
@@ -1415,7 +1405,7 @@
         row += 1
 
-        labelAlignment = gtk.Alignment(xalign = 1.0, yalign = 0.5,
+        labelAlignment = Gtk.Alignment(xalign = 1.0, yalign = 0.5,
                                        xscale = 0.0, yscale = 0.0)
-        label = gtk.Label(xstr("register_nationality"))
+        label = Gtk.Label(xstr("register_nationality"))
         label.set_use_underline(True)
         label.set_use_markup(True)
@@ -1424,26 +1414,26 @@
 
 
-        self._nationality = gtk.Entry()
+        self._nationality = Gtk.Entry()
         self._nationality.set_tooltip_text(xstr("register_nationality_tooltip"))
         table.attach(self._nationality, 1, 2, row, row+1)
         label.set_mnemonic_widget(self._nationality)
 
-        placeholder = gtk.Label()
+        placeholder = Gtk.Label()
         placeholder.set_text(xstr("register_password_mismatch"))
         placeholder.set_use_markup(True)
         placeholder.set_child_visible(False)
         placeholder.hide()
-        table.attach(placeholder, 2, 3, row, row+1)
+        table.attach(placeholder, 2, 4, row, row+1)
 
         row += 1
 
-        labelAlignment = gtk.Alignment(xalign = 1.0, yalign = 0.5,
+        labelAlignment = Gtk.Alignment(xalign = 1.0, yalign = 0.5,
                                        xscale = 0.0, yscale = 0.0)
-        label = gtk.Label(xstr("register_password"))
+        label = Gtk.Label(xstr("register_password"))
         label.set_use_underline(True)
         labelAlignment.add(label)
         table.attach(labelAlignment, 0, 1, row, row+1)
 
-        self._password = gtk.Entry()
+        self._password = Gtk.Entry()
         self._password.set_visibility(False)
         self._password.connect("changed", self._updateButtons)
@@ -1452,20 +1442,20 @@
         label.set_mnemonic_widget(self._password)
 
-        alignment = gtk.Alignment(xalign = 0.0, yalign = 0.5,
+        alignment = Gtk.Alignment(xalign = 0.0, yalign = 0.5,
                                   xscale = 0.0, yscale = 0.0)
-        self._passwordStatus = gtk.Label()
+        self._passwordStatus = Gtk.Label()
         alignment.add(self._passwordStatus)
-        table.attach(alignment, 2, 3, row, row+1)
+        table.attach(alignment, 2, 4, row, row+1)
 
         row += 1
 
-        labelAlignment = gtk.Alignment(xalign = 1.0, yalign = 0.5,
+        labelAlignment = Gtk.Alignment(xalign = 1.0, yalign = 0.5,
                                        xscale = 0.0, yscale = 0.0)
-        label = gtk.Label(xstr("register_password2"))
+        label = Gtk.Label(xstr("register_password2"))
         label.set_use_underline(True)
         labelAlignment.add(label)
         table.attach(labelAlignment, 0, 1, row, row+1)
 
-        self._password2 = gtk.Entry()
+        self._password2 = Gtk.Entry()
         self._password2.set_visibility(False)
         self._password2.connect("changed", self._updateButtons)
@@ -1474,16 +1464,16 @@
         label.set_mnemonic_widget(self._password2)
 
-        alignment = gtk.Alignment(xalign = 0.0, yalign = 0.5,
+        alignment = Gtk.Alignment(xalign = 0.0, yalign = 0.5,
                                   xscale = 0.0, yscale = 0.0)
-        self._password2Status = gtk.Label()
+        self._password2Status = Gtk.Label()
         alignment.add(self._password2Status)
-        table.attach(alignment, 2, 3, row, row+1)
+        table.attach(alignment, 2, 4, row, row+1)
 
         row += 1
 
-        self._rememberButton = gtk.CheckButton(xstr("remember_password"))
+        self._rememberButton = Gtk.CheckButton(xstr("remember_password"))
         self._rememberButton.set_use_underline(True)
         self._rememberButton.set_tooltip_text(xstr("login_remember_tooltip"))
-        table.attach(self._rememberButton, 1, 2, row, row+1)
+        table.attach(self._rememberButton, 1, 3, row, row+1)
 
         cancelButton = \
@@ -1629,13 +1619,13 @@
                                             self.phoneNumber, self.nationality,
                                             self.password)
-        print "Registering with data:"
-        print "  name:", self.name1, self.name2, registrationData.firstName, registrationData.surName, requestedNameOrder
-        print "  yearOfBirth:", self.yearOfBirth, registrationData.yearOfBirth
-        print "  emailAddress:", self.emailAddress, registrationData.emailAddress
-        print "  emailAddressPublic:", self.emailAddressPublic, registrationData.emailAddressPublic
-        print "  vatsimID:", self.vatsimID, registrationData.vatsimID
-        print "  ivaoID:", self.ivaoID, registrationData.ivaoID
-        print "  phoneNumber:", self.phoneNumber, registrationData.phoneNumber
-        print "  nationality:", self.nationality, registrationData.nationality
+        print("Registering with data:")
+        print("  name:", self.name1, self.name2, registrationData.firstName, registrationData.surName, requestedNameOrder)
+        print("  yearOfBirth:", self.yearOfBirth, registrationData.yearOfBirth)
+        print("  emailAddress:", self.emailAddress, registrationData.emailAddress)
+        print("  emailAddressPublic:", self.emailAddressPublic, registrationData.emailAddressPublic)
+        print("  vatsimID:", self.vatsimID, registrationData.vatsimID)
+        print("  ivaoID:", self.ivaoID, registrationData.ivaoID)
+        print("  phoneNumber:", self.phoneNumber, registrationData.phoneNumber)
+        print("  nationality:", self.nationality, registrationData.nationality)
 
         gui = self._wizard.gui
@@ -1645,5 +1635,5 @@
     def _registerResultCallback(self, returned, result):
         """Called when the registration result is available."""
-        gobject.idle_add(self._handleRegisterResult, returned, result)
+        GObject.idle_add(self._handleRegisterResult, returned, result)
 
     def _handleRegisterResult(self, returned, result):
@@ -1653,13 +1643,13 @@
         gui.endBusy()
 
-        print "Registration result:"
-        print "  returned:", returned
+        print("Registration result:")
+        print("  returned:", returned)
         if returned:
-            print "  registered:", result.registered
+            print("  registered:", result.registered)
             if result.registered:
-                print "  pilotID", result.pilotID
-                print "  loggedIn", result.loggedIn
-            print "  emailAlreadyRegistered:", result.emailAlreadyRegistered
-            print "  invalidData:", result.invalidData
+                print("  pilotID", result.pilotID)
+                print("  loggedIn", result.loggedIn)
+            print("  emailAlreadyRegistered:", result.emailAlreadyRegistered)
+            print("  invalidData:", result.invalidData)
 
         registrationOK = returned and result.registered
@@ -1673,5 +1663,5 @@
             else:
                 secondaryMessage = xstr("register_nologin") % (result.pilotID,)
-            messageType = MESSAGETYPE_INFO
+            messageType = Gtk.MessageType.INFO
 
             config = gui.config
@@ -1686,13 +1676,13 @@
         elif returned and result.emailAlreadyRegistered:
             secondaryMessage = xstr("register_email_already")
-            messageType = MESSAGETYPE_ERROR
+            messageType = Gtk.MessageType.ERROR
         elif returned and result.invalidData:
             secondaryMessage = xstr("register_invalid_data")
-            messageType = MESSAGETYPE_ERROR
+            messageType = Gtk.MessageType.ERROR
         else:
             secondaryMessage = xstr("register_error")
-            messageType = MESSAGETYPE_ERROR
-
-        dialog = gtk.MessageDialog(parent = gui.mainWindow,
+            messageType = Gtk.MessageType.ERROR
+
+        dialog = Gtk.MessageDialog(parent = gui.mainWindow,
                                    type = messageType,
                                    message_format = message)
@@ -1728,8 +1718,8 @@
         self._getEntryExamStatusCancelled = False
 
-        alignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
+        alignment = Gtk.Alignment(xalign = 0.5, yalign = 0.5,
                                   xscale = 0.5, yscale = 0.0)
 
-        table = gtk.Table(6, 4)
+        table = Gtk.Table(6, 4)
         table.set_row_spacings(4)
         table.set_col_spacings(0)
@@ -1740,15 +1730,16 @@
         row = 0
 
-        labelAlignment = gtk.Alignment(xalign=0.0, yalign = 0.5,
+        labelAlignment = Gtk.Alignment(xalign=0.0, yalign = 0.5,
                                        xscale=0.0, yscale = 0.0)
-        label = gtk.Label(xstr("student_entry_exam_status"))
+        label = Gtk.Label(xstr("student_entry_exam_status"))
         label.set_alignment(0.0, 0.5)
         labelAlignment.add(label)
         labelAlignment.resize_children()
-        table.attach(labelAlignment, 0, 1, row, row + 1, xoptions = FILL)
-
-        alignment = gtk.Alignment(xalign=0.0, yalign = 0.5,
+        table.attach(labelAlignment, 0, 1, row, row + 1,
+                     xoptions = Gtk.AttachOptions.FILL)
+
+        alignment = Gtk.Alignment(xalign=0.0, yalign = 0.5,
                                   xscale=1.0, yscale = 0.0)
-        self._entryExamStatus = gtk.Label()
+        self._entryExamStatus = Gtk.Label()
         self._entryExamStatus.set_use_markup(True)
         self._entryExamStatus.set_alignment(0.0, 0.5)
@@ -1759,6 +1750,6 @@
         row += 1
 
-        buttonAlignment = gtk.Alignment(xalign=0.0, xscale=1.0)
-        button = self._entryExamButton = gtk.Button(xstr("student_entry_exam"))
+        buttonAlignment = Gtk.Alignment(xalign=0.0, xscale=1.0)
+        button = self._entryExamButton = Gtk.Button(xstr("student_entry_exam"))
         button.set_use_underline(True)
         button.connect("clicked", self._entryExamClicked)
@@ -1766,18 +1757,20 @@
 
         buttonAlignment.add(button)
-        table.attach(buttonAlignment, 0, 4, row, row + 1, xoptions = FILL,
+        table.attach(buttonAlignment, 0, 4, row, row + 1,
+                     xoptions = Gtk.AttachOptions.FILL,
                      ypadding = 4)
 
         row += 3
 
-        labelAlignment = gtk.Alignment(xalign=0.0, yalign = 0.5,
+        labelAlignment = Gtk.Alignment(xalign=0.0, yalign = 0.5,
                                        xscale=0.0, yscale = 0.0)
-        label = gtk.Label(xstr("student_check_flight_status"))
+        label = Gtk.Label(xstr("student_check_flight_status"))
         labelAlignment.add(label)
-        table.attach(labelAlignment, 0, 1, row, row + 1, xoptions = FILL)
-
-        alignment = gtk.Alignment(xalign=0.0, yalign = 0.5,
+        table.attach(labelAlignment, 0, 1, row, row + 1,
+                     xoptions = Gtk.AttachOptions.FILL)
+
+        alignment = Gtk.Alignment(xalign=0.0, yalign = 0.5,
                                   xscale=1.0, yscale = 0.0)
-        self._checkFlightStatus = gtk.Label()
+        self._checkFlightStatus = Gtk.Label()
         self._checkFlightStatus.set_use_markup(True)
         self._checkFlightStatus.set_alignment(0.0, 0.5)
@@ -1787,19 +1780,19 @@
         row += 1
 
-        alignment = gtk.Alignment(xalign=0.0, xscale=1.0)
-
-        hbox = gtk.HBox()
+        alignment = Gtk.Alignment(xalign=0.0, xscale=1.0)
+
+        hbox = Gtk.HBox()
         hbox.set_homogeneous(False)
         hbox.set_spacing(0)
 
-        aircraftTypesModel = gtk.ListStore(str, int)
+        aircraftTypesModel = Gtk.ListStore(str, int)
         for aircraftType in web.BookedFlight.checkFlightTypes:
             aircraftTypesModel.append([aircraftNames[aircraftType],
                                        aircraftType])
 
-        aircraftTypeAlignment = gtk.Alignment(xalign = 0.0, xscale = 1.0)
-
-        self._aircraftType = gtk.ComboBox(model = aircraftTypesModel)
-        renderer = gtk.CellRendererText()
+        aircraftTypeAlignment = Gtk.Alignment(xalign = 0.0, xscale = 1.0)
+
+        self._aircraftType = Gtk.ComboBox(model = aircraftTypesModel)
+        renderer = Gtk.CellRendererText()
         self._aircraftType.pack_start(renderer, True)
         self._aircraftType.add_attribute(renderer, "text", 0)
@@ -1811,6 +1804,6 @@
         hbox.pack_start(aircraftTypeAlignment, False, False, 0)
 
-        buttonAlignment = gtk.Alignment(xalign=0.0, xscale=1.0)
-        button = self._checkFlightButton = gtk.Button(xstr("student_check_flight"))
+        buttonAlignment = Gtk.Alignment(xalign=0.0, xscale=1.0)
+        button = self._checkFlightButton = Gtk.Button(xstr("student_check_flight"))
         button.set_use_underline(True)
         button.connect("clicked", self._checkFlightClicked)
@@ -1820,5 +1813,6 @@
 
         alignment.add(hbox)
-        table.attach(alignment, 0, 4, row, row + 1, xoptions = FILL)
+        table.attach(alignment, 0, 4, row, row + 1,
+                     xoptions = Gtk.AttachOptions.FILL)
 
     @property
@@ -1830,5 +1824,5 @@
     def activate(self):
         """Activate the student page."""
-        print "StudentPage.activate"
+        print("StudentPage.activate")
         self._getEntryExamStatusCancelled = False
 
@@ -1844,5 +1838,5 @@
     def finalize(self):
         """Finalize the page."""
-        print "StudentPage.finalize"
+        print("StudentPage.finalize")
         self._getEntryExamStatusCancelled = True
 
@@ -1854,5 +1848,5 @@
         """Initiate the query of the entry exam status after the interval."""
         if not self._getEntryExamStatusCancelled:
-            gobject.timeout_add(StudentPage._entryExamStatusQueryInterval,
+            GObject.timeout_add(StudentPage._entryExamStatusQueryInterval,
                                 lambda: self._wizard.gui.webHandler. \
                                 getEntryExamStatus(self._entryExamStatusCallback))
@@ -1860,9 +1854,9 @@
     def _entryExamStatusCallback(self, returned, result):
         """Called when the entry exam status is available."""
-        gobject.idle_add(self._handleEntryExamStatus, returned, result)
+        GObject.idle_add(self._handleEntryExamStatus, returned, result)
 
     def _handleEntryExamStatus(self, returned, result):
         """Called when the entry exam status is availabe."""
-        print "_handleEntryExamStatus", returned, result
+        print("_handleEntryExamStatus", returned, result)
         if returned and not self._getEntryExamStatusCancelled:
             self._entryExamLink = result.entryExamLink
@@ -1907,9 +1901,9 @@
         gui = wizard.gui
 
-        dialog = gtk.MessageDialog(parent = gui.mainWindow,
-                                   type = MESSAGETYPE_INFO,
+        dialog = Gtk.MessageDialog(parent = gui.mainWindow,
+                                   type = Gtk.MessageType.INFO,
                                    message_format = xstr("student_fo"))
 
-        dialog.add_button(xstr("button_ok"), RESPONSETYPE_OK)
+        dialog.add_button(xstr("button_ok"), Gtk.ResponseType.OK)
         dialog.set_title(WINDOW_TITLE_BASE)
         secondary = xstr("student_fo_secondary")
@@ -1937,8 +1931,8 @@
         self._selectSimulator = os.name=="nt" or "FORCE_SELECT_SIM" in os.environ
 
-        alignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
+        alignment = Gtk.Alignment(xalign = 0.5, yalign = 0.5,
                                   xscale = 0.0, yscale = 0.0)
 
-        table = gtk.Table(7 if self._selectSimulator else 5, 2)
+        table = Gtk.Table(7 if self._selectSimulator else 5, 2)
         table.set_row_spacings(4)
         table.set_col_spacings(16)
@@ -1947,11 +1941,11 @@
         self.setMainWidget(alignment)
 
-        labelAlignment = gtk.Alignment(xalign=1.0, xscale=0.0)
-        label = gtk.Label(xstr("connect_flightno"))
+        labelAlignment = Gtk.Alignment(xalign=1.0, xscale=0.0)
+        label = Gtk.Label(xstr("connect_flightno"))
         labelAlignment.add(label)
         table.attach(labelAlignment, 0, 1, 0, 1)
 
-        labelAlignment = gtk.Alignment(xalign=0.0, xscale=0.0)
-        self._flightNumber = gtk.Label()
+        labelAlignment = Gtk.Alignment(xalign=0.0, xscale=0.0)
+        self._flightNumber = Gtk.Label()
         self._flightNumber.set_width_chars(9)
         self._flightNumber.set_alignment(0.0, 0.5)
@@ -1959,11 +1953,11 @@
         table.attach(labelAlignment, 1, 2, 0, 1)
 
-        labelAlignment = gtk.Alignment(xalign=1.0, xscale=0.0)
-        label = gtk.Label(xstr("connect_acft"))
+        labelAlignment = Gtk.Alignment(xalign=1.0, xscale=0.0)
+        label = Gtk.Label(xstr("connect_acft"))
         labelAlignment.add(label)
         table.attach(labelAlignment, 0, 1, 1, 2)
 
-        labelAlignment = gtk.Alignment(xalign=0.0, xscale=0.0)
-        self._aircraft = gtk.Label()
+        labelAlignment = Gtk.Alignment(xalign=0.0, xscale=0.0)
+        self._aircraft = Gtk.Label()
         self._aircraft.set_width_chars(25)
         self._aircraft.set_alignment(0.0, 0.5)
@@ -1971,11 +1965,11 @@
         table.attach(labelAlignment, 1, 2, 1, 2)
 
-        labelAlignment = gtk.Alignment(xalign=1.0, xscale=0.0)
-        label = gtk.Label(xstr("connect_tailno"))
+        labelAlignment = Gtk.Alignment(xalign=1.0, xscale=0.0)
+        label = Gtk.Label(xstr("connect_tailno"))
         labelAlignment.add(label)
         table.attach(labelAlignment, 0, 1, 2, 3)
 
-        labelAlignment = gtk.Alignment(xalign=0.0, xscale=0.0)
-        self._tailNumber = gtk.Label()
+        labelAlignment = Gtk.Alignment(xalign=0.0, xscale=0.0)
+        self._tailNumber = Gtk.Label()
         self._tailNumber.set_width_chars(10)
         self._tailNumber.set_alignment(0.0, 0.5)
@@ -1983,11 +1977,11 @@
         table.attach(labelAlignment, 1, 2, 2, 3)
 
-        labelAlignment = gtk.Alignment(xalign=1.0, xscale=0.0)
-        label = gtk.Label(xstr("connect_airport"))
+        labelAlignment = Gtk.Alignment(xalign=1.0, xscale=0.0)
+        label = Gtk.Label(xstr("connect_airport"))
         labelAlignment.add(label)
         table.attach(labelAlignment, 0, 1, 3, 4)
 
-        labelAlignment = gtk.Alignment(xalign=0.0, xscale=0.0)
-        self._departureICAO = gtk.Label()
+        labelAlignment = Gtk.Alignment(xalign=0.0, xscale=0.0)
+        self._departureICAO = Gtk.Label()
         self._departureICAO.set_width_chars(6)
         self._departureICAO.set_alignment(0.0, 0.5)
@@ -1995,11 +1989,11 @@
         table.attach(labelAlignment, 1, 2, 3, 4)
 
-        labelAlignment = gtk.Alignment(xalign=1.0, xscale=0.0)
-        label = gtk.Label(xstr("connect_gate"))
+        labelAlignment = Gtk.Alignment(xalign=1.0, xscale=0.0)
+        label = Gtk.Label(xstr("connect_gate"))
         labelAlignment.add(label)
         table.attach(labelAlignment, 0, 1, 4, 5)
 
-        labelAlignment = gtk.Alignment(xalign=0.0, xscale=0.0)
-        self._departureGate = gtk.Label()
+        labelAlignment = Gtk.Alignment(xalign=0.0, xscale=0.0)
+        self._departureGate = Gtk.Label()
         self._departureGate.set_width_chars(5)
         self._departureGate.set_alignment(0.0, 0.5)
@@ -2008,29 +2002,21 @@
 
         if self._selectSimulator:
-            labelAlignment = gtk.Alignment(xalign=1.0, xscale=0.0, yalign=0.5)
-            label = gtk.Label(xstr("connect_sim"))
+            labelAlignment = Gtk.Alignment(xalign=1.0, xscale=0.0, yalign=0.5)
+            label = Gtk.Label(xstr("connect_sim"))
             labelAlignment.add(label)
             table.attach(labelAlignment, 0, 1, 5, 7)
 
-            selectAlignment = gtk.Alignment(xalign=0.0, xscale=0.0, yalign=0.5)
-
-            selectBox = gtk.HBox()
-            if pygobject:
-                self._selectMSFS = \
-                  gtk.RadioButton.new_with_mnemonic_from_widget(None,
-                                                                xstr("connect_sim_msfs"))
-            else:
-                self._selectMSFS = gtk.RadioButton(None,
-                                                   xstr("connect_sim_msfs"))
+            selectAlignment = Gtk.Alignment(xalign=0.0, xscale=0.0, yalign=0.5)
+
+            selectBox = Gtk.HBox()
+            self._selectMSFS = \
+                Gtk.RadioButton.new_with_mnemonic_from_widget(None,
+                                                              xstr("connect_sim_msfs"))
 
             selectBox.pack_start(self._selectMSFS, False, False, 0);
 
-            if pygobject:
-                self._selectXPlane = \
-                  gtk.RadioButton.new_with_mnemonic_from_widget(self._selectMSFS,
-                                                                xstr("connect_sim_xplane"))
-            else:
-                self._selectXPlane = gtk.RadioButton(self._selectMSFS,
-                                                     xstr("connect_sim_xplane"))
+            self._selectXPlane = \
+                Gtk.RadioButton.new_with_mnemonic_from_widget(self._selectMSFS,
+                                                              xstr("connect_sim_xplane"))
 
             selectBox.pack_start(self._selectXPlane, False, False, 8);
@@ -2122,8 +2108,8 @@
                                           completedHelp = xstr("payload_chelp"))
 
-        alignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
+        alignment = Gtk.Alignment(xalign = 0.5, yalign = 0.5,
                                   xscale = 0.0, yscale = 0.0)
 
-        table = gtk.Table(7, 3)
+        table = Gtk.Table(7, 3)
         table.set_row_spacings(4)
         table.set_col_spacings(16)
@@ -2132,5 +2118,5 @@
         self.setMainWidget(alignment)
 
-        label = gtk.Label(xstr("payload_crew"))
+        label = Gtk.Label(xstr("payload_crew"))
         label.set_use_underline(True)
         label.set_alignment(0.0, 0.5)
@@ -2144,5 +2130,5 @@
         label.set_mnemonic_widget(self._numCrew)
 
-        label = gtk.Label(xstr("payload_pax"))
+        label = Gtk.Label(xstr("payload_pax"))
         label.set_use_underline(True)
         label.set_alignment(0.0, 0.5)
@@ -2156,5 +2142,5 @@
         label.set_mnemonic_widget(self._numPassengers)
 
-        label = gtk.Label(xstr("payload_bag"))
+        label = Gtk.Label(xstr("payload_bag"))
         label.set_use_underline(True)
         label.set_alignment(0.0, 0.5)
@@ -2168,7 +2154,7 @@
         label.set_mnemonic_widget(self._bagWeight)
 
-        table.attach(gtk.Label("kg"), 2, 3, 2, 3)
-
-        label = gtk.Label(xstr("payload_cargo"))
+        table.attach(Gtk.Label("kg"), 2, 3, 2, 3)
+
+        label = Gtk.Label(xstr("payload_cargo"))
         label.set_use_underline(True)
         label.set_alignment(0.0, 0.5)
@@ -2182,7 +2168,7 @@
         label.set_mnemonic_widget(self._cargoWeight)
 
-        table.attach(gtk.Label("kg"), 2, 3, 3, 4)
-
-        label = gtk.Label(xstr("payload_mail"))
+        table.attach(Gtk.Label("kg"), 2, 3, 3, 4)
+
+        label = Gtk.Label(xstr("payload_mail"))
         label.set_use_underline(True)
         label.set_alignment(0.0, 0.5)
@@ -2196,19 +2182,19 @@
         label.set_mnemonic_widget(self._mailWeight)
 
-        table.attach(gtk.Label("kg"), 2, 3, 4, 5)
-
-        label = gtk.Label("<b>" + xstr("payload_zfw") + "</b>")
+        table.attach(Gtk.Label("kg"), 2, 3, 4, 5)
+
+        label = Gtk.Label("<b>" + xstr("payload_zfw") + "</b>")
         label.set_alignment(0.0, 0.5)
         label.set_use_markup(True)
         table.attach(label, 0, 1, 5, 6)
 
-        self._calculatedZFW = gtk.Label()
+        self._calculatedZFW = Gtk.Label()
         self._calculatedZFW.set_width_chars(6)
         self._calculatedZFW.set_alignment(1.0, 0.5)
         table.attach(self._calculatedZFW, 1, 2, 5, 6)
 
-        table.attach(gtk.Label("kg"), 2, 3, 5, 6)
-
-        self._zfwButton = gtk.Button(xstr("payload_fszfw"))
+        table.attach(Gtk.Label("kg"), 2, 3, 5, 6)
+
+        self._zfwButton = Gtk.Button(xstr("payload_fszfw"))
         self._zfwButton.set_use_underline(True)
         self._zfwButton.connect("clicked", self._zfwRequested)
@@ -2216,5 +2202,5 @@
         table.attach(self._zfwButton, 0, 1, 6, 7)
 
-        self._simulatorZFW = gtk.Label("-")
+        self._simulatorZFW = Gtk.Label("-")
         self._simulatorZFW.set_width_chars(6)
         self._simulatorZFW.set_alignment(1.0, 0.5)
@@ -2222,5 +2208,5 @@
         self._simulatorZFWValue = None
 
-        table.attach(gtk.Label("kg"), 2, 3, 6, 7)
+        table.attach(Gtk.Label("kg"), 2, 3, 6, 7)
 
         self.addCancelFlightButton()
@@ -2319,5 +2305,5 @@
     def _handleZFW(self, zfw):
         """Called when the ZFW value is retrieved."""
-        gobject.idle_add(self._processZFW, zfw)
+        GObject.idle_add(self._processZFW, zfw)
 
     def _processZFW(self, zfw):
@@ -2350,8 +2336,8 @@
                                        completedHelp = xstr("time_chelp"))
 
-        alignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
+        alignment = Gtk.Alignment(xalign = 0.5, yalign = 0.5,
                                   xscale = 0.0, yscale = 0.0)
 
-        table = gtk.Table(3, 2)
+        table = Gtk.Table(3, 2)
         table.set_row_spacings(4)
         table.set_col_spacings(16)
@@ -2360,21 +2346,21 @@
         self.setMainWidget(alignment)
 
-        label = gtk.Label(xstr("time_departure"))
+        label = Gtk.Label(xstr("time_departure"))
         label.set_alignment(0.0, 0.5)
         table.attach(label, 0, 1, 0, 1)
 
-        self._departure = gtk.Label()
+        self._departure = Gtk.Label()
         self._departure.set_alignment(0.0, 0.5)
         table.attach(self._departure, 1, 2, 0, 1)
 
-        label = gtk.Label(xstr("time_arrival"))
+        label = Gtk.Label(xstr("time_arrival"))
         label.set_alignment(0.0, 0.5)
         table.attach(label, 0, 1, 1, 2)
 
-        self._arrival = gtk.Label()
+        self._arrival = Gtk.Label()
         self._arrival.set_alignment(0.0, 0.5)
         table.attach(self._arrival, 1, 2, 1, 2)
 
-        self._timeButton = gtk.Button(xstr("time_fs"))
+        self._timeButton = Gtk.Button(xstr("time_fs"))
         self._timeButton.set_use_underline(True)
         self._timeButton.set_tooltip_text(xstr("time_fs_tooltip"))
@@ -2382,5 +2368,5 @@
         table.attach(self._timeButton, 0, 1, 2, 3)
 
-        self._simulatorTime = gtk.Label("-")
+        self._simulatorTime = Gtk.Label("-")
         self._simulatorTime.set_alignment(0.0, 0.5)
         table.attach(self._simulatorTime, 1, 2, 2, 3)
@@ -2409,5 +2395,5 @@
     def _handleTime(self, timestamp):
         """Handle the result of a time retrieval."""
-        gobject.idle_add(self._processTime, timestamp)
+        GObject.idle_add(self._processTime, timestamp)
 
     def _processTime(self, timestamp):
@@ -2453,5 +2439,5 @@
     def _handleFuel(self, fuelData):
         """Callback for the fuel query operation."""
-        gobject.idle_add(self._processFuel, fuelData)
+        GObject.idle_add(self._processFuel, fuelData)
 
     def _processFuel(self, fuelData):
@@ -2472,18 +2458,18 @@
                                         completedHelp = xstr("route_chelp"))
 
-        alignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
+        alignment = Gtk.Alignment(xalign = 0.5, yalign = 0.5,
                                   xscale = 0.0, yscale = 0.0)
 
-        mainBox = gtk.VBox()
+        mainBox = Gtk.VBox()
         alignment.add(mainBox)
         self.setMainWidget(alignment)
 
-        levelBox = gtk.HBox()
-
-        label = gtk.Label(xstr("route_level"))
+        levelBox = Gtk.HBox()
+
+        label = Gtk.Label(xstr("route_level"))
         label.set_use_underline(True)
         levelBox.pack_start(label, True, True, 0)
 
-        self._cruiseLevel = gtk.SpinButton()
+        self._cruiseLevel = Gtk.SpinButton()
         self._cruiseLevel.set_increments(step = 10, page = 100)
         self._cruiseLevel.set_range(min = 0, max = 500)
@@ -2496,5 +2482,5 @@
         levelBox.pack_start(self._cruiseLevel, False, False, 8)
 
-        alignment = gtk.Alignment(xalign = 0.0, yalign = 0.5,
+        alignment = Gtk.Alignment(xalign = 0.0, yalign = 0.5,
                                   xscale = 0.0, yscale = 0.0)
         alignment.add(levelBox)
@@ -2503,27 +2489,24 @@
 
 
-        routeBox = gtk.VBox()
-
-        alignment = gtk.Alignment(xalign = 0.0, yalign = 0.5,
+        routeBox = Gtk.VBox()
+
+        alignment = Gtk.Alignment(xalign = 0.0, yalign = 0.5,
                                   xscale = 0.0, yscale = 0.0)
-        label = gtk.Label(xstr("route_route"))
+        label = Gtk.Label(xstr("route_route"))
         label.set_use_underline(True)
         alignment.add(label)
         routeBox.pack_start(alignment, True, True, 0)
 
-        routeWindow = gtk.ScrolledWindow()
+        routeWindow = Gtk.ScrolledWindow()
         routeWindow.set_size_request(400, 80)
-        routeWindow.set_shadow_type(gtk.ShadowType.IN if pygobject
-                                    else gtk.SHADOW_IN)
-        routeWindow.set_policy(gtk.PolicyType.AUTOMATIC if pygobject
-                               else gtk.POLICY_AUTOMATIC,
-                               gtk.PolicyType.AUTOMATIC if pygobject
-                               else gtk.POLICY_AUTOMATIC)
+        routeWindow.set_shadow_type(Gtk.ShadowType.IN)
+        routeWindow.set_policy(Gtk.PolicyType.AUTOMATIC,
+                               Gtk.PolicyType.AUTOMATIC)
 
         self._uppercasingRoute = False
 
-        self._route = gtk.TextView()
+        self._route = Gtk.TextView()
         self._route.set_tooltip_text(xstr("route_route_tooltip"))
-        self._route.set_wrap_mode(WRAP_WORD)
+        self._route.set_wrap_mode(Gtk.WrapMode.WORD)
         self._route.get_buffer().connect("changed", self._routeChanged)
         self._route.get_buffer().connect_after("insert-text", self._routeInserted)
@@ -2535,11 +2518,11 @@
         mainBox.pack_start(routeBox, True, True, 8)
 
-        alternateBox = gtk.HBox()
-
-        label = gtk.Label(xstr("route_altn"))
+        alternateBox = Gtk.HBox()
+
+        label = Gtk.Label(xstr("route_altn"))
         label.set_use_underline(True)
         alternateBox.pack_start(label, True, True, 0)
 
-        self._alternate = gtk.Entry()
+        self._alternate = Gtk.Entry()
         self._alternate.set_width_chars(6)
         self._alternate.connect("changed", self._alternateChanged)
@@ -2549,5 +2532,5 @@
         alternateBox.pack_start(self._alternate, False, False, 8)
 
-        alignment = gtk.Alignment(xalign = 0.0, yalign = 0.5,
+        alignment = Gtk.Alignment(xalign = 0.0, yalign = 0.5,
                                   xscale = 0.0, yscale = 0.0)
         alignment.add(alternateBox)
@@ -2643,5 +2626,5 @@
 #-----------------------------------------------------------------------------
 
-class SimBriefCredentialsDialog(gtk.Dialog):
+class SimBriefCredentialsDialog(Gtk.Dialog):
     """A dialog window to ask for SimBrief credentials."""
     def __init__(self, gui, userName, password, rememberPassword):
@@ -2650,11 +2633,11 @@
                                                         xstr("simbrief_credentials_title"),
                                                         gui.mainWindow,
-                                                        DIALOG_MODAL)
-        self.add_button(xstr("button_cancel"), RESPONSETYPE_CANCEL)
-        self.add_button(xstr("button_ok"), RESPONSETYPE_OK)
+                                                        Gtk.DialogFlags.MODAL)
+        self.add_button(xstr("button_cancel"), Gtk.ResponseType.CANCEL)
+        self.add_button(xstr("button_ok"), Gtk.ResponseType.OK)
 
         contentArea = self.get_content_area()
 
-        contentAlignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
+        contentAlignment = Gtk.Alignment(xalign = 0.5, yalign = 0.5,
                                          xscale = 0.0, yscale = 0.0)
         contentAlignment.set_padding(padding_top = 4, padding_bottom = 16,
@@ -2663,18 +2646,18 @@
         contentArea.pack_start(contentAlignment, False, False, 0)
 
-        contentVBox = gtk.VBox()
+        contentVBox = Gtk.VBox()
         contentAlignment.add(contentVBox)
 
-        label = gtk.Label(xstr("simbrief_login_failed"))
+        label = Gtk.Label(xstr("simbrief_login_failed"))
         label.set_alignment(0.0, 0.0)
 
         contentVBox.pack_start(label, False, False, 0)
 
-        tableAlignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
+        tableAlignment = Gtk.Alignment(xalign = 0.5, yalign = 0.5,
                                        xscale = 0.0, yscale = 0.0)
         tableAlignment.set_padding(padding_top = 24, padding_bottom = 0,
                                    padding_left = 0, padding_right = 0)
 
-        table = gtk.Table(3, 2)
+        table = Gtk.Table(3, 2)
         table.set_row_spacings(4)
         table.set_col_spacings(16)
@@ -2684,10 +2667,10 @@
         contentVBox.pack_start(tableAlignment, True, True, 0)
 
-        label = gtk.Label(xstr("simbrief_username"))
+        label = Gtk.Label(xstr("simbrief_username"))
         label.set_use_underline(True)
         label.set_alignment(0.0, 0.5)
         table.attach(label, 0, 1, 0, 1)
 
-        self._userName = gtk.Entry()
+        self._userName = Gtk.Entry()
         self._userName.set_width_chars(16)
         #self._userName.connect("changed",
@@ -2698,10 +2681,10 @@
         label.set_mnemonic_widget(self._userName)
 
-        label = gtk.Label(xstr("simbrief_password"))
+        label = Gtk.Label(xstr("simbrief_password"))
         label.set_use_underline(True)
         label.set_alignment(0.0, 0.5)
         table.attach(label, 0, 1, 1, 2)
 
-        self._password = gtk.Entry()
+        self._password = Gtk.Entry()
         self._password.set_visibility(False)
         #self._password.connect("changed",
@@ -2712,5 +2695,5 @@
         label.set_mnemonic_widget(self._password)
 
-        self._rememberButton = gtk.CheckButton(xstr("simbrief_remember_password"))
+        self._rememberButton = Gtk.CheckButton(xstr("simbrief_remember_password"))
         self._rememberButton.set_use_underline(True)
         self._rememberButton.set_tooltip_text(xstr("simbrief_remember_tooltip"))
@@ -2803,8 +2786,8 @@
                                                 xstr("simbrief_setup_chelp"))
 
-        alignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
+        alignment = Gtk.Alignment(xalign = 0.5, yalign = 0.5,
                                   xscale = 0.0, yscale = 0.0)
 
-        table = gtk.Table(9, 3)
+        table = Gtk.Table(9, 3)
         table.set_row_spacings(4)
         table.set_col_spacings(16)
@@ -2813,10 +2796,10 @@
         self.setMainWidget(alignment)
 
-        label = gtk.Label(xstr("simbrief_username"))
+        label = Gtk.Label(xstr("simbrief_username"))
         label.set_use_underline(True)
         label.set_alignment(0.0, 0.5)
         table.attach(label, 0, 1, 0, 1)
 
-        self._userName = gtk.Entry()
+        self._userName = Gtk.Entry()
         self._userName.set_width_chars(16)
         self._userName.connect("changed",
@@ -2826,10 +2809,10 @@
         label.set_mnemonic_widget(self._userName)
 
-        label = gtk.Label(xstr("simbrief_password"))
+        label = Gtk.Label(xstr("simbrief_password"))
         label.set_use_underline(True)
         label.set_alignment(0.0, 0.5)
         table.attach(label, 0, 1, 1, 2)
 
-        self._password = gtk.Entry()
+        self._password = Gtk.Entry()
         self._password.set_visibility(False)
         self._password.connect("changed",
@@ -2839,10 +2822,10 @@
         label.set_mnemonic_widget(self._password)
 
-        self._rememberButton = gtk.CheckButton(xstr("simbrief_remember_password"))
+        self._rememberButton = Gtk.CheckButton(xstr("simbrief_remember_password"))
         self._rememberButton.set_use_underline(True)
         self._rememberButton.set_tooltip_text(xstr("simbrief_remember_tooltip"))
         table.attach(self._rememberButton, 1, 2, 2, 3, ypadding = 8)
 
-        label = gtk.Label(xstr("simbrief_extra_fuel"))
+        label = Gtk.Label(xstr("simbrief_extra_fuel"))
         label.set_use_underline(True)
         label.set_alignment(0.0, 0.5)
@@ -2855,12 +2838,12 @@
         label.set_mnemonic_widget(self._extraFuel)
 
-        table.attach(gtk.Label("kg"), 2, 3, 3, 4)
-
-        label = gtk.Label(xstr("simbrief_takeoff_runway"))
+        table.attach(Gtk.Label("kg"), 2, 3, 3, 4)
+
+        label = Gtk.Label(xstr("simbrief_takeoff_runway"))
         label.set_use_underline(True)
         label.set_alignment(0.0, 0.5)
         table.attach(label, 0, 1, 4, 5)
 
-        self._takeoffRunway = gtk.Entry()
+        self._takeoffRunway = Gtk.Entry()
         self._takeoffRunway.set_width_chars(10)
         self._takeoffRunway.set_tooltip_text(xstr("simbrief_takeoff_runway_tooltip"))
@@ -2869,10 +2852,10 @@
         label.set_mnemonic_widget(self._takeoffRunway)
 
-        label = gtk.Label(xstr("simbrief_landing_runway"))
+        label = Gtk.Label(xstr("simbrief_landing_runway"))
         label.set_use_underline(True)
         label.set_alignment(0.0, 0.5)
         table.attach(label, 0, 1, 5, 6)
 
-        self._landingRunway = gtk.Entry()
+        self._landingRunway = Gtk.Entry()
         self._landingRunway.set_width_chars(10)
         self._landingRunway.set_tooltip_text(xstr("simbrief_takeoff_runway_tooltip"))
@@ -2881,11 +2864,11 @@
         label.set_mnemonic_widget(self._landingRunway)
 
-        label = gtk.Label(xstr("simbrief_climb_profile"))
+        label = Gtk.Label(xstr("simbrief_climb_profile"))
         label.set_use_underline(True)
         label.set_alignment(0.0, 0.5)
         table.attach(label, 0, 1, 6, 7)
 
-        self._climbProfile = gtk.ComboBox()
-        renderer = gtk.CellRendererText()
+        self._climbProfile = Gtk.ComboBox()
+        renderer = Gtk.CellRendererText()
         self._climbProfile.pack_start(renderer, True)
         self._climbProfile.add_attribute(renderer, "text", 0)
@@ -2894,11 +2877,11 @@
         label.set_mnemonic_widget(self._climbProfile)
 
-        label = gtk.Label(xstr("simbrief_cruise_profile"))
+        label = Gtk.Label(xstr("simbrief_cruise_profile"))
         label.set_use_underline(True)
         label.set_alignment(0.0, 0.5)
         table.attach(label, 0, 1, 7, 8)
 
-        self._cruiseProfile = gtk.ComboBox()
-        renderer = gtk.CellRendererText()
+        self._cruiseProfile = Gtk.ComboBox()
+        renderer = Gtk.CellRendererText()
         self._cruiseProfile.pack_start(renderer, True)
         self._cruiseProfile.add_attribute(renderer, "text", 0)
@@ -2907,11 +2890,11 @@
         label.set_mnemonic_widget(self._cruiseProfile)
 
-        label = gtk.Label(xstr("simbrief_descent_profile"))
+        label = Gtk.Label(xstr("simbrief_descent_profile"))
         label.set_use_underline(True)
         label.set_alignment(0.0, 0.5)
         table.attach(label, 0, 1, 8, 9)
 
-        self._descentProfile = gtk.ComboBox()
-        renderer = gtk.CellRendererText()
+        self._descentProfile = Gtk.ComboBox()
+        renderer = Gtk.CellRendererText()
         self._descentProfile.pack_start(renderer, True)
         self._descentProfile.add_attribute(renderer, "text", 0)
@@ -2954,5 +2937,5 @@
                                     (self._descentProfile,
                                      simBriefData.descentProfiles)]:
-            model = gtk.ListStore(str)
+            model = Gtk.ListStore(str)
             for profile in profiles:
                 model.append([profile])
@@ -2991,5 +2974,5 @@
 
             plan = self._getPlan()
-            print "plan:", plan
+            print("plan:", plan)
 
             takeoffRunway = self._takeoffRunway.get_text()
@@ -3027,5 +3010,5 @@
         are returned. Otherwise a dialog box is displayed informing the user of
         invalid credentials and requesting another set of them."""
-        print "_getCredentials", count
+        print("_getCredentials", count)
         if count==0:
             return (self._userName.get_text(), self._password.get_text())
@@ -3040,5 +3023,5 @@
             response = dialog.run()
 
-            if response==RESPONSETYPE_OK:
+            if response==Gtk.ResponseType.OK:
                 userName = dialog.userName
                 self._userName.set_text(userName)
@@ -3061,5 +3044,5 @@
     def _simBriefProgress(self, progress, result, flightInfo):
         """The real SimBrief progress handler."""
-        print "_simBriefProgress", progress, result, flightInfo
+        print("_simBriefProgress", progress, result, flightInfo)
         if result==cef.SIMBRIEF_RESULT_NONE:
             message = SimBriefSetupPage.progress2Message.get(progress,
@@ -3077,11 +3060,11 @@
                 message = SimBriefSetupPage.result2Message.get(result,
                                                                "simbrief_result_unknown")
-                dialog = gtk.MessageDialog(parent = self._wizard.gui.mainWindow,
-                                           type = MESSAGETYPE_ERROR,
+                dialog = Gtk.MessageDialog(parent = self._wizard.gui.mainWindow,
+                                           type = Gtk.MessageType.ERROR,
                                            message_format =
                                            xstr(message) + "\n"+
                                            xstr("simbrief_cancelled"))
 
-                dialog.add_button(xstr("button_ok"), RESPONSETYPE_OK)
+                dialog.add_button(xstr("button_ok"), Gtk.ResponseType.OK)
                 dialog.set_title(WINDOW_TITLE_BASE)
                 secondary = xstr("flightsel_save_failed_sec")
@@ -3179,5 +3162,5 @@
                                               xstr("simbrief_result_title"), "")
 
-        self._alignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
+        self._alignment = Gtk.Alignment(xalign = 0.5, yalign = 0.5,
                                        xscale = 1.0, yscale = 1.0)
 
@@ -3248,5 +3231,5 @@
 #-----------------------------------------------------------------------------
 
-class FuelTank(gtk.VBox):
+class FuelTank(Gtk.VBox):
     """Widget for the fuel tank."""
     def __init__(self, fuelTank, name, capacity, currentWeight):
@@ -3260,25 +3243,23 @@
         self.expectedWeight = currentWeight
 
-        label = gtk.Label("<b>" + name + "</b>")
+        self._label = label = Gtk.Label("<b>" + name + "</b>")
         label.set_use_markup(True)
         label.set_use_underline(True)
-        label.set_justify(JUSTIFY_CENTER)
+        label.set_justify(Gtk.Justification.CENTER)
         label.set_alignment(0.5, 1.0)
-        self.pack_start(label, False, False, 4)
-
-        self._tankFigure = gtk.EventBox()
-        self._tankFigure.set_size_request(38, -1)
+
+        self._tankFigure = Gtk.EventBox()
+        self._tankFigure.set_size_request(38, 200)
         self._tankFigure.set_visible_window(False)
         self._tankFigure.set_tooltip_markup(xstr("fuel_tank_tooltip"))
 
-        if pygobject:
-            self._tankFigure.connect("draw", self._drawTankFigure)
-        else:
-            self._tankFigure.connect("expose_event", self._drawTankFigure)
+        self._tankFigure.connect("draw", self._drawTankFigure)
         self._tankFigure.connect("button_press_event", self._buttonPressed)
         self._tankFigure.connect("motion_notify_event", self._motionNotify)
+
+        self._tankFigure.add_events(Gdk.EventMask.SCROLL_MASK)
         self._tankFigure.connect("scroll-event", self._scrolled)
 
-        alignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
+        alignment = Gtk.Alignment(xalign = 0.5, yalign = 0.5,
                                   xscale = 0.0, yscale = 1.0)
         alignment.add(self._tankFigure)
@@ -3286,5 +3267,5 @@
         self.pack_start(alignment, True, True, 4)
 
-        self._expectedButton = gtk.SpinButton()
+        self._expectedButton = Gtk.SpinButton()
         self._expectedButton.set_numeric(True)
         self._expectedButton.set_range(0, self.capacity)
@@ -3297,8 +3278,13 @@
         label.set_mnemonic_widget(self._expectedButton)
 
-        alignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
-                                  xscale = 0.0, yscale = 1.0)
-        alignment.add(self._expectedButton)
-        self.pack_start(alignment, False, False, 4)
+    @property
+    def label(self):
+        """Get the label with the caption."""
+        return self._label
+
+    @property
+    def expectedButton(self):
+        """Get the button containing the expected value."""
+        return self._expectedButton
 
     def setCurrent(self, currentWeight):
@@ -3324,12 +3310,9 @@
         triangleSize = 5
 
-        context = eventOrContext if pygobject else tankFigure.window.cairo_create()
-        (xOffset, yOffset) = (0, 0) if pygobject \
-                             else (tankFigure.allocation.x, tankFigure.allocation.y)
-
-        width = tankFigure.get_allocated_width() if pygobject \
-                else tankFigure.allocation.width
-        height = tankFigure.get_allocated_height() if pygobject \
-                 else tankFigure.allocation.height
+        context = eventOrContext
+        (xOffset, yOffset) = (0, 0)
+
+        width = tankFigure.get_allocated_width()
+        height = tankFigure.get_allocated_height()
 
         rectangleX0 = triangleSize
@@ -3405,5 +3388,5 @@
     def _motionNotify(self, tankFigure, event):
         """Called when the mouse pointer moves within the area of a tank figure."""
-        if self._enabled and event.state==BUTTON1_MASK:
+        if self._enabled and event.state==Gdk.ModifierType.BUTTON1_MASK:
             self._setExpectedFromY(event.y)
 
@@ -3411,11 +3394,11 @@
         """Called when a scroll event is received."""
         if self._enabled:
-            increment = 1 if event.state==CONTROL_MASK \
-                        else 100 if event.state==SHIFT_MASK \
+            increment = 1 if event.state==Gdk.ModifierType.CONTROL_MASK \
+                        else 100 if event.state==Gdk.ModifierType.SHIFT_MASK \
                         else 10 if event.state==0 else 0
             if increment!=0:
-                if event.direction==SCROLL_DOWN:
+                if event.direction==Gdk.ScrollDirection.DOWN:
                     increment *= -1
-                self._expectedButton.spin(SPIN_USER_DEFINED, increment)
+                self._expectedButton.spin(Gtk.SpinType.USER_DEFINED, increment)
 
     def _expectedChanged(self, spinButton):
@@ -3440,5 +3423,5 @@
         self._fuelTanks = []
         self._fuelTable = None
-        self._fuelAlignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
+        self._fuelAlignment = Gtk.Alignment(xalign = 0.5, yalign = 0.5,
                                             xscale = 0.0, yscale = 1.0)
         self.setMainWidget(self._fuelAlignment)
@@ -3496,6 +3479,8 @@
 
         self._fuelTanks = []
-        self._fuelTable = gtk.Table(numTanks, 1)
-        self._fuelTable.set_col_spacings(16)
+        self._fuelTable = Gtk.Grid()
+        self._fuelTable.set_column_homogeneous(True)
+        self._fuelTable.set_row_spacing(4)
+        self._fuelTable.set_column_spacing(16 if numTanks<5 else 0)
         index = 0
         for (tank, current, capacity) in tankData:
@@ -3504,6 +3489,30 @@
                                      const.fuelTank2string(tank)),
                                 capacity, current)
-            self._fuelTable.attach(fuelTank, index, index+1, 0, 1)
             self._fuelTanks.append(fuelTank)
+
+            alignment = Gtk.Alignment(xalign = 0.5, yalign = 1.0,
+                                      xscale = 1.0, yscale = 0.0)
+            alignment.add(fuelTank.label)
+            self._fuelTable.attach(alignment,
+                                   index*(1 if numTanks<5 else 2), 0,
+                                   1 if numTanks<5 else 3, 1)
+
+            alignment = Gtk.Alignment(xalign = 0.5, yalign = 0.5,
+                                      xscale = 0.0, yscale = 1.0)
+            alignment.add(fuelTank)
+            self._fuelTable.attach(alignment,
+                                   index*(1 if numTanks<5 else 2) +
+                                   (0 if numTanks<5 else 1), 1, 1, 1)
+
+
+            alignment = Gtk.Alignment(xalign = 0.5, yalign = 0.5,
+                                      xscale = 1.0, yscale = 0.0)
+            alignment.add(fuelTank.expectedButton)
+
+            self._fuelTable.attach(alignment,
+                                   index* (1 if numTanks<5 else 2),
+                                   2 if (index%2)==0 or numTanks<5 else 3,
+                                   1 if numTanks<5 else 3, 1)
+
             index += 1
 
@@ -3553,9 +3562,9 @@
             self._wizard.gui.simulator.setFuelLevel([(fuelTank.fuelTank,
                                                       currentLevel)])
-            gobject.timeout_add(50, self._pump)
+            GObject.timeout_add(50, self._pump)
 
     def _notamsCallback(self, returned, result):
         """Callback for the NOTAMs."""
-        gobject.idle_add(self._handleNOTAMs, returned, result)
+        GObject.idle_add(self._handleNOTAMs, returned, result)
 
     def _handleNOTAMs(self, returned, result):
@@ -3576,5 +3585,5 @@
     def _metarsCallback(self, returned, result):
         """Callback for the METARs."""
-        gobject.idle_add(self._handleMETARs, returned, result)
+        GObject.idle_add(self._handleMETARs, returned, result)
 
     def _handleMETARs(self, returned, result):
@@ -3613,26 +3622,24 @@
                                            completedHelp = xstr("briefing_chelp"))
 
-        alignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
+        alignment = Gtk.Alignment(xalign = 0.5, yalign = 0.5,
                                   xscale = 1.0, yscale = 1.0)
 
-        mainBox = gtk.VBox()
+        mainBox = Gtk.VBox()
         alignment.add(mainBox)
         self.setMainWidget(alignment)
 
-        self._notamsFrame = gtk.Frame()
+        self._notamsFrame = Gtk.Frame()
         self._notamsFrame.set_label(xstr("briefing_notams_init"))
-        scrolledWindow = gtk.ScrolledWindow()
+        scrolledWindow = Gtk.ScrolledWindow()
         scrolledWindow.set_size_request(-1, 128)
         # FIXME: these constants should be in common
-        scrolledWindow.set_policy(gtk.PolicyType.AUTOMATIC if pygobject
-                                  else gtk.POLICY_AUTOMATIC,
-                                  gtk.PolicyType.AUTOMATIC if pygobject
-                                  else gtk.POLICY_AUTOMATIC)
-        self._notams = gtk.TextView()
+        scrolledWindow.set_policy(Gtk.PolicyType.AUTOMATIC,
+                                  Gtk.PolicyType.AUTOMATIC)
+        self._notams = Gtk.TextView()
         self._notams.set_editable(False)
         self._notams.set_accepts_tab(False)
-        self._notams.set_wrap_mode(gtk.WrapMode.WORD if pygobject else gtk.WRAP_WORD)
+        self._notams.set_wrap_mode(Gtk.WrapMode.WORD)
         scrolledWindow.add(self._notams)
-        alignment = gtk.Alignment(xalign = 0.0, yalign = 0.0,
+        alignment = Gtk.Alignment(xalign = 0.0, yalign = 0.0,
                                   xscale = 1.0, yscale = 1.0)
         alignment.set_padding(padding_top = 4, padding_bottom = 0,
@@ -3642,22 +3649,20 @@
         mainBox.pack_start(self._notamsFrame, True, True, 4)
 
-        self._metarFrame = gtk.Frame()
+        self._metarFrame = Gtk.Frame()
         self._metarFrame.set_label(xstr("briefing_metar_init"))
-        scrolledWindow = gtk.ScrolledWindow()
+        scrolledWindow = Gtk.ScrolledWindow()
         scrolledWindow.set_size_request(-1, 32)
-        scrolledWindow.set_policy(gtk.PolicyType.AUTOMATIC if pygobject
-                                  else gtk.POLICY_AUTOMATIC,
-                                  gtk.PolicyType.AUTOMATIC if pygobject
-                                  else gtk.POLICY_AUTOMATIC)
+        scrolledWindow.set_policy(Gtk.PolicyType.AUTOMATIC,
+                                  Gtk.PolicyType.AUTOMATIC)
 
         self._updatingMETAR = False
 
-        self._metar = gtk.TextView()
+        self._metar = Gtk.TextView()
         self._metar.set_accepts_tab(False)
-        self._metar.set_wrap_mode(gtk.WrapMode.WORD if pygobject else gtk.WRAP_WORD)
+        self._metar.set_wrap_mode(Gtk.WrapMode.WORD)
         self._metar.get_buffer().connect("changed", self._metarChanged)
         self._metar.get_buffer().connect_after("insert-text", self._metarInserted)
         scrolledWindow.add(self._metar)
-        alignment = gtk.Alignment(xalign = 0.0, yalign = 0.0,
+        alignment = Gtk.Alignment(xalign = 0.0, yalign = 0.0,
                                   xscale = 1.0, yscale = 1.0)
         alignment.set_padding(padding_top = 4, padding_bottom = 0,
@@ -3758,5 +3763,5 @@
     def _metarChanged(self, buffer):
         """Called when the METAR has changed."""
-        print "BriefingPage.metarChanged", self._updatingMETAR
+        print("BriefingPage.metarChanged", self._updatingMETAR)
         if not self._updatingMETAR:
             self.metarEdited = True
@@ -3770,5 +3775,5 @@
 
         It uppercases all characters."""
-        print "BriefingPage.metarInserted", self._updatingMETAR
+        print("BriefingPage.metarInserted", self._updatingMETAR)
         if not self._updatingMETAR:
             self._updatingMETAR = True
@@ -3804,8 +3809,8 @@
         self._forwardAllowed = False
 
-        alignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
+        alignment = Gtk.Alignment(xalign = 0.5, yalign = 0.5,
                                   xscale = 0.0, yscale = 0.0)
 
-        table = gtk.Table(9, 24)
+        table = Gtk.Table(9, 24)
         table.set_row_spacings(4)
         table.set_col_spacings(16)
@@ -3816,10 +3821,10 @@
         row = 0
 
-        label = gtk.Label(xstr("takeoff_metar"))
+        label = Gtk.Label(xstr("takeoff_metar"))
         label.set_use_underline(True)
         label.set_alignment(0.0, 0.5)
         table.attach(label, 0, 1, row, row+1)
 
-        self._metar = gtk.Entry()
+        self._metar = Gtk.Entry()
         self._metar.set_width_chars(40)
         self._metar.set_tooltip_text(xstr("takeoff_metar_tooltip"))
@@ -3833,10 +3838,10 @@
         row += 1
 
-        label = gtk.Label(xstr("takeoff_runway"))
+        label = Gtk.Label(xstr("takeoff_runway"))
         label.set_use_underline(True)
         label.set_alignment(0.0, 0.5)
         table.attach(label, 0, 1, row, row+1)
 
-        self._runway = gtk.Entry()
+        self._runway = Gtk.Entry()
         self._runway.set_width_chars(10)
         self._runway.set_tooltip_text(xstr("takeoff_runway_tooltip"))
@@ -3847,13 +3852,10 @@
         row += 1
 
-        label = gtk.Label(xstr("takeoff_sid"))
+        label = Gtk.Label(xstr("takeoff_sid"))
         label.set_use_underline(True)
         label.set_alignment(0.0, 0.5)
         table.attach(label, 0, 1, row, row+1)
 
-        if pygobject:
-            self._sid = gtk.ComboBox.new_with_model_and_entry(comboModel)
-        else:
-            self._sid = gtk.ComboBoxEntry(comboModel)
+        self._sid = Gtk.ComboBox.new_with_model_and_entry(comboModel)
 
         self._sid.set_entry_text_column(0)
@@ -3866,5 +3868,5 @@
         row += 1
 
-        label = gtk.Label(xstr("takeoff_v1"))
+        label = Gtk.Label(xstr("takeoff_v1"))
         label.set_use_markup(True)
         label.set_use_underline(True)
@@ -3879,5 +3881,5 @@
         label.set_mnemonic_widget(self._v1)
 
-        self._v1Unit = gtk.Label(xstr("label_knots"))
+        self._v1Unit = Gtk.Label(xstr("label_knots"))
         self._v1Unit.set_alignment(0.0, 0.5)
         table.attach(self._v1Unit, 3, 4, row, row+1)
@@ -3885,5 +3887,5 @@
         row += 1
 
-        label = gtk.Label(xstr("takeoff_vr"))
+        label = Gtk.Label(xstr("takeoff_vr"))
         label.set_use_markup(True)
         label.set_use_underline(True)
@@ -3898,5 +3900,5 @@
         label.set_mnemonic_widget(self._vr)
 
-        self._vrUnit = gtk.Label(xstr("label_knots"))
+        self._vrUnit = Gtk.Label(xstr("label_knots"))
         self._vrUnit.set_alignment(0.0, 0.5)
         table.attach(self._vrUnit, 3, 4, row, row+1)
@@ -3904,5 +3906,5 @@
         row += 1
 
-        label = gtk.Label(xstr("takeoff_v2"))
+        label = Gtk.Label(xstr("takeoff_v2"))
         label.set_use_markup(True)
         label.set_use_underline(True)
@@ -3917,5 +3919,5 @@
         label.set_mnemonic_widget(self._v2)
 
-        self._v2Unit = gtk.Label(xstr("label_knots"))
+        self._v2Unit = Gtk.Label(xstr("label_knots"))
         self._v2Unit.set_alignment(0.0, 0.5)
         table.attach(self._v2Unit, 3, 4, row, row+1)
@@ -3925,5 +3927,5 @@
         self._derateType = acft.DERATE_NONE
 
-        self._derateLabel = gtk.Label()
+        self._derateLabel = Gtk.Label()
         self._derateLabel.set_use_underline(True)
         self._derateLabel.set_markup(xstr("takeoff_derate_tupolev"))
@@ -3931,5 +3933,5 @@
         table.attach(self._derateLabel, 0, 1, row, row+1)
 
-        self._derate = gtk.Alignment()
+        self._derate = Gtk.Alignment()
         table.attach(self._derate, 2, 4, row, row+1)
         self._derateWidget = None
@@ -3940,5 +3942,5 @@
         row += 1
 
-        self._antiIceOn = gtk.CheckButton(xstr("takeoff_antiice"))
+        self._antiIceOn = Gtk.CheckButton(xstr("takeoff_antiice"))
         self._antiIceOn.set_use_underline(True)
         self._antiIceOn.set_tooltip_text(xstr("takeoff_antiice_tooltip"))
@@ -3947,5 +3949,5 @@
         row += 1
 
-        self._rto = gtk.CheckButton(xstr("takeoff_rto"))
+        self._rto = Gtk.CheckButton(xstr("takeoff_rto"))
         self._rto.set_use_underline(True)
         self._rto.set_tooltip_text(xstr("takeoff_rto_tooltip"))
@@ -4025,5 +4027,5 @@
     def activate(self):
         """Activate the page."""
-        print "TakeoffPage.activate"
+        print("TakeoffPage.activate")
 
         self._updatingMETAR = True
@@ -4069,5 +4071,5 @@
     def allowForward(self):
         """Allow going to the next page."""
-        print "TakeoffPage.allowForward"
+        print("TakeoffPage.allowForward")
         self._forwardAllowed = True
         self._updateForwardButton()
@@ -4075,5 +4077,5 @@
     def reset(self):
         """Reset the page if the wizard is reset."""
-        print "TakeoffPage.reset"
+        print("TakeoffPage.reset")
 
         super(TakeoffPage, self).reset()
@@ -4095,5 +4097,5 @@
         pages."""
         if self._active:
-            print "TakeoffPage.changeMETAR"
+            print("TakeoffPage.changeMETAR")
             self._updatingMETAR = True
             self._metar.get_buffer().set_text(metar, -1)
@@ -4116,14 +4118,14 @@
                      self.derate is not None)
 
-        print "TakeoffPage._updateForwardButton: forwardAllowed:", self._forwardAllowed, ", sensitive:", sensitive
+        print("TakeoffPage._updateForwardButton: forwardAllowed:", self._forwardAllowed, ", sensitive:", sensitive)
         if self._forwardAllowed:
-            print "  METAR: ", self._metar.get_text()
-            print "  runway: ", self._runway.get_text()
-            print "  SID:", self.sid
-            print "  V1:", self.v1
-            print "  VR:", self.vr
-            print "  V2:", self.v2
-            print "  derateType:", self._derateType
-            print "  derate:", self.derate
+            print("  METAR: ", self._metar.get_text())
+            print("  runway: ", self._runway.get_text())
+            print("  SID:", self.sid)
+            print("  V1:", self.v1)
+            print("  VR:", self.vr)
+            print("  V2:", self.v2)
+            print("  derateType:", self._derateType)
+            print("  derate:", self.derate)
 
         self._button.set_sensitive(sensitive)
@@ -4131,5 +4133,5 @@
     def _valueChanged(self, widget, arg = None):
         """Called when the value of some widget has changed."""
-        print "TakeoffPage._valueChanged"
+        print("TakeoffPage._valueChanged")
 
         self._updateForwardButton()
@@ -4138,5 +4140,5 @@
         """Called when the value of some entry widget has changed and the value
         should be converted to uppercase."""
-        print "TakeoffPage._upperChanged"
+        print("TakeoffPage._upperChanged")
         entry.set_text(entry.get_text().upper())
         self._valueChanged(entry, arg)
@@ -4151,5 +4153,5 @@
     def _derateChanged(self, entry):
         """Called when the value of the derate is changed."""
-        print "TakeoffPage._derateChanged"
+        print("TakeoffPage._derateChanged")
         self._updateForwardButton()
 
@@ -4181,5 +4183,5 @@
             self._derateLabel.set_sensitive(True)
 
-            self._derateEntry = gtk.Entry()
+            self._derateEntry = Gtk.Entry()
             self._derateEntry.set_width_chars(7)
             self._derateEntry.set_tooltip_text(xstr("takeoff_derate_boeing_tooltip"))
@@ -4188,8 +4190,8 @@
             self._derateLabel.set_mnemonic_widget(self._derateEntry)
 
-            self._derateUnit = gtk.Label("%")
+            self._derateUnit = Gtk.Label("%")
             self._derateUnit.set_alignment(0.0, 0.5)
 
-            self._derateWidget = gtk.Table(3, 1)
+            self._derateWidget = Gtk.Table(3, 1)
             self._derateWidget.set_row_spacings(4)
             self._derateWidget.set_col_spacings(16)
@@ -4205,5 +4207,5 @@
             self._derateLabel.set_sensitive(True)
 
-            self._derateWidget = gtk.Entry()
+            self._derateWidget = Gtk.Entry()
             self._derateWidget.set_width_chars(7)
             self._derateWidget.set_tooltip_text(xstr("takeoff_derate_epr_tooltip"))
@@ -4218,22 +4220,14 @@
             self._derateLabel.set_sensitive(True)
 
-            if pygobject:
-                nominal = gtk.RadioButton.\
-                  new_with_label_from_widget(None,
-                                             xstr("takeoff_derate_tupolev_nominal"))
-            else:
-                nominal = gtk.RadioButton(None,
-                                          xstr("takeoff_derate_tupolev_nominal"))
+            nominal = Gtk.RadioButton.\
+                new_with_label_from_widget(None,
+                                           xstr("takeoff_derate_tupolev_nominal"))
             nominal.set_use_underline(True)
             nominal.set_tooltip_text(xstr("takeoff_derate_tupolev_nominal_tooltip"))
             nominal.connect("toggled", self._derateChanged)
 
-            if pygobject:
-                takeoff = gtk.RadioButton.\
-                  new_with_label_from_widget(nominal,
-                                             xstr("takeoff_derate_tupolev_takeoff"))
-            else:
-                takeoff = gtk.RadioButton(nominal,
-                                          xstr("takeoff_derate_tupolev_takeoff"))
+            takeoff = Gtk.RadioButton.\
+                new_with_label_from_widget(nominal,
+                                           xstr("takeoff_derate_tupolev_takeoff"))
 
             takeoff.set_use_underline(True)
@@ -4243,5 +4237,5 @@
             self._derateButtons = [nominal, takeoff]
 
-            self._derateWidget = gtk.HBox()
+            self._derateWidget = Gtk.HBox()
             self._derateWidget.pack_start(nominal, False, False, 4)
             self._derateWidget.pack_start(takeoff, False, False, 4)
@@ -4251,5 +4245,5 @@
             self._derateLabel.set_text("")
 
-            self._derateWidget = gtk.CheckButton(xstr("takeoff_derate_b462"))
+            self._derateWidget = Gtk.CheckButton(xstr("takeoff_derate_b462"))
             self._derateWidget.set_tooltip_text(xstr("takeoff_derate_b462_tooltip"))
             self._derateWidget.set_use_underline(True)
@@ -4262,5 +4256,5 @@
     def _metarChanged(self, entry):
         """Called when the METAR has changed."""
-        print "TakeoffPage.metarChanged", self._updatingMETAR
+        print("TakeoffPage.metarChanged", self._updatingMETAR)
         if not self._updatingMETAR:
             self._updateForwardButton()
@@ -4271,5 +4265,5 @@
 
         It uppercases all characters."""
-        print "TakeoffPage.metarInserted", self._updatingMETAR
+        print("TakeoffPage.metarInserted", self._updatingMETAR)
         if not self._updatingMETAR:
             self._updatingMETAR = True
@@ -4294,22 +4288,22 @@
         self._activated = False
 
-        alignment = gtk.Alignment(xalign = 0.5, yalign = 0.0,
+        alignment = Gtk.Alignment(xalign = 0.5, yalign = 0.0,
                                   xscale = 0.0, yscale = 1.0)
 
-        mainBox = gtk.VBox()
+        mainBox = Gtk.VBox()
         alignment.add(mainBox)
         self.setMainWidget(alignment)
 
-        alignment = gtk.Alignment(xalign = 0.0, yalign = 0.0,
+        alignment = Gtk.Alignment(xalign = 0.0, yalign = 0.0,
                                   xscale = 0.0, yscale = 0.0)
         mainBox.pack_start(alignment, False, False, 16)
 
-        levelBox = gtk.HBox()
-
-        label = gtk.Label(xstr("route_level"))
+        levelBox = Gtk.HBox()
+
+        label = Gtk.Label(xstr("route_level"))
         label.set_use_underline(True)
         levelBox.pack_start(label, True, True, 0)
 
-        self._cruiseLevel = gtk.SpinButton()
+        self._cruiseLevel = Gtk.SpinButton()
         self._cruiseLevel.set_increments(step = 10, page = 100)
         self._cruiseLevel.set_range(min = 50, max = 500)
@@ -4321,5 +4315,5 @@
         levelBox.pack_start(self._cruiseLevel, False, False, 8)
 
-        self._updateButton = gtk.Button(xstr("cruise_route_level_update"));
+        self._updateButton = Gtk.Button(xstr("cruise_route_level_update"));
         self._updateButton.set_use_underline(True)
         self._updateButton.set_tooltip_text(xstr("cruise_route_level_update_tooltip"))
@@ -4330,5 +4324,5 @@
         mainBox.pack_start(levelBox, False, False, 0)
 
-        alignment = gtk.Alignment(xalign = 0.0, yalign = 0.0,
+        alignment = Gtk.Alignment(xalign = 0.0, yalign = 0.0,
                                   xscale = 0.0, yscale = 1.0)
         mainBox.pack_start(alignment, True, True, 0)
@@ -4408,8 +4402,8 @@
         self._flightEnded = False
 
-        alignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
+        alignment = Gtk.Alignment(xalign = 0.5, yalign = 0.5,
                                   xscale = 0.0, yscale = 0.0)
 
-        table = gtk.Table(7, 24)
+        table = Gtk.Table(7, 24)
         table.set_row_spacings(4)
         table.set_col_spacings(16)
@@ -4420,10 +4414,10 @@
         row = 0
 
-        label = gtk.Label(xstr("landing_metar"))
+        label = Gtk.Label(xstr("landing_metar"))
         label.set_use_underline(True)
         label.set_alignment(0.0, 0.5)
         table.attach(label, 1, 2, row, row+1)
 
-        self._metar = gtk.Entry()
+        self._metar = Gtk.Entry()
         self._metar.set_width_chars(40)
         self._metar.set_tooltip_text(xstr("landing_metar_tooltip"))
@@ -4437,13 +4431,10 @@
         row += 1
 
-        label = gtk.Label(xstr("landing_star"))
+        label = Gtk.Label(xstr("landing_star"))
         label.set_use_underline(True)
         label.set_alignment(0.0, 0.5)
         table.attach(label, 1, 2, row, row + 1)
 
-        if pygobject:
-            self._star = gtk.ComboBox.new_with_model_and_entry(comboModel)
-        else:
-            self._star = gtk.ComboBoxEntry(comboModel)
+        self._star = Gtk.ComboBox.new_with_model_and_entry(comboModel)
 
         self._star.set_entry_text_column(0)
@@ -4457,13 +4448,10 @@
         row += 1
 
-        label = gtk.Label(xstr("landing_transition"))
+        label = Gtk.Label(xstr("landing_transition"))
         label.set_use_underline(True)
         label.set_alignment(0.0, 0.5)
         table.attach(label, 1, 2, row, row + 1)
 
-        if pygobject:
-            self._transition = gtk.ComboBox.new_with_model_and_entry(comboModel)
-        else:
-            self._transition = gtk.ComboBoxEntry(comboModel)
+        self._transition = Gtk.ComboBox.new_with_model_and_entry(comboModel)
 
         self._transition.set_entry_text_column(0)
@@ -4477,10 +4465,10 @@
         row += 1
 
-        label = gtk.Label(xstr("landing_runway"))
+        label = Gtk.Label(xstr("landing_runway"))
         label.set_use_underline(True)
         label.set_alignment(0.0, 0.5)
         table.attach(label, 1, 2, row, row + 1)
 
-        self._runway = gtk.Entry()
+        self._runway = Gtk.Entry()
         self._runway.set_width_chars(10)
         self._runway.set_tooltip_text(xstr("landing_runway_tooltip"))
@@ -4491,10 +4479,10 @@
         row += 1
 
-        label = gtk.Label(xstr("landing_approach"))
+        label = Gtk.Label(xstr("landing_approach"))
         label.set_use_underline(True)
         label.set_alignment(0.0, 0.5)
         table.attach(label, 1, 2, row, row + 1)
 
-        self._approachType = gtk.Entry()
+        self._approachType = Gtk.Entry()
         self._approachType.set_width_chars(10)
         self._approachType.set_tooltip_text(xstr("landing_approach_tooltip"))
@@ -4505,5 +4493,5 @@
         row += 1
 
-        label = gtk.Label(xstr("landing_vref"))
+        label = Gtk.Label(xstr("landing_vref"))
         label.set_use_markup(True)
         label.set_use_underline(True)
@@ -4518,10 +4506,10 @@
         label.set_mnemonic_widget(self._vref)
 
-        self._vrefUnit = gtk.Label(xstr("label_knots"))
+        self._vrefUnit = Gtk.Label(xstr("label_knots"))
         table.attach(self._vrefUnit, 4, 5, row, row + 1)
 
         row += 1
 
-        self._antiIceOn = gtk.CheckButton(xstr("landing_antiice"))
+        self._antiIceOn = Gtk.CheckButton(xstr("landing_antiice"))
         self._antiIceOn.set_use_underline(True)
         self._antiIceOn.set_tooltip_text(xstr("landing_antiice_tooltip"))
@@ -4628,5 +4616,5 @@
         pages."""
         if self._active:
-            print "LandingPage.changeMETAR"
+            print("LandingPage.changeMETAR")
             self._updatingMETAR = True
             self._metar.get_buffer().set_text(metar, -1)
@@ -4689,5 +4677,5 @@
     def _metarChanged(self, entry):
         """Called when the METAR has changed."""
-        print "LandingPage.metarChanged", self._updatingMETAR
+        print("LandingPage.metarChanged", self._updatingMETAR)
         if not self._updatingMETAR:
             self._updateForwardButton()
@@ -4698,5 +4686,5 @@
 
         It uppercases all characters."""
-        print "LandingPage.metarInserted", self._updatingMETAR
+        print("LandingPage.metarInserted", self._updatingMETAR)
         if not self._updatingMETAR:
             self._updatingMETAR = True
@@ -4740,5 +4728,5 @@
         self._lastSavePath = os.path.join(self._wizard.gui.config.pirepDirectory,
                                           self._getDefaultPIREPName())
-        self._lastSavePath = text2unicode(self._lastSavePath)
+        self._lastSavePath = self._lastSavePath
         self._savePIREP(page, automatic = True)
 
@@ -4776,6 +4764,6 @@
         dialog.hide()
 
-        if result==RESPONSETYPE_OK:
-            self._lastSavePath = text2unicode(dialog.get_filename())
+        if result==Gtk.ResponseType.OK:
+            self._lastSavePath = dialog.get_filename()
             self._savePIREP(page)
 
@@ -4795,9 +4783,9 @@
 
         if error:
-            type = MESSAGETYPE_ERROR
+            type = Gtk.MessageType.ERROR
             message = xstr("finish_save_failed")
-            secondary = xstr("finish_save_failed_sec") % (text2unicode(error),)
+            secondary = xstr("finish_save_failed_sec") % (error,)
         else:
-            type = MESSAGETYPE_INFO
+            type = Gtk.MessageType.INFO
             message = xstr("finish_save_done")
             if automatic:
@@ -4807,7 +4795,7 @@
             page.setPIREPSaved()
 
-        dialog = gtk.MessageDialog(parent = gui.mainWindow,
+        dialog = Gtk.MessageDialog(parent = gui.mainWindow,
                                    type = type, message_format = message)
-        dialog.add_button(xstr("button_ok"), RESPONSETYPE_OK)
+        dialog.add_button(xstr("button_ok"), Gtk.ResponseType.OK)
         dialog.set_title(WINDOW_TITLE_BASE)
         if secondary is not None:
@@ -4823,20 +4811,20 @@
         if self._savePIREPDialog is None:
             gui = self._wizard.gui
-            dialog = gtk.FileChooserDialog(title = WINDOW_TITLE_BASE + " - " +
+            dialog = Gtk.FileChooserDialog(title = WINDOW_TITLE_BASE + " - " +
                                            xstr("finish_save_title"),
-                                           action = FILE_CHOOSER_ACTION_SAVE,
-                                           buttons = (gtk.STOCK_CANCEL,
-                                                      RESPONSETYPE_CANCEL,
-                                                      gtk.STOCK_OK, RESPONSETYPE_OK),
+                                           action = Gtk.FileChooserAction.SAVE,
+                                           buttons = (Gtk.STOCK_CANCEL,
+                                                      Gtk.ResponseType.CANCEL,
+                                                      Gtk.STOCK_OK, Gtk.ResponseType.OK),
                                            parent = gui.mainWindow)
             dialog.set_modal(True)
             dialog.set_do_overwrite_confirmation(True)
 
-            filter = gtk.FileFilter()
+            filter = Gtk.FileFilter()
             filter.set_name(xstr("file_filter_pireps"))
             filter.add_pattern("*.pirep")
             dialog.add_filter(filter)
 
-            filter = gtk.FileFilter()
+            filter = Gtk.FileFilter()
             filter.set_name(xstr("file_filter_all"))
             filter.add_pattern("*.*")
@@ -4857,8 +4845,8 @@
                                          xstr("finish_title"), help)
 
-        alignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
+        alignment = Gtk.Alignment(xalign = 0.5, yalign = 0.5,
                                   xscale = 0.0, yscale = 0.0)
 
-        table = gtk.Table(10, 2)
+        table = Gtk.Table(10, 2)
         table.set_row_spacings(4)
         table.set_col_spacings(16)
@@ -4869,11 +4857,11 @@
         row = 0
 
-        labelAlignment = gtk.Alignment(xalign=1.0, xscale=0.0)
-        label = gtk.Label(xstr("finish_rating"))
+        labelAlignment = Gtk.Alignment(xalign=1.0, xscale=0.0)
+        label = Gtk.Label(xstr("finish_rating"))
         labelAlignment.add(label)
         table.attach(labelAlignment, 0, 1, row, row+1)
 
-        labelAlignment = gtk.Alignment(xalign=0.0, xscale=0.0)
-        self._flightRating = gtk.Label()
+        labelAlignment = Gtk.Alignment(xalign=0.0, xscale=0.0)
+        self._flightRating = Gtk.Label()
         self._flightRating.set_width_chars(8)
         self._flightRating.set_alignment(0.0, 0.5)
@@ -4884,11 +4872,11 @@
         row += 1
 
-        labelAlignment = gtk.Alignment(xalign=1.0, xscale=0.0)
-        label = gtk.Label(xstr("finish_dep_time"))
+        labelAlignment = Gtk.Alignment(xalign=1.0, xscale=0.0)
+        label = Gtk.Label(xstr("finish_dep_time"))
         labelAlignment.add(label)
         table.attach(labelAlignment, 0, 1, row, row+1)
 
-        labelAlignment = gtk.Alignment(xalign=0.0, xscale=0.0)
-        self._depTime = gtk.Label()
+        labelAlignment = Gtk.Alignment(xalign=0.0, xscale=0.0)
+        self._depTime = Gtk.Label()
         self._depTime.set_width_chars(13)
         self._depTime.set_alignment(0.0, 0.5)
@@ -4900,11 +4888,11 @@
         row += 1
 
-        labelAlignment = gtk.Alignment(xalign=1.0, xscale=0.0)
-        label = gtk.Label(xstr("finish_flight_time"))
+        labelAlignment = Gtk.Alignment(xalign=1.0, xscale=0.0)
+        label = Gtk.Label(xstr("finish_flight_time"))
         labelAlignment.add(label)
         table.attach(labelAlignment, 0, 1, row, row+1)
 
-        labelAlignment = gtk.Alignment(xalign=0.0, xscale=0.0)
-        self._flightTime = gtk.Label()
+        labelAlignment = Gtk.Alignment(xalign=0.0, xscale=0.0)
+        self._flightTime = Gtk.Label()
         self._flightTime.set_width_chars(10)
         self._flightTime.set_alignment(0.0, 0.5)
@@ -4915,11 +4903,11 @@
         row += 1
 
-        labelAlignment = gtk.Alignment(xalign=1.0, xscale=0.0)
-        label = gtk.Label(xstr("finish_block_time"))
+        labelAlignment = Gtk.Alignment(xalign=1.0, xscale=0.0)
+        label = Gtk.Label(xstr("finish_block_time"))
         labelAlignment.add(label)
         table.attach(labelAlignment, 0, 1, row, row+1)
 
-        labelAlignment = gtk.Alignment(xalign=0.0, xscale=0.0)
-        self._blockTime = gtk.Label()
+        labelAlignment = Gtk.Alignment(xalign=0.0, xscale=0.0)
+        self._blockTime = Gtk.Label()
         self._blockTime.set_width_chars(10)
         self._blockTime.set_alignment(0.0, 0.5)
@@ -4930,11 +4918,11 @@
         row += 1
 
-        labelAlignment = gtk.Alignment(xalign=1.0, xscale=0.0)
-        label = gtk.Label(xstr("finish_arr_time"))
+        labelAlignment = Gtk.Alignment(xalign=1.0, xscale=0.0)
+        label = Gtk.Label(xstr("finish_arr_time"))
         labelAlignment.add(label)
         table.attach(labelAlignment, 0, 1, row, row+1)
 
-        labelAlignment = gtk.Alignment(xalign=0.0, xscale=0.0)
-        self._arrTime = gtk.Label()
+        labelAlignment = Gtk.Alignment(xalign=0.0, xscale=0.0)
+        self._arrTime = Gtk.Label()
         self._arrTime.set_width_chars(13)
         self._arrTime.set_alignment(0.0, 0.5)
@@ -4946,11 +4934,11 @@
         row += 1
 
-        labelAlignment = gtk.Alignment(xalign=1.0, xscale=0.0)
-        label = gtk.Label(xstr("finish_distance"))
+        labelAlignment = Gtk.Alignment(xalign=1.0, xscale=0.0)
+        label = Gtk.Label(xstr("finish_distance"))
         labelAlignment.add(label)
         table.attach(labelAlignment, 0, 1, row, row+1)
 
-        labelAlignment = gtk.Alignment(xalign=0.0, xscale=0.0)
-        self._distanceFlown = gtk.Label()
+        labelAlignment = Gtk.Alignment(xalign=0.0, xscale=0.0)
+        self._distanceFlown = Gtk.Label()
         self._distanceFlown.set_width_chars(10)
         self._distanceFlown.set_alignment(0.0, 0.5)
@@ -4961,11 +4949,11 @@
         row += 1
 
-        labelAlignment = gtk.Alignment(xalign=1.0, xscale=0.0)
-        label = gtk.Label(xstr("finish_fuel"))
+        labelAlignment = Gtk.Alignment(xalign=1.0, xscale=0.0)
+        label = Gtk.Label(xstr("finish_fuel"))
         labelAlignment.add(label)
         table.attach(labelAlignment, 0, 1, row, row+1)
 
-        labelAlignment = gtk.Alignment(xalign=0.0, xscale=0.0)
-        self._fuelUsed = gtk.Label()
+        labelAlignment = Gtk.Alignment(xalign=0.0, xscale=0.0)
+        self._fuelUsed = Gtk.Label()
         self._fuelUsed.set_width_chars(10)
         self._fuelUsed.set_alignment(0.0, 0.5)
@@ -4976,7 +4964,7 @@
         row += 1
 
-        labelAlignment = gtk.Alignment(xalign = 1.0, xscale = 0.0,
+        labelAlignment = Gtk.Alignment(xalign = 1.0, xscale = 0.0,
                                        yalign = 0.5, yscale = 0.0)
-        label = gtk.Label(xstr("finish_type"))
+        label = Gtk.Label(xstr("finish_type"))
         label.set_use_underline(True)
         labelAlignment.add(label)
@@ -4987,5 +4975,5 @@
         self._flightType.set_active(0)
         self._flightType.connect("changed", self._flightTypeChanged)
-        flightTypeAlignment = gtk.Alignment(xalign=0.0, xscale=0.0)
+        flightTypeAlignment = Gtk.Alignment(xalign=0.0, xscale=0.0)
         flightTypeAlignment.add(self._flightType)
         table.attach(flightTypeAlignment, 1, 2, row, row+1)
@@ -4994,8 +4982,8 @@
         row += 1
 
-        self._onlineFlight = gtk.CheckButton(xstr("finish_online"))
+        self._onlineFlight = Gtk.CheckButton(xstr("finish_online"))
         self._onlineFlight.set_use_underline(True)
         self._onlineFlight.set_tooltip_text(xstr("finish_online_tooltip"))
-        onlineFlightAlignment = gtk.Alignment(xalign=0.0, xscale=0.0)
+        onlineFlightAlignment = Gtk.Alignment(xalign=0.0, xscale=0.0)
         onlineFlightAlignment.add(self._onlineFlight)
         table.attach(onlineFlightAlignment, 1, 2, row, row + 1)
@@ -5003,20 +4991,20 @@
         row += 1
 
-        labelAlignment = gtk.Alignment(xalign = 1.0, xscale = 0.0,
+        labelAlignment = Gtk.Alignment(xalign = 1.0, xscale = 0.0,
                                        yalign = 0.5, yscale = 0.0)
-        self._gateLabel = gtk.Label(xstr("finish_gate"))
+        self._gateLabel = Gtk.Label(xstr("finish_gate"))
         self._gateLabel.set_use_underline(True)
         labelAlignment.add(self._gateLabel)
         table.attach(labelAlignment, 0, 1, row, row+1)
 
-        self._gatesModel = gtk.ListStore(str)
-
-        self._gate = gtk.ComboBox(model = self._gatesModel)
-        renderer = gtk.CellRendererText()
+        self._gatesModel = Gtk.ListStore(str)
+
+        self._gate = Gtk.ComboBox(model = self._gatesModel)
+        renderer = Gtk.CellRendererText()
         self._gate.pack_start(renderer, True)
         self._gate.add_attribute(renderer, "text", 0)
         self._gate.set_tooltip_text(xstr("finish_gate_tooltip"))
         self._gate.connect("changed", self._gateChanged)
-        gateAlignment = gtk.Alignment(xalign=0.0, xscale=1.0)
+        gateAlignment = Gtk.Alignment(xalign=0.0, xscale=1.0)
         gateAlignment.add(self._gate)
         table.attach(gateAlignment, 1, 2, row, row+1)
@@ -5170,15 +5158,15 @@
         gui = self._wizard.gui
         if not self._pirepSent and not self._pirepSaved:
-            dialog = gtk.MessageDialog(parent = gui.mainWindow,
-                                       type = MESSAGETYPE_QUESTION,
+            dialog = Gtk.MessageDialog(parent = gui.mainWindow,
+                                       type = Gtk.MessageType.QUESTION,
                                        message_format = xstr("finish_newFlight_question"))
 
-            dialog.add_button(xstr("button_no"), RESPONSETYPE_NO)
-            dialog.add_button(xstr("button_yes"), RESPONSETYPE_YES)
+            dialog.add_button(xstr("button_no"), Gtk.ResponseType.NO)
+            dialog.add_button(xstr("button_yes"), Gtk.ResponseType.YES)
 
             dialog.set_title(WINDOW_TITLE_BASE)
             result = dialog.run()
             dialog.hide()
-            if result!=RESPONSETYPE_YES:
+            if result!=Gtk.ResponseType.YES:
                 return
 
@@ -5217,7 +5205,8 @@
         pass
 
-    def _formatTime(self, scheduledTime, realTimestamp, (warning, error)):
+    def _formatTime(self, scheduledTime, realTimestamp, warningError):
         """Format the departure or arrival time based on the given data as a
         markup for a label."""
+        (warning, error) = warningError
         realTime = time.gmtime(realTimestamp)
 
@@ -5287,7 +5276,7 @@
                                                     "")
 
-        alignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
+        alignment = Gtk.Alignment(xalign = 0.5, yalign = 0.5,
                                   xscale = 1.0, yscale = 1.0)
-        self._label = gtk.Label()
+        self._label = Gtk.Label()
         alignment.add(self._label)
 
@@ -5364,5 +5353,5 @@
     def _checkFlightPassedSetCallback(self, returned, result):
         """Called when the check flight status has been set."""
-        gobject.idle_add(self._checkFlightPassedSet, returned, result)
+        GObject.idle_add(self._checkFlightPassedSet, returned, result)
 
     def _checkFlightPassedSet(self, returned, result):
@@ -5375,6 +5364,6 @@
             self._resetGUI()
         else:
-            dialog = gtk.MessageDialog(parent = gui.mainWindow,
-                                       type = MESSAGETYPE_ERROR,
+            dialog = Gtk.MessageDialog(parent = gui.mainWindow,
+                                       type = Gtk.MessageType.ERROR,
                                        message_format =
                                        xstr("chkfinish_passedset_failed"))
@@ -5395,5 +5384,5 @@
 #-----------------------------------------------------------------------------
 
-class Wizard(gtk.VBox):
+class Wizard(Gtk.VBox):
     """The flight wizard."""
     def __init__(self, gui):
@@ -5454,4 +5443,5 @@
 
         self._initialize()
+        self._allocateSize()
 
     def _sizeAllocate(self, widget, allocation):
@@ -5459,4 +5449,12 @@
            self._requestedHeight is not None:
            return
+
+        (maxWidth, maxHeight) = self._allocateSize()
+
+        self._requestedWidth = maxWidth
+        self._requestedHeight = maxHeight
+
+    def _allocateSize(self):
+        """Perform the real size allocation."""
 
         if self._currentPage is not None:
@@ -5469,6 +5467,6 @@
             self.show_all()
             pageSizeRequest = page.size_request()
-            width = pageSizeRequest.width if pygobject else pageSizeRequest[0]
-            height = pageSizeRequest.height if pygobject else pageSizeRequest[1]
+            width = pageSizeRequest.width
+            height = pageSizeRequest.height
             maxWidth = max(maxWidth, width)
             maxHeight = max(maxHeight, height)
@@ -5478,7 +5476,7 @@
             self.add(self._pages[self._currentPage])
 
-        self._requestedWidth = maxWidth
-        self._requestedHeight = maxHeight
         self.set_size_request(maxWidth, maxHeight)
+
+        return (maxWidth, maxHeight)
 
     @property
@@ -5752,5 +5750,5 @@
         elif stage==const.STAGE_LANDING:
             if not self._arrivalBriefingPage.metarEdited:
-                print "Downloading arrival METAR again"
+                print("Downloading arrival METAR again")
                 self.gui.webHandler.getMETARs(self._arrivalMETARCallback,
                                               [self._bookedFlight.arrivalICAO])
@@ -5881,5 +5879,5 @@
     def _loginResultCallback(self, returned, result):
         """The login result callback, called in the web handler's thread."""
-        gobject.idle_add(self._handleLoginResult, returned, result)
+        GObject.idle_add(self._handleLoginResult, returned, result)
 
     def _handleLoginResult(self, returned, result):
@@ -5898,8 +5896,8 @@
                                    if self.entranceExam else
                                    xstr("login_invalid"))
-                dialog = gtk.MessageDialog(parent = self.gui.mainWindow,
-                                           type = MESSAGETYPE_ERROR,
+                dialog = Gtk.MessageDialog(parent = self.gui.mainWindow,
+                                           type = Gtk.MessageType.ERROR,
                                            message_format = message)
-                dialog.add_button(xstr("button_ok"), RESPONSETYPE_OK)
+                dialog.add_button(xstr("button_ok"), Gtk.ResponseType.OK)
                 dialog.set_title(WINDOW_TITLE_BASE)
                 if isReload:
@@ -5915,8 +5913,8 @@
             message = xstr("reload_failconn") if isReload \
                       else xstr("login_failconn")
-            dialog = gtk.MessageDialog(parent = self.gui.mainWindow,
-                                       type = MESSAGETYPE_ERROR,
+            dialog = Gtk.MessageDialog(parent = self.gui.mainWindow,
+                                       type = Gtk.MessageType.ERROR,
                                        message_format = message)
-            dialog.add_button(xstr("button_ok"), RESPONSETYPE_OK)
+            dialog.add_button(xstr("button_ok"), Gtk.ResponseType.OK)
             dialog.set_title(WINDOW_TITLE_BASE)
             secondary = xstr("reload_failconn_sec") if isReload \
@@ -5981,5 +5979,5 @@
     def _arrivalMETARCallback(self, returned, result):
         """Called when the METAR of the arrival airport is retrieved."""
-        gobject.idle_add(self._handleArrivalMETAR, returned, result)
+        GObject.idle_add(self._handleArrivalMETAR, returned, result)
 
     def _handleArrivalMETAR(self, returned, result):
Index: src/mlx/gui/flightlist.py
===================================================================
--- src/mlx/gui/flightlist.py	(revision 868)
+++ src/mlx/gui/flightlist.py	(revision 999)
@@ -22,5 +22,5 @@
         self._convertFn = convertFn
         self._renderer = \
-          gtk.CellRendererText() if renderer is None else renderer
+          Gtk.CellRendererText() if renderer is None else renderer
         self._extraColumnAttributes = extraColumnAttributes
         self._sortable = sortable
@@ -47,12 +47,12 @@
 
         @param index is the 0-based index of the column."""
-        if isinstance(self._renderer, gtk.CellRendererText):
-            column = gtk.TreeViewColumn(self._heading, self._renderer,
+        if isinstance(self._renderer, Gtk.CellRendererText):
+            column = Gtk.TreeViewColumn(self._heading, self._renderer,
                                         text = index)
-        elif isinstance(self._renderer, gtk.CellRendererToggle):
-            column = gtk.TreeViewColumn(self._heading, self._renderer,
+        elif isinstance(self._renderer, Gtk.CellRendererToggle):
+            column = Gtk.TreeViewColumn(self._heading, self._renderer,
                                         active = index)
         else:
-            column = gtk.TreeViewColumn(self._heading, self._renderer)
+            column = Gtk.TreeViewColumn(self._heading, self._renderer)
         column.set_expand(True)
         if self._sortable:
@@ -61,5 +61,5 @@
 
         if self._extraColumnAttributes is not None:
-            for (key, value) in self._extraColumnAttributes.iteritems():
+            for (key, value) in self._extraColumnAttributes.items():
                 if key=="alignment":
                     self._renderer.set_alignment(value, 0.5)
@@ -83,5 +83,5 @@
 #-----------------------------------------------------------------------------
 
-class FlightList(gtk.Alignment):
+class FlightList(Gtk.Alignment):
     """Construct the flight list.
 
@@ -114,13 +114,13 @@
             columnDescriptor.appendType(types)
 
-        self._model = gtk.ListStore(*types)
+        self._model = Gtk.ListStore(*types)
         if defaultSortableIndex is not None:
-            sortOrder = SORT_DESCENDING \
+            sortOrder = Gtk.SortType.DESCENDING \
               if self._columnDescriptors[defaultSortableIndex-1]._defaultDescending \
-              else SORT_ASCENDING
+              else Gtk.SortType.ASCENDING
             self._model.set_sort_column_id(defaultSortableIndex, sortOrder)
-        self._view = gtk.TreeView(self._model)
-
-        flightIndexColumn = gtk.TreeViewColumn()
+        self._view = Gtk.TreeView(self._model)
+
+        flightIndexColumn = Gtk.TreeViewColumn()
         flightIndexColumn.set_visible(False)
         self._view.append_column(flightIndexColumn)
@@ -138,17 +138,14 @@
         selection.connect("changed", self._selectionChanged)
         if multiSelection:
-            selection.set_mode(SELECTION_MULTIPLE)
-
-        scrolledWindow = gtk.ScrolledWindow()
+            selection.set_mode(Gtk.SelectionMode.MULTIPLE)
+
+        scrolledWindow = Gtk.ScrolledWindow()
         scrolledWindow.add(self._view)
         if widthRequest is not None:
             scrolledWindow.set_size_request(widthRequest, -1)
         # FIXME: these should be constants in common.py
-        scrolledWindow.set_policy(gtk.PolicyType.AUTOMATIC if pygobject
-                                  else gtk.POLICY_AUTOMATIC,
-                                  gtk.PolicyType.AUTOMATIC if pygobject
-                                  else gtk.POLICY_AUTOMATIC)
-        scrolledWindow.set_shadow_type(gtk.ShadowType.IN if pygobject
-                                       else gtk.SHADOW_IN)
+        scrolledWindow.set_policy(Gtk.PolicyType.AUTOMATIC,
+                                  Gtk.PolicyType.AUTOMATIC)
+        scrolledWindow.set_shadow_type(Gtk.ShadowType.IN)
 
         super(FlightList, self).__init__(xalign = 0.5, yalign = 0.0,
@@ -171,5 +168,5 @@
     def hasFlights(self):
         """Determine if there are any flights in the list."""
-        return self._model.get_iter_root() is not None
+        return self._model.get_iter_first() is not None
 
     def clear(self):
@@ -209,5 +206,5 @@
     def _buttonPressEvent(self, widget, event):
         """Called when a mouse button is pressed or released."""
-        if event.type!=EVENT_BUTTON_PRESS or event.button!=3 or \
+        if event.type!=Gdk.EventType.BUTTON_PRESS or event.button!=3 or \
            self._popupMenuProducer is None:
             return
@@ -222,8 +219,5 @@
             self._popupMenu = self._popupMenuProducer()
         menu = self._popupMenu
-        if pygobject:
-            menu.popup(None, None, None, None, event.button, event.time)
-        else:
-            menu.popup(None, None, None, event.button, event.time)
+        menu.popup(None, None, None, None, event.button, event.time)
 
     def _selectionChanged(self, selection):
@@ -233,13 +227,13 @@
 #-------------------------------------------------------------------------------
 
-gobject.signal_new("row-activated", FlightList, gobject.SIGNAL_RUN_FIRST,
+GObject.signal_new("row-activated", FlightList, GObject.SIGNAL_RUN_FIRST,
                    None, (int,))
 
-gobject.signal_new("selection-changed", FlightList, gobject.SIGNAL_RUN_FIRST,
+GObject.signal_new("selection-changed", FlightList, GObject.SIGNAL_RUN_FIRST,
                    None, (object,))
 
 #-----------------------------------------------------------------------------
 
-class PendingFlightsFrame(gtk.Frame):
+class PendingFlightsFrame(Gtk.Frame):
     """A frame for a list of pending (reported or rejected) flights.
 
@@ -271,5 +265,6 @@
     def __init__(self, which, wizard, window, pirepEditable = False):
         """Construct the frame with the given title."""
-        super(PendingFlightsFrame, self).__init__(xstr("pendflt_title_" + which))
+        super(PendingFlightsFrame, self).__init__()
+        self.set_label(xstr("pendflt_title_" + which))
 
         self._which = which
@@ -278,9 +273,9 @@
         self._pirepEditable = pirepEditable
 
-        alignment = gtk.Alignment(xscale = 1.0, yscale = 1.0)
+        alignment = Gtk.Alignment(xscale = 1.0, yscale = 1.0)
         alignment.set_padding(padding_top = 2, padding_bottom = 8,
                               padding_left = 4, padding_right = 4)
 
-        hbox = gtk.HBox()
+        hbox = Gtk.HBox()
 
         self._flights = []
@@ -294,7 +289,7 @@
         hbox.pack_start(self._flightList, True, True, 4)
 
-        buttonBox = gtk.VBox()
-
-        self._editButton = gtk.Button(xstr("pendflt_" +
+        buttonBox = Gtk.VBox()
+
+        self._editButton = Gtk.Button(xstr("pendflt_" +
                                            ("edit" if pirepEditable else
                                             "view") + "_" + which))
@@ -304,5 +299,5 @@
         buttonBox.pack_start(self._editButton, False, False, 2)
 
-        self._reflyButton = gtk.Button(xstr("pendflt_refly_" + which))
+        self._reflyButton = Gtk.Button(xstr("pendflt_refly_" + which))
         self._reflyButton.set_sensitive(False)
         self._reflyButton.set_use_underline(True)
@@ -310,5 +305,5 @@
         buttonBox.pack_start(self._reflyButton, False, False, 2)
 
-        self._deleteButton = gtk.Button(xstr("pendflt_delete_" + which))
+        self._deleteButton = Gtk.Button(xstr("pendflt_delete_" + which))
         self._deleteButton.set_sensitive(False)
         self._deleteButton.set_use_underline(True)
@@ -360,5 +355,5 @@
     def _pirepResultCallback(self, returned, result):
         """Called when the PIREP query result is available."""
-        gobject.idle_add(self._handlePIREPResult, returned, result)
+        GObject.idle_add(self._handlePIREPResult, returned, result)
 
     def _handlePIREPResult(self, returned, result):
@@ -392,5 +387,5 @@
     def _reflyResultCallback(self, returned, result):
         """Called when the refly result is available."""
-        gobject.idle_add(self._handleReflyResult, returned, result)
+        GObject.idle_add(self._handleReflyResult, returned, result)
 
     def _handleReflyResult(self, returned, result):
@@ -401,5 +396,5 @@
         gui.endBusy()
 
-        print "PendingFlightsFrame._handleReflyResult", returned, result
+        print("PendingFlightsFrame._handleReflyResult", returned, result)
 
         if returned:
@@ -435,5 +430,5 @@
     def _deleteResultCallback(self, returned, result):
         """Called when the deletion result is available."""
-        gobject.idle_add(self._handleDeleteResult, returned, result)
+        GObject.idle_add(self._handleDeleteResult, returned, result)
 
     def _handleDeleteResult(self, returned, result):
@@ -444,5 +439,5 @@
         gui.endBusy()
 
-        print "PendingFlightsFrame._handleDeleteResult", returned, result
+        print("PendingFlightsFrame._handleDeleteResult", returned, result)
 
         if returned:
@@ -463,7 +458,7 @@
     def _producePopupMenu(self):
         """Create the popup menu for the flights."""
-        menu = gtk.Menu()
-
-        menuItem = gtk.MenuItem()
+        menu = Gtk.Menu()
+
+        menuItem = Gtk.MenuItem()
         menuItem.set_label(xstr("pendflt_" +
                                 ("edit" if self._pirepEditable else "view") +
@@ -475,5 +470,5 @@
         menu.append(menuItem)
 
-        menuItem = gtk.MenuItem()
+        menuItem = Gtk.MenuItem()
         menuItem.set_label(xstr("pendflt_refly_" + self._which))
         menuItem.set_use_underline(True)
@@ -483,5 +478,5 @@
         menu.append(menuItem)
 
-        menuItem = gtk.MenuItem()
+        menuItem = Gtk.MenuItem()
         menuItem.set_label(xstr("pendflt_delete_" + self._which))
         menuItem.set_use_underline(True)
@@ -508,5 +503,5 @@
 #-----------------------------------------------------------------------------
 
-class PendingFlightsWindow(gtk.Window):
+class PendingFlightsWindow(Gtk.Window):
     """The window to display the lists of the pending (reported or rejected)
     flights."""
@@ -522,10 +517,10 @@
         self.set_modal(True)
 
-        mainAlignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
+        mainAlignment = Gtk.Alignment(xalign = 0.5, yalign = 0.5,
                                       xscale = 1.0, yscale = 1.0)
         mainAlignment.set_padding(padding_top = 0, padding_bottom = 12,
                                   padding_left = 8, padding_right = 8)
 
-        vbox = gtk.VBox()
+        vbox = Gtk.VBox()
 
         self._reportedFrame = PendingFlightsFrame("reported", wizard, self,
@@ -536,8 +531,9 @@
         vbox.pack_start(self._rejectedFrame, True, True, 2)
 
-        alignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
+        alignment = Gtk.Alignment(xalign = 0.5, yalign = 0.5,
                                   xscale = 0.0, yscale = 0.0)
-        self._closeButton = gtk.Button(xstr("button_ok"))
+        self._closeButton = Gtk.Button(xstr("button_ok"))
         self._closeButton.connect("clicked", self._closeClicked)
+        self._closeButton.set_use_underline(True)
         alignment.add(self._closeButton)
         vbox.pack_start(alignment, False, False, 2)
@@ -584,5 +580,5 @@
         If the Escape key is pressed, 'delete-event' is emitted to close the
         window."""
-        if gdk.keyval_name(event.keyval) == "Escape":
+        if Gdk.keyval_name(event.keyval) == "Escape":
             self.emit("delete-event", None)
             return True
@@ -590,5 +586,5 @@
 #-----------------------------------------------------------------------------
 
-class AcceptedFlightsWindow(gtk.Window):
+class AcceptedFlightsWindow(Gtk.Window):
     """A window for a list of accepted flights."""
     def getFlightDuration(flightTimeStart, flight):
@@ -626,5 +622,5 @@
                          extraColumnAttributes =
                              { "alignment": 1.0 },
-                         cellDataFn = lambda col, cell, model, iter:
+                         cellDataFn = lambda col, cell, model, iter, data:
                              cell.set_property("text",
                                                "%.0f" %
@@ -642,11 +638,11 @@
         self.set_transient_for(gui.mainWindow)
 
-        alignment = gtk.Alignment(xscale = 1.0, yscale = 1.0)
+        alignment = Gtk.Alignment(xscale = 1.0, yscale = 1.0)
         alignment.set_padding(padding_top = 2, padding_bottom = 8,
                               padding_left = 4, padding_right = 4)
 
-        vbox = gtk.VBox()
-
-        hbox = gtk.HBox()
+        vbox = Gtk.VBox()
+
+        hbox = Gtk.HBox()
         vbox.pack_start(hbox, True, True, 4)
 
@@ -661,18 +657,20 @@
         hbox.pack_start(self._flightList, True, True, 4)
 
-        buttonBox = gtk.VBox()
-
-        self._refreshButton = gtk.Button(xstr("acceptedflt_refresh"))
+        buttonBox = Gtk.VBox()
+
+        self._refreshButton = Gtk.Button(xstr("acceptedflt_refresh"))
         self._refreshButton.set_sensitive(True)
+        self._refreshButton.set_use_underline(True)
         self._refreshButton.connect("clicked", self._refreshClicked)
         buttonBox.pack_start(self._refreshButton, False, False, 2)
 
-        filler = gtk.Alignment(xalign = 0.0, yalign = 0.0,
+        filler = Gtk.Alignment(xalign = 0.0, yalign = 0.0,
                                xscale = 1.0, yscale = 1.0)
         filler.set_size_request(-1, 4)
         buttonBox.pack_start(filler, False, False, 0)
 
-        self._viewButton = gtk.Button(xstr("acceptedflt_view"))
+        self._viewButton = Gtk.Button(xstr("acceptedflt_view"))
         self._viewButton.set_sensitive(False)
+        self._viewButton.set_use_underline(True)
         self._viewButton.connect("clicked", self._viewClicked)
         buttonBox.pack_start(self._viewButton, False, False, 2)
@@ -680,9 +678,10 @@
         hbox.pack_start(buttonBox, False, False, 4)
 
-        buttonAlignment = gtk.Alignment(xscale = 0.0, yscale = 0.0,
+        buttonAlignment = Gtk.Alignment(xscale = 0.0, yscale = 0.0,
                                         xalign = 0.5, yalign = 0.5)
 
-        self._closeButton =  gtk.Button(xstr("button_ok"))
+        self._closeButton =  Gtk.Button(xstr("button_ok"))
         self._closeButton.connect("clicked", self._closeClicked)
+        self._closeButton.set_use_underline(True)
 
         buttonAlignment.add(self._closeButton)
@@ -742,5 +741,5 @@
     def _pirepResultCallback(self, returned, result):
         """Called when the PIREP query result is available."""
-        gobject.idle_add(self._handlePIREPResult, returned, result)
+        GObject.idle_add(self._handlePIREPResult, returned, result)
 
     def _handlePIREPResult(self, returned, result):
@@ -764,5 +763,5 @@
         If the Escape key is pressed, 'delete-event' is emitted to close the
         window."""
-        if gdk.keyval_name(event.keyval) == "Escape":
+        if Gdk.keyval_name(event.keyval) == "Escape":
             self.emit("delete-event", None)
             return True
Index: src/mlx/gui/gates.py
===================================================================
--- src/mlx/gui/gates.py	(revision 619)
+++ src/mlx/gui/gates.py	(revision 996)
@@ -19,5 +19,5 @@
 #-------------------------------------------------------------------------------
 
-class FleetGateStatus(gtk.VBox):
+class FleetGateStatus(Gtk.VBox):
     """The tab to display the fleet and gate status."""
     def __init__(self, gui):
@@ -27,5 +27,5 @@
         self._gui = gui
 
-        mainAlignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
+        mainAlignment = Gtk.Alignment(xalign = 0.5, yalign = 0.5,
                                       xscale = 1.0, yscale = 1.0)
         mainAlignment.set_padding(padding_top = 4, padding_bottom = 4,
@@ -33,20 +33,20 @@
         self.add(mainAlignment)
 
-        self._mainBox = mainBox = gtk.VBox()
+        self._mainBox = mainBox = Gtk.VBox()
         mainAlignment.add(mainBox)
     
-        self._statusBox = statusBox = gtk.HBox()
+        self._statusBox = statusBox = Gtk.HBox()
         mainBox.pack_start(statusBox, True, True, 4)
 
-        fleetFrame = gtk.Frame(label = xstr("gates_fleet_title"))
+        fleetFrame = Gtk.Frame(label = xstr("gates_fleet_title"))
         fleetLabel = fleetFrame.get_label_widget()
         fleetLabel.set_use_underline(True)
         statusBox.pack_start(fleetFrame, False, False, 4)
 
-        self._fleetStore = gtk.ListStore(str, str)
-        self._fleetList = gtk.TreeView(self._fleetStore)
+        self._fleetStore = Gtk.ListStore(str, str)
+        self._fleetList = Gtk.TreeView(self._fleetStore)
         self._fleetList.set_tooltip_markup(xstr("gates_planes_tooltip"))
         fleetLabel.set_mnemonic_widget(self._fleetList)
-        column = gtk.TreeViewColumn(xstr("gates_tailno"), gtk.CellRendererText(),
+        column = Gtk.TreeViewColumn(xstr("gates_tailno"), Gtk.CellRendererText(),
                                     text = 0)
         column.set_expand(True)
@@ -54,5 +54,5 @@
         self._fleetList.append_column(column)
 
-        column = gtk.TreeViewColumn(xstr("gates_planestatus"), gtk.CellRendererText(),
+        column = Gtk.TreeViewColumn(xstr("gates_planestatus"), Gtk.CellRendererText(),
                                     markup = 1)
         column.set_expand(True)
@@ -60,18 +60,15 @@
         self._fleetList.append_column(column)
 
-        scrolledWindow = gtk.ScrolledWindow()
+        scrolledWindow = Gtk.ScrolledWindow()
         scrolledWindow.add(self._fleetList)
         scrolledWindow.set_size_request(200, -1)
         # FIXME: these should be constants in common.py
-        scrolledWindow.set_policy(gtk.PolicyType.AUTOMATIC if pygobject
-                                  else gtk.POLICY_AUTOMATIC,
-                                  gtk.PolicyType.AUTOMATIC if pygobject
-                                  else gtk.POLICY_AUTOMATIC)
-        scrolledWindow.set_shadow_type(gtk.ShadowType.IN if pygobject
-                                       else gtk.SHADOW_IN)
+        scrolledWindow.set_policy(Gtk.PolicyType.AUTOMATIC,
+                                  Gtk.PolicyType.AUTOMATIC)
+        scrolledWindow.set_shadow_type(Gtk.ShadowType.IN)
 
 
         self._fleetAlignment =  alignment = \
-                               gtk.Alignment(xalign = 0.5, yalign = 0.0,
+                               Gtk.Alignment(xalign = 0.5, yalign = 0.0,
                                              xscale = 0.0, yscale = 1.0)
         alignment.set_padding(padding_top = 4, padding_bottom = 4,
@@ -80,11 +77,11 @@
         fleetFrame.add(alignment)        
         
-        self._gatesFrame = gatesFrame = gtk.Frame(label = xstr("gates_gates_title"))
+        self._gatesFrame = gatesFrame = Gtk.Frame(label = xstr("gates_gates_title"))
         statusBox.pack_start(gatesFrame, True, True, 4)        
 
-        self._gatesTable = table = gtk.Table(lhbpGates.numRows,
+        self._gatesTable = table = Gtk.Table(lhbpGates.numRows,
                                              lhbpGates.numColumns)
         table.set_tooltip_markup(xstr("gates_gates_tooltip"))
-        alignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
+        alignment = Gtk.Alignment(xalign = 0.5, yalign = 0.5,
                                   xscale = 1.0, yscale = 1.0)
         alignment.set_padding(padding_top = 4, padding_bottom = 4,
@@ -100,5 +97,5 @@
                 gate = data
 
-                label = gtk.Label()
+                label = Gtk.Label()
                 label.set_markup("<b>" + gate.number + "</b>")
                 table.attach(label, column, column + 1, row, row + 1)
@@ -112,10 +109,10 @@
                 column += 1
 
-        button = gtk.Button(xstr("gates_refresh"))
+        button = Gtk.Button(xstr("gates_refresh"))
         button.set_use_underline(True)
         button.set_tooltip_text(xstr("gates_refresh_tooltip"))
         button.connect("clicked", self._refreshClicked)
 
-        alignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
+        alignment = Gtk.Alignment(xalign = 0.5, yalign = 0.5,
                                   xscale = 0.0, yscale = 0.0)
         alignment.add(button)
@@ -143,5 +140,5 @@
         self._fleetStore.clear()
         if fleet is None:
-            for (gateNumber, label) in self._gateLabels.iteritems():
+            for (gateNumber, label) in self._gateLabels.items():
                 label.set_markup("<b>" + gateNumber + "</b>")
         else:        
@@ -165,7 +162,5 @@
                 self._fleetStore.append([tailNumber, status])
             # FIXME: this should be a constant in common.py
-            self._fleetStore.set_sort_column_id(0,
-                                                gtk.SortType.ASCENDING if pygobject
-                                                else gtk.SORT_ASCENDING)
+            self._fleetStore.set_sort_column_id(0, Gtk.SortType.ASCENDING)
 
             occupiedGateNumbers = fleet.getOccupiedGateNumbers()
Index: src/mlx/gui/gui.py
===================================================================
--- src/mlx/gui/gui.py	(revision 951)
+++ src/mlx/gui/gui.py	(revision 1010)
@@ -1,8 +1,8 @@
 # -*- coding: utf-8 -*-
 
-from statusicon import StatusIcon
-from statusbar import Statusbar
-from info import FlightInfo
-from update import Updater
+from .statusicon import StatusIcon
+from .statusbar import Statusbar
+from .info import FlightInfo
+from .update import Updater
 from mlx.gui.common import *
 from mlx.gui.flight import Wizard
@@ -18,5 +18,5 @@
 from mlx.gui.acars import ACARS
 from mlx.gui.timetable import TimetableWindow
-import cef
+from . import cef
 
 import mlx.const as const
@@ -51,17 +51,17 @@
 class GUI(fs.ConnectionListener):
     """The main GUI class."""
-    _authors = [ (u"Váradi", u"István", "prog_test"),
-                 (u"Galyassy", u"Tamás", "negotiation"),
-                 (u"Kurják", u"Ákos", "test"),
-                 (u"Nagy", u"Dániel", "test"),
-                 (u"Radó", u"Iván", "test"),
-                 (u"Petrovszki", u"Gábor", "test"),
-                 (u"Serfőző", u"Tamás", "test"),
-                 (u"Szebenyi", u"Bálint", "test"),
-                 (u"Zsebényi-Loksa", u"Gergely", "test") ]
+    _authors = [ ("Váradi", "István", "prog_test"),
+                 ("Galyassy", "Tamás", "negotiation"),
+                 ("Kurják", "Ákos", "test"),
+                 ("Nagy", "Dániel", "test"),
+                 ("Radó", "Iván", "test"),
+                 ("Petrovszki", "Gábor", "test"),
+                 ("Serfőző", "Tamás", "test"),
+                 ("Szebenyi", "Bálint", "test"),
+                 ("Zsebényi-Loksa", "Gergely", "test") ]
 
     def __init__(self, programDirectory, config):
         """Construct the GUI."""
-        gobject.threads_init()
+        GObject.threads_init()
 
         self._programDirectory = programDirectory
@@ -108,5 +108,7 @@
         """Build the GUI."""
 
-        self._mainWindow = window = gtk.Window()
+        self._mainWindow = window = Gtk.Window()
+        if os.name!="nt":
+            window.set_visual(window.get_screen().lookup_visual(0x21))
         window.set_title(WINDOW_TITLE_BASE)
         window.set_icon_from_file(os.path.join(iconDirectory, "logo.ico"))
@@ -116,9 +118,9 @@
         if os.name=="nt":
             window.connect("leave-notify-event", self._handleLeaveNotify)
-        accelGroup = gtk.AccelGroup()
+        accelGroup = Gtk.AccelGroup()
         window.add_accel_group(accelGroup)
         window.realize()
 
-        mainVBox = gtk.VBox()
+        mainVBox = Gtk.VBox()
         window.add(mainVBox)
 
@@ -135,9 +137,9 @@
         mainVBox.pack_start(menuBar, False, False, 0)
 
-        self._notebook = gtk.Notebook()
+        self._notebook = Gtk.Notebook()
         mainVBox.pack_start(self._notebook, True, True, 4)
 
         self._wizard = Wizard(self)
-        label = gtk.Label(xstr("tab_flight"))
+        label = Gtk.Label(xstr("tab_flight"))
         label.set_use_underline(True)
         label.set_tooltip_text(xstr("tab_flight_tooltip"))
@@ -145,5 +147,5 @@
 
         self._flightInfo = FlightInfo(self)
-        label = gtk.Label(xstr("tab_flight_info"))
+        label = Gtk.Label(xstr("tab_flight_info"))
         label.set_use_underline(True)
         label.set_tooltip_text(xstr("tab_flight_info_tooltip"))
@@ -152,5 +154,5 @@
 
         self._weightHelp = WeightHelp(self)
-        label = gtk.Label(xstr("tab_weight_help"))
+        label = Gtk.Label(xstr("tab_weight_help"))
         label.set_use_underline(True)
         label.set_tooltip_text(xstr("tab_weight_help_tooltip"))
@@ -159,5 +161,5 @@
         (logWidget, self._logView)  = self._buildLogWidget()
         addFaultTag(self._logView.get_buffer())
-        label = gtk.Label(xstr("tab_log"))
+        label = Gtk.Label(xstr("tab_log"))
         label.set_use_underline(True)
         label.set_tooltip_text(xstr("tab_log_tooltip"))
@@ -165,5 +167,5 @@
 
         self._fleetGateStatus = FleetGateStatus(self)
-        label = gtk.Label(xstr("tab_gates"))
+        label = Gtk.Label(xstr("tab_gates"))
         label.set_use_underline(True)
         label.set_tooltip_text(xstr("tab_gates_tooltip"))
@@ -171,5 +173,5 @@
 
         self._acars = ACARS(self)
-        label = gtk.Label("ACARS")
+        label = Gtk.Label("ACARS")
         label.set_use_underline(True)
         self._notebook.append_page(self._acars, label)
@@ -178,5 +180,5 @@
         self._debugLogWidget.show_all()
 
-        mainVBox.pack_start(gtk.HSeparator(), False, False, 0)
+        mainVBox.pack_start(Gtk.HSeparator(), False, False, 0)
 
         self._statusbar = Statusbar(iconDirectory)
@@ -197,6 +199,4 @@
 
         window.show_all()
-        if os.name=="nt":
-            window.get_window().focus()
 
         self._wizard.grabDefault()
@@ -206,6 +206,5 @@
         self._statusIcon = StatusIcon(iconDirectory, self)
 
-        self._busyCursor = gdk.Cursor(gdk.CursorType.WATCH if pygobject
-                                      else gdk.WATCH)
+        self._busyCursor = Gdk.Cursor(Gdk.CursorType.WATCH)
 
         self._loadPIREPDialog = None
@@ -361,5 +360,5 @@
     def takeoffAntiIceOn(self, value):
         """Set the anti-ice on indicator."""
-        gobject.idle_add(self._setTakeoffAntiIceOn, value)
+        GObject.idle_add(self._setTakeoffAntiIceOn, value)
 
     @property
@@ -401,5 +400,5 @@
     def landingAntiIceOn(self, value):
         """Set the anti-ice on indicator."""
-        gobject.idle_add(self._setLandingAntiIceOn, value)
+        GObject.idle_add(self._setLandingAntiIceOn, value)
 
     @property
@@ -444,10 +443,9 @@
         return self._flightInfo.faultsFullyExplained
 
-    if pygobject:
-        @property
-        def backgroundColour(self):
-            """Get the background colour of the main window."""
-            return self._mainWindow.get_style_context().\
-              get_background_color(gtk.StateFlags.NORMAL)
+    @property
+    def backgroundColour(self):
+        """Get the background colour of the main window."""
+        return self._mainWindow.get_style_context().\
+            get_background_color(Gtk.StateFlags.NORMAL)
 
     def run(self):
@@ -463,5 +461,5 @@
 
         singleton.raiseCallback = self.raiseCallback
-        gtk.main()
+        Gtk.main()
         singleton.raiseCallback = None
 
@@ -472,5 +470,5 @@
     def updateDone(self):
         """Called when the update is done (and there is no need to restart)."""
-        gobject.idle_add(self._updateDone)
+        GObject.idle_add(self._updateDone)
 
     def connected(self, fsType, descriptor):
@@ -481,5 +479,5 @@
         fs.sendMessage(const.MESSAGETYPE_INFORMATION,
                        "Welcome to MAVA Logger X " + const.VERSION)
-        gobject.idle_add(self._handleConnected, fsType, descriptor)
+        GObject.idle_add(self._handleConnected, fsType, descriptor)
 
     def _handleConnected(self, fsType, descriptor):
@@ -496,5 +494,5 @@
         """Called when the connection failed."""
         self._logger.untimedMessage("Connection to the simulator failed")
-        gobject.idle_add(self._connectionFailed)
+        GObject.idle_add(self._connectionFailed)
 
     def _connectionFailed(self):
@@ -503,6 +501,6 @@
         self._statusbar.updateConnection(self._connecting, self._connected)
 
-        dialog = gtk.MessageDialog(parent = self._mainWindow,
-                                   type = MESSAGETYPE_ERROR,
+        dialog = Gtk.MessageDialog(parent = self._mainWindow,
+                                   type = Gtk.MessageType.ERROR,
                                    message_format = xstr("conn_failed"))
 
@@ -529,5 +527,5 @@
             self._flight.disconnected()
 
-        gobject.idle_add(self._disconnected)
+        GObject.idle_add(self._disconnected)
 
     def _disconnected(self):
@@ -535,5 +533,5 @@
         self._statusbar.updateConnection(self._connecting, self._connected)
 
-        dialog = gtk.MessageDialog(type = MESSAGETYPE_ERROR,
+        dialog = Gtk.MessageDialog(type = Gtk.MessageType.ERROR,
                                    message_format = xstr("conn_broken"),
                                    parent = self._mainWindow)
@@ -574,5 +572,5 @@
     def _bookFlightsCallback(self, returned, result):
         """Called when the booking of flights has finished."""
-        gobject.idle_add(self._handleBookFlightsResult, returned, result)
+        GObject.idle_add(self._handleBookFlightsResult, returned, result)
 
     def _handleBookFlightsResult(self, returned, result):
@@ -593,10 +591,10 @@
     def cancelFlight(self):
         """Cancel the current file, if the user confirms it."""
-        dialog = gtk.MessageDialog(parent = self._mainWindow,
-                                   type = MESSAGETYPE_QUESTION,
+        dialog = Gtk.MessageDialog(parent = self._mainWindow,
+                                   type = Gtk.MessageType.QUESTION,
                                    message_format = xstr("cancelFlight_question"))
 
-        dialog.add_button(xstr("button_no"), RESPONSETYPE_NO)
-        dialog.add_button(xstr("button_yes"), RESPONSETYPE_YES)
+        dialog.add_button(xstr("button_no"), Gtk.ResponseType.NO)
+        dialog.add_button(xstr("button_yes"), Gtk.ResponseType.YES)
 
         dialog.set_title(WINDOW_TITLE_BASE)
@@ -604,5 +602,5 @@
         dialog.hide()
 
-        if result==RESPONSETYPE_YES:
+        if result==Gtk.ResponseType.YES:
             self.reset()
 
@@ -655,5 +653,5 @@
     def insertFlightLogLine(self, index, timestampString, text, isFault):
         """Insert the flight log line with the given data."""
-        gobject.idle_add(self._insertFlightLogLine, index,
+        GObject.idle_add(self._insertFlightLogLine, index,
                          formatFlightLogLine(timestampString, text),
                          isFault)
@@ -670,19 +668,19 @@
     def removeFlightLogLine(self, index):
         """Remove the flight log line with the given index."""
-        gobject.idle_add(self._removeFlightLogLine, index)
+        GObject.idle_add(self._removeFlightLogLine, index)
 
     def addFault(self, id, timestampString, text):
         """Add a fault to the list of faults."""
         faultText = formatFlightLogLine(timestampString, text).strip()
-        gobject.idle_add(self._flightInfo.addFault, id, faultText)
+        GObject.idle_add(self._flightInfo.addFault, id, faultText)
 
     def updateFault(self, id, timestampString, text):
         """Update a fault in the list of faults."""
         faultText = formatFlightLogLine(timestampString, text).strip()
-        gobject.idle_add(self._flightInfo.updateFault, id, faultText)
+        GObject.idle_add(self._flightInfo.updateFault, id, faultText)
 
     def clearFault(self, id):
         """Clear a fault in the list of faults."""
-        gobject.idle_add(self._flightInfo.clearFault, id)
+        GObject.idle_add(self._flightInfo.clearFault, id)
 
     def _removeFlightLogLine(self, index):
@@ -696,6 +694,6 @@
     def check(self, flight, aircraft, logger, oldState, state):
         """Update the data."""
-        gobject.idle_add(self._monitorWindow.setData, state)
-        gobject.idle_add(self._statusbar.updateTime, state.timestamp)
+        GObject.idle_add(self._monitorWindow.setData, state)
+        GObject.idle_add(self._statusbar.updateTime, state.timestamp)
 
     def resetFlightStatus(self):
@@ -707,5 +705,5 @@
     def setStage(self, stage):
         """Set the stage of the flight."""
-        gobject.idle_add(self._setStage, stage)
+        GObject.idle_add(self._setStage, stage)
 
     def _setStage(self, stage):
@@ -723,5 +721,5 @@
     def setRating(self, rating):
         """Set the rating of the flight."""
-        gobject.idle_add(self._setRating, rating)
+        GObject.idle_add(self._setRating, rating)
 
     def _setRating(self, rating):
@@ -732,5 +730,5 @@
     def setNoGo(self, reason):
         """Set the rating of the flight to No-Go with the given reason."""
-        gobject.idle_add(self._setNoGo, reason)
+        GObject.idle_add(self._setNoGo, reason)
 
     def _setNoGo(self, reason):
@@ -741,19 +739,14 @@
     def _handleMainWindowState(self, window, event):
         """Hande a change in the state of the window"""
-        iconified = gdk.WindowState.ICONIFIED if pygobject \
-                    else gdk.WINDOW_STATE_ICONIFIED
-
-        if (event.changed_mask&WINDOW_STATE_WITHDRAWN)!=0:
-            if (event.new_window_state&WINDOW_STATE_WITHDRAWN)!=0:
+        iconified = Gdk.WindowState.ICONIFIED
+
+        if (event.changed_mask&Gdk.WindowState.WITHDRAWN)!=0:
+            if (event.new_window_state&Gdk.WindowState.WITHDRAWN)!=0:
                 self._statusIcon.mainWindowHidden()
             else:
                 self._statusIcon.mainWindowShown()
 
-        if self.config.hideMinimizedWindow and not pygobject and \
-           (event.changed_mask&WINDOW_STATE_ICONIFIED)!=0 and \
-           (event.new_window_state&WINDOW_STATE_ICONIFIED)!=0:
-            self.hideMainWindow(savePosition = False)
-        elif (event.changed_mask&WINDOW_STATE_ICONIFIED)!=0 and \
-             (event.new_window_state&WINDOW_STATE_ICONIFIED)==0:
+        if (event.changed_mask&Gdk.WindowState.ICONIFIED)!=0 and \
+           (event.new_window_state&Gdk.WindowState.ICONIFIED)==0:
             self._mainWindow.present()
 
@@ -763,9 +756,9 @@
         Here we reset the focus to the main window as CEF might have acquired
         it earlier."""
-        self._mainWindow.get_window().focus()
+        self._mainWindow.get_window().focus(0)
 
     def raiseCallback(self):
         """Callback for the singleton handling code."""
-        gobject.idle_add(self.raiseMainWindow)
+        GObject.idle_add(self.raiseMainWindow)
 
     def raiseMainWindow(self):
@@ -798,8 +791,5 @@
             self._mainWindow.move(self._mainWindowX, self._mainWindowY)
 
-        if pygobject:
-            self._mainWindow.show()
-        else:
-            self._mainWindow.present()
+        self._mainWindow.show()
         self._mainWindow.deiconify()
 
@@ -858,5 +848,5 @@
             self._stdioText += text
 
-        gobject.idle_add(self._writeStdIO)
+        GObject.idle_add(self._writeStdIO)
 
     def beginBusy(self, message):
@@ -885,5 +875,5 @@
     def getFleetAsync(self, callback = None, force = None):
         """Get the fleet asynchronously."""
-        gobject.idle_add(self.getFleet, callback, force)
+        GObject.idle_add(self.getFleet, callback, force)
 
     def getFleet(self, callback = None, force = False, busyCallback = None):
@@ -920,5 +910,5 @@
             self._wizard.updateRTO()
         else:
-            gobject.idle_add(self.updateRTO, True)
+            GObject.idle_add(self.updateRTO, True)
 
     def rtoToggled(self, indicated):
@@ -928,5 +918,5 @@
     def _fleetResultCallback(self, returned, result):
         """Called when the fleet has been queried."""
-        gobject.idle_add(self._handleFleetResult, returned, result)
+        GObject.idle_add(self._handleFleetResult, returned, result)
 
     def _handleFleetResult(self, returned, result):
@@ -940,8 +930,8 @@
             self._fleet = None
 
-            dialog = gtk.MessageDialog(parent = self.mainWindow,
-                                       type = MESSAGETYPE_ERROR,
+            dialog = Gtk.MessageDialog(parent = self.mainWindow,
+                                       type = Gtk.MessageType.ERROR,
                                        message_format = xstr("fleet_failed"))
-            dialog.add_button(xstr("button_ok"), RESPONSETYPE_OK)
+            dialog.add_button(xstr("button_ok"), Gtk.ResponseType.OK)
             dialog.set_title(WINDOW_TITLE_BASE)
             dialog.run()
@@ -971,5 +961,5 @@
     def _updatePlaneResultCallback(self, returned, result):
         """Called when the status of a plane has been updated."""
-        gobject.idle_add(self._handleUpdatePlaneResult, returned, result)
+        GObject.idle_add(self._handleUpdatePlaneResult, returned, result)
 
     def _handleUpdatePlaneResult(self, returned, result):
@@ -985,8 +975,8 @@
                     self._fleetGateStatus.handleFleet(self._fleet)
         else:
-            dialog = gtk.MessageDialog(parent = self.mainWindow,
-                                       type = MESSAGETYPE_ERROR,
+            dialog = Gtk.MessageDialog(parent = self.mainWindow,
+                                       type = Gtk.MessageType.ERROR,
                                        message_format = xstr("fleet_update_failed"))
-            dialog.add_button(xstr("button_ok"), RESPONSETYPE_ACCEPT)
+            dialog.add_button(xstr("button_ok"), Gtk.ResponseType.ACCEPT)
             dialog.set_title(WINDOW_TITLE_BASE)
             dialog.run()
@@ -1075,43 +1065,46 @@
     def _buildMenuBar(self, accelGroup):
         """Build the main menu bar."""
-        menuBar = gtk.MenuBar()
-
-        fileMenuItem = gtk.MenuItem(xstr("menu_file"))
-        fileMenu = gtk.Menu()
+        menuBar = Gtk.MenuBar()
+
+        fileMenuItem = Gtk.MenuItem(xstr("menu_file"))
+        fileMenu = Gtk.Menu()
         fileMenuItem.set_submenu(fileMenu)
         menuBar.append(fileMenuItem)
 
-        loadPIREPMenuItem = gtk.ImageMenuItem(gtk.STOCK_OPEN)
+        loadPIREPMenuItem = Gtk.ImageMenuItem(Gtk.STOCK_OPEN)
         loadPIREPMenuItem.set_use_stock(True)
         loadPIREPMenuItem.set_label(xstr("menu_file_loadPIREP"))
         loadPIREPMenuItem.add_accelerator("activate", accelGroup,
                                           ord(xstr("menu_file_loadPIREP_key")),
-                                          CONTROL_MASK, ACCEL_VISIBLE)
+                                          Gdk.ModifierType.CONTROL_MASK,
+                                          Gtk.AccelFlags.VISIBLE)
         loadPIREPMenuItem.connect("activate", self._loadPIREP)
         fileMenu.append(loadPIREPMenuItem)
 
-        fileMenu.append(gtk.SeparatorMenuItem())
-
-        quitMenuItem = gtk.ImageMenuItem(gtk.STOCK_QUIT)
+        fileMenu.append(Gtk.SeparatorMenuItem())
+
+        quitMenuItem = Gtk.ImageMenuItem(Gtk.STOCK_QUIT)
         quitMenuItem.set_use_stock(True)
         quitMenuItem.set_label(xstr("menu_file_quit"))
         quitMenuItem.add_accelerator("activate", accelGroup,
                                      ord(xstr("menu_file_quit_key")),
-                                     CONTROL_MASK, ACCEL_VISIBLE)
+                                     Gdk.ModifierType.CONTROL_MASK,
+                                     Gtk.AccelFlags.VISIBLE)
         quitMenuItem.connect("activate", self._quit)
         fileMenu.append(quitMenuItem)
 
-        toolsMenuItem = gtk.MenuItem(xstr("menu_tools"))
-        toolsMenu = gtk.Menu()
+        toolsMenuItem = Gtk.MenuItem(xstr("menu_tools"))
+        toolsMenu = Gtk.Menu()
         toolsMenuItem.set_submenu(toolsMenu)
         menuBar.append(toolsMenuItem)
 
         self._timetableMenuItem = timetableMenuItem = \
-          gtk.ImageMenuItem(gtk.STOCK_INDENT)
+          Gtk.ImageMenuItem(Gtk.STOCK_INDENT)
         timetableMenuItem.set_use_stock(True)
         timetableMenuItem.set_label(xstr("menu_tools_timetable"))
         timetableMenuItem.add_accelerator("activate", accelGroup,
                                           ord(xstr("menu_tools_timetable_key")),
-                                          CONTROL_MASK, ACCEL_VISIBLE)
+                                          Gdk.ModifierType.CONTROL_MASK,
+                                          Gtk.AccelFlags.VISIBLE)
         timetableMenuItem.connect("activate", self.showTimetable)
         self._timetableMenuItem.set_sensitive(False)
@@ -1119,58 +1112,63 @@
 
         self._flightsMenuItem = flightsMenuItem = \
-          gtk.ImageMenuItem(gtk.STOCK_SPELL_CHECK)
+          Gtk.ImageMenuItem(Gtk.STOCK_SPELL_CHECK)
         flightsMenuItem.set_use_stock(True)
         flightsMenuItem.set_label(xstr("menu_tools_flights"))
         flightsMenuItem.add_accelerator("activate", accelGroup,
                                         ord(xstr("menu_tools_flights_key")),
-                                        CONTROL_MASK, ACCEL_VISIBLE)
+                                        Gdk.ModifierType.CONTROL_MASK,
+                                        Gtk.AccelFlags.VISIBLE)
         flightsMenuItem.connect("activate", self.showFlights)
         self._flightsMenuItem.set_sensitive(False)
         toolsMenu.append(flightsMenuItem)
 
-        checklistMenuItem = gtk.ImageMenuItem(gtk.STOCK_APPLY)
+        checklistMenuItem = Gtk.ImageMenuItem(Gtk.STOCK_APPLY)
         checklistMenuItem.set_use_stock(True)
         checklistMenuItem.set_label(xstr("menu_tools_chklst"))
         checklistMenuItem.add_accelerator("activate", accelGroup,
                                           ord(xstr("menu_tools_chklst_key")),
-                                          CONTROL_MASK, ACCEL_VISIBLE)
+                                          Gdk.ModifierType.CONTROL_MASK,
+                                          Gtk.AccelFlags.VISIBLE)
         checklistMenuItem.connect("activate", self._editChecklist)
         toolsMenu.append(checklistMenuItem)
 
-        approachCalloutsMenuItem = gtk.ImageMenuItem(gtk.STOCK_EDIT)
+        approachCalloutsMenuItem = Gtk.ImageMenuItem(Gtk.STOCK_EDIT)
         approachCalloutsMenuItem.set_use_stock(True)
         approachCalloutsMenuItem.set_label(xstr("menu_tools_callouts"))
         approachCalloutsMenuItem.add_accelerator("activate", accelGroup,
                                                  ord(xstr("menu_tools_callouts_key")),
-                                                 CONTROL_MASK, ACCEL_VISIBLE)
+                                                 Gdk.ModifierType.CONTROL_MASK,
+                                                 Gtk.AccelFlags.VISIBLE)
         approachCalloutsMenuItem.connect("activate", self._editApproachCallouts)
         toolsMenu.append(approachCalloutsMenuItem)
 
-        prefsMenuItem = gtk.ImageMenuItem(gtk.STOCK_PREFERENCES)
+        prefsMenuItem = Gtk.ImageMenuItem(Gtk.STOCK_PREFERENCES)
         prefsMenuItem.set_use_stock(True)
         prefsMenuItem.set_label(xstr("menu_tools_prefs"))
         prefsMenuItem.add_accelerator("activate", accelGroup,
                                       ord(xstr("menu_tools_prefs_key")),
-                                      CONTROL_MASK, ACCEL_VISIBLE)
+                                      Gdk.ModifierType.CONTROL_MASK,
+                                      Gtk.AccelFlags.VISIBLE)
         prefsMenuItem.connect("activate", self._editPreferences)
         toolsMenu.append(prefsMenuItem)
 
-        toolsMenu.append(gtk.SeparatorMenuItem())
-
-        bugReportMenuItem = gtk.ImageMenuItem(gtk.STOCK_PASTE)
+        toolsMenu.append(Gtk.SeparatorMenuItem())
+
+        bugReportMenuItem = Gtk.ImageMenuItem(Gtk.STOCK_PASTE)
         bugReportMenuItem.set_use_stock(True)
         bugReportMenuItem.set_label(xstr("menu_tools_bugreport"))
         bugReportMenuItem.add_accelerator("activate", accelGroup,
                                           ord(xstr("menu_tools_bugreport_key")),
-                                          CONTROL_MASK, ACCEL_VISIBLE)
+                                          Gdk.ModifierType.CONTROL_MASK,
+                                          Gtk.AccelFlags.VISIBLE)
         bugReportMenuItem.connect("activate", self._reportBug)
         toolsMenu.append(bugReportMenuItem)
 
-        viewMenuItem = gtk.MenuItem(xstr("menu_view"))
-        viewMenu = gtk.Menu()
+        viewMenuItem = Gtk.MenuItem(xstr("menu_view"))
+        viewMenu = Gtk.Menu()
         viewMenuItem.set_submenu(viewMenu)
         menuBar.append(viewMenuItem)
 
-        self._showMonitorMenuItem = gtk.CheckMenuItem()
+        self._showMonitorMenuItem = Gtk.CheckMenuItem()
         self._showMonitorMenuItem.set_label(xstr("menu_view_monitor"))
         self._showMonitorMenuItem.set_use_underline(True)
@@ -1178,9 +1176,10 @@
         self._showMonitorMenuItem.add_accelerator("activate", accelGroup,
                                                   ord(xstr("menu_view_monitor_key")),
-                                                  CONTROL_MASK, ACCEL_VISIBLE)
+                                                  Gdk.ModifierType.CONTROL_MASK,
+                                                  Gtk.AccelFlags.VISIBLE)
         self._showMonitorMenuItem.connect("toggled", self._toggleMonitorWindow)
         viewMenu.append(self._showMonitorMenuItem)
 
-        showDebugMenuItem = gtk.CheckMenuItem()
+        showDebugMenuItem = Gtk.CheckMenuItem()
         showDebugMenuItem.set_label(xstr("menu_view_debug"))
         showDebugMenuItem.set_use_underline(True)
@@ -1188,30 +1187,33 @@
         showDebugMenuItem.add_accelerator("activate", accelGroup,
                                           ord(xstr("menu_view_debug_key")),
-                                          CONTROL_MASK, ACCEL_VISIBLE)
+                                          Gdk.ModifierType.CONTROL_MASK,
+                                          Gtk.AccelFlags.VISIBLE)
         showDebugMenuItem.connect("toggled", self._toggleDebugLog)
         viewMenu.append(showDebugMenuItem)
 
-        helpMenuItem = gtk.MenuItem(xstr("menu_help"))
-        helpMenu = gtk.Menu()
+        helpMenuItem = Gtk.MenuItem(xstr("menu_help"))
+        helpMenu = Gtk.Menu()
         helpMenuItem.set_submenu(helpMenu)
         menuBar.append(helpMenuItem)
 
-        manualMenuItem = gtk.ImageMenuItem(gtk.STOCK_HELP)
+        manualMenuItem = Gtk.ImageMenuItem(Gtk.STOCK_HELP)
         manualMenuItem.set_use_stock(True)
         manualMenuItem.set_label(xstr("menu_help_manual"))
         manualMenuItem.add_accelerator("activate", accelGroup,
                                        ord(xstr("menu_help_manual_key")),
-                                       CONTROL_MASK, ACCEL_VISIBLE)
+                                       Gdk.ModifierType.CONTROL_MASK,
+                                       Gtk.AccelFlags.VISIBLE)
         manualMenuItem.connect("activate", self._showManual)
         helpMenu.append(manualMenuItem)
 
-        helpMenu.append(gtk.SeparatorMenuItem())
-
-        aboutMenuItem = gtk.ImageMenuItem(gtk.STOCK_ABOUT)
+        helpMenu.append(Gtk.SeparatorMenuItem())
+
+        aboutMenuItem = Gtk.ImageMenuItem(Gtk.STOCK_ABOUT)
         aboutMenuItem.set_use_stock(True)
         aboutMenuItem.set_label(xstr("menu_help_about"))
         aboutMenuItem.add_accelerator("activate", accelGroup,
                                       ord(xstr("menu_help_about_key")),
-                                      CONTROL_MASK, ACCEL_VISIBLE)
+                                      Gdk.ModifierType.CONTROL_MASK,
+                                      Gtk.AccelFlags.VISIBLE)
         aboutMenuItem.connect("activate", self._showAbout)
         helpMenu.append(aboutMenuItem)
@@ -1222,5 +1224,5 @@
         """Toggle the debug log."""
         if menuItem.get_active():
-            label = gtk.Label(xstr("tab_debug_log"))
+            label = Gtk.Label(xstr("tab_debug_log"))
             label.set_use_underline(True)
             label.set_tooltip_text(xstr("tab_debug_log_tooltip"))
@@ -1232,23 +1234,20 @@
     def _buildLogWidget(self):
         """Build the widget for the log."""
-        alignment = gtk.Alignment(xscale = 1.0, yscale = 1.0)
+        alignment = Gtk.Alignment(xscale = 1.0, yscale = 1.0)
 
         alignment.set_padding(padding_top = 8, padding_bottom = 8,
                               padding_left = 16, padding_right = 16)
 
-        logScroller = gtk.ScrolledWindow()
+        logScroller = Gtk.ScrolledWindow()
         # FIXME: these should be constants in common
-        logScroller.set_policy(gtk.PolicyType.AUTOMATIC if pygobject
-                               else gtk.POLICY_AUTOMATIC,
-                               gtk.PolicyType.AUTOMATIC if pygobject
-                               else gtk.POLICY_AUTOMATIC)
-        logScroller.set_shadow_type(gtk.ShadowType.IN if pygobject
-                                    else gtk.SHADOW_IN)
-        logView = gtk.TextView()
+        logScroller.set_policy(Gtk.PolicyType.AUTOMATIC,
+                               Gtk.PolicyType.AUTOMATIC)
+        logScroller.set_shadow_type(Gtk.ShadowType.IN)
+        logView = Gtk.TextView()
         logView.set_editable(False)
         logView.set_cursor_visible(False)
         logScroller.add(logView)
 
-        logBox = gtk.VBox()
+        logBox = Gtk.VBox()
         logBox.pack_start(logScroller, True, True, 0)
         logBox.set_size_request(-1, 200)
@@ -1267,12 +1266,12 @@
         """Quit from the application."""
         if force:
-            result=RESPONSETYPE_YES
-        else:
-            dialog = gtk.MessageDialog(parent = self._mainWindow,
-                                       type = MESSAGETYPE_QUESTION,
+            result=Gtk.ResponseType.YES
+        else:
+            dialog = Gtk.MessageDialog(parent = self._mainWindow,
+                                       type = Gtk.MessageType.QUESTION,
                                        message_format = xstr("quit_question"))
 
-            dialog.add_button(xstr("button_no"), RESPONSETYPE_NO)
-            dialog.add_button(xstr("button_yes"), RESPONSETYPE_YES)
+            dialog.add_button(xstr("button_no"), Gtk.ResponseType.NO)
+            dialog.add_button(xstr("button_yes"), Gtk.ResponseType.YES)
 
             dialog.set_title(WINDOW_TITLE_BASE)
@@ -1280,12 +1279,12 @@
             dialog.hide()
 
-        if result==RESPONSETYPE_YES:
+        if result==Gtk.ResponseType.YES:
             self._statusIcon.destroy()
-            return gtk.main_quit()
+            return Gtk.main_quit()
 
     def _notebookPageSwitch(self, notebook, page, page_num):
         """Called when the current page of the notebook has changed."""
         if page_num==0:
-            gobject.idle_add(self._wizard.grabDefault)
+            GObject.idle_add(self._wizard.grabDefault)
         else:
             self._mainWindow.set_default(None)
@@ -1323,5 +1322,5 @@
     def _timetableCallback(self, returned, result):
         """Called when the timetable has been received."""
-        gobject.idle_add(self._handleTimetable, returned, result)
+        GObject.idle_add(self._handleTimetable, returned, result)
 
     def _handleTimetable(self, returned, result):
@@ -1336,8 +1335,8 @@
             self._timetableWindow.show_all()
         else:
-            dialog = gtk.MessageDialog(parent = self.mainWindow,
-                                       type = MESSAGETYPE_ERROR,
+            dialog = Gtk.MessageDialog(parent = self.mainWindow,
+                                       type = Gtk.MessageType.ERROR,
                                        message_format = xstr("timetable_failed"))
-            dialog.add_button(xstr("button_ok"), RESPONSETYPE_OK)
+            dialog.add_button(xstr("button_ok"), Gtk.ResponseType.OK)
             dialog.set_title(WINDOW_TITLE_BASE)
             dialog.run()
@@ -1355,5 +1354,5 @@
     def _acceptedFlightsCallback(self, returned, result):
         """Called when the accepted flights have been received."""
-        gobject.idle_add(self._handleAcceptedFlights, returned, result)
+        GObject.idle_add(self._handleAcceptedFlights, returned, result)
 
     def _handleAcceptedFlights(self, returned, result):
@@ -1366,8 +1365,8 @@
             self._flightsWindow.show_all()
         else:
-            dialog = gtk.MessageDialog(parent = self.mainWindow,
-                                       type = MESSAGETYPE_ERROR,
+            dialog = Gtk.MessageDialog(parent = self.mainWindow,
+                                       type = Gtk.MessageType.ERROR,
                                        message_format = xstr("acceptedflt_failed"))
-            dialog.add_button(xstr("button_ok"), RESPONSETYPE_OK)
+            dialog.add_button(xstr("button_ok"), Gtk.ResponseType.OK)
             dialog.set_title(WINDOW_TITLE_BASE)
             dialog.run()
@@ -1432,5 +1431,5 @@
         self._pirepEditor.setPIREP(pirep)
         self._pirepEditor.show_all()
-        if self._pirepEditor.run()==RESPONSETYPE_OK:
+        if self._pirepEditor.run()==Gtk.ResponseType.OK:
             self.beginBusy(xstr("pirepEdit_save_busy"))
             self.webHandler.sendPIREP(self._pirepUpdatedCallback, pirep,
@@ -1441,5 +1440,5 @@
     def _pirepUpdatedCallback(self, returned, result):
         """Callback for the PIREP updating result."""
-        gobject.idle_add(self._handlePIREPUpdated, returned, result)
+        GObject.idle_add(self._handlePIREPUpdated, returned, result)
 
     def _handlePIREPUpdated(self, returned, result):
@@ -1447,5 +1446,5 @@
         self.endBusy()
         secondaryMarkup = None
-        type = MESSAGETYPE_ERROR
+        type = Gtk.MessageType.ERROR
         if returned:
             if result.success:
@@ -1460,12 +1459,12 @@
                 secondaryMarkup = xstr("sendPIREP_unknown_sec")
         else:
-            print "PIREP sending failed", result
+            print("PIREP sending failed", result)
             messageFormat = xstr("sendPIREP_failed")
             secondaryMarkup = xstr("sendPIREP_failed_sec")
 
         if type is not None:
-            dialog = gtk.MessageDialog(parent = self._wizard.gui.mainWindow,
+            dialog = Gtk.MessageDialog(parent = self._wizard.gui.mainWindow,
                                        type = type, message_format = messageFormat)
-            dialog.add_button(xstr("button_ok"), RESPONSETYPE_OK)
+            dialog.add_button(xstr("button_ok"), Gtk.ResponseType.OK)
             dialog.set_title(WINDOW_TITLE_BASE)
             if secondaryMarkup is not None:
@@ -1491,13 +1490,13 @@
         dialog.hide()
 
-        if result==RESPONSETYPE_OK:
-            self._lastLoadedPIREP = text2unicode(dialog.get_filename())
+        if result==Gtk.ResponseType.OK:
+            self._lastLoadedPIREP = dialog.get_filename()
 
             pirep = PIREP.load(self._lastLoadedPIREP)
             if pirep is None:
-                dialog = gtk.MessageDialog(parent = self._mainWindow,
-                                           type = MESSAGETYPE_ERROR,
+                dialog = Gtk.MessageDialog(parent = self._mainWindow,
+                                           type = Gtk.MessageType.ERROR,
                                            message_format = xstr("loadPIREP_failed"))
-                dialog.add_button(xstr("button_ok"), RESPONSETYPE_OK)
+                dialog.add_button(xstr("button_ok"), Gtk.ResponseType.OK)
                 dialog.set_title(WINDOW_TITLE_BASE)
                 dialog.format_secondary_markup(xstr("loadPIREP_failed_sec"))
@@ -1510,5 +1509,5 @@
                     result = dialog.run()
 
-                    if result==RESPONSETYPE_OK:
+                    if result==Gtk.ResponseType.OK:
                         self.sendPIREP(pirep)
                     elif result==1:
@@ -1524,20 +1523,20 @@
         If it is not created yet, it will be created."""
         if self._loadPIREPDialog is None:
-            dialog = gtk.FileChooserDialog(title = WINDOW_TITLE_BASE + " - " +
+            dialog = Gtk.FileChooserDialog(title = WINDOW_TITLE_BASE + " - " +
                                            xstr("loadPIREP_browser_title"),
-                                           action = FILE_CHOOSER_ACTION_OPEN,
-                                           buttons = (gtk.STOCK_CANCEL,
-                                                      RESPONSETYPE_CANCEL,
-                                                      gtk.STOCK_OK, RESPONSETYPE_OK),
+                                           action = Gtk.FileChooserAction.OPEN,
+                                           buttons = (Gtk.STOCK_CANCEL,
+                                                      Gtk.ResponseType.CANCEL,
+                                                      Gtk.STOCK_OK, Gtk.ResponseType.OK),
                                            parent = self._mainWindow)
             dialog.set_modal(True)
 
 
-            filter = gtk.FileFilter()
+            filter = Gtk.FileFilter()
             filter.set_name(xstr("file_filter_pireps"))
             filter.add_pattern("*.pirep")
             dialog.add_filter(filter)
 
-            filter = gtk.FileFilter()
+            filter = Gtk.FileFilter()
             filter.set_name(xstr("file_filter_all"))
             filter.add_pattern("*.*")
@@ -1551,13 +1550,13 @@
         """Get a dialog displaying the main information of the flight from the
         PIREP and providing Cancel and Send buttons."""
-        dialog = gtk.Dialog(title = WINDOW_TITLE_BASE + " - " +
+        dialog = Gtk.Dialog(title = WINDOW_TITLE_BASE + " - " +
                             xstr("loadPIREP_send_title"),
                             parent = self._mainWindow,
-                            flags = DIALOG_MODAL)
+                            flags = Gtk.DialogFlags.MODAL)
 
         contentArea = dialog.get_content_area()
 
-        label = gtk.Label(xstr("loadPIREP_send_help"))
-        alignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
+        label = Gtk.Label(xstr("loadPIREP_send_help"))
+        alignment = Gtk.Alignment(xalign = 0.5, yalign = 0.5,
                                   xscale = 0.0, yscale = 0.0)
         alignment.set_padding(padding_top = 16, padding_bottom = 0,
@@ -1566,6 +1565,6 @@
         contentArea.pack_start(alignment, False, False, 8)
 
-        table = gtk.Table(5, 2)
-        tableAlignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
+        table = Gtk.Table(5, 2)
+        tableAlignment = Gtk.Alignment(xalign = 0.5, yalign = 0.5,
                                        xscale = 0.0, yscale = 0.0)
         tableAlignment.set_padding(padding_top = 0, padding_bottom = 32,
@@ -1578,59 +1577,59 @@
         bookedFlight = pirep.bookedFlight
 
-        label = gtk.Label("<b>" + xstr("loadPIREP_send_flightno") + "</b>")
+        label = Gtk.Label("<b>" + xstr("loadPIREP_send_flightno") + "</b>")
         label.set_use_markup(True)
-        labelAlignment = gtk.Alignment(xalign = 1.0, yalign = 0.5,
+        labelAlignment = Gtk.Alignment(xalign = 1.0, yalign = 0.5,
                                        xscale = 0.0, yscale = 0.0)
         labelAlignment.add(label)
         table.attach(labelAlignment, 0, 1, 0, 1)
 
-        label = gtk.Label(bookedFlight.callsign)
-        labelAlignment = gtk.Alignment(xalign = 0.0, yalign = 0.5,
+        label = Gtk.Label(bookedFlight.callsign)
+        labelAlignment = Gtk.Alignment(xalign = 0.0, yalign = 0.5,
                                        xscale = 0.0, yscale = 0.0)
         labelAlignment.add(label)
         table.attach(labelAlignment, 1, 2, 0, 1)
 
-        label = gtk.Label("<b>" + xstr("loadPIREP_send_date") + "</b>")
+        label = Gtk.Label("<b>" + xstr("loadPIREP_send_date") + "</b>")
         label.set_use_markup(True)
-        labelAlignment = gtk.Alignment(xalign = 1.0, yalign = 0.5,
+        labelAlignment = Gtk.Alignment(xalign = 1.0, yalign = 0.5,
                                        xscale = 0.0, yscale = 0.0)
         labelAlignment.add(label)
         table.attach(labelAlignment, 0, 1, 1, 2)
 
-        label = gtk.Label(str(bookedFlight.departureTime.date()))
-        labelAlignment = gtk.Alignment(xalign = 0.0, yalign = 0.5,
+        label = Gtk.Label(str(bookedFlight.departureTime.date()))
+        labelAlignment = Gtk.Alignment(xalign = 0.0, yalign = 0.5,
                                        xscale = 0.0, yscale = 0.0)
         labelAlignment.add(label)
         table.attach(labelAlignment, 1, 2, 1, 2)
 
-        label = gtk.Label("<b>" + xstr("loadPIREP_send_from") + "</b>")
+        label = Gtk.Label("<b>" + xstr("loadPIREP_send_from") + "</b>")
         label.set_use_markup(True)
-        labelAlignment = gtk.Alignment(xalign = 1.0, yalign = 0.5,
+        labelAlignment = Gtk.Alignment(xalign = 1.0, yalign = 0.5,
                                        xscale = 0.0, yscale = 0.0)
         labelAlignment.add(label)
         table.attach(labelAlignment, 0, 1, 2, 3)
 
-        label = gtk.Label(bookedFlight.departureICAO)
-        labelAlignment = gtk.Alignment(xalign = 0.0, yalign = 0.5,
+        label = Gtk.Label(bookedFlight.departureICAO)
+        labelAlignment = Gtk.Alignment(xalign = 0.0, yalign = 0.5,
                                        xscale = 0.0, yscale = 0.0)
         labelAlignment.add(label)
         table.attach(labelAlignment, 1, 2, 2, 3)
 
-        label = gtk.Label("<b>" + xstr("loadPIREP_send_to") + "</b>")
+        label = Gtk.Label("<b>" + xstr("loadPIREP_send_to") + "</b>")
         label.set_use_markup(True)
-        labelAlignment = gtk.Alignment(xalign = 1.0, yalign = 0.5,
+        labelAlignment = Gtk.Alignment(xalign = 1.0, yalign = 0.5,
                                        xscale = 0.0, yscale = 0.0)
         labelAlignment.add(label)
         table.attach(labelAlignment, 0, 1, 3, 4)
 
-        label = gtk.Label(bookedFlight.arrivalICAO)
-        labelAlignment = gtk.Alignment(xalign = 0.0, yalign = 0.5,
+        label = Gtk.Label(bookedFlight.arrivalICAO)
+        labelAlignment = Gtk.Alignment(xalign = 0.0, yalign = 0.5,
                                        xscale = 0.0, yscale = 0.0)
         labelAlignment.add(label)
         table.attach(labelAlignment, 1, 2, 3, 4)
 
-        label = gtk.Label("<b>" + xstr("loadPIREP_send_rating") + "</b>")
+        label = Gtk.Label("<b>" + xstr("loadPIREP_send_rating") + "</b>")
         label.set_use_markup(True)
-        labelAlignment = gtk.Alignment(xalign = 1.0, yalign = 0.5,
+        labelAlignment = Gtk.Alignment(xalign = 1.0, yalign = 0.5,
                                        xscale = 0.0, yscale = 0.0)
         labelAlignment.add(label)
@@ -1638,5 +1637,5 @@
 
         rating = pirep.rating
-        label = gtk.Label()
+        label = Gtk.Label()
         if rating<0:
             label.set_markup('<b><span foreground="red">NO GO</span></b>')
@@ -1644,12 +1643,12 @@
             label.set_text("%.1f %%" % (rating,))
 
-        labelAlignment = gtk.Alignment(xalign = 0.0, yalign = 0.5,
+        labelAlignment = Gtk.Alignment(xalign = 0.0, yalign = 0.5,
                                        xscale = 0.0, yscale = 0.0)
         labelAlignment.add(label)
         table.attach(labelAlignment, 1, 2, 4, 5)
 
-        dialog.add_button(xstr("button_cancel"), RESPONSETYPE_REJECT)
+        dialog.add_button(xstr("button_cancel"), Gtk.ResponseType.REJECT)
         dialog.add_button(xstr("viewPIREP"), 1)
-        dialog.add_button(xstr("sendPIREP"), RESPONSETYPE_OK)
+        dialog.add_button(xstr("sendPIREP"), Gtk.ResponseType.OK)
 
         return dialog
@@ -1663,5 +1662,5 @@
     def _pirepSentCallback(self, returned, result):
         """Callback for the PIREP sending result."""
-        gobject.idle_add(self._handlePIREPSent, returned, result)
+        GObject.idle_add(self._handlePIREPSent, returned, result)
 
     def _handlePIREPSent(self, returned, result):
@@ -1669,8 +1668,8 @@
         self.endBusy()
         secondaryMarkup = None
-        type = MESSAGETYPE_ERROR
+        type = Gtk.MessageType.ERROR
         if returned:
             if result.success:
-                type = MESSAGETYPE_INFO
+                type = Gtk.MessageType.INFO
                 messageFormat = xstr("sendPIREP_success")
                 secondaryMarkup = xstr("sendPIREP_success_sec")
@@ -1684,11 +1683,11 @@
                 secondaryMarkup = xstr("sendPIREP_unknown_sec")
         else:
-            print "PIREP sending failed", result
+            print("PIREP sending failed", result)
             messageFormat = xstr("sendPIREP_failed")
             secondaryMarkup = xstr("sendPIREP_failed_sec")
 
-        dialog = gtk.MessageDialog(parent = self._wizard.gui.mainWindow,
+        dialog = Gtk.MessageDialog(parent = self._wizard.gui.mainWindow,
                                    type = type, message_format = messageFormat)
-        dialog.add_button(xstr("button_ok"), RESPONSETYPE_OK)
+        dialog.add_button(xstr("button_ok"), Gtk.ResponseType.OK)
         dialog.set_title(WINDOW_TITLE_BASE)
         if secondaryMarkup is not None:
@@ -1709,5 +1708,5 @@
 
         for (timestampString, text) in self._logger.lines:
-            description += unicode(formatFlightLogLine(timestampString, text))
+            description += str(formatFlightLogLine(timestampString, text))
 
         description += "\n\n" + ("=" * 40)
@@ -1730,5 +1729,5 @@
     def _bugReportSentCallback(self, returned, result):
         """Callback function for the bug report sending result."""
-        gobject.idle_add(self._handleBugReportSent, returned, result)
+        GObject.idle_add(self._handleBugReportSent, returned, result)
 
     def _handleBugReportSent(self, returned, result):
@@ -1736,8 +1735,8 @@
         self.endBusy()
         secondaryMarkup = None
-        type = MESSAGETYPE_ERROR
+        type = Gtk.MessageType.ERROR
         if returned:
             if result.success:
-                type = MESSAGETYPE_INFO
+                type = Gtk.MessageType.INFO
                 messageFormat = xstr("sendBugReport_success") % (result.ticketID,)
                 secondaryMarkup = xstr("sendBugReport_success_sec")
@@ -1749,7 +1748,7 @@
             secondaryMarkup = xstr("sendBugReport_error_sec")
 
-        dialog = gtk.MessageDialog(parent = self._wizard.gui._bugReportDialog,
+        dialog = Gtk.MessageDialog(parent = self._wizard.gui._bugReportDialog,
                                    type = type, message_format = messageFormat)
-        dialog.add_button(xstr("button_ok"), RESPONSETYPE_OK)
+        dialog.add_button(xstr("button_ok"), Gtk.ResponseType.OK)
         dialog.set_title(WINDOW_TITLE_BASE)
         if secondaryMarkup is not None:
@@ -1796,11 +1795,11 @@
             for index in hotkeys:
                 if index==self._pilotHotkeyIndex:
-                    print "gui.GUI._handleHotkeys: pilot hotkey pressed"
+                    print("gui.GUI._handleHotkeys: pilot hotkey pressed")
                     self._flight.pilotHotkeyPressed()
                 elif index==self._checklistHotkeyIndex:
-                    print "gui.GUI._handleHotkeys: checklist hotkey pressed"
+                    print("gui.GUI._handleHotkeys: checklist hotkey pressed")
                     self._flight.checklistHotkeyPressed()
                 else:
-                    print "gui.GUI._handleHotkeys: unhandled hotkey index:", index
+                    print("gui.GUI._handleHotkeys: unhandled hotkey index:", index)
 
     def _showManual(self, menuitem):
@@ -1823,15 +1822,15 @@
         If it does not exist yet, it will be created."""
         if self._aboutDialog is None:
-            dialog = gtk.AboutDialog()
+            dialog = Gtk.AboutDialog()
             dialog.set_transient_for(self._mainWindow)
             dialog.set_modal(True)
 
             logoPath = os.path.join(self._programDirectory, "logo.png")
-            logo = pixbuf_new_from_file(logoPath)
+            logo = GdkPixbuf.Pixbuf.new_from_file(logoPath)
             dialog.set_logo(logo)
 
             dialog.set_program_name(PROGRAM_NAME)
             dialog.set_version(const.VERSION)
-            dialog.set_copyright("(c) 2012 by István Váradi")
+            dialog.set_copyright("(c) 2012 - 2019 by István Váradi")
             dialog.set_website("http://mlx.varadiistvan.hu")
             dialog.set_website_label(xstr("about_website"))
@@ -1849,7 +1848,4 @@
             dialog.set_license(xstr("about_license"))
 
-            if not pygobject:
-                gtk.about_dialog_set_url_hook(self._showAboutURL, None)
-
             self._aboutDialog = dialog
 
@@ -1875,5 +1871,5 @@
             self._credentialsAvailable = False
 
-            gobject.idle_add(self._getCredentials)
+            GObject.idle_add(self._getCredentials)
 
             while not self._credentialsAvailable:
@@ -1903,5 +1899,5 @@
             response = dialog.run()
 
-            if response==RESPONSETYPE_OK:
+            if response==Gtk.ResponseType.OK:
                 self._credentialsUserName = dialog.userName
                 self._credentialsPassword = dialog.password
@@ -1930,6 +1926,6 @@
 
         if not self.config.pilotID and not self.config.password:
-            dialog = gtk.MessageDialog(parent = self._mainWindow,
-                                       type = MESSAGETYPE_QUESTION,
+            dialog = Gtk.MessageDialog(parent = self._mainWindow,
+                                       type = Gtk.MessageType.QUESTION,
                                        message_format = xstr("register_ask"))
 
Index: src/mlx/gui/info.py
===================================================================
--- src/mlx/gui/info.py	(revision 846)
+++ src/mlx/gui/info.py	(revision 999)
@@ -1,4 +1,4 @@
 
-from common import *
+from .common import *
 
 from mlx.gui.delaycodes import DelayCodeTable
@@ -21,5 +21,5 @@
 #------------------------------------------------------------------------------
 
-class FlightInfo(gtk.VBox):
+class FlightInfo(Gtk.VBox):
     """The flight info tab."""
     @staticmethod
@@ -31,19 +31,19 @@
         - the comment text editor."""
 
-        frame = gtk.Frame(label = label)
+        frame = Gtk.Frame(label = label)
         label = frame.get_label_widget()
         label.set_use_underline(True)
 
-        alignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
+        alignment = Gtk.Alignment(xalign = 0.5, yalign = 0.5,
                                   xscale = 1.0, yscale = 1.0)
         alignment.set_padding(padding_top = 4, padding_bottom = 4,
                               padding_left = 8, padding_right = 8)
 
-        scroller = gtk.ScrolledWindow()
-        scroller.set_policy(POLICY_AUTOMATIC, POLICY_AUTOMATIC)
-        scroller.set_shadow_type(SHADOW_IN)
-
-        comments = gtk.TextView()
-        comments.set_wrap_mode(WRAP_WORD)
+        scroller = Gtk.ScrolledWindow()
+        scroller.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
+        scroller.set_shadow_type(Gtk.ShadowType.IN)
+
+        comments = Gtk.TextView()
+        comments.set_wrap_mode(Gtk.WrapMode.WORD)
         scroller.add(comments)
         alignment.add(scroller)
@@ -60,7 +60,7 @@
         self._callbackObject = callbackObject
 
-        self._commentsAlignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
+        self._commentsAlignment = Gtk.Alignment(xalign = 0.5, yalign = 0.5,
                                                 xscale = 1.0, yscale = 1.0)
-        commentsBox = gtk.HBox()
+        commentsBox = Gtk.HBox()
         commentsBox.set_homogeneous(True)
 
@@ -77,9 +77,9 @@
         self.pack_start(self._commentsAlignment, True, True, 8)
 
-        frame = gtk.Frame(label = xstr("info_delay"))
+        frame = Gtk.Frame(label = xstr("info_delay"))
         label = frame.get_label_widget()
         label.set_use_underline(True)
 
-        alignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
+        alignment = Gtk.Alignment(xalign = 0.5, yalign = 0.5,
                                   xscale = 1.0, yscale = 1.0)
         alignment.set_padding(padding_top = 4, padding_bottom = 4,
@@ -87,14 +87,15 @@
 
         self._delayCodeTable = table = DelayCodeTable(self)
-        self._delayWindow = scrolledWindow = gtk.ScrolledWindow()
+        self._delayWindow = scrolledWindow = Gtk.ScrolledWindow()
         scrolledWindow.add(table)
         scrolledWindow.set_size_request(-1, 185)
-        scrolledWindow.set_policy(POLICY_AUTOMATIC, POLICY_AUTOMATIC)
-        scrolledWindow.set_shadow_type(SHADOW_IN)
+        scrolledWindow.set_policy(Gtk.PolicyType.AUTOMATIC,
+                                  Gtk.PolicyType.AUTOMATIC)
+        scrolledWindow.set_shadow_type(Gtk.ShadowType.IN)
 
         alignment.add(scrolledWindow)
         frame.add(alignment)
 
-        self._delayAlignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
+        self._delayAlignment = Gtk.Alignment(xalign = 0.5, yalign = 0.5,
                                              xscale = 1.0, yscale = 1.0)
         self._delayAlignment.add(frame)
@@ -108,6 +109,6 @@
         """Get the comments."""
         buffer = self._comments.get_buffer()
-        return text2unicode(buffer.get_text(buffer.get_start_iter(),
-                                            buffer.get_end_iter(), True))
+        return buffer.get_text(buffer.get_start_iter(),
+                               buffer.get_end_iter(), True)
 
     @comments.setter
Index: src/mlx/gui/monitor.py
===================================================================
--- src/mlx/gui/monitor.py	(revision 765)
+++ src/mlx/gui/monitor.py	(revision 1005)
@@ -18,5 +18,5 @@
 #------------------------------------------------------------------------------
 
-class MonitorWindow(gtk.Window):
+class MonitorWindow(Gtk.Window):
     """The window for the data monitor."""
     def __init__(self, gui, iconDirectory):
@@ -32,10 +32,10 @@
                      lambda a, b: self._gui.hideMonitorWindow())
 
-        alignment = gtk.Alignment(xscale = 1.0, yscale = 1.0)
+        alignment = Gtk.Alignment(xscale = 1.0, yscale = 1.0)
 
         alignment.set_padding(padding_top = 4, padding_bottom = 10,
                               padding_left = 16, padding_right = 16)
 
-        table = gtk.Table(rows = 9, columns = 14)
+        table = Gtk.Table(rows = 9, columns = 14)
         table.set_homogeneous(False)
         table.set_row_spacings(4)
@@ -46,20 +46,20 @@
         table.attach(self._timestamp, 1, 2, 0, 1)
 
-        self._paused = gtk.Label("PAUSED")
+        self._paused = Gtk.Label("PAUSED")
         table.attach(self._paused, 2, 4, 0, 1)
 
-        self._trickMode = gtk.Label("TRICKMODE")
+        self._trickMode = Gtk.Label("TRICKMODE")
         table.attach(self._trickMode, 4, 6, 0, 1, xoptions = 0)
 
-        self._overspeed = gtk.Label("OVERSPEED")
+        self._overspeed = Gtk.Label("OVERSPEED")
         table.attach(self._overspeed, 6, 8, 0, 1)
 
-        self._stalled = gtk.Label("STALLED")
+        self._stalled = Gtk.Label("STALLED")
         table.attach(self._stalled, 8, 10, 0, 1)
 
-        self._onTheGround = gtk.Label("ONTHEGROUND")
+        self._onTheGround = Gtk.Label("ONTHEGROUND")
         table.attach(self._onTheGround, 10, 11, 0, 1)
 
-        self._antiIceOn = gtk.Label("ANTI-ICE")
+        self._antiIceOn = Gtk.Label("ANTI-ICE")
         table.attach(self._antiIceOn, 11, 12, 0, 1)
 
@@ -128,9 +128,9 @@
         table.attach(self._squawk, 7, 8, 3, 4)
 
-        (label, self._nav1) = self._createLabeledEntry("NAV1:", 5)
+        (label, self._nav1) = self._createLabeledEntry("NAV1:", 6)
         table.attach(label, 8, 9, 3, 4)
         table.attach(self._nav1, 9, 10, 3, 4)
 
-        (label, self._nav2) = self._createLabeledEntry("NAV2:", 5)
+        (label, self._nav2) = self._createLabeledEntry("NAV2:", 6)
         table.attach(label, 10, 11, 3, 4)
         table.attach(self._nav2, 11, 12, 3, 4)
@@ -148,29 +148,29 @@
         table.attach(self._reverser, 9, 12, 4, 5)
 
-        self._navLightsOn = gtk.Label("NAV")
+        self._navLightsOn = Gtk.Label("NAV")
         table.attach(self._navLightsOn, 0, 1, 5, 6)
 
-        self._antiCollisionLightsOn = gtk.Label("ANTICOLLISION")
+        self._antiCollisionLightsOn = Gtk.Label("ANTICOLLISION")
         table.attach(self._antiCollisionLightsOn, 1, 2, 5, 6)
 
-        self._strobeLightsOn = gtk.Label("STROBE")
+        self._strobeLightsOn = Gtk.Label("STROBE")
         table.attach(self._strobeLightsOn, 2, 3, 5, 6)
 
-        self._landingLightsOn = gtk.Label("LANDING")
+        self._landingLightsOn = Gtk.Label("LANDING")
         table.attach(self._landingLightsOn, 3, 4, 5, 6)
 
-        self._pitotHeatOn = gtk.Label("PITOT HEAT")
+        self._pitotHeatOn = Gtk.Label("PITOT HEAT")
         table.attach(self._pitotHeatOn, 4, 5, 5, 6)
 
-        self._parking = gtk.Label("PARKING")
+        self._parking = Gtk.Label("PARKING")
         table.attach(self._parking, 5, 6, 5, 6)
 
-        self._gearControlDown = gtk.Label("GEAR LEVER DOWN")
+        self._gearControlDown = Gtk.Label("GEAR LEVER DOWN")
         table.attach(self._gearControlDown, 6, 8, 5, 6)
 
-        self._gearsDown = gtk.Label("GEARS DOWN")
+        self._gearsDown = Gtk.Label("GEARS DOWN")
         table.attach(self._gearsDown, 8, 10, 5, 6)
 
-        self._spoilersArmed = gtk.Label("SPOILERS ARMED")
+        self._spoilersArmed = Gtk.Label("SPOILERS ARMED")
         table.attach(self._spoilersArmed, 10, 12, 5, 6)
 
@@ -195,8 +195,8 @@
         table.attach(self._elevatorTrim, 11, 12, 6, 7)
 
-        self._apMaster = gtk.Label("AP MASTER")
+        self._apMaster = Gtk.Label("AP MASTER")
         table.attach(self._apMaster, 0, 1, 7, 8)
 
-        self._apHeadingHold = gtk.Label("AP HDG HOLD")
+        self._apHeadingHold = Gtk.Label("AP HDG HOLD")
         table.attach(self._apHeadingHold, 1, 2, 7, 8)
 
@@ -205,8 +205,8 @@
         table.attach(self._apHeading, 3, 4, 7, 8)
 
-        self._xpdrC = gtk.Label("XPDR C")
+        self._xpdrC = Gtk.Label("XPDR C")
         table.attach(self._xpdrC, 4, 5, 7, 8)
 
-        self._apAltitudeHold = gtk.Label("AP ALT HOLD")
+        self._apAltitudeHold = Gtk.Label("AP ALT HOLD")
         table.attach(self._apAltitudeHold, 5, 6, 7, 8)
 
@@ -262,10 +262,10 @@
         - the entry."""
 
-        alignment = gtk.Alignment(xalign = 1.0, yalign = 0.5, xscale = 1.0)
+        alignment = Gtk.Alignment(xalign = 1.0, yalign = 0.5, xscale = 1.0)
         alignment.set_padding(padding_top = 0, padding_bottom = 0,
                               padding_left = 0, padding_right = 16)
-        alignment.add(gtk.Label(label))
-
-        entry = gtk.Entry()
+        alignment.add(Gtk.Label(label))
+
+        entry = Gtk.Entry()
         entry.set_editable(False)
         entry.set_width_chars(width)
Index: src/mlx/gui/pirep.py
===================================================================
--- src/mlx/gui/pirep.py	(revision 855)
+++ src/mlx/gui/pirep.py	(revision 999)
@@ -1,7 +1,7 @@
 
-from common import *
-from dcdata import getTable
-from info import FlightInfo
-from flight import comboModel
+from .common import *
+from .dcdata import getTable
+from .info import FlightInfo
+from .flight import comboModel
 
 from mlx.pirep import PIREP
@@ -26,5 +26,5 @@
 #------------------------------------------------------------------------------
 
-class MessageFrame(gtk.Frame):
+class MessageFrame(Gtk.Frame):
     """A frame containing the information about a PIREP message.
 
@@ -33,20 +33,21 @@
     def __init__(self, message, senderPID, senderName):
         """Construct the frame."""
-        gtk.Frame.__init__(self)
-
-        vbox = gtk.VBox()
-
-        self._heading = heading = gtk.TextView()
+        Gtk.Frame.__init__(self)
+
+        vbox = Gtk.VBox()
+
+        self._heading = heading = Gtk.TextView()
         heading.set_editable(False)
         heading.set_can_focus(False)
-        heading.set_wrap_mode(WRAP_WORD)
+        heading.set_wrap_mode(Gtk.WrapMode.WORD)
+        heading.set_size_request(-1, 16)
 
         buffer = heading.get_buffer()
-        self._headingTag  = buffer.create_tag("heading", weight=WEIGHT_BOLD)
+        self._headingTag  = buffer.create_tag("heading", weight=Pango.Weight.BOLD)
         buffer.set_text("%s - %s" % (senderPID, senderName))
         buffer.apply_tag(self._headingTag,
                          buffer.get_start_iter(), buffer.get_end_iter())
 
-        headingAlignment = gtk.Alignment(xalign = 0.0, yalign = 0.0,
+        headingAlignment = Gtk.Alignment(xalign = 0.0, yalign = 0.0,
                                          xscale = 1.0, yscale = 0.0)
         headingAlignment.set_padding(padding_top = 0, padding_bottom = 0,
@@ -55,6 +56,8 @@
         vbox.pack_start(headingAlignment, True, True, 4)
 
-        self._messageView = messageView = gtk.TextView()
-        messageView.set_wrap_mode(WRAP_WORD)
+        self._messageView = messageView = Gtk.TextView()
+        messageView.set_wrap_mode(Gtk.WrapMode.WORD)
+        messageView.set_editable(False)
+        messageView.set_can_focus(False)
         messageView.set_accepts_tab(False)
         messageView.set_size_request(-1, 60)
@@ -68,16 +71,12 @@
         self.show_all()
 
-        if pygobject:
-            styleContext = self.get_style_context()
-            color = styleContext.get_background_color(gtk.StateFlags.NORMAL)
-            heading.override_background_color(0, color)
-        else:
-            style = self.rc_get_style()
-            heading.modify_base(0, style.bg[0])
+        styleContext = self.get_style_context()
+        color = styleContext.get_background_color(Gtk.StateFlags.NORMAL)
+        heading.override_background_color(0, color)
 
 
 #-------------------------------------------------------------------------------
 
-class MessagesWidget(gtk.Frame):
+class MessagesWidget(Gtk.Frame):
     """The widget for the messages."""
     @staticmethod
@@ -87,5 +86,5 @@
 
     def __init__(self, gui):
-        gtk.Frame.__init__(self)
+        Gtk.Frame.__init__(self)
 
         self._gui = gui
@@ -94,16 +93,16 @@
         label.set_use_underline(True)
 
-        alignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
+        alignment = Gtk.Alignment(xalign = 0.5, yalign = 0.5,
                                   xscale = 1.0, yscale = 1.0)
         alignment.set_padding(padding_top = 4, padding_bottom = 4,
                               padding_left = 4, padding_right = 4)
 
-        self._outerBox = outerBox = gtk.EventBox()
+        self._outerBox = outerBox = Gtk.EventBox()
         outerBox.add(alignment)
 
-        self._innerBox = innerBox = gtk.EventBox()
+        self._innerBox = innerBox = Gtk.EventBox()
         alignment.add(self._innerBox)
 
-        alignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
+        alignment = Gtk.Alignment(xalign = 0.5, yalign = 0.5,
                                   xscale = 1.0, yscale = 1.0)
         alignment.set_padding(padding_top = 0, padding_bottom = 0,
@@ -112,9 +111,9 @@
         innerBox.add(alignment)
 
-        scroller = gtk.ScrolledWindow()
-        scroller.set_policy(POLICY_AUTOMATIC, POLICY_AUTOMATIC)
-        scroller.set_shadow_type(SHADOW_NONE)
-
-        self._messages = gtk.VBox()
+        scroller = Gtk.ScrolledWindow()
+        scroller.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
+        scroller.set_shadow_type(Gtk.ShadowType.NONE)
+
+        self._messages = Gtk.VBox()
         self._messages.set_homogeneous(False)
         scroller.add_with_viewport(self._messages)
@@ -130,5 +129,5 @@
         """Add a message from the given sender."""
 
-        alignment = gtk.Alignment(xalign = 0.0, yalign = 0.0,
+        alignment = Gtk.Alignment(xalign = 0.0, yalign = 0.0,
                                       xscale = 1.0, yscale = 0.0)
         alignment.set_padding(padding_top = 2, padding_bottom = 2,
@@ -155,5 +154,5 @@
 #------------------------------------------------------------------------------
 
-class PIREPViewer(gtk.Dialog):
+class PIREPViewer(Gtk.Dialog):
     """The dialog for PIREP viewing."""
     @staticmethod
@@ -168,12 +167,12 @@
         - the frame,
         - the inner VBox."""
-        frame = gtk.Frame(label = label)
-
-        alignment = gtk.Alignment(xalign = 0.0, yalign = 0.0,
+        frame = Gtk.Frame(label = label)
+
+        alignment = Gtk.Alignment(xalign = 0.0, yalign = 0.0,
                                   xscale = 1.0, yscale = 1.0)
         frame.add(alignment)
         alignment.set_padding(padding_top = 4, padding_bottom = 4,
                               padding_left = 4, padding_right = 4)
-        box = gtk.VBox()
+        box = Gtk.VBox()
         alignment.add(box)
 
@@ -183,5 +182,5 @@
     def getLabel(text, extraText = ""):
         """Get a bold label with the given text."""
-        label = gtk.Label("<b>" + text + "</b>" + extraText)
+        label = Gtk.Label("<b>" + text + "</b>" + extraText)
         label.set_use_markup(True)
         label.set_alignment(0.0, 0.5)
@@ -191,5 +190,5 @@
     def getDataLabel(width = None, xAlignment = 0.0):
         """Get a bold label with the given text."""
-        label = gtk.Label()
+        label = Gtk.Label()
         if width is not None:
             label.set_width_chars(width)
@@ -204,10 +203,11 @@
         - the window,
         - the text view."""
-        scrolledWindow = gtk.ScrolledWindow()
-        scrolledWindow.set_shadow_type(SHADOW_IN)
-        scrolledWindow.set_policy(POLICY_AUTOMATIC, POLICY_AUTOMATIC)
-
-        textView = gtk.TextView()
-        textView.set_wrap_mode(WRAP_WORD)
+        scrolledWindow = Gtk.ScrolledWindow()
+        scrolledWindow.set_shadow_type(Gtk.ShadowType.IN)
+        scrolledWindow.set_policy(Gtk.PolicyType.AUTOMATIC,
+                                  Gtk.PolicyType.AUTOMATIC)
+
+        textView = Gtk.TextView()
+        textView.set_wrap_mode(Gtk.WrapMode.WORD)
         textView.set_editable(editable)
         textView.set_cursor_visible(editable)
@@ -227,5 +227,5 @@
 
         Returns the data label attached."""
-        dataBox = gtk.HBox()
+        dataBox = Gtk.HBox()
         table.attach(dataBox, column, column+1, row, row+1)
 
@@ -252,5 +252,5 @@
     def addHFiller(hBox, width = 8):
         """Add a filler to the given horizontal box."""
-        filler = gtk.Alignment(xalign = 0.0, yalign = 0.0,
+        filler = Gtk.Alignment(xalign = 0.0, yalign = 0.0,
                                xscale = 1.0, yscale = 1.0)
         filler.set_size_request(width, -1)
@@ -260,5 +260,5 @@
     def addVFiller(vBox, height = 4):
         """Add a filler to the given vertical box."""
-        filler = gtk.Alignment(xalign = 0.0, yalign = 0.0,
+        filler = Gtk.Alignment(xalign = 0.0, yalign = 0.0,
                                xscale = 1.0, yscale = 1.0)
         filler.set_size_request(-1, height)
@@ -285,9 +285,9 @@
         contentArea = self.get_content_area()
 
-        self._notebook = gtk.Notebook()
+        self._notebook = Gtk.Notebook()
         contentArea.pack_start(self._notebook, False, False, 4)
 
         dataTab = self._buildDataTab()
-        label = gtk.Label(xstr("pirepView_tab_data"))
+        label = Gtk.Label(xstr("pirepView_tab_data"))
         label.set_use_underline(True)
         label.set_tooltip_text(xstr("pirepView_tab_data_tooltip"))
@@ -295,5 +295,5 @@
 
         commentsTab = self._buildCommentsTab()
-        label = gtk.Label(xstr("pirepView_tab_comments"))
+        label = Gtk.Label(xstr("pirepView_tab_comments"))
         label.set_use_underline(True)
         label.set_tooltip_text(xstr("pirepView_tab_comments_tooltip"))
@@ -301,5 +301,5 @@
 
         logTab = self._buildLogTab()
-        label = gtk.Label(xstr("pirepView_tab_log"))
+        label = Gtk.Label(xstr("pirepView_tab_log"))
         label.set_use_underline(True)
         label.set_tooltip_text(xstr("pirepView_tab_log_tooltip"))
@@ -309,10 +309,10 @@
         if showMessages:
             messagesTab = self._buildMessagesTab()
-            label = gtk.Label(xstr("pirepView_tab_messages"))
+            label = Gtk.Label(xstr("pirepView_tab_messages"))
             label.set_use_underline(True)
             label.set_tooltip_text(xstr("pirepView_tab_messages_tooltip"))
             self._notebook.append_page(messagesTab, label)
 
-        self._okButton = self.add_button(xstr("button_ok"), RESPONSETYPE_OK)
+        self._okButton = self.add_button(xstr("button_ok"), Gtk.ResponseType.OK)
         self._okButton.set_can_default(True)
 
@@ -418,13 +418,13 @@
     def _buildDataTab(self):
         """Build the data tab of the viewer."""
-        table = gtk.Table(1, 2)
+        table = Gtk.Table(1, 2)
         table.set_row_spacings(4)
         table.set_col_spacings(16)
         table.set_homogeneous(True)
 
-        box1 = gtk.VBox()
+        box1 = Gtk.VBox()
         table.attach(box1, 0, 1, 0, 1)
 
-        box2 = gtk.VBox()
+        box2 = Gtk.VBox()
         table.attach(box2, 1, 2, 0, 1)
 
@@ -454,5 +454,5 @@
         (frame, mainBox) = PIREPViewer.createFrame(xstr("pirepView_frame_flight"))
 
-        dataBox = gtk.HBox()
+        dataBox = Gtk.HBox()
         mainBox.pack_start(dataBox, False, False, 0)
 
@@ -469,5 +469,5 @@
         PIREPViewer.addVFiller(mainBox)
 
-        dataBox = gtk.HBox()
+        dataBox = Gtk.HBox()
         mainBox.pack_start(dataBox, False, False, 0)
 
@@ -479,5 +479,5 @@
         PIREPViewer.addVFiller(mainBox)
 
-        table = gtk.Table(3, 2)
+        table = Gtk.Table(3, 2)
         mainBox.pack_start(table, False, False, 0)
         table.set_row_spacings(4)
@@ -504,5 +504,5 @@
                                     width = 6)
 
-        table = gtk.Table(3, 2)
+        table = Gtk.Table(3, 2)
         mainBox.pack_start(table, False, False, 0)
         table.set_row_spacings(4)
@@ -550,5 +550,5 @@
         (frame, mainBox) = PIREPViewer.createFrame(xstr("pirepView_frame_route"))
 
-        levelBox = gtk.HBox()
+        levelBox = Gtk.HBox()
         mainBox.pack_start(levelBox, False, False, 0)
 
@@ -582,5 +582,5 @@
         PIREPViewer.addVFiller(mainBox)
 
-        dataBox = gtk.HBox()
+        dataBox = Gtk.HBox()
         mainBox.pack_start(dataBox, False, False, 0)
 
@@ -609,5 +609,5 @@
         PIREPViewer.addVFiller(mainBox)
 
-        table = gtk.Table(2, 2)
+        table = Gtk.Table(2, 2)
         mainBox.pack_start(table, False, False, 0)
         table.set_row_spacings(4)
@@ -640,5 +640,5 @@
         (frame, mainBox) = PIREPViewer.createFrame(xstr("pirepView_frame_statistics"))
 
-        table = gtk.Table(4, 2)
+        table = Gtk.Table(4, 2)
         mainBox.pack_start(table, False, False, 0)
         table.set_row_spacings(4)
@@ -686,5 +686,5 @@
         (frame, mainBox) = PIREPViewer.createFrame(xstr("pirepView_frame_miscellaneous"))
 
-        table = gtk.Table(3, 2)
+        table = Gtk.Table(3, 2)
         mainBox.pack_start(table, False, False, 0)
         table.set_row_spacings(4)
@@ -738,5 +738,5 @@
     def _buildCommentsTab(self):
         """Build the tab with the comments and flight defects."""
-        table = gtk.Table(2, 1)
+        table = Gtk.Table(2, 1)
         table.set_col_spacings(16)
 
@@ -761,5 +761,5 @@
     def _buildLogTab(self):
         """Build the log tab."""
-        mainBox = gtk.VBox()
+        mainBox = Gtk.VBox()
 
         (logWindow, self._log) = PIREPViewer.getTextWindow(heightRequest = -1)
@@ -771,5 +771,5 @@
     def _buildMessagesTab(self):
         """Build the messages tab."""
-        mainBox = gtk.VBox()
+        mainBox = Gtk.VBox()
 
         self._messages = MessagesWidget(self._gui)
@@ -780,5 +780,5 @@
 #------------------------------------------------------------------------------
 
-class PIREPEditor(gtk.Dialog):
+class PIREPEditor(Gtk.Dialog):
     """A PIREP editor dialog."""
     _delayCodeRE = re.compile("([0-9]{2,3})( \([^\)]*\))")
@@ -790,7 +790,7 @@
         The label will got to cell (column, row), the widget to cell
         (column+1, row)."""
-        label = gtk.Label("<b>" + labelText + "</b>")
+        label = Gtk.Label("<b>" + labelText + "</b>")
         label.set_use_markup(True)
-        alignment = gtk.Alignment(xalign = 0.0, yalign = 0.5,
+        alignment = Gtk.Alignment(xalign = 0.0, yalign = 0.5,
                                   xscale = 0.0, yscale = 0.0)
         alignment.add(label)
@@ -808,5 +808,5 @@
         The label will got to cell (column, row), the spin button to cell
         (column+1, row)."""
-        button = gtk.SpinButton()
+        button = Gtk.SpinButton()
         button.set_range(min = minValue, max = maxValue)
         button.set_increments(step = stepIncrement, page = pageIncrement)
@@ -848,9 +848,9 @@
         contentArea = self.get_content_area()
 
-        self._notebook = gtk.Notebook()
+        self._notebook = Gtk.Notebook()
         contentArea.pack_start(self._notebook, False, False, 4)
 
         dataTab = self._buildDataTab()
-        label = gtk.Label(xstr("pirepView_tab_data"))
+        label = Gtk.Label(xstr("pirepView_tab_data"))
         label.set_use_underline(True)
         label.set_tooltip_text(xstr("pirepView_tab_data_tooltip"))
@@ -858,5 +858,5 @@
 
         self._flightInfo = self._buildCommentsTab()
-        label = gtk.Label(xstr("pirepView_tab_comments"))
+        label = Gtk.Label(xstr("pirepView_tab_comments"))
         label.set_use_underline(True)
         label.set_tooltip_text(xstr("pirepView_tab_comments_tooltip"))
@@ -864,12 +864,12 @@
 
         logTab = self._buildLogTab()
-        label = gtk.Label(xstr("pirepView_tab_log"))
+        label = Gtk.Label(xstr("pirepView_tab_log"))
         label.set_use_underline(True)
         label.set_tooltip_text(xstr("pirepView_tab_log_tooltip"))
         self._notebook.append_page(logTab, label)
 
-        self.add_button(xstr("button_cancel"), RESPONSETYPE_CANCEL)
-
-        self._okButton = self.add_button(xstr("button_save"), RESPONSETYPE_NONE)
+        self.add_button(xstr("button_cancel"), Gtk.ResponseType.CANCEL)
+
+        self._okButton = self.add_button(xstr("button_save"), Gtk.ResponseType.NONE)
         self._okButton.connect("clicked", self._okClicked)
         self._okButton.set_can_default(True)
@@ -1015,13 +1015,13 @@
     def _buildDataTab(self):
         """Build the data tab of the viewer."""
-        table = gtk.Table(1, 2)
+        table = Gtk.Table(1, 2)
         table.set_row_spacings(4)
         table.set_col_spacings(16)
         table.set_homogeneous(True)
 
-        box1 = gtk.VBox()
+        box1 = Gtk.VBox()
         table.attach(box1, 0, 1, 0, 1)
 
-        box2 = gtk.VBox()
+        box2 = Gtk.VBox()
         table.attach(box2, 1, 2, 0, 1)
 
@@ -1051,5 +1051,5 @@
         (frame, mainBox) = PIREPViewer.createFrame(xstr("pirepView_frame_flight"))
 
-        dataBox = gtk.HBox()
+        dataBox = Gtk.HBox()
         mainBox.pack_start(dataBox, False, False, 0)
 
@@ -1066,5 +1066,5 @@
         PIREPViewer.addVFiller(mainBox)
 
-        dataBox = gtk.HBox()
+        dataBox = Gtk.HBox()
         mainBox.pack_start(dataBox, False, False, 0)
 
@@ -1076,5 +1076,5 @@
         PIREPViewer.addVFiller(mainBox)
 
-        table = gtk.Table(3, 2)
+        table = Gtk.Table(3, 2)
         mainBox.pack_start(table, False, False, 0)
         table.set_row_spacings(4)
@@ -1101,5 +1101,5 @@
                                     width = 6)
 
-        table = gtk.Table(3, 2)
+        table = Gtk.Table(3, 2)
         mainBox.pack_start(table, False, False, 0)
         table.set_row_spacings(4)
@@ -1146,5 +1146,5 @@
         (frame, mainBox) = PIREPViewer.createFrame(xstr("pirepView_frame_route"))
 
-        levelBox = gtk.HBox()
+        levelBox = Gtk.HBox()
         mainBox.pack_start(levelBox, False, False, 0)
 
@@ -1153,5 +1153,5 @@
         levelBox.pack_start(label, False, False, 0)
 
-        self._filedCruiseLevel = gtk.SpinButton()
+        self._filedCruiseLevel = Gtk.SpinButton()
         self._filedCruiseLevel.set_increments(step = 10, page = 100)
         self._filedCruiseLevel.set_range(min = 0, max = 500)
@@ -1168,5 +1168,5 @@
         levelBox.pack_start(label, False, False, 0)
 
-        self._modifiedCruiseLevel = gtk.SpinButton()
+        self._modifiedCruiseLevel = Gtk.SpinButton()
         self._modifiedCruiseLevel.set_increments(step = 10, page = 100)
         self._modifiedCruiseLevel.set_range(min = 0, max = 500)
@@ -1202,13 +1202,13 @@
         PIREPViewer.addVFiller(mainBox)
 
-        dataBox = gtk.HBox()
+        dataBox = Gtk.HBox()
         mainBox.pack_start(dataBox, False, False, 0)
 
-        label = gtk.Label("<b>" + xstr("pirepView_runway") + "</b>")
+        label = Gtk.Label("<b>" + xstr("pirepView_runway") + "</b>")
         label.set_use_markup(True)
         dataBox.pack_start(label, False, False, 0)
 
         # FIXME: quite the same as the runway entry boxes in the wizard
-        self._departureRunway = gtk.Entry()
+        self._departureRunway = Gtk.Entry()
         self._departureRunway.set_width_chars(5)
         self._departureRunway.set_tooltip_text(xstr("takeoff_runway_tooltip"))
@@ -1216,5 +1216,5 @@
         dataBox.pack_start(self._departureRunway, False, False, 8)
 
-        label = gtk.Label("<b>" + xstr("pirepView_sid") + "</b>")
+        label = Gtk.Label("<b>" + xstr("pirepView_sid") + "</b>")
         label.set_use_markup(True)
         dataBox.pack_start(label, False, False, 0)
@@ -1222,8 +1222,5 @@
         # FIXME: quite the same as the SID combo box in
         # the flight wizard
-        if pygobject:
-            self._sid = gtk.ComboBox.new_with_model_and_entry(comboModel)
-        else:
-            self._sid = gtk.ComboBoxEntry(comboModel)
+        self._sid = Gtk.ComboBox.new_with_model_and_entry(comboModel)
 
         self._sid.set_entry_text_column(0)
@@ -1251,5 +1248,5 @@
         PIREPViewer.addVFiller(mainBox)
 
-        table = gtk.Table(2, 4)
+        table = Gtk.Table(2, 4)
         mainBox.pack_start(table, False, False, 0)
         table.set_row_spacings(4)
@@ -1257,8 +1254,5 @@
 
         # FIXME: quite the same as in the wizard
-        if pygobject:
-            self._star = gtk.ComboBox.new_with_model_and_entry(comboModel)
-        else:
-            self._star = gtk.ComboBoxEntry(comboModel)
+        self._star = Gtk.ComboBox.new_with_model_and_entry(comboModel)
 
         self._star.set_entry_text_column(0)
@@ -1272,8 +1266,5 @@
 
         # FIXME: quite the same as in the wizard
-        if pygobject:
-            self._transition = gtk.ComboBox.new_with_model_and_entry(comboModel)
-        else:
-            self._transition = gtk.ComboBoxEntry(comboModel)
+        self._transition = Gtk.ComboBox.new_with_model_and_entry(comboModel)
 
         self._transition.set_entry_text_column(0)
@@ -1288,5 +1279,5 @@
 
         # FIXME: quite the same as in the wizard
-        self._approachType = gtk.Entry()
+        self._approachType = Gtk.Entry()
         self._approachType.set_width_chars(10)
         self._approachType.set_tooltip_text(xstr("landing_approach_tooltip"))
@@ -1298,5 +1289,5 @@
 
         # FIXME: quite the same as in the wizard
-        self._arrivalRunway = gtk.Entry()
+        self._arrivalRunway = Gtk.Entry()
         self._arrivalRunway.set_width_chars(10)
         self._arrivalRunway.set_tooltip_text(xstr("landing_runway_tooltip"))
@@ -1313,5 +1304,5 @@
         (frame, mainBox) = PIREPViewer.createFrame(xstr("pirepView_frame_statistics"))
 
-        table = gtk.Table(4, 4)
+        table = Gtk.Table(4, 4)
         mainBox.pack_start(table, False, False, 0)
         table.set_row_spacings(4)
@@ -1365,5 +1356,5 @@
         (frame, mainBox) = PIREPViewer.createFrame(xstr("pirepView_frame_miscellaneous"))
 
-        table = gtk.Table(6, 2)
+        table = Gtk.Table(6, 2)
         mainBox.pack_start(table, False, False, 0)
         table.set_row_spacings(4)
@@ -1413,5 +1404,5 @@
         self._flightType.set_tooltip_text(xstr("pirepEdit_flight_type_tooltip"))
 
-        self._online = gtk.CheckButton(xstr("pirepEdit_online"))
+        self._online = Gtk.CheckButton(xstr("pirepEdit_online"))
         table.attach(self._online, 2, 3, 2, 3)
         self._online.connect("toggled", self._updateButtons)
@@ -1435,5 +1426,5 @@
     def _buildLogTab(self):
         """Build the log tab."""
-        mainBox = gtk.VBox()
+        mainBox = Gtk.VBox()
 
         (logWindow, self._log) = PIREPViewer.getTextWindow(heightRequest = -1)
@@ -1522,5 +1513,5 @@
         The PIREP is updated from the data in the window."""
         if not askYesNo(xstr("pirepEdit_save_question"), parent = self):
-            self.response(RESPONSETYPE_CANCEL)
+            self.response(Gtk.ResponseType.CANCEL)
 
         pirep = self._pirep
@@ -1569,5 +1560,5 @@
         pirep.flightDefects = self._flightInfo.faultsAndExplanations
 
-        self.response(RESPONSETYPE_OK)
+        self.response(Gtk.ResponseType.OK)
 
 
Index: src/mlx/gui/prefs.py
===================================================================
--- src/mlx/gui/prefs.py	(revision 738)
+++ src/mlx/gui/prefs.py	(revision 999)
@@ -1,4 +1,4 @@
 
-from common import *
+from .common import *
 
 from mlx.i18n import xstr
@@ -6,5 +6,5 @@
 import mlx.config as config
 
-import urlparse
+import urllib.parse
 
 #------------------------------------------------------------------------------
@@ -20,5 +20,5 @@
 #------------------------------------------------------------------------------
 
-class Hotkey(gtk.HBox):
+class Hotkey(Gtk.HBox):
     """A widget to handle a hotkey."""
 
@@ -43,7 +43,7 @@
         super(Hotkey, self).__init__()
 
-        label = gtk.Label(labelText)
+        label = Gtk.Label(labelText)
         label.set_use_underline(True)
-        labelAlignment = gtk.Alignment(xalign = 0.0, yalign = 0.5,
+        labelAlignment = Gtk.Alignment(xalign = 0.0, yalign = 0.5,
                                        xscale = 0.0, yscale = 0.0)
         labelAlignment.set_padding(padding_top = 0, padding_bottom = 0,
@@ -52,20 +52,20 @@
         self.pack_start(labelAlignment, False, False, 0)
 
-        self._ctrl = gtk.CheckButton("Ctrl")
+        self._ctrl = Gtk.CheckButton("Ctrl")
         self._ctrl.set_tooltip_text(tooltips[1])
         self._ctrl.connect("toggled", self._ctrlToggled)
         self.pack_start(self._ctrl, False, False, 4)
 
-        self._shift = gtk.CheckButton("Shift")
+        self._shift = Gtk.CheckButton("Shift")
         self._shift.set_tooltip_text(tooltips[2])
         self._shift.connect("toggled", self._shiftToggled)
         self.pack_start(self._shift, False, False, 4)
 
-        self._hotkeyModel = gtk.ListStore(str)
-        for keyCode in range(ord("0"), ord("9")+1) + range(ord("A"), ord("Z")+1):
+        self._hotkeyModel = Gtk.ListStore(str)
+        for keyCode in list(range(ord("0"), ord("9")+1)) + list(range(ord("A"), ord("Z")+1)):
             self._hotkeyModel.append([chr(keyCode)])
 
-        self._hotkey = gtk.ComboBox(model = self._hotkeyModel)
-        cell = gtk.CellRendererText()
+        self._hotkey = Gtk.ComboBox(model = self._hotkeyModel)
+        cell = Gtk.CellRendererText()
         self._hotkey.pack_start(cell, True)
         self._hotkey.add_attribute(cell, 'text', 0)
@@ -161,10 +161,10 @@
 #------------------------------------------------------------------------------
 
-gobject.signal_new("hotkey-changed", Hotkey, gobject.SIGNAL_RUN_FIRST,
+GObject.signal_new("hotkey-changed", Hotkey, GObject.SIGNAL_RUN_FIRST,
                    None, (int,))
 
 #------------------------------------------------------------------------------
 
-class Preferences(gtk.Dialog):
+class Preferences(Gtk.Dialog):
     """The preferences dialog."""
     def __init__(self, gui):
@@ -173,8 +173,8 @@
                                           xstr("prefs_title"),
                                           gui.mainWindow,
-                                          DIALOG_MODAL)
-
-        self.add_button(xstr("button_cancel"), RESPONSETYPE_REJECT)
-        self.add_button(xstr("button_ok"), RESPONSETYPE_ACCEPT)
+                                          Gtk.DialogFlags.MODAL)
+
+        self.add_button(xstr("button_cancel"), Gtk.ResponseType.REJECT)
+        self.add_button(xstr("button_ok"), Gtk.ResponseType.ACCEPT)
         self.set_resizable(False)
 
@@ -184,9 +184,9 @@
         contentArea = self.get_content_area()
 
-        notebook = gtk.Notebook()
+        notebook = Gtk.Notebook()
         contentArea.pack_start(notebook, True, True, 4)
 
         general = self._buildGeneral()
-        label = gtk.Label(xstr("prefs_tab_general"))
+        label = Gtk.Label(xstr("prefs_tab_general"))
         label.set_use_underline(True)
         label.set_tooltip_text(xstr("prefs_tab_general_tooltip"))
@@ -194,5 +194,5 @@
 
         messages = self._buildMessages()
-        label = gtk.Label(xstr("prefs_tab_messages"))
+        label = Gtk.Label(xstr("prefs_tab_messages"))
         label.set_use_underline(True)
         label.set_tooltip_text(xstr("prefs_tab_message_tooltip"))
@@ -200,5 +200,5 @@
 
         sounds = self._buildSounds()
-        label = gtk.Label(xstr("prefs_tab_sounds"))
+        label = Gtk.Label(xstr("prefs_tab_sounds"))
         label.set_use_underline(True)
         label.set_tooltip_text(xstr("prefs_tab_sounds_tooltip"))
@@ -206,5 +206,5 @@
 
         advanced = self._buildAdvanced()
-        label = gtk.Label(xstr("prefs_tab_advanced"))
+        label = Gtk.Label(xstr("prefs_tab_advanced"))
         label.set_use_underline(True)
         label.set_tooltip_text(xstr("prefs_tab_advanced_tooltip"))
@@ -222,5 +222,5 @@
         self.hide()
 
-        if response==RESPONSETYPE_ACCEPT:
+        if response==Gtk.ResponseType.ACCEPT:
             self._toConfig(config)
             config.save()
@@ -296,5 +296,5 @@
                                                        self._vsSmoothingLength)
         config.useSimBrief = self._useSimBrief.get_active()
-        config.pirepDirectory = text2unicode(self._pirepDirectory.get_text())
+        config.pirepDirectory = self._pirepDirectory.get_text()
         config.pirepAutoSave = self._pirepAutoSave.get_active()
 
@@ -326,22 +326,22 @@
     def _buildGeneral(self):
         """Build the page for the general settings."""
-        mainAlignment = gtk.Alignment(xalign = 0.0, yalign = 0.0,
+        mainAlignment = Gtk.Alignment(xalign = 0.0, yalign = 0.0,
                                       xscale = 1.0, yscale = 0.0)
         mainAlignment.set_padding(padding_top = 0, padding_bottom = 8,
                                   padding_left = 4, padding_right = 4)
-        mainBox = gtk.VBox()
+        mainBox = Gtk.VBox()
         mainAlignment.add(mainBox)
 
         guiBox = self._createFrame(mainBox, xstr("prefs_frame_gui"))
 
-        languageBox = gtk.HBox()
+        languageBox = Gtk.HBox()
         guiBox.pack_start(languageBox, False, False, 4)
 
-        label = gtk.Label(xstr("prefs_language"))
+        label = Gtk.Label(xstr("prefs_language"))
         label.set_use_underline(True)
 
         languageBox.pack_start(label, False, False, 4)
 
-        self._languageList = gtk.ListStore(str, str)
+        self._languageList = Gtk.ListStore(str, str)
         for language in const.languages:
             self._languageList.append([xstr("prefs_lang_" + language),
@@ -349,6 +349,6 @@
 
         self._languageComboBox = languageComboBox = \
-            gtk.ComboBox(model = self._languageList)
-        cell = gtk.CellRendererText()
+            Gtk.ComboBox(model = self._languageList)
+        cell = Gtk.CellRendererText()
         languageComboBox.pack_start(cell, True)
         languageComboBox.add_attribute(cell, 'text', 0)
@@ -362,10 +362,10 @@
         self._warnedRestartNeeded = False
 
-        self._hideMinimizedWindow = gtk.CheckButton(xstr("prefs_hideMinimizedWindow"))
+        self._hideMinimizedWindow = Gtk.CheckButton(xstr("prefs_hideMinimizedWindow"))
         self._hideMinimizedWindow.set_use_underline(True)
         self._hideMinimizedWindow.set_tooltip_text(xstr("prefs_hideMinimizedWindow_tooltip"))
         guiBox.pack_start(self._hideMinimizedWindow, False, False, 4)
 
-        self._quitOnClose = gtk.CheckButton(xstr("prefs_quitOnClose"))
+        self._quitOnClose = Gtk.CheckButton(xstr("prefs_quitOnClose"))
         self._quitOnClose.set_use_underline(True)
         self._quitOnClose.set_tooltip_text(xstr("prefs_quitOnClose_tooltip"))
@@ -374,10 +374,10 @@
         onlineBox = self._createFrame(mainBox, xstr("prefs_frame_online"))
 
-        self._onlineGateSystem = gtk.CheckButton(xstr("prefs_onlineGateSystem"))
+        self._onlineGateSystem = Gtk.CheckButton(xstr("prefs_onlineGateSystem"))
         self._onlineGateSystem.set_use_underline(True)
         self._onlineGateSystem.set_tooltip_text(xstr("prefs_onlineGateSystem_tooltip"))
         onlineBox.pack_start(self._onlineGateSystem, False, False, 4)
 
-        self._onlineACARS = gtk.CheckButton(xstr("prefs_onlineACARS"))
+        self._onlineACARS = Gtk.CheckButton(xstr("prefs_onlineACARS"))
         self._onlineACARS.set_use_underline(True)
         self._onlineACARS.set_tooltip_text(xstr("prefs_onlineACARS_tooltip"))
@@ -386,15 +386,15 @@
         simulatorBox = self._createFrame(mainBox, xstr("prefs_frame_simulator"))
 
-        self._flareTimeFromFS = gtk.CheckButton(xstr("prefs_flaretimeFromFS"))
+        self._flareTimeFromFS = Gtk.CheckButton(xstr("prefs_flaretimeFromFS"))
         self._flareTimeFromFS.set_use_underline(True)
         self._flareTimeFromFS.set_tooltip_text(xstr("prefs_flaretimeFromFS_tooltip"))
         simulatorBox.pack_start(self._flareTimeFromFS, False, False, 4)
 
-        self._syncFSTime = gtk.CheckButton(xstr("prefs_syncFSTime"))
+        self._syncFSTime = Gtk.CheckButton(xstr("prefs_syncFSTime"))
         self._syncFSTime.set_use_underline(True)
         self._syncFSTime.set_tooltip_text(xstr("prefs_syncFSTime_tooltip"))
         simulatorBox.pack_start(self._syncFSTime, False, False, 4)
 
-        self._usingFS2Crew = gtk.CheckButton(xstr("prefs_usingFS2Crew"))
+        self._usingFS2Crew = Gtk.CheckButton(xstr("prefs_usingFS2Crew"))
         self._usingFS2Crew.set_use_underline(True)
         self._usingFS2Crew.set_tooltip_text(xstr("prefs_usingFS2Crew_tooltip"))
@@ -413,17 +413,17 @@
         simulatorBox.pack_start(vsSmoothingBox, False, False, 4)
 
-        self._useSimBrief = gtk.CheckButton(xstr("prefs_useSimBrief"))
+        self._useSimBrief = Gtk.CheckButton(xstr("prefs_useSimBrief"))
         self._useSimBrief.set_use_underline(True)
         self._useSimBrief.set_tooltip_text(xstr("prefs_useSimBrief_tooltip"))
         mainBox.pack_start(self._useSimBrief, False, False, 0)
 
-        pirepBox = gtk.HBox()
+        pirepBox = Gtk.HBox()
         mainBox.pack_start(pirepBox, False, False, 8)
 
-        label = gtk.Label(xstr("prefs_pirepDirectory"))
+        label = Gtk.Label(xstr("prefs_pirepDirectory"))
         label.set_use_underline(True)
         pirepBox.pack_start(label, False, False, 4)
 
-        self._pirepDirectory = gtk.Entry()
+        self._pirepDirectory = Gtk.Entry()
         self._pirepDirectory.set_tooltip_text(xstr("prefs_pirepDirectory_tooltip"))
         self._pirepDirectory.connect("changed", self._pirepDirectoryChanged)
@@ -431,10 +431,10 @@
         pirepBox.pack_start(self._pirepDirectory, True, True, 4)
 
-        self._pirepDirectoryButton = gtk.Button(xstr("button_browse"))
+        self._pirepDirectoryButton = Gtk.Button(xstr("button_browse"))
         self._pirepDirectoryButton.connect("clicked",
                                            self._pirepDirectoryButtonClicked)
         pirepBox.pack_start(self._pirepDirectoryButton, False, False, 4)
 
-        self._pirepAutoSave = gtk.CheckButton(xstr("prefs_pirepAutoSave"))
+        self._pirepAutoSave = Gtk.CheckButton(xstr("prefs_pirepAutoSave"))
         self._pirepAutoSave.set_use_underline(True)
         self._pirepAutoSave.set_tooltip_text(xstr("prefs_pirepAutoSave_tooltip"))
@@ -447,12 +447,12 @@
 
         Return the vbox."""
-        frame = gtk.Frame(label = label)
+        frame = Gtk.Frame(label = label)
         mainBox.pack_start(frame, False, False, 4)
-        alignment = gtk.Alignment(xalign = 0.0, yalign = 0.0,
+        alignment = Gtk.Alignment(xalign = 0.0, yalign = 0.0,
                                   xscale = 1.0, yscale = 0.0)
         alignment.set_padding(padding_top = 4, padding_bottom = 0,
                               padding_left = 0, padding_right = 0)
         frame.add(alignment)
-        vbox = gtk.VBox()
+        vbox = Gtk.VBox()
         alignment.add(vbox)
 
@@ -462,7 +462,7 @@
                             maxSeconds = 10):
         """Create a HBox that contains entry fields for smoothing some value."""
-        smoothingBox = gtk.HBox()
-
-        smoothingEnabled = gtk.CheckButton(checkBoxLabel)
+        smoothingBox = Gtk.HBox()
+
+        smoothingEnabled = Gtk.CheckButton(checkBoxLabel)
         smoothingEnabled.set_use_underline(True)
         smoothingEnabled.set_tooltip_text(checkBoxTooltip)
@@ -470,5 +470,5 @@
         smoothingBox.pack_start(smoothingEnabled, False, False, 0)
 
-        smoothingLength = gtk.SpinButton()
+        smoothingLength = Gtk.SpinButton()
         smoothingLength.set_numeric(True)
         smoothingLength.set_range(2, maxSeconds)
@@ -479,5 +479,5 @@
         smoothingBox.pack_start(smoothingLength, False, False, 0)
 
-        smoothingBox.pack_start(gtk.Label(xstr("prefs_smoothing_seconds")),
+        smoothingBox.pack_start(Gtk.Label(xstr("prefs_smoothing_seconds")),
                                 False, False, 4)
 
@@ -511,8 +511,8 @@
         """Called when the language has changed."""
         if not self._changingLanguage and not self._warnedRestartNeeded:
-            dialog = gtk.MessageDialog(parent = self,
-                                       type = MESSAGETYPE_INFO,
+            dialog = Gtk.MessageDialog(parent = self,
+                                       type = Gtk.MessageType.INFO,
                                        message_format = xstr("prefs_restart"))
-            dialog.add_button(xstr("button_ok"), RESPONSETYPE_OK)
+            dialog.add_button(xstr("button_ok"), Gtk.ResponseType.OK)
             dialog.set_title(self.get_title())
             dialog.format_secondary_markup(xstr("prefs_language_restart_sec"))
@@ -548,9 +548,9 @@
     def _pirepDirectoryButtonClicked(self, button):
         """Called when the PIREP directory button is clicked."""
-        dialog = gtk.FileChooserDialog(title = WINDOW_TITLE_BASE + " - " +
+        dialog = Gtk.FileChooserDialog(title = WINDOW_TITLE_BASE + " - " +
                                        xstr("prefs_pirepDirectory_browser_title"),
-                                       action = FILE_CHOOSER_ACTION_SELECT_FOLDER,
-                                       buttons = (gtk.STOCK_CANCEL, RESPONSETYPE_CANCEL,
-                                                  gtk.STOCK_OK, RESPONSETYPE_OK),
+                                       action = Gtk.FileChooserAction.SELECT_FOLDER,
+                                       buttons = (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
+                                                  Gtk.STOCK_OK, Gtk.ResponseType.OK),
                                        parent = self)
         dialog.set_modal(True)
@@ -564,6 +564,6 @@
         dialog.hide()
 
-        if result==RESPONSETYPE_OK:
-            self._pirepDirectory.set_text(text2unicode(dialog.get_filename()))
+        if result==Gtk.ResponseType.OK:
+            self._pirepDirectory.set_text(dialog.get_filename())
 
     def _pirepDirectoryChanged(self, entry):
@@ -578,12 +578,12 @@
         """Build the page for the message settings."""
 
-        mainAlignment = gtk.Alignment(xalign = 0.0, yalign = 0.0,
+        mainAlignment = Gtk.Alignment(xalign = 0.0, yalign = 0.0,
                                       xscale = 0.0, yscale = 0.0)
         mainAlignment.set_padding(padding_top = 16, padding_bottom = 8,
                                   padding_left = 4, padding_right = 4)
-        mainBox = gtk.VBox()
+        mainBox = Gtk.VBox()
         mainAlignment.add(mainBox)
 
-        table = gtk.Table(len(const.messageTypes) + 1, 3)
+        table = Gtk.Table(len(const.messageTypes) + 1, 3)
         table.set_row_spacings(8)
         table.set_col_spacings(32)
@@ -591,11 +591,11 @@
         mainBox.pack_start(table, False, False, 4)
 
-        label = gtk.Label(xstr("prefs_msgs_fs"))
-        label.set_justify(JUSTIFY_CENTER)
+        label = Gtk.Label(xstr("prefs_msgs_fs"))
+        label.set_justify(Gtk.Justification.CENTER)
         label.set_alignment(0.5, 1.0)
         table.attach(label, 1, 2, 0, 1)
 
-        label = gtk.Label(xstr("prefs_msgs_sound"))
-        label.set_justify(JUSTIFY_CENTER)
+        label = Gtk.Label(xstr("prefs_msgs_sound"))
+        label.set_justify(Gtk.Justification.CENTER)
         label.set_alignment(0.5, 1.0)
         table.attach(label, 2, 3, 0, 1)
@@ -606,12 +606,12 @@
         for messageType in const.messageTypes:
             messageTypeStr = const.messageType2string(messageType)
-            label = gtk.Label(xstr("prefs_msgs_type_" + messageTypeStr))
-            label.set_justify(JUSTIFY_CENTER)
+            label = Gtk.Label(xstr("prefs_msgs_type_" + messageTypeStr))
+            label.set_justify(Gtk.Justification.CENTER)
             label.set_use_underline(True)
             label.set_alignment(0.5, 0.5)
             table.attach(label, 0, 1, row, row+1)
 
-            fsCheckButton = gtk.CheckButton()
-            alignment = gtk.Alignment(xscale = 0.0, yscale = 0.0,
+            fsCheckButton = Gtk.CheckButton()
+            alignment = Gtk.Alignment(xscale = 0.0, yscale = 0.0,
                                       xalign = 0.5, yalign = 0.5)
             alignment.add(fsCheckButton)
@@ -619,6 +619,6 @@
             self._msgFSCheckButtons[messageType] = fsCheckButton
 
-            soundCheckButton = gtk.CheckButton()
-            alignment = gtk.Alignment(xscale = 0.0, yscale = 0.0,
+            soundCheckButton = Gtk.CheckButton()
+            alignment = Gtk.Alignment(xscale = 0.0, yscale = 0.0,
                                       xalign = 0.5, yalign = 0.5)
             alignment.add(soundCheckButton)
@@ -626,5 +626,5 @@
             self._msgSoundCheckButtons[messageType] = soundCheckButton
 
-            mnemonicWidget = gtk.Label("")
+            mnemonicWidget = Gtk.Label("")
             table.attach(mnemonicWidget, 3, 4, row, row+1)
             label.set_mnemonic_widget(mnemonicWidget)
@@ -655,16 +655,16 @@
     def _buildSounds(self):
         """Build the page for the sounds."""
-        mainAlignment = gtk.Alignment(xalign = 0.0, yalign = 0.0,
+        mainAlignment = Gtk.Alignment(xalign = 0.0, yalign = 0.0,
                                       xscale = 1.0, yscale = 1.0)
         mainAlignment.set_padding(padding_top = 8, padding_bottom = 8,
                                   padding_left = 4, padding_right = 4)
 
-        mainBox = gtk.VBox()
+        mainBox = Gtk.VBox()
         mainAlignment.add(mainBox)
 
-        backgroundFrame = gtk.Frame(label = xstr("prefs_sounds_frame_bg"))
+        backgroundFrame = Gtk.Frame(label = xstr("prefs_sounds_frame_bg"))
         mainBox.pack_start(backgroundFrame, False, False, 4)
 
-        backgroundAlignment = gtk.Alignment(xalign = 0.0, yalign = 0.0,
+        backgroundAlignment = Gtk.Alignment(xalign = 0.0, yalign = 0.0,
                                             xscale = 1.0, yscale = 0.0)
         backgroundAlignment.set_padding(padding_top = 4, padding_bottom = 4,
@@ -672,17 +672,17 @@
         backgroundFrame.add(backgroundAlignment)
 
-        backgroundBox = gtk.VBox()
+        backgroundBox = Gtk.VBox()
         backgroundAlignment.add(backgroundBox)
 
-        self._enableSounds = gtk.CheckButton(xstr("prefs_sounds_enable"))
+        self._enableSounds = Gtk.CheckButton(xstr("prefs_sounds_enable"))
         self._enableSounds.set_use_underline(True)
         self._enableSounds.set_tooltip_text(xstr("prefs_sounds_enable_tooltip"))
         self._enableSounds.connect("toggled", self._enableSoundsToggled)
-        alignment = gtk.Alignment(xalign = 0.0, yalign = 0.5,
+        alignment = Gtk.Alignment(xalign = 0.0, yalign = 0.5,
                                   xscale = 1.0, yscale = 0.0)
         alignment.add(self._enableSounds)
         backgroundBox.pack_start(alignment, False, False, 4)
 
-        self._pilotControlsSounds = gtk.CheckButton(xstr("prefs_sounds_pilotControls"))
+        self._pilotControlsSounds = Gtk.CheckButton(xstr("prefs_sounds_pilotControls"))
         self._pilotControlsSounds.set_use_underline(True)
         self._pilotControlsSounds.set_tooltip_text(xstr("prefs_sounds_pilotControls_tooltip"))
@@ -697,18 +697,18 @@
         backgroundBox.pack_start(self._pilotHotkey, False, False, 4)
 
-        self._enableApproachCallouts = gtk.CheckButton(xstr("prefs_sounds_approachCallouts"))
+        self._enableApproachCallouts = Gtk.CheckButton(xstr("prefs_sounds_approachCallouts"))
         self._enableApproachCallouts.set_use_underline(True)
         self._enableApproachCallouts.set_tooltip_text(xstr("prefs_sounds_approachCallouts_tooltip"))
         backgroundBox.pack_start(self._enableApproachCallouts, False, False, 4)
 
-        self._speedbrakeAtTD = gtk.CheckButton(xstr("prefs_sounds_speedbrakeAtTD"))
+        self._speedbrakeAtTD = Gtk.CheckButton(xstr("prefs_sounds_speedbrakeAtTD"))
         self._speedbrakeAtTD.set_use_underline(True)
         self._speedbrakeAtTD.set_tooltip_text(xstr("prefs_sounds_speedbrakeAtTD_tooltip"))
         backgroundBox.pack_start(self._speedbrakeAtTD, False, False, 4)
 
-        checklistFrame = gtk.Frame(label = xstr("prefs_sounds_frame_checklists"))
+        checklistFrame = Gtk.Frame(label = xstr("prefs_sounds_frame_checklists"))
         mainBox.pack_start(checklistFrame, False, False, 4)
 
-        checklistAlignment = gtk.Alignment(xalign = 0.0, yalign = 0.0,
+        checklistAlignment = Gtk.Alignment(xalign = 0.0, yalign = 0.0,
                                            xscale = 1.0, yscale = 0.0)
         checklistAlignment.set_padding(padding_top = 4, padding_bottom = 4,
@@ -716,8 +716,8 @@
         checklistFrame.add(checklistAlignment)
 
-        checklistBox = gtk.VBox()
+        checklistBox = Gtk.VBox()
         checklistAlignment.add(checklistBox)
 
-        self._enableChecklists = gtk.CheckButton(xstr("prefs_sounds_enableChecklists"))
+        self._enableChecklists = Gtk.CheckButton(xstr("prefs_sounds_enableChecklists"))
         self._enableChecklists.set_use_underline(True)
         self._enableChecklists.set_tooltip_text(xstr("prefs_sounds_enableChecklists_tooltip"))
@@ -789,12 +789,12 @@
         """Build the page for the advanced settings."""
 
-        mainAlignment = gtk.Alignment(xalign = 0.0, yalign = 0.0,
+        mainAlignment = Gtk.Alignment(xalign = 0.0, yalign = 0.0,
                                       xscale = 1.0, yscale = 0.0)
         mainAlignment.set_padding(padding_top = 16, padding_bottom = 8,
                                   padding_left = 4, padding_right = 4)
-        mainBox = gtk.VBox()
+        mainBox = Gtk.VBox()
         mainAlignment.add(mainBox)
 
-        self._autoUpdate = gtk.CheckButton(xstr("prefs_update_auto"))
+        self._autoUpdate = Gtk.CheckButton(xstr("prefs_update_auto"))
         mainBox.pack_start(self._autoUpdate, False, False, 4)
 
@@ -804,11 +804,11 @@
         self._warnedAutoUpdate = False
 
-        updateURLBox = gtk.HBox()
+        updateURLBox = Gtk.HBox()
         mainBox.pack_start(updateURLBox, False, False, 4)
-        label = gtk.Label(xstr("prefs_update_url"))
+        label = Gtk.Label(xstr("prefs_update_url"))
         label.set_use_underline(True)
         updateURLBox.pack_start(label, False, False, 4)
 
-        self._updateURL = gtk.Entry()
+        self._updateURL = Gtk.Entry()
         label.set_mnemonic_widget(self._updateURL)
         self._updateURL.set_width_chars(40)
@@ -817,5 +817,5 @@
         updateURLBox.pack_start(self._updateURL, True, True, 4)
 
-        self._useRPC = gtk.CheckButton(xstr("prefs_use_rpc"))
+        self._useRPC = Gtk.CheckButton(xstr("prefs_use_rpc"))
         mainBox.pack_start(self._useRPC, False, False, 16)
 
@@ -829,10 +829,10 @@
         sensitive = False
         try:
-            result = urlparse.urlparse(self._updateURL.get_text())
+            result = urllib.parse.urlparse(self._updateURL.get_text())
             sensitive = result.scheme!="" and (result.netloc + result.path)!=""
         except:
             pass
 
-        okButton = self.get_widget_for_response(RESPONSETYPE_ACCEPT)
+        okButton = self.get_widget_for_response(Gtk.ResponseType.ACCEPT)
         okButton.set_sensitive(sensitive)
 
@@ -841,8 +841,8 @@
         if not self._settingFromConfig and not self._warnedAutoUpdate and \
            not self._autoUpdate.get_active():
-            dialog = gtk.MessageDialog(parent = self,
-                                       type = MESSAGETYPE_INFO,
+            dialog = Gtk.MessageDialog(parent = self,
+                                       type = Gtk.MessageType.INFO,
                                        message_format = xstr("prefs_update_auto_warning"))
-            dialog.add_button(xstr("button_ok"), RESPONSETYPE_OK)
+            dialog.add_button(xstr("button_ok"), Gtk.ResponseType.OK)
             dialog.set_title(self.get_title())
             dialog.run()
Index: src/mlx/gui/statusbar.py
===================================================================
--- src/mlx/gui/statusbar.py	(revision 679)
+++ src/mlx/gui/statusbar.py	(revision 999)
@@ -1,4 +1,4 @@
 
-from common import *
+from .common import *
 
 import mlx.const as const
@@ -20,9 +20,9 @@
 #-------------------------------------------------------------------------------
 
-class Statusbar(gtk.Frame, FlightStatusHandler):
+class Statusbar(Gtk.Frame, FlightStatusHandler):
     """A status bar for the logger."""
     def __init__(self, iconDirectory):
         """Construct the status bar."""
-        gtk.Frame.__init__(self)
+        Gtk.Frame.__init__(self)
         FlightStatusHandler.__init__(self)
 
@@ -30,8 +30,7 @@
         self._connected = False
         
-        self.set_shadow_type(gtk.ShadowType.NONE if pygobject
-                             else gtk.SHADOW_NONE)
+        self.set_shadow_type(Gtk.ShadowType.NONE)
 
-        frameAlignment = gtk.Alignment(xscale = 1.0, yscale = 1.0)
+        frameAlignment = Gtk.Alignment(xscale = 1.0, yscale = 1.0)
 
         frameAlignment.set_padding(padding_top = 2, padding_bottom = 2,
@@ -39,33 +38,30 @@
         self.add(frameAlignment)
 
-        statusBox = gtk.HBox()
+        statusBox = Gtk.HBox()
         frameAlignment.add(statusBox)
 
         iconPath = os.path.join(iconDirectory, "conn_grey.png")
-        self._connGreyIcon = pixbuf_new_from_file(iconPath)
+        self._connGreyIcon = GdkPixbuf.Pixbuf.new_from_file(iconPath)
 
         iconPath = os.path.join(iconDirectory, "conn_red.png")
-        self._connRedIcon = pixbuf_new_from_file(iconPath)
+        self._connRedIcon = GdkPixbuf.Pixbuf.new_from_file(iconPath)
 
         iconPath = os.path.join(iconDirectory, "conn_green.png")
-        self._connGreenIcon = pixbuf_new_from_file(iconPath)
+        self._connGreenIcon = GdkPixbuf.Pixbuf.new_from_file(iconPath)
 
-        self._connStateArea = gtk.DrawingArea()
+        self._connStateArea = Gtk.DrawingArea()
         self._connStateArea.set_size_request(18, 18)
         self._connStateArea.set_tooltip_markup(xstr("statusbar_conn_tooltip"))
 
-        if pygobject:
-            self._connStateArea.connect("draw", self._drawConnState)
-        else:
-            self._connStateArea.connect("expose_event", self._drawConnState)
+        self._connStateArea.connect("draw", self._drawConnState)
 
-        alignment = gtk.Alignment(xalign = 0.5, yalign = 0.5)
+        alignment = Gtk.Alignment(xalign = 0.5, yalign = 0.5)
         alignment.add(self._connStateArea)        
 
         statusBox.pack_start(alignment, False, False, 8)
 
-        statusBox.pack_start(gtk.VSeparator(), False, False, 8)
+        statusBox.pack_start(Gtk.VSeparator(), False, False, 8)
 
-        self._stageLabel = gtk.Label()
+        self._stageLabel = Gtk.Label()
         longestStage = xstr("flight_stage_" +
                             const.stage2string(const.STAGE_PUSHANDTAXI))
@@ -76,7 +72,7 @@
         statusBox.pack_start(self._stageLabel, False, False, 8)
 
-        statusBox.pack_start(gtk.VSeparator(), False, False, 8)
+        statusBox.pack_start(Gtk.VSeparator(), False, False, 8)
 
-        self._timeLabel = gtk.Label("--:--:--")
+        self._timeLabel = Gtk.Label("--:--:--")
         self._timeLabel.set_width_chars(8)
         self._timeLabel.set_tooltip_text(xstr("statusbar_time_tooltip"))
@@ -85,7 +81,7 @@
         statusBox.pack_start(self._timeLabel, False, False, 8)
 
-        statusBox.pack_start(gtk.VSeparator(), False, False, 8)
+        statusBox.pack_start(Gtk.VSeparator(), False, False, 8)
 
-        self._ratingLabel = gtk.Label()
+        self._ratingLabel = Gtk.Label()
         self._ratingLabel.set_width_chars(20)
         self._ratingLabel.set_tooltip_text(xstr("statusbar_rating_tooltip"))
@@ -94,5 +90,5 @@
         statusBox.pack_start(self._ratingLabel, False, False, 8)
 
-        self._busyLabel = gtk.Label()
+        self._busyLabel = Gtk.Label()
         self._busyLabel.set_width_chars(30)
         self._busyLabel.set_tooltip_text(xstr("statusbar_busy_tooltip"))
@@ -130,11 +126,6 @@
             icon = self._connGreyIcon
 
-        if pygobject:
-            gdk.cairo_set_source_pixbuf(eventOrContext, icon, 0, 0)
-            eventOrContext.paint()
-        else:
-            gc = connStateArea.get_style().fg_gc[gtk.STATE_NORMAL]
-            drawable = connStateArea.get_window()
-            drawable.draw_pixbuf(gc, icon, 0, 0, 0, 0)
+        Gdk.cairo_set_source_pixbuf(eventOrContext, icon, 0, 0)
+        eventOrContext.paint()
 
     def _updateFlightStatus(self):
Index: src/mlx/gui/statusicon.py
===================================================================
--- src/mlx/gui/statusicon.py	(revision 544)
+++ src/mlx/gui/statusicon.py	(revision 998)
@@ -1,4 +1,4 @@
 
-from common import *
+from .common import *
 
 import mlx.const as const
@@ -30,20 +30,20 @@
         self._selfToggling = False
 
-        menu = gtk.Menu()
+        menu = Gtk.Menu()
 
         if appIndicator:
-            self._stageMenuItem = gtk.MenuItem("-")
+            self._stageMenuItem = Gtk.MenuItem("-")
             self._stageMenuItem.show()
             menu.append(self._stageMenuItem)
 
-            self._ratingMenuItem = gtk.MenuItem("-")
+            self._ratingMenuItem = Gtk.MenuItem("-")
             self._ratingMenuItem.show()
             menu.append(self._ratingMenuItem)
 
-            separator = gtk.SeparatorMenuItem()
+            separator = Gtk.SeparatorMenuItem()
             separator.show()
             menu.append(separator)
 
-        self._showHideMenuItem = gtk.CheckMenuItem()
+        self._showHideMenuItem = Gtk.CheckMenuItem()
         self._showHideMenuItem.set_label(xstr("statusicon_showmain"))
         self._showHideMenuItem.set_active(True)
@@ -52,5 +52,5 @@
         menu.append(self._showHideMenuItem)
 
-        self._showMonitorMenuItem = gtk.CheckMenuItem()
+        self._showMonitorMenuItem = Gtk.CheckMenuItem()
         self._showMonitorMenuItem.set_label(xstr("statusicon_showmonitor"))
         self._showMonitorMenuItem.set_active(False)
@@ -59,9 +59,9 @@
         menu.append(self._showMonitorMenuItem)
 
-        separator = gtk.SeparatorMenuItem()
+        separator = Gtk.SeparatorMenuItem()
         separator.show()
         menu.append(separator)
 
-        self._quitMenuItem = gtk.MenuItem()
+        self._quitMenuItem = Gtk.MenuItem()
         self._quitMenuItem.set_label(xstr("statusicon_quit"))
         self._quitMenuItem.show()
@@ -74,12 +74,7 @@
 
         if appIndicator:
-            if pygobject:
-                indicator = appindicator.Indicator.new ("mava-logger-x", iconFile,
-                                                        appindicator.IndicatorCategory.APPLICATION_STATUS)
-                indicator.set_status (appindicator.IndicatorStatus.ACTIVE)
-            else:
-                indicator = appindicator.Indicator ("mava-logger-x", iconFile,
-                                                    appindicator.CATEGORY_APPLICATION_STATUS)
-                indicator.set_status (appindicator.STATUS_ACTIVE)
+            indicator = AppIndicator3.Indicator.new ("mava-logger-x", iconFile,
+                                                     AppIndicator3.IndicatorCategory.APPLICATION_STATUS)
+            indicator.set_status (AppIndicator3.IndicatorStatus.ACTIVE)
 
             indicator.set_menu(menu)
@@ -87,8 +82,8 @@
         else:
             def popup_menu(status, button, time):
-                menu.popup(None, None, gtk.status_icon_position_menu,
+                menu.popup(None, None, Gtk.status_icon_position_menu,
                            button, time, status)
 
-            statusIcon = gtk.StatusIcon()
+            statusIcon = Gtk.StatusIcon()
             statusIcon.set_from_file(iconFile)
             statusIcon.set_visible(True)
@@ -127,8 +122,5 @@
         """Hide and destroy the status icon."""
         if appIndicator:
-            if pygobject:
-                self._indicator.set_status(appindicator.IndicatorStatus.PASSIVE)
-            else:
-                self._indicator.set_status(appindicator.STATUS_PASSIVE)
+            self._indicator.set_status(AppIndicator3.IndicatorStatus.PASSIVE)
         else:
             self._statusIcon.set_visible(False)
@@ -154,5 +146,5 @@
     def _updateFlightStatus(self):
         """Update the flight status."""
-        stage = u"-" if self._stage is None \
+        stage = "-" if self._stage is None \
                 else xstr("flight_stage_" + const.stage2string(self._stage))
 
@@ -172,5 +164,5 @@
             if self._noGoReason is not None:
                 rating = '<span foreground="red">' + rating + '</span>'
-            markup = u"MAVA Logger X %s\n\n%s: %s\n%s: %s" %\
+            markup = "MAVA Logger X %s\n\n%s: %s\n%s: %s" %\
                      (const.VERSION, xstr("statusicon_stage"), stage,
                       xstr("statusicon_rating"), rating)
Index: src/mlx/gui/timetable.py
===================================================================
--- src/mlx/gui/timetable.py	(revision 879)
+++ src/mlx/gui/timetable.py	(revision 1013)
@@ -4,5 +4,5 @@
 
 from mlx.gui.common import *
-from flightlist import ColumnDescriptor
+from .flightlist import ColumnDescriptor
 from mlx.rpc import ScheduledFlight
 
@@ -14,9 +14,9 @@
 #-----------------------------------------------------------------------------
 
-class Timetable(gtk.Alignment):
+class Timetable(Gtk.Alignment):
     """The widget for the time table."""
     def _getVIPRenderer():
         """Get the renderer for the VIP column."""
-        renderer = gtk.CellRendererToggle()
+        renderer = Gtk.CellRendererToggle()
         renderer.set_activatable(True)
         return renderer
@@ -74,17 +74,15 @@
             columnDescriptor.appendType(types)
 
-        self._model = gtk.ListStore(*types)
+        self._model = Gtk.ListStore(*types)
         if defaultSortableIndex is not None:
-            sortOrder = SORT_DESCENDING \
+            sortOrder = Gtk.SortType.DESCENDING \
               if self._columnDescriptors[defaultSortableIndex-1]._defaultDescending \
-              else SORT_ASCENDING
+              else Gtk.SortType.ASCENDING
             self._model.set_sort_column_id(defaultSortableIndex, sortOrder)
-        self._view = gtk.TreeView(self._model)
-
-        self._tooltips = gtk.Tooltips()
-        self._tooltips.disable()
+        self._view = Gtk.TreeView(self._model)
+
         self._view.connect("motion-notify-event", self._updateTooltip)
 
-        flightPairIndexColumn = gtk.TreeViewColumn()
+        flightPairIndexColumn = Gtk.TreeViewColumn()
         flightPairIndexColumn.set_visible(False)
         self._view.append_column(flightPairIndexColumn)
@@ -104,15 +102,12 @@
         selection.connect("changed", self._selectionChanged)
 
-        scrolledWindow = gtk.ScrolledWindow()
+        scrolledWindow = Gtk.ScrolledWindow()
         scrolledWindow.add(self._view)
         scrolledWindow.set_size_request(800, -1)
 
         # FIXME: these should be constants in common.py
-        scrolledWindow.set_policy(gtk.PolicyType.AUTOMATIC if pygobject
-                                  else gtk.POLICY_AUTOMATIC,
-                                  gtk.PolicyType.AUTOMATIC if pygobject
-                                  else gtk.POLICY_AUTOMATIC)
-        scrolledWindow.set_shadow_type(gtk.ShadowType.IN if pygobject
-                                       else gtk.SHADOW_IN)
+        scrolledWindow.set_policy(Gtk.PolicyType.AUTOMATIC,
+                                  Gtk.PolicyType.AUTOMATIC)
+        scrolledWindow.set_shadow_type(Gtk.ShadowType.IN)
 
         super(Timetable, self).__init__(xalign = 0.5, yalign = 0.0,
@@ -180,5 +175,5 @@
     def _buttonPressEvent(self, widget, event):
         """Called when a mouse button is pressed or released."""
-        if event.type!=EVENT_BUTTON_PRESS or event.button!=3 or \
+        if event.type!=Gdk.EventType.BUTTON_PRESS or event.button!=3 or \
            self._popupMenuProducer is None:
             return
@@ -193,8 +188,5 @@
             self._popupMenu = self._popupMenuProducer()
         menu = self._popupMenu
-        if pygobject:
-            menu.popup(None, None, None, None, event.button, event.time)
-        else:
-            menu.popup(None, None, None, event.button, event.time)
+        menu.popup(None, None, None, None, event.button, event.time)
 
     def _selectionChanged(self, selection):
@@ -225,6 +217,5 @@
             result = widget.get_path_at_pos( int(event.x), int(event.y))
             if result is None:
-                self._tooltips.set_tip(widget, "")
-                self._tooltips.disable()
+                widget.set_tooltip_text("")
             else:
                 (path, col, x, y) = result
@@ -244,17 +235,22 @@
                         text += date.strftime("%Y-%m-%d")
 
-                    self._tooltips.set_tip(widget, text)
-                    self._tooltips.enable()
+                    widget.set_tooltip_text(text)
                 else:
-                    self._tooltips.set_tip(widget, "")
-                    self._tooltips.disable()
-        except Exception, e:
-            print e
-            self._tooltips.set_tip(widget, "")
-            self._tooltips.disable()
+                    widget.set_tooltip_text("")
+        except Exception as e:
+            print(e)
+            widget.set_tooltip_text("")
 
 #-----------------------------------------------------------------------------
 
-class CalendarWindow(gtk.Window):
+GObject.signal_new("row-activated", Timetable, GObject.SIGNAL_RUN_FIRST,
+                   None, (int,))
+
+GObject.signal_new("selection-changed", Timetable, GObject.SIGNAL_RUN_FIRST,
+                   None, (object,))
+
+#-----------------------------------------------------------------------------
+
+class CalendarWindow(Gtk.Window):
     """A window for a calendar."""
     def __init__(self):
@@ -266,10 +262,10 @@
         self.connect("key-press-event", self._keyPressed)
 
-        mainAlignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
+        mainAlignment = Gtk.Alignment(xalign = 0.5, yalign = 0.5,
                                       xscale = 1.0, yscale = 1.0)
         #mainAlignment.set_padding(padding_top = 0, padding_bottom = 12,
         #                              padding_left = 8, padding_right = 8)
 
-        self._calendar = gtk.Calendar()
+        self._calendar = Gtk.Calendar()
         self._calendar.connect("day-selected-double-click", self._daySelectedDoubleClick)
         mainAlignment.add(self._calendar)
@@ -296,5 +292,5 @@
         If the Escape key is pressed, 'delete-event' is emitted to close the
         window."""
-        keyName = gdk.keyval_name(event.keyval)
+        keyName = Gdk.keyval_name(event.keyval)
         if keyName =="Escape":
             self.emit("delete-event", None)
@@ -304,10 +300,10 @@
             return True
 
-gobject.signal_new("date-selected", CalendarWindow, gobject.SIGNAL_RUN_FIRST,
+GObject.signal_new("date-selected", CalendarWindow, GObject.SIGNAL_RUN_FIRST,
                    None, ())
 
 #-----------------------------------------------------------------------------
 
-class BookDialog(gtk.Dialog):
+class BookDialog(Gtk.Dialog):
     """The dialog box to select additional data for a booking."""
     def __init__(self, timetableWindow, flightPair, planes):
@@ -319,18 +315,18 @@
         contentArea = self.get_content_area()
 
-        frame = gtk.Frame(xstr("timetable_book_frame_title"))
+        frame = Gtk.Frame(label = xstr("timetable_book_frame_title"))
         frame.set_size_request(600, -1)
 
-        mainAlignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
+        mainAlignment = Gtk.Alignment(xalign = 0.5, yalign = 0.5,
                                       xscale = 0.0, yscale = 0.0)
         mainAlignment.set_padding(padding_top = 16, padding_bottom = 12,
                                   padding_left = 8, padding_right = 8)
 
-        table = gtk.Table(6, 2)
+        table = Gtk.Table(6, 2)
         table.set_row_spacings(8)
         table.set_col_spacings(16)
 
         row = 0
-        label = gtk.Label()
+        label = Gtk.Label()
         label.set_markup(xstr("timetable_book_callsign"))
         label.set_alignment(0.0, 0.5)
@@ -340,5 +336,5 @@
         if flightPair.flight1 is not None:
             text += " / " + flightPair.flight1.callsign
-        label = gtk.Label(text)
+        label = Gtk.Label(text)
         label.set_alignment(0.0, 0.5)
         table.attach(label, 1, 2, row, row + 1)
@@ -346,5 +342,5 @@
         row += 1
 
-        label = gtk.Label()
+        label = Gtk.Label()
         label.set_markup(xstr("timetable_book_from_to"))
         label.set_alignment(0.0, 0.5)
@@ -355,5 +351,5 @@
         if flightPair.flight1 is not None:
             text += " - " + flightPair.flight1.arrivalICAO
-        label = gtk.Label(text)
+        label = Gtk.Label(text)
         label.set_alignment(0.0, 0.5)
         table.attach(label, 1, 2, row, row + 1)
@@ -363,5 +359,5 @@
         if flightPair.flight0.type==ScheduledFlight.TYPE_VIP and \
            flightPair.flight0.date!=const.defaultDate:
-            label = gtk.Label()
+            label = Gtk.Label()
             label.set_markup(xstr("timetable_book_flightDate"))
             label.set_use_underline(True)
@@ -369,5 +365,5 @@
             table.attach(label, 0, 1, row, row + 1)
 
-            self._flightDate = gtk.Button()
+            self._flightDate = Gtk.Button()
             self._flightDate.connect("clicked", self._flightDateClicked)
             self._flightDate.set_tooltip_text(xstr("timetable_book_flightDate_tooltip"))
@@ -388,5 +384,5 @@
             self._calendarWindow = None
 
-        label = gtk.Label()
+        label = Gtk.Label()
         label.set_markup(xstr("timetable_book_dep_arr"))
         label.set_alignment(0.0, 0.5)
@@ -398,5 +394,5 @@
             text += " / " + str(flightPair.flight1.departureTime) + " - " + \
                     str(flightPair.flight1.arrivalTime)
-        label = gtk.Label(text)
+        label = Gtk.Label(text)
         label.set_alignment(0.0, 0.5)
         table.attach(label, 1, 2, row, row + 1)
@@ -404,5 +400,5 @@
         row += 1
 
-        label = gtk.Label()
+        label = Gtk.Label()
         label.set_markup(xstr("timetable_book_duration"))
         label.set_alignment(0.0, 0.5)
@@ -415,5 +411,5 @@
             duration = flightPair.flight0.duration
             text += " / %02d:%02d" % (duration/3600, (duration%3600)/60)
-        label = gtk.Label(text)
+        label = Gtk.Label(text)
         label.set_alignment(0.0, 0.5)
         table.attach(label, 1, 2, row, row + 1)
@@ -421,5 +417,5 @@
         row += 2
 
-        label = gtk.Label()
+        label = Gtk.Label()
         label.set_markup(xstr("timetable_book_tailNumber"))
         label.set_alignment(0.0, 0.5)
@@ -427,10 +423,10 @@
 
         self._planes = planes
-        tailNumbersModel = gtk.ListStore(str)
+        tailNumbersModel = Gtk.ListStore(str)
         for plane in planes:
             tailNumbersModel.append((plane.tailNumber,))
 
-        self._tailNumber = gtk.ComboBox(model = tailNumbersModel)
-        renderer = gtk.CellRendererText()
+        self._tailNumber = Gtk.ComboBox(model = tailNumbersModel)
+        renderer = Gtk.CellRendererText()
         self._tailNumber.pack_start(renderer, True)
         self._tailNumber.add_attribute(renderer, "text", 0)
@@ -445,7 +441,7 @@
         contentArea.pack_start(frame, True, True, 4)
 
-        self.add_button(xstr("button_cancel"), RESPONSETYPE_CANCEL)
-
-        self._okButton = self.add_button(xstr("button_book"), RESPONSETYPE_OK)
+        self.add_button(xstr("button_cancel"), Gtk.ResponseType.CANCEL)
+
+        self._okButton = self.add_button(xstr("button_book"), Gtk.ResponseType.OK)
         self._okButton.set_use_underline(True)
         self._okButton.set_can_default(True)
@@ -469,5 +465,5 @@
     def _flightDateClicked(self, button):
         """Called when the flight date button is clicked."""
-        self._calendarWindow.set_position(gtk.WIN_POS_MOUSE)
+        self._calendarWindow.set_position(Gtk.WindowPosition.MOUSE)
         self.set_focus(self._calendarWindow)
         self._calendarWindow.show_all()
@@ -485,5 +481,5 @@
 #-----------------------------------------------------------------------------
 
-class TimetableWindow(gtk.Window):
+class TimetableWindow(Gtk.Window):
     """The window to display the timetable."""
     typeFamilies = [
@@ -510,27 +506,28 @@
         self.connect("key-press-event", self._keyPressed)
 
-        mainAlignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
+        mainAlignment = Gtk.Alignment(xalign = 0.5, yalign = 0.5,
                                       xscale = 1.0, yscale = 1.0)
         mainAlignment.set_padding(padding_top = 0, padding_bottom = 12,
                                   padding_left = 8, padding_right = 8)
 
-        vbox = gtk.VBox()
-
-        filterAlignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
+        vbox = Gtk.VBox()
+
+        filterAlignment = Gtk.Alignment(xalign = 0.5, yalign = 0.5,
                                         xscale = 1.0, yscale = 1.0)
 
-        filterFrame = gtk.Frame(xstr("timetable_filter"))
-
-        filterVBox = gtk.VBox()
-
-        topAlignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
+        filterFrame = Gtk.Frame()
+        filterFrame.set_label(xstr("timetable_filter"))
+
+        filterVBox = Gtk.VBox()
+
+        topAlignment = Gtk.Alignment(xalign = 0.5, yalign = 0.5,
                                      xscale = 0.0, yscale = 0.0)
-        topHBox = gtk.HBox()
-
-        label = gtk.Label(xstr("timetable_flightdate"))
+        topHBox = Gtk.HBox()
+
+        label = Gtk.Label(xstr("timetable_flightdate"))
         label.set_use_underline(True)
         topHBox.pack_start(label, False, False, 4)
 
-        self._flightDate = gtk.Button()
+        self._flightDate = Gtk.Button()
         self._flightDate.connect("clicked", self._flightDateClicked)
         self._flightDate.connect("clicked", self._flightDateClicked)
@@ -539,9 +536,9 @@
         topHBox.pack_start(self._flightDate, False, False, 4)
 
-        filler = gtk.Alignment()
+        filler = Gtk.Alignment()
         filler.set_size_request(48, 2)
         topHBox.pack_start(filler, False, True, 0)
 
-        self._regularFlights = gtk.CheckButton(xstr("timetable_show_regular"))
+        self._regularFlights = Gtk.CheckButton(xstr("timetable_show_regular"))
         self._regularFlights.set_use_underline(True)
         self._regularFlights.set_tooltip_text(xstr("timetable_show_regular_tooltip"))
@@ -550,5 +547,5 @@
         topHBox.pack_start(self._regularFlights, False, False, 8)
 
-        self._vipFlights = gtk.CheckButton(xstr("timetable_show_vip"))
+        self._vipFlights = Gtk.CheckButton(xstr("timetable_show_vip"))
         self._vipFlights.set_use_underline(True)
         self._vipFlights.set_tooltip_text(xstr("timetable_show_vip_tooltip"))
@@ -561,8 +558,8 @@
         filterVBox.pack_start(topAlignment, False, False, 4)
 
-        separator = gtk.HSeparator()
+        separator = Gtk.HSeparator()
         filterVBox.pack_start(separator, False, False, 4)
 
-        typeAlignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
+        typeAlignment = Gtk.Alignment(xalign = 0.5, yalign = 0.5,
                                       xscale = 0.0, yscale = 0.0)
 
@@ -570,5 +567,5 @@
         numRows = (len(TimetableWindow.typeFamilies)+numColumns-1)/numColumns
 
-        typeTable = gtk.Table(numRows, numColumns)
+        typeTable = Gtk.Table(numRows, numColumns)
         typeTable.set_col_spacings(8)
         row = 0
@@ -576,5 +573,5 @@
         self._typeFamilyButtons = {}
         for typeFamily in TimetableWindow.typeFamilies:
-            checkButton = gtk.CheckButton(aircraftFamilyNames[typeFamily])
+            checkButton = Gtk.CheckButton(aircraftFamilyNames[typeFamily])
             checkButton.set_active(True)
             checkButton.connect("toggled", self._filterChanged)
@@ -602,9 +599,9 @@
         vbox.pack_start(self._timetable, True, True, 2)
 
-        alignment = gtk.Alignment(xalign = 1.0, yalign = 0.5,
+        alignment = Gtk.Alignment(xalign = 1.0, yalign = 0.5,
                                   xscale = 0.0, yscale = 0.0)
-        buttonBox = gtk.HBox()
-
-        self._bookButton = gtk.Button(xstr("button_book"))
+        buttonBox = Gtk.HBox()
+
+        self._bookButton = Gtk.Button(xstr("button_book"))
         self._bookButton.set_use_underline(True)
         self._bookButton.set_can_default(True)
@@ -613,5 +610,5 @@
         buttonBox.pack_start(self._bookButton, False, False, 4);
 
-        self._closeButton = gtk.Button(xstr("button_close"))
+        self._closeButton = Gtk.Button(xstr("button_close"))
         self._closeButton.set_use_underline(True)
         self._closeButton.connect("clicked", self._closeClicked)
@@ -656,6 +653,7 @@
             typeFamilies.add(const.aircraftType2Family(aircraftType))
 
-        for (typeFamily, checkButton) in self._typeFamilyButtons.iteritems():
+        for (typeFamily, checkButton) in self._typeFamilyButtons.items():
             checkButton.set_sensitive(typeFamily in typeFamilies)
+            checkButton.set_active(typeFamily in typeFamilies)
 
     def clear(self):
@@ -681,5 +679,5 @@
     def _flightDateClicked(self, button):
         """Called when the flight date button is clicked."""
-        self._calendarWindow.set_position(gtk.WIN_POS_MOUSE)
+        self._calendarWindow.set_position(Gtk.WindowPosition.MOUSE)
         self.set_focus(self._calendarWindow)
         self._calendarWindow.show_all()
@@ -705,5 +703,5 @@
         If the Escape key is pressed, 'delete-event' is emitted to close the
         window."""
-        if gdk.keyval_name(event.keyval) == "Escape":
+        if Gdk.keyval_name(event.keyval) == "Escape":
             self.emit("delete-event", None)
             return True
@@ -712,5 +710,5 @@
         """Update the timetable list."""
         aircraftTypes = []
-        for (aircraftFamily, button) in self._typeFamilyButtons.iteritems():
+        for (aircraftFamily, button) in self._typeFamilyButtons.items():
             if button.get_active():
                 aircraftTypes += const.aircraftFamily2Types[aircraftFamily]
@@ -752,5 +750,5 @@
         planes = [plane for plane in fleet
                   if plane.aircraftType == aircraftType]
-        planes.sort(cmp = lambda p1, p2: cmp(p1.tailNumber, p2.tailNumber))
+        planes.sort(key = lambda p: p.tailNumber)
 
         dialog = BookDialog(self, flightPair, planes)
@@ -758,5 +756,5 @@
         result = dialog.run()
         dialog.hide()
-        if result==RESPONSETYPE_OK:
+        if result==Gtk.ResponseType.OK:
             flightIDs = [flightPair.flight0.id]
             if flightPair.flight1 is not None:
@@ -774,15 +772,15 @@
         """Called when the booking has finished."""
         if returned:
-            dialog = gtk.MessageDialog(parent = self,
-                                       type = MESSAGETYPE_INFO,
+            dialog = Gtk.MessageDialog(parent = self,
+                                       type = Gtk.MessageType.INFO,
                                        message_format = xstr("bookflights_successful"))
             dialog.format_secondary_markup(xstr("bookflights_successful_secondary"))
         else:
-            dialog = gtk.MessageDialog(parent = self,
-                                       type = MESSAGETYPE_ERROR,
+            dialog = Gtk.MessageDialog(parent = self,
+                                       type = Gtk.MessageType.ERROR,
                                        message_format = xstr("bookflights_failed"))
             dialog.format_secondary_markup(xstr("bookflights_failed_secondary"))
 
-        dialog.add_button(xstr("button_ok"), RESPONSETYPE_OK)
+        dialog.add_button(xstr("button_ok"), Gtk.ResponseType.OK)
         dialog.set_title(WINDOW_TITLE_BASE)
 
@@ -792,7 +790,7 @@
     def _createTimetablePopupMenu(self):
         """Get the popuop menu for the timetable."""
-        menu = gtk.Menu()
-
-        menuItem = gtk.MenuItem()
+        menu = Gtk.Menu()
+
+        menuItem = Gtk.MenuItem()
         menuItem.set_label(xstr("timetable_popup_book"))
         menuItem.set_use_underline(True)
Index: src/mlx/gui/update.py
===================================================================
--- src/mlx/gui/update.py	(revision 755)
+++ src/mlx/gui/update.py	(revision 996)
@@ -46,5 +46,5 @@
             return
 
-        Updater._progressWindow = window = gtk.Window()
+        Updater._progressWindow = window = Gtk.Window()
         window.set_title(WINDOW_TITLE_BASE + " " + xstr("update_title"))
         window.set_transient_for(parentWindow)
@@ -55,47 +55,44 @@
         window.connect("delete-event", lambda a, b: True)
         window.set_deletable(False)
-        window.set_position(gtk.WindowPosition.CENTER_ON_PARENT if pygobject
-                            else gtk.WIN_POS_CENTER_ON_PARENT)
-
-        mainAlignment = gtk.Alignment(xscale = 1.0)
+        window.set_position(Gtk.WindowPosition.CENTER_ON_PARENT)
+
+        mainAlignment = Gtk.Alignment(xscale = 1.0)
         mainAlignment.set_padding(padding_top = 4, padding_bottom = 10,
                                   padding_left = 16, padding_right = 16)
         window.add(mainAlignment)
 
-        mainVBox = gtk.VBox()
+        mainVBox = Gtk.VBox()
         mainAlignment.add(mainVBox)
 
-        labelAlignment = gtk.Alignment(xalign = 0.0, xscale = 0.0)
-        Updater._progressLabel = progressLabel = gtk.Label()
+        labelAlignment = Gtk.Alignment(xalign = 0.0, xscale = 0.0)
+        Updater._progressLabel = progressLabel = Gtk.Label()
         labelAlignment.add(progressLabel)
         mainVBox.pack_start(labelAlignment, True, True, 4)
         
-        Updater._progressBar = progressBar = gtk.ProgressBar()
+        Updater._progressBar = progressBar = Gtk.ProgressBar()
         mainVBox.pack_start(progressBar, True, True, 4)
 
-        buttonAlignment = gtk.Alignment(xalign = 0.5, xscale = 0.1)
-        Updater._progressOKButton = progressOKButton = gtk.Button("OK")
+        buttonAlignment = Gtk.Alignment(xalign = 0.5, xscale = 0.1)
+        Updater._progressOKButton = progressOKButton = Gtk.Button("OK")
         buttonAlignment.add(progressOKButton)        
         mainVBox.pack_start(buttonAlignment, True, True, 4)
 
         Updater._sudoDialog = sudoDialog = \
-            gtk.Dialog(WINDOW_TITLE_BASE + " " + xstr("update_title"),
+            Gtk.Dialog(WINDOW_TITLE_BASE + " " + xstr("update_title"),
                        parentWindow,
-                       gtk.DialogFlags.MODAL if pygobject else gtk.DIALOG_MODAL)
+                       Gtk.DialogFlags.MODAL)
         sudoDialog.add_button(xstr("button_cancel"), 0)
         sudoDialog.add_button(xstr("button_ok"), 1)
                        
-        infoLabelAlignment = gtk.Alignment(xalign = 0.5, xscale = 0.1)
+        infoLabelAlignment = Gtk.Alignment(xalign = 0.5, xscale = 0.1)
         infoLabelAlignment.set_padding(padding_top = 4, padding_bottom = 10,
                                        padding_left = 16, padding_right = 16)
 
-        infoLabel = gtk.Label(xstr("update_needsudo"))
-        infoLabel.set_justify(gtk.Justification.CENTER if pygobject
-                              else gtk.JUSTIFY_CENTER)
+        infoLabel = Gtk.Label(xstr("update_needsudo"))
+        infoLabel.set_justify(Gtk.Justification.CENTER)
         infoLabelAlignment.add(infoLabel)
         sudoDialog.vbox.pack_start(infoLabelAlignment, True, True, 4)
 
-        sudoDialog.set_position(gtk.WindowPosition.CENTER_ON_PARENT if pygobject
-                                else gtk.WIN_POS_CENTER_ON_PARENT)
+        sudoDialog.set_position(Gtk.WindowPosition.CENTER_ON_PARENT)
 
     def __init__(self, gui, programDirectory, updateURL, parentWindow):
@@ -120,13 +117,13 @@
     def run(self):
         """Execute the thread's operation."""
-        gobject.idle_add(self._startUpdate)
+        GObject.idle_add(self._startUpdate)
         update(self._programDirectory, self._updateURL, self, fromGUI = True)
         if not self._waitAfterFinish:
-            gobject.idle_add(self._progressWindow.hide)
+            GObject.idle_add(self._progressWindow.hide)
             self._gui.updateDone()
 
     def downloadingManifest(self):
         """Called when the downloading of the manifest has started."""
-        gobject.idle_add(self._downloadingManifest)
+        GObject.idle_add(self._downloadingManifest)
 
     def _downloadingManifest(self):
@@ -137,5 +134,5 @@
     def downloadedManifest(self):
         """Called when the downloading of the manifest has finished."""
-        gobject.idle_add(self._downloadedManifest)
+        GObject.idle_add(self._downloadedManifest)
 
     def _downloadedManifest(self):
@@ -147,5 +144,5 @@
         """Called when the program is interested in whether we want to run a
         program with administrator rights to do the update."""
-        gobject.idle_add(self._needSudo)
+        GObject.idle_add(self._needSudo)
         with self._sudoCondition:
             while self._sudoReply is None:
@@ -187,5 +184,5 @@
         """Called when a certain number of bytes are downloaded."""
         self._downloaded = downloaded
-        gobject.idle_add(self._setDownloaded, downloaded)
+        GObject.idle_add(self._setDownloaded, downloaded)
 
     def _setDownloaded(self, downloaded):
@@ -197,5 +194,5 @@
     def startRenaming(self):
         """Called when the renaming of files has started."""
-        gobject.idle_add(self._startRenaming)
+        GObject.idle_add(self._startRenaming)
 
     def _startRenaming(self):
@@ -206,5 +203,5 @@
         """Called when a file has been renamed."""
         self._numModifiedOrNew = count
-        gobject.idle_add(self._renamed, path, count)
+        GObject.idle_add(self._renamed, path, count)
 
     def _renamed(self, path, count):
@@ -215,5 +212,5 @@
     def startRemoving(self):
         """Called when the removing of files has started."""
-        gobject.idle_add(self._startRemoving)
+        GObject.idle_add(self._startRemoving)
 
     def _startRemoving(self):
@@ -224,5 +221,5 @@
         """Called when a file has been removed."""
         self._numRemoved = count
-        gobject.idle_add(self._removed, path, count)
+        GObject.idle_add(self._removed, path, count)
 
     def _removed(self, path, count):
@@ -233,5 +230,5 @@
     def writingManifest(self):
         """Called when the writing of the new manifest file has started."""
-        gobject.idle_add(self._writingManifest)
+        GObject.idle_add(self._writingManifest)
 
     def _writingManifest(self):
@@ -241,5 +238,5 @@
     def done(self):
         """Called when the update has been done."""
-        gobject.idle_add(self._done)
+        GObject.idle_add(self._done)
         self._restart = self._waitAfterFinish
 
@@ -264,5 +261,5 @@
         """Called when the downloading has failed."""
         self._waitAfterFinish = True
-        gobject.idle_add(self._failed, what)
+        GObject.idle_add(self._failed, what)
 
     def _failed(self, what):
Index: src/mlx/gui/weighthelp.py
===================================================================
--- src/mlx/gui/weighthelp.py	(revision 303)
+++ src/mlx/gui/weighthelp.py	(revision 996)
@@ -15,5 +15,5 @@
 #-------------------------------------------------------------------------------
 
-class WeightHelp(gtk.VBox):
+class WeightHelp(Gtk.VBox):
     """The weight calculation help tab."""
     @staticmethod
@@ -40,5 +40,5 @@
         self._gui = gui
 
-        mainAlignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
+        mainAlignment = Gtk.Alignment(xalign = 0.5, yalign = 0.5,
                                       xscale = 1.0, yscale = 1.0)
         mainAlignment.set_padding(padding_top = 4, padding_bottom = 4,
@@ -46,8 +46,8 @@
         self.add(mainAlignment)
 
-        self._mainBox = mainBox = gtk.VBox()
+        self._mainBox = mainBox = Gtk.VBox()
         mainAlignment.add(mainBox)
 
-        self._usingHelp = gtk.CheckButton(xstr("weighthelp_usinghelp"))
+        self._usingHelp = Gtk.CheckButton(xstr("weighthelp_usinghelp"))
         self._usingHelp.set_use_underline(True)
         self._usingHelp.set_tooltip_text(xstr("weighthelp_usinghelp_tooltip"))
@@ -56,252 +56,250 @@
 
         
-        self._weightsTable = table = gtk.Table(16, 5)
+        self._weightsTable = table = Gtk.Table(16, 5)
         table.set_homogeneous(False)
         table.set_row_spacings(4)
         table.set_col_spacings(16)
-        alignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
+        alignment = Gtk.Alignment(xalign = 0.5, yalign = 0.5,
                                   xscale = 0.0, yscale = 0.0)
         alignment.add(table)
         mainBox.pack_start(alignment, True, True, 4)
 
-        alignment = gtk.Alignment(xalign = 1.0, yalign = 0.0,
+        alignment = Gtk.Alignment(xalign = 1.0, yalign = 0.0,
                                   xscale = 0.0, yscale = 0.0)
         alignment.set_padding(padding_bottom = 16, padding_top = 0,
                               padding_left = 0, padding_right = 0)
-        label = gtk.Label(xstr("weighthelp_header_calculated"))
+        label = Gtk.Label(xstr("weighthelp_header_calculated"))
         label.set_use_markup(True)
         # FIXME: should be a constant in common
-        label.set_justify(gtk.Justification.CENTER if pygobject
-                          else gtk.JUSTIFY_CENTER)        
+        label.set_justify(Gtk.Justification.CENTER)
         alignment.add(label)
         table.attach(alignment, 1, 2, 0, 1)
         
-        alignment = gtk.Alignment(xalign = 1.0, yalign = 0.0,
+        alignment = Gtk.Alignment(xalign = 1.0, yalign = 0.0,
                                   xscale = 0.0, yscale = 0.0)
         alignment.set_padding(padding_bottom = 16, padding_top = 0,
                               padding_left = 0, padding_right = 0)
-        button = gtk.Button(xstr("weighthelp_header_simulator"))
+        button = Gtk.Button(xstr("weighthelp_header_simulator"))
         button.set_tooltip_markup(xstr("weighthelp_header_simulator_tooltip"))
         button.connect("clicked", self._fsButtonClicked)
         label = button.get_child()
-        label.set_justify(gtk.Justification.CENTER if pygobject
-                          else gtk.JUSTIFY_CENTER)        
+        label.set_justify(Gtk.Justification.CENTER)
         alignment.add(button)
         table.attach(alignment, 3, 4, 0, 1)
         
 
-        self._crewLabel = gtk.Label(xstr("weighthelp_crew") % ("99",))
-        alignment = gtk.Alignment(xalign = 0.0, yalign = 0.5,
+        self._crewLabel = Gtk.Label(xstr("weighthelp_crew") % ("99",))
+        alignment = Gtk.Alignment(xalign = 0.0, yalign = 0.5,
                                   xscale = 0.0, yscale = 0.0)
         alignment.add(self._crewLabel)
         table.attach(alignment, 0, 1, 1, 2)
 
-        self._crewWeight = gtk.Label("0")
-        alignment = gtk.Alignment(xalign = 1.0, yalign = 0.5,
+        self._crewWeight = Gtk.Label("0")
+        alignment = Gtk.Alignment(xalign = 1.0, yalign = 0.5,
                                   xscale = 0.0, yscale = 0.0)
         alignment.add(self._crewWeight)
         table.attach(alignment, 1, 2, 1, 2)
         
-        table.attach(gtk.Label("kg"), 2, 3, 1, 2)
+        table.attach(Gtk.Label("kg"), 2, 3, 1, 2)
 
         text = xstr("weighthelp_pax") % ("999",)
-        self._paxLabel = gtk.Label(text)
+        self._paxLabel = Gtk.Label(text)
         self._paxLabel.set_width_chars(len(text))
         self._paxLabel.set_alignment(0.0, 0.5)
-        alignment = gtk.Alignment(xalign = 0.0, yalign = 0.5,
+        alignment = Gtk.Alignment(xalign = 0.0, yalign = 0.5,
                                   xscale = 0.0, yscale = 0.0)
         alignment.add(self._paxLabel)
         table.attach(alignment, 0, 1, 2, 3)
 
-        self._paxWeight = gtk.Label("20000")
-        alignment = gtk.Alignment(xalign = 1.0, yalign = 0.5,
+        self._paxWeight = Gtk.Label("20000")
+        alignment = Gtk.Alignment(xalign = 1.0, yalign = 0.5,
                                   xscale = 0.0, yscale = 0.0)
         alignment.add(self._paxWeight)
         table.attach(alignment, 1, 2, 2, 3)
         
-        table.attach(gtk.Label("kg"), 2, 3, 2, 3)
-        
-        label = gtk.Label(xstr("weighthelp_baggage"))
-        alignment = gtk.Alignment(xalign = 0.0, yalign = 0.5,
+        table.attach(Gtk.Label("kg"), 2, 3, 2, 3)
+        
+        label = Gtk.Label(xstr("weighthelp_baggage"))
+        alignment = Gtk.Alignment(xalign = 0.0, yalign = 0.5,
                                   xscale = 0.0, yscale = 0.0)
         alignment.add(label)
         table.attach(alignment, 0, 1, 3, 4)
 
-        self._bagWeight = gtk.Label("2000")
-        alignment = gtk.Alignment(xalign = 1.0, yalign = 0.5,
+        self._bagWeight = Gtk.Label("2000")
+        alignment = Gtk.Alignment(xalign = 1.0, yalign = 0.5,
                                   xscale = 0.0, yscale = 0.0)
         alignment.add(self._bagWeight)
         table.attach(alignment, 1, 2, 3, 4)
         
-        table.attach(gtk.Label("kg"), 2, 3, 3, 4)
-        
-        label = gtk.Label(xstr("weighthelp_cargo"))
-        alignment = gtk.Alignment(xalign = 0.0, yalign = 0.5,
+        table.attach(Gtk.Label("kg"), 2, 3, 3, 4)
+        
+        label = Gtk.Label(xstr("weighthelp_cargo"))
+        alignment = Gtk.Alignment(xalign = 0.0, yalign = 0.5,
                                   xscale = 0.0, yscale = 0.0)
         alignment.add(label)
         table.attach(alignment, 0, 1, 4, 5)
 
-        self._cargoWeight = gtk.Label("2000")
-        alignment = gtk.Alignment(xalign = 1.0, yalign = 0.5,
+        self._cargoWeight = Gtk.Label("2000")
+        alignment = Gtk.Alignment(xalign = 1.0, yalign = 0.5,
                                   xscale = 0.0, yscale = 0.0)
         alignment.add(self._cargoWeight)
         table.attach(alignment, 1, 2, 4, 5)
         
-        table.attach(gtk.Label("kg"), 2, 3, 4, 5)
-        
-        label = gtk.Label(xstr("weighthelp_mail"))
-        alignment = gtk.Alignment(xalign = 0.0, yalign = 0.5,
+        table.attach(Gtk.Label("kg"), 2, 3, 4, 5)
+        
+        label = Gtk.Label(xstr("weighthelp_mail"))
+        alignment = Gtk.Alignment(xalign = 0.0, yalign = 0.5,
                                   xscale = 0.0, yscale = 0.0)
         alignment.add(label)
         table.attach(alignment, 0, 1, 5, 6)
 
-        self._mailWeight = gtk.Label("2000")
-        alignment = gtk.Alignment(xalign = 1.0, yalign = 0.5,
+        self._mailWeight = Gtk.Label("2000")
+        alignment = Gtk.Alignment(xalign = 1.0, yalign = 0.5,
                                   xscale = 0.0, yscale = 0.0)
         alignment.add(self._mailWeight)
         table.attach(alignment, 1, 2, 5, 6)
         
-        table.attach(gtk.Label("kg"), 2, 3, 5, 6)
-
-        table.attach(gtk.HSeparator(), 1, 2, 6, 7)
-
-        label = gtk.Label("<b>" + xstr("weighthelp_payload") + "</b>")
-        label.set_use_markup(True)
-        alignment = gtk.Alignment(xalign = 0.0, yalign = 0.5,
+        table.attach(Gtk.Label("kg"), 2, 3, 5, 6)
+
+        table.attach(Gtk.HSeparator(), 1, 2, 6, 7)
+
+        label = Gtk.Label("<b>" + xstr("weighthelp_payload") + "</b>")
+        label.set_use_markup(True)
+        alignment = Gtk.Alignment(xalign = 0.0, yalign = 0.5,
                                   xscale = 0.0, yscale = 0.0)
         alignment.add(label)
         table.attach(alignment, 0, 1, 7, 8)
 
-        self._payload = gtk.Label("<b>32000</b>")
+        self._payload = Gtk.Label("<b>32000</b>")
         self._payload.set_use_markup(True)
-        alignment = gtk.Alignment(xalign = 1.0, yalign = 0.5,
+        alignment = Gtk.Alignment(xalign = 1.0, yalign = 0.5,
                                   xscale = 0.0, yscale = 0.0)
         alignment.add(self._payload)
         table.attach(alignment, 1, 2, 7, 8)
         
-        table.attach(gtk.Label("kg"), 2, 3, 7, 8)
-
-        self._fsPayload = gtk.Label("<b>32001</b>")
+        table.attach(Gtk.Label("kg"), 2, 3, 7, 8)
+
+        self._fsPayload = Gtk.Label("<b>32001</b>")
         self._fsPayload.set_use_markup(True)
-        alignment = gtk.Alignment(xalign = 1.0, yalign = 0.5,
+        alignment = Gtk.Alignment(xalign = 1.0, yalign = 0.5,
                                   xscale = 0.0, yscale = 0.0)
         alignment.add(self._fsPayload)
         table.attach(alignment, 3, 4, 7, 8)
         
-        table.attach(gtk.Label("kg"), 4, 5, 7, 8)
-
-        label = gtk.Label(xstr("weighthelp_dow"))
-        label.set_use_markup(True)
-        alignment = gtk.Alignment(xalign = 0.0, yalign = 0.5,
+        table.attach(Gtk.Label("kg"), 4, 5, 7, 8)
+
+        label = Gtk.Label(xstr("weighthelp_dow"))
+        label.set_use_markup(True)
+        alignment = Gtk.Alignment(xalign = 0.0, yalign = 0.5,
                                   xscale = 0.0, yscale = 0.0)
         alignment.add(label)
         table.attach(alignment, 0, 1, 8, 9)
 
-        self._dow = gtk.Label("35000")
-        alignment = gtk.Alignment(xalign = 1.0, yalign = 0.5,
+        self._dow = Gtk.Label("35000")
+        alignment = Gtk.Alignment(xalign = 1.0, yalign = 0.5,
                                   xscale = 0.0, yscale = 0.0)
         alignment.add(self._dow)
         table.attach(alignment, 1, 2, 8, 9)
         
-        table.attach(gtk.Label("kg"), 2, 3, 8, 9)
-
-        self._fsDOW = gtk.Label("33012")
-        alignment = gtk.Alignment(xalign = 1.0, yalign = 0.5,
+        table.attach(Gtk.Label("kg"), 2, 3, 8, 9)
+
+        self._fsDOW = Gtk.Label("33012")
+        alignment = Gtk.Alignment(xalign = 1.0, yalign = 0.5,
                                   xscale = 0.0, yscale = 0.0)
         alignment.add(self._fsDOW)
         table.attach(alignment, 3, 4, 8, 9)
         
-        table.attach(gtk.Label("kg"), 4, 5, 8, 9)
-
-        table.attach(gtk.HSeparator(), 1, 2, 9, 10)
-
-        table.attach(gtk.HSeparator(), 3, 4, 9, 10)
-
-        label = gtk.Label("<b>" + xstr("weighthelp_zfw") + "</b>")
-        label.set_use_markup(True)
-        alignment = gtk.Alignment(xalign = 0.0, yalign = 0.5,
+        table.attach(Gtk.Label("kg"), 4, 5, 8, 9)
+
+        table.attach(Gtk.HSeparator(), 1, 2, 9, 10)
+
+        table.attach(Gtk.HSeparator(), 3, 4, 9, 10)
+
+        label = Gtk.Label("<b>" + xstr("weighthelp_zfw") + "</b>")
+        label.set_use_markup(True)
+        alignment = Gtk.Alignment(xalign = 0.0, yalign = 0.5,
                                   xscale = 0.0, yscale = 0.0)
         alignment.add(label)
         table.attach(alignment, 0, 1, 10, 11)
 
-        self._zfw = gtk.Label("<b>122000</b>")
+        self._zfw = Gtk.Label("<b>122000</b>")
         self._zfw.set_use_markup(True)
-        alignment = gtk.Alignment(xalign = 1.0, yalign = 0.5,
+        alignment = Gtk.Alignment(xalign = 1.0, yalign = 0.5,
                                   xscale = 0.0, yscale = 0.0)
         alignment.add(self._zfw)
         table.attach(alignment, 1, 2, 10, 11)
         
-        table.attach(gtk.Label("kg"), 2, 3, 10, 11)
-
-        self._fsZFW = gtk.Label("<b>124000</b>")
+        table.attach(Gtk.Label("kg"), 2, 3, 10, 11)
+
+        self._fsZFW = Gtk.Label("<b>124000</b>")
         self._fsZFW.set_use_markup(True)
-        alignment = gtk.Alignment(xalign = 1.0, yalign = 0.5,
+        alignment = Gtk.Alignment(xalign = 1.0, yalign = 0.5,
                                   xscale = 0.0, yscale = 0.0)
         alignment.add(self._fsZFW)
         table.attach(alignment, 3, 4, 10, 11)
         
-        table.attach(gtk.Label("kg"), 4, 5, 10, 11)
-
-        table.attach(gtk.HSeparator(), 0, 5, 11, 12)
-        
-        label = gtk.Label(xstr("weighthelp_gross"))
-        label.set_use_markup(True)
-        alignment = gtk.Alignment(xalign = 0.0, yalign = 0.5,
+        table.attach(Gtk.Label("kg"), 4, 5, 10, 11)
+
+        table.attach(Gtk.HSeparator(), 0, 5, 11, 12)
+        
+        label = Gtk.Label(xstr("weighthelp_gross"))
+        label.set_use_markup(True)
+        alignment = Gtk.Alignment(xalign = 0.0, yalign = 0.5,
                                   xscale = 0.0, yscale = 0.0)
         alignment.add(label)
         table.attach(alignment, 0, 1, 12, 13)
 
-        self._fsGross = gtk.Label("124000")
-        alignment = gtk.Alignment(xalign = 1.0, yalign = 0.5,
+        self._fsGross = Gtk.Label("124000")
+        alignment = Gtk.Alignment(xalign = 1.0, yalign = 0.5,
                                   xscale = 0.0, yscale = 0.0)
         alignment.add(self._fsGross)
         table.attach(alignment, 3, 4, 12, 13)
         
-        table.attach(gtk.Label("kg"), 4, 5, 12, 13)
-
-        label = gtk.Label(xstr("weighthelp_mzfw"))
-        label.set_use_markup(True)
-        alignment = gtk.Alignment(xalign = 0.0, yalign = 0.5,
+        table.attach(Gtk.Label("kg"), 4, 5, 12, 13)
+
+        label = Gtk.Label(xstr("weighthelp_mzfw"))
+        label.set_use_markup(True)
+        alignment = Gtk.Alignment(xalign = 0.0, yalign = 0.5,
                                   xscale = 0.0, yscale = 0.0)
         alignment.add(label)
         table.attach(alignment, 0, 1, 13, 14)
 
-        self._mzfw = gtk.Label("35000")
-        alignment = gtk.Alignment(xalign = 1.0, yalign = 0.5,
+        self._mzfw = Gtk.Label("35000")
+        alignment = Gtk.Alignment(xalign = 1.0, yalign = 0.5,
                                   xscale = 0.0, yscale = 0.0)
         alignment.add(self._mzfw)
         table.attach(alignment, 1, 2, 13, 14)
         
-        table.attach(gtk.Label("kg"), 2, 3, 13, 14)
-
-        label = gtk.Label(xstr("weighthelp_mtow"))
-        label.set_use_markup(True)
-        alignment = gtk.Alignment(xalign = 0.0, yalign = 0.5,
+        table.attach(Gtk.Label("kg"), 2, 3, 13, 14)
+
+        label = Gtk.Label(xstr("weighthelp_mtow"))
+        label.set_use_markup(True)
+        alignment = Gtk.Alignment(xalign = 0.0, yalign = 0.5,
                                   xscale = 0.0, yscale = 0.0)
         alignment.add(label)
         table.attach(alignment, 0, 1, 14, 15)
 
-        self._mtow = gtk.Label("35000")
-        alignment = gtk.Alignment(xalign = 1.0, yalign = 0.5,
+        self._mtow = Gtk.Label("35000")
+        alignment = Gtk.Alignment(xalign = 1.0, yalign = 0.5,
                                   xscale = 0.0, yscale = 0.0)
         alignment.add(self._mtow)
         table.attach(alignment, 1, 2, 14, 15)
         
-        table.attach(gtk.Label("kg"), 2, 3, 14, 15)
-
-        label = gtk.Label(xstr("weighthelp_mlw"))
-        label.set_use_markup(True)
-        alignment = gtk.Alignment(xalign = 0.0, yalign = 0.5,
+        table.attach(Gtk.Label("kg"), 2, 3, 14, 15)
+
+        label = Gtk.Label(xstr("weighthelp_mlw"))
+        label.set_use_markup(True)
+        alignment = Gtk.Alignment(xalign = 0.0, yalign = 0.5,
                                   xscale = 0.0, yscale = 0.0)
         alignment.add(label)
         table.attach(alignment, 0, 1, 15, 16)
 
-        self._mlw = gtk.Label("35000")
-        alignment = gtk.Alignment(xalign = 1.0, yalign = 0.5,
+        self._mlw = Gtk.Label("35000")
+        alignment = Gtk.Alignment(xalign = 1.0, yalign = 0.5,
                                   xscale = 0.0, yscale = 0.0)
         alignment.add(self._mlw)
         table.attach(alignment, 1, 2, 15, 16)
         
-        table.attach(gtk.Label("kg"), 2, 3, 15, 16)
+        table.attach(Gtk.Label("kg"), 2, 3, 15, 16)
 
         self.show_all()
@@ -468,5 +466,5 @@
     def _handleWeights(self, dow, payload, zfw, grossWeight):
         """Handle the given weights."""
-        gobject.idle_add(self._processWeights, dow, payload, zfw, grossWeight)
+        GObject.idle_add(self._processWeights, dow, payload, zfw, grossWeight)
 
     def _processWeights(self, dow, payload, zfw, grossWeight):
Index: src/mlx/i18n.py
===================================================================
--- src/mlx/i18n.py	(revision 298)
+++ src/mlx/i18n.py	(revision 928)
@@ -24,5 +24,5 @@
 def setLanguage(programDirectory, language):
     """Setup the internationalization support for the given language."""
-    print "i18n.setLanguage", language
+    print("i18n.setLanguage", language)
     translation = _getTranslation(programDirectory, language)
     fallback = _getFallbackFor(programDirectory, language)
@@ -51,5 +51,5 @@
     If not found, the fallback language is searched. If that is not found
     either, the key itself is returned within curly braces."""
-    return _translation.ugettext(key)
+    return _translation.gettext(key)
     
 #------------------------------------------------------------------------------
Index: src/mlx/logger.py
===================================================================
--- src/mlx/logger.py	(revision 634)
+++ src/mlx/logger.py	(revision 921)
@@ -1,10 +1,11 @@
 
-from fs import sendMessage
-import const
-import util
+from .fs import sendMessage
+from . import const
+from . import util
 
 import sys
 import time
 import bisect
+from functools import total_ordering
 
 #--------------------------------------------------------------------------------------
@@ -34,4 +35,5 @@
     increasing IDs."""
 
+    @total_ordering
     class Entry(object):
         """An entry in the log."""
@@ -119,13 +121,19 @@
                                 id = self._id)
 
-        def __cmp__(self, other):
-            """Compare two entries
-
-            First their timestamps are compared, and if those are equal, then
-            their IDs."""
-            result = cmp(self._timestamp, other.timestamp)
-            if result==0:
-                result = cmp(self._id, other._id)
-            return result
+        def __eq__(self, other):
+            """Equality comparison"""
+            return self._timestamp == other.timestamp and \
+                self._id == other._id
+
+        def __ne__(self, other):
+            """Non-equality comparison"""
+            return self._timestamp != other.timestamp or \
+                self._id != other._id
+
+        def __lt__(self, other):
+            """Less-than comparison"""
+            return self._timestamp < other.timestamp or \
+                (self._timestamp == other.timestamp and
+                 self._id < other._id)
 
     class Fault(object):
@@ -235,5 +243,5 @@
     def debug(self, msg):
         """Log a debug message."""
-        print "[DEBUG]", msg
+        print("[DEBUG]", msg)
 
     def stage(self, timestamp, stage):
@@ -326,5 +334,5 @@
         """Get the rating of the flight so far."""
         totalScore = 100
-        for fault in self._faults.itervalues():
+        for fault in self._faults.values():
             score = fault.score
             if score==Logger.NO_GO_SCORE:
Index: src/mlx/mlx.py
===================================================================
--- src/mlx/mlx.py	(revision 800)
+++ src/mlx/mlx.py	(revision 919)
@@ -1,9 +1,9 @@
 
-from config import Config
-from i18n import setLanguage
-from sound import preInitializeSound, initializeSound, finalizeSound
-from util import secondaryInstallation
-from const import VERSION
-from watchdog import Watchdog
+from .config import Config
+from .i18n import setLanguage
+from .sound import preInitializeSound, initializeSound, finalizeSound
+from .util import secondaryInstallation
+from .const import VERSION
+from .watchdog import Watchdog
 
 import os
@@ -60,5 +60,5 @@
 def main():
     """The main operation of the program."""
-    from singleton import SingleInstance, raiseCallbackWrapper
+    from .singleton import SingleInstance, raiseCallbackWrapper
 
     global instance
@@ -86,6 +86,6 @@
     sys.stderr = StdIOHandler(gui)
 
-    print "MAVA Logger X " + VERSION + " debug log"
-    print "The initial configuration:"
+    print("MAVA Logger X " + VERSION + " debug log")
+    print("The initial configuration:")
     config.log()
 
Index: src/mlx/pirep.py
===================================================================
--- src/mlx/pirep.py	(revision 856)
+++ src/mlx/pirep.py	(revision 955)
@@ -1,8 +1,9 @@
 
-from util import utf2unicode
-from flight import Flight
-
-import const
-import cPickle as pickle
+from .util import utf2unicode
+from .flight import Flight
+from .common import fixUnpickled
+
+from . import const
+import pickle as pickle
 import calendar
 import datetime
@@ -65,5 +66,5 @@
     def decodeFlightTypeText(s):
         """Decode the given flight type text."""
-        for (flighType, text) in PIREP._flightTypes.iteritems():
+        for (flighType, text) in PIREP._flightTypes.items():
             if s==text:
                 return flighType
@@ -114,5 +115,5 @@
         try:
             with open(path, "rb") as f:
-                pirep = pickle.load(f)
+                pirep = pickle.load(f, fix_imports = True, encoding = "bytes")
                 if "numCrew" not in dir(pirep):
                     pirep.numCrew = pirep.bookedFlight.numCrew
@@ -124,7 +125,7 @@
                     pirep.mailWeight = pirep.bookedFlight.mailWeight
                 return pirep
-        except Exception, e:
-            print "Failed loading PIREP from %s: %s" % (path,
-                                                        utf2unicode(str(e)))
+        except Exception as e:
+            print("Failed loading PIREP from %s: %s" % (path,
+                                                        utf2unicode(str(e))))
             return None
 
@@ -367,7 +368,7 @@
                 pickle.dump(self, f)
             return None
-        except Exception, e:
+        except Exception as e:
             error = utf2unicode(str(e))
-            print u"Failed saving PIREP to %s: %s" % (path, error)
+            print("Failed saving PIREP to %s: %s" % (path, error))
             return error
 
@@ -412,2 +413,6 @@
 
         return ([], attrs)
+
+    def __setstate__(self, state):
+        """Set the state from the given unpickled dictionary."""
+        self.__dict__.update(fixUnpickled(state))
Index: src/mlx/pyuipc_emu.py
===================================================================
--- src/mlx/pyuipc_emu.py	(revision 298)
+++ src/mlx/pyuipc_emu.py	(revision 919)
@@ -217,9 +217,9 @@
             results.append(int(vs / 60.0 * 0.3048 * 256))
         elif offset==0x0560:  # Latitude
-            results.append(long(latitude*10001750.0*65536.0*65536.0/90.0))
+            results.append(int(latitude*10001750.0*65536.0*65536.0/90.0))
         elif offset==0x0568:  # Longitude
-            results.append(long(longitude*65536.9*65536.0*65536.0*65536.0/360.0))
+            results.append(int(longitude*65536.9*65536.0*65536.0*65536.0/360.0))
         elif offset==0x0570:  # Aircraft altitude in metres (fractional part)
-            results.append(long( (altitude*0.3048*65536*65536)%(65536*65536)))
+            results.append(int( (altitude*0.3048*65536*65536)%(65536*65536)))
         elif offset==0x0574:  # Aircraft altitude in metres (whole part)
             results.append(int(altitude*.3048))
@@ -237,15 +237,15 @@
             centre_fuel = fuel_remaining - 2*side_tank_capacity
             if centre_fuel<0: centre_fuel = 0.0
-            results.append(long(round(centre_fuel/centre_tank_capacity*128.0*65536.0)))
+            results.append(int(round(centre_fuel/centre_tank_capacity*128.0*65536.0)))
         elif offset==0x0b78:  # Centre tank capacity (gallons)
-            results.append(long(round(centre_tank_capacity*KGTOLBS/fuel_weight)))
+            results.append(int(round(centre_tank_capacity*KGTOLBS/fuel_weight)))
         elif offset==0x0b7c or \
              offset==0x0b94:  # Left and right main tank level (%*128*65536)
             fuel = fuel_remaining/2
             if fuel>side_tank_capacity: fuel = side_tank_capacity
-            results.append(long(round(fuel/side_tank_capacity*128.0*65536.0)))
+            results.append(int(round(fuel/side_tank_capacity*128.0*65536.0)))
         elif offset==0x0b80 or \
              offset==0x0b98:  # Left and right main tank capacity (gallons)
-            results.append(long(round(side_tank_capacity*KGTOLBS/fuel_weight)))
+            results.append(int(round(side_tank_capacity*KGTOLBS/fuel_weight)))
         elif offset in [0x0b84, 0x0b88, 0x0b8c, 0x0b90,
                         0x0b9c, 0x0ba0, 0x0ba4, 0x0ba8,
@@ -253,5 +253,5 @@
                         0x1254, 0x1258, 0x125c, 0x1260]:
                               # Other tank capacities and levels
-            results.append(long(0))
+            results.append(int(0))
         elif offset==0x023a:  # Second of time
             results.append(int(tm[5]))
Index: src/mlx/pyuipc_sim.py
===================================================================
--- src/mlx/pyuipc_sim.py	(revision 877)
+++ src/mlx/pyuipc_sim.py	(revision 969)
@@ -1,4 +1,4 @@
 
-import const
+from . import const
 
 import cmd
@@ -9,5 +9,5 @@
 import sys
 import struct
-import cPickle
+import pickle
 import math
 
@@ -184,9 +184,9 @@
     def _readBCD(value):
         """Convert the given value into BCD format."""
-        bcd = (value/1000) % 10
+        bcd = (value//1000) % 10
         bcd <<= 4
-        bcd |= (value/100) % 10
+        bcd |= (value//100) % 10
         bcd <<= 4
-        bcd |= (value/10) % 10
+        bcd |= (value//10) % 10
         bcd <<= 4
         bcd |= value % 10
@@ -342,6 +342,6 @@
         try:
             return self._read(offset, type)
-        except Exception, e:
-            print "failed to read offset %04x: %s" % (offset, str(e))
+        except Exception as e:
+            print("failed to read offset %04x: %s" % (offset, str(e)))
             raise FSUIPCException(ERR_DATA)
 
@@ -360,5 +360,5 @@
             return int(index * flapsIncrement +
                        (self.flapsControl-self.flapsNotches[index]) *
-                       flapsIncrement /
+                       flapsIncrement //
                        (self.flapsNotches[index+1] - self.flapsNotches[index]))
 
@@ -414,9 +414,9 @@
             return 1 if self.overspeed else 0
         elif offset==0x0560:       # Latitude
-            return long(self.latitude * 10001750.0 * 65536.0 * 65536.0 / 90.0)
+            return int(self.latitude * 10001750.0 * 65536.0 * 65536.0 / 90.0)
         elif offset==0x0568:       # Longitude
-            return long(self.longitude * 65536.0 * 65536.0 * 65536.0 * 65536.0 / 360.0)
+            return int(self.longitude * 65536.0 * 65536.0 * 65536.0 * 65536.0 / 360.0)
         elif offset==0x0570:       # Altitude
-            return long(self.altitude * const.FEETTOMETRES * 65536.0 * 65536.0)
+            return int(self.altitude * const.FEETTOMETRES * 65536.0 * 65536.0)
         elif offset==0x0578:       # Pitch
             return int(self.pitch * 65536.0 * 65536.0 / 360.0)
@@ -542,5 +542,5 @@
         elif offset>=0x1400 and offset<=0x1f40 and \
              ((offset-0x1400)%48)==0: # Payload
-            return self.payload[ (offset - 0x1400) / 48 ]
+            return self.payload[ (offset - 0x1400) // 48 ]
         elif offset==0x2000:       # Engine #1 N1
             return self.n1[self.ENGINE_1]
@@ -568,5 +568,5 @@
         elif offset>=0x3210 and offset<0x3210+Values.HOTKEY_SIZE*4:
             tableOffset = offset - 0x3210
-            hotkeyIndex = tableOffset / 4
+            hotkeyIndex = tableOffset // 4
             index = tableOffset % 4
             if type=="b" or type=="c":
@@ -584,8 +584,8 @@
                     return value
                 else:
-                    print "Unhandled offset: %04x" % (offset,)
+                    print("Unhandled offset: %04x" % (offset,))
                     raise FSUIPCException(ERR_DATA)
             else:
-                print "Unhandled offset: %04x" % (offset,)
+                print("Unhandled offset: %04x" % (offset,))
                 raise FSUIPCException(ERR_DATA)
         elif offset==0x32fa:       # Message duration
@@ -602,5 +602,5 @@
             return self._getFlapsControl()
         elif offset==0x3bfa:       # Flaps increment
-            return 16383 / (len(self.flapsNotches)-1)
+            return 16383 // (len(self.flapsNotches)-1)
         elif offset==0x3bfc:       # ZFW
             return int(self.zfw * 256.0 * const.KGSTOLB)
@@ -616,5 +616,5 @@
             return 0 if self.xpdrC else 1
         else:
-            print "Unhandled offset: %04x" % (offset,)
+            print("Unhandled offset: %04x" % (offset,))
             raise FSUIPCException(ERR_DATA)
 
@@ -623,8 +623,8 @@
         try:
             return self._write(offset, value, type)
-        except TypeError, e:
+        except TypeError as e:
             raise e
-        except Exception, e:
-            print "failed to write offset %04x: %s" % (offset, str(e))
+        except Exception as e:
+            print("failed to write offset %04x: %s" % (offset, str(e)))
             raise FSUIPCException(ERR_DATA)
 
@@ -758,5 +758,5 @@
         elif offset==0x0bd0:       # Spoilers
             self.spoilters = 0 if value==0 \
-                             else (value - 4800) / (16383 - 4800)
+                             else (value - 4800) // (16383 - 4800)
         elif offset==0x0bdc:       # Flaps control
             numNotchesM1 = len(self.flapsNotches) - 1
@@ -768,5 +768,5 @@
                 self.flapsControl = self.flapsNotches[index]
                 self.flapsControl += (value - index * flapsIncrement) * \
-                    (self.flapsNotches[index+1] - self.flapsNotches[index]) / \
+                    (self.flapsNotches[index+1] - self.flapsNotches[index]) // \
                     flapsIncrement
         elif offset==0x0be0 or offset==0x0be4:    # Flaps left and  right
@@ -816,5 +816,5 @@
         elif offset>=0x1400 and offset<=0x1f40 and \
              ((offset-0x1400)%48)==0: # Payload
-            self.payload[ (offset - 0x1400) / 48 ] = value
+            self.payload[ (offset - 0x1400) // 48 ] = value
         elif offset==0x2000:       # Engine #1 N1
             self.n1[self.ENGINE_1] = value
@@ -840,5 +840,5 @@
         elif offset>=0x3210 and offset<0x3210+Values.HOTKEY_SIZE*4:
             tableOffset = offset - 0x3210
-            hotkeyIndex = tableOffset / 4
+            hotkeyIndex = tableOffset // 4
             index = tableOffset % 4
             if type=="b" or type=="c":
@@ -852,8 +852,8 @@
                     hotkey[3] = (value>>24) & 0xff
                 else:
-                    print "Unhandled offset: %04x for type '%s'" % (offset, type)
+                    print("Unhandled offset: %04x for type '%s'" % (offset, type))
                     raise FSUIPCException(ERR_DATA)
             else:
-                print "Unhandled offset: %04x for type '%s'" % (offset, type)
+                print("Unhandled offset: %04x for type '%s'" % (offset, type))
                 raise FSUIPCException(ERR_DATA)
         elif offset==0x32fa:       # Message duration
@@ -882,5 +882,5 @@
             self.xpdrC = value==0
         else:
-            print "Unhandled offset: %04x" % (offset,)
+            print("Unhandled offset: %04x" % (offset,))
             raise FSUIPCException(ERR_DATA)
 
@@ -1039,5 +1039,5 @@
                 (length,) = struct.unpack("I", clientSocket.recv(4))
                 data = clientSocket.recv(length)
-                (call, args) = cPickle.loads(data)
+                (call, args) = pickle.loads(data)
                 exception = None
 
@@ -1061,14 +1061,14 @@
                     else:
                         break
-                except Exception, e:
+                except Exception as e:
                     exception = e
 
                 if exception is None:
-                    data = cPickle.dumps((RESULT_RETURNED, result))
+                    data = pickle.dumps((RESULT_RETURNED, result))
                 else:
-                    data = cPickle.dumps((RESULT_EXCEPTION, str(exception)))
+                    data = pickle.dumps((RESULT_EXCEPTION, str(exception)))
                 clientSocket.send(struct.pack("I", len(data)) + data)
-        except Exception, e:
-            print >> sys.stderr, "pyuipc_sim.Server._process: failed with exception:", str(e)
+        except Exception as e:
+            print("pyuipc_sim.Server._process: failed with exception:", str(e), file=sys.stderr)
         finally:
             try:
@@ -1112,14 +1112,14 @@
     def quit(self):
         """Quit from the simulator."""
-        data = cPickle.dumps((CALL_QUIT, None))
+        data = pickle.dumps((CALL_QUIT, None))
         self._socket.send(struct.pack("I", len(data)) + data)
 
     def _call(self, command, data):
         """Perform a call with the given command and data."""
-        data = cPickle.dumps((command, [data]))
+        data = pickle.dumps((command, [data]))
         self._socket.send(struct.pack("I", len(data)) + data)
         (length,) = struct.unpack("I", self._socket.recv(4))
         data = self._socket.recv(length)
-        (resultCode, result) = cPickle.loads(data)
+        (resultCode, result) = pickle.loads(data)
         if resultCode==RESULT_RETURNED:
             return result
@@ -1234,5 +1234,5 @@
                                            lambda value: value * 90.0 /
                                            10001750.0 / 65536.0 / 65536.0,
-                                           lambda word: long(float(word) *
+                                           lambda word: int(float(word) *
                                                              10001750.0 *
                                                              65536.0 * 65536.0 / 90.0))
@@ -1240,5 +1240,5 @@
                                             lambda value: value * 360.0 /
                                             65536.0 / 65536.0 / 65536.0 / 65536.0,
-                                            lambda word: long(float(word) *
+                                            lambda word: int(float(word) *
                                                               65536.0 * 65536.0 *
                                                               65536.0 * 65536.0 /
@@ -1300,5 +1300,5 @@
                                            const.FEETTOMETRES / 65536.0 /
                                            65536.0,
-                                           lambda word: long(float(word) *
+                                           lambda word: int(float(word) *
                                                              const.FEETTOMETRES *
                                                              65536.0 * 65536.0))
@@ -1487,5 +1487,5 @@
             self._valueHandlers["hotkey%d" % (i,)] = ([(0x3210 + i*4, "u")],
                                                       lambda value: "0x%08x" % (value,),
-                                                      lambda word: long(word, 16))
+                                                      lambda word: int(word, 16))
 
         self._valueHandlers["cog"] = ([(0x2ef8, "f")], lambda value: value,
@@ -1537,5 +1537,5 @@
         """Handle unhandle commands."""
         if line=="EOF":
-            print
+            print()
             return self.do_quit("")
         else:
@@ -1548,5 +1548,5 @@
         for name in names:
             if name not in self._valueHandlers:
-                print >> sys.stderr, "Unknown variable: " + name
+                print("Unknown variable: " + name, file=sys.stderr)
                 return False
             valueHandler = self._valueHandlers[name]
@@ -1565,10 +1565,10 @@
                                         else thisResults)
 
-                print name + "=" + str(value)
+                print(name + "=" + str(value))
 
                 index += numResults
                 i+=1
-        except Exception, e:
-            print >> sys.stderr, "Failed to read data: " + str(e)
+        except Exception as e:
+            print("Failed to read data: " + str(e), file=sys.stderr)
 
         return False
@@ -1576,5 +1576,5 @@
     def help_get(self):
         """Print help for the get command."""
-        print "get <variable> [<variable>...]"
+        print("get <variable> [<variable>...]")
 
     def complete_get(self, text, line, begidx, endidx):
@@ -1608,10 +1608,10 @@
             words = argument.split("=")
             if len(words)!=2:
-                print >> sys.stderr, "Invalid argument: " + argument
+                print("Invalid argument: " + argument, file=sys.stderr)
                 return False
 
             (name, value) = words
             if name not in self._valueHandlers:
-                print >> sys.stderr, "Unknown variable: " + name
+                print("Unknown variable: " + name, file=sys.stderr)
                 return False
 
@@ -1625,14 +1625,14 @@
                     data.append((offset, type, values[index]))
                     index += 1
-            except Exception, e:
-                print >> sys.stderr, "Invalid value '%s' for variable %s: %s" % \
-                      (value, name, str(e))
+            except Exception as e:
+                print("Invalid value '%s' for variable %s: %s" % \
+                      (value, name, str(e)), file=sys.stderr)
                 return False
 
         try:
             self._client.write(data)
-            print "Data written"
-        except Exception, e:
-            print >> sys.stderr, "Failed to write data: " + str(e)
+            print("Data written")
+        except Exception as e:
+            print("Failed to write data: " + str(e), file=sys.stderr)
 
         return False
@@ -1640,5 +1640,5 @@
     def help_set(self):
         """Print help for the set command."""
-        print "set <variable>=<value> [<variable>=<value>...]"
+        print("set <variable>=<value> [<variable>=<value>...]")
 
     def complete_set(self, text, line, begidx, endidx):
@@ -1654,12 +1654,12 @@
             value = int(args)
             self._client.setVersion(value)
-            print "Emulating version %d" % (value,)
-        except Exception, e:
-            print >> sys.stderr, "Failed to set the version: " + str(e)
+            print("Emulating version %d" % (value,))
+        except Exception as e:
+            print("Failed to set the version: " + str(e), file=sys.stderr)
 
     def help_setversion(self, usage = False):
         """Help for the setversion command"""
-        if usage: print "Usage:",
-        print "setversion <number>"
+        if usage: print("Usage:", end=' ')
+        print("setversion <number>")
 
     def do_close(self, args):
@@ -1667,7 +1667,7 @@
         try:
             self._client.close()
-            print "Connection closed"
-        except Exception, e:
-            print >> sys.stderr, "Failed to close the connection: " + str(e)
+            print("Connection closed")
+        except Exception as e:
+            print("Failed to close the connection: " + str(e), file=sys.stderr)
 
     def do_failopen(self, args):
@@ -1676,12 +1676,12 @@
             value = self.str2bool(args)
             self._client.failOpen(value)
-            print "Opening will%s fail" % ("" if value else " not",)
-        except Exception, e:
-            print >> sys.stderr, "Failed to set open failure: " + str(e)
+            print("Opening will%s fail" % ("" if value else " not",))
+        except Exception as e:
+            print("Failed to set open failure: " + str(e), file=sys.stderr)
 
     def help_failopen(self, usage = False):
         """Help for the failopen command"""
-        if usage: print "Usage:",
-        print "failopen yes|no"
+        if usage: print("Usage:", end=' ')
+        print("failopen yes|no")
 
     def complete_failopen(self, text, line, begidx, endidx):
Index: src/mlx/rpc.py
===================================================================
--- src/mlx/rpc.py	(revision 889)
+++ src/mlx/rpc.py	(revision 955)
@@ -1,6 +1,6 @@
-import const
-import rpccommon
-
-from common import MAVA_BASE_URL
+from . import const
+from . import rpccommon
+
+from .common import MAVA_BASE_URL, fixUnpickled
 
 import jsonrpclib
@@ -28,5 +28,5 @@
         For all other names, the value will be stored as the same-named
         attribute."""
-        for (key, value) in value.iteritems():
+        for (key, value) in value.items():
             if key in instructions:
                 instruction = instructions[key]
@@ -37,6 +37,6 @@
                     value = instruction(value)
                 except:
-                    print >> sys.stderr, "Failed to convert value '%s' of attribute '%s':" % \
-                        (value, key)
+                    print("Failed to convert value '%s' of attribute '%s':" % \
+                        (value, key), file=sys.stderr)
                     import traceback
                     traceback.print_exc()
@@ -111,9 +111,12 @@
                 cs1 = int(self.callsign[2:])
                 cs2 = int(other.callsign[2:])
-                return cmp(cs1, cs2)
+                return 0 if cs1==cs2 else -1 if cs1<cs2 else 1
             except:
-                return cmp(self.callsign, other.callsign)
+                return 0 if self.callsign==other.callsign \
+                    else -1 if self.callsign<other.callsign else 1
         else:
-            return cmp(getattr(self, name), getattr(other, name))
+            v1 = getattr(self, name)
+            v2 = getattr(other, name)
+            return 0 if v1==v2 else -1 if v1<v2 else 1
 
     def __repr__(self):
@@ -166,6 +169,5 @@
                 flightPairs.append(ScheduledFlightPair(flight))
 
-        flightPairs.sort(cmp = lambda pair1, pair2:
-                         cmp(pair1.flight0.date, pair2.flight0.date))
+        flightPairs.sort(key = lambda pair: pair.flight0.date)
 
         return flightPairs
@@ -297,26 +299,30 @@
     def writeIntoFile(self, f):
         """Write the flight into a file."""
-        print >> f, "callsign=%s" % (self.callsign,)
+        print("callsign=%s" % (self.callsign,), file=f)
         date = self.departureTime.date()
-        print >> f, "date=%04d-%02d-%0d" % (date.year, date.month, date.day)
-        print >> f, "dep_airport=%s" % (self.departureICAO,)
-        print >> f, "dest_airport=%s" % (self.arrivalICAO,)
-        print >> f, "planecode=%s" % \
-              (BookedFlight.TYPE2TYPECODE[self.aircraftType],)
-        print >> f, "planetype=%s" % (self.aircraftTypeName,)
-        print >> f, "tail_nr=%s" % (self.tailNumber,)
-        print >> f, "passenger=%d" % (self.numPassengers,)
-        print >> f, "crew=%d" % (self.numCrew,)
-        print >> f, "bag=%d" % (self.bagWeight,)
-        print >> f, "cargo=%d" % (self.cargoWeight,)
-        print >> f, "mail=%d" % (self.mailWeight,)
-        print >> f, "flight_route=%s" % (self.route,)
+        print("date=%04d-%02d-%0d" % (date.year, date.month, date.day), file=f)
+        print("dep_airport=%s" % (self.departureICAO,), file=f)
+        print("dest_airport=%s" % (self.arrivalICAO,), file=f)
+        print("planecode=%s" % \
+              (BookedFlight.TYPE2TYPECODE[self.aircraftType],), file=f)
+        print("planetype=%s" % (self.aircraftTypeName,), file=f)
+        print("tail_nr=%s" % (self.tailNumber,), file=f)
+        print("passenger=%d" % (self.numPassengers,), file=f)
+        print("crew=%d" % (self.numCrew,), file=f)
+        print("bag=%d" % (self.bagWeight,), file=f)
+        print("cargo=%d" % (self.cargoWeight,), file=f)
+        print("mail=%d" % (self.mailWeight,), file=f)
+        print("flight_route=%s" % (self.route,), file=f)
         departureTime = self.departureTime
-        print >> f, "departure_time=%02d\\:%02d\\:%02d" % \
-              (departureTime.hour, departureTime.minute, departureTime.second)
+        print("departure_time=%02d\\:%02d\\:%02d" % \
+              (departureTime.hour, departureTime.minute, departureTime.second), file=f)
         arrivalTime = self.arrivalTime
-        print >> f, "arrival_time=%02d\\:%02d\\:%02d" % \
-              (arrivalTime.hour, arrivalTime.minute, arrivalTime.second)
-        print >> f, "foglalas_id=%s" % ("0" if self.id is None else self.id,)
+        print("arrival_time=%02d\\:%02d\\:%02d" % \
+              (arrivalTime.hour, arrivalTime.minute, arrivalTime.second), file=f)
+        print("foglalas_id=%s" % ("0" if self.id is None else self.id,), file=f)
+
+    def __setstate__(self, state):
+        """Set the state from the given unpickled dictionary."""
+        self.__dict__.update(fixUnpickled(state))
 
 #---------------------------------------------------------------------------------------
@@ -468,5 +474,5 @@
 
         md5 = hashlib.md5()
-        md5.update(password)
+        md5.update(password.encode("utf-8"))
         self._passwordHash = md5.hexdigest()
 
@@ -523,6 +529,5 @@
 
         for flights in [bookedFlights, reportedFlights, rejectedFlights]:
-            flights.sort(cmp = lambda flight1, flight2:
-                         cmp(flight1.departureTime, flight2.departureTime))
+            flights.sort(key = lambda flight: flight.departureTime)
 
         return (bookedFlights, reportedFlights, rejectedFlights)
Index: src/mlx/rpccommon.py
===================================================================
--- src/mlx/rpccommon.py	(revision 742)
+++ src/mlx/rpccommon.py	(revision 919)
@@ -3,5 +3,5 @@
 #------------------------------------------------------------------------------
 
-import const
+from . import const
 
 #------------------------------------------------------------------------------
@@ -51,5 +51,5 @@
         """Check if the gate of the given plane conflicts with another plane's
         position."""
-        for p in self._planes.itervalues():
+        for p in self._planes.values():
             if p.tailNumber!=plane.tailNumber and \
                p.status==const.PLANE_HOME and \
@@ -62,5 +62,5 @@
         """Get a set containing the numbers of the gates occupied by planes."""
         gateNumbers = set()
-        for p in self._planes.itervalues():
+        for p in self._planes.values():
             if p.status==const.PLANE_HOME and p.gateNumber:
                 gateNumbers.add(p.gateNumber)
@@ -80,5 +80,5 @@
     def __iter__(self):
         """Get an iterator over the planes."""
-        for plane in self._planes.itervalues():
+        for plane in self._planes.values():
             yield plane
 
Index: src/mlx/singleton.py
===================================================================
--- src/mlx/singleton.py	(revision 401)
+++ src/mlx/singleton.py	(revision 1019)
@@ -1,4 +1,4 @@
 
-from util import utf2unicode
+from .util import utf2unicode
 
 import os
@@ -59,8 +59,8 @@
                         break
 
-                    print "singleton._PipeServer.run: created the pipe"
+                    print("singleton._PipeServer.run: created the pipe")
                     try:
                         if win32pipe.ConnectNamedPipe(handle)==0:
-                            print "singleton._PipeServer.run: client connection received"
+                            print("singleton._PipeServer.run: client connection received")
                             (code, message) = \
                                 win32file.ReadFile(handle,
@@ -69,17 +69,17 @@
 
                             if code==0:
-                                print "singleton._PipeServer.run: message received from client"
+                                print("singleton._PipeServer.run: message received from client")
                                 self._raiseCallback()
                             else:
-                                print "singleton._PipeServer.run: failed to read from the pipe"
-                    except Exception, e:
-                        print "singleton._PipeServer.run: exception:",
-                        print utf2unicode(str(e))
+                                print("singleton._PipeServer.run: failed to read from the pipe")
+                    except Exception as e:
+                        print("singleton._PipeServer.run: exception:", end=' ')
+                        print(utf2unicode(str(e)))
                     finally:
                         win32pipe.DisconnectNamedPipe(handle)
                         win32file.CloseHandle(handle)
-            except Exception, e:
-                print "singleton._PipeServer.run: fatal exception:",
-                print utf2unicode(str(e))
+            except Exception as e:
+                print("singleton._PipeServer.run: fatal exception:", end=' ')
+                print(utf2unicode(str(e)))
                             
         def _createPipe(self):
@@ -96,5 +96,5 @@
                                                None)
             if handle==win32file.INVALID_HANDLE_VALUE:
-                print "singleton._PipeServer.run: could not create the handle"
+                print("singleton._PipeServer.run: could not create the handle")
                 return None
             else:
@@ -144,10 +144,10 @@
                     f.close()
                     return
-                except Exception, e:
-                    print "SingleInstance._notifySingleton: failed:",
-                    print utf2unicode(str(e))
+                except Exception as e:
+                    print("SingleInstance._notifySingleton: failed:", end=' ')
+                    print(utf2unicode(str(e)))
                     time.sleep(0.5)
         
-        def __nonzero__(self):
+        def __bool__(self):
             """Return a boolean representation of the object.
 
@@ -194,7 +194,7 @@
                     s.recv(64)
                     self._raiseCallback()
-            except Exception, e:
-                print "singleton._SocketServer.run: fatal exception:",
-                print utf2unicode(str(e))
+            except Exception as e:
+                print("singleton._SocketServer.run: fatal exception:", end=' ')
+                print(utf2unicode(str(e)))
     
     class SingleInstance(object):
@@ -218,5 +218,5 @@
                 fcntl.lockf(self._lockFile, fcntl.LOCK_EX | fcntl.LOCK_NB)
                 self._isSingle = True
-            except Exception, e:
+            except Exception as e:
                 self._lockFile.close()
                 self._lockFile = None
@@ -256,13 +256,13 @@
                 try:
                     s.connect(self._socketName)
-                    s.send("hello")
+                    s.send(bytes("hello", "ascii"))
                     s.close()
                     return
-                except Exception, e:
-                    print "singleton.SingleInstance._notifySingleton: failed:",
-                    print utf2unicode(str(e))
+                except Exception as e:
+                    print("singleton.SingleInstance._notifySingleton: failed:", end=' ')
+                    print(utf2unicode(str(e)))
                     time.sleep(0.5)
 
-        def __nonzero__(self):
+        def __bool__(self):
             """Return a boolean representation of the object.
 
@@ -299,11 +299,11 @@
 if __name__=="__main__":
     def raiseCallback():
-        print "Raise the window!"
+        print("Raise the window!")
 
     instance = SingleInstance("mlx", raiseCallback)
     if instance:
-        print "The first instance"
+        print("The first instance")
         time.sleep(10)
     else:
-        print "The program is already running."
-
+        print("The program is already running.")
+
Index: src/mlx/sound.py
===================================================================
--- src/mlx/sound.py	(revision 800)
+++ src/mlx/sound.py	(revision 995)
@@ -1,4 +1,4 @@
 
-from util import utf2unicode
+from .util import utf2unicode
 
 import os
@@ -43,5 +43,5 @@
             """Send the given command to the MCI."""
             buffer = c_buffer(255)
-            errorCode = self.w32mci(str(command), buffer, 254, 0)
+            errorCode = self.w32mci(str(command).encode(), buffer, 254, 0)
             if errorCode:
                 raise MCIException(self, command, errorCode)
@@ -113,10 +113,10 @@
                     success = True
                     try:
-                        print "Closing", alias
+                        print("Closing", alias)
                         self._mci.send("close " + alias)
-                        print "Closed", alias
-                    except Exception, e:
-                        print "Failed closing " + alias + ":",
-                        print utf2unicode(str(e))
+                        print("Closed", alias)
+                    except Exception as e:
+                        print("Failed closing " + alias + ":", end=' ')
+                        print(utf2unicode(str(e)))
                         success = False
 
@@ -130,5 +130,5 @@
                     try:
                         alias = "mlxsound%d" % (counter,)
-                        print "Starting to play", path, "as", alias
+                        print("Starting to play", path, "as", alias)
                         self._mci.send("open \"%s\" alias %s" % \
                                        (path, alias))
@@ -137,4 +137,5 @@
                         lengthBuffer = self._mci.send("status %s length" % \
                                                       (alias,))
+                        lengthBuffer = str(lengthBuffer, "ascii")
                         self._mci.send("play %s from 0 to %s" % \
                                        (alias, lengthBuffer))
@@ -144,8 +145,8 @@
                             self._pending.append((timeout, (alias, finishData)))
                             self._pending.sort()
-                        print "Started to play", path
-                    except Exception, e:
-                        print "Failed to start playing " + path + ":",
-                        print utf2unicode(str(e))
+                        print("Started to play", path)
+                    except Exception as e:
+                        print("Failed to start playing " + path + ":", end=' ')
+                        print(utf2unicode(str(e)))
                         (finishCallback, extra) = finishData
                         if finishCallback is not None:
@@ -211,5 +212,5 @@
 
         In case of successful initialization, the directory of the sound files
-        is read, the command reader thread is created and the gobject main loop
+        is read, the command reader thread is created and the GObject main loop
         is executed."""
         try:
@@ -217,8 +218,8 @@
             gi.require_version("Gst", "1.0")
             from gi.repository import Gst
-            from gi.repository import GObject as gobject
+            from gi.repository import GObject
 
             Gst.init(None)
-        except Exception, e:
+        except Exception as e:
             outQueue.put(False)
             outQueue.put(e)
@@ -274,5 +275,5 @@
             It is to be executed in a separate thread and it reads the incoming
             queue for commands. The commands with their arguments are added to the
-            idle queue of gobject so that _handleCommand will be called by them.
+            idle queue of GObject so that _handleCommand will be called by them.
 
             If COMMAND_QUIT is received, the thread exits."""
@@ -281,5 +282,5 @@
                 (command, args) = inQueue.get()
 
-                gobject.idle_add(_handleCommand, command, args)
+                GObject.idle_add(_handleCommand, command, args)
                 if command==COMMAND_QUIT:
                     break
@@ -290,5 +291,5 @@
 
 
-        mainLoop = gobject.MainLoop()
+        mainLoop = GObject.MainLoop()
         mainLoop.run()
 
@@ -351,6 +352,6 @@
         else:
             exception = _inQueue.get()
-            print "The Gst library is missing from your system. It is needed for sound playback on Linux:"
-            print exception
+            print("The Gst library is missing from your system. It is needed for sound playback on Linux:")
+            print(exception)
 
     def startSound(name, finishCallback = None, extra = None):
@@ -387,5 +388,5 @@
 
     def callback(result, extra):
-        print "callback", result, extra
+        print("callback", result, extra)
 
     preInitializeSound()
@@ -393,5 +394,5 @@
     soundsPath = os.path.abspath(os.path.join(os.path.dirname(os.path.abspath(__file__)),
                                               "..", "..", "sounds"))
-    print "soundsPath:", soundsPath
+    print("soundsPath:", soundsPath)
     initializeSound(soundsPath)
     startSound("notam.mp3", finishCallback = callback, extra= "notam.mp3")
Index: src/mlx/soundsched.py
===================================================================
--- src/mlx/soundsched.py	(revision 352)
+++ src/mlx/soundsched.py	(revision 919)
@@ -1,6 +1,6 @@
 
-from sound import startSound
-import const
-import fs
+from .sound import startSound
+from . import const
+from . import fs
 
 import threading
@@ -64,7 +64,7 @@
         """Called when the playback of thee sound has finished (or failed)."""
         if success is None:
-            print "Failed to start sound", self._name
+            print("Failed to start sound", self._name)
         elif not success:
-            print "Failed to finish sound", self._name
+            print("Failed to finish sound", self._name)
         with Sound._lock:            
             self._playing -= 1
Index: src/mlx/test.py
===================================================================
--- src/mlx/test.py	(revision 27)
+++ src/mlx/test.py	(revision 919)
@@ -1,9 +1,9 @@
 # Test module
 
-import fs
-import flight
-import logger
-import acft
-import const
+from . import fs
+from . import flight
+from . import logger
+from . import acft
+from . import const
 
 import time
@@ -11,5 +11,5 @@
 
 def callback(data, extra):
-    print data
+    print(data)
 
 def main():
Index: src/mlx/update.py
===================================================================
--- src/mlx/update.py	(revision 957)
+++ src/mlx/update.py	(revision 977)
@@ -1,9 +1,9 @@
 
-from config import Config
-from util import utf2unicode
+from .config import Config
+from .util import utf2unicode
 
 import os
 import sys
-import urllib2
+import urllib.request, urllib.error, urllib.parse
 import tempfile
 import socket
@@ -11,4 +11,6 @@
 import hashlib
 import traceback
+import io
+import certifi
 
 if os.name=="nt":
@@ -57,5 +59,5 @@
 
         Each file is returned as a 3-tuple with items as in the file."""
-        for (path, (size, sum)) in self._files.iteritems():
+        for (path, (size, sum)) in self._files.items():
             yield (path, size, sum)
 
@@ -99,5 +101,5 @@
     def writeInto(self, file):
         """Write the manifest into the file at the given path."""
-        for (path, (size, sum)) in self._files.iteritems():
+        for (path, (size, sum)) in self._files.items():
             file.write("%s\t%d\t%s\n" % (path, size, sum))
 
@@ -201,5 +203,5 @@
     def _send(self, words):
         """Send the given words via the socket."""
-        self._sock.send("\t".join(words) + "\n")
+        self._sock.send(bytes("\t".join(words) + "\n", "utf-8"))
 
 #------------------------------------------------------------------------------
@@ -213,6 +215,6 @@
         with open(manifestPath, "rt") as f:
             manifest.readFrom(f)
-    except Exception, e:
-        print "Error reading the manifest, ignoring:", utf2unicode(str(e))
+    except Exception as e:
+        print("Error reading the manifest, ignoring:", utf2unicode(str(e)))
         manifest = Manifest()
 
@@ -232,10 +234,13 @@
     try:
         updateManifest = Manifest()
-        f= urllib2.urlopen(updateURL + "/" + manifestName)
-        updateManifest.readFrom(f)
-
-    except Exception, e:
+        reply = urllib.request.urlopen(updateURL + "/" + manifestName,
+                                       cafile = certifi.where())
+        charset = reply.headers.get_content_charset()
+        content = reply.read().decode("utf-8" if charset is None else charset)
+        updateManifest.readFrom(io.StringIO(content))
+
+    except Exception as e:
         error = utf2unicode(str(e))
-        print >> sys.stderr, "Error downloading manifest:", error
+        print("Error downloading manifest:", error, file=sys.stderr)
         listener.failed(error)
         return None
@@ -296,5 +301,5 @@
         try:
             sum = hashlib.md5()
-            sum.update(path)
+            sum.update(bytes(path, "utf-8"))
             toremoveDir = getToremoveDir(toremoveDir, directory)
             targetPath = os.path.join(toremoveDir, sum.hexdigest())
@@ -304,6 +309,6 @@
                 pass
             os.rename(path, targetPath)
-        except Exception, e:
-            print "Cannot remove file " + path + ": " + utf2unicode(str(e))
+        except Exception as e:
+            print("Cannot remove file " + path + ": " + utf2unicode(str(e)))
 
 #------------------------------------------------------------------------------
@@ -365,5 +370,6 @@
                 
             with open(targetFile, "wb") as fout:
-                fin = urllib2.urlopen(updateURL + "/" + path)
+                fin = urllib.request.urlopen(updateURL + "/" + path,
+                                             cafile = certifi.where())
                 while True:
                     data = fin.read(256*1024)
@@ -397,10 +403,10 @@
         
         listener.done()
-    except Exception, e:
+    except Exception as e:
         exc = traceback.format_exc()
-        print >> sys.stderr, utf2unicode(exc)
+        print(utf2unicode(exc), file=sys.stderr)
         
         error = utf2unicode(str(e))
-        print >> sys.stderr, "Error:", error
+        print("Error:", error, file=sys.stderr)
 
         listener.failed(error)
@@ -415,5 +421,5 @@
         f.close()
         return True
-    except Exception, e:
+    except Exception as e:
         return False
     finally:
@@ -445,8 +451,8 @@
                 listener.downloadedManifest()
             elif command=="setTotalSize":
-                listener.setTotalSize(int(words[1]), long(words[2]),
+                listener.setTotalSize(int(words[1]), int(words[2]),
                                       int(words[3]), int(words[4]))
             elif command=="setDownloaded":
-                listener.setDownloaded(long(words[1]))
+                listener.setDownloaded(int(words[1]))
             elif command=="startRenaming":
                 listener.startRenaming()
@@ -463,7 +469,7 @@
             elif command=="failed":
                 listener.failed(words[1])
-        except Exception, e:
-            print >> sys.stderr, "Failed to parse line '%s': %s" % \
-                  (line, utf2unicode(str(e)))
+        except Exception as e:
+            print("Failed to parse line '%s': %s" % \
+                  (line, utf2unicode(str(e))), file=sys.stderr)
 
     return buffer
@@ -511,5 +517,5 @@
                 break;
 
-            buffer += data
+            buffer += str(data, "utf-8")
             buffer = processMLXUpdate(buffer, listener)
 
@@ -520,7 +526,7 @@
             process.wait()
         
-    except Exception, e:
+    except Exception as e:
         error = utf2unicode(str(e))
-        print >> sys.stderr, "Failed updating:", error
+        print("Failed updating:", error, file=sys.stderr)
         listener.failed(error)
     finally:
@@ -569,10 +575,10 @@
             updateFiles(directory, updateURL, listener, updateManifest,
                         modifiedAndNew, removed, localRemoved)
-    except Exception, e:
+    except Exception as e:
         exc = traceback.format_exc()
-        print >> sys.stderr, utf2unicode(exc)
+        print(utf2unicode(exc), file=sys.stderr)
         
         error = utf2unicode(str(e))
-        print >> sys.stderr, "Update error:", error
+        print("Update error:", error, file=sys.stderr)
         
         listener.failed(error)
@@ -602,5 +608,5 @@
     except:
         exc = traceback.format_exc()
-        print >> sys.stderr, utf2unicode(exc)
+        print(utf2unicode(exc), file=sys.stderr)
 
 #------------------------------------------------------------------------------
Index: src/mlx/util.py
===================================================================
--- src/mlx/util.py	(revision 784)
+++ src/mlx/util.py	(revision 1004)
@@ -43,7 +43,7 @@
 #------------------------------------------------------------------------------
 
-def getCoordinateString((latitude, longitude)):
+def getCoordinateString(coordinates):
     """Get the string representation of the given coordinate pair."""
-
+    (latitude, longitude) = coordinates
     latitude_str = getLatitudeString(latitude)
     longitude_str = getLongitudeString(longitude)
@@ -79,5 +79,5 @@
     (deg, min, sec, _sign) = getDegMinSec(degree)
 
-    return u"%s%d\u00b0%02d\u2032%02d\u2033" % (prefix, deg, min, sec)
+    return "%s%d\u00b0%02d\u2032%02d\u2033" % (prefix, deg, min, sec)
 
 #------------------------------------------------------------------------------
@@ -174,9 +174,18 @@
 def utf2unicode(text):
     """Convert the given text from UTF-8 encoding to unicode."""
+    if isinstance(text, str):
+        if text.startswith("list indices must be"):
+            import traceback
+            traceback.print_exc()
+
+        return text
+
     try:
-        return unicode(_utf8decoder(text)[0])
+        return str(_utf8decoder(text)[0])
     except:
+        import traceback
+        traceback.print_exc()
         try:
-            return unicode(_latin2decoder(text)[0])
+            return str(_latin2decoder(text)[0])
         except:
-            return unicode(list(text))
+            return str(list(text))
Index: src/mlx/watchdog.py
===================================================================
--- src/mlx/watchdog.py	(revision 535)
+++ src/mlx/watchdog.py	(revision 919)
@@ -60,7 +60,7 @@
 
         if logTimeout:
-            print "Watchdog client %s has timed out!" % (self._name)
+            print("Watchdog client %s has timed out!" % (self._name))
         elif logCleared:
-            print "Watchdog client %s has been cleared." % (self._name)
+            print("Watchdog client %s has been cleared." % (self._name))
 
 #-----------------------------------------------------------------------------
@@ -115,5 +115,5 @@
 
             if t>=nextLogTime:
-                print "Watchdog.run: running"
+                print("Watchdog.run: running")
                 while t>=nextLogTime:
                     nextLogTime += self.LOG_INTERVAL
Index: src/mlx/web.py
===================================================================
--- src/mlx/web.py	(revision 859)
+++ src/mlx/web.py	(revision 963)
@@ -1,24 +1,26 @@
 
-import const
-import util
-from rpc import Registration
-import rpc
-import rpccommon
-
-from common import MAVA_BASE_URL
-from pirep import PIREP
+from . import const
+from . import util
+from .rpc import Registration
+from . import rpc
+from . import rpccommon
+
+from .common import MAVA_BASE_URL
+from .pirep import PIREP
 
 import threading
 import sys
-import urllib
-import urllib2
+import urllib.request, urllib.parse, urllib.error
+import urllib.request, urllib.error, urllib.parse
 import hashlib
 import time
+import re
 import datetime
 import codecs
 import traceback
 import xml.sax
-import xmlrpclib
-import HTMLParser
+import xmlrpc.client
+import html.parser
+import certifi
 
 #---------------------------------------------------------------------------------------
@@ -160,5 +162,5 @@
 
         date = readline(f)
-        print "web.BookedFlight.readFromWeb: date:", date
+        print("web.BookedFlight.readFromWeb: date:", date)
         if date=="0000-00-00": date = "0001-01-01"
 
@@ -233,6 +235,6 @@
 
                 if not lineOK:
-                    print "web.BookedFlight.readFromFile: line %d is invalid" % \
-                          (lineNumber,)
+                    print("web.BookedFlight.readFromFile: line %d is invalid" % \
+                          (lineNumber,))
 
             line = f.readline()
@@ -290,26 +292,26 @@
     def writeIntoFile(self, f):
         """Write the flight into a file."""
-        print >> f, "callsign=%s" % (self.callsign,)
+        print("callsign=%s" % (self.callsign,), file=f)
         date = self.departureTime.date()
-        print >> f, "date=%04d-%02d-%0d" % (date.year, date.month, date.day)
-        print >> f, "dep_airport=%s" % (self.departureICAO,)
-        print >> f, "dest_airport=%s" % (self.arrivalICAO,)
-        print >> f, "planecode=%s" % \
-              (BookedFlight.TYPE2TYPECODE[self.aircraftType],)
-        print >> f, "planetype=%s" % (self.aircraftTypeName,)
-        print >> f, "tail_nr=%s" % (self.tailNumber,)
-        print >> f, "passenger=%d" % (self.numPassengers,)
-        print >> f, "crew=%d" % (self.numCrew,)
-        print >> f, "bag=%d" % (self.bagWeight,)
-        print >> f, "cargo=%d" % (self.cargoWeight,)
-        print >> f, "mail=%d" % (self.mailWeight,)
-        print >> f, "flight_route=%s" % (self.route,)
+        print("date=%04d-%02d-%0d" % (date.year, date.month, date.day), file=f)
+        print("dep_airport=%s" % (self.departureICAO,), file=f)
+        print("dest_airport=%s" % (self.arrivalICAO,), file=f)
+        print("planecode=%s" % \
+              (BookedFlight.TYPE2TYPECODE[self.aircraftType],), file=f)
+        print("planetype=%s" % (self.aircraftTypeName,), file=f)
+        print("tail_nr=%s" % (self.tailNumber,), file=f)
+        print("passenger=%d" % (self.numPassengers,), file=f)
+        print("crew=%d" % (self.numCrew,), file=f)
+        print("bag=%d" % (self.bagWeight,), file=f)
+        print("cargo=%d" % (self.cargoWeight,), file=f)
+        print("mail=%d" % (self.mailWeight,), file=f)
+        print("flight_route=%s" % (self.route,), file=f)
         departureTime = self.departureTime
-        print >> f, "departure_time=%02d\\:%02d\\:%02d" % \
-              (departureTime.hour, departureTime.minute, departureTime.second)
+        print("departure_time=%02d\\:%02d\\:%02d" % \
+              (departureTime.hour, departureTime.minute, departureTime.second), file=f)
         arrivalTime = self.arrivalTime
-        print >> f, "arrival_time=%02d\\:%02d\\:%02d" % \
-              (arrivalTime.hour, arrivalTime.minute, arrivalTime.second)
-        print >> f, "foglalas_id=%s" % ("0" if self.id is None else self.id,)
+        print("arrival_time=%02d\\:%02d\\:%02d" % \
+              (arrivalTime.hour, arrivalTime.minute, arrivalTime.second), file=f)
+        print("foglalas_id=%s" % ("0" if self.id is None else self.id,), file=f)
 
     def _readAircraftType(self, f):
@@ -364,5 +366,5 @@
 
         except:
-            print >> sys.stderr, "Plane string is invalid: '" + s + "'"
+            print("Plane string is invalid: '" + s + "'", file=sys.stderr)
             self.tailNumber = None
 
@@ -470,9 +472,9 @@
 #------------------------------------------------------------------------------
 
-class PilotsWebNOTAMsParser(HTMLParser.HTMLParser):
+class PilotsWebNOTAMsParser(html.parser.HTMLParser):
     """XML handler for the NOTAM query results on the PilotsWeb website."""
     def __init__(self):
         """Construct the handler."""
-        HTMLParser.HTMLParser.__init__(self)
+        html.parser.HTMLParser.__init__(self)
 
         self._notams = []
@@ -513,9 +515,9 @@
         try:
             notam = self._parseCurrentNOTAM2()
-        except Exception, e:
-            print "Error parsing current NOTAM: " + str(e)
+        except Exception as e:
+            print("Error parsing current NOTAM: " + str(e))
 
         if notam is None:
-            print "Could not parse NOTAM: " + self._currentNOTAM
+            print("Could not parse NOTAM: " + self._currentNOTAM)
             if self._currentNOTAM:
                 self._notams.append(self._currentNOTAM + "\n")
@@ -526,5 +528,5 @@
         """Parse the current NOTAM, if possible, and return a NOTAM object."""
         lines = self._currentNOTAM.splitlines()
-        lines = map(lambda line: line.strip(), lines)
+        lines = [line.strip() for line in lines]
 
         if len(lines)<4:
@@ -578,6 +580,9 @@
     def _parseCurrentNOTAM2(self):
         """Parse the current NOTAM with a second, more flexible method."""
+        self._currentNOTAM = self._currentNOTAM.replace("\\n", "\n")
         lines = self._currentNOTAM.splitlines()
-        lines = map(lambda line: line.strip(), lines)
+        if len(lines)==1:
+            lines = lines[0].splitlines()
+        lines = [line.strip() for line in lines]
 
         if not lines:
@@ -592,5 +597,5 @@
                 lines = lines[:-1]
 
-        lines = map(lambda line: line.strip(), lines)
+        lines = [line.strip() for line in lines]
         contents = " ".join(lines).split()
 
@@ -614,4 +619,5 @@
 
         def parseTime(item):
+            item = re.sub("([0-9]+).*", "\\1", item)
             try:
                 return datetime.datetime.strptime(item, "%y%m%d%H%M")
@@ -653,6 +659,6 @@
         """Get a representation of the result."""
         s = "<Result:"
-        for (key, value) in self.__dict__.iteritems():
-            s += " " + key + "=" + unicode(value)
+        for (key, value) in self.__dict__.items():
+            s += " " + key + "=" + str(value)
         s += ">"
         return s
@@ -688,5 +694,5 @@
             result = self.run()
             returned = True
-        except Exception, e:
+        except Exception as e:
             traceback.print_exc()
             result = e
@@ -695,6 +701,6 @@
         try:
             self._callback(returned, result)
-        except Exception, e:
-            print >> sys.stderr, "web.Handler.Request.perform: callback throwed an exception: " + util.utf2unicode(str(e))
+        except Exception as e:
+            print("web.Handler.Request.perform: callback throwed an exception: " + util.utf2unicode(str(e)), file=sys.stderr)
             #traceback.print_exc()
 
@@ -769,5 +775,5 @@
         result = Result()
 
-        f = urllib2.urlopen(url, timeout = 10.0)
+        f = urllib.request.urlopen(url, timeout = 10.0)
 
         status = readline(f)
@@ -791,7 +797,5 @@
                 result.flights.append(flight)
 
-            result.flights.sort(cmp = lambda flight1, flight2:
-                                cmp(flight1.departureTime,
-                                    flight2.departureTime))
+            result.flights.sort(key = lambda flight: flight.departureTime)
 
         f.close()
@@ -880,5 +884,5 @@
         url = MAVA_BASE_URL + "/onlinegates_get.php"
 
-        f = urllib2.urlopen(url, timeout = 10.0)
+        f = urllib.request.urlopen(url, timeout = 10.0)
         result = Result()
         result.fleet = Fleet(f)
@@ -922,9 +926,9 @@
         gateNumber = self._gateNumber if self._gateNumber else ""
 
-        data = urllib.urlencode([("lajstrom", self._tailNumber),
+        data = urllib.parse.urlencode([("lajstrom", self._tailNumber),
                                  ("status", status),
                                  ("kapu", gateNumber)])
 
-        f = urllib2.urlopen(url, data, timeout = 10.0)
+        f = urllib.request.urlopen(url, data, timeout = 10.0)
         line = readline(f)
 
@@ -983,5 +987,5 @@
             url = "http://notams.euroutepro.com/notams.xml"
 
-            f = urllib2.urlopen(url, timeout = 10.0)
+            f = urllib.request.urlopen(url, timeout = 10.0)
             try:
                 xmlParser.parse(f)
@@ -1012,9 +1016,9 @@
               (icao.upper(),)
 
-            f = urllib2.urlopen(url, timeout = 10.0)
+            f = urllib.request.urlopen(url, timeout = 10.0, cafile=certifi.where())
             try:
                 data = f.read(16384)
                 while data:
-                    parser.feed(data)
+                    parser.feed(str(data))
                     data = f.read(16384)
             finally:
@@ -1023,8 +1027,8 @@
             return parser.getNOTAMs()
 
-        except Exception, e:
+        except Exception as e:
             traceback.print_exc()
-            print "mlx.web.GetNOTAMs.getPilotsWebNOTAMs: failed to get NOTAMs for '%s': %s" % \
-                  (icao, str(e))
+            print("mlx.web.GetNOTAMs.getPilotsWebNOTAMs: failed to get NOTAMs for '%s': %s" % \
+                  (icao, str(e)))
             return None
 
@@ -1042,5 +1046,5 @@
         """Perform the retrieval opf the METARs."""
         url = "http://www.aviationweather.gov/adds/dataserver_current/httpparam?"
-        data = urllib.urlencode([ ("dataSource" , "metars"),
+        data = urllib.parse.urlencode([ ("dataSource" , "metars"),
                                   ("requestType",  "retrieve"),
                                   ("format", "csv"),
@@ -1048,16 +1052,22 @@
                                   ("hoursBeforeNow", "24"),
                                   ("mostRecentForEachStation", "constraint")])
-        url += data
-        f = urllib2.urlopen(url, timeout = 10.0)
+        result = Result()
+        result.metars = {}
         try:
-            result = Result()
-            result.metars = {}
-            for line in iter(f.readline, ""):
-                if len(line)>5 and line[4]==' ':
-                    icao = line[0:4]
-                    if icao in self._airports:
-                        result.metars[icao] = line.strip().split(",")[0]
-        finally:
-            f.close()
+            url += data
+            f = urllib.request.urlopen(url, timeout = 10.0, cafile = certifi.where())
+            try:
+                for line in f.readlines():
+                    line = str(line, "iso-8859-1")
+                    if len(line)>5 and line[4]==' ':
+                        icao = line[0:4]
+                        if icao in self._airports:
+                            result.metars[icao] = line.strip().split(",")[0]
+            finally:
+                f.close()
+        except Exception as e:
+            traceback.print_exc()
+            print("mlx.web.GetMETARs.run: failed to get METARs for %s: %s" % \
+                  (self._airports, str(e)))
 
         return result
@@ -1128,10 +1138,10 @@
         data["insdate"] = datetime.date.today().strftime("%Y-%m-%d")
 
-        postData = urllib.urlencode(data)
-        f = urllib2.urlopen(url, postData, timeout = 10.0)
+        postData = urllib.parse.urlencode(data)
+        f = urllib.request.urlopen(url, postData, timeout = 10.0)
         try:
             result = Result()
             line = f.readline().strip()
-            print "PIREP result from website:", line
+            print("PIREP result from website:", line)
             result.success = line=="OK"
             result.alreadyFlown = line=="MARVOLT"
@@ -1178,5 +1188,5 @@
     def run(self):
         """Perform the sending of the ACARS."""
-        print "Sending the online ACARS"
+        print("Sending the online ACARS")
 
         url = MAVA_BASE_URL  + "/acars2/acarsonline.php"
@@ -1204,5 +1214,5 @@
         data["event"] = acars.getEventText()
 
-        f = urllib2.urlopen(url, urllib.urlencode(data), timeout = 10.0)
+        f = urllib.request.urlopen(url, urllib.parse.urlencode(data), timeout = 10.0)
         try:
             result = Result()
@@ -1223,5 +1233,5 @@
     def run(self):
         """Perform the sending of the ACARS."""
-        print "Sending the online ACARS via JSON-RPC"
+        print("Sending the online ACARS via JSON-RPC")
 
         self._client.updateOnlineACARS(self._acars)
@@ -1243,5 +1253,5 @@
     def run(self):
         """Perform the sending of the bug report."""
-        serverProxy = xmlrpclib.ServerProxy("http://mlx.varadiistvan.hu/rpc")
+        serverProxy = xmlrpc.client.ServerProxy("http://mlx.varadiistvan.hu/rpc")
 
         result = Result()
@@ -1254,5 +1264,5 @@
         result.ticketID = serverProxy.ticket.create(self._summary, self._description,
                                                     attributes, True)
-        print "Created ticket with ID:", result.ticketID
+        print("Created ticket with ID:", result.ticketID)
         result.success = True
 
@@ -1288,5 +1298,5 @@
 
         pirepData = self._client.getPIREP(self._flightID)
-        print "pirepData:", pirepData
+        print("pirepData:", pirepData)
 
         bookedFlight = BookedFlight(self._flightID)
@@ -1512,5 +1522,5 @@
 
     def callback(returned, result):
-        print returned, unicode(result)
+        print(returned, str(result))
 
     handler = Handler()
Index: src/mlx/xplane.py
===================================================================
--- src/mlx/xplane.py	(revision 909)
+++ src/mlx/xplane.py	(revision 1004)
@@ -1,7 +1,7 @@
 
-import fs
-import const
-import util
-from watchdog import Watchdog
+from . import fs
+from . import const
+from . import util
+from .watchdog import Watchdog
 
 import threading
@@ -12,4 +12,5 @@
 import codecs
 import math
+from functools import total_ordering
 
 from xplra import XPlane, MultiGetter, MultiSetter, ProtocolException
@@ -106,5 +107,5 @@
             else:
                 return False
-        except ProtocolException, e:
+        except ProtocolException as e:
             self._result = None
             return True
@@ -148,4 +149,5 @@
         return True
 
+@total_ordering
 class PeriodicRequest(object):
     """A periodic request."""
@@ -198,8 +200,15 @@
         pass
 
-    def __cmp__(self, other):
-        """Compare two periodic requests. They are ordered by their next
-        firing times."""
-        return cmp(self._nextFire, other._nextFire)
+    def __eq__(self, other):
+        """Equality comparison by the firing times"""
+        return self._nextFire == other._nextFire
+
+    def __ne__(self, other):
+        """Non-equality comparison by the firing times"""
+        return self._nextFire != other._nextFire
+
+    def __lt__(self, other):
+        """Less-than comparison by the firing times"""
+        return self._nextFire < other._nextFire
 
 class PeriodicDataRequest(PeriodicRequest):
@@ -241,6 +250,6 @@
         try:
             return fun()
-        except Exception, e:
-            print >> sys.stderr, util.utf2unicode(str(e))
+        except Exception as e:
+            print(util.utf2unicode(str(e)), file=sys.stderr)
             return None
 
@@ -312,6 +321,6 @@
             try:
                 multiGetter.execute()
-            except ProtocolException, e:
-                print "xplane.Handler._performRead: " + str(e)
+            except ProtocolException as e:
+                print("xplane.Handler._performRead: " + str(e))
                 raise
 
@@ -514,8 +523,8 @@
                 self._connected = True
                 return attempts
-            except Exception, e:
-                print "xplane.Handler._connect: connection failed: " + \
+            except Exception as e:
+                print("xplane.Handler._connect: connection failed: " + \
                       util.utf2unicode(str(e)) + \
-                      " (attempts: %d)" % (attempts,)
+                      " (attempts: %d)" % (attempts,))
                 if attempts<self.NUM_CONNECTATTEMPTS:
                     time.sleep(self.CONNECT_INTERVAL)
@@ -549,5 +558,5 @@
     def _disconnect(self):
         """Disconnect from the flight simulator."""
-        print "xplane.Handler._disconnect"
+        print("xplane.Handler._disconnect")
         if self._connected:
             try:
@@ -578,10 +587,10 @@
             try:
                 if not request.process(time):
-                    print "xplane.Handler._processRequest: X-Plane returned invalid data too many times, reconnecting"
+                    print("xplane.Handler._processRequest: X-Plane returned invalid data too many times, reconnecting")
                     needReconnect = True
             except Exception as e:
-                print "xplane.Handler._processRequest: X-Plane connection failed (" + \
+                print("xplane.Handler._processRequest: X-Plane connection failed (" + \
                       util.utf2unicode(str(e)) + \
-                      "), reconnecting (attempts=%d)." % (attempts,)
+                      "), reconnecting (attempts=%d)." % (attempts,))
                 needReconnect = True
 
@@ -724,5 +733,4 @@
         self._hotkeyCallback = None
 
-        self._latin1decoder = codecs.getdecoder("iso-8859-1")
         self._fuelCallback = None
 
@@ -804,5 +812,5 @@
 
         duration is the number of seconds to keep the message displayed."""
-        print "xplra.Simulator.sendMessage:", message
+        print("xplra.Simulator.sendMessage:", message)
         self._handler.requestShowMessage(message, duration,
                                          self._handleMessageSent,
@@ -887,5 +895,5 @@
         assert not self._monitoringRequested
 
-        print "xplra.Simulator.disconnect", closingMessage, duration
+        print("xplra.Simulator.disconnect", closingMessage, duration)
 
         self._stopNormal()
@@ -938,6 +946,6 @@
         if self._lastZuluSeconds is not None and \
            zuluSeconds<self._lastZuluSeconds:
-            print "xplane.Simulator._getTimestamp: Zulu seconds have gone backwards (%f -> %f), increasing day offset" % \
-              (self._lastZuluSeconds, zuluSeconds)
+            print("xplane.Simulator._getTimestamp: Zulu seconds have gone backwards (%f -> %f), increasing day offset" % \
+              (self._lastZuluSeconds, zuluSeconds))
             self._timestampDaysOffset += 1
 
@@ -1007,15 +1015,10 @@
 
         Return if a new model was created."""
-        author = self._latin1decoder(author)[0]
-        description = self._latin1decoder(description)[0]
-        notes = self._latin1decoder(notes)[0]
-        liveryPath = self._latin1decoder(liveryPath)[0]
-
         aircraftInfo = (tailnum, author, description, notes, icao, liveryPath)
         if aircraftInfo==self._aircraftInfo:
             return False
 
-        print "xplane.Simulator: new data: %s, %s, %s, %s, %s, %s" % \
-              (tailnum, author, description, notes, icao, liveryPath)
+        print("xplane.Simulator: new data: %s, %s, %s, %s, %s, %s" % \
+              (tailnum, author, description, notes, icao, liveryPath))
 
         self._aircraftInfo = aircraftInfo
@@ -1140,6 +1143,7 @@
             self._handler.disconnect()
 
-    def _handleHotkeysRegistered(self, success, (id, generation)):
+    def _handleHotkeysRegistered(self, success, hotkeySet):
         """Handle the result of the hotkeys having been written."""
+        (id, generation) = hotkeySet
         with self._hotkeyLock:
             if success and id==self._hotkeySetID and \
@@ -1148,8 +1152,9 @@
                   self._handler.requestHotkeysState(0.5,
                                                     self._handleHotkeys,
-                                                    (id, generation))
-
-    def _handleHotkeys(self, data, (id, generation)):
+                                                    hotkeySet)
+
+    def _handleHotkeys(self, data, hotkeySet):
         """Handle the hotkeys."""
+        (id, generation) = hotkeySet
         with self._hotkeyLock:
             if id!=self._hotkeySetID or generation!=self._hotkeySetGeneration:
@@ -1617,6 +1622,6 @@
                               [level * self._fuelTankCapacities[index]]) )
             except:
-                print "xplane.Simulator.setFuelLevel: invalid tank constant: %d" % \
-                  (tank,)
+                print("xplane.Simulator.setFuelLevel: invalid tank constant: %d" % \
+                  (tank,))
 
         handler.requestWrite(data, self._handleFuelWritten)
@@ -1748,8 +1753,8 @@
     """Model handler for the FlyJSim Dash 8-Q400."""
     @staticmethod
-    def doesHandle(aircraft, (tailnum, author, description, notes,
-                              icao, liveryPath)):
+    def doesHandle(aircraft, data):
         """Determine if this model handler handles the aircraft with the given
         name."""
+        (tailnum, author, description, notes, icao, liveryPath) = data
         return aircraft.type==const.AIRCRAFT_DH8D and \
           description.find("Dash 8 Q400")!=-1 and \
@@ -1909,8 +1914,8 @@
     """Model for Felis' Tupolev Tu-154-M aircraft."""
     @staticmethod
-    def doesHandle(aircraft, (tailnum, author, description, notes,
-                              icao, liveryPath)):
+    def doesHandle(aircraft, data):
         """Determine if this model handler handles the aircraft with the given
         name."""
+        (tailnum, author, description, notes, icao, liveryPath) = data
         return aircraft.type==const.AIRCRAFT_T154 and \
           author.find("Felis")!=-1 and \
Index: test/test.sh
===================================================================
--- test/test.sh	(revision 163)
+++ test/test.sh	(revision 956)
@@ -2,5 +2,9 @@
 
 scriptdir=`dirname $0`
-sim="${scriptdir}/../src/mlx/pyuipc_sim.py"
+
+PYTHONPATH="${scriptdir}/../src"
+export PYTHONPATH
+
+sim="mlx.pyuipc_sim"
 
 host="localhost"
@@ -13,5 +17,5 @@
 for line in `cat $1`; do
     read -p "$line"
-    echo $line | python "${sim}" "${host}" >/dev/null
+    echo $line | python3 -m "${sim}" "${host}" >/dev/null
 done
 IFS="${oldIFS}"
Index: nemakeinst.bat
===================================================================
--- winemakeinst.bat	(revision 916)
+++ 	(revision )
@@ -1,10 +1,0 @@
-set MSVCRDIR=c:\windows\winsxs\x86_Microsoft.VC90.CRT*9.0.21022.8*
-set GTKRTDIR=c:\Python27\Lib\site-packages\gtk-2.0\runtime
-set CEFDIR=c:\Python27\Lib\site-packages\cefpython3
-set CHROMEDRIVER=c:\tmp\chromedriver.exe
-set NSISDIR=C:\Program Files\NSIS
-set WINE=yes
-
-C:\Python27\python.exe setup.py py2exe
-
-"%NSISDIR%\makensis" mlx.nsi
