[telegnome] Port from gnome-config to GSettings



commit 48b4e82b6a8de977a5ea67cff30b17578a203790
Author: Colin Watson <cjwatson debian org>
Date:   Sat Jan 30 12:15:23 2016 +0000

    Port from gnome-config to GSettings

 Makefile.am                          |    2 +-
 NEWS                                 |    1 +
 configure.ac                         |    6 +-
 data/.gitignore                      |    1 +
 data/Makefile.am                     |    4 +
 data/org.gnome.telegnome.gschema.xml |   66 +++
 po/POTFILES.in                       |    1 +
 src/Makefile.am                      |    4 +-
 src/channel.c                        |  276 +++++++++++---
 src/channel.h                        |   28 +-
 src/gui.c                            |  721 +++++++++++++++++++++++-----------
 src/gui.h                            |   43 +--
 src/http.c                           |   31 +-
 src/legacy-config.c                  |  209 ++++++++++
 src/legacy-config.h                  |   37 ++
 src/main.c                           |   16 +-
 src/main.h                           |    2 -
 src/prefs.c                          |  386 +++++++++----------
 src/prefs.h                          |    8 +-
 src/view.c                           |    6 +
 src/view.h                           |    2 +-
 21 files changed, 1279 insertions(+), 571 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index c426c59..27b4c8d 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,4 +1,4 @@
-SUBDIRS=src po pixmaps doc
+SUBDIRS = data src po pixmaps doc
 
 EXTRA_DIST = $(srcdir)/telegnome.desktop.in \
        BUGS \
diff --git a/NEWS b/NEWS
index 3389586..7f629f7 100644
--- a/NEWS
+++ b/NEWS
@@ -3,6 +3,7 @@ Changes in TeleGNOME 0.1.2
 
  * Build cleanly with -DGSEAL_ENABLE.
  * Port from GnomeVFS to GIO.
+ * Port from gnome-config to GSettings.
 
 Changes in TeleGNOME 0.1.1
 ==========================
diff --git a/configure.ac b/configure.ac
index 4d3b71f..8c10f68 100644
--- a/configure.ac
+++ b/configure.ac
@@ -12,6 +12,7 @@ GNOME_COMMON_INIT
 GNOME_DEBUG_CHECK
 GNOME_COMPILE_WARNINGS([maximum])
 GNOME_DOC_INIT
+GLIB_GSETTINGS
 
 AC_ISC_POSIX
 AC_PROG_CC
@@ -19,7 +20,9 @@ AC_PROG_CPP
 AC_HEADER_STDC
 AC_PROG_INSTALL
 
-PKG_CHECK_MODULES([TELEGNOME], [glib-2.0 >= 2.34 gtk+-2.0 >= 2.20 gdk-pixbuf-2.0 libgnomeui-2.0 gio-2.0])
+AC_DEFINE_UNQUOTED([SYSCONFDIR], "$sysconfdir", [System configuration directory.])
+
+PKG_CHECK_MODULES([TELEGNOME], [glib-2.0 >= 2.34 gobject-2.0 >= 2.44 gtk+-2.0 >= 2.20 gdk-pixbuf-2.0 
libgnomeui-2.0 gio-2.0 dconf uuid])
 
 PROGRAMS_TELEGNOME="telegnome"
 AC_SUBST(PROGRAMS_TELEGNOME)
@@ -32,6 +35,7 @@ AM_GLIB_DEFINE_LOCALEDIR([GNOMELOCALEDIR])
 IT_PROG_INTLTOOL([0.35.0], [no-xml])
 
 AC_CONFIG_FILES([Makefile 
+          data/Makefile
           pixmaps/Makefile 
           src/Makefile
           po/Makefile.in
diff --git a/data/.gitignore b/data/.gitignore
new file mode 100644
index 0000000..01b581a
--- /dev/null
+++ b/data/.gitignore
@@ -0,0 +1 @@
+org.gnome.telegnome.gschema.valid
diff --git a/data/Makefile.am b/data/Makefile.am
new file mode 100644
index 0000000..52a08c9
--- /dev/null
+++ b/data/Makefile.am
@@ -0,0 +1,4 @@
+gsettings_SCHEMAS = org.gnome.telegnome.gschema.xml
+EXTRA_DIST = $(gsettings_SCHEMAS)
+
+ GSETTINGS_RULES@
diff --git a/data/org.gnome.telegnome.gschema.xml b/data/org.gnome.telegnome.gschema.xml
new file mode 100644
index 0000000..1b47bd6
--- /dev/null
+++ b/data/org.gnome.telegnome.gschema.xml
@@ -0,0 +1,66 @@
+<schemalist>
+  <schema gettext-domain="telegnome" id="org.gnome.telegnome" path="/org/gnome/telegnome/">
+    <key name="legacy-migration-complete" type="b">
+      <default>false</default>
+      <summary>Legacy migration complete</summary>
+      <description>Set internally to true to indicate that TeleGNOME has checked for legacy gnome-config 
settings and migrated any that existed.</description>
+    </key>
+    <key name="channel-children" type="as">
+      <default>[]</default>
+      <summary>Channel children</summary>
+      <description>List of channel IDs.  Each channel folder uses the org.gnome.telegnome.channel 
schema.</description>
+    </key>
+    <key name="current-channel" type="s">
+      <default>''</default>
+      <summary>Current channel</summary>
+      <description>ID of current channel.</description>
+    </key>
+    <key name="zoom-factor" type="i">
+      <default>1</default>
+      <summary>Zoom factor</summary>
+      <description>Page zoom factor.  Larger numbers produce larger text.</description>
+    </key>
+    <key name="paging-enabled" type="b">
+      <default>false</default>
+      <summary>Automatically switch page at periodic intervals</summary>
+      <description>The frequency of paging is controlled by the "interval" key.</description>
+    </key>
+    <key name="paging-interval" type="i">
+      <default>12000</default>
+      <summary>Paging interval</summary>
+      <description>Specifies the interval for the auto-pager, in milliseconds.</description>
+    </key>
+    <key name="current-page-number" type="i">
+      <default>-1</default>
+      <summary>Current page number</summary>
+    </key>
+    <key name="current-subpage-number" type="i">
+      <default>-1</default>
+      <summary>Current subpage number</summary>
+    </key>
+  </schema>
+  <schema gettext-domain="telegnome" id="org.gnome.telegnome.channel">
+    <key name="name" type="s">
+      <default>''</default>
+      <summary>Channel name</summary>
+    </key>
+    <key name="description" type="s">
+      <default>''</default>
+      <summary>Channel description</summary>
+    </key>
+    <key name="page-url" type="s">
+      <default>''</default>
+      <summary>Page URL</summary>
+      <description>URL pattern for pages.  Must contain one C format string substitution accepting an int 
(e.g. %d), for the page number.</description>
+    </key>
+    <key name="subpage-url" type="s">
+      <default>''</default>
+      <summary>Subpage URL</summary>
+      <description>URL pattern for subpages.  Must contain two C format string substitution accepting ints 
(e.g. %d), for the page and subpage numbers respectively.</description>
+    </key>
+    <key name="country" type="s">
+      <default>''</default>
+      <summary>Country code</summary>
+    </key>
+  </schema>
+</schemalist>
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 5ecd58f..31dfbf1 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -1,3 +1,4 @@
+data/org.gnome.telegnome.gschema.xml
 src/http.c
 src/gui.c
 src/gui.h
diff --git a/src/Makefile.am b/src/Makefile.am
index 250c9fd..80b89cd 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -16,7 +16,9 @@ telegnome_SOURCES= \
        pixpack.c \
        pixpack.h \
        channel.c \
-       channel.h
+       channel.h \
+       legacy-config.c \
+       legacy-config.h
 
 LINK_FLAGS= $(GNOME_LIBDIR) $(INTLLIBS) $(GHTTP_LIB)
 telegnome_LDADD=$(LINK_FLAGS) $(GNOME_LIBDIR) $(TELEGNOME_LIBS)
diff --git a/src/channel.c b/src/channel.c
index d5c6b39..a54d327 100644
--- a/src/channel.c
+++ b/src/channel.c
@@ -7,6 +7,7 @@
 **    Copyright (C) 1999, 2000,
 **    Dirk-Jan C. Binnema <djcb dds nl>,
 **    Arjan Scherpenisse <acscherp wins uva nl>
+**    Copyright (C) 2016 Colin Watson <cjwatson debian org>
 **  
 ** This program is free software; you can redistribute it and/or modify
 ** it under the terms of the GNU General Public License as published by
@@ -24,79 +25,246 @@
 **  
 */
 
+#include <stdarg.h>
+
 #include <glib.h>
-#include <libgnome/libgnome.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gio/gio.h>
+#include <uuid.h>
 
 #include "channel.h"
 
-TgChannel *
-tg_channel_new(int id, const char *name, const char *desc, const char *page_url, const char *subpage_url, 
const char *country)
+struct _TgChannel {
+    GObject parent_instance;
+
+    GSettings *settings;
+
+    gchar *uuid;
+    gchar *name;
+    gchar *desc;
+    gchar *page_url;
+    gchar *subpage_url;
+    gchar *country;
+};
+
+enum {
+    PROP_0,
+
+    PROP_UUID,
+    PROP_NAME,
+    PROP_DESC,
+    PROP_PAGE_URL,
+    PROP_SUBPAGE_URL,
+    PROP_COUNTRY
+};
+
+G_DEFINE_TYPE (TgChannel, tg_channel, G_TYPE_OBJECT)
+
+static void
+tg_channel_init (TgChannel *self)
 {
-    TgChannel *t;
-    t = g_malloc(sizeof(TgChannel));
-    
-    t->id = id;
-    t->name = g_string_new(name);
-    t->desc = g_string_new(desc);
-    t->page_url = g_string_new(page_url);
-    t->subpage_url = g_string_new(subpage_url);
-    t->country = g_string_new(country);
-    
-    return t;
 }
 
-TgChannel *
-tg_channel_new_from_config(int id)
+static void
+tg_channel_bind_settings (TgChannel *self)
 {
-    TgChannel *t;
-    GString *prefix;
-    t = g_malloc(sizeof(TgChannel));
+    gchar *path;
 
-    prefix = g_string_new(NULL);
-    g_string_printf(prefix, "/telegnome/Channel%d/", id);
-    gnome_config_push_prefix(prefix->str);
+    path = g_strdup_printf ("/org/gnome/telegnome/channel/%s/", self->uuid);
+    self->settings = g_settings_new_with_path
+       ("org.gnome.telegnome.channel", path);
+    g_settings_bind (self->settings, "name", self, "name",
+                    G_SETTINGS_BIND_DEFAULT);
+    g_settings_bind (self->settings, "description", self, "description",
+                    G_SETTINGS_BIND_DEFAULT);
+    g_settings_bind (self->settings, "page-url", self, "page-url",
+                    G_SETTINGS_BIND_DEFAULT);
+    g_settings_bind (self->settings, "subpage-url", self, "subpage-url",
+                    G_SETTINGS_BIND_DEFAULT);
+    g_settings_bind (self->settings, "country", self, "country",
+                    G_SETTINGS_BIND_DEFAULT);
+}
+
+static void
+tg_channel_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
+{
+    TgChannel *self = TG_CHANNEL (object);
 
-    t->id = id;
-    t->name = g_string_new(gnome_config_get_string("name"));
-    t->desc = g_string_new(gnome_config_get_string("desc"));
-    t->page_url = g_string_new(gnome_config_get_string("page_url"));
-    t->subpage_url = g_string_new(gnome_config_get_string("subpage_url"));
-    t->country = g_string_new(gnome_config_get_string("country"));
+    switch (property_id) {
+       case PROP_UUID:
+           g_value_set_string (value, self->uuid);
+           break;
 
-    gnome_config_pop_prefix();
+       case PROP_NAME:
+           g_value_set_string (value, self->name);
+           break;
 
-    return t;
+       case PROP_DESC:
+           g_value_set_string (value, self->desc);
+           break;
+
+       case PROP_PAGE_URL:
+           g_value_set_string (value, self->page_url);
+           break;
+
+       case PROP_SUBPAGE_URL:
+           g_value_set_string (value, self->subpage_url);
+           break;
+
+       case PROP_COUNTRY:
+           g_value_set_string (value, self->country);
+           break;
+
+       default:
+           G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+           break;
+    }
 }
 
-void
-tg_channel_save_to_config(TgChannel *channel)
+static void
+tg_channel_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
 {
-    GString *prefix;
+    TgChannel *self = TG_CHANNEL (object);
+
+    switch (property_id) {
+       case PROP_UUID:
+           g_free (self->uuid);
+           self->uuid = g_value_dup_string (value);
+           break;
+
+       case PROP_NAME:
+           g_free (self->name);
+           self->name = g_value_dup_string (value);
+           break;
 
-    g_assert(channel != NULL);
+       case PROP_DESC:
+           g_free (self->desc);
+           self->desc = g_value_dup_string (value);
+           break;
+
+       case PROP_PAGE_URL:
+           g_free (self->page_url);
+           self->page_url = g_value_dup_string (value);
+           break;
+
+       case PROP_SUBPAGE_URL:
+           g_free (self->subpage_url);
+           self->subpage_url = g_value_dup_string (value);
+           break;
+
+       case PROP_COUNTRY:
+           g_free (self->country);
+           self->country = g_value_dup_string (value);
+           break;
+
+       default:
+           G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+           break;
+    }
+}
 
-    prefix = g_string_new("a");
-    g_string_printf(prefix, "/telegnome/Channel%d/", channel->id);
-    gnome_config_push_prefix(prefix->str);
+static void
+tg_channel_dispose (GObject *object)
+{
+    TgChannel *self = TG_CHANNEL (object);
+
+    g_clear_object (&self->settings);
+
+    G_OBJECT_CLASS (tg_channel_parent_class)->dispose (object);
+}
+
+static void
+tg_channel_finalize (GObject *object)
+{
+    TgChannel *self = TG_CHANNEL (object);
+
+    g_clear_pointer (&self->name, g_free);
+    g_clear_pointer (&self->desc, g_free);
+    g_clear_pointer (&self->page_url, g_free);
+    g_clear_pointer (&self->subpage_url, g_free);
+    g_clear_pointer (&self->country, g_free);
+
+    G_OBJECT_CLASS (tg_channel_parent_class)->finalize (object);
+}
+
+static void
+tg_channel_class_init (TgChannelClass *klass)
+{
+    GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+    gobject_class->get_property = tg_channel_get_property;
+    gobject_class->set_property = tg_channel_set_property;
+    gobject_class->dispose = tg_channel_dispose;
+    gobject_class->finalize = tg_channel_finalize;
+
+    g_object_class_install_property
+       (gobject_class, PROP_UUID,
+        g_param_spec_string ("uuid",
+                             "UUID", "UUID",
+                             NULL,
+                             G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+                             G_PARAM_CONSTRUCT_ONLY));
+
+    g_object_class_install_property
+       (gobject_class, PROP_NAME,
+        g_param_spec_string ("name",
+                             _("Name"), _("Name"),
+                             NULL,
+                             G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+    g_object_class_install_property
+       (gobject_class, PROP_DESC,
+        g_param_spec_string ("description",
+                             _("Description"), _("Description"),
+                             NULL,
+                             G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+    g_object_class_install_property
+       (gobject_class, PROP_PAGE_URL,
+        g_param_spec_string ("page-url",
+                             _("Page url"), _("Page url"),
+                             NULL,
+                             G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+    g_object_class_install_property
+       (gobject_class, PROP_SUBPAGE_URL,
+        g_param_spec_string ("subpage-url",
+                             _("Subpage url"), _("Subpage url"),
+                             NULL,
+                             G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+    g_object_class_install_property
+       (gobject_class, PROP_COUNTRY,
+        g_param_spec_string ("country",
+                             _("Country"), _("Country"),
+                             NULL,
+                             G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+}
+
+TgChannel *
+tg_channel_new (const gchar *uuid, const gchar *first_property_name, ...)
+{
+    va_list argv;
+    uuid_t uu;
+    gchar real_uuid[37];
+    TgChannel *channel;
 
-    gnome_config_set_string("name", channel->name->str);
-    gnome_config_set_string("desc", channel->desc->str);
-    gnome_config_set_string("page_url", channel->page_url->str);
-    gnome_config_set_string("subpage_url", channel->subpage_url->str);
-    gnome_config_set_string("country", channel->country->str);
-    gnome_config_sync();
-    gnome_config_pop_prefix();
+    va_start (argv, first_property_name);
+    if (!uuid) {
+       uuid_generate (uu);
+       uuid_unparse (uu, real_uuid);
+       uuid = real_uuid;
+    }
+    channel = TG_CHANNEL (g_object_new (TG_TYPE_CHANNEL, "uuid", uuid, NULL));
+    tg_channel_bind_settings (channel);
+    g_object_set_valist (G_OBJECT (channel), first_property_name, argv);
+    va_end (argv);
+    return channel;
 }
-    
-    
 
-void 
-tg_channel_free(TgChannel *channel)
+GSettings *
+tg_channel_get_settings(TgChannel *channel)
 {
-    g_assert(channel != NULL);
-    g_string_free(channel->name, TRUE);
-    g_string_free(channel->page_url, TRUE);
-    g_string_free(channel->subpage_url, TRUE);
-    g_string_free(channel->country, TRUE);
-    g_free(channel);
+    return channel->settings;
 }
diff --git a/src/channel.h b/src/channel.h
index 6794bdb..6053f95 100644
--- a/src/channel.h
+++ b/src/channel.h
@@ -7,6 +7,7 @@
 **    Copyright (C) 1999, 2000,
 **    Dirk-Jan C. Binnema <djcb dds nl>,
 **    Arjan Scherpenisse <acscherp wins uva nl>
+**    Copyright (C) 2016 Colin Watson <cjwatson debian org>
 **  
 ** This program is free software; you can redistribute it and/or modify
 ** it under the terms of the GNU General Public License as published by
@@ -28,19 +29,20 @@
 #define _CHANNEL_H_
 
 #include <glib.h>
+#include <glib-object.h>
 
-typedef struct _TgChannel {
-    gint id;
-    GString *name,
-       *desc,
-       *page_url,
-       *subpage_url,
-       *country;
-} TgChannel;
-
-TgChannel *tg_channel_new(int id, const char *name, const char *desc, const char *page_url, const char 
*subpage_url, const char *country);
-TgChannel *tg_channel_new_from_config(int id);
-void tg_channel_save_to_config(TgChannel *channel);
-void tg_channel_free(TgChannel *channel);
+G_BEGIN_DECLS
+
+#define TG_TYPE_CHANNEL             (tg_channel_get_type ())
+G_DECLARE_FINAL_TYPE (TgChannel, tg_channel, TG, CHANNEL, GObject)
+
+GType tg_channel_get_type (void);
+
+TgChannel *tg_channel_new (const gchar *uuid, const gchar *first_property_name,
+                          ...);
+
+GSettings *tg_channel_get_settings (TgChannel *channel);
+
+G_END_DECLS
 
 #endif
diff --git a/src/gui.c b/src/gui.c
index d25f704..b103afe 100644
--- a/src/gui.c
+++ b/src/gui.c
@@ -6,6 +6,7 @@
 **    Copyright (C) 1999, 2000,
 **    Dirk-Jan C. Binnema <djcb dds nl>,
 **    Arjan Scherpenisse <acscherp wins uva nl>
+**    Copyright (C) 2016 Colin Watson <cjwatson debian org>
 **  
 ** This program is free software; you can redistribute it and/or modify
 ** it under the terms of the GNU General Public License as published by
@@ -23,6 +24,10 @@
 **  
 */
 
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gio/gio.h>
 #include <gdk/gdkkeysyms.h>
 #include <gtk/gtk.h>
 #include <libgnome/libgnome.h>
@@ -34,17 +39,74 @@
 #include "menu.h"
 #include "channel.h"
 
-static TgGui gui;
+struct _TgGui {
+    GObject parent_instance;
+
+    GtkWidget *app;
+
+    GSettings *settings;
+
+    GtkWidget *statusbar;
+    GtkWidget *entry;
+    GtkWidget *pixmap;
+
+    GtkProgressBar *progress;
+
+    GtkWidget *zoomlabel;
+
+    GtkWidget *zoombutton;
+    GtkWidget *pagebutton;
+
+    GtkWidget *channel_menu;
+
+    /* for timer-input */
+    gint logo_timer;
+    gint kb_timer;
+    gint kb_status;
+
+    gint page_timer;
+    gint page_msecs;
+    gboolean page_status; /* auto-paging enabled or disabled */
+    gint page_progress;
+
+    /* FIXME: Multiple views */
+
+    gchar **channel_children;
+    GSList *channels;
+    gchar *current_channel;
+};
+
+enum {
+    PROP_0,
+
+    PROP_CHANNEL_CHILDREN,
+    PROP_CURRENT_CHANNEL,
+    PROP_ZOOM_FACTOR,
+    PROP_PAGING_ENABLED,
+    PROP_PAGING_INTERVAL,
+    PROP_CURRENT_PAGE_NUMBER,
+    PROP_CURRENT_SUBPAGE_NUMBER
+};
+
+G_DEFINE_TYPE (TgGui, tg_gui, G_TYPE_OBJECT)
+
+static TgGui *gui;
 
 static void
 tg_gui_update_title_bar(void)
 {
     char buf[100];
     /* update the title bar */
-    if ((currentview != NULL) && (currentview->channel != NULL) &&
-       (currentview->channel->name != NULL) && (currentview->channel->desc != NULL)) {
-       sprintf(buf, _("TeleGNOME: %s (%s)"), currentview->channel->name->str, 
currentview->channel->desc->str);
-       gtk_window_set_title(GTK_WINDOW(gui.app), buf);
+    if (currentview != NULL && currentview->channel != NULL) {
+       gchar *name, *desc;
+       g_object_get(
+           currentview->channel, "name", &name, "description", &desc, NULL);
+       if (name != NULL && desc != NULL) {
+           sprintf(buf, _("TeleGNOME: %s (%s)"), name, desc);
+           gtk_window_set_title(GTK_WINDOW(gui->app), buf);
+       }
+       g_free(desc);
+       g_free(name);
     }
 }
 
@@ -52,117 +114,67 @@ tg_gui_update_title_bar(void)
 static gint 
 tg_gui_logo_timer(gpointer g) 
 {
-    if (gui.logo_timer != -1)
-       gtk_timeout_remove(gui.logo_timer);
-    gui.logo_timer = -1;
+    if (gui->logo_timer != -1)
+       gtk_timeout_remove(gui->logo_timer);
+    gui->logo_timer = -1;
     tg_gui_get_the_page(FALSE);
     return 0;
 }
 
-static void
-tg_gui_restore_session(void)
+static TgChannel *
+tg_gui_channel_find_by_uuid(const gchar *uuid)
 {
-    /* the kb timer */
-    gui.kb_timer = -1;
-    gui.kb_status = INPUT_NEW;
-
-    gui.page_progress = 0;
-    gui.page_timer = -1;
-    gui.page_status = FALSE;
-    gui.default_server = gnome_config_get_int_with_default("/telegnome/Default/server=0", NULL);
-
-    gui.page_msecs = gnome_config_get_int_with_default("/telegnome/Paging/interval=" DEFAULT_INTERVAL, NULL);
-    gui.progress = gnome_appbar_get_progress(GNOME_APPBAR(gui.statusbar));
-    gtk_progress_bar_set_fraction(gui.progress, 0.0);
+    GSList *cur;
+
+    for (cur = gui->channels; cur; cur = g_slist_next(cur)) {
+       gchar *cur_uuid;
+       g_object_get(G_OBJECT(cur->data), "uuid", &cur_uuid, NULL);
+       if (cur_uuid && g_str_equal(uuid, cur_uuid)) {
+           g_free(cur_uuid);
+           return TG_CHANNEL(g_object_ref(G_OBJECT(cur->data)));
+       }
+       g_free(cur_uuid);
+    }
+    return NULL;
+}
 
-    /* the zoom button */
-    /* FIXME */ /*
-    currentview->zoom_factor=gnome_config_get_int_with_default("/telegnome/Zooming/factor=1", NULL);
-    gtk_label_set(GTK_LABEL(gui.zoomlabel), currentview->zoom_factor==1?"100%":"400%");
-    if (currentview->zoom_factor==2) gtk_toggle_button_toggled(GTK_TOGGLE_BUTTON(gui.zoombutton));
-               */
+/* changes the channel */
+static void 
+tg_gui_channel_select(TgChannel *channel)
+{
+    g_assert(channel != NULL);
 
-    /* the current page */
-    currentview->page_nr = gnome_config_get_int_with_default("/telegnome/Paging/page_nr=-1", NULL);
-    currentview->subpage_nr = gnome_config_get_int_with_default("/telegnome/Paging/subpage_nr=-1", NULL);
+    if (currentview->channel)
+       g_object_unref(G_OBJECT(currentview->channel));
+    currentview->channel = g_object_ref(G_OBJECT(channel));
 
-    /* g_print("Number: %d/%d\n", currentview->page_nr, currentview->subpage_nr); */
-}
+    tg_gui_update_title_bar();
 
-static void
-tg_gui_save_session(void)
-{
-    gnome_config_set_bool("/telegnome/Paging/enabled", gui.page_status);
-    gnome_config_set_int("/telegnome/Paging/interval", gui.page_msecs);
-    gnome_config_set_int("/telegnome/Paging/page_nr", currentview->page_nr);
-    gnome_config_set_int("/telegnome/Paging/subpage_nr", currentview->subpage_nr);
-    gnome_config_set_int("/telegnome/Zooming/factor", currentview->zoom_factor);
-    gnome_config_set_int("/telegnome/Default/server", gui.default_server);
-    gnome_config_sync();
+#if 0
+    {
+       gchar *name, *desc;
+       g_object_get(channel, "name", &name, "desc", &desc, NULL);
+       g_print("Channel Selected: %s (%s)\n", name, desc);
+       g_free(desc);
+       g_free(name);
+    }
+#endif
 }
 
-/* SESSION MANAGEMENT CALLS */
 static void
-tg_gui_die (GnomeClient *client, gpointer client_data)
+tg_gui_channel_menu_item_activate(GtkWidget *w, gpointer data)
 {
-    /* Just exit in a friendly way.  We don't need to
-       save any state here, because the session manager
-       should have sent us a save_yourself-message
-       before.  */
-    gtk_exit (0);
-}
-
-static int 
-tg_gui_save_yourself(GnomeClient *client, int phase,
-                    GnomeSaveStyle save_style, int shutdown,
-                    GnomeInteractStyle interact_style, int fast,
-                    gpointer client_data)
-{
-    /*this is a "discard" command for discarding data from
-      a saved session, usually this will work*/
-    char *argv[]= { "rm", "-r", NULL };
-    
-    /* Save the state using gnome-config stuff. */
-    tg_gui_save_session();
-
-    /* Here is the real SM code. We set the argv to the
-       parameters needed to restart/discard the session that
-       we've just saved and call the
-       gnome_session_set_*_command to tell the session
-       manager it. */
-    /* argv[2]= gnome_config_get_real_path (prefix); */
-    gnome_client_set_discard_command (client, 3, argv);
-    
-    /* Set commands to clone and restart this application.
-       Note that we use the same values for both -- the
-            session management code will automatically add
-            whatever magic option is required to set the session
-            id on startup. The client_data was set to the
-            command used to start this application when
-            tg_gui_save_yourself handler was connected. */
-    argv[0]= (gchar*) client_data;
-    gnome_client_set_clone_command (client, 1, argv);
-    gnome_client_set_restart_command (client, 1, argv);
-    
-    return TRUE;
-}
+    gchar *uuid;
 
-/* changes the channel */
-static void 
-tg_gui_channel_select(GtkWidget *w, gpointer data)
-{
-    TgChannel *channel;
     g_assert(data != NULL);
-
-    channel = (TgChannel *)data;
-
-    currentview->channel = channel;
-    currentview->page_nr = 100;
-    currentview->subpage_nr = 0;
-
-    tg_gui_update_title_bar();
-
-    /* g_print("Channel Selected: %s (%s)\n", channel->name->str, channel->desc->str); */
+    g_object_get(TG_CHANNEL(data), "uuid", &uuid, NULL);
+    g_object_set(
+       gui,
+       "current-channel", uuid,
+       "current-page-number", 100,
+       "current-subpage-number", 0,
+       NULL);
+    g_free(uuid);
     tg_gui_get_the_page(FALSE);
 }
 
@@ -176,18 +188,24 @@ tg_gui_create_channel_menu(void)
     int i;
     TgChannel *channel;
 
-    g_assert(gui.channels != NULL);
+    g_assert(gui->channels != NULL);
     menu = gtk_menu_new();
 
-    for (i=0; i<g_slist_length(gui.channels); i++) {
-       channel = (TgChannel *)g_slist_nth_data(gui.channels, i);
+    for (i=0; i<g_slist_length(gui->channels); i++) {
+       gchar *name;
+
+       channel = TG_CHANNEL(g_slist_nth_data(gui->channels, i));
+       g_object_get(channel, "name", &name, NULL);
 
-       item = gtk_menu_item_new_with_label(channel->name->str);
+       item = gtk_menu_item_new_with_label(name);
 
        g_signal_connect(G_OBJECT(item), "activate",
-                        G_CALLBACK(tg_gui_channel_select), (gpointer)channel);
+                        G_CALLBACK(tg_gui_channel_menu_item_activate),
+                        (gpointer)channel);
        gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
        gtk_widget_show(item);
+
+       g_free(name);
     }
 
     item = gtk_menu_item_new_with_label(_("Channels"));
@@ -198,56 +216,84 @@ tg_gui_create_channel_menu(void)
 }
 
 /*************************
- * Loads all the channels from the config and puts them in the gui.channels GSList
+ * Loads all the channels from the config and puts them in the
+ * gui->channels GSList
  */
 static void
-tg_gui_load_channels_from_config(void)
+tg_gui_reload_channels(void)
 {
-    int count,i;
+    gchar **childp;
     TgChannel *channel;
+    gchar *current_uuid = NULL;
 
-    if (gui.channels != NULL) {
-       g_slist_free_full(gui.channels, (GDestroyNotify)tg_channel_free);
-       gui.channels = NULL;
+    if (gui->channels != NULL) {
+       g_slist_free_full(gui->channels, g_object_unref);
+       gui->channels = NULL;
     }
 
-    count = gnome_config_get_int_with_default("/telegnome/Channels/count=0", NULL);
-    if (count > 0) {
-       for (i=0; i<count; i++) {
-           channel = tg_channel_new_from_config(i);
-           gui.channels = g_slist_append(gui.channels, (gpointer)channel);
-       }
-    } else {
+    if (currentview->channel)
+       g_object_get(currentview->channel, "uuid", &current_uuid, NULL);
+
+    for (childp = gui->channel_children; childp && *childp; ++childp) {
+       channel = tg_channel_new(*childp, NULL);
+       if (channel)
+           gui->channels = g_slist_append(gui->channels, (gpointer)channel);
+    }
+    if (!gui->channels) {
        /* nothing set up yet, fill in some default */
-       count = 1;
+       gchar **children = g_new0(gchar *, 2);
        channel = tg_channel_new(
-           0, "Ceefax, United Kingdom", "UK teletext (BBC)",
-           "http://www.ceefax.tv/cgi-bin/gfx.cgi?page=%03d_0&font=big&channel=bbc1";,
-           "http://www.ceefax.tv/cgi-bin/gfx.cgi?page=%03d_%d&font=big&channel=bbc1";,
-           "gb");
-       gui.channels = g_slist_append(gui.channels, (gpointer)channel);
-       /* ...and save it to the config */
-       gnome_config_set_int("/telegnome/Channels/count", 1);
-       tg_channel_save_to_config(channel);
+           NULL,
+           "name", "Ceefax, United Kingdom",
+           "description", "UK teletext (BBC)",
+           "page-url", "http://www.ceefax.tv/cgi-bin/gfx.cgi?page=%03d_0&font=big&channel=bbc1";,
+           "subpage-url", "http://www.ceefax.tv/cgi-bin/gfx.cgi?page=%03d_%d&font=big&channel=bbc1";,
+           "country", "gb",
+           NULL);
+       gui->channels = g_slist_append(gui->channels, (gpointer)channel);
+       g_object_get(channel, "uuid", &children[0], NULL);
+       g_settings_set_strv(gui->settings, "channel-children",
+                           (const gchar **) children);
+       g_strfreev(children);
+    }
+
+    if (current_uuid)
+       g_object_set(gui, "current-channel", current_uuid, NULL);
+    if (!currentview->channel) {
+       gchar *first_uuid;
+       g_object_get(
+           TG_CHANNEL(gui->channels->data), "uuid", &first_uuid, NULL);
+       g_object_set(
+           gui,
+           "current-channel", first_uuid,
+           "current-page-number", 100,
+           "current-subpage-number", 0,
+           NULL);
+       g_free(first_uuid);
+       if (current_uuid)
+           tg_gui_get_the_page(FALSE);
     }
+    g_free(current_uuid);
 }
 
 static void
 tg_gui_refresh_channel_menu(void)
 {
     /* dispose the menu if it was already added */
-    if (gui.channel_menu != NULL) {
-       g_object_unref(gui.channel_menu);
+    if (gui->channel_menu != NULL) {
+       gtk_container_remove(
+           GTK_CONTAINER(GNOME_APP(gui->app)->menubar), gui->channel_menu);
     }
     
     /* load the channels from disk */
-    tg_gui_load_channels_from_config();
+    tg_gui_reload_channels();
 
     /* create the menu */
-    gui.channel_menu = tg_gui_create_channel_menu();
+    gui->channel_menu = tg_gui_create_channel_menu();
     
     /* and add it to the menu bar */
-    gtk_menu_shell_insert(GTK_MENU_SHELL(GNOME_APP(gui.app)->menubar), gui.channel_menu, 2);
+    gtk_menu_shell_insert(
+       GTK_MENU_SHELL(GNOME_APP(gui->app)->menubar), gui->channel_menu, 2);
 }
 
 /*******************************
@@ -257,8 +303,8 @@ static void
 tg_gui_print_in_statusbar(const char *buf)  /*FIXME: buffersize*/
 {
     g_assert(buf != NULL);
-    gnome_appbar_set_status(GNOME_APPBAR(gui.statusbar), buf);
-    gtk_widget_show(GTK_WIDGET(gui.statusbar));
+    gnome_appbar_set_status(GNOME_APPBAR(gui->statusbar), buf);
+    gtk_widget_show(GTK_WIDGET(gui->statusbar));
 }
 
 /******************************* 
@@ -267,7 +313,8 @@ tg_gui_print_in_statusbar(const char *buf)  /*FIXME: buffersize*/
 static GtkWidget * 
 tg_gui_new_entry (void)
 {
-       GtkWidget *entry=NULL;
+       GtkWidget *entry = NULL;
+
        entry=gtk_entry_new();
        gtk_entry_set_max_length(GTK_ENTRY(entry),
                                 TG_PAGE_SIZE + 1 + TG_SUBPAGE_SIZE);
@@ -282,7 +329,7 @@ tg_gui_new_entry (void)
                         G_CALLBACK(tg_gui_cb_goto_page), NULL);
 
        /* save entry for later ref */
-       gui.entry= entry;
+       gui->entry = entry;
 
        return entry;
 }
@@ -291,12 +338,12 @@ tg_gui_new_entry (void)
 static gint
 tg_gui_pager_timer(gpointer g)
 {
-    gui.page_progress += gui.page_msecs/100;
-    gtk_progress_bar_set_fraction(gui.progress, gui.page_progress / (gdouble)gui.page_msecs);
+    gui->page_progress += gui->page_msecs/100;
+    gtk_progress_bar_set_fraction(gui->progress, gui->page_progress / (gdouble)gui->page_msecs);
 
-    if (gui.page_progress >= gui.page_msecs) {
-       gui.page_progress = 0;
-       gtk_progress_bar_set_fraction(gui.progress, 0.0);
+    if (gui->page_progress >= gui->page_msecs) {
+       gui->page_progress = 0;
+       gtk_progress_bar_set_fraction(gui->progress, 0.0);
        tg_gui_cb_next_page(NULL, NULL);
     }
     return 1;
@@ -305,17 +352,16 @@ tg_gui_pager_timer(gpointer g)
 static void 
 tg_gui_cb_toggle_paging(GtkWidget *w, gpointer data) 
 {
-    gui.page_msecs = gnome_config_get_int_with_default("/telegnome/Paging/interval=" DEFAULT_INTERVAL, NULL);
-    gtk_progress_bar_set_fraction(gui.progress, 0.0);
-    if (gui.page_status==TRUE) {
-       if (gui.page_timer != -1) gtk_timeout_remove(gui.page_timer);
-       gui.page_timer = -1;
-       gui.page_status = FALSE;
-       gui.page_progress = 0;
+    gtk_progress_bar_set_fraction(gui->progress, 0.0);
+    if (gui->page_status) {
+       if (gui->page_timer != -1) gtk_timeout_remove(gui->page_timer);
+       gui->page_timer = -1;
+       gui->page_status = FALSE;
+       gui->page_progress = 0;
     } else {
-       gui.page_progress = 0;
-       gui.page_status = TRUE;
-       gui.page_timer = gtk_timeout_add(gui.page_msecs/100, tg_gui_pager_timer, NULL);
+       gui->page_progress = 0;
+       gui->page_status = TRUE;
+       gui->page_timer = gtk_timeout_add(gui->page_msecs/100, tg_gui_pager_timer, NULL);
     }
 }
 
@@ -368,17 +414,17 @@ tg_gui_new_toolbar (void)
     icon = gtk_image_new_from_stock(GTK_STOCK_MEDIA_PLAY,
                                    GTK_ICON_SIZE_LARGE_TOOLBAR);
     w = gtk_toggle_button_new();
-    gui.pagebutton = w;
+    gui->pagebutton = w;
     gtk_container_add(GTK_CONTAINER(w), icon);
     g_signal_connect(G_OBJECT(w), "clicked",
                     G_CALLBACK(tg_gui_cb_toggle_paging), NULL);
     gtk_toolbar_append_widget(GTK_TOOLBAR(toolbar), w, _("Toggles auto-paging"), NULL);
 
     /* FIXME */ /*
-    gui.zoomlabel = gtk_label_new(_("100%"));
+    gui->zoomlabel = gtk_label_new(_("100%"));
     w = gtk_toggle_button_new();
-    gui.zoombutton = w;
-    gtk_container_add(GTK_CONTAINER(w), gui.zoomlabel);
+    gui->zoombutton = w;
+    gtk_container_add(GTK_CONTAINER(w), gui->zoomlabel);
     g_signal_connect(G_OBJECT(w), "clicked", G_CALLBACK(tg_gui_cb_zoom), NULL);
     gtk_toolbar_append_widget(GTK_TOOLBAR(toolbar), w, _("Toggles zooming"), NULL);
     */
@@ -392,76 +438,277 @@ tg_gui_new_toolbar (void)
     return toolbar;
 }
 
+static void
+tg_gui_init (TgGui *self)
+{
+}
+
+static void
+tg_gui_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
+{
+    TgGui *self = TG_GUI (object);
+
+    switch (property_id) {
+       case PROP_CHANNEL_CHILDREN:
+           g_value_set_boxed (value, self->channel_children);
+           break;
+
+       case PROP_CURRENT_CHANNEL:
+           g_value_set_string (value, self->current_channel);
+           break;
+
+       case PROP_ZOOM_FACTOR:
+           g_value_set_int (value, currentview->zoom_factor);
+           break;
+
+       case PROP_PAGING_ENABLED:
+           g_value_set_boolean (value, self->page_status);
+           break;
+
+       case PROP_PAGING_INTERVAL:
+           g_value_set_int (value, self->page_msecs);
+           break;
+
+       case PROP_CURRENT_PAGE_NUMBER:
+           g_value_set_int (value, currentview->page_nr);
+           break;
+
+       case PROP_CURRENT_SUBPAGE_NUMBER:
+           g_value_set_int (value, currentview->subpage_nr);
+           break;
+
+       default:
+           G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+           break;
+    }
+}
+
+static void
+tg_gui_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
+{
+    TgGui *self = TG_GUI (object);
+    TgChannel *channel;
+
+    switch (property_id) {
+       case PROP_CHANNEL_CHILDREN:
+           g_strfreev (self->channel_children);
+           self->channel_children = g_value_dup_boxed (value);
+           /* TODO: update channel list */
+           break;
+
+       case PROP_CURRENT_CHANNEL:
+           g_free (self->current_channel);
+           self->current_channel = g_value_dup_string (value);
+           channel = tg_gui_channel_find_by_uuid (self->current_channel);
+           if (channel) {
+               tg_gui_channel_select (channel);
+               g_object_unref (G_OBJECT (channel));
+           } else {
+               if (currentview->channel)
+                   g_object_unref (G_OBJECT (currentview->channel));
+               currentview->channel = NULL;
+           }
+           break;
+
+       case PROP_ZOOM_FACTOR:
+           currentview->zoom_factor = g_value_get_int (value);
+           break;
+
+       case PROP_PAGING_ENABLED:
+           self->page_status = g_value_get_boolean (value);
+           break;
+
+       case PROP_PAGING_INTERVAL:
+           self->page_msecs = g_value_get_int (value);
+           break;
+
+       case PROP_CURRENT_PAGE_NUMBER:
+           currentview->page_nr = g_value_get_int (value);
+           break;
+
+       case PROP_CURRENT_SUBPAGE_NUMBER:
+           currentview->subpage_nr = g_value_get_int (value);
+           break;
+
+       default:
+           G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+           break;
+    }
+}
+
+static void
+tg_gui_finalize (GObject *object)
+{
+    TgGui *gui = TG_GUI (object);
+
+    g_clear_pointer (&gui->app, gtk_widget_destroy);
+    g_clear_object (&gui->settings);
+    g_clear_pointer (&gui->channel_children, g_strfreev);
+    if (gui->channels != NULL) {
+       g_slist_free_full (gui->channels, g_object_unref);
+       gui->channels = NULL;
+    }
+
+    G_OBJECT_CLASS (tg_gui_parent_class)->finalize (object);
+}
+
+static void
+tg_gui_class_init (TgGuiClass *klass)
+{
+    GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+    gobject_class->get_property = tg_gui_get_property;
+    gobject_class->set_property = tg_gui_set_property;
+    gobject_class->finalize = tg_gui_finalize;
+
+    g_object_class_install_property
+       (gobject_class, PROP_CHANNEL_CHILDREN,
+        g_param_spec_boxed ("channel-children",
+                            "Channel children",
+                            "List of relative settings paths at which channels are stored",
+                            G_TYPE_STRV,
+                            G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+    g_object_class_install_property
+       (gobject_class, PROP_CURRENT_CHANNEL,
+        g_param_spec_string ("current-channel",
+                             "Current channel", "Current channel",
+                             NULL,
+                             G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+    g_object_class_install_property
+       (gobject_class, PROP_ZOOM_FACTOR,
+        g_param_spec_int ("zoom-factor",
+                          "Zoom factor",
+                          "Page zoom factor.  Larger numbers produce larger text.",
+                          1, 2, 1,
+                          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+    g_object_class_install_property
+       (gobject_class, PROP_PAGING_ENABLED,
+        g_param_spec_boolean ("paging-enabled",
+                              "Paging enabled",
+                              "Automatically switch page at periodic intervals",
+                              FALSE,
+                              G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+    g_object_class_install_property
+       (gobject_class, PROP_PAGING_INTERVAL,
+        g_param_spec_int ("paging-interval",
+                          _("Paging interval"),
+                          _("Specifies the interval for the auto-pager, in milliseconds."),
+                          1000, 60000, 12000,
+                          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+    g_object_class_install_property
+       (gobject_class, PROP_CURRENT_PAGE_NUMBER,
+        g_param_spec_int ("current-page-number",
+                          "Current page number", "Current page number",
+                          -1, G_MAXINT, -1,
+                          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+    g_object_class_install_property
+       (gobject_class, PROP_CURRENT_SUBPAGE_NUMBER,
+        g_param_spec_int ("current-subpage-number",
+                          "Current subpage number", "Current subpage number",
+                          -1, G_MAXINT, -1,
+                          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+}
+
 /*******************************
  * return the app gui, with startpage or NULL
  */
-GtkWidget *
-tg_gui_new (gchar* startpage) 
+TgGui *
+tg_gui_new (GSettings *settings, gchar *startpage)
 {
-    GtkWidget *app, *toolbar, *statusbar;
+    GtkWidget *toolbar;
     GdkPixbuf *pixbuf;
     GError *error = NULL;
 
+    gui = g_object_new (TG_TYPE_GUI, NULL);
+
     /* the app */
-    app= gnome_app_new (PACKAGE, _("TeleGNOME: Teletext for GNOME"));
-    /* gtk_window_set_policy(GTK_WINDOW (app), FALSE, FALSE, TRUE); */
-    gtk_widget_realize(GTK_WIDGET(app));
+    gui->app = gnome_app_new (PACKAGE, _("TeleGNOME: Teletext for GNOME"));
+    /* gtk_window_set_policy (GTK_WINDOW (gui->app), FALSE, FALSE, TRUE); */
+    gtk_widget_realize (GTK_WIDGET (gui->app));
 
     toolbar = tg_gui_new_toolbar();
 
     /* attach a keyboard event */
-    g_signal_connect (G_OBJECT (app),
+    g_signal_connect (G_OBJECT (gui->app),
                      "key_press_event",
                      G_CALLBACK (tg_cb_keypress), NULL);
     
     /* attach the menu */
-    gnome_app_create_menus(GNOME_APP(app), menubar);
+    gnome_app_create_menus (GNOME_APP (gui->app), menubar);
 
-    gnome_app_add_toolbar(GNOME_APP(app), GTK_TOOLBAR(toolbar), "nav_toolbar", 0, BONOBO_DOCK_TOP, 2, 0, 0);
+    gnome_app_add_toolbar (GNOME_APP (gui->app), GTK_TOOLBAR (toolbar),
+                          "nav_toolbar", 0, BONOBO_DOCK_TOP, 2, 0, 0);
 
     /* the view */
     currentview = tg_view_new();
 
     tg_view_set_error_handler(currentview, tg_gui_print_in_statusbar);
+
+    gui->settings = g_object_ref (settings);
+    g_settings_bind (gui->settings, "channel-children", gui, "channel-children",
+                    G_SETTINGS_BIND_DEFAULT);
+    g_settings_bind (gui->settings, "current-channel", gui, "current-channel",
+                    G_SETTINGS_BIND_DEFAULT);
+    g_settings_bind (gui->settings, "zoom-factor", gui, "zoom-factor",
+                    G_SETTINGS_BIND_DEFAULT);
+    g_settings_bind (gui->settings, "paging-enabled", gui, "paging-enabled",
+                    G_SETTINGS_BIND_DEFAULT);
+    g_settings_bind (gui->settings, "paging-interval", gui, "paging-interval",
+                    G_SETTINGS_BIND_DEFAULT);
+    g_settings_bind (gui->settings, "current-page-number", gui, "current-page-number",
+                    G_SETTINGS_BIND_DEFAULT);
+    g_settings_bind (gui->settings, "current-subpage-number", gui, "current-subpage-number",
+                    G_SETTINGS_BIND_DEFAULT);
+
     /* the statusbar */
-    statusbar= gnome_appbar_new(TRUE,TRUE,GNOME_PREFERENCES_NEVER);
-    gnome_app_set_statusbar(GNOME_APP(app), statusbar);
+    gui->statusbar = gnome_appbar_new (TRUE, TRUE, GNOME_PREFERENCES_NEVER);
+    gnome_app_set_statusbar (GNOME_APP (gui->app), gui->statusbar);
 
     /* make menu hints display on the appbar */
-    gnome_app_install_menu_hints(GNOME_APP(app), menubar);
+    gnome_app_install_menu_hints (GNOME_APP (gui->app), menubar);
 
     /* all the contents */
-    gnome_app_set_contents(GNOME_APP(app), tg_view_get_widget(currentview));
-
-    /* save some pointers for reference later */
+    gnome_app_set_contents (GNOME_APP (gui->app),
+                           tg_view_get_widget (currentview));
 
-    gui.statusbar= statusbar;
-    gui.app= app;
-
-    g_signal_connect (G_OBJECT (app), "delete_event",
+    g_signal_connect (G_OBJECT (gui->app), "delete_event",
                      G_CALLBACK (tg_gui_cb_quit),
                      NULL);
 
-    gui.client = gnome_master_client();
-    g_signal_connect (G_OBJECT (gui.client), "save_yourself",
-                     G_CALLBACK (tg_gui_save_yourself),
-                     NULL); /* fixme? */
-    g_signal_connect (G_OBJECT (gui.client), "die",
-                     G_CALLBACK (tg_gui_die), NULL);
+    gtk_widget_show_all (gui->app);
 
-    
-    gtk_widget_show_all(app);
+    gui->kb_timer = -1;
+    gui->kb_status = INPUT_NEW;
+
+    gui->page_progress = 0;
+    gui->page_timer = -1;
 
-    tg_gui_restore_session();
+    gui->progress = gnome_appbar_get_progress(GNOME_APPBAR(gui->statusbar));
+    gtk_progress_bar_set_fraction(gui->progress, 0.0);
 
-    gui.channels = NULL;
-    gui.channel_menu = NULL;
+#if 0
+    /* the zoom button */
+    /* FIXME */
+    gtk_label_set(GTK_LABEL(gui->zoomlabel), currentview->zoom_factor==1?"100%":"400%");
+    if (currentview->zoom_factor==2) gtk_toggle_button_toggled(GTK_TOGGLE_BUTTON(gui->zoombutton));
+#endif
+
+    /* g_print("Number: %d/%d\n", currentview->page_nr, currentview->subpage_nr); */
+
+    gui->channels = NULL;
+    gui->channel_menu = NULL;
 
     tg_gui_refresh_channel_menu();
 
     /* FIXME: */
     /* set the current view, at elem 0 */
-    currentview->channel = (TgChannel *)g_slist_nth_data(gui.channels, gui.default_server);
+    currentview->channel = tg_gui_channel_find_by_uuid(gui->current_channel);
 
     tg_gui_update_title_bar();
 
@@ -479,21 +726,18 @@ tg_gui_new (gchar* startpage)
     /* only auto-change to a page if it was saved the last time */
 
     if (currentview->page_nr >0 )
-       gui.logo_timer = gtk_timeout_add(TG_LOGO_TIMEOUT, tg_gui_logo_timer, NULL);
+       gui->logo_timer = gtk_timeout_add (TG_LOGO_TIMEOUT, tg_gui_logo_timer,
+                                          NULL);
     else
-       gui.logo_timer = -1;
+       gui->logo_timer = -1;
     
-    /*
-    if (GNOME_CLIENT_CONNECTED (gui.client)) {
-       tg_gui_update_entry(currentview->page_nr, currentview->subpage_nr);
-       tg_gui_get_the_page(TRUE);
-       g_print("we are connected to a session manager");
-    } else {
-       g_print("we are NOT connected to a session manager");
-    }
-    */
+    return gui;
+}
 
-    return app;
+GtkWidget *
+tg_gui_get_app (TgGui *gui)
+{
+    return gui->app;
 }
 
 
@@ -509,7 +753,7 @@ tg_gui_update_entry (gint page_nr, gint subpage_nr)
        sprintf(full_num,"%d/%d", page_nr, subpage_nr);
     else
        sprintf(full_num,"%d", page_nr);
-    gtk_entry_set_text(GTK_ENTRY(gui.entry), full_num);
+    gtk_entry_set_text(GTK_ENTRY(gui->entry), full_num);
     
     return 0;
 }
@@ -524,20 +768,21 @@ tg_gui_get_the_page (gboolean redraw)
 {
     /* hide the app */
     if (redraw)
-       gtk_widget_hide(GTK_WIDGET(gui.app));
-    
+       gtk_widget_hide(GTK_WIDGET(gui->app));
+
     /* stop the logo timer */
-    if (gui.logo_timer != -1)
-       gtk_timeout_remove(gui.logo_timer);
-    gui.logo_timer = -1;
+    if (gui->logo_timer != -1)
+       gtk_timeout_remove(gui->logo_timer);
+    gui->logo_timer = -1;
 
-    tg_view_update_page(currentview, &currentview->page_nr, &currentview->subpage_nr);
+    if (currentview->channel)
+       tg_view_update_page(currentview, &currentview->page_nr, &currentview->subpage_nr);
 
     tg_gui_update_entry(currentview->page_nr, currentview->subpage_nr);
     tg_gui_print_in_statusbar ("");
 
     if (redraw) 
-      gtk_widget_show_all (GTK_WIDGET(gui.app));
+      gtk_widget_show_all (GTK_WIDGET(gui->app));
 }
 
 
@@ -547,13 +792,10 @@ tg_gui_get_the_page (gboolean redraw)
 void
 tg_gui_cb_quit (GtkWidget* widget, gpointer data)
 {
-    /* save some */
-    tg_gui_save_session();
-
     /* free the channels */
-    if (gui.channels != NULL) {
-       g_slist_free_full(gui.channels, (GDestroyNotify)tg_channel_free);
-       gui.channels = NULL;
+    if (gui->channels != NULL) {
+       g_slist_free_full(gui->channels, g_object_unref);
+       gui->channels = NULL;
     }
     tg_view_free(currentview);
 
@@ -591,7 +833,7 @@ tg_gui_cb_about (GtkWidget* widget, gpointer data)
        "translator-credits", _("translator-credits"),
        NULL);
 
-    gtk_window_set_transient_for(GTK_WINDOW(about), GTK_WINDOW(gui.app));
+    gtk_window_set_transient_for(GTK_WINDOW(about), GTK_WINDOW(gui->app));
     gtk_window_set_destroy_with_parent(GTK_WINDOW(about), TRUE);
 
     g_signal_connect(about, "destroy", G_CALLBACK(gtk_widget_destroyed),
@@ -605,22 +847,21 @@ tg_gui_cb_about (GtkWidget* widget, gpointer data)
 static void
 tg_gui_refresh_timer (void)
 {
-    gdouble perc = gtk_progress_bar_get_fraction(gui.progress);
+    gdouble perc = gtk_progress_bar_get_fraction(gui->progress);
 
-    gui.page_msecs = gnome_config_get_int_with_default("/telegnome/Paging/interval=" DEFAULT_INTERVAL, NULL);
-    gui.progress = gnome_appbar_get_progress(GNOME_APPBAR(gui.statusbar));
-    gtk_progress_bar_set_fraction(gui.progress, perc);
+    gui->progress = gnome_appbar_get_progress(GNOME_APPBAR(gui->statusbar));
+    gtk_progress_bar_set_fraction(gui->progress, perc);
 
-    if (gui.page_status == TRUE) {
-       gtk_timeout_remove(gui.page_timer);
-       gui.page_timer = gtk_timeout_add(gui.page_msecs/100, tg_gui_pager_timer, NULL);
+    if (gui->page_status) {
+       gtk_timeout_remove(gui->page_timer);
+       gui->page_timer = gtk_timeout_add(gui->page_msecs/100, tg_gui_pager_timer, NULL);
     }
     
-    gui.page_progress =(int)((gui.page_msecs/100)*perc);
+    gui->page_progress =(int)((gui->page_msecs/100)*perc);
 }
 
 static void
-tg_gui_prefs_close_cb (void)
+tg_gui_prefs_close_cb (GtkDialog *dialog, gint response_id, gpointer user_data)
 {
     tg_gui_refresh_channel_menu();
     tg_gui_refresh_timer();
@@ -629,8 +870,7 @@ tg_gui_prefs_close_cb (void)
 void
 tg_gui_cb_preferences (GtkWidget* widget, gpointer data)
 {
-    tg_prefs_show();
-    tg_prefs_set_close_cb(tg_gui_prefs_close_cb);
+    tg_prefs_show(GTK_WINDOW(gui->app), G_CALLBACK(tg_gui_prefs_close_cb));
 }
 
 void
@@ -670,8 +910,8 @@ tg_gui_cb_home (GtkWidget* widget, gpointer data)
 void
 tg_gui_cb_goto_page (GtkWidget *widget, gpointer data)
 {
-    gui.kb_status = INPUT_NEW;
-    if ( -1 == tg_http_get_page_entry (gtk_entry_get_text(GTK_ENTRY(gui.entry)))) {
+    gui->kb_status = INPUT_NEW;
+    if ( -1 == tg_http_get_page_entry (gtk_entry_get_text(GTK_ENTRY(gui->entry)))) {
        tg_gui_print_in_statusbar(_("Error in page entry"));
        return;
     }
@@ -687,10 +927,10 @@ tg_gui_cb_zoom (GtkWidget *widget, gpointer data)
 {
     /* new: just toggle it on click */
     if (currentview->zoom_factor==1) {
-       gtk_label_set_text(GTK_LABEL(gui.zoomlabel),"400%");
+       gtk_label_set_text(GTK_LABEL(gui->zoomlabel),"400%");
        currentview->zoom_factor=2;
     } else if (currentview->zoom_factor==2) {
-       gtk_label_set_text(GTK_LABEL(gui.zoomlabel),"100%");
+       gtk_label_set_text(GTK_LABEL(gui->zoomlabel),"100%");
        currentview->zoom_factor=1;
     }          
     /* now, get the page with the new zoom settings */
@@ -700,9 +940,9 @@ tg_gui_cb_zoom (GtkWidget *widget, gpointer data)
 static gint 
 tg_gui_keyboard_timer (gpointer g) 
 {
-    gtk_timeout_remove(gui.kb_timer);
-    gui.kb_timer = -1;
-    gui.kb_status = INPUT_NEW;
+    gtk_timeout_remove(gui->kb_timer);
+    gui->kb_timer = -1;
+    gui->kb_status = INPUT_NEW;
     return 0;
 }
 
@@ -716,16 +956,17 @@ tg_cb_keypress (GtkWidget *widget, GdkEventKey *event)
     }
     
     /* g_print("keypress\n"); */
-    if (!gtk_widget_is_focus(GTK_WIDGET(gui.entry)))
-       gtk_widget_grab_focus(GTK_WIDGET(gui.entry));
+    if (!gtk_widget_is_focus(GTK_WIDGET(gui->entry)))
+       gtk_widget_grab_focus(GTK_WIDGET(gui->entry));
 
-    if (gui.kb_status == INPUT_NEW) {
-       gtk_entry_set_text(GTK_ENTRY(gui.entry), "");
+    if (gui->kb_status == INPUT_NEW) {
+       gtk_entry_set_text(GTK_ENTRY(gui->entry), "");
     }
 
-    if (gui.kb_timer != -1) 
-       gtk_timeout_remove(gui.kb_timer);
-    gui.kb_timer = gtk_timeout_add(TG_KB_TIMEOUT, tg_gui_keyboard_timer, NULL);
-    gui.kb_status = INPUT_CONTINUED;
+    if (gui->kb_timer != -1)
+       gtk_timeout_remove(gui->kb_timer);
+    gui->kb_timer = gtk_timeout_add(
+       TG_KB_TIMEOUT, tg_gui_keyboard_timer, NULL);
+    gui->kb_status = INPUT_CONTINUED;
     return 0;
 }
diff --git a/src/gui.h b/src/gui.h
index f64fe18..f488a3f 100644
--- a/src/gui.h
+++ b/src/gui.h
@@ -6,6 +6,7 @@
 **    Copyright (C) 1999, 2000,
 **    Dirk-Jan C. Binnema <djcb dds nl>,
 **    Arjan Scherpenisse <acscherp wins uva nl>
+**    Copyright (C) 2016 Colin Watson <cjwatson debian org>
 **  
 ** This program is free software; you can redistribute it and/or modify
 ** it under the terms of the GNU General Public License as published by
@@ -30,14 +31,14 @@
 #include <config.h>
 #endif /* HAVE_CONFIG_H */
 
+#include <glib-object.h>
+#include <gio/gio.h>
 #include <gtk/gtk.h>
 #include <libgnomeui/libgnomeui.h>
 #include "view.h"
 
 #define TG_MAX_CHANNELS 100
 
-GtkWidget *tg_gui_new ();
-
 int tg_gui_update_entry (gint page_nr, gint subpage_nr);
 void tg_gui_get_the_page (gboolean redraw);
 
@@ -53,42 +54,14 @@ void tg_gui_cb_goto_page (GtkWidget* widget, gpointer data);
 void tg_gui_cb_zoom (GtkWidget *widget, gpointer data);
 gint tg_cb_keypress (GtkWidget *widget, GdkEventKey *event);
 
-/* some widgets we need a runtime ref to */
-typedef struct _TgGui {
-    GtkWidget *app;
-    
-    GtkWidget *statusbar;
-    GtkWidget *entry;
-    GtkWidget *pixmap;
-
-    /* for session management */
-    GnomeClient *client;
-    
-    GtkProgressBar *progress;
-    
-    GtkWidget *zoomlabel;
-    gint zoom_factor;
-
-    GtkWidget *zoombutton;
-    GtkWidget *pagebutton;
-
-    GtkWidget *channel_menu;
-
-    /* for timer-input */
-    gint logo_timer;
-    gint kb_timer;
-    gint kb_status;
+#define TG_TYPE_GUI             (tg_gui_get_type ())
+G_DECLARE_FINAL_TYPE (TgGui, tg_gui, TG, GUI, GObject)
 
-    gint page_timer;
-    gint page_msecs;
-    gint page_status; /* auto-paging enabled or disabled */
-    gint page_progress;
+GType tg_gui_get_type (void);
 
-    GSList *channels;
-    gint default_server;
+TgGui *tg_gui_new (GSettings *settings, gchar *startpage);
 
-    /* FIXME: Multiple views */
-} TgGui;
+GtkWidget *tg_gui_get_app (TgGui *gui);
 
 /* DnD target types */
 enum {
diff --git a/src/http.c b/src/http.c
index 0f18632..5953567 100644
--- a/src/http.c
+++ b/src/http.c
@@ -3,6 +3,7 @@
 **    Copyright (C) 1999, 2000,
 **    Dirk-Jan C. Binnema <djcb dds nl>,
 **    Arjan Scherpenisse <acscherp wins uva nl>
+**    Copyright (C) 2016 Colin Watson <cjwatson debian org>
 **  
 ** This program is free software; you can redistribute it and/or modify
 ** it under the terms of the GNU General Public License as published by
@@ -82,9 +83,15 @@ tg_http_get_image (GdkPixbuf **pixbuf)
 
     /* get the image from remote server */
     http_file = g_file_new_for_uri(http_query);
-    http_input = g_file_read(http_file, NULL, NULL);
-    if (!http_input)
+    err = NULL;
+    http_input = g_file_read(http_file, NULL, &err);
+    if (!http_input) {
+       if (err) {
+           g_warning("Unable to fetch '%s': %s", http_query, err->message);
+           g_error_free(err);
+       }
        return TG_ERR_VFS;
+    }
 
     loader = gdk_pixbuf_loader_new();
 
@@ -93,8 +100,7 @@ tg_http_get_image (GdkPixbuf **pixbuf)
                                         NULL, NULL);
        if (bytes_read == 0)
            break;
-       err = NULL;
-       if (!gdk_pixbuf_loader_write(loader, buf, (gsize)bytes_read, &err)) {
+       if (!gdk_pixbuf_loader_write(loader, buf, (gsize)bytes_read, NULL)) {
            retval = TG_ERR_PIXBUF;
            goto out;
        }
@@ -109,7 +115,7 @@ tg_http_get_image (GdkPixbuf **pixbuf)
 
 out:
     if (loader) {
-       if (!gdk_pixbuf_loader_close(loader, &err) && !retval)
+       if (!gdk_pixbuf_loader_close(loader, NULL) && !retval)
            retval = TG_ERR_PIXBUF;
     }
     if (http_input)
@@ -121,15 +127,16 @@ out:
 int
 tg_http_get_query (gchar* buffer, gint page_nr, gint subpage_nr)
 {
+    gchar *url;
+
     if ( subpage_nr>0 ) {    /* do we have a subpage? */
-       sprintf (  buffer, 
-                  currentview->channel->subpage_url->str, 
-                  page_nr, 
-                  subpage_nr);
+       g_object_get(currentview->channel, "subpage-url", &url, NULL);
+       sprintf(buffer, url, page_nr, subpage_nr);
     } else {
-       sprintf (  buffer, 
-                  currentview->channel->page_url->str,
-                  page_nr);
+       g_object_get(currentview->channel, "page-url", &url, NULL);
+       sprintf(buffer, url, page_nr);
     }
+
+    g_free(url);
     return 0;
 }
diff --git a/src/legacy-config.c b/src/legacy-config.c
new file mode 100644
index 0000000..f1b7dc0
--- /dev/null
+++ b/src/legacy-config.c
@@ -0,0 +1,209 @@
+/* legacy-config.c
+ * Part of TeleGNOME, a GNOME app to view Teletext.
+ * This file deals with compatibility with old (gnome-config) configuration
+ * files.
+ */
+
+/*
+** Copyright (C) 2016 Colin Watson <cjwatson debian org>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+**
+*/
+
+#include <stdlib.h>
+
+#include <glib.h>
+#include <gio/gio.h>
+#include <uuid.h>
+
+#include "legacy-config.h"
+
+/* There is no sensible conversion path from gnome-config to GSettings,
+ * especially as we skipped GConf.  Fortunately, gnome-config files were
+ * pretty much just GKeyFiles, so we can roll our own without too much
+ * difficulty.
+ */
+
+static void
+legacy_read_one_file (gpointer data, gpointer user_data)
+{
+    const gchar *name = data;
+    GSList **keyfiles = user_data;
+    GKeyFile *keyfile;
+
+    keyfile = g_key_file_new ();
+    if (g_key_file_load_from_file (keyfile, name, G_KEY_FILE_NONE, NULL))
+       *keyfiles = g_slist_append (*keyfiles, keyfile);
+    else
+       g_key_file_unref (keyfile);
+}
+
+static GSList *
+legacy_read_files (void)
+{
+    GSList *names = NULL;
+    GSList *keyfiles = NULL;
+
+    names = g_slist_append (names, g_build_filename (
+       SYSCONFDIR, "gnome", "config-override", "telegnome", NULL));
+    names = g_slist_append (names, g_build_filename (
+       g_get_home_dir (), ".gnome2", "telegnome", NULL));
+    names = g_slist_append (names, g_build_filename (
+       SYSCONFDIR, "gnome", "config", "telegnome", NULL));
+
+    g_slist_foreach (names, legacy_read_one_file, &keyfiles);
+    g_slist_free_full (names, g_free);
+
+    return keyfiles;
+}
+
+static gchar *
+legacy_get_value (GSList *keyfiles, const gchar *group, const gchar *key)
+{
+    GSList *iter;
+
+    for (iter = keyfiles; iter; iter = g_slist_next (iter)) {
+       gchar *ret = g_key_file_get_string (iter->data, group, key, NULL);
+       if (ret)
+           return ret;
+    }
+
+    return NULL;
+}
+
+void
+legacy_convert (GSettings *settings)
+{
+    GSList *keyfiles;
+    gchar *value;
+    gchar **children;
+    gint channel_count = 0, current_channel = -1, i;
+
+    if (g_settings_get_boolean (settings, "legacy-migration-complete"))
+       return;
+
+    keyfiles = legacy_read_files ();
+
+    value = legacy_get_value (keyfiles, "Channels", "count");
+    if (value)
+       channel_count = atoi (value);
+    g_free (value);
+
+    value = legacy_get_value (keyfiles, "Default", "server");
+    if (value)
+       current_channel = atoi (value);
+    g_free (value);
+
+    value = legacy_get_value (keyfiles, "Zooming", "factor");
+    if (value) {
+       gint zoom_factor = atoi (value);
+       /* clip to 1 or 2 */
+       g_settings_set_int (settings, "zoom-factor", zoom_factor == 1 ? 1 : 2);
+    }
+    g_free (value);
+
+    value = legacy_get_value (keyfiles, "Paging", "enabled");
+    if (value) {
+       gboolean paging_enabled;
+       if (g_ascii_tolower (*value) == 't' ||
+           g_ascii_tolower (*value) == 'y' ||
+           atoi (value))
+           paging_enabled = TRUE;
+       else
+           paging_enabled = FALSE;
+       g_settings_set_boolean (settings, "paging-enabled", paging_enabled);
+    }
+    g_free (value);
+
+    value = legacy_get_value (keyfiles, "Paging", "interval");
+    if (value) {
+       gint paging_interval = atoi (value);
+       g_settings_set_int (settings, "paging-interval", paging_interval);
+    }
+    g_free (value);
+
+    value = legacy_get_value (keyfiles, "Paging", "page_nr");
+    if (value) {
+       gint current_page_number = atoi (value);
+       g_settings_set_int (settings,
+                           "current-page-number", current_page_number);
+    }
+    g_free (value);
+
+    value = legacy_get_value (keyfiles, "Paging", "subpage_nr");
+    if (value) {
+       gint current_subpage_number = atoi (value);
+       g_settings_set_int (settings,
+                           "current-subpage-number", current_subpage_number);
+    }
+    g_free (value);
+
+    children = g_new0 (gchar *, channel_count + 1);
+    for (i = 0; i < channel_count; ++i) {
+       gchar *channel_group = g_strdup_printf ("Channel%d", i);
+       GSettings *channel_settings;
+       uuid_t uu;
+       gchar uuid[37];
+       gchar *child_path;
+
+       uuid_generate (uu);
+       uuid_unparse (uu, uuid);
+       child_path = g_strdup_printf
+           ("/org/gnome/telegnome/channel/%s/", uuid);
+       children[i] = g_strdup (uuid);
+       channel_settings = g_settings_new_with_path
+           ("org.gnome.telegnome.channel", child_path);
+
+       value = legacy_get_value (keyfiles, channel_group, "name");
+       if (value)
+           g_settings_set_string (channel_settings, "name", value);
+       g_free (value);
+
+       value = legacy_get_value (keyfiles, channel_group, "desc");
+       if (value)
+           g_settings_set_string (channel_settings, "description", value);
+       g_free (value);
+
+       value = legacy_get_value (keyfiles, channel_group, "page_url");
+       if (value)
+           g_settings_set_string (channel_settings, "page-url", value);
+       g_free (value);
+
+       value = legacy_get_value (keyfiles, channel_group, "subpage_url");
+       if (value)
+           g_settings_set_string (channel_settings, "subpage-url", value);
+       g_free (value);
+
+       value = legacy_get_value (keyfiles, channel_group, "country");
+       if (value)
+           g_settings_set_string (channel_settings, "country", value);
+       g_free (value);
+
+       if (i == current_channel)
+           g_settings_set_string (settings, "current-channel", uuid);
+
+       g_object_unref (channel_settings);
+       g_free (channel_group);
+    }
+    g_settings_set_strv (settings, "channel-children",
+                        (const gchar * const *) children);
+    g_strfreev (children);
+
+    g_slist_free_full (keyfiles, (GDestroyNotify) g_key_file_unref);
+
+    g_settings_set_boolean (settings, "legacy-migration-complete", TRUE);
+    g_settings_sync ();
+}
diff --git a/src/legacy-config.h b/src/legacy-config.h
new file mode 100644
index 0000000..695608c
--- /dev/null
+++ b/src/legacy-config.h
@@ -0,0 +1,37 @@
+/* legacy-config.h
+ * Part of TeleGNOME, a GNOME app to view Teletext.
+ * This file deals with compatibility with old (gnome-config) configuration
+ * files.
+ */
+
+/*
+** Copyright (C) 2016 Colin Watson <cjwatson debian org>
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+**
+*/
+
+#ifndef _LEGACY_CONFIG_H_
+#define _LEGACY_CONFIG_H_
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <gio/gio.h>
+
+void legacy_convert (GSettings *settings);
+
+#endif /* _LEGACY_CONFIG_H_ */
diff --git a/src/main.c b/src/main.c
index 07cfbf0..094a44c 100644
--- a/src/main.c
+++ b/src/main.c
@@ -6,6 +6,7 @@
 **    Copyright (C) 1999, 2000,
 **    Dirk-Jan C. Binnema <djcb dds nl>,
 **    Arjan Scherpenisse <acscherp wins uva nl>
+**    Copyright (C) 2016 Colin Watson <cjwatson debian org>
 **  
 ** This program is free software; you can redistribute it and/or modify
 ** it under the terms of the GNU General Public License as published by
@@ -30,20 +31,22 @@
 #include <stdio.h>
 #include <string.h>
 
+#include <gio/gio.h>
 #include <gtk/gtk.h>
 #include <libgnome/libgnome.h>
-#include <libgnomeui/libgnomeui.h>
 
 #include "main.h"
 #include "http.h"
 #include "gui.h"
 #include "prefs.h"
+#include "legacy-config.h"
 
 
 int 
 main (int argc, char **argv)
 {
-       GtkWidget *gui;
+       TgGui *gui;
+       GSettings *settings;
 
        bindtextdomain(PACKAGE,GNOMELOCALEDIR);
        textdomain(PACKAGE);
@@ -51,14 +54,17 @@ main (int argc, char **argv)
        gnome_program_init (PACKAGE, VERSION, LIBGNOMEUI_MODULE, argc, argv,
                            NULL);
 
+       settings = g_settings_new ("org.gnome.telegnome");
+       legacy_convert (settings);
+
        /* build gui, handle cmd line args */
        if ((argc >1) && (strlen(argv[1])<6)) {
-               gui = tg_gui_new (argv[1]);
+               gui = tg_gui_new (settings, argv[1]);
        } else {
-               gui = tg_gui_new ("100");
+               gui = tg_gui_new (settings, "100");
        } 
 
-       gtk_widget_show_all(GTK_WIDGET(gui));
+       gtk_widget_show_all (tg_gui_get_app (gui));
        gtk_main();
 
        return 0;
diff --git a/src/main.h b/src/main.h
index a6859cf..dff50e7 100644
--- a/src/main.h
+++ b/src/main.h
@@ -26,8 +26,6 @@
 #include <config.h>
 #endif /* HAVE_CONFIG_H */
 
-#include <glib/gi18n.h>
-
 #include "gui.h"
 #include "http.h"
 
diff --git a/src/prefs.c b/src/prefs.c
index 39b3c37..1063436 100644
--- a/src/prefs.c
+++ b/src/prefs.c
@@ -5,6 +5,7 @@
 
 /*
 ** Copyright (C) 2000 Arjan Scherpenisse <acscherp wins uva nl>
+** Copyright (C) 2016 Colin Watson <cjwatson debian org>
 **  
 ** This program is free software; you can redistribute it and/or modify
 ** it under the terms of the GNU General Public License as published by
@@ -22,9 +23,14 @@
 **  
 */
 
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gio/gio.h>
+#define G_SETTINGS_ENABLE_BACKEND
+#include <gio/gsettingsbackend.h>
 #include <gtk/gtk.h>
-#include <libgnome/libgnome.h>
-#include <libgnomeui/libgnomeui.h>
+#include <dconf.h>
 
 #include "prefs.h"
 #include "channel.h"
@@ -32,139 +38,127 @@
 
 
 typedef struct _TgPrefsWindow {
-    GnomePropertyBox *box;
+    GSettings *settings;
 
-    GtkWidget *page_entry;
-    GtkWidget *sub_page_entry;
-
-    GtkWidget *interval_entry;
-    GtkWidget *proxy_entry;
+    GtkWidget *dialog;
 
     GtkWidget *channel_list;
     GtkWidget *channel_label;
-    gint channel_count;
-    
-    void (*close_callback)(void);
 } TgPrefsWindow;
 
 static TgPrefsWindow *prefs_window;
 
-void
-tg_prefs_set_close_cb( void (*c)(void) )
+static void
+tg_prefs_set_close_cb(GCallback c)
 {
-    g_assert( prefs_window != NULL );
-    prefs_window->close_callback = c;
+    g_assert (prefs_window != NULL);
+    g_signal_connect (G_OBJECT (prefs_window->dialog), "response", c, NULL);
 }
 
 static void
-tg_prefs_fill_channel_list(void)
+tg_prefs_fill_channel_list()
 {
-    int i, newrow;
+    int newrow;
+    gchar **children, **childp;
     TgChannel *channel;
-    char *info[2];
-
-    prefs_window->channel_count = gnome_config_get_int_with_default("/telegnome/Channels/count=0", NULL);
+    gchar *info[2];
 
     gtk_clist_freeze(GTK_CLIST(prefs_window->channel_list));
 
-    for (i=0; i<prefs_window->channel_count; i++) {
-       channel = tg_channel_new_from_config(i);
-       info[0] = channel->country->str;
-       info[1] = channel->name->str;
+    children = g_settings_get_strv(prefs_window->settings, "channel-children");
+    for (childp = children; childp && *childp; ++childp) {
+       channel = tg_channel_new(*childp, NULL);
+       if (!channel)
+           continue;
+       g_object_get(channel, "country", &info[0], "name", &info[1], NULL);
        newrow = gtk_clist_append(GTK_CLIST(prefs_window->channel_list), info);
        gtk_clist_set_row_data_full(GTK_CLIST(prefs_window->channel_list), newrow,
                                    channel,
-                                   (GDestroyNotify)(tg_channel_free));
+                                   g_object_unref);
     }
+    g_strfreev(children);
     gtk_clist_thaw(GTK_CLIST(prefs_window->channel_list));
 }
 
-static void 
-tg_prefs_edit_channel_changed(GtkWidget *dialog, gpointer data)
-{
-    gnome_dialog_set_sensitive(GNOME_DIALOG(data), 0, TRUE);
-}
-
-
 /* pops up a modal dialog, editing the channel. */
 static gboolean
 tg_prefs_edit_channel(TgChannel *orig)
 {
+    GSettings *settings;
     GtkWidget *dialog, *table, *label, *name, *page, *subpage, *desc, *country, *frame;
-    int reply;
+    gint reply;
     gboolean changed = FALSE;
 
     g_assert(orig != NULL);
 
-    dialog = gnome_dialog_new(_("New/Edit Channel"),
-                          GNOME_STOCK_BUTTON_OK,
-                          GNOME_STOCK_BUTTON_CANCEL, NULL);
-    gnome_dialog_set_sensitive(GNOME_DIALOG(dialog), 0, FALSE);
+    settings = tg_channel_get_settings(orig);
+    g_settings_delay(settings);
+
+    dialog = gtk_dialog_new_with_buttons(
+       _("New/Edit Channel"),
+       GTK_WINDOW(prefs_window->dialog),
+       GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+       GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
+       GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
+       NULL);
 
     table = gtk_table_new(5,2, FALSE);
     gtk_table_set_row_spacings(GTK_TABLE(table), 5);
     gtk_table_set_col_spacings(GTK_TABLE(table), 5);
-    
-    
+
     label = gtk_label_new(_("Name"));
     gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5);
     name = gtk_entry_new();
-    gtk_entry_set_text(GTK_ENTRY(name), orig->name->str);
+    g_settings_bind(settings, "name", name, "text", G_SETTINGS_BIND_DEFAULT);
     gtk_table_attach_defaults(GTK_TABLE(table), label, 0,1, 0,1);
     gtk_table_attach_defaults(GTK_TABLE(table), name, 1,2, 0,1);
-    g_signal_connect(G_OBJECT(name), "changed", G_CALLBACK(tg_prefs_edit_channel_changed), (gpointer)dialog);
 
     label = gtk_label_new(_("Description"));
     gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5);
     desc = gtk_entry_new();
-    gtk_entry_set_text(GTK_ENTRY(desc), orig->desc->str);
+    g_settings_bind(settings, "description", desc, "text", G_SETTINGS_BIND_DEFAULT);
     gtk_table_attach_defaults(GTK_TABLE(table), label, 0,1, 1,2);
     gtk_table_attach_defaults(GTK_TABLE(table), desc,  1,2, 1,2);
-    g_signal_connect(G_OBJECT(desc), "changed", G_CALLBACK(tg_prefs_edit_channel_changed), (gpointer)dialog);
 
     label = gtk_label_new(_("Page url"));
     gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5);
     page = gtk_entry_new();
-    gtk_entry_set_text(GTK_ENTRY(page), orig->page_url->str);
+    g_settings_bind(settings, "page-url", page, "text", G_SETTINGS_BIND_DEFAULT);
     gtk_table_attach_defaults(GTK_TABLE(table), label, 0,1, 2,3);
     gtk_table_attach_defaults(GTK_TABLE(table), page,  1,2, 2,3);
-    g_signal_connect(G_OBJECT(page), "changed", G_CALLBACK(tg_prefs_edit_channel_changed), (gpointer)dialog);
 
     label = gtk_label_new(_("Subpage url"));
     gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5);
     subpage = gtk_entry_new();
-    gtk_entry_set_text(GTK_ENTRY(subpage), orig->subpage_url->str);
+    g_settings_bind(settings, "subpage-url", subpage, "text", G_SETTINGS_BIND_DEFAULT);
     gtk_table_attach_defaults(GTK_TABLE(table), label, 0,1,    3,4);
     gtk_table_attach_defaults(GTK_TABLE(table), subpage,  1,2, 3,4);
-    g_signal_connect(G_OBJECT(subpage), "changed", G_CALLBACK(tg_prefs_edit_channel_changed), 
(gpointer)dialog);
 
     label = gtk_label_new(_("Country"));
     gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5);
     country = gtk_entry_new();
-    gtk_entry_set_text(GTK_ENTRY(country), orig->country->str);
+    g_settings_bind(settings, "country", country, "text", G_SETTINGS_BIND_DEFAULT);
     gtk_table_attach_defaults(GTK_TABLE(table), label, 0,1, 4,5);
     gtk_table_attach_defaults(GTK_TABLE(table), country,  1,2, 4,5);
-    g_signal_connect(G_OBJECT(country), "changed", G_CALLBACK(tg_prefs_edit_channel_changed), 
(gpointer)dialog);
 
     frame = gtk_frame_new(_("Channel Information"));
     gtk_container_add(GTK_CONTAINER(frame), table);
 
-    gtk_container_add( GTK_CONTAINER(GNOME_DIALOG(dialog)->vbox), frame);
+    gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), frame);
 
     gtk_widget_show_all(dialog);
 
-    reply = gnome_dialog_run(GNOME_DIALOG(dialog));
-
-    if ( reply == 0 ) {
-       /* update the server entry accordingly */
-       g_string_assign(orig->name, gtk_entry_get_text(GTK_ENTRY(name)));
-       g_string_assign(orig->desc,  gtk_entry_get_text(GTK_ENTRY(desc)));
-       g_string_assign(orig->page_url,  gtk_entry_get_text(GTK_ENTRY(page)));
-       g_string_assign(orig->subpage_url, gtk_entry_get_text(GTK_ENTRY(subpage)));
-       g_string_assign(orig->country, gtk_entry_get_text(GTK_ENTRY(country)));
-       changed = TRUE;
-    } else {
-       changed = FALSE;
+    reply = gtk_dialog_run(GTK_DIALOG(dialog));
+
+    switch (reply) {
+       case GTK_RESPONSE_ACCEPT:
+           g_settings_apply(settings);
+           changed = TRUE;
+           break;
+       default:
+           g_settings_revert(settings);
+           changed = FALSE;
+           break;
     }
     gtk_widget_destroy(dialog);
 
@@ -172,156 +166,164 @@ tg_prefs_edit_channel(TgChannel *orig)
 }
 
 static void
-tg_prefs_cancel_cb(void)
+tg_prefs_response_cb(GtkDialog *dialog, gint response_id, gpointer user_data)
 {
-    g_clear_object(&prefs_window->box);
+    gtk_widget_destroy(GTK_WIDGET(dialog));
+    /* TODO memory leak: clear prefs_window->channel_list */
     g_clear_pointer(&prefs_window, g_free);
 }
 
-static void 
-tg_prefs_apply_cb(GnomePropertyBox *propertybox, gint page_num)
-{
-    int i;
-    TgChannel *channel;
-
-    if (page_num == -1) return;
-
-    gnome_config_set_int("/telegnome/Paging/interval", 
-                        gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(prefs_window->interval_entry)));
-    gnome_config_set_string("/telegnome/Proxy/http_proxy", 
gtk_entry_get_text(GTK_ENTRY(prefs_window->proxy_entry)));
-
-    gnome_config_set_int("/telegnome/Channels/count", GTK_CLIST(prefs_window->channel_list)->rows);
-
-    for (i=0; i < GTK_CLIST(prefs_window->channel_list)->rows; i++) {
-       channel = gtk_clist_get_row_data(GTK_CLIST(prefs_window->channel_list), i);
-       tg_channel_save_to_config(channel);
-    }
-       
-    gnome_config_sync();
-
-    (*prefs_window->close_callback)();
-}
-
 static void
 tg_prefs_channel_list_click_cb(GtkWidget *clist, gint row, gint column,
                               GdkEventButton *event, gpointer data)
 {
     TgChannel *channel;
+    gchar *description;
+
     channel = gtk_clist_get_row_data(GTK_CLIST(clist), row);
-    
-    gtk_label_set_text(GTK_LABEL(prefs_window->channel_label), 
-                      channel->desc->str);
+    g_object_get(channel, "description", &description, NULL);
+    gtk_label_set_text(GTK_LABEL(prefs_window->channel_label), description);
+    g_free(description);
 }
 
 static void 
-tg_prefs_channels_renum(void)
+tg_prefs_sync_channel_children(void)
 {
+    GtkCList *channel_list;
+    gchar **children;
     int i;
     TgChannel *channel;
-    for (i=0; i < GTK_CLIST(prefs_window->channel_list)->rows; i++) {
-       channel = gtk_clist_get_row_data(GTK_CLIST(prefs_window->channel_list), i);
-       channel->id = i;
+
+    channel_list = GTK_CLIST(prefs_window->channel_list);
+    children = g_new0(gchar *, channel_list->rows + 1);
+    for (i = 0; i < channel_list->rows; ++i) {
+       channel = gtk_clist_get_row_data(channel_list, i);
+       g_object_get(channel, "uuid", &children[i], NULL);
     }
+    g_settings_set_strv(prefs_window->settings, "channel-children",
+                       (const gchar **) children);
 }
 
 static void
 tg_prefs_channel_add_cb(void)
 {
     TgChannel *chan;
-    char *info[2];
-    int id;
+    gchar *info[2];
+
+    chan = tg_channel_new(NULL, NULL);
 
-    chan = tg_channel_new(-1,"","","","","");
     if (tg_prefs_edit_channel(chan)) {
-       if (chan->name->len > 0) {
-           info[0] = chan->country->str;
-           info[1] = chan->name->str;
-           id = gtk_clist_append(GTK_CLIST(prefs_window->channel_list), info);
-           chan->id = id;
-           gtk_clist_set_row_data(GTK_CLIST(prefs_window->channel_list), id, (gpointer)chan);
-           gnome_property_box_changed(GNOME_PROPERTY_BOX(prefs_window->box));
-       }
-    }
+       gchar *name;
+
+       g_object_get(chan, "name", &name, NULL);
+       if (strlen(name) > 0) {
+           GtkCList *channel_list = GTK_CLIST(prefs_window->channel_list);
+           gint new_row;
+
+           g_object_get(chan, "country", &info[0], "name", &info[1], NULL);
+           new_row = gtk_clist_append(channel_list, info);
+           gtk_clist_set_row_data(channel_list, new_row, (gpointer)chan);
+           tg_prefs_sync_channel_children();
+       } else
+           g_object_unref(chan);
+       g_free(name);
+    } else
+       g_object_unref(chan);
 }
 
 static void 
 tg_prefs_channel_move_up_cb(void)
 {
-    GList *list;
+    GtkCList *channel_list;
     int row;
-    
-    if ((list = GTK_CLIST(prefs_window->channel_list)->selection) == NULL)
-       return;
-    row = GPOINTER_TO_INT(list->data);
-    
-    if (row >0) {
-       gtk_clist_swap_rows (GTK_CLIST(prefs_window->channel_list), row, row-1);
-       gnome_property_box_changed(GNOME_PROPERTY_BOX(prefs_window->box));
-       tg_prefs_channels_renum();
+
+    channel_list = GTK_CLIST(prefs_window->channel_list);
+    row = GPOINTER_TO_INT(channel_list->selection->data);
+
+    if (row > 0) {
+       gtk_clist_swap_rows(channel_list, row, row-1);
+       tg_prefs_sync_channel_children();
     }
 }
 
 void 
 tg_prefs_channel_move_down_cb(void)
 {
-    GList *list;
+    GtkCList *channel_list;
     int row;
-    
-    if ((list = GTK_CLIST(prefs_window->channel_list)->selection) == NULL)
-       return;
-    row = GPOINTER_TO_INT(list->data);
 
-    if (row < GTK_CLIST( prefs_window->channel_list)->rows-1) {
-       gtk_clist_swap_rows (GTK_CLIST(prefs_window->channel_list), row, row+1);
-       gnome_property_box_changed(GNOME_PROPERTY_BOX(prefs_window->box));
-       tg_prefs_channels_renum();
+    channel_list = GTK_CLIST(prefs_window->channel_list);
+    row = GPOINTER_TO_INT(channel_list->selection->data);
+
+    if (row < channel_list->rows - 1) {
+       gtk_clist_swap_rows(channel_list, row, row+1);
+       tg_prefs_sync_channel_children();
     }
 }
 
 static void
 tg_prefs_channel_edit_cb(void)
 {
-       GList *list;
-       int row;
-
-       TgChannel *channel = NULL;
-
-       if ((list = GTK_CLIST(prefs_window->channel_list)->selection) == NULL)
-               return;
-       row = GPOINTER_TO_INT(list->data);
-
-       channel = (TgChannel *)gtk_clist_get_row_data(GTK_CLIST(prefs_window->channel_list), row);
-       /* update the entry */
-       if (tg_prefs_edit_channel (channel)) {
-           /* ...and update the list. the data is set automagicly. */
-          gtk_clist_set_text(GTK_CLIST(prefs_window->channel_list), row, 0, channel->country->str);
-          gtk_clist_set_text(GTK_CLIST(prefs_window->channel_list), row, 1, channel->name->str);
-          gnome_property_box_changed(GNOME_PROPERTY_BOX(prefs_window->box));
-       }
+    GtkCList *channel_list;
+    int row;
+    TgChannel *channel;
+
+    channel_list = GTK_CLIST(prefs_window->channel_list);
+    row = GPOINTER_TO_INT(channel_list->selection->data);
+
+    channel = TG_CHANNEL(gtk_clist_get_row_data(channel_list, row));
+    /* update the entry */
+    if (tg_prefs_edit_channel(channel)) {
+       /* ...and update the list.  The data is set automagically. */
+       gchar *country, *name;
+       g_object_get(channel, "country", &country, "name", &name, NULL);
+       gtk_clist_set_text(channel_list, row, 0, country);
+       gtk_clist_set_text(channel_list, row, 1, name);
+       g_free(name);
+       g_free(country);
+    }
 }
 
 static void
 tg_prefs_channel_delete_cb(void)
 {
-    GList *list;
+    GtkCList *channel_list;
     int row;
-    
-    if ((list = GTK_CLIST(prefs_window->channel_list)->selection) == NULL)
-       return;
-    
-    row = GPOINTER_TO_INT(list->data);
-    gtk_clist_remove(GTK_CLIST(prefs_window->channel_list), row);
+    TgChannel *channel;
+    gchar *old_uuid;
+    GSettingsBackend *backend;
 
-    tg_prefs_channels_renum();
+    channel_list = GTK_CLIST(prefs_window->channel_list);
+    if (channel_list->selection == NULL)
+       return;
 
-    gnome_property_box_changed(GNOME_PROPERTY_BOX(prefs_window->box));
+    row = GPOINTER_TO_INT(channel_list->selection->data);
+    channel = TG_CHANNEL(gtk_clist_get_row_data(channel_list, row));
+    g_object_get(channel, "uuid", &old_uuid, NULL);
+    gtk_clist_remove(channel_list, row);
+    tg_prefs_sync_channel_children();
+
+    /* Clear out settings debris from the deleted channel if possible. */
+    backend = g_settings_backend_get_default();
+    if (g_str_equal(G_OBJECT_TYPE_NAME(backend), "DConfSettingsBackend")) {
+       gchar *path;
+       DConfClient *client;
+
+       path = g_strdup_printf("/org/gnome/telegnome/channel/%s/", old_uuid);
+       client = dconf_client_new();
+       dconf_client_write_sync(client, path, NULL, NULL, NULL, NULL);
+       g_object_unref(client);
+       g_free(path);
+    }
+    g_object_unref(G_OBJECT(backend));
+    g_free(old_uuid);
 }
 
 /* not a good idea to have a 'misc' page, but i cant come up with a better name */
 static GtkWidget *
 tg_prefs_construct_misc_page(void)
 {
-    GtkWidget *table, *frame, *label, *entry, *proxy_label, *proxy_entry;
+    GtkWidget *table, *frame, *label, *entry;
     GtkAdjustment *adj;
 
     g_assert(prefs_window != NULL);
@@ -339,16 +341,7 @@ tg_prefs_construct_misc_page(void)
     gtk_table_attach_defaults(GTK_TABLE(table), label, 0,1, 0,1);
     gtk_table_attach_defaults(GTK_TABLE(table), entry, 1,2, 0,1);
 
-    gtk_spin_button_set_value(GTK_SPIN_BUTTON(entry), 
-                             gnome_config_get_int_with_default("/telegnome/Paging/interval=" 
DEFAULT_INTERVAL,NULL));
-    proxy_label = gtk_label_new(_("Proxy server"));
-    proxy_entry = gtk_entry_new();
-    gtk_entry_set_max_length(GTK_ENTRY(proxy_entry), 100);
-    gtk_entry_set_text(GTK_ENTRY(proxy_entry), 
-                      gnome_config_get_string_with_default("/telegnome/Proxy/http_proxy=" "",NULL));
-
-    gtk_table_attach_defaults(GTK_TABLE(table), proxy_label, 0,1, 1,2);
-    gtk_table_attach_defaults(GTK_TABLE(table), proxy_entry, 1,2, 1,2);
+    g_settings_bind(prefs_window->settings, "paging-interval", entry, "value", G_SETTINGS_BIND_DEFAULT);
 
     frame = gtk_frame_new(_("Miscelaneous"));
 
@@ -356,13 +349,11 @@ tg_prefs_construct_misc_page(void)
     gtk_container_set_border_width( GTK_CONTAINER(table), 5);
     gtk_container_add( GTK_CONTAINER(frame), table);
 
-    prefs_window->interval_entry = entry;
-    prefs_window->proxy_entry = proxy_entry;
     return frame;
 }
 
 static GtkWidget *
-tg_prefs_construct_channels_page(void)
+tg_prefs_construct_channels_page()
 {
     GtkWidget *hbox, *vbox, *btn;
     char *titles[2] = { N_("Country"), N_("Name") };
@@ -374,6 +365,7 @@ tg_prefs_construct_channels_page(void)
 
     /* the clist */
     prefs_window->channel_list = gtk_clist_new_with_titles( 2, titles );
+    gtk_clist_set_column_width(GTK_CLIST(prefs_window->channel_list), 1, 200);
     gtk_box_pack_start(GTK_BOX(vbox), prefs_window->channel_list, TRUE, TRUE, 0);
 
     /* label for descriptions and stuff */
@@ -394,29 +386,24 @@ tg_prefs_construct_channels_page(void)
     
     /* move up button */
     btn = gtk_button_new_with_label(_("Move up"));
-    /* btn = gnome_stock_or_ordinary_button(GNOME_STOCK_PIXMAP_ADD); */
     gtk_box_pack_start(GTK_BOX(vbox), btn, FALSE, FALSE, 2);
     g_signal_connect(G_OBJECT(btn), "clicked", G_CALLBACK(tg_prefs_channel_move_up_cb), NULL);
     /* move down button */
     btn = gtk_button_new_with_label(_("Move down"));
-    /* btn = gnome_stock_or_ordinary_button(GNOME_STOCK_PIXMAP_ADD); */
     gtk_box_pack_start(GTK_BOX(vbox), btn, FALSE, FALSE, 2);
     g_signal_connect(G_OBJECT(btn), "clicked", G_CALLBACK(tg_prefs_channel_move_down_cb), NULL);
     /* add button */
     btn = gtk_button_new_with_label(_("Add..."));
-    /* btn = gnome_stock_or_ordinary_button(GNOME_STOCK_PIXMAP_ADD); */
     gtk_box_pack_start(GTK_BOX(vbox), btn, FALSE, FALSE, 2);
     g_signal_connect(G_OBJECT(btn), "clicked", G_CALLBACK(tg_prefs_channel_add_cb), NULL);
 
     /* delete button */
     btn = gtk_button_new_with_label(_("Delete"));
-    /* btn = gnome_stock_or_ordinary_button(GNOME_STOCK_PIXMAP_REMOVE); */
     gtk_box_pack_start(GTK_BOX(vbox), btn, FALSE, FALSE, 2);
     g_signal_connect(G_OBJECT(btn), "clicked", G_CALLBACK(tg_prefs_channel_delete_cb), NULL);
 
     /* edit buton */
     btn = gtk_button_new_with_label(_("Edit"));
-    /* btn = gnome_stock_or_ordinary_button(GNOME_STOCK_PIXMAP_PROPERTIES); */
     gtk_box_pack_start(GTK_BOX(vbox), btn, FALSE, FALSE, 2);
     g_signal_connect(G_OBJECT(btn), "clicked", G_CALLBACK(tg_prefs_channel_edit_cb), NULL);
 
@@ -427,50 +414,47 @@ tg_prefs_construct_channels_page(void)
 }
 
 void
-tg_prefs_show(void)
+tg_prefs_show(GtkWindow *parent, GCallback close_cb)
 {
-    GtkWidget *page;
-
     if (prefs_window != NULL) {
-       gdk_window_show(gtk_widget_get_window(GTK_WIDGET(prefs_window->box)));
-       gdk_window_raise(gtk_widget_get_window(GTK_WIDGET(prefs_window->box)));
+       gdk_window_show(gtk_widget_get_window(prefs_window->dialog));
+       gdk_window_raise(gtk_widget_get_window(prefs_window->dialog));
     } else {
-       prefs_window = g_malloc(sizeof(TgPrefsWindow));
+       GtkWidget *content_area, *notebook, *page;
+
+       prefs_window = g_new0(TgPrefsWindow, 1);
 
-       prefs_window->box = GNOME_PROPERTY_BOX (gnome_property_box_new());
-       gtk_window_set_title (GTK_WINDOW(prefs_window->box), _("TeleGNOME: Preferences"));
+       prefs_window->settings = g_settings_new("org.gnome.telegnome");
+
+       prefs_window->dialog = gtk_dialog_new_with_buttons(
+           _("TeleGNOME: Preferences"), parent,
+           GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+           GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
+           GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
+           NULL);
+       content_area = gtk_dialog_get_content_area(
+           GTK_DIALOG(prefs_window->dialog));
+       notebook = gtk_notebook_new();
+       gtk_container_add(GTK_CONTAINER(content_area), notebook);
 
        page = tg_prefs_construct_channels_page();
-       gtk_notebook_append_page(GTK_NOTEBOOK(prefs_window->box->notebook),
-                                page,
+       gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page,
                                 gtk_label_new(_("Channels")));
 
        page = tg_prefs_construct_misc_page();
-       gtk_notebook_append_page(GTK_NOTEBOOK(prefs_window->box->notebook),
-                                page,
+       gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page,
                                 gtk_label_new(_("Misc")));
 
 
-       gtk_notebook_set_show_tabs (GTK_NOTEBOOK(prefs_window->box->notebook),
-                                   TRUE);
-       gtk_notebook_set_show_border (GTK_NOTEBOOK(prefs_window->box->notebook),
-                                     TRUE);
-
-       g_signal_connect (G_OBJECT (prefs_window->box), "apply",
-                         G_CALLBACK (tg_prefs_apply_cb), NULL);
-       g_signal_connect (G_OBJECT (prefs_window->box), "destroy",
-                         G_CALLBACK (tg_prefs_cancel_cb), NULL);
-
-       g_signal_connect_swapped(G_OBJECT(prefs_window->interval_entry), "changed",
-                                G_CALLBACK(gnome_property_box_changed),
-                                G_OBJECT(prefs_window->box));
-       
-       g_signal_connect_swapped(G_OBJECT(prefs_window->proxy_entry), "changed",
-                                G_CALLBACK(gnome_property_box_changed),
-                                G_OBJECT(prefs_window->box));
+       gtk_notebook_set_show_tabs (GTK_NOTEBOOK(notebook), TRUE);
+       gtk_notebook_set_show_border (GTK_NOTEBOOK(notebook), TRUE);
 
+       if (close_cb)
+           tg_prefs_set_close_cb (close_cb);
+       g_signal_connect (G_OBJECT (prefs_window->dialog), "response",
+                         G_CALLBACK (tg_prefs_response_cb), NULL);
 
        /* and, show them all */
-       gtk_widget_show_all(GTK_WIDGET(prefs_window->box));
+       gtk_widget_show_all(prefs_window->dialog);
     }
 }
diff --git a/src/prefs.h b/src/prefs.h
index c4eec44..37201e0 100644
--- a/src/prefs.h
+++ b/src/prefs.h
@@ -4,6 +4,7 @@
 
 /*
 ** Copyright (C) 1999 Dirk-Jan C. Binnema <djcb dds nl>
+** Copyright (C) 2016 Colin Watson <cjwatson debian org>
 **  
 ** This program is free software; you can redistribute it and/or modify
 ** it under the terms of the GNU General Public License as published by
@@ -25,15 +26,12 @@
 #ifndef __PREFS_H__
 #define __PREFS_H__
 
+#include <glib-object.h>
 #include <gtk/gtk.h>
 
-/* some defaults */
-#define DEFAULT_INTERVAL       "12000"
-
 #define TELEGNOME_LOGO         "telegnome/telegnome-logo.png"
 #define TELEGNOME_NOTFOUND     "telegnome/telegnome-logo.png"
 
-void tg_prefs_show(void);
-void tg_prefs_set_close_cb( void (*c)(void) );
+void tg_prefs_show(GtkWindow *parent, GCallback close_cb);
 
 #endif /* __PREFS_H__ */
diff --git a/src/view.c b/src/view.c
index aec9f2e..b8b362d 100644
--- a/src/view.c
+++ b/src/view.c
@@ -7,6 +7,7 @@
 **    Copyright (C) 1999, 2000,
 **    Dirk-Jan C. Binnema <djcb dds nl>,
 **    Arjan Scherpenisse <acscherp wins uva nl>
+**    Copyright (C) 2016 Colin Watson <cjwatson debian org>
 **  
 ** This program is free software; you can redistribute it and/or modify
 ** it under the terms of the GNU General Public License as published by
@@ -24,6 +25,8 @@
 **  
 */
 
+#include <glib.h>
+#include <glib/gi18n.h>
 #include <libgnome/libgnome.h>
 
 #include "view.h"
@@ -48,6 +51,8 @@ tg_view_new(void)
     
     v->zoom_factor = 1.0;
 
+    v->channel = NULL;
+
     v->page_nr = -1;
     v->subpage_nr = -1;
 
@@ -110,6 +115,7 @@ tg_view_update_page(TgView *view, int *major_nr, int *minor_nr)
                            (*major_nr)++;
                            tg_gui_update_entry(*major_nr, *minor_nr);
                            tg_gui_get_the_page(FALSE); /* dont redraw */ 
+                           return 0;
                        } else {
                            (*(view->error_handler))(_("Web server error: Wrong page number?"));
                            *major_nr= old_page;  /* restore */
diff --git a/src/view.h b/src/view.h
index c6eec27..6404369 100644
--- a/src/view.h
+++ b/src/view.h
@@ -54,5 +54,5 @@ gint tg_view_update_pixmap(TgView *view, GdkPixbuf *pixbuf);
 gint tg_view_update_page(TgView *view, int *major_nr, int *minor_nr);
 GtkWidget *tg_view_get_widget(TgView *view);
 void tg_view_free(TgView *view);
-#endif
 
+#endif


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